From 332a6a96fa30c2f3a21dd02e1ed8d36e39c137c4 Mon Sep 17 00:00:00 2001 From: Khasbulat Abdullin Date: Sun, 8 Mar 2026 06:25:42 +0300 Subject: [PATCH 1/2] fix: align managed mode behavior with buf Apply managed mode overrides to all files in the generation request, including dependencies and git_repo inputs, and rely on disable/module/path selectors only to narrow rules. Add regression coverage for generate + git_repo + managed mode, switch the new core test mocks to direct mockery go:generate directives, and update the guide/spec docs plus built search indexes to match the new semantics. --- .../docs/guide/cli/generator/generator.md | 6 +- .../docs/ru-guide/cli/generator/generator.md | 6 +- docs/dist/search/index.en.json | 2 +- docs/dist/search/index.ru.json | 2 +- .../docs/guide/cli/generator/generator.md | 6 +- .../docs/ru-guide/cli/generator/generator.md | 6 +- docs/public/search/index.en.json | 2 +- docs/public/search/index.ru.json | 2 +- internal/core/generate_managed_mode_test.go | 102 ++++ internal/core/lockfile_mock_test.go | 233 +++++++++ internal/core/managed_mode.go | 27 +- internal/core/managed_mode_test.go | 30 +- internal/core/mod.go | 3 + internal/core/storage_mock_test.go | 453 ++++++++++++++++++ mcp/easypconfig/spec_docs.go | 14 +- 15 files changed, 837 insertions(+), 57 deletions(-) create mode 100644 internal/core/generate_managed_mode_test.go create mode 100644 internal/core/lockfile_mock_test.go create mode 100644 internal/core/storage_mock_test.go diff --git a/docs/dist/docs/guide/cli/generator/generator.md b/docs/dist/docs/guide/cli/generator/generator.md index ae474f0f..fa04560d 100644 --- a/docs/dist/docs/guide/cli/generator/generator.md +++ b/docs/dist/docs/guide/cli/generator/generator.md @@ -574,9 +574,9 @@ When managed mode is enabled, EasyP automatically applies file and field options - Objective-C: `objc_class_prefix` defaults to first letters of package parts - C++: `cc_enable_arenas` defaults to `true` -**Overrides** allow you to set specific values for options, with support for filtering by module, path, or field. +**Overrides** allow you to set specific values for options, with support for filtering by module, path, or field. Without `module` or `path`, an override applies to all files in the generation request, including dependencies and `git_repo` inputs. -**Disables** allow you to prevent managed mode from modifying specific options or files. +**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. ### Configuration @@ -759,6 +759,8 @@ generate: module: github.com/mycompany/internal-protos ``` +`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`. + #### Disabling for External Dependencies Disable managed mode for external dependencies that already have their options set: diff --git a/docs/dist/docs/ru-guide/cli/generator/generator.md b/docs/dist/docs/ru-guide/cli/generator/generator.md index 910354ca..6b17395f 100644 --- a/docs/dist/docs/ru-guide/cli/generator/generator.md +++ b/docs/dist/docs/ru-guide/cli/generator/generator.md @@ -574,9 +574,9 @@ Managed mode автоматически устанавливает file и field - Objective-C: `objc_class_prefix` по умолчанию первые буквы частей пакета - C++: `cc_enable_arenas` по умолчанию `true` -**Overrides** позволяют установить конкретные значения для опций с поддержкой фильтрации по модулю, пути или полю. +**Overrides** позволяют установить конкретные значения для опций с поддержкой фильтрации по модулю, пути или полю. Если не указаны `module` и `path`, override применяется ко всем файлам в запросе генерации, включая зависимости и `git_repo` inputs. -**Disables** позволяют предотвратить изменение managed mode определённых опций или файлов. +**Disables** позволяют предотвратить изменение managed mode определённых опций или файлов. Это рекомендуемый способ исключить внешние зависимости, у которых свои опции уже заданы. ### Конфигурация @@ -759,6 +759,8 @@ generate: module: github.com/mycompany/internal-protos ``` +`module` должен точно совпадать с источником модуля в EasyP: это значение из `deps` или `git_repo.url` до `@version` (например, `github.com/mycompany/internal-protos` или `https://github.com/mycompany/internal-protos`). Это не Go module path из `go.mod`. + #### Отключение для внешних зависимостей Отключите managed mode для внешних зависимостей, у которых уже установлены опции: diff --git a/docs/dist/search/index.en.json b/docs/dist/search/index.en.json index 13a3450b..853e288a 100644 --- a/docs/dist/search/index.en.json +++ b/docs/dist/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, required) - Output directory for generated files opts (mapstring, optional) - Plugin-specific options; each key can be a single value or an array of 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 ✅ - 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, path, or field.","content":"How It Works **Overrides** allow you to set specific values for options, with support for filtering by module, path, or field."},{"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.","content":"How It Works **Disables** allow you to prevent managed mode from modifying specific options or files."},{"id":"cli/generator/generator::supported-file-options::92","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::93","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::94","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::95","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::96","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::97","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::98","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::99","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::100","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::101","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::disabling-for-external-dependencies::102","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::103","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::104","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::105","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::106","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::107","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::108","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::109","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::110","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::111","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::112","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::113","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::114","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::115","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::116","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::117","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::118","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::119","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::120","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::121","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::122","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::123","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::124","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::125","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::126","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::127","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::128","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::129","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::130","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::131","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::132","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::133","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::134","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::135","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::136","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::137","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::138","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::139","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::140","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::141","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::142","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::143","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::144","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::145","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::146","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::147","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::148","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::149","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::150","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::151","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::152","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::153","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::154","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::155","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::156","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::157","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::158","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::159","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::160","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::161","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::162","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::163","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::164","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::165","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::166","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::167","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::168","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::169","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::170","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::171","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::172","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::173","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::174","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::175","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::176","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::177","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::178","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::179","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::180","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::181","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::182","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::183","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::184","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-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, required) - Output directory for generated files opts (mapstring, optional) - Plugin-specific options; each key can be a single value or an array of 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 ✅ - 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, path, or field. Without module or path, an override applies to all files in the generation request, including","content":"How It Works **Overrides** allow you to set specific values for options, with support for filtering by module, path, or field. Without module 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::supported-file-options::92","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::93","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::94","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::95","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::96","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::97","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::98","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::99","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::100","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::101","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::102","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::disabling-for-external-dependencies::103","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::104","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::105","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::106","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::107","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::108","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::109","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::110","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::111","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::112","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::113","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::114","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::115","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::116","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::117","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::118","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::119","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::120","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::121","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::122","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::123","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::124","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::125","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::126","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::127","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::128","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::129","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::130","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::131","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::132","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::133","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::134","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::135","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::136","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::137","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::138","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::139","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::140","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::141","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::142","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::143","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::144","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::145","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::146","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::147","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::148","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::149","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::150","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::151","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::152","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::153","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::154","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::155","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::156","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::157","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::158","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::159","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::160","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::161","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::162","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::163","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::164","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::165","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::166","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::167","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::168","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::169","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::170","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::171","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::172","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::173","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::174","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::175","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::176","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::177","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::178","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::179","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::180","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::181","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::182","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::183","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::184","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::185","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/docs/dist/search/index.ru.json b/docs/dist/search/index.ru.json index 8fede7f6..6434c044 100644 --- a/docs/dist/search/index.ru.json +++ b/docs/dist/search/index.ru.json @@ -1 +1 @@ -[{"id":"api-service/overview::top::0","title":"Обзор API Service","path":"/docs/guide/api-service/overview","headings":[],"excerpt":"**Централизованный сервис выполнения protobuf‑плагинов для консистентной изолированной генерации кода**","content":"**Централизованный сервис выполнения protobuf‑плагинов для консистентной изолированной генерации кода**"},{"id":"api-service/overview::top::1","title":"Обзор API Service","path":"/docs/guide/api-service/overview","headings":[],"excerpt":"EasyP API Service устраняет хаос управления плагинами, предоставляя централизованный запуск protobuf/gRPC плагинов в изолированных Docker‑контейнерах. Он даёт единую платформу, позволяющую командам стандартизировать проц","content":"EasyP API Service устраняет хаос управления плагинами, предоставляя централизованный запуск protobuf/gRPC плагинов в изолированных Docker‑контейнерах. Он даёт единую платформу, позволяющую командам стандартизировать процесс генерации кода без операционных затрат на установку и поддержку плагинов на машинах разработчиков."},{"id":"api-service/overview::easyp-api-service::2","title":"Обзор API Service","section":"Зачем нужен EasyP API Service?","path":"/docs/guide/api-service/overview#easyp-api-service","headings":["Зачем нужен EasyP API Service?"],"excerpt":"Зачем нужен EasyP API Service?","content":"Зачем нужен EasyP API Service?"},{"id":"api-service/overview::top::3","title":"Обзор API Service","section":"Проблема","path":"/docs/guide/api-service/overview","headings":["Проблема"],"excerpt":"Проблема Управление генерацией protobuf/gRPC кода в командах порождает существенную операционную сложность:","content":"Проблема Управление генерацией protobuf/gRPC кода в командах порождает существенную операционную сложность:"},{"id":"api-service/overview::top::4","title":"Обзор API Service","section":"Несогласованность версий","path":"/docs/guide/api-service/overview","headings":["Несогласованность версий"],"excerpt":"Несогласованность версий Разработчики локально используют разные версии плагинов → расхождения в генерированном коде и падения сборки Синдром «у меня работает» при различиях окружений Требуется ручная координация, чтобы ","content":"Несогласованность версий Разработчики локально используют разные версии плагинов → расхождения в генерированном коде и падения сборки Синдром «у меня работает» при различиях окружений Требуется ручная координация, чтобы вся команда была синхронизирована по версиям"},{"id":"api-service/overview::top::5","title":"Обзор API Service","section":"Операционные накладные расходы","path":"/docs/guide/api-service/overview","headings":["Операционные накладные расходы"],"excerpt":"Операционные накладные расходы DevOps тратят время на установку и обновление плагинов на рабочих станциях Новый разработчик — ручная настройка правильных версий Обновление плагинов требует коммуникации с каждым отдельно ","content":"Операционные накладные расходы DevOps тратят время на установку и обновление плагинов на рабочих станциях Новый разработчик — ручная настройка правильных версий Обновление плагинов требует коммуникации с каждым отдельно Нет централизованного контроля утверждённых версий"},{"id":"api-service/overview::top::6","title":"Обзор API Service","section":"Риски безопасности и комплаенса","path":"/docs/guide/api-service/overview","headings":["Риски безопасности и комплаенса"],"excerpt":"Риски безопасности и комплаенса Плагины ставятся из разных источников без валидации Нет аудита: какой плагин для какого билда использовался Сложно применять политики безопасности к инструментам генерации","content":"Риски безопасности и комплаенса Плагины ставятся из разных источников без валидации Нет аудита: какой плагин для какого билда использовался Сложно применять политики безопасности к инструментам генерации"},{"id":"api-service/overview::top::7","title":"Обзор API Service","section":"Решение: централизованный запуск плагинов","path":"/docs/guide/api-service/overview","headings":["Решение: централизованный запуск плагинов"],"excerpt":"Решение: централизованный запуск плагинов EasyP API Service решает эти проблемы за счёт централизованного управления:","content":"Решение: централизованный запуск плагинов EasyP API Service решает эти проблемы за счёт централизованного управления:"},{"id":"api-service/overview::top::8","title":"Обзор API Service","section":"Решение: централизованный запуск плагинов","path":"/docs/guide/api-service/overview","headings":["Решение: централизованный запуск плагинов"],"excerpt":"Решение: централизованный запуск плагинов Проблема Решение ---------- --------- **Контроль версий** Мгновенное распространение новых версий через Docker‑образы **Операции** Команда эксплуатации управляет конфигурациями б","content":"Решение: централизованный запуск плагинов Проблема Решение ---------- --------- **Контроль версий** Мгновенное распространение новых версий через Docker‑образы **Операции** Команда эксплуатации управляет конфигурациями без доступа на машины разработчиков **Безопасность** Все плагины запускаются в изолированных контейнерах с ограничениями ресурсов **Консистентность** Единая среда выполнения вне зависимости от локальной установки **Опыт разработчика** Не нужно устанавливать и сопровождать плагины локально"},{"id":"api-service/overview::top::9","title":"Обзор API Service","section":"Архитектура","path":"/docs/guide/api-service/overview","headings":["Архитектура"],"excerpt":"Архитектура Архитектура сервиса упрощена и сфокусирована на надёжном выполнении плагинов:","content":"Архитектура Архитектура сервиса упрощена и сфокусирована на надёжном выполнении плагинов:"},{"id":"api-service/overview::api-layer::10","title":"Обзор API Service","section":"API Layer","path":"/docs/guide/api-service/overview#api-layer","headings":["API Layer"],"excerpt":"API Layer **gRPC Server** — основной API для запросов генерации Каждый запуск плагина — отдельный gRPC‑запрос Получает CodeGeneratorRequest от CLI","content":"API Layer **gRPC Server** — основной API для запросов генерации Каждый запуск плагина — отдельный gRPC‑запрос Получает CodeGeneratorRequest от CLI"},{"id":"api-service/overview::execution-engine::11","title":"Обзор API Service","section":"Execution Engine","path":"/docs/guide/api-service/overview#execution-engine","headings":["Execution Engine"],"excerpt":"Execution Engine **Docker Runtime** — изолированный запуск плагинов Подтягивает образы из публичных реестров (Docker Hub и т.п.) Применяет лимиты CPU/памяти на плагин","content":"Execution Engine **Docker Runtime** — изолированный запуск плагинов Подтягивает образы из публичных реестров (Docker Hub и т.п.) Применяет лимиты CPU/памяти на плагин"},{"id":"api-service/overview::storage-layer::12","title":"Обзор API Service","section":"Storage Layer","path":"/docs/guide/api-service/overview#storage-layer","headings":["Storage Layer"],"excerpt":"Storage Layer **PostgreSQL** хранит параметры выполнения: - Ограничения ресурсов (CPU, память) - Конфигурацию и метаданные плагинов - Логи выполнения (аудит) - _Примечание: функциональность хранения будет расширяться_","content":"Storage Layer **PostgreSQL** хранит параметры выполнения: - Ограничения ресурсов (CPU, память) - Конфигурацию и метаданные плагинов - Логи выполнения (аудит) - _Примечание: функциональность хранения будет расширяться_"},{"id":"api-service/overview::monitoring::13","title":"Обзор API Service","section":"Monitoring","path":"/docs/guide/api-service/overview#monitoring","headings":["Monitoring"],"excerpt":"Monitoring **Prometheus** — сбор метрик Отслеживает время выполнения, успешность, использование ресурсов","content":"Monitoring **Prometheus** — сбор метрик Отслеживает время выполнения, успешность, использование ресурсов"},{"id":"api-service/overview::easyp-cli::14","title":"Обзор API Service","section":"Локальное выполнение (EasyP CLI)","path":"/docs/guide/api-service/overview#easyp-cli","headings":["Локальное выполнение (EasyP CLI)"],"excerpt":"Локальное выполнение (EasyP CLI) При локальном запуске CLI поддерживает: **Installed plugins**: системно установленные protoc плагины **WASM plugins**: лёгкие WebAssembly плагины","content":"Локальное выполнение (EasyP CLI) При локальном запуске CLI поддерживает: **Installed plugins**: системно установленные protoc плагины **WASM plugins**: лёгкие WebAssembly плагины"},{"id":"api-service/overview::api-service::15","title":"Обзор API Service","section":"Удалённое выполнение (API Service)","path":"/docs/guide/api-service/overview#api-service","headings":["Удалённое выполнение (API Service)"],"excerpt":"Удалённое выполнение (API Service) При работе через сервис: **Только Docker**: плагины запускаются как контейнеры **Центральный контроль**: операционная команда управляет доступными версиями **Консистентная среда**: один","content":"Удалённое выполнение (API Service) При работе через сервис: **Только Docker**: плагины запускаются как контейнеры **Центральный контроль**: операционная команда управляет доступными версиями **Консистентная среда**: одинаковое окружение для всех разработчиков"},{"id":"api-service/overview::top::16","title":"Обзор API Service","section":"Шаги выполнения","path":"/docs/guide/api-service/overview","headings":["Шаги выполнения"],"excerpt":"Шаги выполнения **CLI Parsing**: CLI парсит локальные .proto файлы **Request Sending**: Отправляет CodeGeneratorRequest в API Service (по одному на плагин) **Parameter Lookup**: Сервис получает параметры запуска из Postg","content":"Шаги выполнения **CLI Parsing**: CLI парсит локальные .proto файлы **Request Sending**: Отправляет CodeGeneratorRequest в API Service (по одному на плагин) **Parameter Lookup**: Сервис получает параметры запуска из PostgreSQL **Docker Execution**: Запускает плагин в изолированном контейнере **Metrics Recording**: Записывает метрики после завершения **Response**: Возвращает сгенерированный код обратно в CLI"},{"id":"api-service/overview::top::17","title":"Обзор API Service","section":"Ключевые возможности","path":"/docs/guide/api-service/overview","headings":["Ключевые возможности"],"excerpt":"Ключевые возможности Возможность Описание ------------- ---------- **🐳 Изоляция плагинов** Каждый плагин в отдельном безопасном контейнере **⚙️ Контроль ресурсов** Лимиты CPU и памяти на уровне контейнера **📊 Метрики &","content":"Ключевые возможности Возможность Описание ------------- ---------- **🐳 Изоляция плагинов** Каждый плагин в отдельном безопасном контейнере **⚙️ Контроль ресурсов** Лимиты CPU и памяти на уровне контейнера **📊 Метрики & мониторинг** Полный набор Prometheus метрик **🔄 Управление версиями** Централизованно через Docker‑образы **⚡ Простой протокол** Стандарт CodeGeneratorRequest/Response **🔒 Безопасность прежде всего** Изоляция + ограниченные ресурсы"},{"id":"api-service/overview::top::18","title":"Обзор API Service","section":"Конфигурация","path":"/docs/guide/api-service/overview","headings":["Конфигурация"],"excerpt":"Конфигурация Сервис настраивается через переменные окружения.","content":"Конфигурация Сервис настраивается через переменные окружения."},{"id":"api-service/overview::top::19","title":"Обзор API Service","section":"Хранение параметров плагинов","path":"/docs/guide/api-service/overview","headings":["Хранение параметров плагинов"],"excerpt":"Хранение параметров плагинов PostgreSQL хранит параметры выполнения для каждого плагина:","content":"Хранение параметров плагинов PostgreSQL хранит параметры выполнения для каждого плагина:"},{"id":"api-service/overview::top::20","title":"Обзор API Service","section":"Хранение параметров плагинов","path":"/docs/guide/api-service/overview","headings":["Хранение параметров плагинов"],"excerpt":"Хранение параметров плагинов ::: tip Схема хранения будет расширена — аудит логов, аналитика использования, кеширование плагинов. :::","content":"Хранение параметров плагинов ::: tip Схема хранения будет расширена — аудит логов, аналитика использования, кеширование плагинов. :::"},{"id":"api-service/overview::easyp-cli::21","title":"Обзор API Service","section":"Интеграция с EasyP CLI","path":"/docs/guide/api-service/overview#easyp-cli","headings":["Интеграция с EasyP CLI"],"excerpt":"Интеграция с EasyP CLI Пример easyp.yaml для удалённого запуска:","content":"Интеграция с EasyP CLI Пример easyp.yaml для удалённого запуска:"},{"id":"api-service/overview::easyp-cli::22","title":"Обзор API Service","section":"Интеграция с EasyP CLI","path":"/docs/guide/api-service/overview#easyp-cli","headings":["Интеграция с EasyP CLI"],"excerpt":"Интеграция с EasyP CLI Запуск генерации:","content":"Интеграция с EasyP CLI Запуск генерации:"},{"id":"api-service/overview::easyp-cli::23","title":"Обзор API Service","section":"Интеграция с EasyP CLI","path":"/docs/guide/api-service/overview#easyp-cli","headings":["Интеграция с EasyP CLI"],"excerpt":"Интеграция с EasyP CLI CLI: Парсит protobuf‑файлы Отправляет отдельные запросы в сервис для каждого плагина Получает ответы с кодом Записывает файлы в указанные директории","content":"Интеграция с EasyP CLI CLI: Парсит protobuf‑файлы Отправляет отдельные запросы в сервис для каждого плагина Получает ответы с кодом Записывает файлы в указанные директории"},{"id":"api-service/overview::top::24","title":"Обзор API Service","section":"Доступные метрики","path":"/docs/guide/api-service/overview","headings":["Доступные метрики"],"excerpt":"Доступные метрики Метрики Prometheus:","content":"Доступные метрики Метрики Prometheus:"},{"id":"api-service/overview::top::25","title":"Обзор API Service","section":"Доступные метрики","path":"/docs/guide/api-service/overview","headings":["Доступные метрики"],"excerpt":"Доступные метрики Метрика Описание --------- ---------- easyp_api_service_api_grpc_server_handled_total Общее число gRPC запросов по статусам easyp_api_service_api_grpc_server_handling_seconds Гистограмма задержек gRPC e","content":"Доступные метрики Метрика Описание --------- ---------- easyp_api_service_api_grpc_server_handled_total Общее число gRPC запросов по статусам easyp_api_service_api_grpc_server_handling_seconds Гистограмма задержек gRPC easyp_api_service_generated_plugin_code_total Выполнения плагинов по имени easyp_api_service_repo_call_duration_seconds Латентность запросов к БД easyp_api_service_repo_errors_total Количество ошибок доступа к БД easyp_api_service_standard_panics_total Число восстановленных паник"},{"id":"api-service/overview::top::26","title":"Обзор API Service","section":"Характеристики производительности","path":"/docs/guide/api-service/overview","headings":["Характеристики производительности"],"excerpt":"Характеристики производительности Показатель Типичное значение Примечания ----------- ------------------- ----------- **Cold Start** 2–5 сек Первая загрузка образа **Warm Start** 100–500 мс Образ закеширован **Throughput","content":"Характеристики производительности Показатель Типичное значение Примечания ----------- ------------------- ----------- **Cold Start** 2–5 сек Первая загрузка образа **Warm Start** 100–500 мс Образ закеширован **Throughput** 20–50 одновременных Зависит от ресурсов **Memory Usage** 50–200 MB На выполнение одного плагина"},{"id":"api-service/overview::top::27","title":"Обзор API Service","section":"Изоляция контейнеров","path":"/docs/guide/api-service/overview","headings":["Изоляция контейнеров"],"excerpt":"Изоляция контейнеров Каждый плагин в отдельном эфемерном контейнере Нет сетевого доступа в процессе выполнения Лимиты CPU/памяти через Docker Контейнер удаляется после завершения","content":"Изоляция контейнеров Каждый плагин в отдельном эфемерном контейнере Нет сетевого доступа в процессе выполнения Лимиты CPU/памяти через Docker Контейнер удаляется после завершения"},{"id":"api-service/overview::api::28","title":"Обзор API Service","section":"Безопасность API","path":"/docs/guide/api-service/overview#api","headings":["Безопасность API"],"excerpt":"Безопасность API gRPC транспорт Поддержка токенов аутентификации (в продакшн окружениях) Валидация входных данных Аудитные логи в PostgreSQL","content":"Безопасность API gRPC транспорт Поддержка токенов аутентификации (в продакшн окружениях) Валидация входных данных Аудитные логи в PostgreSQL"},{"id":"api-service/overview::top::29","title":"Обзор API Service","section":"Масштабирование","path":"/docs/guide/api-service/overview","headings":["Масштабирование"],"excerpt":"Масштабирование **Горизонтальное**: несколько инстансов за балансировщиком **Ресурсы**: настройка лимитов для тяжёлых плагинов **База данных**: репликация PostgreSQL для отказоустойчивости","content":"Масштабирование **Горизонтальное**: несколько инстансов за балансировщиком **Ресурсы**: настройка лимитов для тяжёлых плагинов **База данных**: репликация PostgreSQL для отказоустойчивости"},{"id":"api-service/overview::top::30","title":"Обзор API Service","section":"Мониторинг","path":"/docs/guide/api-service/overview","headings":["Мониторинг"],"excerpt":"Мониторинг **Метрики**: Prometheus **Алертинг**: оповещения на высокие ошибки/латентность **Логи**: структурированные для аудита и отладки","content":"Мониторинг **Метрики**: Prometheus **Алертинг**: оповещения на высокие ошибки/латентность **Логи**: структурированные для аудита и отладки"},{"id":"api-service/overview::top::31","title":"Обзор API Service","section":"План развития","path":"/docs/guide/api-service/overview","headings":["План развития"],"excerpt":"План развития Запланировано: Кеширование результатов генерации Расширенный аудит и аналитика использования Поддержка приватных реестров плагинов Более умное распределение ресурсов","content":"План развития Запланировано: Кеширование результатов генерации Расширенный аудит и аналитика использования Поддержка приватных реестров плагинов Более умное распределение ресурсов"},{"id":"api-service/overview::top::32","title":"Обзор API Service","section":"Сообщество и поддержка","path":"/docs/guide/api-service/overview","headings":["Сообщество и поддержка"],"excerpt":"Сообщество и поддержка **💬 Telegram чат** — обсуждения **🐛 GitHub Issues** — баги и запросы фич **📖 Документация** — полный набор материалов","content":"Сообщество и поддержка **💬 Telegram чат** — обсуждения **🐛 GitHub Issues** — баги и запросы фич **📖 Документация** — полный набор материалов"},{"id":"api-service/overview::top::33","title":"Обзор API Service","section":"Сообщество и поддержка","path":"/docs/guide/api-service/overview","headings":["Сообщество и поддержка"],"excerpt":"Сообщество и поддержка *Упростите свои protobuf‑воркфлоу с централизованным управлением выполнением плагинов.*","content":"Сообщество и поддержка *Упростите свои protobuf‑воркфлоу с централизованным управлением выполнением плагинов.*"},{"id":"ci-cd/github-actions::top::0","title":"GitHub Actions","path":"/docs/guide/ci-cd/github-actions","headings":[],"excerpt":"Полное руководство по интеграции EasyP в конвейеры GitHub Actions для линтинга, проверки несовместимых изменений, генерации кода и автоматизации релизов.","content":"Полное руководство по интеграции EasyP в конвейеры GitHub Actions для линтинга, проверки несовместимых изменений, генерации кода и автоматизации релизов."},{"id":"ci-cd/github-actions::easyp-ci::1","title":"GitHub Actions","section":"Зачем использовать EasyP в CI","path":"/docs/guide/ci-cd/github-actions#easyp-ci","headings":["Зачем использовать EasyP в CI"],"excerpt":"Зачем использовать EasyP в CI Встраивание EasyP в GitHub Actions даёт: Единообразие правил линтинга и генерации между разработчиками. Автоматическое выявление несовместимых изменений (breaking changes) до мержа. Гарантию","content":"Зачем использовать EasyP в CI Встраивание EasyP в GitHub Actions даёт: Единообразие правил линтинга и генерации между разработчиками. Автоматическое выявление несовместимых изменений (breaking changes) до мержа. Гарантию, что сгенерированный код не «устарел» относительно .proto. Возможность централизованной проверки зависимостей и версии конфигурации."},{"id":"ci-cd/github-actions::top::2","title":"GitHub Actions","section":"Предварительные требования","path":"/docs/guide/ci-cd/github-actions","headings":["Предварительные требования"],"excerpt":"Предварительные требования Репозиторий содержит файл конфигурации easyp.yaml (или находится в корне, если запускается без --cfg). Установлены / определены зависимости в секции deps (если нужны внешние импорты). Для прива","content":"Предварительные требования Репозиторий содержит файл конфигурации easyp.yaml (или находится в корне, если запускается без --cfg). Установлены / определены зависимости в секции deps (если нужны внешние импорты). Для приватных Git-репозиториев настроен доступ (SSH key / deploy key / токен). В workflow есть шаги по установке Go (если EasyP поставляется через go install) или заранее подготовленный бинарь."},{"id":"ci-cd/github-actions::top::3","title":"GitHub Actions","section":"Базовый пример (быстрый старт)","path":"/docs/guide/ci-cd/github-actions","headings":["Базовый пример (быстрый старт)"],"excerpt":"Базовый пример (быстрый старт) Минимальный workflow для проверки линта и несовместимых изменений при открытия Pull Request:","content":"Базовый пример (быстрый старт) Минимальный workflow для проверки линта и несовместимых изменений при открытия Pull Request:"},{"id":"ci-cd/github-actions::top::4","title":"GitHub Actions","section":"Базовый пример (быстрый старт)","path":"/docs/guide/ci-cd/github-actions","headings":["Базовый пример (быстрый старт)"],"excerpt":"Базовый пример (быстрый старт) ```yaml name: easyp-ci","content":"Базовый пример (быстрый старт) ```yaml name: easyp-ci"},{"id":"ci-cd/github-actions::top::5","title":"GitHub Actions","section":"Базовый пример (быстрый старт)","path":"/docs/guide/ci-cd/github-actions","headings":["Базовый пример (быстрый старт)"],"excerpt":"Базовый пример (быстрый старт) on: pull_request: paths: - '**/*.proto' - 'easyp.yaml'","content":"Базовый пример (быстрый старт) on: pull_request: paths: - '**/*.proto' - 'easyp.yaml'"},{"id":"ci-cd/github-actions::top::6","title":"GitHub Actions","section":"Базовый пример (быстрый старт)","path":"/docs/guide/ci-cd/github-actions","headings":["Базовый пример (быстрый старт)"],"excerpt":"Базовый пример (быстрый старт) jobs: lint-and-breaking: runs-on: ubuntu-latest","content":"Базовый пример (быстрый старт) jobs: lint-and-breaking: runs-on: ubuntu-latest"},{"id":"ci-cd/github-actions::top::7","title":"GitHub Actions","section":"Базовый пример (быстрый старт)","path":"/docs/guide/ci-cd/github-actions","headings":["Базовый пример (быстрый старт)"],"excerpt":"Базовый пример (быстрый старт) steps: - name: Checkout uses: actions/checkout@v4","content":"Базовый пример (быстрый старт) steps: - name: Checkout uses: actions/checkout@v4"},{"id":"ci-cd/github-actions::top::8","title":"GitHub Actions","section":"Базовый пример (быстрый старт)","path":"/docs/guide/ci-cd/github-actions","headings":["Базовый пример (быстрый старт)"],"excerpt":"Базовый пример (быстрый старт) name: Setup Go uses: actions/setup-go@v5 with: go-version: '1.22'","content":"Базовый пример (быстрый старт) name: Setup Go uses: actions/setup-go@v5 with: go-version: '1.22'"},{"id":"ci-cd/github-actions::top::9","title":"GitHub Actions","section":"Базовый пример (быстрый старт)","path":"/docs/guide/ci-cd/github-actions","headings":["Базовый пример (быстрый старт)"],"excerpt":"Базовый пример (быстрый старт) name: Install EasyP run: go install github.com/easyp-tech/easyp/cmd/easyp@latest","content":"Базовый пример (быстрый старт) name: Install EasyP run: go install github.com/easyp-tech/easyp/cmd/easyp@latest"},{"id":"ci-cd/github-actions::top::10","title":"GitHub Actions","section":"Базовый пример (быстрый старт)","path":"/docs/guide/ci-cd/github-actions","headings":["Базовый пример (быстрый старт)"],"excerpt":"Базовый пример (быстрый старт) name: Verify EasyP version run: which easyp easyp version","content":"Базовый пример (быстрый старт) name: Verify EasyP version run: which easyp easyp version"},{"id":"ci-cd/github-actions::top::11","title":"GitHub Actions","section":"Базовый пример (быстрый старт)","path":"/docs/guide/ci-cd/github-actions","headings":["Базовый пример (быстрый старт)"],"excerpt":"Базовый пример (быстрый старт) name: Lint run: easyp lint","content":"Базовый пример (быстрый старт) name: Lint run: easyp lint"},{"id":"ci-cd/github-actions::top::12","title":"GitHub Actions","section":"Базовый пример (быстрый старт)","path":"/docs/guide/ci-cd/github-actions","headings":["Базовый пример (быстрый старт)"],"excerpt":"Базовый пример (быстрый старт) name: Breaking changes check (against main) run: easyp breaking --against git-ref=origin/main ```","content":"Базовый пример (быстрый старт) name: Breaking changes check (against main) run: easyp breaking --against git-ref=origin/main ```"},{"id":"ci-cd/github-actions::easyp::13","title":"GitHub Actions","section":"Установка EasyP","path":"/docs/guide/ci-cd/github-actions#easyp","headings":["Установка EasyP"],"excerpt":"Установка EasyP Варианты: Через go install (как в примере выше). Использование заранее собранного бинаря (артефакт релиза).","content":"Установка EasyP Варианты: Через go install (как в примере выше). Использование заранее собранного бинаря (артефакт релиза)."},{"id":"ci-cd/github-actions::top::14","title":"GitHub Actions","section":"Кэширование","path":"/docs/guide/ci-cd/github-actions","headings":["Кэширование"],"excerpt":"Кэширование Для ускорения повторных сборок можно кэшировать: Go модульный кеш (если используете генерацию с плагинами Go). Внешние зависимые Git-клонирования (папки vendor или содержимое deps при использовании easyp mod ","content":"Кэширование Для ускорения повторных сборок можно кэшировать: Go модульный кеш (если используете генерацию с плагинами Go). Внешние зависимые Git-клонирования (папки vendor или содержимое deps при использовании easyp mod download / easyp mod update). Сгенерированный код (если он тяжёлый, но чаще генерируется заново)."},{"id":"ci-cd/github-actions::top::15","title":"GitHub Actions","section":"Кэширование","path":"/docs/guide/ci-cd/github-actions","headings":["Кэширование"],"excerpt":"Кэширование Пример кэширования Go:","content":"Кэширование Пример кэширования Go:"},{"id":"ci-cd/github-actions::top::16","title":"GitHub Actions","section":"Кэширование","path":"/docs/guide/ci-cd/github-actions","headings":["Кэширование"],"excerpt":"Кэширование Пример кэширования каталога зависимостей EasyP (если вы используете локальный vendor-подход):","content":"Кэширование Пример кэширования каталога зависимостей EasyP (если вы используете локальный vendor-подход):"},{"id":"ci-cd/github-actions::top::17","title":"GitHub Actions","section":"Кэширование","path":"/docs/guide/ci-cd/github-actions","headings":["Кэширование"],"excerpt":"Кэширование (Создайте .easyp/deps как целевой каталог, если ваша стратегия скачивания такова.)","content":"Кэширование (Создайте .easyp/deps как целевой каталог, если ваша стратегия скачивания такова.)"},{"id":"ci-cd/github-actions::top::18","title":"GitHub Actions","section":"Линтинг","path":"/docs/guide/ci-cd/github-actions","headings":["Линтинг"],"excerpt":"Линтинг Рекомендуется: В PR: всегда запускать. На main: можно запускать для верификации перед релизом.","content":"Линтинг Рекомендуется: В PR: всегда запускать. На main: можно запускать для верификации перед релизом."},{"id":"ci-cd/github-actions::top::19","title":"GitHub Actions","section":"Линтинг","path":"/docs/guide/ci-cd/github-actions","headings":["Линтинг"],"excerpt":"Линтинг Расширенный пример с выводом подробностей и игнорированием комментариев (если включено в конфиг):","content":"Линтинг Расширенный пример с выводом подробностей и игнорированием комментариев (если включено в конфиг):"},{"id":"ci-cd/github-actions::breaking-changes::20","title":"GitHub Actions","section":"Проверка несовместимых изменений (Breaking Changes)","path":"/docs/guide/ci-cd/github-actions#breaking-changes","headings":["Проверка несовместимых изменений (Breaking Changes)"],"excerpt":"Проверка несовместимых изменений (Breaking Changes) EasyP может сравнивать текущее состояние против ветки / коммита / тега.","content":"Проверка несовместимых изменений (Breaking Changes) EasyP может сравнивать текущее состояние против ветки / коммита / тега."},{"id":"ci-cd/github-actions::breaking-changes::21","title":"GitHub Actions","section":"Проверка несовместимых изменений (Breaking Changes)","path":"/docs/guide/ci-cd/github-actions#breaking-changes","headings":["Проверка несовместимых изменений (Breaking Changes)"],"excerpt":"Проверка несовместимых изменений (Breaking Changes) Примеры: ```bash Сравнить против origin/main easyp breaking --against git-ref=origin/main","content":"Проверка несовместимых изменений (Breaking Changes) Примеры: ```bash Сравнить против origin/main easyp breaking --against git-ref=origin/main"},{"id":"ci-cd/github-actions::breaking-changes::22","title":"GitHub Actions","section":"Проверка несовместимых изменений (Breaking Changes)","path":"/docs/guide/ci-cd/github-actions#breaking-changes","headings":["Проверка несовместимых изменений (Breaking Changes)"],"excerpt":"Проверка несовместимых изменений (Breaking Changes) Сравнить против тега релиза easyp breaking --against git-ref=v1.5.2","content":"Проверка несовместимых изменений (Breaking Changes) Сравнить против тега релиза easyp breaking --against git-ref=v1.5.2"},{"id":"ci-cd/github-actions::breaking-changes::23","title":"GitHub Actions","section":"Проверка несовместимых изменений (Breaking Changes)","path":"/docs/guide/ci-cd/github-actions#breaking-changes","headings":["Проверка несовместимых изменений (Breaking Changes)"],"excerpt":"Проверка несовместимых изменений (Breaking Changes) Игнорировать определённые правила (если у вас настроено в easyp.yaml) easyp breaking ```","content":"Проверка несовместимых изменений (Breaking Changes) Игнорировать определённые правила (если у вас настроено в easyp.yaml) easyp breaking ```"},{"id":"ci-cd/github-actions::breaking-changes::24","title":"GitHub Actions","section":"Проверка несовместимых изменений (Breaking Changes)","path":"/docs/guide/ci-cd/github-actions#breaking-changes","headings":["Проверка несовместимых изменений (Breaking Changes)"],"excerpt":"Проверка несовместимых изменений (Breaking Changes) Workflow шаг:","content":"Проверка несовместимых изменений (Breaking Changes) Workflow шаг:"},{"id":"ci-cd/github-actions::breaking-changes::25","title":"GitHub Actions","section":"Проверка несовместимых изменений (Breaking Changes)","path":"/docs/guide/ci-cd/github-actions#breaking-changes","headings":["Проверка несовместимых изменений (Breaking Changes)"],"excerpt":"Проверка несовместимых изменений (Breaking Changes)","content":"Проверка несовместимых изменений (Breaking Changes)"},{"id":"ci-cd/github-actions::breaking-changes::26","title":"GitHub Actions","section":"Проверка несовместимых изменений (Breaking Changes)","path":"/docs/guide/ci-cd/github-actions#breaking-changes","headings":["Проверка несовместимых изменений (Breaking Changes)"],"excerpt":"Проверка несовместимых изменений (Breaking Changes) Если нужно «мягко» пропустить (например, выводить предупреждения, но не падать билд):","content":"Проверка несовместимых изменений (Breaking Changes) Если нужно «мягко» пропустить (например, выводить предупреждения, но не падать билд):"},{"id":"ci-cd/github-actions::breaking-changes::27","title":"GitHub Actions","section":"Проверка несовместимых изменений (Breaking Changes)","path":"/docs/guide/ci-cd/github-actions#breaking-changes","headings":["Проверка несовместимых изменений (Breaking Changes)"],"excerpt":"Проверка несовместимых изменений (Breaking Changes)","content":"Проверка несовместимых изменений (Breaking Changes)"},{"id":"ci-cd/github-actions::top::28","title":"GitHub Actions","section":"Генерация кода","path":"/docs/guide/ci-cd/github-actions","headings":["Генерация кода"],"excerpt":"Генерация кода Обычно для генерации:","content":"Генерация кода Обычно для генерации:"},{"id":"ci-cd/github-actions::top::29","title":"GitHub Actions","section":"Генерация кода","path":"/docs/guide/ci-cd/github-actions","headings":["Генерация кода"],"excerpt":"Генерация кода Если нужно явно указать конфиг:","content":"Генерация кода Если нужно явно указать конфиг:"},{"id":"ci-cd/github-actions::top::30","title":"GitHub Actions","section":"Генерация кода","path":"/docs/guide/ci-cd/github-actions","headings":["Генерация кода"],"excerpt":"Генерация кода Можно добавить проверку «не осталось ли не закоммиченных изменений» (гарантия, что сгенерированный код актуален):","content":"Генерация кода Можно добавить проверку «не осталось ли не закоммиченных изменений» (гарантия, что сгенерированный код актуален):"},{"id":"ci-cd/github-actions::matrix-strategy::31","title":"GitHub Actions","section":"Матрица (Matrix strategy)","path":"/docs/guide/ci-cd/github-actions#matrix-strategy","headings":["Матрица (Matrix strategy)"],"excerpt":"Матрица (Matrix strategy) Если у вас несколько вариантов конфигураций или разных языков генерации (через плагины), можно использовать matrix:","content":"Матрица (Matrix strategy) Если у вас несколько вариантов конфигураций или разных языков генерации (через плагины), можно использовать matrix:"},{"id":"ci-cd/github-actions::matrix-strategy::32","title":"GitHub Actions","section":"Матрица (Matrix strategy)","path":"/docs/guide/ci-cd/github-actions#matrix-strategy","headings":["Матрица (Matrix strategy)"],"excerpt":"Матрица (Matrix strategy) ```yaml jobs: generate: runs-on: ubuntu-latest strategy: fail-fast: false matrix: lang: [go, python] steps: - uses: actions/checkout@v4","content":"Матрица (Matrix strategy) ```yaml jobs: generate: runs-on: ubuntu-latest strategy: fail-fast: false matrix: lang: [go, python] steps: - uses: actions/checkout@v4"},{"id":"ci-cd/github-actions::matrix-strategy::33","title":"GitHub Actions","section":"Матрица (Matrix strategy)","path":"/docs/guide/ci-cd/github-actions#matrix-strategy","headings":["Матрица (Matrix strategy)"],"excerpt":"Матрица (Matrix strategy) name: Setup Go (only for go) if: matrix.lang == 'go' uses: actions/setup-go@v5 with: go-version: '1.22'","content":"Матрица (Matrix strategy) name: Setup Go (only for go) if: matrix.lang == 'go' uses: actions/setup-go@v5 with: go-version: '1.22'"},{"id":"ci-cd/github-actions::matrix-strategy::34","title":"GitHub Actions","section":"Матрица (Matrix strategy)","path":"/docs/guide/ci-cd/github-actions#matrix-strategy","headings":["Матрица (Matrix strategy)"],"excerpt":"Матрица (Matrix strategy) name: Install EasyP run: go install github.com/easyp-tech/easyp/cmd/easyp@latest","content":"Матрица (Matrix strategy) name: Install EasyP run: go install github.com/easyp-tech/easyp/cmd/easyp@latest"},{"id":"ci-cd/github-actions::matrix-strategy::35","title":"GitHub Actions","section":"Матрица (Matrix strategy)","path":"/docs/guide/ci-cd/github-actions#matrix-strategy","headings":["Матрица (Matrix strategy)"],"excerpt":"Матрица (Matrix strategy) name: Generate run: if [ \"${{ matrix.lang }}\" = \"go\" ]; then easyp generate elif [ \"${{ matrix.lang }}\" = \"python\" ]; then easyp generate --plugin python fi ```","content":"Матрица (Matrix strategy) name: Generate run: if [ \"${{ matrix.lang }}\" = \"go\" ]; then easyp generate elif [ \"${{ matrix.lang }}\" = \"python\" ]; then easyp generate --plugin python fi ```"},{"id":"ci-cd/github-actions::deps::36","title":"GitHub Actions","section":"Работа с приватными репозиториями (deps)","path":"/docs/guide/ci-cd/github-actions#deps","headings":["Работа с приватными репозиториями (deps)"],"excerpt":"Работа с приватными репозиториями (deps) Если вы указываете приватные Git-пакеты в секции deps:","content":"Работа с приватными репозиториями (deps) Если вы указываете приватные Git-пакеты в секции deps:"},{"id":"ci-cd/github-actions::deps::37","title":"GitHub Actions","section":"Работа с приватными репозиториями (deps)","path":"/docs/guide/ci-cd/github-actions#deps","headings":["Работа с приватными репозиториями (deps)"],"excerpt":"Работа с приватными репозиториями (deps) Настройте deploy key или используйте GIT_SSH_COMMAND с токеном. Добавьте known_hosts (либо установите StrictHostKeyChecking=no для внутренних систем, но осознанно).","content":"Работа с приватными репозиториями (deps) Настройте deploy key или используйте GIT_SSH_COMMAND с токеном. Добавьте known_hosts (либо установите StrictHostKeyChecking=no для внутренних систем, но осознанно)."},{"id":"ci-cd/github-actions::deps::38","title":"GitHub Actions","section":"Работа с приватными репозиториями (deps)","path":"/docs/guide/ci-cd/github-actions#deps","headings":["Работа с приватными репозиториями (deps)"],"excerpt":"Работа с приватными репозиториями (deps) Пример:","content":"Работа с приватными репозиториями (deps) Пример:"},{"id":"ci-cd/github-actions::deps::39","title":"GitHub Actions","section":"Работа с приватными репозиториями (deps)","path":"/docs/guide/ci-cd/github-actions#deps","headings":["Работа с приватными репозиториями (deps)"],"excerpt":"Работа с приватными репозиториями (deps) ```yaml name: Prepare SSH run: mkdir -p ~/.ssh echo \"${{ secrets.DEPLOY_KEY }}\" > ~/.ssh/id_rsa chmod 600 ~/.ssh/id_rsa ssh-keyscan github.com >> ~/.ssh/known_hosts","content":"Работа с приватными репозиториями (deps) ```yaml name: Prepare SSH run: mkdir -p ~/.ssh echo \"${{ secrets.DEPLOY_KEY }}\" > ~/.ssh/id_rsa chmod 600 ~/.ssh/id_rsa ssh-keyscan github.com >> ~/.ssh/known_hosts"},{"id":"ci-cd/github-actions::deps::40","title":"GitHub Actions","section":"Работа с приватными репозиториями (deps)","path":"/docs/guide/ci-cd/github-actions#deps","headings":["Работа с приватными репозиториями (deps)"],"excerpt":"Работа с приватными репозиториями (deps) name: Update deps run: easyp mod update ```","content":"Работа с приватными репозиториями (deps) name: Update deps run: easyp mod update ```"},{"id":"ci-cd/github-actions::top::41","title":"GitHub Actions","section":"Оптимизация времени сборки","path":"/docs/guide/ci-cd/github-actions","headings":["Оптимизация времени сборки"],"excerpt":"Оптимизация времени сборки Используйте кэш для Go / deps. Запускайте линт/брейкинг только если изменились .proto или easyp.yaml (paths фильтр). Разделяйте workflow: быстрый линт в PR, тяжелая генерация в push на main. Вы","content":"Оптимизация времени сборки Используйте кэш для Go / deps. Запускайте линт/брейкинг только если изменились .proto или easyp.yaml (paths фильтр). Разделяйте workflow: быстрый линт в PR, тяжелая генерация в push на main. Выносите генерацию OpenAPI / gRPC-Gateway в отдельный job (параллелизм)."},{"id":"ci-cd/github-actions::workflow::42","title":"GitHub Actions","section":"Продвинутый workflow (многостадийный)","path":"/docs/guide/ci-cd/github-actions#workflow","headings":["Продвинутый workflow (многостадийный)"],"excerpt":"Продвинутый workflow (многостадийный) ```yaml name: easyp-pipeline","content":"Продвинутый workflow (многостадийный) ```yaml name: easyp-pipeline"},{"id":"ci-cd/github-actions::workflow::43","title":"GitHub Actions","section":"Продвинутый workflow (многостадийный)","path":"/docs/guide/ci-cd/github-actions#workflow","headings":["Продвинутый workflow (многостадийный)"],"excerpt":"Продвинутый workflow (многостадийный) on: pull_request: paths: - '**/*.proto' - 'easyp.yaml' push: branches: - main","content":"Продвинутый workflow (многостадийный) on: pull_request: paths: - '**/*.proto' - 'easyp.yaml' push: branches: - main"},{"id":"ci-cd/github-actions::workflow::44","title":"GitHub Actions","section":"Продвинутый workflow (многостадийный)","path":"/docs/guide/ci-cd/github-actions#workflow","headings":["Продвинутый workflow (многостадийный)"],"excerpt":"Продвинутый workflow (многостадийный) jobs: validate: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4","content":"Продвинутый workflow (многостадийный) jobs: validate: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4"},{"id":"ci-cd/github-actions::workflow::45","title":"GitHub Actions","section":"Продвинутый workflow (многостадийный)","path":"/docs/guide/ci-cd/github-actions#workflow","headings":["Продвинутый workflow (многостадийный)"],"excerpt":"Продвинутый workflow (многостадийный) uses: actions/setup-go@v5 with: go-version: '1.22'","content":"Продвинутый workflow (многостадийный) uses: actions/setup-go@v5 with: go-version: '1.22'"},{"id":"ci-cd/github-actions::workflow::46","title":"GitHub Actions","section":"Продвинутый workflow (многостадийный)","path":"/docs/guide/ci-cd/github-actions#workflow","headings":["Продвинутый workflow (многостадийный)"],"excerpt":"Продвинутый workflow (многостадийный) name: Install EasyP run: go install github.com/easyp-tech/easyp/cmd/easyp@latest","content":"Продвинутый workflow (многостадийный) name: Install EasyP run: go install github.com/easyp-tech/easyp/cmd/easyp@latest"},{"id":"ci-cd/github-actions::workflow::47","title":"GitHub Actions","section":"Продвинутый workflow (многостадийный)","path":"/docs/guide/ci-cd/github-actions#workflow","headings":["Продвинутый workflow (многостадийный)"],"excerpt":"Продвинутый workflow (многостадийный) name: Lint run: easyp lint","content":"Продвинутый workflow (многостадийный) name: Lint run: easyp lint"},{"id":"ci-cd/github-actions::workflow::48","title":"GitHub Actions","section":"Продвинутый workflow (многостадийный)","path":"/docs/guide/ci-cd/github-actions#workflow","headings":["Продвинутый workflow (многостадийный)"],"excerpt":"Продвинутый workflow (многостадийный) name: Breaking check (against main) if: github.event_name == 'pull_request' run: easyp breaking --against git-ref=origin/main","content":"Продвинутый workflow (многостадийный) name: Breaking check (against main) if: github.event_name == 'pull_request' run: easyp breaking --against git-ref=origin/main"},{"id":"ci-cd/github-actions::workflow::49","title":"GitHub Actions","section":"Продвинутый workflow (многостадийный)","path":"/docs/guide/ci-cd/github-actions#workflow","headings":["Продвинутый workflow (многостадийный)"],"excerpt":"Продвинутый workflow (многостадийный) generate: needs: validate if: github.event_name == 'push' runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-go@v5 with: go-version: '1.22' - name: Insta","content":"Продвинутый workflow (многостадийный) generate: needs: validate if: github.event_name == 'push' runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-go@v5 with: go-version: '1.22' - name: Install EasyP run: go install github.com/easyp-tech/easyp/cmd/easyp@latest - name: Generate Code run: easyp generate - name: Check diffs run: if [ -n \"$(git status --porcelain)\" ]; then echo \"Generated files changed after generate step.\" git diff --name-only exit 1 fi ```"},{"id":"ci-cd/github-actions::top::50","title":"GitHub Actions","section":"Автоматизация релиза (пример)","path":"/docs/guide/ci-cd/github-actions","headings":["Автоматизация релиза (пример)"],"excerpt":"Автоматизация релиза (пример) Можно добавить workflow, который по тегу создаёт релиз и валидирует proto:","content":"Автоматизация релиза (пример) Можно добавить workflow, который по тегу создаёт релиз и валидирует proto:"},{"id":"ci-cd/github-actions::top::51","title":"GitHub Actions","section":"Автоматизация релиза (пример)","path":"/docs/guide/ci-cd/github-actions","headings":["Автоматизация релиза (пример)"],"excerpt":"Автоматизация релиза (пример) ```yaml name: release-verify","content":"Автоматизация релиза (пример) ```yaml name: release-verify"},{"id":"ci-cd/github-actions::top::52","title":"GitHub Actions","section":"Автоматизация релиза (пример)","path":"/docs/guide/ci-cd/github-actions","headings":["Автоматизация релиза (пример)"],"excerpt":"Автоматизация релиза (пример) on: push: tags: - 'v*.*.*'","content":"Автоматизация релиза (пример) on: push: tags: - 'v*.*.*'"},{"id":"ci-cd/github-actions::top::53","title":"GitHub Actions","section":"Автоматизация релиза (пример)","path":"/docs/guide/ci-cd/github-actions","headings":["Автоматизация релиза (пример)"],"excerpt":"Автоматизация релиза (пример) jobs: release-check: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4","content":"Автоматизация релиза (пример) jobs: release-check: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4"},{"id":"ci-cd/github-actions::top::54","title":"GitHub Actions","section":"Автоматизация релиза (пример)","path":"/docs/guide/ci-cd/github-actions","headings":["Автоматизация релиза (пример)"],"excerpt":"Автоматизация релиза (пример) uses: actions/setup-go@v5 with: go-version: '1.22'","content":"Автоматизация релиза (пример) uses: actions/setup-go@v5 with: go-version: '1.22'"},{"id":"ci-cd/github-actions::top::55","title":"GitHub Actions","section":"Автоматизация релиза (пример)","path":"/docs/guide/ci-cd/github-actions","headings":["Автоматизация релиза (пример)"],"excerpt":"Автоматизация релиза (пример) name: Install EasyP run: go install github.com/easyp-tech/easyp/cmd/easyp@latest","content":"Автоматизация релиза (пример) name: Install EasyP run: go install github.com/easyp-tech/easyp/cmd/easyp@latest"},{"id":"ci-cd/github-actions::top::56","title":"GitHub Actions","section":"Автоматизация релиза (пример)","path":"/docs/guide/ci-cd/github-actions","headings":["Автоматизация релиза (пример)"],"excerpt":"Автоматизация релиза (пример) name: Lint run: easyp lint","content":"Автоматизация релиза (пример) name: Lint run: easyp lint"},{"id":"ci-cd/github-actions::top::57","title":"GitHub Actions","section":"Автоматизация релиза (пример)","path":"/docs/guide/ci-cd/github-actions","headings":["Автоматизация релиза (пример)"],"excerpt":"Автоматизация релиза (пример) name: Breaking vs previous tag run: PREV_TAG=$(git tag --sort=-creatordate grep -v \"${GITHUB_REF_NAME}\" head -n1 true) if [ -n \"$PREV_TAG\" ]; then echo \"Comparing against $PREV_TAG\" easyp br","content":"Автоматизация релиза (пример) name: Breaking vs previous tag run: PREV_TAG=$(git tag --sort=-creatordate grep -v \"${GITHUB_REF_NAME}\" head -n1 true) if [ -n \"$PREV_TAG\" ]; then echo \"Comparing against $PREV_TAG\" easyp breaking --against git-ref=$PREV_TAG else echo \"No previous tag, skipping breaking check\" fi"},{"id":"ci-cd/github-actions::top::58","title":"GitHub Actions","section":"Автоматизация релиза (пример)","path":"/docs/guide/ci-cd/github-actions","headings":["Автоматизация релиза (пример)"],"excerpt":"Автоматизация релиза (пример) name: Generate to ensure consistency run: easyp generate ```","content":"Автоматизация релиза (пример) name: Generate to ensure consistency run: easyp generate ```"},{"id":"ci-cd/github-actions::top::59","title":"GitHub Actions","section":"Отладка","path":"/docs/guide/ci-cd/github-actions","headings":["Отладка"],"excerpt":"Отладка Если нужно больше логов:","content":"Отладка Если нужно больше логов:"},{"id":"ci-cd/github-actions::top::60","title":"GitHub Actions","section":"Отладка","path":"/docs/guide/ci-cd/github-actions","headings":["Отладка"],"excerpt":"Отладка Добавьте вывод окружения для диагностики:","content":"Отладка Добавьте вывод окружения для диагностики:"},{"id":"ci-cd/github-actions::top::61","title":"GitHub Actions","section":"Переменные окружения (примерно)","path":"/docs/guide/ci-cd/github-actions","headings":["Переменные окружения (примерно)"],"excerpt":"Переменные окружения (примерно) Переменная Назначение ------------ ----------- EASYP_SERVICE_HOST Хост удалённого API Service (если используете удалённые плагины) EASYP_SERVICE_GRPC_PORT Порт удалённого сервиса GIT_SSH_C","content":"Переменные окружения (примерно) Переменная Назначение ------------ ----------- EASYP_SERVICE_HOST Хост удалённого API Service (если используете удалённые плагины) EASYP_SERVICE_GRPC_PORT Порт удалённого сервиса GIT_SSH_COMMAND Кастомная команда SSH (частные репозитории) GOFLAGS Можно выставить -mod=readonly для Go генерации"},{"id":"ci-cd/github-actions::top::62","title":"GitHub Actions","section":"Переменные окружения (примерно)","path":"/docs/guide/ci-cd/github-actions","headings":["Переменные окружения (примерно)"],"excerpt":"Переменные окружения (примерно) (Используйте только те, что действительно нужны вашему проекту.)","content":"Переменные окружения (примерно) (Используйте только те, что действительно нужны вашему проекту.)"},{"id":"ci-cd/github-actions::top::63","title":"GitHub Actions","section":"Частые ошибки","path":"/docs/guide/ci-cd/github-actions","headings":["Частые ошибки"],"excerpt":"Частые ошибки Симптом Причина Решение --------- --------- --------- Линт падает на неизвестных правилах Правила указаны в easyp.yaml, но версия EasyP их не поддерживает Обновить EasyP (go install ...@latest) breaking сра","content":"Частые ошибки Симптом Причина Решение --------- --------- --------- Линт падает на неизвестных правилах Правила указаны в easyp.yaml, но версия EasyP их не поддерживает Обновить EasyP (go install ...@latest) breaking сравнение ничего не находит Неверный --against (нет fetch удалённой ветки) Добавить шаг git fetch --all --tags Сгенерированный код в PR отличается от main Отсутствует проверка генерации в CI Добавить шаг «Ensure generated code is up-to-date» Приватные deps не скачиваются Нет SSH ключа или токена Настроить secrets + шаг подготовки SSH Долгое выполнение Отсутствует кеш Добавить кэширование модулей и deps"},{"id":"ci-cd/github-actions::top::64","title":"GitHub Actions","section":"Рекомендации по поддержке","path":"/docs/guide/ci-cd/github-actions","headings":["Рекомендации по поддержке"],"excerpt":"Рекомендации по поддержке Заготовить шаблон workflow и копировать между сервисами (DRY). Включить paths фильтры, чтобы не тратить минуты на нерелевантные изменения. Проверять easyp.yaml при изменениях отдельно — можно за","content":"Рекомендации по поддержке Заготовить шаблон workflow и копировать между сервисами (DRY). Включить paths фильтры, чтобы не тратить минуты на нерелевантные изменения. Проверять easyp.yaml при изменениях отдельно — можно запускать «конфигурационный тест» (например, easyp lint без файлов, чтобы убедиться, что конфиг валиден). При появлении новых правил линтера обновляйте конфиг и фиксируйте ошибки сразу в одной ветке."},{"id":"ci-cd/github-actions::top::65","title":"GitHub Actions","section":"Рекомендации по поддержке","path":"/docs/guide/ci-cd/github-actions","headings":["Рекомендации по поддержке"],"excerpt":"Рекомендации по поддержке Готово: вы можете расширять разделы генерации, добавлять OpenAPI / grpc-gateway / validate плагины, матрицы по языкам и интегрировать тесты поверх сгенерированного кода, если требуется.","content":"Рекомендации по поддержке Готово: вы можете расширять разделы генерации, добавлять OpenAPI / grpc-gateway / validate плагины, матрицы по языкам и интегрировать тесты поверх сгенерированного кода, если требуется."},{"id":"ci-cd/gitlab::top::0","title":"GitLab CI","section":"В процессе разработки","path":"/docs/guide/ci-cd/gitlab","headings":["В процессе разработки"],"excerpt":"В процессе разработки Документация по интеграции EasyP с GitLab CI находится в процессе подготовки. Планируемые разделы: Быстрый старт (пример .gitlab-ci.yml для линтинга и проверки несовместимых изменений) Кэширование з","content":"В процессе разработки Документация по интеграции EasyP с GitLab CI находится в процессе подготовки. Планируемые разделы: Быстрый старт (пример .gitlab-ci.yml для линтинга и проверки несовместимых изменений) Кэширование зависимостей и ускорение сборок Генерация кода и проверка актуальности артефактов Работа с приватными Git-репозиториями в deps Матрицы (parallel jobs) для разных языков и плагинов Автоматизация релизов по тегам"},{"id":"ci-cd/gitlab::top::1","title":"GitLab CI","section":"В процессе разработки","path":"/docs/guide/ci-cd/gitlab","headings":["В процессе разработки"],"excerpt":"В процессе разработки Если вам нужен пример прямо сейчас, базовый минимальный вариант может выглядеть так:","content":"В процессе разработки Если вам нужен пример прямо сейчас, базовый минимальный вариант может выглядеть так:"},{"id":"ci-cd/gitlab::top::2","title":"GitLab CI","section":"В процессе разработки","path":"/docs/guide/ci-cd/gitlab","headings":["В процессе разработки"],"excerpt":"В процессе разработки ```yaml stages: - validate - generate","content":"В процессе разработки ```yaml stages: - validate - generate"},{"id":"ci-cd/gitlab::top::3","title":"GitLab CI","section":"В процессе разработки","path":"/docs/guide/ci-cd/gitlab","headings":["В процессе разработки"],"excerpt":"В процессе разработки variables: GO_VERSION: \"1.22\"","content":"В процессе разработки variables: GO_VERSION: \"1.22\""},{"id":"ci-cd/gitlab::top::4","title":"GitLab CI","section":"В процессе разработки","path":"/docs/guide/ci-cd/gitlab","headings":["В процессе разработки"],"excerpt":"В процессе разработки validate: stage: validate image: golang:${GO_VERSION} before_script: - go install github.com/easyp-tech/easyp/cmd/easyp@latest - echo \"EasyP version:\" - easyp version # При необходимости: git fetch ","content":"В процессе разработки validate: stage: validate image: golang:${GO_VERSION} before_script: - go install github.com/easyp-tech/easyp/cmd/easyp@latest - echo \"EasyP version:\" - easyp version # При необходимости: git fetch --all --tags script: - easyp lint - easyp breaking --against git-ref=origin/main only: changes: - \"**/*.proto\" - \"easyp.yaml\""},{"id":"ci-cd/gitlab::top::5","title":"GitLab CI","section":"В процессе разработки","path":"/docs/guide/ci-cd/gitlab","headings":["В процессе разработки"],"excerpt":"В процессе разработки generate: stage: generate image: golang:${GO_VERSION} before_script: - go install github.com/easyp-tech/easyp/cmd/easyp@latest script: - easyp generate - if [ -n \"$(git status --porcelain)\" ]; then ","content":"В процессе разработки generate: stage: generate image: golang:${GO_VERSION} before_script: - go install github.com/easyp-tech/easyp/cmd/easyp@latest script: - easyp generate - if [ -n \"$(git status --porcelain)\" ]; then echo \"Сгенерированный код не актуален. Закоммитьте изменения локально.\" git diff --name-only exit 1 fi only: - main"},{"id":"ci-cd/gitlab::top::6","title":"GitLab CI","section":"В процессе разработки","path":"/docs/guide/ci-cd/gitlab","headings":["В процессе разработки"],"excerpt":"В процессе разработки Дополнительные рекомендации будут добавлены позже.","content":"В процессе разработки Дополнительные рекомендации будут добавлены позже."},{"id":"cli/auto-completion/auto-completion::zsh::0","title":"Автодополнение","section":"Автодополнение для zsh","path":"/docs/guide/cli/auto-completion/auto-completion#zsh","headings":["Автодополнение для zsh"],"excerpt":"Автодополнение для zsh Добавьте следующую строку в ваш файл запуска ~/.zshrc:","content":"Автодополнение для zsh Добавьте следующую строку в ваш файл запуска ~/.zshrc:"},{"id":"cli/auto-completion/auto-completion::zsh::1","title":"Автодополнение","section":"Автодополнение для zsh","path":"/docs/guide/cli/auto-completion/auto-completion#zsh","headings":["Автодополнение для zsh"],"excerpt":"Автодополнение для zsh Перезапустите оболочку или выполните:","content":"Автодополнение для zsh Перезапустите оболочку или выполните:"},{"id":"cli/auto-completion/auto-completion::bash::2","title":"Автодополнение","section":"Автодополнение для Bash","path":"/docs/guide/cli/auto-completion/auto-completion#bash","headings":["Автодополнение для Bash"],"excerpt":"Автодополнение для Bash Установите bash-completion и подключите его в ~/.bashrc. Добавьте следующую строку в файл запуска ~/.bashrc:","content":"Автодополнение для Bash Установите bash-completion и подключите его в ~/.bashrc. Добавьте следующую строку в файл запуска ~/.bashrc:"},{"id":"cli/auto-completion/auto-completion::bash::3","title":"Автодополнение","section":"Автодополнение для Bash","path":"/docs/guide/cli/auto-completion/auto-completion#bash","headings":["Автодополнение для Bash"],"excerpt":"Автодополнение для Bash Перезапустите оболочку или выполните:","content":"Автодополнение для Bash Перезапустите оболочку или выполните:"},{"id":"cli/auto-completion/auto-completion::top::4","title":"Автодополнение","section":"Примечания","path":"/docs/guide/cli/auto-completion/auto-completion","headings":["Примечания"],"excerpt":"Примечания Команда easyp completion выводит скрипт автодополнения для соответствующей оболочки. Если используете другую оболочку (например, fish), можно сгенерировать вывод и сохранить вручную: При обновлении версии Easy","content":"Примечания Команда easyp completion выводит скрипт автодополнения для соответствующей оболочки. Если используете другую оболочку (например, fish), можно сгенерировать вывод и сохранить вручную: При обновлении версии EasyP рекомендуется заново перезагрузить оболочку, чтобы подтянуть возможные изменения в автодополнении."},{"id":"cli/breaking-changes/breaking-changes::top::0","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":[],"excerpt":"Обнаружение несовместимых изменений (Breaking Changes Detection)","content":"Обнаружение несовместимых изменений (Breaking Changes Detection)"},{"id":"cli/breaking-changes/breaking-changes::top::1","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":[],"excerpt":"Механизм EasyP для обнаружения несовместимых (breaking) изменений помогает поддерживать обратную совместимость ваших protobuf API, автоматически выявляя изменения, способные сломать существующих клиентов. Это критично дл","content":"Механизм EasyP для обнаружения несовместимых (breaking) изменений помогает поддерживать обратную совместимость ваших protobuf API, автоматически выявляя изменения, способные сломать существующих клиентов. Это критично для стабильных API в продакшене."},{"id":"cli/breaking-changes/breaking-changes::top::2","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Обзор","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Обзор"],"excerpt":"Обзор Проверка несовместимых изменений сравнивает текущий набор protobuf‑файлов с предыдущей версией (обычно из другой Git ветки) и фиксирует модификации, которые могут вызвать проблемы совместимости для уже работающих к","content":"Обзор Проверка несовместимых изменений сравнивает текущий набор protobuf‑файлов с предыдущей версией (обычно из другой Git ветки) и фиксирует модификации, которые могут вызвать проблемы совместимости для уже работающих клиентов."},{"id":"cli/breaking-changes/breaking-changes::top::3","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Ключевые возможности","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Ключевые возможности"],"excerpt":"Ключевые возможности **Сравнение через Git**: Сопоставление с любой Git‑ссылкой (ветка, тег, commit) **Комплексный анализ**: Проверка сервисов, сообщений, enum'ов, полей и import'ов **Выборочное игнорирование**: Пропуск ","content":"Ключевые возможности **Сравнение через Git**: Сопоставление с любой Git‑ссылкой (ветка, тег, commit) **Комплексный анализ**: Проверка сервисов, сообщений, enum'ов, полей и import'ов **Выборочное игнорирование**: Пропуск указанных директорий из анализа **Детализированные отчёты**: Понятные ошибки с именами файлов, строками и позициями"},{"id":"cli/breaking-changes/breaking-changes::top::4","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Как работает","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Как работает"],"excerpt":"Как работает Детектор breaking changes выполняет следующие шаги:","content":"Как работает Детектор breaking changes выполняет следующие шаги:"},{"id":"cli/breaking-changes/breaking-changes::top::5","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Как работает","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Как работает"],"excerpt":"Как работает **Получение ветки сравнения**: Забирает proto-файлы из указанной Git‑ссылки **Парсинг обеих версий**: Анализирует структуру текущих и предыдущих файлов **Сравнение сущностей**: Последовательно проверяет все ","content":"Как работает **Получение ветки сравнения**: Забирает proto-файлы из указанной Git‑ссылки **Парсинг обеих версий**: Анализирует структуру текущих и предыдущих файлов **Сравнение сущностей**: Последовательно проверяет все элементы protobuf на breaking изменения **Формирование отчёта**: Генерирует подробные записи об ошибках с локациями и описаниями"},{"id":"cli/breaking-changes/breaking-changes::top::6","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Уровень проверки","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Уровень проверки"],"excerpt":"Уровень проверки EasyP реализует уровень проверки **WIRE+**: ✅ **Полная совместимость по wire‑формату** — старые и новые версии могут обмениваться данными ✅ **Обнаружение удалений элементов** — сервисы, сообщения, поля и","content":"Уровень проверки EasyP реализует уровень проверки **WIRE+**: ✅ **Полная совместимость по wire‑формату** — старые и новые версии могут обмениваться данными ✅ **Обнаружение удалений элементов** — сервисы, сообщения, поля и т.п. ✅ **Безопасность типов** — выявляет несовместимые изменения типов ❌ **Переименования полей/методов** — пока не детектируются (в планах) ❌ **Изменения на уровне файлов** — переносы пакетов, file options ещё не проверяются"},{"id":"cli/breaking-changes/breaking-changes::top::7","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Уровень проверки","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Уровень проверки"],"excerpt":"Уровень проверки Это даёт сильные гарантии совместимости и меньше ограничений, чем инструменты, требующие совместимости сгенерированного кода.","content":"Уровень проверки Это даёт сильные гарантии совместимости и меньше ограничений, чем инструменты, требующие совместимости сгенерированного кода."},{"id":"cli/breaking-changes/breaking-changes::top::8","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Конфигурация","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Конфигурация"],"excerpt":"Конфигурация Настройка в easyp.yaml:","content":"Конфигурация Настройка в easyp.yaml:"},{"id":"cli/breaking-changes/breaking-changes::top::9","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Параметры конфигурации","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Параметры конфигурации"],"excerpt":"Параметры конфигурации Option Description Default Required -------- ------------- --------- ---------- against_git_ref Git‑ссылка для сравнения \"master\" No ignore Список директорий для исключения из анализа [] No","content":"Параметры конфигурации Option Description Default Required -------- ------------- --------- ---------- against_git_ref Git‑ссылка для сравнения \"master\" No ignore Список директорий для исключения из анализа [] No"},{"id":"cli/breaking-changes/breaking-changes::top::10","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Базовый пример","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Базовый пример"],"excerpt":"Базовый пример Сравнение текущих изменений с веткой main:","content":"Базовый пример Сравнение текущих изменений с веткой main:"},{"id":"cli/breaking-changes/breaking-changes::top::11","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Использование файла конфигурации","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Использование файла конфигурации"],"excerpt":"Использование файла конфигурации","content":"Использование файла конфигурации"},{"id":"cli/breaking-changes/breaking-changes::top::12","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Уровень проверки","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Уровень проверки"],"excerpt":"Уровень проверки EasyP сейчас работает на уровне **WIRE+**, обеспечивая совместимость wire‑формата плюс защиту от удалений и изменения критичных типов.","content":"Уровень проверки EasyP сейчас работает на уровне **WIRE+**, обеспечивая совместимость wire‑формата плюс защиту от удалений и изменения критичных типов."},{"id":"cli/breaking-changes/breaking-changes::buf::13","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Сравнение с категориями Buf","path":"/docs/guide/cli/breaking-changes/breaking-changes#buf","headings":["Сравнение с категориями Buf"],"excerpt":"Сравнение с категориями Buf Check Type Buf WIRE Buf WIRE_JSON Buf FILE EasyP Current ------------ ---------- --------------- ---------- --------------- **Element Deletions** Service deletion ❌ ❌ ✅ ✅ RPC method deletion ❌","content":"Сравнение с категориями Buf 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::top::14","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Что это означает","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Что это означает"],"excerpt":"Что это означает **✅ EasyP обнаружит:** Все breaking изменения wire‑формата Удаления сервисов, методов, сообщений, полей Изменения типов, ломающие сериализацию Переименования enum‑значений (при сохранении номера)","content":"Что это означает **✅ EasyP обнаружит:** Все breaking изменения wire‑формата Удаления сервисов, методов, сообщений, полей Изменения типов, ломающие сериализацию Переименования enum‑значений (при сохранении номера)"},{"id":"cli/breaking-changes/breaking-changes::top::15","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Что это означает","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Что это означает"],"excerpt":"Что это означает **❌ EasyP НЕ обнаружит:** Переименование полей (с тем же номером) Изменение package File options (go_package, java_package, и т.п.) Перемещение типов между файлами в одном package","content":"Что это означает **❌ EasyP НЕ обнаружит:** Переименование полей (с тем же номером) Изменение package File options (go_package, java_package, и т.п.) Перемещение типов между файлами в одном package"},{"id":"cli/breaking-changes/breaking-changes::breaking-changes::16","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Правила Breaking Changes","path":"/docs/guide/cli/breaking-changes/breaking-changes#breaking-changes","headings":["Правила Breaking Changes"],"excerpt":"Правила Breaking Changes EasyP обнаруживает следующие типы breaking изменений:","content":"Правила Breaking Changes EasyP обнаруживает следующие типы breaking изменений:"},{"id":"cli/breaking-changes/breaking-changes::top::17","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Сравнение уровней","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Сравнение уровней"],"excerpt":"Сравнение уровней Detection Level Description EasyP Support ---------------- ------------- --------------- **WIRE** Совместимость только по wire‑формату ✅ **Full support** **WIRE+** Wire + обнаружение удалений ✅ **Curren","content":"Сравнение уровней Detection Level Description EasyP Support ---------------- ------------- --------------- **WIRE** Совместимость только по wire‑формату ✅ **Full support** **WIRE+** Wire + обнаружение удалений ✅ **Current level** **FILE** Совместимость сгенерированного кода ❌ Partial (planned)"},{"id":"cli/breaking-changes/breaking-changes::top::18","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Категории правил","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Категории правил"],"excerpt":"Категории правил Каждая категория имеет свою документацию с примерами:","content":"Категории правил Каждая категория имеет свою документацию с примерами:"},{"id":"cli/breaking-changes/breaking-changes::service-rpc::19","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"🚨 Изменения Service и RPC","path":"/docs/guide/cli/breaking-changes/breaking-changes#service-rpc","headings":["🚨 Изменения Service и RPC"],"excerpt":"🚨 Изменения Service и RPC 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 и RPC 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-field::20","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"📦 Изменения Message и Field","path":"/docs/guide/cli/breaking-changes/breaking-changes#message-field","headings":["📦 Изменения Message и Field"],"excerpt":"📦 Изменения Message и Field 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 и Field 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::21","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"🔢 Изменения Enum","path":"/docs/guide/cli/breaking-changes/breaking-changes#enum","headings":["🔢 Изменения Enum"],"excerpt":"🔢 Изменения Enum 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 val","content":"🔢 Изменения Enum 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::22","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"🔗 Изменения OneOf","path":"/docs/guide/cli/breaking-changes/breaking-changes#oneof","headings":["🔗 Изменения OneOf"],"excerpt":"🔗 Изменения OneOf Rule Description Status ------ ------------- --------- ONEOF_NO_DELETE OneOf fields cannot be deleted ✅ Implemented ONEOF_FIELD_NO_DELETE Fields within oneofs cannot be deleted ✅ Implemented ONEOF_FIEL","content":"🔗 Изменения OneOf 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::23","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"📥 Изменения Import","path":"/docs/guide/cli/breaking-changes/breaking-changes#import","headings":["📥 Изменения Import"],"excerpt":"📥 Изменения Import Rule Description Status ------ ------------- --------- IMPORT_NO_DELETE Import statements cannot be removed ✅ Implemented","content":"📥 Изменения Import Rule Description Status ------ ------------- --------- IMPORT_NO_DELETE Import statements cannot be removed ✅ Implemented"},{"id":"cli/breaking-changes/breaking-changes::top::24","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Не обнаруживается сейчас","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Не обнаруживается сейчас"],"excerpt":"Не обнаруживается сейчас Изменения ниже **НЕ детектируются** EasyP (могут ломать сгенерированный код):","content":"Не обнаруживается сейчас Изменения ниже **НЕ детектируются** EasyP (могут ломать сгенерированный код):"},{"id":"cli/breaking-changes/breaking-changes::top::25","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Не обнаруживается сейчас","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Не обнаруживается сейчас"],"excerpt":"Не обнаруживается сейчас Change Type Example Impact ------------- --------- -------- Field renaming string name = 1 → string full_name = 1 Ломает код Package changes package v1 → package v2 Меняются пути импорта File opt","content":"Не обнаруживается сейчас Change Type Example Impact ------------- --------- -------- Field renaming string name = 1 → string full_name = 1 Ломает код Package changes package v1 → package v2 Меняются пути импорта File options option go_package = \"old\" → option go_package = \"new\" Меняется расположение кода Moving between files Message перемещено в другой .proto Зависимости import'ов"},{"id":"cli/breaking-changes/breaking-changes::top::26","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Документация правил","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Документация правил"],"excerpt":"Документация правил См. подробные файлы правил для примеров и стратегий миграции:","content":"Документация правил См. подробные файлы правил для примеров и стратегий миграции:"},{"id":"cli/breaking-changes/breaking-changes::top::27","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Документация правил","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Документация правил"],"excerpt":"Документация правил Service: SERVICE_NO_DELETE, RPC_NO_DELETE, RPC_SAME_REQUEST_TYPE, RPC_SAME_RESPONSE_TYPE Message: MESSAGE_NO_DELETE, FIELD_NO_DELETE, FIELD_SAME_TYPE, FIELD_SAME_CARDINALITY Enum: ENUM_NO_DELETE, ENUM","content":"Документация правил Service: SERVICE_NO_DELETE, RPC_NO_DELETE, RPC_SAME_REQUEST_TYPE, RPC_SAME_RESPONSE_TYPE Message: MESSAGE_NO_DELETE, FIELD_NO_DELETE, FIELD_SAME_TYPE, FIELD_SAME_CARDINALITY Enum: ENUM_NO_DELETE, ENUM_VALUE_NO_DELETE, ENUM_VALUE_SAME_NAME OneOf: ONEOF_NO_DELETE, ONEOF_FIELD_NO_DELETE, ONEOF_FIELD_SAME_TYPE Import: IMPORT_NO_DELETE"},{"id":"cli/breaking-changes/breaking-changes::top::28","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Документация правил","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Документация правил"],"excerpt":"Документация правил Каждое правило содержит: ❌ Плохие примеры (breaking) ✅ Безопасные альтернативы 🔧 Стратегии миграции 📋 Реальные сообщения ошибок из EasyP","content":"Документация правил Каждое правило содержит: ❌ Плохие примеры (breaking) ✅ Безопасные альтернативы 🔧 Стратегии миграции 📋 Реальные сообщения ошибок из EasyP"},{"id":"cli/breaking-changes/breaking-changes::top::29","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"✅ Безопасные изменения (разрешены всегда)","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["✅ Безопасные изменения (разрешены всегда)"],"excerpt":"✅ Безопасные изменения (разрешены всегда) ```proto // Добавление новых элементов — безопасно message User { string name = 1; string email = 2; string phone = 3; // ✅ Новое поле }","content":"✅ Безопасные изменения (разрешены всегда) ```proto // Добавление новых элементов — безопасно message User { string name = 1; string email = 2; string phone = 3; // ✅ Новое поле }"},{"id":"cli/breaking-changes/breaking-changes::top::30","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"✅ Безопасные изменения (разрешены всегда)","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["✅ Безопасные изменения (разрешены всегда)"],"excerpt":"✅ Безопасные изменения (разрешены всегда) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc GetUserProfile(GetUserRequest) returns (UserProfile); // ✅ Новый RPC }","content":"✅ Безопасные изменения (разрешены всегда) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc GetUserProfile(GetUserRequest) returns (UserProfile); // ✅ Новый RPC }"},{"id":"cli/breaking-changes/breaking-changes::top::31","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"✅ Безопасные изменения (разрешены всегда)","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["✅ Безопасные изменения (разрешены всегда)"],"excerpt":"✅ Безопасные изменения (разрешены всегда) enum Status { STATUS_UNSPECIFIED = 0; STATUS_ACTIVE = 1; STATUS_PENDING = 2; // ✅ Новое enum значение } ```","content":"✅ Безопасные изменения (разрешены всегда) enum Status { STATUS_UNSPECIFIED = 0; STATUS_ACTIVE = 1; STATUS_PENDING = 2; // ✅ Новое enum значение } ```"},{"id":"cli/breaking-changes/breaking-changes::top::32","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"❌ Несовместимые изменения (обнаруживаются всегда)","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["❌ Несовместимые изменения (обнаруживаются всегда)"],"excerpt":"❌ Несовместимые изменения (обнаруживаются всегда) ```proto // Удаления и смена типов ломают совместимость message User { string name = 1; // ❌ Удалённое поле }","content":"❌ Несовместимые изменения (обнаруживаются всегда) ```proto // Удаления и смена типов ломают совместимость message User { string name = 1; // ❌ Удалённое поле }"},{"id":"cli/breaking-changes/breaking-changes::top::33","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"❌ Несовместимые изменения (обнаруживаются всегда)","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["❌ Несовместимые изменения (обнаруживаются всегда)"],"excerpt":"❌ Несовместимые изменения (обнаруживаются всегда) service UserService { // ❌ Удалённый RPC метод rpc GetUser(GetUserRequestV2) returns (GetUserResponse); // ❌ Изменён тип запроса } ```","content":"❌ Несовместимые изменения (обнаруживаются всегда) service UserService { // ❌ Удалённый RPC метод rpc GetUser(GetUserRequestV2) returns (GetUserResponse); // ❌ Изменён тип запроса } ```"},{"id":"cli/breaking-changes/breaking-changes::top::34","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Сценарий: Изменения пока не детектируются","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Сценарий: Изменения пока не детектируются"],"excerpt":"Сценарий: Изменения пока не детектируются ```proto // 🟡 Ломает сгенерированный код, но проходит проверки EasyP message User { string user_name = 1; // Переименовано с \"name\" string user_email = 2; // Переименовано с \"em","content":"Сценарий: Изменения пока не детектируются ```proto // 🟡 Ломает сгенерированный код, но проходит проверки EasyP message User { string user_name = 1; // Переименовано с \"name\" string user_email = 2; // Переименовано с \"email\" }"},{"id":"cli/breaking-changes/breaking-changes::top::35","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Сценарий: Изменения пока не детектируются","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Сценарий: Изменения пока не детектируются"],"excerpt":"Сценарий: Изменения пока не детектируются service UserService { rpc GetUserProfile(GetUserRequest) returns (GetUserResponse); // Переименовано с GetUser } ```","content":"Сценарий: Изменения пока не детектируются service UserService { rpc GetUserProfile(GetUserRequest) returns (GetUserResponse); // Переименовано с GetUser } ```"},{"id":"cli/breaking-changes/breaking-changes::top::36","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Текстовый формат (по умолчанию)","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Текстовый формат (по умолчанию)"],"excerpt":"Текстовый формат (по умолчанию)","content":"Текстовый формат (по умолчанию)"},{"id":"cli/breaking-changes/breaking-changes::1::37","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"1. Регулярный запуск","path":"/docs/guide/cli/breaking-changes/breaking-changes#1","headings":["1. Регулярный запуск"],"excerpt":"Регулярный запуск Добавьте проверку несовместимых изменений в CI/CD:","content":"Регулярный запуск Добавьте проверку несовместимых изменений в CI/CD:"},{"id":"cli/breaking-changes/breaking-changes::2::38","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"2. Защита веток","path":"/docs/guide/cli/breaking-changes/breaking-changes#2","headings":["2. Защита веток"],"excerpt":"Защита веток Блокируйте слияния с breaking изменениями:","content":"Защита веток Блокируйте слияния с breaking изменениями:"},{"id":"cli/breaking-changes/breaking-changes::3::39","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"3. Стратегия версионирования","path":"/docs/guide/cli/breaking-changes/breaking-changes#3","headings":["3. Стратегия версионирования"],"excerpt":"Стратегия версионирования При необходимости breaking изменений: Создайте новую версию пакета (myservice.v2) Поддерживайте старую версию в период миграции Добавляйте уведомления о деприкации","content":"Стратегия версионирования При необходимости breaking изменений: Создайте новую версию пакета (myservice.v2) Поддерживайте старую версию в период миграции Добавляйте уведомления о деприкации"},{"id":"cli/breaking-changes/breaking-changes::4::40","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"4. Игнорирование путей","path":"/docs/guide/cli/breaking-changes/breaking-changes#4","headings":["4. Игнорирование путей"],"excerpt":"Игнорирование путей Используйте ignore осознанно:","content":"Игнорирование путей Используйте ignore осознанно:"},{"id":"cli/breaking-changes/breaking-changes::repository-does-not-exist::41","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Проблема: \"Repository does not exist\"","path":"/docs/guide/cli/breaking-changes/breaking-changes#repository-does-not-exist","headings":["Проблема: \"Repository does not exist\""],"excerpt":"Проблема: \"Repository does not exist\" Решение: Выполняйте команду внутри Git репозитория с нужной веткой.","content":"Проблема: \"Repository does not exist\" Решение: Выполняйте команду внутри Git репозитория с нужной веткой."},{"id":"cli/breaking-changes/breaking-changes::cannot-find-git-ref::42","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Проблема: \"Cannot find git ref\"","path":"/docs/guide/cli/breaking-changes/breaking-changes#cannot-find-git-ref","headings":["Проблема: \"Cannot find git ref\""],"excerpt":"Проблема: \"Cannot find git ref\" Решение: Проверьте наличие ссылки:","content":"Проблема: \"Cannot find git ref\" Решение: Проверьте наличие ссылки:"},{"id":"cli/breaking-changes/breaking-changes::top::43","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Проблема: Ложные срабатывания на сгенерированный код","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Проблема: Ложные срабатывания на сгенерированный код"],"excerpt":"Проблема: Ложные срабатывания на сгенерированный код Решение: Исключите директории генерации:","content":"Проблема: Ложные срабатывания на сгенерированный код Решение: Исключите директории генерации:"},{"id":"cli/breaking-changes/breaking-changes::top::44","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Проблема: Очень много изменений","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Проблема: Очень много изменений"],"excerpt":"Проблема: Очень много изменений Решение: Создайте новую версию API Вносите изменения постепенно Используйте feature flags","content":"Проблема: Очень много изменений Решение: Создайте новую версию API Вносите изменения постепенно Используйте feature flags"},{"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 - name: Install EasyP run: curl -sSfL https://raw.githubusercontent.com/easyp-tech/easyp/main/install.","content":"GitHub Actions jobs: breaking-changes: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 with: fetch-depth: 0 - 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-pre-push-hook::48","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Pre-commit / pre-push hook","path":"/docs/guide/cli/breaking-changes/breaking-changes#pre-commit-pre-push-hook","headings":["Pre-commit / pre-push hook"],"excerpt":"Pre-commit / pre-push hook ```bash #!/bin/sh .git/hooks/pre-push","content":"Pre-commit / pre-push hook ```bash #!/bin/sh .git/hooks/pre-push"},{"id":"cli/breaking-changes/breaking-changes::pre-commit-pre-push-hook::49","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Pre-commit / pre-push hook","path":"/docs/guide/cli/breaking-changes/breaking-changes#pre-commit-pre-push-hook","headings":["Pre-commit / pre-push hook"],"excerpt":"Pre-commit / pre-push hook protected_branch='main' current_branch=$(git symbolic-ref HEAD sed -e 's,.*/\\(.*\\),\\1,')","content":"Pre-commit / pre-push hook protected_branch='main' current_branch=$(git symbolic-ref HEAD sed -e 's,.*/\\(.*\\),\\1,')"},{"id":"cli/breaking-changes/breaking-changes::pre-commit-pre-push-hook::50","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Pre-commit / pre-push hook","path":"/docs/guide/cli/breaking-changes/breaking-changes#pre-commit-pre-push-hook","headings":["Pre-commit / pre-push hook"],"excerpt":"Pre-commit / pre-push 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.","content":"Pre-commit / pre-push 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::top::51","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Режим отладки","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Режим отладки"],"excerpt":"Режим отладки Включите debug‑логирование:","content":"Режим отладки Включите debug‑логирование:"},{"id":"cli/breaking-changes/breaking-changes::top::52","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Ручное сравнение","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Ручное сравнение"],"excerpt":"Ручное сравнение Для сложных случаев:","content":"Ручное сравнение Для сложных случаев:"},{"id":"cli/breaking-changes/breaking-changes::top::53","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Оптимизация производительности","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Оптимизация производительности"],"excerpt":"Оптимизация производительности Ограничьте область:","content":"Оптимизация производительности Ограничьте область:"},{"id":"cli/breaking-changes/breaking-changes::top::54","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Оптимизация производительности","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Оптимизация производительности"],"excerpt":"Оптимизация производительности","content":"Оптимизация производительности"},{"id":"cli/breaking-changes/breaking-changes::top::55","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Оптимизация производительности","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Оптимизация производительности"],"excerpt":"Оптимизация производительности Механизм обнаружения несовместимых изменений в EasyP обеспечивает надёжную основу для безопасной эволюции protobuf‑схем при сохранении совместимости API.","content":"Оптимизация производительности Механизм обнаружения несовместимых изменений в EasyP обеспечивает надёжную основу для безопасной эволюции protobuf‑схем при сохранении совместимости API."},{"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":"Это правило проверяет, что ни один enum не был удалён из proto‑файлов. Удаление enum ломает совместимость по wire‑формату и сгенерированный код: сохранённые данные могут содержать удалённые значения, а клиентский код опи","content":"Это правило проверяет, что ни один enum не был удалён из proto‑файлов. Удаление enum ломает совместимость по wire‑формату и сгенерированный код: сохранённые данные могут содержать удалённые значения, а клиентский код опирается на сгенерированные типы и константы enum."},{"id":"cli/breaking-changes/rules/enum-no-delete::breaking::1","title":"ENUM_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-no-delete::breaking::2","title":"ENUM_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/enum-no-delete::breaking::3","title":"ENUM_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_CONFIRMED = 2; ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_DELIVERED = 4; }","content":"Плохой (Breaking) 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::breaking::4","title":"ENUM_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) enum UserRole { // [!code --] USER_ROLE_UNSPECIFIED = 0; // [!code --] USER_ROLE_ADMIN = 1; // [!code --] USER_ROLE_USER = 2; // [!code --] } // [!code --]","content":"Плохой (Breaking) 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::breaking::5","title":"ENUM_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message Order { string id = 1; OrderStatus status = 2; UserRole created_by_role = 3; } ```","content":"Плохой (Breaking) message Order { string id = 1; OrderStatus status = 2; UserRole created_by_role = 3; } ```"},{"id":"cli/breaking-changes/rules/enum-no-delete::breaking::6","title":"ENUM_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-no-delete::breaking::7","title":"ENUM_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/enum-no-delete::breaking::8","title":"ENUM_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_CONFIRMED = 2; ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_DELIVERED = 4; }","content":"Плохой (Breaking) 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::breaking::9","title":"ENUM_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) // UserRole enum удалён — BREAKING CHANGE!","content":"Плохой (Breaking) // UserRole enum удалён — BREAKING CHANGE!"},{"id":"cli/breaking-changes/rules/enum-no-delete::breaking::10","title":"ENUM_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message Order { string id = 1; OrderStatus status = 2; UserRole created_by_role = 3; // ERROR: UserRole больше не существует } ```","content":"Плохой (Breaking) message Order { string id = 1; OrderStatus status = 2; UserRole created_by_role = 3; // ERROR: UserRole больше не существует } ```"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::11","title":"ENUM_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры **Удаление вложенного enum:** ```proto // Before message User { string name = 1; Status status = 2; enum Status { // [!code --] STATUS_UNSPECIFIED = 0; // [!code --] STATUS_ACTIVE = 1; // [!code --","content":"Дополнительные примеры **Удаление вложенного enum:** ```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::top::12","title":"ENUM_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры // After - BREAKING CHANGE! message User { string name = 1; Status status = 2; // ERROR: Status удалён // Вложенный enum Status удалён } ```","content":"Дополнительные примеры // After - BREAKING CHANGE! message User { string name = 1; Status status = 2; // ERROR: Status удалён // Вложенный enum Status удалён } ```"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::13","title":"ENUM_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо удаления — пометить enum deprecated:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо удаления — пометить enum deprecated:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::14","title":"ENUM_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::15","title":"ENUM_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_CONFIRMED = 2; ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_DELIVERED = 4; }","content":"Хороший (Безопасный) 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::top::16","title":"ENUM_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) enum UserRole { option deprecated = true; // [!code focus] USER_ROLE_UNSPECIFIED = 0; USER_ROLE_ADMIN = 1; USER_ROLE_USER = 2; }","content":"Хороший (Безопасный) 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::top::17","title":"ENUM_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message Order { string id = 1; OrderStatus status = 2; UserRole created_by_role = 3 [deprecated = true]; // [!code focus] } ```","content":"Хороший (Безопасный) 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::top::18","title":"ENUM_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Или заменить новым enum:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Или заменить новым enum:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::19","title":"ENUM_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::20","title":"ENUM_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_CONFIRMED = 2; ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_DELIVERED = 4; }","content":"Хороший (Безопасный) 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::top::21","title":"ENUM_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) enum UserRole { option deprecated = true; // [!code focus] // Старый enum USER_ROLE_UNSPECIFIED = 0; USER_ROLE_ADMIN = 1; USER_ROLE_USER = 2; }","content":"Хороший (Безопасный) enum UserRole { option deprecated = true; // [!code focus] // Старый enum USER_ROLE_UNSPECIFIED = 0; USER_ROLE_ADMIN = 1; USER_ROLE_USER = 2; }"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::22","title":"ENUM_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) enum UserPermission { // [!code focus] // Новый enum USER_PERMISSION_UNSPECIFIED = 0; // [!code focus] USER_PERMISSION_READ = 1; // [!code focus] USER_PERMISSION_WRITE = 2; // [!code focus] USER_PERM","content":"Хороший (Безопасный) enum UserPermission { // [!code focus] // Новый enum 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::top::23","title":"ENUM_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message Order { string id = 1; OrderStatus status = 2; UserRole created_by_role = 3 [deprecated = true]; // [!code focus] UserPermission created_by_permission = 4; // [!code focus] } ```","content":"Хороший (Безопасный) message Order { string id = 1; OrderStatus status = 2; UserRole created_by_role = 3 [deprecated = true]; // [!code focus] UserPermission created_by_permission = 4; // [!code focus] } ```"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::24","title":"ENUM_NO_DELETE","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Влияние"],"excerpt":"Влияние **Wire Format:** Данные с удалённым enum не десериализуются корректно **Generated Code:** Тип и константы удаляются — компиляция клиентов ломается **Field References:** Поля с типом удалённого enum становятся нев","content":"Влияние **Wire Format:** Данные с удалённым enum не десериализуются корректно **Generated Code:** Тип и константы удаляются — компиляция клиентов ломается **Field References:** Поля с типом удалённого enum становятся невалидны **Switch Statements:** switch по enum ломается (неизвестные кейсы)"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::25","title":"ENUM_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Код клиента ломается:** ```go // Before order := &myapi.Order{ Id: \"order123\", Status: myapi.OrderStatus_ORDER_STATUS_PENDING, CreatedByRole: myapi.UserRole_USER_ROLE_ADMIN, // ERROR после удаления }","content":"Реальный пример **Код клиента ломается:** ```go // Before order := &myapi.Order{ Id: \"order123\", Status: myapi.OrderStatus_ORDER_STATUS_PENDING, CreatedByRole: myapi.UserRole_USER_ROLE_ADMIN, // ERROR после удаления }"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::26","title":"ENUM_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример switch order.CreatedByRole { case myapi.UserRole_USER_ROLE_ADMIN: // ERROR // Admin logic case myapi.UserRole_USER_ROLE_USER: // ERROR // User logic }","content":"Реальный пример switch order.CreatedByRole { case myapi.UserRole_USER_ROLE_ADMIN: // ERROR // Admin logic case myapi.UserRole_USER_ROLE_USER: // ERROR // User logic }"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::27","title":"ENUM_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример // undefined: myapi.UserRole // undefined: myapi.UserRole_USER_ROLE_ADMIN ```","content":"Реальный пример // undefined: myapi.UserRole // undefined: myapi.UserRole_USER_ROLE_ADMIN ```"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::28","title":"ENUM_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Старые данные становятся нечитаемыми:**","content":"Реальный пример **Старые данные становятся нечитаемыми:**"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::29","title":"ENUM_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Серверная логика ломается:**","content":"Реальный пример **Серверная логика ломается:**"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::30","title":"ENUM_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Депрецируйте enum:** **Пометьте поля со старым enum deprecated:** **Создайте новый enum:** **Сервер обрабатывает оба:** **Удалите старый enum в следующей major‑версии.**","content":"Стратегия миграции **Депрецируйте enum:** **Пометьте поля со старым enum deprecated:** **Создайте новый enum:** **Сервер обрабатывает оба:** **Удалите старый enum в следующей major‑версии.**"},{"id":"cli/breaking-changes/rules/enum-no-delete::enum::31","title":"ENUM_NO_DELETE","section":"Редизайн enum","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#enum","headings":["Редизайн enum"],"excerpt":"Редизайн enum ```proto enum Priority { option deprecated = true; PRIORITY_UNSPECIFIED = 0; PRIORITY_LOW = 1; PRIORITY_HIGH = 2; }","content":"Редизайн enum ```proto enum Priority { option deprecated = true; PRIORITY_UNSPECIFIED = 0; PRIORITY_LOW = 1; PRIORITY_HIGH = 2; }"},{"id":"cli/breaking-changes/rules/enum-no-delete::enum::32","title":"ENUM_NO_DELETE","section":"Редизайн enum","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#enum","headings":["Редизайн enum"],"excerpt":"Редизайн enum enum TaskPriority { TASK_PRIORITY_UNSPECIFIED = 0; TASK_PRIORITY_LOW = 1; TASK_PRIORITY_MEDIUM = 2; TASK_PRIORITY_HIGH = 3; TASK_PRIORITY_URGENT = 4; } ```","content":"Редизайн enum enum TaskPriority { 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::enum::33","title":"ENUM_NO_DELETE","section":"Консолидация enum","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#enum","headings":["Консолидация enum"],"excerpt":"Консолидация enum ```proto enum Status { option deprecated = true; STATUS_UNSPECIFIED = 0; STATUS_ACTIVE = 1; }","content":"Консолидация enum ```proto enum Status { option deprecated = true; STATUS_UNSPECIFIED = 0; STATUS_ACTIVE = 1; }"},{"id":"cli/breaking-changes/rules/enum-no-delete::enum::34","title":"ENUM_NO_DELETE","section":"Консолидация enum","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#enum","headings":["Консолидация enum"],"excerpt":"Консолидация enum enum State { option deprecated = true; STATE_UNSPECIFIED = 0; STATE_ENABLED = 1; }","content":"Консолидация enum enum State { option deprecated = true; STATE_UNSPECIFIED = 0; STATE_ENABLED = 1; }"},{"id":"cli/breaking-changes/rules/enum-no-delete::enum::35","title":"ENUM_NO_DELETE","section":"Консолидация enum","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#enum","headings":["Консолидация enum"],"excerpt":"Консолидация enum enum EntityStatus { ENTITY_STATUS_UNSPECIFIED = 0; ENTITY_STATUS_ACTIVE = 1; ENTITY_STATUS_INACTIVE = 2; ENTITY_STATUS_ENABLED = 3; ENTITY_STATUS_DISABLED = 4; } ```","content":"Консолидация enum enum EntityStatus { 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::enum::36","title":"ENUM_NO_DELETE","section":"Перемещение enum в новый пакет","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#enum","headings":["Перемещение enum в новый пакет"],"excerpt":"Перемещение enum в новый пакет ```proto enum UserRole { option deprecated = true; USER_ROLE_UNSPECIFIED = 0; USER_ROLE_ADMIN = 1; }","content":"Перемещение enum в новый пакет ```proto enum UserRole { option deprecated = true; USER_ROLE_UNSPECIFIED = 0; USER_ROLE_ADMIN = 1; }"},{"id":"cli/breaking-changes/rules/enum-no-delete::enum::37","title":"ENUM_NO_DELETE","section":"Перемещение enum в новый пакет","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#enum","headings":["Перемещение enum в новый пакет"],"excerpt":"Перемещение enum в новый пакет import \"common/roles.proto\";","content":"Перемещение enum в новый пакет import \"common/roles.proto\";"},{"id":"cli/breaking-changes/rules/enum-no-delete::enum::38","title":"ENUM_NO_DELETE","section":"Перемещение enum в новый пакет","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#enum","headings":["Перемещение enum в новый пакет"],"excerpt":"Перемещение enum в новый пакет message Order { UserRole old_role = 3 [deprecated = true]; common.UserRole new_role = 4; } ```","content":"Перемещение enum в новый пакет message Order { UserRole old_role = 3 [deprecated = true]; common.UserRole new_role = 4; } ```"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::39","title":"ENUM_NO_DELETE","section":"Версионирование / новая версия пакета","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Версионирование / новая версия пакета"],"excerpt":"Версионирование / новая версия пакета ```proto package myapi.v2;","content":"Версионирование / новая версия пакета ```proto package myapi.v2;"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::40","title":"ENUM_NO_DELETE","section":"Версионирование / новая версия пакета","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Версионирование / новая версия пакета"],"excerpt":"Версионирование / новая версия пакета enum UserPermission { USER_PERMISSION_UNSPECIFIED = 0; USER_PERMISSION_READ = 1; USER_PERMISSION_WRITE = 2; USER_PERMISSION_ADMIN = 3; }","content":"Версионирование / новая версия пакета 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::top::41","title":"ENUM_NO_DELETE","section":"Версионирование / новая версия пакета","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Версионирование / новая версия пакета"],"excerpt":"Версионирование / новая версия пакета message Order { string id = 1; UserPermission created_by_permission = 2; } ```","content":"Версионирование / новая версия пакета message Order { string id = 1; UserPermission created_by_permission = 2; } ```"},{"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":"Правило проверяет, что ни одно значение enum (enum value) не было удалено. Удаление значения ломает совместимость по wire‑формату и сгенерированный код: в уже сохранённых данных могут присутствовать удалённые значения, а","content":"Правило проверяет, что ни одно значение enum (enum value) не было удалено. Удаление значения ломает совместимость по wire‑формату и сгенерированный код: в уже сохранённых данных могут присутствовать удалённые значения, а клиентский код может ссылаться на соответствующие константы."},{"id":"cli/breaking-changes/rules/enum-value-no-delete::breaking::1","title":"ENUM_VALUE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::breaking::2","title":"ENUM_VALUE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::breaking::3","title":"ENUM_VALUE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) 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":"Плохой (Breaking) 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::breaking::4","title":"ENUM_VALUE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) enum Priority { PRIORITY_UNSPECIFIED = 0; PRIORITY_LOW = 1; PRIORITY_MEDIUM = 2; PRIORITY_HIGH = 3; PRIORITY_URGENT = 4; } ```","content":"Плохой (Breaking) 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::breaking::5","title":"ENUM_VALUE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::breaking::6","title":"ENUM_VALUE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::breaking::7","title":"ENUM_VALUE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) 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 --] ","content":"Плохой (Breaking) 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 --] Удалено значение enum — BREAKING! }"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::breaking::8","title":"ENUM_VALUE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) enum Priority { PRIORITY_UNSPECIFIED = 0; PRIORITY_LOW = 1; PRIORITY_MEDIUM = 2; PRIORITY_HIGH = 3; // PRIORITY_URGENT = 4; // [!code --] Удалено значение enum — BREAKING! } ```","content":"Плохой (Breaking) enum Priority { PRIORITY_UNSPECIFIED = 0; PRIORITY_LOW = 1; PRIORITY_MEDIUM = 2; PRIORITY_HIGH = 3; // PRIORITY_URGENT = 4; // [!code --] Удалено значение enum — BREAKING! } ```"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::9","title":"ENUM_VALUE_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры **Множественное удаление значений:** ```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_S","content":"Дополнительные примеры **Множественное удаление значений:** ```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::top::10","title":"ENUM_VALUE_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры // 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","content":"Дополнительные примеры // 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::top::11","title":"ENUM_VALUE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо удаления — пометить значения deprecated:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо удаления — пометить значения deprecated:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::12","title":"ENUM_VALUE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::13","title":"ENUM_VALUE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) 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 = t","content":"Хороший (Безопасный) 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::top::14","title":"ENUM_VALUE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) enum Priority { PRIORITY_UNSPECIFIED = 0; PRIORITY_LOW = 1; PRIORITY_MEDIUM = 2; PRIORITY_HIGH = 3; PRIORITY_URGENT = 4 [deprecated = true]; // [!code focus] } ```","content":"Хороший (Безопасный) 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::top::15","title":"ENUM_VALUE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Или зарезервировать номер и имя после удаления:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Или зарезервировать номер и имя после удаления:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::16","title":"ENUM_VALUE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::17","title":"ENUM_VALUE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) enum OrderStatus { reserved 5; // [!code focus] reserved \"ORDER_STATUS_CANCELLED\"; // [!code focus]","content":"Хороший (Безопасный) enum OrderStatus { reserved 5; // [!code focus] reserved \"ORDER_STATUS_CANCELLED\"; // [!code focus]"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::18","title":"ENUM_VALUE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_CONFIRMED = 2; ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_DELIVERED = 4; }","content":"Хороший (Безопасный) 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::top::19","title":"ENUM_VALUE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) enum Priority { reserved 4; // [!code focus] reserved \"PRIORITY_URGENT\"; // [!code focus]","content":"Хороший (Безопасный) enum Priority { reserved 4; // [!code focus] reserved \"PRIORITY_URGENT\"; // [!code focus]"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::20","title":"ENUM_VALUE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) PRIORITY_UNSPECIFIED = 0; PRIORITY_LOW = 1; PRIORITY_MEDIUM = 2; PRIORITY_HIGH = 3; } ```","content":"Хороший (Безопасный) PRIORITY_UNSPECIFIED = 0; PRIORITY_LOW = 1; PRIORITY_MEDIUM = 2; PRIORITY_HIGH = 3; } ```"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::21","title":"ENUM_VALUE_NO_DELETE","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Влияние"],"excerpt":"Влияние **Wire Format:** Данные с удалёнными значениями не десериализуются корректно **Generated Code:** Константы исчезают — клиентский код не компилируется **Client Applications:** Ссылки на удалённые значения вызывают","content":"Влияние **Wire Format:** Данные с удалёнными значениями не десериализуются корректно **Generated Code:** Константы исчезают — клиентский код не компилируется **Client Applications:** Ссылки на удалённые значения вызывают ошибки компиляции **Switch Statements:** switch по enum ломается (неизвестные case) **Default Handling:** Поведение при неизвестных значениях меняется"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::22","title":"ENUM_VALUE_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Код клиента ломается:** ```go order := &myapi.Order{ Status: myapi.OrderStatus_ORDER_STATUS_CANCELLED, // ERROR после удаления }","content":"Реальный пример **Код клиента ломается:** ```go order := &myapi.Order{ Status: myapi.OrderStatus_ORDER_STATUS_CANCELLED, // ERROR после удаления }"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::23","title":"ENUM_VALUE_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример switch order.Status { case myapi.OrderStatus_ORDER_STATUS_PENDING: // Pending case myapi.OrderStatus_ORDER_STATUS_CANCELLED: // ERROR: undefined // Cancellation default: // Unknown } // undefined: myapi.O","content":"Реальный пример switch order.Status { case myapi.OrderStatus_ORDER_STATUS_PENDING: // Pending case myapi.OrderStatus_ORDER_STATUS_CANCELLED: // ERROR: undefined // Cancellation default: // Unknown } // undefined: myapi.OrderStatus_ORDER_STATUS_CANCELLED ```"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::24","title":"ENUM_VALUE_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Проблемы с уже сохранёнными данными:**","content":"Реальный пример **Проблемы с уже сохранёнными данными:**"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::25","title":"ENUM_VALUE_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Валидация на сервере:** ```go func validateOrderStatus(status OrderStatus) error { switch status { case OrderStatus_ORDER_STATUS_PENDING, OrderStatus_ORDER_STATUS_CONFIRMED, OrderStatus_ORDER_STATUS_SHI","content":"Реальный пример **Валидация на сервере:** ```go 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 после удаления return nil default: return errors.New(\"invalid order status\") } }"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::26","title":"ENUM_VALUE_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример func canModifyOrder(order *Order) bool { return order.Status != OrderStatus_ORDER_STATUS_CANCELLED // ERROR } ```","content":"Реальный пример func canModifyOrder(order *Order) bool { return order.Status != OrderStatus_ORDER_STATUS_CANCELLED // ERROR } ```"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::27","title":"ENUM_VALUE_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Сначала пометить deprecated:** **Перестать использовать deprecated значение в новом коде:** **Обработка legacy в клиенте:** **Резервирование после миграции:** **Никогда не переиспользовать номера** —","content":"Стратегия миграции **Сначала пометить deprecated:** **Перестать использовать deprecated значение в новом коде:** **Обработка legacy в клиенте:** **Резервирование после миграции:** **Никогда не переиспользовать номера** — зарезервированы навсегда."},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::28","title":"ENUM_VALUE_NO_DELETE","section":"Предотвращение переиспользования номера","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Предотвращение переиспользования номера"],"excerpt":"Предотвращение переиспользования номера ```proto enum Status { reserved 2; reserved \"STATUS_DELETED\";","content":"Предотвращение переиспользования номера ```proto enum Status { reserved 2; reserved \"STATUS_DELETED\";"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::29","title":"ENUM_VALUE_NO_DELETE","section":"Предотвращение переиспользования номера","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Предотвращение переиспользования номера"],"excerpt":"Предотвращение переиспользования номера STATUS_UNSPECIFIED = 0; STATUS_ACTIVE = 1; STATUS_INACTIVE = 3; // STATUS_DELETED = 2; // Не переиспользуем } ```","content":"Предотвращение переиспользования номера STATUS_UNSPECIFIED = 0; STATUS_ACTIVE = 1; STATUS_INACTIVE = 3; // STATUS_DELETED = 2; // Не переиспользуем } ```"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::json::30","title":"ENUM_VALUE_NO_DELETE","section":"JSON совместимость","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#json","headings":["JSON совместимость"],"excerpt":"JSON совместимость ```proto enum Color { reserved 2; reserved \"RED\";","content":"JSON совместимость ```proto enum Color { reserved 2; reserved \"RED\";"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::json::31","title":"ENUM_VALUE_NO_DELETE","section":"JSON совместимость","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#json","headings":["JSON совместимость"],"excerpt":"JSON совместимость COLOR_UNSPECIFIED = 0; COLOR_BLUE = 1; COLOR_GREEN = 3; // COLOR_RED = 2; // Был удалён } ```","content":"JSON совместимость COLOR_UNSPECIFIED = 0; COLOR_BLUE = 1; COLOR_GREEN = 3; // COLOR_RED = 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":"Это правило проверяет, что имя enum значения для каждого номера (number) не изменилось. Переименование enum значения при сохранении его номера ломает совместимость JSON и сгенерированный код: клиенты ожидают конкретные и","content":"Это правило проверяет, что имя enum значения для каждого номера (number) не изменилось. Переименование enum значения при сохранении его номера ломает совместимость JSON и сгенерированный код: клиенты ожидают конкретные имена констант."},{"id":"cli/breaking-changes/rules/enum-value-same-name::breaking::1","title":"ENUM_VALUE_SAME_NAME","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-value-same-name::breaking::2","title":"ENUM_VALUE_SAME_NAME","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/enum-value-same-name::breaking::3","title":"ENUM_VALUE_SAME_NAME","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_CONFIRMED = 2; ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_DELIVERED = 4; } ```","content":"Плохой (Breaking) 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::breaking::4","title":"ENUM_VALUE_SAME_NAME","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-value-same-name::breaking::5","title":"ENUM_VALUE_SAME_NAME","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/enum-value-same-name::breaking::6","title":"ENUM_VALUE_SAME_NAME","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_APPROVED = 2; // [!code --] Было ORDER_STATUS_CONFIRMED ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_COMPLETED = 4; // [","content":"Плохой (Breaking) enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_APPROVED = 2; // [!code --] Было ORDER_STATUS_CONFIRMED ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_COMPLETED = 4; // [!code --] Было ORDER_STATUS_DELIVERED } ```"},{"id":"cli/breaking-changes/rules/enum-value-same-name::top::7","title":"ENUM_VALUE_SAME_NAME","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры **Множественные переименования:** ```proto // Before enum UserRole { USER_ROLE_UNSPECIFIED = 0; USER_ROLE_ADMIN = 1; USER_ROLE_MODERATOR = 2; USER_ROLE_USER = 3; }","content":"Дополнительные примеры **Множественные переименования:** ```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::top::8","title":"ENUM_VALUE_SAME_NAME","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры // After - ВСЁ BREAKING enum UserRole { USER_ROLE_UNSPECIFIED = 0; USER_ROLE_ADMINISTRATOR = 1; // BREAKING: ADMIN -> ADMINISTRATOR USER_ROLE_MOD = 2; // BREAKING: MODERATOR -> MOD USER_ROLE_MEMBER","content":"Дополнительные примеры // After - ВСЁ BREAKING 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::top::9","title":"ENUM_VALUE_SAME_NAME","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо переименования — добавить новые значения и пометить старые deprecated:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо переименования — добавить новые значения и пометить старые deprecated:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-value-same-name::top::10","title":"ENUM_VALUE_SAME_NAME","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/enum-value-same-name::top::11","title":"ENUM_VALUE_SAME_NAME","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) 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 [depre","content":"Хороший (Безопасный) 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] // Новое значение вместо переименования ORDER_STATUS_COMPLETED = 6; // [!code focus] } ```"},{"id":"cli/breaking-changes/rules/enum-value-same-name::top::12","title":"ENUM_VALUE_SAME_NAME","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Или создать новую версию enum:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Или создать новую версию enum:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-value-same-name::top::13","title":"ENUM_VALUE_SAME_NAME","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v2; // [!code focus]","content":"Хороший (Безопасный) package myapi.v2; // [!code focus]"},{"id":"cli/breaking-changes/rules/enum-value-same-name::top::14","title":"ENUM_VALUE_SAME_NAME","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_APPROVED = 2; // [!code focus] // «Чистые» имена в v2 ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_COMPLETED = 4; // ","content":"Хороший (Безопасный) enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_APPROVED = 2; // [!code focus] // «Чистые» имена в v2 ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_COMPLETED = 4; // [!code focus] } ```"},{"id":"cli/breaking-changes/rules/enum-value-same-name::top::15","title":"ENUM_VALUE_SAME_NAME","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Влияние"],"excerpt":"Влияние **Generated Code:** Меняются имена констант — компиляция клиентов ломается **JSON Compatibility:** JSON использует имена enum — старые документы не парсятся **Client Applications:** Код со старым именем константы","content":"Влияние **Generated Code:** Меняются имена констант — компиляция клиентов ломается **JSON Compatibility:** JSON использует имена enum — старые документы не парсятся **Client Applications:** Код со старым именем константы не компилируется **Documentation:** Документация устаревает с неправильными именами"},{"id":"cli/breaking-changes/rules/enum-value-same-name::top::16","title":"ENUM_VALUE_SAME_NAME","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Реальный пример"],"excerpt":"Реальный пример **Ломается код клиента:** ```go // Before status := myapi.OrderStatus_ORDER_STATUS_CONFIRMED if order.Status == myapi.OrderStatus_ORDER_STATUS_DELIVERED { // handle delivery }","content":"Реальный пример **Ломается код клиента:** ```go // Before 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::top::17","title":"ENUM_VALUE_SAME_NAME","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Реальный пример"],"excerpt":"Реальный пример // After (переименовано) — ошибки компиляции status := myapi.OrderStatus_ORDER_STATUS_CONFIRMED // ERROR: undefined if order.Status == myapi.OrderStatus_ORDER_STATUS_DELIVERED { // ERROR: undefined // han","content":"Реальный пример // After (переименовано) — ошибки компиляции status := myapi.OrderStatus_ORDER_STATUS_CONFIRMED // ERROR: undefined if order.Status == myapi.OrderStatus_ORDER_STATUS_DELIVERED { // ERROR: undefined // handle delivery } ```"},{"id":"cli/breaking-changes/rules/enum-value-same-name::top::18","title":"ENUM_VALUE_SAME_NAME","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Реальный пример"],"excerpt":"Реальный пример **JSON совместимость ломается:** ```json // Раньше { \"status\": \"ORDER_STATUS_CONFIRMED\" }","content":"Реальный пример **JSON совместимость ломается:** ```json // Раньше { \"status\": \"ORDER_STATUS_CONFIRMED\" }"},{"id":"cli/breaking-changes/rules/enum-value-same-name::top::19","title":"ENUM_VALUE_SAME_NAME","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Реальный пример"],"excerpt":"Реальный пример // После { \"status\": \"ORDER_STATUS_APPROVED\" // Старые JSON больше не парсятся } ```","content":"Реальный пример // После { \"status\": \"ORDER_STATUS_APPROVED\" // Старые JSON больше не парсятся } ```"},{"id":"cli/breaking-changes/rules/enum-value-same-name::top::20","title":"ENUM_VALUE_SAME_NAME","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Добавьте новое значение вместо переименования:**","content":"Стратегия миграции **Добавьте новое значение вместо переименования:**"},{"id":"cli/breaking-changes/rules/enum-value-same-name::top::21","title":"ENUM_VALUE_SAME_NAME","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Сервер обрабатывает оба значения на переходном этапе** **Мигрируйте клиентов** на новые значения **Удалите (reserve) старое имя и номер** в следующей major‑версии:","content":"Стратегия миграции **Сервер обрабатывает оба значения на переходном этапе** **Мигрируйте клиентов** на новые значения **Удалите (reserve) старое имя и номер** в следующей major‑версии:"},{"id":"cli/breaking-changes/rules/enum-value-same-name::allow-alias::22","title":"ENUM_VALUE_SAME_NAME","section":"Allow Alias (исключение)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name#allow-alias","headings":["Allow Alias (исключение)"],"excerpt":"Allow Alias (исключение) С allow_alias = true можно временно иметь два имени для одного номера:","content":"Allow Alias (исключение) С allow_alias = true можно временно иметь два имени для одного номера:"},{"id":"cli/breaking-changes/rules/enum-value-same-name::allow-alias::23","title":"ENUM_VALUE_SAME_NAME","section":"Allow Alias (исключение)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name#allow-alias","headings":["Allow Alias (исключение)"],"excerpt":"Allow Alias (исключение) Примечание: Сейчас EasyP всё равно считает это breaking (может измениться в будущем).","content":"Allow Alias (исключение) Примечание: Сейчас EasyP всё равно считает это breaking (может измениться в будущем)."},{"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":"Это правило проверяет, что ни одно поле сообщения (message field) не было удалено. Удаление поля ломает совместимость по wire‑формату и сгенерированный код: в существующих данных может присутствовать удалённое поле, а кл","content":"Это правило проверяет, что ни одно поле сообщения (message field) не было удалено. Удаление поля ломает совместимость по wire‑формату и сгенерированный код: в существующих данных может присутствовать удалённое поле, а клиентский код может ссылаться на него."},{"id":"cli/breaking-changes/rules/field-no-delete::breaking::1","title":"FIELD_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-no-delete::breaking::2","title":"FIELD_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/field-no-delete::breaking::3","title":"FIELD_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message User { string name = 1; string email = 2; int32 age = 3; string phone = 4; // [!code --] } ```","content":"Плохой (Breaking) message User { string name = 1; string email = 2; int32 age = 3; string phone = 4; // [!code --] } ```"},{"id":"cli/breaking-changes/rules/field-no-delete::breaking::4","title":"FIELD_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-no-delete::breaking::5","title":"FIELD_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/field-no-delete::breaking::6","title":"FIELD_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message User { string name = 1; string email = 2; int32 age = 3; // phone поле удалено — BREAKING CHANGE! } ```","content":"Плохой (Breaking) message User { string name = 1; string email = 2; int32 age = 3; // phone поле удалено — BREAKING CHANGE! } ```"},{"id":"cli/breaking-changes/rules/field-no-delete::top::7","title":"FIELD_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо удаления — пометить поле deprecated:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо удаления — пометить поле deprecated:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-no-delete::top::8","title":"FIELD_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/field-no-delete::top::9","title":"FIELD_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message User { string name = 1; string email = 2; int32 age = 3; string phone = 4 [deprecated = true]; // [!code focus] } ```","content":"Хороший (Безопасный) 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::top::10","title":"FIELD_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Или зарезервировать номер и имя поля после удаления:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Или зарезервировать номер и имя поля после удаления:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-no-delete::top::11","title":"FIELD_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/field-no-delete::top::12","title":"FIELD_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message User { reserved 4; // [!code focus] reserved \"phone\"; // [!code focus] string name = 1; string email = 2; int32 age = 3; } ```","content":"Хороший (Безопасный) 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::top::13","title":"FIELD_NO_DELETE","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete","headings":["Влияние"],"excerpt":"Влияние **Wire Format:** Старые сообщения с удалённым полем некорректно десериализуются **Generated Code:** Удаляются аксессоры (get/set), компиляция клиента ломается **Data Loss:** Потеря сохранённых данных, связанных с","content":"Влияние **Wire Format:** Старые сообщения с удалённым полем некорректно десериализуются **Generated Code:** Удаляются аксессоры (get/set), компиляция клиента ломается **Data Loss:** Потеря сохранённых данных, связанных с полем **JSON Compatibility:** JSON парсеры ожидают наличие поля и могут выдавать ошибки"},{"id":"cli/breaking-changes/rules/field-no-delete::top::14","title":"FIELD_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Сначала пометить deprecated:**","content":"Стратегия миграции **Сначала пометить deprecated:**"},{"id":"cli/breaking-changes/rules/field-no-delete::top::15","title":"FIELD_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Прекратить запись в поле** в прикладном коде","content":"Стратегия миграции **Прекратить запись в поле** в прикладном коде"},{"id":"cli/breaking-changes/rules/field-no-delete::top::16","title":"FIELD_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Зарезервировать поле** в следующей версии, чтобы избежать повторного использования:","content":"Стратегия миграции **Зарезервировать поле** в следующей версии, чтобы избежать повторного использования:"},{"id":"cli/breaking-changes/rules/field-no-delete::top::17","title":"FIELD_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Никогда не переиспользовать номер поля** — должен оставаться в reserved навсегда","content":"Стратегия миграции **Никогда не переиспользовать номер поля** — должен оставаться в reserved навсегда"},{"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":"Правило проверяет, что поля сообщений сохраняют ту же кардинальность (обязательность / optional). Изменение кардинальности поля ломает совместимость по wire‑формату и сгенерированный код: семантика присутствия и ожидания","content":"Правило проверяет, что поля сообщений сохраняют ту же кардинальность (обязательность / optional). Изменение кардинальности поля ломает совместимость по wire‑формату и сгенерированный код: семантика присутствия и ожидания клиентского кода отличаются для optional и required (implicit) полей."},{"id":"cli/breaking-changes/rules/field-same-cardinality::breaking::1","title":"FIELD_SAME_CARDINALITY","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-same-cardinality::breaking::2","title":"FIELD_SAME_CARDINALITY","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/field-same-cardinality::breaking::3","title":"FIELD_SAME_CARDINALITY","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message User { string name = 1; string email = 2; int32 age = 3; }","content":"Плохой (Breaking) message User { string name = 1; string email = 2; int32 age = 3; }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::breaking::4","title":"FIELD_SAME_CARDINALITY","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message CreateUserRequest { string name = 1; optional string email = 2; string phone = 3; } ```","content":"Плохой (Breaking) message CreateUserRequest { string name = 1; optional string email = 2; string phone = 3; } ```"},{"id":"cli/breaking-changes/rules/field-same-cardinality::breaking::5","title":"FIELD_SAME_CARDINALITY","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-same-cardinality::breaking::6","title":"FIELD_SAME_CARDINALITY","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/field-same-cardinality::breaking::7","title":"FIELD_SAME_CARDINALITY","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message User { string name = 1; optional string email = 2; // [!code --] Было required (implicit), стало optional int32 age = 3; }","content":"Плохой (Breaking) message User { string name = 1; optional string email = 2; // [!code --] Было required (implicit), стало optional int32 age = 3; }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::breaking::8","title":"FIELD_SAME_CARDINALITY","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message CreateUserRequest { string name = 1; string email = 2; // [!code --] Было optional, стало требуемым (implicit required) string phone = 3; } ```","content":"Плохой (Breaking) message CreateUserRequest { string name = 1; string email = 2; // [!code --] Было optional, стало требуемым (implicit required) string phone = 3; } ```"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::9","title":"FIELD_SAME_CARDINALITY","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры **Проблемы миграции Proto2 → Proto3:**","content":"Дополнительные примеры **Проблемы миграции Proto2 → Proto3:**"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::10","title":"FIELD_SAME_CARDINALITY","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры ```proto // Before (proto2) syntax = \"proto2\";","content":"Дополнительные примеры ```proto // Before (proto2) syntax = \"proto2\";"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::11","title":"FIELD_SAME_CARDINALITY","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры message Order { required string id = 1; optional string notes = 2; repeated string tags = 3; }","content":"Дополнительные примеры message Order { required string id = 1; optional string notes = 2; repeated string tags = 3; }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::12","title":"FIELD_SAME_CARDINALITY","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры // After (proto3) - BREAKING CHANGES! syntax = \"proto3\";","content":"Дополнительные примеры // After (proto3) - BREAKING CHANGES! syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::13","title":"FIELD_SAME_CARDINALITY","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры message Order { string id = 1; // BREAKING: required -> implicit optional string notes = 2; // BREAKING: explicit optional -> implicit optional repeated string tags = 3; // OK } ```","content":"Дополнительные примеры message Order { string id = 1; // BREAKING: required -> implicit optional string notes = 2; // BREAKING: explicit optional -> implicit optional repeated string tags = 3; // OK } ```"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::14","title":"FIELD_SAME_CARDINALITY","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо изменения кардинальности — добавьте новое поле:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо изменения кардинальности — добавьте новое поле:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::15","title":"FIELD_SAME_CARDINALITY","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::16","title":"FIELD_SAME_CARDINALITY","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message User { string name = 1; string email = 2 [deprecated = true]; // [!code focus] Сохраняем старую кардинальность int32 age = 3; optional string email_optional = 4; // [!code focus] Новое option","content":"Хороший (Безопасный) message User { string name = 1; string email = 2 [deprecated = true]; // [!code focus] Сохраняем старую кардинальность int32 age = 3; optional string email_optional = 4; // [!code focus] Новое optional поле }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::17","title":"FIELD_SAME_CARDINALITY","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message CreateUserRequest { string name = 1; optional string email = 2 [deprecated = true]; // [!code focus] string phone = 3; string email_required = 4; // [!code focus] Новое требуемое поле } ```","content":"Хороший (Безопасный) message CreateUserRequest { string name = 1; optional string email = 2 [deprecated = true]; // [!code focus] string phone = 3; string email_required = 4; // [!code focus] Новое требуемое поле } ```"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::18","title":"FIELD_SAME_CARDINALITY","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Или создайте новую версию сообщения:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Или создайте новую версию сообщения:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::19","title":"FIELD_SAME_CARDINALITY","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v2; // [!code focus]","content":"Хороший (Безопасный) package myapi.v2; // [!code focus]"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::20","title":"FIELD_SAME_CARDINALITY","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message User { string name = 1; optional string email = 2; // [!code focus] Чистая модель в v2 int32 age = 3; }","content":"Хороший (Безопасный) message User { string name = 1; optional string email = 2; // [!code focus] Чистая модель в v2 int32 age = 3; }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::21","title":"FIELD_SAME_CARDINALITY","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message CreateUserRequest { string name = 1; string email = 2; // [!code focus] Требуемое в v2 string phone = 3; } ```","content":"Хороший (Безопасный) message CreateUserRequest { string name = 1; string email = 2; // [!code focus] Требуемое в v2 string phone = 3; } ```"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::22","title":"FIELD_SAME_CARDINALITY","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Влияние"],"excerpt":"Влияние **Wire Format:** Меняется семантика присутствия — клиенты неправильно ожидают поля **Generated Code:** Меняются методы доступа / проверки (has, clear) **Validation:** Правила проверки обязательности переписываютс","content":"Влияние **Wire Format:** Меняется семантика присутствия — клиенты неправильно ожидают поля **Generated Code:** Меняются методы доступа / проверки (has, clear) **Validation:** Правила проверки обязательности переписываются **Default Values:** Optional и required по‑разному обрабатывают отсутствие значения"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::23","title":"FIELD_SAME_CARDINALITY","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Реальный пример"],"excerpt":"Реальный пример **Код клиента ломается при смене кардинальности:** ```go // Before - поле фактически требуется (implicit) user := &myapi.User{ Name: \"John\", Email: \"john@example.com\", Age: 30, }","content":"Реальный пример **Код клиента ломается при смене кардинальности:** ```go // Before - поле фактически требуется (implicit) user := &myapi.User{ Name: \"John\", Email: \"john@example.com\", Age: 30, }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::24","title":"FIELD_SAME_CARDINALITY","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Реальный пример"],"excerpt":"Реальный пример if user.Email != \"\" { // Есть значение }","content":"Реальный пример if user.Email != \"\" { // Есть значение }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::25","title":"FIELD_SAME_CARDINALITY","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Реальный пример"],"excerpt":"Реальный пример // After - поле стало optional (pointer) user := &myapi.User{ Name: \"John\", Age: 30, // Email может отсутствовать }","content":"Реальный пример // After - поле стало optional (pointer) user := &myapi.User{ Name: \"John\", Age: 30, // Email может отсутствовать }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::26","title":"FIELD_SAME_CARDINALITY","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Реальный пример"],"excerpt":"Реальный пример if user.Email != nil && *user.Email != \"\" { // Есть значение (новый способ) }","content":"Реальный пример if user.Email != nil && *user.Email != \"\" { // Есть значение (новый способ) }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::27","title":"FIELD_SAME_CARDINALITY","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Реальный пример"],"excerpt":"Реальный пример user.Email = &emailValue // Присваивание указателя вместо строки ```","content":"Реальный пример user.Email = &emailValue // Присваивание указателя вместо строки ```"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::28","title":"FIELD_SAME_CARDINALITY","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Реальный пример"],"excerpt":"Реальный пример **Валидация на сервере:** ```go // Before func validateUser(user *User) error { if user.Email == \"\" { return errors.New(\"email is required\") } return nil }","content":"Реальный пример **Валидация на сервере:** ```go // Before func validateUser(user *User) error { if user.Email == \"\" { return errors.New(\"email is required\") } return nil }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::29","title":"FIELD_SAME_CARDINALITY","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Реальный пример"],"excerpt":"Реальный пример // After func validateUser(user *User) error { if user.Email == nil { return errors.New(\"email is required\") } if *user.Email == \"\" { return errors.New(\"email cannot be empty\") } return nil } ```","content":"Реальный пример // After func validateUser(user *User) error { if user.Email == nil { return errors.New(\"email is required\") } if *user.Email == \"\" { return errors.New(\"email cannot be empty\") } return nil } ```"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::30","title":"FIELD_SAME_CARDINALITY","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Добавьте новое поле** с нужной кардинальностью:","content":"Стратегия миграции **Добавьте новое поле** с нужной кардинальностью:"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::31","title":"FIELD_SAME_CARDINALITY","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Период двойной записи** — заполняйте оба поля:","content":"Стратегия миграции **Период двойной записи** — заполняйте оба поля:"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::32","title":"FIELD_SAME_CARDINALITY","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Клиенты постепенно переходят**:","content":"Стратегия миграции **Клиенты постепенно переходят**:"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::33","title":"FIELD_SAME_CARDINALITY","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Удаление старого поля** в следующей major‑версии:","content":"Стратегия миграции **Удаление старого поля** в следующей major‑версии:"},{"id":"cli/breaking-changes/rules/field-same-cardinality::proto2-proto3::34","title":"FIELD_SAME_CARDINALITY","section":"Миграция Proto2 → Proto3","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#proto2-proto3","headings":["Миграция Proto2 → Proto3"],"excerpt":"Миграция Proto2 → Proto3 ```proto syntax = \"proto3\"; message Order { string id = 1; // BREAKING если был required }","content":"Миграция Proto2 → Proto3 ```proto syntax = \"proto3\"; message Order { string id = 1; // BREAKING если был required }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::proto2-proto3::35","title":"FIELD_SAME_CARDINALITY","section":"Миграция Proto2 → Proto3","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#proto2-proto3","headings":["Миграция Proto2 → Proto3"],"excerpt":"Миграция Proto2 → Proto3 // Сохранить семантику: syntax = \"proto3\"; message Order { string id = 1; optional string notes = 2; } ```","content":"Миграция Proto2 → Proto3 // Сохранить семантику: syntax = \"proto3\"; message Order { string id = 1; optional string notes = 2; } ```"},{"id":"cli/breaking-changes/rules/field-same-cardinality::optional-required::36","title":"FIELD_SAME_CARDINALITY","section":"Делать optional поле required","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#optional-required","headings":["Делать optional поле required"],"excerpt":"Делать optional поле required ```proto message CreateUserRequest { string name = 1; string email = 2; // BREAKING (раньше optional) }","content":"Делать optional поле required ```proto message CreateUserRequest { string name = 1; string email = 2; // BREAKING (раньше optional) }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::optional-required::37","title":"FIELD_SAME_CARDINALITY","section":"Делать optional поле required","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#optional-required","headings":["Делать optional поле required"],"excerpt":"Делать optional поле required message CreateUserRequest { string name = 1; optional string email = 2 [deprecated = true]; string required_email = 3; } ```","content":"Делать optional поле required message CreateUserRequest { string name = 1; optional string email = 2 [deprecated = true]; string required_email = 3; } ```"},{"id":"cli/breaking-changes/rules/field-same-cardinality::required-optional::38","title":"FIELD_SAME_CARDINALITY","section":"Делать required поле optional","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#required-optional","headings":["Делать required поле optional"],"excerpt":"Делать required поле optional ```proto message User { optional string phone = 3; // BREAKING (было implicit required) }","content":"Делать required поле optional ```proto message User { optional string phone = 3; // BREAKING (было implicit required) }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::required-optional::39","title":"FIELD_SAME_CARDINALITY","section":"Делать required поле optional","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#required-optional","headings":["Делать required поле optional"],"excerpt":"Делать required поле optional message User { string phone = 3 [deprecated = true]; optional string phone_optional = 4; } ```","content":"Делать required поле optional message User { string phone = 3 [deprecated = true]; optional string phone_optional = 4; } ```"},{"id":"cli/breaking-changes/rules/field-same-cardinality::protobuf::40","title":"FIELD_SAME_CARDINALITY","section":"Типы кардинальности в Protobuf","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#protobuf","headings":["Типы кардинальности в Protobuf"],"excerpt":"Типы кардинальности в Protobuf","content":"Типы кардинальности в Protobuf"},{"id":"cli/breaking-changes/rules/field-same-cardinality::proto3::41","title":"FIELD_SAME_CARDINALITY","section":"Proto3","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#proto3","headings":["Proto3"],"excerpt":"Proto3 **Implicit optional**: string name = 1; **Explicit optional**: optional string email = 2; **Repeated**: repeated string tags = 3; **Map**: map metadata = 4;","content":"Proto3 **Implicit optional**: string name = 1; **Explicit optional**: optional string email = 2; **Repeated**: repeated string tags = 3; **Map**: map metadata = 4;"},{"id":"cli/breaking-changes/rules/field-same-cardinality::proto2::42","title":"FIELD_SAME_CARDINALITY","section":"Proto2","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#proto2","headings":["Proto2"],"excerpt":"Proto2 **Required**: required string id = 1; **Optional**: optional string email = 2; **Repeated**: repeated string tags = 3;","content":"Proto2 **Required**: required string id = 1; **Optional**: optional string email = 2; **Repeated**: repeated string tags = 3;"},{"id":"cli/breaking-changes/rules/field-same-cardinality::breaking::43","title":"FIELD_SAME_CARDINALITY","section":"Матрица Breaking изменений","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#breaking","headings":["Матрица Breaking изменений"],"excerpt":"Матрица Breaking изменений From To Result ------ ---- -------- Required Optional ❌ BREAKING Optional Required ❌ BREAKING Implicit Explicit ❌ BREAKING Explicit Implicit ❌ BREAKING Single Repeated ❌ BREAKING Repeated Singl","content":"Матрица Breaking изменений 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":"Правило проверяет, что типы полей сообщений (message fields) не изменяются. Смена типа поля ломает совместимость по wire‑формату и сгенерированный код: бинарное представление и ожидания клиентского кода различаются для р","content":"Правило проверяет, что типы полей сообщений (message fields) не изменяются. Смена типа поля ломает совместимость по wire‑формату и сгенерированный код: бинарное представление и ожидания клиентского кода различаются для разных типов."},{"id":"cli/breaking-changes/rules/field-same-type::breaking::1","title":"FIELD_SAME_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-same-type::breaking::2","title":"FIELD_SAME_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/field-same-type::breaking::3","title":"FIELD_SAME_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message Product { string name = 1; int32 price = 2; bool available = 3; } ```","content":"Плохой (Breaking) message Product { string name = 1; int32 price = 2; bool available = 3; } ```"},{"id":"cli/breaking-changes/rules/field-same-type::breaking::4","title":"FIELD_SAME_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-same-type::breaking::5","title":"FIELD_SAME_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/field-same-type::breaking::6","title":"FIELD_SAME_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message Product { string name = 1; string price = 2; // [!code --] Changed from int32 to string (изменён тип) bool available = 3; } ```","content":"Плохой (Breaking) 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::top::7","title":"FIELD_SAME_TYPE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/field-same-type","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры **Несовместимые изменения типов:** ```proto // Before message Order { string id = 1; int64 timestamp = 2; repeated string tags = 3; OrderStatus status = 4; }","content":"Дополнительные примеры **Несовместимые изменения типов:** ```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::top::8","title":"FIELD_SAME_TYPE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/field-same-type","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры // After - ВСЁ BREAKING message Order { int32 id = 1; // string -> int32: BREAKING string timestamp = 2; // int64 -> string: BREAKING string tags = 3; // repeated -> singular: BREAKING int32 status","content":"Дополнительные примеры // After - ВСЁ BREAKING 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::top::9","title":"FIELD_SAME_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо смены типа — добавьте новое поле:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо смены типа — добавьте новое поле:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-same-type::top::10","title":"FIELD_SAME_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/field-same-type::top::11","title":"FIELD_SAME_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message Product { string name = 1; int32 price = 2 [deprecated = true]; // [!code focus] // Старое поле помечено deprecated bool available = 3; string price_formatted = 4; // [!code focus] // Новое п","content":"Хороший (Безопасный) message Product { string name = 1; int32 price = 2 [deprecated = true]; // [!code focus] // Старое поле помечено deprecated bool available = 3; string price_formatted = 4; // [!code focus] // Новое поле со строковым представлением } ```"},{"id":"cli/breaking-changes/rules/field-same-type::top::12","title":"FIELD_SAME_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Или создайте новую версию сообщения:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Или создайте новую версию сообщения:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-same-type::top::13","title":"FIELD_SAME_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v2; // [!code focus] // Новая версия package","content":"Хороший (Безопасный) package myapi.v2; // [!code focus] // Новая версия package"},{"id":"cli/breaking-changes/rules/field-same-type::top::14","title":"FIELD_SAME_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message Product { string name = 1; string price = 2; // [!code focus] // В v2 уже string bool available = 3; } ```","content":"Хороший (Безопасный) message Product { string name = 1; string price = 2; // [!code focus] // В v2 уже string bool available = 3; } ```"},{"id":"cli/breaking-changes/rules/field-same-type::top::15","title":"FIELD_SAME_TYPE","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/field-same-type","headings":["Влияние"],"excerpt":"Влияние **Wire Format:** Старые бинарные данные не десериализуются корректно **Generated Code:** Меняются типы в сгенерированном коде — клиенты не компилируются **Runtime Errors:** Ошибки парсинга при несовпадении ожидае","content":"Влияние **Wire Format:** Старые бинарные данные не десериализуются корректно **Generated Code:** Меняются типы в сгенерированном коде — клиенты не компилируются **Runtime Errors:** Ошибки парсинга при несовпадении ожидаемого типа **Data Corruption:** Неверная интерпретация байтов данных"},{"id":"cli/breaking-changes/rules/field-same-type::top::16","title":"FIELD_SAME_TYPE","section":"Типовые проблемы изменений типов","path":"/docs/guide/cli/breaking-changes/rules/field-same-type","headings":["Типовые проблемы изменений типов"],"excerpt":"Типовые проблемы изменений типов","content":"Типовые проблемы изменений типов"},{"id":"cli/breaking-changes/rules/field-same-type::top::17","title":"FIELD_SAME_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/field-same-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Добавьте новое поле** с нужным типом:","content":"Стратегия миграции **Добавьте новое поле** с нужным типом:"},{"id":"cli/breaking-changes/rules/field-same-type::top::18","title":"FIELD_SAME_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/field-same-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Период двойной записи** — заполняйте оба поля для совместимости","content":"Стратегия миграции **Период двойной записи** — заполняйте оба поля для совместимости"},{"id":"cli/breaking-changes/rules/field-same-type::top::19","title":"FIELD_SAME_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/field-same-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Мигрируйте клиентов** на новое поле постепенно","content":"Стратегия миграции **Мигрируйте клиентов** на новое поле постепенно"},{"id":"cli/breaking-changes/rules/field-same-type::top::20","title":"FIELD_SAME_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/field-same-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Удалите старое поле** в следующей major‑версии:","content":"Стратегия миграции **Удалите старое поле** в следующей major‑версии:"},{"id":"cli/breaking-changes/rules/field-same-type::wire::21","title":"FIELD_SAME_TYPE","section":"Безопасные изменения (Теоретически wire‑совместимые)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type#wire","headings":["Безопасные изменения (Теоретически wire‑совместимые)"],"excerpt":"Безопасные изменения (Теоретически wire‑совместимые) Примечание: EasyP сейчас считает ЛЮБУЮ смену типа breaking. Однако технически некоторые случаи совместимы:","content":"Безопасные изменения (Теоретически wire‑совместимые) Примечание: EasyP сейчас считает ЛЮБУЮ смену типа breaking. Однако технически некоторые случаи совместимы:"},{"id":"cli/breaking-changes/rules/field-same-type::wire::22","title":"FIELD_SAME_TYPE","section":"Безопасные изменения (Теоретически wire‑совместимые)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type#wire","headings":["Безопасные изменения (Теоретически wire‑совместимые)"],"excerpt":"Безопасные изменения (Теоретически wire‑совместимые) int32 ↔ uint32 (одно кодирование) int64 ↔ uint64 (одно кодирование) string → bytes (если все строки валидный UTF‑8)","content":"Безопасные изменения (Теоретически wire‑совместимые) int32 ↔ uint32 (одно кодирование) int64 ↔ uint64 (одно кодирование) string → bytes (если все строки валидный UTF‑8)"},{"id":"cli/breaking-changes/rules/field-same-type::wire::23","title":"FIELD_SAME_TYPE","section":"Безопасные изменения (Теоретически wire‑совместимые)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type#wire","headings":["Безопасные изменения (Теоретически wire‑совместимые)"],"excerpt":"Безопасные изменения (Теоретически wire‑совместимые) Эти исключения могут получить отдельную обработку в будущих версиях EasyP с более гибкими уровнями строгости.","content":"Безопасные изменения (Теоретически wire‑совместимые) Эти исключения могут получить отдельную обработку в будущих версиях EasyP с более гибкими уровнями строгости."},{"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":"Это правило проверяет, что ни одна инструкция import не была удалена из proto‑файла. Удаление import ломает совместимость по wire‑формату и сгенерированный код: типы из импортируемых файлов могли использоваться в текущем","content":"Это правило проверяет, что ни одна инструкция import не была удалена из proto‑файла. Удаление import ломает совместимость по wire‑формату и сгенерированный код: типы из импортируемых файлов могли использоваться в текущем файле, и их удаление делает эти типы недоступными."},{"id":"cli/breaking-changes/rules/import-no-delete::breaking::1","title":"IMPORT_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/import-no-delete::breaking::2","title":"IMPORT_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/import-no-delete::breaking::3","title":"IMPORT_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) import \"google/protobuf/timestamp.proto\"; import \"google/protobuf/duration.proto\"; import \"common/user.proto\"; import \"common/address.proto\";","content":"Плохой (Breaking) 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::breaking::4","title":"IMPORT_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) 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":"Плохой (Breaking) 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::breaking::5","title":"IMPORT_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/import-no-delete::breaking::6","title":"IMPORT_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/import-no-delete::breaking::7","title":"IMPORT_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) import \"google/protobuf/timestamp.proto\"; // import \"google/protobuf/duration.proto\"; // [!code --] Удалён import — BREAKING // import \"common/user.proto\"; // [!code --] Удалён import — BREAKING // impo","content":"Плохой (Breaking) import \"google/protobuf/timestamp.proto\"; // import \"google/protobuf/duration.proto\"; // [!code --] Удалён import — BREAKING // import \"common/user.proto\"; // [!code --] Удалён import — BREAKING // import \"common/address.proto\"; // [!code --] Удалён import — BREAKING"},{"id":"cli/breaking-changes/rules/import-no-delete::breaking::8","title":"IMPORT_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message Order { string id = 1; google.protobuf.Timestamp created_at = 2; google.protobuf.Duration processing_time = 3; // ERROR: Duration недоступен common.User customer = 4; // ERROR: User недоступен c","content":"Плохой (Breaking) message Order { string id = 1; google.protobuf.Timestamp created_at = 2; google.protobuf.Duration processing_time = 3; // ERROR: Duration недоступен common.User customer = 4; // ERROR: User недоступен common.Address shipping_address = 5; // ERROR: Address недоступен } ```"},{"id":"cli/breaking-changes/rules/import-no-delete::top::9","title":"IMPORT_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры **Сервис ломается при удалённых import:** ```proto // Before import \"google/api/annotations.proto\"; import \"google/protobuf/empty.proto\"; import \"common/auth.proto\";","content":"Дополнительные примеры **Сервис ломается при удалённых import:** ```proto // Before import \"google/api/annotations.proto\"; import \"google/protobuf/empty.proto\"; import \"common/auth.proto\";"},{"id":"cli/breaking-changes/rules/import-no-delete::top::10","title":"IMPORT_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры service OrderService { rpc GetOrder(GetOrderRequest) returns (Order) { option (google.api.http) = { get: \"/v1/orders/{id}\" }; } rpc DeleteOrder(common.AuthRequest) returns (google.protobuf.Empty); ","content":"Дополнительные примеры 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::top::11","title":"IMPORT_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры // After - BREAKING CHANGES! // import \"google/api/annotations.proto\"; // BREAKING: deleted // import \"google/protobuf/empty.proto\"; // BREAKING: deleted // import \"common/auth.proto\"; // BREAKING:","content":"Дополнительные примеры // 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::top::12","title":"IMPORT_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры service OrderService { rpc GetOrder(GetOrderRequest) returns (Order) { option (google.api.http) = { // ERROR: annotations недоступен get: \"/v1/orders/{id}\" }; } rpc DeleteOrder(common.AuthRequest) ","content":"Дополнительные примеры service OrderService { rpc GetOrder(GetOrderRequest) returns (Order) { option (google.api.http) = { // ERROR: annotations недоступен get: \"/v1/orders/{id}\" }; } rpc DeleteOrder(common.AuthRequest) returns (google.protobuf.Empty); // ERROR: типы недоступны } ```"},{"id":"cli/breaking-changes/rules/import-no-delete::top::13","title":"IMPORT_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо удаления оставьте неиспользуемые import:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо удаления оставьте неиспользуемые import:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/import-no-delete::top::14","title":"IMPORT_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/import-no-delete::top::15","title":"IMPORT_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) import \"google/protobuf/timestamp.proto\"; import \"google/protobuf/duration.proto\"; // [!code focus] // Оставляем даже если не используется import \"common/user.proto\"; // [!code focus] import \"common/","content":"Хороший (Безопасный) import \"google/protobuf/timestamp.proto\"; import \"google/protobuf/duration.proto\"; // [!code focus] // Оставляем даже если не используется import \"common/user.proto\"; // [!code focus] import \"common/address.proto\"; // [!code focus]"},{"id":"cli/breaking-changes/rules/import-no-delete::top::16","title":"IMPORT_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message Order { string id = 1; google.protobuf.Timestamp created_at = 2; // Поля, использовавшие Duration/User/Address, удалены — import оставлены } ```","content":"Хороший (Безопасный) message Order { string id = 1; google.protobuf.Timestamp created_at = 2; // Поля, использовавшие Duration/User/Address, удалены — import оставлены } ```"},{"id":"cli/breaking-changes/rules/import-no-delete::top::17","title":"IMPORT_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Или добавьте новые типы, сохранив старые import:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Или добавьте новые типы, сохранив старые import:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/import-no-delete::top::18","title":"IMPORT_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/import-no-delete::top::19","title":"IMPORT_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) import \"google/protobuf/timestamp.proto\"; import \"google/protobuf/duration.proto\"; // [!code focus] import \"common/user.proto\"; // [!code focus] import \"common/address.proto\"; // [!code focus] import","content":"Хороший (Безопасный) import \"google/protobuf/timestamp.proto\"; import \"google/protobuf/duration.proto\"; // [!code focus] import \"common/user.proto\"; // [!code focus] import \"common/address.proto\"; // [!code focus] import \"common/v2/user.proto\"; // [!code focus] // Новый import"},{"id":"cli/breaking-changes/rules/import-no-delete::top::20","title":"IMPORT_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message Order { string id = 1; google.protobuf.Timestamp created_at = 2; google.protobuf.Duration processing_time = 3 [deprecated = true]; // [!code focus] common.User customer = 4 [deprecated = true","content":"Хороший (Безопасный) message Order { string id = 1; google.protobuf.Timestamp created_at = 2; google.protobuf.Duration processing_time = 3 [deprecated = true]; // [!code focus] common.User customer = 4 [deprecated = true]; // [!code focus] common.Address shipping_address = 5 [deprecated = true]; // [!code focus] int32 processing_seconds = 6; common.v2.UserProfile customer_v2 = 7; string shipping_address_text = 8; } ```"},{"id":"cli/breaking-changes/rules/import-no-delete::top::21","title":"IMPORT_NO_DELETE","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Влияние"],"excerpt":"Влияние **Generated Code:** Типы пропадают → ошибка компиляции **Wire Format:** Сообщения с удалёнными типами не десериализуются **Field References:** Поля с этими типами становятся невалидны **Service Definitions:** RPC","content":"Влияние **Generated Code:** Типы пропадают → ошибка компиляции **Wire Format:** Сообщения с удалёнными типами не десериализуются **Field References:** Поля с этими типами становятся невалидны **Service Definitions:** RPC с типами из удалённых файлов ломаются **Options Usage:** Пользовательские опции из импортов недоступны"},{"id":"cli/breaking-changes/rules/import-no-delete::top::22","title":"IMPORT_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Код клиента ломается:**","content":"Реальный пример **Код клиента ломается:**"},{"id":"cli/breaking-changes/rules/import-no-delete::top::23","title":"IMPORT_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Серверная логика ломается:**","content":"Реальный пример **Серверная логика ломается:**"},{"id":"cli/breaking-changes/rules/import-no-delete::top::24","title":"IMPORT_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Компиляция proto ломается:**","content":"Реальный пример **Компиляция proto ломается:**"},{"id":"cli/breaking-changes/rules/import-no-delete::top::25","title":"IMPORT_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции Сохраняйте import даже если типы более не используются: Добавляйте новые import рядом со старыми: Депрецируйте поля со старыми типами постепенно: Сервер: поддерживайте оба варианта: Удаляйте import тол","content":"Стратегия миграции Сохраняйте import даже если типы более не используются: Добавляйте новые import рядом со старыми: Депрецируйте поля со старыми типами постепенно: Сервер: поддерживайте оба варианта: Удаляйте import только в следующей major‑версии после полной миграции."},{"id":"cli/breaking-changes/rules/import-no-delete::top::26","title":"IMPORT_NO_DELETE","section":"Замена зависимости","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Замена зависимости"],"excerpt":"Замена зависимости ```proto import \"old/user.proto\"; // Старый import \"new/user.proto\"; // Новый","content":"Замена зависимости ```proto import \"old/user.proto\"; // Старый import \"new/user.proto\"; // Новый"},{"id":"cli/breaking-changes/rules/import-no-delete::top::27","title":"IMPORT_NO_DELETE","section":"Замена зависимости","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Замена зависимости"],"excerpt":"Замена зависимости message Order { old.User customer = 4 [deprecated = true]; new.UserProfile customer_v2 = 5; } ```","content":"Замена зависимости message Order { old.User customer = 4 [deprecated = true]; new.UserProfile customer_v2 = 5; } ```"},{"id":"cli/breaking-changes/rules/import-no-delete::top::28","title":"IMPORT_NO_DELETE","section":"Удаление функционала","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Удаление функционала"],"excerpt":"Удаление функционала ```proto import \"feature/analytics.proto\"; // Оставить даже если поле удалено","content":"Удаление функционала ```proto import \"feature/analytics.proto\"; // Оставить даже если поле удалено"},{"id":"cli/breaking-changes/rules/import-no-delete::top::29","title":"IMPORT_NO_DELETE","section":"Удаление функционала","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Удаление функционала"],"excerpt":"Удаление функционала message Order { string id = 1; // feature.AnalyticsData analytics = 2; // Поле удалено, import остаётся } ```","content":"Удаление функционала message Order { string id = 1; // feature.AnalyticsData analytics = 2; // Поле удалено, import остаётся } ```"},{"id":"cli/breaking-changes/rules/import-no-delete::protobuf::30","title":"IMPORT_NO_DELETE","section":"Миграция версии protobuf","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#protobuf","headings":["Миграция версии protobuf"],"excerpt":"Миграция версии protobuf ```proto import \"google/protobuf/timestamp.proto\"; import \"google/protobuf/duration.proto\";","content":"Миграция версии protobuf ```proto import \"google/protobuf/timestamp.proto\"; import \"google/protobuf/duration.proto\";"},{"id":"cli/breaking-changes/rules/import-no-delete::protobuf::31","title":"IMPORT_NO_DELETE","section":"Миграция версии protobuf","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#protobuf","headings":["Миграция версии protobuf"],"excerpt":"Миграция версии protobuf message Event { google.protobuf.Timestamp timestamp = 1; int64 timestamp_millis = 2; } ```","content":"Миграция версии protobuf message Event { google.protobuf.Timestamp timestamp = 1; int64 timestamp_millis = 2; } ```"},{"id":"cli/breaking-changes/rules/import-no-delete::top::32","title":"IMPORT_NO_DELETE","section":"Упрощение сложных зависимостей","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Упрощение сложных зависимостей"],"excerpt":"Упрощение сложных зависимостей ```proto import \"complex/config.proto\";","content":"Упрощение сложных зависимостей ```proto import \"complex/config.proto\";"},{"id":"cli/breaking-changes/rules/import-no-delete::top::33","title":"IMPORT_NO_DELETE","section":"Упрощение сложных зависимостей","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Упрощение сложных зависимостей"],"excerpt":"Упрощение сложных зависимостей message Settings { complex.ConfigData config = 1 [deprecated = true]; string config_json = 2; } ```","content":"Упрощение сложных зависимостей message Settings { complex.ConfigData config = 1 [deprecated = true]; string config_json = 2; } ```"},{"id":"cli/breaking-changes/rules/import-no-delete::import-vs::34","title":"IMPORT_NO_DELETE","section":"Удаление import vs использование поля","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#import-vs","headings":["Удаление import vs использование поля"],"excerpt":"Удаление import vs использование поля","content":"Удаление import vs использование поля"},{"id":"cli/breaking-changes/rules/import-no-delete::import::35","title":"IMPORT_NO_DELETE","section":"Аудит import","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#import","headings":["Аудит import"],"excerpt":"Аудит import (Даже если не найдено — не удаляем.)","content":"Аудит 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":"Это правило проверяет, что ни одно сообщение (message) не было удалено из proto‑файлов. Удаление message ломает совместимость по wire‑формату и сгенерированный код: в существующих данных могут присутствовать экземпляры у","content":"Это правило проверяет, что ни одно сообщение (message) не было удалено из proto‑файлов. Удаление message ломает совместимость по wire‑формату и сгенерированный код: в существующих данных могут присутствовать экземпляры удалённого типа, а клиентский код зависит от сгенерированных структур и классов."},{"id":"cli/breaking-changes/rules/message-no-delete::breaking::1","title":"MESSAGE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/message-no-delete::breaking::2","title":"MESSAGE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/message-no-delete::breaking::3","title":"MESSAGE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message User { string name = 1; string email = 2; Address address = 3; }","content":"Плохой (Breaking) message User { string name = 1; string email = 2; Address address = 3; }"},{"id":"cli/breaking-changes/rules/message-no-delete::breaking::4","title":"MESSAGE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message Address { // [!code --] string street = 1; // [!code --] string city = 2; // [!code --] string country = 3; // [!code --] } // [!code --]","content":"Плохой (Breaking) message Address { // [!code --] string street = 1; // [!code --] string city = 2; // [!code --] string country = 3; // [!code --] } // [!code --]"},{"id":"cli/breaking-changes/rules/message-no-delete::breaking::5","title":"MESSAGE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message Order { string id = 1; User user = 2; } ```","content":"Плохой (Breaking) message Order { string id = 1; User user = 2; } ```"},{"id":"cli/breaking-changes/rules/message-no-delete::breaking::6","title":"MESSAGE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/message-no-delete::breaking::7","title":"MESSAGE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/message-no-delete::breaking::8","title":"MESSAGE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message User { string name = 1; string email = 2; Address address = 3; // ERROR: Address больше не существует }","content":"Плохой (Breaking) message User { string name = 1; string email = 2; Address address = 3; // ERROR: Address больше не существует }"},{"id":"cli/breaking-changes/rules/message-no-delete::breaking::9","title":"MESSAGE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) // Address удалён — BREAKING CHANGE!","content":"Плохой (Breaking) // Address удалён — BREAKING CHANGE!"},{"id":"cli/breaking-changes/rules/message-no-delete::breaking::10","title":"MESSAGE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message Order { string id = 1; User user = 2; } ```","content":"Плохой (Breaking) message Order { string id = 1; User user = 2; } ```"},{"id":"cli/breaking-changes/rules/message-no-delete::top::11","title":"MESSAGE_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры **Удаление вложенного сообщения:**","content":"Дополнительные примеры **Удаление вложенного сообщения:**"},{"id":"cli/breaking-changes/rules/message-no-delete::top::12","title":"MESSAGE_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры ```proto // Before message User { string name = 1; Profile profile = 2; message Profile { // [!code --] string bio = 1; // [!code --] string avatar_url = 2; // [!code --] } // [!code --] }","content":"Дополнительные примеры ```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::top::13","title":"MESSAGE_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры // After - BREAKING CHANGE! message User { string name = 1; Profile profile = 2; // ERROR: Profile удалён // Вложенное сообщение Profile удалено } ```","content":"Дополнительные примеры // After - BREAKING CHANGE! message User { string name = 1; Profile profile = 2; // ERROR: Profile удалён // Вложенное сообщение Profile удалено } ```"},{"id":"cli/breaking-changes/rules/message-no-delete::top::14","title":"MESSAGE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо удаления — пометить как deprecated:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо удаления — пометить как deprecated:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/message-no-delete::top::15","title":"MESSAGE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/message-no-delete::top::16","title":"MESSAGE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message User { string name = 1; string email = 2; Address address = 3 [deprecated = true]; // [!code focus] }","content":"Хороший (Безопасный) message User { string name = 1; string email = 2; Address address = 3 [deprecated = true]; // [!code focus] }"},{"id":"cli/breaking-changes/rules/message-no-delete::top::17","title":"MESSAGE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message Address { option deprecated = true; // [!code focus] string street = 1; string city = 2; string country = 3; }","content":"Хороший (Безопасный) message Address { option deprecated = true; // [!code focus] string street = 1; string city = 2; string country = 3; }"},{"id":"cli/breaking-changes/rules/message-no-delete::top::18","title":"MESSAGE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message Order { string id = 1; User user = 2; } ```","content":"Хороший (Безопасный) message Order { string id = 1; User user = 2; } ```"},{"id":"cli/breaking-changes/rules/message-no-delete::top::19","title":"MESSAGE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Или заменить новой версией сообщения:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Или заменить новой версией сообщения:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/message-no-delete::top::20","title":"MESSAGE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/message-no-delete::top::21","title":"MESSAGE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message User { string name = 1; string email = 2; Address address = 3 [deprecated = true]; // [!code focus] // Старое поле AddressV2 address_v2 = 4; // [!code focus] // Новая улучшенная структура }","content":"Хороший (Безопасный) message User { string name = 1; string email = 2; Address address = 3 [deprecated = true]; // [!code focus] // Старое поле AddressV2 address_v2 = 4; // [!code focus] // Новая улучшенная структура }"},{"id":"cli/breaking-changes/rules/message-no-delete::top::22","title":"MESSAGE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message Address { option deprecated = true; // [!code focus] string street = 1; string city = 2; string country = 3; }","content":"Хороший (Безопасный) message Address { option deprecated = true; // [!code focus] string street = 1; string city = 2; string country = 3; }"},{"id":"cli/breaking-changes/rules/message-no-delete::top::23","title":"MESSAGE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) 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 c","content":"Хороший (Безопасный) 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::top::24","title":"MESSAGE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message Order { string id = 1; User user = 2; } ```","content":"Хороший (Безопасный) message Order { string id = 1; User user = 2; } ```"},{"id":"cli/breaking-changes/rules/message-no-delete::top::25","title":"MESSAGE_NO_DELETE","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Влияние"],"excerpt":"Влияние **Wire Format:** Старые данные с удалённым сообщением не десериализуются **Generated Code:** Классы/структуры удаляются — компиляция клиента ломается **Field References:** Поля, использующие удалённый тип, станов","content":"Влияние **Wire Format:** Старые данные с удалённым сообщением не десериализуются **Generated Code:** Классы/структуры удаляются — компиляция клиента ломается **Field References:** Поля, использующие удалённый тип, становятся невалидны **Nested Dependencies:** Все сообщения, ссылающиеся на удалённый тип, ломаются"},{"id":"cli/breaking-changes/rules/message-no-delete::top::26","title":"MESSAGE_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Код клиента ломается:** ```go // Before user := &myapi.User{ Name: \"John Doe\", Email: \"john@example.com\", Address: &myapi.Address{ // ERROR после удаления Street: \"123 Main St\", City: \"New York\", Countr","content":"Реальный пример **Код клиента ломается:** ```go // Before user := &myapi.User{ Name: \"John Doe\", Email: \"john@example.com\", Address: &myapi.Address{ // ERROR после удаления Street: \"123 Main St\", City: \"New York\", Country: \"USA\", }, }"},{"id":"cli/breaking-changes/rules/message-no-delete::top::27","title":"MESSAGE_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример // undefined: myapi.Address ```","content":"Реальный пример // undefined: myapi.Address ```"},{"id":"cli/breaking-changes/rules/message-no-delete::top::28","title":"MESSAGE_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Старые данные становятся нечитаемыми:**","content":"Реальный пример **Старые данные становятся нечитаемыми:**"},{"id":"cli/breaking-changes/rules/message-no-delete::top::29","title":"MESSAGE_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Пометить как deprecated:** **Пометить поля, использующие его:** **Добавить замену при необходимости:** **Удалить в следующей major‑версии после периода миграции**","content":"Стратегия миграции **Пометить как deprecated:** **Пометить поля, использующие его:** **Добавить замену при необходимости:** **Удалить в следующей major‑версии после периода миграции**"},{"id":"cli/breaking-changes/rules/message-no-delete::top::30","title":"MESSAGE_NO_DELETE","section":"Рефакторинг структуры","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Рефакторинг структуры"],"excerpt":"Рефакторинг структуры ```proto message UserInfo { option deprecated = true; string name = 1; string email = 2; }","content":"Рефакторинг структуры ```proto message UserInfo { option deprecated = true; string name = 1; string email = 2; }"},{"id":"cli/breaking-changes/rules/message-no-delete::top::31","title":"MESSAGE_NO_DELETE","section":"Рефакторинг структуры","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Рефакторинг структуры"],"excerpt":"Рефакторинг структуры message UserProfile { string full_name = 1; string email_address = 2; string phone = 3; } ```","content":"Рефакторинг структуры message UserProfile { string full_name = 1; string email_address = 2; string phone = 3; } ```"},{"id":"cli/breaking-changes/rules/message-no-delete::top::32","title":"MESSAGE_NO_DELETE","section":"Удаление «неиспользуемых» сообщений","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Удаление «неиспользуемых» сообщений"],"excerpt":"Удаление «неиспользуемых» сообщений","content":"Удаление «неиспользуемых» сообщений"},{"id":"cli/breaking-changes/rules/message-no-delete::top::33","title":"MESSAGE_NO_DELETE","section":"Миграция версии","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Миграция версии"],"excerpt":"Миграция версии ```proto package myapi.v2;","content":"Миграция версии ```proto package myapi.v2;"},{"id":"cli/breaking-changes/rules/message-no-delete::top::34","title":"MESSAGE_NO_DELETE","section":"Миграция версии","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Миграция версии"],"excerpt":"Миграция версии message User { // Новая структура без устаревших ссылок } ```","content":"Миграция версии message User { // Новая структура без устаревших ссылок } ```"},{"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":"Правило проверяет, что ни одно поле внутри oneof группы не было удалено. Удаление поля из oneof ломает совместимость по wire‑формату и сгенерированный код: в сохранённых данных может присутствовать выбранный вариант, а к","content":"Правило проверяет, что ни одно поле внутри oneof группы не было удалено. Удаление поля из oneof ломает совместимость по wire‑формату и сгенерированный код: в сохранённых данных может присутствовать выбранный вариант, а клиентский код опирается на сгенерированные типы‑обёртки и методы доступа."},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::breaking::1","title":"ONEOF_FIELD_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::breaking::2","title":"ONEOF_FIELD_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::breaking::3","title":"ONEOF_FIELD_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message LoginRequest { string username = 1; oneof credentials { string password = 2; string api_key = 3; string oauth_token = 4; string certificate = 5; } }","content":"Плохой (Breaking) 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::breaking::4","title":"ONEOF_FIELD_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message SearchQuery { oneof filter { string text = 1; int32 user_id = 2; string category = 3; DateRange date_range = 4; } } ```","content":"Плохой (Breaking) 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::breaking::5","title":"ONEOF_FIELD_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::breaking::6","title":"ONEOF_FIELD_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::breaking::7","title":"ONEOF_FIELD_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message LoginRequest { string username = 1; oneof credentials { string password = 2; string api_key = 3; // string oauth_token = 4; // [!code --] Удалено поле oneof — BREAKING! // string certificate = 5","content":"Плохой (Breaking) message LoginRequest { string username = 1; oneof credentials { string password = 2; string api_key = 3; // string oauth_token = 4; // [!code --] Удалено поле oneof — BREAKING! // string certificate = 5; // [!code --] Удалено поле oneof — BREAKING! } }"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::breaking::8","title":"ONEOF_FIELD_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message SearchQuery { oneof filter { string text = 1; int32 user_id = 2; // string category = 3; // [!code --] Удалено поле oneof — BREAKING! // DateRange date_range = 4; // [!code --] Удалено поле oneo","content":"Плохой (Breaking) message SearchQuery { oneof filter { string text = 1; int32 user_id = 2; // string category = 3; // [!code --] Удалено поле oneof — BREAKING! // DateRange date_range = 4; // [!code --] Удалено поле oneof — BREAKING! } } ```"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::9","title":"ONEOF_FIELD_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры **Удаление вложенных oneof полей:** ```proto // Before message PaymentRequest { string order_id = 1; oneof payment_method { CreditCardPayment credit_card = 2; BankTransferPayment bank_transfer = 3;","content":"Дополнительные примеры **Удаление вложенных oneof полей:** ```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::top::10","title":"ONEOF_FIELD_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры // After - BREAKING CHANGES! message PaymentRequest { string order_id = 1; oneof payment_method { CreditCardPayment credit_card = 2; BankTransferPayment bank_transfer = 3; // CryptoPayment crypto =","content":"Дополнительные примеры // 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::top::11","title":"ONEOF_FIELD_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо удаления — пометить поля deprecated:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо удаления — пометить поля deprecated:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::12","title":"ONEOF_FIELD_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::13","title":"ONEOF_FIELD_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) 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 [deprecate","content":"Хороший (Безопасный) 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::top::14","title":"ONEOF_FIELD_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) 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":"Хороший (Безопасный) 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::top::15","title":"ONEOF_FIELD_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Или добавить новые поля, оставив старые:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Или добавить новые поля, оставив старые:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::16","title":"ONEOF_FIELD_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::17","title":"ONEOF_FIELD_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message LoginRequest { string username = 1; oneof credentials { string password = 2; string api_key = 3; string oauth_token = 4 [deprecated = true]; // [!code focus] // Старое поле string certificate","content":"Хороший (Безопасный) 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] OAuthCredentials oauth_v2 = 6; // [!code focus] // Новый структурированный вариант CertificateCredentials cert_v2 = 7; // [!code focus] } } ```"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::18","title":"ONEOF_FIELD_NO_DELETE","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Влияние"],"excerpt":"Влияние **Wire Format:** Данные, содержащие удалённый вариант, не десериализуются корректно **Generated Code:** Удаляются типы‑обёртки и accessor методы — компиляция клиентов ломается **Type Safety:** Логика switch по ти","content":"Влияние **Wire Format:** Данные, содержащие удалённый вариант, не десериализуются корректно **Generated Code:** Удаляются типы‑обёртки и accessor методы — компиляция клиентов ломается **Type Safety:** Логика switch по типам oneof разваливается **Business Logic:** Код, ожидающий конкретный вариант, перестаёт работать"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::19","title":"ONEOF_FIELD_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Код клиента ломается:** ```go // Before loginReq := &myapi.LoginRequest{ Username: \"user123\", }","content":"Реальный пример **Код клиента ломается:** ```go // Before loginReq := &myapi.LoginRequest{ Username: \"user123\", }"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::20","title":"ONEOF_FIELD_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример loginReq.Credentials = &myapi.LoginRequest_OauthToken{ OauthToken: \"token123\", // ERROR после удаления поля }","content":"Реальный пример loginReq.Credentials = &myapi.LoginRequest_OauthToken{ OauthToken: \"token123\", // ERROR после удаления поля }"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::21","title":"ONEOF_FIELD_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример switch cred := loginReq.Credentials.(type) { case *myapi.LoginRequest_Password: return authenticatePassword(cred.Password) case *myapi.LoginRequest_OauthToken: // ERROR: тип удалён return authenticateOAut","content":"Реальный пример switch cred := loginReq.Credentials.(type) { case *myapi.LoginRequest_Password: return authenticatePassword(cred.Password) case *myapi.LoginRequest_OauthToken: // ERROR: тип удалён return authenticateOAuth(cred.OauthToken) case *myapi.LoginRequest_Certificate: // ERROR: тип удалён return authenticateCert(cred.Certificate) default: return errors.New(\"unsupported credential type\") } // undefined: myapi.LoginRequest_OauthToken // undefined: myapi.LoginRequest_Certificate ```"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::22","title":"ONEOF_FIELD_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Серверная логика ломается:**","content":"Реальный пример **Серверная логика ломается:**"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::23","title":"ONEOF_FIELD_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Старые данные становятся нечитаемыми:**","content":"Реальный пример **Старые данные становятся нечитаемыми:**"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::24","title":"ONEOF_FIELD_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Депрецируйте сначала:** **Добавьте новые структурированные поля:** **Сервер: поддерживайте оба варианта:** **Мигрируйте клиентов на новое поле:** **Зарезервируйте номера удалённых полей в следующей m","content":"Стратегия миграции **Депрецируйте сначала:** **Добавьте новые структурированные поля:** **Сервер: поддерживайте оба варианта:** **Мигрируйте клиентов на новое поле:** **Зарезервируйте номера удалённых полей в следующей major‑версии:**"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::25","title":"ONEOF_FIELD_NO_DELETE","section":"Удаление неподдерживаемых методов аутентификации","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Удаление неподдерживаемых методов аутентификации"],"excerpt":"Удаление неподдерживаемых методов аутентификации","content":"Удаление неподдерживаемых методов аутентификации"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::26","title":"ONEOF_FIELD_NO_DELETE","section":"Изменения бизнес‑логики платежей","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Изменения бизнес‑логики платежей"],"excerpt":"Изменения бизнес‑логики платежей","content":"Изменения бизнес‑логики платежей"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::oneof-field-deletion-vs::27","title":"ONEOF_FIELD_NO_DELETE","section":"OneOf Field Deletion vs обычное удаление","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#oneof-field-deletion-vs","headings":["OneOf Field Deletion vs обычное удаление"],"excerpt":"OneOf Field Deletion vs обычное удаление","content":"OneOf Field Deletion vs обычное удаление"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::28","title":"ONEOF_FIELD_NO_DELETE","section":"Отличия от удаления обычного поля","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Отличия от удаления обычного поля"],"excerpt":"Отличия от удаления обычного поля ```proto message User { string name = 1; // string email = 2; // BREAKING: обычное поле }","content":"Отличия от удаления обычного поля ```proto message User { string name = 1; // string email = 2; // BREAKING: обычное поле }"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::29","title":"ONEOF_FIELD_NO_DELETE","section":"Отличия от удаления обычного поля","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Отличия от удаления обычного поля"],"excerpt":"Отличия от удаления обычного поля message User { oneof contact { string email = 1; // string phone = 2; // BREAKING: поле в oneof } } ```","content":"Отличия от удаления обычного поля message User { oneof contact { string email = 1; // string phone = 2; // BREAKING: поле в oneof } } ```"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::30","title":"ONEOF_FIELD_NO_DELETE","section":"Влияние на сгенерированный код","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Влияние на сгенерированный код"],"excerpt":"Влияние на сгенерированный код ```go // Обычное поле: удаляется простой геттер // user.GetEmail()","content":"Влияние на сгенерированный код ```go // Обычное поле: удаляется простой геттер // user.GetEmail()"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::31","title":"ONEOF_FIELD_NO_DELETE","section":"Влияние на сгенерированный код","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Влияние на сгенерированный код"],"excerpt":"Влияние на сгенерированный код // Поле в oneof: пропадает тип-обёртка, кейсы switch ломаются // *LoginRequest_OauthToken ```","content":"Влияние на сгенерированный код // Поле в oneof: пропадает тип-обёртка, кейсы switch ломаются // *LoginRequest_OauthToken ```"},{"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":"Это правило проверяет, что тип поля внутри oneof НЕ меняется. Смена типа любого варианта oneof — несовместимое (breaking) изменение: существующие данные сериализованы с прежним типом, а клиентский код ожидает конкретные ","content":"Это правило проверяет, что тип поля внутри oneof НЕ меняется. Смена типа любого варианта oneof — несовместимое (breaking) изменение: существующие данные сериализованы с прежним типом, а клиентский код ожидает конкретные типы-обёртки и методы доступа, сгенерированные для каждого варианта."},{"id":"cli/breaking-changes/rules/oneof-field-same-type::breaking::1","title":"ONEOF_FIELD_SAME_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::breaking::2","title":"ONEOF_FIELD_SAME_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::breaking::3","title":"ONEOF_FIELD_SAME_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message SearchRequest { string query = 1; oneof filter { string category = 2; int32 user_id = 3; bool is_premium = 4; DateRange date_range = 5; } }","content":"Плохой (Breaking) 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::breaking::4","title":"ONEOF_FIELD_SAME_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message NotificationSettings { oneof delivery { string email = 1; int64 phone_number = 2; WebhookConfig webhook = 3; } } ```","content":"Плохой (Breaking) message NotificationSettings { oneof delivery { string email = 1; int64 phone_number = 2; WebhookConfig webhook = 3; } } ```"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::breaking::5","title":"ONEOF_FIELD_SAME_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::breaking::6","title":"ONEOF_FIELD_SAME_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::breaking::7","title":"ONEOF_FIELD_SAME_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message SearchRequest { string query = 1; oneof filter { int32 category = 2; // [!code --] Было string -> стало int32 (BREAKING) string user_id = 3; // [!code --] Было int32 -> стало string (BREAKING) s","content":"Плохой (Breaking) message SearchRequest { string query = 1; oneof filter { int32 category = 2; // [!code --] Было string -> стало int32 (BREAKING) string user_id = 3; // [!code --] Было int32 -> стало string (BREAKING) string is_premium = 4; // [!code --] Было bool -> стало string (BREAKING) string date_range = 5; // [!code --] Было DateRange -> стало string (BREAKING) } }"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::breaking::8","title":"ONEOF_FIELD_SAME_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message NotificationSettings { oneof delivery { EmailConfig email = 1; // [!code --] Было string -> стало EmailConfig (BREAKING) string phone_number = 2; // [!code --] Было int64 -> стало string (BREAKI","content":"Плохой (Breaking) message NotificationSettings { oneof delivery { EmailConfig email = 1; // [!code --] Было string -> стало EmailConfig (BREAKING) string phone_number = 2; // [!code --] Было int64 -> стало string (BREAKING) string webhook = 3; // [!code --] Было WebhookConfig -> стало string (BREAKING) } } ```"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::9","title":"ONEOF_FIELD_SAME_TYPE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры **Комплексные изменения типов:** ```proto // Before message PaymentRequest { oneof payment_info { CreditCardInfo credit_card = 1; BankAccountInfo bank_account = 2; string paypal_email = 3; CryptoWa","content":"Дополнительные примеры **Комплексные изменения типов:** ```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::top::10","title":"ONEOF_FIELD_SAME_TYPE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры // After - ВСЁ BREAKING message PaymentRequest { oneof payment_info { string credit_card = 1; // CreditCardInfo -> string PayPalInfo bank_account = 2; // BankAccountInfo -> PayPalInfo PayPalInfo pa","content":"Дополнительные примеры // After - ВСЁ BREAKING message PaymentRequest { oneof payment_info { string credit_card = 1; // CreditCardInfo -> string PayPalInfo bank_account = 2; // BankAccountInfo -> PayPalInfo PayPalInfo paypal_email = 3; // string -> PayPalInfo string crypto = 4; // CryptoWalletInfo -> string } } ```"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::11","title":"ONEOF_FIELD_SAME_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо смены типа — добавьте новое поле в тот же oneof:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо смены типа — добавьте новое поле в тот же oneof:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::12","title":"ONEOF_FIELD_SAME_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::13","title":"ONEOF_FIELD_SAME_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message SearchRequest { string query = 1; oneof filter { string category = 2 [deprecated = true]; // Старый тип int32 user_id = 3 [deprecated = true]; bool is_premium = 4 [deprecated = true]; DateRan","content":"Хороший (Безопасный) message SearchRequest { string query = 1; oneof filter { string category = 2 [deprecated = true]; // Старый тип int32 user_id = 3 [deprecated = true]; bool is_premium = 4 [deprecated = true]; DateRange date_range = 5 [deprecated = true]; int32 category_id = 6; // Новая версия string user_identifier = 7; string premium_status = 8; string date_filter = 9; } } ```"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::14","title":"ONEOF_FIELD_SAME_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Или создайте новый oneof:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Или создайте новый oneof:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::15","title":"ONEOF_FIELD_SAME_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::16","title":"ONEOF_FIELD_SAME_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message SearchRequest { string query = 1; oneof filter { option deprecated = true; string category = 2 [deprecated = true]; int32 user_id = 3 [deprecated = true]; bool is_premium = 4 [deprecated = tr","content":"Хороший (Безопасный) message SearchRequest { string query = 1; oneof filter { option deprecated = true; string category = 2 [deprecated = true]; int32 user_id = 3 [deprecated = true]; bool is_premium = 4 [deprecated = true]; DateRange date_range = 5 [deprecated = true]; } oneof filter_v2 { int32 category_id = 6; string user_identifier = 7; PremiumFilter premium_filter = 8; TimeFilter time_filter = 9; } } ```"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::17","title":"ONEOF_FIELD_SAME_TYPE","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Влияние"],"excerpt":"Влияние **Wire Format:** Старые бинарные данные не читаются корректно **Generated Code:** Меняются типы-обёртки, код клиента не компилируется **Type Safety:** switch по варианту oneof ломается **Runtime Errors:** Ошибки ","content":"Влияние **Wire Format:** Старые бинарные данные не читаются корректно **Generated Code:** Меняются типы-обёртки, код клиента не компилируется **Type Safety:** switch по варианту oneof ломается **Runtime Errors:** Ошибки десериализации и логики при несовпадении типов"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::18","title":"ONEOF_FIELD_SAME_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Реальный пример"],"excerpt":"Реальный пример **Ломается клиентский код:** ```go // Before searchReq := &myapi.SearchRequest{ Query: \"golang jobs\", }","content":"Реальный пример **Ломается клиентский код:** ```go // Before searchReq := &myapi.SearchRequest{ Query: \"golang jobs\", }"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::19","title":"ONEOF_FIELD_SAME_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Реальный пример"],"excerpt":"Реальный пример // Устанавливаем вариант oneof searchReq.Filter = &myapi.SearchRequest_Category{ Category: \"engineering\", }","content":"Реальный пример // Устанавливаем вариант oneof searchReq.Filter = &myapi.SearchRequest_Category{ Category: \"engineering\", }"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::20","title":"ONEOF_FIELD_SAME_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Реальный пример"],"excerpt":"Реальный пример // Обработка вариантов switch filter := searchReq.Filter.(type) { case *myapi.SearchRequest_Category: return searchByCategory(filter.Category) case *myapi.SearchRequest_UserId: return searchByUserId(filte","content":"Реальный пример // Обработка вариантов switch filter := searchReq.Filter.(type) { case *myapi.SearchRequest_Category: return searchByCategory(filter.Category) case *myapi.SearchRequest_UserId: return searchByUserId(filter.UserId) default: return errors.New(\"unsupported filter\") }"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::21","title":"ONEOF_FIELD_SAME_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Реальный пример"],"excerpt":"Реальный пример // After — тип Category стал int32 searchReq.Filter = &myapi.SearchRequest_Category{ Category: \"engineering\", // ERROR }","content":"Реальный пример // After — тип Category стал int32 searchReq.Filter = &myapi.SearchRequest_Category{ Category: \"engineering\", // ERROR }"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::22","title":"ONEOF_FIELD_SAME_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Реальный пример"],"excerpt":"Реальный пример switch filter := searchReq.Filter.(type) { case *myapi.SearchRequest_Category: return searchByCategory(filter.Category) // ERROR case *myapi.SearchRequest_UserId: return searchByUserId(filter.UserId) // E","content":"Реальный пример switch filter := searchReq.Filter.(type) { case *myapi.SearchRequest_Category: return searchByCategory(filter.Category) // ERROR case *myapi.SearchRequest_UserId: return searchByUserId(filter.UserId) // ERROR: UserId теперь string } ```"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::23","title":"ONEOF_FIELD_SAME_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Реальный пример"],"excerpt":"Реальный пример **Ломается серверная логика:** ```go // Before func handleSearchFilter(req *SearchRequest) (*SearchResult, error) { switch filter := req.Filter.(type) { case *SearchRequest_Category: return searchDatabase","content":"Реальный пример **Ломается серверная логика:** ```go // Before func handleSearchFilter(req *SearchRequest) (*SearchResult, error) { switch filter := req.Filter.(type) { case *SearchRequest_Category: return searchDatabase(\"category\", filter.Category), nil case *SearchRequest_UserId: return searchDatabase(\"user_id\", strconv.Itoa(int(filter.UserId))), nil default: return nil, errors.New(\"no filter specified\") } }"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::24","title":"ONEOF_FIELD_SAME_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Реальный пример"],"excerpt":"Реальный пример // After — несовпадения типов func handleSearchFilter(req *SearchRequest) (*SearchResult, error) { switch filter := req.Filter.(type) { case *SearchRequest_Category: // filter.Category теперь int32, а код","content":"Реальный пример // After — несовпадения типов func handleSearchFilter(req *SearchRequest) (*SearchResult, error) { switch filter := req.Filter.(type) { case *SearchRequest_Category: // filter.Category теперь int32, а код ожидал string return searchDatabase(\"category\", filter.Category), nil // ERROR case *SearchRequest_UserId: userIdStr := filter.UserId // string вместо int32 userId, _ := strconv.Atoi(userIdStr) return searchDatabase(\"user_id\", strconv.Itoa(userId)), nil } } ```"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::25","title":"ONEOF_FIELD_SAME_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Реальный пример"],"excerpt":"Реальный пример **Порча данных:**","content":"Реальный пример **Порча данных:**"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::26","title":"ONEOF_FIELD_SAME_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции Добавьте новое поле: Сервер поддерживает оба: Клиенты переходят на category_id. Скрипты миграции преобразуют старые данные. В следующей major‑версии:","content":"Стратегия миграции Добавьте новое поле: Сервер поддерживает оба: Клиенты переходят на category_id. Скрипты миграции преобразуют старые данные. В следующей major‑версии:"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::27","title":"ONEOF_FIELD_SAME_TYPE","section":"Переход к структурированным типам","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Переход к структурированным типам"],"excerpt":"Переход к структурированным типам","content":"Переход к структурированным типам"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::28","title":"ONEOF_FIELD_SAME_TYPE","section":"Матрица совместимости","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Матрица совместимости"],"excerpt":"Матрица совместимости From Type To Type Результат ----------- --------- ----------- string int32/int64 ❌ BREAKING int32 string ❌ BREAKING bool string ❌ BREAKING message string ❌ BREAKING string message ❌ BREAKING enum in","content":"Матрица совместимости From Type To Type Результат ----------- --------- ----------- 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::top::29","title":"ONEOF_FIELD_SAME_TYPE","section":"Влияние на сгенерированный код","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Влияние на сгенерированный код"],"excerpt":"Влияние на сгенерированный код","content":"Влияние на сгенерированный код"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::30","title":"ONEOF_FIELD_SAME_TYPE","section":"Валидация","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Валидация"],"excerpt":"Валидация **После (сломано):**","content":"Валидация **После (сломано):**"},{"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":"Это правило проверяет, что ни один oneof блок не был удалён из сообщений. Удаление oneof ломает совместимость по wire‑формату и сгенерированный код: существующие данные могут содержать ранее выбранный вариант, а клиентск","content":"Это правило проверяет, что ни один oneof блок не был удалён из сообщений. Удаление oneof ломает совместимость по wire‑формату и сгенерированный код: существующие данные могут содержать ранее выбранный вариант, а клиентский код зависит от типов-обёрток и методов доступа, генерируемых для oneof."},{"id":"cli/breaking-changes/rules/oneof-no-delete::breaking::1","title":"ONEOF_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-no-delete::breaking::2","title":"ONEOF_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/oneof-no-delete::breaking::3","title":"ONEOF_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message LoginRequest { string username = 1; oneof credentials { string password = 2; string api_key = 3; string oauth_token = 4; } }","content":"Плохой (Breaking) 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::breaking::4","title":"ONEOF_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message PaymentMethod { // [!code --] oneof method { // [!code --] CreditCard credit_card = 1; // [!code --] BankAccount bank_account = 2; // [!code --] PayPal paypal = 3; // [!code --] } // [!code --] ","content":"Плохой (Breaking) 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::breaking::5","title":"ONEOF_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message Order { string id = 1; PaymentMethod payment = 2; } ```","content":"Плохой (Breaking) message Order { string id = 1; PaymentMethod payment = 2; } ```"},{"id":"cli/breaking-changes/rules/oneof-no-delete::breaking::6","title":"ONEOF_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-no-delete::breaking::7","title":"ONEOF_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/oneof-no-delete::breaking::8","title":"ONEOF_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message LoginRequest { string username = 1; // credentials oneof удалён — BREAKING CHANGE! string password = 2; // Теперь обычные поля string api_key = 3; // Потеряна взаимная исключаемость string oauth","content":"Плохой (Breaking) message LoginRequest { string username = 1; // credentials oneof удалён — BREAKING CHANGE! string password = 2; // Теперь обычные поля string api_key = 3; // Потеряна взаимная исключаемость string oauth_token = 4; }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::breaking::9","title":"ONEOF_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message PaymentMethod { // method oneof удалён — BREAKING CHANGE! CreditCard credit_card = 1; // Теперь можно установить все поля одновременно BankAccount bank_account = 2; PayPal paypal = 3; }","content":"Плохой (Breaking) message PaymentMethod { // method oneof удалён — BREAKING CHANGE! CreditCard credit_card = 1; // Теперь можно установить все поля одновременно BankAccount bank_account = 2; PayPal paypal = 3; }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::breaking::10","title":"ONEOF_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message Order { string id = 1; PaymentMethod payment = 2; } ```","content":"Плохой (Breaking) message Order { string id = 1; PaymentMethod payment = 2; } ```"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::11","title":"ONEOF_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры **Удаление вложенного oneof:** ```proto // Before message UserProfile { string name = 1; message ContactInfo { oneof contact_method { // [!code --] string email = 1; // [!code --] string phone = 2;","content":"Дополнительные примеры **Удаление вложенного oneof:** ```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::top::12","title":"ONEOF_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры // After - BREAKING CHANGE! message UserProfile { string name = 1; message ContactInfo { // contact_method oneof удалён string email = 1; // Больше не эксклюзивно string phone = 2; // Можно задать ","content":"Дополнительные примеры // After - BREAKING CHANGE! message UserProfile { string name = 1; message ContactInfo { // contact_method oneof удалён string email = 1; // Больше не эксклюзивно string phone = 2; // Можно задать всё сразу string slack_id = 3; } ContactInfo contact = 2; } ```"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::13","title":"ONEOF_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо удаления — депрецируйте oneof:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо удаления — депрецируйте oneof:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::14","title":"ONEOF_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::15","title":"ONEOF_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message LoginRequest { string username = 1; oneof credentials { option deprecated = true; // [!code focus] string password = 2 [deprecated = true]; // [!code focus] string api_key = 3 [deprecated = t","content":"Хороший (Безопасный) 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::top::16","title":"ONEOF_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message PaymentMethod { oneof method { option deprecated = true; // [!code focus] CreditCard credit_card = 1 [deprecated = true]; // [!code focus] BankAccount bank_account = 2 [deprecated = true]; //","content":"Хороший (Безопасный) 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::top::17","title":"ONEOF_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Или заменить новой структурой:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Или заменить новой структурой:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::18","title":"ONEOF_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::19","title":"ONEOF_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message LoginRequest { string username = 1; oneof credentials { option deprecated = true; // [!code focus] // Старый oneof string password = 2 [deprecated = true]; // [!code focus] string api_key = 3","content":"Хороший (Безопасный) message LoginRequest { string username = 1; oneof credentials { option deprecated = true; // [!code focus] // Старый 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] // Новый дизайн 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::top::20","title":"ONEOF_NO_DELETE","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Влияние"],"excerpt":"Влияние **Wire Format:** Теряются семантика взаимной исключаемости — больше одного поля может быть установлено **Generated Code:** Удаляются типы-обёртки и accessor методы — код клиента не компилируется **Business Logic:","content":"Влияние **Wire Format:** Теряются семантика взаимной исключаемости — больше одного поля может быть установлено **Generated Code:** Удаляются типы-обёртки и accessor методы — код клиента не компилируется **Business Logic:** Нарушаются инварианты «только один из» **Validation:** Логика проверок должна быть переписана вручную"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::21","title":"ONEOF_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Код клиента ломается:** ```go // Before - oneOf даёт взаимную исключаемость loginReq := &myapi.LoginRequest{ Username: \"user123\", }","content":"Реальный пример **Код клиента ломается:** ```go // Before - oneOf даёт взаимную исключаемость loginReq := &myapi.LoginRequest{ Username: \"user123\", }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::22","title":"ONEOF_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример loginReq.Credentials = &myapi.LoginRequest_Password{ Password: \"secret123\", }","content":"Реальный пример loginReq.Credentials = &myapi.LoginRequest_Password{ Password: \"secret123\", }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::23","title":"ONEOF_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример switch cred := loginReq.Credentials.(type) { case *myapi.LoginRequest_Password: // ERROR после удаления return authenticatePassword(cred.Password) case *myapi.LoginRequest_ApiKey: // ERROR после удаления ","content":"Реальный пример switch cred := loginReq.Credentials.(type) { case *myapi.LoginRequest_Password: // ERROR после удаления return authenticatePassword(cred.Password) case *myapi.LoginRequest_ApiKey: // ERROR после удаления return authenticateApiKey(cred.ApiKey) default: return errors.New(\"no credentials provided\") }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::24","title":"ONEOF_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример // Compilation errors: // undefined: myapi.LoginRequest_Password // undefined field: loginReq.Credentials ```","content":"Реальный пример // Compilation errors: // undefined: myapi.LoginRequest_Password // undefined field: loginReq.Credentials ```"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::25","title":"ONEOF_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Валидация на сервере ломается:** ```go // Before func validateLoginRequest(req *LoginRequest) error { if req.Credentials == nil { return errors.New(\"credentials required\") } switch req.Credentials.(type","content":"Реальный пример **Валидация на сервере ломается:** ```go // Before func validateLoginRequest(req *LoginRequest) error { if req.Credentials == nil { return errors.New(\"credentials required\") } 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::top::26","title":"ONEOF_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример // After func validateLoginRequest(req *LoginRequest) error { credCount := 0 if req.Password != \"\" { credCount++ } if req.ApiKey != \"\" { credCount++ } if req.OauthToken != \"\" { credCount++ }","content":"Реальный пример // After func validateLoginRequest(req *LoginRequest) error { credCount := 0 if req.Password != \"\" { credCount++ } if req.ApiKey != \"\" { credCount++ } if req.OauthToken != \"\" { credCount++ }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::27","title":"ONEOF_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример if credCount == 0 { return errors.New(\"no credentials provided\") } if credCount > 1 { return errors.New(\"multiple credentials provided\") }","content":"Реальный пример if credCount == 0 { return errors.New(\"no credentials provided\") } if credCount > 1 { return errors.New(\"multiple credentials provided\") }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::28","title":"ONEOF_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример if req.Password != \"\" { return validatePassword(req.Password) } // Дополнительные проверки вручную... return nil } ```","content":"Реальный пример if req.Password != \"\" { return validatePassword(req.Password) } // Дополнительные проверки вручную... return nil } ```"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::29","title":"ONEOF_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Проблемы бизнес‑логики:** ```go // Before payment := &PaymentMethod{ Method: &PaymentMethod_CreditCard{ CreditCard: &CreditCard{Number: \"1234\"}, }, }","content":"Реальный пример **Проблемы бизнес‑логики:** ```go // Before payment := &PaymentMethod{ Method: &PaymentMethod_CreditCard{ CreditCard: &CreditCard{Number: \"1234\"}, }, }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::30","title":"ONEOF_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример // After — можно задать несколько способов сразу payment := &PaymentMethod{ CreditCard: &CreditCard{Number: \"1234\"}, BankAccount: &BankAccount{Number: \"5678\"}, // Ломает бизнес-логику } ```","content":"Реальный пример // After — можно задать несколько способов сразу payment := &PaymentMethod{ CreditCard: &CreditCard{Number: \"1234\"}, BankAccount: &BankAccount{Number: \"5678\"}, // Ломает бизнес-логику } ```"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::31","title":"ONEOF_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Депрецируйте старый oneof и его поля:**","content":"Стратегия миграции **Депрецируйте старый oneof и его поля:**"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::32","title":"ONEOF_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Создайте новый блок при необходимости:**","content":"Стратегия миграции **Создайте новый блок при необходимости:**"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::33","title":"ONEOF_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Сервер: поддерживайте оба до миграции:**","content":"Стратегия миграции **Сервер: поддерживайте оба до миграции:**"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::34","title":"ONEOF_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Клиенты: переходите на новый oneof:**","content":"Стратегия миграции **Клиенты: переходите на новый oneof:**"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::35","title":"ONEOF_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Удалите старый oneof** в следующей major‑версии.","content":"Стратегия миграции **Удалите старый oneof** в следующей major‑версии."},{"id":"cli/breaking-changes/rules/oneof-no-delete::oneof::36","title":"ONEOF_NO_DELETE","section":"Замена oneof обычными полями","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#oneof","headings":["Замена oneof обычными полями"],"excerpt":"Замена oneof обычными полями ```proto message SearchRequest { // НЕЛЬЗЯ просто убрать oneof — ломает семантику string text_query = 1; // BREAKING int32 user_id = 2; // BREAKING string category = 3; // BREAKING }","content":"Замена oneof обычными полями ```proto message SearchRequest { // НЕЛЬЗЯ просто убрать oneof — ломает семантику string text_query = 1; // BREAKING int32 user_id = 2; // BREAKING string category = 3; // BREAKING }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::oneof::37","title":"ONEOF_NO_DELETE","section":"Замена oneof обычными полями","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#oneof","headings":["Замена oneof обычными полями"],"excerpt":"Замена oneof обычными полями message SearchRequest { oneof query { option deprecated = true; string text_query = 1 [deprecated = true]; int32 user_id = 2 [deprecated = true]; string category = 3 [deprecated = true]; } st","content":"Замена oneof обычными полями message SearchRequest { oneof query { option deprecated = true; string text_query = 1 [deprecated = true]; int32 user_id = 2 [deprecated = true]; string category = 3 [deprecated = true]; } string search_text = 4; repeated string filters = 5; } ```"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::38","title":"ONEOF_NO_DELETE","section":"Упрощение структуры сообщения","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Упрощение структуры сообщения"],"excerpt":"Упрощение структуры сообщения ```proto message NotificationSettings { string email = 1; // BREAKING: был в oneof string phone = 2; // BREAKING string webhook_url = 3; // BREAKING }","content":"Упрощение структуры сообщения ```proto message NotificationSettings { string email = 1; // BREAKING: был в oneof string phone = 2; // BREAKING string webhook_url = 3; // BREAKING }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::39","title":"ONEOF_NO_DELETE","section":"Упрощение структуры сообщения","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Упрощение структуры сообщения"],"excerpt":"Упрощение структуры сообщения message NotificationSettings { oneof delivery_method { EmailNotification email = 1; SmsNotification phone = 2; WebhookNotification webhook = 3; } } ```","content":"Упрощение структуры сообщения message NotificationSettings { oneof delivery_method { EmailNotification email = 1; SmsNotification phone = 2; WebhookNotification webhook = 3; } } ```"},{"id":"cli/breaking-changes/rules/oneof-no-delete::proto2-proto3::40","title":"ONEOF_NO_DELETE","section":"Миграция с proto2 на proto3","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#proto2-proto3","headings":["Миграция с proto2 на proto3"],"excerpt":"Миграция с proto2 на proto3 ```proto // proto2 message Request { optional string name = 1; oneof data { string text = 2; int32 number = 3; } }","content":"Миграция с proto2 на proto3 ```proto // proto2 message Request { optional string name = 1; oneof data { string text = 2; int32 number = 3; } }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::proto2-proto3::41","title":"ONEOF_NO_DELETE","section":"Миграция с proto2 на proto3","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#proto2-proto3","headings":["Миграция с proto2 на proto3"],"excerpt":"Миграция с proto2 на proto3 // proto3 — сохраняем oneof message Request { string name = 1; oneof data { string text = 2; int32 number = 3; } } ```","content":"Миграция с proto2 на proto3 // proto3 — сохраняем oneof message Request { string name = 1; oneof data { string text = 2; int32 number = 3; } } ```"},{"id":"cli/breaking-changes/rules/oneof-no-delete::oneof::42","title":"ONEOF_NO_DELETE","section":"Что даёт oneof","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#oneof","headings":["Что даёт oneof"],"excerpt":"Что даёт oneof Взаимная исключаемость Типобезопасность в коде Ясность намерения API («выбери один») Эффективная сериализация — кодируется только выбранный вариант","content":"Что даёт oneof Взаимная исключаемость Типобезопасность в коде Ясность намерения API («выбери один») Эффективная сериализация — кодируется только выбранный вариант"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::43","title":"ONEOF_NO_DELETE","section":"Что теряется при удалении","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Что теряется при удалении"],"excerpt":"Что теряется при удалении Инвариант «только один» Генерируемые wrapper-типы и методы Автоматическая валидация выбора Понятность контракта API","content":"Что теряется при удалении Инвариант «только один» Генерируемые wrapper-типы и методы Автоматическая валидация выбора Понятность контракта API"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::44","title":"ONEOF_NO_DELETE","section":"Влияние на код генерации","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Влияние на код генерации"],"excerpt":"Влияние на код генерации ```go // С oneof type LoginRequest struct { Username string Credentials isLoginRequest_Credentials }","content":"Влияние на код генерации ```go // С oneof type LoginRequest struct { Username string Credentials isLoginRequest_Credentials }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::45","title":"ONEOF_NO_DELETE","section":"Влияние на код генерации","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Влияние на код генерации"],"excerpt":"Влияние на код генерации // Без oneof type LoginRequest struct { Username string Password string ApiKey string OauthToken string // Возможны многозначные конфликтующие состояния } ```","content":"Влияние на код генерации // Без oneof type LoginRequest struct { Username string Password string ApiKey string 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":"Правило проверяет, что ни один RPC‑метод не был удалён из service. Удаление RPC ломает сгенерированный код и клиентские приложения, которые этот метод вызывают.","content":"Правило проверяет, что ни один RPC‑метод не был удалён из service. Удаление RPC ломает сгенерированный код и клиентские приложения, которые этот метод вызывают."},{"id":"cli/breaking-changes/rules/rpc-no-delete::breaking::1","title":"RPC_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/rpc-no-delete::breaking::2","title":"RPC_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/rpc-no-delete::breaking::3","title":"RPC_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); rpc DeleteUser(DeleteUserRequest) returns (DeleteUserResponse","content":"Плохой (Breaking) 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::breaking::4","title":"RPC_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/rpc-no-delete::breaking::5","title":"RPC_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/rpc-no-delete::breaking::6","title":"RPC_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); // DeleteUser RPC удалён — BREAKING CHANGE! } ```","content":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); // DeleteUser RPC удалён — BREAKING CHANGE! } ```"},{"id":"cli/breaking-changes/rules/rpc-no-delete::top::7","title":"RPC_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо удаления — пометить RPC deprecated:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо удаления — пометить RPC deprecated:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/rpc-no-delete::top::8","title":"RPC_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/rpc-no-delete::top::9","title":"RPC_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); rpc DeleteUser(DeleteUserRequest) returns (DeleteUserRespo","content":"Хороший (Безопасный) 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::top::10","title":"RPC_NO_DELETE","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete","headings":["Влияние"],"excerpt":"Влияние **Generated Code:** Stub/метод исчезает — клиенты не компилируются **Client Applications:** Существующие вызовы метода падают при сборке **Runtime:** gRPC клиенты теряют определение метода","content":"Влияние **Generated Code:** Stub/метод исчезает — клиенты не компилируются **Client Applications:** Существующие вызовы метода падают при сборке **Runtime:** gRPC клиенты теряют определение метода"},{"id":"cli/breaking-changes/rules/rpc-no-delete::top::11","title":"RPC_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Сначала деприкация:**","content":"Стратегия миграции **Сначала деприкация:**"},{"id":"cli/breaking-changes/rules/rpc-no-delete::top::12","title":"RPC_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Имплементация может возвращать ошибку**, указывая что метод устарел (например, INTERNAL / UNIMPLEMENTED)","content":"Стратегия миграции **Имплементация может возвращать ошибку**, указывая что метод устарел (например, INTERNAL / UNIMPLEMENTED)"},{"id":"cli/breaking-changes/rules/rpc-no-delete::top::13","title":"RPC_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Удалить в следующей major‑версии** после миграции всех клиентов","content":"Стратегия миграции **Удалить в следующей major‑версии** после миграции всех клиентов"},{"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":"Это правило проверяет, что RPC‑методы сохраняют прежний тип сообщения запроса (request message type). Изменение типа запроса RPC ломает совместимость по wire‑формату и сгенерированный код: клиенты ожидают конкретную стру","content":"Это правило проверяет, что RPC‑методы сохраняют прежний тип сообщения запроса (request message type). Изменение типа запроса RPC ломает совместимость по wire‑формату и сгенерированный код: клиенты ожидают конкретную структуру при вызове метода."},{"id":"cli/breaking-changes/rules/rpc-same-request-type::breaking::1","title":"RPC_SAME_REQUEST_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::breaking::2","title":"RPC_SAME_REQUEST_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::breaking::3","title":"RPC_SAME_REQUEST_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse); }","content":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse); }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::breaking::4","title":"RPC_SAME_REQUEST_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message GetUserRequest { string user_id = 1; }","content":"Плохой (Breaking) message GetUserRequest { string user_id = 1; }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::breaking::5","title":"RPC_SAME_REQUEST_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message UpdateUserRequest { string user_id = 1; string name = 2; string email = 3; } ```","content":"Плохой (Breaking) message UpdateUserRequest { string user_id = 1; string name = 2; string email = 3; } ```"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::breaking::6","title":"RPC_SAME_REQUEST_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::breaking::7","title":"RPC_SAME_REQUEST_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::breaking::8","title":"RPC_SAME_REQUEST_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequestV2) returns (GetUserResponse); // [!code --] Изменён тип запроса rpc UpdateUser(UserUpdateRequest) returns (UpdateUserResponse); // [!code --] Изменён тип","content":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequestV2) returns (GetUserResponse); // [!code --] Изменён тип запроса rpc UpdateUser(UserUpdateRequest) returns (UpdateUserResponse); // [!code --] Изменён тип запроса }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::breaking::9","title":"RPC_SAME_REQUEST_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message GetUserRequestV2 { // [!code --] Новый тип запроса string id = 1; bool include_profile = 2; }","content":"Плохой (Breaking) message GetUserRequestV2 { // [!code --] Новый тип запроса string id = 1; bool include_profile = 2; }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::breaking::10","title":"RPC_SAME_REQUEST_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message UserUpdateRequest { // [!code --] Новый тип запроса string id = 1; UserProfile profile = 2; } ```","content":"Плохой (Breaking) message UserUpdateRequest { // [!code --] Новый тип запроса string id = 1; UserProfile profile = 2; } ```"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::11","title":"RPC_SAME_REQUEST_TYPE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры **Смена типа из другого пакета:** ```proto // Before import \"common/user.proto\";","content":"Дополнительные примеры **Смена типа из другого пакета:** ```proto // Before import \"common/user.proto\";"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::12","title":"RPC_SAME_REQUEST_TYPE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры service UserService { rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); }","content":"Дополнительные примеры service UserService { rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::13","title":"RPC_SAME_REQUEST_TYPE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры // After - BREAKING CHANGE! import \"v2/user.proto\";","content":"Дополнительные примеры // After - BREAKING CHANGE! import \"v2/user.proto\";"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::14","title":"RPC_SAME_REQUEST_TYPE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры service UserService { rpc CreateUser(v2.CreateUserRequest) returns (CreateUserResponse); // Другой package } ```","content":"Дополнительные примеры service UserService { rpc CreateUser(v2.CreateUserRequest) returns (CreateUserResponse); // Другой package } ```"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::15","title":"RPC_SAME_REQUEST_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо изменения типа — версионируйте RPC:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо изменения типа — версионируйте RPC:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::16","title":"RPC_SAME_REQUEST_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::17","title":"RPC_SAME_REQUEST_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse) { option deprecated = true; // [!code focus] } rpc GetUserV2(GetUserRequestV2) returns (GetUserResponse); // [!code focus] ","content":"Хороший (Безопасный) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse) { option deprecated = true; // [!code focus] } rpc GetUserV2(GetUserRequestV2) returns (GetUserResponse); // [!code focus] // Новый метод rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse) { option deprecated = true; // [!code focus] } rpc UpdateUserV2(UserUpdateRequest) returns (UpdateUserResponse); // [!code focus] // Новый метод }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::18","title":"RPC_SAME_REQUEST_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) // Старые сообщения — для обратной совместимости message GetUserRequest { string user_id = 1; }","content":"Хороший (Безопасный) // Старые сообщения — для обратной совместимости message GetUserRequest { string user_id = 1; }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::19","title":"RPC_SAME_REQUEST_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) // Новая версия сообщения message GetUserRequestV2 { // [!code focus] string id = 1; // [!code focus] bool include_profile = 2; // [!code focus] } // [!code focus] ```","content":"Хороший (Безопасный) // Новая версия сообщения 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::top::20","title":"RPC_SAME_REQUEST_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Или создайте новую версию сервиса (package v2):** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Или создайте новую версию сервиса (package v2):** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::21","title":"RPC_SAME_REQUEST_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v2; // [!code focus]","content":"Хороший (Безопасный) package myapi.v2; // [!code focus]"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::22","title":"RPC_SAME_REQUEST_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); // [!code focus] rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse); // [!code focus] }","content":"Хороший (Безопасный) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); // [!code focus] rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse); // [!code focus] }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::23","title":"RPC_SAME_REQUEST_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message GetUserRequest { // [!code focus] string id = 1; // [!code focus] bool include_profile = 2; // [!code focus] } // [!code focus] ```","content":"Хороший (Безопасный) message GetUserRequest { // [!code focus] string id = 1; // [!code focus] bool include_profile = 2; // [!code focus] } // [!code focus] ```"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::24","title":"RPC_SAME_REQUEST_TYPE","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Влияние"],"excerpt":"Влияние **Wire Format:** Старые запросы клиентов не десериализуются новым сервером **Generated Code:** Сигнатуры методов в stubs меняются — компиляция клиентов падает **gRPC Calls:** Требуется использовать другую структу","content":"Влияние **Wire Format:** Старые запросы клиентов не десериализуются новым сервером **Generated Code:** Сигнатуры методов в stubs меняются — компиляция клиентов падает **gRPC Calls:** Требуется использовать другую структуру запроса **Runtime Errors:** Несоответствие типов вызывает ошибки выполнения"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::25","title":"RPC_SAME_REQUEST_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Реальный пример"],"excerpt":"Реальный пример **Код клиента ломается:** ```go // Before client := myapi.NewUserServiceClient(conn) resp, err := client.GetUser(ctx, &myapi.GetUserRequest{ UserId: \"user123\", })","content":"Реальный пример **Код клиента ломается:** ```go // Before client := myapi.NewUserServiceClient(conn) resp, err := client.GetUser(ctx, &myapi.GetUserRequest{ UserId: \"user123\", })"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::26","title":"RPC_SAME_REQUEST_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Реальный пример"],"excerpt":"Реальный пример // After (тип запроса изменён) client := myapi.NewUserServiceClient(conn) resp, err := client.GetUser(ctx, &myapi.GetUserRequest{ // ERROR: тип не найден UserId: \"user123\", // ERROR: поле не найдено })","content":"Реальный пример // After (тип запроса изменён) client := myapi.NewUserServiceClient(conn) resp, err := client.GetUser(ctx, &myapi.GetUserRequest{ // ERROR: тип не найден UserId: \"user123\", // ERROR: поле не найдено })"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::27","title":"RPC_SAME_REQUEST_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Реальный пример"],"excerpt":"Реальный пример // Новый корректный вызов: resp, err := client.GetUser(ctx, &myapi.GetUserRequestV2{ Id: \"user123\", IncludeProfile: true, }) ```","content":"Реальный пример // Новый корректный вызов: resp, err := client.GetUser(ctx, &myapi.GetUserRequestV2{ Id: \"user123\", IncludeProfile: true, }) ```"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::28","title":"RPC_SAME_REQUEST_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Реальный пример"],"excerpt":"Реальный пример **Серверная реализация ломается:** ```go // Before func (s *server) GetUser(ctx context.Context, req *GetUserRequest) (*GetUserResponse, error) { userID := req.UserId // ... }","content":"Реальный пример **Серверная реализация ломается:** ```go // Before func (s *server) GetUser(ctx context.Context, req *GetUserRequest) (*GetUserResponse, error) { userID := req.UserId // ... }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::29","title":"RPC_SAME_REQUEST_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Реальный пример"],"excerpt":"Реальный пример // After func (s *server) GetUser(ctx context.Context, req *GetUserRequestV2) (*GetUserResponse, error) { userID := req.Id include := req.IncludeProfile // ... новая логика } ```","content":"Реальный пример // After func (s *server) GetUser(ctx context.Context, req *GetUserRequestV2) (*GetUserResponse, error) { userID := req.Id include := req.IncludeProfile // ... новая логика } ```"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::30","title":"RPC_SAME_REQUEST_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Добавьте новый RPC с новым типом запроса:**","content":"Стратегия миграции **Добавьте новый RPC с новым типом запроса:**"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::31","title":"RPC_SAME_REQUEST_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Поддерживайте оба метода на сервере:** ```go func (s *server) GetUser(ctx context.Context, req *GetUserRequest) (*GetUserResponse, error) { return s.getUserInternal(req.UserId, false) }","content":"Стратегия миграции **Поддерживайте оба метода на сервере:** ```go func (s *server) GetUser(ctx context.Context, req *GetUserRequest) (*GetUserResponse, error) { return s.getUserInternal(req.UserId, false) }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::32","title":"RPC_SAME_REQUEST_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции func (s *server) GetUserV2(ctx context.Context, req *GetUserRequestV2) (*GetUserResponse, error) { return s.getUserInternal(req.Id, req.IncludeProfile) } ```","content":"Стратегия миграции func (s *server) GetUserV2(ctx context.Context, req *GetUserRequestV2) (*GetUserResponse, error) { return s.getUserInternal(req.Id, req.IncludeProfile) } ```"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::33","title":"RPC_SAME_REQUEST_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Мигрируйте клиентов на V2:**","content":"Стратегия миграции **Мигрируйте клиентов на V2:**"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::34","title":"RPC_SAME_REQUEST_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Удалите старый метод в следующей major‑версии:**","content":"Стратегия миграции **Удалите старый метод в следующей major‑версии:**"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::35","title":"RPC_SAME_REQUEST_TYPE","section":"Добавление обязательных полей","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Добавление обязательных полей"],"excerpt":"Добавление обязательных полей ```proto // ПЛОХО: меняем существующий запрос message GetUserRequest { string user_id = 1; bool include_deleted = 2; // BREAKING }","content":"Добавление обязательных полей ```proto // ПЛОХО: меняем существующий запрос message GetUserRequest { string user_id = 1; bool include_deleted = 2; // BREAKING }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::36","title":"RPC_SAME_REQUEST_TYPE","section":"Добавление обязательных полей","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Добавление обязательных полей"],"excerpt":"Добавление обязательных полей // Хорошо: новая версия message GetUserRequestV2 { string user_id = 1; bool include_deleted = 2; } ```","content":"Добавление обязательных полей // Хорошо: новая версия message GetUserRequestV2 { string user_id = 1; bool include_deleted = 2; } ```"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::37","title":"RPC_SAME_REQUEST_TYPE","section":"Реструктуризация данных запроса","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Реструктуризация данных запроса"],"excerpt":"Реструктуризация данных запроса ```proto // ПЛОХО: меняем структуру прямо message UpdateUserRequest { UserProfile profile = 1; // BREAKING }","content":"Реструктуризация данных запроса ```proto // ПЛОХО: меняем структуру прямо message UpdateUserRequest { UserProfile profile = 1; // BREAKING }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::38","title":"RPC_SAME_REQUEST_TYPE","section":"Реструктуризация данных запроса","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Реструктуризация данных запроса"],"excerpt":"Реструктуризация данных запроса // Хорошо: версионирование rpc UpdateUser(UpdateUserRequest) returns (...) { option deprecated = true; } rpc UpdateUserV2(UpdateUserRequestV2) returns (...); ```","content":"Реструктуризация данных запроса // Хорошо: версионирование rpc UpdateUser(UpdateUserRequest) returns (...) { option deprecated = true; } rpc UpdateUserV2(UpdateUserRequestV2) returns (...); ```"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::39","title":"RPC_SAME_REQUEST_TYPE","section":"Миграция пакета","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Миграция пакета"],"excerpt":"Миграция пакета ```proto // ПЛОХО: заменяем тип на пакет v2 прямо import \"v2/messages.proto\"; // BREAKING","content":"Миграция пакета ```proto // ПЛОХО: заменяем тип на пакет v2 прямо import \"v2/messages.proto\"; // BREAKING"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::40","title":"RPC_SAME_REQUEST_TYPE","section":"Миграция пакета","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Миграция пакета"],"excerpt":"Миграция пакета // Хорошо: добавляем новый RPC rpc OldMethod(v1.Request) returns (...) { option deprecated = true; } rpc NewMethod(v2.Request) returns (...); ```","content":"Миграция пакета // Хорошо: добавляем новый RPC 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":"Это правило проверяет, что RPC‑методы сохраняют тот же тип ответного сообщения (response message type). Изменение типа ответа RPC ломает совместимость по wire‑формату и сгенерированный код: клиенты ожидают конкретную стр","content":"Это правило проверяет, что RPC‑методы сохраняют тот же тип ответного сообщения (response message type). Изменение типа ответа RPC ломает совместимость по wire‑формату и сгенерированный код: клиенты ожидают конкретную структуру при получении ответа."},{"id":"cli/breaking-changes/rules/rpc-same-response-type::breaking::1","title":"RPC_SAME_RESPONSE_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::breaking::2","title":"RPC_SAME_RESPONSE_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::breaking::3","title":"RPC_SAME_RESPONSE_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse); }","content":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse); }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::breaking::4","title":"RPC_SAME_RESPONSE_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message GetUserResponse { string user_id = 1; string name = 2; string email = 3; }","content":"Плохой (Breaking) message GetUserResponse { string user_id = 1; string name = 2; string email = 3; }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::breaking::5","title":"RPC_SAME_RESPONSE_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message UpdateUserResponse { bool success = 1; string message = 2; } ```","content":"Плохой (Breaking) message UpdateUserResponse { bool success = 1; string message = 2; } ```"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::breaking::6","title":"RPC_SAME_RESPONSE_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::breaking::7","title":"RPC_SAME_RESPONSE_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::breaking::8","title":"RPC_SAME_RESPONSE_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponseV2); // [!code --] Изменён тип ответа rpc UpdateUser(UpdateUserRequest) returns (UserUpdateResponse); // [!code --] Изменён тип ","content":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponseV2); // [!code --] Изменён тип ответа rpc UpdateUser(UpdateUserRequest) returns (UserUpdateResponse); // [!code --] Изменён тип ответа }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::breaking::9","title":"RPC_SAME_RESPONSE_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message GetUserResponseV2 { // [!code --] Другой тип сообщения string id = 1; UserProfile profile = 2; repeated string permissions = 3; }","content":"Плохой (Breaking) message GetUserResponseV2 { // [!code --] Другой тип сообщения string id = 1; UserProfile profile = 2; repeated string permissions = 3; }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::breaking::10","title":"RPC_SAME_RESPONSE_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message UserUpdateResponse { // [!code --] Другой тип сообщения UpdateResult result = 1; UserProfile updated_profile = 2; } ```","content":"Плохой (Breaking) message UserUpdateResponse { // [!code --] Другой тип сообщения UpdateResult result = 1; UserProfile updated_profile = 2; } ```"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::11","title":"RPC_SAME_RESPONSE_TYPE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры **Смена типа из другого пакета:** ```proto // Before import \"common/responses.proto\";","content":"Дополнительные примеры **Смена типа из другого пакета:** ```proto // Before import \"common/responses.proto\";"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::12","title":"RPC_SAME_RESPONSE_TYPE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры service UserService { rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); }","content":"Дополнительные примеры service UserService { rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::13","title":"RPC_SAME_RESPONSE_TYPE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры // After - BREAKING CHANGE! import \"v2/responses.proto\";","content":"Дополнительные примеры // After - BREAKING CHANGE! import \"v2/responses.proto\";"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::14","title":"RPC_SAME_RESPONSE_TYPE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры service UserService { rpc CreateUser(CreateUserRequest) returns (v2.CreateUserResponse); // Другой package } ```","content":"Дополнительные примеры service UserService { rpc CreateUser(CreateUserRequest) returns (v2.CreateUserResponse); // Другой package } ```"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::15","title":"RPC_SAME_RESPONSE_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо изменения типа — версионируйте RPC:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо изменения типа — версионируйте RPC:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::16","title":"RPC_SAME_RESPONSE_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::17","title":"RPC_SAME_RESPONSE_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse) { option deprecated = true; // [!code focus] } rpc GetUserV2(GetUserRequest) returns (GetUserResponseV2); // [!code focus] ","content":"Хороший (Безопасный) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse) { option deprecated = true; // [!code focus] } rpc GetUserV2(GetUserRequest) returns (GetUserResponseV2); // [!code focus] // Новый метод rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse) { option deprecated = true; // [!code focus] } rpc UpdateUserV2(UpdateUserRequest) returns (UserUpdateResponse); // [!code focus] // Новый метод }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::18","title":"RPC_SAME_RESPONSE_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) // Старые сообщения сохраняем для обратной совместимости message GetUserResponse { string user_id = 1; string name = 2; string email = 3; }","content":"Хороший (Безопасный) // Старые сообщения сохраняем для обратной совместимости message GetUserResponse { string user_id = 1; string name = 2; string email = 3; }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::19","title":"RPC_SAME_RESPONSE_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) // Новая расширенная версия message GetUserResponseV2 { // [!code focus] string id = 1; // [!code focus] UserProfile profile = 2; // [!code focus] repeated string permissions = 3; // [!code focus] } ","content":"Хороший (Безопасный) // Новая расширенная версия 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::top::20","title":"RPC_SAME_RESPONSE_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Или создайте новую версию сервиса (package v2):** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Или создайте новую версию сервиса (package v2):** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::21","title":"RPC_SAME_RESPONSE_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v2; // [!code focus]","content":"Хороший (Безопасный) package myapi.v2; // [!code focus]"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::22","title":"RPC_SAME_RESPONSE_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); // [!code focus] rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse); // [!code focus] }","content":"Хороший (Безопасный) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); // [!code focus] rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse); // [!code focus] }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::23","title":"RPC_SAME_RESPONSE_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message GetUserResponse { // [!code focus] string id = 1; // [!code focus] UserProfile profile = 2; // [!code focus] repeated string permissions = 3; // [!code focus] } // [!code focus] ```","content":"Хороший (Безопасный) message GetUserResponse { // [!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::top::24","title":"RPC_SAME_RESPONSE_TYPE","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Влияние"],"excerpt":"Влияние **Wire Format:** Ответы сервера не десериализуются у старых клиентов **Generated Code:** Сигнатуры ожидают старый тип — компиляция падает **gRPC Calls:** Меняются типы в сгенерированных stub'ах **Runtime Errors:*","content":"Влияние **Wire Format:** Ответы сервера не десериализуются у старых клиентов **Generated Code:** Сигнатуры ожидают старый тип — компиляция падает **gRPC Calls:** Меняются типы в сгенерированных stub'ах **Runtime Errors:** Несоответствие типов ломает обработку ответа"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::25","title":"RPC_SAME_RESPONSE_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Реальный пример"],"excerpt":"Реальный пример **Код клиента ломается:** ```go // Before client := myapi.NewUserServiceClient(conn) resp, err := client.GetUser(ctx, &myapi.GetUserRequest{ UserId: \"user123\", }) if err != nil { return err }","content":"Реальный пример **Код клиента ломается:** ```go // Before 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::top::26","title":"RPC_SAME_RESPONSE_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Реальный пример"],"excerpt":"Реальный пример userID := resp.UserId name := resp.Name","content":"Реальный пример userID := resp.UserId name := resp.Name"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::27","title":"RPC_SAME_RESPONSE_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Реальный пример"],"excerpt":"Реальный пример // After (тип ответа изменён) client := myapi.NewUserServiceClient(conn) resp, err := client.GetUser(ctx, &myapi.GetUserRequest{ UserId: \"user123\", }) if err != nil { return err }","content":"Реальный пример // After (тип ответа изменён) 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::top::28","title":"RPC_SAME_RESPONSE_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Реальный пример"],"excerpt":"Реальный пример // Ошибки компиляции: userID := resp.UserId // ERROR name := resp.Name // ERROR","content":"Реальный пример // Ошибки компиляции: userID := resp.UserId // ERROR name := resp.Name // ERROR"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::29","title":"RPC_SAME_RESPONSE_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Реальный пример"],"excerpt":"Реальный пример // Новый способ: userID := resp.Id profile := resp.Profile permissions := resp.Permissions ```","content":"Реальный пример // Новый способ: userID := resp.Id profile := resp.Profile permissions := resp.Permissions ```"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::30","title":"RPC_SAME_RESPONSE_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Реальный пример"],"excerpt":"Реальный пример **Имплементация сервера также должна быть переписана:** ```go // Before func (s *server) GetUser(ctx context.Context, req *GetUserRequest) (*GetUserResponse, error) { return &GetUserResponse{ UserId: \"use","content":"Реальный пример **Имплементация сервера также должна быть переписана:** ```go // Before 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::top::31","title":"RPC_SAME_RESPONSE_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Реальный пример"],"excerpt":"Реальный пример // After func (s *server) GetUser(ctx context.Context, req *GetUserRequest) (*GetUserResponseV2, error) { return &GetUserResponseV2{ Id: \"user123\", Profile: &UserProfile{ Name: \"John Doe\", Email: \"john@ex","content":"Реальный пример // After func (s *server) GetUser(ctx context.Context, req *GetUserRequest) (*GetUserResponseV2, error) { return &GetUserResponseV2{ Id: \"user123\", Profile: &UserProfile{ Name: \"John Doe\", Email: \"john@example.com\", }, Permissions: []string{\"read\"}, }, nil } ```"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::32","title":"RPC_SAME_RESPONSE_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Добавьте новый RPC c новым типом ответа:**","content":"Стратегия миграции **Добавьте новый RPC c новым типом ответа:**"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::33","title":"RPC_SAME_RESPONSE_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Поддерживайте оба на сервере:** ```go func (s *server) GetUser(ctx context.Context, req *GetUserRequest) (*GetUserResponse, error) { user := s.getUserInternal(req.UserId) return &GetUserResponse{ Use","content":"Стратегия миграции **Поддерживайте оба на сервере:** ```go func (s *server) GetUser(ctx context.Context, req *GetUserRequest) (*GetUserResponse, error) { user := s.getUserInternal(req.UserId) return &GetUserResponse{ UserId: user.ID, Name: user.Name, Email: user.Email, }, nil }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::34","title":"RPC_SAME_RESPONSE_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции func (s *server) GetUserV2(ctx context.Context, req *GetUserRequest) (*GetUserResponseV2, error) { user := s.getUserInternal(req.UserId) return &GetUserResponseV2{ Id: user.ID, Profile: &UserProfile{ N","content":"Стратегия миграции func (s *server) GetUserV2(ctx context.Context, req *GetUserRequest) (*GetUserResponseV2, error) { user := s.getUserInternal(req.UserId) return &GetUserResponseV2{ Id: user.ID, Profile: &UserProfile{ Name: user.Name, Email: user.Email, }, Permissions: user.Permissions, }, nil } ```"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::35","title":"RPC_SAME_RESPONSE_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Мигрируйте клиентов на новый RPC:**","content":"Стратегия миграции **Мигрируйте клиентов на новый RPC:**"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::36","title":"RPC_SAME_RESPONSE_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Удалите старый RPC** в следующей major‑версии:","content":"Стратегия миграции **Удалите старый RPC** в следующей major‑версии:"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::37","title":"RPC_SAME_RESPONSE_TYPE","section":"Добавление новых обязательных полей","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Добавление новых обязательных полей"],"excerpt":"Добавление новых обязательных полей ```proto // ПЛОХО: меняем существующий тип message GetUserResponse { string user_id = 1; string name = 2; UserProfile profile = 3; // BREAKING }","content":"Добавление новых обязательных полей ```proto // ПЛОХО: меняем существующий тип message GetUserResponse { string user_id = 1; string name = 2; UserProfile profile = 3; // BREAKING }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::38","title":"RPC_SAME_RESPONSE_TYPE","section":"Добавление новых обязательных полей","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Добавление новых обязательных полей"],"excerpt":"Добавление новых обязательных полей // Хорошо: новая версия message GetUserResponseV2 { string user_id = 1; string name = 2; UserProfile profile = 3; } ```","content":"Добавление новых обязательных полей // Хорошо: новая версия message GetUserResponseV2 { string user_id = 1; string name = 2; UserProfile profile = 3; } ```"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::39","title":"RPC_SAME_RESPONSE_TYPE","section":"Реструктуризация ответа","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Реструктуризация ответа"],"excerpt":"Реструктуризация ответа ```proto // ПЛОХО: меняем структуру прямо message UpdateUserResponse { UserDetails details = 1; // BREAKING }","content":"Реструктуризация ответа ```proto // ПЛОХО: меняем структуру прямо message UpdateUserResponse { UserDetails details = 1; // BREAKING }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::40","title":"RPC_SAME_RESPONSE_TYPE","section":"Реструктуризация ответа","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Реструктуризация ответа"],"excerpt":"Реструктуризация ответа // Хорошо: версионирование rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse) { option deprecated = true; } rpc UpdateUserV2(UpdateUserRequest) returns (UpdateUserResponseV2); ```","content":"Реструктуризация ответа // Хорошо: версионирование rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse) { option deprecated = true; } rpc UpdateUserV2(UpdateUserRequest) returns (UpdateUserResponseV2); ```"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::41","title":"RPC_SAME_RESPONSE_TYPE","section":"Изменение формата ошибок","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Изменение формата ошибок"],"excerpt":"Изменение формата ошибок ```proto // ПЛОХО: меняем формат напрямую message CreateUserResponse { ErrorDetails error = 1; // BREAKING }","content":"Изменение формата ошибок ```proto // ПЛОХО: меняем формат напрямую message CreateUserResponse { ErrorDetails error = 1; // BREAKING }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::42","title":"RPC_SAME_RESPONSE_TYPE","section":"Изменение формата ошибок","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Изменение формата ошибок"],"excerpt":"Изменение формата ошибок // Хорошо: новая версия rpc CreateUser(CreateUserRequest) returns (CreateUserResponse) { option deprecated = true; } rpc CreateUserV2(CreateUserRequest) returns (CreateUserResponseV2); ```","content":"Изменение формата ошибок // Хорошо: новая версия rpc CreateUser(CreateUserRequest) returns (CreateUserResponse) { option deprecated = true; } rpc CreateUserV2(CreateUserRequest) returns (CreateUserResponseV2); ```"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::43","title":"RPC_SAME_RESPONSE_TYPE","section":"Миграция формата","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Миграция формата"],"excerpt":"Миграция формата ```proto // ПЛОХО: перевод простой структуры в сложную message GetUserResponse { UserData data = 1; // BREAKING }","content":"Миграция формата ```proto // ПЛОХО: перевод простой структуры в сложную message GetUserResponse { UserData data = 1; // BREAKING }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::44","title":"RPC_SAME_RESPONSE_TYPE","section":"Миграция формата","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Миграция формата"],"excerpt":"Миграция формата // Хорошо: предоставляем обе версии rpc GetUser(GetUserRequest) returns (GetUserResponse) { option deprecated = true; } rpc GetUserDetailed(GetUserRequest) returns (GetUserDetailedResponse); ```","content":"Миграция формата // Хорошо: предоставляем обе версии 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":"Данное правило проверяет, что ни один service не был удалён из proto‑файлов. Удаление service ломает сгенерированный код и клиентские приложения, которые на него опираются.","content":"Данное правило проверяет, что ни один service не был удалён из proto‑файлов. Удаление service ломает сгенерированный код и клиентские приложения, которые на него опираются."},{"id":"cli/breaking-changes/rules/service-no-delete::breaking::1","title":"SERVICE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/service-no-delete::breaking::2","title":"SERVICE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/service-no-delete::breaking::3","title":"SERVICE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); }","content":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); }"},{"id":"cli/breaking-changes/rules/service-no-delete::breaking::4","title":"SERVICE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) service OrderService { // [!code --] rpc GetOrder(GetOrderRequest) returns (GetOrderResponse); // [!code --] } // [!code --] ```","content":"Плохой (Breaking) service OrderService { // [!code --] rpc GetOrder(GetOrderRequest) returns (GetOrderResponse); // [!code --] } // [!code --] ```"},{"id":"cli/breaking-changes/rules/service-no-delete::breaking::5","title":"SERVICE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/service-no-delete::breaking::6","title":"SERVICE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/service-no-delete::breaking::7","title":"SERVICE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); }","content":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); }"},{"id":"cli/breaking-changes/rules/service-no-delete::breaking::8","title":"SERVICE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) // OrderService удалён — BREAKING CHANGE! ```","content":"Плохой (Breaking) // OrderService удалён — BREAKING CHANGE! ```"},{"id":"cli/breaking-changes/rules/service-no-delete::top::9","title":"SERVICE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо удаления — отметьте service как deprecated:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо удаления — отметьте service как deprecated:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/service-no-delete::top::10","title":"SERVICE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/service-no-delete::top::11","title":"SERVICE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); }","content":"Хороший (Безопасный) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); }"},{"id":"cli/breaking-changes/rules/service-no-delete::top::12","title":"SERVICE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) service OrderService { option deprecated = true; // [!code focus] rpc GetOrder(GetOrderRequest) returns (GetOrderResponse) { option deprecated = true; // [!code focus] } } ```","content":"Хороший (Безопасный) 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::top::13","title":"SERVICE_NO_DELETE","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete","headings":["Влияние"],"excerpt":"Влияние **Generated Code:** Классы / интерфейсы сервиса исчезают — клиенты не компилируются **Client Applications:** Существующие вызовы к удалённому сервису падают на этапе сборки **Runtime:** gRPC клиенты теряют опреде","content":"Влияние **Generated Code:** Классы / интерфейсы сервиса исчезают — клиенты не компилируются **Client Applications:** Существующие вызовы к удалённому сервису падают на этапе сборки **Runtime:** gRPC клиенты теряют определение метода/сервиса"},{"id":"cli/breaking-changes/rules/service-no-delete::top::14","title":"SERVICE_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Сначала деприкация:**","content":"Стратегия миграции **Сначала деприкация:**"},{"id":"cli/breaking-changes/rules/service-no-delete::top::15","title":"SERVICE_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Уведомите клиентов** о сроках вывода из эксплуатации","content":"Стратегия миграции **Уведомите клиентов** о сроках вывода из эксплуатации"},{"id":"cli/breaking-changes/rules/service-no-delete::top::16","title":"SERVICE_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Удалите после периода миграции** в следующей major‑версии","content":"Стратегия миграции **Удалите после периода миграции** в следующей major‑версии"},{"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 Формат вывода для команд с поддержкой нескольких форматов (text/json) значение по умолчанию зависит от команды"},{"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 Базовая директория для поиска файлов Текущая рабочая дир","content":"Command-Specific Flags Flag Short Environment Description Default ------ ------- ------------- ------------- --------- --path -p Directory path to lint . --root -r Базовая директория для поиска файлов Текущая рабочая директория --format -f EASYP_FORMAT Использует глобальный флаг формата (text/json) Использует глобальное значение по умолчанию"},{"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 из поддиректории с правильным разрешением импортов easyp lint --root src/IPC/Contracts --path .","content":"Command-Specific Flags Lint из поддиректории с правильным разрешением импортов 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 # глобальный флаг","content":"Command-Specific Flags JSON output format easyp --format json lint # глобальный флаг"},{"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 Путь к директории с proto файлами для генерации . --root -r Базова","content":"Command-Specific Flags Flag Short Environment Description Default ------ ------- ------------- ------------- --------- --path -p EASYP_ROOT_GENERATE_PATH Путь к директории с proto файлами для генерации . --root -r Базовая директория для поиска файлов Текущая рабочая директория"},{"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 из поддиректории с правильным разрешением импортов easyp generate --root src/IPC/Contracts --path .","content":"Command-Specific Flags Generate из поддиректории с правильным разрешением импортов 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 Использует глобальный флаг формата (text/json) Использует глобальное значение по умолчанию"},{"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 # глобальный флаг ```","content":"Command-Specific Flags JSON output easyp --format json breaking --against main # глобальный флаг ```"},{"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 работает интерактивно: Если в корне целевой директории есть buf.yml/buf.yaml, команда предложит миграцию из Buf. Если easyp.yaml уже существует, команда запросит подтверждение на перезап","content":"Command-Specific Flags easyp init работает интерактивно: Если в корне целевой директории есть buf.yml/buf.yaml, команда предложит миграцию из Buf. Если easyp.yaml уже существует, команда запросит подтверждение на перезапись."},{"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 Путь до файла конфигурации easyp.yaml --format (global) -f EASYP_FORMAT Глобаль","content":"Command-Specific Flags Flag Short Environment Description Default ------ ------- ------------- ------------- --------- --config -c EASYP_CFG Путь до файла конфигурации easyp.yaml --format (global) -f EASYP_FORMAT Глобальный формат вывода для команд с несколькими форматами (json или text) зависит от команды (json для 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 Проверить конфиг по умолчанию с JSON выводом (статус 0 если ошибок нет) easyp validate-config","content":"Command-Specific Flags **Examples:** ```bash Проверить конфиг по умолчанию с JSON выводом (статус 0 если ошибок нет) 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 Проверить другой файл и вывести в текстовом формате (глобальный --format) easyp --format text validate-config --config example.easyp.yaml ```","content":"Command-Specific Flags Проверить другой файл и вывести в текстовом формате (глобальный --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 Формат вывода для поддерживаемых команд (text/json). Если не указан, каждая команда использует своё значение по умолчанию. значение по умолчанию зависит от команды 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::top::45","title":"EasyP Configuration Reference","section":"Переменные окружения в конфигурации","path":"/docs/guide/cli/configuration/configuration","headings":["Переменные окружения в конфигурации"],"excerpt":"Переменные окружения в конфигурации EasyP поддерживает расширение переменных окружения непосредственно в файле конфигурации easyp.yaml. Это позволяет использовать переменные окружения для динамических значений конфигурац","content":"Переменные окружения в конфигурации EasyP поддерживает расширение переменных окружения непосредственно в файле конфигурации easyp.yaml. Это позволяет использовать переменные окружения для динамических значений конфигурации."},{"id":"cli/configuration/configuration::top::46","title":"EasyP Configuration Reference","section":"Переменные окружения в конфигурации","path":"/docs/guide/cli/configuration/configuration","headings":["Переменные окружения в конфигурации"],"excerpt":"Переменные окружения в конфигурации **Пример со всеми поддерживаемыми возможностями:** ```yaml deps: # Базовое расширение: ${VAR} - расширяется в значение переменной VAR - ${GOOGLEAPIS_REPO}@${GOOGLEAPIS_VERSION} # Значе","content":"Переменные окружения в конфигурации **Пример со всеми поддерживаемыми возможностями:** ```yaml deps: # Базовое расширение: ${VAR} - расширяется в значение переменной VAR - ${GOOGLEAPIS_REPO}@${GOOGLEAPIS_VERSION} # Значение по умолчанию: ${VAR:-default} - использует default, если VAR не установлена или пустая - ${GNOSTIC_REPO:-github.com/google/gnostic}@${GNOSTIC_VERSION:-v0.7.0}"},{"id":"cli/configuration/configuration::top::47","title":"EasyP Configuration Reference","section":"Переменные окружения в конфигурации","path":"/docs/guide/cli/configuration/configuration","headings":["Переменные окружения в конфигурации"],"excerpt":"Переменные окружения в конфигурации generate: inputs: # Значение по умолчанию, если INPUT_DIR не установлена - directory: ${INPUT_DIR:-proto} plugins: - name: go # Базовое расширение out: ${OUTPUT_DIR} opts: # Значение п","content":"Переменные окружения в конфигурации generate: inputs: # Значение по умолчанию, если INPUT_DIR не установлена - directory: ${INPUT_DIR:-proto} plugins: - name: go # Базовое расширение out: ${OUTPUT_DIR} opts: # Значение по умолчанию module: ${MODULE_NAME:-github.com/example/project} timeout: ${TIMEOUT:-30} # Экранирование: $$ становится буквальным $, $${VAR} становится буквальным ${VAR} path: \"${BASE_DIR}/$${TEMP}/file\" # Результат: \"/tmp/${TEMP}/file\" (если BASE_DIR=/tmp) literal: \"$$\" # Результат: \"$\" ```"},{"id":"cli/configuration/configuration::top::48","title":"EasyP Configuration Reference","section":"Переменные окружения в конфигурации","path":"/docs/guide/cli/configuration/configuration","headings":["Переменные окружения в конфигурации"],"excerpt":"Переменные окружения в конфигурации **Поддерживаемый синтаксис:** ${VAR} - расширяется в значение переменной VAR ${VAR:-default} - использует default, если VAR не установлена или пустая ${VAR:=default} - использует defau","content":"Переменные окружения в конфигурации **Поддерживаемый синтаксис:** ${VAR} - расширяется в значение переменной VAR ${VAR:-default} - использует default, если VAR не установлена или пустая ${VAR:=default} - использует default, если VAR не установлена или пустая ${VAR-default} - использует default, если VAR не установлена (пустая строка сохраняется) $${VAR} или $$VAR - экранирует в буквальную строку ${VAR} или $VAR $$ - экранирует в буквальный символ $"},{"id":"cli/configuration/configuration::top::49","title":"EasyP Configuration Reference","section":"Переменные окружения в конфигурации","path":"/docs/guide/cli/configuration/configuration","headings":["Переменные окружения в конфигурации"],"excerpt":"Переменные окружения в конфигурации **Примечание:** Переменные окружения расширяются до парсинга YAML, поэтому любой паттерн ${STRING} будет обработан. Используйте $$ для экранирования символов доллара, когда нужны буква","content":"Переменные окружения в конфигурации **Примечание:** Переменные окружения расширяются до парсинга YAML, поэтому любой паттерн ${STRING} будет обработан. Используйте $$ для экранирования символов доллара, когда нужны буквальные значения."},{"id":"cli/configuration/configuration::version::50","title":"EasyP Configuration Reference","section":"version","path":"/docs/guide/cli/configuration/configuration#version","headings":["version"],"excerpt":"version **Опционально (legacy-совместимость).** Поле поддерживается для обратной совместимости и может быть опущено в новых конфигурациях.","content":"version **Опционально (legacy-совместимость).** Поле поддерживается для обратной совместимости и может быть опущено в новых конфигурациях."},{"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:** не задано **Рекомендация:** если сохраняете поле, используйте v1alpha","content":"version **Type:** string **Default:** не задано **Рекомендация:** если сохраняете поле, используйте v1alpha"},{"id":"cli/configuration/configuration::version::52","title":"EasyP Configuration Reference","section":"version","path":"/docs/guide/cli/configuration/configuration#version","headings":["version"],"excerpt":"version На поведение рантайма это поле не влияет.","content":"version На поведение рантайма это поле не влияет."},{"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, required) - Output directory for generated files opts (mapstring, optional) - Plugin-specific options; each key can be a single value or an array of 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::top::0","title":"Go","section":"Установка плагинов","path":"/docs/guide/cli/generator/examples/go","headings":["Установка плагинов"],"excerpt":"Установка плагинов Сначала установите необходимые плагины для работы с gRPC:","content":"Установка плагинов Сначала установите необходимые плагины для работы с gRPC:"},{"id":"cli/generator/examples/go::top::1","title":"Go","section":"Установка плагинов","path":"/docs/guide/cli/generator/examples/go","headings":["Установка плагинов"],"excerpt":"Установка плагинов Эти команды установят плагины protoc-gen-go и protoc-gen-go-grpc для использования с EasyP.","content":"Установка плагинов Эти команды установят плагины protoc-gen-go и protoc-gen-go-grpc для использования с EasyP."},{"id":"cli/generator/examples/go::proto::2","title":"Go","section":"Пример proto‑сервиса","path":"/docs/guide/cli/generator/examples/go#proto","headings":["Пример proto‑сервиса"],"excerpt":"Пример proto‑сервиса Ниже пример proto-файла для сервиса Echo:","content":"Пример proto‑сервиса Ниже пример proto-файла для сервиса Echo:"},{"id":"cli/generator/examples/go::proto::3","title":"Go","section":"Пример proto‑сервиса","path":"/docs/guide/cli/generator/examples/go#proto","headings":["Пример proto‑сервиса"],"excerpt":"Пример proto‑сервиса ```proto syntax = \"proto3\";","content":"Пример proto‑сервиса ```proto syntax = \"proto3\";"},{"id":"cli/generator/examples/go::proto::4","title":"Go","section":"Пример proto‑сервиса","path":"/docs/guide/cli/generator/examples/go#proto","headings":["Пример proto‑сервиса"],"excerpt":"Пример proto‑сервиса package api.echo.v1;","content":"Пример proto‑сервиса package api.echo.v1;"},{"id":"cli/generator/examples/go::proto::5","title":"Go","section":"Пример proto‑сервиса","path":"/docs/guide/cli/generator/examples/go#proto","headings":["Пример proto‑сервиса"],"excerpt":"Пример proto‑сервиса option go_package = \"github.com/easyp-tech/example/api/echo/v1;pb\";","content":"Пример proto‑сервиса option go_package = \"github.com/easyp-tech/example/api/echo/v1;pb\";"},{"id":"cli/generator/examples/go::proto::6","title":"Go","section":"Пример proto‑сервиса","path":"/docs/guide/cli/generator/examples/go#proto","headings":["Пример proto‑сервиса"],"excerpt":"Пример proto‑сервиса service EchoAPI { rpc Echo(EchoRequest) returns (EchoResponse); rpc EchoStream(EchoStreamRequest) returns (EchoResponse); }","content":"Пример proto‑сервиса service EchoAPI { rpc Echo(EchoRequest) returns (EchoResponse); rpc EchoStream(EchoStreamRequest) returns (EchoResponse); }"},{"id":"cli/generator/examples/go::proto::7","title":"Go","section":"Пример proto‑сервиса","path":"/docs/guide/cli/generator/examples/go#proto","headings":["Пример proto‑сервиса"],"excerpt":"Пример proto‑сервиса message EchoRequest { string payload = 1; }","content":"Пример proto‑сервиса message EchoRequest { string payload = 1; }"},{"id":"cli/generator/examples/go::proto::8","title":"Go","section":"Пример proto‑сервиса","path":"/docs/guide/cli/generator/examples/go#proto","headings":["Пример proto‑сервиса"],"excerpt":"Пример proto‑сервиса message EchoResponse { string payload = 2; }","content":"Пример proto‑сервиса message EchoResponse { string payload = 2; }"},{"id":"cli/generator/examples/go::proto::9","title":"Go","section":"Пример proto‑сервиса","path":"/docs/guide/cli/generator/examples/go#proto","headings":["Пример proto‑сервиса"],"excerpt":"Пример proto‑сервиса message EchoStreamRequest { string payload = 1; }","content":"Пример proto‑сервиса message EchoStreamRequest { string payload = 1; }"},{"id":"cli/generator/examples/go::proto::10","title":"Go","section":"Пример proto‑сервиса","path":"/docs/guide/cli/generator/examples/go#proto","headings":["Пример proto‑сервиса"],"excerpt":"Пример proto‑сервиса message EchoStreamResponse { string payload = 2; } ```","content":"Пример proto‑сервиса message EchoStreamResponse { string payload = 2; } ```"},{"id":"cli/generator/examples/go::top::11","title":"Go","section":"Настройка конфигурации","path":"/docs/guide/cli/generator/examples/go","headings":["Настройка конфигурации"],"excerpt":"Настройка конфигурации Создайте и настройте файл конфигурации easyp.yaml:","content":"Настройка конфигурации Создайте и настройте файл конфигурации easyp.yaml:"},{"id":"cli/generator/examples/go::top::12","title":"Go","section":"Настройка конфигурации","path":"/docs/guide/cli/generator/examples/go","headings":["Настройка конфигурации"],"excerpt":"Настройка конфигурации Этот файл указывает использование двух плагинов: go для генерации Go-кода и go-grpc для генерации gRPC-кода, вместе с их опциями.","content":"Настройка конфигурации Этот файл указывает использование двух плагинов: go для генерации Go-кода и go-grpc для генерации gRPC-кода, вместе с их опциями."},{"id":"cli/generator/examples/go::top::13","title":"Go","section":"Генерация кода","path":"/docs/guide/cli/generator/examples/go","headings":["Генерация кода"],"excerpt":"Генерация кода Чтобы сгенерировать код, выполните команду:","content":"Генерация кода Чтобы сгенерировать код, выполните команду:"},{"id":"cli/generator/examples/go::top::14","title":"Go","section":"Генерация кода","path":"/docs/guide/cli/generator/examples/go","headings":["Генерация кода"],"excerpt":"Генерация кода Если флаг --cfg не указан, по умолчанию используется файл easyp.yaml в текущей директории:","content":"Генерация кода Если флаг --cfg не указан, по умолчанию используется файл easyp.yaml в текущей директории:"},{"id":"cli/generator/examples/go::top::15","title":"Go","section":"Генерация кода","path":"/docs/guide/cli/generator/examples/go","headings":["Генерация кода"],"excerpt":"Генерация кода Теперь у вас есть сгенерированный Go‑код, с которым можно напрямую работать.","content":"Генерация кода Теперь у вас есть сгенерированный Go‑код, с которым можно напрямую работать."},{"id":"cli/generator/examples/grpc-gateway::top::0","title":"gRPC-Gateway","section":"Установка плагинов","path":"/docs/guide/cli/generator/examples/grpc-gateway","headings":["Установка плагинов"],"excerpt":"Установка плагинов В дополнение к плагинам для работы с gRPC, необходимо установить следующие плагины для gRPC-Gateway:","content":"Установка плагинов В дополнение к плагинам для работы с gRPC, необходимо установить следующие плагины для gRPC-Gateway:"},{"id":"cli/generator/examples/grpc-gateway::top::1","title":"gRPC-Gateway","section":"Установка плагинов","path":"/docs/guide/cli/generator/examples/grpc-gateway","headings":["Установка плагинов"],"excerpt":"Установка плагинов go install google.golang.org/protobuf/cmd/protoc-gen-go@latest go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest go install github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2@","content":"Установка плагинов go install google.golang.org/protobuf/cmd/protoc-gen-go@latest go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest go install github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2@latest go install github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway@latest"},{"id":"cli/generator/examples/grpc-gateway::top::2","title":"gRPC-Gateway","section":"Установка плагинов","path":"/docs/guide/cli/generator/examples/grpc-gateway","headings":["Установка плагинов"],"excerpt":"Установка плагинов Эти команды установят плагины protoc-gen-go, protoc-gen-go-grpc, protoc-gen-openapiv2 и protoc-gen-grpc-gateway для использования с EasyP.","content":"Установка плагинов Эти команды установят плагины protoc-gen-go, protoc-gen-go-grpc, protoc-gen-openapiv2 и protoc-gen-grpc-gateway для использования с EasyP."},{"id":"cli/generator/examples/grpc-gateway::proto::3","title":"gRPC-Gateway","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/grpc-gateway#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса Ниже — исходный proto‑файл для сервиса Echo:","content":"Пример Proto сервиса Ниже — исходный proto‑файл для сервиса Echo:"},{"id":"cli/generator/examples/grpc-gateway::proto::4","title":"gRPC-Gateway","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/grpc-gateway#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса syntax = \"proto3\";","content":"Пример Proto сервиса syntax = \"proto3\";"},{"id":"cli/generator/examples/grpc-gateway::proto::5","title":"gRPC-Gateway","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/grpc-gateway#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса package api.echo.v1;","content":"Пример Proto сервиса package api.echo.v1;"},{"id":"cli/generator/examples/grpc-gateway::proto::6","title":"gRPC-Gateway","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/grpc-gateway#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса option go_package = \"github.com/easyp-tech/example/api/echo/v1;pb\";","content":"Пример Proto сервиса option go_package = \"github.com/easyp-tech/example/api/echo/v1;pb\";"},{"id":"cli/generator/examples/grpc-gateway::proto::7","title":"gRPC-Gateway","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/grpc-gateway#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса service EchoAPI { rpc Echo(EchoRequest) returns (EchoResponse); }","content":"Пример Proto сервиса service EchoAPI { rpc Echo(EchoRequest) returns (EchoResponse); }"},{"id":"cli/generator/examples/grpc-gateway::proto::8","title":"gRPC-Gateway","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/grpc-gateway#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса message EchoRequest { string payload = 1; }","content":"Пример Proto сервиса message EchoRequest { string payload = 1; }"},{"id":"cli/generator/examples/grpc-gateway::proto::9","title":"gRPC-Gateway","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/grpc-gateway#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса message EchoResponse { string payload = 2; }","content":"Пример Proto сервиса message EchoResponse { string payload = 2; }"},{"id":"cli/generator/examples/grpc-gateway::proto::10","title":"gRPC-Gateway","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/grpc-gateway#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса Чтобы использовать gRPC-Gateway, обновите proto‑файл, добавив HTTP‑опции:","content":"Пример Proto сервиса Чтобы использовать gRPC-Gateway, обновите proto‑файл, добавив HTTP‑опции:"},{"id":"cli/generator/examples/grpc-gateway::proto::11","title":"gRPC-Gateway","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/grpc-gateway#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса syntax = \"proto3\"; import \"google/api/annotations.proto\";","content":"Пример Proto сервиса syntax = \"proto3\"; import \"google/api/annotations.proto\";"},{"id":"cli/generator/examples/grpc-gateway::proto::12","title":"gRPC-Gateway","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/grpc-gateway#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса package api.echo.v1;","content":"Пример Proto сервиса package api.echo.v1;"},{"id":"cli/generator/examples/grpc-gateway::proto::13","title":"gRPC-Gateway","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/grpc-gateway#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса option go_package = \"github.com/easyp-tech/example/api/echo/v1;pb\";","content":"Пример Proto сервиса option go_package = \"github.com/easyp-tech/example/api/echo/v1;pb\";"},{"id":"cli/generator/examples/grpc-gateway::proto::14","title":"gRPC-Gateway","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/grpc-gateway#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса service EchoAPI { rpc Echo(EchoRequest) returns (EchoResponse) { option (google.api.http) = { // [!code ++] post: \"/api/v1/echo\" // [!code ++] body: \"*\" // [!code ++] }; // [!code ++] } }","content":"Пример Proto сервиса 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::proto::15","title":"gRPC-Gateway","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/grpc-gateway#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса message EchoRequest { string payload = 1; }","content":"Пример Proto сервиса message EchoRequest { string payload = 1; }"},{"id":"cli/generator/examples/grpc-gateway::proto::16","title":"gRPC-Gateway","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/grpc-gateway#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса message EchoResponse { string payload = 2; }","content":"Пример Proto сервиса message EchoResponse { string payload = 2; }"},{"id":"cli/generator/examples/grpc-gateway::top::17","title":"gRPC-Gateway","section":"Настройка конфигурации","path":"/docs/guide/cli/generator/examples/grpc-gateway","headings":["Настройка конфигурации"],"excerpt":"Настройка конфигурации Обновите файл easyp.yaml, добавив необходимые зависимости и плагины: deps: # [!code ++] - github.com/googleapis/googleapis # [!code ++]","content":"Настройка конфигурации Обновите файл easyp.yaml, добавив необходимые зависимости и плагины: deps: # [!code ++] - github.com/googleapis/googleapis # [!code ++]"},{"id":"cli/generator/examples/grpc-gateway::top::18","title":"gRPC-Gateway","section":"Настройка конфигурации","path":"/docs/guide/cli/generator/examples/grpc-gateway","headings":["Настройка конфигурации"],"excerpt":"Настройка конфигурации 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":"Настройка конфигурации 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::top::19","title":"gRPC-Gateway","section":"Настройка конфигурации","path":"/docs/guide/cli/generator/examples/grpc-gateway","headings":["Настройка конфигурации"],"excerpt":"Настройка конфигурации Секция deps перечисляет зависимости, необходимые для импортов proto‑файлов. В данном случае добавляем github.com/googleapis/googleapis, поскольку там находится файл annotations.proto, используемый ","content":"Настройка конфигурации Секция deps перечисляет зависимости, необходимые для импортов proto‑файлов. В данном случае добавляем github.com/googleapis/googleapis, поскольку там находится файл annotations.proto, используемый в определении сервиса."},{"id":"cli/generator/examples/grpc-gateway::top::20","title":"gRPC-Gateway","section":"Обновление зависимостей","path":"/docs/guide/cli/generator/examples/grpc-gateway","headings":["Обновление зависимостей"],"excerpt":"Обновление зависимостей После обновления конфигурации выполните команду для загрузки указанных зависимостей:","content":"Обновление зависимостей После обновления конфигурации выполните команду для загрузки указанных зависимостей:"},{"id":"cli/generator/examples/grpc-gateway::top::21","title":"gRPC-Gateway","section":"Обновление зависимостей","path":"/docs/guide/cli/generator/examples/grpc-gateway","headings":["Обновление зависимостей"],"excerpt":"Обновление зависимостей easyp mod update","content":"Обновление зависимостей easyp mod update"},{"id":"cli/generator/examples/grpc-gateway::top::22","title":"gRPC-Gateway","section":"Обновление зависимостей","path":"/docs/guide/cli/generator/examples/grpc-gateway","headings":["Обновление зависимостей"],"excerpt":"Обновление зависимостей Больше деталей по управлению зависимостями см. в разделе Package Manager.","content":"Обновление зависимостей Больше деталей по управлению зависимостями см. в разделе Package Manager."},{"id":"cli/generator/examples/grpc-gateway::top::23","title":"gRPC-Gateway","section":"Генерация кода","path":"/docs/guide/cli/generator/examples/grpc-gateway","headings":["Генерация кода"],"excerpt":"Генерация кода Для генерации кода используйте:","content":"Генерация кода Для генерации кода используйте:"},{"id":"cli/generator/examples/grpc-gateway::top::24","title":"gRPC-Gateway","section":"Генерация кода","path":"/docs/guide/cli/generator/examples/grpc-gateway","headings":["Генерация кода"],"excerpt":"Генерация кода easyp --cfg easyp.yaml generate","content":"Генерация кода easyp --cfg easyp.yaml generate"},{"id":"cli/generator/examples/grpc-gateway::top::25","title":"gRPC-Gateway","section":"Генерация кода","path":"/docs/guide/cli/generator/examples/grpc-gateway","headings":["Генерация кода"],"excerpt":"Генерация кода Если флаг --cfg не указан, по умолчанию используется файл easyp.yaml из текущей директории:","content":"Генерация кода Если флаг --cfg не указан, по умолчанию используется файл easyp.yaml из текущей директории:"},{"id":"cli/generator/examples/grpc-gateway::top::26","title":"gRPC-Gateway","section":"Генерация кода","path":"/docs/guide/cli/generator/examples/grpc-gateway","headings":["Генерация кода"],"excerpt":"Генерация кода Теперь у вас сгенерированы Go‑код и код gRPC-Gateway, с которыми можно работать напрямую.","content":"Генерация кода Теперь у вас сгенерированы Go‑код и код gRPC-Gateway, с которыми можно работать напрямую."},{"id":"cli/generator/examples/validate::top::0","title":"Validate","section":"Установка плагинов","path":"/docs/guide/cli/generator/examples/validate","headings":["Установка плагинов"],"excerpt":"Установка плагинов Сначала установите необходимые плагины для работы с gRPC и проверок (validate):","content":"Установка плагинов Сначала установите необходимые плагины для работы с gRPC и проверок (validate):"},{"id":"cli/generator/examples/validate::top::1","title":"Validate","section":"Установка плагинов","path":"/docs/guide/cli/generator/examples/validate","headings":["Установка плагинов"],"excerpt":"Установка плагинов Эти команды установят плагины protoc-gen-go, protoc-gen-go-grpc и protoc-gen-validate для использования вместе с EasyP.","content":"Установка плагинов Эти команды установят плагины protoc-gen-go, protoc-gen-go-grpc и protoc-gen-validate для использования вместе с EasyP."},{"id":"cli/generator/examples/validate::proto::2","title":"Validate","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/validate#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса Ниже пример proto‑файла для сервиса Echo:","content":"Пример Proto сервиса Ниже пример proto‑файла для сервиса Echo:"},{"id":"cli/generator/examples/validate::proto::3","title":"Validate","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/validate#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса ```proto syntax = \"proto3\";","content":"Пример Proto сервиса ```proto syntax = \"proto3\";"},{"id":"cli/generator/examples/validate::proto::4","title":"Validate","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/validate#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса package api.echo.v1;","content":"Пример Proto сервиса package api.echo.v1;"},{"id":"cli/generator/examples/validate::proto::5","title":"Validate","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/validate#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса import \"validate/validate.proto\";","content":"Пример Proto сервиса import \"validate/validate.proto\";"},{"id":"cli/generator/examples/validate::proto::6","title":"Validate","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/validate#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса option go_package = \"github.com/easyp-tech/example/api/echo/v1;pb\";","content":"Пример Proto сервиса option go_package = \"github.com/easyp-tech/example/api/echo/v1;pb\";"},{"id":"cli/generator/examples/validate::proto::7","title":"Validate","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/validate#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса service EchoAPI { rpc Echo(EchoRequest) returns (EchoResponse); rpc EchoStream(EchoStreamRequest) returns (EchoResponse); }","content":"Пример Proto сервиса service EchoAPI { rpc Echo(EchoRequest) returns (EchoResponse); rpc EchoStream(EchoStreamRequest) returns (EchoResponse); }"},{"id":"cli/generator/examples/validate::proto::8","title":"Validate","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/validate#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса message EchoRequest { string payload = 1 [(validate.rules).string = {max_len: 200}]; }","content":"Пример Proto сервиса message EchoRequest { string payload = 1 [(validate.rules).string = {max_len: 200}]; }"},{"id":"cli/generator/examples/validate::proto::9","title":"Validate","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/validate#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса message EchoResponse { string payload = 2; }","content":"Пример Proto сервиса message EchoResponse { string payload = 2; }"},{"id":"cli/generator/examples/validate::proto::10","title":"Validate","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/validate#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса message EchoStreamRequest { string payload = 1 [(validate.rules).string = {max_len: 200}]; }","content":"Пример Proto сервиса message EchoStreamRequest { string payload = 1 [(validate.rules).string = {max_len: 200}]; }"},{"id":"cli/generator/examples/validate::proto::11","title":"Validate","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/validate#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса message EchoStreamResponse { string payload = 2; } ```","content":"Пример Proto сервиса message EchoStreamResponse { string payload = 2; } ```"},{"id":"cli/generator/examples/validate::top::12","title":"Validate","section":"Настройка конфигурации","path":"/docs/guide/cli/generator/examples/validate","headings":["Настройка конфигурации"],"excerpt":"Настройка конфигурации Создайте и настройте файл конфигурации easyp.yaml:","content":"Настройка конфигурации Создайте и настройте файл конфигурации easyp.yaml:"},{"id":"cli/generator/examples/validate::top::13","title":"Validate","section":"Настройка конфигурации","path":"/docs/guide/cli/generator/examples/validate","headings":["Настройка конфигурации"],"excerpt":"Настройка конфигурации ```yaml deps: # [!code ++] - github.com/bufbuild/protoc-gen-validate # [!code ++]","content":"Настройка конфигурации ```yaml deps: # [!code ++] - github.com/bufbuild/protoc-gen-validate # [!code ++]"},{"id":"cli/generator/examples/validate::top::14","title":"Validate","section":"Настройка конфигурации","path":"/docs/guide/cli/generator/examples/validate","headings":["Настройка конфигурации"],"excerpt":"Настройка конфигурации 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: sourc","content":"Настройка конфигурации 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::top::15","title":"Validate","section":"Генерация кода","path":"/docs/guide/cli/generator/examples/validate","headings":["Генерация кода"],"excerpt":"Генерация кода Чтобы сгенерировать код, выполните команду:","content":"Генерация кода Чтобы сгенерировать код, выполните команду:"},{"id":"cli/generator/examples/validate::top::16","title":"Validate","section":"Генерация кода","path":"/docs/guide/cli/generator/examples/validate","headings":["Генерация кода"],"excerpt":"Генерация кода Если флаг --cfg не указан, по умолчанию используется файл easyp.yaml из текущего каталога:","content":"Генерация кода Если флаг --cfg не указан, по умолчанию используется файл easyp.yaml из текущего каталога:"},{"id":"cli/generator/examples/validate::top::17","title":"Validate","section":"Генерация кода","path":"/docs/guide/cli/generator/examples/validate","headings":["Генерация кода"],"excerpt":"Генерация кода Теперь у вас есть сгенерированный Go‑код с поддержкой валидации, и вы можете напрямую использовать его в проекте.","content":"Генерация кода Теперь у вас есть сгенерированный Go‑код с поддержкой валидации, и вы можете напрямую использовать его в проекте."},{"id":"cli/generator/generator::top::0","title":"Генератор","path":"/docs/guide/cli/generator/generator","headings":[],"excerpt":"EasyP включает мощный генератор, который упрощает процесс получения кода из proto‑файлов. Благодаря YAML‑конфигурациям работа становится гораздо более удобной и интуитивной по сравнению с прямым использованием команды pr","content":"EasyP включает мощный генератор, который упрощает процесс получения кода из proto‑файлов. Благодаря YAML‑конфигурациям работа становится гораздо более удобной и интуитивной по сравнению с прямым использованием команды protoc."},{"id":"cli/generator/generator::top::1","title":"Генератор","section":"Ключевые особенности генератора","path":"/docs/guide/cli/generator/generator","headings":["Ключевые особенности генератора"],"excerpt":"Ключевые особенности генератора **Упрощённая генерация кода**: - Генерация кода из proto через декларативную YAML‑конфигурацию. - Избавляет от необходимости писать длинные и сложные команды protoc.","content":"Ключевые особенности генератора **Упрощённая генерация кода**: - Генерация кода из proto через декларативную YAML‑конфигурацию. - Избавляет от необходимости писать длинные и сложные команды protoc."},{"id":"cli/generator/generator::top::2","title":"Генератор","section":"Ключевые особенности генератора","path":"/docs/guide/cli/generator/generator","headings":["Ключевые особенности генератора"],"excerpt":"Ключевые особенности генератора **Обёртка над protoc**: - EasyP выступает как удобный слой над protoc, предоставляя декларативный API. - Поддерживает все опции и плагины, доступные protoc.","content":"Ключевые особенности генератора **Обёртка над protoc**: - EasyP выступает как удобный слой над protoc, предоставляя декларативный API. - Поддерживает все опции и плагины, доступные protoc."},{"id":"cli/generator/generator::top::3","title":"Генератор","section":"Ключевые особенности генератора","path":"/docs/guide/cli/generator/generator","headings":["Ключевые особенности генератора"],"excerpt":"Ключевые особенности генератора **Гибкость и кастомизация**: - Используются те же параметры, что и у плагинов protoc, прямо в конфиге. - Поддерживается множество плагинов и их параметры в одной конфигурации.","content":"Ключевые особенности генератора **Гибкость и кастомизация**: - Используются те же параметры, что и у плагинов protoc, прямо в конфиге. - Поддерживается множество плагинов и их параметры в одной конфигурации."},{"id":"cli/generator/generator::top::4","title":"Генератор","section":"Ключевые особенности генератора","path":"/docs/guide/cli/generator/generator","headings":["Ключевые особенности генератора"],"excerpt":"Ключевые особенности генератора **Генерация из нескольких источников**: - Локальные директории и удалённые Git‑репозитории одновременно. - Лёгкая интеграция с существующими проектами и репозиториями.","content":"Ключевые особенности генератора **Генерация из нескольких источников**: - Локальные директории и удалённые Git‑репозитории одновременно. - Лёгкая интеграция с существующими проектами и репозиториями."},{"id":"cli/generator/generator::top::5","title":"Генератор","section":"Ключевые особенности генератора","path":"/docs/guide/cli/generator/generator","headings":["Ключевые особенности генератора"],"excerpt":"Ключевые особенности генератора **Удалённая генерация**: - Генерация из удалённых Git репозиториев без локального checkout.","content":"Ключевые особенности генератора **Удалённая генерация**: - Генерация из удалённых Git репозиториев без локального checkout."},{"id":"cli/generator/generator::top::6","title":"Генератор","section":"Ключевые особенности генератора","path":"/docs/guide/cli/generator/generator","headings":["Ключевые особенности генератора"],"excerpt":"Ключевые особенности генератора **Интеграция с менеджером пакетов**: - Прозрачная работа с зависимостями через пакетный менеджер EasyP. - Автоматическое разрешение и подключение proto‑зависимостей.","content":"Ключевые особенности генератора **Интеграция с менеджером пакетов**: - Прозрачная работа с зависимостями через пакетный менеджер EasyP. - Автоматическое разрешение и подключение proto‑зависимостей."},{"id":"cli/generator/generator::complete-configuration-example::7","title":"Генератор","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":"Генератор","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":"Генератор","section":"Complete Configuration Example","path":"/docs/guide/cli/generator/generator#complete-configuration-example","headings":["Complete Configuration Example"],"excerpt":"Complete Configuration Example Managed mode - автоматическая установка file и field опций managed: enabled: true disable: - module: github.com/googleapis/googleapis # Отключить для конкретного модуля override: - file_opt","content":"Complete Configuration Example Managed mode - автоматическая установка file и field опций managed: enabled: true disable: - module: github.com/googleapis/googleapis # Отключить для конкретного модуля 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/ # Применить к конкретному пути"},{"id":"cli/generator/generator::complete-configuration-example::10","title":"Генератор","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":"Генератор","section":"Локальный ввод (Local Directory Input)","path":"/docs/guide/cli/generator/generator#local-directory-input","headings":["Локальный ввод (Local Directory Input)"],"excerpt":"Локальный ввод (Local Directory Input) Локальная директория — самый распространённый и простой способ указать откуда брать proto для генерации. Используйте этот вариант, если файлы уже находятся в репозитории проекта.","content":"Локальный ввод (Local Directory Input) Локальная директория — самый распространённый и простой способ указать откуда брать proto для генерации. Используйте этот вариант, если файлы уже находятся в репозитории проекта."},{"id":"cli/generator/generator::local-directory-input::12","title":"Генератор","section":"Локальный ввод (Local Directory Input)","path":"/docs/guide/cli/generator/generator#local-directory-input","headings":["Локальный ввод (Local Directory Input)"],"excerpt":"Локальный ввод (Local Directory Input) **Когда применять:** Proto файлы находятся в кодовой базе проекта Нужен полный контроль над структурой каталогов Проект — один сервис или приложение Файлы меняются не слишком часто","content":"Локальный ввод (Local Directory Input) **Когда применять:** Proto файлы находятся в кодовой базе проекта Нужен полный контроль над структурой каталогов Проект — один сервис или приложение Файлы меняются не слишком часто"},{"id":"cli/generator/generator::local-directory-input::13","title":"Генератор","section":"Локальный ввод (Local Directory Input)","path":"/docs/guide/cli/generator/generator#local-directory-input","headings":["Локальный ввод (Local Directory Input)"],"excerpt":"Локальный ввод (Local Directory Input)","content":"Локальный ввод (Local Directory Input)"},{"id":"cli/generator/generator::local-directory-input::14","title":"Генератор","section":"Локальный ввод (Local Directory Input)","path":"/docs/guide/cli/generator/generator#local-directory-input","headings":["Локальный ввод (Local Directory Input)"],"excerpt":"Локальный ввод (Local Directory Input) Параметр root особенно полезен в монорепозиториях: он позволяет управлять тем, откуда будут резолвиться пути импортов. Если указать родительскую директорию, импорты будут оцениватьс","content":"Локальный ввод (Local Directory Input) Параметр root особенно полезен в монорепозиториях: он позволяет управлять тем, откуда будут резолвиться пути импортов. Если указать родительскую директорию, импорты будут оцениваться относительно неё, а не текущего рабочего каталога."},{"id":"cli/generator/generator::local-directory-input::15","title":"Генератор","section":"Локальный ввод (Local Directory Input)","path":"/docs/guide/cli/generator/generator#local-directory-input","headings":["Локальный ввод (Local Directory Input)"],"excerpt":"Локальный ввод (Local Directory Input) **Параметры:**","content":"Локальный ввод (Local Directory Input) **Параметры:**"},{"id":"cli/generator/generator::local-directory-input::16","title":"Генератор","section":"Локальный ввод (Local Directory Input)","path":"/docs/guide/cli/generator/generator#local-directory-input","headings":["Локальный ввод (Local Directory Input)"],"excerpt":"Локальный ввод (Local Directory Input) Параметр Тип Обязателен Значение по умолчанию Описание ---------- ----- ------------ ----------------------- ---------- path string ✅ - Каталог, содержащий proto файлы root string ❌","content":"Локальный ввод (Local Directory Input) Параметр Тип Обязателен Значение по умолчанию Описание ---------- ----- ------------ ----------------------- ---------- path string ✅ - Каталог, содержащий proto файлы root string ❌ \".\" Корневая директория для разрешения import путей"},{"id":"cli/generator/generator::local-directory-input::17","title":"Генератор","section":"Локальный ввод (Local Directory Input)","path":"/docs/guide/cli/generator/generator#local-directory-input","headings":["Локальный ввод (Local Directory Input)"],"excerpt":"Локальный ввод (Local Directory Input) **Примеры:**","content":"Локальный ввод (Local Directory Input) **Примеры:**"},{"id":"cli/generator/generator::local-directory-input::18","title":"Генератор","section":"Локальный ввод (Local Directory Input)","path":"/docs/guide/cli/generator/generator#local-directory-input","headings":["Локальный ввод (Local Directory Input)"],"excerpt":"Локальный ввод (Local Directory Input) Ниже показана разница между базовым указанием директории и расширенной конфигурацией с пользовательским корнем импортов:","content":"Локальный ввод (Local Directory Input) Ниже показана разница между базовым указанием директории и расширенной конфигурацией с пользовательским корнем импортов:"},{"id":"cli/generator/generator::local-directory-input::19","title":"Генератор","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::20","title":"Генератор","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::git-remote-git-repository-input::21","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) Этот тип входных данных позволяет генерировать код из proto‑файлов, находящихся в удалённых репозиториях, без локального checkout. Особенно полезно при использовани","content":"Удалённый Git репозиторий (Remote Git Repository Input) Этот тип входных данных позволяет генерировать код из proto‑файлов, находящихся в удалённых репозиториях, без локального checkout. Особенно полезно при использовании API других команд или внешних поставщиков."},{"id":"cli/generator/generator::git-remote-git-repository-input::22","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) **Когда использовать:** Потребление proto определений из других сервисов/команд Интеграция с внешними вендорскими API Работа с общими библиотеками proto в нескольки","content":"Удалённый Git репозиторий (Remote Git Repository Input) **Когда использовать:** Потребление proto определений из других сервисов/команд Интеграция с внешними вендорскими API Работа с общими библиотеками proto в нескольких проектах Необходимо гарантировать корректную (зафиксированную) версию внешних API"},{"id":"cli/generator/generator::git-remote-git-repository-input::23","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) **Рекомендации:** В продакшене всегда фиксируйте версии (@v1.0.0, а не latest) Используйте семантические версии при наличии — проще сопровождать Предпочитайте публи","content":"Удалённый Git репозиторий (Remote Git Repository Input) **Рекомендации:** В продакшене всегда фиксируйте версии (@v1.0.0, а не latest) Используйте семантические версии при наличии — проще сопровождать Предпочитайте публичные теги вместо хеша коммита (лучше отслеживаемость)"},{"id":"cli/generator/generator::git-remote-git-repository-input::24","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input)","content":"Удалённый Git репозиторий (Remote Git Repository Input)"},{"id":"cli/generator/generator::git-remote-git-repository-input::25","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) Параметр root задаёт корень для разрешения импортов файлов из этого репозитория.","content":"Удалённый Git репозиторий (Remote Git Repository Input) Параметр root задаёт корень для разрешения импортов файлов из этого репозитория."},{"id":"cli/generator/generator::git-remote-git-repository-input::26","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) **Параметры:**","content":"Удалённый Git репозиторий (Remote Git Repository Input) **Параметры:**"},{"id":"cli/generator/generator::git-remote-git-repository-input::27","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) Параметр Тип Обязателен По умолчанию Описание ---------- ----- ------------ -------------- ---------- url string ✅ - URL Git репозитория с необязательной версией / ","content":"Удалённый Git репозиторий (Remote Git Repository Input) Параметр Тип Обязателен По умолчанию Описание ---------- ----- ------------ -------------- ---------- url string ✅ - URL Git репозитория с необязательной версией / тегом / коммитом sub_directory string ❌ \"\" Поддиректория внутри репозитория, где лежат proto root string ❌ \"\" Корневой путь для разрешения импортов"},{"id":"cli/generator/generator::git-remote-git-repository-input::28","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) **Варианты формата URL:**","content":"Удалённый Git репозиторий (Remote Git Repository Input) **Варианты формата URL:**"},{"id":"cli/generator/generator::git-remote-git-repository-input::29","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) EasyP поддерживает несколько форматов для ссылки на удалённые репозитории. Каждый подходит под разные требования по стабильности:","content":"Удалённый Git репозиторий (Remote Git Repository Input) EasyP поддерживает несколько форматов для ссылки на удалённые репозитории. Каждый подходит под разные требования по стабильности:"},{"id":"cli/generator/generator::git-remote-git-repository-input::30","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) **Tagged versions** — для продакшена, стабильные неизменяемые ссылки **Semantic versions** — читаемость и управление зависимостями **Commit hashes** — доступ к конк","content":"Удалённый Git репозиторий (Remote Git Repository Input) **Tagged versions** — для продакшена, стабильные неизменяемые ссылки **Semantic versions** — читаемость и управление зависимостями **Commit hashes** — доступ к конкретному коммиту, если нет тега **Latest** — только для разработки, непредсказуемо **Full HTTPS URLs** — приватные репозитории или нестандартный хостинг"},{"id":"cli/generator/generator::git-remote-git-repository-input::31","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) ```yaml Тег — стабильно для продакшена url: \"github.com/googleapis/googleapis@common-protos-1_3_1\"","content":"Удалённый Git репозиторий (Remote Git Repository Input) ```yaml Тег — стабильно для продакшена url: \"github.com/googleapis/googleapis@common-protos-1_3_1\""},{"id":"cli/generator/generator::git-remote-git-repository-input::32","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) Семантическая версия url: \"github.com/grpc-ecosystem/grpc-gateway@v2.19.1\"","content":"Удалённый Git репозиторий (Remote Git Repository Input) Семантическая версия url: \"github.com/grpc-ecosystem/grpc-gateway@v2.19.1\""},{"id":"cli/generator/generator::git-remote-git-repository-input::33","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) Хеш коммита — точечный фикс url: \"github.com/company/protos@abc123def456\"","content":"Удалённый Git репозиторий (Remote Git Repository Input) Хеш коммита — точечный фикс url: \"github.com/company/protos@abc123def456\""},{"id":"cli/generator/generator::git-remote-git-repository-input::34","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) Latest — только dev, НЕ для продакшена url: \"github.com/company/protos\"","content":"Удалённый Git репозиторий (Remote Git Repository Input) Latest — только dev, НЕ для продакшена url: \"github.com/company/protos\""},{"id":"cli/generator/generator::git-remote-git-repository-input::35","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) Полный HTTPS URL — приватный или кастомный Git url: \"https://github.com/company/private-protos.git\" ```","content":"Удалённый Git репозиторий (Remote Git Repository Input) Полный HTTPS URL — приватный или кастомный Git url: \"https://github.com/company/private-protos.git\" ```"},{"id":"cli/generator/generator::git-remote-git-repository-input::36","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) **Примеры:**","content":"Удалённый Git репозиторий (Remote Git Repository Input) **Примеры:**"},{"id":"cli/generator/generator::git-remote-git-repository-input::37","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) Ниже паттерны использования удалённых источников в разных сценариях:","content":"Удалённый Git репозиторий (Remote Git Repository Input) Ниже паттерны использования удалённых источников в разных сценариях:"},{"id":"cli/generator/generator::git-remote-git-repository-input::38","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input)","content":"Удалённый Git репозиторий (Remote Git Repository Input)"},{"id":"cli/generator/generator::top::39","title":"Генератор","section":"Конфигурация плагинов","path":"/docs/guide/cli/generator/generator","headings":["Конфигурация плагинов"],"excerpt":"Конфигурация плагинов Конфигурация плагинов определяет какие генераторы кода будут запущены и как они себя ведут. EasyP поддерживает любой плагин protoc, что делает его крайне гибким для разных языковых экосистем и сцена","content":"Конфигурация плагинов Конфигурация плагинов определяет какие генераторы кода будут запущены и как они себя ведут. EasyP поддерживает любой плагин protoc, что делает его крайне гибким для разных языковых экосистем и сценариев."},{"id":"cli/generator/generator::top::40","title":"Генератор","section":"Конфигурация плагинов","path":"/docs/guide/cli/generator/generator","headings":["Конфигурация плагинов"],"excerpt":"Конфигурация плагинов На верхнем уровне есть **четыре способа указать, как именно запускать плагин**:","content":"Конфигурация плагинов На верхнем уровне есть **четыре способа указать, как именно запускать плагин**:"},{"id":"cli/generator/generator::top::41","title":"Генератор","section":"Конфигурация плагинов","path":"/docs/guide/cli/generator/generator","headings":["Конфигурация плагинов"],"excerpt":"Конфигурация плагинов **name** – запуск плагина по имени из PATH или использование встроенного плагина. **path** – запуск плагина по абсолютному/относительному пути к исполняемому файлу. **remote** – удалённый плагин по ","content":"Конфигурация плагинов **name** – запуск плагина по имени из PATH или использование встроенного плагина. **path** – запуск плагина по абсолютному/относительному пути к исполняемому файлу. **remote** – удалённый плагин по URL (через remote‑executor EasyP). **command** – запуск плагина через произвольную команду (например, go run ...)."},{"id":"cli/generator/generator::top::42","title":"Генератор","section":"Конфигурация плагинов","path":"/docs/guide/cli/generator/generator","headings":["Конфигурация плагинов"],"excerpt":"Конфигурация плагинов Для каждого плагина должен быть указан **ровно один** из параметров name, path, remote или command.","content":"Конфигурация плагинов Для каждого плагина должен быть указан **ровно один** из параметров name, path, remote или command."},{"id":"cli/generator/generator::name::43","title":"Генератор","section":"Плагин по имени (name)","path":"/docs/guide/cli/generator/generator#name","headings":["Плагин по имени (name)"],"excerpt":"Плагин по имени (name) Локальный режим по имени — стандартный: плагины установлены в системе и запускаются напрямую через EasyP.","content":"Плагин по имени (name) Локальный режим по имени — стандартный: плагины установлены в системе и запускаются напрямую через EasyP."},{"id":"cli/generator/generator::name::44","title":"Генератор","section":"Плагин по имени (name)","path":"/docs/guide/cli/generator/generator#name","headings":["Плагин по имени (name)"],"excerpt":"Плагин по имени (name) **Когда использовать name:** Стандартные языки (Go, Python, TypeScript и т.д.) Есть контроль над окружением сборки Критична производительность (нет сетевых задержек) Хочется опираться на PATH или в","content":"Плагин по имени (name) **Когда использовать name:** Стандартные языки (Go, Python, TypeScript и т.д.) Есть контроль над окружением сборки Критична производительность (нет сетевых задержек) Хочется опираться на PATH или встроенные плагины"},{"id":"cli/generator/generator::name::45","title":"Генератор","section":"Плагин по имени (name)","path":"/docs/guide/cli/generator/generator#name","headings":["Плагин по имени (name)"],"excerpt":"Плагин по имени (name) **Требования к установке:** Плагины установлены и доступны в PATH (если не используются встроенные). Имена следуют шаблону protoc-gen-{name}. Установка через менеджеры пакетов (go install, npm inst","content":"Плагин по имени (name) **Требования к установке:** Плагины установлены и доступны в PATH (если не используются встроенные). Имена следуют шаблону protoc-gen-{name}. Установка через менеджеры пакетов (go install, npm install, pip install и т.п.)."},{"id":"cli/generator/generator::name::46","title":"Генератор","section":"Плагин по имени (name)","path":"/docs/guide/cli/generator/generator#name","headings":["Плагин по имени (name)"],"excerpt":"Плагин по имени (name) Параметр with_imports критичен при использовании зависимостей из пакетного менеджера: установите true, чтобы прототипы из секции deps попали в генерацию.","content":"Плагин по имени (name) Параметр with_imports критичен при использовании зависимостей из пакетного менеджера: установите true, чтобы прототипы из секции deps попали в генерацию."},{"id":"cli/generator/generator::path::47","title":"Генератор","section":"Плагин по пути (path)","path":"/docs/guide/cli/generator/generator#path","headings":["Плагин по пути (path)"],"excerpt":"Плагин по пути (path) Иногда нужно запускать плагин из конкретного бинарника, не добавляя его в PATH (например, бинарь в репозитории или в build‑директории). В этом случае можно указать явный путь:","content":"Плагин по пути (path) Иногда нужно запускать плагин из конкретного бинарника, не добавляя его в PATH (например, бинарь в репозитории или в build‑директории). В этом случае можно указать явный путь:"},{"id":"cli/generator/generator::path::48","title":"Генератор","section":"Плагин по пути (path)","path":"/docs/guide/cli/generator/generator#path","headings":["Плагин по пути (path)"],"excerpt":"Плагин по пути (path) **Когда использовать path:** Бинарники плагинов хранятся в репозитории (для воспроизводимых сборок). Используются несколько версий одного и того же плагина параллельно. Не хочется «загрязнять» глоба","content":"Плагин по пути (path) **Когда использовать path:** Бинарники плагинов хранятся в репозитории (для воспроизводимых сборок). Используются несколько версий одного и того же плагина параллельно. Не хочется «загрязнять» глобальный PATH."},{"id":"cli/generator/generator::remote::49","title":"Генератор","section":"Удалённый плагин (remote)","path":"/docs/guide/cli/generator/generator#remote","headings":["Удалённый плагин (remote)"],"excerpt":"Удалённый плагин (remote) Удалённые плагины выполняются по URL. EasyP отправляет на удалённую сторону CodeGeneratorRequest и получает обратно CodeGeneratorResponse.","content":"Удалённый плагин (remote) Удалённые плагины выполняются по URL. EasyP отправляет на удалённую сторону CodeGeneratorRequest и получает обратно CodeGeneratorResponse."},{"id":"cli/generator/generator::remote::50","title":"Генератор","section":"Удалённый плагин (remote)","path":"/docs/guide/cli/generator/generator#remote","headings":["Удалённый плагин (remote)"],"excerpt":"Удалённый плагин (remote) Ниже приведён реальный пример использования EasyP API Service как удалённого исполнителя плагинов (тот же формат используется в разделе про API Service):","content":"Удалённый плагин (remote) Ниже приведён реальный пример использования EasyP API Service как удалённого исполнителя плагинов (тот же формат используется в разделе про API Service):"},{"id":"cli/generator/generator::remote::51","title":"Генератор","section":"Удалённый плагин (remote)","path":"/docs/guide/cli/generator/generator#remote","headings":["Удалённый плагин (remote)"],"excerpt":"Удалённый плагин (remote) ```yaml generate: plugins: # Удалённое выполнение плагинов через EasyP API Service - remote: api.easyp.tech/protobuf/go:v1.36.10 out: . opts: paths: source_relative","content":"Удалённый плагин (remote) ```yaml generate: plugins: # Удалённое выполнение плагинов через EasyP API Service - remote: api.easyp.tech/protobuf/go:v1.36.10 out: . opts: paths: source_relative"},{"id":"cli/generator/generator::remote::52","title":"Генератор","section":"Удалённый плагин (remote)","path":"/docs/guide/cli/generator/generator#remote","headings":["Удалённый плагин (remote)"],"excerpt":"Удалённый плагин (remote) remote: api.easyp.tech/grpc/go:v1.5.1 out: . opts: paths: source_relative ```","content":"Удалённый плагин (remote) remote: api.easyp.tech/grpc/go:v1.5.1 out: . opts: paths: source_relative ```"},{"id":"cli/generator/generator::remote::53","title":"Генератор","section":"Удалённый плагин (remote)","path":"/docs/guide/cli/generator/generator#remote","headings":["Удалённый плагин (remote)"],"excerpt":"Удалённый плагин (remote) **Типичные сценарии для remote:** Централизованный сервис плагинов внутри компании (например, EasyP API Service). Запуск тяжёлых плагинов на выделенных машинах вместо CI‑агентов. Совместное испо","content":"Удалённый плагин (remote) **Типичные сценарии для remote:** Централизованный сервис плагинов внутри компании (например, EasyP API Service). Запуск тяжёлых плагинов на выделенных машинах вместо CI‑агентов. Совместное использование одной реализации плагина разными командами."},{"id":"cli/generator/generator::command::54","title":"Генератор","section":"Выполнение плагина через команду (command)","path":"/docs/guide/cli/generator/generator#command","headings":["Выполнение плагина через команду (command)"],"excerpt":"Выполнение плагина через команду (command) Вы можете указать плагин как массив команд для выполнения. Это полезно для запуска плагинов через go run или любые другие инструменты без предварительной установки бинарника пла","content":"Выполнение плагина через команду (command) Вы можете указать плагин как массив команд для выполнения. Это полезно для запуска плагинов через go run или любые другие инструменты без предварительной установки бинарника плагина:"},{"id":"cli/generator/generator::command::55","title":"Генератор","section":"Выполнение плагина через команду (command)","path":"/docs/guide/cli/generator/generator#command","headings":["Выполнение плагина через команду (command)"],"excerpt":"Выполнение плагина через команду (command)","content":"Выполнение плагина через команду (command)"},{"id":"cli/generator/generator::command::56","title":"Генератор","section":"Выполнение плагина через команду (command)","path":"/docs/guide/cli/generator/generator#command","headings":["Выполнение плагина через команду (command)"],"excerpt":"Выполнение плагина через команду (command) В этом режиме EasyP: **запускает указанную команду** как дочерний процесс; **пишет CodeGeneratorRequest в stdin** процесса; **читает CodeGeneratorResponse из stdout**, как и для","content":"Выполнение плагина через команду (command) В этом режиме EasyP: **запускает указанную команду** как дочерний процесс; **пишет CodeGeneratorRequest в stdin** процесса; **читает CodeGeneratorResponse из stdout**, как и для обычных плагинов protoc."},{"id":"cli/generator/generator::command::57","title":"Генератор","section":"Выполнение плагина через команду (command)","path":"/docs/guide/cli/generator/generator#command","headings":["Выполнение плагина через команду (command)"],"excerpt":"Выполнение плагина через команду (command) **Приоритет источников плагина:** command — выполнение через указанную команду (наивысший приоритет) remote — удалённый плагин через URL name — локальный плагин из PATH или встр","content":"Выполнение плагина через команду (command) **Приоритет источников плагина:** command — выполнение через указанную команду (наивысший приоритет) remote — удалённый плагин через URL name — локальный плагин из PATH или встроенный плагин path — путь к исполняемому файлу плагина"},{"id":"cli/generator/generator::command::58","title":"Генератор","section":"Выполнение плагина через команду (command)","path":"/docs/guide/cli/generator/generator#command","headings":["Выполнение плагина через команду (command)"],"excerpt":"Выполнение плагина через команду (command) **Параметры (источники и общие опции плагина):**","content":"Выполнение плагина через команду (command) **Параметры (источники и общие опции плагина):**"},{"id":"cli/generator/generator::command::59","title":"Генератор","section":"Выполнение плагина через команду (command)","path":"/docs/guide/cli/generator/generator#command","headings":["Выполнение плагина через команду (command)"],"excerpt":"Выполнение плагина через команду (command) Параметр Тип Обязателен По умолчанию Описание ---------- ----- ------------ -------------- ---------- name string ❌ - Имя / идентификатор плагина (например, go, go-grpc, grpc-ga","content":"Выполнение плагина через команду (command) Параметр Тип Обязателен По умолчанию Описание ---------- ----- ------------ -------------- ---------- name string ❌ - Имя / идентификатор плагина (например, go, go-grpc, grpc-gateway) command []string ❌ - Команда для выполнения плагина (например, [\"go\", \"run\", \"package\"]) remote string ❌ - URL удалённого плагина path string ❌ - Путь к исполняемому файлу плагина out string ✅ - Директория для сгенерированных файлов opts mapstring ❌ {} Специфичные опции плагина; значения-списки передаются как повторяющиеся key=value with_imports bool ❌ false Включать proto из зависимостей"},{"id":"cli/generator/generator::command::60","title":"Генератор","section":"Выполнение плагина через команду (command)","path":"/docs/guide/cli/generator/generator#command","headings":["Выполнение плагина через команду (command)"],"excerpt":"Выполнение плагина через команду (command) **Примечание:** Для каждого плагина должен быть указан ровно один источник (name, command, remote или path). Если opts.outputServices задан как [\"grpc-js\", \"generic-definitions\"","content":"Выполнение плагина через команду (command) **Примечание:** Для каждого плагина должен быть указан ровно один источник (name, command, remote или path). Если opts.outputServices задан как [\"grpc-js\", \"generic-definitions\"], EasyP передаст outputServices=grpc-js,outputServices=generic-definitions."},{"id":"cli/generator/generator::command::61","title":"Генератор","section":"Выполнение плагина через команду (command)","path":"/docs/guide/cli/generator/generator#command","headings":["Выполнение плагина через команду (command)"],"excerpt":"Выполнение плагина через команду (command) **Примеры использования источника command:**","content":"Выполнение плагина через команду (command) **Примеры использования источника command:**"},{"id":"cli/generator/generator::command::62","title":"Генератор","section":"Выполнение плагина через команду (command)","path":"/docs/guide/cli/generator/generator#command","headings":["Выполнение плагина через команду (command)"],"excerpt":"Выполнение плагина через команду (command) ```yaml generate: inputs: - directory: \"proto\"","content":"Выполнение плагина через команду (command) ```yaml generate: inputs: - directory: \"proto\""},{"id":"cli/generator/generator::command::63","title":"Генератор","section":"Выполнение плагина через команду (command)","path":"/docs/guide/cli/generator/generator#command","headings":["Выполнение плагина через команду (command)"],"excerpt":"Выполнение плагина через команду (command) plugins: # 1) gRPC-Gateway через go run (без предварительной установки бинарника) - command: [\"go\", \"run\", \"github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway@v2.","content":"Выполнение плагина через команду (command) plugins: # 1) gRPC-Gateway через go run (без предварительной установки бинарника) - 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::command::64","title":"Генератор","section":"Выполнение плагина через команду (command)","path":"/docs/guide/cli/generator/generator#command","headings":["Выполнение плагина через команду (command)"],"excerpt":"Выполнение плагина через команду (command) 2) protoc-gen-validate через go run - command: [\"go\", \"run\", \"github.com/bufbuild/protoc-gen-validate@v0.10.1\"] out: ./gen/go opts: paths: source_relative lang: go","content":"Выполнение плагина через команду (command) 2) protoc-gen-validate через 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::command::65","title":"Генератор","section":"Выполнение плагина через команду (command)","path":"/docs/guide/cli/generator/generator#command","headings":["Выполнение плагина через команду (command)"],"excerpt":"Выполнение плагина через команду (command) 3) Произвольный кастомный скрипт-обёртка - command: [\"bash\", \"./scripts/custom-protoc-plugin.sh\"] out: ./gen/custom opts: foo: bar ```","content":"Выполнение плагина через команду (command) 3) Произвольный кастомный скрипт-обёртка - command: [\"bash\", \"./scripts/custom-protoc-plugin.sh\"] out: ./gen/custom opts: foo: bar ```"},{"id":"cli/generator/generator::builtin-plugins::66","title":"Генератор","section":"Встроенные плагины (Builtin Plugins)","path":"/docs/guide/cli/generator/generator#builtin-plugins","headings":["Встроенные плагины (Builtin Plugins)"],"excerpt":"Встроенные плагины (Builtin Plugins) EasyP поддерживает встроенные плагины для базовых языков protobuf и gRPC. Эти плагины встроены в бинарник как WASM-модули и не требуют установки внешних зависимостей.","content":"Встроенные плагины (Builtin Plugins) EasyP поддерживает встроенные плагины для базовых языков protobuf и gRPC. Эти плагины встроены в бинарник как WASM-модули и не требуют установки внешних зависимостей."},{"id":"cli/generator/generator::builtin-plugins::67","title":"Генератор","section":"Встроенные плагины (Builtin Plugins)","path":"/docs/guide/cli/generator/generator#builtin-plugins","headings":["Встроенные плагины (Builtin Plugins)"],"excerpt":"Встроенные плагины (Builtin Plugins) **Преимущества встроенных плагинов:** **Портативность**: Один бинарник со всеми необходимыми плагинами **Удобство**: Не требуется установка внешних зависимостей **Стабильность**: Верс","content":"Встроенные плагины (Builtin Plugins) **Преимущества встроенных плагинов:** **Портативность**: Один бинарник со всеми необходимыми плагинами **Удобство**: Не требуется установка внешних зависимостей **Стабильность**: Версии плагинов зафиксированы в бинарнике **Изоляция**: Не зависит от системных установок плагинов"},{"id":"cli/generator/generator::builtin-plugins::68","title":"Генератор","section":"Встроенные плагины (Builtin Plugins)","path":"/docs/guide/cli/generator/generator#builtin-plugins","headings":["Встроенные плагины (Builtin Plugins)"],"excerpt":"Встроенные плагины (Builtin Plugins) **Поддерживаемые встроенные плагины:**","content":"Встроенные плагины (Builtin Plugins) **Поддерживаемые встроенные плагины:**"},{"id":"cli/generator/generator::protobuf::69","title":"Генератор","section":"Protobuf базовые плагины","path":"/docs/guide/cli/generator/generator#protobuf","headings":["Protobuf базовые плагины"],"excerpt":"Protobuf базовые плагины Следующие плагины встроены для генерации базового protobuf кода:","content":"Protobuf базовые плагины Следующие плагины встроены для генерации базового protobuf кода:"},{"id":"cli/generator/generator::protobuf::70","title":"Генератор","section":"Protobuf базовые плагины","path":"/docs/guide/cli/generator/generator#protobuf","headings":["Protobuf базовые плагины"],"excerpt":"Protobuf базовые плагины Имя плагина Описание Соответствующий protoc плагин ------------- ---------- ------------------------------- cpp Генерация C++ кода из proto файлов protoc-gen-cpp csharp Генерация C# кода из proto","content":"Protobuf базовые плагины Имя плагина Описание Соответствующий protoc плагин ------------- ---------- ------------------------------- cpp Генерация C++ кода из proto файлов protoc-gen-cpp csharp Генерация C# кода из proto файлов protoc-gen-csharp java Генерация Java кода из proto файлов protoc-gen-java kotlin Генерация Kotlin кода из proto файлов protoc-gen-kotlin objc Генерация Objective-C кода из proto файлов protoc-gen-objc php Генерация PHP кода из proto файлов protoc-gen-php python Генерация Python кода из proto файлов protoc-gen-python ruby Генерация Ruby кода из proto файлов protoc-gen-ruby"},{"id":"cli/generator/generator::grpc::71","title":"Генератор","section":"gRPC плагины","path":"/docs/guide/cli/generator/generator#grpc","headings":["gRPC плагины"],"excerpt":"gRPC плагины Следующие плагины встроены для генерации gRPC кода:","content":"gRPC плагины Следующие плагины встроены для генерации gRPC кода:"},{"id":"cli/generator/generator::grpc::72","title":"Генератор","section":"gRPC плагины","path":"/docs/guide/cli/generator/generator#grpc","headings":["gRPC плагины"],"excerpt":"gRPC плагины Имя плагина Описание Соответствующий protoc плагин ------------- ---------- ------------------------------- grpc_cpp Генерация gRPC кода для C++ grpc_cpp_plugin grpc_csharp Генерация gRPC кода для C# grpc_cs","content":"gRPC плагины Имя плагина Описание Соответствующий protoc плагин ------------- ---------- ------------------------------- grpc_cpp Генерация gRPC кода для C++ grpc_cpp_plugin grpc_csharp Генерация gRPC кода для C# grpc_csharp_plugin grpc_java Генерация gRPC кода для Java grpc_java_plugin grpc_node Генерация gRPC кода для Node.js grpc_node_plugin grpc_objc Генерация gRPC кода для Objective-C grpc_objective_c_plugin grpc_php Генерация gRPC кода для PHP grpc_php_plugin grpc_python Генерация gRPC кода для Python grpc_python_plugin grpc_ruby Генерация gRPC кода для Ruby grpc_ruby_plugin"},{"id":"cli/generator/generator::grpc::73","title":"Генератор","section":"gRPC плагины","path":"/docs/guide/cli/generator/generator#grpc","headings":["gRPC плагины"],"excerpt":"gRPC плагины **Логика выбора плагина:**","content":"gRPC плагины **Логика выбора плагина:**"},{"id":"cli/generator/generator::grpc::74","title":"Генератор","section":"gRPC плагины","path":"/docs/guide/cli/generator/generator#grpc","headings":["gRPC плагины"],"excerpt":"gRPC плагины EasyP использует следующий приоритет при выборе executor'а для плагина:","content":"gRPC плагины EasyP использует следующий приоритет при выборе executor'а для плагина:"},{"id":"cli/generator/generator::grpc::75","title":"Генератор","section":"gRPC плагины","path":"/docs/guide/cli/generator/generator#grpc","headings":["gRPC плагины"],"excerpt":"gRPC плагины **Удалённый плагин** (если указан url) — всегда имеет наивысший приоритет **Встроенный плагин** (если плагин встроен и не найден в PATH) — используется автоматически **Локальный плагин** (из PATH) — использу","content":"gRPC плагины **Удалённый плагин** (если указан url) — всегда имеет наивысший приоритет **Встроенный плагин** (если плагин встроен и не найден в PATH) — используется автоматически **Локальный плагин** (из PATH) — используется по умолчанию для обратной совместимости"},{"id":"cli/generator/generator::grpc::76","title":"Генератор","section":"gRPC плагины","path":"/docs/guide/cli/generator/generator#grpc","headings":["gRPC плагины"],"excerpt":"gRPC плагины **Пример использования:**","content":"gRPC плагины **Пример использования:**"},{"id":"cli/generator/generator::grpc::77","title":"Генератор","section":"gRPC плагины","path":"/docs/guide/cli/generator/generator#grpc","headings":["gRPC плагины"],"excerpt":"gRPC плагины Встроенные плагины включены в бинарник EasyP:","content":"gRPC плагины Встроенные плагины включены в бинарник EasyP:"},{"id":"cli/generator/generator::grpc::78","title":"Генератор","section":"gRPC плагины","path":"/docs/guide/cli/generator/generator#grpc","headings":["gRPC плагины"],"excerpt":"gRPC плагины ```bash Сборка go build ./cmd/easyp","content":"gRPC плагины ```bash Сборка go build ./cmd/easyp"},{"id":"cli/generator/generator::grpc::79","title":"Генератор","section":"gRPC плагины","path":"/docs/guide/cli/generator/generator#grpc","headings":["gRPC плагины"],"excerpt":"gRPC плагины Установка go install github.com/easyp-tech/easyp/cmd/easyp@latest ```","content":"gRPC плагины Установка go install github.com/easyp-tech/easyp/cmd/easyp@latest ```"},{"id":"cli/generator/generator::grpc::80","title":"Генератор","section":"gRPC плагины","path":"/docs/guide/cli/generator/generator#grpc","headings":["gRPC плагины"],"excerpt":"gRPC плагины **Обратная совместимость:**","content":"gRPC плагины **Обратная совместимость:**"},{"id":"cli/generator/generator::grpc::81","title":"Генератор","section":"gRPC плагины","path":"/docs/guide/cli/generator/generator#grpc","headings":["gRPC плагины"],"excerpt":"gRPC плагины Встроенные плагины полностью совместимы с существующими конфигурациями. Если плагин найден в PATH, он будет использован вместо встроенного. Это гарантирует, что:","content":"gRPC плагины Встроенные плагины полностью совместимы с существующими конфигурациями. Если плагин найден в PATH, он будет использован вместо встроенного. Это гарантирует, что:"},{"id":"cli/generator/generator::grpc::82","title":"Генератор","section":"gRPC плагины","path":"/docs/guide/cli/generator/generator#grpc","headings":["gRPC плагины"],"excerpt":"gRPC плагины Существующие конфигурации продолжают работать без изменений Можно переопределить встроенный плагин, установив его в системе Приоритет отдаётся локальным установкам для гибкости","content":"gRPC плагины Существующие конфигурации продолжают работать без изменений Можно переопределить встроенный плагин, установив его в системе Приоритет отдаётся локальным установкам для гибкости"},{"id":"cli/generator/generator::top::83","title":"Генератор","section":"Справочник опций плагинов","path":"/docs/guide/cli/generator/generator","headings":["Справочник опций плагинов"],"excerpt":"Справочник опций плагинов Ниже перечислены наиболее часто используемые плагины и их настройки. Каждый плагин имеет параметры, влияющие на результат генерации — понимание этих опций важно для получения нужного вывода.","content":"Справочник опций плагинов Ниже перечислены наиболее часто используемые плагины и их настройки. Каждый плагин имеет параметры, влияющие на результат генерации — понимание этих опций важно для получения нужного вывода."},{"id":"cli/generator/generator::go-plugins::84","title":"Генератор","section":"Go Plugins","path":"/docs/guide/cli/generator/generator#go-plugins","headings":["Go Plugins"],"excerpt":"Go Plugins Плагины для Go — самые зрелые и распространённые. Опция paths управляет тем, как формируются пути импортов; остальные опции дают тонкую настройку вывода.","content":"Go Plugins Плагины для Go — самые зрелые и распространённые. Опция paths управляет тем, как формируются пути импортов; остальные опции дают тонкую настройку вывода."},{"id":"cli/generator/generator::grpc-gateway-plugins::85","title":"Генератор","section":"gRPC-Gateway Plugins","path":"/docs/guide/cli/generator/generator#grpc-gateway-plugins","headings":["gRPC-Gateway Plugins"],"excerpt":"gRPC-Gateway Plugins Позволяют экспонировать gRPC сервисы как REST API и генерировать OpenAPI. Критично для HTTP/JSON поверх gRPC.","content":"gRPC-Gateway Plugins Позволяют экспонировать gRPC сервисы как REST API и генерировать OpenAPI. Критично для HTTP/JSON поверх gRPC."},{"id":"cli/generator/generator::validation-plugins::86","title":"Генератор","section":"Validation Plugins","path":"/docs/guide/cli/generator/generator#validation-plugins","headings":["Validation Plugins"],"excerpt":"Validation Plugins Генерируют код валидации на основе правил в proto, устраняя ручную проверку.","content":"Validation Plugins Генерируют код валидации на основе правил в proto, устраняя ручную проверку."},{"id":"cli/generator/generator::typescriptjavascript-plugins::87","title":"Генератор","section":"TypeScript/JavaScript Plugins","path":"/docs/guide/cli/generator/generator#typescriptjavascript-plugins","headings":["TypeScript/JavaScript Plugins"],"excerpt":"TypeScript/JavaScript Plugins TypeScript плагины нужны фронтенду: типобезопасные интерфейсы и клиенты.","content":"TypeScript/JavaScript Plugins TypeScript плагины нужны фронтенду: типобезопасные интерфейсы и клиенты."},{"id":"cli/generator/generator::managed-mode::88","title":"Генератор","section":"Managed Mode","path":"/docs/guide/cli/generator/generator#managed-mode","headings":["Managed Mode"],"excerpt":"Managed Mode Managed mode автоматически устанавливает file и field опции в protobuf дескрипторах во время генерации кода без изменения исходных .proto файлов. Эта функция совместима с managed mode в buf и обеспечивает ед","content":"Managed Mode Managed mode автоматически устанавливает file и field опции в protobuf дескрипторах во время генерации кода без изменения исходных .proto файлов. Эта функция совместима с managed mode в buf и обеспечивает единообразный способ управления языково-специфичными опциями в вашей кодовой базе."},{"id":"cli/generator/generator::managed-mode::89","title":"Генератор","section":"Managed Mode","path":"/docs/guide/cli/generator/generator#managed-mode","headings":["Managed Mode"],"excerpt":"Managed Mode **Ключевые преимущества:** **Без изменений proto файлов**: Опции применяются во время генерации, proto файлы остаются чистыми **Согласованные значения по умолчанию**: Автоматическое применение языковых согла","content":"Managed Mode **Ключевые преимущества:** **Без изменений proto файлов**: Опции применяются во время генерации, proto файлы остаются чистыми **Согласованные значения по умолчанию**: Автоматическое применение языковых соглашений об именовании **Централизованная конфигурация**: Управление всеми опциями в одном месте (easyp.yaml) **Правила для модулей**: Применение разных опций к разным модулям или путям **Совместимость с buf**: Работает так же, как managed mode в buf"},{"id":"cli/generator/generator::top::90","title":"Генератор","section":"Как это работает","path":"/docs/guide/cli/generator/generator","headings":["Как это работает"],"excerpt":"Как это работает Когда managed mode включён, EasyP автоматически применяет file и field опции к protobuf дескрипторам перед генерацией кода. Это происходит в памяти, поэтому исходные .proto файлы остаются неизменными.","content":"Как это работает Когда managed mode включён, EasyP автоматически применяет file и field опции к protobuf дескрипторам перед генерацией кода. Это происходит в памяти, поэтому исходные .proto файлы остаются неизменными."},{"id":"cli/generator/generator::top::91","title":"Генератор","section":"Как это работает","path":"/docs/guide/cli/generator/generator","headings":["Как это работает"],"excerpt":"Как это работает **Значения по умолчанию** применяются для определённых опций на основе языковых соглашений: Java: java_package_prefix по умолчанию \"com\", java_multiple_files по умолчанию true C#: csharp_namespace по умо","content":"Как это работает **Значения по умолчанию** применяются для определённых опций на основе языковых соглашений: Java: java_package_prefix по умолчанию \"com\", java_multiple_files по умолчанию true C#: csharp_namespace по умолчанию PascalCase имени пакета Ruby: ruby_package по умолчанию PascalCase с разделителем :: PHP: php_namespace по умолчанию PascalCase с разделителем \\ Objective-C: objc_class_prefix по умолчанию первые буквы частей пакета C++: cc_enable_arenas по умолчанию true"},{"id":"cli/generator/generator::top::92","title":"Генератор","section":"Как это работает","path":"/docs/guide/cli/generator/generator","headings":["Как это работает"],"excerpt":"Как это работает **Overrides** позволяют установить конкретные значения для опций с поддержкой фильтрации по модулю, пути или полю.","content":"Как это работает **Overrides** позволяют установить конкретные значения для опций с поддержкой фильтрации по модулю, пути или полю."},{"id":"cli/generator/generator::top::93","title":"Генератор","section":"Как это работает","path":"/docs/guide/cli/generator/generator","headings":["Как это работает"],"excerpt":"Как это работает **Disables** позволяют предотвратить изменение managed mode определённых опций или файлов.","content":"Как это работает **Disables** позволяют предотвратить изменение managed mode определённых опций или файлов."},{"id":"cli/generator/generator::file-options::94","title":"Генератор","section":"Поддерживаемые File Options","path":"/docs/guide/cli/generator/generator#file-options","headings":["Поддерживаемые File Options"],"excerpt":"Поддерживаемые File Options Опция Описание Есть значение по умолчанию? ------- ---------- ---------------------------- go_package Go import path ❌ go_package_prefix Префикс для Go import paths ❌ java_package Имя Java пак","content":"Поддерживаемые File Options Опция Описание Есть значение по умолчанию? ------- ---------- ---------------------------- go_package Go import path ❌ go_package_prefix Префикс для Go import paths ❌ java_package Имя Java пакета ❌ java_package_prefix Префикс для Java пакетов ✅ (\"com\") java_package_suffix Суффикс для Java пакетов ❌ java_multiple_files Генерировать несколько Java файлов ✅ (true) java_outer_classname Имя внешнего класса ✅ (PascalCase + \"Proto\") java_string_check_utf8 UTF-8 валидация ❌ csharp_namespace C# namespace ✅ (PascalCase) csharp_namespace_prefix Префикс для C# namespaces ❌ ruby_package Имя Ruby модуля ✅ (PascalCase с ::) ruby_package_suffix Суффикс для Ruby пакетов ❌ php_namespace PHP namespace ✅ (PascalCase с \\) php_metadata_namespace PHP metadata namespace ❌ php_metadata_namespace_suffix Суффикс для PHP metadata ❌ objc_class_prefix Objective-C префикс класса ✅ (Первые буквы) swift_prefix Swift префикс ❌ optimize_for Оптимизация генерации кода ❌ cc_enable_arenas C++ arena аллокация ✅ (true)"},{"id":"cli/generator/generator::field-options::95","title":"Генератор","section":"Поддерживаемые Field Options","path":"/docs/guide/cli/generator/generator#field-options","headings":["Поддерживаемые Field Options"],"excerpt":"Поддерживаемые Field Options Опция Описание Применяется к ------- ---------- --------------- jstype JavaScript тип для 64-битных целых чисел int64, uint64, sint64, fixed64, sfixed64","content":"Поддерживаемые Field Options Опция Описание Применяется к ------- ---------- --------------- jstype JavaScript тип для 64-битных целых чисел int64, uint64, sint64, fixed64, sfixed64"},{"id":"cli/generator/generator::top::96","title":"Генератор","section":"Базовая настройка со значениями по умолчанию","path":"/docs/guide/cli/generator/generator","headings":["Базовая настройка со значениями по умолчанию"],"excerpt":"Базовая настройка со значениями по умолчанию Включите managed mode для получения автоматических значений по умолчанию для всех поддерживаемых языков:","content":"Базовая настройка со значениями по умолчанию Включите managed mode для получения автоматических значений по умолчанию для всех поддерживаемых языков:"},{"id":"cli/generator/generator::top::97","title":"Генератор","section":"Базовая настройка со значениями по умолчанию","path":"/docs/guide/cli/generator/generator","headings":["Базовая настройка со значениями по умолчанию"],"excerpt":"Базовая настройка со значениями по умолчанию","content":"Базовая настройка со значениями по умолчанию"},{"id":"cli/generator/generator::top::98","title":"Генератор","section":"Базовая настройка со значениями по умолчанию","path":"/docs/guide/cli/generator/generator","headings":["Базовая настройка со значениями по умолчанию"],"excerpt":"Базовая настройка со значениями по умолчанию Это автоматически установит: java_package в com. для всех файлов java_multiple_files в true csharp_namespace в PascalCase имени пакета ruby_package в PascalCase с разделителем","content":"Базовая настройка со значениями по умолчанию Это автоматически установит: java_package в com. для всех файлов java_multiple_files в true csharp_namespace в PascalCase имени пакета ruby_package в PascalCase с разделителем :: И многое другое..."},{"id":"cli/generator/generator::go::99","title":"Генератор","section":"Кастомный префикс Go пакета","path":"/docs/guide/cli/generator/generator#go","headings":["Кастомный префикс Go пакета"],"excerpt":"Кастомный префикс Go пакета Переопределите префикс Go пакета для вашего проекта:","content":"Кастомный префикс Go пакета Переопределите префикс Go пакета для вашего проекта:"},{"id":"cli/generator/generator::go::100","title":"Генератор","section":"Кастомный префикс Go пакета","path":"/docs/guide/cli/generator/generator#go","headings":["Кастомный префикс Go пакета"],"excerpt":"Кастомный префикс Go пакета Это установит go_package в github.com/mycompany/myproject/gen/go/ для всех файлов.","content":"Кастомный префикс Go пакета Это установит go_package в github.com/mycompany/myproject/gen/go/ для всех файлов."},{"id":"cli/generator/generator::go::101","title":"Генератор","section":"Динамические пути Go пакетов с маркерами","path":"/docs/guide/cli/generator/generator#go","headings":["Динамические пути Go пакетов с маркерами"],"excerpt":"Динамические пути Go пакетов с маркерами Для более сложной генерации путей можно использовать маркеры в значениях go_package_prefix или go_package:","content":"Динамические пути Go пакетов с маркерами Для более сложной генерации путей можно использовать маркеры в значениях go_package_prefix или go_package:"},{"id":"cli/generator/generator::go::102","title":"Генератор","section":"Динамические пути Go пакетов с маркерами","path":"/docs/guide/cli/generator/generator#go","headings":["Динамические пути Go пакетов с маркерами"],"excerpt":"Динамические пути Go пакетов с маркерами","content":"Динамические пути Go пакетов с маркерами"},{"id":"cli/generator/generator::go::103","title":"Генератор","section":"Динамические пути Go пакетов с маркерами","path":"/docs/guide/cli/generator/generator#go","headings":["Динамические пути Go пакетов с маркерами"],"excerpt":"Динамические пути Go пакетов с маркерами **Доступные маркеры:** {{file_path}} - Полный путь файла без расширения .proto - Пример: internal/cms/as.proto → internal/cms/as {{file_dir}} - Только путь директории, без имени ф","content":"Динамические пути Go пакетов с маркерами **Доступные маркеры:** {{file_path}} - Полный путь файла без расширения .proto - Пример: internal/cms/as.proto → internal/cms/as {{file_dir}} - Только путь директории, без имени файла - Пример: internal/cms/as.proto → internal/cms {{file_dir_without:prefix/}} - Путь директории с удалением префикса и базового имени файла без суффиксов _service/_grpc - Пример: {{file_dir_without:internal/}} для internal/cms/as_service.proto → cms/as {{file_path_without:prefix/}} - Полный путь файла с удалением префикса - Пример: {{file_path_without:internal/}} для internal/cms/as.proto → cms/as"},{"id":"cli/generator/generator::top::104","title":"Генератор","section":"Переопределения для конкретных модулей","path":"/docs/guide/cli/generator/generator","headings":["Переопределения для конкретных модулей"],"excerpt":"Переопределения для конкретных модулей Примените разные опции к разным модулям:","content":"Переопределения для конкретных модулей Примените разные опции к разным модулям:"},{"id":"cli/generator/generator::top::105","title":"Генератор","section":"Переопределения для конкретных модулей","path":"/docs/guide/cli/generator/generator","headings":["Переопределения для конкретных модулей"],"excerpt":"Переопределения для конкретных модулей","content":"Переопределения для конкретных модулей"},{"id":"cli/generator/generator::top::106","title":"Генератор","section":"Отключение для внешних зависимостей","path":"/docs/guide/cli/generator/generator","headings":["Отключение для внешних зависимостей"],"excerpt":"Отключение для внешних зависимостей Отключите managed mode для внешних зависимостей, у которых уже установлены опции:","content":"Отключение для внешних зависимостей Отключите managed mode для внешних зависимостей, у которых уже установлены опции:"},{"id":"cli/generator/generator::top::107","title":"Генератор","section":"Отключение для внешних зависимостей","path":"/docs/guide/cli/generator/generator","headings":["Отключение для внешних зависимостей"],"excerpt":"Отключение для внешних зависимостей","content":"Отключение для внешних зависимостей"},{"id":"cli/generator/generator::javascript::108","title":"Генератор","section":"Типобезопасность JavaScript","path":"/docs/guide/cli/generator/generator#javascript","headings":["Типобезопасность JavaScript"],"excerpt":"Типобезопасность JavaScript Установите jstype в JS_STRING для всех 64-битных целочисленных полей, чтобы предотвратить потерю точности в JavaScript:","content":"Типобезопасность JavaScript Установите jstype в JS_STRING для всех 64-битных целочисленных полей, чтобы предотвратить потерю точности в JavaScript:"},{"id":"cli/generator/generator::top::109","title":"Генератор","section":"Совпадение путей","path":"/docs/guide/cli/generator/generator","headings":["Совпадение путей"],"excerpt":"Совпадение путей Совпадение путей в managed mode использует префиксное совпадение (как в buf):","content":"Совпадение путей Совпадение путей в managed mode использует префиксное совпадение (как в buf):"},{"id":"cli/generator/generator::top::110","title":"Генератор","section":"Совпадение путей","path":"/docs/guide/cli/generator/generator","headings":["Совпадение путей"],"excerpt":"Совпадение путей **Путь директории** (заканчивается на /): Совпадает со всеми файлами в этой директории и поддиректориях - Пример: path: \"internal/cms/\" совпадает с internal/cms/as.proto, internal/cms/node.proto, interna","content":"Совпадение путей **Путь директории** (заканчивается на /): Совпадает со всеми файлами в этой директории и поддиректориях - Пример: path: \"internal/cms/\" совпадает с internal/cms/as.proto, internal/cms/node.proto, internal/cms/v1/service.proto **Точный путь файла** (заканчивается на .proto): Совпадает только с этим конкретным файлом - Пример: path: \"internal/cms/as.proto\" совпадает только с internal/cms/as.proto **Префиксный путь** (без завершающего / или .proto): Использует префиксное совпадение (не директориально-осознанное) - Пример: path: \"internal/cms\" совпадает с internal/cms/as.proto, но также с internal/cmsv2/file.proto - **Совет**: Используйте префиксные пути для группировки нескольких файлов с одинаковым значением. Например, path: \"internal/cms/bmi\" совпадает и с internal/cms/bmi.proto, и с internal/cms/bmi_service.proto, что позволяет установить одно и то же значение go_package для обоих файлов одним правилом."},{"id":"cli/generator/generator::top::111","title":"Генератор","section":"Приоритет правил","path":"/docs/guide/cli/generator/generator","headings":["Приоритет правил"],"excerpt":"Приоритет правил Когда несколько правил соответствуют одному файлу или полю, применяется следующий приоритет:","content":"Приоритет правил Когда несколько правил соответствуют одному файлу или полю, применяется следующий приоритет:"},{"id":"cli/generator/generator::top::112","title":"Генератор","section":"Приоритет правил","path":"/docs/guide/cli/generator/generator","headings":["Приоритет правил"],"excerpt":"Приоритет правил **Disable правила** имеют приоритет — если опция отключена, она не будет применена **Override правила** применяются по порядку — последнее совпадающее правило побеждает **Значения по умолчанию** применяю","content":"Приоритет правил **Disable правила** имеют приоритет — если опция отключена, она не будет применена **Override правила** применяются по порядку — последнее совпадающее правило побеждает **Значения по умолчанию** применяются только если нет совпадающего override и опция не отключена"},{"id":"cli/generator/generator::buf::113","title":"Генератор","section":"Совместимость с buf","path":"/docs/guide/cli/generator/generator#buf","headings":["Совместимость с buf"],"excerpt":"Совместимость с buf Managed mode в EasyP совместим с managed mode в buf. Тот же формат конфигурации и поведение применяются, что упрощает миграцию между инструментами или использование обоих в одном workflow.","content":"Совместимость с buf Managed mode в EasyP совместим с managed mode в buf. Тот же формат конфигурации и поведение применяются, что упрощает миграцию между инструментами или использование обоих в одном workflow."},{"id":"cli/generator/generator::descriptor-set::114","title":"Генератор","section":"Генерация Descriptor Set","path":"/docs/guide/cli/generator/generator#descriptor-set","headings":["Генерация Descriptor Set"],"excerpt":"Генерация Descriptor Set **https://protobuf.dev/programming-guides/techniques/#self-description**","content":"Генерация Descriptor Set **https://protobuf.dev/programming-guides/techniques/#self-description**"},{"id":"cli/generator/generator::descriptor-set::115","title":"Генератор","section":"Генерация Descriptor Set","path":"/docs/guide/cli/generator/generator#descriptor-set","headings":["Генерация Descriptor Set"],"excerpt":"Генерация Descriptor Set EasyP поддерживает генерацию бинарных FileDescriptorSet файлов с помощью флага --descriptor_set_out. Это позволяет создавать самоописывающиеся protobuf сообщения, которые включают информацию о сх","content":"Генерация Descriptor Set EasyP поддерживает генерацию бинарных FileDescriptorSet файлов с помощью флага --descriptor_set_out. Это позволяет создавать самоописывающиеся protobuf сообщения, которые включают информацию о схеме вместе с данными."},{"id":"cli/generator/generator::descriptor-set::116","title":"Генератор","section":"Генерация Descriptor Set","path":"/docs/guide/cli/generator/generator#descriptor-set","headings":["Генерация Descriptor Set"],"excerpt":"Генерация Descriptor Set **Флаги CLI:**","content":"Генерация Descriptor Set **Флаги CLI:**"},{"id":"cli/generator/generator::descriptor-set::117","title":"Генератор","section":"Генерация Descriptor Set","path":"/docs/guide/cli/generator/generator#descriptor-set","headings":["Генерация Descriptor Set"],"excerpt":"Генерация Descriptor Set --descriptor_set_out - Путь для вывода бинарного FileDescriptorSet --include_imports - Включить все транзитивные зависимости в FileDescriptorSet","content":"Генерация Descriptor Set --descriptor_set_out - Путь для вывода бинарного FileDescriptorSet --include_imports - Включить все транзитивные зависимости в FileDescriptorSet"},{"id":"cli/generator/generator::descriptor-set::118","title":"Генератор","section":"Генерация Descriptor Set","path":"/docs/guide/cli/generator/generator#descriptor-set","headings":["Генерация Descriptor Set"],"excerpt":"Генерация Descriptor Set **Пример:**","content":"Генерация Descriptor Set **Пример:**"},{"id":"cli/generator/generator::descriptor-set::119","title":"Генератор","section":"Генерация Descriptor Set","path":"/docs/guide/cli/generator/generator#descriptor-set","headings":["Генерация Descriptor Set"],"excerpt":"Генерация Descriptor Set ```bash Генерация descriptor set только с целевыми файлами easyp generate --descriptor_set_out=./schema.pb","content":"Генерация Descriptor Set ```bash Генерация descriptor set только с целевыми файлами easyp generate --descriptor_set_out=./schema.pb"},{"id":"cli/generator/generator::descriptor-set::120","title":"Генератор","section":"Генерация Descriptor Set","path":"/docs/guide/cli/generator/generator#descriptor-set","headings":["Генерация Descriptor Set"],"excerpt":"Генерация Descriptor Set Генерация descriptor set со всеми зависимостями easyp generate --descriptor_set_out=./schema.pb --include_imports ```","content":"Генерация Descriptor Set Генерация descriptor set со всеми зависимостями easyp generate --descriptor_set_out=./schema.pb --include_imports ```"},{"id":"cli/generator/generator::descriptor-set::121","title":"Генератор","section":"Генерация Descriptor Set","path":"/docs/guide/cli/generator/generator#descriptor-set","headings":["Генерация Descriptor Set"],"excerpt":"Генерация Descriptor Set Самоописывающиеся сообщения полезны для динамического парсинга сообщений, валидации схемы во время выполнения, реестров схем и создания универсальных gRPC клиентов. Для получения дополнительной и","content":"Генерация Descriptor Set Самоописывающиеся сообщения полезны для динамического парсинга сообщений, валидации схемы во время выполнения, реестров схем и создания универсальных gRPC клиентов. Для получения дополнительной информации см. документацию Protocol Buffers о самоописании."},{"id":"cli/generator/generator::top::122","title":"Генератор","section":"Интеграция с менеджером пакетов","path":"/docs/guide/cli/generator/generator","headings":["Интеграция с менеджером пакетов"],"excerpt":"Интеграция с менеджером пакетов Одной из самых мощных возможностей EasyP является бесшовная интеграция генератора кода с менеджером пакетов. Это устраняет проблему ручного управления proto‑зависимостями и гарантирует, чт","content":"Интеграция с менеджером пакетов Одной из самых мощных возможностей EasyP является бесшовная интеграция генератора кода с менеджером пакетов. Это устраняет проблему ручного управления proto‑зависимостями и гарантирует, что при генерации используются корректные (зафиксированные) версии импортируемых файлов."},{"id":"cli/generator/generator::top::123","title":"Генератор","section":"Интеграция с менеджером пакетов","path":"/docs/guide/cli/generator/generator","headings":["Интеграция с менеджером пакетов"],"excerpt":"Интеграция с менеджером пакетов **Ключевые преимущества:** **Автоматическое разрешение зависимостей**: не нужно вручную прописывать пути импортов **Согласованность версий**: фиксация в easyp.lock гарантирует воспроизводи","content":"Интеграция с менеджером пакетов **Ключевые преимущества:** **Автоматическое разрешение зависимостей**: не нужно вручную прописывать пути импортов **Согласованность версий**: фиксация в easyp.lock гарантирует воспроизводимость **Транзитивные зависимости**: вложенные цепочки подтягиваются автоматически **Производительность**: локальный кеш — скачивание один раз и повторное использование"},{"id":"cli/generator/generator::top::124","title":"Генератор","section":"Автоматическое разрешение зависимостей","path":"/docs/guide/cli/generator/generator","headings":["Автоматическое разрешение зависимостей"],"excerpt":"Автоматическое разрешение зависимостей Когда вы указываете зависимости в секции deps, генератор автоматически добавляет их в путь импортов. Ваши proto‑файлы могут делать стандартные import из этих зависимостей без дополн","content":"Автоматическое разрешение зависимостей Когда вы указываете зависимости в секции deps, генератор автоматически добавляет их в путь импортов. Ваши proto‑файлы могут делать стандартные import из этих зависимостей без дополнительной настройки."},{"id":"cli/generator/generator::top::125","title":"Генератор","section":"Автоматическое разрешение зависимостей","path":"/docs/guide/cli/generator/generator","headings":["Автоматическое разрешение зависимостей"],"excerpt":"Автоматическое разрешение зависимостей **Как это работает:** EasyP скачивает и кеширует зависимости из deps Во время генерации кешированные файлы автоматически добавляются в import‑path protoc Ваши proto‑файлы используют","content":"Автоматическое разрешение зависимостей **Как это работает:** EasyP скачивает и кеширует зависимости из deps Во время генерации кешированные файлы автоматически добавляются в import‑path protoc Ваши proto‑файлы используют обычные import строки для обращения к зависимостям При with_imports: true в вывод попадают и локальные файлы, и файлы зависимостей"},{"id":"cli/generator/generator::top::126","title":"Генератор","section":"Автоматическое разрешение зависимостей","path":"/docs/guide/cli/generator/generator","headings":["Автоматическое разрешение зависимостей"],"excerpt":"Автоматическое разрешение зависимостей Ниже простой пример — зависимости указываются один раз в deps, далее они доступны при генерации автоматически:","content":"Автоматическое разрешение зависимостей Ниже простой пример — зависимости указываются один раз в deps, далее они доступны при генерации автоматически:"},{"id":"cli/generator/generator::top::127","title":"Генератор","section":"Автоматическое разрешение зависимостей","path":"/docs/guide/cli/generator/generator","headings":["Автоматическое разрешение зависимостей"],"excerpt":"Автоматическое разрешение зависимостей ```yaml deps: - github.com/googleapis/googleapis@common-protos-1_3_1 - github.com/grpc-ecosystem/grpc-gateway@v2.19.1","content":"Автоматическое разрешение зависимостей ```yaml deps: - github.com/googleapis/googleapis@common-protos-1_3_1 - github.com/grpc-ecosystem/grpc-gateway@v2.19.1"},{"id":"cli/generator/generator::top::128","title":"Генератор","section":"Автоматическое разрешение зависимостей","path":"/docs/guide/cli/generator/generator","headings":["Автоматическое разрешение зависимостей"],"excerpt":"Автоматическое разрешение зависимостей generate: inputs: - directory: \"proto\" plugins: - name: go out: ./gen/go opts: paths: source_relative with_imports: true # This automatically includes googleapis and grpc-gateway pr","content":"Автоматическое разрешение зависимостей 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::top::129","title":"Генератор","section":"Примеры использования зависимостей","path":"/docs/guide/cli/generator/generator","headings":["Примеры использования зависимостей"],"excerpt":"Примеры использования зависимостей Ниже показаны распространённые способы интеграции внешних proto‑зависимостей в процесс генерации.","content":"Примеры использования зависимостей Ниже показаны распространённые способы интеграции внешних proto‑зависимостей в процесс генерации."},{"id":"cli/generator/generator::google-apis::130","title":"Генератор","section":"Использование Google APIs","path":"/docs/guide/cli/generator/generator#google-apis","headings":["Использование Google APIs"],"excerpt":"Использование Google APIs Google APIs — одна из самых популярных коллекций зависимостей: стандартные типы, аннотации для REST, проверки и общие структуры данных.","content":"Использование Google APIs Google APIs — одна из самых популярных коллекций зависимостей: стандартные типы, аннотации для REST, проверки и общие структуры данных."},{"id":"cli/generator/generator::google-apis::131","title":"Генератор","section":"Использование Google APIs","path":"/docs/guide/cli/generator/generator#google-apis","headings":["Использование Google APIs"],"excerpt":"Использование Google APIs **Когда использовать Google APIs:** Построение REST поверх gRPC (gRPC-Gateway) Нужны стандартные типы (Timestamp, Duration, Any) Требуются аннотации поведения полей (field behavior) Интеграция с","content":"Использование Google APIs **Когда использовать Google APIs:** Построение REST поверх gRPC (gRPC-Gateway) Нужны стандартные типы (Timestamp, Duration, Any) Требуются аннотации поведения полей (field behavior) Интеграция с сервисами Google Cloud"},{"id":"cli/generator/generator::google-apis::132","title":"Генератор","section":"Использование Google APIs","path":"/docs/guide/cli/generator/generator#google-apis","headings":["Использование Google APIs"],"excerpt":"Использование Google APIs Минимальная конфигурация для подключения Google APIs:","content":"Использование Google APIs Минимальная конфигурация для подключения Google APIs:"},{"id":"cli/generator/generator::google-apis::133","title":"Генератор","section":"Использование Google APIs","path":"/docs/guide/cli/generator/generator#google-apis","headings":["Использование Google APIs"],"excerpt":"Использование Google APIs ```yaml deps: - github.com/googleapis/googleapis@common-protos-1_3_1","content":"Использование Google APIs ```yaml deps: - github.com/googleapis/googleapis@common-protos-1_3_1"},{"id":"cli/generator/generator::google-apis::134","title":"Генератор","section":"Использование Google APIs","path":"/docs/guide/cli/generator/generator#google-apis","headings":["Использование Google APIs"],"excerpt":"Использование Google APIs generate: inputs: - directory: \"api/proto\" plugins: - name: go out: ./gen/go opts: paths: source_relative with_imports: true ```","content":"Использование Google APIs generate: inputs: - directory: \"api/proto\" plugins: - name: go out: ./gen/go opts: paths: source_relative with_imports: true ```"},{"id":"cli/generator/generator::google-apis::135","title":"Генератор","section":"Использование Google APIs","path":"/docs/guide/cli/generator/generator#google-apis","headings":["Использование Google APIs"],"excerpt":"Использование Google APIs **Важно:** Всегда фиксируйте версию (например common-protos-1_3_1) — не используйте latest в продакшене.","content":"Использование Google APIs **Важно:** Всегда фиксируйте версию (например common-protos-1_3_1) — не используйте latest в продакшене."},{"id":"cli/generator/generator::google-apis::136","title":"Генератор","section":"Использование Google APIs","path":"/docs/guide/cli/generator/generator#google-apis","headings":["Использование Google APIs"],"excerpt":"Использование Google APIs После настройки ваши proto могут импортировать определения Google API. Ниже пример сервиса с HTTP аннотацией:","content":"Использование Google APIs После настройки ваши proto могут импортировать определения Google API. Ниже пример сервиса с HTTP аннотацией:"},{"id":"cli/generator/generator::google-apis::137","title":"Генератор","section":"Использование Google APIs","path":"/docs/guide/cli/generator/generator#google-apis","headings":["Использование Google APIs"],"excerpt":"Использование Google APIs ```proto // api/proto/service.proto syntax = \"proto3\";","content":"Использование Google APIs ```proto // api/proto/service.proto syntax = \"proto3\";"},{"id":"cli/generator/generator::google-apis::138","title":"Генератор","section":"Использование Google APIs","path":"/docs/guide/cli/generator/generator#google-apis","headings":["Использование Google APIs"],"excerpt":"Использование Google APIs import \"google/api/annotations.proto\"; import \"google/protobuf/timestamp.proto\";","content":"Использование Google APIs import \"google/api/annotations.proto\"; import \"google/protobuf/timestamp.proto\";"},{"id":"cli/generator/generator::google-apis::139","title":"Генератор","section":"Использование Google APIs","path":"/docs/guide/cli/generator/generator#google-apis","headings":["Использование Google APIs"],"excerpt":"Использование Google APIs service MyService { rpc GetData(GetDataRequest) returns (GetDataResponse) { option (google.api.http) = { get: \"/v1/data\" }; } } ```","content":"Использование Google APIs service MyService { rpc GetData(GetDataRequest) returns (GetDataResponse) { option (google.api.http) = { get: \"/v1/data\" }; } } ```"},{"id":"cli/generator/generator::top::140","title":"Генератор","section":"Использование правил валидации","path":"/docs/guide/cli/generator/generator","headings":["Использование правил валидации"],"excerpt":"Использование правил валидации protoc-gen-validate даёт мощную проверку полей прямо в определениях proto, устраняя необходимость писать отдельную логику валидации в приложении.","content":"Использование правил валидации protoc-gen-validate даёт мощную проверку полей прямо в определениях proto, устраняя необходимость писать отдельную логику валидации в приложении."},{"id":"cli/generator/generator::top::141","title":"Генератор","section":"Использование правил валидации","path":"/docs/guide/cli/generator/generator","headings":["Использование правил валидации"],"excerpt":"Использование правил валидации **Когда применять валидацию:** Проверка входных данных API Ограничения моделей БД Проверка конфигурационных файлов Любая ситуация, где критична целостность данных","content":"Использование правил валидации **Когда применять валидацию:** Проверка входных данных API Ограничения моделей БД Проверка конфигурационных файлов Любая ситуация, где критична целостность данных"},{"id":"cli/generator/generator::top::142","title":"Генератор","section":"Использование правил валидации","path":"/docs/guide/cli/generator/generator","headings":["Использование правил валидации"],"excerpt":"Использование правил валидации **Преимущества:** Правила валидации — часть proto (единый источник истины) Генерация создаёт функции проверки автоматически Единообразие проверок между языками Производительнее чем проверка","content":"Использование правил валидации **Преимущества:** Правила валидации — часть proto (единый источник истины) Генерация создаёт функции проверки автоматически Единообразие проверок между языками Производительнее чем проверка через runtime reflection"},{"id":"cli/generator/generator::top::143","title":"Генератор","section":"Использование правил валидации","path":"/docs/guide/cli/generator/generator","headings":["Использование правил валидации"],"excerpt":"Использование правил валидации ```yaml deps: - github.com/bufbuild/protoc-gen-validate@v0.10.1","content":"Использование правил валидации ```yaml deps: - github.com/bufbuild/protoc-gen-validate@v0.10.1"},{"id":"cli/generator/generator::top::144","title":"Генератор","section":"Использование правил валидации","path":"/docs/guide/cli/generator/generator","headings":["Использование правил валидации"],"excerpt":"Использование правил валидации 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":"Использование правил валидации 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::top::145","title":"Генератор","section":"Использование правил валидации","path":"/docs/guide/cli/generator/generator","headings":["Использование правил валидации"],"excerpt":"Использование правил валидации **Примечание:** Нужны одновременно зависимость (для импортов proto) и плагин (для генерации кода), чтобы получить полноценную поддержку валидации.","content":"Использование правил валидации **Примечание:** Нужны одновременно зависимость (для импортов proto) и плагин (для генерации кода), чтобы получить полноценную поддержку валидации."},{"id":"cli/generator/generator::top::146","title":"Генератор","section":"Использование правил валидации","path":"/docs/guide/cli/generator/generator","headings":["Использование правил валидации"],"excerpt":"Использование правил валидации Так выглядят правила валидации в proto — сгенерированный код будет автоматически их применять:","content":"Использование правил валидации Так выглядят правила валидации в proto — сгенерированный код будет автоматически их применять:"},{"id":"cli/generator/generator::top::147","title":"Генератор","section":"Использование правил валидации","path":"/docs/guide/cli/generator/generator","headings":["Использование правил валидации"],"excerpt":"Использование правил валидации ```proto // proto/user.proto syntax = \"proto3\";","content":"Использование правил валидации ```proto // proto/user.proto syntax = \"proto3\";"},{"id":"cli/generator/generator::top::148","title":"Генератор","section":"Использование правил валидации","path":"/docs/guide/cli/generator/generator","headings":["Использование правил валидации"],"excerpt":"Использование правил валидации import \"validate/validate.proto\";","content":"Использование правил валидации import \"validate/validate.proto\";"},{"id":"cli/generator/generator::top::149","title":"Генератор","section":"Использование правил валидации","path":"/docs/guide/cli/generator/generator","headings":["Использование правил валидации"],"excerpt":"Использование правил валидации message User { string email = 1 [(validate.rules).string.email = true]; int32 age = 2 [(validate.rules).int32.gte = 0]; } ```","content":"Использование правил валидации message User { string email = 1 [(validate.rules).string.email = true]; int32 age = 2 [(validate.rules).int32.gte = 0]; } ```"},{"id":"cli/generator/generator::top::150","title":"Генератор","section":"Комплексная конфигурация с несколькими зависимостями","path":"/docs/guide/cli/generator/generator","headings":["Комплексная конфигурация с несколькими зависимостями"],"excerpt":"Комплексная конфигурация с несколькими зависимостями Пример ниже показывает продакшен‑конфигурацию, объединяющую несколько зависимостей и плагины для полного цикла разработки API:","content":"Комплексная конфигурация с несколькими зависимостями Пример ниже показывает продакшен‑конфигурацию, объединяющую несколько зависимостей и плагины для полного цикла разработки API:"},{"id":"cli/generator/generator::top::151","title":"Генератор","section":"Комплексная конфигурация с несколькими зависимостями","path":"/docs/guide/cli/generator/generator","headings":["Комплексная конфигурация с несколькими зависимостями"],"excerpt":"Комплексная конфигурация с несколькими зависимостями ```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 HT","content":"Комплексная конфигурация с несколькими зависимостями ```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::top::152","title":"Генератор","section":"Комплексная конфигурация с несколькими зависимостями","path":"/docs/guide/cli/generator/generator","headings":["Комплексная конфигурация с несколькими зависимостями"],"excerpt":"Комплексная конфигурация с несколькими зависимостями generate: inputs: - directory: \"api/proto\" plugins: # Go code generation - Core protobuf structures - name: go out: ./gen/go opts: paths: source_relative module: githu","content":"Комплексная конфигурация с несколькими зависимостями 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::top::153","title":"Генератор","section":"Интеграция с кешем зависимостей","path":"/docs/guide/cli/generator/generator","headings":["Интеграция с кешем зависимостей"],"excerpt":"Интеграция с кешем зависимостей Генератор использует модульный кеш EasyP для ускорения сборок:","content":"Интеграция с кешем зависимостей Генератор использует модульный кеш EasyP для ускорения сборок:"},{"id":"cli/generator/generator::top::154","title":"Генератор","section":"Интеграция с кешем зависимостей","path":"/docs/guide/cli/generator/generator","headings":["Интеграция с кешем зависимостей"],"excerpt":"Интеграция с кешем зависимостей ```bash Download dependencies once easyp mod download","content":"Интеграция с кешем зависимостей ```bash Download dependencies once easyp mod download"},{"id":"cli/generator/generator::top::155","title":"Генератор","section":"Интеграция с кешем зависимостей","path":"/docs/guide/cli/generator/generator","headings":["Интеграция с кешем зависимостей"],"excerpt":"Интеграция с кешем зависимостей Generate code (uses cached dependencies) easyp generate","content":"Интеграция с кешем зависимостей Generate code (uses cached dependencies) easyp generate"},{"id":"cli/generator/generator::top::156","title":"Генератор","section":"Интеграция с кешем зависимостей","path":"/docs/guide/cli/generator/generator","headings":["Интеграция с кешем зависимостей"],"excerpt":"Интеграция с кешем зависимостей Dependencies are cached in ~/.easyp/mod/ ls ~/.easyp/mod/github.com/googleapis/googleapis/ ```","content":"Интеграция с кешем зависимостей Dependencies are cached in ~/.easyp/mod/ ls ~/.easyp/mod/github.com/googleapis/googleapis/ ```"},{"id":"cli/generator/generator::top::157","title":"Генератор","section":"Удалённая генерация","path":"/docs/guide/cli/generator/generator","headings":["Удалённая генерация"],"excerpt":"Удалённая генерация Удалённая генерация — мощная возможность, позволяющая генерировать код из proto‑файлов в удалённых Git‑репозиториях без локального checkout. Это поддерживает микросервисную архитектуру, где команды ис","content":"Удалённая генерация Удалённая генерация — мощная возможность, позволяющая генерировать код из proto‑файлов в удалённых Git‑репозиториях без локального checkout. Это поддерживает микросервисную архитектуру, где команды используют API друг друга без жёсткой связки."},{"id":"cli/generator/generator::top::158","title":"Генератор","section":"Удалённая генерация","path":"/docs/guide/cli/generator/generator","headings":["Удалённая генерация"],"excerpt":"Удалённая генерация **Преимущества:** **Развязка разработки**: Команды развиваются независимо, используя версии API друг друга **Контроль версий**: Фиксация внешних API гарантирует стабильность **Меньше размер репозитори","content":"Удалённая генерация **Преимущества:** **Развязка разработки**: Команды развиваются независимо, используя версии API друг друга **Контроль версий**: Фиксация внешних API гарантирует стабильность **Меньше размер репозитория**: Нет необходимости в vendoring/submodule внешних proto **Автоматические обновления**: Легко перейти на новую версию по готовности"},{"id":"cli/generator/generator::top::159","title":"Генератор","section":"Удалённая генерация","path":"/docs/guide/cli/generator/generator","headings":["Удалённая генерация"],"excerpt":"Удалённая генерация **Рекомендации:** В продакшене используйте только тегированные версии В разработке можно тестировать latest, но в проде фиксируйте При наличии используйте семантическое версионирование Учитывайте сете","content":"Удалённая генерация **Рекомендации:** В продакшене используйте только тегированные версии В разработке можно тестировать latest, но в проде фиксируйте При наличии используйте семантическое версионирование Учитывайте сетевые ограничения в CI/CD"},{"id":"cli/generator/generator::proto::160","title":"Генератор","section":"Источники удалённых proto","path":"/docs/guide/cli/generator/generator#proto","headings":["Источники удалённых proto"],"excerpt":"Источники удалённых proto Генерация напрямую из удалённых репозиториев — полезно в микросервисной архитектуре, где разные команды владеют разными proto.","content":"Источники удалённых proto Генерация напрямую из удалённых репозиториев — полезно в микросервисной архитектуре, где разные команды владеют разными proto."},{"id":"cli/generator/generator::proto::161","title":"Генератор","section":"Источники удалённых proto","path":"/docs/guide/cli/generator/generator#proto","headings":["Источники удалённых proto"],"excerpt":"Источники удалённых proto **Типовой workflow:** Команда A публикует proto с версиями в Git Команда B добавляет их в свой easyp.yaml При генерации EasyP скачивает и подключает удалённые proto Сгенерированный код содержит ","content":"Источники удалённых proto **Типовой workflow:** Команда A публикует proto с версиями в Git Команда B добавляет их в свой easyp.yaml При генерации EasyP скачивает и подключает удалённые proto Сгенерированный код содержит клиентские библиотеки сервисов команды A"},{"id":"cli/generator/generator::proto::162","title":"Генератор","section":"Источники удалённых proto","path":"/docs/guide/cli/generator/generator#proto","headings":["Источники удалённых proto"],"excerpt":"Источники удалённых proto Практический пример объединения локальных и удалённых источников в одной конфигурации генерации:","content":"Источники удалённых proto Практический пример объединения локальных и удалённых источников в одной конфигурации генерации:"},{"id":"cli/generator/generator::top::163","title":"Генератор","section":"Сценарии использования удалённой генерации","path":"/docs/guide/cli/generator/generator","headings":["Сценарии использования удалённой генерации"],"excerpt":"Сценарии использования удалённой генерации Примеры ниже показывают реальные ситуации, где удалённая генерация даёт ощутимую выгоду.","content":"Сценарии использования удалённой генерации Примеры ниже показывают реальные ситуации, где удалённая генерация даёт ощутимую выгоду."},{"id":"cli/generator/generator::multi-team-development::164","title":"Генератор","section":"Много команд (Multi-Team Development)","path":"/docs/guide/cli/generator/generator#multi-team-development","headings":["Много команд (Multi-Team Development)"],"excerpt":"Много команд (Multi-Team Development) Мультикомандная разработка особенно выигрывает: вместо координации общих репозиториев и сложного управления зависимостями — независимая эволюция API с контролируемыми обновлениями че","content":"Много команд (Multi-Team Development) Мультикомандная разработка особенно выигрывает: вместо координации общих репозиториев и сложного управления зависимостями — независимая эволюция API с контролируемыми обновлениями через версии."},{"id":"cli/generator/generator::multi-team-development::165","title":"Генератор","section":"Много команд (Multi-Team Development)","path":"/docs/guide/cli/generator/generator#multi-team-development","headings":["Много команд (Multi-Team Development)"],"excerpt":"Много команд (Multi-Team Development) Паттерн ценен в крупных организациях, где: Команды имеют разные циклы релизов и скорости разработки Владение API определено, потребление — массовое Нужно избежать overhead от координ","content":"Много команд (Multi-Team Development) Паттерн ценен в крупных организациях, где: Команды имеют разные циклы релизов и скорости разработки Владение API определено, потребление — массовое Нужно избежать overhead от координации общих proto репозиториев Команды используют разные стеки, но должны взаимодействовать"},{"id":"cli/generator/generator::multi-team-development::166","title":"Генератор","section":"Много команд (Multi-Team Development)","path":"/docs/guide/cli/generator/generator#multi-team-development","headings":["Много команд (Multi-Team Development)"],"excerpt":"Много команд (Multi-Team Development)","content":"Много команд (Multi-Team Development)"},{"id":"cli/generator/generator::api::167","title":"Генератор","section":"Интеграция с API вендоров","path":"/docs/guide/cli/generator/generator#api","headings":["Интеграция с API вендоров"],"excerpt":"Интеграция с API вендоров Многие вендоры публикуют proto для своих API, позволяя генерировать типобезопасных клиентов вместо ручных HTTP реализаций. Это повышает типовую строгость, автоматизирует сериализацию и часто уск","content":"Интеграция с API вендоров Многие вендоры публикуют proto для своих API, позволяя генерировать типобезопасных клиентов вместо ручных HTTP реализаций. Это повышает типовую строгость, автоматизирует сериализацию и часто ускоряет работу."},{"id":"cli/generator/generator::api::168","title":"Генератор","section":"Интеграция с API вендоров","path":"/docs/guide/cli/generator/generator#api","headings":["Интеграция с API вендоров"],"excerpt":"Интеграция с API вендоров Преимущества использования proto от вендоров: **Type safety**: Проверка типов на этапе компиляции **Automatic updates**: Новые возможности приходят с обновлением версии **Consistency**: Единые п","content":"Интеграция с API вендоров Преимущества использования proto от вендоров: **Type safety**: Проверка типов на этапе компиляции **Automatic updates**: Новые возможности приходят с обновлением версии **Consistency**: Единые паттерны интерфейсов между интеграциями **Performance**: Бинарная сериализация быстрее JSON **Documentation**: Proto выступают источником истины для API"},{"id":"cli/generator/generator::top::169","title":"Генератор","section":"Команды","path":"/docs/guide/cli/generator/generator","headings":["Команды"],"excerpt":"Команды CLI EasyP предоставляет гибкие варианты запуска генерации с разными конфигурациями и окружениями.","content":"Команды CLI EasyP предоставляет гибкие варианты запуска генерации с разными конфигурациями и окружениями."},{"id":"cli/generator/generator::top::170","title":"Генератор","section":"Базовая генерация","path":"/docs/guide/cli/generator/generator","headings":["Базовая генерация"],"excerpt":"Базовая генерация Ниже наиболее часто применяемые варианты команд для разработки и продакшена:","content":"Базовая генерация Ниже наиболее часто применяемые варианты команд для разработки и продакшена:"},{"id":"cli/generator/generator::top::171","title":"Генератор","section":"Базовая генерация","path":"/docs/guide/cli/generator/generator","headings":["Базовая генерация"],"excerpt":"Базовая генерация ```bash Use default easyp.yaml configuration - Most common for development easyp generate","content":"Базовая генерация ```bash Use default easyp.yaml configuration - Most common for development easyp generate"},{"id":"cli/generator/generator::top::172","title":"Генератор","section":"Базовая генерация","path":"/docs/guide/cli/generator/generator","headings":["Базовая генерация"],"excerpt":"Базовая генерация Use custom configuration file - Essential for multi-environment setups easyp --cfg production.easyp.yaml generate","content":"Базовая генерация Use custom configuration file - Essential for multi-environment setups easyp --cfg production.easyp.yaml generate"},{"id":"cli/generator/generator::top::173","title":"Генератор","section":"Базовая генерация","path":"/docs/guide/cli/generator/generator","headings":["Базовая генерация"],"excerpt":"Базовая генерация Generate with debug logs - Helpful for debugging and CI/CD easyp --debug generate","content":"Базовая генерация Generate with debug logs - Helpful for debugging and CI/CD easyp --debug generate"},{"id":"cli/generator/generator::top::174","title":"Генератор","section":"Базовая генерация","path":"/docs/guide/cli/generator/generator","headings":["Базовая генерация"],"excerpt":"Базовая генерация Generate with custom cache location - Useful for CI systems or shared environments EASYPPATH=/tmp/easyp-cache easyp generate ```","content":"Базовая генерация Generate with custom cache location - Useful for CI systems or shared environments EASYPPATH=/tmp/easyp-cache easyp generate ```"},{"id":"cli/generator/generator::top::175","title":"Генератор","section":"Интеграция с менеджером пакетов","path":"/docs/guide/cli/generator/generator","headings":["Интеграция с менеджером пакетов"],"excerpt":"Интеграция с менеджером пакетов Интеграция с менеджером пакетов позволяет либо явно управлять зависимостями, либо поручить это генератору. Явный путь даёт больше контроля, автоматический — больше удобства:","content":"Интеграция с менеджером пакетов Интеграция с менеджером пакетов позволяет либо явно управлять зависимостями, либо поручить это генератору. Явный путь даёт больше контроля, автоматический — больше удобства:"},{"id":"cli/generator/generator::top::176","title":"Генератор","section":"Интеграция с менеджером пакетов","path":"/docs/guide/cli/generator/generator","headings":["Интеграция с менеджером пакетов"],"excerpt":"Интеграция с менеджером пакетов ```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":"Интеграция с менеджером пакетов ```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::top::177","title":"Генератор","section":"Интеграция с менеджером пакетов","path":"/docs/guide/cli/generator/generator","headings":["Интеграция с менеджером пакетов"],"excerpt":"Интеграция с менеджером пакетов Automatic workflow - Convenient for development (generate downloads dependencies automatically) easyp generate ```","content":"Интеграция с менеджером пакетов Automatic workflow - Convenient for development (generate downloads dependencies automatically) easyp generate ```"},{"id":"cli/generator/generator::advanced-usage::178","title":"Генератор","section":"Расширенное использование (Advanced Usage)","path":"/docs/guide/cli/generator/generator#advanced-usage","headings":["Расширенное использование (Advanced Usage)"],"excerpt":"Расширенное использование (Advanced Usage) Эти варианты полезны для специфических сценариев деплоя, отладки или когда нужен более тонкий контроль процесса генерации:","content":"Расширенное использование (Advanced Usage) Эти варианты полезны для специфических сценариев деплоя, отладки или когда нужен более тонкий контроль процесса генерации:"},{"id":"cli/generator/generator::advanced-usage::179","title":"Генератор","section":"Расширенное использование (Advanced Usage)","path":"/docs/guide/cli/generator/generator#advanced-usage","headings":["Расширенное использование (Advanced Usage)"],"excerpt":"Расширенное использование (Advanced Usage) ```bash Генерация из конкретной директории (перекрывает настройку в файле конфигурации) easyp generate --path=./api/proto","content":"Расширенное использование (Advanced Usage) ```bash Генерация из конкретной директории (перекрывает настройку в файле конфигурации) easyp generate --path=./api/proto"},{"id":"cli/generator/generator::advanced-usage::180","title":"Генератор","section":"Расширенное использование (Advanced Usage)","path":"/docs/guide/cli/generator/generator#advanced-usage","headings":["Расширенное использование (Advanced Usage)"],"excerpt":"Расширенное использование (Advanced Usage) Генерация с vendored зависимостями (оффлайн / Docker контейнеры) easyp mod vendor easyp generate","content":"Расширенное использование (Advanced Usage) Генерация с vendored зависимостями (оффлайн / Docker контейнеры) easyp mod vendor easyp generate"},{"id":"cli/generator/generator::advanced-usage::181","title":"Генератор","section":"Расширенное использование (Advanced Usage)","path":"/docs/guide/cli/generator/generator#advanced-usage","headings":["Расширенное использование (Advanced Usage)"],"excerpt":"Расширенное использование (Advanced Usage) Генерация из кастомного project root (удобно для монореп и вложенных рабочих директорий) easyp generate --root=/usr/local/src/my-project --path=./api/proto ```","content":"Расширенное использование (Advanced Usage) Генерация из кастомного project root (удобно для монореп и вложенных рабочих директорий) easyp generate --root=/usr/local/src/my-project --path=./api/proto ```"},{"id":"cli/generator/generator::common-patterns::182","title":"Генератор","section":"Типовые паттерны (Common Patterns)","path":"/docs/guide/cli/generator/generator#common-patterns","headings":["Типовые паттерны (Common Patterns)"],"excerpt":"Типовые паттерны (Common Patterns) Эти схемы отражают реальные сценарии и лучшие практики организации генерации кода в разных структурах проектов.","content":"Типовые паттерны (Common Patterns) Эти схемы отражают реальные сценарии и лучшие практики организации генерации кода в разных структурах проектов."},{"id":"cli/generator/generator::multi-language-generation::183","title":"Генератор","section":"Мульти-языковая генерация (Multi-Language Generation)","path":"/docs/guide/cli/generator/generator#multi-language-generation","headings":["Мульти-языковая генерация (Multi-Language Generation)"],"excerpt":"Мульти-языковая генерация (Multi-Language Generation) Мульти-языковая генерация критична для компаний, использующих разные технологии в стеке. EasyP облегчает получение согласованных клиентских библиотек и типов для неск","content":"Мульти-языковая генерация (Multi-Language Generation) Мульти-языковая генерация критична для компаний, использующих разные технологии в стеке. EasyP облегчает получение согласованных клиентских библиотек и типов для нескольких языков из одного источника proto."},{"id":"cli/generator/generator::multi-language-generation::184","title":"Генератор","section":"Мульти-языковая генерация (Multi-Language Generation)","path":"/docs/guide/cli/generator/generator#multi-language-generation","headings":["Мульти-языковая генерация (Multi-Language Generation)"],"excerpt":"Мульти-языковая генерация (Multi-Language Generation) **Типовые сценарии:** **Full‑stack приложения**: backend на Go/Java + фронтенд на TypeScript **Платформы данных**: сервисы на Go + аналитика / ML на Python **Микросер","content":"Мульти-языковая генерация (Multi-Language Generation) **Типовые сценарии:** **Full‑stack приложения**: backend на Go/Java + фронтенд на TypeScript **Платформы данных**: сервисы на Go + аналитика / ML на Python **Микросервисы**: каждый сервис — оптимальный язык под задачу **Внешние SDK**: предоставление клиентских библиотек партнёрам **Интеграция с легаси**: современные gRPC сервисы + старые системы"},{"id":"cli/generator/generator::multi-language-generation::185","title":"Генератор","section":"Мульти-языковая генерация (Multi-Language Generation)","path":"/docs/guide/cli/generator/generator#multi-language-generation","headings":["Мульти-языковая генерация (Multi-Language Generation)"],"excerpt":"Мульти-языковая генерация (Multi-Language Generation) **Производительность:** Каждый плагин запускается отдельно — время растёт линейно от количества плагинов Для больших наборов используйте параллельный запуск (make -j4","content":"Мульти-языковая генерация (Multi-Language Generation) **Производительность:** Каждый плагин запускается отдельно — время растёт линейно от количества плагинов Для больших наборов используйте параллельный запуск (make -j4) Структурируйте выходные директории иерархически — меньше конфликтов Плагины имеют разную скорость — профилируйте сборку для поиска узких мест"},{"id":"cli/generator/generator::multi-language-generation::186","title":"Генератор","section":"Мульти-языковая генерация (Multi-Language Generation)","path":"/docs/guide/cli/generator/generator#multi-language-generation","headings":["Мульти-языковая генерация (Multi-Language Generation)"],"excerpt":"Мульти-языковая генерация (Multi-Language Generation) **Преимущества сопровождения:** Единый источник истины для API снижает риск расхождения схем Согласованные типы уменьшают интеграционные баги Автоматическая синхрониз","content":"Мульти-языковая генерация (Multi-Language Generation) **Преимущества сопровождения:** Единый источник истины для API снижает риск расхождения схем Согласованные типы уменьшают интеграционные баги Автоматическая синхронизация при изменении proto исключает ручные правки Меньше риска дрейфа API между реализациями на разных языках Рефакторинг упрощается — изменения транзитивно отражаются во всех артефактах"},{"id":"cli/generator/generator::multi-language-generation::187","title":"Генератор","section":"Мульти-языковая генерация (Multi-Language Generation)","path":"/docs/guide/cli/generator/generator#multi-language-generation","headings":["Мульти-языковая генерация (Multi-Language Generation)"],"excerpt":"Мульти-языковая генерация (Multi-Language Generation) Ниже пример типичной мульти-языковой конфигурации для full‑stack приложения: backend, веб‑клиент, аналитика и документация:","content":"Мульти-языковая генерация (Multi-Language Generation) Ниже пример типичной мульти-языковой конфигурации для full‑stack приложения: backend, веб‑клиент, аналитика и документация:"},{"id":"cli/generator/generator::multi-language-generation::188","title":"Генератор","section":"Мульти-языковая генерация (Multi-Language Generation)","path":"/docs/guide/cli/generator/generator#multi-language-generation","headings":["Мульти-языковая генерация (Multi-Language Generation)"],"excerpt":"Мульти-языковая генерация (Multi-Language Generation)","content":"Мульти-языковая генерация (Multi-Language Generation)"},{"id":"cli/generator/generator::multi-language-generation::189","title":"Генератор","section":"Мульти-языковая генерация (Multi-Language Generation)","path":"/docs/guide/cli/generator/generator#multi-language-generation","headings":["Мульти-языковая генерация (Multi-Language Generation)"],"excerpt":"Мульти-языковая генерация (Multi-Language Generation) **Совет по организации:** Используйте отдельные выходные директории для каждого языка, чтобы избежать конфликтов файлов и упростить интеграцию с языковыми сборочными ","content":"Мульти-языковая генерация (Multi-Language Generation) **Совет по организации:** Используйте отдельные выходные директории для каждого языка, чтобы избежать конфликтов файлов и упростить интеграцию с языковыми сборочными системами."},{"id":"cli/generator/generator::multi-language-generation::190","title":"Генератор","section":"Мульти-языковая генерация (Multi-Language Generation)","path":"/docs/guide/cli/generator/generator#multi-language-generation","headings":["Мульти-языковая генерация (Multi-Language Generation)"],"excerpt":"Мульти-языковая генерация (Multi-Language Generation) Генератор EasyP — комплексное решение для генерации кода из Protocol Buffers: от простой локальной разработки до сложных enterprise‑сценариев с удалёнными зависимостя","content":"Мульти-языковая генерация (Multi-Language Generation) Генератор EasyP — комплексное решение для генерации кода из Protocol Buffers: от простой локальной разработки до сложных enterprise‑сценариев с удалёнными зависимостями и мульти-языковым выводом."},{"id":"cli/linter/linter::proto::0","title":"Линтер","section":"Зачем нужен линтер для proto файлов?","path":"/docs/guide/cli/linter/linter#proto","headings":["Зачем нужен линтер для proto файлов?"],"excerpt":"Зачем нужен линтер для proto файлов? Линтеры играют ключевую роль в современной разработке, особенно когда речь о .proto файлах. Они обеспечивают единый стиль и структуру, помогают находить потенциальные ошибки на ранних","content":"Зачем нужен линтер для proto файлов? Линтеры играют ключевую роль в современной разработке, особенно когда речь о .proto файлах. Они обеспечивают единый стиль и структуру, помогают находить потенциальные ошибки на ранних этапах и поддерживают читаемость кода. Это даёт выгоды:"},{"id":"cli/linter/linter::proto::1","title":"Линтер","section":"Зачем нужен линтер для proto файлов?","path":"/docs/guide/cli/linter/linter#proto","headings":["Зачем нужен линтер для proto файлов?"],"excerpt":"Зачем нужен линтер для proto файлов? **Снижение затрат на разработку:** Ошибки ловятся раньше, меньше времени на отладку. **Улучшение командного взаимодействия:** Единообразный код легче понимать и сопровождать. **Бизнес","content":"Зачем нужен линтер для proto файлов? **Снижение затрат на разработку:** Ошибки ловятся раньше, меньше времени на отладку. **Улучшение командного взаимодействия:** Единообразный код легче понимать и сопровождать. **Бизнес-эффективность:** Более качественный код → меньше инцидентов в проде → ниже стоимость поддержки."},{"id":"cli/linter/linter::top::2","title":"Линтер","section":"Справочник по конфигурации","path":"/docs/guide/cli/linter/linter","headings":["Справочник по конфигурации"],"excerpt":"Справочник по конфигурации Конфигурация линтера настраивается в секции lint файла easyp.yaml.","content":"Справочник по конфигурации Конфигурация линтера настраивается в секции lint файла easyp.yaml."},{"id":"cli/linter/linter::use-string::3","title":"Линтер","section":"use ([]string)","path":"/docs/guide/cli/linter/linter#use-string","headings":["use ([]string)"],"excerpt":"use ([]string) Определяет набор правил или категорий для включения. Можно смешивать категории и конкретные правила.","content":"use ([]string) Определяет набор правил или категорий для включения. Можно смешивать категории и конкретные правила."},{"id":"cli/linter/linter::use-string::4","title":"Линтер","section":"use ([]string)","path":"/docs/guide/cli/linter/linter#use-string","headings":["use ([]string)"],"excerpt":"use ([]string) **Категории:** **MINIMAL**: Базовая согласованность пакетов **BASIC**: Соглашения по именованию и структуре **DEFAULT**: Рекомендованные правила для большинства проектов **COMMENTS**: Требования к коммента","content":"use ([]string) **Категории:** **MINIMAL**: Базовая согласованность пакетов **BASIC**: Соглашения по именованию и структуре **DEFAULT**: Рекомендованные правила для большинства проектов **COMMENTS**: Требования к комментариям **UNARY_RPC**: Ограничение на streaming RPC"},{"id":"cli/linter/linter::use-string::5","title":"Линтер","section":"use ([]string)","path":"/docs/guide/cli/linter/linter#use-string","headings":["use ([]string)"],"excerpt":"use ([]string) **Индивидуальные правила:** Любое имя правила (например ENUM_PASCAL_CASE, FIELD_LOWER_SNAKE_CASE)","content":"use ([]string) **Индивидуальные правила:** Любое имя правила (например ENUM_PASCAL_CASE, FIELD_LOWER_SNAKE_CASE)"},{"id":"cli/linter/linter::use-string::6","title":"Линтер","section":"use ([]string)","path":"/docs/guide/cli/linter/linter#use-string","headings":["use ([]string)"],"excerpt":"use ([]string) **Примеры:** ```yaml Только категории use: [MINIMAL, BASIC, DEFAULT]","content":"use ([]string) **Примеры:** ```yaml Только категории use: [MINIMAL, BASIC, DEFAULT]"},{"id":"cli/linter/linter::use-string::7","title":"Линтер","section":"use ([]string)","path":"/docs/guide/cli/linter/linter#use-string","headings":["use ([]string)"],"excerpt":"use ([]string) Смешивание use: - MINIMAL - COMMENT_SERVICE - COMMENT_RPC - ENUM_PASCAL_CASE","content":"use ([]string) Смешивание use: - MINIMAL - COMMENT_SERVICE - COMMENT_RPC - ENUM_PASCAL_CASE"},{"id":"cli/linter/linter::use-string::8","title":"Линтер","section":"use ([]string)","path":"/docs/guide/cli/linter/linter#use-string","headings":["use ([]string)"],"excerpt":"use ([]string) Точный набор use: - PACKAGE_DEFINED - SERVICE_PASCAL_CASE - FIELD_LOWER_SNAKE_CASE ```","content":"use ([]string) Точный набор use: - PACKAGE_DEFINED - SERVICE_PASCAL_CASE - FIELD_LOWER_SNAKE_CASE ```"},{"id":"cli/linter/linter::enum_zero_value_suffix-string::9","title":"Линтер","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) Обязывает нулевое значение enum иметь заданный суффикс.","content":"enum_zero_value_suffix (string) Обязывает нулевое значение enum иметь заданный суффикс."},{"id":"cli/linter/linter::enum_zero_value_suffix-string::10","title":"Линтер","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) **Обычно:** \"UNSPECIFIED\", \"UNKNOWN\", \"DEFAULT\"","content":"enum_zero_value_suffix (string) **Обычно:** \"UNSPECIFIED\", \"UNKNOWN\", \"DEFAULT\""},{"id":"cli/linter/linter::enum_zero_value_suffix-string::11","title":"Линтер","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)","content":"enum_zero_value_suffix (string)"},{"id":"cli/linter/linter::service_suffix-string::12","title":"Линтер","section":"service_suffix (string)","path":"/docs/guide/cli/linter/linter#service_suffix-string","headings":["service_suffix (string)"],"excerpt":"service_suffix (string) Требуемый суффикс для имён сервисов (унификация стиля).","content":"service_suffix (string) Требуемый суффикс для имён сервисов (унификация стиля)."},{"id":"cli/linter/linter::ignore-string::13","title":"Линтер","section":"ignore ([]string)","path":"/docs/guide/cli/linter/linter#ignore-string","headings":["ignore ([]string)"],"excerpt":"ignore ([]string) Полное исключение путей из линтинга.","content":"ignore ([]string) Полное исключение путей из линтинга."},{"id":"cli/linter/linter::ignore-string::14","title":"Линтер","section":"ignore ([]string)","path":"/docs/guide/cli/linter/linter#ignore-string","headings":["ignore ([]string)"],"excerpt":"ignore ([]string) **Use cases:** vendor / third_party сгенерированные файлы легаси подпакеты тестовые фикстуры","content":"ignore ([]string) **Use cases:** vendor / third_party сгенерированные файлы легаси подпакеты тестовые фикстуры"},{"id":"cli/linter/linter::except-string::15","title":"Линтер","section":"except ([]string)","path":"/docs/guide/cli/linter/linter#except-string","headings":["except ([]string)"],"excerpt":"except ([]string) Глобально отключает правила.","content":"except ([]string) Глобально отключает правила."},{"id":"cli/linter/linter::allow_comment_ignores-bool::16","title":"Линтер","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) Разрешает инлайн‑игнор правил комментариями.","content":"allow_comment_ignores (bool) Разрешает инлайн‑игнор правил комментариями."},{"id":"cli/linter/linter::ignore_only-mapstringstring::17","title":"Линтер","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) Таргетированное игнорирование конкретных правил для указанных путей.","content":"ignore_only (mapstringstring) Таргетированное игнорирование конкретных правил для указанных путей."},{"id":"cli/linter/linter::top::18","title":"Линтер","section":"Игнор правил комментариями","path":"/docs/guide/cli/linter/linter","headings":["Игнор правил комментариями"],"excerpt":"Игнор правил комментариями Если включён allow_comment_ignores, можно точечно отключать правила.","content":"Игнор правил комментариями Если включён allow_comment_ignores, можно точечно отключать правила."},{"id":"cli/linter/linter::top::19","title":"Линтер","section":"Несколько правил в одной строке","path":"/docs/guide/cli/linter/linter","headings":["Несколько правил в одной строке"],"excerpt":"Несколько правил в одной строке","content":"Несколько правил в одной строке"},{"id":"cli/linter/linter::top::20","title":"Линтер","section":"Используйте редко","path":"/docs/guide/cli/linter/linter","headings":["Используйте редко"],"excerpt":"Используйте редко Частое игнорирование = сигнал пересмотреть конфигурацию.","content":"Используйте редко Частое игнорирование = сигнал пересмотреть конфигурацию."},{"id":"cli/linter/linter::top::21","title":"Линтер","section":"Предпочитайте конфигурацию","path":"/docs/guide/cli/linter/linter","headings":["Предпочитайте конфигурацию"],"excerpt":"Предпочитайте конфигурацию Если нужно игнорировать правило в группе файлов — используйте ignore_only.","content":"Предпочитайте конфигурацию Если нужно игнорировать правило в группе файлов — используйте ignore_only."},{"id":"cli/linter/linter::top::22","title":"Линтер","section":"Категории линтера","path":"/docs/guide/cli/linter/linter","headings":["Категории линтера"],"excerpt":"Категории линтера Категории помогают быстро выбрать уровень строгости.","content":"Категории линтера Категории помогают быстро выбрать уровень строгости."},{"id":"cli/linter/linter::top::23","title":"Линтер","section":"Категории линтера","path":"/docs/guide/cli/linter/linter","headings":["Категории линтера"],"excerpt":"Категории линтера **Когда использовать:** **MINIMAL**: Минимальная базовая целостность **BASIC**: Частые соглашения имен **DEFAULT**: Дополнительные проверки качества **COMMENTS**: Обязательные комментарии (API, команды)","content":"Категории линтера **Когда использовать:** **MINIMAL**: Минимальная базовая целостность **BASIC**: Частые соглашения имен **DEFAULT**: Дополнительные проверки качества **COMMENTS**: Обязательные комментарии (API, команды) **UNARY_RPC**: Ограничить streaming RPC"},{"id":"cli/linter/linter::minimal::24","title":"Линтер","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::25","title":"Линтер","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::26","title":"Линтер","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::27","title":"Линтер","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::28","title":"Линтер","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::top::29","title":"Линтер","section":"Заключение","path":"/docs/guide/cli/linter/linter","headings":["Заключение"],"excerpt":"Заключение Внедрение EasyP линдера для ваших proto файлов заметно улучшит workflow, качество и поддерживаемость кода. Полная совместимость с Buf позволяет командам мигрировать без боли, используя гибкую конфигурацию и мо","content":"Заключение Внедрение EasyP линдера для ваших proto файлов заметно улучшит workflow, качество и поддерживаемость кода. Полная совместимость с Buf позволяет командам мигрировать без боли, используя гибкую конфигурацию и мощные возможности из коробки."},{"id":"cli/linter/rules/comment-enum-value::top::0","title":"COMMENT_ENUM_VALUE","path":"/docs/guide/cli/linter/rules/comment-enum-value","headings":[],"excerpt":"Это правило проверяет, что все значения enum имеют комментарий.","content":"Это правило проверяет, что все значения enum имеют комментарий."},{"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 ```proto syntax = \"proto3\";","content":"Good ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/comment-enum-value::good::4","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":"Это правило проверяет, что enum имеет комментарий.","content":"Это правило проверяет, что enum имеет комментарий."},{"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":"Это правило проверяет, что все поля сообщений имеют комментарий.","content":"Это правило проверяет, что все поля сообщений имеют комментарий."},{"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":"Это правило проверяет, что message имеет комментарий.","content":"Это правило проверяет, что message имеет комментарий."},{"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 ```proto syntax = \"proto3\";","content":"Bad ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/comment-message::bad::2","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::3","title":"COMMENT_MESSAGE","section":"Good","path":"/docs/guide/cli/linter/rules/comment-message#good","headings":["Good"],"excerpt":"Good ```proto syntax = \"proto3\";","content":"Good ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/comment-message::good::4","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":"Это правило проверяет, что oneof имеет комментарий.","content":"Это правило проверяет, что oneof имеет комментарий."},{"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":"Это правило проверяет, что сервис имеет комментарий.","content":"Это правило проверяет, что сервис имеет комментарий."},{"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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **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":"Это правило проверяет, что все файлы в заданной директории находятся в одном и том же package.","content":"Это правило проверяет, что все файлы в заданной директории находятся в одном и том же 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":"Это правило проверяет, что первое значение enum равно нулю.","content":"Это правило проверяет, что первое значение enum равно нулю."},{"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 ```proto syntax = \"proto3\";","content":"Bad ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/enum-first-value-zero::bad::3","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::4","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::5","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":"Это правило проверяет, что опция allow_alias не установлена в значение true внутри enum.","content":"Это правило проверяет, что опция allow_alias не установлена в значение true внутри 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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **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":"Это правило проверяет, что имена enum написаны в стиле PascalCase.","content":"Это правило проверяет, что имена enum написаны в стиле 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":"Это правило проверяет, что все значения enum имеют префикс, совпадающий с именем enum.","content":"Это правило проверяет, что все значения enum имеют префикс, совпадающий с именем enum."},{"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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **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":"Это правило проверяет, что значения enum записаны в стиле UPPER_SNAKE_CASE.","content":"Это правило проверяет, что значения enum записаны в стиле 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":"Это правило проверяет, что все нулевые значения enum имеют суффикс _NONE или ваш кастомный (пользовательский) суффикс.","content":"Это правило проверяет, что все нулевые значения enum имеют суффикс _NONE или ваш кастомный (пользовательский) суффикс."},{"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":"**MINIMAL** **BASIC** **DEFAULT**","content":"**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":"Это правило проверяет, что имена полей сообщений записаны в стиле lower_snake_case.","content":"Это правило проверяет, что имена полей сообщений записаны в стиле 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":"Это правило проверяет, что все файлы имеют имя в формате lower_snake_case (только строчные буквы, цифры и символ подчеркивания, без пробелов и заглавных букв).","content":"Это правило проверяет, что все файлы имеют имя в формате 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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **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":"Это правило проверяет, что в proto-файле не используются public импорты (оператор import public \"...\").","content":"Это правило проверяет, что в proto-файле не используются public импорты (оператор import public \"...\")."},{"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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **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":"Это правило проверяет, что в proto‑файле не используются weak‑импорты (import weak \"...\").","content":"Это правило проверяет, что в proto‑файле не используются weak‑импорты (import weak \"...\")."},{"id":"cli/linter/rules/import-no-weak::top::2","title":"IMPORT_NO_WEAK","path":"/docs/guide/cli/linter/rules/import-no-weak","headings":[],"excerpt":"Weak import (синтаксис import weak) допустим в proto2, но его использование усложняет анализ зависимостей и может приводить к неочевидным ошибкам при генерации кода. Рекомендуется всегда использовать обычный import.","content":"Weak import (синтаксис import weak) допустим в proto2, но его использование усложняет анализ зависимостей и может приводить к неочевидным ошибкам при генерации кода. Рекомендуется всегда использовать обычный import."},{"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 ```proto syntax = \"proto2\";","content":"Bad ```proto syntax = \"proto2\";"},{"id":"cli/linter/rules/import-no-weak::bad::4","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::5","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::6","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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **MINIMAL** **BASIC** **DEFAULT**"},{"id":"cli/linter/rules/import-used::top::1","title":"IMPORT_USED","path":"/docs/guide/cli/linter/rules/import-used","headings":[],"excerpt":"Это правило проверяет, что все импорты используются в proto-файле.","content":"Это правило проверяет, что все импорты используются в proto-файле."},{"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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **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":"Это правило проверяет, что имена сообщений (message) записаны в стиле PascalCase.","content":"Это правило проверяет, что имена сообщений (message) записаны в стиле 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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **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":"Это правило проверяет, что имена oneof записаны в стиле lower_snake_case.","content":"Это правило проверяет, что имена oneof записаны в стиле 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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **MINIMAL** **BASIC** **DEFAULT**"},{"id":"cli/linter/rules/package-defined::top::1","title":"PACKAGE_DEFINED","path":"/docs/guide/cli/linter/rules/package-defined","headings":[],"excerpt":"Это правило проверяет, что во всех файлах присутствует директива package.","content":"Это правило проверяет, что во всех файлах присутствует директива package."},{"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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **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":"Это правило проверяет, что все файлы находятся в директории, имя которой соответствует имени их пакета.","content":"Это правило проверяет, что все файлы находятся в директории, имя которой соответствует имени их пакета."},{"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":"Это правило проверяет, что имена package записаны в формате lower_snake_case (строчные буквы, при необходимости цифры и символ подчеркивания, без пробелов и заглавных букв).","content":"Это правило проверяет, что имена package записаны в формате 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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **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":"Это правило проверяет, что все файлы с заданным пакетом используют одно и то же пространство имён C# (csharp_namespace).","content":"Это правило проверяет, что все файлы с заданным пакетом используют одно и то же пространство имён C# (csharp_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\"; // [!code focus] ```","content":"Good option csharp_namespace = \"Foo.Bar\"; // [!code focus] ```"},{"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 ```proto // File: pkg/bar.proto","content":"Good ```proto // File: pkg/bar.proto"},{"id":"cli/linter/rules/package-same-csharp-namespace::good::9","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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **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":"Это правило проверяет, что все файлы с данным package находятся в одной директории.","content":"Это правило проверяет, что все файлы с данным package находятся в одной директории."},{"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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **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":"Это правило проверяет, что все файлы с одним и тем же package используют одно и то же значение опции go_package.","content":"Это правило проверяет, что все файлы с одним и тем же package используют одно и то же значение опции 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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **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":"Это правило проверяет, что все файлы с одним и тем же package используют одинаковое значение опции java_package.","content":"Это правило проверяет, что все файлы с одним и тем же package используют одинаковое значение опции 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 ```proto // File: pkg/bar.proto","content":"Bad ```proto // File: pkg/bar.proto"},{"id":"cli/linter/rules/package-same-java-multiple-files::bad::6","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::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 ```proto // File: pkg/foo.proto","content":"Good ```proto // File: pkg/foo.proto"},{"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 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::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 ```proto // File: pkg/bar.proto","content":"Good ```proto // File: pkg/bar.proto"},{"id":"cli/linter/rules/package-same-java-multiple-files::good::10","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":"Это правило проверяет, что все файлы с одним и тем же package используют одно и то же значение опции java_package.","content":"Это правило проверяет, что все файлы с одним и тем же package используют одно и то же значение опции 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":"Это правило проверяет, что все файлы с одним и тем же package используют одно и то же значение опции php_namespace.","content":"Это правило проверяет, что все файлы с одним и тем же package используют одно и то же значение опции 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":"Это правило проверяет, что все файлы с одним и тем же package используют один и тот же swift_prefix.","content":"Это правило проверяет, что все файлы с одним и тем же package используют один и тот же 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":"Это правило проверяет, что суффикс версии пакета имеет формат _vX, где X — числовая версия.","content":"Это правило проверяет, что суффикс версии пакета имеет формат _vX, где X — числовая версия."},{"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":"Это правило проверяет, что RPC не использует клиентский стриминг (запрос не является stream ...).","content":"Это правило проверяет, что RPC не использует клиентский стриминг (запрос не является stream ...)."},{"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":"Это правило проверяет, что RPC не использует серверный стриминг (ответ не является stream ...).","content":"Это правило проверяет, что RPC не использует серверный стриминг (ответ не является stream ...)."},{"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":"Это правило проверяет, что все имена RPC написаны в стиле PascalCase.","content":"Это правило проверяет, что все имена RPC написаны в стиле 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":"Это правило проверяет, что все сообщения запроса и ответа RPC уникальны: для каждого метода используются собственные (не переиспользуются одинаковые пары Request / Response у разных RPC).","content":"Это правило проверяет, что все сообщения запроса и ответа RPC уникальны: для каждого метода используются собственные (не переиспользуются одинаковые пары Request / Response у разных RPC)."},{"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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **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":"Это правило проверяет, что все сообщения запроса RPC названы в формате MethodRequest.","content":"Это правило проверяет, что все сообщения запроса RPC названы в формате 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":"Это правило проверяет, что все сообщения ответа RPC названы в формате MethodResponse.","content":"Это правило проверяет, что все сообщения ответа RPC названы в формате 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":"**MINIMAL** **BASIC** **DEFAULT**","content":"**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":"Это правило проверяет, что все имена сервисов написаны в стиле PascalCase.","content":"Это правило проверяет, что все имена сервисов написаны в стиле 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":"Это правило проверяет, что все сервисы имеют суффикс Service или ваш пользовательский суффикс.","content":"Это правило проверяет, что все сервисы имеют суффикс Service или ваш пользовательский суффикс."},{"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 против Buf: управление пакетами","path":"/docs/guide/cli/package-manager/easyp-vs-buf","headings":[],"excerpt":"EasyP против Buf: управление пакетами","content":"EasyP против Buf: управление пакетами"},{"id":"cli/package-manager/easyp-vs-buf::top::1","title":"EasyP против Buf: управление пакетами","path":"/docs/guide/cli/package-manager/easyp-vs-buf","headings":[],"excerpt":"Этот документ даёт подробное сравнение децентрализованного подхода EasyP к управлению пакетами и централизованной модели Buf через Buf Schema Registry (BSR), чтобы помочь понять ключевые различия и выбрать подходящее реш","content":"Этот документ даёт подробное сравнение децентрализованного подхода EasyP к управлению пакетами и централизованной модели Buf через Buf Schema Registry (BSR), чтобы помочь понять ключевые различия и выбрать подходящее решение для ваших задач."},{"id":"cli/package-manager/easyp-vs-buf::easyp-git::2","title":"EasyP против Buf: управление пакетами","section":"EasyP: децентрализованный подход на базе Git","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp-git","headings":["EasyP: децентрализованный подход на базе Git"],"excerpt":"EasyP: децентрализованный подход на базе Git","content":"EasyP: децентрализованный подход на базе Git"},{"id":"cli/package-manager/easyp-vs-buf::buf-bsr::3","title":"EasyP против Buf: управление пакетами","section":"Buf: централизованный реестр (BSR)","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf-bsr","headings":["Buf: централизованный реестр (BSR)"],"excerpt":"Buf: централизованный реестр (BSR)","content":"Buf: централизованный реестр (BSR)"},{"id":"cli/package-manager/easyp-vs-buf::top::4","title":"EasyP против Buf: управление пакетами","section":"Краткое резюме различий","path":"/docs/guide/cli/package-manager/easyp-vs-buf","headings":["Краткое резюме различий"],"excerpt":"Краткое резюме различий Аспект EasyP Buf -------- ------- ----- **Архитектура** Децентрализованная (Git) Централизованная (реестр BSR) **Источник зависимостей** Любой Git репозиторий Только модули BSR **Единая точка отка","content":"Краткое резюме различий Аспект EasyP Buf -------- ------- ----- **Архитектура** Децентрализованная (Git) Централизованная (реестр BSR) **Источник зависимостей** Любой Git репозиторий Только модули BSR **Единая точка отказа** Нет Да (buf.build) **Enterprise / air‑gapped** Полная поддержка Требует доступа к BSR или приватного BSR **Аутентификация** Git (SSH / HTTPS) Токены Buf + Git **Vendor lock‑in** Отсутствует Привязка к экосистеме Buf **Частные репозитории** Нативно через Git Нужно опубликовать в BSR **Оффлайн поддержка** Полная (через vendoring) Ограничена (кэшированные модули) **Стоимость** Бесплатно (использует существующий Git) Бесплатный тариф + платные планы **Сложность настройки** Минимальная Средняя (настройка BSR)"},{"id":"cli/package-manager/easyp-vs-buf::top::5","title":"EasyP против Buf: управление пакетами","section":"Подробное сравнение возможностей","path":"/docs/guide/cli/package-manager/easyp-vs-buf","headings":["Подробное сравнение возможностей"],"excerpt":"Подробное сравнение возможностей","content":"Подробное сравнение возможностей"},{"id":"cli/package-manager/easyp-vs-buf::1::6","title":"EasyP против Buf: управление пакетами","section":"1. Философия управления зависимостями","path":"/docs/guide/cli/package-manager/easyp-vs-buf#1","headings":["1. Философия управления зависимостями"],"excerpt":"Философия управления зависимостями","content":"Философия управления зависимостями"},{"id":"cli/package-manager/easyp-vs-buf::easyp-git::7","title":"EasyP против Buf: управление пакетами","section":"EasyP: «Любой Git репозиторий — это пакет»","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp-git","headings":["EasyP: «Любой Git репозиторий — это пакет»"],"excerpt":"EasyP: «Любой Git репозиторий — это пакет»","content":"EasyP: «Любой Git репозиторий — это пакет»"},{"id":"cli/package-manager/easyp-vs-buf::easyp-git::8","title":"EasyP против Buf: управление пакетами","section":"EasyP: «Любой Git репозиторий — это пакет»","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp-git","headings":["EasyP: «Любой Git репозиторий — это пакет»"],"excerpt":"EasyP: «Любой Git репозиторий — это пакет» **Преимущества:** ✅ Использование любого существующего репозитория сразу ✅ Не нужно «публиковать» в отдельный реестр ✅ Истинный источник версий — Git ✅ Работает с приватными сер","content":"EasyP: «Любой Git репозиторий — это пакет» **Преимущества:** ✅ Использование любого существующего репозитория сразу ✅ Не нужно «публиковать» в отдельный реестр ✅ Истинный источник версий — Git ✅ Работает с приватными серверами без доп. настроек"},{"id":"cli/package-manager/easyp-vs-buf::buf::9","title":"EasyP против Buf: управление пакетами","section":"Buf: «Сначала реестр»","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf","headings":["Buf: «Сначала реестр»"],"excerpt":"Buf: «Сначала реестр» **Преимущества:** ✅ Курируемые, проверенные модули ✅ Богатые метаданные и документация ✅ Визуализация графа зависимостей ✅ Принуждение семантического версионирования","content":"Buf: «Сначала реестр» **Преимущества:** ✅ Курируемые, проверенные модули ✅ Богатые метаданные и документация ✅ Визуализация графа зависимостей ✅ Принуждение семантического версионирования"},{"id":"cli/package-manager/easyp-vs-buf::buf::10","title":"EasyP против Buf: управление пакетами","section":"Buf: «Сначала реестр»","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf","headings":["Buf: «Сначала реестр»"],"excerpt":"Buf: «Сначала реестр» **Ограничения:** ❌ Нужно опубликовать в BSR перед использованием ❌ Требует аккаунт и аутентификацию ❌ Нельзя напрямую сослаться на произвольный Git репозиторий","content":"Buf: «Сначала реестр» **Ограничения:** ❌ Нужно опубликовать в BSR перед использованием ❌ Требует аккаунт и аутентификацию ❌ Нельзя напрямую сослаться на произвольный Git репозиторий"},{"id":"cli/package-manager/easyp-vs-buf::2-airgapped::11","title":"EasyP против Buf: управление пакетами","section":"2. Корпоративные и изолированные (air‑gapped) среды","path":"/docs/guide/cli/package-manager/easyp-vs-buf#2-airgapped","headings":["2. Корпоративные и изолированные (air‑gapped) среды"],"excerpt":"Корпоративные и изолированные (air‑gapped) среды","content":"Корпоративные и изолированные (air‑gapped) среды"},{"id":"cli/package-manager/easyp-vs-buf::easyp::12","title":"EasyP против Buf: управление пакетами","section":"EasyP: Полноценная оффлайн‑поддержка","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["EasyP: Полноценная оффлайн‑поддержка"],"excerpt":"EasyP: Полноценная оффлайн‑поддержка **Сценарий**: крупная компания со строгими сетевыми политиками","content":"EasyP: Полноценная оффлайн‑поддержка **Сценарий**: крупная компания со строгими сетевыми политиками"},{"id":"cli/package-manager/easyp-vs-buf::easyp::13","title":"EasyP против Buf: управление пакетами","section":"EasyP: Полноценная оффлайн‑поддержка","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["EasyP: Полноценная оффлайн‑поддержка"],"excerpt":"EasyP: Полноценная оффлайн‑поддержка ```bash Среда с доступом в интернет easyp mod download # Скачивает в ~/.easyp/ easyp mod vendor # Создает easyp_vendor/","content":"EasyP: Полноценная оффлайн‑поддержка ```bash Среда с доступом в интернет easyp mod download # Скачивает в ~/.easyp/ easyp mod vendor # Создает easyp_vendor/"},{"id":"cli/package-manager/easyp-vs-buf::easyp::14","title":"EasyP против Buf: управление пакетами","section":"EasyP: Полноценная оффлайн‑поддержка","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["EasyP: Полноценная оффлайн‑поддержка"],"excerpt":"EasyP: Полноценная оффлайн‑поддержка Перенос в изолированный сегмент tar -czf easyp-deps.tar.gz ~/.easyp easyp_vendor/ ... перенос архива ...","content":"EasyP: Полноценная оффлайн‑поддержка Перенос в изолированный сегмент tar -czf easyp-deps.tar.gz ~/.easyp easyp_vendor/ ... перенос архива ..."},{"id":"cli/package-manager/easyp-vs-buf::easyp::15","title":"EasyP против Buf: управление пакетами","section":"EasyP: Полноценная оффлайн‑поддержка","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["EasyP: Полноценная оффлайн‑поддержка"],"excerpt":"EasyP: Полноценная оффлайн‑поддержка В изолированной среде tar -xzf easyp-deps.tar.gz export EASYPPATH=$PWD/.easyp easyp generate # Работает оффлайн ```","content":"EasyP: Полноценная оффлайн‑поддержка В изолированной среде tar -xzf easyp-deps.tar.gz export EASYPPATH=$PWD/.easyp easyp generate # Работает оффлайн ```"},{"id":"cli/package-manager/easyp-vs-buf::easyp::16","title":"EasyP против Buf: управление пакетами","section":"EasyP: Полноценная оффлайн‑поддержка","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["EasyP: Полноценная оффлайн‑поддержка"],"excerpt":"EasyP: Полноценная оффлайн‑поддержка **Плюсы:** ✅ Не зависит от внешних сервисов ✅ Не нужен внутренний реестр ✅ Использует существующую Git инфраструктуру ✅ Простая файловая дистрибуция","content":"EasyP: Полноценная оффлайн‑поддержка **Плюсы:** ✅ Не зависит от внешних сервисов ✅ Не нужен внутренний реестр ✅ Использует существующую Git инфраструктуру ✅ Простая файловая дистрибуция"},{"id":"cli/package-manager/easyp-vs-buf::buf::17","title":"EasyP против Buf: управление пакетами","section":"Buf: Требует инфраструктуру реестра","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf","headings":["Buf: Требует инфраструктуру реестра"],"excerpt":"Buf: Требует инфраструктуру реестра ```bash Вариант 1: использовать buf.build (нужен интернет) buf mod download","content":"Buf: Требует инфраструктуру реестра ```bash Вариант 1: использовать buf.build (нужен интернет) buf mod download"},{"id":"cli/package-manager/easyp-vs-buf::buf::18","title":"EasyP против Buf: управление пакетами","section":"Buf: Требует инфраструктуру реестра","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf","headings":["Buf: Требует инфраструктуру реестра"],"excerpt":"Buf: Требует инфраструктуру реестра Вариант 2: поднимать приватный BSR (сложно) Развернуть сервер реестра Перепубликовать все модули внутрь Настроить доступы, аутентификацию Поддерживать работоспособность ```","content":"Buf: Требует инфраструктуру реестра Вариант 2: поднимать приватный BSR (сложно) Развернуть сервер реестра Перепубликовать все модули внутрь Настроить доступы, аутентификацию Поддерживать работоспособность ```"},{"id":"cli/package-manager/easyp-vs-buf::buf::19","title":"EasyP против Buf: управление пакетами","section":"Buf: Требует инфраструктуру реестра","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf","headings":["Buf: Требует инфраструктуру реестра"],"excerpt":"Buf: Требует инфраструктуру реестра **Минусы:** ❌ Постоянный интернет или дорогой приватный BSR ❌ Сложная инфраструктура для частных установок ❌ Все модули нужно републиковать ❌ Дополнительные операционные затраты","content":"Buf: Требует инфраструктуру реестра **Минусы:** ❌ Постоянный интернет или дорогой приватный BSR ❌ Сложная инфраструктура для частных установок ❌ Все модули нужно републиковать ❌ Дополнительные операционные затраты"},{"id":"cli/package-manager/easyp-vs-buf::easyp::20","title":"EasyP против Buf: управление пакетами","section":"EasyP: Прямой контроль","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["EasyP: Прямой контроль"],"excerpt":"EasyP: Прямой контроль ```yaml Полный контроль источников deps: # Публичный репозиторий — ваша конкретная версия - github.com/googleapis/googleapis@common-protos-1_3_1","content":"EasyP: Прямой контроль ```yaml Полный контроль источников deps: # Публичный репозиторий — ваша конкретная версия - github.com/googleapis/googleapis@common-protos-1_3_1"},{"id":"cli/package-manager/easyp-vs-buf::easyp::21","title":"EasyP против Buf: управление пакетами","section":"EasyP: Прямой контроль","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["EasyP: Прямой контроль"],"excerpt":"EasyP: Прямой контроль Внутренний репозиторий - gitlab.company.com/security/validated-protos@v1.0.0","content":"EasyP: Прямой контроль Внутренний репозиторий - gitlab.company.com/security/validated-protos@v1.0.0"},{"id":"cli/package-manager/easyp-vs-buf::easyp::22","title":"EasyP против Buf: управление пакетами","section":"EasyP: Прямой контроль","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["EasyP: Прямой контроль"],"excerpt":"EasyP: Прямой контроль Точный коммит (горячий фикс) - github.com/bufbuild/protoc-gen-validate@abc123def456 ```","content":"EasyP: Прямой контроль Точный коммит (горячий фикс) - github.com/bufbuild/protoc-gen-validate@abc123def456 ```"},{"id":"cli/package-manager/easyp-vs-buf::easyp::23","title":"EasyP против Buf: управление пакетами","section":"EasyP: Прямой контроль","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["EasyP: Прямой контроль"],"excerpt":"EasyP: Прямой контроль **Преимущества по безопасности:** ✅ Нет посредника — берём из исходного репозитория ✅ Аудит через историю Git ✅ Нельзя «забанить» доступ извне ✅ Свои процессы сканирования / валидации ✅ Можно форкн","content":"EasyP: Прямой контроль **Преимущества по безопасности:** ✅ Нет посредника — берём из исходного репозитория ✅ Аудит через историю Git ✅ Нельзя «забанить» доступ извне ✅ Свои процессы сканирования / валидации ✅ Можно форкнуть и удерживать критические версии"},{"id":"cli/package-manager/easyp-vs-buf::buf::24","title":"EasyP против Buf: управление пакетами","section":"Buf: Зависимость от реестра","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf","headings":["Buf: Зависимость от реестра"],"excerpt":"Buf: Зависимость от реестра **Риски:** ⚠️ Посредник контролирует доступность ⚠️ Возможны ограничения / санкции на аккаунт ⚠️ Модуль могут удалить или депрекейтнуть ⚠️ Политики обновлений диктуются стороной ⚠️ Нужно довер","content":"Buf: Зависимость от реестра **Риски:** ⚠️ Посредник контролирует доступность ⚠️ Возможны ограничения / санкции на аккаунт ⚠️ Модуль могут удалить или депрекейтнуть ⚠️ Политики обновлений диктуются стороной ⚠️ Нужно доверять внешней безопасности"},{"id":"cli/package-manager/easyp-vs-buf::1::25","title":"EasyP против Buf: управление пакетами","section":"Сценарий 1: Стартап с публичными зависимостями","path":"/docs/guide/cli/package-manager/easyp-vs-buf#1","headings":["Сценарий 1: Стартап с публичными зависимостями"],"excerpt":"Сценарий 1: Стартап с публичными зависимостями **EasyP:**","content":"Сценарий 1: Стартап с публичными зависимостями **EasyP:**"},{"id":"cli/package-manager/easyp-vs-buf::1::26","title":"EasyP против Buf: управление пакетами","section":"Сценарий 1: Стартап с публичными зависимостями","path":"/docs/guide/cli/package-manager/easyp-vs-buf#1","headings":["Сценарий 1: Стартап с публичными зависимостями"],"excerpt":"Сценарий 1: Стартап с публичными зависимостями **Buf:**","content":"Сценарий 1: Стартап с публичными зависимостями **Buf:**"},{"id":"cli/package-manager/easyp-vs-buf::1::27","title":"EasyP против Buf: управление пакетами","section":"Сценарий 1: Стартап с публичными зависимостями","path":"/docs/guide/cli/package-manager/easyp-vs-buf#1","headings":["Сценарий 1: Стартап с публичными зависимостями"],"excerpt":"Сценарий 1: Стартап с публичными зависимостями **Итог:** Паритет — оба хорошо подходят для публичных пакетов.","content":"Сценарий 1: Стартап с публичными зависимостями **Итог:** Паритет — оба хорошо подходят для публичных пакетов."},{"id":"cli/package-manager/easyp-vs-buf::2::28","title":"EasyP против Buf: управление пакетами","section":"Сценарий 2: Компания со смешанными публичными/приватными зависимостями","path":"/docs/guide/cli/package-manager/easyp-vs-buf#2","headings":["Сценарий 2: Компания со смешанными публичными/приватными зависимостями"],"excerpt":"Сценарий 2: Компания со смешанными публичными/приватными зависимостями **EasyP:**","content":"Сценарий 2: Компания со смешанными публичными/приватными зависимостями **EasyP:**"},{"id":"cli/package-manager/easyp-vs-buf::2::29","title":"EasyP против Buf: управление пакетами","section":"Сценарий 2: Компания со смешанными публичными/приватными зависимостями","path":"/docs/guide/cli/package-manager/easyp-vs-buf#2","headings":["Сценарий 2: Компания со смешанными публичными/приватными зависимостями"],"excerpt":"Сценарий 2: Компания со смешанными публичными/приватными зависимостями **Buf:**","content":"Сценарий 2: Компания со смешанными публичными/приватными зависимостями **Buf:**"},{"id":"cli/package-manager/easyp-vs-buf::2::30","title":"EasyP против Buf: управление пакетами","section":"Сценарий 2: Компания со смешанными публичными/приватными зависимостями","path":"/docs/guide/cli/package-manager/easyp-vs-buf#2","headings":["Сценарий 2: Компания со смешанными публичными/приватными зависимостями"],"excerpt":"Сценарий 2: Компания со смешанными публичными/приватными зависимостями **Итог:** **EasyP** — не требует публикации внутрь BSR.","content":"Сценарий 2: Компания со смешанными публичными/приватными зависимостями **Итог:** **EasyP** — не требует публикации внутрь BSR."},{"id":"cli/package-manager/easyp-vs-buf::3-airgap::31","title":"EasyP против Buf: управление пакетами","section":"Сценарий 3: Государственный / оборонный подрядчик (полный air‑gap)","path":"/docs/guide/cli/package-manager/easyp-vs-buf#3-airgap","headings":["Сценарий 3: Государственный / оборонный подрядчик (полный air‑gap)"],"excerpt":"Сценарий 3: Государственный / оборонный подрядчик (полный air‑gap) **EasyP:**","content":"Сценарий 3: Государственный / оборонный подрядчик (полный air‑gap) **EasyP:**"},{"id":"cli/package-manager/easyp-vs-buf::3-airgap::32","title":"EasyP против Buf: управление пакетами","section":"Сценарий 3: Государственный / оборонный подрядчик (полный air‑gap)","path":"/docs/guide/cli/package-manager/easyp-vs-buf#3-airgap","headings":["Сценарий 3: Государственный / оборонный подрядчик (полный air‑gap)"],"excerpt":"Сценарий 3: Государственный / оборонный подрядчик (полный air‑gap) **Buf:**","content":"Сценарий 3: Государственный / оборонный подрядчик (полный air‑gap) **Buf:**"},{"id":"cli/package-manager/easyp-vs-buf::3-airgap::33","title":"EasyP против Buf: управление пакетами","section":"Сценарий 3: Государственный / оборонный подрядчик (полный air‑gap)","path":"/docs/guide/cli/package-manager/easyp-vs-buf#3-airgap","headings":["Сценарий 3: Государственный / оборонный подрядчик (полный air‑gap)"],"excerpt":"Сценарий 3: Государственный / оборонный подрядчик (полный air‑gap) **Итог:** **EasyP** — значительно проще.","content":"Сценарий 3: Государственный / оборонный подрядчик (полный air‑gap) **Итог:** **EasyP** — значительно проще."},{"id":"cli/package-manager/easyp-vs-buf::4::34","title":"EasyP против Buf: управление пакетами","section":"Сценарий 4: Комплаенс и аудит","path":"/docs/guide/cli/package-manager/easyp-vs-buf#4","headings":["Сценарий 4: Комплаенс и аудит"],"excerpt":"Сценарий 4: Комплаенс и аудит **EasyP:** ✅ Прямой аудит изменений (коммиты) ✅ Нет внешних точек зависимости в проде ✅ Повторяемость через фиксированные коммиты / vendor ✅ Управление уязвимостями — в ваших руках","content":"Сценарий 4: Комплаенс и аудит **EasyP:** ✅ Прямой аудит изменений (коммиты) ✅ Нет внешних точек зависимости в проде ✅ Повторяемость через фиксированные коммиты / vendor ✅ Управление уязвимостями — в ваших руках"},{"id":"cli/package-manager/easyp-vs-buf::4::35","title":"EasyP против Buf: управление пакетами","section":"Сценарий 4: Комплаенс и аудит","path":"/docs/guide/cli/package-manager/easyp-vs-buf#4","headings":["Сценарий 4: Комплаенс и аудит"],"excerpt":"Сценарий 4: Комплаенс и аудит **Buf:** ⚠️ Нужно учитывать BSR в области аудита ⚠️ Дополнительный риск третьей стороны ⚠️ Модули — внешние контролируемые артефакты ⚠️ Сложнее трассировать от реестра к исходникам","content":"Сценарий 4: Комплаенс и аудит **Buf:** ⚠️ Нужно учитывать BSR в области аудита ⚠️ Дополнительный риск третьей стороны ⚠️ Модули — внешние контролируемые артефакты ⚠️ Сложнее трассировать от реестра к исходникам"},{"id":"cli/package-manager/easyp-vs-buf::4::36","title":"EasyP против Buf: управление пакетами","section":"Сценарий 4: Комплаенс и аудит","path":"/docs/guide/cli/package-manager/easyp-vs-buf#4","headings":["Сценарий 4: Комплаенс и аудит"],"excerpt":"Сценарий 4: Комплаенс и аудит **Итог:** **EasyP** — проще для комплаенса.","content":"Сценарий 4: Комплаенс и аудит **Итог:** **EasyP** — проще для комплаенса."},{"id":"cli/package-manager/easyp-vs-buf::easyp::37","title":"EasyP против Buf: управление пакетами","section":"EasyP: Нулевая дополнительная инфраструктура","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["EasyP: Нулевая дополнительная инфраструктура"],"excerpt":"EasyP: Нулевая дополнительная инфраструктура **Затраты:** ✅ $0 — используете существующий Git ✅ Нет дополнительных сервисов/серверов ✅ Нет лицензирования ✅ Масштабирование в рамках Git","content":"EasyP: Нулевая дополнительная инфраструктура **Затраты:** ✅ $0 — используете существующий Git ✅ Нет дополнительных сервисов/серверов ✅ Нет лицензирования ✅ Масштабирование в рамках Git"},{"id":"cli/package-manager/easyp-vs-buf::easyp::38","title":"EasyP против Buf: управление пакетами","section":"EasyP: Нулевая дополнительная инфраструктура","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["EasyP: Нулевая дополнительная инфраструктура"],"excerpt":"EasyP: Нулевая дополнительная инфраструктура **Инфраструктура:** Использует текущие репозитории (GitHub/GitLab/и т.д.) Аутентификация — штатная Резервирование/DR — как уже настроено для Git","content":"EasyP: Нулевая дополнительная инфраструктура **Инфраструктура:** Использует текущие репозитории (GitHub/GitLab/и т.д.) Аутентификация — штатная Резервирование/DR — как уже настроено для Git"},{"id":"cli/package-manager/easyp-vs-buf::buf::39","title":"EasyP против Buf: управление пакетами","section":"Buf: Затраты на реестр","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf","headings":["Buf: Затраты на реестр"],"excerpt":"Buf: Затраты на реестр **Hosted BSR (buf.build):** ✅ Бесплатный уровень ❌ Платные тарифы для приватного и расширенного использования ❌ Потенциальные изменения ценовой политики ❌ Вопросы локализации данных","content":"Buf: Затраты на реестр **Hosted BSR (buf.build):** ✅ Бесплатный уровень ❌ Платные тарифы для приватного и расширенного использования ❌ Потенциальные изменения ценовой политики ❌ Вопросы локализации данных"},{"id":"cli/package-manager/easyp-vs-buf::buf::40","title":"EasyP против Buf: управление пакетами","section":"Buf: Затраты на реестр","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf","headings":["Buf: Затраты на реестр"],"excerpt":"Buf: Затраты на реестр **Приватный BSR:** ❌ Серверы, БД, балансировка ❌ Мониторинг, обновления, бэкапы ❌ Лицензирование enterprise функционала ❌ Доп. планирование отказоустойчивости","content":"Buf: Затраты на реестр **Приватный BSR:** ❌ Серверы, БД, балансировка ❌ Мониторинг, обновления, бэкапы ❌ Лицензирование enterprise функционала ❌ Доп. планирование отказоустойчивости"},{"id":"cli/package-manager/easyp-vs-buf::easyp::41","title":"EasyP против Buf: управление пакетами","section":"EasyP: Нет привязки","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["EasyP: Нет привязки"],"excerpt":"EasyP: Нет привязки **Миграция ИЗ EasyP:** (Обычные Git ссылки — легко перенести в другой инструмент.)","content":"EasyP: Нет привязки **Миграция ИЗ EasyP:** (Обычные Git ссылки — легко перенести в другой инструмент.)"},{"id":"cli/package-manager/easyp-vs-buf::easyp::42","title":"EasyP против Buf: управление пакетами","section":"EasyP: Нет привязки","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["EasyP: Нет привязки"],"excerpt":"EasyP: Нет привязки **Миграция В EasyP:**","content":"EasyP: Нет привязки **Миграция В EasyP:**"},{"id":"cli/package-manager/easyp-vs-buf::buf-lockin::43","title":"EasyP против Buf: управление пакетами","section":"Buf: Потенциальный lock‑in","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf-lockin","headings":["Buf: Потенциальный lock‑in"],"excerpt":"Buf: Потенциальный lock‑in **Миграция ИЗ Buf:** ❌ Нужно сопоставить BSR модули с исходными Git репо ❌ Имена модулей BSR не совпадают с URL ❌ Возможна потеря удобных метаданных ❌ Сложно при глубокой интеграции с BSR","content":"Buf: Потенциальный lock‑in **Миграция ИЗ Buf:** ❌ Нужно сопоставить BSR модули с исходными Git репо ❌ Имена модулей BSR не совпадают с URL ❌ Возможна потеря удобных метаданных ❌ Сложно при глубокой интеграции с BSR"},{"id":"cli/package-manager/easyp-vs-buf::buf-lockin::44","title":"EasyP против Buf: управление пакетами","section":"Buf: Потенциальный lock‑in","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf-lockin","headings":["Buf: Потенциальный lock‑in"],"excerpt":"Buf: Потенциальный lock‑in **Миграция В Buf:** ❌ Нужно опубликовать всё в BSR ❌ Нельзя ссылаться напрямую на Git ❌ Принять workflow BSR (push/pull модулей)","content":"Buf: Потенциальный lock‑in **Миграция В Buf:** ❌ Нужно опубликовать всё в BSR ❌ Нельзя ссылаться напрямую на Git ❌ Принять workflow BSR (push/pull модулей)"},{"id":"cli/package-manager/easyp-vs-buf::easyp::45","title":"EasyP против Buf: управление пакетами","section":"Выберите EasyP, если:","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["Выберите EasyP, если:"],"excerpt":"Выберите EasyP, если: ✅ **Air‑gapped / закрытые среды** Нужна работа без внешних сервисов Строгий комплаенс / контроль цепочки поставок","content":"Выберите EasyP, если: ✅ **Air‑gapped / закрытые среды** Нужна работа без внешних сервисов Строгий комплаенс / контроль цепочки поставок"},{"id":"cli/package-manager/easyp-vs-buf::easyp::46","title":"EasyP против Buf: управление пакетами","section":"Выберите EasyP, если:","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["Выберите EasyP, если:"],"excerpt":"Выберите EasyP, если: ✅ **Фокус на безопасности** Контроль источников зависимостей Минимизация рисков третьих сторон","content":"Выберите EasyP, если: ✅ **Фокус на безопасности** Контроль источников зависимостей Минимизация рисков третьих сторон"},{"id":"cli/package-manager/easyp-vs-buf::easyp::47","title":"EasyP против Buf: управление пакетами","section":"Выберите EasyP, если:","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["Выберите EasyP, если:"],"excerpt":"Выберите EasyP, если: ✅ **Git‑центричная культура** Частные репозитории — норма Не хотите добавлять новый ключевой сервис","content":"Выберите EasyP, если: ✅ **Git‑центричная культура** Частные репозитории — норма Не хотите добавлять новый ключевой сервис"},{"id":"cli/package-manager/easyp-vs-buf::easyp::48","title":"EasyP против Buf: управление пакетами","section":"Выберите EasyP, если:","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["Выберите EasyP, если:"],"excerpt":"Выберите EasyP, если: ✅ **Ограниченный бюджет** Минимизация операционных расходов Предсказуемая стоимость = 0","content":"Выберите EasyP, если: ✅ **Ограниченный бюджет** Минимизация операционных расходов Предсказуемая стоимость = 0"},{"id":"cli/package-manager/easyp-vs-buf::easyp::49","title":"EasyP против Buf: управление пакетами","section":"Выберите EasyP, если:","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["Выберите EasyP, если:"],"excerpt":"Выберите EasyP, если: ✅ **Смешанные публичные/частные зависимости** Не хотите перекладывать всё в реестр Нужна гибкость форматов и размещения","content":"Выберите EasyP, если: ✅ **Смешанные публичные/частные зависимости** Не хотите перекладывать всё в реестр Нужна гибкость форматов и размещения"},{"id":"cli/package-manager/easyp-vs-buf::buf::50","title":"EasyP против Buf: управление пакетами","section":"Выберите Buf, если:","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf","headings":["Выберите Buf, если:"],"excerpt":"Выберите Buf, если: ✅ **Глубокая интеграция в экосистему BSR** Уже используете линтеры / генерацию Buf Нужны курируемые официальные модули Важны метаданные и граф зависимостей","content":"Выберите Buf, если: ✅ **Глубокая интеграция в экосистему BSR** Уже используете линтеры / генерацию Buf Нужны курируемые официальные модули Важны метаданные и граф зависимостей"},{"id":"cli/package-manager/easyp-vs-buf::buf::51","title":"EasyP против Buf: управление пакетами","section":"Выберите Buf, если:","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf","headings":["Выберите Buf, если:"],"excerpt":"Выберите Buf, если: ✅ **Сотрудничество и открытая разработка** Централизованное обнаружение модулей Совместная работа над общими пакетами","content":"Выберите Buf, если: ✅ **Сотрудничество и открытая разработка** Централизованное обнаружение модулей Совместная работа над общими пакетами"},{"id":"cli/package-manager/easyp-vs-buf::buf::52","title":"EasyP против Buf: управление пакетами","section":"Выберите Buf, если:","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf","headings":["Выберите Buf, если:"],"excerpt":"Выберите Buf, если: ✅ **Команда новичков в protobuf** Требуется «направляющая» структура Ценность документации внутри реестра","content":"Выберите Buf, если: ✅ **Команда новичков в protobuf** Требуется «направляющая» структура Ценность документации внутри реестра"},{"id":"cli/package-manager/easyp-vs-buf::buf::53","title":"EasyP против Buf: управление пакетами","section":"Выберите Buf, если:","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf","headings":["Выберите Buf, если:"],"excerpt":"Выберите Buf, если: ✅ **Небольшой набор публичных зависимостей** В основном используете популярные общие пакеты Вас устраивает зависимость от BSR","content":"Выберите Buf, если: ✅ **Небольшой набор публичных зависимостей** В основном используете популярные общие пакеты Вас устраивает зависимость от BSR"},{"id":"cli/package-manager/easyp-vs-buf::buf-easyp::54","title":"EasyP против Buf: управление пакетами","section":"Переход с Buf на EasyP","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf-easyp","headings":["Переход с Buf на EasyP"],"excerpt":"Переход с Buf на EasyP Найдите исходные Git репозитории для каждого модуля BSR Сопоставьте имена BSR → Git ссылки (с версиями/тегами) Обновите конфигурацию (easyp.yaml) Протестируйте генерацию и совместимость","content":"Переход с Buf на EasyP Найдите исходные Git репозитории для каждого модуля BSR Сопоставьте имена BSR → Git ссылки (с версиями/тегами) Обновите конфигурацию (easyp.yaml) Протестируйте генерацию и совместимость"},{"id":"cli/package-manager/easyp-vs-buf::buf-easyp::55","title":"EasyP против Buf: управление пакетами","section":"Переход с Buf на EasyP","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf-easyp","headings":["Переход с Buf на EasyP"],"excerpt":"Переход с Buf на EasyP ```yaml Было (buf.yaml) deps: - buf.build/googleapis/googleapis - buf.build/grpc/grpc","content":"Переход с Buf на EasyP ```yaml Было (buf.yaml) deps: - buf.build/googleapis/googleapis - buf.build/grpc/grpc"},{"id":"cli/package-manager/easyp-vs-buf::buf-easyp::56","title":"EasyP против Buf: управление пакетами","section":"Переход с Buf на EasyP","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf-easyp","headings":["Переход с Buf на EasyP"],"excerpt":"Переход с Buf на EasyP Стало (easyp.yaml) deps: - github.com/googleapis/googleapis@common-protos-1_3_1 - github.com/grpc/grpc@v1.50.0 ```","content":"Переход с Buf на EasyP Стало (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::easyp-buf::57","title":"EasyP против Buf: управление пакетами","section":"Переход с EasyP на Buf","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp-buf","headings":["Переход с EasyP на Buf"],"excerpt":"Переход с EasyP на Buf Опубликуйте используемые репозитории как модули BSR Настройте аутентификацию / организацию Buf Замените Git ссылки на BSR модули Перейдите к push/pull workflow Buf","content":"Переход с EasyP на Buf Опубликуйте используемые репозитории как модули BSR Настройте аутентификацию / организацию Buf Замените Git ссылки на BSR модули Перейдите к push/pull workflow Buf"},{"id":"cli/package-manager/easyp-vs-buf::top::58","title":"EasyP против Buf: управление пакетами","section":"Заключение","path":"/docs/guide/cli/package-manager/easyp-vs-buf","headings":["Заключение"],"excerpt":"Заключение Оба инструмента решают задачу управления зависимостями protobuf, но подходят под разные приоритеты:","content":"Заключение Оба инструмента решают задачу управления зависимостями protobuf, но подходят под разные приоритеты:"},{"id":"cli/package-manager/easyp-vs-buf::top::59","title":"EasyP против Buf: управление пакетами","section":"Заключение","path":"/docs/guide/cli/package-manager/easyp-vs-buf","headings":["Заключение"],"excerpt":"Заключение **Сильные стороны EasyP:** Корпоративные / изолированные среды Жёсткие требования безопасности и аудита Минимальные затраты и отсутствие доп. инфраструктуры Прямое использование Git (без промежуточного слоя) П","content":"Заключение **Сильные стороны EasyP:** Корпоративные / изолированные среды Жёсткие требования безопасности и аудита Минимальные затраты и отсутствие доп. инфраструктуры Прямое использование Git (без промежуточного слоя) Простота масштабирования"},{"id":"cli/package-manager/easyp-vs-buf::top::60","title":"EasyP против Buf: управление пакетами","section":"Заключение","path":"/docs/guide/cli/package-manager/easyp-vs-buf","headings":["Заключение"],"excerpt":"Заключение **Сильные стороны Buf:** Богатая экосистема вокруг реестра Курируемые и документированные модули Удобство для новых команд в protobuf Средства визуализации и централизованного обмена","content":"Заключение **Сильные стороны Buf:** Богатая экосистема вокруг реестра Курируемые и документированные модули Удобство для новых команд в protobuf Средства визуализации и централизованного обмена"},{"id":"cli/package-manager/easyp-vs-buf::top::61","title":"EasyP против Buf: управление пакетами","section":"Заключение","path":"/docs/guide/cli/package-manager/easyp-vs-buf","headings":["Заключение"],"excerpt":"Заключение Выбор часто сводится к балансу между **контролем vs. удобством**, **безопасностью vs. централизованными функциями**, и **стоимостью vs. managed‑сервисом**.","content":"Заключение Выбор часто сводится к балансу между **контролем vs. удобством**, **безопасностью vs. централизованными функциями**, и **стоимостью vs. managed‑сервисом**."},{"id":"cli/package-manager/easyp-vs-buf::top::62","title":"EasyP против Buf: управление пакетами","section":"Заключение","path":"/docs/guide/cli/package-manager/easyp-vs-buf","headings":["Заключение"],"excerpt":"Заключение Для большинства enterprise‑окружений децентрализованный Git‑подход EasyP обеспечивает нужные гибкость, безопасность и предсказуемость расходов, тогда как Buf отлично подходит командам, которым важна централизо","content":"Заключение Для большинства enterprise‑окружений децентрализованный Git‑подход EasyP обеспечивает нужные гибкость, безопасность и предсказуемость расходов, тогда как Buf отлично подходит командам, которым важна централизованная коллаборация и богатая экосистема вокруг реестра."},{"id":"cli/package-manager/package-manager::top::0","title":"Менеджер пакетов","path":"/docs/guide/cli/package-manager/package-manager","headings":[],"excerpt":"EasyP предоставляет мощный менеджер пакетов для protobuf‑зависимостей, упрощающий их управление за счёт децентрализованного подхода на базе Git. В отличие от централизованных решений, EasyP работает напрямую с Git‑репози","content":"EasyP предоставляет мощный менеджер пакетов для protobuf‑зависимостей, упрощающий их управление за счёт децентрализованного подхода на базе Git. В отличие от централизованных решений, EasyP работает напрямую с Git‑репозиториями, давая вам полный контроль."},{"id":"cli/package-manager/package-manager::top::1","title":"Менеджер пакетов","section":"Обзор","path":"/docs/guide/cli/package-manager/package-manager","headings":["Обзор"],"excerpt":"Обзор Менеджер пакетов EasyP следует философии **Go modules** — любой Git‑репозиторий может быть источником. Это даёт преимущества:","content":"Обзор Менеджер пакетов EasyP следует философии **Go modules** — любой Git‑репозиторий может быть источником. Это даёт преимущества:"},{"id":"cli/package-manager/package-manager::top::2","title":"Менеджер пакетов","section":"Обзор","path":"/docs/guide/cli/package-manager/package-manager","headings":["Обзор"],"excerpt":"Обзор **Децентрализация** — нет единой точки отказа или контроля **Безопасность** — прямой доступ к исходникам **Гибкость** — публичные, приватные и корпоративные репозитории **Воспроизводимость** — lock‑файлы обеспечива","content":"Обзор **Децентрализация** — нет единой точки отказа или контроля **Безопасность** — прямой доступ к исходникам **Гибкость** — публичные, приватные и корпоративные репозитории **Воспроизводимость** — lock‑файлы обеспечивают одинаковые сборки **Производительность** — локальный кеш сокращает сетевые запросы"},{"id":"cli/package-manager/package-manager::top::3","title":"Менеджер пакетов","section":"Основные возможности","path":"/docs/guide/cli/package-manager/package-manager","headings":["Основные возможности"],"excerpt":"Основные возможности Возможность Описание ------------- ---------- **Git-Native** Любой Git репозиторий, не нужен спец‑сервер **Множество форматов версий** Теги, коммиты, псевдо‑версии, latest **Lock Files** Воспроизводи","content":"Основные возможности Возможность Описание ------------- ---------- **Git-Native** Любой Git репозиторий, не нужен спец‑сервер **Множество форматов версий** Теги, коммиты, псевдо‑версии, latest **Lock Files** Воспроизводимые сборки через easyp.lock **Локальный кеш** Архитектура как у Go modules **Vendoring** Локальное копирование для оффлайн сборок **YAML конфигурация** Простые и читаемые декларации"},{"id":"cli/package-manager/package-manager::top::4","title":"Менеджер пакетов","section":"Архитектура","path":"/docs/guide/cli/package-manager/package-manager","headings":["Архитектура"],"excerpt":"Архитектура EasyP использует двухуровневый кеш, вдохновлённый Go modules:","content":"Архитектура EasyP использует двухуровневый кеш, вдохновлённый Go modules:"},{"id":"cli/package-manager/package-manager::top::5","title":"Менеджер пакетов","section":"Расположение кеша","path":"/docs/guide/cli/package-manager/package-manager","headings":["Расположение кеша"],"excerpt":"Расположение кеша Окружение Путь Как задать ----------- ------ ----------- **По умолчанию** $HOME/.easyp Автоматически **Свое** Любая директория Переменная EASYPPATH **CI/CD** В каталоге проекта export EASYPPATH=$CI_PROJ","content":"Расположение кеша Окружение Путь Как задать ----------- ------ ----------- **По умолчанию** $HOME/.easyp Автоматически **Свое** Любая директория Переменная EASYPPATH **CI/CD** В каталоге проекта export EASYPPATH=$CI_PROJECT_DIR/.easyp"},{"id":"cli/package-manager/package-manager::top::6","title":"Менеджер пакетов","section":"Базовая конфигурация","path":"/docs/guide/cli/package-manager/package-manager","headings":["Базовая конфигурация"],"excerpt":"Базовая конфигурация Зависимости описываются в easyp.yaml:","content":"Базовая конфигурация Зависимости описываются в easyp.yaml:"},{"id":"cli/package-manager/package-manager::multi-environment-setup::7","title":"Менеджер пакетов","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 # Последнее для разработки - github.com/mycompany/internal-protos # Внутренние изменения - github.com/bufbuild/protoc-gen-va","content":"Multi-Environment Setup ```yaml development.easyp.yaml deps: - github.com/googleapis/googleapis # Последнее для разработки - github.com/mycompany/internal-protos # Внутренние изменения - github.com/bufbuild/protoc-gen-validate # Новые фичи"},{"id":"cli/package-manager/package-manager::multi-environment-setup::8","title":"Менеджер пакетов","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 # Зафиксировано - github.com/mycompany/internal-protos@v2.1.0 # Стабильно - github.com/bufbuild/protoc-gen-valida","content":"Multi-Environment Setup production.easyp.yaml deps: - github.com/googleapis/googleapis@common-protos-1_3_1 # Зафиксировано - github.com/mycompany/internal-protos@v2.1.0 # Стабильно - github.com/bufbuild/protoc-gen-validate@v0.10.1 # Проверено ```"},{"id":"cli/package-manager/package-manager::top::9","title":"Менеджер пакетов","section":"Приватные репозитории","path":"/docs/guide/cli/package-manager/package-manager","headings":["Приватные репозитории"],"excerpt":"Приватные репозитории ```yaml deps: # Публичное - github.com/googleapis/googleapis@common-protos-1_3_1","content":"Приватные репозитории ```yaml deps: # Публичное - github.com/googleapis/googleapis@common-protos-1_3_1"},{"id":"cli/package-manager/package-manager::top::10","title":"Менеджер пакетов","section":"Приватные репозитории","path":"/docs/guide/cli/package-manager/package-manager","headings":["Приватные репозитории"],"excerpt":"Приватные репозитории Частные - github.com/mycompany/auth-protos@v1.5.0 - github.com/mycompany/common-types@v2.0.1","content":"Приватные репозитории Частные - github.com/mycompany/auth-protos@v1.5.0 - github.com/mycompany/common-types@v2.0.1"},{"id":"cli/package-manager/package-manager::top::11","title":"Менеджер пакетов","section":"Приватные репозитории","path":"/docs/guide/cli/package-manager/package-manager","headings":["Приватные репозитории"],"excerpt":"Приватные репозитории Внутренний GitLab - gitlab.company.com/platform/messaging-protos@v0.3.0 ```","content":"Приватные репозитории Внутренний GitLab - gitlab.company.com/platform/messaging-protos@v0.3.0 ```"},{"id":"cli/package-manager/package-manager::top::12","title":"Менеджер пакетов","section":"Стратегии версионирования","path":"/docs/guide/cli/package-manager/package-manager","headings":["Стратегии версионирования"],"excerpt":"Стратегии версионирования Поддерживаются разные способы фиксации версий:","content":"Стратегии версионирования Поддерживаются разные способы фиксации версий:"},{"id":"cli/package-manager/package-manager::1::13","title":"Менеджер пакетов","section":"1. Семантические теги (для продакшена)","path":"/docs/guide/cli/package-manager/package-manager#1","headings":["1. Семантические теги (для продакшена)"],"excerpt":"Семантические теги (для продакшена)","content":"Семантические теги (для продакшена)"},{"id":"cli/package-manager/package-manager::1::14","title":"Менеджер пакетов","section":"1. Семантические теги (для продакшена)","path":"/docs/guide/cli/package-manager/package-manager#1","headings":["1. Семантические теги (для продакшена)"],"excerpt":"Семантические теги (для продакшена) **Используйте когда:** Продакшен Стабильное потребление API Нужна воспроизводимость","content":"Семантические теги (для продакшена) **Используйте когда:** Продакшен Стабильное потребление API Нужна воспроизводимость"},{"id":"cli/package-manager/package-manager::2-development::15","title":"Менеджер пакетов","section":"2. Последний тег (development)","path":"/docs/guide/cli/package-manager/package-manager#2-development","headings":["2. Последний тег (development)"],"excerpt":"Последний тег (development) **Подходит для:** Активной разработки Получения свежих возможностей Тестирования совместимости","content":"Последний тег (development) **Подходит для:** Активной разработки Получения свежих возможностей Тестирования совместимости"},{"id":"cli/package-manager/package-manager::3-bleeding-edge::16","title":"Менеджер пакетов","section":"3. Хеш коммита (Bleeding Edge)","path":"/docs/guide/cli/package-manager/package-manager#3-bleeding-edge","headings":["3. Хеш коммита (Bleeding Edge)"],"excerpt":"Хеш коммита (Bleeding Edge) **Когда нужно:** Нерелизные фичи Тест конкретного фикса Вклад в upstream","content":"Хеш коммита (Bleeding Edge) **Когда нужно:** Нерелизные фичи Тест конкретного фикса Вклад в upstream"},{"id":"cli/package-manager/package-manager::4::17","title":"Менеджер пакетов","section":"4. Псевдо‑версии (автоматически)","path":"/docs/guide/cli/package-manager/package-manager#4","headings":["4. Псевдо‑версии (автоматически)"],"excerpt":"Псевдо‑версии (автоматически) Если нет подходящего тега — создаётся псевдо‑версия:","content":"Псевдо‑версии (автоматически) Если нет подходящего тега — создаётся псевдо‑версия:"},{"id":"cli/package-manager/package-manager::easyp-mod-download::18","title":"Менеджер пакетов","section":"easyp mod download","path":"/docs/guide/cli/package-manager/package-manager#easyp-mod-download","headings":["easyp mod download"],"excerpt":"easyp mod download Скачивает и устанавливает все объявленные зависимости.","content":"easyp mod download Скачивает и устанавливает все объявленные зависимости."},{"id":"cli/package-manager/package-manager::easyp-mod-download::19","title":"Менеджер пакетов","section":"easyp mod download","path":"/docs/guide/cli/package-manager/package-manager#easyp-mod-download","headings":["easyp mod download"],"excerpt":"easyp mod download **Что делает:** Разрешает версии (теги → коммиты) Скачивает архивы в cache/download Проверяет контрольные суммы Распаковывает в cache/mod Обновляет easyp.lock","content":"easyp mod download **Что делает:** Разрешает версии (теги → коммиты) Скачивает архивы в cache/download Проверяет контрольные суммы Распаковывает в cache/mod Обновляет easyp.lock"},{"id":"cli/package-manager/package-manager::easyp-mod-download::20","title":"Менеджер пакетов","section":"easyp mod download","path":"/docs/guide/cli/package-manager/package-manager#easyp-mod-download","headings":["easyp mod download"],"excerpt":"easyp mod download **Пример:**","content":"easyp mod download **Пример:**"},{"id":"cli/package-manager/package-manager::easyp-mod-vendor::21","title":"Менеджер пакетов","section":"easyp mod vendor","path":"/docs/guide/cli/package-manager/package-manager#easyp-mod-vendor","headings":["easyp mod vendor"],"excerpt":"easyp mod vendor Копирует все proto зависимости в локальный easyp_vendor/ для оффлайна.","content":"easyp mod vendor Копирует все proto зависимости в локальный easyp_vendor/ для оффлайна."},{"id":"cli/package-manager/package-manager::easyp-mod-vendor::22","title":"Менеджер пакетов","section":"easyp mod vendor","path":"/docs/guide/cli/package-manager/package-manager#easyp-mod-vendor","headings":["easyp mod vendor"],"excerpt":"easyp mod vendor **Сценарии:** Docker сборки Air-gapped окружения Воспроизводимость Ускорение","content":"easyp mod vendor **Сценарии:** Docker сборки Air-gapped окружения Воспроизводимость Ускорение"},{"id":"cli/package-manager/package-manager::easyp-mod-update::23","title":"Менеджер пакетов","section":"easyp mod update","path":"/docs/guide/cli/package-manager/package-manager#easyp-mod-update","headings":["easyp mod update"],"excerpt":"easyp mod update Обновляет версии согласно easyp.yaml, пересоздаёт lock.","content":"easyp mod update Обновляет версии согласно easyp.yaml, пересоздаёт lock."},{"id":"cli/package-manager/package-manager::lock::24","title":"Менеджер пакетов","section":"Lock файл","path":"/docs/guide/cli/package-manager/package-manager#lock","headings":["Lock файл"],"excerpt":"Lock файл easyp.lock фиксирует точные версии и хеш содержимого:","content":"Lock файл easyp.lock фиксирует точные версии и хеш содержимого:"},{"id":"cli/package-manager/package-manager::lock::25","title":"Менеджер пакетов","section":"Lock файл","path":"/docs/guide/cli/package-manager/package-manager#lock","headings":["Lock файл"],"excerpt":"Lock файл **Формат строки:** Путь модуля Версия (тег или псевдо) Хеш содержимого (h1:)","content":"Lock файл **Формат строки:** Путь модуля Версия (тег или псевдо) Хеш содержимого (h1:)"},{"id":"cli/package-manager/package-manager::lock::26","title":"Менеджер пакетов","section":"Lock файл","path":"/docs/guide/cli/package-manager/package-manager#lock","headings":["Lock файл"],"excerpt":"Lock файл **Практики:** ✅ Коммитить easyp.lock ✅ Осознанно обновлять mod update ✅ Ревью изменений версий ❌ Не редактировать вручную","content":"Lock файл **Практики:** ✅ Коммитить easyp.lock ✅ Осознанно обновлять mod update ✅ Ревью изменений версий ❌ Не редактировать вручную"},{"id":"cli/package-manager/package-manager::top::27","title":"Менеджер пакетов","section":"Публичные репозитории","path":"/docs/guide/cli/package-manager/package-manager","headings":["Публичные репозитории"],"excerpt":"Публичные репозитории Работают без настроек:","content":"Публичные репозитории Работают без настроек:"},{"id":"cli/package-manager/package-manager::ssh::28","title":"Менеджер пакетов","section":"SSH ключи (рекомендуется)","path":"/docs/guide/cli/package-manager/package-manager#ssh","headings":["SSH ключи (рекомендуется)"],"excerpt":"SSH ключи (рекомендуется) Конфиг остаётся с HTTPS URL:","content":"SSH ключи (рекомендуется) Конфиг остаётся с HTTPS URL:"},{"id":"cli/package-manager/package-manager::personal-access-tokens::29","title":"Менеджер пакетов","section":"Personal Access Tokens","path":"/docs/guide/cli/package-manager/package-manager#personal-access-tokens","headings":["Personal Access Tokens"],"excerpt":"Personal Access Tokens ```bash git config --global credential.helper store echo \"https://username:token@github.com\" >> ~/.git-credentials","content":"Personal Access Tokens ```bash git config --global credential.helper store echo \"https://username:token@github.com\" >> ~/.git-credentials"},{"id":"cli/package-manager/package-manager::personal-access-tokens::30","title":"Менеджер пакетов","section":"Personal Access Tokens","path":"/docs/guide/cli/package-manager/package-manager#personal-access-tokens","headings":["Personal Access Tokens"],"excerpt":"Personal Access Tokens git config --global url.\"https://username:token@github.com/mycompany\".insteadOf \"https://github.com/mycompany\" ```","content":"Personal Access Tokens git config --global url.\"https://username:token@github.com/mycompany\".insteadOf \"https://github.com/mycompany\" ```"},{"id":"cli/package-manager/package-manager::top::31","title":"Менеджер пакетов","section":"Инициализация проекта","path":"/docs/guide/cli/package-manager/package-manager","headings":["Инициализация проекта"],"excerpt":"Инициализация проекта ```bash cat > easyp.yaml << EOF deps: - github.com/googleapis/googleapis - github.com/grpc-ecosystem/grpc-gateway@v2.19.1 EOF","content":"Инициализация проекта ```bash 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::top::32","title":"Менеджер пакетов","section":"Инициализация проекта","path":"/docs/guide/cli/package-manager/package-manager","headings":["Инициализация проекта"],"excerpt":"Инициализация проекта easyp mod download ls ~/.easyp/mod/github.com/googleapis/googleapis/ ```","content":"Инициализация проекта easyp mod download ls ~/.easyp/mod/github.com/googleapis/googleapis/ ```"},{"id":"cli/package-manager/package-manager::repository-not-found-authentication-failed::33","title":"Менеджер пакетов","section":"\"Repository not found\" / \"Authentication failed\"","path":"/docs/guide/cli/package-manager/package-manager#repository-not-found-authentication-failed","headings":["\"Repository not found\" / \"Authentication failed\""],"excerpt":"\"Repository not found\" / \"Authentication failed\"","content":"\"Repository not found\" / \"Authentication failed\""},{"id":"cli/package-manager/package-manager::cache-corruption-checksum-mismatch::34","title":"Менеджер пакетов","section":"\"Cache corruption\" / \"Checksum mismatch\"","path":"/docs/guide/cli/package-manager/package-manager#cache-corruption-checksum-mismatch","headings":["\"Cache corruption\" / \"Checksum mismatch\""],"excerpt":"\"Cache corruption\" / \"Checksum mismatch\"","content":"\"Cache corruption\" / \"Checksum mismatch\""},{"id":"cli/package-manager/package-manager::docker-multi-stage::35","title":"Менеджер пакетов","section":"Docker multi-stage","path":"/docs/guide/cli/package-manager/package-manager#docker-multi-stage","headings":["Docker multi-stage"],"excerpt":"Docker multi-stage ```dockerfile FROM ghcr.io/easyp-tech/easyp:latest AS deps WORKDIR /workspace COPY easyp.yaml easyp.lock ./ RUN easyp mod vendor","content":"Docker multi-stage ```dockerfile 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::36","title":"Менеджер пакетов","section":"Docker multi-stage","path":"/docs/guide/cli/package-manager/package-manager#docker-multi-stage","headings":["Docker multi-stage"],"excerpt":"Docker multi-stage FROM alpine:latest AS build WORKDIR /app COPY --from=deps /workspace/easyp_vendor ./easyp_vendor COPY . . RUN easyp generate ```","content":"Docker multi-stage FROM alpine:latest AS build WORKDIR /app COPY --from=deps /workspace/easyp_vendor ./easyp_vendor COPY . . RUN easyp generate ```"},{"id":"cli/package-manager/package-manager::monorepo::37","title":"Менеджер пакетов","section":"Monorepo","path":"/docs/guide/cli/package-manager/package-manager#monorepo","headings":["Monorepo"],"excerpt":"Monorepo Каждый easyp.yaml может иметь свой набор зависимостей.","content":"Monorepo Каждый easyp.yaml может иметь свой набор зависимостей."},{"id":"cli/package-manager/package-manager::workflow::38","title":"Менеджер пакетов","section":"Workflow разработки","path":"/docs/guide/cli/package-manager/package-manager#workflow","headings":["Workflow разработки"],"excerpt":"Workflow разработки ✅ Latest теги в активной разработке ✅ Фиксация версий в продакшене ✅ Коммит lock файла ✅ Ревью обновлений ✅ Тест после обновления","content":"Workflow разработки ✅ Latest теги в активной разработке ✅ Фиксация версий в продакшене ✅ Коммит lock файла ✅ Ревью обновлений ✅ Тест после обновления"},{"id":"cli/package-manager/package-manager::top::39","title":"Менеджер пакетов","section":"Безопасность","path":"/docs/guide/cli/package-manager/package-manager","headings":["Безопасность"],"excerpt":"Безопасность ✅ Фиксируйте версии ✅ Используйте SSH ключи ✅ Оценивайте новые зависимости ✅ Следите за уязвимостями ❌ Не храните секреты в конфиге","content":"Безопасность ✅ Фиксируйте версии ✅ Используйте SSH ключи ✅ Оценивайте новые зависимости ✅ Следите за уязвимостями ❌ Не храните секреты в конфиге"},{"id":"cli/package-manager/package-manager::top::40","title":"Менеджер пакетов","section":"Производительность","path":"/docs/guide/cli/package-manager/package-manager","headings":["Производительность"],"excerpt":"Производительность ✅ Агрессивное кеширование в CI ✅ Vendoring для частых сборок ✅ Чистка старого кеша ✅ Общий кеш для команды","content":"Производительность ✅ Агрессивное кеширование в CI ✅ Vendoring для частых сборок ✅ Чистка старого кеша ✅ Общий кеш для команды"},{"id":"cli/package-manager/package-manager::top::41","title":"Менеджер пакетов","section":"Командная работа","path":"/docs/guide/cli/package-manager/package-manager","headings":["Командная работа"],"excerpt":"Командная работа ✅ Документация по аутентификации ✅ Единые инструменты ✅ Автоматизация обновлений с тестами ✅ Общий кеш при возможности","content":"Командная работа ✅ Документация по аутентификации ✅ Единые инструменты ✅ Автоматизация обновлений с тестами ✅ Общий кеш при возможности"},{"id":"cli/package-manager/package-manager::top::42","title":"Менеджер пакетов","section":"Командная работа","path":"/docs/guide/cli/package-manager/package-manager","headings":["Командная работа"],"excerpt":"Командная работа Менеджер пакетов EasyP — масштабируемое децентрализованное решение от одиночных проектов до enterprise, сохраняя простоту и надёжность.","content":"Командная работа Менеджер пакетов EasyP — масштабируемое децентрализованное решение от одиночных проектов до enterprise, сохраняя простоту и надёжность."},{"id":"introduction/install::top::0","title":"Установка EasyP CLI","section":"Установка через менеджер пакетов системы","path":"/docs/guide/introduction/install","headings":["Установка через менеджер пакетов системы"],"excerpt":"Установка через менеджер пакетов системы","content":"Установка через менеджер пакетов системы"},{"id":"introduction/install::top::1","title":"Установка EasyP CLI","section":"Рекомендуемый способ установки","path":"/docs/guide/introduction/install","headings":["Рекомендуемый способ установки"],"excerpt":"Рекомендуемый способ установки","content":"Рекомендуемый способ установки"},{"id":"introduction/install::homebrew::2","title":"Установка EasyP CLI","section":"Homebrew","path":"/docs/guide/introduction/install#homebrew","headings":["Homebrew"],"excerpt":"Homebrew Можно установить бинарный релиз в macOS через Homebrew:","content":"Homebrew Можно установить бинарный релиз в macOS через Homebrew:"},{"id":"introduction/install::homebrew::3","title":"Установка EasyP CLI","section":"Homebrew","path":"/docs/guide/introduction/install#homebrew","headings":["Homebrew"],"excerpt":"Homebrew Work in progress — поддержка других менеджеров (apt, yum, pacman и т.д.) в процессе.","content":"Homebrew Work in progress — поддержка других менеджеров (apt, yum, pacman и т.д.) в процессе."},{"id":"introduction/install::_-_::4","title":"Установка EasyP CLI","section":"_Не рекомендуется_","path":"/docs/guide/introduction/install#_-_","headings":["_Не рекомендуется_"],"excerpt":"_Не рекомендуется_ Локальная установка менее предпочтительна, потому что пакетные менеджеры обеспечивают: Автоматические обновления и патчи безопасности Лучшую интеграцию с системой Упрощённую установку и удаление Подпис","content":"_Не рекомендуется_ Локальная установка менее предпочтительна, потому что пакетные менеджеры обеспечивают: Автоматические обновления и патчи безопасности Лучшую интеграцию с системой Упрощённую установку и удаление Подписанные и проверенные бинарники"},{"id":"introduction/install::go-install::5","title":"Установка EasyP CLI","section":"Установка через go install","path":"/docs/guide/introduction/install#go-install","headings":["Установка через go install"],"excerpt":"Установка через go install Команда установит последнюю стабильную версию easyp:","content":"Установка через go install Команда установит последнюю стабильную версию easyp:"},{"id":"introduction/install::top::6","title":"Установка EasyP CLI","section":"Сборка из исходников","path":"/docs/guide/introduction/install","headings":["Сборка из исходников"],"excerpt":"Сборка из исходников Клонирование репозитория","content":"Сборка из исходников Клонирование репозитория"},{"id":"introduction/install::top::7","title":"Установка EasyP CLI","section":"Сборка из исходников","path":"/docs/guide/introduction/install","headings":["Сборка из исходников"],"excerpt":"Сборка из исходников Сборка с помощью Go","content":"Сборка из исходников Сборка с помощью Go"},{"id":"introduction/quickstart::top::0","title":"Быстрый старт (Quickstart)","path":"/docs/guide/introduction/quickstart","headings":[],"excerpt":"EasyP — современный toolkit для работы с файлами Protobuf. В этом кратком руководстве вы научитесь:","content":"EasyP — современный toolkit для работы с файлами Protobuf. В этом кратком руководстве вы научитесь:"},{"id":"introduction/quickstart::top::1","title":"Быстрый старт (Quickstart)","path":"/docs/guide/introduction/quickstart","headings":[],"excerpt":"**Инициализировать** проект с конфигурацией EasyP **Настраивать линтинг**, чтобы ловить ошибки и соблюдать лучшие практики **Управлять зависимостями** из Git‑репозиториев **Генерировать код** из ваших Protobuf файлов","content":"**Инициализировать** проект с конфигурацией EasyP **Настраивать линтинг**, чтобы ловить ошибки и соблюдать лучшие практики **Управлять зависимостями** из Git‑репозиториев **Генерировать код** из ваших Protobuf файлов"},{"id":"introduction/quickstart::top::2","title":"Быстрый старт (Quickstart)","section":"Предварительные требования","path":"/docs/guide/introduction/quickstart","headings":["Предварительные требования"],"excerpt":"Предварительные требования Перед началом убедитесь, что у вас установлены:","content":"Предварительные требования Перед началом убедитесь, что у вас установлены:"},{"id":"introduction/quickstart::top::3","title":"Быстрый старт (Quickstart)","section":"Предварительные требования","path":"/docs/guide/introduction/quickstart","headings":["Предварительные требования"],"excerpt":"Предварительные требования **EasyP CLI** — см. руководство по установке **Git** доступен в вашем $PATH **Файлы .proto** (или создайте их по ходу)","content":"Предварительные требования **EasyP CLI** — см. руководство по установке **Git** доступен в вашем $PATH **Файлы .proto** (или создайте их по ходу)"},{"id":"introduction/quickstart::top::4","title":"Быстрый старт (Quickstart)","section":"Предварительные требования","path":"/docs/guide/introduction/quickstart","headings":["Предварительные требования"],"excerpt":"Предварительные требования Проверить версию EasyP:","content":"Предварительные требования Проверить версию EasyP:"},{"id":"introduction/quickstart::top::5","title":"Быстрый старт (Quickstart)","section":"Инициализация проекта","path":"/docs/guide/introduction/quickstart","headings":["Инициализация проекта"],"excerpt":"Инициализация проекта Создайте базовый файл конфигурации easyp.yaml в корне проекта:","content":"Инициализация проекта Создайте базовый файл конфигурации easyp.yaml в корне проекта:"},{"id":"introduction/quickstart::top::6","title":"Быстрый старт (Quickstart)","section":"Инициализация проекта","path":"/docs/guide/introduction/quickstart","headings":["Инициализация проекта"],"excerpt":"Инициализация проекта Команда генерирует шаблон easyp.yaml с комментариями, дефолтными lint-правилами и настройками breaking-check. easyp init работает интерактивно: если в корне есть buf.yml/buf.yaml, EasyP предложит ми","content":"Инициализация проекта Команда генерирует шаблон easyp.yaml с комментариями, дефолтными lint-правилами и настройками breaking-check. easyp init работает интерактивно: если в корне есть buf.yml/buf.yaml, EasyP предложит миграцию; если easyp.yaml уже существует, попросит подтверждение перед перезаписью."},{"id":"introduction/quickstart::top::7","title":"Быстрый старт (Quickstart)","section":"Настройка линтинга","path":"/docs/guide/introduction/quickstart","headings":["Настройка линтинга"],"excerpt":"Настройка линтинга Линтинг помогает находить проблемы и поддерживать единый стиль. EasyP использует правила, совместимые с Buf.","content":"Настройка линтинга Линтинг помогает находить проблемы и поддерживать единый стиль. EasyP использует правила, совместимые с Buf."},{"id":"introduction/quickstart::top::8","title":"Быстрый старт (Quickstart)","section":"Настройка линтинга","path":"/docs/guide/introduction/quickstart","headings":["Настройка линтинга"],"excerpt":"Настройка линтинга Секция lint уже создаётся командой easyp init. При необходимости отредактируйте её, например так:","content":"Настройка линтинга Секция lint уже создаётся командой easyp init. При необходимости отредактируйте её, например так:"},{"id":"introduction/quickstart::top::9","title":"Быстрый старт (Quickstart)","section":"Настройка линтинга","path":"/docs/guide/introduction/quickstart","headings":["Настройка линтинга"],"excerpt":"Настройка линтинга Запустите линтер:","content":"Настройка линтинга Запустите линтер:"},{"id":"introduction/quickstart::top::10","title":"Быстрый старт (Quickstart)","section":"Настройка линтинга","path":"/docs/guide/introduction/quickstart","headings":["Настройка линтинга"],"excerpt":"Настройка линтинга Линтер проверит все .proto файлы и сообщит о найденных проблемах.","content":"Настройка линтинга Линтер проверит все .proto файлы и сообщит о найденных проблемах."},{"id":"introduction/quickstart::top::11","title":"Быстрый старт (Quickstart)","section":"Настройка линтинга","path":"/docs/guide/introduction/quickstart","headings":["Настройка линтинга"],"excerpt":"Настройка линтинга ::: tip Правила линтинга EasyP на 100% совместимы с Buf — мигрировать просто. :::","content":"Настройка линтинга ::: tip Правила линтинга EasyP на 100% совместимы с Buf — мигрировать просто. :::"},{"id":"introduction/quickstart::top::12","title":"Быстрый старт (Quickstart)","section":"Управление зависимостями","path":"/docs/guide/introduction/quickstart","headings":["Управление зависимостями"],"excerpt":"Управление зависимостями Если вы используете сторонние protobuf пакеты (например Google APIs или gRPC Gateway), EasyP упрощает их подключение.","content":"Управление зависимостями Если вы используете сторонние protobuf пакеты (например Google APIs или gRPC Gateway), EasyP упрощает их подключение."},{"id":"introduction/quickstart::top::13","title":"Быстрый старт (Quickstart)","section":"Формат зависимости","path":"/docs/guide/introduction/quickstart","headings":["Формат зависимости"],"excerpt":"Формат зависимости Запись: $GIT_LINK@$VERSION","content":"Формат зависимости Запись: $GIT_LINK@$VERSION"},{"id":"introduction/quickstart::top::14","title":"Быстрый старт (Quickstart)","section":"Формат зависимости","path":"/docs/guide/introduction/quickstart","headings":["Формат зависимости"],"excerpt":"Формат зависимости **$GIT_LINK** — URL любого Git‑репозитория (GitHub, GitLab и т.д.) **$VERSION** — тег или хеш коммита (опционально)","content":"Формат зависимости **$GIT_LINK** — URL любого Git‑репозитория (GitHub, GitLab и т.д.) **$VERSION** — тег или хеш коммита (опционально)"},{"id":"introduction/quickstart::top::15","title":"Быстрый старт (Quickstart)","section":"Формат зависимости","path":"/docs/guide/introduction/quickstart","headings":["Формат зависимости"],"excerpt":"Формат зависимости Если версия не указана — берётся последний коммит из основной ветки.","content":"Формат зависимости Если версия не указана — берётся последний коммит из основной ветки."},{"id":"introduction/quickstart::top::16","title":"Быстрый старт (Quickstart)","section":"Добавление зависимостей","path":"/docs/guide/introduction/quickstart","headings":["Добавление зависимостей"],"excerpt":"Добавление зависимостей Дополните easyp.yaml:","content":"Добавление зависимостей Дополните easyp.yaml:"},{"id":"introduction/quickstart::top::17","title":"Быстрый старт (Quickstart)","section":"Загрузка зависимостей","path":"/docs/guide/introduction/quickstart","headings":["Загрузка зависимостей"],"excerpt":"Загрузка зависимостей Команда: Скачивает версии из easyp.lock, если он существует Иначе — берёт из easyp.yaml и создаёт easyp.lock","content":"Загрузка зависимостей Команда: Скачивает версии из easyp.lock, если он существует Иначе — берёт из easyp.yaml и создаёт easyp.lock"},{"id":"introduction/quickstart::top::18","title":"Быстрый старт (Quickstart)","section":"Загрузка зависимостей","path":"/docs/guide/introduction/quickstart","headings":["Загрузка зависимостей"],"excerpt":"Загрузка зависимостей ::: info Совет: easyp mod update — игнорирует lock‑файл и подтягивает актуальные версии из easyp.yaml. :::","content":"Загрузка зависимостей ::: info Совет: easyp mod update — игнорирует lock‑файл и подтягивает актуальные версии из easyp.yaml. :::"},{"id":"introduction/quickstart::top::19","title":"Быстрый старт (Quickstart)","section":"Генерация кода","path":"/docs/guide/introduction/quickstart","headings":["Генерация кода"],"excerpt":"Генерация кода EasyP поддерживает все стандартные protoc‑плагины.","content":"Генерация кода EasyP поддерживает все стандартные protoc‑плагины."},{"id":"introduction/quickstart::top::20","title":"Быстрый старт (Quickstart)","section":"Конфигурация генерации","path":"/docs/guide/introduction/quickstart","headings":["Конфигурация генерации"],"excerpt":"Конфигурация генерации Добавьте плагины:","content":"Конфигурация генерации Добавьте плагины:"},{"id":"introduction/quickstart::top::21","title":"Быстрый старт (Quickstart)","section":"Запуск генерации","path":"/docs/guide/introduction/quickstart","headings":["Запуск генерации"],"excerpt":"Запуск генерации EasyP выполнит: Разрешение всех зависимостей Подключение к сервису EasyP (или локальный режим) Запуск указанных плагинов Вывод сгенерированного кода в нужные директории","content":"Запуск генерации EasyP выполнит: Разрешение всех зависимостей Подключение к сервису EasyP (или локальный режим) Запуск указанных плагинов Вывод сгенерированного кода в нужные директории"},{"id":"introduction/quickstart::top::22","title":"Быстрый старт (Quickstart)","section":"Запуск генерации","path":"/docs/guide/introduction/quickstart","headings":["Запуск генерации"],"excerpt":"Запуск генерации ::: tip Гибридный рантайм: WASM для скорости, Docker — для тяжёлых плагинов. :::","content":"Запуск генерации ::: tip Гибридный рантайм: WASM для скорости, Docker — для тяжёлых плагинов. :::"},{"id":"introduction/quickstart::top::23","title":"Быстрый старт (Quickstart)","section":"Следующие шаги","path":"/docs/guide/introduction/quickstart","headings":["Следующие шаги"],"excerpt":"Следующие шаги Поздравляем! 🎉 Вы успешно: ✅ Инициализировали проект EasyP ✅ Настроили линтинг ✅ Управляете внешними зависимостями ✅ Сгенерировали код из .proto","content":"Следующие шаги Поздравляем! 🎉 Вы успешно: ✅ Инициализировали проект EasyP ✅ Настроили линтинг ✅ Управляете внешними зависимостями ✅ Сгенерировали код из .proto"},{"id":"introduction/quickstart::top::24","title":"Быстрый старт (Quickstart)","section":"Узнать больше","path":"/docs/guide/introduction/quickstart","headings":["Узнать больше"],"excerpt":"Узнать больше **CLI Reference** — подробности по командам **API Service** — удалённая генерация **Configuration** — все опции конфигурации","content":"Узнать больше **CLI Reference** — подробности по командам **API Service** — удалённая генерация **Configuration** — все опции конфигурации"},{"id":"introduction/quickstart::top::25","title":"Быстрый старт (Quickstart)","section":"Узнать больше","path":"/docs/guide/introduction/quickstart","headings":["Узнать больше"],"excerpt":"Узнать больше *Приятной работы с Protobuf — без боли! 🚀*","content":"Узнать больше *Приятной работы с Protobuf — без боли! 🚀*"},{"id":"introduction/what-is::top::0","title":"Что такое EasyP?","path":"/docs/guide/introduction/what-is","headings":[],"excerpt":"EasyP — это современный инструментарий для работы с Protocol Buffers, который объединяет весь ваш protobuf‑workflow в один мощный CLI‑инструмент. Он совмещает линтинг, управление пакетами, генерацию кода и проверку совме","content":"EasyP — это современный инструментарий для работы с Protocol Buffers, который объединяет весь ваш protobuf‑workflow в один мощный CLI‑инструмент. Он совмещает линтинг, управление пакетами, генерацию кода и проверку совместимости в единой среде и устраняет сложность традиционной работы с protobuf."},{"id":"introduction/what-is::top::1","title":"Что такое EasyP?","path":"/docs/guide/introduction/what-is","headings":[],"excerpt":"Хотите просто попробовать? Перейдите сразу к разделу Quickstart.","content":"Хотите просто попробовать? Перейдите сразу к разделу Quickstart."},{"id":"introduction/what-is::protobuf::2","title":"Что такое EasyP?","section":"Проблема: фрагментированные protobuf‑процессы","path":"/docs/guide/introduction/what-is#protobuf","headings":["Проблема: фрагментированные protobuf‑процессы"],"excerpt":"Проблема: фрагментированные protobuf‑процессы Работа с Protocol Buffers в разных проектах часто создает лишнюю сложность и трение:","content":"Проблема: фрагментированные protobuf‑процессы Работа с Protocol Buffers в разных проектах часто создает лишнюю сложность и трение:"},{"id":"introduction/what-is::top::3","title":"Что такое EasyP?","section":"Хаос инструментов","path":"/docs/guide/introduction/what-is","headings":["Хаос инструментов"],"excerpt":"Хаос инструментов **Много отдельных утилит**: Отдельно для линтинга, генерации и управления зависимостями **Несогласованные конфигурации**: Разные форматы и правила в разных командах **Сложный онбординг**: Новым разработ","content":"Хаос инструментов **Много отдельных утилит**: Отдельно для линтинга, генерации и управления зависимостями **Несогласованные конфигурации**: Разные форматы и правила в разных командах **Сложный онбординг**: Новым разработчикам нужно долго вникать"},{"id":"introduction/what-is::top::4","title":"Что такое EasyP?","section":"Проблемы управления зависимостями","path":"/docs/guide/introduction/what-is","headings":["Проблемы управления зависимостями"],"excerpt":"Проблемы управления зависимостями **Нет стандартизированного подхода**: Каждый проект решает это по‑своему **Конфликты версий**: Трудно сводить разные версии одних и тех же proto‑библиотек **Неповторяемость сборок**: Сло","content":"Проблемы управления зависимостями **Нет стандартизированного подхода**: Каждый проект решает это по‑своему **Конфликты версий**: Трудно сводить разные версии одних и тех же proto‑библиотек **Неповторяемость сборок**: Сложно гарантировать одинаковый результат в разных окружениях"},{"id":"introduction/what-is::top::5","title":"Что такое EasyP?","section":"Трение в разработке","path":"/docs/guide/introduction/what-is","headings":["Трение в разработке"],"excerpt":"Трение в разработке **Ручные операции**: Много повторяющихся шагов **Разрастание конфигураций**: Множество файлов и форматов **Затратная проверка совместимости**: Часто вручную и постфактум","content":"Трение в разработке **Ручные операции**: Много повторяющихся шагов **Разрастание конфигураций**: Множество файлов и форматов **Затратная проверка совместимости**: Часто вручную и постфактум"},{"id":"introduction/what-is::protobuf::6","title":"Что такое EasyP?","section":"Решение: единый protobuf‑инструментарий","path":"/docs/guide/introduction/what-is#protobuf","headings":["Решение: единый protobuf‑инструментарий"],"excerpt":"Решение: единый protobuf‑инструментарий EasyP устраняет эти проблемы, предоставляя целостный opinionated‑подход и стандартизируя процессы:","content":"Решение: единый protobuf‑инструментарий EasyP устраняет эти проблемы, предоставляя целостный opinionated‑подход и стандартизируя процессы:"},{"id":"introduction/what-is::top::7","title":"Что такое EasyP?","section":"Один инструмент — все задачи","path":"/docs/guide/introduction/what-is","headings":["Один инструмент — все задачи"],"excerpt":"Один инструмент — все задачи Вместо жонглирования утилитами EasyP даёт: **Linting** с расширенными наборами правил **Package management** с Git‑нативными зависимостями **Code generation** локально и удалённо **Breaking c","content":"Один инструмент — все задачи Вместо жонглирования утилитами EasyP даёт: **Linting** с расширенными наборами правил **Package management** с Git‑нативными зависимостями **Code generation** локально и удалённо **Breaking change detection** для контроля совместимости API"},{"id":"introduction/what-is::top::8","title":"Что такое EasyP?","section":"Единая конфигурация","path":"/docs/guide/introduction/what-is","headings":["Единая конфигурация"],"excerpt":"Единая конфигурация Один файл easyp.yaml описывает весь workflow — меньше расхождений, проще сопровождать.","content":"Единая конфигурация Один файл easyp.yaml описывает весь workflow — меньше расхождений, проще сопровождать."},{"id":"introduction/what-is::gitnative::9","title":"Что такое EasyP?","section":"Git‑native зависимости","path":"/docs/guide/introduction/what-is#gitnative","headings":["Git‑native зависимости"],"excerpt":"Git‑native зависимости Прямое использование Git‑репозиториев вместо централизованных реестров: прозрачная история, контроль версий, воспроизводимые сборки.","content":"Git‑native зависимости Прямое использование Git‑репозиториев вместо централизованных реестров: прозрачная история, контроль версий, воспроизводимые сборки."},{"id":"introduction/what-is::top::10","title":"Что такое EasyP?","section":"Ключевые возможности","path":"/docs/guide/introduction/what-is","headings":["Ключевые возможности"],"excerpt":"Ключевые возможности Feature Description --------- ------------- 🔍 **Comprehensive Linting** Полная поддержка правил buf с настраиваемыми профилями для лучших практик API‑дизайна. 📦 **Smart Package Manager** Git‑ориент","content":"Ключевые возможности Feature Description --------- ------------- 🔍 **Comprehensive Linting** Полная поддержка правил buf с настраиваемыми профилями для лучших практик API‑дизайна. 📦 **Smart Package Manager** Git‑ориентированное управление зависимостями с lock‑файлом для воспроизводимости. ⚡ **Code Generation** Многозадачная генерация кода с поддержкой локальных и удалённых protoc‑плагинов. 🔄 **Breaking Change Detection** Автоматическая проверка совместимости API против веток Git. 🌐 **Remote Plugin Support** Выполнение плагинов через централизованный EasyP API сервис без локальных установок. 🎯 **Developer Experience** Автодополнение, понятные ошибки, единая структура и документация."},{"id":"introduction/what-is::top::11","title":"Что такое EasyP?","section":"Типы поддерживаемых плагинов","path":"/docs/guide/introduction/what-is","headings":["Типы поддерживаемых плагинов"],"excerpt":"Типы поддерживаемых плагинов EasyP гибко подходит к выполнению генерации:","content":"Типы поддерживаемых плагинов EasyP гибко подходит к выполнению генерации:"},{"id":"introduction/what-is::local-plugins::12","title":"Что такое EasyP?","section":"Local Plugins","path":"/docs/guide/introduction/what-is#local-plugins","headings":["Local Plugins"],"excerpt":"Local Plugins Стандартные установленные protoc‑плагины:","content":"Local Plugins Стандартные установленные protoc‑плагины:"},{"id":"introduction/what-is::remote-plugins::13","title":"Что такое EasyP?","section":"Remote Plugins","path":"/docs/guide/introduction/what-is#remote-plugins","headings":["Remote Plugins"],"excerpt":"Remote Plugins Плагины через EasyP API сервис для воспроизводимости:","content":"Remote Plugins Плагины через EasyP API сервис для воспроизводимости:"},{"id":"introduction/what-is::custom-plugins::14","title":"Что такое EasyP?","section":"Custom Plugins","path":"/docs/guide/introduction/what-is#custom-plugins","headings":["Custom Plugins"],"excerpt":"Custom Plugins Поддержка экосистемы пользовательских расширений.","content":"Custom Plugins Поддержка экосистемы пользовательских расширений."},{"id":"introduction/what-is::top::15","title":"Что такое EasyP?","section":"Децентрализованный менеджмент пакетов","path":"/docs/guide/introduction/what-is","headings":["Децентрализованный менеджмент пакетов"],"excerpt":"Децентрализованный менеджмент пакетов В отличие от других решений EasyP не требует централизованного реестра. Любой Git‑репозиторий может быть источником:","content":"Децентрализованный менеджмент пакетов В отличие от других решений EasyP не требует централизованного реестра. Любой Git‑репозиторий может быть источником:"},{"id":"introduction/what-is::top::16","title":"Что такое EasyP?","section":"Децентрализованный менеджмент пакетов","path":"/docs/guide/introduction/what-is","headings":["Децентрализованный менеджмент пакетов"],"excerpt":"Децентрализованный менеджмент пакетов **Гибкость**: Любой Git‑хостинг (GitHub, GitLab, self‑hosted) **Нет vendor lock‑in**: Зависимости не привязаны к одному провайдеру **Полная история**: Ветки, теги, ревью **Enterprise","content":"Децентрализованный менеджмент пакетов **Гибкость**: Любой Git‑хостинг (GitHub, GitLab, self‑hosted) **Нет vendor lock‑in**: Зависимости не привязаны к одному провайдеру **Полная история**: Ветки, теги, ревью **Enterprise‑совместимость**: Поддержка приватных репозиториев"},{"id":"introduction/what-is::buf::17","title":"Что такое EasyP?","section":"Бесшовная миграция с Buf","path":"/docs/guide/introduction/what-is#buf","headings":["Бесшовная миграция с Buf"],"excerpt":"Бесшовная миграция с Buf EasyP изначально совместим с экосистемой buf:","content":"Бесшовная миграция с Buf EasyP изначально совместим с экосистемой buf:"},{"id":"introduction/what-is::buf::18","title":"Что такое EasyP?","section":"Бесшовная миграция с Buf","path":"/docs/guide/introduction/what-is#buf","headings":["Бесшовная миграция с Buf"],"excerpt":"Бесшовная миграция с Buf **Совпадающие rule sets** **Похожая структура YAML** **Минимальные изменения для замены** **Постепенное внедрение** без ломки текущего пайплайна","content":"Бесшовная миграция с Buf **Совпадающие rule sets** **Похожая структура YAML** **Минимальные изменения для замены** **Постепенное внедрение** без ломки текущего пайплайна"},{"id":"introduction/what-is::easyp-vs-bufbuild::19","title":"Что такое EasyP?","section":"EasyP vs buf.build","path":"/docs/guide/introduction/what-is#easyp-vs-bufbuild","headings":["EasyP vs buf.build"],"excerpt":"EasyP vs buf.build Feature EasyP buf.build --------- -------- ----------- **Dependency Management** Git‑репозитории Buf Schema Registry (BSR) **Vendor Lock-in** Нет Привязка к BSR для полного функционала **Plugin Executi","content":"EasyP vs buf.build Feature EasyP buf.build --------- -------- ----------- **Dependency Management** Git‑репозитории Buf Schema Registry (BSR) **Vendor Lock-in** Нет Привязка к BSR для полного функционала **Plugin Execution** Local + Remote Local + BSR plugins **Private Dependencies** Любой Git провайдер BSR или ручное управление **Offline Development** Полная поддержка (mod vendor) Ограниченно без доступа к BSR **Enterprise Integration** Использует существующий Git Требует настройку BSR **Breaking Change Detection** Против любой Git ссылки Аналогично **Package Distribution** Любой Git Публикация через BSR **License** Apache 2.0 Apache 2.0 **Community** Growing Established"},{"id":"introduction/what-is::easyp-vs-bufbuild::20","title":"Что такое EasyP?","section":"EasyP vs buf.build","path":"/docs/guide/introduction/what-is#easyp-vs-bufbuild","headings":["EasyP vs buf.build"],"excerpt":"EasyP vs buf.build **Преимущества миграции:** Без изменения инфраструктуры Плавное принятие новых возможностей Гибрид локальных и удалённых плагинов Единая конфигурация вместо набора файлов","content":"EasyP vs buf.build **Преимущества миграции:** Без изменения инфраструктуры Плавное принятие новых возможностей Гибрид локальных и удалённых плагинов Единая конфигурация вместо набора файлов"},{"id":"introduction/what-is::protobuf::21","title":"Что такое EasyP?","section":"Наши цели для Protobuf","path":"/docs/guide/introduction/what-is#protobuf","headings":["Наши цели для Protobuf"],"excerpt":"Наши цели для Protobuf Миссия EasyP — ускорить принятие **schema‑driven API** через удобный, надёжный и прозрачный инструментарий.","content":"Наши цели для Protobuf Миссия EasyP — ускорить принятие **schema‑driven API** через удобный, надёжный и прозрачный инструментарий."},{"id":"introduction/what-is::top::22","title":"Что такое EasyP?","section":"Современная экосистема","path":"/docs/guide/introduction/what-is","headings":["Современная экосистема"],"excerpt":"Современная экосистема Повышаем DX вокруг protobuf, чтобы конкурентно выглядеть по простоте против REST/JSON, сохраняя типовую строгость и производительность.","content":"Современная экосистема Повышаем DX вокруг protobuf, чтобы конкурентно выглядеть по простоте против REST/JSON, сохраняя типовую строгость и производительность."},{"id":"introduction/what-is::developer-experience::23","title":"Что такое EasyP?","section":"Developer Experience прежде всего","path":"/docs/guide/introduction/what-is#developer-experience","headings":["Developer Experience прежде всего"],"excerpt":"Developer Experience прежде всего Интуитивный CLI, понятные ошибки, ясные сообщения, минимальная фрагментация.","content":"Developer Experience прежде всего Интуитивный CLI, понятные ошибки, ясные сообщения, минимальная фрагментация."},{"id":"introduction/what-is::enterprise::24","title":"Что такое EasyP?","section":"Готов к Enterprise","path":"/docs/guide/introduction/what-is#enterprise","headings":["Готов к Enterprise"],"excerpt":"Готов к Enterprise Воспроизводимые сборки, приватные репозитории, интеграция в CI/CD.","content":"Готов к Enterprise Воспроизводимые сборки, приватные репозитории, интеграция в CI/CD."},{"id":"introduction/what-is::top::25","title":"Что такое EasyP?","section":"Для индивидуальных разработчиков","path":"/docs/guide/introduction/what-is","headings":["Для индивидуальных разработчиков"],"excerpt":"Для индивидуальных разработчиков Быстрый старт за минуты Один инструмент — меньше когнитивной нагрузки Понятная документация","content":"Для индивидуальных разработчиков Быстрый старт за минуты Один инструмент — меньше когнитивной нагрузки Понятная документация"},{"id":"introduction/what-is::top::26","title":"Что такое EasyP?","section":"Для команд","path":"/docs/guide/introduction/what-is","headings":["Для команд"],"excerpt":"Для команд Единые стандарты Повторяемые сборки (lock‑файл) Ускоренный онбординг","content":"Для команд Единые стандарты Повторяемые сборки (lock‑файл) Ускоренный онбординг"},{"id":"introduction/what-is::top::27","title":"Что такое EasyP?","section":"Для организаций","path":"/docs/guide/introduction/what-is","headings":["Для организаций"],"excerpt":"Для организаций Нет vendor lock‑in Безопасность приватных репозиториев Лёгкая интеграция в существующие пайплайны","content":"Для организаций Нет vendor lock‑in Безопасность приватных репозиториев Лёгкая интеграция в существующие пайплайны"},{"id":"introduction/what-is::top::28","title":"Что такое EasyP?","section":"Что дальше?","path":"/docs/guide/introduction/what-is","headings":["Что дальше?"],"excerpt":"Что дальше? EasyP упрощает работу с protobuf — фокусируйтесь на API, а не на рутине. Хотите начать?","content":"Что дальше? EasyP упрощает работу с protobuf — фокусируйтесь на API, а не на рутине. Хотите начать?"},{"id":"introduction/what-is::top::29","title":"Что такое EasyP?","section":"Что дальше?","path":"/docs/guide/introduction/what-is","headings":["Что дальше?"],"excerpt":"Что дальше? Смотрите Installation Guide и Quickstart.","content":"Что дальше? Смотрите Installation Guide и Quickstart."},{"id":"introduction/what-is::stargazers-over-time::30","title":"Что такое 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 В работе","content":"Buf CLI В работе"},{"id":"migration/protoc::top::0","title":"Миграция с protoc на EasyP","path":"/docs/guide/migration/protoc","headings":[],"excerpt":"Исходная англоязычная версия файла содержала только заголовок и пометку “Work in progress”. Ниже — полноценный русскоязычный черновик раздела миграции. Уточни, если требуется сократить или изменить уровень детализации.","content":"Исходная англоязычная версия файла содержала только заголовок и пометку “Work in progress”. Ниже — полноценный русскоязычный черновик раздела миграции. Уточни, если требуется сократить или изменить уровень детализации."},{"id":"migration/protoc::1::1","title":"Миграция с protoc на EasyP","section":"1. Краткое сравнение","path":"/docs/guide/migration/protoc#1","headings":["1. Краткое сравнение"],"excerpt":"Краткое сравнение Аспект protoc EasyP -------- ---------- ------- Базовая роль Базовый компилятор .proto файлов Инструмент “всё в одном”: линтинг, проверка несовместимых изменений, менеджер пакетов, генерация Конфигураци","content":"Краткое сравнение Аспект protoc EasyP -------- ---------- ------- Базовая роль Базовый компилятор .proto файлов Инструмент “всё в одном”: линтинг, проверка несовместимых изменений, менеджер пакетов, генерация Конфигурация Чаще shell‑скрипты / Makefile / вручную передаваемые флаги Единый файл easyp.yaml (YAML или JSON) Управление зависимостями Ручной git clone, submodule, vendoring Секция deps с Git‑репозиториями Набор правил линтера Нет встроенного Встроенный линтер с правилами (можно включать/исключать) Проверка breaking changes Отсутствует из коробки Команда easyp breaking Расширенные плагины Установка и вызов через флаги --plugin Плагины через конфиг; поддержка удалённого выполнения (API Service) и стандартного локального Единообразие в CI Нужно собирать вручную Консистентные команды: lint, breaking, generate"},{"id":"migration/protoc::2::2","title":"Миграция с protoc на EasyP","section":"2. Когда имеет смысл мигрировать","path":"/docs/guide/migration/protoc#2","headings":["2. Когда имеет смысл мигрировать"],"excerpt":"Когда имеет смысл мигрировать Миграция на EasyP особенно полезна если: Есть потребность в автоматической проверке качества (стиль, именование) .proto файлов. Нужна защита от нелегитимных несовместимых изменений при эволю","content":"Когда имеет смысл мигрировать Миграция на EasyP особенно полезна если: Есть потребность в автоматической проверке качества (стиль, именование) .proto файлов. Нужна защита от нелегитимных несовместимых изменений при эволюции схем. В проекте используется несколько языков генерации и растёт число скриптов вокруг protoc. Вы хотите единый конфиг вместо множества shell/Makefile комбинаций. Планируется централизованное исполнение плагинов (через API Service) или унификация окружения в CI."},{"id":"migration/protoc::3-protoc::3","title":"Миграция с protoc на EasyP","section":"3. Типичный сценарий “до” (только protoc)","path":"/docs/guide/migration/protoc#3-protoc","headings":["3. Типичный сценарий “до” (только protoc)"],"excerpt":"Типичный сценарий “до” (только protoc) Пример: локальные скрипты / Makefile:","content":"Типичный сценарий “до” (только protoc) Пример: локальные скрипты / Makefile:"},{"id":"migration/protoc::3-protoc::4","title":"Миграция с protoc на EasyP","section":"3. Типичный сценарий “до” (только protoc)","path":"/docs/guide/migration/protoc#3-protoc","headings":["3. Типичный сценарий “до” (только protoc)"],"excerpt":"Типичный сценарий “до” (только protoc)","content":"Типичный сценарий “до” (только protoc)"},{"id":"migration/protoc::3-protoc::5","title":"Миграция с protoc на EasyP","section":"3. Типичный сценарий “до” (только protoc)","path":"/docs/guide/migration/protoc#3-protoc","headings":["3. Типичный сценарий “до” (только protoc)"],"excerpt":"Типичный сценарий “до” (только protoc) Дополнительные зависимости (googleapis, validate, grpc-gateway) скачиваются вручную или через submodules.","content":"Типичный сценарий “до” (только protoc) Дополнительные зависимости (googleapis, validate, grpc-gateway) скачиваются вручную или через submodules."},{"id":"migration/protoc::4-easyp::6","title":"Миграция с protoc на EasyP","section":"4. Типичный сценарий “после” (EasyP)","path":"/docs/guide/migration/protoc#4-easyp","headings":["4. Типичный сценарий “после” (EasyP)"],"excerpt":"Типичный сценарий “после” (EasyP) Единый файл easyp.yaml:","content":"Типичный сценарий “после” (EasyP) Единый файл easyp.yaml:"},{"id":"migration/protoc::4-easyp::7","title":"Миграция с protoc на EasyP","section":"4. Типичный сценарий “после” (EasyP)","path":"/docs/guide/migration/protoc#4-easyp","headings":["4. Типичный сценарий “после” (EasyP)"],"excerpt":"Типичный сценарий “после” (EasyP) ```yaml deps: - github.com/googleapis/googleapis - github.com/envoyproxy/protoc-gen-validate","content":"Типичный сценарий “после” (EasyP) ```yaml deps: - github.com/googleapis/googleapis - github.com/envoyproxy/protoc-gen-validate"},{"id":"migration/protoc::4-easyp::8","title":"Миграция с protoc на EasyP","section":"4. Типичный сценарий “после” (EasyP)","path":"/docs/guide/migration/protoc#4-easyp","headings":["4. Типичный сценарий “после” (EasyP)"],"excerpt":"Типичный сценарий “после” (EasyP) generate: plugins: - name: go out: gen/go opts: paths: source_relative - name: go-grpc out: gen/go opts: paths: source_relative require_unimplemented_servers: false - name: validate out:","content":"Типичный сценарий “после” (EasyP) generate: plugins: - name: go out: gen/go opts: paths: source_relative - name: go-grpc out: gen/go opts: paths: source_relative require_unimplemented_servers: false - name: validate out: gen/go opts: paths: source_relative lang: \"go\" ```"},{"id":"migration/protoc::4-easyp::9","title":"Миграция с protoc на EasyP","section":"4. Типичный сценарий “после” (EasyP)","path":"/docs/guide/migration/protoc#4-easyp","headings":["4. Типичный сценарий “после” (EasyP)"],"excerpt":"Типичный сценарий “после” (EasyP) Команды:","content":"Типичный сценарий “после” (EasyP) Команды:"},{"id":"migration/protoc::5::10","title":"Миграция с protoc на EasyP","section":"5. Пошаговая миграция","path":"/docs/guide/migration/protoc#5","headings":["5. Пошаговая миграция"],"excerpt":"Пошаговая миграция Инвентаризация: - Соберите список всех вызовов protoc (скрипты, Makefile, CI). - Зафиксируйте используемые плагины и их версии. Создание easyp.yaml: - Поле version не обязательно (можете оставить его т","content":"Пошаговая миграция Инвентаризация: - Соберите список всех вызовов protoc (скрипты, Makefile, CI). - Зафиксируйте используемые плагины и их версии. Создание easyp.yaml: - Поле version не обязательно (можете оставить его только для обратной совместимости). - Перенесите плагины в секцию generate.plugins. - Укажите опции, которые ранее передавались в командной строке. Зависимости: - Все внешние каталоги (googleapis, validate, grpc-gateway и т.п.) занесите в deps. - Удалите лишние submodules при необходимости. Линтер: - Запустите easyp lint и посмотрите на предупреждения. - При необходимости добавьте lint.use, lint.ignore, lint.except. Проверка breaking changes: - Выберите референс (обычно origin/main или предыдущий тег). - Запустите easyp breaking --against git-ref=origin/main. - Настройте игнорируемые изменения (breaking.ignore), если нужно. Обновление CI: - Замените прямые вызовы protoc на easyp generate. - Добавьте отдельные шаги lint и breaking. Очистка: - Удалите устаревшие генерационные скрипты, если они дублируют функционал EasyP. Документация: - Обновите README / CONTRIBUTING (новый способ генерации). Верификация: - Сравните результат генерации до и после (git diff). - Убедитесь, что имена файлов и пути совпадают или скорректируйте структуру."},{"id":"migration/protoc::6-ci-github-actions::11","title":"Миграция с protoc на EasyP","section":"6. Замена в CI (пример GitHub Actions)","path":"/docs/guide/migration/protoc#6-ci-github-actions","headings":["6. Замена в CI (пример GitHub Actions)"],"excerpt":"Замена в CI (пример GitHub Actions) ```yaml name: Install EasyP run: go install github.com/easyp-tech/easyp/cmd/easyp@latest","content":"Замена в CI (пример GitHub Actions) ```yaml name: Install EasyP run: go install github.com/easyp-tech/easyp/cmd/easyp@latest"},{"id":"migration/protoc::6-ci-github-actions::12","title":"Миграция с protoc на EasyP","section":"6. Замена в CI (пример GitHub Actions)","path":"/docs/guide/migration/protoc#6-ci-github-actions","headings":["6. Замена в CI (пример GitHub Actions)"],"excerpt":"Замена в CI (пример GitHub Actions) name: Lint run: easyp lint","content":"Замена в CI (пример GitHub Actions) name: Lint run: easyp lint"},{"id":"migration/protoc::6-ci-github-actions::13","title":"Миграция с protoc на EasyP","section":"6. Замена в CI (пример GitHub Actions)","path":"/docs/guide/migration/protoc#6-ci-github-actions","headings":["6. Замена в CI (пример GitHub Actions)"],"excerpt":"Замена в CI (пример GitHub Actions) name: Breaking run: easyp breaking --against git-ref=origin/main","content":"Замена в CI (пример GitHub Actions) name: Breaking run: easyp breaking --against git-ref=origin/main"},{"id":"migration/protoc::6-ci-github-actions::14","title":"Миграция с protoc на EasyP","section":"6. Замена в CI (пример GitHub Actions)","path":"/docs/guide/migration/protoc#6-ci-github-actions","headings":["6. Замена в CI (пример GitHub Actions)"],"excerpt":"Замена в CI (пример GitHub Actions) name: Generate run: easyp generate ```","content":"Замена в CI (пример GitHub Actions) name: Generate run: easyp generate ```"},{"id":"migration/protoc::7::15","title":"Миграция с protoc на EasyP","section":"7. Работа с плагинами","path":"/docs/guide/migration/protoc#7","headings":["7. Работа с плагинами"],"excerpt":"Работа с плагинами Тип В protoc В EasyP ----- ---------- --------- Стандартные (protoc-gen-go) Указание через --go_out plugins: - name: go ... gRPC --go-grpc_out Второй плагин go-grpc Validate Доп. установка + --validate","content":"Работа с плагинами Тип В protoc В EasyP ----- ---------- --------- Стандартные (protoc-gen-go) Указание через --go_out plugins: - name: go ... gRPC --go-grpc_out Второй плагин go-grpc Validate Доп. установка + --validate_out - name: validate с opts gRPC-Gateway / OpenAPI --grpc-gateway_out / --openapiv2_out Плагины grpc-gateway, openapiv2 Кастомные Путь к бинарю / --plugin=protoc-gen-xxx - name: xxx или удалённый remote: (если используется API Service)"},{"id":"migration/protoc::7::16","title":"Миграция с protoc на EasyP","section":"7. Работа с плагинами","path":"/docs/guide/migration/protoc#7","headings":["7. Работа с плагинами"],"excerpt":"Работа с плагинами Если вы переходите на удалённое выполнение (API Service), записи в конфиге могут выглядеть так:","content":"Работа с плагинами Если вы переходите на удалённое выполнение (API Service), записи в конфиге могут выглядеть так:"},{"id":"migration/protoc::8::17","title":"Миграция с protoc на EasyP","section":"8. Проверка корректности после миграции","path":"/docs/guide/migration/protoc#8","headings":["8. Проверка корректности после миграции"],"excerpt":"Проверка корректности после миграции git diff после easyp generate — не должно быть неожиданных изменений. Сравнить размер и содержимое каталога сгенерированных файлов. Запустить ваш потребляющий код (сборка, тесты). Про","content":"Проверка корректности после миграции git diff после easyp generate — не должно быть неожиданных изменений. Сравнить размер и содержимое каталога сгенерированных файлов. Запустить ваш потребляющий код (сборка, тесты). Проверить, что плагины (validate, grpc-gateway) продолжают вставлять необходимые аннотации / опции. Линт не должен выдавать критичных ошибок — скорректируйте стиль .proto, если требуется."},{"id":"migration/protoc::9::18","title":"Миграция с protoc на EasyP","section":"9. Частые проблемы","path":"/docs/guide/migration/protoc#9","headings":["9. Частые проблемы"],"excerpt":"Частые проблемы Проблема Причина Решение ---------- --------- --------- Плагин не найден Не установлен или не указан в PATH Выполнить go install ... или добавить в конфиг как remote Ошибка импорта .proto Отсутствует репо","content":"Частые проблемы Проблема Причина Решение ---------- --------- --------- Плагин не найден Не установлен или не указан в PATH Выполнить go install ... или добавить в конфиг как remote Ошибка импорта .proto Отсутствует репозиторий в deps Добавить адрес в секцию deps и easyp mod update Несовместимые изменения на каждом PR Отсутствует игнор/настройка сравнения Уточнить ветку/тег в --against или настроить breaking.ignore Локально работает, в CI падает В CI нет зависимостей (не вызван update) Добавить шаг easyp mod update перед generate Дубликаты сгенерированных файлов Изменена структура путей или out Синхронизировать out и paths: source_relative опции"},{"id":"migration/protoc::10-go::19","title":"Миграция с protoc на EasyP","section":"10. Минимальный пример конфигурации (только Go)","path":"/docs/guide/migration/protoc#10-go","headings":["10. Минимальный пример конфигурации (только Go)"],"excerpt":"Минимальный пример конфигурации (только Go)","content":"Минимальный пример конфигурации (только Go)"},{"id":"migration/protoc::10-go::20","title":"Миграция с protoc на EasyP","section":"10. Минимальный пример конфигурации (только Go)","path":"/docs/guide/migration/protoc#10-go","headings":["10. Минимальный пример конфигурации (только Go)"],"excerpt":"Минимальный пример конфигурации (только Go) Команды:","content":"Минимальный пример конфигурации (только Go) Команды:"},{"id":"migration/protoc::11-go-grpc-gateway-validate-breaking-lint::21","title":"Миграция с protoc на EasyP","section":"11. Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint)","path":"/docs/guide/migration/protoc#11-go-grpc-gateway-validate-breaking-lint","headings":["11. Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint)"],"excerpt":"Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint) ```yaml lint: use: - ENUM_FIRST_VALUE_ZERO - SERVICE_SUFFIX allow_comment_ignores: false enum_zero_value_suffix: _NONE service_suffix: Service","content":"Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint) ```yaml lint: use: - ENUM_FIRST_VALUE_ZERO - SERVICE_SUFFIX allow_comment_ignores: false enum_zero_value_suffix: _NONE service_suffix: Service"},{"id":"migration/protoc::11-go-grpc-gateway-validate-breaking-lint::22","title":"Миграция с protoc на EasyP","section":"11. Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint)","path":"/docs/guide/migration/protoc#11-go-grpc-gateway-validate-breaking-lint","headings":["11. Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint)"],"excerpt":"Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint) deps: - github.com/googleapis/googleapis - github.com/envoyproxy/protoc-gen-validate","content":"Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint) deps: - github.com/googleapis/googleapis - github.com/envoyproxy/protoc-gen-validate"},{"id":"migration/protoc::11-go-grpc-gateway-validate-breaking-lint::23","title":"Миграция с protoc на EasyP","section":"11. Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint)","path":"/docs/guide/migration/protoc#11-go-grpc-gateway-validate-breaking-lint","headings":["11. Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint)"],"excerpt":"Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint) generate: plugins: - name: go out: gen/go opts: paths: source_relative - name: go-grpc out: gen/go opts: paths: source_relative require_unimplemented_","content":"Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint) generate: plugins: - name: go out: gen/go opts: paths: source_relative - name: go-grpc out: gen/go opts: paths: source_relative require_unimplemented_servers: false - name: validate out: gen/go opts: paths: source_relative lang: \"go\" - name: grpc-gateway out: gen/go opts: paths: source_relative - name: openapiv2 out: gen/openapi opts: simple_operation_ids: true"},{"id":"migration/protoc::11-go-grpc-gateway-validate-breaking-lint::24","title":"Миграция с protoc на EasyP","section":"11. Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint)","path":"/docs/guide/migration/protoc#11-go-grpc-gateway-validate-breaking-lint","headings":["11. Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint)"],"excerpt":"Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint) breaking: against_git_ref: main ignore: - ENUM_VALUE_SAME_NAME ```","content":"Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint) breaking: against_git_ref: main ignore: - ENUM_VALUE_SAME_NAME ```"},{"id":"migration/protoc::12-checklist::25","title":"Миграция с protoc на EasyP","section":"12. Checklist миграции","path":"/docs/guide/migration/protoc#12-checklist","headings":["12. Checklist миграции"],"excerpt":"Checklist миграции [ ] Собраны все текущие вызовы protoc. [ ] Создан easyp.yaml с секциями generate и (опционально) lint, breaking. [ ] Добавлены все внешние зависимости в deps. [ ] Успешно выполнен easyp mod update. [ ]","content":"Checklist миграции [ ] Собраны все текущие вызовы protoc. [ ] Создан easyp.yaml с секциями generate и (опционально) lint, breaking. [ ] Добавлены все внешние зависимости в deps. [ ] Успешно выполнен easyp mod update. [ ] easyp generate даёт идентичный или ожидаемо обновлённый результат. [ ] easyp lint проходит без критичных ошибок (или ошибки обработаны). [ ] easyp breaking --against git-ref=origin/main не выдаёт неожиданных блокирующих нарушений. [ ] CI обновлён (заменены прямые вызовы protoc). [ ] Документация проекта обновлена (README: как генерировать)."},{"id":"migration/protoc::13::26","title":"Миграция с protoc на EasyP","section":"13. Дополнительные рекомендации","path":"/docs/guide/migration/protoc#13","headings":["13. Дополнительные рекомендации"],"excerpt":"Дополнительные рекомендации Сначала мигрируйте один сервис / пакет — снизит риск массовых конфликтов. Закоммитьте easyp.yaml отдельно, затем выполните генерацию и линт — проще ревью. Если нужны разные наборы плагинов для","content":"Дополнительные рекомендации Сначала мигрируйте один сервис / пакет — снизит риск массовых конфликтов. Закоммитьте easyp.yaml отдельно, затем выполните генерацию и линт — проще ревью. Если нужны разные наборы плагинов для разных микросервисов — используйте несколько конфигов (например: easyp.microservice-a.yaml + easyp.microservice-b.yaml). Внедрите проверку актуальности генерации: шаг CI, который валидирует отсутствие diff после easyp generate."},{"id":"migration/protoc::14::27","title":"Миграция с protoc на EasyP","section":"14. Статус","path":"/docs/guide/migration/protoc#14","headings":["14. Статус"],"excerpt":"Статус Этот файл — русская расширенная версия, заменяющая placeholder “Work in progress”. При появлении новых возможностей EasyP (дополнительные поля в конфиге, новые плагины, расширения breaking‑проверок) обновите соотв","content":"Статус Этот файл — русская расширенная версия, заменяющая placeholder “Work in progress”. При появлении новых возможностей EasyP (дополнительные поля в конфиге, новые плагины, расширения breaking‑проверок) обновите соответствующие разделы."},{"id":"migration/protoc::14::28","title":"Миграция с protoc на EasyP","section":"14. Статус","path":"/docs/guide/migration/protoc#14","headings":["14. Статус"],"excerpt":"Статус Если нужен упрощённый вариант (только перевод без расширения), сообщи — могу сократить до минимальных двух блоков.","content":"Статус Если нужен упрощённый вариант (только перевод без расширения), сообщи — могу сократить до минимальных двух блоков."},{"id":"migration/protolock::top::0","title":"Protolock","path":"/docs/guide/migration/protolock","headings":[],"excerpt":"Protolock В процессе разработки","content":"Protolock В процессе разработки"},{"id":"migration/prototool::top::0","title":"Prototool","section":"Состояние","path":"/docs/guide/migration/prototool","headings":["Состояние"],"excerpt":"Состояние Этот раздел был помечен как “Work in progress” в оригинальной английской версии. Ниже — переведённое и дополненное практическое руководство по миграции с Prototool на EasyP. Имя инструмента Prototool не перевод","content":"Состояние Этот раздел был помечен как “Work in progress” в оригинальной английской версии. Ниже — переведённое и дополненное практическое руководство по миграции с Prototool на EasyP. Имя инструмента Prototool не переводится."},{"id":"migration/prototool::top::1","title":"Prototool","section":"Цель миграции","path":"/docs/guide/migration/prototool","headings":["Цель миграции"],"excerpt":"Цель миграции Перейти от конфигурации и рабочих процессов Prototool к эквиваленту на EasyP с минимальными изменениями, сохранив: Линтинг .proto файлов. Генерацию кода через protoc-плагины. Управление зависимостями. Прове","content":"Цель миграции Перейти от конфигурации и рабочих процессов Prototool к эквиваленту на EasyP с минимальными изменениями, сохранив: Линтинг .proto файлов. Генерацию кода через protoc-плагины. Управление зависимостями. Проверку несовместимых изменений (в Prototool это приходилось реализовывать внешними инструментами; в EasyP встроено)."},{"id":"migration/prototool::top::2","title":"Prototool","section":"Кратко о различиях","path":"/docs/guide/migration/prototool","headings":["Кратко о различиях"],"excerpt":"Кратко о различиях Область Prototool EasyP Комментарий --------- ----------- ------- ------------- Конфигурация prototool.yaml easyp.yaml Форматы YAML/JSON поддерживаются; структура отличается. Линтинг Встроенные наборы ","content":"Кратко о различиях Область Prototool EasyP Комментарий --------- ----------- ------- ------------- Конфигурация prototool.yaml easyp.yaml Форматы YAML/JSON поддерживаются; структура отличается. Линтинг Встроенные наборы + кастомные правила Наборы через lint.use, тонкая настройка ignore/except EasyP даёт больше гибкости группировки. Генерация Раздел generate + плагины через Docker/локально generate.plugins (локальные/WASM/удалённые) EasyP может выполнять плагины удалённо (API Service). Зависимости Обычно через include-пути / внешние git clone вручную Секция deps (Git репозитории) + mod update Более декларативно. Breaking Changes Нет встроенного механизма Секция breaking + команда easyp breaking Из коробки. Lock-in Зависимость от модели Prototool Минималистичный формат, «любой Git — пакет» Облегчает выход / интеграцию с другими экосистемами."},{"id":"migration/prototool::prototool::3","title":"Prototool","section":"Типовая структура Prototool (упрощённо)","path":"/docs/guide/migration/prototool#prototool","headings":["Типовая структура Prototool (упрощённо)"],"excerpt":"Типовая структура Prototool (упрощённо)","content":"Типовая структура Prototool (упрощённо)"},{"id":"migration/prototool::prototool::4","title":"Prototool","section":"Типовая структура Prototool (упрощённо)","path":"/docs/guide/migration/prototool#prototool","headings":["Типовая структура Prototool (упрощённо)"],"excerpt":"Типовая структура Prototool (упрощённо) Особенности: include_paths задаёт пути поиска импортов. lint.group + rules.add/remove регулируют активные проверки. generate.plugins описывает плагины для protoc.","content":"Типовая структура Prototool (упрощённо) Особенности: include_paths задаёт пути поиска импортов. lint.group + rules.add/remove регулируют активные проверки. generate.plugins описывает плагины для protoc."},{"id":"migration/prototool::prototool::5","title":"Prototool","section":"Типовая структура Prototool (упрощённо)","path":"/docs/guide/migration/prototool#prototool","headings":["Типовая структура Prototool (упрощённо)"],"excerpt":"Типовая структура Prototool (упрощённо) ---","content":"Типовая структура Prototool (упрощённо) ---"},{"id":"migration/prototool::easyp::6","title":"Prototool","section":"Эквивалент на EasyP","path":"/docs/guide/migration/prototool#easyp","headings":["Эквивалент на EasyP"],"excerpt":"Эквивалент на EasyP ```yaml easyp.yaml (пример) deps: - github.com/org/common-protos # вместо manual include - github.com/org/third-party-protos","content":"Эквивалент на EasyP ```yaml easyp.yaml (пример) deps: - github.com/org/common-protos # вместо manual include - github.com/org/third-party-protos"},{"id":"migration/prototool::easyp::7","title":"Prototool","section":"Эквивалент на EasyP","path":"/docs/guide/migration/prototool#easyp","headings":["Эквивалент на EasyP"],"excerpt":"Эквивалент на EasyP lint: use: - MINIMAL - BASIC enum_zero_value_suffix: \"_NONE\" service_suffix: \"Service\" ignore: - COMMENT_FIELD except: - ENUM_VALUE_PREFIX allow_comment_ignores: true","content":"Эквивалент на EasyP lint: use: - MINIMAL - BASIC enum_zero_value_suffix: \"_NONE\" service_suffix: \"Service\" ignore: - COMMENT_FIELD except: - ENUM_VALUE_PREFIX allow_comment_ignores: true"},{"id":"migration/prototool::easyp::8","title":"Prototool","section":"Эквивалент на EasyP","path":"/docs/guide/migration/prototool#easyp","headings":["Эквивалент на EasyP"],"excerpt":"Эквивалент на EasyP generate: plugins: - name: go out: gen/go opts: paths: source_relative - name: go-grpc out: gen/go opts: paths: source_relative require_unimplemented_servers: false","content":"Эквивалент на EasyP generate: plugins: - name: go out: gen/go opts: paths: source_relative - name: go-grpc out: gen/go opts: paths: source_relative require_unimplemented_servers: false"},{"id":"migration/prototool::easyp::9","title":"Prototool","section":"Эквивалент на EasyP","path":"/docs/guide/migration/prototool#easyp","headings":["Эквивалент на EasyP"],"excerpt":"Эквивалент на EasyP breaking: against_git_ref: main ignore: - FIELD_SAME_TYPE ```","content":"Эквивалент на EasyP breaking: against_git_ref: main ignore: - FIELD_SAME_TYPE ```"},{"id":"migration/prototool::easyp::10","title":"Prototool","section":"Эквивалент на EasyP","path":"/docs/guide/migration/prototool#easyp","headings":["Эквивалент на EasyP"],"excerpt":"Эквивалент на EasyP Комментарии: deps заменяет необходимость вручную прописывать include paths: EasyP подтянет их через git. lint.use активирует наборы правил (MINIMAL/BASIC/DEFAULT и т.д.). Дополнительные настройки (enu","content":"Эквивалент на EasyP Комментарии: deps заменяет необходимость вручную прописывать include paths: EasyP подтянет их через git. lint.use активирует наборы правил (MINIMAL/BASIC/DEFAULT и т.д.). Дополнительные настройки (enum_zero_value_suffix, service_suffix) задают политики нейминга. breaking позволяет сразу контролировать несовместимые изменения."},{"id":"migration/prototool::top::11","title":"Prototool","section":"Шаги миграции","path":"/docs/guide/migration/prototool","headings":["Шаги миграции"],"excerpt":"Шаги миграции Инвентаризация: - Соберите текущий prototool.yaml, списки include paths и плагины. - Зафиксируйте используемые кастомные правила, если есть.","content":"Шаги миграции Инвентаризация: - Соберите текущий prototool.yaml, списки include paths и плагины. - Зафиксируйте используемые кастомные правила, если есть."},{"id":"migration/prototool::top::12","title":"Prototool","section":"Шаги миграции","path":"/docs/guide/migration/prototool","headings":["Шаги миграции"],"excerpt":"Шаги миграции Зависимости: - Любые каталоги, которые вы вручную добавляли в include_paths, преобразуйте в git-репозитории (если ещё нет). - Добавьте их в deps (формат: github.com/owner/repo или путь к вашей приватной сис","content":"Шаги миграции Зависимости: - Любые каталоги, которые вы вручную добавляли в include_paths, преобразуйте в git-репозитории (если ещё нет). - Добавьте их в deps (формат: github.com/owner/repo или путь к вашей приватной системе Git)."},{"id":"migration/prototool::top::13","title":"Prototool","section":"Шаги миграции","path":"/docs/guide/migration/prototool","headings":["Шаги миграции"],"excerpt":"Шаги миграции Линтинг: - Определите какой group использовался (basic, default, …) → сопоставьте с наборами EasyP (MINIMAL, BASIC, DEFAULT). - Индивидуальные добавления (rules.add) перенесите в lint.use или except/ignore:","content":"Шаги миграции Линтинг: - Определите какой group использовался (basic, default, …) → сопоставьте с наборами EasyP (MINIMAL, BASIC, DEFAULT). - Индивидуальные добавления (rules.add) перенесите в lint.use или except/ignore: - Если правило нужно активировать — включите через набор или явно. - Если нужно отключить — добавьте в ignore."},{"id":"migration/prototool::top::14","title":"Prototool","section":"Шаги миграции","path":"/docs/guide/migration/prototool","headings":["Шаги миграции"],"excerpt":"Шаги миграции Генерация: - Сохраните список плагинов. В большинстве случаев имена совпадут (go, go-grpc, др.). - Если раньше использовали Docker-окружение Prototool — проверьте поддержку удалённых плагинов через API Serv","content":"Шаги миграции Генерация: - Сохраните список плагинов. В большинстве случаев имена совпадут (go, go-grpc, др.). - Если раньше использовали Docker-окружение Prototool — проверьте поддержку удалённых плагинов через API Service EasyP (опционально). - Перепишите в секцию generate.plugins."},{"id":"migration/prototool::top::15","title":"Prototool","section":"Шаги миграции","path":"/docs/guide/migration/prototool","headings":["Шаги миграции"],"excerpt":"Шаги миграции Дополнительные опции: - Настройки нейминга enum/service перенести в enum_zero_value_suffix, service_suffix. - Если были внешние скрипты для проверки breaking changes — удалите их и включите breaking с again","content":"Шаги миграции Дополнительные опции: - Настройки нейминга enum/service перенести в enum_zero_value_suffix, service_suffix. - Если были внешние скрипты для проверки breaking changes — удалите их и включите breaking с against_git_ref."},{"id":"migration/prototool::top::16","title":"Prototool","section":"Шаги миграции","path":"/docs/guide/migration/prototool","headings":["Шаги миграции"],"excerpt":"Шаги миграции Верификация: - Запустите: easyp mod update (скачивание deps). - Затем: easyp lint. - Далее: easyp generate. - И, если нужно: easyp breaking --against git-ref=origin/main.","content":"Шаги миграции Верификация: - Запустите: easyp mod update (скачивание deps). - Затем: easyp lint. - Далее: easyp generate. - И, если нужно: easyp breaking --against git-ref=origin/main."},{"id":"migration/prototool::top::17","title":"Prototool","section":"Шаги миграции","path":"/docs/guide/migration/prototool","headings":["Шаги миграции"],"excerpt":"Шаги миграции CI/CD: - Обновите workflow (GitHub Actions / GitLab) — замените вызовы Prototool на EasyP команды. - Добавьте шаг проверки несовместимых изменений.","content":"Шаги миграции CI/CD: - Обновите workflow (GitHub Actions / GitLab) — замените вызовы Prototool на EasyP команды. - Добавьте шаг проверки несовместимых изменений."},{"id":"migration/prototool::top::18","title":"Prototool","section":"Сопоставление правил (общая идея)","path":"/docs/guide/migration/prototool","headings":["Сопоставление правил (общая идея)"],"excerpt":"Сопоставление правил (общая идея) Prototool концепт EasyP ------------------- ------ lint.group lint.use (наборы) rules.add/remove except / ignore include_paths deps (git источники) plugins generate.plugins (внешние скри","content":"Сопоставление правил (общая идея) Prototool концепт EasyP ------------------- ------ lint.group lint.use (наборы) rules.add/remove except / ignore include_paths deps (git источники) plugins generate.plugins (внешние скрипты для breaking) breaking секция + команда"},{"id":"migration/prototool::top::19","title":"Prototool","section":"Сопоставление правил (общая идея)","path":"/docs/guide/migration/prototool","headings":["Сопоставление правил (общая идея)"],"excerpt":"Сопоставление правил (общая идея) ---","content":"Сопоставление правил (общая идея) ---"},{"id":"migration/prototool::top::20","title":"Prototool","section":"Приватные репозитории","path":"/docs/guide/migration/prototool","headings":["Приватные репозитории"],"excerpt":"Приватные репозитории Если ранее Prototool просто видел локальные каталоги, теперь: Добавьте SSH ключи/токены в CI для доступа к приватным Git. Укажите их в deps как обычные git-URL (формат зависит от реализации EasyP; д","content":"Приватные репозитории Если ранее Prototool просто видел локальные каталоги, теперь: Добавьте SSH ключи/токены в CI для доступа к приватным Git. Укажите их в deps как обычные git-URL (формат зависит от реализации EasyP; для публичных — стандартный)."},{"id":"migration/prototool::top::21","title":"Prototool","section":"Типовые проблемы при миграции","path":"/docs/guide/migration/prototool","headings":["Типовые проблемы при миграции"],"excerpt":"Типовые проблемы при миграции Проблема Причина Решение ---------- --------- --------- Правила линтера не совпадают Неверное сопоставление групп Проверить документацию EasyP по наборам правил Импорты не находятся Забыли д","content":"Типовые проблемы при миграции Проблема Причина Решение ---------- --------- --------- Правила линтера не совпадают Неверное сопоставление групп Проверить документацию EasyP по наборам правил Импорты не находятся Забыли добавить репозиторий в deps Добавить в deps и выполнить easyp mod update Генерация падает на опциях Плагин требует другие flags Проверить opts и документацию плагина breaking сообщает слишком много Слишком строгий базовый набор Добавить конкретные правила в breaking.ignore Долгая генерация Нет кеша/много deps Включить кэширование в CI (vendor/.easyp/deps)"},{"id":"migration/prototool::top::22","title":"Prototool","section":"Типовые проблемы при миграции","path":"/docs/guide/migration/prototool","headings":["Типовые проблемы при миграции"],"excerpt":"Типовые проблемы при миграции ---","content":"Типовые проблемы при миграции ---"},{"id":"migration/prototool::top::23","title":"Prototool","section":"Минимальная конфигурация после миграции","path":"/docs/guide/migration/prototool","headings":["Минимальная конфигурация после миграции"],"excerpt":"Минимальная конфигурация после миграции","content":"Минимальная конфигурация после миграции"},{"id":"migration/prototool::top::24","title":"Prototool","section":"Минимальная конфигурация после миграции","path":"/docs/guide/migration/prototool","headings":["Минимальная конфигурация после миграции"],"excerpt":"Минимальная конфигурация после миграции ---","content":"Минимальная конфигурация после миграции ---"},{"id":"migration/prototool::top::25","title":"Prototool","section":"Рекомендации по упрощению","path":"/docs/guide/migration/prototool","headings":["Рекомендации по упрощению"],"excerpt":"Рекомендации по упрощению Начните с минимального lint.use (MINIMAL), затем постепенно включайте дополнительные наборы. Не переносите слепо все ignore — часть правил может уже быть улучшена в EasyP. Сначала настроить deps","content":"Рекомендации по упрощению Начните с минимального lint.use (MINIMAL), затем постепенно включайте дополнительные наборы. Не переносите слепо все ignore — часть правил может уже быть улучшена в EasyP. Сначала настроить deps и генерацию, затем усложнять линт/нейминг. Фиксируйте миграцию по шагам (коммиты: deps → lint → generate → breaking → CI)."},{"id":"migration/prototool::top::26","title":"Prototool","section":"Проверка результата","path":"/docs/guide/migration/prototool","headings":["Проверка результата"],"excerpt":"Проверка результата Скрипт локальной быстрой проверки (пример):","content":"Проверка результата Скрипт локальной быстрой проверки (пример):"},{"id":"migration/prototool::top::27","title":"Prototool","section":"Проверка результата","path":"/docs/guide/migration/prototool","headings":["Проверка результата"],"excerpt":"Проверка результата ```bash #!/usr/bin/env bash set -euo pipefail","content":"Проверка результата ```bash #!/usr/bin/env bash set -euo pipefail"},{"id":"migration/prototool::top::28","title":"Prototool","section":"Проверка результата","path":"/docs/guide/migration/prototool","headings":["Проверка результата"],"excerpt":"Проверка результата echo \"[1] deps update\" easyp mod update","content":"Проверка результата echo \"[1] deps update\" easyp mod update"},{"id":"migration/prototool::top::29","title":"Prototool","section":"Проверка результата","path":"/docs/guide/migration/prototool","headings":["Проверка результата"],"excerpt":"Проверка результата echo \"[2] lint\" easyp lint","content":"Проверка результата echo \"[2] lint\" easyp lint"},{"id":"migration/prototool::top::30","title":"Prototool","section":"Проверка результата","path":"/docs/guide/migration/prototool","headings":["Проверка результата"],"excerpt":"Проверка результата echo \"[3] breaking vs main\" easyp breaking --against git-ref=origin/main echo \"Breaking changes detected (review needed)\"","content":"Проверка результата echo \"[3] breaking vs main\" easyp breaking --against git-ref=origin/main echo \"Breaking changes detected (review needed)\""},{"id":"migration/prototool::top::31","title":"Prototool","section":"Проверка результата","path":"/docs/guide/migration/prototool","headings":["Проверка результата"],"excerpt":"Проверка результата echo \"[4] generate\" easyp generate","content":"Проверка результата echo \"[4] generate\" easyp generate"},{"id":"migration/prototool::top::32","title":"Prototool","section":"Проверка результата","path":"/docs/guide/migration/prototool","headings":["Проверка результата"],"excerpt":"Проверка результата echo \"Done.\" ```","content":"Проверка результата echo \"Done.\" ```"},{"id":"migration/prototool::top::33","title":"Prototool","section":"Заключение","path":"/docs/guide/migration/prototool","headings":["Заключение"],"excerpt":"Заключение Миграция с Prototool на EasyP сводится к: Переносу путей и внешних каталогов в декларативные deps. Переформатированию линта под lint.use + ignore/except. Переносу генерации в generate.plugins. Добавлению встро","content":"Заключение Миграция с Prototool на EasyP сводится к: Переносу путей и внешних каталогов в декларативные deps. Переформатированию линта под lint.use + ignore/except. Переносу генерации в generate.plugins. Добавлению встроенного механизма breaking. Адаптации CI."},{"id":"migration/prototool::top::34","title":"Prototool","section":"Заключение","path":"/docs/guide/migration/prototool","headings":["Заключение"],"excerpt":"Заключение После этого конфигурация становится более прозрачной, а проверка несовместимых изменений — из коробки.","content":"Заключение После этого конфигурация становится более прозрачной, а проверка несовместимых изменений — из коробки."},{"id":"migration/prototool::top::35","title":"Prototool","section":"Заключение","path":"/docs/guide/migration/prototool","headings":["Заключение"],"excerpt":"Заключение *Готово: базовый перевод и расширенное руководство по миграции с Prototool на EasyP.*","content":"Заключение *Готово: базовый перевод и расширенное руководство по миграции с Prototool на EasyP.*"},{"id":"TRANSLATION_STATUS::top::0","title":"Translation Status (ru-guide)","path":"/docs/guide/TRANSLATION_STATUS","headings":[],"excerpt":"Этот файл отслеживает прогресс перевода русской документации. Используемые статусы: TODO — требуется перевод IN_PROGRESS — перевод начат, требуется вычитка DONE — перевод завершён и вычитан SKIPPED — не требует перевода ","content":"Этот файл отслеживает прогресс перевода русской документации. Используемые статусы: TODO — требуется перевод IN_PROGRESS — перевод начат, требуется вычитка DONE — перевод завершён и вычитан SKIPPED — не требует перевода (намеренно оставлено на английском)"},{"id":"TRANSLATION_STATUS::top::1","title":"Translation Status (ru-guide)","path":"/docs/guide/TRANSLATION_STATUS","headings":[],"excerpt":"Правила: После полного перевода файла убрать исходный английский текст и маркер Термины протокола и ключевые идентификаторы (названия правил, CLI команды, YAML ключи) НЕ переводим. Если структура исходного файла изменила","content":"Правила: После полного перевода файла убрать исходный английский текст и маркер Термины протокола и ключевые идентификаторы (названия правил, CLI команды, YAML ключи) НЕ переводим. Если структура исходного файла изменилась — добавить в начало: Для больших изменений: сначала IN_PROGRESS, после вычитки менять на DONE."},{"id":"TRANSLATION_STATUS::summary::2","title":"Translation Status (ru-guide)","section":"Summary","path":"/docs/guide/TRANSLATION_STATUS#summary","headings":["Summary"],"excerpt":"Summary Итого файлов: 76 DONE: 76 IN_PROGRESS: 0 TODO: 0","content":"Summary Итого файлов: 76 DONE: 76 IN_PROGRESS: 0 TODO: 0"},{"id":"TRANSLATION_STATUS::priority-order::3","title":"Translation Status (ru-guide)","section":"Priority Order (рекомендованный)","path":"/docs/guide/TRANSLATION_STATUS#priority-order","headings":["Priority Order (рекомендованный)"],"excerpt":"Priority Order (рекомендованный) introduction/what-is.md introduction/quickstart.md introduction/install.md cli/linter/linter.md cli/generator/generator.md cli/package-manager/package-manager.md cli/breaking-changes/brea","content":"Priority Order (рекомендованный) introduction/what-is.md introduction/quickstart.md introduction/install.md cli/linter/linter.md cli/generator/generator.md cli/package-manager/package-manager.md cli/breaking-changes/breaking-changes.md api-service/overview.md migration/* (пакетом)"},{"id":"TRANSLATION_STATUS::priority-order::4","title":"Translation Status (ru-guide)","section":"Priority Order (рекомендованный)","path":"/docs/guide/TRANSLATION_STATUS#priority-order","headings":["Priority Order (рекомендованный)"],"excerpt":"Priority Order (рекомендованный) ---","content":"Priority Order (рекомендованный) ---"},{"id":"TRANSLATION_STATUS::file-status-table::5","title":"Translation Status (ru-guide)","section":"File Status Table","path":"/docs/guide/TRANSLATION_STATUS#file-status-table","headings":["File Status Table"],"excerpt":"File Status Table File Status Notes ------ -------- ------- introduction/what-is.md DONE Полный перевод выполнен introduction/quickstart.md DONE Структура сохранена, перевод вычитан introduction/install.md DONE Переведен","content":"File Status Table File Status Notes ------ -------- ------- introduction/what-is.md DONE Полный перевод выполнен introduction/quickstart.md DONE Структура сохранена, перевод вычитан introduction/install.md DONE Переведено, команды проверены api-service/overview.md DONE Переведено ci-cd/github-actions.md DONE Переведено ci-cd/gitlab.md DONE Переведено cli/auto-completion/auto-completion.md DONE Переведено cli/breaking-changes/breaking-changes.md DONE Переведено и вычитано cli/breaking-changes/rules/enum-no-delete.md DONE Переведено cli/breaking-changes/rules/enum-value-no-delete.md DONE Переведено cli/breaking-changes/rules/enum-value-same-name.md DONE Переведено cli/breaking-changes/rules/field-no-delete.md DONE Переведено cli/breaking-changes/rules/field-same-cardinality.md DONE Переведено cli/breaking-changes/rules/field-same-type.md DONE Переведено cli/breaking-changes/rules/import-no-delete.md DONE Переведено cli/breaking-changes/rules/message-no-delete.md DONE Переведено cli/breaking-changes/rules/oneof-field-no-delete.md DONE Переведено cli/breaking-changes/rules/oneof-field-same-type.md DONE Переведено cli/breaking-changes/rules/oneof-no-delete.md DONE Переведено cli/breaking-changes/rules/rpc-no-delete.md DONE Переведено cli/breaking-changes/rules/rpc-same-request-type.md DONE Переведено cli/breaking-changes/rules/rpc-same-response-type.md DONE Переведено cli/breaking-changes/rules/service-no-delete.md DONE Переведено cli/configuration/configuration.md DONE Переведено cli/generator/examples/go.md DONE Переведено cli/generator/examples/grpc-gateway.md DONE Переведено cli/generator/examples/validate.md DONE Переведено cli/generator/generator.md DONE Переведено и вычитано cli/linter/linter.md DONE Переведено и вычитано cli/linter/rules/comment-enum-value.md DONE Переведено cli/linter/rules/comment-enum.md DONE Переведено cli/linter/rules/comment-field.md DONE Переведено cli/linter/rules/comment-message.md DONE Переведено cli/linter/rules/comment-oneof.md DONE Переведено cli/linter/rules/comment-rpc.md DONE Переведено cli/linter/rules/comment-service.md DONE Переведено cli/linter/rules/directory-same-package.md DONE Переведено cli/linter/rules/enum-first-value-zero.md DONE Переведено cli/linter/rules/enum-no-allow-alias.md DONE Переведено cli/linter/rules/enum-pascal-case.md DONE Переведено cli/linter/rules/enum-value-prefix.md DONE Переведено cli/linter/rules/enum-value-upper-snake-case.md DONE Переведено cli/linter/rules/enum-zero-value-suffix.md DONE Переведено cli/linter/rules/field-lower-snake-case.md DONE Переведено cli/linter/rules/file-lower-snake-case.md DONE Переведено cli/linter/rules/import-no-public.md DONE Переведено cli/linter/rules/import-no-weak.md DONE Переведено cli/linter/rules/import-used.md DONE Переведено cli/linter/rules/message-pascal-case.md DONE Переведено cli/linter/rules/oneof-lower-snake-case.md DONE Переведено cli/linter/rules/package-defined.md DONE Переведено cli/linter/rules/package-directory-match.md DONE Переведено cli/linter/rules/package-lower-snake-case.md DONE Переведено cli/linter/rules/package-same-csharp-namespace.md DONE Переведено cli/linter/rules/package-same-directory.md DONE Переведено cli/linter/rules/package-same-go-package.md DONE Переведено cli/linter/rules/package-same-java-multiple-files.md DONE Переведено cli/linter/rules/package-same-java-package.md DONE Переведено cli/linter/rules/package-same-php-namespace.md DONE Переведено cli/linter/rules/package-same-ruby-package.md DONE Переведено cli/linter/rules/package-same-swift-prefix.md DONE Переведено cli/linter/rules/package-version-suffix.md DONE Переведено cli/linter/rules/rpc-no-client-streaming.md DONE Переведено cli/linter/rules/rpc-no-server-streaming.md DONE Переведено cli/linter/rules/rpc-pascal-case.md DONE Переведено cli/linter/rules/rpc-request-response-unique.md DONE Переведено cli/linter/rules/rpc-request-standard-name.md DONE Переведено cli/linter/rules/rpc-response-standard-name.md DONE Переведено cli/linter/rules/service-pascal-case.md DONE Переведено cli/linter/rules/service-suffix.md DONE Переведено cli/package-manager/easyp-vs-buf.md DONE Переведено cli/package-manager/package-manager.md DONE Переведено и вычитано migration/buf-cli.md DONE Переведено migration/protoc.md DONE Переведено migration/protolock.md DONE Переведено migration/prototool.md DONE Переведено"},{"id":"TRANSLATION_STATUS::workflow::6","title":"Translation Status (ru-guide)","section":"Workflow","path":"/docs/guide/TRANSLATION_STATUS#workflow","headings":["Workflow"],"excerpt":"Workflow Выбираем файл со статусом TODO. Меняем статус на IN_PROGRESS здесь. Переводим, проверяем терминологию (сверка с глоссарием — добавить позже). Меняем статус на DONE. Удаляем маркер внутри файла.","content":"Workflow Выбираем файл со статусом TODO. Меняем статус на IN_PROGRESS здесь. Переводим, проверяем терминологию (сверка с глоссарием — добавить позже). Меняем статус на DONE. Удаляем маркер внутри файла."},{"id":"TRANSLATION_STATUS::planned-terminology::7","title":"Translation Status (ru-guide)","section":"Planned Terminology (черновик)","path":"/docs/guide/TRANSLATION_STATUS#planned-terminology","headings":["Planned Terminology (черновик)"],"excerpt":"Planned Terminology (черновик) EN RU Notes ---- ---- ------- Linting Линтинг Транслитерация Breaking Changes Несовместимые изменения Название секции Dependency Зависимость Code Generation Генерация кода Lock file Lock-фа","content":"Planned Terminology (черновик) EN RU Notes ---- ---- ------- Linting Линтинг Транслитерация Breaking Changes Несовместимые изменения Название секции Dependency Зависимость Code Generation Генерация кода Lock file Lock-файл Remote Plugin Удалённый плагин Package Manager Менеджер пакетов"},{"id":"TRANSLATION_STATUS::planned-terminology::8","title":"Translation Status (ru-guide)","section":"Planned Terminology (черновик)","path":"/docs/guide/TRANSLATION_STATUS#planned-terminology","headings":["Planned Terminology (черновик)"],"excerpt":"Planned Terminology (черновик) (Будет дополнено.)","content":"Planned Terminology (черновик) (Будет дополнено.)"},{"id":"TRANSLATION_STATUS::planned-terminology::9","title":"Translation Status (ru-guide)","section":"Planned Terminology (черновик)","path":"/docs/guide/TRANSLATION_STATUS#planned-terminology","headings":["Planned Terminology (черновик)"],"excerpt":"Planned Terminology (черновик) ---","content":"Planned Terminology (черновик) ---"},{"id":"TRANSLATION_STATUS::top::10","title":"Translation Status (ru-guide)","section":"История обновлений","path":"/docs/guide/TRANSLATION_STATUS","headings":["История обновлений"],"excerpt":"История обновлений Initial file created: all statuses set (3 IN_PROGRESS, rest TODO). Marked breaking-changes page as DONE. Linter rules (41 файлов) переведены: статусы DONE. Breaking-changes rules (15 файлов) вычитаны и","content":"История обновлений Initial file created: all statuses set (3 IN_PROGRESS, rest TODO). Marked breaking-changes page as DONE. Linter rules (41 файлов) переведены: статусы DONE. Breaking-changes rules (15 файлов) вычитаны и помечены DONE. Все оставшиеся страницы переведены: итог DONE = 76."}] \ No newline at end of file +[{"id":"api-service/overview::top::0","title":"Обзор API Service","path":"/docs/guide/api-service/overview","headings":[],"excerpt":"**Централизованный сервис выполнения protobuf‑плагинов для консистентной изолированной генерации кода**","content":"**Централизованный сервис выполнения protobuf‑плагинов для консистентной изолированной генерации кода**"},{"id":"api-service/overview::top::1","title":"Обзор API Service","path":"/docs/guide/api-service/overview","headings":[],"excerpt":"EasyP API Service устраняет хаос управления плагинами, предоставляя централизованный запуск protobuf/gRPC плагинов в изолированных Docker‑контейнерах. Он даёт единую платформу, позволяющую командам стандартизировать проц","content":"EasyP API Service устраняет хаос управления плагинами, предоставляя централизованный запуск protobuf/gRPC плагинов в изолированных Docker‑контейнерах. Он даёт единую платформу, позволяющую командам стандартизировать процесс генерации кода без операционных затрат на установку и поддержку плагинов на машинах разработчиков."},{"id":"api-service/overview::easyp-api-service::2","title":"Обзор API Service","section":"Зачем нужен EasyP API Service?","path":"/docs/guide/api-service/overview#easyp-api-service","headings":["Зачем нужен EasyP API Service?"],"excerpt":"Зачем нужен EasyP API Service?","content":"Зачем нужен EasyP API Service?"},{"id":"api-service/overview::top::3","title":"Обзор API Service","section":"Проблема","path":"/docs/guide/api-service/overview","headings":["Проблема"],"excerpt":"Проблема Управление генерацией protobuf/gRPC кода в командах порождает существенную операционную сложность:","content":"Проблема Управление генерацией protobuf/gRPC кода в командах порождает существенную операционную сложность:"},{"id":"api-service/overview::top::4","title":"Обзор API Service","section":"Несогласованность версий","path":"/docs/guide/api-service/overview","headings":["Несогласованность версий"],"excerpt":"Несогласованность версий Разработчики локально используют разные версии плагинов → расхождения в генерированном коде и падения сборки Синдром «у меня работает» при различиях окружений Требуется ручная координация, чтобы ","content":"Несогласованность версий Разработчики локально используют разные версии плагинов → расхождения в генерированном коде и падения сборки Синдром «у меня работает» при различиях окружений Требуется ручная координация, чтобы вся команда была синхронизирована по версиям"},{"id":"api-service/overview::top::5","title":"Обзор API Service","section":"Операционные накладные расходы","path":"/docs/guide/api-service/overview","headings":["Операционные накладные расходы"],"excerpt":"Операционные накладные расходы DevOps тратят время на установку и обновление плагинов на рабочих станциях Новый разработчик — ручная настройка правильных версий Обновление плагинов требует коммуникации с каждым отдельно ","content":"Операционные накладные расходы DevOps тратят время на установку и обновление плагинов на рабочих станциях Новый разработчик — ручная настройка правильных версий Обновление плагинов требует коммуникации с каждым отдельно Нет централизованного контроля утверждённых версий"},{"id":"api-service/overview::top::6","title":"Обзор API Service","section":"Риски безопасности и комплаенса","path":"/docs/guide/api-service/overview","headings":["Риски безопасности и комплаенса"],"excerpt":"Риски безопасности и комплаенса Плагины ставятся из разных источников без валидации Нет аудита: какой плагин для какого билда использовался Сложно применять политики безопасности к инструментам генерации","content":"Риски безопасности и комплаенса Плагины ставятся из разных источников без валидации Нет аудита: какой плагин для какого билда использовался Сложно применять политики безопасности к инструментам генерации"},{"id":"api-service/overview::top::7","title":"Обзор API Service","section":"Решение: централизованный запуск плагинов","path":"/docs/guide/api-service/overview","headings":["Решение: централизованный запуск плагинов"],"excerpt":"Решение: централизованный запуск плагинов EasyP API Service решает эти проблемы за счёт централизованного управления:","content":"Решение: централизованный запуск плагинов EasyP API Service решает эти проблемы за счёт централизованного управления:"},{"id":"api-service/overview::top::8","title":"Обзор API Service","section":"Решение: централизованный запуск плагинов","path":"/docs/guide/api-service/overview","headings":["Решение: централизованный запуск плагинов"],"excerpt":"Решение: централизованный запуск плагинов Проблема Решение ---------- --------- **Контроль версий** Мгновенное распространение новых версий через Docker‑образы **Операции** Команда эксплуатации управляет конфигурациями б","content":"Решение: централизованный запуск плагинов Проблема Решение ---------- --------- **Контроль версий** Мгновенное распространение новых версий через Docker‑образы **Операции** Команда эксплуатации управляет конфигурациями без доступа на машины разработчиков **Безопасность** Все плагины запускаются в изолированных контейнерах с ограничениями ресурсов **Консистентность** Единая среда выполнения вне зависимости от локальной установки **Опыт разработчика** Не нужно устанавливать и сопровождать плагины локально"},{"id":"api-service/overview::top::9","title":"Обзор API Service","section":"Архитектура","path":"/docs/guide/api-service/overview","headings":["Архитектура"],"excerpt":"Архитектура Архитектура сервиса упрощена и сфокусирована на надёжном выполнении плагинов:","content":"Архитектура Архитектура сервиса упрощена и сфокусирована на надёжном выполнении плагинов:"},{"id":"api-service/overview::api-layer::10","title":"Обзор API Service","section":"API Layer","path":"/docs/guide/api-service/overview#api-layer","headings":["API Layer"],"excerpt":"API Layer **gRPC Server** — основной API для запросов генерации Каждый запуск плагина — отдельный gRPC‑запрос Получает CodeGeneratorRequest от CLI","content":"API Layer **gRPC Server** — основной API для запросов генерации Каждый запуск плагина — отдельный gRPC‑запрос Получает CodeGeneratorRequest от CLI"},{"id":"api-service/overview::execution-engine::11","title":"Обзор API Service","section":"Execution Engine","path":"/docs/guide/api-service/overview#execution-engine","headings":["Execution Engine"],"excerpt":"Execution Engine **Docker Runtime** — изолированный запуск плагинов Подтягивает образы из публичных реестров (Docker Hub и т.п.) Применяет лимиты CPU/памяти на плагин","content":"Execution Engine **Docker Runtime** — изолированный запуск плагинов Подтягивает образы из публичных реестров (Docker Hub и т.п.) Применяет лимиты CPU/памяти на плагин"},{"id":"api-service/overview::storage-layer::12","title":"Обзор API Service","section":"Storage Layer","path":"/docs/guide/api-service/overview#storage-layer","headings":["Storage Layer"],"excerpt":"Storage Layer **PostgreSQL** хранит параметры выполнения: - Ограничения ресурсов (CPU, память) - Конфигурацию и метаданные плагинов - Логи выполнения (аудит) - _Примечание: функциональность хранения будет расширяться_","content":"Storage Layer **PostgreSQL** хранит параметры выполнения: - Ограничения ресурсов (CPU, память) - Конфигурацию и метаданные плагинов - Логи выполнения (аудит) - _Примечание: функциональность хранения будет расширяться_"},{"id":"api-service/overview::monitoring::13","title":"Обзор API Service","section":"Monitoring","path":"/docs/guide/api-service/overview#monitoring","headings":["Monitoring"],"excerpt":"Monitoring **Prometheus** — сбор метрик Отслеживает время выполнения, успешность, использование ресурсов","content":"Monitoring **Prometheus** — сбор метрик Отслеживает время выполнения, успешность, использование ресурсов"},{"id":"api-service/overview::easyp-cli::14","title":"Обзор API Service","section":"Локальное выполнение (EasyP CLI)","path":"/docs/guide/api-service/overview#easyp-cli","headings":["Локальное выполнение (EasyP CLI)"],"excerpt":"Локальное выполнение (EasyP CLI) При локальном запуске CLI поддерживает: **Installed plugins**: системно установленные protoc плагины **WASM plugins**: лёгкие WebAssembly плагины","content":"Локальное выполнение (EasyP CLI) При локальном запуске CLI поддерживает: **Installed plugins**: системно установленные protoc плагины **WASM plugins**: лёгкие WebAssembly плагины"},{"id":"api-service/overview::api-service::15","title":"Обзор API Service","section":"Удалённое выполнение (API Service)","path":"/docs/guide/api-service/overview#api-service","headings":["Удалённое выполнение (API Service)"],"excerpt":"Удалённое выполнение (API Service) При работе через сервис: **Только Docker**: плагины запускаются как контейнеры **Центральный контроль**: операционная команда управляет доступными версиями **Консистентная среда**: один","content":"Удалённое выполнение (API Service) При работе через сервис: **Только Docker**: плагины запускаются как контейнеры **Центральный контроль**: операционная команда управляет доступными версиями **Консистентная среда**: одинаковое окружение для всех разработчиков"},{"id":"api-service/overview::top::16","title":"Обзор API Service","section":"Шаги выполнения","path":"/docs/guide/api-service/overview","headings":["Шаги выполнения"],"excerpt":"Шаги выполнения **CLI Parsing**: CLI парсит локальные .proto файлы **Request Sending**: Отправляет CodeGeneratorRequest в API Service (по одному на плагин) **Parameter Lookup**: Сервис получает параметры запуска из Postg","content":"Шаги выполнения **CLI Parsing**: CLI парсит локальные .proto файлы **Request Sending**: Отправляет CodeGeneratorRequest в API Service (по одному на плагин) **Parameter Lookup**: Сервис получает параметры запуска из PostgreSQL **Docker Execution**: Запускает плагин в изолированном контейнере **Metrics Recording**: Записывает метрики после завершения **Response**: Возвращает сгенерированный код обратно в CLI"},{"id":"api-service/overview::top::17","title":"Обзор API Service","section":"Ключевые возможности","path":"/docs/guide/api-service/overview","headings":["Ключевые возможности"],"excerpt":"Ключевые возможности Возможность Описание ------------- ---------- **🐳 Изоляция плагинов** Каждый плагин в отдельном безопасном контейнере **⚙️ Контроль ресурсов** Лимиты CPU и памяти на уровне контейнера **📊 Метрики &","content":"Ключевые возможности Возможность Описание ------------- ---------- **🐳 Изоляция плагинов** Каждый плагин в отдельном безопасном контейнере **⚙️ Контроль ресурсов** Лимиты CPU и памяти на уровне контейнера **📊 Метрики & мониторинг** Полный набор Prometheus метрик **🔄 Управление версиями** Централизованно через Docker‑образы **⚡ Простой протокол** Стандарт CodeGeneratorRequest/Response **🔒 Безопасность прежде всего** Изоляция + ограниченные ресурсы"},{"id":"api-service/overview::top::18","title":"Обзор API Service","section":"Конфигурация","path":"/docs/guide/api-service/overview","headings":["Конфигурация"],"excerpt":"Конфигурация Сервис настраивается через переменные окружения.","content":"Конфигурация Сервис настраивается через переменные окружения."},{"id":"api-service/overview::top::19","title":"Обзор API Service","section":"Хранение параметров плагинов","path":"/docs/guide/api-service/overview","headings":["Хранение параметров плагинов"],"excerpt":"Хранение параметров плагинов PostgreSQL хранит параметры выполнения для каждого плагина:","content":"Хранение параметров плагинов PostgreSQL хранит параметры выполнения для каждого плагина:"},{"id":"api-service/overview::top::20","title":"Обзор API Service","section":"Хранение параметров плагинов","path":"/docs/guide/api-service/overview","headings":["Хранение параметров плагинов"],"excerpt":"Хранение параметров плагинов ::: tip Схема хранения будет расширена — аудит логов, аналитика использования, кеширование плагинов. :::","content":"Хранение параметров плагинов ::: tip Схема хранения будет расширена — аудит логов, аналитика использования, кеширование плагинов. :::"},{"id":"api-service/overview::easyp-cli::21","title":"Обзор API Service","section":"Интеграция с EasyP CLI","path":"/docs/guide/api-service/overview#easyp-cli","headings":["Интеграция с EasyP CLI"],"excerpt":"Интеграция с EasyP CLI Пример easyp.yaml для удалённого запуска:","content":"Интеграция с EasyP CLI Пример easyp.yaml для удалённого запуска:"},{"id":"api-service/overview::easyp-cli::22","title":"Обзор API Service","section":"Интеграция с EasyP CLI","path":"/docs/guide/api-service/overview#easyp-cli","headings":["Интеграция с EasyP CLI"],"excerpt":"Интеграция с EasyP CLI Запуск генерации:","content":"Интеграция с EasyP CLI Запуск генерации:"},{"id":"api-service/overview::easyp-cli::23","title":"Обзор API Service","section":"Интеграция с EasyP CLI","path":"/docs/guide/api-service/overview#easyp-cli","headings":["Интеграция с EasyP CLI"],"excerpt":"Интеграция с EasyP CLI CLI: Парсит protobuf‑файлы Отправляет отдельные запросы в сервис для каждого плагина Получает ответы с кодом Записывает файлы в указанные директории","content":"Интеграция с EasyP CLI CLI: Парсит protobuf‑файлы Отправляет отдельные запросы в сервис для каждого плагина Получает ответы с кодом Записывает файлы в указанные директории"},{"id":"api-service/overview::top::24","title":"Обзор API Service","section":"Доступные метрики","path":"/docs/guide/api-service/overview","headings":["Доступные метрики"],"excerpt":"Доступные метрики Метрики Prometheus:","content":"Доступные метрики Метрики Prometheus:"},{"id":"api-service/overview::top::25","title":"Обзор API Service","section":"Доступные метрики","path":"/docs/guide/api-service/overview","headings":["Доступные метрики"],"excerpt":"Доступные метрики Метрика Описание --------- ---------- easyp_api_service_api_grpc_server_handled_total Общее число gRPC запросов по статусам easyp_api_service_api_grpc_server_handling_seconds Гистограмма задержек gRPC e","content":"Доступные метрики Метрика Описание --------- ---------- easyp_api_service_api_grpc_server_handled_total Общее число gRPC запросов по статусам easyp_api_service_api_grpc_server_handling_seconds Гистограмма задержек gRPC easyp_api_service_generated_plugin_code_total Выполнения плагинов по имени easyp_api_service_repo_call_duration_seconds Латентность запросов к БД easyp_api_service_repo_errors_total Количество ошибок доступа к БД easyp_api_service_standard_panics_total Число восстановленных паник"},{"id":"api-service/overview::top::26","title":"Обзор API Service","section":"Характеристики производительности","path":"/docs/guide/api-service/overview","headings":["Характеристики производительности"],"excerpt":"Характеристики производительности Показатель Типичное значение Примечания ----------- ------------------- ----------- **Cold Start** 2–5 сек Первая загрузка образа **Warm Start** 100–500 мс Образ закеширован **Throughput","content":"Характеристики производительности Показатель Типичное значение Примечания ----------- ------------------- ----------- **Cold Start** 2–5 сек Первая загрузка образа **Warm Start** 100–500 мс Образ закеширован **Throughput** 20–50 одновременных Зависит от ресурсов **Memory Usage** 50–200 MB На выполнение одного плагина"},{"id":"api-service/overview::top::27","title":"Обзор API Service","section":"Изоляция контейнеров","path":"/docs/guide/api-service/overview","headings":["Изоляция контейнеров"],"excerpt":"Изоляция контейнеров Каждый плагин в отдельном эфемерном контейнере Нет сетевого доступа в процессе выполнения Лимиты CPU/памяти через Docker Контейнер удаляется после завершения","content":"Изоляция контейнеров Каждый плагин в отдельном эфемерном контейнере Нет сетевого доступа в процессе выполнения Лимиты CPU/памяти через Docker Контейнер удаляется после завершения"},{"id":"api-service/overview::api::28","title":"Обзор API Service","section":"Безопасность API","path":"/docs/guide/api-service/overview#api","headings":["Безопасность API"],"excerpt":"Безопасность API gRPC транспорт Поддержка токенов аутентификации (в продакшн окружениях) Валидация входных данных Аудитные логи в PostgreSQL","content":"Безопасность API gRPC транспорт Поддержка токенов аутентификации (в продакшн окружениях) Валидация входных данных Аудитные логи в PostgreSQL"},{"id":"api-service/overview::top::29","title":"Обзор API Service","section":"Масштабирование","path":"/docs/guide/api-service/overview","headings":["Масштабирование"],"excerpt":"Масштабирование **Горизонтальное**: несколько инстансов за балансировщиком **Ресурсы**: настройка лимитов для тяжёлых плагинов **База данных**: репликация PostgreSQL для отказоустойчивости","content":"Масштабирование **Горизонтальное**: несколько инстансов за балансировщиком **Ресурсы**: настройка лимитов для тяжёлых плагинов **База данных**: репликация PostgreSQL для отказоустойчивости"},{"id":"api-service/overview::top::30","title":"Обзор API Service","section":"Мониторинг","path":"/docs/guide/api-service/overview","headings":["Мониторинг"],"excerpt":"Мониторинг **Метрики**: Prometheus **Алертинг**: оповещения на высокие ошибки/латентность **Логи**: структурированные для аудита и отладки","content":"Мониторинг **Метрики**: Prometheus **Алертинг**: оповещения на высокие ошибки/латентность **Логи**: структурированные для аудита и отладки"},{"id":"api-service/overview::top::31","title":"Обзор API Service","section":"План развития","path":"/docs/guide/api-service/overview","headings":["План развития"],"excerpt":"План развития Запланировано: Кеширование результатов генерации Расширенный аудит и аналитика использования Поддержка приватных реестров плагинов Более умное распределение ресурсов","content":"План развития Запланировано: Кеширование результатов генерации Расширенный аудит и аналитика использования Поддержка приватных реестров плагинов Более умное распределение ресурсов"},{"id":"api-service/overview::top::32","title":"Обзор API Service","section":"Сообщество и поддержка","path":"/docs/guide/api-service/overview","headings":["Сообщество и поддержка"],"excerpt":"Сообщество и поддержка **💬 Telegram чат** — обсуждения **🐛 GitHub Issues** — баги и запросы фич **📖 Документация** — полный набор материалов","content":"Сообщество и поддержка **💬 Telegram чат** — обсуждения **🐛 GitHub Issues** — баги и запросы фич **📖 Документация** — полный набор материалов"},{"id":"api-service/overview::top::33","title":"Обзор API Service","section":"Сообщество и поддержка","path":"/docs/guide/api-service/overview","headings":["Сообщество и поддержка"],"excerpt":"Сообщество и поддержка *Упростите свои protobuf‑воркфлоу с централизованным управлением выполнением плагинов.*","content":"Сообщество и поддержка *Упростите свои protobuf‑воркфлоу с централизованным управлением выполнением плагинов.*"},{"id":"ci-cd/github-actions::top::0","title":"GitHub Actions","path":"/docs/guide/ci-cd/github-actions","headings":[],"excerpt":"Полное руководство по интеграции EasyP в конвейеры GitHub Actions для линтинга, проверки несовместимых изменений, генерации кода и автоматизации релизов.","content":"Полное руководство по интеграции EasyP в конвейеры GitHub Actions для линтинга, проверки несовместимых изменений, генерации кода и автоматизации релизов."},{"id":"ci-cd/github-actions::easyp-ci::1","title":"GitHub Actions","section":"Зачем использовать EasyP в CI","path":"/docs/guide/ci-cd/github-actions#easyp-ci","headings":["Зачем использовать EasyP в CI"],"excerpt":"Зачем использовать EasyP в CI Встраивание EasyP в GitHub Actions даёт: Единообразие правил линтинга и генерации между разработчиками. Автоматическое выявление несовместимых изменений (breaking changes) до мержа. Гарантию","content":"Зачем использовать EasyP в CI Встраивание EasyP в GitHub Actions даёт: Единообразие правил линтинга и генерации между разработчиками. Автоматическое выявление несовместимых изменений (breaking changes) до мержа. Гарантию, что сгенерированный код не «устарел» относительно .proto. Возможность централизованной проверки зависимостей и версии конфигурации."},{"id":"ci-cd/github-actions::top::2","title":"GitHub Actions","section":"Предварительные требования","path":"/docs/guide/ci-cd/github-actions","headings":["Предварительные требования"],"excerpt":"Предварительные требования Репозиторий содержит файл конфигурации easyp.yaml (или находится в корне, если запускается без --cfg). Установлены / определены зависимости в секции deps (если нужны внешние импорты). Для прива","content":"Предварительные требования Репозиторий содержит файл конфигурации easyp.yaml (или находится в корне, если запускается без --cfg). Установлены / определены зависимости в секции deps (если нужны внешние импорты). Для приватных Git-репозиториев настроен доступ (SSH key / deploy key / токен). В workflow есть шаги по установке Go (если EasyP поставляется через go install) или заранее подготовленный бинарь."},{"id":"ci-cd/github-actions::top::3","title":"GitHub Actions","section":"Базовый пример (быстрый старт)","path":"/docs/guide/ci-cd/github-actions","headings":["Базовый пример (быстрый старт)"],"excerpt":"Базовый пример (быстрый старт) Минимальный workflow для проверки линта и несовместимых изменений при открытия Pull Request:","content":"Базовый пример (быстрый старт) Минимальный workflow для проверки линта и несовместимых изменений при открытия Pull Request:"},{"id":"ci-cd/github-actions::top::4","title":"GitHub Actions","section":"Базовый пример (быстрый старт)","path":"/docs/guide/ci-cd/github-actions","headings":["Базовый пример (быстрый старт)"],"excerpt":"Базовый пример (быстрый старт) ```yaml name: easyp-ci","content":"Базовый пример (быстрый старт) ```yaml name: easyp-ci"},{"id":"ci-cd/github-actions::top::5","title":"GitHub Actions","section":"Базовый пример (быстрый старт)","path":"/docs/guide/ci-cd/github-actions","headings":["Базовый пример (быстрый старт)"],"excerpt":"Базовый пример (быстрый старт) on: pull_request: paths: - '**/*.proto' - 'easyp.yaml'","content":"Базовый пример (быстрый старт) on: pull_request: paths: - '**/*.proto' - 'easyp.yaml'"},{"id":"ci-cd/github-actions::top::6","title":"GitHub Actions","section":"Базовый пример (быстрый старт)","path":"/docs/guide/ci-cd/github-actions","headings":["Базовый пример (быстрый старт)"],"excerpt":"Базовый пример (быстрый старт) jobs: lint-and-breaking: runs-on: ubuntu-latest","content":"Базовый пример (быстрый старт) jobs: lint-and-breaking: runs-on: ubuntu-latest"},{"id":"ci-cd/github-actions::top::7","title":"GitHub Actions","section":"Базовый пример (быстрый старт)","path":"/docs/guide/ci-cd/github-actions","headings":["Базовый пример (быстрый старт)"],"excerpt":"Базовый пример (быстрый старт) steps: - name: Checkout uses: actions/checkout@v4","content":"Базовый пример (быстрый старт) steps: - name: Checkout uses: actions/checkout@v4"},{"id":"ci-cd/github-actions::top::8","title":"GitHub Actions","section":"Базовый пример (быстрый старт)","path":"/docs/guide/ci-cd/github-actions","headings":["Базовый пример (быстрый старт)"],"excerpt":"Базовый пример (быстрый старт) name: Setup Go uses: actions/setup-go@v5 with: go-version: '1.22'","content":"Базовый пример (быстрый старт) name: Setup Go uses: actions/setup-go@v5 with: go-version: '1.22'"},{"id":"ci-cd/github-actions::top::9","title":"GitHub Actions","section":"Базовый пример (быстрый старт)","path":"/docs/guide/ci-cd/github-actions","headings":["Базовый пример (быстрый старт)"],"excerpt":"Базовый пример (быстрый старт) name: Install EasyP run: go install github.com/easyp-tech/easyp/cmd/easyp@latest","content":"Базовый пример (быстрый старт) name: Install EasyP run: go install github.com/easyp-tech/easyp/cmd/easyp@latest"},{"id":"ci-cd/github-actions::top::10","title":"GitHub Actions","section":"Базовый пример (быстрый старт)","path":"/docs/guide/ci-cd/github-actions","headings":["Базовый пример (быстрый старт)"],"excerpt":"Базовый пример (быстрый старт) name: Verify EasyP version run: which easyp easyp version","content":"Базовый пример (быстрый старт) name: Verify EasyP version run: which easyp easyp version"},{"id":"ci-cd/github-actions::top::11","title":"GitHub Actions","section":"Базовый пример (быстрый старт)","path":"/docs/guide/ci-cd/github-actions","headings":["Базовый пример (быстрый старт)"],"excerpt":"Базовый пример (быстрый старт) name: Lint run: easyp lint","content":"Базовый пример (быстрый старт) name: Lint run: easyp lint"},{"id":"ci-cd/github-actions::top::12","title":"GitHub Actions","section":"Базовый пример (быстрый старт)","path":"/docs/guide/ci-cd/github-actions","headings":["Базовый пример (быстрый старт)"],"excerpt":"Базовый пример (быстрый старт) name: Breaking changes check (against main) run: easyp breaking --against git-ref=origin/main ```","content":"Базовый пример (быстрый старт) name: Breaking changes check (against main) run: easyp breaking --against git-ref=origin/main ```"},{"id":"ci-cd/github-actions::easyp::13","title":"GitHub Actions","section":"Установка EasyP","path":"/docs/guide/ci-cd/github-actions#easyp","headings":["Установка EasyP"],"excerpt":"Установка EasyP Варианты: Через go install (как в примере выше). Использование заранее собранного бинаря (артефакт релиза).","content":"Установка EasyP Варианты: Через go install (как в примере выше). Использование заранее собранного бинаря (артефакт релиза)."},{"id":"ci-cd/github-actions::top::14","title":"GitHub Actions","section":"Кэширование","path":"/docs/guide/ci-cd/github-actions","headings":["Кэширование"],"excerpt":"Кэширование Для ускорения повторных сборок можно кэшировать: Go модульный кеш (если используете генерацию с плагинами Go). Внешние зависимые Git-клонирования (папки vendor или содержимое deps при использовании easyp mod ","content":"Кэширование Для ускорения повторных сборок можно кэшировать: Go модульный кеш (если используете генерацию с плагинами Go). Внешние зависимые Git-клонирования (папки vendor или содержимое deps при использовании easyp mod download / easyp mod update). Сгенерированный код (если он тяжёлый, но чаще генерируется заново)."},{"id":"ci-cd/github-actions::top::15","title":"GitHub Actions","section":"Кэширование","path":"/docs/guide/ci-cd/github-actions","headings":["Кэширование"],"excerpt":"Кэширование Пример кэширования Go:","content":"Кэширование Пример кэширования Go:"},{"id":"ci-cd/github-actions::top::16","title":"GitHub Actions","section":"Кэширование","path":"/docs/guide/ci-cd/github-actions","headings":["Кэширование"],"excerpt":"Кэширование Пример кэширования каталога зависимостей EasyP (если вы используете локальный vendor-подход):","content":"Кэширование Пример кэширования каталога зависимостей EasyP (если вы используете локальный vendor-подход):"},{"id":"ci-cd/github-actions::top::17","title":"GitHub Actions","section":"Кэширование","path":"/docs/guide/ci-cd/github-actions","headings":["Кэширование"],"excerpt":"Кэширование (Создайте .easyp/deps как целевой каталог, если ваша стратегия скачивания такова.)","content":"Кэширование (Создайте .easyp/deps как целевой каталог, если ваша стратегия скачивания такова.)"},{"id":"ci-cd/github-actions::top::18","title":"GitHub Actions","section":"Линтинг","path":"/docs/guide/ci-cd/github-actions","headings":["Линтинг"],"excerpt":"Линтинг Рекомендуется: В PR: всегда запускать. На main: можно запускать для верификации перед релизом.","content":"Линтинг Рекомендуется: В PR: всегда запускать. На main: можно запускать для верификации перед релизом."},{"id":"ci-cd/github-actions::top::19","title":"GitHub Actions","section":"Линтинг","path":"/docs/guide/ci-cd/github-actions","headings":["Линтинг"],"excerpt":"Линтинг Расширенный пример с выводом подробностей и игнорированием комментариев (если включено в конфиг):","content":"Линтинг Расширенный пример с выводом подробностей и игнорированием комментариев (если включено в конфиг):"},{"id":"ci-cd/github-actions::breaking-changes::20","title":"GitHub Actions","section":"Проверка несовместимых изменений (Breaking Changes)","path":"/docs/guide/ci-cd/github-actions#breaking-changes","headings":["Проверка несовместимых изменений (Breaking Changes)"],"excerpt":"Проверка несовместимых изменений (Breaking Changes) EasyP может сравнивать текущее состояние против ветки / коммита / тега.","content":"Проверка несовместимых изменений (Breaking Changes) EasyP может сравнивать текущее состояние против ветки / коммита / тега."},{"id":"ci-cd/github-actions::breaking-changes::21","title":"GitHub Actions","section":"Проверка несовместимых изменений (Breaking Changes)","path":"/docs/guide/ci-cd/github-actions#breaking-changes","headings":["Проверка несовместимых изменений (Breaking Changes)"],"excerpt":"Проверка несовместимых изменений (Breaking Changes) Примеры: ```bash Сравнить против origin/main easyp breaking --against git-ref=origin/main","content":"Проверка несовместимых изменений (Breaking Changes) Примеры: ```bash Сравнить против origin/main easyp breaking --against git-ref=origin/main"},{"id":"ci-cd/github-actions::breaking-changes::22","title":"GitHub Actions","section":"Проверка несовместимых изменений (Breaking Changes)","path":"/docs/guide/ci-cd/github-actions#breaking-changes","headings":["Проверка несовместимых изменений (Breaking Changes)"],"excerpt":"Проверка несовместимых изменений (Breaking Changes) Сравнить против тега релиза easyp breaking --against git-ref=v1.5.2","content":"Проверка несовместимых изменений (Breaking Changes) Сравнить против тега релиза easyp breaking --against git-ref=v1.5.2"},{"id":"ci-cd/github-actions::breaking-changes::23","title":"GitHub Actions","section":"Проверка несовместимых изменений (Breaking Changes)","path":"/docs/guide/ci-cd/github-actions#breaking-changes","headings":["Проверка несовместимых изменений (Breaking Changes)"],"excerpt":"Проверка несовместимых изменений (Breaking Changes) Игнорировать определённые правила (если у вас настроено в easyp.yaml) easyp breaking ```","content":"Проверка несовместимых изменений (Breaking Changes) Игнорировать определённые правила (если у вас настроено в easyp.yaml) easyp breaking ```"},{"id":"ci-cd/github-actions::breaking-changes::24","title":"GitHub Actions","section":"Проверка несовместимых изменений (Breaking Changes)","path":"/docs/guide/ci-cd/github-actions#breaking-changes","headings":["Проверка несовместимых изменений (Breaking Changes)"],"excerpt":"Проверка несовместимых изменений (Breaking Changes) Workflow шаг:","content":"Проверка несовместимых изменений (Breaking Changes) Workflow шаг:"},{"id":"ci-cd/github-actions::breaking-changes::25","title":"GitHub Actions","section":"Проверка несовместимых изменений (Breaking Changes)","path":"/docs/guide/ci-cd/github-actions#breaking-changes","headings":["Проверка несовместимых изменений (Breaking Changes)"],"excerpt":"Проверка несовместимых изменений (Breaking Changes)","content":"Проверка несовместимых изменений (Breaking Changes)"},{"id":"ci-cd/github-actions::breaking-changes::26","title":"GitHub Actions","section":"Проверка несовместимых изменений (Breaking Changes)","path":"/docs/guide/ci-cd/github-actions#breaking-changes","headings":["Проверка несовместимых изменений (Breaking Changes)"],"excerpt":"Проверка несовместимых изменений (Breaking Changes) Если нужно «мягко» пропустить (например, выводить предупреждения, но не падать билд):","content":"Проверка несовместимых изменений (Breaking Changes) Если нужно «мягко» пропустить (например, выводить предупреждения, но не падать билд):"},{"id":"ci-cd/github-actions::breaking-changes::27","title":"GitHub Actions","section":"Проверка несовместимых изменений (Breaking Changes)","path":"/docs/guide/ci-cd/github-actions#breaking-changes","headings":["Проверка несовместимых изменений (Breaking Changes)"],"excerpt":"Проверка несовместимых изменений (Breaking Changes)","content":"Проверка несовместимых изменений (Breaking Changes)"},{"id":"ci-cd/github-actions::top::28","title":"GitHub Actions","section":"Генерация кода","path":"/docs/guide/ci-cd/github-actions","headings":["Генерация кода"],"excerpt":"Генерация кода Обычно для генерации:","content":"Генерация кода Обычно для генерации:"},{"id":"ci-cd/github-actions::top::29","title":"GitHub Actions","section":"Генерация кода","path":"/docs/guide/ci-cd/github-actions","headings":["Генерация кода"],"excerpt":"Генерация кода Если нужно явно указать конфиг:","content":"Генерация кода Если нужно явно указать конфиг:"},{"id":"ci-cd/github-actions::top::30","title":"GitHub Actions","section":"Генерация кода","path":"/docs/guide/ci-cd/github-actions","headings":["Генерация кода"],"excerpt":"Генерация кода Можно добавить проверку «не осталось ли не закоммиченных изменений» (гарантия, что сгенерированный код актуален):","content":"Генерация кода Можно добавить проверку «не осталось ли не закоммиченных изменений» (гарантия, что сгенерированный код актуален):"},{"id":"ci-cd/github-actions::matrix-strategy::31","title":"GitHub Actions","section":"Матрица (Matrix strategy)","path":"/docs/guide/ci-cd/github-actions#matrix-strategy","headings":["Матрица (Matrix strategy)"],"excerpt":"Матрица (Matrix strategy) Если у вас несколько вариантов конфигураций или разных языков генерации (через плагины), можно использовать matrix:","content":"Матрица (Matrix strategy) Если у вас несколько вариантов конфигураций или разных языков генерации (через плагины), можно использовать matrix:"},{"id":"ci-cd/github-actions::matrix-strategy::32","title":"GitHub Actions","section":"Матрица (Matrix strategy)","path":"/docs/guide/ci-cd/github-actions#matrix-strategy","headings":["Матрица (Matrix strategy)"],"excerpt":"Матрица (Matrix strategy) ```yaml jobs: generate: runs-on: ubuntu-latest strategy: fail-fast: false matrix: lang: [go, python] steps: - uses: actions/checkout@v4","content":"Матрица (Matrix strategy) ```yaml jobs: generate: runs-on: ubuntu-latest strategy: fail-fast: false matrix: lang: [go, python] steps: - uses: actions/checkout@v4"},{"id":"ci-cd/github-actions::matrix-strategy::33","title":"GitHub Actions","section":"Матрица (Matrix strategy)","path":"/docs/guide/ci-cd/github-actions#matrix-strategy","headings":["Матрица (Matrix strategy)"],"excerpt":"Матрица (Matrix strategy) name: Setup Go (only for go) if: matrix.lang == 'go' uses: actions/setup-go@v5 with: go-version: '1.22'","content":"Матрица (Matrix strategy) name: Setup Go (only for go) if: matrix.lang == 'go' uses: actions/setup-go@v5 with: go-version: '1.22'"},{"id":"ci-cd/github-actions::matrix-strategy::34","title":"GitHub Actions","section":"Матрица (Matrix strategy)","path":"/docs/guide/ci-cd/github-actions#matrix-strategy","headings":["Матрица (Matrix strategy)"],"excerpt":"Матрица (Matrix strategy) name: Install EasyP run: go install github.com/easyp-tech/easyp/cmd/easyp@latest","content":"Матрица (Matrix strategy) name: Install EasyP run: go install github.com/easyp-tech/easyp/cmd/easyp@latest"},{"id":"ci-cd/github-actions::matrix-strategy::35","title":"GitHub Actions","section":"Матрица (Matrix strategy)","path":"/docs/guide/ci-cd/github-actions#matrix-strategy","headings":["Матрица (Matrix strategy)"],"excerpt":"Матрица (Matrix strategy) name: Generate run: if [ \"${{ matrix.lang }}\" = \"go\" ]; then easyp generate elif [ \"${{ matrix.lang }}\" = \"python\" ]; then easyp generate --plugin python fi ```","content":"Матрица (Matrix strategy) name: Generate run: if [ \"${{ matrix.lang }}\" = \"go\" ]; then easyp generate elif [ \"${{ matrix.lang }}\" = \"python\" ]; then easyp generate --plugin python fi ```"},{"id":"ci-cd/github-actions::deps::36","title":"GitHub Actions","section":"Работа с приватными репозиториями (deps)","path":"/docs/guide/ci-cd/github-actions#deps","headings":["Работа с приватными репозиториями (deps)"],"excerpt":"Работа с приватными репозиториями (deps) Если вы указываете приватные Git-пакеты в секции deps:","content":"Работа с приватными репозиториями (deps) Если вы указываете приватные Git-пакеты в секции deps:"},{"id":"ci-cd/github-actions::deps::37","title":"GitHub Actions","section":"Работа с приватными репозиториями (deps)","path":"/docs/guide/ci-cd/github-actions#deps","headings":["Работа с приватными репозиториями (deps)"],"excerpt":"Работа с приватными репозиториями (deps) Настройте deploy key или используйте GIT_SSH_COMMAND с токеном. Добавьте known_hosts (либо установите StrictHostKeyChecking=no для внутренних систем, но осознанно).","content":"Работа с приватными репозиториями (deps) Настройте deploy key или используйте GIT_SSH_COMMAND с токеном. Добавьте known_hosts (либо установите StrictHostKeyChecking=no для внутренних систем, но осознанно)."},{"id":"ci-cd/github-actions::deps::38","title":"GitHub Actions","section":"Работа с приватными репозиториями (deps)","path":"/docs/guide/ci-cd/github-actions#deps","headings":["Работа с приватными репозиториями (deps)"],"excerpt":"Работа с приватными репозиториями (deps) Пример:","content":"Работа с приватными репозиториями (deps) Пример:"},{"id":"ci-cd/github-actions::deps::39","title":"GitHub Actions","section":"Работа с приватными репозиториями (deps)","path":"/docs/guide/ci-cd/github-actions#deps","headings":["Работа с приватными репозиториями (deps)"],"excerpt":"Работа с приватными репозиториями (deps) ```yaml name: Prepare SSH run: mkdir -p ~/.ssh echo \"${{ secrets.DEPLOY_KEY }}\" > ~/.ssh/id_rsa chmod 600 ~/.ssh/id_rsa ssh-keyscan github.com >> ~/.ssh/known_hosts","content":"Работа с приватными репозиториями (deps) ```yaml name: Prepare SSH run: mkdir -p ~/.ssh echo \"${{ secrets.DEPLOY_KEY }}\" > ~/.ssh/id_rsa chmod 600 ~/.ssh/id_rsa ssh-keyscan github.com >> ~/.ssh/known_hosts"},{"id":"ci-cd/github-actions::deps::40","title":"GitHub Actions","section":"Работа с приватными репозиториями (deps)","path":"/docs/guide/ci-cd/github-actions#deps","headings":["Работа с приватными репозиториями (deps)"],"excerpt":"Работа с приватными репозиториями (deps) name: Update deps run: easyp mod update ```","content":"Работа с приватными репозиториями (deps) name: Update deps run: easyp mod update ```"},{"id":"ci-cd/github-actions::top::41","title":"GitHub Actions","section":"Оптимизация времени сборки","path":"/docs/guide/ci-cd/github-actions","headings":["Оптимизация времени сборки"],"excerpt":"Оптимизация времени сборки Используйте кэш для Go / deps. Запускайте линт/брейкинг только если изменились .proto или easyp.yaml (paths фильтр). Разделяйте workflow: быстрый линт в PR, тяжелая генерация в push на main. Вы","content":"Оптимизация времени сборки Используйте кэш для Go / deps. Запускайте линт/брейкинг только если изменились .proto или easyp.yaml (paths фильтр). Разделяйте workflow: быстрый линт в PR, тяжелая генерация в push на main. Выносите генерацию OpenAPI / gRPC-Gateway в отдельный job (параллелизм)."},{"id":"ci-cd/github-actions::workflow::42","title":"GitHub Actions","section":"Продвинутый workflow (многостадийный)","path":"/docs/guide/ci-cd/github-actions#workflow","headings":["Продвинутый workflow (многостадийный)"],"excerpt":"Продвинутый workflow (многостадийный) ```yaml name: easyp-pipeline","content":"Продвинутый workflow (многостадийный) ```yaml name: easyp-pipeline"},{"id":"ci-cd/github-actions::workflow::43","title":"GitHub Actions","section":"Продвинутый workflow (многостадийный)","path":"/docs/guide/ci-cd/github-actions#workflow","headings":["Продвинутый workflow (многостадийный)"],"excerpt":"Продвинутый workflow (многостадийный) on: pull_request: paths: - '**/*.proto' - 'easyp.yaml' push: branches: - main","content":"Продвинутый workflow (многостадийный) on: pull_request: paths: - '**/*.proto' - 'easyp.yaml' push: branches: - main"},{"id":"ci-cd/github-actions::workflow::44","title":"GitHub Actions","section":"Продвинутый workflow (многостадийный)","path":"/docs/guide/ci-cd/github-actions#workflow","headings":["Продвинутый workflow (многостадийный)"],"excerpt":"Продвинутый workflow (многостадийный) jobs: validate: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4","content":"Продвинутый workflow (многостадийный) jobs: validate: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4"},{"id":"ci-cd/github-actions::workflow::45","title":"GitHub Actions","section":"Продвинутый workflow (многостадийный)","path":"/docs/guide/ci-cd/github-actions#workflow","headings":["Продвинутый workflow (многостадийный)"],"excerpt":"Продвинутый workflow (многостадийный) uses: actions/setup-go@v5 with: go-version: '1.22'","content":"Продвинутый workflow (многостадийный) uses: actions/setup-go@v5 with: go-version: '1.22'"},{"id":"ci-cd/github-actions::workflow::46","title":"GitHub Actions","section":"Продвинутый workflow (многостадийный)","path":"/docs/guide/ci-cd/github-actions#workflow","headings":["Продвинутый workflow (многостадийный)"],"excerpt":"Продвинутый workflow (многостадийный) name: Install EasyP run: go install github.com/easyp-tech/easyp/cmd/easyp@latest","content":"Продвинутый workflow (многостадийный) name: Install EasyP run: go install github.com/easyp-tech/easyp/cmd/easyp@latest"},{"id":"ci-cd/github-actions::workflow::47","title":"GitHub Actions","section":"Продвинутый workflow (многостадийный)","path":"/docs/guide/ci-cd/github-actions#workflow","headings":["Продвинутый workflow (многостадийный)"],"excerpt":"Продвинутый workflow (многостадийный) name: Lint run: easyp lint","content":"Продвинутый workflow (многостадийный) name: Lint run: easyp lint"},{"id":"ci-cd/github-actions::workflow::48","title":"GitHub Actions","section":"Продвинутый workflow (многостадийный)","path":"/docs/guide/ci-cd/github-actions#workflow","headings":["Продвинутый workflow (многостадийный)"],"excerpt":"Продвинутый workflow (многостадийный) name: Breaking check (against main) if: github.event_name == 'pull_request' run: easyp breaking --against git-ref=origin/main","content":"Продвинутый workflow (многостадийный) name: Breaking check (against main) if: github.event_name == 'pull_request' run: easyp breaking --against git-ref=origin/main"},{"id":"ci-cd/github-actions::workflow::49","title":"GitHub Actions","section":"Продвинутый workflow (многостадийный)","path":"/docs/guide/ci-cd/github-actions#workflow","headings":["Продвинутый workflow (многостадийный)"],"excerpt":"Продвинутый workflow (многостадийный) generate: needs: validate if: github.event_name == 'push' runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-go@v5 with: go-version: '1.22' - name: Insta","content":"Продвинутый workflow (многостадийный) generate: needs: validate if: github.event_name == 'push' runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-go@v5 with: go-version: '1.22' - name: Install EasyP run: go install github.com/easyp-tech/easyp/cmd/easyp@latest - name: Generate Code run: easyp generate - name: Check diffs run: if [ -n \"$(git status --porcelain)\" ]; then echo \"Generated files changed after generate step.\" git diff --name-only exit 1 fi ```"},{"id":"ci-cd/github-actions::top::50","title":"GitHub Actions","section":"Автоматизация релиза (пример)","path":"/docs/guide/ci-cd/github-actions","headings":["Автоматизация релиза (пример)"],"excerpt":"Автоматизация релиза (пример) Можно добавить workflow, который по тегу создаёт релиз и валидирует proto:","content":"Автоматизация релиза (пример) Можно добавить workflow, который по тегу создаёт релиз и валидирует proto:"},{"id":"ci-cd/github-actions::top::51","title":"GitHub Actions","section":"Автоматизация релиза (пример)","path":"/docs/guide/ci-cd/github-actions","headings":["Автоматизация релиза (пример)"],"excerpt":"Автоматизация релиза (пример) ```yaml name: release-verify","content":"Автоматизация релиза (пример) ```yaml name: release-verify"},{"id":"ci-cd/github-actions::top::52","title":"GitHub Actions","section":"Автоматизация релиза (пример)","path":"/docs/guide/ci-cd/github-actions","headings":["Автоматизация релиза (пример)"],"excerpt":"Автоматизация релиза (пример) on: push: tags: - 'v*.*.*'","content":"Автоматизация релиза (пример) on: push: tags: - 'v*.*.*'"},{"id":"ci-cd/github-actions::top::53","title":"GitHub Actions","section":"Автоматизация релиза (пример)","path":"/docs/guide/ci-cd/github-actions","headings":["Автоматизация релиза (пример)"],"excerpt":"Автоматизация релиза (пример) jobs: release-check: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4","content":"Автоматизация релиза (пример) jobs: release-check: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4"},{"id":"ci-cd/github-actions::top::54","title":"GitHub Actions","section":"Автоматизация релиза (пример)","path":"/docs/guide/ci-cd/github-actions","headings":["Автоматизация релиза (пример)"],"excerpt":"Автоматизация релиза (пример) uses: actions/setup-go@v5 with: go-version: '1.22'","content":"Автоматизация релиза (пример) uses: actions/setup-go@v5 with: go-version: '1.22'"},{"id":"ci-cd/github-actions::top::55","title":"GitHub Actions","section":"Автоматизация релиза (пример)","path":"/docs/guide/ci-cd/github-actions","headings":["Автоматизация релиза (пример)"],"excerpt":"Автоматизация релиза (пример) name: Install EasyP run: go install github.com/easyp-tech/easyp/cmd/easyp@latest","content":"Автоматизация релиза (пример) name: Install EasyP run: go install github.com/easyp-tech/easyp/cmd/easyp@latest"},{"id":"ci-cd/github-actions::top::56","title":"GitHub Actions","section":"Автоматизация релиза (пример)","path":"/docs/guide/ci-cd/github-actions","headings":["Автоматизация релиза (пример)"],"excerpt":"Автоматизация релиза (пример) name: Lint run: easyp lint","content":"Автоматизация релиза (пример) name: Lint run: easyp lint"},{"id":"ci-cd/github-actions::top::57","title":"GitHub Actions","section":"Автоматизация релиза (пример)","path":"/docs/guide/ci-cd/github-actions","headings":["Автоматизация релиза (пример)"],"excerpt":"Автоматизация релиза (пример) name: Breaking vs previous tag run: PREV_TAG=$(git tag --sort=-creatordate grep -v \"${GITHUB_REF_NAME}\" head -n1 true) if [ -n \"$PREV_TAG\" ]; then echo \"Comparing against $PREV_TAG\" easyp br","content":"Автоматизация релиза (пример) name: Breaking vs previous tag run: PREV_TAG=$(git tag --sort=-creatordate grep -v \"${GITHUB_REF_NAME}\" head -n1 true) if [ -n \"$PREV_TAG\" ]; then echo \"Comparing against $PREV_TAG\" easyp breaking --against git-ref=$PREV_TAG else echo \"No previous tag, skipping breaking check\" fi"},{"id":"ci-cd/github-actions::top::58","title":"GitHub Actions","section":"Автоматизация релиза (пример)","path":"/docs/guide/ci-cd/github-actions","headings":["Автоматизация релиза (пример)"],"excerpt":"Автоматизация релиза (пример) name: Generate to ensure consistency run: easyp generate ```","content":"Автоматизация релиза (пример) name: Generate to ensure consistency run: easyp generate ```"},{"id":"ci-cd/github-actions::top::59","title":"GitHub Actions","section":"Отладка","path":"/docs/guide/ci-cd/github-actions","headings":["Отладка"],"excerpt":"Отладка Если нужно больше логов:","content":"Отладка Если нужно больше логов:"},{"id":"ci-cd/github-actions::top::60","title":"GitHub Actions","section":"Отладка","path":"/docs/guide/ci-cd/github-actions","headings":["Отладка"],"excerpt":"Отладка Добавьте вывод окружения для диагностики:","content":"Отладка Добавьте вывод окружения для диагностики:"},{"id":"ci-cd/github-actions::top::61","title":"GitHub Actions","section":"Переменные окружения (примерно)","path":"/docs/guide/ci-cd/github-actions","headings":["Переменные окружения (примерно)"],"excerpt":"Переменные окружения (примерно) Переменная Назначение ------------ ----------- EASYP_SERVICE_HOST Хост удалённого API Service (если используете удалённые плагины) EASYP_SERVICE_GRPC_PORT Порт удалённого сервиса GIT_SSH_C","content":"Переменные окружения (примерно) Переменная Назначение ------------ ----------- EASYP_SERVICE_HOST Хост удалённого API Service (если используете удалённые плагины) EASYP_SERVICE_GRPC_PORT Порт удалённого сервиса GIT_SSH_COMMAND Кастомная команда SSH (частные репозитории) GOFLAGS Можно выставить -mod=readonly для Go генерации"},{"id":"ci-cd/github-actions::top::62","title":"GitHub Actions","section":"Переменные окружения (примерно)","path":"/docs/guide/ci-cd/github-actions","headings":["Переменные окружения (примерно)"],"excerpt":"Переменные окружения (примерно) (Используйте только те, что действительно нужны вашему проекту.)","content":"Переменные окружения (примерно) (Используйте только те, что действительно нужны вашему проекту.)"},{"id":"ci-cd/github-actions::top::63","title":"GitHub Actions","section":"Частые ошибки","path":"/docs/guide/ci-cd/github-actions","headings":["Частые ошибки"],"excerpt":"Частые ошибки Симптом Причина Решение --------- --------- --------- Линт падает на неизвестных правилах Правила указаны в easyp.yaml, но версия EasyP их не поддерживает Обновить EasyP (go install ...@latest) breaking сра","content":"Частые ошибки Симптом Причина Решение --------- --------- --------- Линт падает на неизвестных правилах Правила указаны в easyp.yaml, но версия EasyP их не поддерживает Обновить EasyP (go install ...@latest) breaking сравнение ничего не находит Неверный --against (нет fetch удалённой ветки) Добавить шаг git fetch --all --tags Сгенерированный код в PR отличается от main Отсутствует проверка генерации в CI Добавить шаг «Ensure generated code is up-to-date» Приватные deps не скачиваются Нет SSH ключа или токена Настроить secrets + шаг подготовки SSH Долгое выполнение Отсутствует кеш Добавить кэширование модулей и deps"},{"id":"ci-cd/github-actions::top::64","title":"GitHub Actions","section":"Рекомендации по поддержке","path":"/docs/guide/ci-cd/github-actions","headings":["Рекомендации по поддержке"],"excerpt":"Рекомендации по поддержке Заготовить шаблон workflow и копировать между сервисами (DRY). Включить paths фильтры, чтобы не тратить минуты на нерелевантные изменения. Проверять easyp.yaml при изменениях отдельно — можно за","content":"Рекомендации по поддержке Заготовить шаблон workflow и копировать между сервисами (DRY). Включить paths фильтры, чтобы не тратить минуты на нерелевантные изменения. Проверять easyp.yaml при изменениях отдельно — можно запускать «конфигурационный тест» (например, easyp lint без файлов, чтобы убедиться, что конфиг валиден). При появлении новых правил линтера обновляйте конфиг и фиксируйте ошибки сразу в одной ветке."},{"id":"ci-cd/github-actions::top::65","title":"GitHub Actions","section":"Рекомендации по поддержке","path":"/docs/guide/ci-cd/github-actions","headings":["Рекомендации по поддержке"],"excerpt":"Рекомендации по поддержке Готово: вы можете расширять разделы генерации, добавлять OpenAPI / grpc-gateway / validate плагины, матрицы по языкам и интегрировать тесты поверх сгенерированного кода, если требуется.","content":"Рекомендации по поддержке Готово: вы можете расширять разделы генерации, добавлять OpenAPI / grpc-gateway / validate плагины, матрицы по языкам и интегрировать тесты поверх сгенерированного кода, если требуется."},{"id":"ci-cd/gitlab::top::0","title":"GitLab CI","section":"В процессе разработки","path":"/docs/guide/ci-cd/gitlab","headings":["В процессе разработки"],"excerpt":"В процессе разработки Документация по интеграции EasyP с GitLab CI находится в процессе подготовки. Планируемые разделы: Быстрый старт (пример .gitlab-ci.yml для линтинга и проверки несовместимых изменений) Кэширование з","content":"В процессе разработки Документация по интеграции EasyP с GitLab CI находится в процессе подготовки. Планируемые разделы: Быстрый старт (пример .gitlab-ci.yml для линтинга и проверки несовместимых изменений) Кэширование зависимостей и ускорение сборок Генерация кода и проверка актуальности артефактов Работа с приватными Git-репозиториями в deps Матрицы (parallel jobs) для разных языков и плагинов Автоматизация релизов по тегам"},{"id":"ci-cd/gitlab::top::1","title":"GitLab CI","section":"В процессе разработки","path":"/docs/guide/ci-cd/gitlab","headings":["В процессе разработки"],"excerpt":"В процессе разработки Если вам нужен пример прямо сейчас, базовый минимальный вариант может выглядеть так:","content":"В процессе разработки Если вам нужен пример прямо сейчас, базовый минимальный вариант может выглядеть так:"},{"id":"ci-cd/gitlab::top::2","title":"GitLab CI","section":"В процессе разработки","path":"/docs/guide/ci-cd/gitlab","headings":["В процессе разработки"],"excerpt":"В процессе разработки ```yaml stages: - validate - generate","content":"В процессе разработки ```yaml stages: - validate - generate"},{"id":"ci-cd/gitlab::top::3","title":"GitLab CI","section":"В процессе разработки","path":"/docs/guide/ci-cd/gitlab","headings":["В процессе разработки"],"excerpt":"В процессе разработки variables: GO_VERSION: \"1.22\"","content":"В процессе разработки variables: GO_VERSION: \"1.22\""},{"id":"ci-cd/gitlab::top::4","title":"GitLab CI","section":"В процессе разработки","path":"/docs/guide/ci-cd/gitlab","headings":["В процессе разработки"],"excerpt":"В процессе разработки validate: stage: validate image: golang:${GO_VERSION} before_script: - go install github.com/easyp-tech/easyp/cmd/easyp@latest - echo \"EasyP version:\" - easyp version # При необходимости: git fetch ","content":"В процессе разработки validate: stage: validate image: golang:${GO_VERSION} before_script: - go install github.com/easyp-tech/easyp/cmd/easyp@latest - echo \"EasyP version:\" - easyp version # При необходимости: git fetch --all --tags script: - easyp lint - easyp breaking --against git-ref=origin/main only: changes: - \"**/*.proto\" - \"easyp.yaml\""},{"id":"ci-cd/gitlab::top::5","title":"GitLab CI","section":"В процессе разработки","path":"/docs/guide/ci-cd/gitlab","headings":["В процессе разработки"],"excerpt":"В процессе разработки generate: stage: generate image: golang:${GO_VERSION} before_script: - go install github.com/easyp-tech/easyp/cmd/easyp@latest script: - easyp generate - if [ -n \"$(git status --porcelain)\" ]; then ","content":"В процессе разработки generate: stage: generate image: golang:${GO_VERSION} before_script: - go install github.com/easyp-tech/easyp/cmd/easyp@latest script: - easyp generate - if [ -n \"$(git status --porcelain)\" ]; then echo \"Сгенерированный код не актуален. Закоммитьте изменения локально.\" git diff --name-only exit 1 fi only: - main"},{"id":"ci-cd/gitlab::top::6","title":"GitLab CI","section":"В процессе разработки","path":"/docs/guide/ci-cd/gitlab","headings":["В процессе разработки"],"excerpt":"В процессе разработки Дополнительные рекомендации будут добавлены позже.","content":"В процессе разработки Дополнительные рекомендации будут добавлены позже."},{"id":"cli/auto-completion/auto-completion::zsh::0","title":"Автодополнение","section":"Автодополнение для zsh","path":"/docs/guide/cli/auto-completion/auto-completion#zsh","headings":["Автодополнение для zsh"],"excerpt":"Автодополнение для zsh Добавьте следующую строку в ваш файл запуска ~/.zshrc:","content":"Автодополнение для zsh Добавьте следующую строку в ваш файл запуска ~/.zshrc:"},{"id":"cli/auto-completion/auto-completion::zsh::1","title":"Автодополнение","section":"Автодополнение для zsh","path":"/docs/guide/cli/auto-completion/auto-completion#zsh","headings":["Автодополнение для zsh"],"excerpt":"Автодополнение для zsh Перезапустите оболочку или выполните:","content":"Автодополнение для zsh Перезапустите оболочку или выполните:"},{"id":"cli/auto-completion/auto-completion::bash::2","title":"Автодополнение","section":"Автодополнение для Bash","path":"/docs/guide/cli/auto-completion/auto-completion#bash","headings":["Автодополнение для Bash"],"excerpt":"Автодополнение для Bash Установите bash-completion и подключите его в ~/.bashrc. Добавьте следующую строку в файл запуска ~/.bashrc:","content":"Автодополнение для Bash Установите bash-completion и подключите его в ~/.bashrc. Добавьте следующую строку в файл запуска ~/.bashrc:"},{"id":"cli/auto-completion/auto-completion::bash::3","title":"Автодополнение","section":"Автодополнение для Bash","path":"/docs/guide/cli/auto-completion/auto-completion#bash","headings":["Автодополнение для Bash"],"excerpt":"Автодополнение для Bash Перезапустите оболочку или выполните:","content":"Автодополнение для Bash Перезапустите оболочку или выполните:"},{"id":"cli/auto-completion/auto-completion::top::4","title":"Автодополнение","section":"Примечания","path":"/docs/guide/cli/auto-completion/auto-completion","headings":["Примечания"],"excerpt":"Примечания Команда easyp completion выводит скрипт автодополнения для соответствующей оболочки. Если используете другую оболочку (например, fish), можно сгенерировать вывод и сохранить вручную: При обновлении версии Easy","content":"Примечания Команда easyp completion выводит скрипт автодополнения для соответствующей оболочки. Если используете другую оболочку (например, fish), можно сгенерировать вывод и сохранить вручную: При обновлении версии EasyP рекомендуется заново перезагрузить оболочку, чтобы подтянуть возможные изменения в автодополнении."},{"id":"cli/breaking-changes/breaking-changes::top::0","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":[],"excerpt":"Обнаружение несовместимых изменений (Breaking Changes Detection)","content":"Обнаружение несовместимых изменений (Breaking Changes Detection)"},{"id":"cli/breaking-changes/breaking-changes::top::1","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":[],"excerpt":"Механизм EasyP для обнаружения несовместимых (breaking) изменений помогает поддерживать обратную совместимость ваших protobuf API, автоматически выявляя изменения, способные сломать существующих клиентов. Это критично дл","content":"Механизм EasyP для обнаружения несовместимых (breaking) изменений помогает поддерживать обратную совместимость ваших protobuf API, автоматически выявляя изменения, способные сломать существующих клиентов. Это критично для стабильных API в продакшене."},{"id":"cli/breaking-changes/breaking-changes::top::2","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Обзор","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Обзор"],"excerpt":"Обзор Проверка несовместимых изменений сравнивает текущий набор protobuf‑файлов с предыдущей версией (обычно из другой Git ветки) и фиксирует модификации, которые могут вызвать проблемы совместимости для уже работающих к","content":"Обзор Проверка несовместимых изменений сравнивает текущий набор protobuf‑файлов с предыдущей версией (обычно из другой Git ветки) и фиксирует модификации, которые могут вызвать проблемы совместимости для уже работающих клиентов."},{"id":"cli/breaking-changes/breaking-changes::top::3","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Ключевые возможности","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Ключевые возможности"],"excerpt":"Ключевые возможности **Сравнение через Git**: Сопоставление с любой Git‑ссылкой (ветка, тег, commit) **Комплексный анализ**: Проверка сервисов, сообщений, enum'ов, полей и import'ов **Выборочное игнорирование**: Пропуск ","content":"Ключевые возможности **Сравнение через Git**: Сопоставление с любой Git‑ссылкой (ветка, тег, commit) **Комплексный анализ**: Проверка сервисов, сообщений, enum'ов, полей и import'ов **Выборочное игнорирование**: Пропуск указанных директорий из анализа **Детализированные отчёты**: Понятные ошибки с именами файлов, строками и позициями"},{"id":"cli/breaking-changes/breaking-changes::top::4","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Как работает","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Как работает"],"excerpt":"Как работает Детектор breaking changes выполняет следующие шаги:","content":"Как работает Детектор breaking changes выполняет следующие шаги:"},{"id":"cli/breaking-changes/breaking-changes::top::5","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Как работает","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Как работает"],"excerpt":"Как работает **Получение ветки сравнения**: Забирает proto-файлы из указанной Git‑ссылки **Парсинг обеих версий**: Анализирует структуру текущих и предыдущих файлов **Сравнение сущностей**: Последовательно проверяет все ","content":"Как работает **Получение ветки сравнения**: Забирает proto-файлы из указанной Git‑ссылки **Парсинг обеих версий**: Анализирует структуру текущих и предыдущих файлов **Сравнение сущностей**: Последовательно проверяет все элементы protobuf на breaking изменения **Формирование отчёта**: Генерирует подробные записи об ошибках с локациями и описаниями"},{"id":"cli/breaking-changes/breaking-changes::top::6","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Уровень проверки","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Уровень проверки"],"excerpt":"Уровень проверки EasyP реализует уровень проверки **WIRE+**: ✅ **Полная совместимость по wire‑формату** — старые и новые версии могут обмениваться данными ✅ **Обнаружение удалений элементов** — сервисы, сообщения, поля и","content":"Уровень проверки EasyP реализует уровень проверки **WIRE+**: ✅ **Полная совместимость по wire‑формату** — старые и новые версии могут обмениваться данными ✅ **Обнаружение удалений элементов** — сервисы, сообщения, поля и т.п. ✅ **Безопасность типов** — выявляет несовместимые изменения типов ❌ **Переименования полей/методов** — пока не детектируются (в планах) ❌ **Изменения на уровне файлов** — переносы пакетов, file options ещё не проверяются"},{"id":"cli/breaking-changes/breaking-changes::top::7","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Уровень проверки","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Уровень проверки"],"excerpt":"Уровень проверки Это даёт сильные гарантии совместимости и меньше ограничений, чем инструменты, требующие совместимости сгенерированного кода.","content":"Уровень проверки Это даёт сильные гарантии совместимости и меньше ограничений, чем инструменты, требующие совместимости сгенерированного кода."},{"id":"cli/breaking-changes/breaking-changes::top::8","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Конфигурация","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Конфигурация"],"excerpt":"Конфигурация Настройка в easyp.yaml:","content":"Конфигурация Настройка в easyp.yaml:"},{"id":"cli/breaking-changes/breaking-changes::top::9","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Параметры конфигурации","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Параметры конфигурации"],"excerpt":"Параметры конфигурации Option Description Default Required -------- ------------- --------- ---------- against_git_ref Git‑ссылка для сравнения \"master\" No ignore Список директорий для исключения из анализа [] No","content":"Параметры конфигурации Option Description Default Required -------- ------------- --------- ---------- against_git_ref Git‑ссылка для сравнения \"master\" No ignore Список директорий для исключения из анализа [] No"},{"id":"cli/breaking-changes/breaking-changes::top::10","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Базовый пример","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Базовый пример"],"excerpt":"Базовый пример Сравнение текущих изменений с веткой main:","content":"Базовый пример Сравнение текущих изменений с веткой main:"},{"id":"cli/breaking-changes/breaking-changes::top::11","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Использование файла конфигурации","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Использование файла конфигурации"],"excerpt":"Использование файла конфигурации","content":"Использование файла конфигурации"},{"id":"cli/breaking-changes/breaking-changes::top::12","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Уровень проверки","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Уровень проверки"],"excerpt":"Уровень проверки EasyP сейчас работает на уровне **WIRE+**, обеспечивая совместимость wire‑формата плюс защиту от удалений и изменения критичных типов.","content":"Уровень проверки EasyP сейчас работает на уровне **WIRE+**, обеспечивая совместимость wire‑формата плюс защиту от удалений и изменения критичных типов."},{"id":"cli/breaking-changes/breaking-changes::buf::13","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Сравнение с категориями Buf","path":"/docs/guide/cli/breaking-changes/breaking-changes#buf","headings":["Сравнение с категориями Buf"],"excerpt":"Сравнение с категориями Buf Check Type Buf WIRE Buf WIRE_JSON Buf FILE EasyP Current ------------ ---------- --------------- ---------- --------------- **Element Deletions** Service deletion ❌ ❌ ✅ ✅ RPC method deletion ❌","content":"Сравнение с категориями Buf 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::top::14","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Что это означает","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Что это означает"],"excerpt":"Что это означает **✅ EasyP обнаружит:** Все breaking изменения wire‑формата Удаления сервисов, методов, сообщений, полей Изменения типов, ломающие сериализацию Переименования enum‑значений (при сохранении номера)","content":"Что это означает **✅ EasyP обнаружит:** Все breaking изменения wire‑формата Удаления сервисов, методов, сообщений, полей Изменения типов, ломающие сериализацию Переименования enum‑значений (при сохранении номера)"},{"id":"cli/breaking-changes/breaking-changes::top::15","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Что это означает","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Что это означает"],"excerpt":"Что это означает **❌ EasyP НЕ обнаружит:** Переименование полей (с тем же номером) Изменение package File options (go_package, java_package, и т.п.) Перемещение типов между файлами в одном package","content":"Что это означает **❌ EasyP НЕ обнаружит:** Переименование полей (с тем же номером) Изменение package File options (go_package, java_package, и т.п.) Перемещение типов между файлами в одном package"},{"id":"cli/breaking-changes/breaking-changes::breaking-changes::16","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Правила Breaking Changes","path":"/docs/guide/cli/breaking-changes/breaking-changes#breaking-changes","headings":["Правила Breaking Changes"],"excerpt":"Правила Breaking Changes EasyP обнаруживает следующие типы breaking изменений:","content":"Правила Breaking Changes EasyP обнаруживает следующие типы breaking изменений:"},{"id":"cli/breaking-changes/breaking-changes::top::17","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Сравнение уровней","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Сравнение уровней"],"excerpt":"Сравнение уровней Detection Level Description EasyP Support ---------------- ------------- --------------- **WIRE** Совместимость только по wire‑формату ✅ **Full support** **WIRE+** Wire + обнаружение удалений ✅ **Curren","content":"Сравнение уровней Detection Level Description EasyP Support ---------------- ------------- --------------- **WIRE** Совместимость только по wire‑формату ✅ **Full support** **WIRE+** Wire + обнаружение удалений ✅ **Current level** **FILE** Совместимость сгенерированного кода ❌ Partial (planned)"},{"id":"cli/breaking-changes/breaking-changes::top::18","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Категории правил","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Категории правил"],"excerpt":"Категории правил Каждая категория имеет свою документацию с примерами:","content":"Категории правил Каждая категория имеет свою документацию с примерами:"},{"id":"cli/breaking-changes/breaking-changes::service-rpc::19","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"🚨 Изменения Service и RPC","path":"/docs/guide/cli/breaking-changes/breaking-changes#service-rpc","headings":["🚨 Изменения Service и RPC"],"excerpt":"🚨 Изменения Service и RPC 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 и RPC 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-field::20","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"📦 Изменения Message и Field","path":"/docs/guide/cli/breaking-changes/breaking-changes#message-field","headings":["📦 Изменения Message и Field"],"excerpt":"📦 Изменения Message и Field 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 и Field 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::21","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"🔢 Изменения Enum","path":"/docs/guide/cli/breaking-changes/breaking-changes#enum","headings":["🔢 Изменения Enum"],"excerpt":"🔢 Изменения Enum 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 val","content":"🔢 Изменения Enum 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::22","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"🔗 Изменения OneOf","path":"/docs/guide/cli/breaking-changes/breaking-changes#oneof","headings":["🔗 Изменения OneOf"],"excerpt":"🔗 Изменения OneOf Rule Description Status ------ ------------- --------- ONEOF_NO_DELETE OneOf fields cannot be deleted ✅ Implemented ONEOF_FIELD_NO_DELETE Fields within oneofs cannot be deleted ✅ Implemented ONEOF_FIEL","content":"🔗 Изменения OneOf 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::23","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"📥 Изменения Import","path":"/docs/guide/cli/breaking-changes/breaking-changes#import","headings":["📥 Изменения Import"],"excerpt":"📥 Изменения Import Rule Description Status ------ ------------- --------- IMPORT_NO_DELETE Import statements cannot be removed ✅ Implemented","content":"📥 Изменения Import Rule Description Status ------ ------------- --------- IMPORT_NO_DELETE Import statements cannot be removed ✅ Implemented"},{"id":"cli/breaking-changes/breaking-changes::top::24","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Не обнаруживается сейчас","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Не обнаруживается сейчас"],"excerpt":"Не обнаруживается сейчас Изменения ниже **НЕ детектируются** EasyP (могут ломать сгенерированный код):","content":"Не обнаруживается сейчас Изменения ниже **НЕ детектируются** EasyP (могут ломать сгенерированный код):"},{"id":"cli/breaking-changes/breaking-changes::top::25","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Не обнаруживается сейчас","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Не обнаруживается сейчас"],"excerpt":"Не обнаруживается сейчас Change Type Example Impact ------------- --------- -------- Field renaming string name = 1 → string full_name = 1 Ломает код Package changes package v1 → package v2 Меняются пути импорта File opt","content":"Не обнаруживается сейчас Change Type Example Impact ------------- --------- -------- Field renaming string name = 1 → string full_name = 1 Ломает код Package changes package v1 → package v2 Меняются пути импорта File options option go_package = \"old\" → option go_package = \"new\" Меняется расположение кода Moving between files Message перемещено в другой .proto Зависимости import'ов"},{"id":"cli/breaking-changes/breaking-changes::top::26","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Документация правил","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Документация правил"],"excerpt":"Документация правил См. подробные файлы правил для примеров и стратегий миграции:","content":"Документация правил См. подробные файлы правил для примеров и стратегий миграции:"},{"id":"cli/breaking-changes/breaking-changes::top::27","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Документация правил","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Документация правил"],"excerpt":"Документация правил Service: SERVICE_NO_DELETE, RPC_NO_DELETE, RPC_SAME_REQUEST_TYPE, RPC_SAME_RESPONSE_TYPE Message: MESSAGE_NO_DELETE, FIELD_NO_DELETE, FIELD_SAME_TYPE, FIELD_SAME_CARDINALITY Enum: ENUM_NO_DELETE, ENUM","content":"Документация правил Service: SERVICE_NO_DELETE, RPC_NO_DELETE, RPC_SAME_REQUEST_TYPE, RPC_SAME_RESPONSE_TYPE Message: MESSAGE_NO_DELETE, FIELD_NO_DELETE, FIELD_SAME_TYPE, FIELD_SAME_CARDINALITY Enum: ENUM_NO_DELETE, ENUM_VALUE_NO_DELETE, ENUM_VALUE_SAME_NAME OneOf: ONEOF_NO_DELETE, ONEOF_FIELD_NO_DELETE, ONEOF_FIELD_SAME_TYPE Import: IMPORT_NO_DELETE"},{"id":"cli/breaking-changes/breaking-changes::top::28","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Документация правил","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Документация правил"],"excerpt":"Документация правил Каждое правило содержит: ❌ Плохие примеры (breaking) ✅ Безопасные альтернативы 🔧 Стратегии миграции 📋 Реальные сообщения ошибок из EasyP","content":"Документация правил Каждое правило содержит: ❌ Плохие примеры (breaking) ✅ Безопасные альтернативы 🔧 Стратегии миграции 📋 Реальные сообщения ошибок из EasyP"},{"id":"cli/breaking-changes/breaking-changes::top::29","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"✅ Безопасные изменения (разрешены всегда)","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["✅ Безопасные изменения (разрешены всегда)"],"excerpt":"✅ Безопасные изменения (разрешены всегда) ```proto // Добавление новых элементов — безопасно message User { string name = 1; string email = 2; string phone = 3; // ✅ Новое поле }","content":"✅ Безопасные изменения (разрешены всегда) ```proto // Добавление новых элементов — безопасно message User { string name = 1; string email = 2; string phone = 3; // ✅ Новое поле }"},{"id":"cli/breaking-changes/breaking-changes::top::30","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"✅ Безопасные изменения (разрешены всегда)","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["✅ Безопасные изменения (разрешены всегда)"],"excerpt":"✅ Безопасные изменения (разрешены всегда) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc GetUserProfile(GetUserRequest) returns (UserProfile); // ✅ Новый RPC }","content":"✅ Безопасные изменения (разрешены всегда) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc GetUserProfile(GetUserRequest) returns (UserProfile); // ✅ Новый RPC }"},{"id":"cli/breaking-changes/breaking-changes::top::31","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"✅ Безопасные изменения (разрешены всегда)","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["✅ Безопасные изменения (разрешены всегда)"],"excerpt":"✅ Безопасные изменения (разрешены всегда) enum Status { STATUS_UNSPECIFIED = 0; STATUS_ACTIVE = 1; STATUS_PENDING = 2; // ✅ Новое enum значение } ```","content":"✅ Безопасные изменения (разрешены всегда) enum Status { STATUS_UNSPECIFIED = 0; STATUS_ACTIVE = 1; STATUS_PENDING = 2; // ✅ Новое enum значение } ```"},{"id":"cli/breaking-changes/breaking-changes::top::32","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"❌ Несовместимые изменения (обнаруживаются всегда)","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["❌ Несовместимые изменения (обнаруживаются всегда)"],"excerpt":"❌ Несовместимые изменения (обнаруживаются всегда) ```proto // Удаления и смена типов ломают совместимость message User { string name = 1; // ❌ Удалённое поле }","content":"❌ Несовместимые изменения (обнаруживаются всегда) ```proto // Удаления и смена типов ломают совместимость message User { string name = 1; // ❌ Удалённое поле }"},{"id":"cli/breaking-changes/breaking-changes::top::33","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"❌ Несовместимые изменения (обнаруживаются всегда)","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["❌ Несовместимые изменения (обнаруживаются всегда)"],"excerpt":"❌ Несовместимые изменения (обнаруживаются всегда) service UserService { // ❌ Удалённый RPC метод rpc GetUser(GetUserRequestV2) returns (GetUserResponse); // ❌ Изменён тип запроса } ```","content":"❌ Несовместимые изменения (обнаруживаются всегда) service UserService { // ❌ Удалённый RPC метод rpc GetUser(GetUserRequestV2) returns (GetUserResponse); // ❌ Изменён тип запроса } ```"},{"id":"cli/breaking-changes/breaking-changes::top::34","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Сценарий: Изменения пока не детектируются","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Сценарий: Изменения пока не детектируются"],"excerpt":"Сценарий: Изменения пока не детектируются ```proto // 🟡 Ломает сгенерированный код, но проходит проверки EasyP message User { string user_name = 1; // Переименовано с \"name\" string user_email = 2; // Переименовано с \"em","content":"Сценарий: Изменения пока не детектируются ```proto // 🟡 Ломает сгенерированный код, но проходит проверки EasyP message User { string user_name = 1; // Переименовано с \"name\" string user_email = 2; // Переименовано с \"email\" }"},{"id":"cli/breaking-changes/breaking-changes::top::35","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Сценарий: Изменения пока не детектируются","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Сценарий: Изменения пока не детектируются"],"excerpt":"Сценарий: Изменения пока не детектируются service UserService { rpc GetUserProfile(GetUserRequest) returns (GetUserResponse); // Переименовано с GetUser } ```","content":"Сценарий: Изменения пока не детектируются service UserService { rpc GetUserProfile(GetUserRequest) returns (GetUserResponse); // Переименовано с GetUser } ```"},{"id":"cli/breaking-changes/breaking-changes::top::36","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Текстовый формат (по умолчанию)","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Текстовый формат (по умолчанию)"],"excerpt":"Текстовый формат (по умолчанию)","content":"Текстовый формат (по умолчанию)"},{"id":"cli/breaking-changes/breaking-changes::1::37","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"1. Регулярный запуск","path":"/docs/guide/cli/breaking-changes/breaking-changes#1","headings":["1. Регулярный запуск"],"excerpt":"Регулярный запуск Добавьте проверку несовместимых изменений в CI/CD:","content":"Регулярный запуск Добавьте проверку несовместимых изменений в CI/CD:"},{"id":"cli/breaking-changes/breaking-changes::2::38","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"2. Защита веток","path":"/docs/guide/cli/breaking-changes/breaking-changes#2","headings":["2. Защита веток"],"excerpt":"Защита веток Блокируйте слияния с breaking изменениями:","content":"Защита веток Блокируйте слияния с breaking изменениями:"},{"id":"cli/breaking-changes/breaking-changes::3::39","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"3. Стратегия версионирования","path":"/docs/guide/cli/breaking-changes/breaking-changes#3","headings":["3. Стратегия версионирования"],"excerpt":"Стратегия версионирования При необходимости breaking изменений: Создайте новую версию пакета (myservice.v2) Поддерживайте старую версию в период миграции Добавляйте уведомления о деприкации","content":"Стратегия версионирования При необходимости breaking изменений: Создайте новую версию пакета (myservice.v2) Поддерживайте старую версию в период миграции Добавляйте уведомления о деприкации"},{"id":"cli/breaking-changes/breaking-changes::4::40","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"4. Игнорирование путей","path":"/docs/guide/cli/breaking-changes/breaking-changes#4","headings":["4. Игнорирование путей"],"excerpt":"Игнорирование путей Используйте ignore осознанно:","content":"Игнорирование путей Используйте ignore осознанно:"},{"id":"cli/breaking-changes/breaking-changes::repository-does-not-exist::41","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Проблема: \"Repository does not exist\"","path":"/docs/guide/cli/breaking-changes/breaking-changes#repository-does-not-exist","headings":["Проблема: \"Repository does not exist\""],"excerpt":"Проблема: \"Repository does not exist\" Решение: Выполняйте команду внутри Git репозитория с нужной веткой.","content":"Проблема: \"Repository does not exist\" Решение: Выполняйте команду внутри Git репозитория с нужной веткой."},{"id":"cli/breaking-changes/breaking-changes::cannot-find-git-ref::42","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Проблема: \"Cannot find git ref\"","path":"/docs/guide/cli/breaking-changes/breaking-changes#cannot-find-git-ref","headings":["Проблема: \"Cannot find git ref\""],"excerpt":"Проблема: \"Cannot find git ref\" Решение: Проверьте наличие ссылки:","content":"Проблема: \"Cannot find git ref\" Решение: Проверьте наличие ссылки:"},{"id":"cli/breaking-changes/breaking-changes::top::43","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Проблема: Ложные срабатывания на сгенерированный код","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Проблема: Ложные срабатывания на сгенерированный код"],"excerpt":"Проблема: Ложные срабатывания на сгенерированный код Решение: Исключите директории генерации:","content":"Проблема: Ложные срабатывания на сгенерированный код Решение: Исключите директории генерации:"},{"id":"cli/breaking-changes/breaking-changes::top::44","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Проблема: Очень много изменений","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Проблема: Очень много изменений"],"excerpt":"Проблема: Очень много изменений Решение: Создайте новую версию API Вносите изменения постепенно Используйте feature flags","content":"Проблема: Очень много изменений Решение: Создайте новую версию API Вносите изменения постепенно Используйте feature flags"},{"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 - name: Install EasyP run: curl -sSfL https://raw.githubusercontent.com/easyp-tech/easyp/main/install.","content":"GitHub Actions jobs: breaking-changes: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 with: fetch-depth: 0 - 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-pre-push-hook::48","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Pre-commit / pre-push hook","path":"/docs/guide/cli/breaking-changes/breaking-changes#pre-commit-pre-push-hook","headings":["Pre-commit / pre-push hook"],"excerpt":"Pre-commit / pre-push hook ```bash #!/bin/sh .git/hooks/pre-push","content":"Pre-commit / pre-push hook ```bash #!/bin/sh .git/hooks/pre-push"},{"id":"cli/breaking-changes/breaking-changes::pre-commit-pre-push-hook::49","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Pre-commit / pre-push hook","path":"/docs/guide/cli/breaking-changes/breaking-changes#pre-commit-pre-push-hook","headings":["Pre-commit / pre-push hook"],"excerpt":"Pre-commit / pre-push hook protected_branch='main' current_branch=$(git symbolic-ref HEAD sed -e 's,.*/\\(.*\\),\\1,')","content":"Pre-commit / pre-push hook protected_branch='main' current_branch=$(git symbolic-ref HEAD sed -e 's,.*/\\(.*\\),\\1,')"},{"id":"cli/breaking-changes/breaking-changes::pre-commit-pre-push-hook::50","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Pre-commit / pre-push hook","path":"/docs/guide/cli/breaking-changes/breaking-changes#pre-commit-pre-push-hook","headings":["Pre-commit / pre-push hook"],"excerpt":"Pre-commit / pre-push 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.","content":"Pre-commit / pre-push 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::top::51","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Режим отладки","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Режим отладки"],"excerpt":"Режим отладки Включите debug‑логирование:","content":"Режим отладки Включите debug‑логирование:"},{"id":"cli/breaking-changes/breaking-changes::top::52","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Ручное сравнение","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Ручное сравнение"],"excerpt":"Ручное сравнение Для сложных случаев:","content":"Ручное сравнение Для сложных случаев:"},{"id":"cli/breaking-changes/breaking-changes::top::53","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Оптимизация производительности","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Оптимизация производительности"],"excerpt":"Оптимизация производительности Ограничьте область:","content":"Оптимизация производительности Ограничьте область:"},{"id":"cli/breaking-changes/breaking-changes::top::54","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Оптимизация производительности","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Оптимизация производительности"],"excerpt":"Оптимизация производительности","content":"Оптимизация производительности"},{"id":"cli/breaking-changes/breaking-changes::top::55","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Оптимизация производительности","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Оптимизация производительности"],"excerpt":"Оптимизация производительности Механизм обнаружения несовместимых изменений в EasyP обеспечивает надёжную основу для безопасной эволюции protobuf‑схем при сохранении совместимости API.","content":"Оптимизация производительности Механизм обнаружения несовместимых изменений в EasyP обеспечивает надёжную основу для безопасной эволюции protobuf‑схем при сохранении совместимости API."},{"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":"Это правило проверяет, что ни один enum не был удалён из proto‑файлов. Удаление enum ломает совместимость по wire‑формату и сгенерированный код: сохранённые данные могут содержать удалённые значения, а клиентский код опи","content":"Это правило проверяет, что ни один enum не был удалён из proto‑файлов. Удаление enum ломает совместимость по wire‑формату и сгенерированный код: сохранённые данные могут содержать удалённые значения, а клиентский код опирается на сгенерированные типы и константы enum."},{"id":"cli/breaking-changes/rules/enum-no-delete::breaking::1","title":"ENUM_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-no-delete::breaking::2","title":"ENUM_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/enum-no-delete::breaking::3","title":"ENUM_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_CONFIRMED = 2; ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_DELIVERED = 4; }","content":"Плохой (Breaking) 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::breaking::4","title":"ENUM_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) enum UserRole { // [!code --] USER_ROLE_UNSPECIFIED = 0; // [!code --] USER_ROLE_ADMIN = 1; // [!code --] USER_ROLE_USER = 2; // [!code --] } // [!code --]","content":"Плохой (Breaking) 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::breaking::5","title":"ENUM_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message Order { string id = 1; OrderStatus status = 2; UserRole created_by_role = 3; } ```","content":"Плохой (Breaking) message Order { string id = 1; OrderStatus status = 2; UserRole created_by_role = 3; } ```"},{"id":"cli/breaking-changes/rules/enum-no-delete::breaking::6","title":"ENUM_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-no-delete::breaking::7","title":"ENUM_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/enum-no-delete::breaking::8","title":"ENUM_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_CONFIRMED = 2; ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_DELIVERED = 4; }","content":"Плохой (Breaking) 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::breaking::9","title":"ENUM_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) // UserRole enum удалён — BREAKING CHANGE!","content":"Плохой (Breaking) // UserRole enum удалён — BREAKING CHANGE!"},{"id":"cli/breaking-changes/rules/enum-no-delete::breaking::10","title":"ENUM_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message Order { string id = 1; OrderStatus status = 2; UserRole created_by_role = 3; // ERROR: UserRole больше не существует } ```","content":"Плохой (Breaking) message Order { string id = 1; OrderStatus status = 2; UserRole created_by_role = 3; // ERROR: UserRole больше не существует } ```"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::11","title":"ENUM_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры **Удаление вложенного enum:** ```proto // Before message User { string name = 1; Status status = 2; enum Status { // [!code --] STATUS_UNSPECIFIED = 0; // [!code --] STATUS_ACTIVE = 1; // [!code --","content":"Дополнительные примеры **Удаление вложенного enum:** ```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::top::12","title":"ENUM_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры // After - BREAKING CHANGE! message User { string name = 1; Status status = 2; // ERROR: Status удалён // Вложенный enum Status удалён } ```","content":"Дополнительные примеры // After - BREAKING CHANGE! message User { string name = 1; Status status = 2; // ERROR: Status удалён // Вложенный enum Status удалён } ```"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::13","title":"ENUM_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо удаления — пометить enum deprecated:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо удаления — пометить enum deprecated:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::14","title":"ENUM_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::15","title":"ENUM_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_CONFIRMED = 2; ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_DELIVERED = 4; }","content":"Хороший (Безопасный) 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::top::16","title":"ENUM_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) enum UserRole { option deprecated = true; // [!code focus] USER_ROLE_UNSPECIFIED = 0; USER_ROLE_ADMIN = 1; USER_ROLE_USER = 2; }","content":"Хороший (Безопасный) 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::top::17","title":"ENUM_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message Order { string id = 1; OrderStatus status = 2; UserRole created_by_role = 3 [deprecated = true]; // [!code focus] } ```","content":"Хороший (Безопасный) 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::top::18","title":"ENUM_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Или заменить новым enum:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Или заменить новым enum:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::19","title":"ENUM_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::20","title":"ENUM_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_CONFIRMED = 2; ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_DELIVERED = 4; }","content":"Хороший (Безопасный) 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::top::21","title":"ENUM_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) enum UserRole { option deprecated = true; // [!code focus] // Старый enum USER_ROLE_UNSPECIFIED = 0; USER_ROLE_ADMIN = 1; USER_ROLE_USER = 2; }","content":"Хороший (Безопасный) enum UserRole { option deprecated = true; // [!code focus] // Старый enum USER_ROLE_UNSPECIFIED = 0; USER_ROLE_ADMIN = 1; USER_ROLE_USER = 2; }"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::22","title":"ENUM_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) enum UserPermission { // [!code focus] // Новый enum USER_PERMISSION_UNSPECIFIED = 0; // [!code focus] USER_PERMISSION_READ = 1; // [!code focus] USER_PERMISSION_WRITE = 2; // [!code focus] USER_PERM","content":"Хороший (Безопасный) enum UserPermission { // [!code focus] // Новый enum 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::top::23","title":"ENUM_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message Order { string id = 1; OrderStatus status = 2; UserRole created_by_role = 3 [deprecated = true]; // [!code focus] UserPermission created_by_permission = 4; // [!code focus] } ```","content":"Хороший (Безопасный) message Order { string id = 1; OrderStatus status = 2; UserRole created_by_role = 3 [deprecated = true]; // [!code focus] UserPermission created_by_permission = 4; // [!code focus] } ```"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::24","title":"ENUM_NO_DELETE","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Влияние"],"excerpt":"Влияние **Wire Format:** Данные с удалённым enum не десериализуются корректно **Generated Code:** Тип и константы удаляются — компиляция клиентов ломается **Field References:** Поля с типом удалённого enum становятся нев","content":"Влияние **Wire Format:** Данные с удалённым enum не десериализуются корректно **Generated Code:** Тип и константы удаляются — компиляция клиентов ломается **Field References:** Поля с типом удалённого enum становятся невалидны **Switch Statements:** switch по enum ломается (неизвестные кейсы)"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::25","title":"ENUM_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Код клиента ломается:** ```go // Before order := &myapi.Order{ Id: \"order123\", Status: myapi.OrderStatus_ORDER_STATUS_PENDING, CreatedByRole: myapi.UserRole_USER_ROLE_ADMIN, // ERROR после удаления }","content":"Реальный пример **Код клиента ломается:** ```go // Before order := &myapi.Order{ Id: \"order123\", Status: myapi.OrderStatus_ORDER_STATUS_PENDING, CreatedByRole: myapi.UserRole_USER_ROLE_ADMIN, // ERROR после удаления }"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::26","title":"ENUM_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример switch order.CreatedByRole { case myapi.UserRole_USER_ROLE_ADMIN: // ERROR // Admin logic case myapi.UserRole_USER_ROLE_USER: // ERROR // User logic }","content":"Реальный пример switch order.CreatedByRole { case myapi.UserRole_USER_ROLE_ADMIN: // ERROR // Admin logic case myapi.UserRole_USER_ROLE_USER: // ERROR // User logic }"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::27","title":"ENUM_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример // undefined: myapi.UserRole // undefined: myapi.UserRole_USER_ROLE_ADMIN ```","content":"Реальный пример // undefined: myapi.UserRole // undefined: myapi.UserRole_USER_ROLE_ADMIN ```"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::28","title":"ENUM_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Старые данные становятся нечитаемыми:**","content":"Реальный пример **Старые данные становятся нечитаемыми:**"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::29","title":"ENUM_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Серверная логика ломается:**","content":"Реальный пример **Серверная логика ломается:**"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::30","title":"ENUM_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Депрецируйте enum:** **Пометьте поля со старым enum deprecated:** **Создайте новый enum:** **Сервер обрабатывает оба:** **Удалите старый enum в следующей major‑версии.**","content":"Стратегия миграции **Депрецируйте enum:** **Пометьте поля со старым enum deprecated:** **Создайте новый enum:** **Сервер обрабатывает оба:** **Удалите старый enum в следующей major‑версии.**"},{"id":"cli/breaking-changes/rules/enum-no-delete::enum::31","title":"ENUM_NO_DELETE","section":"Редизайн enum","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#enum","headings":["Редизайн enum"],"excerpt":"Редизайн enum ```proto enum Priority { option deprecated = true; PRIORITY_UNSPECIFIED = 0; PRIORITY_LOW = 1; PRIORITY_HIGH = 2; }","content":"Редизайн enum ```proto enum Priority { option deprecated = true; PRIORITY_UNSPECIFIED = 0; PRIORITY_LOW = 1; PRIORITY_HIGH = 2; }"},{"id":"cli/breaking-changes/rules/enum-no-delete::enum::32","title":"ENUM_NO_DELETE","section":"Редизайн enum","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#enum","headings":["Редизайн enum"],"excerpt":"Редизайн enum enum TaskPriority { TASK_PRIORITY_UNSPECIFIED = 0; TASK_PRIORITY_LOW = 1; TASK_PRIORITY_MEDIUM = 2; TASK_PRIORITY_HIGH = 3; TASK_PRIORITY_URGENT = 4; } ```","content":"Редизайн enum enum TaskPriority { 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::enum::33","title":"ENUM_NO_DELETE","section":"Консолидация enum","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#enum","headings":["Консолидация enum"],"excerpt":"Консолидация enum ```proto enum Status { option deprecated = true; STATUS_UNSPECIFIED = 0; STATUS_ACTIVE = 1; }","content":"Консолидация enum ```proto enum Status { option deprecated = true; STATUS_UNSPECIFIED = 0; STATUS_ACTIVE = 1; }"},{"id":"cli/breaking-changes/rules/enum-no-delete::enum::34","title":"ENUM_NO_DELETE","section":"Консолидация enum","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#enum","headings":["Консолидация enum"],"excerpt":"Консолидация enum enum State { option deprecated = true; STATE_UNSPECIFIED = 0; STATE_ENABLED = 1; }","content":"Консолидация enum enum State { option deprecated = true; STATE_UNSPECIFIED = 0; STATE_ENABLED = 1; }"},{"id":"cli/breaking-changes/rules/enum-no-delete::enum::35","title":"ENUM_NO_DELETE","section":"Консолидация enum","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#enum","headings":["Консолидация enum"],"excerpt":"Консолидация enum enum EntityStatus { ENTITY_STATUS_UNSPECIFIED = 0; ENTITY_STATUS_ACTIVE = 1; ENTITY_STATUS_INACTIVE = 2; ENTITY_STATUS_ENABLED = 3; ENTITY_STATUS_DISABLED = 4; } ```","content":"Консолидация enum enum EntityStatus { 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::enum::36","title":"ENUM_NO_DELETE","section":"Перемещение enum в новый пакет","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#enum","headings":["Перемещение enum в новый пакет"],"excerpt":"Перемещение enum в новый пакет ```proto enum UserRole { option deprecated = true; USER_ROLE_UNSPECIFIED = 0; USER_ROLE_ADMIN = 1; }","content":"Перемещение enum в новый пакет ```proto enum UserRole { option deprecated = true; USER_ROLE_UNSPECIFIED = 0; USER_ROLE_ADMIN = 1; }"},{"id":"cli/breaking-changes/rules/enum-no-delete::enum::37","title":"ENUM_NO_DELETE","section":"Перемещение enum в новый пакет","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#enum","headings":["Перемещение enum в новый пакет"],"excerpt":"Перемещение enum в новый пакет import \"common/roles.proto\";","content":"Перемещение enum в новый пакет import \"common/roles.proto\";"},{"id":"cli/breaking-changes/rules/enum-no-delete::enum::38","title":"ENUM_NO_DELETE","section":"Перемещение enum в новый пакет","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#enum","headings":["Перемещение enum в новый пакет"],"excerpt":"Перемещение enum в новый пакет message Order { UserRole old_role = 3 [deprecated = true]; common.UserRole new_role = 4; } ```","content":"Перемещение enum в новый пакет message Order { UserRole old_role = 3 [deprecated = true]; common.UserRole new_role = 4; } ```"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::39","title":"ENUM_NO_DELETE","section":"Версионирование / новая версия пакета","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Версионирование / новая версия пакета"],"excerpt":"Версионирование / новая версия пакета ```proto package myapi.v2;","content":"Версионирование / новая версия пакета ```proto package myapi.v2;"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::40","title":"ENUM_NO_DELETE","section":"Версионирование / новая версия пакета","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Версионирование / новая версия пакета"],"excerpt":"Версионирование / новая версия пакета enum UserPermission { USER_PERMISSION_UNSPECIFIED = 0; USER_PERMISSION_READ = 1; USER_PERMISSION_WRITE = 2; USER_PERMISSION_ADMIN = 3; }","content":"Версионирование / новая версия пакета 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::top::41","title":"ENUM_NO_DELETE","section":"Версионирование / новая версия пакета","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Версионирование / новая версия пакета"],"excerpt":"Версионирование / новая версия пакета message Order { string id = 1; UserPermission created_by_permission = 2; } ```","content":"Версионирование / новая версия пакета message Order { string id = 1; UserPermission created_by_permission = 2; } ```"},{"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":"Правило проверяет, что ни одно значение enum (enum value) не было удалено. Удаление значения ломает совместимость по wire‑формату и сгенерированный код: в уже сохранённых данных могут присутствовать удалённые значения, а","content":"Правило проверяет, что ни одно значение enum (enum value) не было удалено. Удаление значения ломает совместимость по wire‑формату и сгенерированный код: в уже сохранённых данных могут присутствовать удалённые значения, а клиентский код может ссылаться на соответствующие константы."},{"id":"cli/breaking-changes/rules/enum-value-no-delete::breaking::1","title":"ENUM_VALUE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::breaking::2","title":"ENUM_VALUE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::breaking::3","title":"ENUM_VALUE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) 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":"Плохой (Breaking) 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::breaking::4","title":"ENUM_VALUE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) enum Priority { PRIORITY_UNSPECIFIED = 0; PRIORITY_LOW = 1; PRIORITY_MEDIUM = 2; PRIORITY_HIGH = 3; PRIORITY_URGENT = 4; } ```","content":"Плохой (Breaking) 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::breaking::5","title":"ENUM_VALUE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::breaking::6","title":"ENUM_VALUE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::breaking::7","title":"ENUM_VALUE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) 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 --] ","content":"Плохой (Breaking) 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 --] Удалено значение enum — BREAKING! }"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::breaking::8","title":"ENUM_VALUE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) enum Priority { PRIORITY_UNSPECIFIED = 0; PRIORITY_LOW = 1; PRIORITY_MEDIUM = 2; PRIORITY_HIGH = 3; // PRIORITY_URGENT = 4; // [!code --] Удалено значение enum — BREAKING! } ```","content":"Плохой (Breaking) enum Priority { PRIORITY_UNSPECIFIED = 0; PRIORITY_LOW = 1; PRIORITY_MEDIUM = 2; PRIORITY_HIGH = 3; // PRIORITY_URGENT = 4; // [!code --] Удалено значение enum — BREAKING! } ```"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::9","title":"ENUM_VALUE_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры **Множественное удаление значений:** ```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_S","content":"Дополнительные примеры **Множественное удаление значений:** ```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::top::10","title":"ENUM_VALUE_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры // 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","content":"Дополнительные примеры // 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::top::11","title":"ENUM_VALUE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо удаления — пометить значения deprecated:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо удаления — пометить значения deprecated:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::12","title":"ENUM_VALUE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::13","title":"ENUM_VALUE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) 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 = t","content":"Хороший (Безопасный) 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::top::14","title":"ENUM_VALUE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) enum Priority { PRIORITY_UNSPECIFIED = 0; PRIORITY_LOW = 1; PRIORITY_MEDIUM = 2; PRIORITY_HIGH = 3; PRIORITY_URGENT = 4 [deprecated = true]; // [!code focus] } ```","content":"Хороший (Безопасный) 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::top::15","title":"ENUM_VALUE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Или зарезервировать номер и имя после удаления:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Или зарезервировать номер и имя после удаления:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::16","title":"ENUM_VALUE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::17","title":"ENUM_VALUE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) enum OrderStatus { reserved 5; // [!code focus] reserved \"ORDER_STATUS_CANCELLED\"; // [!code focus]","content":"Хороший (Безопасный) enum OrderStatus { reserved 5; // [!code focus] reserved \"ORDER_STATUS_CANCELLED\"; // [!code focus]"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::18","title":"ENUM_VALUE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_CONFIRMED = 2; ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_DELIVERED = 4; }","content":"Хороший (Безопасный) 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::top::19","title":"ENUM_VALUE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) enum Priority { reserved 4; // [!code focus] reserved \"PRIORITY_URGENT\"; // [!code focus]","content":"Хороший (Безопасный) enum Priority { reserved 4; // [!code focus] reserved \"PRIORITY_URGENT\"; // [!code focus]"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::20","title":"ENUM_VALUE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) PRIORITY_UNSPECIFIED = 0; PRIORITY_LOW = 1; PRIORITY_MEDIUM = 2; PRIORITY_HIGH = 3; } ```","content":"Хороший (Безопасный) PRIORITY_UNSPECIFIED = 0; PRIORITY_LOW = 1; PRIORITY_MEDIUM = 2; PRIORITY_HIGH = 3; } ```"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::21","title":"ENUM_VALUE_NO_DELETE","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Влияние"],"excerpt":"Влияние **Wire Format:** Данные с удалёнными значениями не десериализуются корректно **Generated Code:** Константы исчезают — клиентский код не компилируется **Client Applications:** Ссылки на удалённые значения вызывают","content":"Влияние **Wire Format:** Данные с удалёнными значениями не десериализуются корректно **Generated Code:** Константы исчезают — клиентский код не компилируется **Client Applications:** Ссылки на удалённые значения вызывают ошибки компиляции **Switch Statements:** switch по enum ломается (неизвестные case) **Default Handling:** Поведение при неизвестных значениях меняется"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::22","title":"ENUM_VALUE_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Код клиента ломается:** ```go order := &myapi.Order{ Status: myapi.OrderStatus_ORDER_STATUS_CANCELLED, // ERROR после удаления }","content":"Реальный пример **Код клиента ломается:** ```go order := &myapi.Order{ Status: myapi.OrderStatus_ORDER_STATUS_CANCELLED, // ERROR после удаления }"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::23","title":"ENUM_VALUE_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример switch order.Status { case myapi.OrderStatus_ORDER_STATUS_PENDING: // Pending case myapi.OrderStatus_ORDER_STATUS_CANCELLED: // ERROR: undefined // Cancellation default: // Unknown } // undefined: myapi.O","content":"Реальный пример switch order.Status { case myapi.OrderStatus_ORDER_STATUS_PENDING: // Pending case myapi.OrderStatus_ORDER_STATUS_CANCELLED: // ERROR: undefined // Cancellation default: // Unknown } // undefined: myapi.OrderStatus_ORDER_STATUS_CANCELLED ```"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::24","title":"ENUM_VALUE_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Проблемы с уже сохранёнными данными:**","content":"Реальный пример **Проблемы с уже сохранёнными данными:**"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::25","title":"ENUM_VALUE_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Валидация на сервере:** ```go func validateOrderStatus(status OrderStatus) error { switch status { case OrderStatus_ORDER_STATUS_PENDING, OrderStatus_ORDER_STATUS_CONFIRMED, OrderStatus_ORDER_STATUS_SHI","content":"Реальный пример **Валидация на сервере:** ```go 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 после удаления return nil default: return errors.New(\"invalid order status\") } }"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::26","title":"ENUM_VALUE_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример func canModifyOrder(order *Order) bool { return order.Status != OrderStatus_ORDER_STATUS_CANCELLED // ERROR } ```","content":"Реальный пример func canModifyOrder(order *Order) bool { return order.Status != OrderStatus_ORDER_STATUS_CANCELLED // ERROR } ```"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::27","title":"ENUM_VALUE_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Сначала пометить deprecated:** **Перестать использовать deprecated значение в новом коде:** **Обработка legacy в клиенте:** **Резервирование после миграции:** **Никогда не переиспользовать номера** —","content":"Стратегия миграции **Сначала пометить deprecated:** **Перестать использовать deprecated значение в новом коде:** **Обработка legacy в клиенте:** **Резервирование после миграции:** **Никогда не переиспользовать номера** — зарезервированы навсегда."},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::28","title":"ENUM_VALUE_NO_DELETE","section":"Предотвращение переиспользования номера","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Предотвращение переиспользования номера"],"excerpt":"Предотвращение переиспользования номера ```proto enum Status { reserved 2; reserved \"STATUS_DELETED\";","content":"Предотвращение переиспользования номера ```proto enum Status { reserved 2; reserved \"STATUS_DELETED\";"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::29","title":"ENUM_VALUE_NO_DELETE","section":"Предотвращение переиспользования номера","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Предотвращение переиспользования номера"],"excerpt":"Предотвращение переиспользования номера STATUS_UNSPECIFIED = 0; STATUS_ACTIVE = 1; STATUS_INACTIVE = 3; // STATUS_DELETED = 2; // Не переиспользуем } ```","content":"Предотвращение переиспользования номера STATUS_UNSPECIFIED = 0; STATUS_ACTIVE = 1; STATUS_INACTIVE = 3; // STATUS_DELETED = 2; // Не переиспользуем } ```"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::json::30","title":"ENUM_VALUE_NO_DELETE","section":"JSON совместимость","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#json","headings":["JSON совместимость"],"excerpt":"JSON совместимость ```proto enum Color { reserved 2; reserved \"RED\";","content":"JSON совместимость ```proto enum Color { reserved 2; reserved \"RED\";"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::json::31","title":"ENUM_VALUE_NO_DELETE","section":"JSON совместимость","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#json","headings":["JSON совместимость"],"excerpt":"JSON совместимость COLOR_UNSPECIFIED = 0; COLOR_BLUE = 1; COLOR_GREEN = 3; // COLOR_RED = 2; // Был удалён } ```","content":"JSON совместимость COLOR_UNSPECIFIED = 0; COLOR_BLUE = 1; COLOR_GREEN = 3; // COLOR_RED = 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":"Это правило проверяет, что имя enum значения для каждого номера (number) не изменилось. Переименование enum значения при сохранении его номера ломает совместимость JSON и сгенерированный код: клиенты ожидают конкретные и","content":"Это правило проверяет, что имя enum значения для каждого номера (number) не изменилось. Переименование enum значения при сохранении его номера ломает совместимость JSON и сгенерированный код: клиенты ожидают конкретные имена констант."},{"id":"cli/breaking-changes/rules/enum-value-same-name::breaking::1","title":"ENUM_VALUE_SAME_NAME","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-value-same-name::breaking::2","title":"ENUM_VALUE_SAME_NAME","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/enum-value-same-name::breaking::3","title":"ENUM_VALUE_SAME_NAME","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_CONFIRMED = 2; ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_DELIVERED = 4; } ```","content":"Плохой (Breaking) 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::breaking::4","title":"ENUM_VALUE_SAME_NAME","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-value-same-name::breaking::5","title":"ENUM_VALUE_SAME_NAME","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/enum-value-same-name::breaking::6","title":"ENUM_VALUE_SAME_NAME","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_APPROVED = 2; // [!code --] Было ORDER_STATUS_CONFIRMED ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_COMPLETED = 4; // [","content":"Плохой (Breaking) enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_APPROVED = 2; // [!code --] Было ORDER_STATUS_CONFIRMED ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_COMPLETED = 4; // [!code --] Было ORDER_STATUS_DELIVERED } ```"},{"id":"cli/breaking-changes/rules/enum-value-same-name::top::7","title":"ENUM_VALUE_SAME_NAME","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры **Множественные переименования:** ```proto // Before enum UserRole { USER_ROLE_UNSPECIFIED = 0; USER_ROLE_ADMIN = 1; USER_ROLE_MODERATOR = 2; USER_ROLE_USER = 3; }","content":"Дополнительные примеры **Множественные переименования:** ```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::top::8","title":"ENUM_VALUE_SAME_NAME","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры // After - ВСЁ BREAKING enum UserRole { USER_ROLE_UNSPECIFIED = 0; USER_ROLE_ADMINISTRATOR = 1; // BREAKING: ADMIN -> ADMINISTRATOR USER_ROLE_MOD = 2; // BREAKING: MODERATOR -> MOD USER_ROLE_MEMBER","content":"Дополнительные примеры // After - ВСЁ BREAKING 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::top::9","title":"ENUM_VALUE_SAME_NAME","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо переименования — добавить новые значения и пометить старые deprecated:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо переименования — добавить новые значения и пометить старые deprecated:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-value-same-name::top::10","title":"ENUM_VALUE_SAME_NAME","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/enum-value-same-name::top::11","title":"ENUM_VALUE_SAME_NAME","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) 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 [depre","content":"Хороший (Безопасный) 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] // Новое значение вместо переименования ORDER_STATUS_COMPLETED = 6; // [!code focus] } ```"},{"id":"cli/breaking-changes/rules/enum-value-same-name::top::12","title":"ENUM_VALUE_SAME_NAME","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Или создать новую версию enum:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Или создать новую версию enum:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-value-same-name::top::13","title":"ENUM_VALUE_SAME_NAME","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v2; // [!code focus]","content":"Хороший (Безопасный) package myapi.v2; // [!code focus]"},{"id":"cli/breaking-changes/rules/enum-value-same-name::top::14","title":"ENUM_VALUE_SAME_NAME","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_APPROVED = 2; // [!code focus] // «Чистые» имена в v2 ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_COMPLETED = 4; // ","content":"Хороший (Безопасный) enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_APPROVED = 2; // [!code focus] // «Чистые» имена в v2 ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_COMPLETED = 4; // [!code focus] } ```"},{"id":"cli/breaking-changes/rules/enum-value-same-name::top::15","title":"ENUM_VALUE_SAME_NAME","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Влияние"],"excerpt":"Влияние **Generated Code:** Меняются имена констант — компиляция клиентов ломается **JSON Compatibility:** JSON использует имена enum — старые документы не парсятся **Client Applications:** Код со старым именем константы","content":"Влияние **Generated Code:** Меняются имена констант — компиляция клиентов ломается **JSON Compatibility:** JSON использует имена enum — старые документы не парсятся **Client Applications:** Код со старым именем константы не компилируется **Documentation:** Документация устаревает с неправильными именами"},{"id":"cli/breaking-changes/rules/enum-value-same-name::top::16","title":"ENUM_VALUE_SAME_NAME","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Реальный пример"],"excerpt":"Реальный пример **Ломается код клиента:** ```go // Before status := myapi.OrderStatus_ORDER_STATUS_CONFIRMED if order.Status == myapi.OrderStatus_ORDER_STATUS_DELIVERED { // handle delivery }","content":"Реальный пример **Ломается код клиента:** ```go // Before 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::top::17","title":"ENUM_VALUE_SAME_NAME","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Реальный пример"],"excerpt":"Реальный пример // After (переименовано) — ошибки компиляции status := myapi.OrderStatus_ORDER_STATUS_CONFIRMED // ERROR: undefined if order.Status == myapi.OrderStatus_ORDER_STATUS_DELIVERED { // ERROR: undefined // han","content":"Реальный пример // After (переименовано) — ошибки компиляции status := myapi.OrderStatus_ORDER_STATUS_CONFIRMED // ERROR: undefined if order.Status == myapi.OrderStatus_ORDER_STATUS_DELIVERED { // ERROR: undefined // handle delivery } ```"},{"id":"cli/breaking-changes/rules/enum-value-same-name::top::18","title":"ENUM_VALUE_SAME_NAME","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Реальный пример"],"excerpt":"Реальный пример **JSON совместимость ломается:** ```json // Раньше { \"status\": \"ORDER_STATUS_CONFIRMED\" }","content":"Реальный пример **JSON совместимость ломается:** ```json // Раньше { \"status\": \"ORDER_STATUS_CONFIRMED\" }"},{"id":"cli/breaking-changes/rules/enum-value-same-name::top::19","title":"ENUM_VALUE_SAME_NAME","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Реальный пример"],"excerpt":"Реальный пример // После { \"status\": \"ORDER_STATUS_APPROVED\" // Старые JSON больше не парсятся } ```","content":"Реальный пример // После { \"status\": \"ORDER_STATUS_APPROVED\" // Старые JSON больше не парсятся } ```"},{"id":"cli/breaking-changes/rules/enum-value-same-name::top::20","title":"ENUM_VALUE_SAME_NAME","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Добавьте новое значение вместо переименования:**","content":"Стратегия миграции **Добавьте новое значение вместо переименования:**"},{"id":"cli/breaking-changes/rules/enum-value-same-name::top::21","title":"ENUM_VALUE_SAME_NAME","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Сервер обрабатывает оба значения на переходном этапе** **Мигрируйте клиентов** на новые значения **Удалите (reserve) старое имя и номер** в следующей major‑версии:","content":"Стратегия миграции **Сервер обрабатывает оба значения на переходном этапе** **Мигрируйте клиентов** на новые значения **Удалите (reserve) старое имя и номер** в следующей major‑версии:"},{"id":"cli/breaking-changes/rules/enum-value-same-name::allow-alias::22","title":"ENUM_VALUE_SAME_NAME","section":"Allow Alias (исключение)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name#allow-alias","headings":["Allow Alias (исключение)"],"excerpt":"Allow Alias (исключение) С allow_alias = true можно временно иметь два имени для одного номера:","content":"Allow Alias (исключение) С allow_alias = true можно временно иметь два имени для одного номера:"},{"id":"cli/breaking-changes/rules/enum-value-same-name::allow-alias::23","title":"ENUM_VALUE_SAME_NAME","section":"Allow Alias (исключение)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name#allow-alias","headings":["Allow Alias (исключение)"],"excerpt":"Allow Alias (исключение) Примечание: Сейчас EasyP всё равно считает это breaking (может измениться в будущем).","content":"Allow Alias (исключение) Примечание: Сейчас EasyP всё равно считает это breaking (может измениться в будущем)."},{"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":"Это правило проверяет, что ни одно поле сообщения (message field) не было удалено. Удаление поля ломает совместимость по wire‑формату и сгенерированный код: в существующих данных может присутствовать удалённое поле, а кл","content":"Это правило проверяет, что ни одно поле сообщения (message field) не было удалено. Удаление поля ломает совместимость по wire‑формату и сгенерированный код: в существующих данных может присутствовать удалённое поле, а клиентский код может ссылаться на него."},{"id":"cli/breaking-changes/rules/field-no-delete::breaking::1","title":"FIELD_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-no-delete::breaking::2","title":"FIELD_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/field-no-delete::breaking::3","title":"FIELD_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message User { string name = 1; string email = 2; int32 age = 3; string phone = 4; // [!code --] } ```","content":"Плохой (Breaking) message User { string name = 1; string email = 2; int32 age = 3; string phone = 4; // [!code --] } ```"},{"id":"cli/breaking-changes/rules/field-no-delete::breaking::4","title":"FIELD_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-no-delete::breaking::5","title":"FIELD_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/field-no-delete::breaking::6","title":"FIELD_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message User { string name = 1; string email = 2; int32 age = 3; // phone поле удалено — BREAKING CHANGE! } ```","content":"Плохой (Breaking) message User { string name = 1; string email = 2; int32 age = 3; // phone поле удалено — BREAKING CHANGE! } ```"},{"id":"cli/breaking-changes/rules/field-no-delete::top::7","title":"FIELD_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо удаления — пометить поле deprecated:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо удаления — пометить поле deprecated:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-no-delete::top::8","title":"FIELD_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/field-no-delete::top::9","title":"FIELD_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message User { string name = 1; string email = 2; int32 age = 3; string phone = 4 [deprecated = true]; // [!code focus] } ```","content":"Хороший (Безопасный) 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::top::10","title":"FIELD_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Или зарезервировать номер и имя поля после удаления:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Или зарезервировать номер и имя поля после удаления:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-no-delete::top::11","title":"FIELD_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/field-no-delete::top::12","title":"FIELD_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message User { reserved 4; // [!code focus] reserved \"phone\"; // [!code focus] string name = 1; string email = 2; int32 age = 3; } ```","content":"Хороший (Безопасный) 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::top::13","title":"FIELD_NO_DELETE","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete","headings":["Влияние"],"excerpt":"Влияние **Wire Format:** Старые сообщения с удалённым полем некорректно десериализуются **Generated Code:** Удаляются аксессоры (get/set), компиляция клиента ломается **Data Loss:** Потеря сохранённых данных, связанных с","content":"Влияние **Wire Format:** Старые сообщения с удалённым полем некорректно десериализуются **Generated Code:** Удаляются аксессоры (get/set), компиляция клиента ломается **Data Loss:** Потеря сохранённых данных, связанных с полем **JSON Compatibility:** JSON парсеры ожидают наличие поля и могут выдавать ошибки"},{"id":"cli/breaking-changes/rules/field-no-delete::top::14","title":"FIELD_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Сначала пометить deprecated:**","content":"Стратегия миграции **Сначала пометить deprecated:**"},{"id":"cli/breaking-changes/rules/field-no-delete::top::15","title":"FIELD_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Прекратить запись в поле** в прикладном коде","content":"Стратегия миграции **Прекратить запись в поле** в прикладном коде"},{"id":"cli/breaking-changes/rules/field-no-delete::top::16","title":"FIELD_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Зарезервировать поле** в следующей версии, чтобы избежать повторного использования:","content":"Стратегия миграции **Зарезервировать поле** в следующей версии, чтобы избежать повторного использования:"},{"id":"cli/breaking-changes/rules/field-no-delete::top::17","title":"FIELD_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Никогда не переиспользовать номер поля** — должен оставаться в reserved навсегда","content":"Стратегия миграции **Никогда не переиспользовать номер поля** — должен оставаться в reserved навсегда"},{"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":"Правило проверяет, что поля сообщений сохраняют ту же кардинальность (обязательность / optional). Изменение кардинальности поля ломает совместимость по wire‑формату и сгенерированный код: семантика присутствия и ожидания","content":"Правило проверяет, что поля сообщений сохраняют ту же кардинальность (обязательность / optional). Изменение кардинальности поля ломает совместимость по wire‑формату и сгенерированный код: семантика присутствия и ожидания клиентского кода отличаются для optional и required (implicit) полей."},{"id":"cli/breaking-changes/rules/field-same-cardinality::breaking::1","title":"FIELD_SAME_CARDINALITY","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-same-cardinality::breaking::2","title":"FIELD_SAME_CARDINALITY","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/field-same-cardinality::breaking::3","title":"FIELD_SAME_CARDINALITY","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message User { string name = 1; string email = 2; int32 age = 3; }","content":"Плохой (Breaking) message User { string name = 1; string email = 2; int32 age = 3; }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::breaking::4","title":"FIELD_SAME_CARDINALITY","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message CreateUserRequest { string name = 1; optional string email = 2; string phone = 3; } ```","content":"Плохой (Breaking) message CreateUserRequest { string name = 1; optional string email = 2; string phone = 3; } ```"},{"id":"cli/breaking-changes/rules/field-same-cardinality::breaking::5","title":"FIELD_SAME_CARDINALITY","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-same-cardinality::breaking::6","title":"FIELD_SAME_CARDINALITY","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/field-same-cardinality::breaking::7","title":"FIELD_SAME_CARDINALITY","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message User { string name = 1; optional string email = 2; // [!code --] Было required (implicit), стало optional int32 age = 3; }","content":"Плохой (Breaking) message User { string name = 1; optional string email = 2; // [!code --] Было required (implicit), стало optional int32 age = 3; }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::breaking::8","title":"FIELD_SAME_CARDINALITY","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message CreateUserRequest { string name = 1; string email = 2; // [!code --] Было optional, стало требуемым (implicit required) string phone = 3; } ```","content":"Плохой (Breaking) message CreateUserRequest { string name = 1; string email = 2; // [!code --] Было optional, стало требуемым (implicit required) string phone = 3; } ```"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::9","title":"FIELD_SAME_CARDINALITY","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры **Проблемы миграции Proto2 → Proto3:**","content":"Дополнительные примеры **Проблемы миграции Proto2 → Proto3:**"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::10","title":"FIELD_SAME_CARDINALITY","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры ```proto // Before (proto2) syntax = \"proto2\";","content":"Дополнительные примеры ```proto // Before (proto2) syntax = \"proto2\";"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::11","title":"FIELD_SAME_CARDINALITY","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры message Order { required string id = 1; optional string notes = 2; repeated string tags = 3; }","content":"Дополнительные примеры message Order { required string id = 1; optional string notes = 2; repeated string tags = 3; }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::12","title":"FIELD_SAME_CARDINALITY","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры // After (proto3) - BREAKING CHANGES! syntax = \"proto3\";","content":"Дополнительные примеры // After (proto3) - BREAKING CHANGES! syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::13","title":"FIELD_SAME_CARDINALITY","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры message Order { string id = 1; // BREAKING: required -> implicit optional string notes = 2; // BREAKING: explicit optional -> implicit optional repeated string tags = 3; // OK } ```","content":"Дополнительные примеры message Order { string id = 1; // BREAKING: required -> implicit optional string notes = 2; // BREAKING: explicit optional -> implicit optional repeated string tags = 3; // OK } ```"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::14","title":"FIELD_SAME_CARDINALITY","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо изменения кардинальности — добавьте новое поле:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо изменения кардинальности — добавьте новое поле:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::15","title":"FIELD_SAME_CARDINALITY","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::16","title":"FIELD_SAME_CARDINALITY","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message User { string name = 1; string email = 2 [deprecated = true]; // [!code focus] Сохраняем старую кардинальность int32 age = 3; optional string email_optional = 4; // [!code focus] Новое option","content":"Хороший (Безопасный) message User { string name = 1; string email = 2 [deprecated = true]; // [!code focus] Сохраняем старую кардинальность int32 age = 3; optional string email_optional = 4; // [!code focus] Новое optional поле }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::17","title":"FIELD_SAME_CARDINALITY","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message CreateUserRequest { string name = 1; optional string email = 2 [deprecated = true]; // [!code focus] string phone = 3; string email_required = 4; // [!code focus] Новое требуемое поле } ```","content":"Хороший (Безопасный) message CreateUserRequest { string name = 1; optional string email = 2 [deprecated = true]; // [!code focus] string phone = 3; string email_required = 4; // [!code focus] Новое требуемое поле } ```"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::18","title":"FIELD_SAME_CARDINALITY","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Или создайте новую версию сообщения:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Или создайте новую версию сообщения:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::19","title":"FIELD_SAME_CARDINALITY","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v2; // [!code focus]","content":"Хороший (Безопасный) package myapi.v2; // [!code focus]"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::20","title":"FIELD_SAME_CARDINALITY","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message User { string name = 1; optional string email = 2; // [!code focus] Чистая модель в v2 int32 age = 3; }","content":"Хороший (Безопасный) message User { string name = 1; optional string email = 2; // [!code focus] Чистая модель в v2 int32 age = 3; }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::21","title":"FIELD_SAME_CARDINALITY","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message CreateUserRequest { string name = 1; string email = 2; // [!code focus] Требуемое в v2 string phone = 3; } ```","content":"Хороший (Безопасный) message CreateUserRequest { string name = 1; string email = 2; // [!code focus] Требуемое в v2 string phone = 3; } ```"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::22","title":"FIELD_SAME_CARDINALITY","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Влияние"],"excerpt":"Влияние **Wire Format:** Меняется семантика присутствия — клиенты неправильно ожидают поля **Generated Code:** Меняются методы доступа / проверки (has, clear) **Validation:** Правила проверки обязательности переписываютс","content":"Влияние **Wire Format:** Меняется семантика присутствия — клиенты неправильно ожидают поля **Generated Code:** Меняются методы доступа / проверки (has, clear) **Validation:** Правила проверки обязательности переписываются **Default Values:** Optional и required по‑разному обрабатывают отсутствие значения"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::23","title":"FIELD_SAME_CARDINALITY","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Реальный пример"],"excerpt":"Реальный пример **Код клиента ломается при смене кардинальности:** ```go // Before - поле фактически требуется (implicit) user := &myapi.User{ Name: \"John\", Email: \"john@example.com\", Age: 30, }","content":"Реальный пример **Код клиента ломается при смене кардинальности:** ```go // Before - поле фактически требуется (implicit) user := &myapi.User{ Name: \"John\", Email: \"john@example.com\", Age: 30, }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::24","title":"FIELD_SAME_CARDINALITY","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Реальный пример"],"excerpt":"Реальный пример if user.Email != \"\" { // Есть значение }","content":"Реальный пример if user.Email != \"\" { // Есть значение }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::25","title":"FIELD_SAME_CARDINALITY","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Реальный пример"],"excerpt":"Реальный пример // After - поле стало optional (pointer) user := &myapi.User{ Name: \"John\", Age: 30, // Email может отсутствовать }","content":"Реальный пример // After - поле стало optional (pointer) user := &myapi.User{ Name: \"John\", Age: 30, // Email может отсутствовать }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::26","title":"FIELD_SAME_CARDINALITY","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Реальный пример"],"excerpt":"Реальный пример if user.Email != nil && *user.Email != \"\" { // Есть значение (новый способ) }","content":"Реальный пример if user.Email != nil && *user.Email != \"\" { // Есть значение (новый способ) }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::27","title":"FIELD_SAME_CARDINALITY","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Реальный пример"],"excerpt":"Реальный пример user.Email = &emailValue // Присваивание указателя вместо строки ```","content":"Реальный пример user.Email = &emailValue // Присваивание указателя вместо строки ```"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::28","title":"FIELD_SAME_CARDINALITY","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Реальный пример"],"excerpt":"Реальный пример **Валидация на сервере:** ```go // Before func validateUser(user *User) error { if user.Email == \"\" { return errors.New(\"email is required\") } return nil }","content":"Реальный пример **Валидация на сервере:** ```go // Before func validateUser(user *User) error { if user.Email == \"\" { return errors.New(\"email is required\") } return nil }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::29","title":"FIELD_SAME_CARDINALITY","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Реальный пример"],"excerpt":"Реальный пример // After func validateUser(user *User) error { if user.Email == nil { return errors.New(\"email is required\") } if *user.Email == \"\" { return errors.New(\"email cannot be empty\") } return nil } ```","content":"Реальный пример // After func validateUser(user *User) error { if user.Email == nil { return errors.New(\"email is required\") } if *user.Email == \"\" { return errors.New(\"email cannot be empty\") } return nil } ```"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::30","title":"FIELD_SAME_CARDINALITY","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Добавьте новое поле** с нужной кардинальностью:","content":"Стратегия миграции **Добавьте новое поле** с нужной кардинальностью:"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::31","title":"FIELD_SAME_CARDINALITY","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Период двойной записи** — заполняйте оба поля:","content":"Стратегия миграции **Период двойной записи** — заполняйте оба поля:"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::32","title":"FIELD_SAME_CARDINALITY","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Клиенты постепенно переходят**:","content":"Стратегия миграции **Клиенты постепенно переходят**:"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::33","title":"FIELD_SAME_CARDINALITY","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Удаление старого поля** в следующей major‑версии:","content":"Стратегия миграции **Удаление старого поля** в следующей major‑версии:"},{"id":"cli/breaking-changes/rules/field-same-cardinality::proto2-proto3::34","title":"FIELD_SAME_CARDINALITY","section":"Миграция Proto2 → Proto3","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#proto2-proto3","headings":["Миграция Proto2 → Proto3"],"excerpt":"Миграция Proto2 → Proto3 ```proto syntax = \"proto3\"; message Order { string id = 1; // BREAKING если был required }","content":"Миграция Proto2 → Proto3 ```proto syntax = \"proto3\"; message Order { string id = 1; // BREAKING если был required }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::proto2-proto3::35","title":"FIELD_SAME_CARDINALITY","section":"Миграция Proto2 → Proto3","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#proto2-proto3","headings":["Миграция Proto2 → Proto3"],"excerpt":"Миграция Proto2 → Proto3 // Сохранить семантику: syntax = \"proto3\"; message Order { string id = 1; optional string notes = 2; } ```","content":"Миграция Proto2 → Proto3 // Сохранить семантику: syntax = \"proto3\"; message Order { string id = 1; optional string notes = 2; } ```"},{"id":"cli/breaking-changes/rules/field-same-cardinality::optional-required::36","title":"FIELD_SAME_CARDINALITY","section":"Делать optional поле required","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#optional-required","headings":["Делать optional поле required"],"excerpt":"Делать optional поле required ```proto message CreateUserRequest { string name = 1; string email = 2; // BREAKING (раньше optional) }","content":"Делать optional поле required ```proto message CreateUserRequest { string name = 1; string email = 2; // BREAKING (раньше optional) }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::optional-required::37","title":"FIELD_SAME_CARDINALITY","section":"Делать optional поле required","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#optional-required","headings":["Делать optional поле required"],"excerpt":"Делать optional поле required message CreateUserRequest { string name = 1; optional string email = 2 [deprecated = true]; string required_email = 3; } ```","content":"Делать optional поле required message CreateUserRequest { string name = 1; optional string email = 2 [deprecated = true]; string required_email = 3; } ```"},{"id":"cli/breaking-changes/rules/field-same-cardinality::required-optional::38","title":"FIELD_SAME_CARDINALITY","section":"Делать required поле optional","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#required-optional","headings":["Делать required поле optional"],"excerpt":"Делать required поле optional ```proto message User { optional string phone = 3; // BREAKING (было implicit required) }","content":"Делать required поле optional ```proto message User { optional string phone = 3; // BREAKING (было implicit required) }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::required-optional::39","title":"FIELD_SAME_CARDINALITY","section":"Делать required поле optional","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#required-optional","headings":["Делать required поле optional"],"excerpt":"Делать required поле optional message User { string phone = 3 [deprecated = true]; optional string phone_optional = 4; } ```","content":"Делать required поле optional message User { string phone = 3 [deprecated = true]; optional string phone_optional = 4; } ```"},{"id":"cli/breaking-changes/rules/field-same-cardinality::protobuf::40","title":"FIELD_SAME_CARDINALITY","section":"Типы кардинальности в Protobuf","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#protobuf","headings":["Типы кардинальности в Protobuf"],"excerpt":"Типы кардинальности в Protobuf","content":"Типы кардинальности в Protobuf"},{"id":"cli/breaking-changes/rules/field-same-cardinality::proto3::41","title":"FIELD_SAME_CARDINALITY","section":"Proto3","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#proto3","headings":["Proto3"],"excerpt":"Proto3 **Implicit optional**: string name = 1; **Explicit optional**: optional string email = 2; **Repeated**: repeated string tags = 3; **Map**: map metadata = 4;","content":"Proto3 **Implicit optional**: string name = 1; **Explicit optional**: optional string email = 2; **Repeated**: repeated string tags = 3; **Map**: map metadata = 4;"},{"id":"cli/breaking-changes/rules/field-same-cardinality::proto2::42","title":"FIELD_SAME_CARDINALITY","section":"Proto2","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#proto2","headings":["Proto2"],"excerpt":"Proto2 **Required**: required string id = 1; **Optional**: optional string email = 2; **Repeated**: repeated string tags = 3;","content":"Proto2 **Required**: required string id = 1; **Optional**: optional string email = 2; **Repeated**: repeated string tags = 3;"},{"id":"cli/breaking-changes/rules/field-same-cardinality::breaking::43","title":"FIELD_SAME_CARDINALITY","section":"Матрица Breaking изменений","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#breaking","headings":["Матрица Breaking изменений"],"excerpt":"Матрица Breaking изменений From To Result ------ ---- -------- Required Optional ❌ BREAKING Optional Required ❌ BREAKING Implicit Explicit ❌ BREAKING Explicit Implicit ❌ BREAKING Single Repeated ❌ BREAKING Repeated Singl","content":"Матрица Breaking изменений 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":"Правило проверяет, что типы полей сообщений (message fields) не изменяются. Смена типа поля ломает совместимость по wire‑формату и сгенерированный код: бинарное представление и ожидания клиентского кода различаются для р","content":"Правило проверяет, что типы полей сообщений (message fields) не изменяются. Смена типа поля ломает совместимость по wire‑формату и сгенерированный код: бинарное представление и ожидания клиентского кода различаются для разных типов."},{"id":"cli/breaking-changes/rules/field-same-type::breaking::1","title":"FIELD_SAME_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-same-type::breaking::2","title":"FIELD_SAME_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/field-same-type::breaking::3","title":"FIELD_SAME_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message Product { string name = 1; int32 price = 2; bool available = 3; } ```","content":"Плохой (Breaking) message Product { string name = 1; int32 price = 2; bool available = 3; } ```"},{"id":"cli/breaking-changes/rules/field-same-type::breaking::4","title":"FIELD_SAME_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-same-type::breaking::5","title":"FIELD_SAME_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/field-same-type::breaking::6","title":"FIELD_SAME_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message Product { string name = 1; string price = 2; // [!code --] Changed from int32 to string (изменён тип) bool available = 3; } ```","content":"Плохой (Breaking) 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::top::7","title":"FIELD_SAME_TYPE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/field-same-type","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры **Несовместимые изменения типов:** ```proto // Before message Order { string id = 1; int64 timestamp = 2; repeated string tags = 3; OrderStatus status = 4; }","content":"Дополнительные примеры **Несовместимые изменения типов:** ```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::top::8","title":"FIELD_SAME_TYPE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/field-same-type","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры // After - ВСЁ BREAKING message Order { int32 id = 1; // string -> int32: BREAKING string timestamp = 2; // int64 -> string: BREAKING string tags = 3; // repeated -> singular: BREAKING int32 status","content":"Дополнительные примеры // After - ВСЁ BREAKING 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::top::9","title":"FIELD_SAME_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо смены типа — добавьте новое поле:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо смены типа — добавьте новое поле:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-same-type::top::10","title":"FIELD_SAME_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/field-same-type::top::11","title":"FIELD_SAME_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message Product { string name = 1; int32 price = 2 [deprecated = true]; // [!code focus] // Старое поле помечено deprecated bool available = 3; string price_formatted = 4; // [!code focus] // Новое п","content":"Хороший (Безопасный) message Product { string name = 1; int32 price = 2 [deprecated = true]; // [!code focus] // Старое поле помечено deprecated bool available = 3; string price_formatted = 4; // [!code focus] // Новое поле со строковым представлением } ```"},{"id":"cli/breaking-changes/rules/field-same-type::top::12","title":"FIELD_SAME_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Или создайте новую версию сообщения:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Или создайте новую версию сообщения:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-same-type::top::13","title":"FIELD_SAME_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v2; // [!code focus] // Новая версия package","content":"Хороший (Безопасный) package myapi.v2; // [!code focus] // Новая версия package"},{"id":"cli/breaking-changes/rules/field-same-type::top::14","title":"FIELD_SAME_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message Product { string name = 1; string price = 2; // [!code focus] // В v2 уже string bool available = 3; } ```","content":"Хороший (Безопасный) message Product { string name = 1; string price = 2; // [!code focus] // В v2 уже string bool available = 3; } ```"},{"id":"cli/breaking-changes/rules/field-same-type::top::15","title":"FIELD_SAME_TYPE","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/field-same-type","headings":["Влияние"],"excerpt":"Влияние **Wire Format:** Старые бинарные данные не десериализуются корректно **Generated Code:** Меняются типы в сгенерированном коде — клиенты не компилируются **Runtime Errors:** Ошибки парсинга при несовпадении ожидае","content":"Влияние **Wire Format:** Старые бинарные данные не десериализуются корректно **Generated Code:** Меняются типы в сгенерированном коде — клиенты не компилируются **Runtime Errors:** Ошибки парсинга при несовпадении ожидаемого типа **Data Corruption:** Неверная интерпретация байтов данных"},{"id":"cli/breaking-changes/rules/field-same-type::top::16","title":"FIELD_SAME_TYPE","section":"Типовые проблемы изменений типов","path":"/docs/guide/cli/breaking-changes/rules/field-same-type","headings":["Типовые проблемы изменений типов"],"excerpt":"Типовые проблемы изменений типов","content":"Типовые проблемы изменений типов"},{"id":"cli/breaking-changes/rules/field-same-type::top::17","title":"FIELD_SAME_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/field-same-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Добавьте новое поле** с нужным типом:","content":"Стратегия миграции **Добавьте новое поле** с нужным типом:"},{"id":"cli/breaking-changes/rules/field-same-type::top::18","title":"FIELD_SAME_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/field-same-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Период двойной записи** — заполняйте оба поля для совместимости","content":"Стратегия миграции **Период двойной записи** — заполняйте оба поля для совместимости"},{"id":"cli/breaking-changes/rules/field-same-type::top::19","title":"FIELD_SAME_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/field-same-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Мигрируйте клиентов** на новое поле постепенно","content":"Стратегия миграции **Мигрируйте клиентов** на новое поле постепенно"},{"id":"cli/breaking-changes/rules/field-same-type::top::20","title":"FIELD_SAME_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/field-same-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Удалите старое поле** в следующей major‑версии:","content":"Стратегия миграции **Удалите старое поле** в следующей major‑версии:"},{"id":"cli/breaking-changes/rules/field-same-type::wire::21","title":"FIELD_SAME_TYPE","section":"Безопасные изменения (Теоретически wire‑совместимые)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type#wire","headings":["Безопасные изменения (Теоретически wire‑совместимые)"],"excerpt":"Безопасные изменения (Теоретически wire‑совместимые) Примечание: EasyP сейчас считает ЛЮБУЮ смену типа breaking. Однако технически некоторые случаи совместимы:","content":"Безопасные изменения (Теоретически wire‑совместимые) Примечание: EasyP сейчас считает ЛЮБУЮ смену типа breaking. Однако технически некоторые случаи совместимы:"},{"id":"cli/breaking-changes/rules/field-same-type::wire::22","title":"FIELD_SAME_TYPE","section":"Безопасные изменения (Теоретически wire‑совместимые)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type#wire","headings":["Безопасные изменения (Теоретически wire‑совместимые)"],"excerpt":"Безопасные изменения (Теоретически wire‑совместимые) int32 ↔ uint32 (одно кодирование) int64 ↔ uint64 (одно кодирование) string → bytes (если все строки валидный UTF‑8)","content":"Безопасные изменения (Теоретически wire‑совместимые) int32 ↔ uint32 (одно кодирование) int64 ↔ uint64 (одно кодирование) string → bytes (если все строки валидный UTF‑8)"},{"id":"cli/breaking-changes/rules/field-same-type::wire::23","title":"FIELD_SAME_TYPE","section":"Безопасные изменения (Теоретически wire‑совместимые)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type#wire","headings":["Безопасные изменения (Теоретически wire‑совместимые)"],"excerpt":"Безопасные изменения (Теоретически wire‑совместимые) Эти исключения могут получить отдельную обработку в будущих версиях EasyP с более гибкими уровнями строгости.","content":"Безопасные изменения (Теоретически wire‑совместимые) Эти исключения могут получить отдельную обработку в будущих версиях EasyP с более гибкими уровнями строгости."},{"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":"Это правило проверяет, что ни одна инструкция import не была удалена из proto‑файла. Удаление import ломает совместимость по wire‑формату и сгенерированный код: типы из импортируемых файлов могли использоваться в текущем","content":"Это правило проверяет, что ни одна инструкция import не была удалена из proto‑файла. Удаление import ломает совместимость по wire‑формату и сгенерированный код: типы из импортируемых файлов могли использоваться в текущем файле, и их удаление делает эти типы недоступными."},{"id":"cli/breaking-changes/rules/import-no-delete::breaking::1","title":"IMPORT_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/import-no-delete::breaking::2","title":"IMPORT_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/import-no-delete::breaking::3","title":"IMPORT_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) import \"google/protobuf/timestamp.proto\"; import \"google/protobuf/duration.proto\"; import \"common/user.proto\"; import \"common/address.proto\";","content":"Плохой (Breaking) 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::breaking::4","title":"IMPORT_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) 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":"Плохой (Breaking) 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::breaking::5","title":"IMPORT_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/import-no-delete::breaking::6","title":"IMPORT_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/import-no-delete::breaking::7","title":"IMPORT_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) import \"google/protobuf/timestamp.proto\"; // import \"google/protobuf/duration.proto\"; // [!code --] Удалён import — BREAKING // import \"common/user.proto\"; // [!code --] Удалён import — BREAKING // impo","content":"Плохой (Breaking) import \"google/protobuf/timestamp.proto\"; // import \"google/protobuf/duration.proto\"; // [!code --] Удалён import — BREAKING // import \"common/user.proto\"; // [!code --] Удалён import — BREAKING // import \"common/address.proto\"; // [!code --] Удалён import — BREAKING"},{"id":"cli/breaking-changes/rules/import-no-delete::breaking::8","title":"IMPORT_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message Order { string id = 1; google.protobuf.Timestamp created_at = 2; google.protobuf.Duration processing_time = 3; // ERROR: Duration недоступен common.User customer = 4; // ERROR: User недоступен c","content":"Плохой (Breaking) message Order { string id = 1; google.protobuf.Timestamp created_at = 2; google.protobuf.Duration processing_time = 3; // ERROR: Duration недоступен common.User customer = 4; // ERROR: User недоступен common.Address shipping_address = 5; // ERROR: Address недоступен } ```"},{"id":"cli/breaking-changes/rules/import-no-delete::top::9","title":"IMPORT_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры **Сервис ломается при удалённых import:** ```proto // Before import \"google/api/annotations.proto\"; import \"google/protobuf/empty.proto\"; import \"common/auth.proto\";","content":"Дополнительные примеры **Сервис ломается при удалённых import:** ```proto // Before import \"google/api/annotations.proto\"; import \"google/protobuf/empty.proto\"; import \"common/auth.proto\";"},{"id":"cli/breaking-changes/rules/import-no-delete::top::10","title":"IMPORT_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры service OrderService { rpc GetOrder(GetOrderRequest) returns (Order) { option (google.api.http) = { get: \"/v1/orders/{id}\" }; } rpc DeleteOrder(common.AuthRequest) returns (google.protobuf.Empty); ","content":"Дополнительные примеры 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::top::11","title":"IMPORT_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры // After - BREAKING CHANGES! // import \"google/api/annotations.proto\"; // BREAKING: deleted // import \"google/protobuf/empty.proto\"; // BREAKING: deleted // import \"common/auth.proto\"; // BREAKING:","content":"Дополнительные примеры // 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::top::12","title":"IMPORT_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры service OrderService { rpc GetOrder(GetOrderRequest) returns (Order) { option (google.api.http) = { // ERROR: annotations недоступен get: \"/v1/orders/{id}\" }; } rpc DeleteOrder(common.AuthRequest) ","content":"Дополнительные примеры service OrderService { rpc GetOrder(GetOrderRequest) returns (Order) { option (google.api.http) = { // ERROR: annotations недоступен get: \"/v1/orders/{id}\" }; } rpc DeleteOrder(common.AuthRequest) returns (google.protobuf.Empty); // ERROR: типы недоступны } ```"},{"id":"cli/breaking-changes/rules/import-no-delete::top::13","title":"IMPORT_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо удаления оставьте неиспользуемые import:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо удаления оставьте неиспользуемые import:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/import-no-delete::top::14","title":"IMPORT_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/import-no-delete::top::15","title":"IMPORT_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) import \"google/protobuf/timestamp.proto\"; import \"google/protobuf/duration.proto\"; // [!code focus] // Оставляем даже если не используется import \"common/user.proto\"; // [!code focus] import \"common/","content":"Хороший (Безопасный) import \"google/protobuf/timestamp.proto\"; import \"google/protobuf/duration.proto\"; // [!code focus] // Оставляем даже если не используется import \"common/user.proto\"; // [!code focus] import \"common/address.proto\"; // [!code focus]"},{"id":"cli/breaking-changes/rules/import-no-delete::top::16","title":"IMPORT_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message Order { string id = 1; google.protobuf.Timestamp created_at = 2; // Поля, использовавшие Duration/User/Address, удалены — import оставлены } ```","content":"Хороший (Безопасный) message Order { string id = 1; google.protobuf.Timestamp created_at = 2; // Поля, использовавшие Duration/User/Address, удалены — import оставлены } ```"},{"id":"cli/breaking-changes/rules/import-no-delete::top::17","title":"IMPORT_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Или добавьте новые типы, сохранив старые import:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Или добавьте новые типы, сохранив старые import:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/import-no-delete::top::18","title":"IMPORT_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/import-no-delete::top::19","title":"IMPORT_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) import \"google/protobuf/timestamp.proto\"; import \"google/protobuf/duration.proto\"; // [!code focus] import \"common/user.proto\"; // [!code focus] import \"common/address.proto\"; // [!code focus] import","content":"Хороший (Безопасный) import \"google/protobuf/timestamp.proto\"; import \"google/protobuf/duration.proto\"; // [!code focus] import \"common/user.proto\"; // [!code focus] import \"common/address.proto\"; // [!code focus] import \"common/v2/user.proto\"; // [!code focus] // Новый import"},{"id":"cli/breaking-changes/rules/import-no-delete::top::20","title":"IMPORT_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message Order { string id = 1; google.protobuf.Timestamp created_at = 2; google.protobuf.Duration processing_time = 3 [deprecated = true]; // [!code focus] common.User customer = 4 [deprecated = true","content":"Хороший (Безопасный) message Order { string id = 1; google.protobuf.Timestamp created_at = 2; google.protobuf.Duration processing_time = 3 [deprecated = true]; // [!code focus] common.User customer = 4 [deprecated = true]; // [!code focus] common.Address shipping_address = 5 [deprecated = true]; // [!code focus] int32 processing_seconds = 6; common.v2.UserProfile customer_v2 = 7; string shipping_address_text = 8; } ```"},{"id":"cli/breaking-changes/rules/import-no-delete::top::21","title":"IMPORT_NO_DELETE","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Влияние"],"excerpt":"Влияние **Generated Code:** Типы пропадают → ошибка компиляции **Wire Format:** Сообщения с удалёнными типами не десериализуются **Field References:** Поля с этими типами становятся невалидны **Service Definitions:** RPC","content":"Влияние **Generated Code:** Типы пропадают → ошибка компиляции **Wire Format:** Сообщения с удалёнными типами не десериализуются **Field References:** Поля с этими типами становятся невалидны **Service Definitions:** RPC с типами из удалённых файлов ломаются **Options Usage:** Пользовательские опции из импортов недоступны"},{"id":"cli/breaking-changes/rules/import-no-delete::top::22","title":"IMPORT_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Код клиента ломается:**","content":"Реальный пример **Код клиента ломается:**"},{"id":"cli/breaking-changes/rules/import-no-delete::top::23","title":"IMPORT_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Серверная логика ломается:**","content":"Реальный пример **Серверная логика ломается:**"},{"id":"cli/breaking-changes/rules/import-no-delete::top::24","title":"IMPORT_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Компиляция proto ломается:**","content":"Реальный пример **Компиляция proto ломается:**"},{"id":"cli/breaking-changes/rules/import-no-delete::top::25","title":"IMPORT_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции Сохраняйте import даже если типы более не используются: Добавляйте новые import рядом со старыми: Депрецируйте поля со старыми типами постепенно: Сервер: поддерживайте оба варианта: Удаляйте import тол","content":"Стратегия миграции Сохраняйте import даже если типы более не используются: Добавляйте новые import рядом со старыми: Депрецируйте поля со старыми типами постепенно: Сервер: поддерживайте оба варианта: Удаляйте import только в следующей major‑версии после полной миграции."},{"id":"cli/breaking-changes/rules/import-no-delete::top::26","title":"IMPORT_NO_DELETE","section":"Замена зависимости","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Замена зависимости"],"excerpt":"Замена зависимости ```proto import \"old/user.proto\"; // Старый import \"new/user.proto\"; // Новый","content":"Замена зависимости ```proto import \"old/user.proto\"; // Старый import \"new/user.proto\"; // Новый"},{"id":"cli/breaking-changes/rules/import-no-delete::top::27","title":"IMPORT_NO_DELETE","section":"Замена зависимости","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Замена зависимости"],"excerpt":"Замена зависимости message Order { old.User customer = 4 [deprecated = true]; new.UserProfile customer_v2 = 5; } ```","content":"Замена зависимости message Order { old.User customer = 4 [deprecated = true]; new.UserProfile customer_v2 = 5; } ```"},{"id":"cli/breaking-changes/rules/import-no-delete::top::28","title":"IMPORT_NO_DELETE","section":"Удаление функционала","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Удаление функционала"],"excerpt":"Удаление функционала ```proto import \"feature/analytics.proto\"; // Оставить даже если поле удалено","content":"Удаление функционала ```proto import \"feature/analytics.proto\"; // Оставить даже если поле удалено"},{"id":"cli/breaking-changes/rules/import-no-delete::top::29","title":"IMPORT_NO_DELETE","section":"Удаление функционала","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Удаление функционала"],"excerpt":"Удаление функционала message Order { string id = 1; // feature.AnalyticsData analytics = 2; // Поле удалено, import остаётся } ```","content":"Удаление функционала message Order { string id = 1; // feature.AnalyticsData analytics = 2; // Поле удалено, import остаётся } ```"},{"id":"cli/breaking-changes/rules/import-no-delete::protobuf::30","title":"IMPORT_NO_DELETE","section":"Миграция версии protobuf","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#protobuf","headings":["Миграция версии protobuf"],"excerpt":"Миграция версии protobuf ```proto import \"google/protobuf/timestamp.proto\"; import \"google/protobuf/duration.proto\";","content":"Миграция версии protobuf ```proto import \"google/protobuf/timestamp.proto\"; import \"google/protobuf/duration.proto\";"},{"id":"cli/breaking-changes/rules/import-no-delete::protobuf::31","title":"IMPORT_NO_DELETE","section":"Миграция версии protobuf","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#protobuf","headings":["Миграция версии protobuf"],"excerpt":"Миграция версии protobuf message Event { google.protobuf.Timestamp timestamp = 1; int64 timestamp_millis = 2; } ```","content":"Миграция версии protobuf message Event { google.protobuf.Timestamp timestamp = 1; int64 timestamp_millis = 2; } ```"},{"id":"cli/breaking-changes/rules/import-no-delete::top::32","title":"IMPORT_NO_DELETE","section":"Упрощение сложных зависимостей","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Упрощение сложных зависимостей"],"excerpt":"Упрощение сложных зависимостей ```proto import \"complex/config.proto\";","content":"Упрощение сложных зависимостей ```proto import \"complex/config.proto\";"},{"id":"cli/breaking-changes/rules/import-no-delete::top::33","title":"IMPORT_NO_DELETE","section":"Упрощение сложных зависимостей","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Упрощение сложных зависимостей"],"excerpt":"Упрощение сложных зависимостей message Settings { complex.ConfigData config = 1 [deprecated = true]; string config_json = 2; } ```","content":"Упрощение сложных зависимостей message Settings { complex.ConfigData config = 1 [deprecated = true]; string config_json = 2; } ```"},{"id":"cli/breaking-changes/rules/import-no-delete::import-vs::34","title":"IMPORT_NO_DELETE","section":"Удаление import vs использование поля","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#import-vs","headings":["Удаление import vs использование поля"],"excerpt":"Удаление import vs использование поля","content":"Удаление import vs использование поля"},{"id":"cli/breaking-changes/rules/import-no-delete::import::35","title":"IMPORT_NO_DELETE","section":"Аудит import","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#import","headings":["Аудит import"],"excerpt":"Аудит import (Даже если не найдено — не удаляем.)","content":"Аудит 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":"Это правило проверяет, что ни одно сообщение (message) не было удалено из proto‑файлов. Удаление message ломает совместимость по wire‑формату и сгенерированный код: в существующих данных могут присутствовать экземпляры у","content":"Это правило проверяет, что ни одно сообщение (message) не было удалено из proto‑файлов. Удаление message ломает совместимость по wire‑формату и сгенерированный код: в существующих данных могут присутствовать экземпляры удалённого типа, а клиентский код зависит от сгенерированных структур и классов."},{"id":"cli/breaking-changes/rules/message-no-delete::breaking::1","title":"MESSAGE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/message-no-delete::breaking::2","title":"MESSAGE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/message-no-delete::breaking::3","title":"MESSAGE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message User { string name = 1; string email = 2; Address address = 3; }","content":"Плохой (Breaking) message User { string name = 1; string email = 2; Address address = 3; }"},{"id":"cli/breaking-changes/rules/message-no-delete::breaking::4","title":"MESSAGE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message Address { // [!code --] string street = 1; // [!code --] string city = 2; // [!code --] string country = 3; // [!code --] } // [!code --]","content":"Плохой (Breaking) message Address { // [!code --] string street = 1; // [!code --] string city = 2; // [!code --] string country = 3; // [!code --] } // [!code --]"},{"id":"cli/breaking-changes/rules/message-no-delete::breaking::5","title":"MESSAGE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message Order { string id = 1; User user = 2; } ```","content":"Плохой (Breaking) message Order { string id = 1; User user = 2; } ```"},{"id":"cli/breaking-changes/rules/message-no-delete::breaking::6","title":"MESSAGE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/message-no-delete::breaking::7","title":"MESSAGE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/message-no-delete::breaking::8","title":"MESSAGE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message User { string name = 1; string email = 2; Address address = 3; // ERROR: Address больше не существует }","content":"Плохой (Breaking) message User { string name = 1; string email = 2; Address address = 3; // ERROR: Address больше не существует }"},{"id":"cli/breaking-changes/rules/message-no-delete::breaking::9","title":"MESSAGE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) // Address удалён — BREAKING CHANGE!","content":"Плохой (Breaking) // Address удалён — BREAKING CHANGE!"},{"id":"cli/breaking-changes/rules/message-no-delete::breaking::10","title":"MESSAGE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message Order { string id = 1; User user = 2; } ```","content":"Плохой (Breaking) message Order { string id = 1; User user = 2; } ```"},{"id":"cli/breaking-changes/rules/message-no-delete::top::11","title":"MESSAGE_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры **Удаление вложенного сообщения:**","content":"Дополнительные примеры **Удаление вложенного сообщения:**"},{"id":"cli/breaking-changes/rules/message-no-delete::top::12","title":"MESSAGE_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры ```proto // Before message User { string name = 1; Profile profile = 2; message Profile { // [!code --] string bio = 1; // [!code --] string avatar_url = 2; // [!code --] } // [!code --] }","content":"Дополнительные примеры ```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::top::13","title":"MESSAGE_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры // After - BREAKING CHANGE! message User { string name = 1; Profile profile = 2; // ERROR: Profile удалён // Вложенное сообщение Profile удалено } ```","content":"Дополнительные примеры // After - BREAKING CHANGE! message User { string name = 1; Profile profile = 2; // ERROR: Profile удалён // Вложенное сообщение Profile удалено } ```"},{"id":"cli/breaking-changes/rules/message-no-delete::top::14","title":"MESSAGE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо удаления — пометить как deprecated:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо удаления — пометить как deprecated:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/message-no-delete::top::15","title":"MESSAGE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/message-no-delete::top::16","title":"MESSAGE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message User { string name = 1; string email = 2; Address address = 3 [deprecated = true]; // [!code focus] }","content":"Хороший (Безопасный) message User { string name = 1; string email = 2; Address address = 3 [deprecated = true]; // [!code focus] }"},{"id":"cli/breaking-changes/rules/message-no-delete::top::17","title":"MESSAGE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message Address { option deprecated = true; // [!code focus] string street = 1; string city = 2; string country = 3; }","content":"Хороший (Безопасный) message Address { option deprecated = true; // [!code focus] string street = 1; string city = 2; string country = 3; }"},{"id":"cli/breaking-changes/rules/message-no-delete::top::18","title":"MESSAGE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message Order { string id = 1; User user = 2; } ```","content":"Хороший (Безопасный) message Order { string id = 1; User user = 2; } ```"},{"id":"cli/breaking-changes/rules/message-no-delete::top::19","title":"MESSAGE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Или заменить новой версией сообщения:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Или заменить новой версией сообщения:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/message-no-delete::top::20","title":"MESSAGE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/message-no-delete::top::21","title":"MESSAGE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message User { string name = 1; string email = 2; Address address = 3 [deprecated = true]; // [!code focus] // Старое поле AddressV2 address_v2 = 4; // [!code focus] // Новая улучшенная структура }","content":"Хороший (Безопасный) message User { string name = 1; string email = 2; Address address = 3 [deprecated = true]; // [!code focus] // Старое поле AddressV2 address_v2 = 4; // [!code focus] // Новая улучшенная структура }"},{"id":"cli/breaking-changes/rules/message-no-delete::top::22","title":"MESSAGE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message Address { option deprecated = true; // [!code focus] string street = 1; string city = 2; string country = 3; }","content":"Хороший (Безопасный) message Address { option deprecated = true; // [!code focus] string street = 1; string city = 2; string country = 3; }"},{"id":"cli/breaking-changes/rules/message-no-delete::top::23","title":"MESSAGE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) 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 c","content":"Хороший (Безопасный) 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::top::24","title":"MESSAGE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message Order { string id = 1; User user = 2; } ```","content":"Хороший (Безопасный) message Order { string id = 1; User user = 2; } ```"},{"id":"cli/breaking-changes/rules/message-no-delete::top::25","title":"MESSAGE_NO_DELETE","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Влияние"],"excerpt":"Влияние **Wire Format:** Старые данные с удалённым сообщением не десериализуются **Generated Code:** Классы/структуры удаляются — компиляция клиента ломается **Field References:** Поля, использующие удалённый тип, станов","content":"Влияние **Wire Format:** Старые данные с удалённым сообщением не десериализуются **Generated Code:** Классы/структуры удаляются — компиляция клиента ломается **Field References:** Поля, использующие удалённый тип, становятся невалидны **Nested Dependencies:** Все сообщения, ссылающиеся на удалённый тип, ломаются"},{"id":"cli/breaking-changes/rules/message-no-delete::top::26","title":"MESSAGE_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Код клиента ломается:** ```go // Before user := &myapi.User{ Name: \"John Doe\", Email: \"john@example.com\", Address: &myapi.Address{ // ERROR после удаления Street: \"123 Main St\", City: \"New York\", Countr","content":"Реальный пример **Код клиента ломается:** ```go // Before user := &myapi.User{ Name: \"John Doe\", Email: \"john@example.com\", Address: &myapi.Address{ // ERROR после удаления Street: \"123 Main St\", City: \"New York\", Country: \"USA\", }, }"},{"id":"cli/breaking-changes/rules/message-no-delete::top::27","title":"MESSAGE_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример // undefined: myapi.Address ```","content":"Реальный пример // undefined: myapi.Address ```"},{"id":"cli/breaking-changes/rules/message-no-delete::top::28","title":"MESSAGE_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Старые данные становятся нечитаемыми:**","content":"Реальный пример **Старые данные становятся нечитаемыми:**"},{"id":"cli/breaking-changes/rules/message-no-delete::top::29","title":"MESSAGE_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Пометить как deprecated:** **Пометить поля, использующие его:** **Добавить замену при необходимости:** **Удалить в следующей major‑версии после периода миграции**","content":"Стратегия миграции **Пометить как deprecated:** **Пометить поля, использующие его:** **Добавить замену при необходимости:** **Удалить в следующей major‑версии после периода миграции**"},{"id":"cli/breaking-changes/rules/message-no-delete::top::30","title":"MESSAGE_NO_DELETE","section":"Рефакторинг структуры","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Рефакторинг структуры"],"excerpt":"Рефакторинг структуры ```proto message UserInfo { option deprecated = true; string name = 1; string email = 2; }","content":"Рефакторинг структуры ```proto message UserInfo { option deprecated = true; string name = 1; string email = 2; }"},{"id":"cli/breaking-changes/rules/message-no-delete::top::31","title":"MESSAGE_NO_DELETE","section":"Рефакторинг структуры","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Рефакторинг структуры"],"excerpt":"Рефакторинг структуры message UserProfile { string full_name = 1; string email_address = 2; string phone = 3; } ```","content":"Рефакторинг структуры message UserProfile { string full_name = 1; string email_address = 2; string phone = 3; } ```"},{"id":"cli/breaking-changes/rules/message-no-delete::top::32","title":"MESSAGE_NO_DELETE","section":"Удаление «неиспользуемых» сообщений","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Удаление «неиспользуемых» сообщений"],"excerpt":"Удаление «неиспользуемых» сообщений","content":"Удаление «неиспользуемых» сообщений"},{"id":"cli/breaking-changes/rules/message-no-delete::top::33","title":"MESSAGE_NO_DELETE","section":"Миграция версии","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Миграция версии"],"excerpt":"Миграция версии ```proto package myapi.v2;","content":"Миграция версии ```proto package myapi.v2;"},{"id":"cli/breaking-changes/rules/message-no-delete::top::34","title":"MESSAGE_NO_DELETE","section":"Миграция версии","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Миграция версии"],"excerpt":"Миграция версии message User { // Новая структура без устаревших ссылок } ```","content":"Миграция версии message User { // Новая структура без устаревших ссылок } ```"},{"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":"Правило проверяет, что ни одно поле внутри oneof группы не было удалено. Удаление поля из oneof ломает совместимость по wire‑формату и сгенерированный код: в сохранённых данных может присутствовать выбранный вариант, а к","content":"Правило проверяет, что ни одно поле внутри oneof группы не было удалено. Удаление поля из oneof ломает совместимость по wire‑формату и сгенерированный код: в сохранённых данных может присутствовать выбранный вариант, а клиентский код опирается на сгенерированные типы‑обёртки и методы доступа."},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::breaking::1","title":"ONEOF_FIELD_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::breaking::2","title":"ONEOF_FIELD_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::breaking::3","title":"ONEOF_FIELD_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message LoginRequest { string username = 1; oneof credentials { string password = 2; string api_key = 3; string oauth_token = 4; string certificate = 5; } }","content":"Плохой (Breaking) 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::breaking::4","title":"ONEOF_FIELD_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message SearchQuery { oneof filter { string text = 1; int32 user_id = 2; string category = 3; DateRange date_range = 4; } } ```","content":"Плохой (Breaking) 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::breaking::5","title":"ONEOF_FIELD_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::breaking::6","title":"ONEOF_FIELD_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::breaking::7","title":"ONEOF_FIELD_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message LoginRequest { string username = 1; oneof credentials { string password = 2; string api_key = 3; // string oauth_token = 4; // [!code --] Удалено поле oneof — BREAKING! // string certificate = 5","content":"Плохой (Breaking) message LoginRequest { string username = 1; oneof credentials { string password = 2; string api_key = 3; // string oauth_token = 4; // [!code --] Удалено поле oneof — BREAKING! // string certificate = 5; // [!code --] Удалено поле oneof — BREAKING! } }"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::breaking::8","title":"ONEOF_FIELD_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message SearchQuery { oneof filter { string text = 1; int32 user_id = 2; // string category = 3; // [!code --] Удалено поле oneof — BREAKING! // DateRange date_range = 4; // [!code --] Удалено поле oneo","content":"Плохой (Breaking) message SearchQuery { oneof filter { string text = 1; int32 user_id = 2; // string category = 3; // [!code --] Удалено поле oneof — BREAKING! // DateRange date_range = 4; // [!code --] Удалено поле oneof — BREAKING! } } ```"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::9","title":"ONEOF_FIELD_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры **Удаление вложенных oneof полей:** ```proto // Before message PaymentRequest { string order_id = 1; oneof payment_method { CreditCardPayment credit_card = 2; BankTransferPayment bank_transfer = 3;","content":"Дополнительные примеры **Удаление вложенных oneof полей:** ```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::top::10","title":"ONEOF_FIELD_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры // After - BREAKING CHANGES! message PaymentRequest { string order_id = 1; oneof payment_method { CreditCardPayment credit_card = 2; BankTransferPayment bank_transfer = 3; // CryptoPayment crypto =","content":"Дополнительные примеры // 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::top::11","title":"ONEOF_FIELD_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо удаления — пометить поля deprecated:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо удаления — пометить поля deprecated:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::12","title":"ONEOF_FIELD_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::13","title":"ONEOF_FIELD_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) 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 [deprecate","content":"Хороший (Безопасный) 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::top::14","title":"ONEOF_FIELD_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) 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":"Хороший (Безопасный) 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::top::15","title":"ONEOF_FIELD_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Или добавить новые поля, оставив старые:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Или добавить новые поля, оставив старые:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::16","title":"ONEOF_FIELD_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::17","title":"ONEOF_FIELD_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message LoginRequest { string username = 1; oneof credentials { string password = 2; string api_key = 3; string oauth_token = 4 [deprecated = true]; // [!code focus] // Старое поле string certificate","content":"Хороший (Безопасный) 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] OAuthCredentials oauth_v2 = 6; // [!code focus] // Новый структурированный вариант CertificateCredentials cert_v2 = 7; // [!code focus] } } ```"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::18","title":"ONEOF_FIELD_NO_DELETE","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Влияние"],"excerpt":"Влияние **Wire Format:** Данные, содержащие удалённый вариант, не десериализуются корректно **Generated Code:** Удаляются типы‑обёртки и accessor методы — компиляция клиентов ломается **Type Safety:** Логика switch по ти","content":"Влияние **Wire Format:** Данные, содержащие удалённый вариант, не десериализуются корректно **Generated Code:** Удаляются типы‑обёртки и accessor методы — компиляция клиентов ломается **Type Safety:** Логика switch по типам oneof разваливается **Business Logic:** Код, ожидающий конкретный вариант, перестаёт работать"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::19","title":"ONEOF_FIELD_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Код клиента ломается:** ```go // Before loginReq := &myapi.LoginRequest{ Username: \"user123\", }","content":"Реальный пример **Код клиента ломается:** ```go // Before loginReq := &myapi.LoginRequest{ Username: \"user123\", }"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::20","title":"ONEOF_FIELD_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример loginReq.Credentials = &myapi.LoginRequest_OauthToken{ OauthToken: \"token123\", // ERROR после удаления поля }","content":"Реальный пример loginReq.Credentials = &myapi.LoginRequest_OauthToken{ OauthToken: \"token123\", // ERROR после удаления поля }"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::21","title":"ONEOF_FIELD_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример switch cred := loginReq.Credentials.(type) { case *myapi.LoginRequest_Password: return authenticatePassword(cred.Password) case *myapi.LoginRequest_OauthToken: // ERROR: тип удалён return authenticateOAut","content":"Реальный пример switch cred := loginReq.Credentials.(type) { case *myapi.LoginRequest_Password: return authenticatePassword(cred.Password) case *myapi.LoginRequest_OauthToken: // ERROR: тип удалён return authenticateOAuth(cred.OauthToken) case *myapi.LoginRequest_Certificate: // ERROR: тип удалён return authenticateCert(cred.Certificate) default: return errors.New(\"unsupported credential type\") } // undefined: myapi.LoginRequest_OauthToken // undefined: myapi.LoginRequest_Certificate ```"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::22","title":"ONEOF_FIELD_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Серверная логика ломается:**","content":"Реальный пример **Серверная логика ломается:**"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::23","title":"ONEOF_FIELD_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Старые данные становятся нечитаемыми:**","content":"Реальный пример **Старые данные становятся нечитаемыми:**"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::24","title":"ONEOF_FIELD_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Депрецируйте сначала:** **Добавьте новые структурированные поля:** **Сервер: поддерживайте оба варианта:** **Мигрируйте клиентов на новое поле:** **Зарезервируйте номера удалённых полей в следующей m","content":"Стратегия миграции **Депрецируйте сначала:** **Добавьте новые структурированные поля:** **Сервер: поддерживайте оба варианта:** **Мигрируйте клиентов на новое поле:** **Зарезервируйте номера удалённых полей в следующей major‑версии:**"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::25","title":"ONEOF_FIELD_NO_DELETE","section":"Удаление неподдерживаемых методов аутентификации","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Удаление неподдерживаемых методов аутентификации"],"excerpt":"Удаление неподдерживаемых методов аутентификации","content":"Удаление неподдерживаемых методов аутентификации"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::26","title":"ONEOF_FIELD_NO_DELETE","section":"Изменения бизнес‑логики платежей","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Изменения бизнес‑логики платежей"],"excerpt":"Изменения бизнес‑логики платежей","content":"Изменения бизнес‑логики платежей"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::oneof-field-deletion-vs::27","title":"ONEOF_FIELD_NO_DELETE","section":"OneOf Field Deletion vs обычное удаление","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#oneof-field-deletion-vs","headings":["OneOf Field Deletion vs обычное удаление"],"excerpt":"OneOf Field Deletion vs обычное удаление","content":"OneOf Field Deletion vs обычное удаление"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::28","title":"ONEOF_FIELD_NO_DELETE","section":"Отличия от удаления обычного поля","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Отличия от удаления обычного поля"],"excerpt":"Отличия от удаления обычного поля ```proto message User { string name = 1; // string email = 2; // BREAKING: обычное поле }","content":"Отличия от удаления обычного поля ```proto message User { string name = 1; // string email = 2; // BREAKING: обычное поле }"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::29","title":"ONEOF_FIELD_NO_DELETE","section":"Отличия от удаления обычного поля","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Отличия от удаления обычного поля"],"excerpt":"Отличия от удаления обычного поля message User { oneof contact { string email = 1; // string phone = 2; // BREAKING: поле в oneof } } ```","content":"Отличия от удаления обычного поля message User { oneof contact { string email = 1; // string phone = 2; // BREAKING: поле в oneof } } ```"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::30","title":"ONEOF_FIELD_NO_DELETE","section":"Влияние на сгенерированный код","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Влияние на сгенерированный код"],"excerpt":"Влияние на сгенерированный код ```go // Обычное поле: удаляется простой геттер // user.GetEmail()","content":"Влияние на сгенерированный код ```go // Обычное поле: удаляется простой геттер // user.GetEmail()"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::31","title":"ONEOF_FIELD_NO_DELETE","section":"Влияние на сгенерированный код","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Влияние на сгенерированный код"],"excerpt":"Влияние на сгенерированный код // Поле в oneof: пропадает тип-обёртка, кейсы switch ломаются // *LoginRequest_OauthToken ```","content":"Влияние на сгенерированный код // Поле в oneof: пропадает тип-обёртка, кейсы switch ломаются // *LoginRequest_OauthToken ```"},{"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":"Это правило проверяет, что тип поля внутри oneof НЕ меняется. Смена типа любого варианта oneof — несовместимое (breaking) изменение: существующие данные сериализованы с прежним типом, а клиентский код ожидает конкретные ","content":"Это правило проверяет, что тип поля внутри oneof НЕ меняется. Смена типа любого варианта oneof — несовместимое (breaking) изменение: существующие данные сериализованы с прежним типом, а клиентский код ожидает конкретные типы-обёртки и методы доступа, сгенерированные для каждого варианта."},{"id":"cli/breaking-changes/rules/oneof-field-same-type::breaking::1","title":"ONEOF_FIELD_SAME_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::breaking::2","title":"ONEOF_FIELD_SAME_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::breaking::3","title":"ONEOF_FIELD_SAME_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message SearchRequest { string query = 1; oneof filter { string category = 2; int32 user_id = 3; bool is_premium = 4; DateRange date_range = 5; } }","content":"Плохой (Breaking) 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::breaking::4","title":"ONEOF_FIELD_SAME_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message NotificationSettings { oneof delivery { string email = 1; int64 phone_number = 2; WebhookConfig webhook = 3; } } ```","content":"Плохой (Breaking) message NotificationSettings { oneof delivery { string email = 1; int64 phone_number = 2; WebhookConfig webhook = 3; } } ```"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::breaking::5","title":"ONEOF_FIELD_SAME_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::breaking::6","title":"ONEOF_FIELD_SAME_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::breaking::7","title":"ONEOF_FIELD_SAME_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message SearchRequest { string query = 1; oneof filter { int32 category = 2; // [!code --] Было string -> стало int32 (BREAKING) string user_id = 3; // [!code --] Было int32 -> стало string (BREAKING) s","content":"Плохой (Breaking) message SearchRequest { string query = 1; oneof filter { int32 category = 2; // [!code --] Было string -> стало int32 (BREAKING) string user_id = 3; // [!code --] Было int32 -> стало string (BREAKING) string is_premium = 4; // [!code --] Было bool -> стало string (BREAKING) string date_range = 5; // [!code --] Было DateRange -> стало string (BREAKING) } }"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::breaking::8","title":"ONEOF_FIELD_SAME_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message NotificationSettings { oneof delivery { EmailConfig email = 1; // [!code --] Было string -> стало EmailConfig (BREAKING) string phone_number = 2; // [!code --] Было int64 -> стало string (BREAKI","content":"Плохой (Breaking) message NotificationSettings { oneof delivery { EmailConfig email = 1; // [!code --] Было string -> стало EmailConfig (BREAKING) string phone_number = 2; // [!code --] Было int64 -> стало string (BREAKING) string webhook = 3; // [!code --] Было WebhookConfig -> стало string (BREAKING) } } ```"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::9","title":"ONEOF_FIELD_SAME_TYPE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры **Комплексные изменения типов:** ```proto // Before message PaymentRequest { oneof payment_info { CreditCardInfo credit_card = 1; BankAccountInfo bank_account = 2; string paypal_email = 3; CryptoWa","content":"Дополнительные примеры **Комплексные изменения типов:** ```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::top::10","title":"ONEOF_FIELD_SAME_TYPE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры // After - ВСЁ BREAKING message PaymentRequest { oneof payment_info { string credit_card = 1; // CreditCardInfo -> string PayPalInfo bank_account = 2; // BankAccountInfo -> PayPalInfo PayPalInfo pa","content":"Дополнительные примеры // After - ВСЁ BREAKING message PaymentRequest { oneof payment_info { string credit_card = 1; // CreditCardInfo -> string PayPalInfo bank_account = 2; // BankAccountInfo -> PayPalInfo PayPalInfo paypal_email = 3; // string -> PayPalInfo string crypto = 4; // CryptoWalletInfo -> string } } ```"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::11","title":"ONEOF_FIELD_SAME_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо смены типа — добавьте новое поле в тот же oneof:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо смены типа — добавьте новое поле в тот же oneof:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::12","title":"ONEOF_FIELD_SAME_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::13","title":"ONEOF_FIELD_SAME_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message SearchRequest { string query = 1; oneof filter { string category = 2 [deprecated = true]; // Старый тип int32 user_id = 3 [deprecated = true]; bool is_premium = 4 [deprecated = true]; DateRan","content":"Хороший (Безопасный) message SearchRequest { string query = 1; oneof filter { string category = 2 [deprecated = true]; // Старый тип int32 user_id = 3 [deprecated = true]; bool is_premium = 4 [deprecated = true]; DateRange date_range = 5 [deprecated = true]; int32 category_id = 6; // Новая версия string user_identifier = 7; string premium_status = 8; string date_filter = 9; } } ```"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::14","title":"ONEOF_FIELD_SAME_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Или создайте новый oneof:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Или создайте новый oneof:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::15","title":"ONEOF_FIELD_SAME_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::16","title":"ONEOF_FIELD_SAME_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message SearchRequest { string query = 1; oneof filter { option deprecated = true; string category = 2 [deprecated = true]; int32 user_id = 3 [deprecated = true]; bool is_premium = 4 [deprecated = tr","content":"Хороший (Безопасный) message SearchRequest { string query = 1; oneof filter { option deprecated = true; string category = 2 [deprecated = true]; int32 user_id = 3 [deprecated = true]; bool is_premium = 4 [deprecated = true]; DateRange date_range = 5 [deprecated = true]; } oneof filter_v2 { int32 category_id = 6; string user_identifier = 7; PremiumFilter premium_filter = 8; TimeFilter time_filter = 9; } } ```"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::17","title":"ONEOF_FIELD_SAME_TYPE","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Влияние"],"excerpt":"Влияние **Wire Format:** Старые бинарные данные не читаются корректно **Generated Code:** Меняются типы-обёртки, код клиента не компилируется **Type Safety:** switch по варианту oneof ломается **Runtime Errors:** Ошибки ","content":"Влияние **Wire Format:** Старые бинарные данные не читаются корректно **Generated Code:** Меняются типы-обёртки, код клиента не компилируется **Type Safety:** switch по варианту oneof ломается **Runtime Errors:** Ошибки десериализации и логики при несовпадении типов"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::18","title":"ONEOF_FIELD_SAME_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Реальный пример"],"excerpt":"Реальный пример **Ломается клиентский код:** ```go // Before searchReq := &myapi.SearchRequest{ Query: \"golang jobs\", }","content":"Реальный пример **Ломается клиентский код:** ```go // Before searchReq := &myapi.SearchRequest{ Query: \"golang jobs\", }"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::19","title":"ONEOF_FIELD_SAME_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Реальный пример"],"excerpt":"Реальный пример // Устанавливаем вариант oneof searchReq.Filter = &myapi.SearchRequest_Category{ Category: \"engineering\", }","content":"Реальный пример // Устанавливаем вариант oneof searchReq.Filter = &myapi.SearchRequest_Category{ Category: \"engineering\", }"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::20","title":"ONEOF_FIELD_SAME_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Реальный пример"],"excerpt":"Реальный пример // Обработка вариантов switch filter := searchReq.Filter.(type) { case *myapi.SearchRequest_Category: return searchByCategory(filter.Category) case *myapi.SearchRequest_UserId: return searchByUserId(filte","content":"Реальный пример // Обработка вариантов switch filter := searchReq.Filter.(type) { case *myapi.SearchRequest_Category: return searchByCategory(filter.Category) case *myapi.SearchRequest_UserId: return searchByUserId(filter.UserId) default: return errors.New(\"unsupported filter\") }"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::21","title":"ONEOF_FIELD_SAME_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Реальный пример"],"excerpt":"Реальный пример // After — тип Category стал int32 searchReq.Filter = &myapi.SearchRequest_Category{ Category: \"engineering\", // ERROR }","content":"Реальный пример // After — тип Category стал int32 searchReq.Filter = &myapi.SearchRequest_Category{ Category: \"engineering\", // ERROR }"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::22","title":"ONEOF_FIELD_SAME_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Реальный пример"],"excerpt":"Реальный пример switch filter := searchReq.Filter.(type) { case *myapi.SearchRequest_Category: return searchByCategory(filter.Category) // ERROR case *myapi.SearchRequest_UserId: return searchByUserId(filter.UserId) // E","content":"Реальный пример switch filter := searchReq.Filter.(type) { case *myapi.SearchRequest_Category: return searchByCategory(filter.Category) // ERROR case *myapi.SearchRequest_UserId: return searchByUserId(filter.UserId) // ERROR: UserId теперь string } ```"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::23","title":"ONEOF_FIELD_SAME_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Реальный пример"],"excerpt":"Реальный пример **Ломается серверная логика:** ```go // Before func handleSearchFilter(req *SearchRequest) (*SearchResult, error) { switch filter := req.Filter.(type) { case *SearchRequest_Category: return searchDatabase","content":"Реальный пример **Ломается серверная логика:** ```go // Before func handleSearchFilter(req *SearchRequest) (*SearchResult, error) { switch filter := req.Filter.(type) { case *SearchRequest_Category: return searchDatabase(\"category\", filter.Category), nil case *SearchRequest_UserId: return searchDatabase(\"user_id\", strconv.Itoa(int(filter.UserId))), nil default: return nil, errors.New(\"no filter specified\") } }"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::24","title":"ONEOF_FIELD_SAME_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Реальный пример"],"excerpt":"Реальный пример // After — несовпадения типов func handleSearchFilter(req *SearchRequest) (*SearchResult, error) { switch filter := req.Filter.(type) { case *SearchRequest_Category: // filter.Category теперь int32, а код","content":"Реальный пример // After — несовпадения типов func handleSearchFilter(req *SearchRequest) (*SearchResult, error) { switch filter := req.Filter.(type) { case *SearchRequest_Category: // filter.Category теперь int32, а код ожидал string return searchDatabase(\"category\", filter.Category), nil // ERROR case *SearchRequest_UserId: userIdStr := filter.UserId // string вместо int32 userId, _ := strconv.Atoi(userIdStr) return searchDatabase(\"user_id\", strconv.Itoa(userId)), nil } } ```"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::25","title":"ONEOF_FIELD_SAME_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Реальный пример"],"excerpt":"Реальный пример **Порча данных:**","content":"Реальный пример **Порча данных:**"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::26","title":"ONEOF_FIELD_SAME_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции Добавьте новое поле: Сервер поддерживает оба: Клиенты переходят на category_id. Скрипты миграции преобразуют старые данные. В следующей major‑версии:","content":"Стратегия миграции Добавьте новое поле: Сервер поддерживает оба: Клиенты переходят на category_id. Скрипты миграции преобразуют старые данные. В следующей major‑версии:"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::27","title":"ONEOF_FIELD_SAME_TYPE","section":"Переход к структурированным типам","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Переход к структурированным типам"],"excerpt":"Переход к структурированным типам","content":"Переход к структурированным типам"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::28","title":"ONEOF_FIELD_SAME_TYPE","section":"Матрица совместимости","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Матрица совместимости"],"excerpt":"Матрица совместимости From Type To Type Результат ----------- --------- ----------- string int32/int64 ❌ BREAKING int32 string ❌ BREAKING bool string ❌ BREAKING message string ❌ BREAKING string message ❌ BREAKING enum in","content":"Матрица совместимости From Type To Type Результат ----------- --------- ----------- 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::top::29","title":"ONEOF_FIELD_SAME_TYPE","section":"Влияние на сгенерированный код","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Влияние на сгенерированный код"],"excerpt":"Влияние на сгенерированный код","content":"Влияние на сгенерированный код"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::30","title":"ONEOF_FIELD_SAME_TYPE","section":"Валидация","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Валидация"],"excerpt":"Валидация **После (сломано):**","content":"Валидация **После (сломано):**"},{"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":"Это правило проверяет, что ни один oneof блок не был удалён из сообщений. Удаление oneof ломает совместимость по wire‑формату и сгенерированный код: существующие данные могут содержать ранее выбранный вариант, а клиентск","content":"Это правило проверяет, что ни один oneof блок не был удалён из сообщений. Удаление oneof ломает совместимость по wire‑формату и сгенерированный код: существующие данные могут содержать ранее выбранный вариант, а клиентский код зависит от типов-обёрток и методов доступа, генерируемых для oneof."},{"id":"cli/breaking-changes/rules/oneof-no-delete::breaking::1","title":"ONEOF_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-no-delete::breaking::2","title":"ONEOF_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/oneof-no-delete::breaking::3","title":"ONEOF_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message LoginRequest { string username = 1; oneof credentials { string password = 2; string api_key = 3; string oauth_token = 4; } }","content":"Плохой (Breaking) 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::breaking::4","title":"ONEOF_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message PaymentMethod { // [!code --] oneof method { // [!code --] CreditCard credit_card = 1; // [!code --] BankAccount bank_account = 2; // [!code --] PayPal paypal = 3; // [!code --] } // [!code --] ","content":"Плохой (Breaking) 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::breaking::5","title":"ONEOF_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message Order { string id = 1; PaymentMethod payment = 2; } ```","content":"Плохой (Breaking) message Order { string id = 1; PaymentMethod payment = 2; } ```"},{"id":"cli/breaking-changes/rules/oneof-no-delete::breaking::6","title":"ONEOF_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-no-delete::breaking::7","title":"ONEOF_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/oneof-no-delete::breaking::8","title":"ONEOF_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message LoginRequest { string username = 1; // credentials oneof удалён — BREAKING CHANGE! string password = 2; // Теперь обычные поля string api_key = 3; // Потеряна взаимная исключаемость string oauth","content":"Плохой (Breaking) message LoginRequest { string username = 1; // credentials oneof удалён — BREAKING CHANGE! string password = 2; // Теперь обычные поля string api_key = 3; // Потеряна взаимная исключаемость string oauth_token = 4; }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::breaking::9","title":"ONEOF_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message PaymentMethod { // method oneof удалён — BREAKING CHANGE! CreditCard credit_card = 1; // Теперь можно установить все поля одновременно BankAccount bank_account = 2; PayPal paypal = 3; }","content":"Плохой (Breaking) message PaymentMethod { // method oneof удалён — BREAKING CHANGE! CreditCard credit_card = 1; // Теперь можно установить все поля одновременно BankAccount bank_account = 2; PayPal paypal = 3; }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::breaking::10","title":"ONEOF_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message Order { string id = 1; PaymentMethod payment = 2; } ```","content":"Плохой (Breaking) message Order { string id = 1; PaymentMethod payment = 2; } ```"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::11","title":"ONEOF_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры **Удаление вложенного oneof:** ```proto // Before message UserProfile { string name = 1; message ContactInfo { oneof contact_method { // [!code --] string email = 1; // [!code --] string phone = 2;","content":"Дополнительные примеры **Удаление вложенного oneof:** ```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::top::12","title":"ONEOF_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры // After - BREAKING CHANGE! message UserProfile { string name = 1; message ContactInfo { // contact_method oneof удалён string email = 1; // Больше не эксклюзивно string phone = 2; // Можно задать ","content":"Дополнительные примеры // After - BREAKING CHANGE! message UserProfile { string name = 1; message ContactInfo { // contact_method oneof удалён string email = 1; // Больше не эксклюзивно string phone = 2; // Можно задать всё сразу string slack_id = 3; } ContactInfo contact = 2; } ```"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::13","title":"ONEOF_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо удаления — депрецируйте oneof:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо удаления — депрецируйте oneof:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::14","title":"ONEOF_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::15","title":"ONEOF_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message LoginRequest { string username = 1; oneof credentials { option deprecated = true; // [!code focus] string password = 2 [deprecated = true]; // [!code focus] string api_key = 3 [deprecated = t","content":"Хороший (Безопасный) 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::top::16","title":"ONEOF_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message PaymentMethod { oneof method { option deprecated = true; // [!code focus] CreditCard credit_card = 1 [deprecated = true]; // [!code focus] BankAccount bank_account = 2 [deprecated = true]; //","content":"Хороший (Безопасный) 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::top::17","title":"ONEOF_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Или заменить новой структурой:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Или заменить новой структурой:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::18","title":"ONEOF_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::19","title":"ONEOF_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message LoginRequest { string username = 1; oneof credentials { option deprecated = true; // [!code focus] // Старый oneof string password = 2 [deprecated = true]; // [!code focus] string api_key = 3","content":"Хороший (Безопасный) message LoginRequest { string username = 1; oneof credentials { option deprecated = true; // [!code focus] // Старый 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] // Новый дизайн 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::top::20","title":"ONEOF_NO_DELETE","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Влияние"],"excerpt":"Влияние **Wire Format:** Теряются семантика взаимной исключаемости — больше одного поля может быть установлено **Generated Code:** Удаляются типы-обёртки и accessor методы — код клиента не компилируется **Business Logic:","content":"Влияние **Wire Format:** Теряются семантика взаимной исключаемости — больше одного поля может быть установлено **Generated Code:** Удаляются типы-обёртки и accessor методы — код клиента не компилируется **Business Logic:** Нарушаются инварианты «только один из» **Validation:** Логика проверок должна быть переписана вручную"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::21","title":"ONEOF_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Код клиента ломается:** ```go // Before - oneOf даёт взаимную исключаемость loginReq := &myapi.LoginRequest{ Username: \"user123\", }","content":"Реальный пример **Код клиента ломается:** ```go // Before - oneOf даёт взаимную исключаемость loginReq := &myapi.LoginRequest{ Username: \"user123\", }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::22","title":"ONEOF_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример loginReq.Credentials = &myapi.LoginRequest_Password{ Password: \"secret123\", }","content":"Реальный пример loginReq.Credentials = &myapi.LoginRequest_Password{ Password: \"secret123\", }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::23","title":"ONEOF_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример switch cred := loginReq.Credentials.(type) { case *myapi.LoginRequest_Password: // ERROR после удаления return authenticatePassword(cred.Password) case *myapi.LoginRequest_ApiKey: // ERROR после удаления ","content":"Реальный пример switch cred := loginReq.Credentials.(type) { case *myapi.LoginRequest_Password: // ERROR после удаления return authenticatePassword(cred.Password) case *myapi.LoginRequest_ApiKey: // ERROR после удаления return authenticateApiKey(cred.ApiKey) default: return errors.New(\"no credentials provided\") }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::24","title":"ONEOF_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример // Compilation errors: // undefined: myapi.LoginRequest_Password // undefined field: loginReq.Credentials ```","content":"Реальный пример // Compilation errors: // undefined: myapi.LoginRequest_Password // undefined field: loginReq.Credentials ```"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::25","title":"ONEOF_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Валидация на сервере ломается:** ```go // Before func validateLoginRequest(req *LoginRequest) error { if req.Credentials == nil { return errors.New(\"credentials required\") } switch req.Credentials.(type","content":"Реальный пример **Валидация на сервере ломается:** ```go // Before func validateLoginRequest(req *LoginRequest) error { if req.Credentials == nil { return errors.New(\"credentials required\") } 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::top::26","title":"ONEOF_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример // After func validateLoginRequest(req *LoginRequest) error { credCount := 0 if req.Password != \"\" { credCount++ } if req.ApiKey != \"\" { credCount++ } if req.OauthToken != \"\" { credCount++ }","content":"Реальный пример // After func validateLoginRequest(req *LoginRequest) error { credCount := 0 if req.Password != \"\" { credCount++ } if req.ApiKey != \"\" { credCount++ } if req.OauthToken != \"\" { credCount++ }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::27","title":"ONEOF_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример if credCount == 0 { return errors.New(\"no credentials provided\") } if credCount > 1 { return errors.New(\"multiple credentials provided\") }","content":"Реальный пример if credCount == 0 { return errors.New(\"no credentials provided\") } if credCount > 1 { return errors.New(\"multiple credentials provided\") }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::28","title":"ONEOF_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример if req.Password != \"\" { return validatePassword(req.Password) } // Дополнительные проверки вручную... return nil } ```","content":"Реальный пример if req.Password != \"\" { return validatePassword(req.Password) } // Дополнительные проверки вручную... return nil } ```"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::29","title":"ONEOF_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Проблемы бизнес‑логики:** ```go // Before payment := &PaymentMethod{ Method: &PaymentMethod_CreditCard{ CreditCard: &CreditCard{Number: \"1234\"}, }, }","content":"Реальный пример **Проблемы бизнес‑логики:** ```go // Before payment := &PaymentMethod{ Method: &PaymentMethod_CreditCard{ CreditCard: &CreditCard{Number: \"1234\"}, }, }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::30","title":"ONEOF_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример // After — можно задать несколько способов сразу payment := &PaymentMethod{ CreditCard: &CreditCard{Number: \"1234\"}, BankAccount: &BankAccount{Number: \"5678\"}, // Ломает бизнес-логику } ```","content":"Реальный пример // After — можно задать несколько способов сразу payment := &PaymentMethod{ CreditCard: &CreditCard{Number: \"1234\"}, BankAccount: &BankAccount{Number: \"5678\"}, // Ломает бизнес-логику } ```"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::31","title":"ONEOF_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Депрецируйте старый oneof и его поля:**","content":"Стратегия миграции **Депрецируйте старый oneof и его поля:**"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::32","title":"ONEOF_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Создайте новый блок при необходимости:**","content":"Стратегия миграции **Создайте новый блок при необходимости:**"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::33","title":"ONEOF_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Сервер: поддерживайте оба до миграции:**","content":"Стратегия миграции **Сервер: поддерживайте оба до миграции:**"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::34","title":"ONEOF_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Клиенты: переходите на новый oneof:**","content":"Стратегия миграции **Клиенты: переходите на новый oneof:**"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::35","title":"ONEOF_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Удалите старый oneof** в следующей major‑версии.","content":"Стратегия миграции **Удалите старый oneof** в следующей major‑версии."},{"id":"cli/breaking-changes/rules/oneof-no-delete::oneof::36","title":"ONEOF_NO_DELETE","section":"Замена oneof обычными полями","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#oneof","headings":["Замена oneof обычными полями"],"excerpt":"Замена oneof обычными полями ```proto message SearchRequest { // НЕЛЬЗЯ просто убрать oneof — ломает семантику string text_query = 1; // BREAKING int32 user_id = 2; // BREAKING string category = 3; // BREAKING }","content":"Замена oneof обычными полями ```proto message SearchRequest { // НЕЛЬЗЯ просто убрать oneof — ломает семантику string text_query = 1; // BREAKING int32 user_id = 2; // BREAKING string category = 3; // BREAKING }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::oneof::37","title":"ONEOF_NO_DELETE","section":"Замена oneof обычными полями","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#oneof","headings":["Замена oneof обычными полями"],"excerpt":"Замена oneof обычными полями message SearchRequest { oneof query { option deprecated = true; string text_query = 1 [deprecated = true]; int32 user_id = 2 [deprecated = true]; string category = 3 [deprecated = true]; } st","content":"Замена oneof обычными полями message SearchRequest { oneof query { option deprecated = true; string text_query = 1 [deprecated = true]; int32 user_id = 2 [deprecated = true]; string category = 3 [deprecated = true]; } string search_text = 4; repeated string filters = 5; } ```"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::38","title":"ONEOF_NO_DELETE","section":"Упрощение структуры сообщения","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Упрощение структуры сообщения"],"excerpt":"Упрощение структуры сообщения ```proto message NotificationSettings { string email = 1; // BREAKING: был в oneof string phone = 2; // BREAKING string webhook_url = 3; // BREAKING }","content":"Упрощение структуры сообщения ```proto message NotificationSettings { string email = 1; // BREAKING: был в oneof string phone = 2; // BREAKING string webhook_url = 3; // BREAKING }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::39","title":"ONEOF_NO_DELETE","section":"Упрощение структуры сообщения","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Упрощение структуры сообщения"],"excerpt":"Упрощение структуры сообщения message NotificationSettings { oneof delivery_method { EmailNotification email = 1; SmsNotification phone = 2; WebhookNotification webhook = 3; } } ```","content":"Упрощение структуры сообщения message NotificationSettings { oneof delivery_method { EmailNotification email = 1; SmsNotification phone = 2; WebhookNotification webhook = 3; } } ```"},{"id":"cli/breaking-changes/rules/oneof-no-delete::proto2-proto3::40","title":"ONEOF_NO_DELETE","section":"Миграция с proto2 на proto3","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#proto2-proto3","headings":["Миграция с proto2 на proto3"],"excerpt":"Миграция с proto2 на proto3 ```proto // proto2 message Request { optional string name = 1; oneof data { string text = 2; int32 number = 3; } }","content":"Миграция с proto2 на proto3 ```proto // proto2 message Request { optional string name = 1; oneof data { string text = 2; int32 number = 3; } }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::proto2-proto3::41","title":"ONEOF_NO_DELETE","section":"Миграция с proto2 на proto3","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#proto2-proto3","headings":["Миграция с proto2 на proto3"],"excerpt":"Миграция с proto2 на proto3 // proto3 — сохраняем oneof message Request { string name = 1; oneof data { string text = 2; int32 number = 3; } } ```","content":"Миграция с proto2 на proto3 // proto3 — сохраняем oneof message Request { string name = 1; oneof data { string text = 2; int32 number = 3; } } ```"},{"id":"cli/breaking-changes/rules/oneof-no-delete::oneof::42","title":"ONEOF_NO_DELETE","section":"Что даёт oneof","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#oneof","headings":["Что даёт oneof"],"excerpt":"Что даёт oneof Взаимная исключаемость Типобезопасность в коде Ясность намерения API («выбери один») Эффективная сериализация — кодируется только выбранный вариант","content":"Что даёт oneof Взаимная исключаемость Типобезопасность в коде Ясность намерения API («выбери один») Эффективная сериализация — кодируется только выбранный вариант"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::43","title":"ONEOF_NO_DELETE","section":"Что теряется при удалении","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Что теряется при удалении"],"excerpt":"Что теряется при удалении Инвариант «только один» Генерируемые wrapper-типы и методы Автоматическая валидация выбора Понятность контракта API","content":"Что теряется при удалении Инвариант «только один» Генерируемые wrapper-типы и методы Автоматическая валидация выбора Понятность контракта API"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::44","title":"ONEOF_NO_DELETE","section":"Влияние на код генерации","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Влияние на код генерации"],"excerpt":"Влияние на код генерации ```go // С oneof type LoginRequest struct { Username string Credentials isLoginRequest_Credentials }","content":"Влияние на код генерации ```go // С oneof type LoginRequest struct { Username string Credentials isLoginRequest_Credentials }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::45","title":"ONEOF_NO_DELETE","section":"Влияние на код генерации","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Влияние на код генерации"],"excerpt":"Влияние на код генерации // Без oneof type LoginRequest struct { Username string Password string ApiKey string OauthToken string // Возможны многозначные конфликтующие состояния } ```","content":"Влияние на код генерации // Без oneof type LoginRequest struct { Username string Password string ApiKey string 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":"Правило проверяет, что ни один RPC‑метод не был удалён из service. Удаление RPC ломает сгенерированный код и клиентские приложения, которые этот метод вызывают.","content":"Правило проверяет, что ни один RPC‑метод не был удалён из service. Удаление RPC ломает сгенерированный код и клиентские приложения, которые этот метод вызывают."},{"id":"cli/breaking-changes/rules/rpc-no-delete::breaking::1","title":"RPC_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/rpc-no-delete::breaking::2","title":"RPC_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/rpc-no-delete::breaking::3","title":"RPC_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); rpc DeleteUser(DeleteUserRequest) returns (DeleteUserResponse","content":"Плохой (Breaking) 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::breaking::4","title":"RPC_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/rpc-no-delete::breaking::5","title":"RPC_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/rpc-no-delete::breaking::6","title":"RPC_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); // DeleteUser RPC удалён — BREAKING CHANGE! } ```","content":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); // DeleteUser RPC удалён — BREAKING CHANGE! } ```"},{"id":"cli/breaking-changes/rules/rpc-no-delete::top::7","title":"RPC_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо удаления — пометить RPC deprecated:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо удаления — пометить RPC deprecated:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/rpc-no-delete::top::8","title":"RPC_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/rpc-no-delete::top::9","title":"RPC_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); rpc DeleteUser(DeleteUserRequest) returns (DeleteUserRespo","content":"Хороший (Безопасный) 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::top::10","title":"RPC_NO_DELETE","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete","headings":["Влияние"],"excerpt":"Влияние **Generated Code:** Stub/метод исчезает — клиенты не компилируются **Client Applications:** Существующие вызовы метода падают при сборке **Runtime:** gRPC клиенты теряют определение метода","content":"Влияние **Generated Code:** Stub/метод исчезает — клиенты не компилируются **Client Applications:** Существующие вызовы метода падают при сборке **Runtime:** gRPC клиенты теряют определение метода"},{"id":"cli/breaking-changes/rules/rpc-no-delete::top::11","title":"RPC_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Сначала деприкация:**","content":"Стратегия миграции **Сначала деприкация:**"},{"id":"cli/breaking-changes/rules/rpc-no-delete::top::12","title":"RPC_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Имплементация может возвращать ошибку**, указывая что метод устарел (например, INTERNAL / UNIMPLEMENTED)","content":"Стратегия миграции **Имплементация может возвращать ошибку**, указывая что метод устарел (например, INTERNAL / UNIMPLEMENTED)"},{"id":"cli/breaking-changes/rules/rpc-no-delete::top::13","title":"RPC_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Удалить в следующей major‑версии** после миграции всех клиентов","content":"Стратегия миграции **Удалить в следующей major‑версии** после миграции всех клиентов"},{"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":"Это правило проверяет, что RPC‑методы сохраняют прежний тип сообщения запроса (request message type). Изменение типа запроса RPC ломает совместимость по wire‑формату и сгенерированный код: клиенты ожидают конкретную стру","content":"Это правило проверяет, что RPC‑методы сохраняют прежний тип сообщения запроса (request message type). Изменение типа запроса RPC ломает совместимость по wire‑формату и сгенерированный код: клиенты ожидают конкретную структуру при вызове метода."},{"id":"cli/breaking-changes/rules/rpc-same-request-type::breaking::1","title":"RPC_SAME_REQUEST_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::breaking::2","title":"RPC_SAME_REQUEST_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::breaking::3","title":"RPC_SAME_REQUEST_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse); }","content":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse); }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::breaking::4","title":"RPC_SAME_REQUEST_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message GetUserRequest { string user_id = 1; }","content":"Плохой (Breaking) message GetUserRequest { string user_id = 1; }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::breaking::5","title":"RPC_SAME_REQUEST_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message UpdateUserRequest { string user_id = 1; string name = 2; string email = 3; } ```","content":"Плохой (Breaking) message UpdateUserRequest { string user_id = 1; string name = 2; string email = 3; } ```"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::breaking::6","title":"RPC_SAME_REQUEST_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::breaking::7","title":"RPC_SAME_REQUEST_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::breaking::8","title":"RPC_SAME_REQUEST_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequestV2) returns (GetUserResponse); // [!code --] Изменён тип запроса rpc UpdateUser(UserUpdateRequest) returns (UpdateUserResponse); // [!code --] Изменён тип","content":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequestV2) returns (GetUserResponse); // [!code --] Изменён тип запроса rpc UpdateUser(UserUpdateRequest) returns (UpdateUserResponse); // [!code --] Изменён тип запроса }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::breaking::9","title":"RPC_SAME_REQUEST_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message GetUserRequestV2 { // [!code --] Новый тип запроса string id = 1; bool include_profile = 2; }","content":"Плохой (Breaking) message GetUserRequestV2 { // [!code --] Новый тип запроса string id = 1; bool include_profile = 2; }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::breaking::10","title":"RPC_SAME_REQUEST_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message UserUpdateRequest { // [!code --] Новый тип запроса string id = 1; UserProfile profile = 2; } ```","content":"Плохой (Breaking) message UserUpdateRequest { // [!code --] Новый тип запроса string id = 1; UserProfile profile = 2; } ```"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::11","title":"RPC_SAME_REQUEST_TYPE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры **Смена типа из другого пакета:** ```proto // Before import \"common/user.proto\";","content":"Дополнительные примеры **Смена типа из другого пакета:** ```proto // Before import \"common/user.proto\";"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::12","title":"RPC_SAME_REQUEST_TYPE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры service UserService { rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); }","content":"Дополнительные примеры service UserService { rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::13","title":"RPC_SAME_REQUEST_TYPE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры // After - BREAKING CHANGE! import \"v2/user.proto\";","content":"Дополнительные примеры // After - BREAKING CHANGE! import \"v2/user.proto\";"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::14","title":"RPC_SAME_REQUEST_TYPE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры service UserService { rpc CreateUser(v2.CreateUserRequest) returns (CreateUserResponse); // Другой package } ```","content":"Дополнительные примеры service UserService { rpc CreateUser(v2.CreateUserRequest) returns (CreateUserResponse); // Другой package } ```"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::15","title":"RPC_SAME_REQUEST_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо изменения типа — версионируйте RPC:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо изменения типа — версионируйте RPC:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::16","title":"RPC_SAME_REQUEST_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::17","title":"RPC_SAME_REQUEST_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse) { option deprecated = true; // [!code focus] } rpc GetUserV2(GetUserRequestV2) returns (GetUserResponse); // [!code focus] ","content":"Хороший (Безопасный) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse) { option deprecated = true; // [!code focus] } rpc GetUserV2(GetUserRequestV2) returns (GetUserResponse); // [!code focus] // Новый метод rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse) { option deprecated = true; // [!code focus] } rpc UpdateUserV2(UserUpdateRequest) returns (UpdateUserResponse); // [!code focus] // Новый метод }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::18","title":"RPC_SAME_REQUEST_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) // Старые сообщения — для обратной совместимости message GetUserRequest { string user_id = 1; }","content":"Хороший (Безопасный) // Старые сообщения — для обратной совместимости message GetUserRequest { string user_id = 1; }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::19","title":"RPC_SAME_REQUEST_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) // Новая версия сообщения message GetUserRequestV2 { // [!code focus] string id = 1; // [!code focus] bool include_profile = 2; // [!code focus] } // [!code focus] ```","content":"Хороший (Безопасный) // Новая версия сообщения 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::top::20","title":"RPC_SAME_REQUEST_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Или создайте новую версию сервиса (package v2):** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Или создайте новую версию сервиса (package v2):** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::21","title":"RPC_SAME_REQUEST_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v2; // [!code focus]","content":"Хороший (Безопасный) package myapi.v2; // [!code focus]"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::22","title":"RPC_SAME_REQUEST_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); // [!code focus] rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse); // [!code focus] }","content":"Хороший (Безопасный) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); // [!code focus] rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse); // [!code focus] }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::23","title":"RPC_SAME_REQUEST_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message GetUserRequest { // [!code focus] string id = 1; // [!code focus] bool include_profile = 2; // [!code focus] } // [!code focus] ```","content":"Хороший (Безопасный) message GetUserRequest { // [!code focus] string id = 1; // [!code focus] bool include_profile = 2; // [!code focus] } // [!code focus] ```"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::24","title":"RPC_SAME_REQUEST_TYPE","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Влияние"],"excerpt":"Влияние **Wire Format:** Старые запросы клиентов не десериализуются новым сервером **Generated Code:** Сигнатуры методов в stubs меняются — компиляция клиентов падает **gRPC Calls:** Требуется использовать другую структу","content":"Влияние **Wire Format:** Старые запросы клиентов не десериализуются новым сервером **Generated Code:** Сигнатуры методов в stubs меняются — компиляция клиентов падает **gRPC Calls:** Требуется использовать другую структуру запроса **Runtime Errors:** Несоответствие типов вызывает ошибки выполнения"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::25","title":"RPC_SAME_REQUEST_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Реальный пример"],"excerpt":"Реальный пример **Код клиента ломается:** ```go // Before client := myapi.NewUserServiceClient(conn) resp, err := client.GetUser(ctx, &myapi.GetUserRequest{ UserId: \"user123\", })","content":"Реальный пример **Код клиента ломается:** ```go // Before client := myapi.NewUserServiceClient(conn) resp, err := client.GetUser(ctx, &myapi.GetUserRequest{ UserId: \"user123\", })"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::26","title":"RPC_SAME_REQUEST_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Реальный пример"],"excerpt":"Реальный пример // After (тип запроса изменён) client := myapi.NewUserServiceClient(conn) resp, err := client.GetUser(ctx, &myapi.GetUserRequest{ // ERROR: тип не найден UserId: \"user123\", // ERROR: поле не найдено })","content":"Реальный пример // After (тип запроса изменён) client := myapi.NewUserServiceClient(conn) resp, err := client.GetUser(ctx, &myapi.GetUserRequest{ // ERROR: тип не найден UserId: \"user123\", // ERROR: поле не найдено })"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::27","title":"RPC_SAME_REQUEST_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Реальный пример"],"excerpt":"Реальный пример // Новый корректный вызов: resp, err := client.GetUser(ctx, &myapi.GetUserRequestV2{ Id: \"user123\", IncludeProfile: true, }) ```","content":"Реальный пример // Новый корректный вызов: resp, err := client.GetUser(ctx, &myapi.GetUserRequestV2{ Id: \"user123\", IncludeProfile: true, }) ```"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::28","title":"RPC_SAME_REQUEST_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Реальный пример"],"excerpt":"Реальный пример **Серверная реализация ломается:** ```go // Before func (s *server) GetUser(ctx context.Context, req *GetUserRequest) (*GetUserResponse, error) { userID := req.UserId // ... }","content":"Реальный пример **Серверная реализация ломается:** ```go // Before func (s *server) GetUser(ctx context.Context, req *GetUserRequest) (*GetUserResponse, error) { userID := req.UserId // ... }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::29","title":"RPC_SAME_REQUEST_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Реальный пример"],"excerpt":"Реальный пример // After func (s *server) GetUser(ctx context.Context, req *GetUserRequestV2) (*GetUserResponse, error) { userID := req.Id include := req.IncludeProfile // ... новая логика } ```","content":"Реальный пример // After func (s *server) GetUser(ctx context.Context, req *GetUserRequestV2) (*GetUserResponse, error) { userID := req.Id include := req.IncludeProfile // ... новая логика } ```"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::30","title":"RPC_SAME_REQUEST_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Добавьте новый RPC с новым типом запроса:**","content":"Стратегия миграции **Добавьте новый RPC с новым типом запроса:**"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::31","title":"RPC_SAME_REQUEST_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Поддерживайте оба метода на сервере:** ```go func (s *server) GetUser(ctx context.Context, req *GetUserRequest) (*GetUserResponse, error) { return s.getUserInternal(req.UserId, false) }","content":"Стратегия миграции **Поддерживайте оба метода на сервере:** ```go func (s *server) GetUser(ctx context.Context, req *GetUserRequest) (*GetUserResponse, error) { return s.getUserInternal(req.UserId, false) }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::32","title":"RPC_SAME_REQUEST_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции func (s *server) GetUserV2(ctx context.Context, req *GetUserRequestV2) (*GetUserResponse, error) { return s.getUserInternal(req.Id, req.IncludeProfile) } ```","content":"Стратегия миграции func (s *server) GetUserV2(ctx context.Context, req *GetUserRequestV2) (*GetUserResponse, error) { return s.getUserInternal(req.Id, req.IncludeProfile) } ```"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::33","title":"RPC_SAME_REQUEST_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Мигрируйте клиентов на V2:**","content":"Стратегия миграции **Мигрируйте клиентов на V2:**"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::34","title":"RPC_SAME_REQUEST_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Удалите старый метод в следующей major‑версии:**","content":"Стратегия миграции **Удалите старый метод в следующей major‑версии:**"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::35","title":"RPC_SAME_REQUEST_TYPE","section":"Добавление обязательных полей","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Добавление обязательных полей"],"excerpt":"Добавление обязательных полей ```proto // ПЛОХО: меняем существующий запрос message GetUserRequest { string user_id = 1; bool include_deleted = 2; // BREAKING }","content":"Добавление обязательных полей ```proto // ПЛОХО: меняем существующий запрос message GetUserRequest { string user_id = 1; bool include_deleted = 2; // BREAKING }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::36","title":"RPC_SAME_REQUEST_TYPE","section":"Добавление обязательных полей","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Добавление обязательных полей"],"excerpt":"Добавление обязательных полей // Хорошо: новая версия message GetUserRequestV2 { string user_id = 1; bool include_deleted = 2; } ```","content":"Добавление обязательных полей // Хорошо: новая версия message GetUserRequestV2 { string user_id = 1; bool include_deleted = 2; } ```"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::37","title":"RPC_SAME_REQUEST_TYPE","section":"Реструктуризация данных запроса","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Реструктуризация данных запроса"],"excerpt":"Реструктуризация данных запроса ```proto // ПЛОХО: меняем структуру прямо message UpdateUserRequest { UserProfile profile = 1; // BREAKING }","content":"Реструктуризация данных запроса ```proto // ПЛОХО: меняем структуру прямо message UpdateUserRequest { UserProfile profile = 1; // BREAKING }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::38","title":"RPC_SAME_REQUEST_TYPE","section":"Реструктуризация данных запроса","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Реструктуризация данных запроса"],"excerpt":"Реструктуризация данных запроса // Хорошо: версионирование rpc UpdateUser(UpdateUserRequest) returns (...) { option deprecated = true; } rpc UpdateUserV2(UpdateUserRequestV2) returns (...); ```","content":"Реструктуризация данных запроса // Хорошо: версионирование rpc UpdateUser(UpdateUserRequest) returns (...) { option deprecated = true; } rpc UpdateUserV2(UpdateUserRequestV2) returns (...); ```"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::39","title":"RPC_SAME_REQUEST_TYPE","section":"Миграция пакета","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Миграция пакета"],"excerpt":"Миграция пакета ```proto // ПЛОХО: заменяем тип на пакет v2 прямо import \"v2/messages.proto\"; // BREAKING","content":"Миграция пакета ```proto // ПЛОХО: заменяем тип на пакет v2 прямо import \"v2/messages.proto\"; // BREAKING"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::40","title":"RPC_SAME_REQUEST_TYPE","section":"Миграция пакета","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Миграция пакета"],"excerpt":"Миграция пакета // Хорошо: добавляем новый RPC rpc OldMethod(v1.Request) returns (...) { option deprecated = true; } rpc NewMethod(v2.Request) returns (...); ```","content":"Миграция пакета // Хорошо: добавляем новый RPC 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":"Это правило проверяет, что RPC‑методы сохраняют тот же тип ответного сообщения (response message type). Изменение типа ответа RPC ломает совместимость по wire‑формату и сгенерированный код: клиенты ожидают конкретную стр","content":"Это правило проверяет, что RPC‑методы сохраняют тот же тип ответного сообщения (response message type). Изменение типа ответа RPC ломает совместимость по wire‑формату и сгенерированный код: клиенты ожидают конкретную структуру при получении ответа."},{"id":"cli/breaking-changes/rules/rpc-same-response-type::breaking::1","title":"RPC_SAME_RESPONSE_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::breaking::2","title":"RPC_SAME_RESPONSE_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::breaking::3","title":"RPC_SAME_RESPONSE_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse); }","content":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse); }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::breaking::4","title":"RPC_SAME_RESPONSE_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message GetUserResponse { string user_id = 1; string name = 2; string email = 3; }","content":"Плохой (Breaking) message GetUserResponse { string user_id = 1; string name = 2; string email = 3; }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::breaking::5","title":"RPC_SAME_RESPONSE_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message UpdateUserResponse { bool success = 1; string message = 2; } ```","content":"Плохой (Breaking) message UpdateUserResponse { bool success = 1; string message = 2; } ```"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::breaking::6","title":"RPC_SAME_RESPONSE_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::breaking::7","title":"RPC_SAME_RESPONSE_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::breaking::8","title":"RPC_SAME_RESPONSE_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponseV2); // [!code --] Изменён тип ответа rpc UpdateUser(UpdateUserRequest) returns (UserUpdateResponse); // [!code --] Изменён тип ","content":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponseV2); // [!code --] Изменён тип ответа rpc UpdateUser(UpdateUserRequest) returns (UserUpdateResponse); // [!code --] Изменён тип ответа }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::breaking::9","title":"RPC_SAME_RESPONSE_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message GetUserResponseV2 { // [!code --] Другой тип сообщения string id = 1; UserProfile profile = 2; repeated string permissions = 3; }","content":"Плохой (Breaking) message GetUserResponseV2 { // [!code --] Другой тип сообщения string id = 1; UserProfile profile = 2; repeated string permissions = 3; }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::breaking::10","title":"RPC_SAME_RESPONSE_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message UserUpdateResponse { // [!code --] Другой тип сообщения UpdateResult result = 1; UserProfile updated_profile = 2; } ```","content":"Плохой (Breaking) message UserUpdateResponse { // [!code --] Другой тип сообщения UpdateResult result = 1; UserProfile updated_profile = 2; } ```"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::11","title":"RPC_SAME_RESPONSE_TYPE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры **Смена типа из другого пакета:** ```proto // Before import \"common/responses.proto\";","content":"Дополнительные примеры **Смена типа из другого пакета:** ```proto // Before import \"common/responses.proto\";"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::12","title":"RPC_SAME_RESPONSE_TYPE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры service UserService { rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); }","content":"Дополнительные примеры service UserService { rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::13","title":"RPC_SAME_RESPONSE_TYPE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры // After - BREAKING CHANGE! import \"v2/responses.proto\";","content":"Дополнительные примеры // After - BREAKING CHANGE! import \"v2/responses.proto\";"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::14","title":"RPC_SAME_RESPONSE_TYPE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры service UserService { rpc CreateUser(CreateUserRequest) returns (v2.CreateUserResponse); // Другой package } ```","content":"Дополнительные примеры service UserService { rpc CreateUser(CreateUserRequest) returns (v2.CreateUserResponse); // Другой package } ```"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::15","title":"RPC_SAME_RESPONSE_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо изменения типа — версионируйте RPC:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо изменения типа — версионируйте RPC:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::16","title":"RPC_SAME_RESPONSE_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::17","title":"RPC_SAME_RESPONSE_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse) { option deprecated = true; // [!code focus] } rpc GetUserV2(GetUserRequest) returns (GetUserResponseV2); // [!code focus] ","content":"Хороший (Безопасный) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse) { option deprecated = true; // [!code focus] } rpc GetUserV2(GetUserRequest) returns (GetUserResponseV2); // [!code focus] // Новый метод rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse) { option deprecated = true; // [!code focus] } rpc UpdateUserV2(UpdateUserRequest) returns (UserUpdateResponse); // [!code focus] // Новый метод }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::18","title":"RPC_SAME_RESPONSE_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) // Старые сообщения сохраняем для обратной совместимости message GetUserResponse { string user_id = 1; string name = 2; string email = 3; }","content":"Хороший (Безопасный) // Старые сообщения сохраняем для обратной совместимости message GetUserResponse { string user_id = 1; string name = 2; string email = 3; }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::19","title":"RPC_SAME_RESPONSE_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) // Новая расширенная версия message GetUserResponseV2 { // [!code focus] string id = 1; // [!code focus] UserProfile profile = 2; // [!code focus] repeated string permissions = 3; // [!code focus] } ","content":"Хороший (Безопасный) // Новая расширенная версия 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::top::20","title":"RPC_SAME_RESPONSE_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Или создайте новую версию сервиса (package v2):** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Или создайте новую версию сервиса (package v2):** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::21","title":"RPC_SAME_RESPONSE_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v2; // [!code focus]","content":"Хороший (Безопасный) package myapi.v2; // [!code focus]"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::22","title":"RPC_SAME_RESPONSE_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); // [!code focus] rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse); // [!code focus] }","content":"Хороший (Безопасный) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); // [!code focus] rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse); // [!code focus] }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::23","title":"RPC_SAME_RESPONSE_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message GetUserResponse { // [!code focus] string id = 1; // [!code focus] UserProfile profile = 2; // [!code focus] repeated string permissions = 3; // [!code focus] } // [!code focus] ```","content":"Хороший (Безопасный) message GetUserResponse { // [!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::top::24","title":"RPC_SAME_RESPONSE_TYPE","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Влияние"],"excerpt":"Влияние **Wire Format:** Ответы сервера не десериализуются у старых клиентов **Generated Code:** Сигнатуры ожидают старый тип — компиляция падает **gRPC Calls:** Меняются типы в сгенерированных stub'ах **Runtime Errors:*","content":"Влияние **Wire Format:** Ответы сервера не десериализуются у старых клиентов **Generated Code:** Сигнатуры ожидают старый тип — компиляция падает **gRPC Calls:** Меняются типы в сгенерированных stub'ах **Runtime Errors:** Несоответствие типов ломает обработку ответа"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::25","title":"RPC_SAME_RESPONSE_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Реальный пример"],"excerpt":"Реальный пример **Код клиента ломается:** ```go // Before client := myapi.NewUserServiceClient(conn) resp, err := client.GetUser(ctx, &myapi.GetUserRequest{ UserId: \"user123\", }) if err != nil { return err }","content":"Реальный пример **Код клиента ломается:** ```go // Before 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::top::26","title":"RPC_SAME_RESPONSE_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Реальный пример"],"excerpt":"Реальный пример userID := resp.UserId name := resp.Name","content":"Реальный пример userID := resp.UserId name := resp.Name"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::27","title":"RPC_SAME_RESPONSE_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Реальный пример"],"excerpt":"Реальный пример // After (тип ответа изменён) client := myapi.NewUserServiceClient(conn) resp, err := client.GetUser(ctx, &myapi.GetUserRequest{ UserId: \"user123\", }) if err != nil { return err }","content":"Реальный пример // After (тип ответа изменён) 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::top::28","title":"RPC_SAME_RESPONSE_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Реальный пример"],"excerpt":"Реальный пример // Ошибки компиляции: userID := resp.UserId // ERROR name := resp.Name // ERROR","content":"Реальный пример // Ошибки компиляции: userID := resp.UserId // ERROR name := resp.Name // ERROR"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::29","title":"RPC_SAME_RESPONSE_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Реальный пример"],"excerpt":"Реальный пример // Новый способ: userID := resp.Id profile := resp.Profile permissions := resp.Permissions ```","content":"Реальный пример // Новый способ: userID := resp.Id profile := resp.Profile permissions := resp.Permissions ```"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::30","title":"RPC_SAME_RESPONSE_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Реальный пример"],"excerpt":"Реальный пример **Имплементация сервера также должна быть переписана:** ```go // Before func (s *server) GetUser(ctx context.Context, req *GetUserRequest) (*GetUserResponse, error) { return &GetUserResponse{ UserId: \"use","content":"Реальный пример **Имплементация сервера также должна быть переписана:** ```go // Before 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::top::31","title":"RPC_SAME_RESPONSE_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Реальный пример"],"excerpt":"Реальный пример // After func (s *server) GetUser(ctx context.Context, req *GetUserRequest) (*GetUserResponseV2, error) { return &GetUserResponseV2{ Id: \"user123\", Profile: &UserProfile{ Name: \"John Doe\", Email: \"john@ex","content":"Реальный пример // After func (s *server) GetUser(ctx context.Context, req *GetUserRequest) (*GetUserResponseV2, error) { return &GetUserResponseV2{ Id: \"user123\", Profile: &UserProfile{ Name: \"John Doe\", Email: \"john@example.com\", }, Permissions: []string{\"read\"}, }, nil } ```"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::32","title":"RPC_SAME_RESPONSE_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Добавьте новый RPC c новым типом ответа:**","content":"Стратегия миграции **Добавьте новый RPC c новым типом ответа:**"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::33","title":"RPC_SAME_RESPONSE_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Поддерживайте оба на сервере:** ```go func (s *server) GetUser(ctx context.Context, req *GetUserRequest) (*GetUserResponse, error) { user := s.getUserInternal(req.UserId) return &GetUserResponse{ Use","content":"Стратегия миграции **Поддерживайте оба на сервере:** ```go func (s *server) GetUser(ctx context.Context, req *GetUserRequest) (*GetUserResponse, error) { user := s.getUserInternal(req.UserId) return &GetUserResponse{ UserId: user.ID, Name: user.Name, Email: user.Email, }, nil }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::34","title":"RPC_SAME_RESPONSE_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции func (s *server) GetUserV2(ctx context.Context, req *GetUserRequest) (*GetUserResponseV2, error) { user := s.getUserInternal(req.UserId) return &GetUserResponseV2{ Id: user.ID, Profile: &UserProfile{ N","content":"Стратегия миграции func (s *server) GetUserV2(ctx context.Context, req *GetUserRequest) (*GetUserResponseV2, error) { user := s.getUserInternal(req.UserId) return &GetUserResponseV2{ Id: user.ID, Profile: &UserProfile{ Name: user.Name, Email: user.Email, }, Permissions: user.Permissions, }, nil } ```"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::35","title":"RPC_SAME_RESPONSE_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Мигрируйте клиентов на новый RPC:**","content":"Стратегия миграции **Мигрируйте клиентов на новый RPC:**"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::36","title":"RPC_SAME_RESPONSE_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Удалите старый RPC** в следующей major‑версии:","content":"Стратегия миграции **Удалите старый RPC** в следующей major‑версии:"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::37","title":"RPC_SAME_RESPONSE_TYPE","section":"Добавление новых обязательных полей","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Добавление новых обязательных полей"],"excerpt":"Добавление новых обязательных полей ```proto // ПЛОХО: меняем существующий тип message GetUserResponse { string user_id = 1; string name = 2; UserProfile profile = 3; // BREAKING }","content":"Добавление новых обязательных полей ```proto // ПЛОХО: меняем существующий тип message GetUserResponse { string user_id = 1; string name = 2; UserProfile profile = 3; // BREAKING }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::38","title":"RPC_SAME_RESPONSE_TYPE","section":"Добавление новых обязательных полей","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Добавление новых обязательных полей"],"excerpt":"Добавление новых обязательных полей // Хорошо: новая версия message GetUserResponseV2 { string user_id = 1; string name = 2; UserProfile profile = 3; } ```","content":"Добавление новых обязательных полей // Хорошо: новая версия message GetUserResponseV2 { string user_id = 1; string name = 2; UserProfile profile = 3; } ```"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::39","title":"RPC_SAME_RESPONSE_TYPE","section":"Реструктуризация ответа","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Реструктуризация ответа"],"excerpt":"Реструктуризация ответа ```proto // ПЛОХО: меняем структуру прямо message UpdateUserResponse { UserDetails details = 1; // BREAKING }","content":"Реструктуризация ответа ```proto // ПЛОХО: меняем структуру прямо message UpdateUserResponse { UserDetails details = 1; // BREAKING }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::40","title":"RPC_SAME_RESPONSE_TYPE","section":"Реструктуризация ответа","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Реструктуризация ответа"],"excerpt":"Реструктуризация ответа // Хорошо: версионирование rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse) { option deprecated = true; } rpc UpdateUserV2(UpdateUserRequest) returns (UpdateUserResponseV2); ```","content":"Реструктуризация ответа // Хорошо: версионирование rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse) { option deprecated = true; } rpc UpdateUserV2(UpdateUserRequest) returns (UpdateUserResponseV2); ```"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::41","title":"RPC_SAME_RESPONSE_TYPE","section":"Изменение формата ошибок","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Изменение формата ошибок"],"excerpt":"Изменение формата ошибок ```proto // ПЛОХО: меняем формат напрямую message CreateUserResponse { ErrorDetails error = 1; // BREAKING }","content":"Изменение формата ошибок ```proto // ПЛОХО: меняем формат напрямую message CreateUserResponse { ErrorDetails error = 1; // BREAKING }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::42","title":"RPC_SAME_RESPONSE_TYPE","section":"Изменение формата ошибок","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Изменение формата ошибок"],"excerpt":"Изменение формата ошибок // Хорошо: новая версия rpc CreateUser(CreateUserRequest) returns (CreateUserResponse) { option deprecated = true; } rpc CreateUserV2(CreateUserRequest) returns (CreateUserResponseV2); ```","content":"Изменение формата ошибок // Хорошо: новая версия rpc CreateUser(CreateUserRequest) returns (CreateUserResponse) { option deprecated = true; } rpc CreateUserV2(CreateUserRequest) returns (CreateUserResponseV2); ```"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::43","title":"RPC_SAME_RESPONSE_TYPE","section":"Миграция формата","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Миграция формата"],"excerpt":"Миграция формата ```proto // ПЛОХО: перевод простой структуры в сложную message GetUserResponse { UserData data = 1; // BREAKING }","content":"Миграция формата ```proto // ПЛОХО: перевод простой структуры в сложную message GetUserResponse { UserData data = 1; // BREAKING }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::44","title":"RPC_SAME_RESPONSE_TYPE","section":"Миграция формата","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Миграция формата"],"excerpt":"Миграция формата // Хорошо: предоставляем обе версии rpc GetUser(GetUserRequest) returns (GetUserResponse) { option deprecated = true; } rpc GetUserDetailed(GetUserRequest) returns (GetUserDetailedResponse); ```","content":"Миграция формата // Хорошо: предоставляем обе версии 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":"Данное правило проверяет, что ни один service не был удалён из proto‑файлов. Удаление service ломает сгенерированный код и клиентские приложения, которые на него опираются.","content":"Данное правило проверяет, что ни один service не был удалён из proto‑файлов. Удаление service ломает сгенерированный код и клиентские приложения, которые на него опираются."},{"id":"cli/breaking-changes/rules/service-no-delete::breaking::1","title":"SERVICE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/service-no-delete::breaking::2","title":"SERVICE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/service-no-delete::breaking::3","title":"SERVICE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); }","content":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); }"},{"id":"cli/breaking-changes/rules/service-no-delete::breaking::4","title":"SERVICE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) service OrderService { // [!code --] rpc GetOrder(GetOrderRequest) returns (GetOrderResponse); // [!code --] } // [!code --] ```","content":"Плохой (Breaking) service OrderService { // [!code --] rpc GetOrder(GetOrderRequest) returns (GetOrderResponse); // [!code --] } // [!code --] ```"},{"id":"cli/breaking-changes/rules/service-no-delete::breaking::5","title":"SERVICE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/service-no-delete::breaking::6","title":"SERVICE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/service-no-delete::breaking::7","title":"SERVICE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); }","content":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); }"},{"id":"cli/breaking-changes/rules/service-no-delete::breaking::8","title":"SERVICE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) // OrderService удалён — BREAKING CHANGE! ```","content":"Плохой (Breaking) // OrderService удалён — BREAKING CHANGE! ```"},{"id":"cli/breaking-changes/rules/service-no-delete::top::9","title":"SERVICE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо удаления — отметьте service как deprecated:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо удаления — отметьте service как deprecated:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/service-no-delete::top::10","title":"SERVICE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/service-no-delete::top::11","title":"SERVICE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); }","content":"Хороший (Безопасный) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); }"},{"id":"cli/breaking-changes/rules/service-no-delete::top::12","title":"SERVICE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) service OrderService { option deprecated = true; // [!code focus] rpc GetOrder(GetOrderRequest) returns (GetOrderResponse) { option deprecated = true; // [!code focus] } } ```","content":"Хороший (Безопасный) 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::top::13","title":"SERVICE_NO_DELETE","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete","headings":["Влияние"],"excerpt":"Влияние **Generated Code:** Классы / интерфейсы сервиса исчезают — клиенты не компилируются **Client Applications:** Существующие вызовы к удалённому сервису падают на этапе сборки **Runtime:** gRPC клиенты теряют опреде","content":"Влияние **Generated Code:** Классы / интерфейсы сервиса исчезают — клиенты не компилируются **Client Applications:** Существующие вызовы к удалённому сервису падают на этапе сборки **Runtime:** gRPC клиенты теряют определение метода/сервиса"},{"id":"cli/breaking-changes/rules/service-no-delete::top::14","title":"SERVICE_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Сначала деприкация:**","content":"Стратегия миграции **Сначала деприкация:**"},{"id":"cli/breaking-changes/rules/service-no-delete::top::15","title":"SERVICE_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Уведомите клиентов** о сроках вывода из эксплуатации","content":"Стратегия миграции **Уведомите клиентов** о сроках вывода из эксплуатации"},{"id":"cli/breaking-changes/rules/service-no-delete::top::16","title":"SERVICE_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Удалите после периода миграции** в следующей major‑версии","content":"Стратегия миграции **Удалите после периода миграции** в следующей major‑версии"},{"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 Формат вывода для команд с поддержкой нескольких форматов (text/json) значение по умолчанию зависит от команды"},{"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 Базовая директория для поиска файлов Текущая рабочая дир","content":"Command-Specific Flags Flag Short Environment Description Default ------ ------- ------------- ------------- --------- --path -p Directory path to lint . --root -r Базовая директория для поиска файлов Текущая рабочая директория --format -f EASYP_FORMAT Использует глобальный флаг формата (text/json) Использует глобальное значение по умолчанию"},{"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 из поддиректории с правильным разрешением импортов easyp lint --root src/IPC/Contracts --path .","content":"Command-Specific Flags Lint из поддиректории с правильным разрешением импортов 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 # глобальный флаг","content":"Command-Specific Flags JSON output format easyp --format json lint # глобальный флаг"},{"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 Путь к директории с proto файлами для генерации . --root -r Базова","content":"Command-Specific Flags Flag Short Environment Description Default ------ ------- ------------- ------------- --------- --path -p EASYP_ROOT_GENERATE_PATH Путь к директории с proto файлами для генерации . --root -r Базовая директория для поиска файлов Текущая рабочая директория"},{"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 из поддиректории с правильным разрешением импортов easyp generate --root src/IPC/Contracts --path .","content":"Command-Specific Flags Generate из поддиректории с правильным разрешением импортов 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 Использует глобальный флаг формата (text/json) Использует глобальное значение по умолчанию"},{"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 # глобальный флаг ```","content":"Command-Specific Flags JSON output easyp --format json breaking --against main # глобальный флаг ```"},{"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 работает интерактивно: Если в корне целевой директории есть buf.yml/buf.yaml, команда предложит миграцию из Buf. Если easyp.yaml уже существует, команда запросит подтверждение на перезап","content":"Command-Specific Flags easyp init работает интерактивно: Если в корне целевой директории есть buf.yml/buf.yaml, команда предложит миграцию из Buf. Если easyp.yaml уже существует, команда запросит подтверждение на перезапись."},{"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 Путь до файла конфигурации easyp.yaml --format (global) -f EASYP_FORMAT Глобаль","content":"Command-Specific Flags Flag Short Environment Description Default ------ ------- ------------- ------------- --------- --config -c EASYP_CFG Путь до файла конфигурации easyp.yaml --format (global) -f EASYP_FORMAT Глобальный формат вывода для команд с несколькими форматами (json или text) зависит от команды (json для 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 Проверить конфиг по умолчанию с JSON выводом (статус 0 если ошибок нет) easyp validate-config","content":"Command-Specific Flags **Examples:** ```bash Проверить конфиг по умолчанию с JSON выводом (статус 0 если ошибок нет) 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 Проверить другой файл и вывести в текстовом формате (глобальный --format) easyp --format text validate-config --config example.easyp.yaml ```","content":"Command-Specific Flags Проверить другой файл и вывести в текстовом формате (глобальный --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 Формат вывода для поддерживаемых команд (text/json). Если не указан, каждая команда использует своё значение по умолчанию. значение по умолчанию зависит от команды 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::top::45","title":"EasyP Configuration Reference","section":"Переменные окружения в конфигурации","path":"/docs/guide/cli/configuration/configuration","headings":["Переменные окружения в конфигурации"],"excerpt":"Переменные окружения в конфигурации EasyP поддерживает расширение переменных окружения непосредственно в файле конфигурации easyp.yaml. Это позволяет использовать переменные окружения для динамических значений конфигурац","content":"Переменные окружения в конфигурации EasyP поддерживает расширение переменных окружения непосредственно в файле конфигурации easyp.yaml. Это позволяет использовать переменные окружения для динамических значений конфигурации."},{"id":"cli/configuration/configuration::top::46","title":"EasyP Configuration Reference","section":"Переменные окружения в конфигурации","path":"/docs/guide/cli/configuration/configuration","headings":["Переменные окружения в конфигурации"],"excerpt":"Переменные окружения в конфигурации **Пример со всеми поддерживаемыми возможностями:** ```yaml deps: # Базовое расширение: ${VAR} - расширяется в значение переменной VAR - ${GOOGLEAPIS_REPO}@${GOOGLEAPIS_VERSION} # Значе","content":"Переменные окружения в конфигурации **Пример со всеми поддерживаемыми возможностями:** ```yaml deps: # Базовое расширение: ${VAR} - расширяется в значение переменной VAR - ${GOOGLEAPIS_REPO}@${GOOGLEAPIS_VERSION} # Значение по умолчанию: ${VAR:-default} - использует default, если VAR не установлена или пустая - ${GNOSTIC_REPO:-github.com/google/gnostic}@${GNOSTIC_VERSION:-v0.7.0}"},{"id":"cli/configuration/configuration::top::47","title":"EasyP Configuration Reference","section":"Переменные окружения в конфигурации","path":"/docs/guide/cli/configuration/configuration","headings":["Переменные окружения в конфигурации"],"excerpt":"Переменные окружения в конфигурации generate: inputs: # Значение по умолчанию, если INPUT_DIR не установлена - directory: ${INPUT_DIR:-proto} plugins: - name: go # Базовое расширение out: ${OUTPUT_DIR} opts: # Значение п","content":"Переменные окружения в конфигурации generate: inputs: # Значение по умолчанию, если INPUT_DIR не установлена - directory: ${INPUT_DIR:-proto} plugins: - name: go # Базовое расширение out: ${OUTPUT_DIR} opts: # Значение по умолчанию module: ${MODULE_NAME:-github.com/example/project} timeout: ${TIMEOUT:-30} # Экранирование: $$ становится буквальным $, $${VAR} становится буквальным ${VAR} path: \"${BASE_DIR}/$${TEMP}/file\" # Результат: \"/tmp/${TEMP}/file\" (если BASE_DIR=/tmp) literal: \"$$\" # Результат: \"$\" ```"},{"id":"cli/configuration/configuration::top::48","title":"EasyP Configuration Reference","section":"Переменные окружения в конфигурации","path":"/docs/guide/cli/configuration/configuration","headings":["Переменные окружения в конфигурации"],"excerpt":"Переменные окружения в конфигурации **Поддерживаемый синтаксис:** ${VAR} - расширяется в значение переменной VAR ${VAR:-default} - использует default, если VAR не установлена или пустая ${VAR:=default} - использует defau","content":"Переменные окружения в конфигурации **Поддерживаемый синтаксис:** ${VAR} - расширяется в значение переменной VAR ${VAR:-default} - использует default, если VAR не установлена или пустая ${VAR:=default} - использует default, если VAR не установлена или пустая ${VAR-default} - использует default, если VAR не установлена (пустая строка сохраняется) $${VAR} или $$VAR - экранирует в буквальную строку ${VAR} или $VAR $$ - экранирует в буквальный символ $"},{"id":"cli/configuration/configuration::top::49","title":"EasyP Configuration Reference","section":"Переменные окружения в конфигурации","path":"/docs/guide/cli/configuration/configuration","headings":["Переменные окружения в конфигурации"],"excerpt":"Переменные окружения в конфигурации **Примечание:** Переменные окружения расширяются до парсинга YAML, поэтому любой паттерн ${STRING} будет обработан. Используйте $$ для экранирования символов доллара, когда нужны буква","content":"Переменные окружения в конфигурации **Примечание:** Переменные окружения расширяются до парсинга YAML, поэтому любой паттерн ${STRING} будет обработан. Используйте $$ для экранирования символов доллара, когда нужны буквальные значения."},{"id":"cli/configuration/configuration::version::50","title":"EasyP Configuration Reference","section":"version","path":"/docs/guide/cli/configuration/configuration#version","headings":["version"],"excerpt":"version **Опционально (legacy-совместимость).** Поле поддерживается для обратной совместимости и может быть опущено в новых конфигурациях.","content":"version **Опционально (legacy-совместимость).** Поле поддерживается для обратной совместимости и может быть опущено в новых конфигурациях."},{"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:** не задано **Рекомендация:** если сохраняете поле, используйте v1alpha","content":"version **Type:** string **Default:** не задано **Рекомендация:** если сохраняете поле, используйте v1alpha"},{"id":"cli/configuration/configuration::version::52","title":"EasyP Configuration Reference","section":"version","path":"/docs/guide/cli/configuration/configuration#version","headings":["version"],"excerpt":"version На поведение рантайма это поле не влияет.","content":"version На поведение рантайма это поле не влияет."},{"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, required) - Output directory for generated files opts (mapstring, optional) - Plugin-specific options; each key can be a single value or an array of 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::top::0","title":"Go","section":"Установка плагинов","path":"/docs/guide/cli/generator/examples/go","headings":["Установка плагинов"],"excerpt":"Установка плагинов Сначала установите необходимые плагины для работы с gRPC:","content":"Установка плагинов Сначала установите необходимые плагины для работы с gRPC:"},{"id":"cli/generator/examples/go::top::1","title":"Go","section":"Установка плагинов","path":"/docs/guide/cli/generator/examples/go","headings":["Установка плагинов"],"excerpt":"Установка плагинов Эти команды установят плагины protoc-gen-go и protoc-gen-go-grpc для использования с EasyP.","content":"Установка плагинов Эти команды установят плагины protoc-gen-go и protoc-gen-go-grpc для использования с EasyP."},{"id":"cli/generator/examples/go::proto::2","title":"Go","section":"Пример proto‑сервиса","path":"/docs/guide/cli/generator/examples/go#proto","headings":["Пример proto‑сервиса"],"excerpt":"Пример proto‑сервиса Ниже пример proto-файла для сервиса Echo:","content":"Пример proto‑сервиса Ниже пример proto-файла для сервиса Echo:"},{"id":"cli/generator/examples/go::proto::3","title":"Go","section":"Пример proto‑сервиса","path":"/docs/guide/cli/generator/examples/go#proto","headings":["Пример proto‑сервиса"],"excerpt":"Пример proto‑сервиса ```proto syntax = \"proto3\";","content":"Пример proto‑сервиса ```proto syntax = \"proto3\";"},{"id":"cli/generator/examples/go::proto::4","title":"Go","section":"Пример proto‑сервиса","path":"/docs/guide/cli/generator/examples/go#proto","headings":["Пример proto‑сервиса"],"excerpt":"Пример proto‑сервиса package api.echo.v1;","content":"Пример proto‑сервиса package api.echo.v1;"},{"id":"cli/generator/examples/go::proto::5","title":"Go","section":"Пример proto‑сервиса","path":"/docs/guide/cli/generator/examples/go#proto","headings":["Пример proto‑сервиса"],"excerpt":"Пример proto‑сервиса option go_package = \"github.com/easyp-tech/example/api/echo/v1;pb\";","content":"Пример proto‑сервиса option go_package = \"github.com/easyp-tech/example/api/echo/v1;pb\";"},{"id":"cli/generator/examples/go::proto::6","title":"Go","section":"Пример proto‑сервиса","path":"/docs/guide/cli/generator/examples/go#proto","headings":["Пример proto‑сервиса"],"excerpt":"Пример proto‑сервиса service EchoAPI { rpc Echo(EchoRequest) returns (EchoResponse); rpc EchoStream(EchoStreamRequest) returns (EchoResponse); }","content":"Пример proto‑сервиса service EchoAPI { rpc Echo(EchoRequest) returns (EchoResponse); rpc EchoStream(EchoStreamRequest) returns (EchoResponse); }"},{"id":"cli/generator/examples/go::proto::7","title":"Go","section":"Пример proto‑сервиса","path":"/docs/guide/cli/generator/examples/go#proto","headings":["Пример proto‑сервиса"],"excerpt":"Пример proto‑сервиса message EchoRequest { string payload = 1; }","content":"Пример proto‑сервиса message EchoRequest { string payload = 1; }"},{"id":"cli/generator/examples/go::proto::8","title":"Go","section":"Пример proto‑сервиса","path":"/docs/guide/cli/generator/examples/go#proto","headings":["Пример proto‑сервиса"],"excerpt":"Пример proto‑сервиса message EchoResponse { string payload = 2; }","content":"Пример proto‑сервиса message EchoResponse { string payload = 2; }"},{"id":"cli/generator/examples/go::proto::9","title":"Go","section":"Пример proto‑сервиса","path":"/docs/guide/cli/generator/examples/go#proto","headings":["Пример proto‑сервиса"],"excerpt":"Пример proto‑сервиса message EchoStreamRequest { string payload = 1; }","content":"Пример proto‑сервиса message EchoStreamRequest { string payload = 1; }"},{"id":"cli/generator/examples/go::proto::10","title":"Go","section":"Пример proto‑сервиса","path":"/docs/guide/cli/generator/examples/go#proto","headings":["Пример proto‑сервиса"],"excerpt":"Пример proto‑сервиса message EchoStreamResponse { string payload = 2; } ```","content":"Пример proto‑сервиса message EchoStreamResponse { string payload = 2; } ```"},{"id":"cli/generator/examples/go::top::11","title":"Go","section":"Настройка конфигурации","path":"/docs/guide/cli/generator/examples/go","headings":["Настройка конфигурации"],"excerpt":"Настройка конфигурации Создайте и настройте файл конфигурации easyp.yaml:","content":"Настройка конфигурации Создайте и настройте файл конфигурации easyp.yaml:"},{"id":"cli/generator/examples/go::top::12","title":"Go","section":"Настройка конфигурации","path":"/docs/guide/cli/generator/examples/go","headings":["Настройка конфигурации"],"excerpt":"Настройка конфигурации Этот файл указывает использование двух плагинов: go для генерации Go-кода и go-grpc для генерации gRPC-кода, вместе с их опциями.","content":"Настройка конфигурации Этот файл указывает использование двух плагинов: go для генерации Go-кода и go-grpc для генерации gRPC-кода, вместе с их опциями."},{"id":"cli/generator/examples/go::top::13","title":"Go","section":"Генерация кода","path":"/docs/guide/cli/generator/examples/go","headings":["Генерация кода"],"excerpt":"Генерация кода Чтобы сгенерировать код, выполните команду:","content":"Генерация кода Чтобы сгенерировать код, выполните команду:"},{"id":"cli/generator/examples/go::top::14","title":"Go","section":"Генерация кода","path":"/docs/guide/cli/generator/examples/go","headings":["Генерация кода"],"excerpt":"Генерация кода Если флаг --cfg не указан, по умолчанию используется файл easyp.yaml в текущей директории:","content":"Генерация кода Если флаг --cfg не указан, по умолчанию используется файл easyp.yaml в текущей директории:"},{"id":"cli/generator/examples/go::top::15","title":"Go","section":"Генерация кода","path":"/docs/guide/cli/generator/examples/go","headings":["Генерация кода"],"excerpt":"Генерация кода Теперь у вас есть сгенерированный Go‑код, с которым можно напрямую работать.","content":"Генерация кода Теперь у вас есть сгенерированный Go‑код, с которым можно напрямую работать."},{"id":"cli/generator/examples/grpc-gateway::top::0","title":"gRPC-Gateway","section":"Установка плагинов","path":"/docs/guide/cli/generator/examples/grpc-gateway","headings":["Установка плагинов"],"excerpt":"Установка плагинов В дополнение к плагинам для работы с gRPC, необходимо установить следующие плагины для gRPC-Gateway:","content":"Установка плагинов В дополнение к плагинам для работы с gRPC, необходимо установить следующие плагины для gRPC-Gateway:"},{"id":"cli/generator/examples/grpc-gateway::top::1","title":"gRPC-Gateway","section":"Установка плагинов","path":"/docs/guide/cli/generator/examples/grpc-gateway","headings":["Установка плагинов"],"excerpt":"Установка плагинов go install google.golang.org/protobuf/cmd/protoc-gen-go@latest go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest go install github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2@","content":"Установка плагинов go install google.golang.org/protobuf/cmd/protoc-gen-go@latest go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest go install github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2@latest go install github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway@latest"},{"id":"cli/generator/examples/grpc-gateway::top::2","title":"gRPC-Gateway","section":"Установка плагинов","path":"/docs/guide/cli/generator/examples/grpc-gateway","headings":["Установка плагинов"],"excerpt":"Установка плагинов Эти команды установят плагины protoc-gen-go, protoc-gen-go-grpc, protoc-gen-openapiv2 и protoc-gen-grpc-gateway для использования с EasyP.","content":"Установка плагинов Эти команды установят плагины protoc-gen-go, protoc-gen-go-grpc, protoc-gen-openapiv2 и protoc-gen-grpc-gateway для использования с EasyP."},{"id":"cli/generator/examples/grpc-gateway::proto::3","title":"gRPC-Gateway","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/grpc-gateway#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса Ниже — исходный proto‑файл для сервиса Echo:","content":"Пример Proto сервиса Ниже — исходный proto‑файл для сервиса Echo:"},{"id":"cli/generator/examples/grpc-gateway::proto::4","title":"gRPC-Gateway","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/grpc-gateway#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса syntax = \"proto3\";","content":"Пример Proto сервиса syntax = \"proto3\";"},{"id":"cli/generator/examples/grpc-gateway::proto::5","title":"gRPC-Gateway","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/grpc-gateway#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса package api.echo.v1;","content":"Пример Proto сервиса package api.echo.v1;"},{"id":"cli/generator/examples/grpc-gateway::proto::6","title":"gRPC-Gateway","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/grpc-gateway#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса option go_package = \"github.com/easyp-tech/example/api/echo/v1;pb\";","content":"Пример Proto сервиса option go_package = \"github.com/easyp-tech/example/api/echo/v1;pb\";"},{"id":"cli/generator/examples/grpc-gateway::proto::7","title":"gRPC-Gateway","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/grpc-gateway#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса service EchoAPI { rpc Echo(EchoRequest) returns (EchoResponse); }","content":"Пример Proto сервиса service EchoAPI { rpc Echo(EchoRequest) returns (EchoResponse); }"},{"id":"cli/generator/examples/grpc-gateway::proto::8","title":"gRPC-Gateway","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/grpc-gateway#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса message EchoRequest { string payload = 1; }","content":"Пример Proto сервиса message EchoRequest { string payload = 1; }"},{"id":"cli/generator/examples/grpc-gateway::proto::9","title":"gRPC-Gateway","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/grpc-gateway#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса message EchoResponse { string payload = 2; }","content":"Пример Proto сервиса message EchoResponse { string payload = 2; }"},{"id":"cli/generator/examples/grpc-gateway::proto::10","title":"gRPC-Gateway","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/grpc-gateway#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса Чтобы использовать gRPC-Gateway, обновите proto‑файл, добавив HTTP‑опции:","content":"Пример Proto сервиса Чтобы использовать gRPC-Gateway, обновите proto‑файл, добавив HTTP‑опции:"},{"id":"cli/generator/examples/grpc-gateway::proto::11","title":"gRPC-Gateway","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/grpc-gateway#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса syntax = \"proto3\"; import \"google/api/annotations.proto\";","content":"Пример Proto сервиса syntax = \"proto3\"; import \"google/api/annotations.proto\";"},{"id":"cli/generator/examples/grpc-gateway::proto::12","title":"gRPC-Gateway","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/grpc-gateway#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса package api.echo.v1;","content":"Пример Proto сервиса package api.echo.v1;"},{"id":"cli/generator/examples/grpc-gateway::proto::13","title":"gRPC-Gateway","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/grpc-gateway#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса option go_package = \"github.com/easyp-tech/example/api/echo/v1;pb\";","content":"Пример Proto сервиса option go_package = \"github.com/easyp-tech/example/api/echo/v1;pb\";"},{"id":"cli/generator/examples/grpc-gateway::proto::14","title":"gRPC-Gateway","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/grpc-gateway#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса service EchoAPI { rpc Echo(EchoRequest) returns (EchoResponse) { option (google.api.http) = { // [!code ++] post: \"/api/v1/echo\" // [!code ++] body: \"*\" // [!code ++] }; // [!code ++] } }","content":"Пример Proto сервиса 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::proto::15","title":"gRPC-Gateway","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/grpc-gateway#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса message EchoRequest { string payload = 1; }","content":"Пример Proto сервиса message EchoRequest { string payload = 1; }"},{"id":"cli/generator/examples/grpc-gateway::proto::16","title":"gRPC-Gateway","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/grpc-gateway#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса message EchoResponse { string payload = 2; }","content":"Пример Proto сервиса message EchoResponse { string payload = 2; }"},{"id":"cli/generator/examples/grpc-gateway::top::17","title":"gRPC-Gateway","section":"Настройка конфигурации","path":"/docs/guide/cli/generator/examples/grpc-gateway","headings":["Настройка конфигурации"],"excerpt":"Настройка конфигурации Обновите файл easyp.yaml, добавив необходимые зависимости и плагины: deps: # [!code ++] - github.com/googleapis/googleapis # [!code ++]","content":"Настройка конфигурации Обновите файл easyp.yaml, добавив необходимые зависимости и плагины: deps: # [!code ++] - github.com/googleapis/googleapis # [!code ++]"},{"id":"cli/generator/examples/grpc-gateway::top::18","title":"gRPC-Gateway","section":"Настройка конфигурации","path":"/docs/guide/cli/generator/examples/grpc-gateway","headings":["Настройка конфигурации"],"excerpt":"Настройка конфигурации 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":"Настройка конфигурации 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::top::19","title":"gRPC-Gateway","section":"Настройка конфигурации","path":"/docs/guide/cli/generator/examples/grpc-gateway","headings":["Настройка конфигурации"],"excerpt":"Настройка конфигурации Секция deps перечисляет зависимости, необходимые для импортов proto‑файлов. В данном случае добавляем github.com/googleapis/googleapis, поскольку там находится файл annotations.proto, используемый ","content":"Настройка конфигурации Секция deps перечисляет зависимости, необходимые для импортов proto‑файлов. В данном случае добавляем github.com/googleapis/googleapis, поскольку там находится файл annotations.proto, используемый в определении сервиса."},{"id":"cli/generator/examples/grpc-gateway::top::20","title":"gRPC-Gateway","section":"Обновление зависимостей","path":"/docs/guide/cli/generator/examples/grpc-gateway","headings":["Обновление зависимостей"],"excerpt":"Обновление зависимостей После обновления конфигурации выполните команду для загрузки указанных зависимостей:","content":"Обновление зависимостей После обновления конфигурации выполните команду для загрузки указанных зависимостей:"},{"id":"cli/generator/examples/grpc-gateway::top::21","title":"gRPC-Gateway","section":"Обновление зависимостей","path":"/docs/guide/cli/generator/examples/grpc-gateway","headings":["Обновление зависимостей"],"excerpt":"Обновление зависимостей easyp mod update","content":"Обновление зависимостей easyp mod update"},{"id":"cli/generator/examples/grpc-gateway::top::22","title":"gRPC-Gateway","section":"Обновление зависимостей","path":"/docs/guide/cli/generator/examples/grpc-gateway","headings":["Обновление зависимостей"],"excerpt":"Обновление зависимостей Больше деталей по управлению зависимостями см. в разделе Package Manager.","content":"Обновление зависимостей Больше деталей по управлению зависимостями см. в разделе Package Manager."},{"id":"cli/generator/examples/grpc-gateway::top::23","title":"gRPC-Gateway","section":"Генерация кода","path":"/docs/guide/cli/generator/examples/grpc-gateway","headings":["Генерация кода"],"excerpt":"Генерация кода Для генерации кода используйте:","content":"Генерация кода Для генерации кода используйте:"},{"id":"cli/generator/examples/grpc-gateway::top::24","title":"gRPC-Gateway","section":"Генерация кода","path":"/docs/guide/cli/generator/examples/grpc-gateway","headings":["Генерация кода"],"excerpt":"Генерация кода easyp --cfg easyp.yaml generate","content":"Генерация кода easyp --cfg easyp.yaml generate"},{"id":"cli/generator/examples/grpc-gateway::top::25","title":"gRPC-Gateway","section":"Генерация кода","path":"/docs/guide/cli/generator/examples/grpc-gateway","headings":["Генерация кода"],"excerpt":"Генерация кода Если флаг --cfg не указан, по умолчанию используется файл easyp.yaml из текущей директории:","content":"Генерация кода Если флаг --cfg не указан, по умолчанию используется файл easyp.yaml из текущей директории:"},{"id":"cli/generator/examples/grpc-gateway::top::26","title":"gRPC-Gateway","section":"Генерация кода","path":"/docs/guide/cli/generator/examples/grpc-gateway","headings":["Генерация кода"],"excerpt":"Генерация кода Теперь у вас сгенерированы Go‑код и код gRPC-Gateway, с которыми можно работать напрямую.","content":"Генерация кода Теперь у вас сгенерированы Go‑код и код gRPC-Gateway, с которыми можно работать напрямую."},{"id":"cli/generator/examples/validate::top::0","title":"Validate","section":"Установка плагинов","path":"/docs/guide/cli/generator/examples/validate","headings":["Установка плагинов"],"excerpt":"Установка плагинов Сначала установите необходимые плагины для работы с gRPC и проверок (validate):","content":"Установка плагинов Сначала установите необходимые плагины для работы с gRPC и проверок (validate):"},{"id":"cli/generator/examples/validate::top::1","title":"Validate","section":"Установка плагинов","path":"/docs/guide/cli/generator/examples/validate","headings":["Установка плагинов"],"excerpt":"Установка плагинов Эти команды установят плагины protoc-gen-go, protoc-gen-go-grpc и protoc-gen-validate для использования вместе с EasyP.","content":"Установка плагинов Эти команды установят плагины protoc-gen-go, protoc-gen-go-grpc и protoc-gen-validate для использования вместе с EasyP."},{"id":"cli/generator/examples/validate::proto::2","title":"Validate","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/validate#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса Ниже пример proto‑файла для сервиса Echo:","content":"Пример Proto сервиса Ниже пример proto‑файла для сервиса Echo:"},{"id":"cli/generator/examples/validate::proto::3","title":"Validate","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/validate#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса ```proto syntax = \"proto3\";","content":"Пример Proto сервиса ```proto syntax = \"proto3\";"},{"id":"cli/generator/examples/validate::proto::4","title":"Validate","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/validate#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса package api.echo.v1;","content":"Пример Proto сервиса package api.echo.v1;"},{"id":"cli/generator/examples/validate::proto::5","title":"Validate","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/validate#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса import \"validate/validate.proto\";","content":"Пример Proto сервиса import \"validate/validate.proto\";"},{"id":"cli/generator/examples/validate::proto::6","title":"Validate","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/validate#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса option go_package = \"github.com/easyp-tech/example/api/echo/v1;pb\";","content":"Пример Proto сервиса option go_package = \"github.com/easyp-tech/example/api/echo/v1;pb\";"},{"id":"cli/generator/examples/validate::proto::7","title":"Validate","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/validate#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса service EchoAPI { rpc Echo(EchoRequest) returns (EchoResponse); rpc EchoStream(EchoStreamRequest) returns (EchoResponse); }","content":"Пример Proto сервиса service EchoAPI { rpc Echo(EchoRequest) returns (EchoResponse); rpc EchoStream(EchoStreamRequest) returns (EchoResponse); }"},{"id":"cli/generator/examples/validate::proto::8","title":"Validate","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/validate#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса message EchoRequest { string payload = 1 [(validate.rules).string = {max_len: 200}]; }","content":"Пример Proto сервиса message EchoRequest { string payload = 1 [(validate.rules).string = {max_len: 200}]; }"},{"id":"cli/generator/examples/validate::proto::9","title":"Validate","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/validate#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса message EchoResponse { string payload = 2; }","content":"Пример Proto сервиса message EchoResponse { string payload = 2; }"},{"id":"cli/generator/examples/validate::proto::10","title":"Validate","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/validate#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса message EchoStreamRequest { string payload = 1 [(validate.rules).string = {max_len: 200}]; }","content":"Пример Proto сервиса message EchoStreamRequest { string payload = 1 [(validate.rules).string = {max_len: 200}]; }"},{"id":"cli/generator/examples/validate::proto::11","title":"Validate","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/validate#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса message EchoStreamResponse { string payload = 2; } ```","content":"Пример Proto сервиса message EchoStreamResponse { string payload = 2; } ```"},{"id":"cli/generator/examples/validate::top::12","title":"Validate","section":"Настройка конфигурации","path":"/docs/guide/cli/generator/examples/validate","headings":["Настройка конфигурации"],"excerpt":"Настройка конфигурации Создайте и настройте файл конфигурации easyp.yaml:","content":"Настройка конфигурации Создайте и настройте файл конфигурации easyp.yaml:"},{"id":"cli/generator/examples/validate::top::13","title":"Validate","section":"Настройка конфигурации","path":"/docs/guide/cli/generator/examples/validate","headings":["Настройка конфигурации"],"excerpt":"Настройка конфигурации ```yaml deps: # [!code ++] - github.com/bufbuild/protoc-gen-validate # [!code ++]","content":"Настройка конфигурации ```yaml deps: # [!code ++] - github.com/bufbuild/protoc-gen-validate # [!code ++]"},{"id":"cli/generator/examples/validate::top::14","title":"Validate","section":"Настройка конфигурации","path":"/docs/guide/cli/generator/examples/validate","headings":["Настройка конфигурации"],"excerpt":"Настройка конфигурации 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: sourc","content":"Настройка конфигурации 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::top::15","title":"Validate","section":"Генерация кода","path":"/docs/guide/cli/generator/examples/validate","headings":["Генерация кода"],"excerpt":"Генерация кода Чтобы сгенерировать код, выполните команду:","content":"Генерация кода Чтобы сгенерировать код, выполните команду:"},{"id":"cli/generator/examples/validate::top::16","title":"Validate","section":"Генерация кода","path":"/docs/guide/cli/generator/examples/validate","headings":["Генерация кода"],"excerpt":"Генерация кода Если флаг --cfg не указан, по умолчанию используется файл easyp.yaml из текущего каталога:","content":"Генерация кода Если флаг --cfg не указан, по умолчанию используется файл easyp.yaml из текущего каталога:"},{"id":"cli/generator/examples/validate::top::17","title":"Validate","section":"Генерация кода","path":"/docs/guide/cli/generator/examples/validate","headings":["Генерация кода"],"excerpt":"Генерация кода Теперь у вас есть сгенерированный Go‑код с поддержкой валидации, и вы можете напрямую использовать его в проекте.","content":"Генерация кода Теперь у вас есть сгенерированный Go‑код с поддержкой валидации, и вы можете напрямую использовать его в проекте."},{"id":"cli/generator/generator::top::0","title":"Генератор","path":"/docs/guide/cli/generator/generator","headings":[],"excerpt":"EasyP включает мощный генератор, который упрощает процесс получения кода из proto‑файлов. Благодаря YAML‑конфигурациям работа становится гораздо более удобной и интуитивной по сравнению с прямым использованием команды pr","content":"EasyP включает мощный генератор, который упрощает процесс получения кода из proto‑файлов. Благодаря YAML‑конфигурациям работа становится гораздо более удобной и интуитивной по сравнению с прямым использованием команды protoc."},{"id":"cli/generator/generator::top::1","title":"Генератор","section":"Ключевые особенности генератора","path":"/docs/guide/cli/generator/generator","headings":["Ключевые особенности генератора"],"excerpt":"Ключевые особенности генератора **Упрощённая генерация кода**: - Генерация кода из proto через декларативную YAML‑конфигурацию. - Избавляет от необходимости писать длинные и сложные команды protoc.","content":"Ключевые особенности генератора **Упрощённая генерация кода**: - Генерация кода из proto через декларативную YAML‑конфигурацию. - Избавляет от необходимости писать длинные и сложные команды protoc."},{"id":"cli/generator/generator::top::2","title":"Генератор","section":"Ключевые особенности генератора","path":"/docs/guide/cli/generator/generator","headings":["Ключевые особенности генератора"],"excerpt":"Ключевые особенности генератора **Обёртка над protoc**: - EasyP выступает как удобный слой над protoc, предоставляя декларативный API. - Поддерживает все опции и плагины, доступные protoc.","content":"Ключевые особенности генератора **Обёртка над protoc**: - EasyP выступает как удобный слой над protoc, предоставляя декларативный API. - Поддерживает все опции и плагины, доступные protoc."},{"id":"cli/generator/generator::top::3","title":"Генератор","section":"Ключевые особенности генератора","path":"/docs/guide/cli/generator/generator","headings":["Ключевые особенности генератора"],"excerpt":"Ключевые особенности генератора **Гибкость и кастомизация**: - Используются те же параметры, что и у плагинов protoc, прямо в конфиге. - Поддерживается множество плагинов и их параметры в одной конфигурации.","content":"Ключевые особенности генератора **Гибкость и кастомизация**: - Используются те же параметры, что и у плагинов protoc, прямо в конфиге. - Поддерживается множество плагинов и их параметры в одной конфигурации."},{"id":"cli/generator/generator::top::4","title":"Генератор","section":"Ключевые особенности генератора","path":"/docs/guide/cli/generator/generator","headings":["Ключевые особенности генератора"],"excerpt":"Ключевые особенности генератора **Генерация из нескольких источников**: - Локальные директории и удалённые Git‑репозитории одновременно. - Лёгкая интеграция с существующими проектами и репозиториями.","content":"Ключевые особенности генератора **Генерация из нескольких источников**: - Локальные директории и удалённые Git‑репозитории одновременно. - Лёгкая интеграция с существующими проектами и репозиториями."},{"id":"cli/generator/generator::top::5","title":"Генератор","section":"Ключевые особенности генератора","path":"/docs/guide/cli/generator/generator","headings":["Ключевые особенности генератора"],"excerpt":"Ключевые особенности генератора **Удалённая генерация**: - Генерация из удалённых Git репозиториев без локального checkout.","content":"Ключевые особенности генератора **Удалённая генерация**: - Генерация из удалённых Git репозиториев без локального checkout."},{"id":"cli/generator/generator::top::6","title":"Генератор","section":"Ключевые особенности генератора","path":"/docs/guide/cli/generator/generator","headings":["Ключевые особенности генератора"],"excerpt":"Ключевые особенности генератора **Интеграция с менеджером пакетов**: - Прозрачная работа с зависимостями через пакетный менеджер EasyP. - Автоматическое разрешение и подключение proto‑зависимостей.","content":"Ключевые особенности генератора **Интеграция с менеджером пакетов**: - Прозрачная работа с зависимостями через пакетный менеджер EasyP. - Автоматическое разрешение и подключение proto‑зависимостей."},{"id":"cli/generator/generator::complete-configuration-example::7","title":"Генератор","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":"Генератор","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":"Генератор","section":"Complete Configuration Example","path":"/docs/guide/cli/generator/generator#complete-configuration-example","headings":["Complete Configuration Example"],"excerpt":"Complete Configuration Example Managed mode - автоматическая установка file и field опций managed: enabled: true disable: - module: github.com/googleapis/googleapis # Отключить для конкретного модуля override: - file_opt","content":"Complete Configuration Example Managed mode - автоматическая установка file и field опций managed: enabled: true disable: - module: github.com/googleapis/googleapis # Отключить для конкретного модуля 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/ # Применить к конкретному пути"},{"id":"cli/generator/generator::complete-configuration-example::10","title":"Генератор","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":"Генератор","section":"Локальный ввод (Local Directory Input)","path":"/docs/guide/cli/generator/generator#local-directory-input","headings":["Локальный ввод (Local Directory Input)"],"excerpt":"Локальный ввод (Local Directory Input) Локальная директория — самый распространённый и простой способ указать откуда брать proto для генерации. Используйте этот вариант, если файлы уже находятся в репозитории проекта.","content":"Локальный ввод (Local Directory Input) Локальная директория — самый распространённый и простой способ указать откуда брать proto для генерации. Используйте этот вариант, если файлы уже находятся в репозитории проекта."},{"id":"cli/generator/generator::local-directory-input::12","title":"Генератор","section":"Локальный ввод (Local Directory Input)","path":"/docs/guide/cli/generator/generator#local-directory-input","headings":["Локальный ввод (Local Directory Input)"],"excerpt":"Локальный ввод (Local Directory Input) **Когда применять:** Proto файлы находятся в кодовой базе проекта Нужен полный контроль над структурой каталогов Проект — один сервис или приложение Файлы меняются не слишком часто","content":"Локальный ввод (Local Directory Input) **Когда применять:** Proto файлы находятся в кодовой базе проекта Нужен полный контроль над структурой каталогов Проект — один сервис или приложение Файлы меняются не слишком часто"},{"id":"cli/generator/generator::local-directory-input::13","title":"Генератор","section":"Локальный ввод (Local Directory Input)","path":"/docs/guide/cli/generator/generator#local-directory-input","headings":["Локальный ввод (Local Directory Input)"],"excerpt":"Локальный ввод (Local Directory Input)","content":"Локальный ввод (Local Directory Input)"},{"id":"cli/generator/generator::local-directory-input::14","title":"Генератор","section":"Локальный ввод (Local Directory Input)","path":"/docs/guide/cli/generator/generator#local-directory-input","headings":["Локальный ввод (Local Directory Input)"],"excerpt":"Локальный ввод (Local Directory Input) Параметр root особенно полезен в монорепозиториях: он позволяет управлять тем, откуда будут резолвиться пути импортов. Если указать родительскую директорию, импорты будут оцениватьс","content":"Локальный ввод (Local Directory Input) Параметр root особенно полезен в монорепозиториях: он позволяет управлять тем, откуда будут резолвиться пути импортов. Если указать родительскую директорию, импорты будут оцениваться относительно неё, а не текущего рабочего каталога."},{"id":"cli/generator/generator::local-directory-input::15","title":"Генератор","section":"Локальный ввод (Local Directory Input)","path":"/docs/guide/cli/generator/generator#local-directory-input","headings":["Локальный ввод (Local Directory Input)"],"excerpt":"Локальный ввод (Local Directory Input) **Параметры:**","content":"Локальный ввод (Local Directory Input) **Параметры:**"},{"id":"cli/generator/generator::local-directory-input::16","title":"Генератор","section":"Локальный ввод (Local Directory Input)","path":"/docs/guide/cli/generator/generator#local-directory-input","headings":["Локальный ввод (Local Directory Input)"],"excerpt":"Локальный ввод (Local Directory Input) Параметр Тип Обязателен Значение по умолчанию Описание ---------- ----- ------------ ----------------------- ---------- path string ✅ - Каталог, содержащий proto файлы root string ❌","content":"Локальный ввод (Local Directory Input) Параметр Тип Обязателен Значение по умолчанию Описание ---------- ----- ------------ ----------------------- ---------- path string ✅ - Каталог, содержащий proto файлы root string ❌ \".\" Корневая директория для разрешения import путей"},{"id":"cli/generator/generator::local-directory-input::17","title":"Генератор","section":"Локальный ввод (Local Directory Input)","path":"/docs/guide/cli/generator/generator#local-directory-input","headings":["Локальный ввод (Local Directory Input)"],"excerpt":"Локальный ввод (Local Directory Input) **Примеры:**","content":"Локальный ввод (Local Directory Input) **Примеры:**"},{"id":"cli/generator/generator::local-directory-input::18","title":"Генератор","section":"Локальный ввод (Local Directory Input)","path":"/docs/guide/cli/generator/generator#local-directory-input","headings":["Локальный ввод (Local Directory Input)"],"excerpt":"Локальный ввод (Local Directory Input) Ниже показана разница между базовым указанием директории и расширенной конфигурацией с пользовательским корнем импортов:","content":"Локальный ввод (Local Directory Input) Ниже показана разница между базовым указанием директории и расширенной конфигурацией с пользовательским корнем импортов:"},{"id":"cli/generator/generator::local-directory-input::19","title":"Генератор","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::20","title":"Генератор","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::git-remote-git-repository-input::21","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) Этот тип входных данных позволяет генерировать код из proto‑файлов, находящихся в удалённых репозиториях, без локального checkout. Особенно полезно при использовани","content":"Удалённый Git репозиторий (Remote Git Repository Input) Этот тип входных данных позволяет генерировать код из proto‑файлов, находящихся в удалённых репозиториях, без локального checkout. Особенно полезно при использовании API других команд или внешних поставщиков."},{"id":"cli/generator/generator::git-remote-git-repository-input::22","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) **Когда использовать:** Потребление proto определений из других сервисов/команд Интеграция с внешними вендорскими API Работа с общими библиотеками proto в нескольки","content":"Удалённый Git репозиторий (Remote Git Repository Input) **Когда использовать:** Потребление proto определений из других сервисов/команд Интеграция с внешними вендорскими API Работа с общими библиотеками proto в нескольких проектах Необходимо гарантировать корректную (зафиксированную) версию внешних API"},{"id":"cli/generator/generator::git-remote-git-repository-input::23","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) **Рекомендации:** В продакшене всегда фиксируйте версии (@v1.0.0, а не latest) Используйте семантические версии при наличии — проще сопровождать Предпочитайте публи","content":"Удалённый Git репозиторий (Remote Git Repository Input) **Рекомендации:** В продакшене всегда фиксируйте версии (@v1.0.0, а не latest) Используйте семантические версии при наличии — проще сопровождать Предпочитайте публичные теги вместо хеша коммита (лучше отслеживаемость)"},{"id":"cli/generator/generator::git-remote-git-repository-input::24","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input)","content":"Удалённый Git репозиторий (Remote Git Repository Input)"},{"id":"cli/generator/generator::git-remote-git-repository-input::25","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) Параметр root задаёт корень для разрешения импортов файлов из этого репозитория.","content":"Удалённый Git репозиторий (Remote Git Repository Input) Параметр root задаёт корень для разрешения импортов файлов из этого репозитория."},{"id":"cli/generator/generator::git-remote-git-repository-input::26","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) **Параметры:**","content":"Удалённый Git репозиторий (Remote Git Repository Input) **Параметры:**"},{"id":"cli/generator/generator::git-remote-git-repository-input::27","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) Параметр Тип Обязателен По умолчанию Описание ---------- ----- ------------ -------------- ---------- url string ✅ - URL Git репозитория с необязательной версией / ","content":"Удалённый Git репозиторий (Remote Git Repository Input) Параметр Тип Обязателен По умолчанию Описание ---------- ----- ------------ -------------- ---------- url string ✅ - URL Git репозитория с необязательной версией / тегом / коммитом sub_directory string ❌ \"\" Поддиректория внутри репозитория, где лежат proto root string ❌ \"\" Корневой путь для разрешения импортов"},{"id":"cli/generator/generator::git-remote-git-repository-input::28","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) **Варианты формата URL:**","content":"Удалённый Git репозиторий (Remote Git Repository Input) **Варианты формата URL:**"},{"id":"cli/generator/generator::git-remote-git-repository-input::29","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) EasyP поддерживает несколько форматов для ссылки на удалённые репозитории. Каждый подходит под разные требования по стабильности:","content":"Удалённый Git репозиторий (Remote Git Repository Input) EasyP поддерживает несколько форматов для ссылки на удалённые репозитории. Каждый подходит под разные требования по стабильности:"},{"id":"cli/generator/generator::git-remote-git-repository-input::30","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) **Tagged versions** — для продакшена, стабильные неизменяемые ссылки **Semantic versions** — читаемость и управление зависимостями **Commit hashes** — доступ к конк","content":"Удалённый Git репозиторий (Remote Git Repository Input) **Tagged versions** — для продакшена, стабильные неизменяемые ссылки **Semantic versions** — читаемость и управление зависимостями **Commit hashes** — доступ к конкретному коммиту, если нет тега **Latest** — только для разработки, непредсказуемо **Full HTTPS URLs** — приватные репозитории или нестандартный хостинг"},{"id":"cli/generator/generator::git-remote-git-repository-input::31","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) ```yaml Тег — стабильно для продакшена url: \"github.com/googleapis/googleapis@common-protos-1_3_1\"","content":"Удалённый Git репозиторий (Remote Git Repository Input) ```yaml Тег — стабильно для продакшена url: \"github.com/googleapis/googleapis@common-protos-1_3_1\""},{"id":"cli/generator/generator::git-remote-git-repository-input::32","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) Семантическая версия url: \"github.com/grpc-ecosystem/grpc-gateway@v2.19.1\"","content":"Удалённый Git репозиторий (Remote Git Repository Input) Семантическая версия url: \"github.com/grpc-ecosystem/grpc-gateway@v2.19.1\""},{"id":"cli/generator/generator::git-remote-git-repository-input::33","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) Хеш коммита — точечный фикс url: \"github.com/company/protos@abc123def456\"","content":"Удалённый Git репозиторий (Remote Git Repository Input) Хеш коммита — точечный фикс url: \"github.com/company/protos@abc123def456\""},{"id":"cli/generator/generator::git-remote-git-repository-input::34","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) Latest — только dev, НЕ для продакшена url: \"github.com/company/protos\"","content":"Удалённый Git репозиторий (Remote Git Repository Input) Latest — только dev, НЕ для продакшена url: \"github.com/company/protos\""},{"id":"cli/generator/generator::git-remote-git-repository-input::35","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) Полный HTTPS URL — приватный или кастомный Git url: \"https://github.com/company/private-protos.git\" ```","content":"Удалённый Git репозиторий (Remote Git Repository Input) Полный HTTPS URL — приватный или кастомный Git url: \"https://github.com/company/private-protos.git\" ```"},{"id":"cli/generator/generator::git-remote-git-repository-input::36","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) **Примеры:**","content":"Удалённый Git репозиторий (Remote Git Repository Input) **Примеры:**"},{"id":"cli/generator/generator::git-remote-git-repository-input::37","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) Ниже паттерны использования удалённых источников в разных сценариях:","content":"Удалённый Git репозиторий (Remote Git Repository Input) Ниже паттерны использования удалённых источников в разных сценариях:"},{"id":"cli/generator/generator::git-remote-git-repository-input::38","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input)","content":"Удалённый Git репозиторий (Remote Git Repository Input)"},{"id":"cli/generator/generator::top::39","title":"Генератор","section":"Конфигурация плагинов","path":"/docs/guide/cli/generator/generator","headings":["Конфигурация плагинов"],"excerpt":"Конфигурация плагинов Конфигурация плагинов определяет какие генераторы кода будут запущены и как они себя ведут. EasyP поддерживает любой плагин protoc, что делает его крайне гибким для разных языковых экосистем и сцена","content":"Конфигурация плагинов Конфигурация плагинов определяет какие генераторы кода будут запущены и как они себя ведут. EasyP поддерживает любой плагин protoc, что делает его крайне гибким для разных языковых экосистем и сценариев."},{"id":"cli/generator/generator::top::40","title":"Генератор","section":"Конфигурация плагинов","path":"/docs/guide/cli/generator/generator","headings":["Конфигурация плагинов"],"excerpt":"Конфигурация плагинов На верхнем уровне есть **четыре способа указать, как именно запускать плагин**:","content":"Конфигурация плагинов На верхнем уровне есть **четыре способа указать, как именно запускать плагин**:"},{"id":"cli/generator/generator::top::41","title":"Генератор","section":"Конфигурация плагинов","path":"/docs/guide/cli/generator/generator","headings":["Конфигурация плагинов"],"excerpt":"Конфигурация плагинов **name** – запуск плагина по имени из PATH или использование встроенного плагина. **path** – запуск плагина по абсолютному/относительному пути к исполняемому файлу. **remote** – удалённый плагин по ","content":"Конфигурация плагинов **name** – запуск плагина по имени из PATH или использование встроенного плагина. **path** – запуск плагина по абсолютному/относительному пути к исполняемому файлу. **remote** – удалённый плагин по URL (через remote‑executor EasyP). **command** – запуск плагина через произвольную команду (например, go run ...)."},{"id":"cli/generator/generator::top::42","title":"Генератор","section":"Конфигурация плагинов","path":"/docs/guide/cli/generator/generator","headings":["Конфигурация плагинов"],"excerpt":"Конфигурация плагинов Для каждого плагина должен быть указан **ровно один** из параметров name, path, remote или command.","content":"Конфигурация плагинов Для каждого плагина должен быть указан **ровно один** из параметров name, path, remote или command."},{"id":"cli/generator/generator::name::43","title":"Генератор","section":"Плагин по имени (name)","path":"/docs/guide/cli/generator/generator#name","headings":["Плагин по имени (name)"],"excerpt":"Плагин по имени (name) Локальный режим по имени — стандартный: плагины установлены в системе и запускаются напрямую через EasyP.","content":"Плагин по имени (name) Локальный режим по имени — стандартный: плагины установлены в системе и запускаются напрямую через EasyP."},{"id":"cli/generator/generator::name::44","title":"Генератор","section":"Плагин по имени (name)","path":"/docs/guide/cli/generator/generator#name","headings":["Плагин по имени (name)"],"excerpt":"Плагин по имени (name) **Когда использовать name:** Стандартные языки (Go, Python, TypeScript и т.д.) Есть контроль над окружением сборки Критична производительность (нет сетевых задержек) Хочется опираться на PATH или в","content":"Плагин по имени (name) **Когда использовать name:** Стандартные языки (Go, Python, TypeScript и т.д.) Есть контроль над окружением сборки Критична производительность (нет сетевых задержек) Хочется опираться на PATH или встроенные плагины"},{"id":"cli/generator/generator::name::45","title":"Генератор","section":"Плагин по имени (name)","path":"/docs/guide/cli/generator/generator#name","headings":["Плагин по имени (name)"],"excerpt":"Плагин по имени (name) **Требования к установке:** Плагины установлены и доступны в PATH (если не используются встроенные). Имена следуют шаблону protoc-gen-{name}. Установка через менеджеры пакетов (go install, npm inst","content":"Плагин по имени (name) **Требования к установке:** Плагины установлены и доступны в PATH (если не используются встроенные). Имена следуют шаблону protoc-gen-{name}. Установка через менеджеры пакетов (go install, npm install, pip install и т.п.)."},{"id":"cli/generator/generator::name::46","title":"Генератор","section":"Плагин по имени (name)","path":"/docs/guide/cli/generator/generator#name","headings":["Плагин по имени (name)"],"excerpt":"Плагин по имени (name) Параметр with_imports критичен при использовании зависимостей из пакетного менеджера: установите true, чтобы прототипы из секции deps попали в генерацию.","content":"Плагин по имени (name) Параметр with_imports критичен при использовании зависимостей из пакетного менеджера: установите true, чтобы прототипы из секции deps попали в генерацию."},{"id":"cli/generator/generator::path::47","title":"Генератор","section":"Плагин по пути (path)","path":"/docs/guide/cli/generator/generator#path","headings":["Плагин по пути (path)"],"excerpt":"Плагин по пути (path) Иногда нужно запускать плагин из конкретного бинарника, не добавляя его в PATH (например, бинарь в репозитории или в build‑директории). В этом случае можно указать явный путь:","content":"Плагин по пути (path) Иногда нужно запускать плагин из конкретного бинарника, не добавляя его в PATH (например, бинарь в репозитории или в build‑директории). В этом случае можно указать явный путь:"},{"id":"cli/generator/generator::path::48","title":"Генератор","section":"Плагин по пути (path)","path":"/docs/guide/cli/generator/generator#path","headings":["Плагин по пути (path)"],"excerpt":"Плагин по пути (path) **Когда использовать path:** Бинарники плагинов хранятся в репозитории (для воспроизводимых сборок). Используются несколько версий одного и того же плагина параллельно. Не хочется «загрязнять» глоба","content":"Плагин по пути (path) **Когда использовать path:** Бинарники плагинов хранятся в репозитории (для воспроизводимых сборок). Используются несколько версий одного и того же плагина параллельно. Не хочется «загрязнять» глобальный PATH."},{"id":"cli/generator/generator::remote::49","title":"Генератор","section":"Удалённый плагин (remote)","path":"/docs/guide/cli/generator/generator#remote","headings":["Удалённый плагин (remote)"],"excerpt":"Удалённый плагин (remote) Удалённые плагины выполняются по URL. EasyP отправляет на удалённую сторону CodeGeneratorRequest и получает обратно CodeGeneratorResponse.","content":"Удалённый плагин (remote) Удалённые плагины выполняются по URL. EasyP отправляет на удалённую сторону CodeGeneratorRequest и получает обратно CodeGeneratorResponse."},{"id":"cli/generator/generator::remote::50","title":"Генератор","section":"Удалённый плагин (remote)","path":"/docs/guide/cli/generator/generator#remote","headings":["Удалённый плагин (remote)"],"excerpt":"Удалённый плагин (remote) Ниже приведён реальный пример использования EasyP API Service как удалённого исполнителя плагинов (тот же формат используется в разделе про API Service):","content":"Удалённый плагин (remote) Ниже приведён реальный пример использования EasyP API Service как удалённого исполнителя плагинов (тот же формат используется в разделе про API Service):"},{"id":"cli/generator/generator::remote::51","title":"Генератор","section":"Удалённый плагин (remote)","path":"/docs/guide/cli/generator/generator#remote","headings":["Удалённый плагин (remote)"],"excerpt":"Удалённый плагин (remote) ```yaml generate: plugins: # Удалённое выполнение плагинов через EasyP API Service - remote: api.easyp.tech/protobuf/go:v1.36.10 out: . opts: paths: source_relative","content":"Удалённый плагин (remote) ```yaml generate: plugins: # Удалённое выполнение плагинов через EasyP API Service - remote: api.easyp.tech/protobuf/go:v1.36.10 out: . opts: paths: source_relative"},{"id":"cli/generator/generator::remote::52","title":"Генератор","section":"Удалённый плагин (remote)","path":"/docs/guide/cli/generator/generator#remote","headings":["Удалённый плагин (remote)"],"excerpt":"Удалённый плагин (remote) remote: api.easyp.tech/grpc/go:v1.5.1 out: . opts: paths: source_relative ```","content":"Удалённый плагин (remote) remote: api.easyp.tech/grpc/go:v1.5.1 out: . opts: paths: source_relative ```"},{"id":"cli/generator/generator::remote::53","title":"Генератор","section":"Удалённый плагин (remote)","path":"/docs/guide/cli/generator/generator#remote","headings":["Удалённый плагин (remote)"],"excerpt":"Удалённый плагин (remote) **Типичные сценарии для remote:** Централизованный сервис плагинов внутри компании (например, EasyP API Service). Запуск тяжёлых плагинов на выделенных машинах вместо CI‑агентов. Совместное испо","content":"Удалённый плагин (remote) **Типичные сценарии для remote:** Централизованный сервис плагинов внутри компании (например, EasyP API Service). Запуск тяжёлых плагинов на выделенных машинах вместо CI‑агентов. Совместное использование одной реализации плагина разными командами."},{"id":"cli/generator/generator::command::54","title":"Генератор","section":"Выполнение плагина через команду (command)","path":"/docs/guide/cli/generator/generator#command","headings":["Выполнение плагина через команду (command)"],"excerpt":"Выполнение плагина через команду (command) Вы можете указать плагин как массив команд для выполнения. Это полезно для запуска плагинов через go run или любые другие инструменты без предварительной установки бинарника пла","content":"Выполнение плагина через команду (command) Вы можете указать плагин как массив команд для выполнения. Это полезно для запуска плагинов через go run или любые другие инструменты без предварительной установки бинарника плагина:"},{"id":"cli/generator/generator::command::55","title":"Генератор","section":"Выполнение плагина через команду (command)","path":"/docs/guide/cli/generator/generator#command","headings":["Выполнение плагина через команду (command)"],"excerpt":"Выполнение плагина через команду (command)","content":"Выполнение плагина через команду (command)"},{"id":"cli/generator/generator::command::56","title":"Генератор","section":"Выполнение плагина через команду (command)","path":"/docs/guide/cli/generator/generator#command","headings":["Выполнение плагина через команду (command)"],"excerpt":"Выполнение плагина через команду (command) В этом режиме EasyP: **запускает указанную команду** как дочерний процесс; **пишет CodeGeneratorRequest в stdin** процесса; **читает CodeGeneratorResponse из stdout**, как и для","content":"Выполнение плагина через команду (command) В этом режиме EasyP: **запускает указанную команду** как дочерний процесс; **пишет CodeGeneratorRequest в stdin** процесса; **читает CodeGeneratorResponse из stdout**, как и для обычных плагинов protoc."},{"id":"cli/generator/generator::command::57","title":"Генератор","section":"Выполнение плагина через команду (command)","path":"/docs/guide/cli/generator/generator#command","headings":["Выполнение плагина через команду (command)"],"excerpt":"Выполнение плагина через команду (command) **Приоритет источников плагина:** command — выполнение через указанную команду (наивысший приоритет) remote — удалённый плагин через URL name — локальный плагин из PATH или встр","content":"Выполнение плагина через команду (command) **Приоритет источников плагина:** command — выполнение через указанную команду (наивысший приоритет) remote — удалённый плагин через URL name — локальный плагин из PATH или встроенный плагин path — путь к исполняемому файлу плагина"},{"id":"cli/generator/generator::command::58","title":"Генератор","section":"Выполнение плагина через команду (command)","path":"/docs/guide/cli/generator/generator#command","headings":["Выполнение плагина через команду (command)"],"excerpt":"Выполнение плагина через команду (command) **Параметры (источники и общие опции плагина):**","content":"Выполнение плагина через команду (command) **Параметры (источники и общие опции плагина):**"},{"id":"cli/generator/generator::command::59","title":"Генератор","section":"Выполнение плагина через команду (command)","path":"/docs/guide/cli/generator/generator#command","headings":["Выполнение плагина через команду (command)"],"excerpt":"Выполнение плагина через команду (command) Параметр Тип Обязателен По умолчанию Описание ---------- ----- ------------ -------------- ---------- name string ❌ - Имя / идентификатор плагина (например, go, go-grpc, grpc-ga","content":"Выполнение плагина через команду (command) Параметр Тип Обязателен По умолчанию Описание ---------- ----- ------------ -------------- ---------- name string ❌ - Имя / идентификатор плагина (например, go, go-grpc, grpc-gateway) command []string ❌ - Команда для выполнения плагина (например, [\"go\", \"run\", \"package\"]) remote string ❌ - URL удалённого плагина path string ❌ - Путь к исполняемому файлу плагина out string ✅ - Директория для сгенерированных файлов opts mapstring ❌ {} Специфичные опции плагина; значения-списки передаются как повторяющиеся key=value with_imports bool ❌ false Включать proto из зависимостей"},{"id":"cli/generator/generator::command::60","title":"Генератор","section":"Выполнение плагина через команду (command)","path":"/docs/guide/cli/generator/generator#command","headings":["Выполнение плагина через команду (command)"],"excerpt":"Выполнение плагина через команду (command) **Примечание:** Для каждого плагина должен быть указан ровно один источник (name, command, remote или path). Если opts.outputServices задан как [\"grpc-js\", \"generic-definitions\"","content":"Выполнение плагина через команду (command) **Примечание:** Для каждого плагина должен быть указан ровно один источник (name, command, remote или path). Если opts.outputServices задан как [\"grpc-js\", \"generic-definitions\"], EasyP передаст outputServices=grpc-js,outputServices=generic-definitions."},{"id":"cli/generator/generator::command::61","title":"Генератор","section":"Выполнение плагина через команду (command)","path":"/docs/guide/cli/generator/generator#command","headings":["Выполнение плагина через команду (command)"],"excerpt":"Выполнение плагина через команду (command) **Примеры использования источника command:**","content":"Выполнение плагина через команду (command) **Примеры использования источника command:**"},{"id":"cli/generator/generator::command::62","title":"Генератор","section":"Выполнение плагина через команду (command)","path":"/docs/guide/cli/generator/generator#command","headings":["Выполнение плагина через команду (command)"],"excerpt":"Выполнение плагина через команду (command) ```yaml generate: inputs: - directory: \"proto\"","content":"Выполнение плагина через команду (command) ```yaml generate: inputs: - directory: \"proto\""},{"id":"cli/generator/generator::command::63","title":"Генератор","section":"Выполнение плагина через команду (command)","path":"/docs/guide/cli/generator/generator#command","headings":["Выполнение плагина через команду (command)"],"excerpt":"Выполнение плагина через команду (command) plugins: # 1) gRPC-Gateway через go run (без предварительной установки бинарника) - command: [\"go\", \"run\", \"github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway@v2.","content":"Выполнение плагина через команду (command) plugins: # 1) gRPC-Gateway через go run (без предварительной установки бинарника) - 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::command::64","title":"Генератор","section":"Выполнение плагина через команду (command)","path":"/docs/guide/cli/generator/generator#command","headings":["Выполнение плагина через команду (command)"],"excerpt":"Выполнение плагина через команду (command) 2) protoc-gen-validate через go run - command: [\"go\", \"run\", \"github.com/bufbuild/protoc-gen-validate@v0.10.1\"] out: ./gen/go opts: paths: source_relative lang: go","content":"Выполнение плагина через команду (command) 2) protoc-gen-validate через 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::command::65","title":"Генератор","section":"Выполнение плагина через команду (command)","path":"/docs/guide/cli/generator/generator#command","headings":["Выполнение плагина через команду (command)"],"excerpt":"Выполнение плагина через команду (command) 3) Произвольный кастомный скрипт-обёртка - command: [\"bash\", \"./scripts/custom-protoc-plugin.sh\"] out: ./gen/custom opts: foo: bar ```","content":"Выполнение плагина через команду (command) 3) Произвольный кастомный скрипт-обёртка - command: [\"bash\", \"./scripts/custom-protoc-plugin.sh\"] out: ./gen/custom opts: foo: bar ```"},{"id":"cli/generator/generator::builtin-plugins::66","title":"Генератор","section":"Встроенные плагины (Builtin Plugins)","path":"/docs/guide/cli/generator/generator#builtin-plugins","headings":["Встроенные плагины (Builtin Plugins)"],"excerpt":"Встроенные плагины (Builtin Plugins) EasyP поддерживает встроенные плагины для базовых языков protobuf и gRPC. Эти плагины встроены в бинарник как WASM-модули и не требуют установки внешних зависимостей.","content":"Встроенные плагины (Builtin Plugins) EasyP поддерживает встроенные плагины для базовых языков protobuf и gRPC. Эти плагины встроены в бинарник как WASM-модули и не требуют установки внешних зависимостей."},{"id":"cli/generator/generator::builtin-plugins::67","title":"Генератор","section":"Встроенные плагины (Builtin Plugins)","path":"/docs/guide/cli/generator/generator#builtin-plugins","headings":["Встроенные плагины (Builtin Plugins)"],"excerpt":"Встроенные плагины (Builtin Plugins) **Преимущества встроенных плагинов:** **Портативность**: Один бинарник со всеми необходимыми плагинами **Удобство**: Не требуется установка внешних зависимостей **Стабильность**: Верс","content":"Встроенные плагины (Builtin Plugins) **Преимущества встроенных плагинов:** **Портативность**: Один бинарник со всеми необходимыми плагинами **Удобство**: Не требуется установка внешних зависимостей **Стабильность**: Версии плагинов зафиксированы в бинарнике **Изоляция**: Не зависит от системных установок плагинов"},{"id":"cli/generator/generator::builtin-plugins::68","title":"Генератор","section":"Встроенные плагины (Builtin Plugins)","path":"/docs/guide/cli/generator/generator#builtin-plugins","headings":["Встроенные плагины (Builtin Plugins)"],"excerpt":"Встроенные плагины (Builtin Plugins) **Поддерживаемые встроенные плагины:**","content":"Встроенные плагины (Builtin Plugins) **Поддерживаемые встроенные плагины:**"},{"id":"cli/generator/generator::protobuf::69","title":"Генератор","section":"Protobuf базовые плагины","path":"/docs/guide/cli/generator/generator#protobuf","headings":["Protobuf базовые плагины"],"excerpt":"Protobuf базовые плагины Следующие плагины встроены для генерации базового protobuf кода:","content":"Protobuf базовые плагины Следующие плагины встроены для генерации базового protobuf кода:"},{"id":"cli/generator/generator::protobuf::70","title":"Генератор","section":"Protobuf базовые плагины","path":"/docs/guide/cli/generator/generator#protobuf","headings":["Protobuf базовые плагины"],"excerpt":"Protobuf базовые плагины Имя плагина Описание Соответствующий protoc плагин ------------- ---------- ------------------------------- cpp Генерация C++ кода из proto файлов protoc-gen-cpp csharp Генерация C# кода из proto","content":"Protobuf базовые плагины Имя плагина Описание Соответствующий protoc плагин ------------- ---------- ------------------------------- cpp Генерация C++ кода из proto файлов protoc-gen-cpp csharp Генерация C# кода из proto файлов protoc-gen-csharp java Генерация Java кода из proto файлов protoc-gen-java kotlin Генерация Kotlin кода из proto файлов protoc-gen-kotlin objc Генерация Objective-C кода из proto файлов protoc-gen-objc php Генерация PHP кода из proto файлов protoc-gen-php python Генерация Python кода из proto файлов protoc-gen-python ruby Генерация Ruby кода из proto файлов protoc-gen-ruby"},{"id":"cli/generator/generator::grpc::71","title":"Генератор","section":"gRPC плагины","path":"/docs/guide/cli/generator/generator#grpc","headings":["gRPC плагины"],"excerpt":"gRPC плагины Следующие плагины встроены для генерации gRPC кода:","content":"gRPC плагины Следующие плагины встроены для генерации gRPC кода:"},{"id":"cli/generator/generator::grpc::72","title":"Генератор","section":"gRPC плагины","path":"/docs/guide/cli/generator/generator#grpc","headings":["gRPC плагины"],"excerpt":"gRPC плагины Имя плагина Описание Соответствующий protoc плагин ------------- ---------- ------------------------------- grpc_cpp Генерация gRPC кода для C++ grpc_cpp_plugin grpc_csharp Генерация gRPC кода для C# grpc_cs","content":"gRPC плагины Имя плагина Описание Соответствующий protoc плагин ------------- ---------- ------------------------------- grpc_cpp Генерация gRPC кода для C++ grpc_cpp_plugin grpc_csharp Генерация gRPC кода для C# grpc_csharp_plugin grpc_java Генерация gRPC кода для Java grpc_java_plugin grpc_node Генерация gRPC кода для Node.js grpc_node_plugin grpc_objc Генерация gRPC кода для Objective-C grpc_objective_c_plugin grpc_php Генерация gRPC кода для PHP grpc_php_plugin grpc_python Генерация gRPC кода для Python grpc_python_plugin grpc_ruby Генерация gRPC кода для Ruby grpc_ruby_plugin"},{"id":"cli/generator/generator::grpc::73","title":"Генератор","section":"gRPC плагины","path":"/docs/guide/cli/generator/generator#grpc","headings":["gRPC плагины"],"excerpt":"gRPC плагины **Логика выбора плагина:**","content":"gRPC плагины **Логика выбора плагина:**"},{"id":"cli/generator/generator::grpc::74","title":"Генератор","section":"gRPC плагины","path":"/docs/guide/cli/generator/generator#grpc","headings":["gRPC плагины"],"excerpt":"gRPC плагины EasyP использует следующий приоритет при выборе executor'а для плагина:","content":"gRPC плагины EasyP использует следующий приоритет при выборе executor'а для плагина:"},{"id":"cli/generator/generator::grpc::75","title":"Генератор","section":"gRPC плагины","path":"/docs/guide/cli/generator/generator#grpc","headings":["gRPC плагины"],"excerpt":"gRPC плагины **Удалённый плагин** (если указан url) — всегда имеет наивысший приоритет **Встроенный плагин** (если плагин встроен и не найден в PATH) — используется автоматически **Локальный плагин** (из PATH) — использу","content":"gRPC плагины **Удалённый плагин** (если указан url) — всегда имеет наивысший приоритет **Встроенный плагин** (если плагин встроен и не найден в PATH) — используется автоматически **Локальный плагин** (из PATH) — используется по умолчанию для обратной совместимости"},{"id":"cli/generator/generator::grpc::76","title":"Генератор","section":"gRPC плагины","path":"/docs/guide/cli/generator/generator#grpc","headings":["gRPC плагины"],"excerpt":"gRPC плагины **Пример использования:**","content":"gRPC плагины **Пример использования:**"},{"id":"cli/generator/generator::grpc::77","title":"Генератор","section":"gRPC плагины","path":"/docs/guide/cli/generator/generator#grpc","headings":["gRPC плагины"],"excerpt":"gRPC плагины Встроенные плагины включены в бинарник EasyP:","content":"gRPC плагины Встроенные плагины включены в бинарник EasyP:"},{"id":"cli/generator/generator::grpc::78","title":"Генератор","section":"gRPC плагины","path":"/docs/guide/cli/generator/generator#grpc","headings":["gRPC плагины"],"excerpt":"gRPC плагины ```bash Сборка go build ./cmd/easyp","content":"gRPC плагины ```bash Сборка go build ./cmd/easyp"},{"id":"cli/generator/generator::grpc::79","title":"Генератор","section":"gRPC плагины","path":"/docs/guide/cli/generator/generator#grpc","headings":["gRPC плагины"],"excerpt":"gRPC плагины Установка go install github.com/easyp-tech/easyp/cmd/easyp@latest ```","content":"gRPC плагины Установка go install github.com/easyp-tech/easyp/cmd/easyp@latest ```"},{"id":"cli/generator/generator::grpc::80","title":"Генератор","section":"gRPC плагины","path":"/docs/guide/cli/generator/generator#grpc","headings":["gRPC плагины"],"excerpt":"gRPC плагины **Обратная совместимость:**","content":"gRPC плагины **Обратная совместимость:**"},{"id":"cli/generator/generator::grpc::81","title":"Генератор","section":"gRPC плагины","path":"/docs/guide/cli/generator/generator#grpc","headings":["gRPC плагины"],"excerpt":"gRPC плагины Встроенные плагины полностью совместимы с существующими конфигурациями. Если плагин найден в PATH, он будет использован вместо встроенного. Это гарантирует, что:","content":"gRPC плагины Встроенные плагины полностью совместимы с существующими конфигурациями. Если плагин найден в PATH, он будет использован вместо встроенного. Это гарантирует, что:"},{"id":"cli/generator/generator::grpc::82","title":"Генератор","section":"gRPC плагины","path":"/docs/guide/cli/generator/generator#grpc","headings":["gRPC плагины"],"excerpt":"gRPC плагины Существующие конфигурации продолжают работать без изменений Можно переопределить встроенный плагин, установив его в системе Приоритет отдаётся локальным установкам для гибкости","content":"gRPC плагины Существующие конфигурации продолжают работать без изменений Можно переопределить встроенный плагин, установив его в системе Приоритет отдаётся локальным установкам для гибкости"},{"id":"cli/generator/generator::top::83","title":"Генератор","section":"Справочник опций плагинов","path":"/docs/guide/cli/generator/generator","headings":["Справочник опций плагинов"],"excerpt":"Справочник опций плагинов Ниже перечислены наиболее часто используемые плагины и их настройки. Каждый плагин имеет параметры, влияющие на результат генерации — понимание этих опций важно для получения нужного вывода.","content":"Справочник опций плагинов Ниже перечислены наиболее часто используемые плагины и их настройки. Каждый плагин имеет параметры, влияющие на результат генерации — понимание этих опций важно для получения нужного вывода."},{"id":"cli/generator/generator::go-plugins::84","title":"Генератор","section":"Go Plugins","path":"/docs/guide/cli/generator/generator#go-plugins","headings":["Go Plugins"],"excerpt":"Go Plugins Плагины для Go — самые зрелые и распространённые. Опция paths управляет тем, как формируются пути импортов; остальные опции дают тонкую настройку вывода.","content":"Go Plugins Плагины для Go — самые зрелые и распространённые. Опция paths управляет тем, как формируются пути импортов; остальные опции дают тонкую настройку вывода."},{"id":"cli/generator/generator::grpc-gateway-plugins::85","title":"Генератор","section":"gRPC-Gateway Plugins","path":"/docs/guide/cli/generator/generator#grpc-gateway-plugins","headings":["gRPC-Gateway Plugins"],"excerpt":"gRPC-Gateway Plugins Позволяют экспонировать gRPC сервисы как REST API и генерировать OpenAPI. Критично для HTTP/JSON поверх gRPC.","content":"gRPC-Gateway Plugins Позволяют экспонировать gRPC сервисы как REST API и генерировать OpenAPI. Критично для HTTP/JSON поверх gRPC."},{"id":"cli/generator/generator::validation-plugins::86","title":"Генератор","section":"Validation Plugins","path":"/docs/guide/cli/generator/generator#validation-plugins","headings":["Validation Plugins"],"excerpt":"Validation Plugins Генерируют код валидации на основе правил в proto, устраняя ручную проверку.","content":"Validation Plugins Генерируют код валидации на основе правил в proto, устраняя ручную проверку."},{"id":"cli/generator/generator::typescriptjavascript-plugins::87","title":"Генератор","section":"TypeScript/JavaScript Plugins","path":"/docs/guide/cli/generator/generator#typescriptjavascript-plugins","headings":["TypeScript/JavaScript Plugins"],"excerpt":"TypeScript/JavaScript Plugins TypeScript плагины нужны фронтенду: типобезопасные интерфейсы и клиенты.","content":"TypeScript/JavaScript Plugins TypeScript плагины нужны фронтенду: типобезопасные интерфейсы и клиенты."},{"id":"cli/generator/generator::managed-mode::88","title":"Генератор","section":"Managed Mode","path":"/docs/guide/cli/generator/generator#managed-mode","headings":["Managed Mode"],"excerpt":"Managed Mode Managed mode автоматически устанавливает file и field опции в protobuf дескрипторах во время генерации кода без изменения исходных .proto файлов. Эта функция совместима с managed mode в buf и обеспечивает ед","content":"Managed Mode Managed mode автоматически устанавливает file и field опции в protobuf дескрипторах во время генерации кода без изменения исходных .proto файлов. Эта функция совместима с managed mode в buf и обеспечивает единообразный способ управления языково-специфичными опциями в вашей кодовой базе."},{"id":"cli/generator/generator::managed-mode::89","title":"Генератор","section":"Managed Mode","path":"/docs/guide/cli/generator/generator#managed-mode","headings":["Managed Mode"],"excerpt":"Managed Mode **Ключевые преимущества:** **Без изменений proto файлов**: Опции применяются во время генерации, proto файлы остаются чистыми **Согласованные значения по умолчанию**: Автоматическое применение языковых согла","content":"Managed Mode **Ключевые преимущества:** **Без изменений proto файлов**: Опции применяются во время генерации, proto файлы остаются чистыми **Согласованные значения по умолчанию**: Автоматическое применение языковых соглашений об именовании **Централизованная конфигурация**: Управление всеми опциями в одном месте (easyp.yaml) **Правила для модулей**: Применение разных опций к разным модулям или путям **Совместимость с buf**: Работает так же, как managed mode в buf"},{"id":"cli/generator/generator::top::90","title":"Генератор","section":"Как это работает","path":"/docs/guide/cli/generator/generator","headings":["Как это работает"],"excerpt":"Как это работает Когда managed mode включён, EasyP автоматически применяет file и field опции к protobuf дескрипторам перед генерацией кода. Это происходит в памяти, поэтому исходные .proto файлы остаются неизменными.","content":"Как это работает Когда managed mode включён, EasyP автоматически применяет file и field опции к protobuf дескрипторам перед генерацией кода. Это происходит в памяти, поэтому исходные .proto файлы остаются неизменными."},{"id":"cli/generator/generator::top::91","title":"Генератор","section":"Как это работает","path":"/docs/guide/cli/generator/generator","headings":["Как это работает"],"excerpt":"Как это работает **Значения по умолчанию** применяются для определённых опций на основе языковых соглашений: Java: java_package_prefix по умолчанию \"com\", java_multiple_files по умолчанию true C#: csharp_namespace по умо","content":"Как это работает **Значения по умолчанию** применяются для определённых опций на основе языковых соглашений: Java: java_package_prefix по умолчанию \"com\", java_multiple_files по умолчанию true C#: csharp_namespace по умолчанию PascalCase имени пакета Ruby: ruby_package по умолчанию PascalCase с разделителем :: PHP: php_namespace по умолчанию PascalCase с разделителем \\ Objective-C: objc_class_prefix по умолчанию первые буквы частей пакета C++: cc_enable_arenas по умолчанию true"},{"id":"cli/generator/generator::top::92","title":"Генератор","section":"Как это работает","path":"/docs/guide/cli/generator/generator","headings":["Как это работает"],"excerpt":"Как это работает **Overrides** позволяют установить конкретные значения для опций с поддержкой фильтрации по модулю, пути или полю. Если не указаны module и path, override применяется ко всем файлам в запросе генерации, ","content":"Как это работает **Overrides** позволяют установить конкретные значения для опций с поддержкой фильтрации по модулю, пути или полю. Если не указаны module и path, override применяется ко всем файлам в запросе генерации, включая зависимости и git_repo inputs."},{"id":"cli/generator/generator::top::93","title":"Генератор","section":"Как это работает","path":"/docs/guide/cli/generator/generator","headings":["Как это работает"],"excerpt":"Как это работает **Disables** позволяют предотвратить изменение managed mode определённых опций или файлов. Это рекомендуемый способ исключить внешние зависимости, у которых свои опции уже заданы.","content":"Как это работает **Disables** позволяют предотвратить изменение managed mode определённых опций или файлов. Это рекомендуемый способ исключить внешние зависимости, у которых свои опции уже заданы."},{"id":"cli/generator/generator::file-options::94","title":"Генератор","section":"Поддерживаемые File Options","path":"/docs/guide/cli/generator/generator#file-options","headings":["Поддерживаемые File Options"],"excerpt":"Поддерживаемые File Options Опция Описание Есть значение по умолчанию? ------- ---------- ---------------------------- go_package Go import path ❌ go_package_prefix Префикс для Go import paths ❌ java_package Имя Java пак","content":"Поддерживаемые File Options Опция Описание Есть значение по умолчанию? ------- ---------- ---------------------------- go_package Go import path ❌ go_package_prefix Префикс для Go import paths ❌ java_package Имя Java пакета ❌ java_package_prefix Префикс для Java пакетов ✅ (\"com\") java_package_suffix Суффикс для Java пакетов ❌ java_multiple_files Генерировать несколько Java файлов ✅ (true) java_outer_classname Имя внешнего класса ✅ (PascalCase + \"Proto\") java_string_check_utf8 UTF-8 валидация ❌ csharp_namespace C# namespace ✅ (PascalCase) csharp_namespace_prefix Префикс для C# namespaces ❌ ruby_package Имя Ruby модуля ✅ (PascalCase с ::) ruby_package_suffix Суффикс для Ruby пакетов ❌ php_namespace PHP namespace ✅ (PascalCase с \\) php_metadata_namespace PHP metadata namespace ❌ php_metadata_namespace_suffix Суффикс для PHP metadata ❌ objc_class_prefix Objective-C префикс класса ✅ (Первые буквы) swift_prefix Swift префикс ❌ optimize_for Оптимизация генерации кода ❌ cc_enable_arenas C++ arena аллокация ✅ (true)"},{"id":"cli/generator/generator::field-options::95","title":"Генератор","section":"Поддерживаемые Field Options","path":"/docs/guide/cli/generator/generator#field-options","headings":["Поддерживаемые Field Options"],"excerpt":"Поддерживаемые Field Options Опция Описание Применяется к ------- ---------- --------------- jstype JavaScript тип для 64-битных целых чисел int64, uint64, sint64, fixed64, sfixed64","content":"Поддерживаемые Field Options Опция Описание Применяется к ------- ---------- --------------- jstype JavaScript тип для 64-битных целых чисел int64, uint64, sint64, fixed64, sfixed64"},{"id":"cli/generator/generator::top::96","title":"Генератор","section":"Базовая настройка со значениями по умолчанию","path":"/docs/guide/cli/generator/generator","headings":["Базовая настройка со значениями по умолчанию"],"excerpt":"Базовая настройка со значениями по умолчанию Включите managed mode для получения автоматических значений по умолчанию для всех поддерживаемых языков:","content":"Базовая настройка со значениями по умолчанию Включите managed mode для получения автоматических значений по умолчанию для всех поддерживаемых языков:"},{"id":"cli/generator/generator::top::97","title":"Генератор","section":"Базовая настройка со значениями по умолчанию","path":"/docs/guide/cli/generator/generator","headings":["Базовая настройка со значениями по умолчанию"],"excerpt":"Базовая настройка со значениями по умолчанию","content":"Базовая настройка со значениями по умолчанию"},{"id":"cli/generator/generator::top::98","title":"Генератор","section":"Базовая настройка со значениями по умолчанию","path":"/docs/guide/cli/generator/generator","headings":["Базовая настройка со значениями по умолчанию"],"excerpt":"Базовая настройка со значениями по умолчанию Это автоматически установит: java_package в com. для всех файлов java_multiple_files в true csharp_namespace в PascalCase имени пакета ruby_package в PascalCase с разделителем","content":"Базовая настройка со значениями по умолчанию Это автоматически установит: java_package в com. для всех файлов java_multiple_files в true csharp_namespace в PascalCase имени пакета ruby_package в PascalCase с разделителем :: И многое другое..."},{"id":"cli/generator/generator::go::99","title":"Генератор","section":"Кастомный префикс Go пакета","path":"/docs/guide/cli/generator/generator#go","headings":["Кастомный префикс Go пакета"],"excerpt":"Кастомный префикс Go пакета Переопределите префикс Go пакета для вашего проекта:","content":"Кастомный префикс Go пакета Переопределите префикс Go пакета для вашего проекта:"},{"id":"cli/generator/generator::go::100","title":"Генератор","section":"Кастомный префикс Go пакета","path":"/docs/guide/cli/generator/generator#go","headings":["Кастомный префикс Go пакета"],"excerpt":"Кастомный префикс Go пакета Это установит go_package в github.com/mycompany/myproject/gen/go/ для всех файлов.","content":"Кастомный префикс Go пакета Это установит go_package в github.com/mycompany/myproject/gen/go/ для всех файлов."},{"id":"cli/generator/generator::go::101","title":"Генератор","section":"Динамические пути Go пакетов с маркерами","path":"/docs/guide/cli/generator/generator#go","headings":["Динамические пути Go пакетов с маркерами"],"excerpt":"Динамические пути Go пакетов с маркерами Для более сложной генерации путей можно использовать маркеры в значениях go_package_prefix или go_package:","content":"Динамические пути Go пакетов с маркерами Для более сложной генерации путей можно использовать маркеры в значениях go_package_prefix или go_package:"},{"id":"cli/generator/generator::go::102","title":"Генератор","section":"Динамические пути Go пакетов с маркерами","path":"/docs/guide/cli/generator/generator#go","headings":["Динамические пути Go пакетов с маркерами"],"excerpt":"Динамические пути Go пакетов с маркерами","content":"Динамические пути Go пакетов с маркерами"},{"id":"cli/generator/generator::go::103","title":"Генератор","section":"Динамические пути Go пакетов с маркерами","path":"/docs/guide/cli/generator/generator#go","headings":["Динамические пути Go пакетов с маркерами"],"excerpt":"Динамические пути Go пакетов с маркерами **Доступные маркеры:** {{file_path}} - Полный путь файла без расширения .proto - Пример: internal/cms/as.proto → internal/cms/as {{file_dir}} - Только путь директории, без имени ф","content":"Динамические пути Go пакетов с маркерами **Доступные маркеры:** {{file_path}} - Полный путь файла без расширения .proto - Пример: internal/cms/as.proto → internal/cms/as {{file_dir}} - Только путь директории, без имени файла - Пример: internal/cms/as.proto → internal/cms {{file_dir_without:prefix/}} - Путь директории с удалением префикса и базового имени файла без суффиксов _service/_grpc - Пример: {{file_dir_without:internal/}} для internal/cms/as_service.proto → cms/as {{file_path_without:prefix/}} - Полный путь файла с удалением префикса - Пример: {{file_path_without:internal/}} для internal/cms/as.proto → cms/as"},{"id":"cli/generator/generator::top::104","title":"Генератор","section":"Переопределения для конкретных модулей","path":"/docs/guide/cli/generator/generator","headings":["Переопределения для конкретных модулей"],"excerpt":"Переопределения для конкретных модулей Примените разные опции к разным модулям:","content":"Переопределения для конкретных модулей Примените разные опции к разным модулям:"},{"id":"cli/generator/generator::top::105","title":"Генератор","section":"Переопределения для конкретных модулей","path":"/docs/guide/cli/generator/generator","headings":["Переопределения для конкретных модулей"],"excerpt":"Переопределения для конкретных модулей","content":"Переопределения для конкретных модулей"},{"id":"cli/generator/generator::top::106","title":"Генератор","section":"Переопределения для конкретных модулей","path":"/docs/guide/cli/generator/generator","headings":["Переопределения для конкретных модулей"],"excerpt":"Переопределения для конкретных модулей module должен точно совпадать с источником модуля в EasyP: это значение из deps или git_repo.url до @version (например, github.com/mycompany/internal-protos или https://github.com/m","content":"Переопределения для конкретных модулей module должен точно совпадать с источником модуля в EasyP: это значение из deps или git_repo.url до @version (например, github.com/mycompany/internal-protos или https://github.com/mycompany/internal-protos). Это не Go module path из go.mod."},{"id":"cli/generator/generator::top::107","title":"Генератор","section":"Отключение для внешних зависимостей","path":"/docs/guide/cli/generator/generator","headings":["Отключение для внешних зависимостей"],"excerpt":"Отключение для внешних зависимостей Отключите managed mode для внешних зависимостей, у которых уже установлены опции:","content":"Отключение для внешних зависимостей Отключите managed mode для внешних зависимостей, у которых уже установлены опции:"},{"id":"cli/generator/generator::top::108","title":"Генератор","section":"Отключение для внешних зависимостей","path":"/docs/guide/cli/generator/generator","headings":["Отключение для внешних зависимостей"],"excerpt":"Отключение для внешних зависимостей","content":"Отключение для внешних зависимостей"},{"id":"cli/generator/generator::javascript::109","title":"Генератор","section":"Типобезопасность JavaScript","path":"/docs/guide/cli/generator/generator#javascript","headings":["Типобезопасность JavaScript"],"excerpt":"Типобезопасность JavaScript Установите jstype в JS_STRING для всех 64-битных целочисленных полей, чтобы предотвратить потерю точности в JavaScript:","content":"Типобезопасность JavaScript Установите jstype в JS_STRING для всех 64-битных целочисленных полей, чтобы предотвратить потерю точности в JavaScript:"},{"id":"cli/generator/generator::top::110","title":"Генератор","section":"Совпадение путей","path":"/docs/guide/cli/generator/generator","headings":["Совпадение путей"],"excerpt":"Совпадение путей Совпадение путей в managed mode использует префиксное совпадение (как в buf):","content":"Совпадение путей Совпадение путей в managed mode использует префиксное совпадение (как в buf):"},{"id":"cli/generator/generator::top::111","title":"Генератор","section":"Совпадение путей","path":"/docs/guide/cli/generator/generator","headings":["Совпадение путей"],"excerpt":"Совпадение путей **Путь директории** (заканчивается на /): Совпадает со всеми файлами в этой директории и поддиректориях - Пример: path: \"internal/cms/\" совпадает с internal/cms/as.proto, internal/cms/node.proto, interna","content":"Совпадение путей **Путь директории** (заканчивается на /): Совпадает со всеми файлами в этой директории и поддиректориях - Пример: path: \"internal/cms/\" совпадает с internal/cms/as.proto, internal/cms/node.proto, internal/cms/v1/service.proto **Точный путь файла** (заканчивается на .proto): Совпадает только с этим конкретным файлом - Пример: path: \"internal/cms/as.proto\" совпадает только с internal/cms/as.proto **Префиксный путь** (без завершающего / или .proto): Использует префиксное совпадение (не директориально-осознанное) - Пример: path: \"internal/cms\" совпадает с internal/cms/as.proto, но также с internal/cmsv2/file.proto - **Совет**: Используйте префиксные пути для группировки нескольких файлов с одинаковым значением. Например, path: \"internal/cms/bmi\" совпадает и с internal/cms/bmi.proto, и с internal/cms/bmi_service.proto, что позволяет установить одно и то же значение go_package для обоих файлов одним правилом."},{"id":"cli/generator/generator::top::112","title":"Генератор","section":"Приоритет правил","path":"/docs/guide/cli/generator/generator","headings":["Приоритет правил"],"excerpt":"Приоритет правил Когда несколько правил соответствуют одному файлу или полю, применяется следующий приоритет:","content":"Приоритет правил Когда несколько правил соответствуют одному файлу или полю, применяется следующий приоритет:"},{"id":"cli/generator/generator::top::113","title":"Генератор","section":"Приоритет правил","path":"/docs/guide/cli/generator/generator","headings":["Приоритет правил"],"excerpt":"Приоритет правил **Disable правила** имеют приоритет — если опция отключена, она не будет применена **Override правила** применяются по порядку — последнее совпадающее правило побеждает **Значения по умолчанию** применяю","content":"Приоритет правил **Disable правила** имеют приоритет — если опция отключена, она не будет применена **Override правила** применяются по порядку — последнее совпадающее правило побеждает **Значения по умолчанию** применяются только если нет совпадающего override и опция не отключена"},{"id":"cli/generator/generator::buf::114","title":"Генератор","section":"Совместимость с buf","path":"/docs/guide/cli/generator/generator#buf","headings":["Совместимость с buf"],"excerpt":"Совместимость с buf Managed mode в EasyP совместим с managed mode в buf. Тот же формат конфигурации и поведение применяются, что упрощает миграцию между инструментами или использование обоих в одном workflow.","content":"Совместимость с buf Managed mode в EasyP совместим с managed mode в buf. Тот же формат конфигурации и поведение применяются, что упрощает миграцию между инструментами или использование обоих в одном workflow."},{"id":"cli/generator/generator::descriptor-set::115","title":"Генератор","section":"Генерация Descriptor Set","path":"/docs/guide/cli/generator/generator#descriptor-set","headings":["Генерация Descriptor Set"],"excerpt":"Генерация Descriptor Set **https://protobuf.dev/programming-guides/techniques/#self-description**","content":"Генерация Descriptor Set **https://protobuf.dev/programming-guides/techniques/#self-description**"},{"id":"cli/generator/generator::descriptor-set::116","title":"Генератор","section":"Генерация Descriptor Set","path":"/docs/guide/cli/generator/generator#descriptor-set","headings":["Генерация Descriptor Set"],"excerpt":"Генерация Descriptor Set EasyP поддерживает генерацию бинарных FileDescriptorSet файлов с помощью флага --descriptor_set_out. Это позволяет создавать самоописывающиеся protobuf сообщения, которые включают информацию о сх","content":"Генерация Descriptor Set EasyP поддерживает генерацию бинарных FileDescriptorSet файлов с помощью флага --descriptor_set_out. Это позволяет создавать самоописывающиеся protobuf сообщения, которые включают информацию о схеме вместе с данными."},{"id":"cli/generator/generator::descriptor-set::117","title":"Генератор","section":"Генерация Descriptor Set","path":"/docs/guide/cli/generator/generator#descriptor-set","headings":["Генерация Descriptor Set"],"excerpt":"Генерация Descriptor Set **Флаги CLI:**","content":"Генерация Descriptor Set **Флаги CLI:**"},{"id":"cli/generator/generator::descriptor-set::118","title":"Генератор","section":"Генерация Descriptor Set","path":"/docs/guide/cli/generator/generator#descriptor-set","headings":["Генерация Descriptor Set"],"excerpt":"Генерация Descriptor Set --descriptor_set_out - Путь для вывода бинарного FileDescriptorSet --include_imports - Включить все транзитивные зависимости в FileDescriptorSet","content":"Генерация Descriptor Set --descriptor_set_out - Путь для вывода бинарного FileDescriptorSet --include_imports - Включить все транзитивные зависимости в FileDescriptorSet"},{"id":"cli/generator/generator::descriptor-set::119","title":"Генератор","section":"Генерация Descriptor Set","path":"/docs/guide/cli/generator/generator#descriptor-set","headings":["Генерация Descriptor Set"],"excerpt":"Генерация Descriptor Set **Пример:**","content":"Генерация Descriptor Set **Пример:**"},{"id":"cli/generator/generator::descriptor-set::120","title":"Генератор","section":"Генерация Descriptor Set","path":"/docs/guide/cli/generator/generator#descriptor-set","headings":["Генерация Descriptor Set"],"excerpt":"Генерация Descriptor Set ```bash Генерация descriptor set только с целевыми файлами easyp generate --descriptor_set_out=./schema.pb","content":"Генерация Descriptor Set ```bash Генерация descriptor set только с целевыми файлами easyp generate --descriptor_set_out=./schema.pb"},{"id":"cli/generator/generator::descriptor-set::121","title":"Генератор","section":"Генерация Descriptor Set","path":"/docs/guide/cli/generator/generator#descriptor-set","headings":["Генерация Descriptor Set"],"excerpt":"Генерация Descriptor Set Генерация descriptor set со всеми зависимостями easyp generate --descriptor_set_out=./schema.pb --include_imports ```","content":"Генерация Descriptor Set Генерация descriptor set со всеми зависимостями easyp generate --descriptor_set_out=./schema.pb --include_imports ```"},{"id":"cli/generator/generator::descriptor-set::122","title":"Генератор","section":"Генерация Descriptor Set","path":"/docs/guide/cli/generator/generator#descriptor-set","headings":["Генерация Descriptor Set"],"excerpt":"Генерация Descriptor Set Самоописывающиеся сообщения полезны для динамического парсинга сообщений, валидации схемы во время выполнения, реестров схем и создания универсальных gRPC клиентов. Для получения дополнительной и","content":"Генерация Descriptor Set Самоописывающиеся сообщения полезны для динамического парсинга сообщений, валидации схемы во время выполнения, реестров схем и создания универсальных gRPC клиентов. Для получения дополнительной информации см. документацию Protocol Buffers о самоописании."},{"id":"cli/generator/generator::top::123","title":"Генератор","section":"Интеграция с менеджером пакетов","path":"/docs/guide/cli/generator/generator","headings":["Интеграция с менеджером пакетов"],"excerpt":"Интеграция с менеджером пакетов Одной из самых мощных возможностей EasyP является бесшовная интеграция генератора кода с менеджером пакетов. Это устраняет проблему ручного управления proto‑зависимостями и гарантирует, чт","content":"Интеграция с менеджером пакетов Одной из самых мощных возможностей EasyP является бесшовная интеграция генератора кода с менеджером пакетов. Это устраняет проблему ручного управления proto‑зависимостями и гарантирует, что при генерации используются корректные (зафиксированные) версии импортируемых файлов."},{"id":"cli/generator/generator::top::124","title":"Генератор","section":"Интеграция с менеджером пакетов","path":"/docs/guide/cli/generator/generator","headings":["Интеграция с менеджером пакетов"],"excerpt":"Интеграция с менеджером пакетов **Ключевые преимущества:** **Автоматическое разрешение зависимостей**: не нужно вручную прописывать пути импортов **Согласованность версий**: фиксация в easyp.lock гарантирует воспроизводи","content":"Интеграция с менеджером пакетов **Ключевые преимущества:** **Автоматическое разрешение зависимостей**: не нужно вручную прописывать пути импортов **Согласованность версий**: фиксация в easyp.lock гарантирует воспроизводимость **Транзитивные зависимости**: вложенные цепочки подтягиваются автоматически **Производительность**: локальный кеш — скачивание один раз и повторное использование"},{"id":"cli/generator/generator::top::125","title":"Генератор","section":"Автоматическое разрешение зависимостей","path":"/docs/guide/cli/generator/generator","headings":["Автоматическое разрешение зависимостей"],"excerpt":"Автоматическое разрешение зависимостей Когда вы указываете зависимости в секции deps, генератор автоматически добавляет их в путь импортов. Ваши proto‑файлы могут делать стандартные import из этих зависимостей без дополн","content":"Автоматическое разрешение зависимостей Когда вы указываете зависимости в секции deps, генератор автоматически добавляет их в путь импортов. Ваши proto‑файлы могут делать стандартные import из этих зависимостей без дополнительной настройки."},{"id":"cli/generator/generator::top::126","title":"Генератор","section":"Автоматическое разрешение зависимостей","path":"/docs/guide/cli/generator/generator","headings":["Автоматическое разрешение зависимостей"],"excerpt":"Автоматическое разрешение зависимостей **Как это работает:** EasyP скачивает и кеширует зависимости из deps Во время генерации кешированные файлы автоматически добавляются в import‑path protoc Ваши proto‑файлы используют","content":"Автоматическое разрешение зависимостей **Как это работает:** EasyP скачивает и кеширует зависимости из deps Во время генерации кешированные файлы автоматически добавляются в import‑path protoc Ваши proto‑файлы используют обычные import строки для обращения к зависимостям При with_imports: true в вывод попадают и локальные файлы, и файлы зависимостей"},{"id":"cli/generator/generator::top::127","title":"Генератор","section":"Автоматическое разрешение зависимостей","path":"/docs/guide/cli/generator/generator","headings":["Автоматическое разрешение зависимостей"],"excerpt":"Автоматическое разрешение зависимостей Ниже простой пример — зависимости указываются один раз в deps, далее они доступны при генерации автоматически:","content":"Автоматическое разрешение зависимостей Ниже простой пример — зависимости указываются один раз в deps, далее они доступны при генерации автоматически:"},{"id":"cli/generator/generator::top::128","title":"Генератор","section":"Автоматическое разрешение зависимостей","path":"/docs/guide/cli/generator/generator","headings":["Автоматическое разрешение зависимостей"],"excerpt":"Автоматическое разрешение зависимостей ```yaml deps: - github.com/googleapis/googleapis@common-protos-1_3_1 - github.com/grpc-ecosystem/grpc-gateway@v2.19.1","content":"Автоматическое разрешение зависимостей ```yaml deps: - github.com/googleapis/googleapis@common-protos-1_3_1 - github.com/grpc-ecosystem/grpc-gateway@v2.19.1"},{"id":"cli/generator/generator::top::129","title":"Генератор","section":"Автоматическое разрешение зависимостей","path":"/docs/guide/cli/generator/generator","headings":["Автоматическое разрешение зависимостей"],"excerpt":"Автоматическое разрешение зависимостей generate: inputs: - directory: \"proto\" plugins: - name: go out: ./gen/go opts: paths: source_relative with_imports: true # This automatically includes googleapis and grpc-gateway pr","content":"Автоматическое разрешение зависимостей 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::top::130","title":"Генератор","section":"Примеры использования зависимостей","path":"/docs/guide/cli/generator/generator","headings":["Примеры использования зависимостей"],"excerpt":"Примеры использования зависимостей Ниже показаны распространённые способы интеграции внешних proto‑зависимостей в процесс генерации.","content":"Примеры использования зависимостей Ниже показаны распространённые способы интеграции внешних proto‑зависимостей в процесс генерации."},{"id":"cli/generator/generator::google-apis::131","title":"Генератор","section":"Использование Google APIs","path":"/docs/guide/cli/generator/generator#google-apis","headings":["Использование Google APIs"],"excerpt":"Использование Google APIs Google APIs — одна из самых популярных коллекций зависимостей: стандартные типы, аннотации для REST, проверки и общие структуры данных.","content":"Использование Google APIs Google APIs — одна из самых популярных коллекций зависимостей: стандартные типы, аннотации для REST, проверки и общие структуры данных."},{"id":"cli/generator/generator::google-apis::132","title":"Генератор","section":"Использование Google APIs","path":"/docs/guide/cli/generator/generator#google-apis","headings":["Использование Google APIs"],"excerpt":"Использование Google APIs **Когда использовать Google APIs:** Построение REST поверх gRPC (gRPC-Gateway) Нужны стандартные типы (Timestamp, Duration, Any) Требуются аннотации поведения полей (field behavior) Интеграция с","content":"Использование Google APIs **Когда использовать Google APIs:** Построение REST поверх gRPC (gRPC-Gateway) Нужны стандартные типы (Timestamp, Duration, Any) Требуются аннотации поведения полей (field behavior) Интеграция с сервисами Google Cloud"},{"id":"cli/generator/generator::google-apis::133","title":"Генератор","section":"Использование Google APIs","path":"/docs/guide/cli/generator/generator#google-apis","headings":["Использование Google APIs"],"excerpt":"Использование Google APIs Минимальная конфигурация для подключения Google APIs:","content":"Использование Google APIs Минимальная конфигурация для подключения Google APIs:"},{"id":"cli/generator/generator::google-apis::134","title":"Генератор","section":"Использование Google APIs","path":"/docs/guide/cli/generator/generator#google-apis","headings":["Использование Google APIs"],"excerpt":"Использование Google APIs ```yaml deps: - github.com/googleapis/googleapis@common-protos-1_3_1","content":"Использование Google APIs ```yaml deps: - github.com/googleapis/googleapis@common-protos-1_3_1"},{"id":"cli/generator/generator::google-apis::135","title":"Генератор","section":"Использование Google APIs","path":"/docs/guide/cli/generator/generator#google-apis","headings":["Использование Google APIs"],"excerpt":"Использование Google APIs generate: inputs: - directory: \"api/proto\" plugins: - name: go out: ./gen/go opts: paths: source_relative with_imports: true ```","content":"Использование Google APIs generate: inputs: - directory: \"api/proto\" plugins: - name: go out: ./gen/go opts: paths: source_relative with_imports: true ```"},{"id":"cli/generator/generator::google-apis::136","title":"Генератор","section":"Использование Google APIs","path":"/docs/guide/cli/generator/generator#google-apis","headings":["Использование Google APIs"],"excerpt":"Использование Google APIs **Важно:** Всегда фиксируйте версию (например common-protos-1_3_1) — не используйте latest в продакшене.","content":"Использование Google APIs **Важно:** Всегда фиксируйте версию (например common-protos-1_3_1) — не используйте latest в продакшене."},{"id":"cli/generator/generator::google-apis::137","title":"Генератор","section":"Использование Google APIs","path":"/docs/guide/cli/generator/generator#google-apis","headings":["Использование Google APIs"],"excerpt":"Использование Google APIs После настройки ваши proto могут импортировать определения Google API. Ниже пример сервиса с HTTP аннотацией:","content":"Использование Google APIs После настройки ваши proto могут импортировать определения Google API. Ниже пример сервиса с HTTP аннотацией:"},{"id":"cli/generator/generator::google-apis::138","title":"Генератор","section":"Использование Google APIs","path":"/docs/guide/cli/generator/generator#google-apis","headings":["Использование Google APIs"],"excerpt":"Использование Google APIs ```proto // api/proto/service.proto syntax = \"proto3\";","content":"Использование Google APIs ```proto // api/proto/service.proto syntax = \"proto3\";"},{"id":"cli/generator/generator::google-apis::139","title":"Генератор","section":"Использование Google APIs","path":"/docs/guide/cli/generator/generator#google-apis","headings":["Использование Google APIs"],"excerpt":"Использование Google APIs import \"google/api/annotations.proto\"; import \"google/protobuf/timestamp.proto\";","content":"Использование Google APIs import \"google/api/annotations.proto\"; import \"google/protobuf/timestamp.proto\";"},{"id":"cli/generator/generator::google-apis::140","title":"Генератор","section":"Использование Google APIs","path":"/docs/guide/cli/generator/generator#google-apis","headings":["Использование Google APIs"],"excerpt":"Использование Google APIs service MyService { rpc GetData(GetDataRequest) returns (GetDataResponse) { option (google.api.http) = { get: \"/v1/data\" }; } } ```","content":"Использование Google APIs service MyService { rpc GetData(GetDataRequest) returns (GetDataResponse) { option (google.api.http) = { get: \"/v1/data\" }; } } ```"},{"id":"cli/generator/generator::top::141","title":"Генератор","section":"Использование правил валидации","path":"/docs/guide/cli/generator/generator","headings":["Использование правил валидации"],"excerpt":"Использование правил валидации protoc-gen-validate даёт мощную проверку полей прямо в определениях proto, устраняя необходимость писать отдельную логику валидации в приложении.","content":"Использование правил валидации protoc-gen-validate даёт мощную проверку полей прямо в определениях proto, устраняя необходимость писать отдельную логику валидации в приложении."},{"id":"cli/generator/generator::top::142","title":"Генератор","section":"Использование правил валидации","path":"/docs/guide/cli/generator/generator","headings":["Использование правил валидации"],"excerpt":"Использование правил валидации **Когда применять валидацию:** Проверка входных данных API Ограничения моделей БД Проверка конфигурационных файлов Любая ситуация, где критична целостность данных","content":"Использование правил валидации **Когда применять валидацию:** Проверка входных данных API Ограничения моделей БД Проверка конфигурационных файлов Любая ситуация, где критична целостность данных"},{"id":"cli/generator/generator::top::143","title":"Генератор","section":"Использование правил валидации","path":"/docs/guide/cli/generator/generator","headings":["Использование правил валидации"],"excerpt":"Использование правил валидации **Преимущества:** Правила валидации — часть proto (единый источник истины) Генерация создаёт функции проверки автоматически Единообразие проверок между языками Производительнее чем проверка","content":"Использование правил валидации **Преимущества:** Правила валидации — часть proto (единый источник истины) Генерация создаёт функции проверки автоматически Единообразие проверок между языками Производительнее чем проверка через runtime reflection"},{"id":"cli/generator/generator::top::144","title":"Генератор","section":"Использование правил валидации","path":"/docs/guide/cli/generator/generator","headings":["Использование правил валидации"],"excerpt":"Использование правил валидации ```yaml deps: - github.com/bufbuild/protoc-gen-validate@v0.10.1","content":"Использование правил валидации ```yaml deps: - github.com/bufbuild/protoc-gen-validate@v0.10.1"},{"id":"cli/generator/generator::top::145","title":"Генератор","section":"Использование правил валидации","path":"/docs/guide/cli/generator/generator","headings":["Использование правил валидации"],"excerpt":"Использование правил валидации 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":"Использование правил валидации 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::top::146","title":"Генератор","section":"Использование правил валидации","path":"/docs/guide/cli/generator/generator","headings":["Использование правил валидации"],"excerpt":"Использование правил валидации **Примечание:** Нужны одновременно зависимость (для импортов proto) и плагин (для генерации кода), чтобы получить полноценную поддержку валидации.","content":"Использование правил валидации **Примечание:** Нужны одновременно зависимость (для импортов proto) и плагин (для генерации кода), чтобы получить полноценную поддержку валидации."},{"id":"cli/generator/generator::top::147","title":"Генератор","section":"Использование правил валидации","path":"/docs/guide/cli/generator/generator","headings":["Использование правил валидации"],"excerpt":"Использование правил валидации Так выглядят правила валидации в proto — сгенерированный код будет автоматически их применять:","content":"Использование правил валидации Так выглядят правила валидации в proto — сгенерированный код будет автоматически их применять:"},{"id":"cli/generator/generator::top::148","title":"Генератор","section":"Использование правил валидации","path":"/docs/guide/cli/generator/generator","headings":["Использование правил валидации"],"excerpt":"Использование правил валидации ```proto // proto/user.proto syntax = \"proto3\";","content":"Использование правил валидации ```proto // proto/user.proto syntax = \"proto3\";"},{"id":"cli/generator/generator::top::149","title":"Генератор","section":"Использование правил валидации","path":"/docs/guide/cli/generator/generator","headings":["Использование правил валидации"],"excerpt":"Использование правил валидации import \"validate/validate.proto\";","content":"Использование правил валидации import \"validate/validate.proto\";"},{"id":"cli/generator/generator::top::150","title":"Генератор","section":"Использование правил валидации","path":"/docs/guide/cli/generator/generator","headings":["Использование правил валидации"],"excerpt":"Использование правил валидации message User { string email = 1 [(validate.rules).string.email = true]; int32 age = 2 [(validate.rules).int32.gte = 0]; } ```","content":"Использование правил валидации message User { string email = 1 [(validate.rules).string.email = true]; int32 age = 2 [(validate.rules).int32.gte = 0]; } ```"},{"id":"cli/generator/generator::top::151","title":"Генератор","section":"Комплексная конфигурация с несколькими зависимостями","path":"/docs/guide/cli/generator/generator","headings":["Комплексная конфигурация с несколькими зависимостями"],"excerpt":"Комплексная конфигурация с несколькими зависимостями Пример ниже показывает продакшен‑конфигурацию, объединяющую несколько зависимостей и плагины для полного цикла разработки API:","content":"Комплексная конфигурация с несколькими зависимостями Пример ниже показывает продакшен‑конфигурацию, объединяющую несколько зависимостей и плагины для полного цикла разработки API:"},{"id":"cli/generator/generator::top::152","title":"Генератор","section":"Комплексная конфигурация с несколькими зависимостями","path":"/docs/guide/cli/generator/generator","headings":["Комплексная конфигурация с несколькими зависимостями"],"excerpt":"Комплексная конфигурация с несколькими зависимостями ```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 HT","content":"Комплексная конфигурация с несколькими зависимостями ```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::top::153","title":"Генератор","section":"Комплексная конфигурация с несколькими зависимостями","path":"/docs/guide/cli/generator/generator","headings":["Комплексная конфигурация с несколькими зависимостями"],"excerpt":"Комплексная конфигурация с несколькими зависимостями generate: inputs: - directory: \"api/proto\" plugins: # Go code generation - Core protobuf structures - name: go out: ./gen/go opts: paths: source_relative module: githu","content":"Комплексная конфигурация с несколькими зависимостями 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::top::154","title":"Генератор","section":"Интеграция с кешем зависимостей","path":"/docs/guide/cli/generator/generator","headings":["Интеграция с кешем зависимостей"],"excerpt":"Интеграция с кешем зависимостей Генератор использует модульный кеш EasyP для ускорения сборок:","content":"Интеграция с кешем зависимостей Генератор использует модульный кеш EasyP для ускорения сборок:"},{"id":"cli/generator/generator::top::155","title":"Генератор","section":"Интеграция с кешем зависимостей","path":"/docs/guide/cli/generator/generator","headings":["Интеграция с кешем зависимостей"],"excerpt":"Интеграция с кешем зависимостей ```bash Download dependencies once easyp mod download","content":"Интеграция с кешем зависимостей ```bash Download dependencies once easyp mod download"},{"id":"cli/generator/generator::top::156","title":"Генератор","section":"Интеграция с кешем зависимостей","path":"/docs/guide/cli/generator/generator","headings":["Интеграция с кешем зависимостей"],"excerpt":"Интеграция с кешем зависимостей Generate code (uses cached dependencies) easyp generate","content":"Интеграция с кешем зависимостей Generate code (uses cached dependencies) easyp generate"},{"id":"cli/generator/generator::top::157","title":"Генератор","section":"Интеграция с кешем зависимостей","path":"/docs/guide/cli/generator/generator","headings":["Интеграция с кешем зависимостей"],"excerpt":"Интеграция с кешем зависимостей Dependencies are cached in ~/.easyp/mod/ ls ~/.easyp/mod/github.com/googleapis/googleapis/ ```","content":"Интеграция с кешем зависимостей Dependencies are cached in ~/.easyp/mod/ ls ~/.easyp/mod/github.com/googleapis/googleapis/ ```"},{"id":"cli/generator/generator::top::158","title":"Генератор","section":"Удалённая генерация","path":"/docs/guide/cli/generator/generator","headings":["Удалённая генерация"],"excerpt":"Удалённая генерация Удалённая генерация — мощная возможность, позволяющая генерировать код из proto‑файлов в удалённых Git‑репозиториях без локального checkout. Это поддерживает микросервисную архитектуру, где команды ис","content":"Удалённая генерация Удалённая генерация — мощная возможность, позволяющая генерировать код из proto‑файлов в удалённых Git‑репозиториях без локального checkout. Это поддерживает микросервисную архитектуру, где команды используют API друг друга без жёсткой связки."},{"id":"cli/generator/generator::top::159","title":"Генератор","section":"Удалённая генерация","path":"/docs/guide/cli/generator/generator","headings":["Удалённая генерация"],"excerpt":"Удалённая генерация **Преимущества:** **Развязка разработки**: Команды развиваются независимо, используя версии API друг друга **Контроль версий**: Фиксация внешних API гарантирует стабильность **Меньше размер репозитори","content":"Удалённая генерация **Преимущества:** **Развязка разработки**: Команды развиваются независимо, используя версии API друг друга **Контроль версий**: Фиксация внешних API гарантирует стабильность **Меньше размер репозитория**: Нет необходимости в vendoring/submodule внешних proto **Автоматические обновления**: Легко перейти на новую версию по готовности"},{"id":"cli/generator/generator::top::160","title":"Генератор","section":"Удалённая генерация","path":"/docs/guide/cli/generator/generator","headings":["Удалённая генерация"],"excerpt":"Удалённая генерация **Рекомендации:** В продакшене используйте только тегированные версии В разработке можно тестировать latest, но в проде фиксируйте При наличии используйте семантическое версионирование Учитывайте сете","content":"Удалённая генерация **Рекомендации:** В продакшене используйте только тегированные версии В разработке можно тестировать latest, но в проде фиксируйте При наличии используйте семантическое версионирование Учитывайте сетевые ограничения в CI/CD"},{"id":"cli/generator/generator::proto::161","title":"Генератор","section":"Источники удалённых proto","path":"/docs/guide/cli/generator/generator#proto","headings":["Источники удалённых proto"],"excerpt":"Источники удалённых proto Генерация напрямую из удалённых репозиториев — полезно в микросервисной архитектуре, где разные команды владеют разными proto.","content":"Источники удалённых proto Генерация напрямую из удалённых репозиториев — полезно в микросервисной архитектуре, где разные команды владеют разными proto."},{"id":"cli/generator/generator::proto::162","title":"Генератор","section":"Источники удалённых proto","path":"/docs/guide/cli/generator/generator#proto","headings":["Источники удалённых proto"],"excerpt":"Источники удалённых proto **Типовой workflow:** Команда A публикует proto с версиями в Git Команда B добавляет их в свой easyp.yaml При генерации EasyP скачивает и подключает удалённые proto Сгенерированный код содержит ","content":"Источники удалённых proto **Типовой workflow:** Команда A публикует proto с версиями в Git Команда B добавляет их в свой easyp.yaml При генерации EasyP скачивает и подключает удалённые proto Сгенерированный код содержит клиентские библиотеки сервисов команды A"},{"id":"cli/generator/generator::proto::163","title":"Генератор","section":"Источники удалённых proto","path":"/docs/guide/cli/generator/generator#proto","headings":["Источники удалённых proto"],"excerpt":"Источники удалённых proto Практический пример объединения локальных и удалённых источников в одной конфигурации генерации:","content":"Источники удалённых proto Практический пример объединения локальных и удалённых источников в одной конфигурации генерации:"},{"id":"cli/generator/generator::top::164","title":"Генератор","section":"Сценарии использования удалённой генерации","path":"/docs/guide/cli/generator/generator","headings":["Сценарии использования удалённой генерации"],"excerpt":"Сценарии использования удалённой генерации Примеры ниже показывают реальные ситуации, где удалённая генерация даёт ощутимую выгоду.","content":"Сценарии использования удалённой генерации Примеры ниже показывают реальные ситуации, где удалённая генерация даёт ощутимую выгоду."},{"id":"cli/generator/generator::multi-team-development::165","title":"Генератор","section":"Много команд (Multi-Team Development)","path":"/docs/guide/cli/generator/generator#multi-team-development","headings":["Много команд (Multi-Team Development)"],"excerpt":"Много команд (Multi-Team Development) Мультикомандная разработка особенно выигрывает: вместо координации общих репозиториев и сложного управления зависимостями — независимая эволюция API с контролируемыми обновлениями че","content":"Много команд (Multi-Team Development) Мультикомандная разработка особенно выигрывает: вместо координации общих репозиториев и сложного управления зависимостями — независимая эволюция API с контролируемыми обновлениями через версии."},{"id":"cli/generator/generator::multi-team-development::166","title":"Генератор","section":"Много команд (Multi-Team Development)","path":"/docs/guide/cli/generator/generator#multi-team-development","headings":["Много команд (Multi-Team Development)"],"excerpt":"Много команд (Multi-Team Development) Паттерн ценен в крупных организациях, где: Команды имеют разные циклы релизов и скорости разработки Владение API определено, потребление — массовое Нужно избежать overhead от координ","content":"Много команд (Multi-Team Development) Паттерн ценен в крупных организациях, где: Команды имеют разные циклы релизов и скорости разработки Владение API определено, потребление — массовое Нужно избежать overhead от координации общих proto репозиториев Команды используют разные стеки, но должны взаимодействовать"},{"id":"cli/generator/generator::multi-team-development::167","title":"Генератор","section":"Много команд (Multi-Team Development)","path":"/docs/guide/cli/generator/generator#multi-team-development","headings":["Много команд (Multi-Team Development)"],"excerpt":"Много команд (Multi-Team Development)","content":"Много команд (Multi-Team Development)"},{"id":"cli/generator/generator::api::168","title":"Генератор","section":"Интеграция с API вендоров","path":"/docs/guide/cli/generator/generator#api","headings":["Интеграция с API вендоров"],"excerpt":"Интеграция с API вендоров Многие вендоры публикуют proto для своих API, позволяя генерировать типобезопасных клиентов вместо ручных HTTP реализаций. Это повышает типовую строгость, автоматизирует сериализацию и часто уск","content":"Интеграция с API вендоров Многие вендоры публикуют proto для своих API, позволяя генерировать типобезопасных клиентов вместо ручных HTTP реализаций. Это повышает типовую строгость, автоматизирует сериализацию и часто ускоряет работу."},{"id":"cli/generator/generator::api::169","title":"Генератор","section":"Интеграция с API вендоров","path":"/docs/guide/cli/generator/generator#api","headings":["Интеграция с API вендоров"],"excerpt":"Интеграция с API вендоров Преимущества использования proto от вендоров: **Type safety**: Проверка типов на этапе компиляции **Automatic updates**: Новые возможности приходят с обновлением версии **Consistency**: Единые п","content":"Интеграция с API вендоров Преимущества использования proto от вендоров: **Type safety**: Проверка типов на этапе компиляции **Automatic updates**: Новые возможности приходят с обновлением версии **Consistency**: Единые паттерны интерфейсов между интеграциями **Performance**: Бинарная сериализация быстрее JSON **Documentation**: Proto выступают источником истины для API"},{"id":"cli/generator/generator::top::170","title":"Генератор","section":"Команды","path":"/docs/guide/cli/generator/generator","headings":["Команды"],"excerpt":"Команды CLI EasyP предоставляет гибкие варианты запуска генерации с разными конфигурациями и окружениями.","content":"Команды CLI EasyP предоставляет гибкие варианты запуска генерации с разными конфигурациями и окружениями."},{"id":"cli/generator/generator::top::171","title":"Генератор","section":"Базовая генерация","path":"/docs/guide/cli/generator/generator","headings":["Базовая генерация"],"excerpt":"Базовая генерация Ниже наиболее часто применяемые варианты команд для разработки и продакшена:","content":"Базовая генерация Ниже наиболее часто применяемые варианты команд для разработки и продакшена:"},{"id":"cli/generator/generator::top::172","title":"Генератор","section":"Базовая генерация","path":"/docs/guide/cli/generator/generator","headings":["Базовая генерация"],"excerpt":"Базовая генерация ```bash Use default easyp.yaml configuration - Most common for development easyp generate","content":"Базовая генерация ```bash Use default easyp.yaml configuration - Most common for development easyp generate"},{"id":"cli/generator/generator::top::173","title":"Генератор","section":"Базовая генерация","path":"/docs/guide/cli/generator/generator","headings":["Базовая генерация"],"excerpt":"Базовая генерация Use custom configuration file - Essential for multi-environment setups easyp --cfg production.easyp.yaml generate","content":"Базовая генерация Use custom configuration file - Essential for multi-environment setups easyp --cfg production.easyp.yaml generate"},{"id":"cli/generator/generator::top::174","title":"Генератор","section":"Базовая генерация","path":"/docs/guide/cli/generator/generator","headings":["Базовая генерация"],"excerpt":"Базовая генерация Generate with debug logs - Helpful for debugging and CI/CD easyp --debug generate","content":"Базовая генерация Generate with debug logs - Helpful for debugging and CI/CD easyp --debug generate"},{"id":"cli/generator/generator::top::175","title":"Генератор","section":"Базовая генерация","path":"/docs/guide/cli/generator/generator","headings":["Базовая генерация"],"excerpt":"Базовая генерация Generate with custom cache location - Useful for CI systems or shared environments EASYPPATH=/tmp/easyp-cache easyp generate ```","content":"Базовая генерация Generate with custom cache location - Useful for CI systems or shared environments EASYPPATH=/tmp/easyp-cache easyp generate ```"},{"id":"cli/generator/generator::top::176","title":"Генератор","section":"Интеграция с менеджером пакетов","path":"/docs/guide/cli/generator/generator","headings":["Интеграция с менеджером пакетов"],"excerpt":"Интеграция с менеджером пакетов Интеграция с менеджером пакетов позволяет либо явно управлять зависимостями, либо поручить это генератору. Явный путь даёт больше контроля, автоматический — больше удобства:","content":"Интеграция с менеджером пакетов Интеграция с менеджером пакетов позволяет либо явно управлять зависимостями, либо поручить это генератору. Явный путь даёт больше контроля, автоматический — больше удобства:"},{"id":"cli/generator/generator::top::177","title":"Генератор","section":"Интеграция с менеджером пакетов","path":"/docs/guide/cli/generator/generator","headings":["Интеграция с менеджером пакетов"],"excerpt":"Интеграция с менеджером пакетов ```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":"Интеграция с менеджером пакетов ```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::top::178","title":"Генератор","section":"Интеграция с менеджером пакетов","path":"/docs/guide/cli/generator/generator","headings":["Интеграция с менеджером пакетов"],"excerpt":"Интеграция с менеджером пакетов Automatic workflow - Convenient for development (generate downloads dependencies automatically) easyp generate ```","content":"Интеграция с менеджером пакетов Automatic workflow - Convenient for development (generate downloads dependencies automatically) easyp generate ```"},{"id":"cli/generator/generator::advanced-usage::179","title":"Генератор","section":"Расширенное использование (Advanced Usage)","path":"/docs/guide/cli/generator/generator#advanced-usage","headings":["Расширенное использование (Advanced Usage)"],"excerpt":"Расширенное использование (Advanced Usage) Эти варианты полезны для специфических сценариев деплоя, отладки или когда нужен более тонкий контроль процесса генерации:","content":"Расширенное использование (Advanced Usage) Эти варианты полезны для специфических сценариев деплоя, отладки или когда нужен более тонкий контроль процесса генерации:"},{"id":"cli/generator/generator::advanced-usage::180","title":"Генератор","section":"Расширенное использование (Advanced Usage)","path":"/docs/guide/cli/generator/generator#advanced-usage","headings":["Расширенное использование (Advanced Usage)"],"excerpt":"Расширенное использование (Advanced Usage) ```bash Генерация из конкретной директории (перекрывает настройку в файле конфигурации) easyp generate --path=./api/proto","content":"Расширенное использование (Advanced Usage) ```bash Генерация из конкретной директории (перекрывает настройку в файле конфигурации) easyp generate --path=./api/proto"},{"id":"cli/generator/generator::advanced-usage::181","title":"Генератор","section":"Расширенное использование (Advanced Usage)","path":"/docs/guide/cli/generator/generator#advanced-usage","headings":["Расширенное использование (Advanced Usage)"],"excerpt":"Расширенное использование (Advanced Usage) Генерация с vendored зависимостями (оффлайн / Docker контейнеры) easyp mod vendor easyp generate","content":"Расширенное использование (Advanced Usage) Генерация с vendored зависимостями (оффлайн / Docker контейнеры) easyp mod vendor easyp generate"},{"id":"cli/generator/generator::advanced-usage::182","title":"Генератор","section":"Расширенное использование (Advanced Usage)","path":"/docs/guide/cli/generator/generator#advanced-usage","headings":["Расширенное использование (Advanced Usage)"],"excerpt":"Расширенное использование (Advanced Usage) Генерация из кастомного project root (удобно для монореп и вложенных рабочих директорий) easyp generate --root=/usr/local/src/my-project --path=./api/proto ```","content":"Расширенное использование (Advanced Usage) Генерация из кастомного project root (удобно для монореп и вложенных рабочих директорий) easyp generate --root=/usr/local/src/my-project --path=./api/proto ```"},{"id":"cli/generator/generator::common-patterns::183","title":"Генератор","section":"Типовые паттерны (Common Patterns)","path":"/docs/guide/cli/generator/generator#common-patterns","headings":["Типовые паттерны (Common Patterns)"],"excerpt":"Типовые паттерны (Common Patterns) Эти схемы отражают реальные сценарии и лучшие практики организации генерации кода в разных структурах проектов.","content":"Типовые паттерны (Common Patterns) Эти схемы отражают реальные сценарии и лучшие практики организации генерации кода в разных структурах проектов."},{"id":"cli/generator/generator::multi-language-generation::184","title":"Генератор","section":"Мульти-языковая генерация (Multi-Language Generation)","path":"/docs/guide/cli/generator/generator#multi-language-generation","headings":["Мульти-языковая генерация (Multi-Language Generation)"],"excerpt":"Мульти-языковая генерация (Multi-Language Generation) Мульти-языковая генерация критична для компаний, использующих разные технологии в стеке. EasyP облегчает получение согласованных клиентских библиотек и типов для неск","content":"Мульти-языковая генерация (Multi-Language Generation) Мульти-языковая генерация критична для компаний, использующих разные технологии в стеке. EasyP облегчает получение согласованных клиентских библиотек и типов для нескольких языков из одного источника proto."},{"id":"cli/generator/generator::multi-language-generation::185","title":"Генератор","section":"Мульти-языковая генерация (Multi-Language Generation)","path":"/docs/guide/cli/generator/generator#multi-language-generation","headings":["Мульти-языковая генерация (Multi-Language Generation)"],"excerpt":"Мульти-языковая генерация (Multi-Language Generation) **Типовые сценарии:** **Full‑stack приложения**: backend на Go/Java + фронтенд на TypeScript **Платформы данных**: сервисы на Go + аналитика / ML на Python **Микросер","content":"Мульти-языковая генерация (Multi-Language Generation) **Типовые сценарии:** **Full‑stack приложения**: backend на Go/Java + фронтенд на TypeScript **Платформы данных**: сервисы на Go + аналитика / ML на Python **Микросервисы**: каждый сервис — оптимальный язык под задачу **Внешние SDK**: предоставление клиентских библиотек партнёрам **Интеграция с легаси**: современные gRPC сервисы + старые системы"},{"id":"cli/generator/generator::multi-language-generation::186","title":"Генератор","section":"Мульти-языковая генерация (Multi-Language Generation)","path":"/docs/guide/cli/generator/generator#multi-language-generation","headings":["Мульти-языковая генерация (Multi-Language Generation)"],"excerpt":"Мульти-языковая генерация (Multi-Language Generation) **Производительность:** Каждый плагин запускается отдельно — время растёт линейно от количества плагинов Для больших наборов используйте параллельный запуск (make -j4","content":"Мульти-языковая генерация (Multi-Language Generation) **Производительность:** Каждый плагин запускается отдельно — время растёт линейно от количества плагинов Для больших наборов используйте параллельный запуск (make -j4) Структурируйте выходные директории иерархически — меньше конфликтов Плагины имеют разную скорость — профилируйте сборку для поиска узких мест"},{"id":"cli/generator/generator::multi-language-generation::187","title":"Генератор","section":"Мульти-языковая генерация (Multi-Language Generation)","path":"/docs/guide/cli/generator/generator#multi-language-generation","headings":["Мульти-языковая генерация (Multi-Language Generation)"],"excerpt":"Мульти-языковая генерация (Multi-Language Generation) **Преимущества сопровождения:** Единый источник истины для API снижает риск расхождения схем Согласованные типы уменьшают интеграционные баги Автоматическая синхрониз","content":"Мульти-языковая генерация (Multi-Language Generation) **Преимущества сопровождения:** Единый источник истины для API снижает риск расхождения схем Согласованные типы уменьшают интеграционные баги Автоматическая синхронизация при изменении proto исключает ручные правки Меньше риска дрейфа API между реализациями на разных языках Рефакторинг упрощается — изменения транзитивно отражаются во всех артефактах"},{"id":"cli/generator/generator::multi-language-generation::188","title":"Генератор","section":"Мульти-языковая генерация (Multi-Language Generation)","path":"/docs/guide/cli/generator/generator#multi-language-generation","headings":["Мульти-языковая генерация (Multi-Language Generation)"],"excerpt":"Мульти-языковая генерация (Multi-Language Generation) Ниже пример типичной мульти-языковой конфигурации для full‑stack приложения: backend, веб‑клиент, аналитика и документация:","content":"Мульти-языковая генерация (Multi-Language Generation) Ниже пример типичной мульти-языковой конфигурации для full‑stack приложения: backend, веб‑клиент, аналитика и документация:"},{"id":"cli/generator/generator::multi-language-generation::189","title":"Генератор","section":"Мульти-языковая генерация (Multi-Language Generation)","path":"/docs/guide/cli/generator/generator#multi-language-generation","headings":["Мульти-языковая генерация (Multi-Language Generation)"],"excerpt":"Мульти-языковая генерация (Multi-Language Generation)","content":"Мульти-языковая генерация (Multi-Language Generation)"},{"id":"cli/generator/generator::multi-language-generation::190","title":"Генератор","section":"Мульти-языковая генерация (Multi-Language Generation)","path":"/docs/guide/cli/generator/generator#multi-language-generation","headings":["Мульти-языковая генерация (Multi-Language Generation)"],"excerpt":"Мульти-языковая генерация (Multi-Language Generation) **Совет по организации:** Используйте отдельные выходные директории для каждого языка, чтобы избежать конфликтов файлов и упростить интеграцию с языковыми сборочными ","content":"Мульти-языковая генерация (Multi-Language Generation) **Совет по организации:** Используйте отдельные выходные директории для каждого языка, чтобы избежать конфликтов файлов и упростить интеграцию с языковыми сборочными системами."},{"id":"cli/generator/generator::multi-language-generation::191","title":"Генератор","section":"Мульти-языковая генерация (Multi-Language Generation)","path":"/docs/guide/cli/generator/generator#multi-language-generation","headings":["Мульти-языковая генерация (Multi-Language Generation)"],"excerpt":"Мульти-языковая генерация (Multi-Language Generation) Генератор EasyP — комплексное решение для генерации кода из Protocol Buffers: от простой локальной разработки до сложных enterprise‑сценариев с удалёнными зависимостя","content":"Мульти-языковая генерация (Multi-Language Generation) Генератор EasyP — комплексное решение для генерации кода из Protocol Buffers: от простой локальной разработки до сложных enterprise‑сценариев с удалёнными зависимостями и мульти-языковым выводом."},{"id":"cli/linter/linter::proto::0","title":"Линтер","section":"Зачем нужен линтер для proto файлов?","path":"/docs/guide/cli/linter/linter#proto","headings":["Зачем нужен линтер для proto файлов?"],"excerpt":"Зачем нужен линтер для proto файлов? Линтеры играют ключевую роль в современной разработке, особенно когда речь о .proto файлах. Они обеспечивают единый стиль и структуру, помогают находить потенциальные ошибки на ранних","content":"Зачем нужен линтер для proto файлов? Линтеры играют ключевую роль в современной разработке, особенно когда речь о .proto файлах. Они обеспечивают единый стиль и структуру, помогают находить потенциальные ошибки на ранних этапах и поддерживают читаемость кода. Это даёт выгоды:"},{"id":"cli/linter/linter::proto::1","title":"Линтер","section":"Зачем нужен линтер для proto файлов?","path":"/docs/guide/cli/linter/linter#proto","headings":["Зачем нужен линтер для proto файлов?"],"excerpt":"Зачем нужен линтер для proto файлов? **Снижение затрат на разработку:** Ошибки ловятся раньше, меньше времени на отладку. **Улучшение командного взаимодействия:** Единообразный код легче понимать и сопровождать. **Бизнес","content":"Зачем нужен линтер для proto файлов? **Снижение затрат на разработку:** Ошибки ловятся раньше, меньше времени на отладку. **Улучшение командного взаимодействия:** Единообразный код легче понимать и сопровождать. **Бизнес-эффективность:** Более качественный код → меньше инцидентов в проде → ниже стоимость поддержки."},{"id":"cli/linter/linter::top::2","title":"Линтер","section":"Справочник по конфигурации","path":"/docs/guide/cli/linter/linter","headings":["Справочник по конфигурации"],"excerpt":"Справочник по конфигурации Конфигурация линтера настраивается в секции lint файла easyp.yaml.","content":"Справочник по конфигурации Конфигурация линтера настраивается в секции lint файла easyp.yaml."},{"id":"cli/linter/linter::use-string::3","title":"Линтер","section":"use ([]string)","path":"/docs/guide/cli/linter/linter#use-string","headings":["use ([]string)"],"excerpt":"use ([]string) Определяет набор правил или категорий для включения. Можно смешивать категории и конкретные правила.","content":"use ([]string) Определяет набор правил или категорий для включения. Можно смешивать категории и конкретные правила."},{"id":"cli/linter/linter::use-string::4","title":"Линтер","section":"use ([]string)","path":"/docs/guide/cli/linter/linter#use-string","headings":["use ([]string)"],"excerpt":"use ([]string) **Категории:** **MINIMAL**: Базовая согласованность пакетов **BASIC**: Соглашения по именованию и структуре **DEFAULT**: Рекомендованные правила для большинства проектов **COMMENTS**: Требования к коммента","content":"use ([]string) **Категории:** **MINIMAL**: Базовая согласованность пакетов **BASIC**: Соглашения по именованию и структуре **DEFAULT**: Рекомендованные правила для большинства проектов **COMMENTS**: Требования к комментариям **UNARY_RPC**: Ограничение на streaming RPC"},{"id":"cli/linter/linter::use-string::5","title":"Линтер","section":"use ([]string)","path":"/docs/guide/cli/linter/linter#use-string","headings":["use ([]string)"],"excerpt":"use ([]string) **Индивидуальные правила:** Любое имя правила (например ENUM_PASCAL_CASE, FIELD_LOWER_SNAKE_CASE)","content":"use ([]string) **Индивидуальные правила:** Любое имя правила (например ENUM_PASCAL_CASE, FIELD_LOWER_SNAKE_CASE)"},{"id":"cli/linter/linter::use-string::6","title":"Линтер","section":"use ([]string)","path":"/docs/guide/cli/linter/linter#use-string","headings":["use ([]string)"],"excerpt":"use ([]string) **Примеры:** ```yaml Только категории use: [MINIMAL, BASIC, DEFAULT]","content":"use ([]string) **Примеры:** ```yaml Только категории use: [MINIMAL, BASIC, DEFAULT]"},{"id":"cli/linter/linter::use-string::7","title":"Линтер","section":"use ([]string)","path":"/docs/guide/cli/linter/linter#use-string","headings":["use ([]string)"],"excerpt":"use ([]string) Смешивание use: - MINIMAL - COMMENT_SERVICE - COMMENT_RPC - ENUM_PASCAL_CASE","content":"use ([]string) Смешивание use: - MINIMAL - COMMENT_SERVICE - COMMENT_RPC - ENUM_PASCAL_CASE"},{"id":"cli/linter/linter::use-string::8","title":"Линтер","section":"use ([]string)","path":"/docs/guide/cli/linter/linter#use-string","headings":["use ([]string)"],"excerpt":"use ([]string) Точный набор use: - PACKAGE_DEFINED - SERVICE_PASCAL_CASE - FIELD_LOWER_SNAKE_CASE ```","content":"use ([]string) Точный набор use: - PACKAGE_DEFINED - SERVICE_PASCAL_CASE - FIELD_LOWER_SNAKE_CASE ```"},{"id":"cli/linter/linter::enum_zero_value_suffix-string::9","title":"Линтер","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) Обязывает нулевое значение enum иметь заданный суффикс.","content":"enum_zero_value_suffix (string) Обязывает нулевое значение enum иметь заданный суффикс."},{"id":"cli/linter/linter::enum_zero_value_suffix-string::10","title":"Линтер","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) **Обычно:** \"UNSPECIFIED\", \"UNKNOWN\", \"DEFAULT\"","content":"enum_zero_value_suffix (string) **Обычно:** \"UNSPECIFIED\", \"UNKNOWN\", \"DEFAULT\""},{"id":"cli/linter/linter::enum_zero_value_suffix-string::11","title":"Линтер","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)","content":"enum_zero_value_suffix (string)"},{"id":"cli/linter/linter::service_suffix-string::12","title":"Линтер","section":"service_suffix (string)","path":"/docs/guide/cli/linter/linter#service_suffix-string","headings":["service_suffix (string)"],"excerpt":"service_suffix (string) Требуемый суффикс для имён сервисов (унификация стиля).","content":"service_suffix (string) Требуемый суффикс для имён сервисов (унификация стиля)."},{"id":"cli/linter/linter::ignore-string::13","title":"Линтер","section":"ignore ([]string)","path":"/docs/guide/cli/linter/linter#ignore-string","headings":["ignore ([]string)"],"excerpt":"ignore ([]string) Полное исключение путей из линтинга.","content":"ignore ([]string) Полное исключение путей из линтинга."},{"id":"cli/linter/linter::ignore-string::14","title":"Линтер","section":"ignore ([]string)","path":"/docs/guide/cli/linter/linter#ignore-string","headings":["ignore ([]string)"],"excerpt":"ignore ([]string) **Use cases:** vendor / third_party сгенерированные файлы легаси подпакеты тестовые фикстуры","content":"ignore ([]string) **Use cases:** vendor / third_party сгенерированные файлы легаси подпакеты тестовые фикстуры"},{"id":"cli/linter/linter::except-string::15","title":"Линтер","section":"except ([]string)","path":"/docs/guide/cli/linter/linter#except-string","headings":["except ([]string)"],"excerpt":"except ([]string) Глобально отключает правила.","content":"except ([]string) Глобально отключает правила."},{"id":"cli/linter/linter::allow_comment_ignores-bool::16","title":"Линтер","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) Разрешает инлайн‑игнор правил комментариями.","content":"allow_comment_ignores (bool) Разрешает инлайн‑игнор правил комментариями."},{"id":"cli/linter/linter::ignore_only-mapstringstring::17","title":"Линтер","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) Таргетированное игнорирование конкретных правил для указанных путей.","content":"ignore_only (mapstringstring) Таргетированное игнорирование конкретных правил для указанных путей."},{"id":"cli/linter/linter::top::18","title":"Линтер","section":"Игнор правил комментариями","path":"/docs/guide/cli/linter/linter","headings":["Игнор правил комментариями"],"excerpt":"Игнор правил комментариями Если включён allow_comment_ignores, можно точечно отключать правила.","content":"Игнор правил комментариями Если включён allow_comment_ignores, можно точечно отключать правила."},{"id":"cli/linter/linter::top::19","title":"Линтер","section":"Несколько правил в одной строке","path":"/docs/guide/cli/linter/linter","headings":["Несколько правил в одной строке"],"excerpt":"Несколько правил в одной строке","content":"Несколько правил в одной строке"},{"id":"cli/linter/linter::top::20","title":"Линтер","section":"Используйте редко","path":"/docs/guide/cli/linter/linter","headings":["Используйте редко"],"excerpt":"Используйте редко Частое игнорирование = сигнал пересмотреть конфигурацию.","content":"Используйте редко Частое игнорирование = сигнал пересмотреть конфигурацию."},{"id":"cli/linter/linter::top::21","title":"Линтер","section":"Предпочитайте конфигурацию","path":"/docs/guide/cli/linter/linter","headings":["Предпочитайте конфигурацию"],"excerpt":"Предпочитайте конфигурацию Если нужно игнорировать правило в группе файлов — используйте ignore_only.","content":"Предпочитайте конфигурацию Если нужно игнорировать правило в группе файлов — используйте ignore_only."},{"id":"cli/linter/linter::top::22","title":"Линтер","section":"Категории линтера","path":"/docs/guide/cli/linter/linter","headings":["Категории линтера"],"excerpt":"Категории линтера Категории помогают быстро выбрать уровень строгости.","content":"Категории линтера Категории помогают быстро выбрать уровень строгости."},{"id":"cli/linter/linter::top::23","title":"Линтер","section":"Категории линтера","path":"/docs/guide/cli/linter/linter","headings":["Категории линтера"],"excerpt":"Категории линтера **Когда использовать:** **MINIMAL**: Минимальная базовая целостность **BASIC**: Частые соглашения имен **DEFAULT**: Дополнительные проверки качества **COMMENTS**: Обязательные комментарии (API, команды)","content":"Категории линтера **Когда использовать:** **MINIMAL**: Минимальная базовая целостность **BASIC**: Частые соглашения имен **DEFAULT**: Дополнительные проверки качества **COMMENTS**: Обязательные комментарии (API, команды) **UNARY_RPC**: Ограничить streaming RPC"},{"id":"cli/linter/linter::minimal::24","title":"Линтер","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::25","title":"Линтер","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::26","title":"Линтер","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::27","title":"Линтер","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::28","title":"Линтер","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::top::29","title":"Линтер","section":"Заключение","path":"/docs/guide/cli/linter/linter","headings":["Заключение"],"excerpt":"Заключение Внедрение EasyP линдера для ваших proto файлов заметно улучшит workflow, качество и поддерживаемость кода. Полная совместимость с Buf позволяет командам мигрировать без боли, используя гибкую конфигурацию и мо","content":"Заключение Внедрение EasyP линдера для ваших proto файлов заметно улучшит workflow, качество и поддерживаемость кода. Полная совместимость с Buf позволяет командам мигрировать без боли, используя гибкую конфигурацию и мощные возможности из коробки."},{"id":"cli/linter/rules/comment-enum-value::top::0","title":"COMMENT_ENUM_VALUE","path":"/docs/guide/cli/linter/rules/comment-enum-value","headings":[],"excerpt":"Это правило проверяет, что все значения enum имеют комментарий.","content":"Это правило проверяет, что все значения enum имеют комментарий."},{"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 ```proto syntax = \"proto3\";","content":"Good ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/comment-enum-value::good::4","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":"Это правило проверяет, что enum имеет комментарий.","content":"Это правило проверяет, что enum имеет комментарий."},{"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":"Это правило проверяет, что все поля сообщений имеют комментарий.","content":"Это правило проверяет, что все поля сообщений имеют комментарий."},{"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":"Это правило проверяет, что message имеет комментарий.","content":"Это правило проверяет, что message имеет комментарий."},{"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 ```proto syntax = \"proto3\";","content":"Bad ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/comment-message::bad::2","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::3","title":"COMMENT_MESSAGE","section":"Good","path":"/docs/guide/cli/linter/rules/comment-message#good","headings":["Good"],"excerpt":"Good ```proto syntax = \"proto3\";","content":"Good ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/comment-message::good::4","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":"Это правило проверяет, что oneof имеет комментарий.","content":"Это правило проверяет, что oneof имеет комментарий."},{"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":"Это правило проверяет, что сервис имеет комментарий.","content":"Это правило проверяет, что сервис имеет комментарий."},{"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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **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":"Это правило проверяет, что все файлы в заданной директории находятся в одном и том же package.","content":"Это правило проверяет, что все файлы в заданной директории находятся в одном и том же 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":"Это правило проверяет, что первое значение enum равно нулю.","content":"Это правило проверяет, что первое значение enum равно нулю."},{"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 ```proto syntax = \"proto3\";","content":"Bad ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/enum-first-value-zero::bad::3","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::4","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::5","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":"Это правило проверяет, что опция allow_alias не установлена в значение true внутри enum.","content":"Это правило проверяет, что опция allow_alias не установлена в значение true внутри 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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **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":"Это правило проверяет, что имена enum написаны в стиле PascalCase.","content":"Это правило проверяет, что имена enum написаны в стиле 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":"Это правило проверяет, что все значения enum имеют префикс, совпадающий с именем enum.","content":"Это правило проверяет, что все значения enum имеют префикс, совпадающий с именем enum."},{"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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **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":"Это правило проверяет, что значения enum записаны в стиле UPPER_SNAKE_CASE.","content":"Это правило проверяет, что значения enum записаны в стиле 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":"Это правило проверяет, что все нулевые значения enum имеют суффикс _NONE или ваш кастомный (пользовательский) суффикс.","content":"Это правило проверяет, что все нулевые значения enum имеют суффикс _NONE или ваш кастомный (пользовательский) суффикс."},{"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":"**MINIMAL** **BASIC** **DEFAULT**","content":"**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":"Это правило проверяет, что имена полей сообщений записаны в стиле lower_snake_case.","content":"Это правило проверяет, что имена полей сообщений записаны в стиле 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":"Это правило проверяет, что все файлы имеют имя в формате lower_snake_case (только строчные буквы, цифры и символ подчеркивания, без пробелов и заглавных букв).","content":"Это правило проверяет, что все файлы имеют имя в формате 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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **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":"Это правило проверяет, что в proto-файле не используются public импорты (оператор import public \"...\").","content":"Это правило проверяет, что в proto-файле не используются public импорты (оператор import public \"...\")."},{"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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **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":"Это правило проверяет, что в proto‑файле не используются weak‑импорты (import weak \"...\").","content":"Это правило проверяет, что в proto‑файле не используются weak‑импорты (import weak \"...\")."},{"id":"cli/linter/rules/import-no-weak::top::2","title":"IMPORT_NO_WEAK","path":"/docs/guide/cli/linter/rules/import-no-weak","headings":[],"excerpt":"Weak import (синтаксис import weak) допустим в proto2, но его использование усложняет анализ зависимостей и может приводить к неочевидным ошибкам при генерации кода. Рекомендуется всегда использовать обычный import.","content":"Weak import (синтаксис import weak) допустим в proto2, но его использование усложняет анализ зависимостей и может приводить к неочевидным ошибкам при генерации кода. Рекомендуется всегда использовать обычный import."},{"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 ```proto syntax = \"proto2\";","content":"Bad ```proto syntax = \"proto2\";"},{"id":"cli/linter/rules/import-no-weak::bad::4","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::5","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::6","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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **MINIMAL** **BASIC** **DEFAULT**"},{"id":"cli/linter/rules/import-used::top::1","title":"IMPORT_USED","path":"/docs/guide/cli/linter/rules/import-used","headings":[],"excerpt":"Это правило проверяет, что все импорты используются в proto-файле.","content":"Это правило проверяет, что все импорты используются в proto-файле."},{"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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **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":"Это правило проверяет, что имена сообщений (message) записаны в стиле PascalCase.","content":"Это правило проверяет, что имена сообщений (message) записаны в стиле 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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **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":"Это правило проверяет, что имена oneof записаны в стиле lower_snake_case.","content":"Это правило проверяет, что имена oneof записаны в стиле 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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **MINIMAL** **BASIC** **DEFAULT**"},{"id":"cli/linter/rules/package-defined::top::1","title":"PACKAGE_DEFINED","path":"/docs/guide/cli/linter/rules/package-defined","headings":[],"excerpt":"Это правило проверяет, что во всех файлах присутствует директива package.","content":"Это правило проверяет, что во всех файлах присутствует директива package."},{"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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **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":"Это правило проверяет, что все файлы находятся в директории, имя которой соответствует имени их пакета.","content":"Это правило проверяет, что все файлы находятся в директории, имя которой соответствует имени их пакета."},{"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":"Это правило проверяет, что имена package записаны в формате lower_snake_case (строчные буквы, при необходимости цифры и символ подчеркивания, без пробелов и заглавных букв).","content":"Это правило проверяет, что имена package записаны в формате 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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **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":"Это правило проверяет, что все файлы с заданным пакетом используют одно и то же пространство имён C# (csharp_namespace).","content":"Это правило проверяет, что все файлы с заданным пакетом используют одно и то же пространство имён C# (csharp_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\"; // [!code focus] ```","content":"Good option csharp_namespace = \"Foo.Bar\"; // [!code focus] ```"},{"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 ```proto // File: pkg/bar.proto","content":"Good ```proto // File: pkg/bar.proto"},{"id":"cli/linter/rules/package-same-csharp-namespace::good::9","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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **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":"Это правило проверяет, что все файлы с данным package находятся в одной директории.","content":"Это правило проверяет, что все файлы с данным package находятся в одной директории."},{"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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **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":"Это правило проверяет, что все файлы с одним и тем же package используют одно и то же значение опции go_package.","content":"Это правило проверяет, что все файлы с одним и тем же package используют одно и то же значение опции 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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **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":"Это правило проверяет, что все файлы с одним и тем же package используют одинаковое значение опции java_package.","content":"Это правило проверяет, что все файлы с одним и тем же package используют одинаковое значение опции 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 ```proto // File: pkg/bar.proto","content":"Bad ```proto // File: pkg/bar.proto"},{"id":"cli/linter/rules/package-same-java-multiple-files::bad::6","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::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 ```proto // File: pkg/foo.proto","content":"Good ```proto // File: pkg/foo.proto"},{"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 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::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 ```proto // File: pkg/bar.proto","content":"Good ```proto // File: pkg/bar.proto"},{"id":"cli/linter/rules/package-same-java-multiple-files::good::10","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":"Это правило проверяет, что все файлы с одним и тем же package используют одно и то же значение опции java_package.","content":"Это правило проверяет, что все файлы с одним и тем же package используют одно и то же значение опции 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":"Это правило проверяет, что все файлы с одним и тем же package используют одно и то же значение опции php_namespace.","content":"Это правило проверяет, что все файлы с одним и тем же package используют одно и то же значение опции 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":"Это правило проверяет, что все файлы с одним и тем же package используют один и тот же swift_prefix.","content":"Это правило проверяет, что все файлы с одним и тем же package используют один и тот же 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":"Это правило проверяет, что суффикс версии пакета имеет формат _vX, где X — числовая версия.","content":"Это правило проверяет, что суффикс версии пакета имеет формат _vX, где X — числовая версия."},{"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":"Это правило проверяет, что RPC не использует клиентский стриминг (запрос не является stream ...).","content":"Это правило проверяет, что RPC не использует клиентский стриминг (запрос не является stream ...)."},{"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":"Это правило проверяет, что RPC не использует серверный стриминг (ответ не является stream ...).","content":"Это правило проверяет, что RPC не использует серверный стриминг (ответ не является stream ...)."},{"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":"Это правило проверяет, что все имена RPC написаны в стиле PascalCase.","content":"Это правило проверяет, что все имена RPC написаны в стиле 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":"Это правило проверяет, что все сообщения запроса и ответа RPC уникальны: для каждого метода используются собственные (не переиспользуются одинаковые пары Request / Response у разных RPC).","content":"Это правило проверяет, что все сообщения запроса и ответа RPC уникальны: для каждого метода используются собственные (не переиспользуются одинаковые пары Request / Response у разных RPC)."},{"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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **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":"Это правило проверяет, что все сообщения запроса RPC названы в формате MethodRequest.","content":"Это правило проверяет, что все сообщения запроса RPC названы в формате 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":"Это правило проверяет, что все сообщения ответа RPC названы в формате MethodResponse.","content":"Это правило проверяет, что все сообщения ответа RPC названы в формате 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":"**MINIMAL** **BASIC** **DEFAULT**","content":"**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":"Это правило проверяет, что все имена сервисов написаны в стиле PascalCase.","content":"Это правило проверяет, что все имена сервисов написаны в стиле 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":"Это правило проверяет, что все сервисы имеют суффикс Service или ваш пользовательский суффикс.","content":"Это правило проверяет, что все сервисы имеют суффикс Service или ваш пользовательский суффикс."},{"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 против Buf: управление пакетами","path":"/docs/guide/cli/package-manager/easyp-vs-buf","headings":[],"excerpt":"EasyP против Buf: управление пакетами","content":"EasyP против Buf: управление пакетами"},{"id":"cli/package-manager/easyp-vs-buf::top::1","title":"EasyP против Buf: управление пакетами","path":"/docs/guide/cli/package-manager/easyp-vs-buf","headings":[],"excerpt":"Этот документ даёт подробное сравнение децентрализованного подхода EasyP к управлению пакетами и централизованной модели Buf через Buf Schema Registry (BSR), чтобы помочь понять ключевые различия и выбрать подходящее реш","content":"Этот документ даёт подробное сравнение децентрализованного подхода EasyP к управлению пакетами и централизованной модели Buf через Buf Schema Registry (BSR), чтобы помочь понять ключевые различия и выбрать подходящее решение для ваших задач."},{"id":"cli/package-manager/easyp-vs-buf::easyp-git::2","title":"EasyP против Buf: управление пакетами","section":"EasyP: децентрализованный подход на базе Git","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp-git","headings":["EasyP: децентрализованный подход на базе Git"],"excerpt":"EasyP: децентрализованный подход на базе Git","content":"EasyP: децентрализованный подход на базе Git"},{"id":"cli/package-manager/easyp-vs-buf::buf-bsr::3","title":"EasyP против Buf: управление пакетами","section":"Buf: централизованный реестр (BSR)","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf-bsr","headings":["Buf: централизованный реестр (BSR)"],"excerpt":"Buf: централизованный реестр (BSR)","content":"Buf: централизованный реестр (BSR)"},{"id":"cli/package-manager/easyp-vs-buf::top::4","title":"EasyP против Buf: управление пакетами","section":"Краткое резюме различий","path":"/docs/guide/cli/package-manager/easyp-vs-buf","headings":["Краткое резюме различий"],"excerpt":"Краткое резюме различий Аспект EasyP Buf -------- ------- ----- **Архитектура** Децентрализованная (Git) Централизованная (реестр BSR) **Источник зависимостей** Любой Git репозиторий Только модули BSR **Единая точка отка","content":"Краткое резюме различий Аспект EasyP Buf -------- ------- ----- **Архитектура** Децентрализованная (Git) Централизованная (реестр BSR) **Источник зависимостей** Любой Git репозиторий Только модули BSR **Единая точка отказа** Нет Да (buf.build) **Enterprise / air‑gapped** Полная поддержка Требует доступа к BSR или приватного BSR **Аутентификация** Git (SSH / HTTPS) Токены Buf + Git **Vendor lock‑in** Отсутствует Привязка к экосистеме Buf **Частные репозитории** Нативно через Git Нужно опубликовать в BSR **Оффлайн поддержка** Полная (через vendoring) Ограничена (кэшированные модули) **Стоимость** Бесплатно (использует существующий Git) Бесплатный тариф + платные планы **Сложность настройки** Минимальная Средняя (настройка BSR)"},{"id":"cli/package-manager/easyp-vs-buf::top::5","title":"EasyP против Buf: управление пакетами","section":"Подробное сравнение возможностей","path":"/docs/guide/cli/package-manager/easyp-vs-buf","headings":["Подробное сравнение возможностей"],"excerpt":"Подробное сравнение возможностей","content":"Подробное сравнение возможностей"},{"id":"cli/package-manager/easyp-vs-buf::1::6","title":"EasyP против Buf: управление пакетами","section":"1. Философия управления зависимостями","path":"/docs/guide/cli/package-manager/easyp-vs-buf#1","headings":["1. Философия управления зависимостями"],"excerpt":"Философия управления зависимостями","content":"Философия управления зависимостями"},{"id":"cli/package-manager/easyp-vs-buf::easyp-git::7","title":"EasyP против Buf: управление пакетами","section":"EasyP: «Любой Git репозиторий — это пакет»","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp-git","headings":["EasyP: «Любой Git репозиторий — это пакет»"],"excerpt":"EasyP: «Любой Git репозиторий — это пакет»","content":"EasyP: «Любой Git репозиторий — это пакет»"},{"id":"cli/package-manager/easyp-vs-buf::easyp-git::8","title":"EasyP против Buf: управление пакетами","section":"EasyP: «Любой Git репозиторий — это пакет»","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp-git","headings":["EasyP: «Любой Git репозиторий — это пакет»"],"excerpt":"EasyP: «Любой Git репозиторий — это пакет» **Преимущества:** ✅ Использование любого существующего репозитория сразу ✅ Не нужно «публиковать» в отдельный реестр ✅ Истинный источник версий — Git ✅ Работает с приватными сер","content":"EasyP: «Любой Git репозиторий — это пакет» **Преимущества:** ✅ Использование любого существующего репозитория сразу ✅ Не нужно «публиковать» в отдельный реестр ✅ Истинный источник версий — Git ✅ Работает с приватными серверами без доп. настроек"},{"id":"cli/package-manager/easyp-vs-buf::buf::9","title":"EasyP против Buf: управление пакетами","section":"Buf: «Сначала реестр»","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf","headings":["Buf: «Сначала реестр»"],"excerpt":"Buf: «Сначала реестр» **Преимущества:** ✅ Курируемые, проверенные модули ✅ Богатые метаданные и документация ✅ Визуализация графа зависимостей ✅ Принуждение семантического версионирования","content":"Buf: «Сначала реестр» **Преимущества:** ✅ Курируемые, проверенные модули ✅ Богатые метаданные и документация ✅ Визуализация графа зависимостей ✅ Принуждение семантического версионирования"},{"id":"cli/package-manager/easyp-vs-buf::buf::10","title":"EasyP против Buf: управление пакетами","section":"Buf: «Сначала реестр»","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf","headings":["Buf: «Сначала реестр»"],"excerpt":"Buf: «Сначала реестр» **Ограничения:** ❌ Нужно опубликовать в BSR перед использованием ❌ Требует аккаунт и аутентификацию ❌ Нельзя напрямую сослаться на произвольный Git репозиторий","content":"Buf: «Сначала реестр» **Ограничения:** ❌ Нужно опубликовать в BSR перед использованием ❌ Требует аккаунт и аутентификацию ❌ Нельзя напрямую сослаться на произвольный Git репозиторий"},{"id":"cli/package-manager/easyp-vs-buf::2-airgapped::11","title":"EasyP против Buf: управление пакетами","section":"2. Корпоративные и изолированные (air‑gapped) среды","path":"/docs/guide/cli/package-manager/easyp-vs-buf#2-airgapped","headings":["2. Корпоративные и изолированные (air‑gapped) среды"],"excerpt":"Корпоративные и изолированные (air‑gapped) среды","content":"Корпоративные и изолированные (air‑gapped) среды"},{"id":"cli/package-manager/easyp-vs-buf::easyp::12","title":"EasyP против Buf: управление пакетами","section":"EasyP: Полноценная оффлайн‑поддержка","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["EasyP: Полноценная оффлайн‑поддержка"],"excerpt":"EasyP: Полноценная оффлайн‑поддержка **Сценарий**: крупная компания со строгими сетевыми политиками","content":"EasyP: Полноценная оффлайн‑поддержка **Сценарий**: крупная компания со строгими сетевыми политиками"},{"id":"cli/package-manager/easyp-vs-buf::easyp::13","title":"EasyP против Buf: управление пакетами","section":"EasyP: Полноценная оффлайн‑поддержка","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["EasyP: Полноценная оффлайн‑поддержка"],"excerpt":"EasyP: Полноценная оффлайн‑поддержка ```bash Среда с доступом в интернет easyp mod download # Скачивает в ~/.easyp/ easyp mod vendor # Создает easyp_vendor/","content":"EasyP: Полноценная оффлайн‑поддержка ```bash Среда с доступом в интернет easyp mod download # Скачивает в ~/.easyp/ easyp mod vendor # Создает easyp_vendor/"},{"id":"cli/package-manager/easyp-vs-buf::easyp::14","title":"EasyP против Buf: управление пакетами","section":"EasyP: Полноценная оффлайн‑поддержка","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["EasyP: Полноценная оффлайн‑поддержка"],"excerpt":"EasyP: Полноценная оффлайн‑поддержка Перенос в изолированный сегмент tar -czf easyp-deps.tar.gz ~/.easyp easyp_vendor/ ... перенос архива ...","content":"EasyP: Полноценная оффлайн‑поддержка Перенос в изолированный сегмент tar -czf easyp-deps.tar.gz ~/.easyp easyp_vendor/ ... перенос архива ..."},{"id":"cli/package-manager/easyp-vs-buf::easyp::15","title":"EasyP против Buf: управление пакетами","section":"EasyP: Полноценная оффлайн‑поддержка","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["EasyP: Полноценная оффлайн‑поддержка"],"excerpt":"EasyP: Полноценная оффлайн‑поддержка В изолированной среде tar -xzf easyp-deps.tar.gz export EASYPPATH=$PWD/.easyp easyp generate # Работает оффлайн ```","content":"EasyP: Полноценная оффлайн‑поддержка В изолированной среде tar -xzf easyp-deps.tar.gz export EASYPPATH=$PWD/.easyp easyp generate # Работает оффлайн ```"},{"id":"cli/package-manager/easyp-vs-buf::easyp::16","title":"EasyP против Buf: управление пакетами","section":"EasyP: Полноценная оффлайн‑поддержка","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["EasyP: Полноценная оффлайн‑поддержка"],"excerpt":"EasyP: Полноценная оффлайн‑поддержка **Плюсы:** ✅ Не зависит от внешних сервисов ✅ Не нужен внутренний реестр ✅ Использует существующую Git инфраструктуру ✅ Простая файловая дистрибуция","content":"EasyP: Полноценная оффлайн‑поддержка **Плюсы:** ✅ Не зависит от внешних сервисов ✅ Не нужен внутренний реестр ✅ Использует существующую Git инфраструктуру ✅ Простая файловая дистрибуция"},{"id":"cli/package-manager/easyp-vs-buf::buf::17","title":"EasyP против Buf: управление пакетами","section":"Buf: Требует инфраструктуру реестра","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf","headings":["Buf: Требует инфраструктуру реестра"],"excerpt":"Buf: Требует инфраструктуру реестра ```bash Вариант 1: использовать buf.build (нужен интернет) buf mod download","content":"Buf: Требует инфраструктуру реестра ```bash Вариант 1: использовать buf.build (нужен интернет) buf mod download"},{"id":"cli/package-manager/easyp-vs-buf::buf::18","title":"EasyP против Buf: управление пакетами","section":"Buf: Требует инфраструктуру реестра","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf","headings":["Buf: Требует инфраструктуру реестра"],"excerpt":"Buf: Требует инфраструктуру реестра Вариант 2: поднимать приватный BSR (сложно) Развернуть сервер реестра Перепубликовать все модули внутрь Настроить доступы, аутентификацию Поддерживать работоспособность ```","content":"Buf: Требует инфраструктуру реестра Вариант 2: поднимать приватный BSR (сложно) Развернуть сервер реестра Перепубликовать все модули внутрь Настроить доступы, аутентификацию Поддерживать работоспособность ```"},{"id":"cli/package-manager/easyp-vs-buf::buf::19","title":"EasyP против Buf: управление пакетами","section":"Buf: Требует инфраструктуру реестра","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf","headings":["Buf: Требует инфраструктуру реестра"],"excerpt":"Buf: Требует инфраструктуру реестра **Минусы:** ❌ Постоянный интернет или дорогой приватный BSR ❌ Сложная инфраструктура для частных установок ❌ Все модули нужно републиковать ❌ Дополнительные операционные затраты","content":"Buf: Требует инфраструктуру реестра **Минусы:** ❌ Постоянный интернет или дорогой приватный BSR ❌ Сложная инфраструктура для частных установок ❌ Все модули нужно републиковать ❌ Дополнительные операционные затраты"},{"id":"cli/package-manager/easyp-vs-buf::easyp::20","title":"EasyP против Buf: управление пакетами","section":"EasyP: Прямой контроль","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["EasyP: Прямой контроль"],"excerpt":"EasyP: Прямой контроль ```yaml Полный контроль источников deps: # Публичный репозиторий — ваша конкретная версия - github.com/googleapis/googleapis@common-protos-1_3_1","content":"EasyP: Прямой контроль ```yaml Полный контроль источников deps: # Публичный репозиторий — ваша конкретная версия - github.com/googleapis/googleapis@common-protos-1_3_1"},{"id":"cli/package-manager/easyp-vs-buf::easyp::21","title":"EasyP против Buf: управление пакетами","section":"EasyP: Прямой контроль","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["EasyP: Прямой контроль"],"excerpt":"EasyP: Прямой контроль Внутренний репозиторий - gitlab.company.com/security/validated-protos@v1.0.0","content":"EasyP: Прямой контроль Внутренний репозиторий - gitlab.company.com/security/validated-protos@v1.0.0"},{"id":"cli/package-manager/easyp-vs-buf::easyp::22","title":"EasyP против Buf: управление пакетами","section":"EasyP: Прямой контроль","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["EasyP: Прямой контроль"],"excerpt":"EasyP: Прямой контроль Точный коммит (горячий фикс) - github.com/bufbuild/protoc-gen-validate@abc123def456 ```","content":"EasyP: Прямой контроль Точный коммит (горячий фикс) - github.com/bufbuild/protoc-gen-validate@abc123def456 ```"},{"id":"cli/package-manager/easyp-vs-buf::easyp::23","title":"EasyP против Buf: управление пакетами","section":"EasyP: Прямой контроль","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["EasyP: Прямой контроль"],"excerpt":"EasyP: Прямой контроль **Преимущества по безопасности:** ✅ Нет посредника — берём из исходного репозитория ✅ Аудит через историю Git ✅ Нельзя «забанить» доступ извне ✅ Свои процессы сканирования / валидации ✅ Можно форкн","content":"EasyP: Прямой контроль **Преимущества по безопасности:** ✅ Нет посредника — берём из исходного репозитория ✅ Аудит через историю Git ✅ Нельзя «забанить» доступ извне ✅ Свои процессы сканирования / валидации ✅ Можно форкнуть и удерживать критические версии"},{"id":"cli/package-manager/easyp-vs-buf::buf::24","title":"EasyP против Buf: управление пакетами","section":"Buf: Зависимость от реестра","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf","headings":["Buf: Зависимость от реестра"],"excerpt":"Buf: Зависимость от реестра **Риски:** ⚠️ Посредник контролирует доступность ⚠️ Возможны ограничения / санкции на аккаунт ⚠️ Модуль могут удалить или депрекейтнуть ⚠️ Политики обновлений диктуются стороной ⚠️ Нужно довер","content":"Buf: Зависимость от реестра **Риски:** ⚠️ Посредник контролирует доступность ⚠️ Возможны ограничения / санкции на аккаунт ⚠️ Модуль могут удалить или депрекейтнуть ⚠️ Политики обновлений диктуются стороной ⚠️ Нужно доверять внешней безопасности"},{"id":"cli/package-manager/easyp-vs-buf::1::25","title":"EasyP против Buf: управление пакетами","section":"Сценарий 1: Стартап с публичными зависимостями","path":"/docs/guide/cli/package-manager/easyp-vs-buf#1","headings":["Сценарий 1: Стартап с публичными зависимостями"],"excerpt":"Сценарий 1: Стартап с публичными зависимостями **EasyP:**","content":"Сценарий 1: Стартап с публичными зависимостями **EasyP:**"},{"id":"cli/package-manager/easyp-vs-buf::1::26","title":"EasyP против Buf: управление пакетами","section":"Сценарий 1: Стартап с публичными зависимостями","path":"/docs/guide/cli/package-manager/easyp-vs-buf#1","headings":["Сценарий 1: Стартап с публичными зависимостями"],"excerpt":"Сценарий 1: Стартап с публичными зависимостями **Buf:**","content":"Сценарий 1: Стартап с публичными зависимостями **Buf:**"},{"id":"cli/package-manager/easyp-vs-buf::1::27","title":"EasyP против Buf: управление пакетами","section":"Сценарий 1: Стартап с публичными зависимостями","path":"/docs/guide/cli/package-manager/easyp-vs-buf#1","headings":["Сценарий 1: Стартап с публичными зависимостями"],"excerpt":"Сценарий 1: Стартап с публичными зависимостями **Итог:** Паритет — оба хорошо подходят для публичных пакетов.","content":"Сценарий 1: Стартап с публичными зависимостями **Итог:** Паритет — оба хорошо подходят для публичных пакетов."},{"id":"cli/package-manager/easyp-vs-buf::2::28","title":"EasyP против Buf: управление пакетами","section":"Сценарий 2: Компания со смешанными публичными/приватными зависимостями","path":"/docs/guide/cli/package-manager/easyp-vs-buf#2","headings":["Сценарий 2: Компания со смешанными публичными/приватными зависимостями"],"excerpt":"Сценарий 2: Компания со смешанными публичными/приватными зависимостями **EasyP:**","content":"Сценарий 2: Компания со смешанными публичными/приватными зависимостями **EasyP:**"},{"id":"cli/package-manager/easyp-vs-buf::2::29","title":"EasyP против Buf: управление пакетами","section":"Сценарий 2: Компания со смешанными публичными/приватными зависимостями","path":"/docs/guide/cli/package-manager/easyp-vs-buf#2","headings":["Сценарий 2: Компания со смешанными публичными/приватными зависимостями"],"excerpt":"Сценарий 2: Компания со смешанными публичными/приватными зависимостями **Buf:**","content":"Сценарий 2: Компания со смешанными публичными/приватными зависимостями **Buf:**"},{"id":"cli/package-manager/easyp-vs-buf::2::30","title":"EasyP против Buf: управление пакетами","section":"Сценарий 2: Компания со смешанными публичными/приватными зависимостями","path":"/docs/guide/cli/package-manager/easyp-vs-buf#2","headings":["Сценарий 2: Компания со смешанными публичными/приватными зависимостями"],"excerpt":"Сценарий 2: Компания со смешанными публичными/приватными зависимостями **Итог:** **EasyP** — не требует публикации внутрь BSR.","content":"Сценарий 2: Компания со смешанными публичными/приватными зависимостями **Итог:** **EasyP** — не требует публикации внутрь BSR."},{"id":"cli/package-manager/easyp-vs-buf::3-airgap::31","title":"EasyP против Buf: управление пакетами","section":"Сценарий 3: Государственный / оборонный подрядчик (полный air‑gap)","path":"/docs/guide/cli/package-manager/easyp-vs-buf#3-airgap","headings":["Сценарий 3: Государственный / оборонный подрядчик (полный air‑gap)"],"excerpt":"Сценарий 3: Государственный / оборонный подрядчик (полный air‑gap) **EasyP:**","content":"Сценарий 3: Государственный / оборонный подрядчик (полный air‑gap) **EasyP:**"},{"id":"cli/package-manager/easyp-vs-buf::3-airgap::32","title":"EasyP против Buf: управление пакетами","section":"Сценарий 3: Государственный / оборонный подрядчик (полный air‑gap)","path":"/docs/guide/cli/package-manager/easyp-vs-buf#3-airgap","headings":["Сценарий 3: Государственный / оборонный подрядчик (полный air‑gap)"],"excerpt":"Сценарий 3: Государственный / оборонный подрядчик (полный air‑gap) **Buf:**","content":"Сценарий 3: Государственный / оборонный подрядчик (полный air‑gap) **Buf:**"},{"id":"cli/package-manager/easyp-vs-buf::3-airgap::33","title":"EasyP против Buf: управление пакетами","section":"Сценарий 3: Государственный / оборонный подрядчик (полный air‑gap)","path":"/docs/guide/cli/package-manager/easyp-vs-buf#3-airgap","headings":["Сценарий 3: Государственный / оборонный подрядчик (полный air‑gap)"],"excerpt":"Сценарий 3: Государственный / оборонный подрядчик (полный air‑gap) **Итог:** **EasyP** — значительно проще.","content":"Сценарий 3: Государственный / оборонный подрядчик (полный air‑gap) **Итог:** **EasyP** — значительно проще."},{"id":"cli/package-manager/easyp-vs-buf::4::34","title":"EasyP против Buf: управление пакетами","section":"Сценарий 4: Комплаенс и аудит","path":"/docs/guide/cli/package-manager/easyp-vs-buf#4","headings":["Сценарий 4: Комплаенс и аудит"],"excerpt":"Сценарий 4: Комплаенс и аудит **EasyP:** ✅ Прямой аудит изменений (коммиты) ✅ Нет внешних точек зависимости в проде ✅ Повторяемость через фиксированные коммиты / vendor ✅ Управление уязвимостями — в ваших руках","content":"Сценарий 4: Комплаенс и аудит **EasyP:** ✅ Прямой аудит изменений (коммиты) ✅ Нет внешних точек зависимости в проде ✅ Повторяемость через фиксированные коммиты / vendor ✅ Управление уязвимостями — в ваших руках"},{"id":"cli/package-manager/easyp-vs-buf::4::35","title":"EasyP против Buf: управление пакетами","section":"Сценарий 4: Комплаенс и аудит","path":"/docs/guide/cli/package-manager/easyp-vs-buf#4","headings":["Сценарий 4: Комплаенс и аудит"],"excerpt":"Сценарий 4: Комплаенс и аудит **Buf:** ⚠️ Нужно учитывать BSR в области аудита ⚠️ Дополнительный риск третьей стороны ⚠️ Модули — внешние контролируемые артефакты ⚠️ Сложнее трассировать от реестра к исходникам","content":"Сценарий 4: Комплаенс и аудит **Buf:** ⚠️ Нужно учитывать BSR в области аудита ⚠️ Дополнительный риск третьей стороны ⚠️ Модули — внешние контролируемые артефакты ⚠️ Сложнее трассировать от реестра к исходникам"},{"id":"cli/package-manager/easyp-vs-buf::4::36","title":"EasyP против Buf: управление пакетами","section":"Сценарий 4: Комплаенс и аудит","path":"/docs/guide/cli/package-manager/easyp-vs-buf#4","headings":["Сценарий 4: Комплаенс и аудит"],"excerpt":"Сценарий 4: Комплаенс и аудит **Итог:** **EasyP** — проще для комплаенса.","content":"Сценарий 4: Комплаенс и аудит **Итог:** **EasyP** — проще для комплаенса."},{"id":"cli/package-manager/easyp-vs-buf::easyp::37","title":"EasyP против Buf: управление пакетами","section":"EasyP: Нулевая дополнительная инфраструктура","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["EasyP: Нулевая дополнительная инфраструктура"],"excerpt":"EasyP: Нулевая дополнительная инфраструктура **Затраты:** ✅ $0 — используете существующий Git ✅ Нет дополнительных сервисов/серверов ✅ Нет лицензирования ✅ Масштабирование в рамках Git","content":"EasyP: Нулевая дополнительная инфраструктура **Затраты:** ✅ $0 — используете существующий Git ✅ Нет дополнительных сервисов/серверов ✅ Нет лицензирования ✅ Масштабирование в рамках Git"},{"id":"cli/package-manager/easyp-vs-buf::easyp::38","title":"EasyP против Buf: управление пакетами","section":"EasyP: Нулевая дополнительная инфраструктура","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["EasyP: Нулевая дополнительная инфраструктура"],"excerpt":"EasyP: Нулевая дополнительная инфраструктура **Инфраструктура:** Использует текущие репозитории (GitHub/GitLab/и т.д.) Аутентификация — штатная Резервирование/DR — как уже настроено для Git","content":"EasyP: Нулевая дополнительная инфраструктура **Инфраструктура:** Использует текущие репозитории (GitHub/GitLab/и т.д.) Аутентификация — штатная Резервирование/DR — как уже настроено для Git"},{"id":"cli/package-manager/easyp-vs-buf::buf::39","title":"EasyP против Buf: управление пакетами","section":"Buf: Затраты на реестр","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf","headings":["Buf: Затраты на реестр"],"excerpt":"Buf: Затраты на реестр **Hosted BSR (buf.build):** ✅ Бесплатный уровень ❌ Платные тарифы для приватного и расширенного использования ❌ Потенциальные изменения ценовой политики ❌ Вопросы локализации данных","content":"Buf: Затраты на реестр **Hosted BSR (buf.build):** ✅ Бесплатный уровень ❌ Платные тарифы для приватного и расширенного использования ❌ Потенциальные изменения ценовой политики ❌ Вопросы локализации данных"},{"id":"cli/package-manager/easyp-vs-buf::buf::40","title":"EasyP против Buf: управление пакетами","section":"Buf: Затраты на реестр","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf","headings":["Buf: Затраты на реестр"],"excerpt":"Buf: Затраты на реестр **Приватный BSR:** ❌ Серверы, БД, балансировка ❌ Мониторинг, обновления, бэкапы ❌ Лицензирование enterprise функционала ❌ Доп. планирование отказоустойчивости","content":"Buf: Затраты на реестр **Приватный BSR:** ❌ Серверы, БД, балансировка ❌ Мониторинг, обновления, бэкапы ❌ Лицензирование enterprise функционала ❌ Доп. планирование отказоустойчивости"},{"id":"cli/package-manager/easyp-vs-buf::easyp::41","title":"EasyP против Buf: управление пакетами","section":"EasyP: Нет привязки","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["EasyP: Нет привязки"],"excerpt":"EasyP: Нет привязки **Миграция ИЗ EasyP:** (Обычные Git ссылки — легко перенести в другой инструмент.)","content":"EasyP: Нет привязки **Миграция ИЗ EasyP:** (Обычные Git ссылки — легко перенести в другой инструмент.)"},{"id":"cli/package-manager/easyp-vs-buf::easyp::42","title":"EasyP против Buf: управление пакетами","section":"EasyP: Нет привязки","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["EasyP: Нет привязки"],"excerpt":"EasyP: Нет привязки **Миграция В EasyP:**","content":"EasyP: Нет привязки **Миграция В EasyP:**"},{"id":"cli/package-manager/easyp-vs-buf::buf-lockin::43","title":"EasyP против Buf: управление пакетами","section":"Buf: Потенциальный lock‑in","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf-lockin","headings":["Buf: Потенциальный lock‑in"],"excerpt":"Buf: Потенциальный lock‑in **Миграция ИЗ Buf:** ❌ Нужно сопоставить BSR модули с исходными Git репо ❌ Имена модулей BSR не совпадают с URL ❌ Возможна потеря удобных метаданных ❌ Сложно при глубокой интеграции с BSR","content":"Buf: Потенциальный lock‑in **Миграция ИЗ Buf:** ❌ Нужно сопоставить BSR модули с исходными Git репо ❌ Имена модулей BSR не совпадают с URL ❌ Возможна потеря удобных метаданных ❌ Сложно при глубокой интеграции с BSR"},{"id":"cli/package-manager/easyp-vs-buf::buf-lockin::44","title":"EasyP против Buf: управление пакетами","section":"Buf: Потенциальный lock‑in","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf-lockin","headings":["Buf: Потенциальный lock‑in"],"excerpt":"Buf: Потенциальный lock‑in **Миграция В Buf:** ❌ Нужно опубликовать всё в BSR ❌ Нельзя ссылаться напрямую на Git ❌ Принять workflow BSR (push/pull модулей)","content":"Buf: Потенциальный lock‑in **Миграция В Buf:** ❌ Нужно опубликовать всё в BSR ❌ Нельзя ссылаться напрямую на Git ❌ Принять workflow BSR (push/pull модулей)"},{"id":"cli/package-manager/easyp-vs-buf::easyp::45","title":"EasyP против Buf: управление пакетами","section":"Выберите EasyP, если:","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["Выберите EasyP, если:"],"excerpt":"Выберите EasyP, если: ✅ **Air‑gapped / закрытые среды** Нужна работа без внешних сервисов Строгий комплаенс / контроль цепочки поставок","content":"Выберите EasyP, если: ✅ **Air‑gapped / закрытые среды** Нужна работа без внешних сервисов Строгий комплаенс / контроль цепочки поставок"},{"id":"cli/package-manager/easyp-vs-buf::easyp::46","title":"EasyP против Buf: управление пакетами","section":"Выберите EasyP, если:","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["Выберите EasyP, если:"],"excerpt":"Выберите EasyP, если: ✅ **Фокус на безопасности** Контроль источников зависимостей Минимизация рисков третьих сторон","content":"Выберите EasyP, если: ✅ **Фокус на безопасности** Контроль источников зависимостей Минимизация рисков третьих сторон"},{"id":"cli/package-manager/easyp-vs-buf::easyp::47","title":"EasyP против Buf: управление пакетами","section":"Выберите EasyP, если:","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["Выберите EasyP, если:"],"excerpt":"Выберите EasyP, если: ✅ **Git‑центричная культура** Частные репозитории — норма Не хотите добавлять новый ключевой сервис","content":"Выберите EasyP, если: ✅ **Git‑центричная культура** Частные репозитории — норма Не хотите добавлять новый ключевой сервис"},{"id":"cli/package-manager/easyp-vs-buf::easyp::48","title":"EasyP против Buf: управление пакетами","section":"Выберите EasyP, если:","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["Выберите EasyP, если:"],"excerpt":"Выберите EasyP, если: ✅ **Ограниченный бюджет** Минимизация операционных расходов Предсказуемая стоимость = 0","content":"Выберите EasyP, если: ✅ **Ограниченный бюджет** Минимизация операционных расходов Предсказуемая стоимость = 0"},{"id":"cli/package-manager/easyp-vs-buf::easyp::49","title":"EasyP против Buf: управление пакетами","section":"Выберите EasyP, если:","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["Выберите EasyP, если:"],"excerpt":"Выберите EasyP, если: ✅ **Смешанные публичные/частные зависимости** Не хотите перекладывать всё в реестр Нужна гибкость форматов и размещения","content":"Выберите EasyP, если: ✅ **Смешанные публичные/частные зависимости** Не хотите перекладывать всё в реестр Нужна гибкость форматов и размещения"},{"id":"cli/package-manager/easyp-vs-buf::buf::50","title":"EasyP против Buf: управление пакетами","section":"Выберите Buf, если:","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf","headings":["Выберите Buf, если:"],"excerpt":"Выберите Buf, если: ✅ **Глубокая интеграция в экосистему BSR** Уже используете линтеры / генерацию Buf Нужны курируемые официальные модули Важны метаданные и граф зависимостей","content":"Выберите Buf, если: ✅ **Глубокая интеграция в экосистему BSR** Уже используете линтеры / генерацию Buf Нужны курируемые официальные модули Важны метаданные и граф зависимостей"},{"id":"cli/package-manager/easyp-vs-buf::buf::51","title":"EasyP против Buf: управление пакетами","section":"Выберите Buf, если:","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf","headings":["Выберите Buf, если:"],"excerpt":"Выберите Buf, если: ✅ **Сотрудничество и открытая разработка** Централизованное обнаружение модулей Совместная работа над общими пакетами","content":"Выберите Buf, если: ✅ **Сотрудничество и открытая разработка** Централизованное обнаружение модулей Совместная работа над общими пакетами"},{"id":"cli/package-manager/easyp-vs-buf::buf::52","title":"EasyP против Buf: управление пакетами","section":"Выберите Buf, если:","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf","headings":["Выберите Buf, если:"],"excerpt":"Выберите Buf, если: ✅ **Команда новичков в protobuf** Требуется «направляющая» структура Ценность документации внутри реестра","content":"Выберите Buf, если: ✅ **Команда новичков в protobuf** Требуется «направляющая» структура Ценность документации внутри реестра"},{"id":"cli/package-manager/easyp-vs-buf::buf::53","title":"EasyP против Buf: управление пакетами","section":"Выберите Buf, если:","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf","headings":["Выберите Buf, если:"],"excerpt":"Выберите Buf, если: ✅ **Небольшой набор публичных зависимостей** В основном используете популярные общие пакеты Вас устраивает зависимость от BSR","content":"Выберите Buf, если: ✅ **Небольшой набор публичных зависимостей** В основном используете популярные общие пакеты Вас устраивает зависимость от BSR"},{"id":"cli/package-manager/easyp-vs-buf::buf-easyp::54","title":"EasyP против Buf: управление пакетами","section":"Переход с Buf на EasyP","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf-easyp","headings":["Переход с Buf на EasyP"],"excerpt":"Переход с Buf на EasyP Найдите исходные Git репозитории для каждого модуля BSR Сопоставьте имена BSR → Git ссылки (с версиями/тегами) Обновите конфигурацию (easyp.yaml) Протестируйте генерацию и совместимость","content":"Переход с Buf на EasyP Найдите исходные Git репозитории для каждого модуля BSR Сопоставьте имена BSR → Git ссылки (с версиями/тегами) Обновите конфигурацию (easyp.yaml) Протестируйте генерацию и совместимость"},{"id":"cli/package-manager/easyp-vs-buf::buf-easyp::55","title":"EasyP против Buf: управление пакетами","section":"Переход с Buf на EasyP","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf-easyp","headings":["Переход с Buf на EasyP"],"excerpt":"Переход с Buf на EasyP ```yaml Было (buf.yaml) deps: - buf.build/googleapis/googleapis - buf.build/grpc/grpc","content":"Переход с Buf на EasyP ```yaml Было (buf.yaml) deps: - buf.build/googleapis/googleapis - buf.build/grpc/grpc"},{"id":"cli/package-manager/easyp-vs-buf::buf-easyp::56","title":"EasyP против Buf: управление пакетами","section":"Переход с Buf на EasyP","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf-easyp","headings":["Переход с Buf на EasyP"],"excerpt":"Переход с Buf на EasyP Стало (easyp.yaml) deps: - github.com/googleapis/googleapis@common-protos-1_3_1 - github.com/grpc/grpc@v1.50.0 ```","content":"Переход с Buf на EasyP Стало (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::easyp-buf::57","title":"EasyP против Buf: управление пакетами","section":"Переход с EasyP на Buf","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp-buf","headings":["Переход с EasyP на Buf"],"excerpt":"Переход с EasyP на Buf Опубликуйте используемые репозитории как модули BSR Настройте аутентификацию / организацию Buf Замените Git ссылки на BSR модули Перейдите к push/pull workflow Buf","content":"Переход с EasyP на Buf Опубликуйте используемые репозитории как модули BSR Настройте аутентификацию / организацию Buf Замените Git ссылки на BSR модули Перейдите к push/pull workflow Buf"},{"id":"cli/package-manager/easyp-vs-buf::top::58","title":"EasyP против Buf: управление пакетами","section":"Заключение","path":"/docs/guide/cli/package-manager/easyp-vs-buf","headings":["Заключение"],"excerpt":"Заключение Оба инструмента решают задачу управления зависимостями protobuf, но подходят под разные приоритеты:","content":"Заключение Оба инструмента решают задачу управления зависимостями protobuf, но подходят под разные приоритеты:"},{"id":"cli/package-manager/easyp-vs-buf::top::59","title":"EasyP против Buf: управление пакетами","section":"Заключение","path":"/docs/guide/cli/package-manager/easyp-vs-buf","headings":["Заключение"],"excerpt":"Заключение **Сильные стороны EasyP:** Корпоративные / изолированные среды Жёсткие требования безопасности и аудита Минимальные затраты и отсутствие доп. инфраструктуры Прямое использование Git (без промежуточного слоя) П","content":"Заключение **Сильные стороны EasyP:** Корпоративные / изолированные среды Жёсткие требования безопасности и аудита Минимальные затраты и отсутствие доп. инфраструктуры Прямое использование Git (без промежуточного слоя) Простота масштабирования"},{"id":"cli/package-manager/easyp-vs-buf::top::60","title":"EasyP против Buf: управление пакетами","section":"Заключение","path":"/docs/guide/cli/package-manager/easyp-vs-buf","headings":["Заключение"],"excerpt":"Заключение **Сильные стороны Buf:** Богатая экосистема вокруг реестра Курируемые и документированные модули Удобство для новых команд в protobuf Средства визуализации и централизованного обмена","content":"Заключение **Сильные стороны Buf:** Богатая экосистема вокруг реестра Курируемые и документированные модули Удобство для новых команд в protobuf Средства визуализации и централизованного обмена"},{"id":"cli/package-manager/easyp-vs-buf::top::61","title":"EasyP против Buf: управление пакетами","section":"Заключение","path":"/docs/guide/cli/package-manager/easyp-vs-buf","headings":["Заключение"],"excerpt":"Заключение Выбор часто сводится к балансу между **контролем vs. удобством**, **безопасностью vs. централизованными функциями**, и **стоимостью vs. managed‑сервисом**.","content":"Заключение Выбор часто сводится к балансу между **контролем vs. удобством**, **безопасностью vs. централизованными функциями**, и **стоимостью vs. managed‑сервисом**."},{"id":"cli/package-manager/easyp-vs-buf::top::62","title":"EasyP против Buf: управление пакетами","section":"Заключение","path":"/docs/guide/cli/package-manager/easyp-vs-buf","headings":["Заключение"],"excerpt":"Заключение Для большинства enterprise‑окружений децентрализованный Git‑подход EasyP обеспечивает нужные гибкость, безопасность и предсказуемость расходов, тогда как Buf отлично подходит командам, которым важна централизо","content":"Заключение Для большинства enterprise‑окружений децентрализованный Git‑подход EasyP обеспечивает нужные гибкость, безопасность и предсказуемость расходов, тогда как Buf отлично подходит командам, которым важна централизованная коллаборация и богатая экосистема вокруг реестра."},{"id":"cli/package-manager/package-manager::top::0","title":"Менеджер пакетов","path":"/docs/guide/cli/package-manager/package-manager","headings":[],"excerpt":"EasyP предоставляет мощный менеджер пакетов для protobuf‑зависимостей, упрощающий их управление за счёт децентрализованного подхода на базе Git. В отличие от централизованных решений, EasyP работает напрямую с Git‑репози","content":"EasyP предоставляет мощный менеджер пакетов для protobuf‑зависимостей, упрощающий их управление за счёт децентрализованного подхода на базе Git. В отличие от централизованных решений, EasyP работает напрямую с Git‑репозиториями, давая вам полный контроль."},{"id":"cli/package-manager/package-manager::top::1","title":"Менеджер пакетов","section":"Обзор","path":"/docs/guide/cli/package-manager/package-manager","headings":["Обзор"],"excerpt":"Обзор Менеджер пакетов EasyP следует философии **Go modules** — любой Git‑репозиторий может быть источником. Это даёт преимущества:","content":"Обзор Менеджер пакетов EasyP следует философии **Go modules** — любой Git‑репозиторий может быть источником. Это даёт преимущества:"},{"id":"cli/package-manager/package-manager::top::2","title":"Менеджер пакетов","section":"Обзор","path":"/docs/guide/cli/package-manager/package-manager","headings":["Обзор"],"excerpt":"Обзор **Децентрализация** — нет единой точки отказа или контроля **Безопасность** — прямой доступ к исходникам **Гибкость** — публичные, приватные и корпоративные репозитории **Воспроизводимость** — lock‑файлы обеспечива","content":"Обзор **Децентрализация** — нет единой точки отказа или контроля **Безопасность** — прямой доступ к исходникам **Гибкость** — публичные, приватные и корпоративные репозитории **Воспроизводимость** — lock‑файлы обеспечивают одинаковые сборки **Производительность** — локальный кеш сокращает сетевые запросы"},{"id":"cli/package-manager/package-manager::top::3","title":"Менеджер пакетов","section":"Основные возможности","path":"/docs/guide/cli/package-manager/package-manager","headings":["Основные возможности"],"excerpt":"Основные возможности Возможность Описание ------------- ---------- **Git-Native** Любой Git репозиторий, не нужен спец‑сервер **Множество форматов версий** Теги, коммиты, псевдо‑версии, latest **Lock Files** Воспроизводи","content":"Основные возможности Возможность Описание ------------- ---------- **Git-Native** Любой Git репозиторий, не нужен спец‑сервер **Множество форматов версий** Теги, коммиты, псевдо‑версии, latest **Lock Files** Воспроизводимые сборки через easyp.lock **Локальный кеш** Архитектура как у Go modules **Vendoring** Локальное копирование для оффлайн сборок **YAML конфигурация** Простые и читаемые декларации"},{"id":"cli/package-manager/package-manager::top::4","title":"Менеджер пакетов","section":"Архитектура","path":"/docs/guide/cli/package-manager/package-manager","headings":["Архитектура"],"excerpt":"Архитектура EasyP использует двухуровневый кеш, вдохновлённый Go modules:","content":"Архитектура EasyP использует двухуровневый кеш, вдохновлённый Go modules:"},{"id":"cli/package-manager/package-manager::top::5","title":"Менеджер пакетов","section":"Расположение кеша","path":"/docs/guide/cli/package-manager/package-manager","headings":["Расположение кеша"],"excerpt":"Расположение кеша Окружение Путь Как задать ----------- ------ ----------- **По умолчанию** $HOME/.easyp Автоматически **Свое** Любая директория Переменная EASYPPATH **CI/CD** В каталоге проекта export EASYPPATH=$CI_PROJ","content":"Расположение кеша Окружение Путь Как задать ----------- ------ ----------- **По умолчанию** $HOME/.easyp Автоматически **Свое** Любая директория Переменная EASYPPATH **CI/CD** В каталоге проекта export EASYPPATH=$CI_PROJECT_DIR/.easyp"},{"id":"cli/package-manager/package-manager::top::6","title":"Менеджер пакетов","section":"Базовая конфигурация","path":"/docs/guide/cli/package-manager/package-manager","headings":["Базовая конфигурация"],"excerpt":"Базовая конфигурация Зависимости описываются в easyp.yaml:","content":"Базовая конфигурация Зависимости описываются в easyp.yaml:"},{"id":"cli/package-manager/package-manager::multi-environment-setup::7","title":"Менеджер пакетов","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 # Последнее для разработки - github.com/mycompany/internal-protos # Внутренние изменения - github.com/bufbuild/protoc-gen-va","content":"Multi-Environment Setup ```yaml development.easyp.yaml deps: - github.com/googleapis/googleapis # Последнее для разработки - github.com/mycompany/internal-protos # Внутренние изменения - github.com/bufbuild/protoc-gen-validate # Новые фичи"},{"id":"cli/package-manager/package-manager::multi-environment-setup::8","title":"Менеджер пакетов","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 # Зафиксировано - github.com/mycompany/internal-protos@v2.1.0 # Стабильно - github.com/bufbuild/protoc-gen-valida","content":"Multi-Environment Setup production.easyp.yaml deps: - github.com/googleapis/googleapis@common-protos-1_3_1 # Зафиксировано - github.com/mycompany/internal-protos@v2.1.0 # Стабильно - github.com/bufbuild/protoc-gen-validate@v0.10.1 # Проверено ```"},{"id":"cli/package-manager/package-manager::top::9","title":"Менеджер пакетов","section":"Приватные репозитории","path":"/docs/guide/cli/package-manager/package-manager","headings":["Приватные репозитории"],"excerpt":"Приватные репозитории ```yaml deps: # Публичное - github.com/googleapis/googleapis@common-protos-1_3_1","content":"Приватные репозитории ```yaml deps: # Публичное - github.com/googleapis/googleapis@common-protos-1_3_1"},{"id":"cli/package-manager/package-manager::top::10","title":"Менеджер пакетов","section":"Приватные репозитории","path":"/docs/guide/cli/package-manager/package-manager","headings":["Приватные репозитории"],"excerpt":"Приватные репозитории Частные - github.com/mycompany/auth-protos@v1.5.0 - github.com/mycompany/common-types@v2.0.1","content":"Приватные репозитории Частные - github.com/mycompany/auth-protos@v1.5.0 - github.com/mycompany/common-types@v2.0.1"},{"id":"cli/package-manager/package-manager::top::11","title":"Менеджер пакетов","section":"Приватные репозитории","path":"/docs/guide/cli/package-manager/package-manager","headings":["Приватные репозитории"],"excerpt":"Приватные репозитории Внутренний GitLab - gitlab.company.com/platform/messaging-protos@v0.3.0 ```","content":"Приватные репозитории Внутренний GitLab - gitlab.company.com/platform/messaging-protos@v0.3.0 ```"},{"id":"cli/package-manager/package-manager::top::12","title":"Менеджер пакетов","section":"Стратегии версионирования","path":"/docs/guide/cli/package-manager/package-manager","headings":["Стратегии версионирования"],"excerpt":"Стратегии версионирования Поддерживаются разные способы фиксации версий:","content":"Стратегии версионирования Поддерживаются разные способы фиксации версий:"},{"id":"cli/package-manager/package-manager::1::13","title":"Менеджер пакетов","section":"1. Семантические теги (для продакшена)","path":"/docs/guide/cli/package-manager/package-manager#1","headings":["1. Семантические теги (для продакшена)"],"excerpt":"Семантические теги (для продакшена)","content":"Семантические теги (для продакшена)"},{"id":"cli/package-manager/package-manager::1::14","title":"Менеджер пакетов","section":"1. Семантические теги (для продакшена)","path":"/docs/guide/cli/package-manager/package-manager#1","headings":["1. Семантические теги (для продакшена)"],"excerpt":"Семантические теги (для продакшена) **Используйте когда:** Продакшен Стабильное потребление API Нужна воспроизводимость","content":"Семантические теги (для продакшена) **Используйте когда:** Продакшен Стабильное потребление API Нужна воспроизводимость"},{"id":"cli/package-manager/package-manager::2-development::15","title":"Менеджер пакетов","section":"2. Последний тег (development)","path":"/docs/guide/cli/package-manager/package-manager#2-development","headings":["2. Последний тег (development)"],"excerpt":"Последний тег (development) **Подходит для:** Активной разработки Получения свежих возможностей Тестирования совместимости","content":"Последний тег (development) **Подходит для:** Активной разработки Получения свежих возможностей Тестирования совместимости"},{"id":"cli/package-manager/package-manager::3-bleeding-edge::16","title":"Менеджер пакетов","section":"3. Хеш коммита (Bleeding Edge)","path":"/docs/guide/cli/package-manager/package-manager#3-bleeding-edge","headings":["3. Хеш коммита (Bleeding Edge)"],"excerpt":"Хеш коммита (Bleeding Edge) **Когда нужно:** Нерелизные фичи Тест конкретного фикса Вклад в upstream","content":"Хеш коммита (Bleeding Edge) **Когда нужно:** Нерелизные фичи Тест конкретного фикса Вклад в upstream"},{"id":"cli/package-manager/package-manager::4::17","title":"Менеджер пакетов","section":"4. Псевдо‑версии (автоматически)","path":"/docs/guide/cli/package-manager/package-manager#4","headings":["4. Псевдо‑версии (автоматически)"],"excerpt":"Псевдо‑версии (автоматически) Если нет подходящего тега — создаётся псевдо‑версия:","content":"Псевдо‑версии (автоматически) Если нет подходящего тега — создаётся псевдо‑версия:"},{"id":"cli/package-manager/package-manager::easyp-mod-download::18","title":"Менеджер пакетов","section":"easyp mod download","path":"/docs/guide/cli/package-manager/package-manager#easyp-mod-download","headings":["easyp mod download"],"excerpt":"easyp mod download Скачивает и устанавливает все объявленные зависимости.","content":"easyp mod download Скачивает и устанавливает все объявленные зависимости."},{"id":"cli/package-manager/package-manager::easyp-mod-download::19","title":"Менеджер пакетов","section":"easyp mod download","path":"/docs/guide/cli/package-manager/package-manager#easyp-mod-download","headings":["easyp mod download"],"excerpt":"easyp mod download **Что делает:** Разрешает версии (теги → коммиты) Скачивает архивы в cache/download Проверяет контрольные суммы Распаковывает в cache/mod Обновляет easyp.lock","content":"easyp mod download **Что делает:** Разрешает версии (теги → коммиты) Скачивает архивы в cache/download Проверяет контрольные суммы Распаковывает в cache/mod Обновляет easyp.lock"},{"id":"cli/package-manager/package-manager::easyp-mod-download::20","title":"Менеджер пакетов","section":"easyp mod download","path":"/docs/guide/cli/package-manager/package-manager#easyp-mod-download","headings":["easyp mod download"],"excerpt":"easyp mod download **Пример:**","content":"easyp mod download **Пример:**"},{"id":"cli/package-manager/package-manager::easyp-mod-vendor::21","title":"Менеджер пакетов","section":"easyp mod vendor","path":"/docs/guide/cli/package-manager/package-manager#easyp-mod-vendor","headings":["easyp mod vendor"],"excerpt":"easyp mod vendor Копирует все proto зависимости в локальный easyp_vendor/ для оффлайна.","content":"easyp mod vendor Копирует все proto зависимости в локальный easyp_vendor/ для оффлайна."},{"id":"cli/package-manager/package-manager::easyp-mod-vendor::22","title":"Менеджер пакетов","section":"easyp mod vendor","path":"/docs/guide/cli/package-manager/package-manager#easyp-mod-vendor","headings":["easyp mod vendor"],"excerpt":"easyp mod vendor **Сценарии:** Docker сборки Air-gapped окружения Воспроизводимость Ускорение","content":"easyp mod vendor **Сценарии:** Docker сборки Air-gapped окружения Воспроизводимость Ускорение"},{"id":"cli/package-manager/package-manager::easyp-mod-update::23","title":"Менеджер пакетов","section":"easyp mod update","path":"/docs/guide/cli/package-manager/package-manager#easyp-mod-update","headings":["easyp mod update"],"excerpt":"easyp mod update Обновляет версии согласно easyp.yaml, пересоздаёт lock.","content":"easyp mod update Обновляет версии согласно easyp.yaml, пересоздаёт lock."},{"id":"cli/package-manager/package-manager::lock::24","title":"Менеджер пакетов","section":"Lock файл","path":"/docs/guide/cli/package-manager/package-manager#lock","headings":["Lock файл"],"excerpt":"Lock файл easyp.lock фиксирует точные версии и хеш содержимого:","content":"Lock файл easyp.lock фиксирует точные версии и хеш содержимого:"},{"id":"cli/package-manager/package-manager::lock::25","title":"Менеджер пакетов","section":"Lock файл","path":"/docs/guide/cli/package-manager/package-manager#lock","headings":["Lock файл"],"excerpt":"Lock файл **Формат строки:** Путь модуля Версия (тег или псевдо) Хеш содержимого (h1:)","content":"Lock файл **Формат строки:** Путь модуля Версия (тег или псевдо) Хеш содержимого (h1:)"},{"id":"cli/package-manager/package-manager::lock::26","title":"Менеджер пакетов","section":"Lock файл","path":"/docs/guide/cli/package-manager/package-manager#lock","headings":["Lock файл"],"excerpt":"Lock файл **Практики:** ✅ Коммитить easyp.lock ✅ Осознанно обновлять mod update ✅ Ревью изменений версий ❌ Не редактировать вручную","content":"Lock файл **Практики:** ✅ Коммитить easyp.lock ✅ Осознанно обновлять mod update ✅ Ревью изменений версий ❌ Не редактировать вручную"},{"id":"cli/package-manager/package-manager::top::27","title":"Менеджер пакетов","section":"Публичные репозитории","path":"/docs/guide/cli/package-manager/package-manager","headings":["Публичные репозитории"],"excerpt":"Публичные репозитории Работают без настроек:","content":"Публичные репозитории Работают без настроек:"},{"id":"cli/package-manager/package-manager::ssh::28","title":"Менеджер пакетов","section":"SSH ключи (рекомендуется)","path":"/docs/guide/cli/package-manager/package-manager#ssh","headings":["SSH ключи (рекомендуется)"],"excerpt":"SSH ключи (рекомендуется) Конфиг остаётся с HTTPS URL:","content":"SSH ключи (рекомендуется) Конфиг остаётся с HTTPS URL:"},{"id":"cli/package-manager/package-manager::personal-access-tokens::29","title":"Менеджер пакетов","section":"Personal Access Tokens","path":"/docs/guide/cli/package-manager/package-manager#personal-access-tokens","headings":["Personal Access Tokens"],"excerpt":"Personal Access Tokens ```bash git config --global credential.helper store echo \"https://username:token@github.com\" >> ~/.git-credentials","content":"Personal Access Tokens ```bash git config --global credential.helper store echo \"https://username:token@github.com\" >> ~/.git-credentials"},{"id":"cli/package-manager/package-manager::personal-access-tokens::30","title":"Менеджер пакетов","section":"Personal Access Tokens","path":"/docs/guide/cli/package-manager/package-manager#personal-access-tokens","headings":["Personal Access Tokens"],"excerpt":"Personal Access Tokens git config --global url.\"https://username:token@github.com/mycompany\".insteadOf \"https://github.com/mycompany\" ```","content":"Personal Access Tokens git config --global url.\"https://username:token@github.com/mycompany\".insteadOf \"https://github.com/mycompany\" ```"},{"id":"cli/package-manager/package-manager::top::31","title":"Менеджер пакетов","section":"Инициализация проекта","path":"/docs/guide/cli/package-manager/package-manager","headings":["Инициализация проекта"],"excerpt":"Инициализация проекта ```bash cat > easyp.yaml << EOF deps: - github.com/googleapis/googleapis - github.com/grpc-ecosystem/grpc-gateway@v2.19.1 EOF","content":"Инициализация проекта ```bash 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::top::32","title":"Менеджер пакетов","section":"Инициализация проекта","path":"/docs/guide/cli/package-manager/package-manager","headings":["Инициализация проекта"],"excerpt":"Инициализация проекта easyp mod download ls ~/.easyp/mod/github.com/googleapis/googleapis/ ```","content":"Инициализация проекта easyp mod download ls ~/.easyp/mod/github.com/googleapis/googleapis/ ```"},{"id":"cli/package-manager/package-manager::repository-not-found-authentication-failed::33","title":"Менеджер пакетов","section":"\"Repository not found\" / \"Authentication failed\"","path":"/docs/guide/cli/package-manager/package-manager#repository-not-found-authentication-failed","headings":["\"Repository not found\" / \"Authentication failed\""],"excerpt":"\"Repository not found\" / \"Authentication failed\"","content":"\"Repository not found\" / \"Authentication failed\""},{"id":"cli/package-manager/package-manager::cache-corruption-checksum-mismatch::34","title":"Менеджер пакетов","section":"\"Cache corruption\" / \"Checksum mismatch\"","path":"/docs/guide/cli/package-manager/package-manager#cache-corruption-checksum-mismatch","headings":["\"Cache corruption\" / \"Checksum mismatch\""],"excerpt":"\"Cache corruption\" / \"Checksum mismatch\"","content":"\"Cache corruption\" / \"Checksum mismatch\""},{"id":"cli/package-manager/package-manager::docker-multi-stage::35","title":"Менеджер пакетов","section":"Docker multi-stage","path":"/docs/guide/cli/package-manager/package-manager#docker-multi-stage","headings":["Docker multi-stage"],"excerpt":"Docker multi-stage ```dockerfile FROM ghcr.io/easyp-tech/easyp:latest AS deps WORKDIR /workspace COPY easyp.yaml easyp.lock ./ RUN easyp mod vendor","content":"Docker multi-stage ```dockerfile 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::36","title":"Менеджер пакетов","section":"Docker multi-stage","path":"/docs/guide/cli/package-manager/package-manager#docker-multi-stage","headings":["Docker multi-stage"],"excerpt":"Docker multi-stage FROM alpine:latest AS build WORKDIR /app COPY --from=deps /workspace/easyp_vendor ./easyp_vendor COPY . . RUN easyp generate ```","content":"Docker multi-stage FROM alpine:latest AS build WORKDIR /app COPY --from=deps /workspace/easyp_vendor ./easyp_vendor COPY . . RUN easyp generate ```"},{"id":"cli/package-manager/package-manager::monorepo::37","title":"Менеджер пакетов","section":"Monorepo","path":"/docs/guide/cli/package-manager/package-manager#monorepo","headings":["Monorepo"],"excerpt":"Monorepo Каждый easyp.yaml может иметь свой набор зависимостей.","content":"Monorepo Каждый easyp.yaml может иметь свой набор зависимостей."},{"id":"cli/package-manager/package-manager::workflow::38","title":"Менеджер пакетов","section":"Workflow разработки","path":"/docs/guide/cli/package-manager/package-manager#workflow","headings":["Workflow разработки"],"excerpt":"Workflow разработки ✅ Latest теги в активной разработке ✅ Фиксация версий в продакшене ✅ Коммит lock файла ✅ Ревью обновлений ✅ Тест после обновления","content":"Workflow разработки ✅ Latest теги в активной разработке ✅ Фиксация версий в продакшене ✅ Коммит lock файла ✅ Ревью обновлений ✅ Тест после обновления"},{"id":"cli/package-manager/package-manager::top::39","title":"Менеджер пакетов","section":"Безопасность","path":"/docs/guide/cli/package-manager/package-manager","headings":["Безопасность"],"excerpt":"Безопасность ✅ Фиксируйте версии ✅ Используйте SSH ключи ✅ Оценивайте новые зависимости ✅ Следите за уязвимостями ❌ Не храните секреты в конфиге","content":"Безопасность ✅ Фиксируйте версии ✅ Используйте SSH ключи ✅ Оценивайте новые зависимости ✅ Следите за уязвимостями ❌ Не храните секреты в конфиге"},{"id":"cli/package-manager/package-manager::top::40","title":"Менеджер пакетов","section":"Производительность","path":"/docs/guide/cli/package-manager/package-manager","headings":["Производительность"],"excerpt":"Производительность ✅ Агрессивное кеширование в CI ✅ Vendoring для частых сборок ✅ Чистка старого кеша ✅ Общий кеш для команды","content":"Производительность ✅ Агрессивное кеширование в CI ✅ Vendoring для частых сборок ✅ Чистка старого кеша ✅ Общий кеш для команды"},{"id":"cli/package-manager/package-manager::top::41","title":"Менеджер пакетов","section":"Командная работа","path":"/docs/guide/cli/package-manager/package-manager","headings":["Командная работа"],"excerpt":"Командная работа ✅ Документация по аутентификации ✅ Единые инструменты ✅ Автоматизация обновлений с тестами ✅ Общий кеш при возможности","content":"Командная работа ✅ Документация по аутентификации ✅ Единые инструменты ✅ Автоматизация обновлений с тестами ✅ Общий кеш при возможности"},{"id":"cli/package-manager/package-manager::top::42","title":"Менеджер пакетов","section":"Командная работа","path":"/docs/guide/cli/package-manager/package-manager","headings":["Командная работа"],"excerpt":"Командная работа Менеджер пакетов EasyP — масштабируемое децентрализованное решение от одиночных проектов до enterprise, сохраняя простоту и надёжность.","content":"Командная работа Менеджер пакетов EasyP — масштабируемое децентрализованное решение от одиночных проектов до enterprise, сохраняя простоту и надёжность."},{"id":"introduction/install::top::0","title":"Установка EasyP CLI","section":"Установка через менеджер пакетов системы","path":"/docs/guide/introduction/install","headings":["Установка через менеджер пакетов системы"],"excerpt":"Установка через менеджер пакетов системы","content":"Установка через менеджер пакетов системы"},{"id":"introduction/install::top::1","title":"Установка EasyP CLI","section":"Рекомендуемый способ установки","path":"/docs/guide/introduction/install","headings":["Рекомендуемый способ установки"],"excerpt":"Рекомендуемый способ установки","content":"Рекомендуемый способ установки"},{"id":"introduction/install::homebrew::2","title":"Установка EasyP CLI","section":"Homebrew","path":"/docs/guide/introduction/install#homebrew","headings":["Homebrew"],"excerpt":"Homebrew Можно установить бинарный релиз в macOS через Homebrew:","content":"Homebrew Можно установить бинарный релиз в macOS через Homebrew:"},{"id":"introduction/install::homebrew::3","title":"Установка EasyP CLI","section":"Homebrew","path":"/docs/guide/introduction/install#homebrew","headings":["Homebrew"],"excerpt":"Homebrew Work in progress — поддержка других менеджеров (apt, yum, pacman и т.д.) в процессе.","content":"Homebrew Work in progress — поддержка других менеджеров (apt, yum, pacman и т.д.) в процессе."},{"id":"introduction/install::_-_::4","title":"Установка EasyP CLI","section":"_Не рекомендуется_","path":"/docs/guide/introduction/install#_-_","headings":["_Не рекомендуется_"],"excerpt":"_Не рекомендуется_ Локальная установка менее предпочтительна, потому что пакетные менеджеры обеспечивают: Автоматические обновления и патчи безопасности Лучшую интеграцию с системой Упрощённую установку и удаление Подпис","content":"_Не рекомендуется_ Локальная установка менее предпочтительна, потому что пакетные менеджеры обеспечивают: Автоматические обновления и патчи безопасности Лучшую интеграцию с системой Упрощённую установку и удаление Подписанные и проверенные бинарники"},{"id":"introduction/install::go-install::5","title":"Установка EasyP CLI","section":"Установка через go install","path":"/docs/guide/introduction/install#go-install","headings":["Установка через go install"],"excerpt":"Установка через go install Команда установит последнюю стабильную версию easyp:","content":"Установка через go install Команда установит последнюю стабильную версию easyp:"},{"id":"introduction/install::top::6","title":"Установка EasyP CLI","section":"Сборка из исходников","path":"/docs/guide/introduction/install","headings":["Сборка из исходников"],"excerpt":"Сборка из исходников Клонирование репозитория","content":"Сборка из исходников Клонирование репозитория"},{"id":"introduction/install::top::7","title":"Установка EasyP CLI","section":"Сборка из исходников","path":"/docs/guide/introduction/install","headings":["Сборка из исходников"],"excerpt":"Сборка из исходников Сборка с помощью Go","content":"Сборка из исходников Сборка с помощью Go"},{"id":"introduction/quickstart::top::0","title":"Быстрый старт (Quickstart)","path":"/docs/guide/introduction/quickstart","headings":[],"excerpt":"EasyP — современный toolkit для работы с файлами Protobuf. В этом кратком руководстве вы научитесь:","content":"EasyP — современный toolkit для работы с файлами Protobuf. В этом кратком руководстве вы научитесь:"},{"id":"introduction/quickstart::top::1","title":"Быстрый старт (Quickstart)","path":"/docs/guide/introduction/quickstart","headings":[],"excerpt":"**Инициализировать** проект с конфигурацией EasyP **Настраивать линтинг**, чтобы ловить ошибки и соблюдать лучшие практики **Управлять зависимостями** из Git‑репозиториев **Генерировать код** из ваших Protobuf файлов","content":"**Инициализировать** проект с конфигурацией EasyP **Настраивать линтинг**, чтобы ловить ошибки и соблюдать лучшие практики **Управлять зависимостями** из Git‑репозиториев **Генерировать код** из ваших Protobuf файлов"},{"id":"introduction/quickstart::top::2","title":"Быстрый старт (Quickstart)","section":"Предварительные требования","path":"/docs/guide/introduction/quickstart","headings":["Предварительные требования"],"excerpt":"Предварительные требования Перед началом убедитесь, что у вас установлены:","content":"Предварительные требования Перед началом убедитесь, что у вас установлены:"},{"id":"introduction/quickstart::top::3","title":"Быстрый старт (Quickstart)","section":"Предварительные требования","path":"/docs/guide/introduction/quickstart","headings":["Предварительные требования"],"excerpt":"Предварительные требования **EasyP CLI** — см. руководство по установке **Git** доступен в вашем $PATH **Файлы .proto** (или создайте их по ходу)","content":"Предварительные требования **EasyP CLI** — см. руководство по установке **Git** доступен в вашем $PATH **Файлы .proto** (или создайте их по ходу)"},{"id":"introduction/quickstart::top::4","title":"Быстрый старт (Quickstart)","section":"Предварительные требования","path":"/docs/guide/introduction/quickstart","headings":["Предварительные требования"],"excerpt":"Предварительные требования Проверить версию EasyP:","content":"Предварительные требования Проверить версию EasyP:"},{"id":"introduction/quickstart::top::5","title":"Быстрый старт (Quickstart)","section":"Инициализация проекта","path":"/docs/guide/introduction/quickstart","headings":["Инициализация проекта"],"excerpt":"Инициализация проекта Создайте базовый файл конфигурации easyp.yaml в корне проекта:","content":"Инициализация проекта Создайте базовый файл конфигурации easyp.yaml в корне проекта:"},{"id":"introduction/quickstart::top::6","title":"Быстрый старт (Quickstart)","section":"Инициализация проекта","path":"/docs/guide/introduction/quickstart","headings":["Инициализация проекта"],"excerpt":"Инициализация проекта Команда генерирует шаблон easyp.yaml с комментариями, дефолтными lint-правилами и настройками breaking-check. easyp init работает интерактивно: если в корне есть buf.yml/buf.yaml, EasyP предложит ми","content":"Инициализация проекта Команда генерирует шаблон easyp.yaml с комментариями, дефолтными lint-правилами и настройками breaking-check. easyp init работает интерактивно: если в корне есть buf.yml/buf.yaml, EasyP предложит миграцию; если easyp.yaml уже существует, попросит подтверждение перед перезаписью."},{"id":"introduction/quickstart::top::7","title":"Быстрый старт (Quickstart)","section":"Настройка линтинга","path":"/docs/guide/introduction/quickstart","headings":["Настройка линтинга"],"excerpt":"Настройка линтинга Линтинг помогает находить проблемы и поддерживать единый стиль. EasyP использует правила, совместимые с Buf.","content":"Настройка линтинга Линтинг помогает находить проблемы и поддерживать единый стиль. EasyP использует правила, совместимые с Buf."},{"id":"introduction/quickstart::top::8","title":"Быстрый старт (Quickstart)","section":"Настройка линтинга","path":"/docs/guide/introduction/quickstart","headings":["Настройка линтинга"],"excerpt":"Настройка линтинга Секция lint уже создаётся командой easyp init. При необходимости отредактируйте её, например так:","content":"Настройка линтинга Секция lint уже создаётся командой easyp init. При необходимости отредактируйте её, например так:"},{"id":"introduction/quickstart::top::9","title":"Быстрый старт (Quickstart)","section":"Настройка линтинга","path":"/docs/guide/introduction/quickstart","headings":["Настройка линтинга"],"excerpt":"Настройка линтинга Запустите линтер:","content":"Настройка линтинга Запустите линтер:"},{"id":"introduction/quickstart::top::10","title":"Быстрый старт (Quickstart)","section":"Настройка линтинга","path":"/docs/guide/introduction/quickstart","headings":["Настройка линтинга"],"excerpt":"Настройка линтинга Линтер проверит все .proto файлы и сообщит о найденных проблемах.","content":"Настройка линтинга Линтер проверит все .proto файлы и сообщит о найденных проблемах."},{"id":"introduction/quickstart::top::11","title":"Быстрый старт (Quickstart)","section":"Настройка линтинга","path":"/docs/guide/introduction/quickstart","headings":["Настройка линтинга"],"excerpt":"Настройка линтинга ::: tip Правила линтинга EasyP на 100% совместимы с Buf — мигрировать просто. :::","content":"Настройка линтинга ::: tip Правила линтинга EasyP на 100% совместимы с Buf — мигрировать просто. :::"},{"id":"introduction/quickstart::top::12","title":"Быстрый старт (Quickstart)","section":"Управление зависимостями","path":"/docs/guide/introduction/quickstart","headings":["Управление зависимостями"],"excerpt":"Управление зависимостями Если вы используете сторонние protobuf пакеты (например Google APIs или gRPC Gateway), EasyP упрощает их подключение.","content":"Управление зависимостями Если вы используете сторонние protobuf пакеты (например Google APIs или gRPC Gateway), EasyP упрощает их подключение."},{"id":"introduction/quickstart::top::13","title":"Быстрый старт (Quickstart)","section":"Формат зависимости","path":"/docs/guide/introduction/quickstart","headings":["Формат зависимости"],"excerpt":"Формат зависимости Запись: $GIT_LINK@$VERSION","content":"Формат зависимости Запись: $GIT_LINK@$VERSION"},{"id":"introduction/quickstart::top::14","title":"Быстрый старт (Quickstart)","section":"Формат зависимости","path":"/docs/guide/introduction/quickstart","headings":["Формат зависимости"],"excerpt":"Формат зависимости **$GIT_LINK** — URL любого Git‑репозитория (GitHub, GitLab и т.д.) **$VERSION** — тег или хеш коммита (опционально)","content":"Формат зависимости **$GIT_LINK** — URL любого Git‑репозитория (GitHub, GitLab и т.д.) **$VERSION** — тег или хеш коммита (опционально)"},{"id":"introduction/quickstart::top::15","title":"Быстрый старт (Quickstart)","section":"Формат зависимости","path":"/docs/guide/introduction/quickstart","headings":["Формат зависимости"],"excerpt":"Формат зависимости Если версия не указана — берётся последний коммит из основной ветки.","content":"Формат зависимости Если версия не указана — берётся последний коммит из основной ветки."},{"id":"introduction/quickstart::top::16","title":"Быстрый старт (Quickstart)","section":"Добавление зависимостей","path":"/docs/guide/introduction/quickstart","headings":["Добавление зависимостей"],"excerpt":"Добавление зависимостей Дополните easyp.yaml:","content":"Добавление зависимостей Дополните easyp.yaml:"},{"id":"introduction/quickstart::top::17","title":"Быстрый старт (Quickstart)","section":"Загрузка зависимостей","path":"/docs/guide/introduction/quickstart","headings":["Загрузка зависимостей"],"excerpt":"Загрузка зависимостей Команда: Скачивает версии из easyp.lock, если он существует Иначе — берёт из easyp.yaml и создаёт easyp.lock","content":"Загрузка зависимостей Команда: Скачивает версии из easyp.lock, если он существует Иначе — берёт из easyp.yaml и создаёт easyp.lock"},{"id":"introduction/quickstart::top::18","title":"Быстрый старт (Quickstart)","section":"Загрузка зависимостей","path":"/docs/guide/introduction/quickstart","headings":["Загрузка зависимостей"],"excerpt":"Загрузка зависимостей ::: info Совет: easyp mod update — игнорирует lock‑файл и подтягивает актуальные версии из easyp.yaml. :::","content":"Загрузка зависимостей ::: info Совет: easyp mod update — игнорирует lock‑файл и подтягивает актуальные версии из easyp.yaml. :::"},{"id":"introduction/quickstart::top::19","title":"Быстрый старт (Quickstart)","section":"Генерация кода","path":"/docs/guide/introduction/quickstart","headings":["Генерация кода"],"excerpt":"Генерация кода EasyP поддерживает все стандартные protoc‑плагины.","content":"Генерация кода EasyP поддерживает все стандартные protoc‑плагины."},{"id":"introduction/quickstart::top::20","title":"Быстрый старт (Quickstart)","section":"Конфигурация генерации","path":"/docs/guide/introduction/quickstart","headings":["Конфигурация генерации"],"excerpt":"Конфигурация генерации Добавьте плагины:","content":"Конфигурация генерации Добавьте плагины:"},{"id":"introduction/quickstart::top::21","title":"Быстрый старт (Quickstart)","section":"Запуск генерации","path":"/docs/guide/introduction/quickstart","headings":["Запуск генерации"],"excerpt":"Запуск генерации EasyP выполнит: Разрешение всех зависимостей Подключение к сервису EasyP (или локальный режим) Запуск указанных плагинов Вывод сгенерированного кода в нужные директории","content":"Запуск генерации EasyP выполнит: Разрешение всех зависимостей Подключение к сервису EasyP (или локальный режим) Запуск указанных плагинов Вывод сгенерированного кода в нужные директории"},{"id":"introduction/quickstart::top::22","title":"Быстрый старт (Quickstart)","section":"Запуск генерации","path":"/docs/guide/introduction/quickstart","headings":["Запуск генерации"],"excerpt":"Запуск генерации ::: tip Гибридный рантайм: WASM для скорости, Docker — для тяжёлых плагинов. :::","content":"Запуск генерации ::: tip Гибридный рантайм: WASM для скорости, Docker — для тяжёлых плагинов. :::"},{"id":"introduction/quickstart::top::23","title":"Быстрый старт (Quickstart)","section":"Следующие шаги","path":"/docs/guide/introduction/quickstart","headings":["Следующие шаги"],"excerpt":"Следующие шаги Поздравляем! 🎉 Вы успешно: ✅ Инициализировали проект EasyP ✅ Настроили линтинг ✅ Управляете внешними зависимостями ✅ Сгенерировали код из .proto","content":"Следующие шаги Поздравляем! 🎉 Вы успешно: ✅ Инициализировали проект EasyP ✅ Настроили линтинг ✅ Управляете внешними зависимостями ✅ Сгенерировали код из .proto"},{"id":"introduction/quickstart::top::24","title":"Быстрый старт (Quickstart)","section":"Узнать больше","path":"/docs/guide/introduction/quickstart","headings":["Узнать больше"],"excerpt":"Узнать больше **CLI Reference** — подробности по командам **API Service** — удалённая генерация **Configuration** — все опции конфигурации","content":"Узнать больше **CLI Reference** — подробности по командам **API Service** — удалённая генерация **Configuration** — все опции конфигурации"},{"id":"introduction/quickstart::top::25","title":"Быстрый старт (Quickstart)","section":"Узнать больше","path":"/docs/guide/introduction/quickstart","headings":["Узнать больше"],"excerpt":"Узнать больше *Приятной работы с Protobuf — без боли! 🚀*","content":"Узнать больше *Приятной работы с Protobuf — без боли! 🚀*"},{"id":"introduction/what-is::top::0","title":"Что такое EasyP?","path":"/docs/guide/introduction/what-is","headings":[],"excerpt":"EasyP — это современный инструментарий для работы с Protocol Buffers, который объединяет весь ваш protobuf‑workflow в один мощный CLI‑инструмент. Он совмещает линтинг, управление пакетами, генерацию кода и проверку совме","content":"EasyP — это современный инструментарий для работы с Protocol Buffers, который объединяет весь ваш protobuf‑workflow в один мощный CLI‑инструмент. Он совмещает линтинг, управление пакетами, генерацию кода и проверку совместимости в единой среде и устраняет сложность традиционной работы с protobuf."},{"id":"introduction/what-is::top::1","title":"Что такое EasyP?","path":"/docs/guide/introduction/what-is","headings":[],"excerpt":"Хотите просто попробовать? Перейдите сразу к разделу Quickstart.","content":"Хотите просто попробовать? Перейдите сразу к разделу Quickstart."},{"id":"introduction/what-is::protobuf::2","title":"Что такое EasyP?","section":"Проблема: фрагментированные protobuf‑процессы","path":"/docs/guide/introduction/what-is#protobuf","headings":["Проблема: фрагментированные protobuf‑процессы"],"excerpt":"Проблема: фрагментированные protobuf‑процессы Работа с Protocol Buffers в разных проектах часто создает лишнюю сложность и трение:","content":"Проблема: фрагментированные protobuf‑процессы Работа с Protocol Buffers в разных проектах часто создает лишнюю сложность и трение:"},{"id":"introduction/what-is::top::3","title":"Что такое EasyP?","section":"Хаос инструментов","path":"/docs/guide/introduction/what-is","headings":["Хаос инструментов"],"excerpt":"Хаос инструментов **Много отдельных утилит**: Отдельно для линтинга, генерации и управления зависимостями **Несогласованные конфигурации**: Разные форматы и правила в разных командах **Сложный онбординг**: Новым разработ","content":"Хаос инструментов **Много отдельных утилит**: Отдельно для линтинга, генерации и управления зависимостями **Несогласованные конфигурации**: Разные форматы и правила в разных командах **Сложный онбординг**: Новым разработчикам нужно долго вникать"},{"id":"introduction/what-is::top::4","title":"Что такое EasyP?","section":"Проблемы управления зависимостями","path":"/docs/guide/introduction/what-is","headings":["Проблемы управления зависимостями"],"excerpt":"Проблемы управления зависимостями **Нет стандартизированного подхода**: Каждый проект решает это по‑своему **Конфликты версий**: Трудно сводить разные версии одних и тех же proto‑библиотек **Неповторяемость сборок**: Сло","content":"Проблемы управления зависимостями **Нет стандартизированного подхода**: Каждый проект решает это по‑своему **Конфликты версий**: Трудно сводить разные версии одних и тех же proto‑библиотек **Неповторяемость сборок**: Сложно гарантировать одинаковый результат в разных окружениях"},{"id":"introduction/what-is::top::5","title":"Что такое EasyP?","section":"Трение в разработке","path":"/docs/guide/introduction/what-is","headings":["Трение в разработке"],"excerpt":"Трение в разработке **Ручные операции**: Много повторяющихся шагов **Разрастание конфигураций**: Множество файлов и форматов **Затратная проверка совместимости**: Часто вручную и постфактум","content":"Трение в разработке **Ручные операции**: Много повторяющихся шагов **Разрастание конфигураций**: Множество файлов и форматов **Затратная проверка совместимости**: Часто вручную и постфактум"},{"id":"introduction/what-is::protobuf::6","title":"Что такое EasyP?","section":"Решение: единый protobuf‑инструментарий","path":"/docs/guide/introduction/what-is#protobuf","headings":["Решение: единый protobuf‑инструментарий"],"excerpt":"Решение: единый protobuf‑инструментарий EasyP устраняет эти проблемы, предоставляя целостный opinionated‑подход и стандартизируя процессы:","content":"Решение: единый protobuf‑инструментарий EasyP устраняет эти проблемы, предоставляя целостный opinionated‑подход и стандартизируя процессы:"},{"id":"introduction/what-is::top::7","title":"Что такое EasyP?","section":"Один инструмент — все задачи","path":"/docs/guide/introduction/what-is","headings":["Один инструмент — все задачи"],"excerpt":"Один инструмент — все задачи Вместо жонглирования утилитами EasyP даёт: **Linting** с расширенными наборами правил **Package management** с Git‑нативными зависимостями **Code generation** локально и удалённо **Breaking c","content":"Один инструмент — все задачи Вместо жонглирования утилитами EasyP даёт: **Linting** с расширенными наборами правил **Package management** с Git‑нативными зависимостями **Code generation** локально и удалённо **Breaking change detection** для контроля совместимости API"},{"id":"introduction/what-is::top::8","title":"Что такое EasyP?","section":"Единая конфигурация","path":"/docs/guide/introduction/what-is","headings":["Единая конфигурация"],"excerpt":"Единая конфигурация Один файл easyp.yaml описывает весь workflow — меньше расхождений, проще сопровождать.","content":"Единая конфигурация Один файл easyp.yaml описывает весь workflow — меньше расхождений, проще сопровождать."},{"id":"introduction/what-is::gitnative::9","title":"Что такое EasyP?","section":"Git‑native зависимости","path":"/docs/guide/introduction/what-is#gitnative","headings":["Git‑native зависимости"],"excerpt":"Git‑native зависимости Прямое использование Git‑репозиториев вместо централизованных реестров: прозрачная история, контроль версий, воспроизводимые сборки.","content":"Git‑native зависимости Прямое использование Git‑репозиториев вместо централизованных реестров: прозрачная история, контроль версий, воспроизводимые сборки."},{"id":"introduction/what-is::top::10","title":"Что такое EasyP?","section":"Ключевые возможности","path":"/docs/guide/introduction/what-is","headings":["Ключевые возможности"],"excerpt":"Ключевые возможности Feature Description --------- ------------- 🔍 **Comprehensive Linting** Полная поддержка правил buf с настраиваемыми профилями для лучших практик API‑дизайна. 📦 **Smart Package Manager** Git‑ориент","content":"Ключевые возможности Feature Description --------- ------------- 🔍 **Comprehensive Linting** Полная поддержка правил buf с настраиваемыми профилями для лучших практик API‑дизайна. 📦 **Smart Package Manager** Git‑ориентированное управление зависимостями с lock‑файлом для воспроизводимости. ⚡ **Code Generation** Многозадачная генерация кода с поддержкой локальных и удалённых protoc‑плагинов. 🔄 **Breaking Change Detection** Автоматическая проверка совместимости API против веток Git. 🌐 **Remote Plugin Support** Выполнение плагинов через централизованный EasyP API сервис без локальных установок. 🎯 **Developer Experience** Автодополнение, понятные ошибки, единая структура и документация."},{"id":"introduction/what-is::top::11","title":"Что такое EasyP?","section":"Типы поддерживаемых плагинов","path":"/docs/guide/introduction/what-is","headings":["Типы поддерживаемых плагинов"],"excerpt":"Типы поддерживаемых плагинов EasyP гибко подходит к выполнению генерации:","content":"Типы поддерживаемых плагинов EasyP гибко подходит к выполнению генерации:"},{"id":"introduction/what-is::local-plugins::12","title":"Что такое EasyP?","section":"Local Plugins","path":"/docs/guide/introduction/what-is#local-plugins","headings":["Local Plugins"],"excerpt":"Local Plugins Стандартные установленные protoc‑плагины:","content":"Local Plugins Стандартные установленные protoc‑плагины:"},{"id":"introduction/what-is::remote-plugins::13","title":"Что такое EasyP?","section":"Remote Plugins","path":"/docs/guide/introduction/what-is#remote-plugins","headings":["Remote Plugins"],"excerpt":"Remote Plugins Плагины через EasyP API сервис для воспроизводимости:","content":"Remote Plugins Плагины через EasyP API сервис для воспроизводимости:"},{"id":"introduction/what-is::custom-plugins::14","title":"Что такое EasyP?","section":"Custom Plugins","path":"/docs/guide/introduction/what-is#custom-plugins","headings":["Custom Plugins"],"excerpt":"Custom Plugins Поддержка экосистемы пользовательских расширений.","content":"Custom Plugins Поддержка экосистемы пользовательских расширений."},{"id":"introduction/what-is::top::15","title":"Что такое EasyP?","section":"Децентрализованный менеджмент пакетов","path":"/docs/guide/introduction/what-is","headings":["Децентрализованный менеджмент пакетов"],"excerpt":"Децентрализованный менеджмент пакетов В отличие от других решений EasyP не требует централизованного реестра. Любой Git‑репозиторий может быть источником:","content":"Децентрализованный менеджмент пакетов В отличие от других решений EasyP не требует централизованного реестра. Любой Git‑репозиторий может быть источником:"},{"id":"introduction/what-is::top::16","title":"Что такое EasyP?","section":"Децентрализованный менеджмент пакетов","path":"/docs/guide/introduction/what-is","headings":["Децентрализованный менеджмент пакетов"],"excerpt":"Децентрализованный менеджмент пакетов **Гибкость**: Любой Git‑хостинг (GitHub, GitLab, self‑hosted) **Нет vendor lock‑in**: Зависимости не привязаны к одному провайдеру **Полная история**: Ветки, теги, ревью **Enterprise","content":"Децентрализованный менеджмент пакетов **Гибкость**: Любой Git‑хостинг (GitHub, GitLab, self‑hosted) **Нет vendor lock‑in**: Зависимости не привязаны к одному провайдеру **Полная история**: Ветки, теги, ревью **Enterprise‑совместимость**: Поддержка приватных репозиториев"},{"id":"introduction/what-is::buf::17","title":"Что такое EasyP?","section":"Бесшовная миграция с Buf","path":"/docs/guide/introduction/what-is#buf","headings":["Бесшовная миграция с Buf"],"excerpt":"Бесшовная миграция с Buf EasyP изначально совместим с экосистемой buf:","content":"Бесшовная миграция с Buf EasyP изначально совместим с экосистемой buf:"},{"id":"introduction/what-is::buf::18","title":"Что такое EasyP?","section":"Бесшовная миграция с Buf","path":"/docs/guide/introduction/what-is#buf","headings":["Бесшовная миграция с Buf"],"excerpt":"Бесшовная миграция с Buf **Совпадающие rule sets** **Похожая структура YAML** **Минимальные изменения для замены** **Постепенное внедрение** без ломки текущего пайплайна","content":"Бесшовная миграция с Buf **Совпадающие rule sets** **Похожая структура YAML** **Минимальные изменения для замены** **Постепенное внедрение** без ломки текущего пайплайна"},{"id":"introduction/what-is::easyp-vs-bufbuild::19","title":"Что такое EasyP?","section":"EasyP vs buf.build","path":"/docs/guide/introduction/what-is#easyp-vs-bufbuild","headings":["EasyP vs buf.build"],"excerpt":"EasyP vs buf.build Feature EasyP buf.build --------- -------- ----------- **Dependency Management** Git‑репозитории Buf Schema Registry (BSR) **Vendor Lock-in** Нет Привязка к BSR для полного функционала **Plugin Executi","content":"EasyP vs buf.build Feature EasyP buf.build --------- -------- ----------- **Dependency Management** Git‑репозитории Buf Schema Registry (BSR) **Vendor Lock-in** Нет Привязка к BSR для полного функционала **Plugin Execution** Local + Remote Local + BSR plugins **Private Dependencies** Любой Git провайдер BSR или ручное управление **Offline Development** Полная поддержка (mod vendor) Ограниченно без доступа к BSR **Enterprise Integration** Использует существующий Git Требует настройку BSR **Breaking Change Detection** Против любой Git ссылки Аналогично **Package Distribution** Любой Git Публикация через BSR **License** Apache 2.0 Apache 2.0 **Community** Growing Established"},{"id":"introduction/what-is::easyp-vs-bufbuild::20","title":"Что такое EasyP?","section":"EasyP vs buf.build","path":"/docs/guide/introduction/what-is#easyp-vs-bufbuild","headings":["EasyP vs buf.build"],"excerpt":"EasyP vs buf.build **Преимущества миграции:** Без изменения инфраструктуры Плавное принятие новых возможностей Гибрид локальных и удалённых плагинов Единая конфигурация вместо набора файлов","content":"EasyP vs buf.build **Преимущества миграции:** Без изменения инфраструктуры Плавное принятие новых возможностей Гибрид локальных и удалённых плагинов Единая конфигурация вместо набора файлов"},{"id":"introduction/what-is::protobuf::21","title":"Что такое EasyP?","section":"Наши цели для Protobuf","path":"/docs/guide/introduction/what-is#protobuf","headings":["Наши цели для Protobuf"],"excerpt":"Наши цели для Protobuf Миссия EasyP — ускорить принятие **schema‑driven API** через удобный, надёжный и прозрачный инструментарий.","content":"Наши цели для Protobuf Миссия EasyP — ускорить принятие **schema‑driven API** через удобный, надёжный и прозрачный инструментарий."},{"id":"introduction/what-is::top::22","title":"Что такое EasyP?","section":"Современная экосистема","path":"/docs/guide/introduction/what-is","headings":["Современная экосистема"],"excerpt":"Современная экосистема Повышаем DX вокруг protobuf, чтобы конкурентно выглядеть по простоте против REST/JSON, сохраняя типовую строгость и производительность.","content":"Современная экосистема Повышаем DX вокруг protobuf, чтобы конкурентно выглядеть по простоте против REST/JSON, сохраняя типовую строгость и производительность."},{"id":"introduction/what-is::developer-experience::23","title":"Что такое EasyP?","section":"Developer Experience прежде всего","path":"/docs/guide/introduction/what-is#developer-experience","headings":["Developer Experience прежде всего"],"excerpt":"Developer Experience прежде всего Интуитивный CLI, понятные ошибки, ясные сообщения, минимальная фрагментация.","content":"Developer Experience прежде всего Интуитивный CLI, понятные ошибки, ясные сообщения, минимальная фрагментация."},{"id":"introduction/what-is::enterprise::24","title":"Что такое EasyP?","section":"Готов к Enterprise","path":"/docs/guide/introduction/what-is#enterprise","headings":["Готов к Enterprise"],"excerpt":"Готов к Enterprise Воспроизводимые сборки, приватные репозитории, интеграция в CI/CD.","content":"Готов к Enterprise Воспроизводимые сборки, приватные репозитории, интеграция в CI/CD."},{"id":"introduction/what-is::top::25","title":"Что такое EasyP?","section":"Для индивидуальных разработчиков","path":"/docs/guide/introduction/what-is","headings":["Для индивидуальных разработчиков"],"excerpt":"Для индивидуальных разработчиков Быстрый старт за минуты Один инструмент — меньше когнитивной нагрузки Понятная документация","content":"Для индивидуальных разработчиков Быстрый старт за минуты Один инструмент — меньше когнитивной нагрузки Понятная документация"},{"id":"introduction/what-is::top::26","title":"Что такое EasyP?","section":"Для команд","path":"/docs/guide/introduction/what-is","headings":["Для команд"],"excerpt":"Для команд Единые стандарты Повторяемые сборки (lock‑файл) Ускоренный онбординг","content":"Для команд Единые стандарты Повторяемые сборки (lock‑файл) Ускоренный онбординг"},{"id":"introduction/what-is::top::27","title":"Что такое EasyP?","section":"Для организаций","path":"/docs/guide/introduction/what-is","headings":["Для организаций"],"excerpt":"Для организаций Нет vendor lock‑in Безопасность приватных репозиториев Лёгкая интеграция в существующие пайплайны","content":"Для организаций Нет vendor lock‑in Безопасность приватных репозиториев Лёгкая интеграция в существующие пайплайны"},{"id":"introduction/what-is::top::28","title":"Что такое EasyP?","section":"Что дальше?","path":"/docs/guide/introduction/what-is","headings":["Что дальше?"],"excerpt":"Что дальше? EasyP упрощает работу с protobuf — фокусируйтесь на API, а не на рутине. Хотите начать?","content":"Что дальше? EasyP упрощает работу с protobuf — фокусируйтесь на API, а не на рутине. Хотите начать?"},{"id":"introduction/what-is::top::29","title":"Что такое EasyP?","section":"Что дальше?","path":"/docs/guide/introduction/what-is","headings":["Что дальше?"],"excerpt":"Что дальше? Смотрите Installation Guide и Quickstart.","content":"Что дальше? Смотрите Installation Guide и Quickstart."},{"id":"introduction/what-is::stargazers-over-time::30","title":"Что такое 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 В работе","content":"Buf CLI В работе"},{"id":"migration/protoc::top::0","title":"Миграция с protoc на EasyP","path":"/docs/guide/migration/protoc","headings":[],"excerpt":"Исходная англоязычная версия файла содержала только заголовок и пометку “Work in progress”. Ниже — полноценный русскоязычный черновик раздела миграции. Уточни, если требуется сократить или изменить уровень детализации.","content":"Исходная англоязычная версия файла содержала только заголовок и пометку “Work in progress”. Ниже — полноценный русскоязычный черновик раздела миграции. Уточни, если требуется сократить или изменить уровень детализации."},{"id":"migration/protoc::1::1","title":"Миграция с protoc на EasyP","section":"1. Краткое сравнение","path":"/docs/guide/migration/protoc#1","headings":["1. Краткое сравнение"],"excerpt":"Краткое сравнение Аспект protoc EasyP -------- ---------- ------- Базовая роль Базовый компилятор .proto файлов Инструмент “всё в одном”: линтинг, проверка несовместимых изменений, менеджер пакетов, генерация Конфигураци","content":"Краткое сравнение Аспект protoc EasyP -------- ---------- ------- Базовая роль Базовый компилятор .proto файлов Инструмент “всё в одном”: линтинг, проверка несовместимых изменений, менеджер пакетов, генерация Конфигурация Чаще shell‑скрипты / Makefile / вручную передаваемые флаги Единый файл easyp.yaml (YAML или JSON) Управление зависимостями Ручной git clone, submodule, vendoring Секция deps с Git‑репозиториями Набор правил линтера Нет встроенного Встроенный линтер с правилами (можно включать/исключать) Проверка breaking changes Отсутствует из коробки Команда easyp breaking Расширенные плагины Установка и вызов через флаги --plugin Плагины через конфиг; поддержка удалённого выполнения (API Service) и стандартного локального Единообразие в CI Нужно собирать вручную Консистентные команды: lint, breaking, generate"},{"id":"migration/protoc::2::2","title":"Миграция с protoc на EasyP","section":"2. Когда имеет смысл мигрировать","path":"/docs/guide/migration/protoc#2","headings":["2. Когда имеет смысл мигрировать"],"excerpt":"Когда имеет смысл мигрировать Миграция на EasyP особенно полезна если: Есть потребность в автоматической проверке качества (стиль, именование) .proto файлов. Нужна защита от нелегитимных несовместимых изменений при эволю","content":"Когда имеет смысл мигрировать Миграция на EasyP особенно полезна если: Есть потребность в автоматической проверке качества (стиль, именование) .proto файлов. Нужна защита от нелегитимных несовместимых изменений при эволюции схем. В проекте используется несколько языков генерации и растёт число скриптов вокруг protoc. Вы хотите единый конфиг вместо множества shell/Makefile комбинаций. Планируется централизованное исполнение плагинов (через API Service) или унификация окружения в CI."},{"id":"migration/protoc::3-protoc::3","title":"Миграция с protoc на EasyP","section":"3. Типичный сценарий “до” (только protoc)","path":"/docs/guide/migration/protoc#3-protoc","headings":["3. Типичный сценарий “до” (только protoc)"],"excerpt":"Типичный сценарий “до” (только protoc) Пример: локальные скрипты / Makefile:","content":"Типичный сценарий “до” (только protoc) Пример: локальные скрипты / Makefile:"},{"id":"migration/protoc::3-protoc::4","title":"Миграция с protoc на EasyP","section":"3. Типичный сценарий “до” (только protoc)","path":"/docs/guide/migration/protoc#3-protoc","headings":["3. Типичный сценарий “до” (только protoc)"],"excerpt":"Типичный сценарий “до” (только protoc)","content":"Типичный сценарий “до” (только protoc)"},{"id":"migration/protoc::3-protoc::5","title":"Миграция с protoc на EasyP","section":"3. Типичный сценарий “до” (только protoc)","path":"/docs/guide/migration/protoc#3-protoc","headings":["3. Типичный сценарий “до” (только protoc)"],"excerpt":"Типичный сценарий “до” (только protoc) Дополнительные зависимости (googleapis, validate, grpc-gateway) скачиваются вручную или через submodules.","content":"Типичный сценарий “до” (только protoc) Дополнительные зависимости (googleapis, validate, grpc-gateway) скачиваются вручную или через submodules."},{"id":"migration/protoc::4-easyp::6","title":"Миграция с protoc на EasyP","section":"4. Типичный сценарий “после” (EasyP)","path":"/docs/guide/migration/protoc#4-easyp","headings":["4. Типичный сценарий “после” (EasyP)"],"excerpt":"Типичный сценарий “после” (EasyP) Единый файл easyp.yaml:","content":"Типичный сценарий “после” (EasyP) Единый файл easyp.yaml:"},{"id":"migration/protoc::4-easyp::7","title":"Миграция с protoc на EasyP","section":"4. Типичный сценарий “после” (EasyP)","path":"/docs/guide/migration/protoc#4-easyp","headings":["4. Типичный сценарий “после” (EasyP)"],"excerpt":"Типичный сценарий “после” (EasyP) ```yaml deps: - github.com/googleapis/googleapis - github.com/envoyproxy/protoc-gen-validate","content":"Типичный сценарий “после” (EasyP) ```yaml deps: - github.com/googleapis/googleapis - github.com/envoyproxy/protoc-gen-validate"},{"id":"migration/protoc::4-easyp::8","title":"Миграция с protoc на EasyP","section":"4. Типичный сценарий “после” (EasyP)","path":"/docs/guide/migration/protoc#4-easyp","headings":["4. Типичный сценарий “после” (EasyP)"],"excerpt":"Типичный сценарий “после” (EasyP) generate: plugins: - name: go out: gen/go opts: paths: source_relative - name: go-grpc out: gen/go opts: paths: source_relative require_unimplemented_servers: false - name: validate out:","content":"Типичный сценарий “после” (EasyP) generate: plugins: - name: go out: gen/go opts: paths: source_relative - name: go-grpc out: gen/go opts: paths: source_relative require_unimplemented_servers: false - name: validate out: gen/go opts: paths: source_relative lang: \"go\" ```"},{"id":"migration/protoc::4-easyp::9","title":"Миграция с protoc на EasyP","section":"4. Типичный сценарий “после” (EasyP)","path":"/docs/guide/migration/protoc#4-easyp","headings":["4. Типичный сценарий “после” (EasyP)"],"excerpt":"Типичный сценарий “после” (EasyP) Команды:","content":"Типичный сценарий “после” (EasyP) Команды:"},{"id":"migration/protoc::5::10","title":"Миграция с protoc на EasyP","section":"5. Пошаговая миграция","path":"/docs/guide/migration/protoc#5","headings":["5. Пошаговая миграция"],"excerpt":"Пошаговая миграция Инвентаризация: - Соберите список всех вызовов protoc (скрипты, Makefile, CI). - Зафиксируйте используемые плагины и их версии. Создание easyp.yaml: - Поле version не обязательно (можете оставить его т","content":"Пошаговая миграция Инвентаризация: - Соберите список всех вызовов protoc (скрипты, Makefile, CI). - Зафиксируйте используемые плагины и их версии. Создание easyp.yaml: - Поле version не обязательно (можете оставить его только для обратной совместимости). - Перенесите плагины в секцию generate.plugins. - Укажите опции, которые ранее передавались в командной строке. Зависимости: - Все внешние каталоги (googleapis, validate, grpc-gateway и т.п.) занесите в deps. - Удалите лишние submodules при необходимости. Линтер: - Запустите easyp lint и посмотрите на предупреждения. - При необходимости добавьте lint.use, lint.ignore, lint.except. Проверка breaking changes: - Выберите референс (обычно origin/main или предыдущий тег). - Запустите easyp breaking --against git-ref=origin/main. - Настройте игнорируемые изменения (breaking.ignore), если нужно. Обновление CI: - Замените прямые вызовы protoc на easyp generate. - Добавьте отдельные шаги lint и breaking. Очистка: - Удалите устаревшие генерационные скрипты, если они дублируют функционал EasyP. Документация: - Обновите README / CONTRIBUTING (новый способ генерации). Верификация: - Сравните результат генерации до и после (git diff). - Убедитесь, что имена файлов и пути совпадают или скорректируйте структуру."},{"id":"migration/protoc::6-ci-github-actions::11","title":"Миграция с protoc на EasyP","section":"6. Замена в CI (пример GitHub Actions)","path":"/docs/guide/migration/protoc#6-ci-github-actions","headings":["6. Замена в CI (пример GitHub Actions)"],"excerpt":"Замена в CI (пример GitHub Actions) ```yaml name: Install EasyP run: go install github.com/easyp-tech/easyp/cmd/easyp@latest","content":"Замена в CI (пример GitHub Actions) ```yaml name: Install EasyP run: go install github.com/easyp-tech/easyp/cmd/easyp@latest"},{"id":"migration/protoc::6-ci-github-actions::12","title":"Миграция с protoc на EasyP","section":"6. Замена в CI (пример GitHub Actions)","path":"/docs/guide/migration/protoc#6-ci-github-actions","headings":["6. Замена в CI (пример GitHub Actions)"],"excerpt":"Замена в CI (пример GitHub Actions) name: Lint run: easyp lint","content":"Замена в CI (пример GitHub Actions) name: Lint run: easyp lint"},{"id":"migration/protoc::6-ci-github-actions::13","title":"Миграция с protoc на EasyP","section":"6. Замена в CI (пример GitHub Actions)","path":"/docs/guide/migration/protoc#6-ci-github-actions","headings":["6. Замена в CI (пример GitHub Actions)"],"excerpt":"Замена в CI (пример GitHub Actions) name: Breaking run: easyp breaking --against git-ref=origin/main","content":"Замена в CI (пример GitHub Actions) name: Breaking run: easyp breaking --against git-ref=origin/main"},{"id":"migration/protoc::6-ci-github-actions::14","title":"Миграция с protoc на EasyP","section":"6. Замена в CI (пример GitHub Actions)","path":"/docs/guide/migration/protoc#6-ci-github-actions","headings":["6. Замена в CI (пример GitHub Actions)"],"excerpt":"Замена в CI (пример GitHub Actions) name: Generate run: easyp generate ```","content":"Замена в CI (пример GitHub Actions) name: Generate run: easyp generate ```"},{"id":"migration/protoc::7::15","title":"Миграция с protoc на EasyP","section":"7. Работа с плагинами","path":"/docs/guide/migration/protoc#7","headings":["7. Работа с плагинами"],"excerpt":"Работа с плагинами Тип В protoc В EasyP ----- ---------- --------- Стандартные (protoc-gen-go) Указание через --go_out plugins: - name: go ... gRPC --go-grpc_out Второй плагин go-grpc Validate Доп. установка + --validate","content":"Работа с плагинами Тип В protoc В EasyP ----- ---------- --------- Стандартные (protoc-gen-go) Указание через --go_out plugins: - name: go ... gRPC --go-grpc_out Второй плагин go-grpc Validate Доп. установка + --validate_out - name: validate с opts gRPC-Gateway / OpenAPI --grpc-gateway_out / --openapiv2_out Плагины grpc-gateway, openapiv2 Кастомные Путь к бинарю / --plugin=protoc-gen-xxx - name: xxx или удалённый remote: (если используется API Service)"},{"id":"migration/protoc::7::16","title":"Миграция с protoc на EasyP","section":"7. Работа с плагинами","path":"/docs/guide/migration/protoc#7","headings":["7. Работа с плагинами"],"excerpt":"Работа с плагинами Если вы переходите на удалённое выполнение (API Service), записи в конфиге могут выглядеть так:","content":"Работа с плагинами Если вы переходите на удалённое выполнение (API Service), записи в конфиге могут выглядеть так:"},{"id":"migration/protoc::8::17","title":"Миграция с protoc на EasyP","section":"8. Проверка корректности после миграции","path":"/docs/guide/migration/protoc#8","headings":["8. Проверка корректности после миграции"],"excerpt":"Проверка корректности после миграции git diff после easyp generate — не должно быть неожиданных изменений. Сравнить размер и содержимое каталога сгенерированных файлов. Запустить ваш потребляющий код (сборка, тесты). Про","content":"Проверка корректности после миграции git diff после easyp generate — не должно быть неожиданных изменений. Сравнить размер и содержимое каталога сгенерированных файлов. Запустить ваш потребляющий код (сборка, тесты). Проверить, что плагины (validate, grpc-gateway) продолжают вставлять необходимые аннотации / опции. Линт не должен выдавать критичных ошибок — скорректируйте стиль .proto, если требуется."},{"id":"migration/protoc::9::18","title":"Миграция с protoc на EasyP","section":"9. Частые проблемы","path":"/docs/guide/migration/protoc#9","headings":["9. Частые проблемы"],"excerpt":"Частые проблемы Проблема Причина Решение ---------- --------- --------- Плагин не найден Не установлен или не указан в PATH Выполнить go install ... или добавить в конфиг как remote Ошибка импорта .proto Отсутствует репо","content":"Частые проблемы Проблема Причина Решение ---------- --------- --------- Плагин не найден Не установлен или не указан в PATH Выполнить go install ... или добавить в конфиг как remote Ошибка импорта .proto Отсутствует репозиторий в deps Добавить адрес в секцию deps и easyp mod update Несовместимые изменения на каждом PR Отсутствует игнор/настройка сравнения Уточнить ветку/тег в --against или настроить breaking.ignore Локально работает, в CI падает В CI нет зависимостей (не вызван update) Добавить шаг easyp mod update перед generate Дубликаты сгенерированных файлов Изменена структура путей или out Синхронизировать out и paths: source_relative опции"},{"id":"migration/protoc::10-go::19","title":"Миграция с protoc на EasyP","section":"10. Минимальный пример конфигурации (только Go)","path":"/docs/guide/migration/protoc#10-go","headings":["10. Минимальный пример конфигурации (только Go)"],"excerpt":"Минимальный пример конфигурации (только Go)","content":"Минимальный пример конфигурации (только Go)"},{"id":"migration/protoc::10-go::20","title":"Миграция с protoc на EasyP","section":"10. Минимальный пример конфигурации (только Go)","path":"/docs/guide/migration/protoc#10-go","headings":["10. Минимальный пример конфигурации (только Go)"],"excerpt":"Минимальный пример конфигурации (только Go) Команды:","content":"Минимальный пример конфигурации (только Go) Команды:"},{"id":"migration/protoc::11-go-grpc-gateway-validate-breaking-lint::21","title":"Миграция с protoc на EasyP","section":"11. Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint)","path":"/docs/guide/migration/protoc#11-go-grpc-gateway-validate-breaking-lint","headings":["11. Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint)"],"excerpt":"Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint) ```yaml lint: use: - ENUM_FIRST_VALUE_ZERO - SERVICE_SUFFIX allow_comment_ignores: false enum_zero_value_suffix: _NONE service_suffix: Service","content":"Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint) ```yaml lint: use: - ENUM_FIRST_VALUE_ZERO - SERVICE_SUFFIX allow_comment_ignores: false enum_zero_value_suffix: _NONE service_suffix: Service"},{"id":"migration/protoc::11-go-grpc-gateway-validate-breaking-lint::22","title":"Миграция с protoc на EasyP","section":"11. Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint)","path":"/docs/guide/migration/protoc#11-go-grpc-gateway-validate-breaking-lint","headings":["11. Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint)"],"excerpt":"Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint) deps: - github.com/googleapis/googleapis - github.com/envoyproxy/protoc-gen-validate","content":"Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint) deps: - github.com/googleapis/googleapis - github.com/envoyproxy/protoc-gen-validate"},{"id":"migration/protoc::11-go-grpc-gateway-validate-breaking-lint::23","title":"Миграция с protoc на EasyP","section":"11. Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint)","path":"/docs/guide/migration/protoc#11-go-grpc-gateway-validate-breaking-lint","headings":["11. Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint)"],"excerpt":"Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint) generate: plugins: - name: go out: gen/go opts: paths: source_relative - name: go-grpc out: gen/go opts: paths: source_relative require_unimplemented_","content":"Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint) generate: plugins: - name: go out: gen/go opts: paths: source_relative - name: go-grpc out: gen/go opts: paths: source_relative require_unimplemented_servers: false - name: validate out: gen/go opts: paths: source_relative lang: \"go\" - name: grpc-gateway out: gen/go opts: paths: source_relative - name: openapiv2 out: gen/openapi opts: simple_operation_ids: true"},{"id":"migration/protoc::11-go-grpc-gateway-validate-breaking-lint::24","title":"Миграция с protoc на EasyP","section":"11. Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint)","path":"/docs/guide/migration/protoc#11-go-grpc-gateway-validate-breaking-lint","headings":["11. Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint)"],"excerpt":"Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint) breaking: against_git_ref: main ignore: - ENUM_VALUE_SAME_NAME ```","content":"Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint) breaking: against_git_ref: main ignore: - ENUM_VALUE_SAME_NAME ```"},{"id":"migration/protoc::12-checklist::25","title":"Миграция с protoc на EasyP","section":"12. Checklist миграции","path":"/docs/guide/migration/protoc#12-checklist","headings":["12. Checklist миграции"],"excerpt":"Checklist миграции [ ] Собраны все текущие вызовы protoc. [ ] Создан easyp.yaml с секциями generate и (опционально) lint, breaking. [ ] Добавлены все внешние зависимости в deps. [ ] Успешно выполнен easyp mod update. [ ]","content":"Checklist миграции [ ] Собраны все текущие вызовы protoc. [ ] Создан easyp.yaml с секциями generate и (опционально) lint, breaking. [ ] Добавлены все внешние зависимости в deps. [ ] Успешно выполнен easyp mod update. [ ] easyp generate даёт идентичный или ожидаемо обновлённый результат. [ ] easyp lint проходит без критичных ошибок (или ошибки обработаны). [ ] easyp breaking --against git-ref=origin/main не выдаёт неожиданных блокирующих нарушений. [ ] CI обновлён (заменены прямые вызовы protoc). [ ] Документация проекта обновлена (README: как генерировать)."},{"id":"migration/protoc::13::26","title":"Миграция с protoc на EasyP","section":"13. Дополнительные рекомендации","path":"/docs/guide/migration/protoc#13","headings":["13. Дополнительные рекомендации"],"excerpt":"Дополнительные рекомендации Сначала мигрируйте один сервис / пакет — снизит риск массовых конфликтов. Закоммитьте easyp.yaml отдельно, затем выполните генерацию и линт — проще ревью. Если нужны разные наборы плагинов для","content":"Дополнительные рекомендации Сначала мигрируйте один сервис / пакет — снизит риск массовых конфликтов. Закоммитьте easyp.yaml отдельно, затем выполните генерацию и линт — проще ревью. Если нужны разные наборы плагинов для разных микросервисов — используйте несколько конфигов (например: easyp.microservice-a.yaml + easyp.microservice-b.yaml). Внедрите проверку актуальности генерации: шаг CI, который валидирует отсутствие diff после easyp generate."},{"id":"migration/protoc::14::27","title":"Миграция с protoc на EasyP","section":"14. Статус","path":"/docs/guide/migration/protoc#14","headings":["14. Статус"],"excerpt":"Статус Этот файл — русская расширенная версия, заменяющая placeholder “Work in progress”. При появлении новых возможностей EasyP (дополнительные поля в конфиге, новые плагины, расширения breaking‑проверок) обновите соотв","content":"Статус Этот файл — русская расширенная версия, заменяющая placeholder “Work in progress”. При появлении новых возможностей EasyP (дополнительные поля в конфиге, новые плагины, расширения breaking‑проверок) обновите соответствующие разделы."},{"id":"migration/protoc::14::28","title":"Миграция с protoc на EasyP","section":"14. Статус","path":"/docs/guide/migration/protoc#14","headings":["14. Статус"],"excerpt":"Статус Если нужен упрощённый вариант (только перевод без расширения), сообщи — могу сократить до минимальных двух блоков.","content":"Статус Если нужен упрощённый вариант (только перевод без расширения), сообщи — могу сократить до минимальных двух блоков."},{"id":"migration/protolock::top::0","title":"Protolock","path":"/docs/guide/migration/protolock","headings":[],"excerpt":"Protolock В процессе разработки","content":"Protolock В процессе разработки"},{"id":"migration/prototool::top::0","title":"Prototool","section":"Состояние","path":"/docs/guide/migration/prototool","headings":["Состояние"],"excerpt":"Состояние Этот раздел был помечен как “Work in progress” в оригинальной английской версии. Ниже — переведённое и дополненное практическое руководство по миграции с Prototool на EasyP. Имя инструмента Prototool не перевод","content":"Состояние Этот раздел был помечен как “Work in progress” в оригинальной английской версии. Ниже — переведённое и дополненное практическое руководство по миграции с Prototool на EasyP. Имя инструмента Prototool не переводится."},{"id":"migration/prototool::top::1","title":"Prototool","section":"Цель миграции","path":"/docs/guide/migration/prototool","headings":["Цель миграции"],"excerpt":"Цель миграции Перейти от конфигурации и рабочих процессов Prototool к эквиваленту на EasyP с минимальными изменениями, сохранив: Линтинг .proto файлов. Генерацию кода через protoc-плагины. Управление зависимостями. Прове","content":"Цель миграции Перейти от конфигурации и рабочих процессов Prototool к эквиваленту на EasyP с минимальными изменениями, сохранив: Линтинг .proto файлов. Генерацию кода через protoc-плагины. Управление зависимостями. Проверку несовместимых изменений (в Prototool это приходилось реализовывать внешними инструментами; в EasyP встроено)."},{"id":"migration/prototool::top::2","title":"Prototool","section":"Кратко о различиях","path":"/docs/guide/migration/prototool","headings":["Кратко о различиях"],"excerpt":"Кратко о различиях Область Prototool EasyP Комментарий --------- ----------- ------- ------------- Конфигурация prototool.yaml easyp.yaml Форматы YAML/JSON поддерживаются; структура отличается. Линтинг Встроенные наборы ","content":"Кратко о различиях Область Prototool EasyP Комментарий --------- ----------- ------- ------------- Конфигурация prototool.yaml easyp.yaml Форматы YAML/JSON поддерживаются; структура отличается. Линтинг Встроенные наборы + кастомные правила Наборы через lint.use, тонкая настройка ignore/except EasyP даёт больше гибкости группировки. Генерация Раздел generate + плагины через Docker/локально generate.plugins (локальные/WASM/удалённые) EasyP может выполнять плагины удалённо (API Service). Зависимости Обычно через include-пути / внешние git clone вручную Секция deps (Git репозитории) + mod update Более декларативно. Breaking Changes Нет встроенного механизма Секция breaking + команда easyp breaking Из коробки. Lock-in Зависимость от модели Prototool Минималистичный формат, «любой Git — пакет» Облегчает выход / интеграцию с другими экосистемами."},{"id":"migration/prototool::prototool::3","title":"Prototool","section":"Типовая структура Prototool (упрощённо)","path":"/docs/guide/migration/prototool#prototool","headings":["Типовая структура Prototool (упрощённо)"],"excerpt":"Типовая структура Prototool (упрощённо)","content":"Типовая структура Prototool (упрощённо)"},{"id":"migration/prototool::prototool::4","title":"Prototool","section":"Типовая структура Prototool (упрощённо)","path":"/docs/guide/migration/prototool#prototool","headings":["Типовая структура Prototool (упрощённо)"],"excerpt":"Типовая структура Prototool (упрощённо) Особенности: include_paths задаёт пути поиска импортов. lint.group + rules.add/remove регулируют активные проверки. generate.plugins описывает плагины для protoc.","content":"Типовая структура Prototool (упрощённо) Особенности: include_paths задаёт пути поиска импортов. lint.group + rules.add/remove регулируют активные проверки. generate.plugins описывает плагины для protoc."},{"id":"migration/prototool::prototool::5","title":"Prototool","section":"Типовая структура Prototool (упрощённо)","path":"/docs/guide/migration/prototool#prototool","headings":["Типовая структура Prototool (упрощённо)"],"excerpt":"Типовая структура Prototool (упрощённо) ---","content":"Типовая структура Prototool (упрощённо) ---"},{"id":"migration/prototool::easyp::6","title":"Prototool","section":"Эквивалент на EasyP","path":"/docs/guide/migration/prototool#easyp","headings":["Эквивалент на EasyP"],"excerpt":"Эквивалент на EasyP ```yaml easyp.yaml (пример) deps: - github.com/org/common-protos # вместо manual include - github.com/org/third-party-protos","content":"Эквивалент на EasyP ```yaml easyp.yaml (пример) deps: - github.com/org/common-protos # вместо manual include - github.com/org/third-party-protos"},{"id":"migration/prototool::easyp::7","title":"Prototool","section":"Эквивалент на EasyP","path":"/docs/guide/migration/prototool#easyp","headings":["Эквивалент на EasyP"],"excerpt":"Эквивалент на EasyP lint: use: - MINIMAL - BASIC enum_zero_value_suffix: \"_NONE\" service_suffix: \"Service\" ignore: - COMMENT_FIELD except: - ENUM_VALUE_PREFIX allow_comment_ignores: true","content":"Эквивалент на EasyP lint: use: - MINIMAL - BASIC enum_zero_value_suffix: \"_NONE\" service_suffix: \"Service\" ignore: - COMMENT_FIELD except: - ENUM_VALUE_PREFIX allow_comment_ignores: true"},{"id":"migration/prototool::easyp::8","title":"Prototool","section":"Эквивалент на EasyP","path":"/docs/guide/migration/prototool#easyp","headings":["Эквивалент на EasyP"],"excerpt":"Эквивалент на EasyP generate: plugins: - name: go out: gen/go opts: paths: source_relative - name: go-grpc out: gen/go opts: paths: source_relative require_unimplemented_servers: false","content":"Эквивалент на EasyP generate: plugins: - name: go out: gen/go opts: paths: source_relative - name: go-grpc out: gen/go opts: paths: source_relative require_unimplemented_servers: false"},{"id":"migration/prototool::easyp::9","title":"Prototool","section":"Эквивалент на EasyP","path":"/docs/guide/migration/prototool#easyp","headings":["Эквивалент на EasyP"],"excerpt":"Эквивалент на EasyP breaking: against_git_ref: main ignore: - FIELD_SAME_TYPE ```","content":"Эквивалент на EasyP breaking: against_git_ref: main ignore: - FIELD_SAME_TYPE ```"},{"id":"migration/prototool::easyp::10","title":"Prototool","section":"Эквивалент на EasyP","path":"/docs/guide/migration/prototool#easyp","headings":["Эквивалент на EasyP"],"excerpt":"Эквивалент на EasyP Комментарии: deps заменяет необходимость вручную прописывать include paths: EasyP подтянет их через git. lint.use активирует наборы правил (MINIMAL/BASIC/DEFAULT и т.д.). Дополнительные настройки (enu","content":"Эквивалент на EasyP Комментарии: deps заменяет необходимость вручную прописывать include paths: EasyP подтянет их через git. lint.use активирует наборы правил (MINIMAL/BASIC/DEFAULT и т.д.). Дополнительные настройки (enum_zero_value_suffix, service_suffix) задают политики нейминга. breaking позволяет сразу контролировать несовместимые изменения."},{"id":"migration/prototool::top::11","title":"Prototool","section":"Шаги миграции","path":"/docs/guide/migration/prototool","headings":["Шаги миграции"],"excerpt":"Шаги миграции Инвентаризация: - Соберите текущий prototool.yaml, списки include paths и плагины. - Зафиксируйте используемые кастомные правила, если есть.","content":"Шаги миграции Инвентаризация: - Соберите текущий prototool.yaml, списки include paths и плагины. - Зафиксируйте используемые кастомные правила, если есть."},{"id":"migration/prototool::top::12","title":"Prototool","section":"Шаги миграции","path":"/docs/guide/migration/prototool","headings":["Шаги миграции"],"excerpt":"Шаги миграции Зависимости: - Любые каталоги, которые вы вручную добавляли в include_paths, преобразуйте в git-репозитории (если ещё нет). - Добавьте их в deps (формат: github.com/owner/repo или путь к вашей приватной сис","content":"Шаги миграции Зависимости: - Любые каталоги, которые вы вручную добавляли в include_paths, преобразуйте в git-репозитории (если ещё нет). - Добавьте их в deps (формат: github.com/owner/repo или путь к вашей приватной системе Git)."},{"id":"migration/prototool::top::13","title":"Prototool","section":"Шаги миграции","path":"/docs/guide/migration/prototool","headings":["Шаги миграции"],"excerpt":"Шаги миграции Линтинг: - Определите какой group использовался (basic, default, …) → сопоставьте с наборами EasyP (MINIMAL, BASIC, DEFAULT). - Индивидуальные добавления (rules.add) перенесите в lint.use или except/ignore:","content":"Шаги миграции Линтинг: - Определите какой group использовался (basic, default, …) → сопоставьте с наборами EasyP (MINIMAL, BASIC, DEFAULT). - Индивидуальные добавления (rules.add) перенесите в lint.use или except/ignore: - Если правило нужно активировать — включите через набор или явно. - Если нужно отключить — добавьте в ignore."},{"id":"migration/prototool::top::14","title":"Prototool","section":"Шаги миграции","path":"/docs/guide/migration/prototool","headings":["Шаги миграции"],"excerpt":"Шаги миграции Генерация: - Сохраните список плагинов. В большинстве случаев имена совпадут (go, go-grpc, др.). - Если раньше использовали Docker-окружение Prototool — проверьте поддержку удалённых плагинов через API Serv","content":"Шаги миграции Генерация: - Сохраните список плагинов. В большинстве случаев имена совпадут (go, go-grpc, др.). - Если раньше использовали Docker-окружение Prototool — проверьте поддержку удалённых плагинов через API Service EasyP (опционально). - Перепишите в секцию generate.plugins."},{"id":"migration/prototool::top::15","title":"Prototool","section":"Шаги миграции","path":"/docs/guide/migration/prototool","headings":["Шаги миграции"],"excerpt":"Шаги миграции Дополнительные опции: - Настройки нейминга enum/service перенести в enum_zero_value_suffix, service_suffix. - Если были внешние скрипты для проверки breaking changes — удалите их и включите breaking с again","content":"Шаги миграции Дополнительные опции: - Настройки нейминга enum/service перенести в enum_zero_value_suffix, service_suffix. - Если были внешние скрипты для проверки breaking changes — удалите их и включите breaking с against_git_ref."},{"id":"migration/prototool::top::16","title":"Prototool","section":"Шаги миграции","path":"/docs/guide/migration/prototool","headings":["Шаги миграции"],"excerpt":"Шаги миграции Верификация: - Запустите: easyp mod update (скачивание deps). - Затем: easyp lint. - Далее: easyp generate. - И, если нужно: easyp breaking --against git-ref=origin/main.","content":"Шаги миграции Верификация: - Запустите: easyp mod update (скачивание deps). - Затем: easyp lint. - Далее: easyp generate. - И, если нужно: easyp breaking --against git-ref=origin/main."},{"id":"migration/prototool::top::17","title":"Prototool","section":"Шаги миграции","path":"/docs/guide/migration/prototool","headings":["Шаги миграции"],"excerpt":"Шаги миграции CI/CD: - Обновите workflow (GitHub Actions / GitLab) — замените вызовы Prototool на EasyP команды. - Добавьте шаг проверки несовместимых изменений.","content":"Шаги миграции CI/CD: - Обновите workflow (GitHub Actions / GitLab) — замените вызовы Prototool на EasyP команды. - Добавьте шаг проверки несовместимых изменений."},{"id":"migration/prototool::top::18","title":"Prototool","section":"Сопоставление правил (общая идея)","path":"/docs/guide/migration/prototool","headings":["Сопоставление правил (общая идея)"],"excerpt":"Сопоставление правил (общая идея) Prototool концепт EasyP ------------------- ------ lint.group lint.use (наборы) rules.add/remove except / ignore include_paths deps (git источники) plugins generate.plugins (внешние скри","content":"Сопоставление правил (общая идея) Prototool концепт EasyP ------------------- ------ lint.group lint.use (наборы) rules.add/remove except / ignore include_paths deps (git источники) plugins generate.plugins (внешние скрипты для breaking) breaking секция + команда"},{"id":"migration/prototool::top::19","title":"Prototool","section":"Сопоставление правил (общая идея)","path":"/docs/guide/migration/prototool","headings":["Сопоставление правил (общая идея)"],"excerpt":"Сопоставление правил (общая идея) ---","content":"Сопоставление правил (общая идея) ---"},{"id":"migration/prototool::top::20","title":"Prototool","section":"Приватные репозитории","path":"/docs/guide/migration/prototool","headings":["Приватные репозитории"],"excerpt":"Приватные репозитории Если ранее Prototool просто видел локальные каталоги, теперь: Добавьте SSH ключи/токены в CI для доступа к приватным Git. Укажите их в deps как обычные git-URL (формат зависит от реализации EasyP; д","content":"Приватные репозитории Если ранее Prototool просто видел локальные каталоги, теперь: Добавьте SSH ключи/токены в CI для доступа к приватным Git. Укажите их в deps как обычные git-URL (формат зависит от реализации EasyP; для публичных — стандартный)."},{"id":"migration/prototool::top::21","title":"Prototool","section":"Типовые проблемы при миграции","path":"/docs/guide/migration/prototool","headings":["Типовые проблемы при миграции"],"excerpt":"Типовые проблемы при миграции Проблема Причина Решение ---------- --------- --------- Правила линтера не совпадают Неверное сопоставление групп Проверить документацию EasyP по наборам правил Импорты не находятся Забыли д","content":"Типовые проблемы при миграции Проблема Причина Решение ---------- --------- --------- Правила линтера не совпадают Неверное сопоставление групп Проверить документацию EasyP по наборам правил Импорты не находятся Забыли добавить репозиторий в deps Добавить в deps и выполнить easyp mod update Генерация падает на опциях Плагин требует другие flags Проверить opts и документацию плагина breaking сообщает слишком много Слишком строгий базовый набор Добавить конкретные правила в breaking.ignore Долгая генерация Нет кеша/много deps Включить кэширование в CI (vendor/.easyp/deps)"},{"id":"migration/prototool::top::22","title":"Prototool","section":"Типовые проблемы при миграции","path":"/docs/guide/migration/prototool","headings":["Типовые проблемы при миграции"],"excerpt":"Типовые проблемы при миграции ---","content":"Типовые проблемы при миграции ---"},{"id":"migration/prototool::top::23","title":"Prototool","section":"Минимальная конфигурация после миграции","path":"/docs/guide/migration/prototool","headings":["Минимальная конфигурация после миграции"],"excerpt":"Минимальная конфигурация после миграции","content":"Минимальная конфигурация после миграции"},{"id":"migration/prototool::top::24","title":"Prototool","section":"Минимальная конфигурация после миграции","path":"/docs/guide/migration/prototool","headings":["Минимальная конфигурация после миграции"],"excerpt":"Минимальная конфигурация после миграции ---","content":"Минимальная конфигурация после миграции ---"},{"id":"migration/prototool::top::25","title":"Prototool","section":"Рекомендации по упрощению","path":"/docs/guide/migration/prototool","headings":["Рекомендации по упрощению"],"excerpt":"Рекомендации по упрощению Начните с минимального lint.use (MINIMAL), затем постепенно включайте дополнительные наборы. Не переносите слепо все ignore — часть правил может уже быть улучшена в EasyP. Сначала настроить deps","content":"Рекомендации по упрощению Начните с минимального lint.use (MINIMAL), затем постепенно включайте дополнительные наборы. Не переносите слепо все ignore — часть правил может уже быть улучшена в EasyP. Сначала настроить deps и генерацию, затем усложнять линт/нейминг. Фиксируйте миграцию по шагам (коммиты: deps → lint → generate → breaking → CI)."},{"id":"migration/prototool::top::26","title":"Prototool","section":"Проверка результата","path":"/docs/guide/migration/prototool","headings":["Проверка результата"],"excerpt":"Проверка результата Скрипт локальной быстрой проверки (пример):","content":"Проверка результата Скрипт локальной быстрой проверки (пример):"},{"id":"migration/prototool::top::27","title":"Prototool","section":"Проверка результата","path":"/docs/guide/migration/prototool","headings":["Проверка результата"],"excerpt":"Проверка результата ```bash #!/usr/bin/env bash set -euo pipefail","content":"Проверка результата ```bash #!/usr/bin/env bash set -euo pipefail"},{"id":"migration/prototool::top::28","title":"Prototool","section":"Проверка результата","path":"/docs/guide/migration/prototool","headings":["Проверка результата"],"excerpt":"Проверка результата echo \"[1] deps update\" easyp mod update","content":"Проверка результата echo \"[1] deps update\" easyp mod update"},{"id":"migration/prototool::top::29","title":"Prototool","section":"Проверка результата","path":"/docs/guide/migration/prototool","headings":["Проверка результата"],"excerpt":"Проверка результата echo \"[2] lint\" easyp lint","content":"Проверка результата echo \"[2] lint\" easyp lint"},{"id":"migration/prototool::top::30","title":"Prototool","section":"Проверка результата","path":"/docs/guide/migration/prototool","headings":["Проверка результата"],"excerpt":"Проверка результата echo \"[3] breaking vs main\" easyp breaking --against git-ref=origin/main echo \"Breaking changes detected (review needed)\"","content":"Проверка результата echo \"[3] breaking vs main\" easyp breaking --against git-ref=origin/main echo \"Breaking changes detected (review needed)\""},{"id":"migration/prototool::top::31","title":"Prototool","section":"Проверка результата","path":"/docs/guide/migration/prototool","headings":["Проверка результата"],"excerpt":"Проверка результата echo \"[4] generate\" easyp generate","content":"Проверка результата echo \"[4] generate\" easyp generate"},{"id":"migration/prototool::top::32","title":"Prototool","section":"Проверка результата","path":"/docs/guide/migration/prototool","headings":["Проверка результата"],"excerpt":"Проверка результата echo \"Done.\" ```","content":"Проверка результата echo \"Done.\" ```"},{"id":"migration/prototool::top::33","title":"Prototool","section":"Заключение","path":"/docs/guide/migration/prototool","headings":["Заключение"],"excerpt":"Заключение Миграция с Prototool на EasyP сводится к: Переносу путей и внешних каталогов в декларативные deps. Переформатированию линта под lint.use + ignore/except. Переносу генерации в generate.plugins. Добавлению встро","content":"Заключение Миграция с Prototool на EasyP сводится к: Переносу путей и внешних каталогов в декларативные deps. Переформатированию линта под lint.use + ignore/except. Переносу генерации в generate.plugins. Добавлению встроенного механизма breaking. Адаптации CI."},{"id":"migration/prototool::top::34","title":"Prototool","section":"Заключение","path":"/docs/guide/migration/prototool","headings":["Заключение"],"excerpt":"Заключение После этого конфигурация становится более прозрачной, а проверка несовместимых изменений — из коробки.","content":"Заключение После этого конфигурация становится более прозрачной, а проверка несовместимых изменений — из коробки."},{"id":"migration/prototool::top::35","title":"Prototool","section":"Заключение","path":"/docs/guide/migration/prototool","headings":["Заключение"],"excerpt":"Заключение *Готово: базовый перевод и расширенное руководство по миграции с Prototool на EasyP.*","content":"Заключение *Готово: базовый перевод и расширенное руководство по миграции с Prototool на EasyP.*"},{"id":"TRANSLATION_STATUS::top::0","title":"Translation Status (ru-guide)","path":"/docs/guide/TRANSLATION_STATUS","headings":[],"excerpt":"Этот файл отслеживает прогресс перевода русской документации. Используемые статусы: TODO — требуется перевод IN_PROGRESS — перевод начат, требуется вычитка DONE — перевод завершён и вычитан SKIPPED — не требует перевода ","content":"Этот файл отслеживает прогресс перевода русской документации. Используемые статусы: TODO — требуется перевод IN_PROGRESS — перевод начат, требуется вычитка DONE — перевод завершён и вычитан SKIPPED — не требует перевода (намеренно оставлено на английском)"},{"id":"TRANSLATION_STATUS::top::1","title":"Translation Status (ru-guide)","path":"/docs/guide/TRANSLATION_STATUS","headings":[],"excerpt":"Правила: После полного перевода файла убрать исходный английский текст и маркер Термины протокола и ключевые идентификаторы (названия правил, CLI команды, YAML ключи) НЕ переводим. Если структура исходного файла изменила","content":"Правила: После полного перевода файла убрать исходный английский текст и маркер Термины протокола и ключевые идентификаторы (названия правил, CLI команды, YAML ключи) НЕ переводим. Если структура исходного файла изменилась — добавить в начало: Для больших изменений: сначала IN_PROGRESS, после вычитки менять на DONE."},{"id":"TRANSLATION_STATUS::summary::2","title":"Translation Status (ru-guide)","section":"Summary","path":"/docs/guide/TRANSLATION_STATUS#summary","headings":["Summary"],"excerpt":"Summary Итого файлов: 76 DONE: 76 IN_PROGRESS: 0 TODO: 0","content":"Summary Итого файлов: 76 DONE: 76 IN_PROGRESS: 0 TODO: 0"},{"id":"TRANSLATION_STATUS::priority-order::3","title":"Translation Status (ru-guide)","section":"Priority Order (рекомендованный)","path":"/docs/guide/TRANSLATION_STATUS#priority-order","headings":["Priority Order (рекомендованный)"],"excerpt":"Priority Order (рекомендованный) introduction/what-is.md introduction/quickstart.md introduction/install.md cli/linter/linter.md cli/generator/generator.md cli/package-manager/package-manager.md cli/breaking-changes/brea","content":"Priority Order (рекомендованный) introduction/what-is.md introduction/quickstart.md introduction/install.md cli/linter/linter.md cli/generator/generator.md cli/package-manager/package-manager.md cli/breaking-changes/breaking-changes.md api-service/overview.md migration/* (пакетом)"},{"id":"TRANSLATION_STATUS::priority-order::4","title":"Translation Status (ru-guide)","section":"Priority Order (рекомендованный)","path":"/docs/guide/TRANSLATION_STATUS#priority-order","headings":["Priority Order (рекомендованный)"],"excerpt":"Priority Order (рекомендованный) ---","content":"Priority Order (рекомендованный) ---"},{"id":"TRANSLATION_STATUS::file-status-table::5","title":"Translation Status (ru-guide)","section":"File Status Table","path":"/docs/guide/TRANSLATION_STATUS#file-status-table","headings":["File Status Table"],"excerpt":"File Status Table File Status Notes ------ -------- ------- introduction/what-is.md DONE Полный перевод выполнен introduction/quickstart.md DONE Структура сохранена, перевод вычитан introduction/install.md DONE Переведен","content":"File Status Table File Status Notes ------ -------- ------- introduction/what-is.md DONE Полный перевод выполнен introduction/quickstart.md DONE Структура сохранена, перевод вычитан introduction/install.md DONE Переведено, команды проверены api-service/overview.md DONE Переведено ci-cd/github-actions.md DONE Переведено ci-cd/gitlab.md DONE Переведено cli/auto-completion/auto-completion.md DONE Переведено cli/breaking-changes/breaking-changes.md DONE Переведено и вычитано cli/breaking-changes/rules/enum-no-delete.md DONE Переведено cli/breaking-changes/rules/enum-value-no-delete.md DONE Переведено cli/breaking-changes/rules/enum-value-same-name.md DONE Переведено cli/breaking-changes/rules/field-no-delete.md DONE Переведено cli/breaking-changes/rules/field-same-cardinality.md DONE Переведено cli/breaking-changes/rules/field-same-type.md DONE Переведено cli/breaking-changes/rules/import-no-delete.md DONE Переведено cli/breaking-changes/rules/message-no-delete.md DONE Переведено cli/breaking-changes/rules/oneof-field-no-delete.md DONE Переведено cli/breaking-changes/rules/oneof-field-same-type.md DONE Переведено cli/breaking-changes/rules/oneof-no-delete.md DONE Переведено cli/breaking-changes/rules/rpc-no-delete.md DONE Переведено cli/breaking-changes/rules/rpc-same-request-type.md DONE Переведено cli/breaking-changes/rules/rpc-same-response-type.md DONE Переведено cli/breaking-changes/rules/service-no-delete.md DONE Переведено cli/configuration/configuration.md DONE Переведено cli/generator/examples/go.md DONE Переведено cli/generator/examples/grpc-gateway.md DONE Переведено cli/generator/examples/validate.md DONE Переведено cli/generator/generator.md DONE Переведено и вычитано cli/linter/linter.md DONE Переведено и вычитано cli/linter/rules/comment-enum-value.md DONE Переведено cli/linter/rules/comment-enum.md DONE Переведено cli/linter/rules/comment-field.md DONE Переведено cli/linter/rules/comment-message.md DONE Переведено cli/linter/rules/comment-oneof.md DONE Переведено cli/linter/rules/comment-rpc.md DONE Переведено cli/linter/rules/comment-service.md DONE Переведено cli/linter/rules/directory-same-package.md DONE Переведено cli/linter/rules/enum-first-value-zero.md DONE Переведено cli/linter/rules/enum-no-allow-alias.md DONE Переведено cli/linter/rules/enum-pascal-case.md DONE Переведено cli/linter/rules/enum-value-prefix.md DONE Переведено cli/linter/rules/enum-value-upper-snake-case.md DONE Переведено cli/linter/rules/enum-zero-value-suffix.md DONE Переведено cli/linter/rules/field-lower-snake-case.md DONE Переведено cli/linter/rules/file-lower-snake-case.md DONE Переведено cli/linter/rules/import-no-public.md DONE Переведено cli/linter/rules/import-no-weak.md DONE Переведено cli/linter/rules/import-used.md DONE Переведено cli/linter/rules/message-pascal-case.md DONE Переведено cli/linter/rules/oneof-lower-snake-case.md DONE Переведено cli/linter/rules/package-defined.md DONE Переведено cli/linter/rules/package-directory-match.md DONE Переведено cli/linter/rules/package-lower-snake-case.md DONE Переведено cli/linter/rules/package-same-csharp-namespace.md DONE Переведено cli/linter/rules/package-same-directory.md DONE Переведено cli/linter/rules/package-same-go-package.md DONE Переведено cli/linter/rules/package-same-java-multiple-files.md DONE Переведено cli/linter/rules/package-same-java-package.md DONE Переведено cli/linter/rules/package-same-php-namespace.md DONE Переведено cli/linter/rules/package-same-ruby-package.md DONE Переведено cli/linter/rules/package-same-swift-prefix.md DONE Переведено cli/linter/rules/package-version-suffix.md DONE Переведено cli/linter/rules/rpc-no-client-streaming.md DONE Переведено cli/linter/rules/rpc-no-server-streaming.md DONE Переведено cli/linter/rules/rpc-pascal-case.md DONE Переведено cli/linter/rules/rpc-request-response-unique.md DONE Переведено cli/linter/rules/rpc-request-standard-name.md DONE Переведено cli/linter/rules/rpc-response-standard-name.md DONE Переведено cli/linter/rules/service-pascal-case.md DONE Переведено cli/linter/rules/service-suffix.md DONE Переведено cli/package-manager/easyp-vs-buf.md DONE Переведено cli/package-manager/package-manager.md DONE Переведено и вычитано migration/buf-cli.md DONE Переведено migration/protoc.md DONE Переведено migration/protolock.md DONE Переведено migration/prototool.md DONE Переведено"},{"id":"TRANSLATION_STATUS::workflow::6","title":"Translation Status (ru-guide)","section":"Workflow","path":"/docs/guide/TRANSLATION_STATUS#workflow","headings":["Workflow"],"excerpt":"Workflow Выбираем файл со статусом TODO. Меняем статус на IN_PROGRESS здесь. Переводим, проверяем терминологию (сверка с глоссарием — добавить позже). Меняем статус на DONE. Удаляем маркер внутри файла.","content":"Workflow Выбираем файл со статусом TODO. Меняем статус на IN_PROGRESS здесь. Переводим, проверяем терминологию (сверка с глоссарием — добавить позже). Меняем статус на DONE. Удаляем маркер внутри файла."},{"id":"TRANSLATION_STATUS::planned-terminology::7","title":"Translation Status (ru-guide)","section":"Planned Terminology (черновик)","path":"/docs/guide/TRANSLATION_STATUS#planned-terminology","headings":["Planned Terminology (черновик)"],"excerpt":"Planned Terminology (черновик) EN RU Notes ---- ---- ------- Linting Линтинг Транслитерация Breaking Changes Несовместимые изменения Название секции Dependency Зависимость Code Generation Генерация кода Lock file Lock-фа","content":"Planned Terminology (черновик) EN RU Notes ---- ---- ------- Linting Линтинг Транслитерация Breaking Changes Несовместимые изменения Название секции Dependency Зависимость Code Generation Генерация кода Lock file Lock-файл Remote Plugin Удалённый плагин Package Manager Менеджер пакетов"},{"id":"TRANSLATION_STATUS::planned-terminology::8","title":"Translation Status (ru-guide)","section":"Planned Terminology (черновик)","path":"/docs/guide/TRANSLATION_STATUS#planned-terminology","headings":["Planned Terminology (черновик)"],"excerpt":"Planned Terminology (черновик) (Будет дополнено.)","content":"Planned Terminology (черновик) (Будет дополнено.)"},{"id":"TRANSLATION_STATUS::planned-terminology::9","title":"Translation Status (ru-guide)","section":"Planned Terminology (черновик)","path":"/docs/guide/TRANSLATION_STATUS#planned-terminology","headings":["Planned Terminology (черновик)"],"excerpt":"Planned Terminology (черновик) ---","content":"Planned Terminology (черновик) ---"},{"id":"TRANSLATION_STATUS::top::10","title":"Translation Status (ru-guide)","section":"История обновлений","path":"/docs/guide/TRANSLATION_STATUS","headings":["История обновлений"],"excerpt":"История обновлений Initial file created: all statuses set (3 IN_PROGRESS, rest TODO). Marked breaking-changes page as DONE. Linter rules (41 файлов) переведены: статусы DONE. Breaking-changes rules (15 файлов) вычитаны и","content":"История обновлений Initial file created: all statuses set (3 IN_PROGRESS, rest TODO). Marked breaking-changes page as DONE. Linter rules (41 файлов) переведены: статусы DONE. Breaking-changes rules (15 файлов) вычитаны и помечены DONE. Все оставшиеся страницы переведены: итог DONE = 76."}] \ No newline at end of file diff --git a/docs/public/docs/guide/cli/generator/generator.md b/docs/public/docs/guide/cli/generator/generator.md index ae474f0f..fa04560d 100644 --- a/docs/public/docs/guide/cli/generator/generator.md +++ b/docs/public/docs/guide/cli/generator/generator.md @@ -574,9 +574,9 @@ When managed mode is enabled, EasyP automatically applies file and field options - Objective-C: `objc_class_prefix` defaults to first letters of package parts - C++: `cc_enable_arenas` defaults to `true` -**Overrides** allow you to set specific values for options, with support for filtering by module, path, or field. +**Overrides** allow you to set specific values for options, with support for filtering by module, path, or field. Without `module` or `path`, an override applies to all files in the generation request, including dependencies and `git_repo` inputs. -**Disables** allow you to prevent managed mode from modifying specific options or files. +**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. ### Configuration @@ -759,6 +759,8 @@ generate: module: github.com/mycompany/internal-protos ``` +`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`. + #### Disabling for External Dependencies Disable managed mode for external dependencies that already have their options set: diff --git a/docs/public/docs/ru-guide/cli/generator/generator.md b/docs/public/docs/ru-guide/cli/generator/generator.md index 910354ca..6b17395f 100644 --- a/docs/public/docs/ru-guide/cli/generator/generator.md +++ b/docs/public/docs/ru-guide/cli/generator/generator.md @@ -574,9 +574,9 @@ Managed mode автоматически устанавливает file и field - Objective-C: `objc_class_prefix` по умолчанию первые буквы частей пакета - C++: `cc_enable_arenas` по умолчанию `true` -**Overrides** позволяют установить конкретные значения для опций с поддержкой фильтрации по модулю, пути или полю. +**Overrides** позволяют установить конкретные значения для опций с поддержкой фильтрации по модулю, пути или полю. Если не указаны `module` и `path`, override применяется ко всем файлам в запросе генерации, включая зависимости и `git_repo` inputs. -**Disables** позволяют предотвратить изменение managed mode определённых опций или файлов. +**Disables** позволяют предотвратить изменение managed mode определённых опций или файлов. Это рекомендуемый способ исключить внешние зависимости, у которых свои опции уже заданы. ### Конфигурация @@ -759,6 +759,8 @@ generate: module: github.com/mycompany/internal-protos ``` +`module` должен точно совпадать с источником модуля в EasyP: это значение из `deps` или `git_repo.url` до `@version` (например, `github.com/mycompany/internal-protos` или `https://github.com/mycompany/internal-protos`). Это не Go module path из `go.mod`. + #### Отключение для внешних зависимостей Отключите managed mode для внешних зависимостей, у которых уже установлены опции: diff --git a/docs/public/search/index.en.json b/docs/public/search/index.en.json index 13a3450b..853e288a 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, required) - Output directory for generated files opts (mapstring, optional) - Plugin-specific options; each key can be a single value or an array of 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 ✅ - 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, path, or field.","content":"How It Works **Overrides** allow you to set specific values for options, with support for filtering by module, path, or field."},{"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.","content":"How It Works **Disables** allow you to prevent managed mode from modifying specific options or files."},{"id":"cli/generator/generator::supported-file-options::92","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::93","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::94","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::95","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::96","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::97","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::98","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::99","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::100","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::101","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::disabling-for-external-dependencies::102","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::103","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::104","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::105","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::106","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::107","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::108","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::109","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::110","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::111","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::112","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::113","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::114","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::115","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::116","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::117","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::118","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::119","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::120","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::121","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::122","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::123","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::124","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::125","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::126","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::127","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::128","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::129","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::130","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::131","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::132","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::133","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::134","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::135","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::136","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::137","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::138","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::139","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::140","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::141","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::142","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::143","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::144","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::145","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::146","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::147","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::148","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::149","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::150","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::151","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::152","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::153","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::154","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::155","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::156","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::157","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::158","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::159","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::160","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::161","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::162","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::163","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::164","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::165","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::166","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::167","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::168","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::169","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::170","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::171","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::172","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::173","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::174","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::175","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::176","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::177","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::178","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::179","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::180","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::181","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::182","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::183","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::184","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-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, required) - Output directory for generated files opts (mapstring, optional) - Plugin-specific options; each key can be a single value or an array of 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 ✅ - 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, path, or field. Without module or path, an override applies to all files in the generation request, including","content":"How It Works **Overrides** allow you to set specific values for options, with support for filtering by module, path, or field. Without module 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::supported-file-options::92","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::93","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::94","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::95","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::96","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::97","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::98","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::99","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::100","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::101","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::102","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::disabling-for-external-dependencies::103","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::104","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::105","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::106","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::107","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::108","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::109","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::110","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::111","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::112","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::113","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::114","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::115","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::116","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::117","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::118","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::119","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::120","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::121","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::122","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::123","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::124","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::125","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::126","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::127","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::128","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::129","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::130","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::131","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::132","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::133","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::134","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::135","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::136","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::137","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::138","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::139","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::140","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::141","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::142","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::143","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::144","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::145","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::146","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::147","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::148","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::149","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::150","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::151","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::152","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::153","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::154","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::155","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::156","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::157","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::158","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::159","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::160","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::161","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::162","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::163","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::164","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::165","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::166","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::167","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::168","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::169","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::170","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::171","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::172","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::173","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::174","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::175","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::176","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::177","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::178","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::179","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::180","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::181","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::182","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::183","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::184","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::185","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/docs/public/search/index.ru.json b/docs/public/search/index.ru.json index 8fede7f6..6434c044 100644 --- a/docs/public/search/index.ru.json +++ b/docs/public/search/index.ru.json @@ -1 +1 @@ -[{"id":"api-service/overview::top::0","title":"Обзор API Service","path":"/docs/guide/api-service/overview","headings":[],"excerpt":"**Централизованный сервис выполнения protobuf‑плагинов для консистентной изолированной генерации кода**","content":"**Централизованный сервис выполнения protobuf‑плагинов для консистентной изолированной генерации кода**"},{"id":"api-service/overview::top::1","title":"Обзор API Service","path":"/docs/guide/api-service/overview","headings":[],"excerpt":"EasyP API Service устраняет хаос управления плагинами, предоставляя централизованный запуск protobuf/gRPC плагинов в изолированных Docker‑контейнерах. Он даёт единую платформу, позволяющую командам стандартизировать проц","content":"EasyP API Service устраняет хаос управления плагинами, предоставляя централизованный запуск protobuf/gRPC плагинов в изолированных Docker‑контейнерах. Он даёт единую платформу, позволяющую командам стандартизировать процесс генерации кода без операционных затрат на установку и поддержку плагинов на машинах разработчиков."},{"id":"api-service/overview::easyp-api-service::2","title":"Обзор API Service","section":"Зачем нужен EasyP API Service?","path":"/docs/guide/api-service/overview#easyp-api-service","headings":["Зачем нужен EasyP API Service?"],"excerpt":"Зачем нужен EasyP API Service?","content":"Зачем нужен EasyP API Service?"},{"id":"api-service/overview::top::3","title":"Обзор API Service","section":"Проблема","path":"/docs/guide/api-service/overview","headings":["Проблема"],"excerpt":"Проблема Управление генерацией protobuf/gRPC кода в командах порождает существенную операционную сложность:","content":"Проблема Управление генерацией protobuf/gRPC кода в командах порождает существенную операционную сложность:"},{"id":"api-service/overview::top::4","title":"Обзор API Service","section":"Несогласованность версий","path":"/docs/guide/api-service/overview","headings":["Несогласованность версий"],"excerpt":"Несогласованность версий Разработчики локально используют разные версии плагинов → расхождения в генерированном коде и падения сборки Синдром «у меня работает» при различиях окружений Требуется ручная координация, чтобы ","content":"Несогласованность версий Разработчики локально используют разные версии плагинов → расхождения в генерированном коде и падения сборки Синдром «у меня работает» при различиях окружений Требуется ручная координация, чтобы вся команда была синхронизирована по версиям"},{"id":"api-service/overview::top::5","title":"Обзор API Service","section":"Операционные накладные расходы","path":"/docs/guide/api-service/overview","headings":["Операционные накладные расходы"],"excerpt":"Операционные накладные расходы DevOps тратят время на установку и обновление плагинов на рабочих станциях Новый разработчик — ручная настройка правильных версий Обновление плагинов требует коммуникации с каждым отдельно ","content":"Операционные накладные расходы DevOps тратят время на установку и обновление плагинов на рабочих станциях Новый разработчик — ручная настройка правильных версий Обновление плагинов требует коммуникации с каждым отдельно Нет централизованного контроля утверждённых версий"},{"id":"api-service/overview::top::6","title":"Обзор API Service","section":"Риски безопасности и комплаенса","path":"/docs/guide/api-service/overview","headings":["Риски безопасности и комплаенса"],"excerpt":"Риски безопасности и комплаенса Плагины ставятся из разных источников без валидации Нет аудита: какой плагин для какого билда использовался Сложно применять политики безопасности к инструментам генерации","content":"Риски безопасности и комплаенса Плагины ставятся из разных источников без валидации Нет аудита: какой плагин для какого билда использовался Сложно применять политики безопасности к инструментам генерации"},{"id":"api-service/overview::top::7","title":"Обзор API Service","section":"Решение: централизованный запуск плагинов","path":"/docs/guide/api-service/overview","headings":["Решение: централизованный запуск плагинов"],"excerpt":"Решение: централизованный запуск плагинов EasyP API Service решает эти проблемы за счёт централизованного управления:","content":"Решение: централизованный запуск плагинов EasyP API Service решает эти проблемы за счёт централизованного управления:"},{"id":"api-service/overview::top::8","title":"Обзор API Service","section":"Решение: централизованный запуск плагинов","path":"/docs/guide/api-service/overview","headings":["Решение: централизованный запуск плагинов"],"excerpt":"Решение: централизованный запуск плагинов Проблема Решение ---------- --------- **Контроль версий** Мгновенное распространение новых версий через Docker‑образы **Операции** Команда эксплуатации управляет конфигурациями б","content":"Решение: централизованный запуск плагинов Проблема Решение ---------- --------- **Контроль версий** Мгновенное распространение новых версий через Docker‑образы **Операции** Команда эксплуатации управляет конфигурациями без доступа на машины разработчиков **Безопасность** Все плагины запускаются в изолированных контейнерах с ограничениями ресурсов **Консистентность** Единая среда выполнения вне зависимости от локальной установки **Опыт разработчика** Не нужно устанавливать и сопровождать плагины локально"},{"id":"api-service/overview::top::9","title":"Обзор API Service","section":"Архитектура","path":"/docs/guide/api-service/overview","headings":["Архитектура"],"excerpt":"Архитектура Архитектура сервиса упрощена и сфокусирована на надёжном выполнении плагинов:","content":"Архитектура Архитектура сервиса упрощена и сфокусирована на надёжном выполнении плагинов:"},{"id":"api-service/overview::api-layer::10","title":"Обзор API Service","section":"API Layer","path":"/docs/guide/api-service/overview#api-layer","headings":["API Layer"],"excerpt":"API Layer **gRPC Server** — основной API для запросов генерации Каждый запуск плагина — отдельный gRPC‑запрос Получает CodeGeneratorRequest от CLI","content":"API Layer **gRPC Server** — основной API для запросов генерации Каждый запуск плагина — отдельный gRPC‑запрос Получает CodeGeneratorRequest от CLI"},{"id":"api-service/overview::execution-engine::11","title":"Обзор API Service","section":"Execution Engine","path":"/docs/guide/api-service/overview#execution-engine","headings":["Execution Engine"],"excerpt":"Execution Engine **Docker Runtime** — изолированный запуск плагинов Подтягивает образы из публичных реестров (Docker Hub и т.п.) Применяет лимиты CPU/памяти на плагин","content":"Execution Engine **Docker Runtime** — изолированный запуск плагинов Подтягивает образы из публичных реестров (Docker Hub и т.п.) Применяет лимиты CPU/памяти на плагин"},{"id":"api-service/overview::storage-layer::12","title":"Обзор API Service","section":"Storage Layer","path":"/docs/guide/api-service/overview#storage-layer","headings":["Storage Layer"],"excerpt":"Storage Layer **PostgreSQL** хранит параметры выполнения: - Ограничения ресурсов (CPU, память) - Конфигурацию и метаданные плагинов - Логи выполнения (аудит) - _Примечание: функциональность хранения будет расширяться_","content":"Storage Layer **PostgreSQL** хранит параметры выполнения: - Ограничения ресурсов (CPU, память) - Конфигурацию и метаданные плагинов - Логи выполнения (аудит) - _Примечание: функциональность хранения будет расширяться_"},{"id":"api-service/overview::monitoring::13","title":"Обзор API Service","section":"Monitoring","path":"/docs/guide/api-service/overview#monitoring","headings":["Monitoring"],"excerpt":"Monitoring **Prometheus** — сбор метрик Отслеживает время выполнения, успешность, использование ресурсов","content":"Monitoring **Prometheus** — сбор метрик Отслеживает время выполнения, успешность, использование ресурсов"},{"id":"api-service/overview::easyp-cli::14","title":"Обзор API Service","section":"Локальное выполнение (EasyP CLI)","path":"/docs/guide/api-service/overview#easyp-cli","headings":["Локальное выполнение (EasyP CLI)"],"excerpt":"Локальное выполнение (EasyP CLI) При локальном запуске CLI поддерживает: **Installed plugins**: системно установленные protoc плагины **WASM plugins**: лёгкие WebAssembly плагины","content":"Локальное выполнение (EasyP CLI) При локальном запуске CLI поддерживает: **Installed plugins**: системно установленные protoc плагины **WASM plugins**: лёгкие WebAssembly плагины"},{"id":"api-service/overview::api-service::15","title":"Обзор API Service","section":"Удалённое выполнение (API Service)","path":"/docs/guide/api-service/overview#api-service","headings":["Удалённое выполнение (API Service)"],"excerpt":"Удалённое выполнение (API Service) При работе через сервис: **Только Docker**: плагины запускаются как контейнеры **Центральный контроль**: операционная команда управляет доступными версиями **Консистентная среда**: один","content":"Удалённое выполнение (API Service) При работе через сервис: **Только Docker**: плагины запускаются как контейнеры **Центральный контроль**: операционная команда управляет доступными версиями **Консистентная среда**: одинаковое окружение для всех разработчиков"},{"id":"api-service/overview::top::16","title":"Обзор API Service","section":"Шаги выполнения","path":"/docs/guide/api-service/overview","headings":["Шаги выполнения"],"excerpt":"Шаги выполнения **CLI Parsing**: CLI парсит локальные .proto файлы **Request Sending**: Отправляет CodeGeneratorRequest в API Service (по одному на плагин) **Parameter Lookup**: Сервис получает параметры запуска из Postg","content":"Шаги выполнения **CLI Parsing**: CLI парсит локальные .proto файлы **Request Sending**: Отправляет CodeGeneratorRequest в API Service (по одному на плагин) **Parameter Lookup**: Сервис получает параметры запуска из PostgreSQL **Docker Execution**: Запускает плагин в изолированном контейнере **Metrics Recording**: Записывает метрики после завершения **Response**: Возвращает сгенерированный код обратно в CLI"},{"id":"api-service/overview::top::17","title":"Обзор API Service","section":"Ключевые возможности","path":"/docs/guide/api-service/overview","headings":["Ключевые возможности"],"excerpt":"Ключевые возможности Возможность Описание ------------- ---------- **🐳 Изоляция плагинов** Каждый плагин в отдельном безопасном контейнере **⚙️ Контроль ресурсов** Лимиты CPU и памяти на уровне контейнера **📊 Метрики &","content":"Ключевые возможности Возможность Описание ------------- ---------- **🐳 Изоляция плагинов** Каждый плагин в отдельном безопасном контейнере **⚙️ Контроль ресурсов** Лимиты CPU и памяти на уровне контейнера **📊 Метрики & мониторинг** Полный набор Prometheus метрик **🔄 Управление версиями** Централизованно через Docker‑образы **⚡ Простой протокол** Стандарт CodeGeneratorRequest/Response **🔒 Безопасность прежде всего** Изоляция + ограниченные ресурсы"},{"id":"api-service/overview::top::18","title":"Обзор API Service","section":"Конфигурация","path":"/docs/guide/api-service/overview","headings":["Конфигурация"],"excerpt":"Конфигурация Сервис настраивается через переменные окружения.","content":"Конфигурация Сервис настраивается через переменные окружения."},{"id":"api-service/overview::top::19","title":"Обзор API Service","section":"Хранение параметров плагинов","path":"/docs/guide/api-service/overview","headings":["Хранение параметров плагинов"],"excerpt":"Хранение параметров плагинов PostgreSQL хранит параметры выполнения для каждого плагина:","content":"Хранение параметров плагинов PostgreSQL хранит параметры выполнения для каждого плагина:"},{"id":"api-service/overview::top::20","title":"Обзор API Service","section":"Хранение параметров плагинов","path":"/docs/guide/api-service/overview","headings":["Хранение параметров плагинов"],"excerpt":"Хранение параметров плагинов ::: tip Схема хранения будет расширена — аудит логов, аналитика использования, кеширование плагинов. :::","content":"Хранение параметров плагинов ::: tip Схема хранения будет расширена — аудит логов, аналитика использования, кеширование плагинов. :::"},{"id":"api-service/overview::easyp-cli::21","title":"Обзор API Service","section":"Интеграция с EasyP CLI","path":"/docs/guide/api-service/overview#easyp-cli","headings":["Интеграция с EasyP CLI"],"excerpt":"Интеграция с EasyP CLI Пример easyp.yaml для удалённого запуска:","content":"Интеграция с EasyP CLI Пример easyp.yaml для удалённого запуска:"},{"id":"api-service/overview::easyp-cli::22","title":"Обзор API Service","section":"Интеграция с EasyP CLI","path":"/docs/guide/api-service/overview#easyp-cli","headings":["Интеграция с EasyP CLI"],"excerpt":"Интеграция с EasyP CLI Запуск генерации:","content":"Интеграция с EasyP CLI Запуск генерации:"},{"id":"api-service/overview::easyp-cli::23","title":"Обзор API Service","section":"Интеграция с EasyP CLI","path":"/docs/guide/api-service/overview#easyp-cli","headings":["Интеграция с EasyP CLI"],"excerpt":"Интеграция с EasyP CLI CLI: Парсит protobuf‑файлы Отправляет отдельные запросы в сервис для каждого плагина Получает ответы с кодом Записывает файлы в указанные директории","content":"Интеграция с EasyP CLI CLI: Парсит protobuf‑файлы Отправляет отдельные запросы в сервис для каждого плагина Получает ответы с кодом Записывает файлы в указанные директории"},{"id":"api-service/overview::top::24","title":"Обзор API Service","section":"Доступные метрики","path":"/docs/guide/api-service/overview","headings":["Доступные метрики"],"excerpt":"Доступные метрики Метрики Prometheus:","content":"Доступные метрики Метрики Prometheus:"},{"id":"api-service/overview::top::25","title":"Обзор API Service","section":"Доступные метрики","path":"/docs/guide/api-service/overview","headings":["Доступные метрики"],"excerpt":"Доступные метрики Метрика Описание --------- ---------- easyp_api_service_api_grpc_server_handled_total Общее число gRPC запросов по статусам easyp_api_service_api_grpc_server_handling_seconds Гистограмма задержек gRPC e","content":"Доступные метрики Метрика Описание --------- ---------- easyp_api_service_api_grpc_server_handled_total Общее число gRPC запросов по статусам easyp_api_service_api_grpc_server_handling_seconds Гистограмма задержек gRPC easyp_api_service_generated_plugin_code_total Выполнения плагинов по имени easyp_api_service_repo_call_duration_seconds Латентность запросов к БД easyp_api_service_repo_errors_total Количество ошибок доступа к БД easyp_api_service_standard_panics_total Число восстановленных паник"},{"id":"api-service/overview::top::26","title":"Обзор API Service","section":"Характеристики производительности","path":"/docs/guide/api-service/overview","headings":["Характеристики производительности"],"excerpt":"Характеристики производительности Показатель Типичное значение Примечания ----------- ------------------- ----------- **Cold Start** 2–5 сек Первая загрузка образа **Warm Start** 100–500 мс Образ закеширован **Throughput","content":"Характеристики производительности Показатель Типичное значение Примечания ----------- ------------------- ----------- **Cold Start** 2–5 сек Первая загрузка образа **Warm Start** 100–500 мс Образ закеширован **Throughput** 20–50 одновременных Зависит от ресурсов **Memory Usage** 50–200 MB На выполнение одного плагина"},{"id":"api-service/overview::top::27","title":"Обзор API Service","section":"Изоляция контейнеров","path":"/docs/guide/api-service/overview","headings":["Изоляция контейнеров"],"excerpt":"Изоляция контейнеров Каждый плагин в отдельном эфемерном контейнере Нет сетевого доступа в процессе выполнения Лимиты CPU/памяти через Docker Контейнер удаляется после завершения","content":"Изоляция контейнеров Каждый плагин в отдельном эфемерном контейнере Нет сетевого доступа в процессе выполнения Лимиты CPU/памяти через Docker Контейнер удаляется после завершения"},{"id":"api-service/overview::api::28","title":"Обзор API Service","section":"Безопасность API","path":"/docs/guide/api-service/overview#api","headings":["Безопасность API"],"excerpt":"Безопасность API gRPC транспорт Поддержка токенов аутентификации (в продакшн окружениях) Валидация входных данных Аудитные логи в PostgreSQL","content":"Безопасность API gRPC транспорт Поддержка токенов аутентификации (в продакшн окружениях) Валидация входных данных Аудитные логи в PostgreSQL"},{"id":"api-service/overview::top::29","title":"Обзор API Service","section":"Масштабирование","path":"/docs/guide/api-service/overview","headings":["Масштабирование"],"excerpt":"Масштабирование **Горизонтальное**: несколько инстансов за балансировщиком **Ресурсы**: настройка лимитов для тяжёлых плагинов **База данных**: репликация PostgreSQL для отказоустойчивости","content":"Масштабирование **Горизонтальное**: несколько инстансов за балансировщиком **Ресурсы**: настройка лимитов для тяжёлых плагинов **База данных**: репликация PostgreSQL для отказоустойчивости"},{"id":"api-service/overview::top::30","title":"Обзор API Service","section":"Мониторинг","path":"/docs/guide/api-service/overview","headings":["Мониторинг"],"excerpt":"Мониторинг **Метрики**: Prometheus **Алертинг**: оповещения на высокие ошибки/латентность **Логи**: структурированные для аудита и отладки","content":"Мониторинг **Метрики**: Prometheus **Алертинг**: оповещения на высокие ошибки/латентность **Логи**: структурированные для аудита и отладки"},{"id":"api-service/overview::top::31","title":"Обзор API Service","section":"План развития","path":"/docs/guide/api-service/overview","headings":["План развития"],"excerpt":"План развития Запланировано: Кеширование результатов генерации Расширенный аудит и аналитика использования Поддержка приватных реестров плагинов Более умное распределение ресурсов","content":"План развития Запланировано: Кеширование результатов генерации Расширенный аудит и аналитика использования Поддержка приватных реестров плагинов Более умное распределение ресурсов"},{"id":"api-service/overview::top::32","title":"Обзор API Service","section":"Сообщество и поддержка","path":"/docs/guide/api-service/overview","headings":["Сообщество и поддержка"],"excerpt":"Сообщество и поддержка **💬 Telegram чат** — обсуждения **🐛 GitHub Issues** — баги и запросы фич **📖 Документация** — полный набор материалов","content":"Сообщество и поддержка **💬 Telegram чат** — обсуждения **🐛 GitHub Issues** — баги и запросы фич **📖 Документация** — полный набор материалов"},{"id":"api-service/overview::top::33","title":"Обзор API Service","section":"Сообщество и поддержка","path":"/docs/guide/api-service/overview","headings":["Сообщество и поддержка"],"excerpt":"Сообщество и поддержка *Упростите свои protobuf‑воркфлоу с централизованным управлением выполнением плагинов.*","content":"Сообщество и поддержка *Упростите свои protobuf‑воркфлоу с централизованным управлением выполнением плагинов.*"},{"id":"ci-cd/github-actions::top::0","title":"GitHub Actions","path":"/docs/guide/ci-cd/github-actions","headings":[],"excerpt":"Полное руководство по интеграции EasyP в конвейеры GitHub Actions для линтинга, проверки несовместимых изменений, генерации кода и автоматизации релизов.","content":"Полное руководство по интеграции EasyP в конвейеры GitHub Actions для линтинга, проверки несовместимых изменений, генерации кода и автоматизации релизов."},{"id":"ci-cd/github-actions::easyp-ci::1","title":"GitHub Actions","section":"Зачем использовать EasyP в CI","path":"/docs/guide/ci-cd/github-actions#easyp-ci","headings":["Зачем использовать EasyP в CI"],"excerpt":"Зачем использовать EasyP в CI Встраивание EasyP в GitHub Actions даёт: Единообразие правил линтинга и генерации между разработчиками. Автоматическое выявление несовместимых изменений (breaking changes) до мержа. Гарантию","content":"Зачем использовать EasyP в CI Встраивание EasyP в GitHub Actions даёт: Единообразие правил линтинга и генерации между разработчиками. Автоматическое выявление несовместимых изменений (breaking changes) до мержа. Гарантию, что сгенерированный код не «устарел» относительно .proto. Возможность централизованной проверки зависимостей и версии конфигурации."},{"id":"ci-cd/github-actions::top::2","title":"GitHub Actions","section":"Предварительные требования","path":"/docs/guide/ci-cd/github-actions","headings":["Предварительные требования"],"excerpt":"Предварительные требования Репозиторий содержит файл конфигурации easyp.yaml (или находится в корне, если запускается без --cfg). Установлены / определены зависимости в секции deps (если нужны внешние импорты). Для прива","content":"Предварительные требования Репозиторий содержит файл конфигурации easyp.yaml (или находится в корне, если запускается без --cfg). Установлены / определены зависимости в секции deps (если нужны внешние импорты). Для приватных Git-репозиториев настроен доступ (SSH key / deploy key / токен). В workflow есть шаги по установке Go (если EasyP поставляется через go install) или заранее подготовленный бинарь."},{"id":"ci-cd/github-actions::top::3","title":"GitHub Actions","section":"Базовый пример (быстрый старт)","path":"/docs/guide/ci-cd/github-actions","headings":["Базовый пример (быстрый старт)"],"excerpt":"Базовый пример (быстрый старт) Минимальный workflow для проверки линта и несовместимых изменений при открытия Pull Request:","content":"Базовый пример (быстрый старт) Минимальный workflow для проверки линта и несовместимых изменений при открытия Pull Request:"},{"id":"ci-cd/github-actions::top::4","title":"GitHub Actions","section":"Базовый пример (быстрый старт)","path":"/docs/guide/ci-cd/github-actions","headings":["Базовый пример (быстрый старт)"],"excerpt":"Базовый пример (быстрый старт) ```yaml name: easyp-ci","content":"Базовый пример (быстрый старт) ```yaml name: easyp-ci"},{"id":"ci-cd/github-actions::top::5","title":"GitHub Actions","section":"Базовый пример (быстрый старт)","path":"/docs/guide/ci-cd/github-actions","headings":["Базовый пример (быстрый старт)"],"excerpt":"Базовый пример (быстрый старт) on: pull_request: paths: - '**/*.proto' - 'easyp.yaml'","content":"Базовый пример (быстрый старт) on: pull_request: paths: - '**/*.proto' - 'easyp.yaml'"},{"id":"ci-cd/github-actions::top::6","title":"GitHub Actions","section":"Базовый пример (быстрый старт)","path":"/docs/guide/ci-cd/github-actions","headings":["Базовый пример (быстрый старт)"],"excerpt":"Базовый пример (быстрый старт) jobs: lint-and-breaking: runs-on: ubuntu-latest","content":"Базовый пример (быстрый старт) jobs: lint-and-breaking: runs-on: ubuntu-latest"},{"id":"ci-cd/github-actions::top::7","title":"GitHub Actions","section":"Базовый пример (быстрый старт)","path":"/docs/guide/ci-cd/github-actions","headings":["Базовый пример (быстрый старт)"],"excerpt":"Базовый пример (быстрый старт) steps: - name: Checkout uses: actions/checkout@v4","content":"Базовый пример (быстрый старт) steps: - name: Checkout uses: actions/checkout@v4"},{"id":"ci-cd/github-actions::top::8","title":"GitHub Actions","section":"Базовый пример (быстрый старт)","path":"/docs/guide/ci-cd/github-actions","headings":["Базовый пример (быстрый старт)"],"excerpt":"Базовый пример (быстрый старт) name: Setup Go uses: actions/setup-go@v5 with: go-version: '1.22'","content":"Базовый пример (быстрый старт) name: Setup Go uses: actions/setup-go@v5 with: go-version: '1.22'"},{"id":"ci-cd/github-actions::top::9","title":"GitHub Actions","section":"Базовый пример (быстрый старт)","path":"/docs/guide/ci-cd/github-actions","headings":["Базовый пример (быстрый старт)"],"excerpt":"Базовый пример (быстрый старт) name: Install EasyP run: go install github.com/easyp-tech/easyp/cmd/easyp@latest","content":"Базовый пример (быстрый старт) name: Install EasyP run: go install github.com/easyp-tech/easyp/cmd/easyp@latest"},{"id":"ci-cd/github-actions::top::10","title":"GitHub Actions","section":"Базовый пример (быстрый старт)","path":"/docs/guide/ci-cd/github-actions","headings":["Базовый пример (быстрый старт)"],"excerpt":"Базовый пример (быстрый старт) name: Verify EasyP version run: which easyp easyp version","content":"Базовый пример (быстрый старт) name: Verify EasyP version run: which easyp easyp version"},{"id":"ci-cd/github-actions::top::11","title":"GitHub Actions","section":"Базовый пример (быстрый старт)","path":"/docs/guide/ci-cd/github-actions","headings":["Базовый пример (быстрый старт)"],"excerpt":"Базовый пример (быстрый старт) name: Lint run: easyp lint","content":"Базовый пример (быстрый старт) name: Lint run: easyp lint"},{"id":"ci-cd/github-actions::top::12","title":"GitHub Actions","section":"Базовый пример (быстрый старт)","path":"/docs/guide/ci-cd/github-actions","headings":["Базовый пример (быстрый старт)"],"excerpt":"Базовый пример (быстрый старт) name: Breaking changes check (against main) run: easyp breaking --against git-ref=origin/main ```","content":"Базовый пример (быстрый старт) name: Breaking changes check (against main) run: easyp breaking --against git-ref=origin/main ```"},{"id":"ci-cd/github-actions::easyp::13","title":"GitHub Actions","section":"Установка EasyP","path":"/docs/guide/ci-cd/github-actions#easyp","headings":["Установка EasyP"],"excerpt":"Установка EasyP Варианты: Через go install (как в примере выше). Использование заранее собранного бинаря (артефакт релиза).","content":"Установка EasyP Варианты: Через go install (как в примере выше). Использование заранее собранного бинаря (артефакт релиза)."},{"id":"ci-cd/github-actions::top::14","title":"GitHub Actions","section":"Кэширование","path":"/docs/guide/ci-cd/github-actions","headings":["Кэширование"],"excerpt":"Кэширование Для ускорения повторных сборок можно кэшировать: Go модульный кеш (если используете генерацию с плагинами Go). Внешние зависимые Git-клонирования (папки vendor или содержимое deps при использовании easyp mod ","content":"Кэширование Для ускорения повторных сборок можно кэшировать: Go модульный кеш (если используете генерацию с плагинами Go). Внешние зависимые Git-клонирования (папки vendor или содержимое deps при использовании easyp mod download / easyp mod update). Сгенерированный код (если он тяжёлый, но чаще генерируется заново)."},{"id":"ci-cd/github-actions::top::15","title":"GitHub Actions","section":"Кэширование","path":"/docs/guide/ci-cd/github-actions","headings":["Кэширование"],"excerpt":"Кэширование Пример кэширования Go:","content":"Кэширование Пример кэширования Go:"},{"id":"ci-cd/github-actions::top::16","title":"GitHub Actions","section":"Кэширование","path":"/docs/guide/ci-cd/github-actions","headings":["Кэширование"],"excerpt":"Кэширование Пример кэширования каталога зависимостей EasyP (если вы используете локальный vendor-подход):","content":"Кэширование Пример кэширования каталога зависимостей EasyP (если вы используете локальный vendor-подход):"},{"id":"ci-cd/github-actions::top::17","title":"GitHub Actions","section":"Кэширование","path":"/docs/guide/ci-cd/github-actions","headings":["Кэширование"],"excerpt":"Кэширование (Создайте .easyp/deps как целевой каталог, если ваша стратегия скачивания такова.)","content":"Кэширование (Создайте .easyp/deps как целевой каталог, если ваша стратегия скачивания такова.)"},{"id":"ci-cd/github-actions::top::18","title":"GitHub Actions","section":"Линтинг","path":"/docs/guide/ci-cd/github-actions","headings":["Линтинг"],"excerpt":"Линтинг Рекомендуется: В PR: всегда запускать. На main: можно запускать для верификации перед релизом.","content":"Линтинг Рекомендуется: В PR: всегда запускать. На main: можно запускать для верификации перед релизом."},{"id":"ci-cd/github-actions::top::19","title":"GitHub Actions","section":"Линтинг","path":"/docs/guide/ci-cd/github-actions","headings":["Линтинг"],"excerpt":"Линтинг Расширенный пример с выводом подробностей и игнорированием комментариев (если включено в конфиг):","content":"Линтинг Расширенный пример с выводом подробностей и игнорированием комментариев (если включено в конфиг):"},{"id":"ci-cd/github-actions::breaking-changes::20","title":"GitHub Actions","section":"Проверка несовместимых изменений (Breaking Changes)","path":"/docs/guide/ci-cd/github-actions#breaking-changes","headings":["Проверка несовместимых изменений (Breaking Changes)"],"excerpt":"Проверка несовместимых изменений (Breaking Changes) EasyP может сравнивать текущее состояние против ветки / коммита / тега.","content":"Проверка несовместимых изменений (Breaking Changes) EasyP может сравнивать текущее состояние против ветки / коммита / тега."},{"id":"ci-cd/github-actions::breaking-changes::21","title":"GitHub Actions","section":"Проверка несовместимых изменений (Breaking Changes)","path":"/docs/guide/ci-cd/github-actions#breaking-changes","headings":["Проверка несовместимых изменений (Breaking Changes)"],"excerpt":"Проверка несовместимых изменений (Breaking Changes) Примеры: ```bash Сравнить против origin/main easyp breaking --against git-ref=origin/main","content":"Проверка несовместимых изменений (Breaking Changes) Примеры: ```bash Сравнить против origin/main easyp breaking --against git-ref=origin/main"},{"id":"ci-cd/github-actions::breaking-changes::22","title":"GitHub Actions","section":"Проверка несовместимых изменений (Breaking Changes)","path":"/docs/guide/ci-cd/github-actions#breaking-changes","headings":["Проверка несовместимых изменений (Breaking Changes)"],"excerpt":"Проверка несовместимых изменений (Breaking Changes) Сравнить против тега релиза easyp breaking --against git-ref=v1.5.2","content":"Проверка несовместимых изменений (Breaking Changes) Сравнить против тега релиза easyp breaking --against git-ref=v1.5.2"},{"id":"ci-cd/github-actions::breaking-changes::23","title":"GitHub Actions","section":"Проверка несовместимых изменений (Breaking Changes)","path":"/docs/guide/ci-cd/github-actions#breaking-changes","headings":["Проверка несовместимых изменений (Breaking Changes)"],"excerpt":"Проверка несовместимых изменений (Breaking Changes) Игнорировать определённые правила (если у вас настроено в easyp.yaml) easyp breaking ```","content":"Проверка несовместимых изменений (Breaking Changes) Игнорировать определённые правила (если у вас настроено в easyp.yaml) easyp breaking ```"},{"id":"ci-cd/github-actions::breaking-changes::24","title":"GitHub Actions","section":"Проверка несовместимых изменений (Breaking Changes)","path":"/docs/guide/ci-cd/github-actions#breaking-changes","headings":["Проверка несовместимых изменений (Breaking Changes)"],"excerpt":"Проверка несовместимых изменений (Breaking Changes) Workflow шаг:","content":"Проверка несовместимых изменений (Breaking Changes) Workflow шаг:"},{"id":"ci-cd/github-actions::breaking-changes::25","title":"GitHub Actions","section":"Проверка несовместимых изменений (Breaking Changes)","path":"/docs/guide/ci-cd/github-actions#breaking-changes","headings":["Проверка несовместимых изменений (Breaking Changes)"],"excerpt":"Проверка несовместимых изменений (Breaking Changes)","content":"Проверка несовместимых изменений (Breaking Changes)"},{"id":"ci-cd/github-actions::breaking-changes::26","title":"GitHub Actions","section":"Проверка несовместимых изменений (Breaking Changes)","path":"/docs/guide/ci-cd/github-actions#breaking-changes","headings":["Проверка несовместимых изменений (Breaking Changes)"],"excerpt":"Проверка несовместимых изменений (Breaking Changes) Если нужно «мягко» пропустить (например, выводить предупреждения, но не падать билд):","content":"Проверка несовместимых изменений (Breaking Changes) Если нужно «мягко» пропустить (например, выводить предупреждения, но не падать билд):"},{"id":"ci-cd/github-actions::breaking-changes::27","title":"GitHub Actions","section":"Проверка несовместимых изменений (Breaking Changes)","path":"/docs/guide/ci-cd/github-actions#breaking-changes","headings":["Проверка несовместимых изменений (Breaking Changes)"],"excerpt":"Проверка несовместимых изменений (Breaking Changes)","content":"Проверка несовместимых изменений (Breaking Changes)"},{"id":"ci-cd/github-actions::top::28","title":"GitHub Actions","section":"Генерация кода","path":"/docs/guide/ci-cd/github-actions","headings":["Генерация кода"],"excerpt":"Генерация кода Обычно для генерации:","content":"Генерация кода Обычно для генерации:"},{"id":"ci-cd/github-actions::top::29","title":"GitHub Actions","section":"Генерация кода","path":"/docs/guide/ci-cd/github-actions","headings":["Генерация кода"],"excerpt":"Генерация кода Если нужно явно указать конфиг:","content":"Генерация кода Если нужно явно указать конфиг:"},{"id":"ci-cd/github-actions::top::30","title":"GitHub Actions","section":"Генерация кода","path":"/docs/guide/ci-cd/github-actions","headings":["Генерация кода"],"excerpt":"Генерация кода Можно добавить проверку «не осталось ли не закоммиченных изменений» (гарантия, что сгенерированный код актуален):","content":"Генерация кода Можно добавить проверку «не осталось ли не закоммиченных изменений» (гарантия, что сгенерированный код актуален):"},{"id":"ci-cd/github-actions::matrix-strategy::31","title":"GitHub Actions","section":"Матрица (Matrix strategy)","path":"/docs/guide/ci-cd/github-actions#matrix-strategy","headings":["Матрица (Matrix strategy)"],"excerpt":"Матрица (Matrix strategy) Если у вас несколько вариантов конфигураций или разных языков генерации (через плагины), можно использовать matrix:","content":"Матрица (Matrix strategy) Если у вас несколько вариантов конфигураций или разных языков генерации (через плагины), можно использовать matrix:"},{"id":"ci-cd/github-actions::matrix-strategy::32","title":"GitHub Actions","section":"Матрица (Matrix strategy)","path":"/docs/guide/ci-cd/github-actions#matrix-strategy","headings":["Матрица (Matrix strategy)"],"excerpt":"Матрица (Matrix strategy) ```yaml jobs: generate: runs-on: ubuntu-latest strategy: fail-fast: false matrix: lang: [go, python] steps: - uses: actions/checkout@v4","content":"Матрица (Matrix strategy) ```yaml jobs: generate: runs-on: ubuntu-latest strategy: fail-fast: false matrix: lang: [go, python] steps: - uses: actions/checkout@v4"},{"id":"ci-cd/github-actions::matrix-strategy::33","title":"GitHub Actions","section":"Матрица (Matrix strategy)","path":"/docs/guide/ci-cd/github-actions#matrix-strategy","headings":["Матрица (Matrix strategy)"],"excerpt":"Матрица (Matrix strategy) name: Setup Go (only for go) if: matrix.lang == 'go' uses: actions/setup-go@v5 with: go-version: '1.22'","content":"Матрица (Matrix strategy) name: Setup Go (only for go) if: matrix.lang == 'go' uses: actions/setup-go@v5 with: go-version: '1.22'"},{"id":"ci-cd/github-actions::matrix-strategy::34","title":"GitHub Actions","section":"Матрица (Matrix strategy)","path":"/docs/guide/ci-cd/github-actions#matrix-strategy","headings":["Матрица (Matrix strategy)"],"excerpt":"Матрица (Matrix strategy) name: Install EasyP run: go install github.com/easyp-tech/easyp/cmd/easyp@latest","content":"Матрица (Matrix strategy) name: Install EasyP run: go install github.com/easyp-tech/easyp/cmd/easyp@latest"},{"id":"ci-cd/github-actions::matrix-strategy::35","title":"GitHub Actions","section":"Матрица (Matrix strategy)","path":"/docs/guide/ci-cd/github-actions#matrix-strategy","headings":["Матрица (Matrix strategy)"],"excerpt":"Матрица (Matrix strategy) name: Generate run: if [ \"${{ matrix.lang }}\" = \"go\" ]; then easyp generate elif [ \"${{ matrix.lang }}\" = \"python\" ]; then easyp generate --plugin python fi ```","content":"Матрица (Matrix strategy) name: Generate run: if [ \"${{ matrix.lang }}\" = \"go\" ]; then easyp generate elif [ \"${{ matrix.lang }}\" = \"python\" ]; then easyp generate --plugin python fi ```"},{"id":"ci-cd/github-actions::deps::36","title":"GitHub Actions","section":"Работа с приватными репозиториями (deps)","path":"/docs/guide/ci-cd/github-actions#deps","headings":["Работа с приватными репозиториями (deps)"],"excerpt":"Работа с приватными репозиториями (deps) Если вы указываете приватные Git-пакеты в секции deps:","content":"Работа с приватными репозиториями (deps) Если вы указываете приватные Git-пакеты в секции deps:"},{"id":"ci-cd/github-actions::deps::37","title":"GitHub Actions","section":"Работа с приватными репозиториями (deps)","path":"/docs/guide/ci-cd/github-actions#deps","headings":["Работа с приватными репозиториями (deps)"],"excerpt":"Работа с приватными репозиториями (deps) Настройте deploy key или используйте GIT_SSH_COMMAND с токеном. Добавьте known_hosts (либо установите StrictHostKeyChecking=no для внутренних систем, но осознанно).","content":"Работа с приватными репозиториями (deps) Настройте deploy key или используйте GIT_SSH_COMMAND с токеном. Добавьте known_hosts (либо установите StrictHostKeyChecking=no для внутренних систем, но осознанно)."},{"id":"ci-cd/github-actions::deps::38","title":"GitHub Actions","section":"Работа с приватными репозиториями (deps)","path":"/docs/guide/ci-cd/github-actions#deps","headings":["Работа с приватными репозиториями (deps)"],"excerpt":"Работа с приватными репозиториями (deps) Пример:","content":"Работа с приватными репозиториями (deps) Пример:"},{"id":"ci-cd/github-actions::deps::39","title":"GitHub Actions","section":"Работа с приватными репозиториями (deps)","path":"/docs/guide/ci-cd/github-actions#deps","headings":["Работа с приватными репозиториями (deps)"],"excerpt":"Работа с приватными репозиториями (deps) ```yaml name: Prepare SSH run: mkdir -p ~/.ssh echo \"${{ secrets.DEPLOY_KEY }}\" > ~/.ssh/id_rsa chmod 600 ~/.ssh/id_rsa ssh-keyscan github.com >> ~/.ssh/known_hosts","content":"Работа с приватными репозиториями (deps) ```yaml name: Prepare SSH run: mkdir -p ~/.ssh echo \"${{ secrets.DEPLOY_KEY }}\" > ~/.ssh/id_rsa chmod 600 ~/.ssh/id_rsa ssh-keyscan github.com >> ~/.ssh/known_hosts"},{"id":"ci-cd/github-actions::deps::40","title":"GitHub Actions","section":"Работа с приватными репозиториями (deps)","path":"/docs/guide/ci-cd/github-actions#deps","headings":["Работа с приватными репозиториями (deps)"],"excerpt":"Работа с приватными репозиториями (deps) name: Update deps run: easyp mod update ```","content":"Работа с приватными репозиториями (deps) name: Update deps run: easyp mod update ```"},{"id":"ci-cd/github-actions::top::41","title":"GitHub Actions","section":"Оптимизация времени сборки","path":"/docs/guide/ci-cd/github-actions","headings":["Оптимизация времени сборки"],"excerpt":"Оптимизация времени сборки Используйте кэш для Go / deps. Запускайте линт/брейкинг только если изменились .proto или easyp.yaml (paths фильтр). Разделяйте workflow: быстрый линт в PR, тяжелая генерация в push на main. Вы","content":"Оптимизация времени сборки Используйте кэш для Go / deps. Запускайте линт/брейкинг только если изменились .proto или easyp.yaml (paths фильтр). Разделяйте workflow: быстрый линт в PR, тяжелая генерация в push на main. Выносите генерацию OpenAPI / gRPC-Gateway в отдельный job (параллелизм)."},{"id":"ci-cd/github-actions::workflow::42","title":"GitHub Actions","section":"Продвинутый workflow (многостадийный)","path":"/docs/guide/ci-cd/github-actions#workflow","headings":["Продвинутый workflow (многостадийный)"],"excerpt":"Продвинутый workflow (многостадийный) ```yaml name: easyp-pipeline","content":"Продвинутый workflow (многостадийный) ```yaml name: easyp-pipeline"},{"id":"ci-cd/github-actions::workflow::43","title":"GitHub Actions","section":"Продвинутый workflow (многостадийный)","path":"/docs/guide/ci-cd/github-actions#workflow","headings":["Продвинутый workflow (многостадийный)"],"excerpt":"Продвинутый workflow (многостадийный) on: pull_request: paths: - '**/*.proto' - 'easyp.yaml' push: branches: - main","content":"Продвинутый workflow (многостадийный) on: pull_request: paths: - '**/*.proto' - 'easyp.yaml' push: branches: - main"},{"id":"ci-cd/github-actions::workflow::44","title":"GitHub Actions","section":"Продвинутый workflow (многостадийный)","path":"/docs/guide/ci-cd/github-actions#workflow","headings":["Продвинутый workflow (многостадийный)"],"excerpt":"Продвинутый workflow (многостадийный) jobs: validate: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4","content":"Продвинутый workflow (многостадийный) jobs: validate: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4"},{"id":"ci-cd/github-actions::workflow::45","title":"GitHub Actions","section":"Продвинутый workflow (многостадийный)","path":"/docs/guide/ci-cd/github-actions#workflow","headings":["Продвинутый workflow (многостадийный)"],"excerpt":"Продвинутый workflow (многостадийный) uses: actions/setup-go@v5 with: go-version: '1.22'","content":"Продвинутый workflow (многостадийный) uses: actions/setup-go@v5 with: go-version: '1.22'"},{"id":"ci-cd/github-actions::workflow::46","title":"GitHub Actions","section":"Продвинутый workflow (многостадийный)","path":"/docs/guide/ci-cd/github-actions#workflow","headings":["Продвинутый workflow (многостадийный)"],"excerpt":"Продвинутый workflow (многостадийный) name: Install EasyP run: go install github.com/easyp-tech/easyp/cmd/easyp@latest","content":"Продвинутый workflow (многостадийный) name: Install EasyP run: go install github.com/easyp-tech/easyp/cmd/easyp@latest"},{"id":"ci-cd/github-actions::workflow::47","title":"GitHub Actions","section":"Продвинутый workflow (многостадийный)","path":"/docs/guide/ci-cd/github-actions#workflow","headings":["Продвинутый workflow (многостадийный)"],"excerpt":"Продвинутый workflow (многостадийный) name: Lint run: easyp lint","content":"Продвинутый workflow (многостадийный) name: Lint run: easyp lint"},{"id":"ci-cd/github-actions::workflow::48","title":"GitHub Actions","section":"Продвинутый workflow (многостадийный)","path":"/docs/guide/ci-cd/github-actions#workflow","headings":["Продвинутый workflow (многостадийный)"],"excerpt":"Продвинутый workflow (многостадийный) name: Breaking check (against main) if: github.event_name == 'pull_request' run: easyp breaking --against git-ref=origin/main","content":"Продвинутый workflow (многостадийный) name: Breaking check (against main) if: github.event_name == 'pull_request' run: easyp breaking --against git-ref=origin/main"},{"id":"ci-cd/github-actions::workflow::49","title":"GitHub Actions","section":"Продвинутый workflow (многостадийный)","path":"/docs/guide/ci-cd/github-actions#workflow","headings":["Продвинутый workflow (многостадийный)"],"excerpt":"Продвинутый workflow (многостадийный) generate: needs: validate if: github.event_name == 'push' runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-go@v5 with: go-version: '1.22' - name: Insta","content":"Продвинутый workflow (многостадийный) generate: needs: validate if: github.event_name == 'push' runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-go@v5 with: go-version: '1.22' - name: Install EasyP run: go install github.com/easyp-tech/easyp/cmd/easyp@latest - name: Generate Code run: easyp generate - name: Check diffs run: if [ -n \"$(git status --porcelain)\" ]; then echo \"Generated files changed after generate step.\" git diff --name-only exit 1 fi ```"},{"id":"ci-cd/github-actions::top::50","title":"GitHub Actions","section":"Автоматизация релиза (пример)","path":"/docs/guide/ci-cd/github-actions","headings":["Автоматизация релиза (пример)"],"excerpt":"Автоматизация релиза (пример) Можно добавить workflow, который по тегу создаёт релиз и валидирует proto:","content":"Автоматизация релиза (пример) Можно добавить workflow, который по тегу создаёт релиз и валидирует proto:"},{"id":"ci-cd/github-actions::top::51","title":"GitHub Actions","section":"Автоматизация релиза (пример)","path":"/docs/guide/ci-cd/github-actions","headings":["Автоматизация релиза (пример)"],"excerpt":"Автоматизация релиза (пример) ```yaml name: release-verify","content":"Автоматизация релиза (пример) ```yaml name: release-verify"},{"id":"ci-cd/github-actions::top::52","title":"GitHub Actions","section":"Автоматизация релиза (пример)","path":"/docs/guide/ci-cd/github-actions","headings":["Автоматизация релиза (пример)"],"excerpt":"Автоматизация релиза (пример) on: push: tags: - 'v*.*.*'","content":"Автоматизация релиза (пример) on: push: tags: - 'v*.*.*'"},{"id":"ci-cd/github-actions::top::53","title":"GitHub Actions","section":"Автоматизация релиза (пример)","path":"/docs/guide/ci-cd/github-actions","headings":["Автоматизация релиза (пример)"],"excerpt":"Автоматизация релиза (пример) jobs: release-check: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4","content":"Автоматизация релиза (пример) jobs: release-check: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4"},{"id":"ci-cd/github-actions::top::54","title":"GitHub Actions","section":"Автоматизация релиза (пример)","path":"/docs/guide/ci-cd/github-actions","headings":["Автоматизация релиза (пример)"],"excerpt":"Автоматизация релиза (пример) uses: actions/setup-go@v5 with: go-version: '1.22'","content":"Автоматизация релиза (пример) uses: actions/setup-go@v5 with: go-version: '1.22'"},{"id":"ci-cd/github-actions::top::55","title":"GitHub Actions","section":"Автоматизация релиза (пример)","path":"/docs/guide/ci-cd/github-actions","headings":["Автоматизация релиза (пример)"],"excerpt":"Автоматизация релиза (пример) name: Install EasyP run: go install github.com/easyp-tech/easyp/cmd/easyp@latest","content":"Автоматизация релиза (пример) name: Install EasyP run: go install github.com/easyp-tech/easyp/cmd/easyp@latest"},{"id":"ci-cd/github-actions::top::56","title":"GitHub Actions","section":"Автоматизация релиза (пример)","path":"/docs/guide/ci-cd/github-actions","headings":["Автоматизация релиза (пример)"],"excerpt":"Автоматизация релиза (пример) name: Lint run: easyp lint","content":"Автоматизация релиза (пример) name: Lint run: easyp lint"},{"id":"ci-cd/github-actions::top::57","title":"GitHub Actions","section":"Автоматизация релиза (пример)","path":"/docs/guide/ci-cd/github-actions","headings":["Автоматизация релиза (пример)"],"excerpt":"Автоматизация релиза (пример) name: Breaking vs previous tag run: PREV_TAG=$(git tag --sort=-creatordate grep -v \"${GITHUB_REF_NAME}\" head -n1 true) if [ -n \"$PREV_TAG\" ]; then echo \"Comparing against $PREV_TAG\" easyp br","content":"Автоматизация релиза (пример) name: Breaking vs previous tag run: PREV_TAG=$(git tag --sort=-creatordate grep -v \"${GITHUB_REF_NAME}\" head -n1 true) if [ -n \"$PREV_TAG\" ]; then echo \"Comparing against $PREV_TAG\" easyp breaking --against git-ref=$PREV_TAG else echo \"No previous tag, skipping breaking check\" fi"},{"id":"ci-cd/github-actions::top::58","title":"GitHub Actions","section":"Автоматизация релиза (пример)","path":"/docs/guide/ci-cd/github-actions","headings":["Автоматизация релиза (пример)"],"excerpt":"Автоматизация релиза (пример) name: Generate to ensure consistency run: easyp generate ```","content":"Автоматизация релиза (пример) name: Generate to ensure consistency run: easyp generate ```"},{"id":"ci-cd/github-actions::top::59","title":"GitHub Actions","section":"Отладка","path":"/docs/guide/ci-cd/github-actions","headings":["Отладка"],"excerpt":"Отладка Если нужно больше логов:","content":"Отладка Если нужно больше логов:"},{"id":"ci-cd/github-actions::top::60","title":"GitHub Actions","section":"Отладка","path":"/docs/guide/ci-cd/github-actions","headings":["Отладка"],"excerpt":"Отладка Добавьте вывод окружения для диагностики:","content":"Отладка Добавьте вывод окружения для диагностики:"},{"id":"ci-cd/github-actions::top::61","title":"GitHub Actions","section":"Переменные окружения (примерно)","path":"/docs/guide/ci-cd/github-actions","headings":["Переменные окружения (примерно)"],"excerpt":"Переменные окружения (примерно) Переменная Назначение ------------ ----------- EASYP_SERVICE_HOST Хост удалённого API Service (если используете удалённые плагины) EASYP_SERVICE_GRPC_PORT Порт удалённого сервиса GIT_SSH_C","content":"Переменные окружения (примерно) Переменная Назначение ------------ ----------- EASYP_SERVICE_HOST Хост удалённого API Service (если используете удалённые плагины) EASYP_SERVICE_GRPC_PORT Порт удалённого сервиса GIT_SSH_COMMAND Кастомная команда SSH (частные репозитории) GOFLAGS Можно выставить -mod=readonly для Go генерации"},{"id":"ci-cd/github-actions::top::62","title":"GitHub Actions","section":"Переменные окружения (примерно)","path":"/docs/guide/ci-cd/github-actions","headings":["Переменные окружения (примерно)"],"excerpt":"Переменные окружения (примерно) (Используйте только те, что действительно нужны вашему проекту.)","content":"Переменные окружения (примерно) (Используйте только те, что действительно нужны вашему проекту.)"},{"id":"ci-cd/github-actions::top::63","title":"GitHub Actions","section":"Частые ошибки","path":"/docs/guide/ci-cd/github-actions","headings":["Частые ошибки"],"excerpt":"Частые ошибки Симптом Причина Решение --------- --------- --------- Линт падает на неизвестных правилах Правила указаны в easyp.yaml, но версия EasyP их не поддерживает Обновить EasyP (go install ...@latest) breaking сра","content":"Частые ошибки Симптом Причина Решение --------- --------- --------- Линт падает на неизвестных правилах Правила указаны в easyp.yaml, но версия EasyP их не поддерживает Обновить EasyP (go install ...@latest) breaking сравнение ничего не находит Неверный --against (нет fetch удалённой ветки) Добавить шаг git fetch --all --tags Сгенерированный код в PR отличается от main Отсутствует проверка генерации в CI Добавить шаг «Ensure generated code is up-to-date» Приватные deps не скачиваются Нет SSH ключа или токена Настроить secrets + шаг подготовки SSH Долгое выполнение Отсутствует кеш Добавить кэширование модулей и deps"},{"id":"ci-cd/github-actions::top::64","title":"GitHub Actions","section":"Рекомендации по поддержке","path":"/docs/guide/ci-cd/github-actions","headings":["Рекомендации по поддержке"],"excerpt":"Рекомендации по поддержке Заготовить шаблон workflow и копировать между сервисами (DRY). Включить paths фильтры, чтобы не тратить минуты на нерелевантные изменения. Проверять easyp.yaml при изменениях отдельно — можно за","content":"Рекомендации по поддержке Заготовить шаблон workflow и копировать между сервисами (DRY). Включить paths фильтры, чтобы не тратить минуты на нерелевантные изменения. Проверять easyp.yaml при изменениях отдельно — можно запускать «конфигурационный тест» (например, easyp lint без файлов, чтобы убедиться, что конфиг валиден). При появлении новых правил линтера обновляйте конфиг и фиксируйте ошибки сразу в одной ветке."},{"id":"ci-cd/github-actions::top::65","title":"GitHub Actions","section":"Рекомендации по поддержке","path":"/docs/guide/ci-cd/github-actions","headings":["Рекомендации по поддержке"],"excerpt":"Рекомендации по поддержке Готово: вы можете расширять разделы генерации, добавлять OpenAPI / grpc-gateway / validate плагины, матрицы по языкам и интегрировать тесты поверх сгенерированного кода, если требуется.","content":"Рекомендации по поддержке Готово: вы можете расширять разделы генерации, добавлять OpenAPI / grpc-gateway / validate плагины, матрицы по языкам и интегрировать тесты поверх сгенерированного кода, если требуется."},{"id":"ci-cd/gitlab::top::0","title":"GitLab CI","section":"В процессе разработки","path":"/docs/guide/ci-cd/gitlab","headings":["В процессе разработки"],"excerpt":"В процессе разработки Документация по интеграции EasyP с GitLab CI находится в процессе подготовки. Планируемые разделы: Быстрый старт (пример .gitlab-ci.yml для линтинга и проверки несовместимых изменений) Кэширование з","content":"В процессе разработки Документация по интеграции EasyP с GitLab CI находится в процессе подготовки. Планируемые разделы: Быстрый старт (пример .gitlab-ci.yml для линтинга и проверки несовместимых изменений) Кэширование зависимостей и ускорение сборок Генерация кода и проверка актуальности артефактов Работа с приватными Git-репозиториями в deps Матрицы (parallel jobs) для разных языков и плагинов Автоматизация релизов по тегам"},{"id":"ci-cd/gitlab::top::1","title":"GitLab CI","section":"В процессе разработки","path":"/docs/guide/ci-cd/gitlab","headings":["В процессе разработки"],"excerpt":"В процессе разработки Если вам нужен пример прямо сейчас, базовый минимальный вариант может выглядеть так:","content":"В процессе разработки Если вам нужен пример прямо сейчас, базовый минимальный вариант может выглядеть так:"},{"id":"ci-cd/gitlab::top::2","title":"GitLab CI","section":"В процессе разработки","path":"/docs/guide/ci-cd/gitlab","headings":["В процессе разработки"],"excerpt":"В процессе разработки ```yaml stages: - validate - generate","content":"В процессе разработки ```yaml stages: - validate - generate"},{"id":"ci-cd/gitlab::top::3","title":"GitLab CI","section":"В процессе разработки","path":"/docs/guide/ci-cd/gitlab","headings":["В процессе разработки"],"excerpt":"В процессе разработки variables: GO_VERSION: \"1.22\"","content":"В процессе разработки variables: GO_VERSION: \"1.22\""},{"id":"ci-cd/gitlab::top::4","title":"GitLab CI","section":"В процессе разработки","path":"/docs/guide/ci-cd/gitlab","headings":["В процессе разработки"],"excerpt":"В процессе разработки validate: stage: validate image: golang:${GO_VERSION} before_script: - go install github.com/easyp-tech/easyp/cmd/easyp@latest - echo \"EasyP version:\" - easyp version # При необходимости: git fetch ","content":"В процессе разработки validate: stage: validate image: golang:${GO_VERSION} before_script: - go install github.com/easyp-tech/easyp/cmd/easyp@latest - echo \"EasyP version:\" - easyp version # При необходимости: git fetch --all --tags script: - easyp lint - easyp breaking --against git-ref=origin/main only: changes: - \"**/*.proto\" - \"easyp.yaml\""},{"id":"ci-cd/gitlab::top::5","title":"GitLab CI","section":"В процессе разработки","path":"/docs/guide/ci-cd/gitlab","headings":["В процессе разработки"],"excerpt":"В процессе разработки generate: stage: generate image: golang:${GO_VERSION} before_script: - go install github.com/easyp-tech/easyp/cmd/easyp@latest script: - easyp generate - if [ -n \"$(git status --porcelain)\" ]; then ","content":"В процессе разработки generate: stage: generate image: golang:${GO_VERSION} before_script: - go install github.com/easyp-tech/easyp/cmd/easyp@latest script: - easyp generate - if [ -n \"$(git status --porcelain)\" ]; then echo \"Сгенерированный код не актуален. Закоммитьте изменения локально.\" git diff --name-only exit 1 fi only: - main"},{"id":"ci-cd/gitlab::top::6","title":"GitLab CI","section":"В процессе разработки","path":"/docs/guide/ci-cd/gitlab","headings":["В процессе разработки"],"excerpt":"В процессе разработки Дополнительные рекомендации будут добавлены позже.","content":"В процессе разработки Дополнительные рекомендации будут добавлены позже."},{"id":"cli/auto-completion/auto-completion::zsh::0","title":"Автодополнение","section":"Автодополнение для zsh","path":"/docs/guide/cli/auto-completion/auto-completion#zsh","headings":["Автодополнение для zsh"],"excerpt":"Автодополнение для zsh Добавьте следующую строку в ваш файл запуска ~/.zshrc:","content":"Автодополнение для zsh Добавьте следующую строку в ваш файл запуска ~/.zshrc:"},{"id":"cli/auto-completion/auto-completion::zsh::1","title":"Автодополнение","section":"Автодополнение для zsh","path":"/docs/guide/cli/auto-completion/auto-completion#zsh","headings":["Автодополнение для zsh"],"excerpt":"Автодополнение для zsh Перезапустите оболочку или выполните:","content":"Автодополнение для zsh Перезапустите оболочку или выполните:"},{"id":"cli/auto-completion/auto-completion::bash::2","title":"Автодополнение","section":"Автодополнение для Bash","path":"/docs/guide/cli/auto-completion/auto-completion#bash","headings":["Автодополнение для Bash"],"excerpt":"Автодополнение для Bash Установите bash-completion и подключите его в ~/.bashrc. Добавьте следующую строку в файл запуска ~/.bashrc:","content":"Автодополнение для Bash Установите bash-completion и подключите его в ~/.bashrc. Добавьте следующую строку в файл запуска ~/.bashrc:"},{"id":"cli/auto-completion/auto-completion::bash::3","title":"Автодополнение","section":"Автодополнение для Bash","path":"/docs/guide/cli/auto-completion/auto-completion#bash","headings":["Автодополнение для Bash"],"excerpt":"Автодополнение для Bash Перезапустите оболочку или выполните:","content":"Автодополнение для Bash Перезапустите оболочку или выполните:"},{"id":"cli/auto-completion/auto-completion::top::4","title":"Автодополнение","section":"Примечания","path":"/docs/guide/cli/auto-completion/auto-completion","headings":["Примечания"],"excerpt":"Примечания Команда easyp completion выводит скрипт автодополнения для соответствующей оболочки. Если используете другую оболочку (например, fish), можно сгенерировать вывод и сохранить вручную: При обновлении версии Easy","content":"Примечания Команда easyp completion выводит скрипт автодополнения для соответствующей оболочки. Если используете другую оболочку (например, fish), можно сгенерировать вывод и сохранить вручную: При обновлении версии EasyP рекомендуется заново перезагрузить оболочку, чтобы подтянуть возможные изменения в автодополнении."},{"id":"cli/breaking-changes/breaking-changes::top::0","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":[],"excerpt":"Обнаружение несовместимых изменений (Breaking Changes Detection)","content":"Обнаружение несовместимых изменений (Breaking Changes Detection)"},{"id":"cli/breaking-changes/breaking-changes::top::1","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":[],"excerpt":"Механизм EasyP для обнаружения несовместимых (breaking) изменений помогает поддерживать обратную совместимость ваших protobuf API, автоматически выявляя изменения, способные сломать существующих клиентов. Это критично дл","content":"Механизм EasyP для обнаружения несовместимых (breaking) изменений помогает поддерживать обратную совместимость ваших protobuf API, автоматически выявляя изменения, способные сломать существующих клиентов. Это критично для стабильных API в продакшене."},{"id":"cli/breaking-changes/breaking-changes::top::2","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Обзор","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Обзор"],"excerpt":"Обзор Проверка несовместимых изменений сравнивает текущий набор protobuf‑файлов с предыдущей версией (обычно из другой Git ветки) и фиксирует модификации, которые могут вызвать проблемы совместимости для уже работающих к","content":"Обзор Проверка несовместимых изменений сравнивает текущий набор protobuf‑файлов с предыдущей версией (обычно из другой Git ветки) и фиксирует модификации, которые могут вызвать проблемы совместимости для уже работающих клиентов."},{"id":"cli/breaking-changes/breaking-changes::top::3","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Ключевые возможности","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Ключевые возможности"],"excerpt":"Ключевые возможности **Сравнение через Git**: Сопоставление с любой Git‑ссылкой (ветка, тег, commit) **Комплексный анализ**: Проверка сервисов, сообщений, enum'ов, полей и import'ов **Выборочное игнорирование**: Пропуск ","content":"Ключевые возможности **Сравнение через Git**: Сопоставление с любой Git‑ссылкой (ветка, тег, commit) **Комплексный анализ**: Проверка сервисов, сообщений, enum'ов, полей и import'ов **Выборочное игнорирование**: Пропуск указанных директорий из анализа **Детализированные отчёты**: Понятные ошибки с именами файлов, строками и позициями"},{"id":"cli/breaking-changes/breaking-changes::top::4","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Как работает","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Как работает"],"excerpt":"Как работает Детектор breaking changes выполняет следующие шаги:","content":"Как работает Детектор breaking changes выполняет следующие шаги:"},{"id":"cli/breaking-changes/breaking-changes::top::5","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Как работает","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Как работает"],"excerpt":"Как работает **Получение ветки сравнения**: Забирает proto-файлы из указанной Git‑ссылки **Парсинг обеих версий**: Анализирует структуру текущих и предыдущих файлов **Сравнение сущностей**: Последовательно проверяет все ","content":"Как работает **Получение ветки сравнения**: Забирает proto-файлы из указанной Git‑ссылки **Парсинг обеих версий**: Анализирует структуру текущих и предыдущих файлов **Сравнение сущностей**: Последовательно проверяет все элементы protobuf на breaking изменения **Формирование отчёта**: Генерирует подробные записи об ошибках с локациями и описаниями"},{"id":"cli/breaking-changes/breaking-changes::top::6","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Уровень проверки","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Уровень проверки"],"excerpt":"Уровень проверки EasyP реализует уровень проверки **WIRE+**: ✅ **Полная совместимость по wire‑формату** — старые и новые версии могут обмениваться данными ✅ **Обнаружение удалений элементов** — сервисы, сообщения, поля и","content":"Уровень проверки EasyP реализует уровень проверки **WIRE+**: ✅ **Полная совместимость по wire‑формату** — старые и новые версии могут обмениваться данными ✅ **Обнаружение удалений элементов** — сервисы, сообщения, поля и т.п. ✅ **Безопасность типов** — выявляет несовместимые изменения типов ❌ **Переименования полей/методов** — пока не детектируются (в планах) ❌ **Изменения на уровне файлов** — переносы пакетов, file options ещё не проверяются"},{"id":"cli/breaking-changes/breaking-changes::top::7","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Уровень проверки","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Уровень проверки"],"excerpt":"Уровень проверки Это даёт сильные гарантии совместимости и меньше ограничений, чем инструменты, требующие совместимости сгенерированного кода.","content":"Уровень проверки Это даёт сильные гарантии совместимости и меньше ограничений, чем инструменты, требующие совместимости сгенерированного кода."},{"id":"cli/breaking-changes/breaking-changes::top::8","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Конфигурация","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Конфигурация"],"excerpt":"Конфигурация Настройка в easyp.yaml:","content":"Конфигурация Настройка в easyp.yaml:"},{"id":"cli/breaking-changes/breaking-changes::top::9","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Параметры конфигурации","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Параметры конфигурации"],"excerpt":"Параметры конфигурации Option Description Default Required -------- ------------- --------- ---------- against_git_ref Git‑ссылка для сравнения \"master\" No ignore Список директорий для исключения из анализа [] No","content":"Параметры конфигурации Option Description Default Required -------- ------------- --------- ---------- against_git_ref Git‑ссылка для сравнения \"master\" No ignore Список директорий для исключения из анализа [] No"},{"id":"cli/breaking-changes/breaking-changes::top::10","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Базовый пример","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Базовый пример"],"excerpt":"Базовый пример Сравнение текущих изменений с веткой main:","content":"Базовый пример Сравнение текущих изменений с веткой main:"},{"id":"cli/breaking-changes/breaking-changes::top::11","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Использование файла конфигурации","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Использование файла конфигурации"],"excerpt":"Использование файла конфигурации","content":"Использование файла конфигурации"},{"id":"cli/breaking-changes/breaking-changes::top::12","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Уровень проверки","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Уровень проверки"],"excerpt":"Уровень проверки EasyP сейчас работает на уровне **WIRE+**, обеспечивая совместимость wire‑формата плюс защиту от удалений и изменения критичных типов.","content":"Уровень проверки EasyP сейчас работает на уровне **WIRE+**, обеспечивая совместимость wire‑формата плюс защиту от удалений и изменения критичных типов."},{"id":"cli/breaking-changes/breaking-changes::buf::13","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Сравнение с категориями Buf","path":"/docs/guide/cli/breaking-changes/breaking-changes#buf","headings":["Сравнение с категориями Buf"],"excerpt":"Сравнение с категориями Buf Check Type Buf WIRE Buf WIRE_JSON Buf FILE EasyP Current ------------ ---------- --------------- ---------- --------------- **Element Deletions** Service deletion ❌ ❌ ✅ ✅ RPC method deletion ❌","content":"Сравнение с категориями Buf 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::top::14","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Что это означает","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Что это означает"],"excerpt":"Что это означает **✅ EasyP обнаружит:** Все breaking изменения wire‑формата Удаления сервисов, методов, сообщений, полей Изменения типов, ломающие сериализацию Переименования enum‑значений (при сохранении номера)","content":"Что это означает **✅ EasyP обнаружит:** Все breaking изменения wire‑формата Удаления сервисов, методов, сообщений, полей Изменения типов, ломающие сериализацию Переименования enum‑значений (при сохранении номера)"},{"id":"cli/breaking-changes/breaking-changes::top::15","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Что это означает","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Что это означает"],"excerpt":"Что это означает **❌ EasyP НЕ обнаружит:** Переименование полей (с тем же номером) Изменение package File options (go_package, java_package, и т.п.) Перемещение типов между файлами в одном package","content":"Что это означает **❌ EasyP НЕ обнаружит:** Переименование полей (с тем же номером) Изменение package File options (go_package, java_package, и т.п.) Перемещение типов между файлами в одном package"},{"id":"cli/breaking-changes/breaking-changes::breaking-changes::16","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Правила Breaking Changes","path":"/docs/guide/cli/breaking-changes/breaking-changes#breaking-changes","headings":["Правила Breaking Changes"],"excerpt":"Правила Breaking Changes EasyP обнаруживает следующие типы breaking изменений:","content":"Правила Breaking Changes EasyP обнаруживает следующие типы breaking изменений:"},{"id":"cli/breaking-changes/breaking-changes::top::17","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Сравнение уровней","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Сравнение уровней"],"excerpt":"Сравнение уровней Detection Level Description EasyP Support ---------------- ------------- --------------- **WIRE** Совместимость только по wire‑формату ✅ **Full support** **WIRE+** Wire + обнаружение удалений ✅ **Curren","content":"Сравнение уровней Detection Level Description EasyP Support ---------------- ------------- --------------- **WIRE** Совместимость только по wire‑формату ✅ **Full support** **WIRE+** Wire + обнаружение удалений ✅ **Current level** **FILE** Совместимость сгенерированного кода ❌ Partial (planned)"},{"id":"cli/breaking-changes/breaking-changes::top::18","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Категории правил","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Категории правил"],"excerpt":"Категории правил Каждая категория имеет свою документацию с примерами:","content":"Категории правил Каждая категория имеет свою документацию с примерами:"},{"id":"cli/breaking-changes/breaking-changes::service-rpc::19","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"🚨 Изменения Service и RPC","path":"/docs/guide/cli/breaking-changes/breaking-changes#service-rpc","headings":["🚨 Изменения Service и RPC"],"excerpt":"🚨 Изменения Service и RPC 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 и RPC 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-field::20","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"📦 Изменения Message и Field","path":"/docs/guide/cli/breaking-changes/breaking-changes#message-field","headings":["📦 Изменения Message и Field"],"excerpt":"📦 Изменения Message и Field 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 и Field 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::21","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"🔢 Изменения Enum","path":"/docs/guide/cli/breaking-changes/breaking-changes#enum","headings":["🔢 Изменения Enum"],"excerpt":"🔢 Изменения Enum 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 val","content":"🔢 Изменения Enum 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::22","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"🔗 Изменения OneOf","path":"/docs/guide/cli/breaking-changes/breaking-changes#oneof","headings":["🔗 Изменения OneOf"],"excerpt":"🔗 Изменения OneOf Rule Description Status ------ ------------- --------- ONEOF_NO_DELETE OneOf fields cannot be deleted ✅ Implemented ONEOF_FIELD_NO_DELETE Fields within oneofs cannot be deleted ✅ Implemented ONEOF_FIEL","content":"🔗 Изменения OneOf 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::23","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"📥 Изменения Import","path":"/docs/guide/cli/breaking-changes/breaking-changes#import","headings":["📥 Изменения Import"],"excerpt":"📥 Изменения Import Rule Description Status ------ ------------- --------- IMPORT_NO_DELETE Import statements cannot be removed ✅ Implemented","content":"📥 Изменения Import Rule Description Status ------ ------------- --------- IMPORT_NO_DELETE Import statements cannot be removed ✅ Implemented"},{"id":"cli/breaking-changes/breaking-changes::top::24","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Не обнаруживается сейчас","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Не обнаруживается сейчас"],"excerpt":"Не обнаруживается сейчас Изменения ниже **НЕ детектируются** EasyP (могут ломать сгенерированный код):","content":"Не обнаруживается сейчас Изменения ниже **НЕ детектируются** EasyP (могут ломать сгенерированный код):"},{"id":"cli/breaking-changes/breaking-changes::top::25","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Не обнаруживается сейчас","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Не обнаруживается сейчас"],"excerpt":"Не обнаруживается сейчас Change Type Example Impact ------------- --------- -------- Field renaming string name = 1 → string full_name = 1 Ломает код Package changes package v1 → package v2 Меняются пути импорта File opt","content":"Не обнаруживается сейчас Change Type Example Impact ------------- --------- -------- Field renaming string name = 1 → string full_name = 1 Ломает код Package changes package v1 → package v2 Меняются пути импорта File options option go_package = \"old\" → option go_package = \"new\" Меняется расположение кода Moving between files Message перемещено в другой .proto Зависимости import'ов"},{"id":"cli/breaking-changes/breaking-changes::top::26","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Документация правил","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Документация правил"],"excerpt":"Документация правил См. подробные файлы правил для примеров и стратегий миграции:","content":"Документация правил См. подробные файлы правил для примеров и стратегий миграции:"},{"id":"cli/breaking-changes/breaking-changes::top::27","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Документация правил","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Документация правил"],"excerpt":"Документация правил Service: SERVICE_NO_DELETE, RPC_NO_DELETE, RPC_SAME_REQUEST_TYPE, RPC_SAME_RESPONSE_TYPE Message: MESSAGE_NO_DELETE, FIELD_NO_DELETE, FIELD_SAME_TYPE, FIELD_SAME_CARDINALITY Enum: ENUM_NO_DELETE, ENUM","content":"Документация правил Service: SERVICE_NO_DELETE, RPC_NO_DELETE, RPC_SAME_REQUEST_TYPE, RPC_SAME_RESPONSE_TYPE Message: MESSAGE_NO_DELETE, FIELD_NO_DELETE, FIELD_SAME_TYPE, FIELD_SAME_CARDINALITY Enum: ENUM_NO_DELETE, ENUM_VALUE_NO_DELETE, ENUM_VALUE_SAME_NAME OneOf: ONEOF_NO_DELETE, ONEOF_FIELD_NO_DELETE, ONEOF_FIELD_SAME_TYPE Import: IMPORT_NO_DELETE"},{"id":"cli/breaking-changes/breaking-changes::top::28","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Документация правил","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Документация правил"],"excerpt":"Документация правил Каждое правило содержит: ❌ Плохие примеры (breaking) ✅ Безопасные альтернативы 🔧 Стратегии миграции 📋 Реальные сообщения ошибок из EasyP","content":"Документация правил Каждое правило содержит: ❌ Плохие примеры (breaking) ✅ Безопасные альтернативы 🔧 Стратегии миграции 📋 Реальные сообщения ошибок из EasyP"},{"id":"cli/breaking-changes/breaking-changes::top::29","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"✅ Безопасные изменения (разрешены всегда)","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["✅ Безопасные изменения (разрешены всегда)"],"excerpt":"✅ Безопасные изменения (разрешены всегда) ```proto // Добавление новых элементов — безопасно message User { string name = 1; string email = 2; string phone = 3; // ✅ Новое поле }","content":"✅ Безопасные изменения (разрешены всегда) ```proto // Добавление новых элементов — безопасно message User { string name = 1; string email = 2; string phone = 3; // ✅ Новое поле }"},{"id":"cli/breaking-changes/breaking-changes::top::30","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"✅ Безопасные изменения (разрешены всегда)","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["✅ Безопасные изменения (разрешены всегда)"],"excerpt":"✅ Безопасные изменения (разрешены всегда) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc GetUserProfile(GetUserRequest) returns (UserProfile); // ✅ Новый RPC }","content":"✅ Безопасные изменения (разрешены всегда) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc GetUserProfile(GetUserRequest) returns (UserProfile); // ✅ Новый RPC }"},{"id":"cli/breaking-changes/breaking-changes::top::31","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"✅ Безопасные изменения (разрешены всегда)","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["✅ Безопасные изменения (разрешены всегда)"],"excerpt":"✅ Безопасные изменения (разрешены всегда) enum Status { STATUS_UNSPECIFIED = 0; STATUS_ACTIVE = 1; STATUS_PENDING = 2; // ✅ Новое enum значение } ```","content":"✅ Безопасные изменения (разрешены всегда) enum Status { STATUS_UNSPECIFIED = 0; STATUS_ACTIVE = 1; STATUS_PENDING = 2; // ✅ Новое enum значение } ```"},{"id":"cli/breaking-changes/breaking-changes::top::32","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"❌ Несовместимые изменения (обнаруживаются всегда)","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["❌ Несовместимые изменения (обнаруживаются всегда)"],"excerpt":"❌ Несовместимые изменения (обнаруживаются всегда) ```proto // Удаления и смена типов ломают совместимость message User { string name = 1; // ❌ Удалённое поле }","content":"❌ Несовместимые изменения (обнаруживаются всегда) ```proto // Удаления и смена типов ломают совместимость message User { string name = 1; // ❌ Удалённое поле }"},{"id":"cli/breaking-changes/breaking-changes::top::33","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"❌ Несовместимые изменения (обнаруживаются всегда)","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["❌ Несовместимые изменения (обнаруживаются всегда)"],"excerpt":"❌ Несовместимые изменения (обнаруживаются всегда) service UserService { // ❌ Удалённый RPC метод rpc GetUser(GetUserRequestV2) returns (GetUserResponse); // ❌ Изменён тип запроса } ```","content":"❌ Несовместимые изменения (обнаруживаются всегда) service UserService { // ❌ Удалённый RPC метод rpc GetUser(GetUserRequestV2) returns (GetUserResponse); // ❌ Изменён тип запроса } ```"},{"id":"cli/breaking-changes/breaking-changes::top::34","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Сценарий: Изменения пока не детектируются","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Сценарий: Изменения пока не детектируются"],"excerpt":"Сценарий: Изменения пока не детектируются ```proto // 🟡 Ломает сгенерированный код, но проходит проверки EasyP message User { string user_name = 1; // Переименовано с \"name\" string user_email = 2; // Переименовано с \"em","content":"Сценарий: Изменения пока не детектируются ```proto // 🟡 Ломает сгенерированный код, но проходит проверки EasyP message User { string user_name = 1; // Переименовано с \"name\" string user_email = 2; // Переименовано с \"email\" }"},{"id":"cli/breaking-changes/breaking-changes::top::35","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Сценарий: Изменения пока не детектируются","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Сценарий: Изменения пока не детектируются"],"excerpt":"Сценарий: Изменения пока не детектируются service UserService { rpc GetUserProfile(GetUserRequest) returns (GetUserResponse); // Переименовано с GetUser } ```","content":"Сценарий: Изменения пока не детектируются service UserService { rpc GetUserProfile(GetUserRequest) returns (GetUserResponse); // Переименовано с GetUser } ```"},{"id":"cli/breaking-changes/breaking-changes::top::36","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Текстовый формат (по умолчанию)","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Текстовый формат (по умолчанию)"],"excerpt":"Текстовый формат (по умолчанию)","content":"Текстовый формат (по умолчанию)"},{"id":"cli/breaking-changes/breaking-changes::1::37","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"1. Регулярный запуск","path":"/docs/guide/cli/breaking-changes/breaking-changes#1","headings":["1. Регулярный запуск"],"excerpt":"Регулярный запуск Добавьте проверку несовместимых изменений в CI/CD:","content":"Регулярный запуск Добавьте проверку несовместимых изменений в CI/CD:"},{"id":"cli/breaking-changes/breaking-changes::2::38","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"2. Защита веток","path":"/docs/guide/cli/breaking-changes/breaking-changes#2","headings":["2. Защита веток"],"excerpt":"Защита веток Блокируйте слияния с breaking изменениями:","content":"Защита веток Блокируйте слияния с breaking изменениями:"},{"id":"cli/breaking-changes/breaking-changes::3::39","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"3. Стратегия версионирования","path":"/docs/guide/cli/breaking-changes/breaking-changes#3","headings":["3. Стратегия версионирования"],"excerpt":"Стратегия версионирования При необходимости breaking изменений: Создайте новую версию пакета (myservice.v2) Поддерживайте старую версию в период миграции Добавляйте уведомления о деприкации","content":"Стратегия версионирования При необходимости breaking изменений: Создайте новую версию пакета (myservice.v2) Поддерживайте старую версию в период миграции Добавляйте уведомления о деприкации"},{"id":"cli/breaking-changes/breaking-changes::4::40","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"4. Игнорирование путей","path":"/docs/guide/cli/breaking-changes/breaking-changes#4","headings":["4. Игнорирование путей"],"excerpt":"Игнорирование путей Используйте ignore осознанно:","content":"Игнорирование путей Используйте ignore осознанно:"},{"id":"cli/breaking-changes/breaking-changes::repository-does-not-exist::41","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Проблема: \"Repository does not exist\"","path":"/docs/guide/cli/breaking-changes/breaking-changes#repository-does-not-exist","headings":["Проблема: \"Repository does not exist\""],"excerpt":"Проблема: \"Repository does not exist\" Решение: Выполняйте команду внутри Git репозитория с нужной веткой.","content":"Проблема: \"Repository does not exist\" Решение: Выполняйте команду внутри Git репозитория с нужной веткой."},{"id":"cli/breaking-changes/breaking-changes::cannot-find-git-ref::42","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Проблема: \"Cannot find git ref\"","path":"/docs/guide/cli/breaking-changes/breaking-changes#cannot-find-git-ref","headings":["Проблема: \"Cannot find git ref\""],"excerpt":"Проблема: \"Cannot find git ref\" Решение: Проверьте наличие ссылки:","content":"Проблема: \"Cannot find git ref\" Решение: Проверьте наличие ссылки:"},{"id":"cli/breaking-changes/breaking-changes::top::43","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Проблема: Ложные срабатывания на сгенерированный код","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Проблема: Ложные срабатывания на сгенерированный код"],"excerpt":"Проблема: Ложные срабатывания на сгенерированный код Решение: Исключите директории генерации:","content":"Проблема: Ложные срабатывания на сгенерированный код Решение: Исключите директории генерации:"},{"id":"cli/breaking-changes/breaking-changes::top::44","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Проблема: Очень много изменений","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Проблема: Очень много изменений"],"excerpt":"Проблема: Очень много изменений Решение: Создайте новую версию API Вносите изменения постепенно Используйте feature flags","content":"Проблема: Очень много изменений Решение: Создайте новую версию API Вносите изменения постепенно Используйте feature flags"},{"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 - name: Install EasyP run: curl -sSfL https://raw.githubusercontent.com/easyp-tech/easyp/main/install.","content":"GitHub Actions jobs: breaking-changes: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 with: fetch-depth: 0 - 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-pre-push-hook::48","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Pre-commit / pre-push hook","path":"/docs/guide/cli/breaking-changes/breaking-changes#pre-commit-pre-push-hook","headings":["Pre-commit / pre-push hook"],"excerpt":"Pre-commit / pre-push hook ```bash #!/bin/sh .git/hooks/pre-push","content":"Pre-commit / pre-push hook ```bash #!/bin/sh .git/hooks/pre-push"},{"id":"cli/breaking-changes/breaking-changes::pre-commit-pre-push-hook::49","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Pre-commit / pre-push hook","path":"/docs/guide/cli/breaking-changes/breaking-changes#pre-commit-pre-push-hook","headings":["Pre-commit / pre-push hook"],"excerpt":"Pre-commit / pre-push hook protected_branch='main' current_branch=$(git symbolic-ref HEAD sed -e 's,.*/\\(.*\\),\\1,')","content":"Pre-commit / pre-push hook protected_branch='main' current_branch=$(git symbolic-ref HEAD sed -e 's,.*/\\(.*\\),\\1,')"},{"id":"cli/breaking-changes/breaking-changes::pre-commit-pre-push-hook::50","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Pre-commit / pre-push hook","path":"/docs/guide/cli/breaking-changes/breaking-changes#pre-commit-pre-push-hook","headings":["Pre-commit / pre-push hook"],"excerpt":"Pre-commit / pre-push 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.","content":"Pre-commit / pre-push 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::top::51","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Режим отладки","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Режим отладки"],"excerpt":"Режим отладки Включите debug‑логирование:","content":"Режим отладки Включите debug‑логирование:"},{"id":"cli/breaking-changes/breaking-changes::top::52","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Ручное сравнение","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Ручное сравнение"],"excerpt":"Ручное сравнение Для сложных случаев:","content":"Ручное сравнение Для сложных случаев:"},{"id":"cli/breaking-changes/breaking-changes::top::53","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Оптимизация производительности","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Оптимизация производительности"],"excerpt":"Оптимизация производительности Ограничьте область:","content":"Оптимизация производительности Ограничьте область:"},{"id":"cli/breaking-changes/breaking-changes::top::54","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Оптимизация производительности","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Оптимизация производительности"],"excerpt":"Оптимизация производительности","content":"Оптимизация производительности"},{"id":"cli/breaking-changes/breaking-changes::top::55","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Оптимизация производительности","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Оптимизация производительности"],"excerpt":"Оптимизация производительности Механизм обнаружения несовместимых изменений в EasyP обеспечивает надёжную основу для безопасной эволюции protobuf‑схем при сохранении совместимости API.","content":"Оптимизация производительности Механизм обнаружения несовместимых изменений в EasyP обеспечивает надёжную основу для безопасной эволюции protobuf‑схем при сохранении совместимости API."},{"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":"Это правило проверяет, что ни один enum не был удалён из proto‑файлов. Удаление enum ломает совместимость по wire‑формату и сгенерированный код: сохранённые данные могут содержать удалённые значения, а клиентский код опи","content":"Это правило проверяет, что ни один enum не был удалён из proto‑файлов. Удаление enum ломает совместимость по wire‑формату и сгенерированный код: сохранённые данные могут содержать удалённые значения, а клиентский код опирается на сгенерированные типы и константы enum."},{"id":"cli/breaking-changes/rules/enum-no-delete::breaking::1","title":"ENUM_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-no-delete::breaking::2","title":"ENUM_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/enum-no-delete::breaking::3","title":"ENUM_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_CONFIRMED = 2; ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_DELIVERED = 4; }","content":"Плохой (Breaking) 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::breaking::4","title":"ENUM_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) enum UserRole { // [!code --] USER_ROLE_UNSPECIFIED = 0; // [!code --] USER_ROLE_ADMIN = 1; // [!code --] USER_ROLE_USER = 2; // [!code --] } // [!code --]","content":"Плохой (Breaking) 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::breaking::5","title":"ENUM_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message Order { string id = 1; OrderStatus status = 2; UserRole created_by_role = 3; } ```","content":"Плохой (Breaking) message Order { string id = 1; OrderStatus status = 2; UserRole created_by_role = 3; } ```"},{"id":"cli/breaking-changes/rules/enum-no-delete::breaking::6","title":"ENUM_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-no-delete::breaking::7","title":"ENUM_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/enum-no-delete::breaking::8","title":"ENUM_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_CONFIRMED = 2; ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_DELIVERED = 4; }","content":"Плохой (Breaking) 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::breaking::9","title":"ENUM_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) // UserRole enum удалён — BREAKING CHANGE!","content":"Плохой (Breaking) // UserRole enum удалён — BREAKING CHANGE!"},{"id":"cli/breaking-changes/rules/enum-no-delete::breaking::10","title":"ENUM_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message Order { string id = 1; OrderStatus status = 2; UserRole created_by_role = 3; // ERROR: UserRole больше не существует } ```","content":"Плохой (Breaking) message Order { string id = 1; OrderStatus status = 2; UserRole created_by_role = 3; // ERROR: UserRole больше не существует } ```"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::11","title":"ENUM_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры **Удаление вложенного enum:** ```proto // Before message User { string name = 1; Status status = 2; enum Status { // [!code --] STATUS_UNSPECIFIED = 0; // [!code --] STATUS_ACTIVE = 1; // [!code --","content":"Дополнительные примеры **Удаление вложенного enum:** ```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::top::12","title":"ENUM_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры // After - BREAKING CHANGE! message User { string name = 1; Status status = 2; // ERROR: Status удалён // Вложенный enum Status удалён } ```","content":"Дополнительные примеры // After - BREAKING CHANGE! message User { string name = 1; Status status = 2; // ERROR: Status удалён // Вложенный enum Status удалён } ```"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::13","title":"ENUM_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо удаления — пометить enum deprecated:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо удаления — пометить enum deprecated:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::14","title":"ENUM_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::15","title":"ENUM_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_CONFIRMED = 2; ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_DELIVERED = 4; }","content":"Хороший (Безопасный) 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::top::16","title":"ENUM_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) enum UserRole { option deprecated = true; // [!code focus] USER_ROLE_UNSPECIFIED = 0; USER_ROLE_ADMIN = 1; USER_ROLE_USER = 2; }","content":"Хороший (Безопасный) 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::top::17","title":"ENUM_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message Order { string id = 1; OrderStatus status = 2; UserRole created_by_role = 3 [deprecated = true]; // [!code focus] } ```","content":"Хороший (Безопасный) 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::top::18","title":"ENUM_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Или заменить новым enum:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Или заменить новым enum:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::19","title":"ENUM_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::20","title":"ENUM_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_CONFIRMED = 2; ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_DELIVERED = 4; }","content":"Хороший (Безопасный) 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::top::21","title":"ENUM_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) enum UserRole { option deprecated = true; // [!code focus] // Старый enum USER_ROLE_UNSPECIFIED = 0; USER_ROLE_ADMIN = 1; USER_ROLE_USER = 2; }","content":"Хороший (Безопасный) enum UserRole { option deprecated = true; // [!code focus] // Старый enum USER_ROLE_UNSPECIFIED = 0; USER_ROLE_ADMIN = 1; USER_ROLE_USER = 2; }"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::22","title":"ENUM_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) enum UserPermission { // [!code focus] // Новый enum USER_PERMISSION_UNSPECIFIED = 0; // [!code focus] USER_PERMISSION_READ = 1; // [!code focus] USER_PERMISSION_WRITE = 2; // [!code focus] USER_PERM","content":"Хороший (Безопасный) enum UserPermission { // [!code focus] // Новый enum 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::top::23","title":"ENUM_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message Order { string id = 1; OrderStatus status = 2; UserRole created_by_role = 3 [deprecated = true]; // [!code focus] UserPermission created_by_permission = 4; // [!code focus] } ```","content":"Хороший (Безопасный) message Order { string id = 1; OrderStatus status = 2; UserRole created_by_role = 3 [deprecated = true]; // [!code focus] UserPermission created_by_permission = 4; // [!code focus] } ```"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::24","title":"ENUM_NO_DELETE","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Влияние"],"excerpt":"Влияние **Wire Format:** Данные с удалённым enum не десериализуются корректно **Generated Code:** Тип и константы удаляются — компиляция клиентов ломается **Field References:** Поля с типом удалённого enum становятся нев","content":"Влияние **Wire Format:** Данные с удалённым enum не десериализуются корректно **Generated Code:** Тип и константы удаляются — компиляция клиентов ломается **Field References:** Поля с типом удалённого enum становятся невалидны **Switch Statements:** switch по enum ломается (неизвестные кейсы)"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::25","title":"ENUM_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Код клиента ломается:** ```go // Before order := &myapi.Order{ Id: \"order123\", Status: myapi.OrderStatus_ORDER_STATUS_PENDING, CreatedByRole: myapi.UserRole_USER_ROLE_ADMIN, // ERROR после удаления }","content":"Реальный пример **Код клиента ломается:** ```go // Before order := &myapi.Order{ Id: \"order123\", Status: myapi.OrderStatus_ORDER_STATUS_PENDING, CreatedByRole: myapi.UserRole_USER_ROLE_ADMIN, // ERROR после удаления }"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::26","title":"ENUM_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример switch order.CreatedByRole { case myapi.UserRole_USER_ROLE_ADMIN: // ERROR // Admin logic case myapi.UserRole_USER_ROLE_USER: // ERROR // User logic }","content":"Реальный пример switch order.CreatedByRole { case myapi.UserRole_USER_ROLE_ADMIN: // ERROR // Admin logic case myapi.UserRole_USER_ROLE_USER: // ERROR // User logic }"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::27","title":"ENUM_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример // undefined: myapi.UserRole // undefined: myapi.UserRole_USER_ROLE_ADMIN ```","content":"Реальный пример // undefined: myapi.UserRole // undefined: myapi.UserRole_USER_ROLE_ADMIN ```"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::28","title":"ENUM_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Старые данные становятся нечитаемыми:**","content":"Реальный пример **Старые данные становятся нечитаемыми:**"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::29","title":"ENUM_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Серверная логика ломается:**","content":"Реальный пример **Серверная логика ломается:**"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::30","title":"ENUM_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Депрецируйте enum:** **Пометьте поля со старым enum deprecated:** **Создайте новый enum:** **Сервер обрабатывает оба:** **Удалите старый enum в следующей major‑версии.**","content":"Стратегия миграции **Депрецируйте enum:** **Пометьте поля со старым enum deprecated:** **Создайте новый enum:** **Сервер обрабатывает оба:** **Удалите старый enum в следующей major‑версии.**"},{"id":"cli/breaking-changes/rules/enum-no-delete::enum::31","title":"ENUM_NO_DELETE","section":"Редизайн enum","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#enum","headings":["Редизайн enum"],"excerpt":"Редизайн enum ```proto enum Priority { option deprecated = true; PRIORITY_UNSPECIFIED = 0; PRIORITY_LOW = 1; PRIORITY_HIGH = 2; }","content":"Редизайн enum ```proto enum Priority { option deprecated = true; PRIORITY_UNSPECIFIED = 0; PRIORITY_LOW = 1; PRIORITY_HIGH = 2; }"},{"id":"cli/breaking-changes/rules/enum-no-delete::enum::32","title":"ENUM_NO_DELETE","section":"Редизайн enum","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#enum","headings":["Редизайн enum"],"excerpt":"Редизайн enum enum TaskPriority { TASK_PRIORITY_UNSPECIFIED = 0; TASK_PRIORITY_LOW = 1; TASK_PRIORITY_MEDIUM = 2; TASK_PRIORITY_HIGH = 3; TASK_PRIORITY_URGENT = 4; } ```","content":"Редизайн enum enum TaskPriority { 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::enum::33","title":"ENUM_NO_DELETE","section":"Консолидация enum","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#enum","headings":["Консолидация enum"],"excerpt":"Консолидация enum ```proto enum Status { option deprecated = true; STATUS_UNSPECIFIED = 0; STATUS_ACTIVE = 1; }","content":"Консолидация enum ```proto enum Status { option deprecated = true; STATUS_UNSPECIFIED = 0; STATUS_ACTIVE = 1; }"},{"id":"cli/breaking-changes/rules/enum-no-delete::enum::34","title":"ENUM_NO_DELETE","section":"Консолидация enum","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#enum","headings":["Консолидация enum"],"excerpt":"Консолидация enum enum State { option deprecated = true; STATE_UNSPECIFIED = 0; STATE_ENABLED = 1; }","content":"Консолидация enum enum State { option deprecated = true; STATE_UNSPECIFIED = 0; STATE_ENABLED = 1; }"},{"id":"cli/breaking-changes/rules/enum-no-delete::enum::35","title":"ENUM_NO_DELETE","section":"Консолидация enum","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#enum","headings":["Консолидация enum"],"excerpt":"Консолидация enum enum EntityStatus { ENTITY_STATUS_UNSPECIFIED = 0; ENTITY_STATUS_ACTIVE = 1; ENTITY_STATUS_INACTIVE = 2; ENTITY_STATUS_ENABLED = 3; ENTITY_STATUS_DISABLED = 4; } ```","content":"Консолидация enum enum EntityStatus { 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::enum::36","title":"ENUM_NO_DELETE","section":"Перемещение enum в новый пакет","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#enum","headings":["Перемещение enum в новый пакет"],"excerpt":"Перемещение enum в новый пакет ```proto enum UserRole { option deprecated = true; USER_ROLE_UNSPECIFIED = 0; USER_ROLE_ADMIN = 1; }","content":"Перемещение enum в новый пакет ```proto enum UserRole { option deprecated = true; USER_ROLE_UNSPECIFIED = 0; USER_ROLE_ADMIN = 1; }"},{"id":"cli/breaking-changes/rules/enum-no-delete::enum::37","title":"ENUM_NO_DELETE","section":"Перемещение enum в новый пакет","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#enum","headings":["Перемещение enum в новый пакет"],"excerpt":"Перемещение enum в новый пакет import \"common/roles.proto\";","content":"Перемещение enum в новый пакет import \"common/roles.proto\";"},{"id":"cli/breaking-changes/rules/enum-no-delete::enum::38","title":"ENUM_NO_DELETE","section":"Перемещение enum в новый пакет","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#enum","headings":["Перемещение enum в новый пакет"],"excerpt":"Перемещение enum в новый пакет message Order { UserRole old_role = 3 [deprecated = true]; common.UserRole new_role = 4; } ```","content":"Перемещение enum в новый пакет message Order { UserRole old_role = 3 [deprecated = true]; common.UserRole new_role = 4; } ```"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::39","title":"ENUM_NO_DELETE","section":"Версионирование / новая версия пакета","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Версионирование / новая версия пакета"],"excerpt":"Версионирование / новая версия пакета ```proto package myapi.v2;","content":"Версионирование / новая версия пакета ```proto package myapi.v2;"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::40","title":"ENUM_NO_DELETE","section":"Версионирование / новая версия пакета","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Версионирование / новая версия пакета"],"excerpt":"Версионирование / новая версия пакета enum UserPermission { USER_PERMISSION_UNSPECIFIED = 0; USER_PERMISSION_READ = 1; USER_PERMISSION_WRITE = 2; USER_PERMISSION_ADMIN = 3; }","content":"Версионирование / новая версия пакета 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::top::41","title":"ENUM_NO_DELETE","section":"Версионирование / новая версия пакета","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Версионирование / новая версия пакета"],"excerpt":"Версионирование / новая версия пакета message Order { string id = 1; UserPermission created_by_permission = 2; } ```","content":"Версионирование / новая версия пакета message Order { string id = 1; UserPermission created_by_permission = 2; } ```"},{"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":"Правило проверяет, что ни одно значение enum (enum value) не было удалено. Удаление значения ломает совместимость по wire‑формату и сгенерированный код: в уже сохранённых данных могут присутствовать удалённые значения, а","content":"Правило проверяет, что ни одно значение enum (enum value) не было удалено. Удаление значения ломает совместимость по wire‑формату и сгенерированный код: в уже сохранённых данных могут присутствовать удалённые значения, а клиентский код может ссылаться на соответствующие константы."},{"id":"cli/breaking-changes/rules/enum-value-no-delete::breaking::1","title":"ENUM_VALUE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::breaking::2","title":"ENUM_VALUE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::breaking::3","title":"ENUM_VALUE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) 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":"Плохой (Breaking) 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::breaking::4","title":"ENUM_VALUE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) enum Priority { PRIORITY_UNSPECIFIED = 0; PRIORITY_LOW = 1; PRIORITY_MEDIUM = 2; PRIORITY_HIGH = 3; PRIORITY_URGENT = 4; } ```","content":"Плохой (Breaking) 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::breaking::5","title":"ENUM_VALUE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::breaking::6","title":"ENUM_VALUE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::breaking::7","title":"ENUM_VALUE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) 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 --] ","content":"Плохой (Breaking) 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 --] Удалено значение enum — BREAKING! }"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::breaking::8","title":"ENUM_VALUE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) enum Priority { PRIORITY_UNSPECIFIED = 0; PRIORITY_LOW = 1; PRIORITY_MEDIUM = 2; PRIORITY_HIGH = 3; // PRIORITY_URGENT = 4; // [!code --] Удалено значение enum — BREAKING! } ```","content":"Плохой (Breaking) enum Priority { PRIORITY_UNSPECIFIED = 0; PRIORITY_LOW = 1; PRIORITY_MEDIUM = 2; PRIORITY_HIGH = 3; // PRIORITY_URGENT = 4; // [!code --] Удалено значение enum — BREAKING! } ```"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::9","title":"ENUM_VALUE_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры **Множественное удаление значений:** ```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_S","content":"Дополнительные примеры **Множественное удаление значений:** ```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::top::10","title":"ENUM_VALUE_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры // 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","content":"Дополнительные примеры // 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::top::11","title":"ENUM_VALUE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо удаления — пометить значения deprecated:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо удаления — пометить значения deprecated:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::12","title":"ENUM_VALUE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::13","title":"ENUM_VALUE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) 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 = t","content":"Хороший (Безопасный) 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::top::14","title":"ENUM_VALUE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) enum Priority { PRIORITY_UNSPECIFIED = 0; PRIORITY_LOW = 1; PRIORITY_MEDIUM = 2; PRIORITY_HIGH = 3; PRIORITY_URGENT = 4 [deprecated = true]; // [!code focus] } ```","content":"Хороший (Безопасный) 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::top::15","title":"ENUM_VALUE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Или зарезервировать номер и имя после удаления:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Или зарезервировать номер и имя после удаления:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::16","title":"ENUM_VALUE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::17","title":"ENUM_VALUE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) enum OrderStatus { reserved 5; // [!code focus] reserved \"ORDER_STATUS_CANCELLED\"; // [!code focus]","content":"Хороший (Безопасный) enum OrderStatus { reserved 5; // [!code focus] reserved \"ORDER_STATUS_CANCELLED\"; // [!code focus]"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::18","title":"ENUM_VALUE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_CONFIRMED = 2; ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_DELIVERED = 4; }","content":"Хороший (Безопасный) 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::top::19","title":"ENUM_VALUE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) enum Priority { reserved 4; // [!code focus] reserved \"PRIORITY_URGENT\"; // [!code focus]","content":"Хороший (Безопасный) enum Priority { reserved 4; // [!code focus] reserved \"PRIORITY_URGENT\"; // [!code focus]"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::20","title":"ENUM_VALUE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) PRIORITY_UNSPECIFIED = 0; PRIORITY_LOW = 1; PRIORITY_MEDIUM = 2; PRIORITY_HIGH = 3; } ```","content":"Хороший (Безопасный) PRIORITY_UNSPECIFIED = 0; PRIORITY_LOW = 1; PRIORITY_MEDIUM = 2; PRIORITY_HIGH = 3; } ```"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::21","title":"ENUM_VALUE_NO_DELETE","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Влияние"],"excerpt":"Влияние **Wire Format:** Данные с удалёнными значениями не десериализуются корректно **Generated Code:** Константы исчезают — клиентский код не компилируется **Client Applications:** Ссылки на удалённые значения вызывают","content":"Влияние **Wire Format:** Данные с удалёнными значениями не десериализуются корректно **Generated Code:** Константы исчезают — клиентский код не компилируется **Client Applications:** Ссылки на удалённые значения вызывают ошибки компиляции **Switch Statements:** switch по enum ломается (неизвестные case) **Default Handling:** Поведение при неизвестных значениях меняется"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::22","title":"ENUM_VALUE_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Код клиента ломается:** ```go order := &myapi.Order{ Status: myapi.OrderStatus_ORDER_STATUS_CANCELLED, // ERROR после удаления }","content":"Реальный пример **Код клиента ломается:** ```go order := &myapi.Order{ Status: myapi.OrderStatus_ORDER_STATUS_CANCELLED, // ERROR после удаления }"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::23","title":"ENUM_VALUE_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример switch order.Status { case myapi.OrderStatus_ORDER_STATUS_PENDING: // Pending case myapi.OrderStatus_ORDER_STATUS_CANCELLED: // ERROR: undefined // Cancellation default: // Unknown } // undefined: myapi.O","content":"Реальный пример switch order.Status { case myapi.OrderStatus_ORDER_STATUS_PENDING: // Pending case myapi.OrderStatus_ORDER_STATUS_CANCELLED: // ERROR: undefined // Cancellation default: // Unknown } // undefined: myapi.OrderStatus_ORDER_STATUS_CANCELLED ```"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::24","title":"ENUM_VALUE_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Проблемы с уже сохранёнными данными:**","content":"Реальный пример **Проблемы с уже сохранёнными данными:**"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::25","title":"ENUM_VALUE_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Валидация на сервере:** ```go func validateOrderStatus(status OrderStatus) error { switch status { case OrderStatus_ORDER_STATUS_PENDING, OrderStatus_ORDER_STATUS_CONFIRMED, OrderStatus_ORDER_STATUS_SHI","content":"Реальный пример **Валидация на сервере:** ```go 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 после удаления return nil default: return errors.New(\"invalid order status\") } }"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::26","title":"ENUM_VALUE_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример func canModifyOrder(order *Order) bool { return order.Status != OrderStatus_ORDER_STATUS_CANCELLED // ERROR } ```","content":"Реальный пример func canModifyOrder(order *Order) bool { return order.Status != OrderStatus_ORDER_STATUS_CANCELLED // ERROR } ```"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::27","title":"ENUM_VALUE_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Сначала пометить deprecated:** **Перестать использовать deprecated значение в новом коде:** **Обработка legacy в клиенте:** **Резервирование после миграции:** **Никогда не переиспользовать номера** —","content":"Стратегия миграции **Сначала пометить deprecated:** **Перестать использовать deprecated значение в новом коде:** **Обработка legacy в клиенте:** **Резервирование после миграции:** **Никогда не переиспользовать номера** — зарезервированы навсегда."},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::28","title":"ENUM_VALUE_NO_DELETE","section":"Предотвращение переиспользования номера","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Предотвращение переиспользования номера"],"excerpt":"Предотвращение переиспользования номера ```proto enum Status { reserved 2; reserved \"STATUS_DELETED\";","content":"Предотвращение переиспользования номера ```proto enum Status { reserved 2; reserved \"STATUS_DELETED\";"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::29","title":"ENUM_VALUE_NO_DELETE","section":"Предотвращение переиспользования номера","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Предотвращение переиспользования номера"],"excerpt":"Предотвращение переиспользования номера STATUS_UNSPECIFIED = 0; STATUS_ACTIVE = 1; STATUS_INACTIVE = 3; // STATUS_DELETED = 2; // Не переиспользуем } ```","content":"Предотвращение переиспользования номера STATUS_UNSPECIFIED = 0; STATUS_ACTIVE = 1; STATUS_INACTIVE = 3; // STATUS_DELETED = 2; // Не переиспользуем } ```"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::json::30","title":"ENUM_VALUE_NO_DELETE","section":"JSON совместимость","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#json","headings":["JSON совместимость"],"excerpt":"JSON совместимость ```proto enum Color { reserved 2; reserved \"RED\";","content":"JSON совместимость ```proto enum Color { reserved 2; reserved \"RED\";"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::json::31","title":"ENUM_VALUE_NO_DELETE","section":"JSON совместимость","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#json","headings":["JSON совместимость"],"excerpt":"JSON совместимость COLOR_UNSPECIFIED = 0; COLOR_BLUE = 1; COLOR_GREEN = 3; // COLOR_RED = 2; // Был удалён } ```","content":"JSON совместимость COLOR_UNSPECIFIED = 0; COLOR_BLUE = 1; COLOR_GREEN = 3; // COLOR_RED = 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":"Это правило проверяет, что имя enum значения для каждого номера (number) не изменилось. Переименование enum значения при сохранении его номера ломает совместимость JSON и сгенерированный код: клиенты ожидают конкретные и","content":"Это правило проверяет, что имя enum значения для каждого номера (number) не изменилось. Переименование enum значения при сохранении его номера ломает совместимость JSON и сгенерированный код: клиенты ожидают конкретные имена констант."},{"id":"cli/breaking-changes/rules/enum-value-same-name::breaking::1","title":"ENUM_VALUE_SAME_NAME","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-value-same-name::breaking::2","title":"ENUM_VALUE_SAME_NAME","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/enum-value-same-name::breaking::3","title":"ENUM_VALUE_SAME_NAME","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_CONFIRMED = 2; ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_DELIVERED = 4; } ```","content":"Плохой (Breaking) 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::breaking::4","title":"ENUM_VALUE_SAME_NAME","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-value-same-name::breaking::5","title":"ENUM_VALUE_SAME_NAME","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/enum-value-same-name::breaking::6","title":"ENUM_VALUE_SAME_NAME","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_APPROVED = 2; // [!code --] Было ORDER_STATUS_CONFIRMED ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_COMPLETED = 4; // [","content":"Плохой (Breaking) enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_APPROVED = 2; // [!code --] Было ORDER_STATUS_CONFIRMED ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_COMPLETED = 4; // [!code --] Было ORDER_STATUS_DELIVERED } ```"},{"id":"cli/breaking-changes/rules/enum-value-same-name::top::7","title":"ENUM_VALUE_SAME_NAME","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры **Множественные переименования:** ```proto // Before enum UserRole { USER_ROLE_UNSPECIFIED = 0; USER_ROLE_ADMIN = 1; USER_ROLE_MODERATOR = 2; USER_ROLE_USER = 3; }","content":"Дополнительные примеры **Множественные переименования:** ```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::top::8","title":"ENUM_VALUE_SAME_NAME","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры // After - ВСЁ BREAKING enum UserRole { USER_ROLE_UNSPECIFIED = 0; USER_ROLE_ADMINISTRATOR = 1; // BREAKING: ADMIN -> ADMINISTRATOR USER_ROLE_MOD = 2; // BREAKING: MODERATOR -> MOD USER_ROLE_MEMBER","content":"Дополнительные примеры // After - ВСЁ BREAKING 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::top::9","title":"ENUM_VALUE_SAME_NAME","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо переименования — добавить новые значения и пометить старые deprecated:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо переименования — добавить новые значения и пометить старые deprecated:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-value-same-name::top::10","title":"ENUM_VALUE_SAME_NAME","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/enum-value-same-name::top::11","title":"ENUM_VALUE_SAME_NAME","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) 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 [depre","content":"Хороший (Безопасный) 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] // Новое значение вместо переименования ORDER_STATUS_COMPLETED = 6; // [!code focus] } ```"},{"id":"cli/breaking-changes/rules/enum-value-same-name::top::12","title":"ENUM_VALUE_SAME_NAME","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Или создать новую версию enum:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Или создать новую версию enum:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-value-same-name::top::13","title":"ENUM_VALUE_SAME_NAME","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v2; // [!code focus]","content":"Хороший (Безопасный) package myapi.v2; // [!code focus]"},{"id":"cli/breaking-changes/rules/enum-value-same-name::top::14","title":"ENUM_VALUE_SAME_NAME","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_APPROVED = 2; // [!code focus] // «Чистые» имена в v2 ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_COMPLETED = 4; // ","content":"Хороший (Безопасный) enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_APPROVED = 2; // [!code focus] // «Чистые» имена в v2 ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_COMPLETED = 4; // [!code focus] } ```"},{"id":"cli/breaking-changes/rules/enum-value-same-name::top::15","title":"ENUM_VALUE_SAME_NAME","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Влияние"],"excerpt":"Влияние **Generated Code:** Меняются имена констант — компиляция клиентов ломается **JSON Compatibility:** JSON использует имена enum — старые документы не парсятся **Client Applications:** Код со старым именем константы","content":"Влияние **Generated Code:** Меняются имена констант — компиляция клиентов ломается **JSON Compatibility:** JSON использует имена enum — старые документы не парсятся **Client Applications:** Код со старым именем константы не компилируется **Documentation:** Документация устаревает с неправильными именами"},{"id":"cli/breaking-changes/rules/enum-value-same-name::top::16","title":"ENUM_VALUE_SAME_NAME","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Реальный пример"],"excerpt":"Реальный пример **Ломается код клиента:** ```go // Before status := myapi.OrderStatus_ORDER_STATUS_CONFIRMED if order.Status == myapi.OrderStatus_ORDER_STATUS_DELIVERED { // handle delivery }","content":"Реальный пример **Ломается код клиента:** ```go // Before 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::top::17","title":"ENUM_VALUE_SAME_NAME","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Реальный пример"],"excerpt":"Реальный пример // After (переименовано) — ошибки компиляции status := myapi.OrderStatus_ORDER_STATUS_CONFIRMED // ERROR: undefined if order.Status == myapi.OrderStatus_ORDER_STATUS_DELIVERED { // ERROR: undefined // han","content":"Реальный пример // After (переименовано) — ошибки компиляции status := myapi.OrderStatus_ORDER_STATUS_CONFIRMED // ERROR: undefined if order.Status == myapi.OrderStatus_ORDER_STATUS_DELIVERED { // ERROR: undefined // handle delivery } ```"},{"id":"cli/breaking-changes/rules/enum-value-same-name::top::18","title":"ENUM_VALUE_SAME_NAME","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Реальный пример"],"excerpt":"Реальный пример **JSON совместимость ломается:** ```json // Раньше { \"status\": \"ORDER_STATUS_CONFIRMED\" }","content":"Реальный пример **JSON совместимость ломается:** ```json // Раньше { \"status\": \"ORDER_STATUS_CONFIRMED\" }"},{"id":"cli/breaking-changes/rules/enum-value-same-name::top::19","title":"ENUM_VALUE_SAME_NAME","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Реальный пример"],"excerpt":"Реальный пример // После { \"status\": \"ORDER_STATUS_APPROVED\" // Старые JSON больше не парсятся } ```","content":"Реальный пример // После { \"status\": \"ORDER_STATUS_APPROVED\" // Старые JSON больше не парсятся } ```"},{"id":"cli/breaking-changes/rules/enum-value-same-name::top::20","title":"ENUM_VALUE_SAME_NAME","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Добавьте новое значение вместо переименования:**","content":"Стратегия миграции **Добавьте новое значение вместо переименования:**"},{"id":"cli/breaking-changes/rules/enum-value-same-name::top::21","title":"ENUM_VALUE_SAME_NAME","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Сервер обрабатывает оба значения на переходном этапе** **Мигрируйте клиентов** на новые значения **Удалите (reserve) старое имя и номер** в следующей major‑версии:","content":"Стратегия миграции **Сервер обрабатывает оба значения на переходном этапе** **Мигрируйте клиентов** на новые значения **Удалите (reserve) старое имя и номер** в следующей major‑версии:"},{"id":"cli/breaking-changes/rules/enum-value-same-name::allow-alias::22","title":"ENUM_VALUE_SAME_NAME","section":"Allow Alias (исключение)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name#allow-alias","headings":["Allow Alias (исключение)"],"excerpt":"Allow Alias (исключение) С allow_alias = true можно временно иметь два имени для одного номера:","content":"Allow Alias (исключение) С allow_alias = true можно временно иметь два имени для одного номера:"},{"id":"cli/breaking-changes/rules/enum-value-same-name::allow-alias::23","title":"ENUM_VALUE_SAME_NAME","section":"Allow Alias (исключение)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name#allow-alias","headings":["Allow Alias (исключение)"],"excerpt":"Allow Alias (исключение) Примечание: Сейчас EasyP всё равно считает это breaking (может измениться в будущем).","content":"Allow Alias (исключение) Примечание: Сейчас EasyP всё равно считает это breaking (может измениться в будущем)."},{"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":"Это правило проверяет, что ни одно поле сообщения (message field) не было удалено. Удаление поля ломает совместимость по wire‑формату и сгенерированный код: в существующих данных может присутствовать удалённое поле, а кл","content":"Это правило проверяет, что ни одно поле сообщения (message field) не было удалено. Удаление поля ломает совместимость по wire‑формату и сгенерированный код: в существующих данных может присутствовать удалённое поле, а клиентский код может ссылаться на него."},{"id":"cli/breaking-changes/rules/field-no-delete::breaking::1","title":"FIELD_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-no-delete::breaking::2","title":"FIELD_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/field-no-delete::breaking::3","title":"FIELD_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message User { string name = 1; string email = 2; int32 age = 3; string phone = 4; // [!code --] } ```","content":"Плохой (Breaking) message User { string name = 1; string email = 2; int32 age = 3; string phone = 4; // [!code --] } ```"},{"id":"cli/breaking-changes/rules/field-no-delete::breaking::4","title":"FIELD_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-no-delete::breaking::5","title":"FIELD_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/field-no-delete::breaking::6","title":"FIELD_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message User { string name = 1; string email = 2; int32 age = 3; // phone поле удалено — BREAKING CHANGE! } ```","content":"Плохой (Breaking) message User { string name = 1; string email = 2; int32 age = 3; // phone поле удалено — BREAKING CHANGE! } ```"},{"id":"cli/breaking-changes/rules/field-no-delete::top::7","title":"FIELD_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо удаления — пометить поле deprecated:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо удаления — пометить поле deprecated:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-no-delete::top::8","title":"FIELD_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/field-no-delete::top::9","title":"FIELD_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message User { string name = 1; string email = 2; int32 age = 3; string phone = 4 [deprecated = true]; // [!code focus] } ```","content":"Хороший (Безопасный) 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::top::10","title":"FIELD_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Или зарезервировать номер и имя поля после удаления:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Или зарезервировать номер и имя поля после удаления:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-no-delete::top::11","title":"FIELD_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/field-no-delete::top::12","title":"FIELD_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message User { reserved 4; // [!code focus] reserved \"phone\"; // [!code focus] string name = 1; string email = 2; int32 age = 3; } ```","content":"Хороший (Безопасный) 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::top::13","title":"FIELD_NO_DELETE","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete","headings":["Влияние"],"excerpt":"Влияние **Wire Format:** Старые сообщения с удалённым полем некорректно десериализуются **Generated Code:** Удаляются аксессоры (get/set), компиляция клиента ломается **Data Loss:** Потеря сохранённых данных, связанных с","content":"Влияние **Wire Format:** Старые сообщения с удалённым полем некорректно десериализуются **Generated Code:** Удаляются аксессоры (get/set), компиляция клиента ломается **Data Loss:** Потеря сохранённых данных, связанных с полем **JSON Compatibility:** JSON парсеры ожидают наличие поля и могут выдавать ошибки"},{"id":"cli/breaking-changes/rules/field-no-delete::top::14","title":"FIELD_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Сначала пометить deprecated:**","content":"Стратегия миграции **Сначала пометить deprecated:**"},{"id":"cli/breaking-changes/rules/field-no-delete::top::15","title":"FIELD_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Прекратить запись в поле** в прикладном коде","content":"Стратегия миграции **Прекратить запись в поле** в прикладном коде"},{"id":"cli/breaking-changes/rules/field-no-delete::top::16","title":"FIELD_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Зарезервировать поле** в следующей версии, чтобы избежать повторного использования:","content":"Стратегия миграции **Зарезервировать поле** в следующей версии, чтобы избежать повторного использования:"},{"id":"cli/breaking-changes/rules/field-no-delete::top::17","title":"FIELD_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Никогда не переиспользовать номер поля** — должен оставаться в reserved навсегда","content":"Стратегия миграции **Никогда не переиспользовать номер поля** — должен оставаться в reserved навсегда"},{"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":"Правило проверяет, что поля сообщений сохраняют ту же кардинальность (обязательность / optional). Изменение кардинальности поля ломает совместимость по wire‑формату и сгенерированный код: семантика присутствия и ожидания","content":"Правило проверяет, что поля сообщений сохраняют ту же кардинальность (обязательность / optional). Изменение кардинальности поля ломает совместимость по wire‑формату и сгенерированный код: семантика присутствия и ожидания клиентского кода отличаются для optional и required (implicit) полей."},{"id":"cli/breaking-changes/rules/field-same-cardinality::breaking::1","title":"FIELD_SAME_CARDINALITY","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-same-cardinality::breaking::2","title":"FIELD_SAME_CARDINALITY","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/field-same-cardinality::breaking::3","title":"FIELD_SAME_CARDINALITY","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message User { string name = 1; string email = 2; int32 age = 3; }","content":"Плохой (Breaking) message User { string name = 1; string email = 2; int32 age = 3; }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::breaking::4","title":"FIELD_SAME_CARDINALITY","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message CreateUserRequest { string name = 1; optional string email = 2; string phone = 3; } ```","content":"Плохой (Breaking) message CreateUserRequest { string name = 1; optional string email = 2; string phone = 3; } ```"},{"id":"cli/breaking-changes/rules/field-same-cardinality::breaking::5","title":"FIELD_SAME_CARDINALITY","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-same-cardinality::breaking::6","title":"FIELD_SAME_CARDINALITY","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/field-same-cardinality::breaking::7","title":"FIELD_SAME_CARDINALITY","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message User { string name = 1; optional string email = 2; // [!code --] Было required (implicit), стало optional int32 age = 3; }","content":"Плохой (Breaking) message User { string name = 1; optional string email = 2; // [!code --] Было required (implicit), стало optional int32 age = 3; }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::breaking::8","title":"FIELD_SAME_CARDINALITY","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message CreateUserRequest { string name = 1; string email = 2; // [!code --] Было optional, стало требуемым (implicit required) string phone = 3; } ```","content":"Плохой (Breaking) message CreateUserRequest { string name = 1; string email = 2; // [!code --] Было optional, стало требуемым (implicit required) string phone = 3; } ```"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::9","title":"FIELD_SAME_CARDINALITY","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры **Проблемы миграции Proto2 → Proto3:**","content":"Дополнительные примеры **Проблемы миграции Proto2 → Proto3:**"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::10","title":"FIELD_SAME_CARDINALITY","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры ```proto // Before (proto2) syntax = \"proto2\";","content":"Дополнительные примеры ```proto // Before (proto2) syntax = \"proto2\";"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::11","title":"FIELD_SAME_CARDINALITY","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры message Order { required string id = 1; optional string notes = 2; repeated string tags = 3; }","content":"Дополнительные примеры message Order { required string id = 1; optional string notes = 2; repeated string tags = 3; }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::12","title":"FIELD_SAME_CARDINALITY","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры // After (proto3) - BREAKING CHANGES! syntax = \"proto3\";","content":"Дополнительные примеры // After (proto3) - BREAKING CHANGES! syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::13","title":"FIELD_SAME_CARDINALITY","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры message Order { string id = 1; // BREAKING: required -> implicit optional string notes = 2; // BREAKING: explicit optional -> implicit optional repeated string tags = 3; // OK } ```","content":"Дополнительные примеры message Order { string id = 1; // BREAKING: required -> implicit optional string notes = 2; // BREAKING: explicit optional -> implicit optional repeated string tags = 3; // OK } ```"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::14","title":"FIELD_SAME_CARDINALITY","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо изменения кардинальности — добавьте новое поле:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо изменения кардинальности — добавьте новое поле:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::15","title":"FIELD_SAME_CARDINALITY","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::16","title":"FIELD_SAME_CARDINALITY","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message User { string name = 1; string email = 2 [deprecated = true]; // [!code focus] Сохраняем старую кардинальность int32 age = 3; optional string email_optional = 4; // [!code focus] Новое option","content":"Хороший (Безопасный) message User { string name = 1; string email = 2 [deprecated = true]; // [!code focus] Сохраняем старую кардинальность int32 age = 3; optional string email_optional = 4; // [!code focus] Новое optional поле }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::17","title":"FIELD_SAME_CARDINALITY","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message CreateUserRequest { string name = 1; optional string email = 2 [deprecated = true]; // [!code focus] string phone = 3; string email_required = 4; // [!code focus] Новое требуемое поле } ```","content":"Хороший (Безопасный) message CreateUserRequest { string name = 1; optional string email = 2 [deprecated = true]; // [!code focus] string phone = 3; string email_required = 4; // [!code focus] Новое требуемое поле } ```"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::18","title":"FIELD_SAME_CARDINALITY","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Или создайте новую версию сообщения:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Или создайте новую версию сообщения:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::19","title":"FIELD_SAME_CARDINALITY","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v2; // [!code focus]","content":"Хороший (Безопасный) package myapi.v2; // [!code focus]"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::20","title":"FIELD_SAME_CARDINALITY","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message User { string name = 1; optional string email = 2; // [!code focus] Чистая модель в v2 int32 age = 3; }","content":"Хороший (Безопасный) message User { string name = 1; optional string email = 2; // [!code focus] Чистая модель в v2 int32 age = 3; }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::21","title":"FIELD_SAME_CARDINALITY","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message CreateUserRequest { string name = 1; string email = 2; // [!code focus] Требуемое в v2 string phone = 3; } ```","content":"Хороший (Безопасный) message CreateUserRequest { string name = 1; string email = 2; // [!code focus] Требуемое в v2 string phone = 3; } ```"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::22","title":"FIELD_SAME_CARDINALITY","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Влияние"],"excerpt":"Влияние **Wire Format:** Меняется семантика присутствия — клиенты неправильно ожидают поля **Generated Code:** Меняются методы доступа / проверки (has, clear) **Validation:** Правила проверки обязательности переписываютс","content":"Влияние **Wire Format:** Меняется семантика присутствия — клиенты неправильно ожидают поля **Generated Code:** Меняются методы доступа / проверки (has, clear) **Validation:** Правила проверки обязательности переписываются **Default Values:** Optional и required по‑разному обрабатывают отсутствие значения"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::23","title":"FIELD_SAME_CARDINALITY","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Реальный пример"],"excerpt":"Реальный пример **Код клиента ломается при смене кардинальности:** ```go // Before - поле фактически требуется (implicit) user := &myapi.User{ Name: \"John\", Email: \"john@example.com\", Age: 30, }","content":"Реальный пример **Код клиента ломается при смене кардинальности:** ```go // Before - поле фактически требуется (implicit) user := &myapi.User{ Name: \"John\", Email: \"john@example.com\", Age: 30, }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::24","title":"FIELD_SAME_CARDINALITY","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Реальный пример"],"excerpt":"Реальный пример if user.Email != \"\" { // Есть значение }","content":"Реальный пример if user.Email != \"\" { // Есть значение }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::25","title":"FIELD_SAME_CARDINALITY","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Реальный пример"],"excerpt":"Реальный пример // After - поле стало optional (pointer) user := &myapi.User{ Name: \"John\", Age: 30, // Email может отсутствовать }","content":"Реальный пример // After - поле стало optional (pointer) user := &myapi.User{ Name: \"John\", Age: 30, // Email может отсутствовать }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::26","title":"FIELD_SAME_CARDINALITY","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Реальный пример"],"excerpt":"Реальный пример if user.Email != nil && *user.Email != \"\" { // Есть значение (новый способ) }","content":"Реальный пример if user.Email != nil && *user.Email != \"\" { // Есть значение (новый способ) }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::27","title":"FIELD_SAME_CARDINALITY","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Реальный пример"],"excerpt":"Реальный пример user.Email = &emailValue // Присваивание указателя вместо строки ```","content":"Реальный пример user.Email = &emailValue // Присваивание указателя вместо строки ```"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::28","title":"FIELD_SAME_CARDINALITY","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Реальный пример"],"excerpt":"Реальный пример **Валидация на сервере:** ```go // Before func validateUser(user *User) error { if user.Email == \"\" { return errors.New(\"email is required\") } return nil }","content":"Реальный пример **Валидация на сервере:** ```go // Before func validateUser(user *User) error { if user.Email == \"\" { return errors.New(\"email is required\") } return nil }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::29","title":"FIELD_SAME_CARDINALITY","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Реальный пример"],"excerpt":"Реальный пример // After func validateUser(user *User) error { if user.Email == nil { return errors.New(\"email is required\") } if *user.Email == \"\" { return errors.New(\"email cannot be empty\") } return nil } ```","content":"Реальный пример // After func validateUser(user *User) error { if user.Email == nil { return errors.New(\"email is required\") } if *user.Email == \"\" { return errors.New(\"email cannot be empty\") } return nil } ```"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::30","title":"FIELD_SAME_CARDINALITY","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Добавьте новое поле** с нужной кардинальностью:","content":"Стратегия миграции **Добавьте новое поле** с нужной кардинальностью:"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::31","title":"FIELD_SAME_CARDINALITY","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Период двойной записи** — заполняйте оба поля:","content":"Стратегия миграции **Период двойной записи** — заполняйте оба поля:"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::32","title":"FIELD_SAME_CARDINALITY","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Клиенты постепенно переходят**:","content":"Стратегия миграции **Клиенты постепенно переходят**:"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::33","title":"FIELD_SAME_CARDINALITY","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Удаление старого поля** в следующей major‑версии:","content":"Стратегия миграции **Удаление старого поля** в следующей major‑версии:"},{"id":"cli/breaking-changes/rules/field-same-cardinality::proto2-proto3::34","title":"FIELD_SAME_CARDINALITY","section":"Миграция Proto2 → Proto3","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#proto2-proto3","headings":["Миграция Proto2 → Proto3"],"excerpt":"Миграция Proto2 → Proto3 ```proto syntax = \"proto3\"; message Order { string id = 1; // BREAKING если был required }","content":"Миграция Proto2 → Proto3 ```proto syntax = \"proto3\"; message Order { string id = 1; // BREAKING если был required }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::proto2-proto3::35","title":"FIELD_SAME_CARDINALITY","section":"Миграция Proto2 → Proto3","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#proto2-proto3","headings":["Миграция Proto2 → Proto3"],"excerpt":"Миграция Proto2 → Proto3 // Сохранить семантику: syntax = \"proto3\"; message Order { string id = 1; optional string notes = 2; } ```","content":"Миграция Proto2 → Proto3 // Сохранить семантику: syntax = \"proto3\"; message Order { string id = 1; optional string notes = 2; } ```"},{"id":"cli/breaking-changes/rules/field-same-cardinality::optional-required::36","title":"FIELD_SAME_CARDINALITY","section":"Делать optional поле required","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#optional-required","headings":["Делать optional поле required"],"excerpt":"Делать optional поле required ```proto message CreateUserRequest { string name = 1; string email = 2; // BREAKING (раньше optional) }","content":"Делать optional поле required ```proto message CreateUserRequest { string name = 1; string email = 2; // BREAKING (раньше optional) }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::optional-required::37","title":"FIELD_SAME_CARDINALITY","section":"Делать optional поле required","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#optional-required","headings":["Делать optional поле required"],"excerpt":"Делать optional поле required message CreateUserRequest { string name = 1; optional string email = 2 [deprecated = true]; string required_email = 3; } ```","content":"Делать optional поле required message CreateUserRequest { string name = 1; optional string email = 2 [deprecated = true]; string required_email = 3; } ```"},{"id":"cli/breaking-changes/rules/field-same-cardinality::required-optional::38","title":"FIELD_SAME_CARDINALITY","section":"Делать required поле optional","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#required-optional","headings":["Делать required поле optional"],"excerpt":"Делать required поле optional ```proto message User { optional string phone = 3; // BREAKING (было implicit required) }","content":"Делать required поле optional ```proto message User { optional string phone = 3; // BREAKING (было implicit required) }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::required-optional::39","title":"FIELD_SAME_CARDINALITY","section":"Делать required поле optional","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#required-optional","headings":["Делать required поле optional"],"excerpt":"Делать required поле optional message User { string phone = 3 [deprecated = true]; optional string phone_optional = 4; } ```","content":"Делать required поле optional message User { string phone = 3 [deprecated = true]; optional string phone_optional = 4; } ```"},{"id":"cli/breaking-changes/rules/field-same-cardinality::protobuf::40","title":"FIELD_SAME_CARDINALITY","section":"Типы кардинальности в Protobuf","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#protobuf","headings":["Типы кардинальности в Protobuf"],"excerpt":"Типы кардинальности в Protobuf","content":"Типы кардинальности в Protobuf"},{"id":"cli/breaking-changes/rules/field-same-cardinality::proto3::41","title":"FIELD_SAME_CARDINALITY","section":"Proto3","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#proto3","headings":["Proto3"],"excerpt":"Proto3 **Implicit optional**: string name = 1; **Explicit optional**: optional string email = 2; **Repeated**: repeated string tags = 3; **Map**: map metadata = 4;","content":"Proto3 **Implicit optional**: string name = 1; **Explicit optional**: optional string email = 2; **Repeated**: repeated string tags = 3; **Map**: map metadata = 4;"},{"id":"cli/breaking-changes/rules/field-same-cardinality::proto2::42","title":"FIELD_SAME_CARDINALITY","section":"Proto2","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#proto2","headings":["Proto2"],"excerpt":"Proto2 **Required**: required string id = 1; **Optional**: optional string email = 2; **Repeated**: repeated string tags = 3;","content":"Proto2 **Required**: required string id = 1; **Optional**: optional string email = 2; **Repeated**: repeated string tags = 3;"},{"id":"cli/breaking-changes/rules/field-same-cardinality::breaking::43","title":"FIELD_SAME_CARDINALITY","section":"Матрица Breaking изменений","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#breaking","headings":["Матрица Breaking изменений"],"excerpt":"Матрица Breaking изменений From To Result ------ ---- -------- Required Optional ❌ BREAKING Optional Required ❌ BREAKING Implicit Explicit ❌ BREAKING Explicit Implicit ❌ BREAKING Single Repeated ❌ BREAKING Repeated Singl","content":"Матрица Breaking изменений 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":"Правило проверяет, что типы полей сообщений (message fields) не изменяются. Смена типа поля ломает совместимость по wire‑формату и сгенерированный код: бинарное представление и ожидания клиентского кода различаются для р","content":"Правило проверяет, что типы полей сообщений (message fields) не изменяются. Смена типа поля ломает совместимость по wire‑формату и сгенерированный код: бинарное представление и ожидания клиентского кода различаются для разных типов."},{"id":"cli/breaking-changes/rules/field-same-type::breaking::1","title":"FIELD_SAME_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-same-type::breaking::2","title":"FIELD_SAME_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/field-same-type::breaking::3","title":"FIELD_SAME_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message Product { string name = 1; int32 price = 2; bool available = 3; } ```","content":"Плохой (Breaking) message Product { string name = 1; int32 price = 2; bool available = 3; } ```"},{"id":"cli/breaking-changes/rules/field-same-type::breaking::4","title":"FIELD_SAME_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-same-type::breaking::5","title":"FIELD_SAME_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/field-same-type::breaking::6","title":"FIELD_SAME_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message Product { string name = 1; string price = 2; // [!code --] Changed from int32 to string (изменён тип) bool available = 3; } ```","content":"Плохой (Breaking) 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::top::7","title":"FIELD_SAME_TYPE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/field-same-type","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры **Несовместимые изменения типов:** ```proto // Before message Order { string id = 1; int64 timestamp = 2; repeated string tags = 3; OrderStatus status = 4; }","content":"Дополнительные примеры **Несовместимые изменения типов:** ```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::top::8","title":"FIELD_SAME_TYPE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/field-same-type","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры // After - ВСЁ BREAKING message Order { int32 id = 1; // string -> int32: BREAKING string timestamp = 2; // int64 -> string: BREAKING string tags = 3; // repeated -> singular: BREAKING int32 status","content":"Дополнительные примеры // After - ВСЁ BREAKING 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::top::9","title":"FIELD_SAME_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо смены типа — добавьте новое поле:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо смены типа — добавьте новое поле:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-same-type::top::10","title":"FIELD_SAME_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/field-same-type::top::11","title":"FIELD_SAME_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message Product { string name = 1; int32 price = 2 [deprecated = true]; // [!code focus] // Старое поле помечено deprecated bool available = 3; string price_formatted = 4; // [!code focus] // Новое п","content":"Хороший (Безопасный) message Product { string name = 1; int32 price = 2 [deprecated = true]; // [!code focus] // Старое поле помечено deprecated bool available = 3; string price_formatted = 4; // [!code focus] // Новое поле со строковым представлением } ```"},{"id":"cli/breaking-changes/rules/field-same-type::top::12","title":"FIELD_SAME_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Или создайте новую версию сообщения:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Или создайте новую версию сообщения:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-same-type::top::13","title":"FIELD_SAME_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v2; // [!code focus] // Новая версия package","content":"Хороший (Безопасный) package myapi.v2; // [!code focus] // Новая версия package"},{"id":"cli/breaking-changes/rules/field-same-type::top::14","title":"FIELD_SAME_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message Product { string name = 1; string price = 2; // [!code focus] // В v2 уже string bool available = 3; } ```","content":"Хороший (Безопасный) message Product { string name = 1; string price = 2; // [!code focus] // В v2 уже string bool available = 3; } ```"},{"id":"cli/breaking-changes/rules/field-same-type::top::15","title":"FIELD_SAME_TYPE","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/field-same-type","headings":["Влияние"],"excerpt":"Влияние **Wire Format:** Старые бинарные данные не десериализуются корректно **Generated Code:** Меняются типы в сгенерированном коде — клиенты не компилируются **Runtime Errors:** Ошибки парсинга при несовпадении ожидае","content":"Влияние **Wire Format:** Старые бинарные данные не десериализуются корректно **Generated Code:** Меняются типы в сгенерированном коде — клиенты не компилируются **Runtime Errors:** Ошибки парсинга при несовпадении ожидаемого типа **Data Corruption:** Неверная интерпретация байтов данных"},{"id":"cli/breaking-changes/rules/field-same-type::top::16","title":"FIELD_SAME_TYPE","section":"Типовые проблемы изменений типов","path":"/docs/guide/cli/breaking-changes/rules/field-same-type","headings":["Типовые проблемы изменений типов"],"excerpt":"Типовые проблемы изменений типов","content":"Типовые проблемы изменений типов"},{"id":"cli/breaking-changes/rules/field-same-type::top::17","title":"FIELD_SAME_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/field-same-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Добавьте новое поле** с нужным типом:","content":"Стратегия миграции **Добавьте новое поле** с нужным типом:"},{"id":"cli/breaking-changes/rules/field-same-type::top::18","title":"FIELD_SAME_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/field-same-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Период двойной записи** — заполняйте оба поля для совместимости","content":"Стратегия миграции **Период двойной записи** — заполняйте оба поля для совместимости"},{"id":"cli/breaking-changes/rules/field-same-type::top::19","title":"FIELD_SAME_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/field-same-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Мигрируйте клиентов** на новое поле постепенно","content":"Стратегия миграции **Мигрируйте клиентов** на новое поле постепенно"},{"id":"cli/breaking-changes/rules/field-same-type::top::20","title":"FIELD_SAME_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/field-same-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Удалите старое поле** в следующей major‑версии:","content":"Стратегия миграции **Удалите старое поле** в следующей major‑версии:"},{"id":"cli/breaking-changes/rules/field-same-type::wire::21","title":"FIELD_SAME_TYPE","section":"Безопасные изменения (Теоретически wire‑совместимые)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type#wire","headings":["Безопасные изменения (Теоретически wire‑совместимые)"],"excerpt":"Безопасные изменения (Теоретически wire‑совместимые) Примечание: EasyP сейчас считает ЛЮБУЮ смену типа breaking. Однако технически некоторые случаи совместимы:","content":"Безопасные изменения (Теоретически wire‑совместимые) Примечание: EasyP сейчас считает ЛЮБУЮ смену типа breaking. Однако технически некоторые случаи совместимы:"},{"id":"cli/breaking-changes/rules/field-same-type::wire::22","title":"FIELD_SAME_TYPE","section":"Безопасные изменения (Теоретически wire‑совместимые)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type#wire","headings":["Безопасные изменения (Теоретически wire‑совместимые)"],"excerpt":"Безопасные изменения (Теоретически wire‑совместимые) int32 ↔ uint32 (одно кодирование) int64 ↔ uint64 (одно кодирование) string → bytes (если все строки валидный UTF‑8)","content":"Безопасные изменения (Теоретически wire‑совместимые) int32 ↔ uint32 (одно кодирование) int64 ↔ uint64 (одно кодирование) string → bytes (если все строки валидный UTF‑8)"},{"id":"cli/breaking-changes/rules/field-same-type::wire::23","title":"FIELD_SAME_TYPE","section":"Безопасные изменения (Теоретически wire‑совместимые)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type#wire","headings":["Безопасные изменения (Теоретически wire‑совместимые)"],"excerpt":"Безопасные изменения (Теоретически wire‑совместимые) Эти исключения могут получить отдельную обработку в будущих версиях EasyP с более гибкими уровнями строгости.","content":"Безопасные изменения (Теоретически wire‑совместимые) Эти исключения могут получить отдельную обработку в будущих версиях EasyP с более гибкими уровнями строгости."},{"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":"Это правило проверяет, что ни одна инструкция import не была удалена из proto‑файла. Удаление import ломает совместимость по wire‑формату и сгенерированный код: типы из импортируемых файлов могли использоваться в текущем","content":"Это правило проверяет, что ни одна инструкция import не была удалена из proto‑файла. Удаление import ломает совместимость по wire‑формату и сгенерированный код: типы из импортируемых файлов могли использоваться в текущем файле, и их удаление делает эти типы недоступными."},{"id":"cli/breaking-changes/rules/import-no-delete::breaking::1","title":"IMPORT_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/import-no-delete::breaking::2","title":"IMPORT_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/import-no-delete::breaking::3","title":"IMPORT_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) import \"google/protobuf/timestamp.proto\"; import \"google/protobuf/duration.proto\"; import \"common/user.proto\"; import \"common/address.proto\";","content":"Плохой (Breaking) 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::breaking::4","title":"IMPORT_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) 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":"Плохой (Breaking) 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::breaking::5","title":"IMPORT_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/import-no-delete::breaking::6","title":"IMPORT_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/import-no-delete::breaking::7","title":"IMPORT_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) import \"google/protobuf/timestamp.proto\"; // import \"google/protobuf/duration.proto\"; // [!code --] Удалён import — BREAKING // import \"common/user.proto\"; // [!code --] Удалён import — BREAKING // impo","content":"Плохой (Breaking) import \"google/protobuf/timestamp.proto\"; // import \"google/protobuf/duration.proto\"; // [!code --] Удалён import — BREAKING // import \"common/user.proto\"; // [!code --] Удалён import — BREAKING // import \"common/address.proto\"; // [!code --] Удалён import — BREAKING"},{"id":"cli/breaking-changes/rules/import-no-delete::breaking::8","title":"IMPORT_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message Order { string id = 1; google.protobuf.Timestamp created_at = 2; google.protobuf.Duration processing_time = 3; // ERROR: Duration недоступен common.User customer = 4; // ERROR: User недоступен c","content":"Плохой (Breaking) message Order { string id = 1; google.protobuf.Timestamp created_at = 2; google.protobuf.Duration processing_time = 3; // ERROR: Duration недоступен common.User customer = 4; // ERROR: User недоступен common.Address shipping_address = 5; // ERROR: Address недоступен } ```"},{"id":"cli/breaking-changes/rules/import-no-delete::top::9","title":"IMPORT_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры **Сервис ломается при удалённых import:** ```proto // Before import \"google/api/annotations.proto\"; import \"google/protobuf/empty.proto\"; import \"common/auth.proto\";","content":"Дополнительные примеры **Сервис ломается при удалённых import:** ```proto // Before import \"google/api/annotations.proto\"; import \"google/protobuf/empty.proto\"; import \"common/auth.proto\";"},{"id":"cli/breaking-changes/rules/import-no-delete::top::10","title":"IMPORT_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры service OrderService { rpc GetOrder(GetOrderRequest) returns (Order) { option (google.api.http) = { get: \"/v1/orders/{id}\" }; } rpc DeleteOrder(common.AuthRequest) returns (google.protobuf.Empty); ","content":"Дополнительные примеры 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::top::11","title":"IMPORT_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры // After - BREAKING CHANGES! // import \"google/api/annotations.proto\"; // BREAKING: deleted // import \"google/protobuf/empty.proto\"; // BREAKING: deleted // import \"common/auth.proto\"; // BREAKING:","content":"Дополнительные примеры // 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::top::12","title":"IMPORT_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры service OrderService { rpc GetOrder(GetOrderRequest) returns (Order) { option (google.api.http) = { // ERROR: annotations недоступен get: \"/v1/orders/{id}\" }; } rpc DeleteOrder(common.AuthRequest) ","content":"Дополнительные примеры service OrderService { rpc GetOrder(GetOrderRequest) returns (Order) { option (google.api.http) = { // ERROR: annotations недоступен get: \"/v1/orders/{id}\" }; } rpc DeleteOrder(common.AuthRequest) returns (google.protobuf.Empty); // ERROR: типы недоступны } ```"},{"id":"cli/breaking-changes/rules/import-no-delete::top::13","title":"IMPORT_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо удаления оставьте неиспользуемые import:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо удаления оставьте неиспользуемые import:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/import-no-delete::top::14","title":"IMPORT_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/import-no-delete::top::15","title":"IMPORT_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) import \"google/protobuf/timestamp.proto\"; import \"google/protobuf/duration.proto\"; // [!code focus] // Оставляем даже если не используется import \"common/user.proto\"; // [!code focus] import \"common/","content":"Хороший (Безопасный) import \"google/protobuf/timestamp.proto\"; import \"google/protobuf/duration.proto\"; // [!code focus] // Оставляем даже если не используется import \"common/user.proto\"; // [!code focus] import \"common/address.proto\"; // [!code focus]"},{"id":"cli/breaking-changes/rules/import-no-delete::top::16","title":"IMPORT_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message Order { string id = 1; google.protobuf.Timestamp created_at = 2; // Поля, использовавшие Duration/User/Address, удалены — import оставлены } ```","content":"Хороший (Безопасный) message Order { string id = 1; google.protobuf.Timestamp created_at = 2; // Поля, использовавшие Duration/User/Address, удалены — import оставлены } ```"},{"id":"cli/breaking-changes/rules/import-no-delete::top::17","title":"IMPORT_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Или добавьте новые типы, сохранив старые import:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Или добавьте новые типы, сохранив старые import:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/import-no-delete::top::18","title":"IMPORT_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/import-no-delete::top::19","title":"IMPORT_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) import \"google/protobuf/timestamp.proto\"; import \"google/protobuf/duration.proto\"; // [!code focus] import \"common/user.proto\"; // [!code focus] import \"common/address.proto\"; // [!code focus] import","content":"Хороший (Безопасный) import \"google/protobuf/timestamp.proto\"; import \"google/protobuf/duration.proto\"; // [!code focus] import \"common/user.proto\"; // [!code focus] import \"common/address.proto\"; // [!code focus] import \"common/v2/user.proto\"; // [!code focus] // Новый import"},{"id":"cli/breaking-changes/rules/import-no-delete::top::20","title":"IMPORT_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message Order { string id = 1; google.protobuf.Timestamp created_at = 2; google.protobuf.Duration processing_time = 3 [deprecated = true]; // [!code focus] common.User customer = 4 [deprecated = true","content":"Хороший (Безопасный) message Order { string id = 1; google.protobuf.Timestamp created_at = 2; google.protobuf.Duration processing_time = 3 [deprecated = true]; // [!code focus] common.User customer = 4 [deprecated = true]; // [!code focus] common.Address shipping_address = 5 [deprecated = true]; // [!code focus] int32 processing_seconds = 6; common.v2.UserProfile customer_v2 = 7; string shipping_address_text = 8; } ```"},{"id":"cli/breaking-changes/rules/import-no-delete::top::21","title":"IMPORT_NO_DELETE","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Влияние"],"excerpt":"Влияние **Generated Code:** Типы пропадают → ошибка компиляции **Wire Format:** Сообщения с удалёнными типами не десериализуются **Field References:** Поля с этими типами становятся невалидны **Service Definitions:** RPC","content":"Влияние **Generated Code:** Типы пропадают → ошибка компиляции **Wire Format:** Сообщения с удалёнными типами не десериализуются **Field References:** Поля с этими типами становятся невалидны **Service Definitions:** RPC с типами из удалённых файлов ломаются **Options Usage:** Пользовательские опции из импортов недоступны"},{"id":"cli/breaking-changes/rules/import-no-delete::top::22","title":"IMPORT_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Код клиента ломается:**","content":"Реальный пример **Код клиента ломается:**"},{"id":"cli/breaking-changes/rules/import-no-delete::top::23","title":"IMPORT_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Серверная логика ломается:**","content":"Реальный пример **Серверная логика ломается:**"},{"id":"cli/breaking-changes/rules/import-no-delete::top::24","title":"IMPORT_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Компиляция proto ломается:**","content":"Реальный пример **Компиляция proto ломается:**"},{"id":"cli/breaking-changes/rules/import-no-delete::top::25","title":"IMPORT_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции Сохраняйте import даже если типы более не используются: Добавляйте новые import рядом со старыми: Депрецируйте поля со старыми типами постепенно: Сервер: поддерживайте оба варианта: Удаляйте import тол","content":"Стратегия миграции Сохраняйте import даже если типы более не используются: Добавляйте новые import рядом со старыми: Депрецируйте поля со старыми типами постепенно: Сервер: поддерживайте оба варианта: Удаляйте import только в следующей major‑версии после полной миграции."},{"id":"cli/breaking-changes/rules/import-no-delete::top::26","title":"IMPORT_NO_DELETE","section":"Замена зависимости","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Замена зависимости"],"excerpt":"Замена зависимости ```proto import \"old/user.proto\"; // Старый import \"new/user.proto\"; // Новый","content":"Замена зависимости ```proto import \"old/user.proto\"; // Старый import \"new/user.proto\"; // Новый"},{"id":"cli/breaking-changes/rules/import-no-delete::top::27","title":"IMPORT_NO_DELETE","section":"Замена зависимости","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Замена зависимости"],"excerpt":"Замена зависимости message Order { old.User customer = 4 [deprecated = true]; new.UserProfile customer_v2 = 5; } ```","content":"Замена зависимости message Order { old.User customer = 4 [deprecated = true]; new.UserProfile customer_v2 = 5; } ```"},{"id":"cli/breaking-changes/rules/import-no-delete::top::28","title":"IMPORT_NO_DELETE","section":"Удаление функционала","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Удаление функционала"],"excerpt":"Удаление функционала ```proto import \"feature/analytics.proto\"; // Оставить даже если поле удалено","content":"Удаление функционала ```proto import \"feature/analytics.proto\"; // Оставить даже если поле удалено"},{"id":"cli/breaking-changes/rules/import-no-delete::top::29","title":"IMPORT_NO_DELETE","section":"Удаление функционала","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Удаление функционала"],"excerpt":"Удаление функционала message Order { string id = 1; // feature.AnalyticsData analytics = 2; // Поле удалено, import остаётся } ```","content":"Удаление функционала message Order { string id = 1; // feature.AnalyticsData analytics = 2; // Поле удалено, import остаётся } ```"},{"id":"cli/breaking-changes/rules/import-no-delete::protobuf::30","title":"IMPORT_NO_DELETE","section":"Миграция версии protobuf","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#protobuf","headings":["Миграция версии protobuf"],"excerpt":"Миграция версии protobuf ```proto import \"google/protobuf/timestamp.proto\"; import \"google/protobuf/duration.proto\";","content":"Миграция версии protobuf ```proto import \"google/protobuf/timestamp.proto\"; import \"google/protobuf/duration.proto\";"},{"id":"cli/breaking-changes/rules/import-no-delete::protobuf::31","title":"IMPORT_NO_DELETE","section":"Миграция версии protobuf","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#protobuf","headings":["Миграция версии protobuf"],"excerpt":"Миграция версии protobuf message Event { google.protobuf.Timestamp timestamp = 1; int64 timestamp_millis = 2; } ```","content":"Миграция версии protobuf message Event { google.protobuf.Timestamp timestamp = 1; int64 timestamp_millis = 2; } ```"},{"id":"cli/breaking-changes/rules/import-no-delete::top::32","title":"IMPORT_NO_DELETE","section":"Упрощение сложных зависимостей","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Упрощение сложных зависимостей"],"excerpt":"Упрощение сложных зависимостей ```proto import \"complex/config.proto\";","content":"Упрощение сложных зависимостей ```proto import \"complex/config.proto\";"},{"id":"cli/breaking-changes/rules/import-no-delete::top::33","title":"IMPORT_NO_DELETE","section":"Упрощение сложных зависимостей","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Упрощение сложных зависимостей"],"excerpt":"Упрощение сложных зависимостей message Settings { complex.ConfigData config = 1 [deprecated = true]; string config_json = 2; } ```","content":"Упрощение сложных зависимостей message Settings { complex.ConfigData config = 1 [deprecated = true]; string config_json = 2; } ```"},{"id":"cli/breaking-changes/rules/import-no-delete::import-vs::34","title":"IMPORT_NO_DELETE","section":"Удаление import vs использование поля","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#import-vs","headings":["Удаление import vs использование поля"],"excerpt":"Удаление import vs использование поля","content":"Удаление import vs использование поля"},{"id":"cli/breaking-changes/rules/import-no-delete::import::35","title":"IMPORT_NO_DELETE","section":"Аудит import","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#import","headings":["Аудит import"],"excerpt":"Аудит import (Даже если не найдено — не удаляем.)","content":"Аудит 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":"Это правило проверяет, что ни одно сообщение (message) не было удалено из proto‑файлов. Удаление message ломает совместимость по wire‑формату и сгенерированный код: в существующих данных могут присутствовать экземпляры у","content":"Это правило проверяет, что ни одно сообщение (message) не было удалено из proto‑файлов. Удаление message ломает совместимость по wire‑формату и сгенерированный код: в существующих данных могут присутствовать экземпляры удалённого типа, а клиентский код зависит от сгенерированных структур и классов."},{"id":"cli/breaking-changes/rules/message-no-delete::breaking::1","title":"MESSAGE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/message-no-delete::breaking::2","title":"MESSAGE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/message-no-delete::breaking::3","title":"MESSAGE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message User { string name = 1; string email = 2; Address address = 3; }","content":"Плохой (Breaking) message User { string name = 1; string email = 2; Address address = 3; }"},{"id":"cli/breaking-changes/rules/message-no-delete::breaking::4","title":"MESSAGE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message Address { // [!code --] string street = 1; // [!code --] string city = 2; // [!code --] string country = 3; // [!code --] } // [!code --]","content":"Плохой (Breaking) message Address { // [!code --] string street = 1; // [!code --] string city = 2; // [!code --] string country = 3; // [!code --] } // [!code --]"},{"id":"cli/breaking-changes/rules/message-no-delete::breaking::5","title":"MESSAGE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message Order { string id = 1; User user = 2; } ```","content":"Плохой (Breaking) message Order { string id = 1; User user = 2; } ```"},{"id":"cli/breaking-changes/rules/message-no-delete::breaking::6","title":"MESSAGE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/message-no-delete::breaking::7","title":"MESSAGE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/message-no-delete::breaking::8","title":"MESSAGE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message User { string name = 1; string email = 2; Address address = 3; // ERROR: Address больше не существует }","content":"Плохой (Breaking) message User { string name = 1; string email = 2; Address address = 3; // ERROR: Address больше не существует }"},{"id":"cli/breaking-changes/rules/message-no-delete::breaking::9","title":"MESSAGE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) // Address удалён — BREAKING CHANGE!","content":"Плохой (Breaking) // Address удалён — BREAKING CHANGE!"},{"id":"cli/breaking-changes/rules/message-no-delete::breaking::10","title":"MESSAGE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message Order { string id = 1; User user = 2; } ```","content":"Плохой (Breaking) message Order { string id = 1; User user = 2; } ```"},{"id":"cli/breaking-changes/rules/message-no-delete::top::11","title":"MESSAGE_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры **Удаление вложенного сообщения:**","content":"Дополнительные примеры **Удаление вложенного сообщения:**"},{"id":"cli/breaking-changes/rules/message-no-delete::top::12","title":"MESSAGE_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры ```proto // Before message User { string name = 1; Profile profile = 2; message Profile { // [!code --] string bio = 1; // [!code --] string avatar_url = 2; // [!code --] } // [!code --] }","content":"Дополнительные примеры ```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::top::13","title":"MESSAGE_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры // After - BREAKING CHANGE! message User { string name = 1; Profile profile = 2; // ERROR: Profile удалён // Вложенное сообщение Profile удалено } ```","content":"Дополнительные примеры // After - BREAKING CHANGE! message User { string name = 1; Profile profile = 2; // ERROR: Profile удалён // Вложенное сообщение Profile удалено } ```"},{"id":"cli/breaking-changes/rules/message-no-delete::top::14","title":"MESSAGE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо удаления — пометить как deprecated:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо удаления — пометить как deprecated:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/message-no-delete::top::15","title":"MESSAGE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/message-no-delete::top::16","title":"MESSAGE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message User { string name = 1; string email = 2; Address address = 3 [deprecated = true]; // [!code focus] }","content":"Хороший (Безопасный) message User { string name = 1; string email = 2; Address address = 3 [deprecated = true]; // [!code focus] }"},{"id":"cli/breaking-changes/rules/message-no-delete::top::17","title":"MESSAGE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message Address { option deprecated = true; // [!code focus] string street = 1; string city = 2; string country = 3; }","content":"Хороший (Безопасный) message Address { option deprecated = true; // [!code focus] string street = 1; string city = 2; string country = 3; }"},{"id":"cli/breaking-changes/rules/message-no-delete::top::18","title":"MESSAGE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message Order { string id = 1; User user = 2; } ```","content":"Хороший (Безопасный) message Order { string id = 1; User user = 2; } ```"},{"id":"cli/breaking-changes/rules/message-no-delete::top::19","title":"MESSAGE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Или заменить новой версией сообщения:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Или заменить новой версией сообщения:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/message-no-delete::top::20","title":"MESSAGE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/message-no-delete::top::21","title":"MESSAGE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message User { string name = 1; string email = 2; Address address = 3 [deprecated = true]; // [!code focus] // Старое поле AddressV2 address_v2 = 4; // [!code focus] // Новая улучшенная структура }","content":"Хороший (Безопасный) message User { string name = 1; string email = 2; Address address = 3 [deprecated = true]; // [!code focus] // Старое поле AddressV2 address_v2 = 4; // [!code focus] // Новая улучшенная структура }"},{"id":"cli/breaking-changes/rules/message-no-delete::top::22","title":"MESSAGE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message Address { option deprecated = true; // [!code focus] string street = 1; string city = 2; string country = 3; }","content":"Хороший (Безопасный) message Address { option deprecated = true; // [!code focus] string street = 1; string city = 2; string country = 3; }"},{"id":"cli/breaking-changes/rules/message-no-delete::top::23","title":"MESSAGE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) 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 c","content":"Хороший (Безопасный) 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::top::24","title":"MESSAGE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message Order { string id = 1; User user = 2; } ```","content":"Хороший (Безопасный) message Order { string id = 1; User user = 2; } ```"},{"id":"cli/breaking-changes/rules/message-no-delete::top::25","title":"MESSAGE_NO_DELETE","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Влияние"],"excerpt":"Влияние **Wire Format:** Старые данные с удалённым сообщением не десериализуются **Generated Code:** Классы/структуры удаляются — компиляция клиента ломается **Field References:** Поля, использующие удалённый тип, станов","content":"Влияние **Wire Format:** Старые данные с удалённым сообщением не десериализуются **Generated Code:** Классы/структуры удаляются — компиляция клиента ломается **Field References:** Поля, использующие удалённый тип, становятся невалидны **Nested Dependencies:** Все сообщения, ссылающиеся на удалённый тип, ломаются"},{"id":"cli/breaking-changes/rules/message-no-delete::top::26","title":"MESSAGE_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Код клиента ломается:** ```go // Before user := &myapi.User{ Name: \"John Doe\", Email: \"john@example.com\", Address: &myapi.Address{ // ERROR после удаления Street: \"123 Main St\", City: \"New York\", Countr","content":"Реальный пример **Код клиента ломается:** ```go // Before user := &myapi.User{ Name: \"John Doe\", Email: \"john@example.com\", Address: &myapi.Address{ // ERROR после удаления Street: \"123 Main St\", City: \"New York\", Country: \"USA\", }, }"},{"id":"cli/breaking-changes/rules/message-no-delete::top::27","title":"MESSAGE_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример // undefined: myapi.Address ```","content":"Реальный пример // undefined: myapi.Address ```"},{"id":"cli/breaking-changes/rules/message-no-delete::top::28","title":"MESSAGE_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Старые данные становятся нечитаемыми:**","content":"Реальный пример **Старые данные становятся нечитаемыми:**"},{"id":"cli/breaking-changes/rules/message-no-delete::top::29","title":"MESSAGE_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Пометить как deprecated:** **Пометить поля, использующие его:** **Добавить замену при необходимости:** **Удалить в следующей major‑версии после периода миграции**","content":"Стратегия миграции **Пометить как deprecated:** **Пометить поля, использующие его:** **Добавить замену при необходимости:** **Удалить в следующей major‑версии после периода миграции**"},{"id":"cli/breaking-changes/rules/message-no-delete::top::30","title":"MESSAGE_NO_DELETE","section":"Рефакторинг структуры","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Рефакторинг структуры"],"excerpt":"Рефакторинг структуры ```proto message UserInfo { option deprecated = true; string name = 1; string email = 2; }","content":"Рефакторинг структуры ```proto message UserInfo { option deprecated = true; string name = 1; string email = 2; }"},{"id":"cli/breaking-changes/rules/message-no-delete::top::31","title":"MESSAGE_NO_DELETE","section":"Рефакторинг структуры","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Рефакторинг структуры"],"excerpt":"Рефакторинг структуры message UserProfile { string full_name = 1; string email_address = 2; string phone = 3; } ```","content":"Рефакторинг структуры message UserProfile { string full_name = 1; string email_address = 2; string phone = 3; } ```"},{"id":"cli/breaking-changes/rules/message-no-delete::top::32","title":"MESSAGE_NO_DELETE","section":"Удаление «неиспользуемых» сообщений","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Удаление «неиспользуемых» сообщений"],"excerpt":"Удаление «неиспользуемых» сообщений","content":"Удаление «неиспользуемых» сообщений"},{"id":"cli/breaking-changes/rules/message-no-delete::top::33","title":"MESSAGE_NO_DELETE","section":"Миграция версии","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Миграция версии"],"excerpt":"Миграция версии ```proto package myapi.v2;","content":"Миграция версии ```proto package myapi.v2;"},{"id":"cli/breaking-changes/rules/message-no-delete::top::34","title":"MESSAGE_NO_DELETE","section":"Миграция версии","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Миграция версии"],"excerpt":"Миграция версии message User { // Новая структура без устаревших ссылок } ```","content":"Миграция версии message User { // Новая структура без устаревших ссылок } ```"},{"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":"Правило проверяет, что ни одно поле внутри oneof группы не было удалено. Удаление поля из oneof ломает совместимость по wire‑формату и сгенерированный код: в сохранённых данных может присутствовать выбранный вариант, а к","content":"Правило проверяет, что ни одно поле внутри oneof группы не было удалено. Удаление поля из oneof ломает совместимость по wire‑формату и сгенерированный код: в сохранённых данных может присутствовать выбранный вариант, а клиентский код опирается на сгенерированные типы‑обёртки и методы доступа."},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::breaking::1","title":"ONEOF_FIELD_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::breaking::2","title":"ONEOF_FIELD_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::breaking::3","title":"ONEOF_FIELD_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message LoginRequest { string username = 1; oneof credentials { string password = 2; string api_key = 3; string oauth_token = 4; string certificate = 5; } }","content":"Плохой (Breaking) 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::breaking::4","title":"ONEOF_FIELD_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message SearchQuery { oneof filter { string text = 1; int32 user_id = 2; string category = 3; DateRange date_range = 4; } } ```","content":"Плохой (Breaking) 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::breaking::5","title":"ONEOF_FIELD_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::breaking::6","title":"ONEOF_FIELD_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::breaking::7","title":"ONEOF_FIELD_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message LoginRequest { string username = 1; oneof credentials { string password = 2; string api_key = 3; // string oauth_token = 4; // [!code --] Удалено поле oneof — BREAKING! // string certificate = 5","content":"Плохой (Breaking) message LoginRequest { string username = 1; oneof credentials { string password = 2; string api_key = 3; // string oauth_token = 4; // [!code --] Удалено поле oneof — BREAKING! // string certificate = 5; // [!code --] Удалено поле oneof — BREAKING! } }"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::breaking::8","title":"ONEOF_FIELD_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message SearchQuery { oneof filter { string text = 1; int32 user_id = 2; // string category = 3; // [!code --] Удалено поле oneof — BREAKING! // DateRange date_range = 4; // [!code --] Удалено поле oneo","content":"Плохой (Breaking) message SearchQuery { oneof filter { string text = 1; int32 user_id = 2; // string category = 3; // [!code --] Удалено поле oneof — BREAKING! // DateRange date_range = 4; // [!code --] Удалено поле oneof — BREAKING! } } ```"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::9","title":"ONEOF_FIELD_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры **Удаление вложенных oneof полей:** ```proto // Before message PaymentRequest { string order_id = 1; oneof payment_method { CreditCardPayment credit_card = 2; BankTransferPayment bank_transfer = 3;","content":"Дополнительные примеры **Удаление вложенных oneof полей:** ```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::top::10","title":"ONEOF_FIELD_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры // After - BREAKING CHANGES! message PaymentRequest { string order_id = 1; oneof payment_method { CreditCardPayment credit_card = 2; BankTransferPayment bank_transfer = 3; // CryptoPayment crypto =","content":"Дополнительные примеры // 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::top::11","title":"ONEOF_FIELD_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо удаления — пометить поля deprecated:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо удаления — пометить поля deprecated:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::12","title":"ONEOF_FIELD_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::13","title":"ONEOF_FIELD_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) 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 [deprecate","content":"Хороший (Безопасный) 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::top::14","title":"ONEOF_FIELD_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) 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":"Хороший (Безопасный) 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::top::15","title":"ONEOF_FIELD_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Или добавить новые поля, оставив старые:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Или добавить новые поля, оставив старые:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::16","title":"ONEOF_FIELD_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::17","title":"ONEOF_FIELD_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message LoginRequest { string username = 1; oneof credentials { string password = 2; string api_key = 3; string oauth_token = 4 [deprecated = true]; // [!code focus] // Старое поле string certificate","content":"Хороший (Безопасный) 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] OAuthCredentials oauth_v2 = 6; // [!code focus] // Новый структурированный вариант CertificateCredentials cert_v2 = 7; // [!code focus] } } ```"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::18","title":"ONEOF_FIELD_NO_DELETE","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Влияние"],"excerpt":"Влияние **Wire Format:** Данные, содержащие удалённый вариант, не десериализуются корректно **Generated Code:** Удаляются типы‑обёртки и accessor методы — компиляция клиентов ломается **Type Safety:** Логика switch по ти","content":"Влияние **Wire Format:** Данные, содержащие удалённый вариант, не десериализуются корректно **Generated Code:** Удаляются типы‑обёртки и accessor методы — компиляция клиентов ломается **Type Safety:** Логика switch по типам oneof разваливается **Business Logic:** Код, ожидающий конкретный вариант, перестаёт работать"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::19","title":"ONEOF_FIELD_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Код клиента ломается:** ```go // Before loginReq := &myapi.LoginRequest{ Username: \"user123\", }","content":"Реальный пример **Код клиента ломается:** ```go // Before loginReq := &myapi.LoginRequest{ Username: \"user123\", }"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::20","title":"ONEOF_FIELD_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример loginReq.Credentials = &myapi.LoginRequest_OauthToken{ OauthToken: \"token123\", // ERROR после удаления поля }","content":"Реальный пример loginReq.Credentials = &myapi.LoginRequest_OauthToken{ OauthToken: \"token123\", // ERROR после удаления поля }"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::21","title":"ONEOF_FIELD_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример switch cred := loginReq.Credentials.(type) { case *myapi.LoginRequest_Password: return authenticatePassword(cred.Password) case *myapi.LoginRequest_OauthToken: // ERROR: тип удалён return authenticateOAut","content":"Реальный пример switch cred := loginReq.Credentials.(type) { case *myapi.LoginRequest_Password: return authenticatePassword(cred.Password) case *myapi.LoginRequest_OauthToken: // ERROR: тип удалён return authenticateOAuth(cred.OauthToken) case *myapi.LoginRequest_Certificate: // ERROR: тип удалён return authenticateCert(cred.Certificate) default: return errors.New(\"unsupported credential type\") } // undefined: myapi.LoginRequest_OauthToken // undefined: myapi.LoginRequest_Certificate ```"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::22","title":"ONEOF_FIELD_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Серверная логика ломается:**","content":"Реальный пример **Серверная логика ломается:**"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::23","title":"ONEOF_FIELD_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Старые данные становятся нечитаемыми:**","content":"Реальный пример **Старые данные становятся нечитаемыми:**"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::24","title":"ONEOF_FIELD_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Депрецируйте сначала:** **Добавьте новые структурированные поля:** **Сервер: поддерживайте оба варианта:** **Мигрируйте клиентов на новое поле:** **Зарезервируйте номера удалённых полей в следующей m","content":"Стратегия миграции **Депрецируйте сначала:** **Добавьте новые структурированные поля:** **Сервер: поддерживайте оба варианта:** **Мигрируйте клиентов на новое поле:** **Зарезервируйте номера удалённых полей в следующей major‑версии:**"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::25","title":"ONEOF_FIELD_NO_DELETE","section":"Удаление неподдерживаемых методов аутентификации","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Удаление неподдерживаемых методов аутентификации"],"excerpt":"Удаление неподдерживаемых методов аутентификации","content":"Удаление неподдерживаемых методов аутентификации"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::26","title":"ONEOF_FIELD_NO_DELETE","section":"Изменения бизнес‑логики платежей","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Изменения бизнес‑логики платежей"],"excerpt":"Изменения бизнес‑логики платежей","content":"Изменения бизнес‑логики платежей"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::oneof-field-deletion-vs::27","title":"ONEOF_FIELD_NO_DELETE","section":"OneOf Field Deletion vs обычное удаление","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#oneof-field-deletion-vs","headings":["OneOf Field Deletion vs обычное удаление"],"excerpt":"OneOf Field Deletion vs обычное удаление","content":"OneOf Field Deletion vs обычное удаление"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::28","title":"ONEOF_FIELD_NO_DELETE","section":"Отличия от удаления обычного поля","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Отличия от удаления обычного поля"],"excerpt":"Отличия от удаления обычного поля ```proto message User { string name = 1; // string email = 2; // BREAKING: обычное поле }","content":"Отличия от удаления обычного поля ```proto message User { string name = 1; // string email = 2; // BREAKING: обычное поле }"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::29","title":"ONEOF_FIELD_NO_DELETE","section":"Отличия от удаления обычного поля","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Отличия от удаления обычного поля"],"excerpt":"Отличия от удаления обычного поля message User { oneof contact { string email = 1; // string phone = 2; // BREAKING: поле в oneof } } ```","content":"Отличия от удаления обычного поля message User { oneof contact { string email = 1; // string phone = 2; // BREAKING: поле в oneof } } ```"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::30","title":"ONEOF_FIELD_NO_DELETE","section":"Влияние на сгенерированный код","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Влияние на сгенерированный код"],"excerpt":"Влияние на сгенерированный код ```go // Обычное поле: удаляется простой геттер // user.GetEmail()","content":"Влияние на сгенерированный код ```go // Обычное поле: удаляется простой геттер // user.GetEmail()"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::31","title":"ONEOF_FIELD_NO_DELETE","section":"Влияние на сгенерированный код","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Влияние на сгенерированный код"],"excerpt":"Влияние на сгенерированный код // Поле в oneof: пропадает тип-обёртка, кейсы switch ломаются // *LoginRequest_OauthToken ```","content":"Влияние на сгенерированный код // Поле в oneof: пропадает тип-обёртка, кейсы switch ломаются // *LoginRequest_OauthToken ```"},{"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":"Это правило проверяет, что тип поля внутри oneof НЕ меняется. Смена типа любого варианта oneof — несовместимое (breaking) изменение: существующие данные сериализованы с прежним типом, а клиентский код ожидает конкретные ","content":"Это правило проверяет, что тип поля внутри oneof НЕ меняется. Смена типа любого варианта oneof — несовместимое (breaking) изменение: существующие данные сериализованы с прежним типом, а клиентский код ожидает конкретные типы-обёртки и методы доступа, сгенерированные для каждого варианта."},{"id":"cli/breaking-changes/rules/oneof-field-same-type::breaking::1","title":"ONEOF_FIELD_SAME_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::breaking::2","title":"ONEOF_FIELD_SAME_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::breaking::3","title":"ONEOF_FIELD_SAME_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message SearchRequest { string query = 1; oneof filter { string category = 2; int32 user_id = 3; bool is_premium = 4; DateRange date_range = 5; } }","content":"Плохой (Breaking) 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::breaking::4","title":"ONEOF_FIELD_SAME_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message NotificationSettings { oneof delivery { string email = 1; int64 phone_number = 2; WebhookConfig webhook = 3; } } ```","content":"Плохой (Breaking) message NotificationSettings { oneof delivery { string email = 1; int64 phone_number = 2; WebhookConfig webhook = 3; } } ```"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::breaking::5","title":"ONEOF_FIELD_SAME_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::breaking::6","title":"ONEOF_FIELD_SAME_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::breaking::7","title":"ONEOF_FIELD_SAME_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message SearchRequest { string query = 1; oneof filter { int32 category = 2; // [!code --] Было string -> стало int32 (BREAKING) string user_id = 3; // [!code --] Было int32 -> стало string (BREAKING) s","content":"Плохой (Breaking) message SearchRequest { string query = 1; oneof filter { int32 category = 2; // [!code --] Было string -> стало int32 (BREAKING) string user_id = 3; // [!code --] Было int32 -> стало string (BREAKING) string is_premium = 4; // [!code --] Было bool -> стало string (BREAKING) string date_range = 5; // [!code --] Было DateRange -> стало string (BREAKING) } }"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::breaking::8","title":"ONEOF_FIELD_SAME_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message NotificationSettings { oneof delivery { EmailConfig email = 1; // [!code --] Было string -> стало EmailConfig (BREAKING) string phone_number = 2; // [!code --] Было int64 -> стало string (BREAKI","content":"Плохой (Breaking) message NotificationSettings { oneof delivery { EmailConfig email = 1; // [!code --] Было string -> стало EmailConfig (BREAKING) string phone_number = 2; // [!code --] Было int64 -> стало string (BREAKING) string webhook = 3; // [!code --] Было WebhookConfig -> стало string (BREAKING) } } ```"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::9","title":"ONEOF_FIELD_SAME_TYPE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры **Комплексные изменения типов:** ```proto // Before message PaymentRequest { oneof payment_info { CreditCardInfo credit_card = 1; BankAccountInfo bank_account = 2; string paypal_email = 3; CryptoWa","content":"Дополнительные примеры **Комплексные изменения типов:** ```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::top::10","title":"ONEOF_FIELD_SAME_TYPE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры // After - ВСЁ BREAKING message PaymentRequest { oneof payment_info { string credit_card = 1; // CreditCardInfo -> string PayPalInfo bank_account = 2; // BankAccountInfo -> PayPalInfo PayPalInfo pa","content":"Дополнительные примеры // After - ВСЁ BREAKING message PaymentRequest { oneof payment_info { string credit_card = 1; // CreditCardInfo -> string PayPalInfo bank_account = 2; // BankAccountInfo -> PayPalInfo PayPalInfo paypal_email = 3; // string -> PayPalInfo string crypto = 4; // CryptoWalletInfo -> string } } ```"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::11","title":"ONEOF_FIELD_SAME_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо смены типа — добавьте новое поле в тот же oneof:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо смены типа — добавьте новое поле в тот же oneof:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::12","title":"ONEOF_FIELD_SAME_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::13","title":"ONEOF_FIELD_SAME_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message SearchRequest { string query = 1; oneof filter { string category = 2 [deprecated = true]; // Старый тип int32 user_id = 3 [deprecated = true]; bool is_premium = 4 [deprecated = true]; DateRan","content":"Хороший (Безопасный) message SearchRequest { string query = 1; oneof filter { string category = 2 [deprecated = true]; // Старый тип int32 user_id = 3 [deprecated = true]; bool is_premium = 4 [deprecated = true]; DateRange date_range = 5 [deprecated = true]; int32 category_id = 6; // Новая версия string user_identifier = 7; string premium_status = 8; string date_filter = 9; } } ```"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::14","title":"ONEOF_FIELD_SAME_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Или создайте новый oneof:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Или создайте новый oneof:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::15","title":"ONEOF_FIELD_SAME_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::16","title":"ONEOF_FIELD_SAME_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message SearchRequest { string query = 1; oneof filter { option deprecated = true; string category = 2 [deprecated = true]; int32 user_id = 3 [deprecated = true]; bool is_premium = 4 [deprecated = tr","content":"Хороший (Безопасный) message SearchRequest { string query = 1; oneof filter { option deprecated = true; string category = 2 [deprecated = true]; int32 user_id = 3 [deprecated = true]; bool is_premium = 4 [deprecated = true]; DateRange date_range = 5 [deprecated = true]; } oneof filter_v2 { int32 category_id = 6; string user_identifier = 7; PremiumFilter premium_filter = 8; TimeFilter time_filter = 9; } } ```"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::17","title":"ONEOF_FIELD_SAME_TYPE","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Влияние"],"excerpt":"Влияние **Wire Format:** Старые бинарные данные не читаются корректно **Generated Code:** Меняются типы-обёртки, код клиента не компилируется **Type Safety:** switch по варианту oneof ломается **Runtime Errors:** Ошибки ","content":"Влияние **Wire Format:** Старые бинарные данные не читаются корректно **Generated Code:** Меняются типы-обёртки, код клиента не компилируется **Type Safety:** switch по варианту oneof ломается **Runtime Errors:** Ошибки десериализации и логики при несовпадении типов"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::18","title":"ONEOF_FIELD_SAME_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Реальный пример"],"excerpt":"Реальный пример **Ломается клиентский код:** ```go // Before searchReq := &myapi.SearchRequest{ Query: \"golang jobs\", }","content":"Реальный пример **Ломается клиентский код:** ```go // Before searchReq := &myapi.SearchRequest{ Query: \"golang jobs\", }"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::19","title":"ONEOF_FIELD_SAME_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Реальный пример"],"excerpt":"Реальный пример // Устанавливаем вариант oneof searchReq.Filter = &myapi.SearchRequest_Category{ Category: \"engineering\", }","content":"Реальный пример // Устанавливаем вариант oneof searchReq.Filter = &myapi.SearchRequest_Category{ Category: \"engineering\", }"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::20","title":"ONEOF_FIELD_SAME_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Реальный пример"],"excerpt":"Реальный пример // Обработка вариантов switch filter := searchReq.Filter.(type) { case *myapi.SearchRequest_Category: return searchByCategory(filter.Category) case *myapi.SearchRequest_UserId: return searchByUserId(filte","content":"Реальный пример // Обработка вариантов switch filter := searchReq.Filter.(type) { case *myapi.SearchRequest_Category: return searchByCategory(filter.Category) case *myapi.SearchRequest_UserId: return searchByUserId(filter.UserId) default: return errors.New(\"unsupported filter\") }"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::21","title":"ONEOF_FIELD_SAME_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Реальный пример"],"excerpt":"Реальный пример // After — тип Category стал int32 searchReq.Filter = &myapi.SearchRequest_Category{ Category: \"engineering\", // ERROR }","content":"Реальный пример // After — тип Category стал int32 searchReq.Filter = &myapi.SearchRequest_Category{ Category: \"engineering\", // ERROR }"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::22","title":"ONEOF_FIELD_SAME_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Реальный пример"],"excerpt":"Реальный пример switch filter := searchReq.Filter.(type) { case *myapi.SearchRequest_Category: return searchByCategory(filter.Category) // ERROR case *myapi.SearchRequest_UserId: return searchByUserId(filter.UserId) // E","content":"Реальный пример switch filter := searchReq.Filter.(type) { case *myapi.SearchRequest_Category: return searchByCategory(filter.Category) // ERROR case *myapi.SearchRequest_UserId: return searchByUserId(filter.UserId) // ERROR: UserId теперь string } ```"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::23","title":"ONEOF_FIELD_SAME_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Реальный пример"],"excerpt":"Реальный пример **Ломается серверная логика:** ```go // Before func handleSearchFilter(req *SearchRequest) (*SearchResult, error) { switch filter := req.Filter.(type) { case *SearchRequest_Category: return searchDatabase","content":"Реальный пример **Ломается серверная логика:** ```go // Before func handleSearchFilter(req *SearchRequest) (*SearchResult, error) { switch filter := req.Filter.(type) { case *SearchRequest_Category: return searchDatabase(\"category\", filter.Category), nil case *SearchRequest_UserId: return searchDatabase(\"user_id\", strconv.Itoa(int(filter.UserId))), nil default: return nil, errors.New(\"no filter specified\") } }"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::24","title":"ONEOF_FIELD_SAME_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Реальный пример"],"excerpt":"Реальный пример // After — несовпадения типов func handleSearchFilter(req *SearchRequest) (*SearchResult, error) { switch filter := req.Filter.(type) { case *SearchRequest_Category: // filter.Category теперь int32, а код","content":"Реальный пример // After — несовпадения типов func handleSearchFilter(req *SearchRequest) (*SearchResult, error) { switch filter := req.Filter.(type) { case *SearchRequest_Category: // filter.Category теперь int32, а код ожидал string return searchDatabase(\"category\", filter.Category), nil // ERROR case *SearchRequest_UserId: userIdStr := filter.UserId // string вместо int32 userId, _ := strconv.Atoi(userIdStr) return searchDatabase(\"user_id\", strconv.Itoa(userId)), nil } } ```"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::25","title":"ONEOF_FIELD_SAME_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Реальный пример"],"excerpt":"Реальный пример **Порча данных:**","content":"Реальный пример **Порча данных:**"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::26","title":"ONEOF_FIELD_SAME_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции Добавьте новое поле: Сервер поддерживает оба: Клиенты переходят на category_id. Скрипты миграции преобразуют старые данные. В следующей major‑версии:","content":"Стратегия миграции Добавьте новое поле: Сервер поддерживает оба: Клиенты переходят на category_id. Скрипты миграции преобразуют старые данные. В следующей major‑версии:"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::27","title":"ONEOF_FIELD_SAME_TYPE","section":"Переход к структурированным типам","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Переход к структурированным типам"],"excerpt":"Переход к структурированным типам","content":"Переход к структурированным типам"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::28","title":"ONEOF_FIELD_SAME_TYPE","section":"Матрица совместимости","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Матрица совместимости"],"excerpt":"Матрица совместимости From Type To Type Результат ----------- --------- ----------- string int32/int64 ❌ BREAKING int32 string ❌ BREAKING bool string ❌ BREAKING message string ❌ BREAKING string message ❌ BREAKING enum in","content":"Матрица совместимости From Type To Type Результат ----------- --------- ----------- 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::top::29","title":"ONEOF_FIELD_SAME_TYPE","section":"Влияние на сгенерированный код","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Влияние на сгенерированный код"],"excerpt":"Влияние на сгенерированный код","content":"Влияние на сгенерированный код"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::30","title":"ONEOF_FIELD_SAME_TYPE","section":"Валидация","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Валидация"],"excerpt":"Валидация **После (сломано):**","content":"Валидация **После (сломано):**"},{"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":"Это правило проверяет, что ни один oneof блок не был удалён из сообщений. Удаление oneof ломает совместимость по wire‑формату и сгенерированный код: существующие данные могут содержать ранее выбранный вариант, а клиентск","content":"Это правило проверяет, что ни один oneof блок не был удалён из сообщений. Удаление oneof ломает совместимость по wire‑формату и сгенерированный код: существующие данные могут содержать ранее выбранный вариант, а клиентский код зависит от типов-обёрток и методов доступа, генерируемых для oneof."},{"id":"cli/breaking-changes/rules/oneof-no-delete::breaking::1","title":"ONEOF_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-no-delete::breaking::2","title":"ONEOF_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/oneof-no-delete::breaking::3","title":"ONEOF_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message LoginRequest { string username = 1; oneof credentials { string password = 2; string api_key = 3; string oauth_token = 4; } }","content":"Плохой (Breaking) 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::breaking::4","title":"ONEOF_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message PaymentMethod { // [!code --] oneof method { // [!code --] CreditCard credit_card = 1; // [!code --] BankAccount bank_account = 2; // [!code --] PayPal paypal = 3; // [!code --] } // [!code --] ","content":"Плохой (Breaking) 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::breaking::5","title":"ONEOF_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message Order { string id = 1; PaymentMethod payment = 2; } ```","content":"Плохой (Breaking) message Order { string id = 1; PaymentMethod payment = 2; } ```"},{"id":"cli/breaking-changes/rules/oneof-no-delete::breaking::6","title":"ONEOF_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-no-delete::breaking::7","title":"ONEOF_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/oneof-no-delete::breaking::8","title":"ONEOF_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message LoginRequest { string username = 1; // credentials oneof удалён — BREAKING CHANGE! string password = 2; // Теперь обычные поля string api_key = 3; // Потеряна взаимная исключаемость string oauth","content":"Плохой (Breaking) message LoginRequest { string username = 1; // credentials oneof удалён — BREAKING CHANGE! string password = 2; // Теперь обычные поля string api_key = 3; // Потеряна взаимная исключаемость string oauth_token = 4; }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::breaking::9","title":"ONEOF_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message PaymentMethod { // method oneof удалён — BREAKING CHANGE! CreditCard credit_card = 1; // Теперь можно установить все поля одновременно BankAccount bank_account = 2; PayPal paypal = 3; }","content":"Плохой (Breaking) message PaymentMethod { // method oneof удалён — BREAKING CHANGE! CreditCard credit_card = 1; // Теперь можно установить все поля одновременно BankAccount bank_account = 2; PayPal paypal = 3; }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::breaking::10","title":"ONEOF_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message Order { string id = 1; PaymentMethod payment = 2; } ```","content":"Плохой (Breaking) message Order { string id = 1; PaymentMethod payment = 2; } ```"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::11","title":"ONEOF_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры **Удаление вложенного oneof:** ```proto // Before message UserProfile { string name = 1; message ContactInfo { oneof contact_method { // [!code --] string email = 1; // [!code --] string phone = 2;","content":"Дополнительные примеры **Удаление вложенного oneof:** ```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::top::12","title":"ONEOF_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры // After - BREAKING CHANGE! message UserProfile { string name = 1; message ContactInfo { // contact_method oneof удалён string email = 1; // Больше не эксклюзивно string phone = 2; // Можно задать ","content":"Дополнительные примеры // After - BREAKING CHANGE! message UserProfile { string name = 1; message ContactInfo { // contact_method oneof удалён string email = 1; // Больше не эксклюзивно string phone = 2; // Можно задать всё сразу string slack_id = 3; } ContactInfo contact = 2; } ```"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::13","title":"ONEOF_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо удаления — депрецируйте oneof:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо удаления — депрецируйте oneof:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::14","title":"ONEOF_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::15","title":"ONEOF_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message LoginRequest { string username = 1; oneof credentials { option deprecated = true; // [!code focus] string password = 2 [deprecated = true]; // [!code focus] string api_key = 3 [deprecated = t","content":"Хороший (Безопасный) 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::top::16","title":"ONEOF_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message PaymentMethod { oneof method { option deprecated = true; // [!code focus] CreditCard credit_card = 1 [deprecated = true]; // [!code focus] BankAccount bank_account = 2 [deprecated = true]; //","content":"Хороший (Безопасный) 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::top::17","title":"ONEOF_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Или заменить новой структурой:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Или заменить новой структурой:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::18","title":"ONEOF_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::19","title":"ONEOF_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message LoginRequest { string username = 1; oneof credentials { option deprecated = true; // [!code focus] // Старый oneof string password = 2 [deprecated = true]; // [!code focus] string api_key = 3","content":"Хороший (Безопасный) message LoginRequest { string username = 1; oneof credentials { option deprecated = true; // [!code focus] // Старый 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] // Новый дизайн 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::top::20","title":"ONEOF_NO_DELETE","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Влияние"],"excerpt":"Влияние **Wire Format:** Теряются семантика взаимной исключаемости — больше одного поля может быть установлено **Generated Code:** Удаляются типы-обёртки и accessor методы — код клиента не компилируется **Business Logic:","content":"Влияние **Wire Format:** Теряются семантика взаимной исключаемости — больше одного поля может быть установлено **Generated Code:** Удаляются типы-обёртки и accessor методы — код клиента не компилируется **Business Logic:** Нарушаются инварианты «только один из» **Validation:** Логика проверок должна быть переписана вручную"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::21","title":"ONEOF_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Код клиента ломается:** ```go // Before - oneOf даёт взаимную исключаемость loginReq := &myapi.LoginRequest{ Username: \"user123\", }","content":"Реальный пример **Код клиента ломается:** ```go // Before - oneOf даёт взаимную исключаемость loginReq := &myapi.LoginRequest{ Username: \"user123\", }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::22","title":"ONEOF_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример loginReq.Credentials = &myapi.LoginRequest_Password{ Password: \"secret123\", }","content":"Реальный пример loginReq.Credentials = &myapi.LoginRequest_Password{ Password: \"secret123\", }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::23","title":"ONEOF_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример switch cred := loginReq.Credentials.(type) { case *myapi.LoginRequest_Password: // ERROR после удаления return authenticatePassword(cred.Password) case *myapi.LoginRequest_ApiKey: // ERROR после удаления ","content":"Реальный пример switch cred := loginReq.Credentials.(type) { case *myapi.LoginRequest_Password: // ERROR после удаления return authenticatePassword(cred.Password) case *myapi.LoginRequest_ApiKey: // ERROR после удаления return authenticateApiKey(cred.ApiKey) default: return errors.New(\"no credentials provided\") }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::24","title":"ONEOF_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример // Compilation errors: // undefined: myapi.LoginRequest_Password // undefined field: loginReq.Credentials ```","content":"Реальный пример // Compilation errors: // undefined: myapi.LoginRequest_Password // undefined field: loginReq.Credentials ```"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::25","title":"ONEOF_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Валидация на сервере ломается:** ```go // Before func validateLoginRequest(req *LoginRequest) error { if req.Credentials == nil { return errors.New(\"credentials required\") } switch req.Credentials.(type","content":"Реальный пример **Валидация на сервере ломается:** ```go // Before func validateLoginRequest(req *LoginRequest) error { if req.Credentials == nil { return errors.New(\"credentials required\") } 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::top::26","title":"ONEOF_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример // After func validateLoginRequest(req *LoginRequest) error { credCount := 0 if req.Password != \"\" { credCount++ } if req.ApiKey != \"\" { credCount++ } if req.OauthToken != \"\" { credCount++ }","content":"Реальный пример // After func validateLoginRequest(req *LoginRequest) error { credCount := 0 if req.Password != \"\" { credCount++ } if req.ApiKey != \"\" { credCount++ } if req.OauthToken != \"\" { credCount++ }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::27","title":"ONEOF_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример if credCount == 0 { return errors.New(\"no credentials provided\") } if credCount > 1 { return errors.New(\"multiple credentials provided\") }","content":"Реальный пример if credCount == 0 { return errors.New(\"no credentials provided\") } if credCount > 1 { return errors.New(\"multiple credentials provided\") }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::28","title":"ONEOF_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример if req.Password != \"\" { return validatePassword(req.Password) } // Дополнительные проверки вручную... return nil } ```","content":"Реальный пример if req.Password != \"\" { return validatePassword(req.Password) } // Дополнительные проверки вручную... return nil } ```"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::29","title":"ONEOF_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Проблемы бизнес‑логики:** ```go // Before payment := &PaymentMethod{ Method: &PaymentMethod_CreditCard{ CreditCard: &CreditCard{Number: \"1234\"}, }, }","content":"Реальный пример **Проблемы бизнес‑логики:** ```go // Before payment := &PaymentMethod{ Method: &PaymentMethod_CreditCard{ CreditCard: &CreditCard{Number: \"1234\"}, }, }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::30","title":"ONEOF_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример // After — можно задать несколько способов сразу payment := &PaymentMethod{ CreditCard: &CreditCard{Number: \"1234\"}, BankAccount: &BankAccount{Number: \"5678\"}, // Ломает бизнес-логику } ```","content":"Реальный пример // After — можно задать несколько способов сразу payment := &PaymentMethod{ CreditCard: &CreditCard{Number: \"1234\"}, BankAccount: &BankAccount{Number: \"5678\"}, // Ломает бизнес-логику } ```"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::31","title":"ONEOF_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Депрецируйте старый oneof и его поля:**","content":"Стратегия миграции **Депрецируйте старый oneof и его поля:**"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::32","title":"ONEOF_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Создайте новый блок при необходимости:**","content":"Стратегия миграции **Создайте новый блок при необходимости:**"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::33","title":"ONEOF_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Сервер: поддерживайте оба до миграции:**","content":"Стратегия миграции **Сервер: поддерживайте оба до миграции:**"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::34","title":"ONEOF_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Клиенты: переходите на новый oneof:**","content":"Стратегия миграции **Клиенты: переходите на новый oneof:**"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::35","title":"ONEOF_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Удалите старый oneof** в следующей major‑версии.","content":"Стратегия миграции **Удалите старый oneof** в следующей major‑версии."},{"id":"cli/breaking-changes/rules/oneof-no-delete::oneof::36","title":"ONEOF_NO_DELETE","section":"Замена oneof обычными полями","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#oneof","headings":["Замена oneof обычными полями"],"excerpt":"Замена oneof обычными полями ```proto message SearchRequest { // НЕЛЬЗЯ просто убрать oneof — ломает семантику string text_query = 1; // BREAKING int32 user_id = 2; // BREAKING string category = 3; // BREAKING }","content":"Замена oneof обычными полями ```proto message SearchRequest { // НЕЛЬЗЯ просто убрать oneof — ломает семантику string text_query = 1; // BREAKING int32 user_id = 2; // BREAKING string category = 3; // BREAKING }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::oneof::37","title":"ONEOF_NO_DELETE","section":"Замена oneof обычными полями","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#oneof","headings":["Замена oneof обычными полями"],"excerpt":"Замена oneof обычными полями message SearchRequest { oneof query { option deprecated = true; string text_query = 1 [deprecated = true]; int32 user_id = 2 [deprecated = true]; string category = 3 [deprecated = true]; } st","content":"Замена oneof обычными полями message SearchRequest { oneof query { option deprecated = true; string text_query = 1 [deprecated = true]; int32 user_id = 2 [deprecated = true]; string category = 3 [deprecated = true]; } string search_text = 4; repeated string filters = 5; } ```"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::38","title":"ONEOF_NO_DELETE","section":"Упрощение структуры сообщения","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Упрощение структуры сообщения"],"excerpt":"Упрощение структуры сообщения ```proto message NotificationSettings { string email = 1; // BREAKING: был в oneof string phone = 2; // BREAKING string webhook_url = 3; // BREAKING }","content":"Упрощение структуры сообщения ```proto message NotificationSettings { string email = 1; // BREAKING: был в oneof string phone = 2; // BREAKING string webhook_url = 3; // BREAKING }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::39","title":"ONEOF_NO_DELETE","section":"Упрощение структуры сообщения","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Упрощение структуры сообщения"],"excerpt":"Упрощение структуры сообщения message NotificationSettings { oneof delivery_method { EmailNotification email = 1; SmsNotification phone = 2; WebhookNotification webhook = 3; } } ```","content":"Упрощение структуры сообщения message NotificationSettings { oneof delivery_method { EmailNotification email = 1; SmsNotification phone = 2; WebhookNotification webhook = 3; } } ```"},{"id":"cli/breaking-changes/rules/oneof-no-delete::proto2-proto3::40","title":"ONEOF_NO_DELETE","section":"Миграция с proto2 на proto3","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#proto2-proto3","headings":["Миграция с proto2 на proto3"],"excerpt":"Миграция с proto2 на proto3 ```proto // proto2 message Request { optional string name = 1; oneof data { string text = 2; int32 number = 3; } }","content":"Миграция с proto2 на proto3 ```proto // proto2 message Request { optional string name = 1; oneof data { string text = 2; int32 number = 3; } }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::proto2-proto3::41","title":"ONEOF_NO_DELETE","section":"Миграция с proto2 на proto3","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#proto2-proto3","headings":["Миграция с proto2 на proto3"],"excerpt":"Миграция с proto2 на proto3 // proto3 — сохраняем oneof message Request { string name = 1; oneof data { string text = 2; int32 number = 3; } } ```","content":"Миграция с proto2 на proto3 // proto3 — сохраняем oneof message Request { string name = 1; oneof data { string text = 2; int32 number = 3; } } ```"},{"id":"cli/breaking-changes/rules/oneof-no-delete::oneof::42","title":"ONEOF_NO_DELETE","section":"Что даёт oneof","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#oneof","headings":["Что даёт oneof"],"excerpt":"Что даёт oneof Взаимная исключаемость Типобезопасность в коде Ясность намерения API («выбери один») Эффективная сериализация — кодируется только выбранный вариант","content":"Что даёт oneof Взаимная исключаемость Типобезопасность в коде Ясность намерения API («выбери один») Эффективная сериализация — кодируется только выбранный вариант"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::43","title":"ONEOF_NO_DELETE","section":"Что теряется при удалении","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Что теряется при удалении"],"excerpt":"Что теряется при удалении Инвариант «только один» Генерируемые wrapper-типы и методы Автоматическая валидация выбора Понятность контракта API","content":"Что теряется при удалении Инвариант «только один» Генерируемые wrapper-типы и методы Автоматическая валидация выбора Понятность контракта API"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::44","title":"ONEOF_NO_DELETE","section":"Влияние на код генерации","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Влияние на код генерации"],"excerpt":"Влияние на код генерации ```go // С oneof type LoginRequest struct { Username string Credentials isLoginRequest_Credentials }","content":"Влияние на код генерации ```go // С oneof type LoginRequest struct { Username string Credentials isLoginRequest_Credentials }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::45","title":"ONEOF_NO_DELETE","section":"Влияние на код генерации","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Влияние на код генерации"],"excerpt":"Влияние на код генерации // Без oneof type LoginRequest struct { Username string Password string ApiKey string OauthToken string // Возможны многозначные конфликтующие состояния } ```","content":"Влияние на код генерации // Без oneof type LoginRequest struct { Username string Password string ApiKey string 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":"Правило проверяет, что ни один RPC‑метод не был удалён из service. Удаление RPC ломает сгенерированный код и клиентские приложения, которые этот метод вызывают.","content":"Правило проверяет, что ни один RPC‑метод не был удалён из service. Удаление RPC ломает сгенерированный код и клиентские приложения, которые этот метод вызывают."},{"id":"cli/breaking-changes/rules/rpc-no-delete::breaking::1","title":"RPC_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/rpc-no-delete::breaking::2","title":"RPC_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/rpc-no-delete::breaking::3","title":"RPC_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); rpc DeleteUser(DeleteUserRequest) returns (DeleteUserResponse","content":"Плохой (Breaking) 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::breaking::4","title":"RPC_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/rpc-no-delete::breaking::5","title":"RPC_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/rpc-no-delete::breaking::6","title":"RPC_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); // DeleteUser RPC удалён — BREAKING CHANGE! } ```","content":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); // DeleteUser RPC удалён — BREAKING CHANGE! } ```"},{"id":"cli/breaking-changes/rules/rpc-no-delete::top::7","title":"RPC_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо удаления — пометить RPC deprecated:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо удаления — пометить RPC deprecated:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/rpc-no-delete::top::8","title":"RPC_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/rpc-no-delete::top::9","title":"RPC_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); rpc DeleteUser(DeleteUserRequest) returns (DeleteUserRespo","content":"Хороший (Безопасный) 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::top::10","title":"RPC_NO_DELETE","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete","headings":["Влияние"],"excerpt":"Влияние **Generated Code:** Stub/метод исчезает — клиенты не компилируются **Client Applications:** Существующие вызовы метода падают при сборке **Runtime:** gRPC клиенты теряют определение метода","content":"Влияние **Generated Code:** Stub/метод исчезает — клиенты не компилируются **Client Applications:** Существующие вызовы метода падают при сборке **Runtime:** gRPC клиенты теряют определение метода"},{"id":"cli/breaking-changes/rules/rpc-no-delete::top::11","title":"RPC_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Сначала деприкация:**","content":"Стратегия миграции **Сначала деприкация:**"},{"id":"cli/breaking-changes/rules/rpc-no-delete::top::12","title":"RPC_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Имплементация может возвращать ошибку**, указывая что метод устарел (например, INTERNAL / UNIMPLEMENTED)","content":"Стратегия миграции **Имплементация может возвращать ошибку**, указывая что метод устарел (например, INTERNAL / UNIMPLEMENTED)"},{"id":"cli/breaking-changes/rules/rpc-no-delete::top::13","title":"RPC_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Удалить в следующей major‑версии** после миграции всех клиентов","content":"Стратегия миграции **Удалить в следующей major‑версии** после миграции всех клиентов"},{"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":"Это правило проверяет, что RPC‑методы сохраняют прежний тип сообщения запроса (request message type). Изменение типа запроса RPC ломает совместимость по wire‑формату и сгенерированный код: клиенты ожидают конкретную стру","content":"Это правило проверяет, что RPC‑методы сохраняют прежний тип сообщения запроса (request message type). Изменение типа запроса RPC ломает совместимость по wire‑формату и сгенерированный код: клиенты ожидают конкретную структуру при вызове метода."},{"id":"cli/breaking-changes/rules/rpc-same-request-type::breaking::1","title":"RPC_SAME_REQUEST_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::breaking::2","title":"RPC_SAME_REQUEST_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::breaking::3","title":"RPC_SAME_REQUEST_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse); }","content":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse); }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::breaking::4","title":"RPC_SAME_REQUEST_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message GetUserRequest { string user_id = 1; }","content":"Плохой (Breaking) message GetUserRequest { string user_id = 1; }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::breaking::5","title":"RPC_SAME_REQUEST_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message UpdateUserRequest { string user_id = 1; string name = 2; string email = 3; } ```","content":"Плохой (Breaking) message UpdateUserRequest { string user_id = 1; string name = 2; string email = 3; } ```"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::breaking::6","title":"RPC_SAME_REQUEST_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::breaking::7","title":"RPC_SAME_REQUEST_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::breaking::8","title":"RPC_SAME_REQUEST_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequestV2) returns (GetUserResponse); // [!code --] Изменён тип запроса rpc UpdateUser(UserUpdateRequest) returns (UpdateUserResponse); // [!code --] Изменён тип","content":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequestV2) returns (GetUserResponse); // [!code --] Изменён тип запроса rpc UpdateUser(UserUpdateRequest) returns (UpdateUserResponse); // [!code --] Изменён тип запроса }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::breaking::9","title":"RPC_SAME_REQUEST_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message GetUserRequestV2 { // [!code --] Новый тип запроса string id = 1; bool include_profile = 2; }","content":"Плохой (Breaking) message GetUserRequestV2 { // [!code --] Новый тип запроса string id = 1; bool include_profile = 2; }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::breaking::10","title":"RPC_SAME_REQUEST_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message UserUpdateRequest { // [!code --] Новый тип запроса string id = 1; UserProfile profile = 2; } ```","content":"Плохой (Breaking) message UserUpdateRequest { // [!code --] Новый тип запроса string id = 1; UserProfile profile = 2; } ```"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::11","title":"RPC_SAME_REQUEST_TYPE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры **Смена типа из другого пакета:** ```proto // Before import \"common/user.proto\";","content":"Дополнительные примеры **Смена типа из другого пакета:** ```proto // Before import \"common/user.proto\";"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::12","title":"RPC_SAME_REQUEST_TYPE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры service UserService { rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); }","content":"Дополнительные примеры service UserService { rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::13","title":"RPC_SAME_REQUEST_TYPE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры // After - BREAKING CHANGE! import \"v2/user.proto\";","content":"Дополнительные примеры // After - BREAKING CHANGE! import \"v2/user.proto\";"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::14","title":"RPC_SAME_REQUEST_TYPE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры service UserService { rpc CreateUser(v2.CreateUserRequest) returns (CreateUserResponse); // Другой package } ```","content":"Дополнительные примеры service UserService { rpc CreateUser(v2.CreateUserRequest) returns (CreateUserResponse); // Другой package } ```"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::15","title":"RPC_SAME_REQUEST_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо изменения типа — версионируйте RPC:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо изменения типа — версионируйте RPC:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::16","title":"RPC_SAME_REQUEST_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::17","title":"RPC_SAME_REQUEST_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse) { option deprecated = true; // [!code focus] } rpc GetUserV2(GetUserRequestV2) returns (GetUserResponse); // [!code focus] ","content":"Хороший (Безопасный) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse) { option deprecated = true; // [!code focus] } rpc GetUserV2(GetUserRequestV2) returns (GetUserResponse); // [!code focus] // Новый метод rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse) { option deprecated = true; // [!code focus] } rpc UpdateUserV2(UserUpdateRequest) returns (UpdateUserResponse); // [!code focus] // Новый метод }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::18","title":"RPC_SAME_REQUEST_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) // Старые сообщения — для обратной совместимости message GetUserRequest { string user_id = 1; }","content":"Хороший (Безопасный) // Старые сообщения — для обратной совместимости message GetUserRequest { string user_id = 1; }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::19","title":"RPC_SAME_REQUEST_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) // Новая версия сообщения message GetUserRequestV2 { // [!code focus] string id = 1; // [!code focus] bool include_profile = 2; // [!code focus] } // [!code focus] ```","content":"Хороший (Безопасный) // Новая версия сообщения 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::top::20","title":"RPC_SAME_REQUEST_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Или создайте новую версию сервиса (package v2):** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Или создайте новую версию сервиса (package v2):** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::21","title":"RPC_SAME_REQUEST_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v2; // [!code focus]","content":"Хороший (Безопасный) package myapi.v2; // [!code focus]"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::22","title":"RPC_SAME_REQUEST_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); // [!code focus] rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse); // [!code focus] }","content":"Хороший (Безопасный) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); // [!code focus] rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse); // [!code focus] }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::23","title":"RPC_SAME_REQUEST_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message GetUserRequest { // [!code focus] string id = 1; // [!code focus] bool include_profile = 2; // [!code focus] } // [!code focus] ```","content":"Хороший (Безопасный) message GetUserRequest { // [!code focus] string id = 1; // [!code focus] bool include_profile = 2; // [!code focus] } // [!code focus] ```"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::24","title":"RPC_SAME_REQUEST_TYPE","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Влияние"],"excerpt":"Влияние **Wire Format:** Старые запросы клиентов не десериализуются новым сервером **Generated Code:** Сигнатуры методов в stubs меняются — компиляция клиентов падает **gRPC Calls:** Требуется использовать другую структу","content":"Влияние **Wire Format:** Старые запросы клиентов не десериализуются новым сервером **Generated Code:** Сигнатуры методов в stubs меняются — компиляция клиентов падает **gRPC Calls:** Требуется использовать другую структуру запроса **Runtime Errors:** Несоответствие типов вызывает ошибки выполнения"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::25","title":"RPC_SAME_REQUEST_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Реальный пример"],"excerpt":"Реальный пример **Код клиента ломается:** ```go // Before client := myapi.NewUserServiceClient(conn) resp, err := client.GetUser(ctx, &myapi.GetUserRequest{ UserId: \"user123\", })","content":"Реальный пример **Код клиента ломается:** ```go // Before client := myapi.NewUserServiceClient(conn) resp, err := client.GetUser(ctx, &myapi.GetUserRequest{ UserId: \"user123\", })"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::26","title":"RPC_SAME_REQUEST_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Реальный пример"],"excerpt":"Реальный пример // After (тип запроса изменён) client := myapi.NewUserServiceClient(conn) resp, err := client.GetUser(ctx, &myapi.GetUserRequest{ // ERROR: тип не найден UserId: \"user123\", // ERROR: поле не найдено })","content":"Реальный пример // After (тип запроса изменён) client := myapi.NewUserServiceClient(conn) resp, err := client.GetUser(ctx, &myapi.GetUserRequest{ // ERROR: тип не найден UserId: \"user123\", // ERROR: поле не найдено })"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::27","title":"RPC_SAME_REQUEST_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Реальный пример"],"excerpt":"Реальный пример // Новый корректный вызов: resp, err := client.GetUser(ctx, &myapi.GetUserRequestV2{ Id: \"user123\", IncludeProfile: true, }) ```","content":"Реальный пример // Новый корректный вызов: resp, err := client.GetUser(ctx, &myapi.GetUserRequestV2{ Id: \"user123\", IncludeProfile: true, }) ```"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::28","title":"RPC_SAME_REQUEST_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Реальный пример"],"excerpt":"Реальный пример **Серверная реализация ломается:** ```go // Before func (s *server) GetUser(ctx context.Context, req *GetUserRequest) (*GetUserResponse, error) { userID := req.UserId // ... }","content":"Реальный пример **Серверная реализация ломается:** ```go // Before func (s *server) GetUser(ctx context.Context, req *GetUserRequest) (*GetUserResponse, error) { userID := req.UserId // ... }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::29","title":"RPC_SAME_REQUEST_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Реальный пример"],"excerpt":"Реальный пример // After func (s *server) GetUser(ctx context.Context, req *GetUserRequestV2) (*GetUserResponse, error) { userID := req.Id include := req.IncludeProfile // ... новая логика } ```","content":"Реальный пример // After func (s *server) GetUser(ctx context.Context, req *GetUserRequestV2) (*GetUserResponse, error) { userID := req.Id include := req.IncludeProfile // ... новая логика } ```"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::30","title":"RPC_SAME_REQUEST_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Добавьте новый RPC с новым типом запроса:**","content":"Стратегия миграции **Добавьте новый RPC с новым типом запроса:**"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::31","title":"RPC_SAME_REQUEST_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Поддерживайте оба метода на сервере:** ```go func (s *server) GetUser(ctx context.Context, req *GetUserRequest) (*GetUserResponse, error) { return s.getUserInternal(req.UserId, false) }","content":"Стратегия миграции **Поддерживайте оба метода на сервере:** ```go func (s *server) GetUser(ctx context.Context, req *GetUserRequest) (*GetUserResponse, error) { return s.getUserInternal(req.UserId, false) }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::32","title":"RPC_SAME_REQUEST_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции func (s *server) GetUserV2(ctx context.Context, req *GetUserRequestV2) (*GetUserResponse, error) { return s.getUserInternal(req.Id, req.IncludeProfile) } ```","content":"Стратегия миграции func (s *server) GetUserV2(ctx context.Context, req *GetUserRequestV2) (*GetUserResponse, error) { return s.getUserInternal(req.Id, req.IncludeProfile) } ```"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::33","title":"RPC_SAME_REQUEST_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Мигрируйте клиентов на V2:**","content":"Стратегия миграции **Мигрируйте клиентов на V2:**"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::34","title":"RPC_SAME_REQUEST_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Удалите старый метод в следующей major‑версии:**","content":"Стратегия миграции **Удалите старый метод в следующей major‑версии:**"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::35","title":"RPC_SAME_REQUEST_TYPE","section":"Добавление обязательных полей","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Добавление обязательных полей"],"excerpt":"Добавление обязательных полей ```proto // ПЛОХО: меняем существующий запрос message GetUserRequest { string user_id = 1; bool include_deleted = 2; // BREAKING }","content":"Добавление обязательных полей ```proto // ПЛОХО: меняем существующий запрос message GetUserRequest { string user_id = 1; bool include_deleted = 2; // BREAKING }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::36","title":"RPC_SAME_REQUEST_TYPE","section":"Добавление обязательных полей","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Добавление обязательных полей"],"excerpt":"Добавление обязательных полей // Хорошо: новая версия message GetUserRequestV2 { string user_id = 1; bool include_deleted = 2; } ```","content":"Добавление обязательных полей // Хорошо: новая версия message GetUserRequestV2 { string user_id = 1; bool include_deleted = 2; } ```"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::37","title":"RPC_SAME_REQUEST_TYPE","section":"Реструктуризация данных запроса","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Реструктуризация данных запроса"],"excerpt":"Реструктуризация данных запроса ```proto // ПЛОХО: меняем структуру прямо message UpdateUserRequest { UserProfile profile = 1; // BREAKING }","content":"Реструктуризация данных запроса ```proto // ПЛОХО: меняем структуру прямо message UpdateUserRequest { UserProfile profile = 1; // BREAKING }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::38","title":"RPC_SAME_REQUEST_TYPE","section":"Реструктуризация данных запроса","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Реструктуризация данных запроса"],"excerpt":"Реструктуризация данных запроса // Хорошо: версионирование rpc UpdateUser(UpdateUserRequest) returns (...) { option deprecated = true; } rpc UpdateUserV2(UpdateUserRequestV2) returns (...); ```","content":"Реструктуризация данных запроса // Хорошо: версионирование rpc UpdateUser(UpdateUserRequest) returns (...) { option deprecated = true; } rpc UpdateUserV2(UpdateUserRequestV2) returns (...); ```"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::39","title":"RPC_SAME_REQUEST_TYPE","section":"Миграция пакета","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Миграция пакета"],"excerpt":"Миграция пакета ```proto // ПЛОХО: заменяем тип на пакет v2 прямо import \"v2/messages.proto\"; // BREAKING","content":"Миграция пакета ```proto // ПЛОХО: заменяем тип на пакет v2 прямо import \"v2/messages.proto\"; // BREAKING"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::40","title":"RPC_SAME_REQUEST_TYPE","section":"Миграция пакета","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Миграция пакета"],"excerpt":"Миграция пакета // Хорошо: добавляем новый RPC rpc OldMethod(v1.Request) returns (...) { option deprecated = true; } rpc NewMethod(v2.Request) returns (...); ```","content":"Миграция пакета // Хорошо: добавляем новый RPC 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":"Это правило проверяет, что RPC‑методы сохраняют тот же тип ответного сообщения (response message type). Изменение типа ответа RPC ломает совместимость по wire‑формату и сгенерированный код: клиенты ожидают конкретную стр","content":"Это правило проверяет, что RPC‑методы сохраняют тот же тип ответного сообщения (response message type). Изменение типа ответа RPC ломает совместимость по wire‑формату и сгенерированный код: клиенты ожидают конкретную структуру при получении ответа."},{"id":"cli/breaking-changes/rules/rpc-same-response-type::breaking::1","title":"RPC_SAME_RESPONSE_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::breaking::2","title":"RPC_SAME_RESPONSE_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::breaking::3","title":"RPC_SAME_RESPONSE_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse); }","content":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse); }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::breaking::4","title":"RPC_SAME_RESPONSE_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message GetUserResponse { string user_id = 1; string name = 2; string email = 3; }","content":"Плохой (Breaking) message GetUserResponse { string user_id = 1; string name = 2; string email = 3; }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::breaking::5","title":"RPC_SAME_RESPONSE_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message UpdateUserResponse { bool success = 1; string message = 2; } ```","content":"Плохой (Breaking) message UpdateUserResponse { bool success = 1; string message = 2; } ```"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::breaking::6","title":"RPC_SAME_RESPONSE_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::breaking::7","title":"RPC_SAME_RESPONSE_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::breaking::8","title":"RPC_SAME_RESPONSE_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponseV2); // [!code --] Изменён тип ответа rpc UpdateUser(UpdateUserRequest) returns (UserUpdateResponse); // [!code --] Изменён тип ","content":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponseV2); // [!code --] Изменён тип ответа rpc UpdateUser(UpdateUserRequest) returns (UserUpdateResponse); // [!code --] Изменён тип ответа }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::breaking::9","title":"RPC_SAME_RESPONSE_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message GetUserResponseV2 { // [!code --] Другой тип сообщения string id = 1; UserProfile profile = 2; repeated string permissions = 3; }","content":"Плохой (Breaking) message GetUserResponseV2 { // [!code --] Другой тип сообщения string id = 1; UserProfile profile = 2; repeated string permissions = 3; }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::breaking::10","title":"RPC_SAME_RESPONSE_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message UserUpdateResponse { // [!code --] Другой тип сообщения UpdateResult result = 1; UserProfile updated_profile = 2; } ```","content":"Плохой (Breaking) message UserUpdateResponse { // [!code --] Другой тип сообщения UpdateResult result = 1; UserProfile updated_profile = 2; } ```"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::11","title":"RPC_SAME_RESPONSE_TYPE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры **Смена типа из другого пакета:** ```proto // Before import \"common/responses.proto\";","content":"Дополнительные примеры **Смена типа из другого пакета:** ```proto // Before import \"common/responses.proto\";"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::12","title":"RPC_SAME_RESPONSE_TYPE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры service UserService { rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); }","content":"Дополнительные примеры service UserService { rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::13","title":"RPC_SAME_RESPONSE_TYPE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры // After - BREAKING CHANGE! import \"v2/responses.proto\";","content":"Дополнительные примеры // After - BREAKING CHANGE! import \"v2/responses.proto\";"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::14","title":"RPC_SAME_RESPONSE_TYPE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры service UserService { rpc CreateUser(CreateUserRequest) returns (v2.CreateUserResponse); // Другой package } ```","content":"Дополнительные примеры service UserService { rpc CreateUser(CreateUserRequest) returns (v2.CreateUserResponse); // Другой package } ```"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::15","title":"RPC_SAME_RESPONSE_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо изменения типа — версионируйте RPC:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо изменения типа — версионируйте RPC:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::16","title":"RPC_SAME_RESPONSE_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::17","title":"RPC_SAME_RESPONSE_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse) { option deprecated = true; // [!code focus] } rpc GetUserV2(GetUserRequest) returns (GetUserResponseV2); // [!code focus] ","content":"Хороший (Безопасный) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse) { option deprecated = true; // [!code focus] } rpc GetUserV2(GetUserRequest) returns (GetUserResponseV2); // [!code focus] // Новый метод rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse) { option deprecated = true; // [!code focus] } rpc UpdateUserV2(UpdateUserRequest) returns (UserUpdateResponse); // [!code focus] // Новый метод }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::18","title":"RPC_SAME_RESPONSE_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) // Старые сообщения сохраняем для обратной совместимости message GetUserResponse { string user_id = 1; string name = 2; string email = 3; }","content":"Хороший (Безопасный) // Старые сообщения сохраняем для обратной совместимости message GetUserResponse { string user_id = 1; string name = 2; string email = 3; }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::19","title":"RPC_SAME_RESPONSE_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) // Новая расширенная версия message GetUserResponseV2 { // [!code focus] string id = 1; // [!code focus] UserProfile profile = 2; // [!code focus] repeated string permissions = 3; // [!code focus] } ","content":"Хороший (Безопасный) // Новая расширенная версия 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::top::20","title":"RPC_SAME_RESPONSE_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Или создайте новую версию сервиса (package v2):** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Или создайте новую версию сервиса (package v2):** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::21","title":"RPC_SAME_RESPONSE_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v2; // [!code focus]","content":"Хороший (Безопасный) package myapi.v2; // [!code focus]"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::22","title":"RPC_SAME_RESPONSE_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); // [!code focus] rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse); // [!code focus] }","content":"Хороший (Безопасный) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); // [!code focus] rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse); // [!code focus] }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::23","title":"RPC_SAME_RESPONSE_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message GetUserResponse { // [!code focus] string id = 1; // [!code focus] UserProfile profile = 2; // [!code focus] repeated string permissions = 3; // [!code focus] } // [!code focus] ```","content":"Хороший (Безопасный) message GetUserResponse { // [!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::top::24","title":"RPC_SAME_RESPONSE_TYPE","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Влияние"],"excerpt":"Влияние **Wire Format:** Ответы сервера не десериализуются у старых клиентов **Generated Code:** Сигнатуры ожидают старый тип — компиляция падает **gRPC Calls:** Меняются типы в сгенерированных stub'ах **Runtime Errors:*","content":"Влияние **Wire Format:** Ответы сервера не десериализуются у старых клиентов **Generated Code:** Сигнатуры ожидают старый тип — компиляция падает **gRPC Calls:** Меняются типы в сгенерированных stub'ах **Runtime Errors:** Несоответствие типов ломает обработку ответа"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::25","title":"RPC_SAME_RESPONSE_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Реальный пример"],"excerpt":"Реальный пример **Код клиента ломается:** ```go // Before client := myapi.NewUserServiceClient(conn) resp, err := client.GetUser(ctx, &myapi.GetUserRequest{ UserId: \"user123\", }) if err != nil { return err }","content":"Реальный пример **Код клиента ломается:** ```go // Before 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::top::26","title":"RPC_SAME_RESPONSE_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Реальный пример"],"excerpt":"Реальный пример userID := resp.UserId name := resp.Name","content":"Реальный пример userID := resp.UserId name := resp.Name"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::27","title":"RPC_SAME_RESPONSE_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Реальный пример"],"excerpt":"Реальный пример // After (тип ответа изменён) client := myapi.NewUserServiceClient(conn) resp, err := client.GetUser(ctx, &myapi.GetUserRequest{ UserId: \"user123\", }) if err != nil { return err }","content":"Реальный пример // After (тип ответа изменён) 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::top::28","title":"RPC_SAME_RESPONSE_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Реальный пример"],"excerpt":"Реальный пример // Ошибки компиляции: userID := resp.UserId // ERROR name := resp.Name // ERROR","content":"Реальный пример // Ошибки компиляции: userID := resp.UserId // ERROR name := resp.Name // ERROR"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::29","title":"RPC_SAME_RESPONSE_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Реальный пример"],"excerpt":"Реальный пример // Новый способ: userID := resp.Id profile := resp.Profile permissions := resp.Permissions ```","content":"Реальный пример // Новый способ: userID := resp.Id profile := resp.Profile permissions := resp.Permissions ```"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::30","title":"RPC_SAME_RESPONSE_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Реальный пример"],"excerpt":"Реальный пример **Имплементация сервера также должна быть переписана:** ```go // Before func (s *server) GetUser(ctx context.Context, req *GetUserRequest) (*GetUserResponse, error) { return &GetUserResponse{ UserId: \"use","content":"Реальный пример **Имплементация сервера также должна быть переписана:** ```go // Before 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::top::31","title":"RPC_SAME_RESPONSE_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Реальный пример"],"excerpt":"Реальный пример // After func (s *server) GetUser(ctx context.Context, req *GetUserRequest) (*GetUserResponseV2, error) { return &GetUserResponseV2{ Id: \"user123\", Profile: &UserProfile{ Name: \"John Doe\", Email: \"john@ex","content":"Реальный пример // After func (s *server) GetUser(ctx context.Context, req *GetUserRequest) (*GetUserResponseV2, error) { return &GetUserResponseV2{ Id: \"user123\", Profile: &UserProfile{ Name: \"John Doe\", Email: \"john@example.com\", }, Permissions: []string{\"read\"}, }, nil } ```"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::32","title":"RPC_SAME_RESPONSE_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Добавьте новый RPC c новым типом ответа:**","content":"Стратегия миграции **Добавьте новый RPC c новым типом ответа:**"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::33","title":"RPC_SAME_RESPONSE_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Поддерживайте оба на сервере:** ```go func (s *server) GetUser(ctx context.Context, req *GetUserRequest) (*GetUserResponse, error) { user := s.getUserInternal(req.UserId) return &GetUserResponse{ Use","content":"Стратегия миграции **Поддерживайте оба на сервере:** ```go func (s *server) GetUser(ctx context.Context, req *GetUserRequest) (*GetUserResponse, error) { user := s.getUserInternal(req.UserId) return &GetUserResponse{ UserId: user.ID, Name: user.Name, Email: user.Email, }, nil }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::34","title":"RPC_SAME_RESPONSE_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции func (s *server) GetUserV2(ctx context.Context, req *GetUserRequest) (*GetUserResponseV2, error) { user := s.getUserInternal(req.UserId) return &GetUserResponseV2{ Id: user.ID, Profile: &UserProfile{ N","content":"Стратегия миграции func (s *server) GetUserV2(ctx context.Context, req *GetUserRequest) (*GetUserResponseV2, error) { user := s.getUserInternal(req.UserId) return &GetUserResponseV2{ Id: user.ID, Profile: &UserProfile{ Name: user.Name, Email: user.Email, }, Permissions: user.Permissions, }, nil } ```"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::35","title":"RPC_SAME_RESPONSE_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Мигрируйте клиентов на новый RPC:**","content":"Стратегия миграции **Мигрируйте клиентов на новый RPC:**"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::36","title":"RPC_SAME_RESPONSE_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Удалите старый RPC** в следующей major‑версии:","content":"Стратегия миграции **Удалите старый RPC** в следующей major‑версии:"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::37","title":"RPC_SAME_RESPONSE_TYPE","section":"Добавление новых обязательных полей","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Добавление новых обязательных полей"],"excerpt":"Добавление новых обязательных полей ```proto // ПЛОХО: меняем существующий тип message GetUserResponse { string user_id = 1; string name = 2; UserProfile profile = 3; // BREAKING }","content":"Добавление новых обязательных полей ```proto // ПЛОХО: меняем существующий тип message GetUserResponse { string user_id = 1; string name = 2; UserProfile profile = 3; // BREAKING }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::38","title":"RPC_SAME_RESPONSE_TYPE","section":"Добавление новых обязательных полей","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Добавление новых обязательных полей"],"excerpt":"Добавление новых обязательных полей // Хорошо: новая версия message GetUserResponseV2 { string user_id = 1; string name = 2; UserProfile profile = 3; } ```","content":"Добавление новых обязательных полей // Хорошо: новая версия message GetUserResponseV2 { string user_id = 1; string name = 2; UserProfile profile = 3; } ```"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::39","title":"RPC_SAME_RESPONSE_TYPE","section":"Реструктуризация ответа","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Реструктуризация ответа"],"excerpt":"Реструктуризация ответа ```proto // ПЛОХО: меняем структуру прямо message UpdateUserResponse { UserDetails details = 1; // BREAKING }","content":"Реструктуризация ответа ```proto // ПЛОХО: меняем структуру прямо message UpdateUserResponse { UserDetails details = 1; // BREAKING }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::40","title":"RPC_SAME_RESPONSE_TYPE","section":"Реструктуризация ответа","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Реструктуризация ответа"],"excerpt":"Реструктуризация ответа // Хорошо: версионирование rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse) { option deprecated = true; } rpc UpdateUserV2(UpdateUserRequest) returns (UpdateUserResponseV2); ```","content":"Реструктуризация ответа // Хорошо: версионирование rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse) { option deprecated = true; } rpc UpdateUserV2(UpdateUserRequest) returns (UpdateUserResponseV2); ```"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::41","title":"RPC_SAME_RESPONSE_TYPE","section":"Изменение формата ошибок","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Изменение формата ошибок"],"excerpt":"Изменение формата ошибок ```proto // ПЛОХО: меняем формат напрямую message CreateUserResponse { ErrorDetails error = 1; // BREAKING }","content":"Изменение формата ошибок ```proto // ПЛОХО: меняем формат напрямую message CreateUserResponse { ErrorDetails error = 1; // BREAKING }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::42","title":"RPC_SAME_RESPONSE_TYPE","section":"Изменение формата ошибок","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Изменение формата ошибок"],"excerpt":"Изменение формата ошибок // Хорошо: новая версия rpc CreateUser(CreateUserRequest) returns (CreateUserResponse) { option deprecated = true; } rpc CreateUserV2(CreateUserRequest) returns (CreateUserResponseV2); ```","content":"Изменение формата ошибок // Хорошо: новая версия rpc CreateUser(CreateUserRequest) returns (CreateUserResponse) { option deprecated = true; } rpc CreateUserV2(CreateUserRequest) returns (CreateUserResponseV2); ```"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::43","title":"RPC_SAME_RESPONSE_TYPE","section":"Миграция формата","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Миграция формата"],"excerpt":"Миграция формата ```proto // ПЛОХО: перевод простой структуры в сложную message GetUserResponse { UserData data = 1; // BREAKING }","content":"Миграция формата ```proto // ПЛОХО: перевод простой структуры в сложную message GetUserResponse { UserData data = 1; // BREAKING }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::44","title":"RPC_SAME_RESPONSE_TYPE","section":"Миграция формата","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Миграция формата"],"excerpt":"Миграция формата // Хорошо: предоставляем обе версии rpc GetUser(GetUserRequest) returns (GetUserResponse) { option deprecated = true; } rpc GetUserDetailed(GetUserRequest) returns (GetUserDetailedResponse); ```","content":"Миграция формата // Хорошо: предоставляем обе версии 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":"Данное правило проверяет, что ни один service не был удалён из proto‑файлов. Удаление service ломает сгенерированный код и клиентские приложения, которые на него опираются.","content":"Данное правило проверяет, что ни один service не был удалён из proto‑файлов. Удаление service ломает сгенерированный код и клиентские приложения, которые на него опираются."},{"id":"cli/breaking-changes/rules/service-no-delete::breaking::1","title":"SERVICE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/service-no-delete::breaking::2","title":"SERVICE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/service-no-delete::breaking::3","title":"SERVICE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); }","content":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); }"},{"id":"cli/breaking-changes/rules/service-no-delete::breaking::4","title":"SERVICE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) service OrderService { // [!code --] rpc GetOrder(GetOrderRequest) returns (GetOrderResponse); // [!code --] } // [!code --] ```","content":"Плохой (Breaking) service OrderService { // [!code --] rpc GetOrder(GetOrderRequest) returns (GetOrderResponse); // [!code --] } // [!code --] ```"},{"id":"cli/breaking-changes/rules/service-no-delete::breaking::5","title":"SERVICE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/service-no-delete::breaking::6","title":"SERVICE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/service-no-delete::breaking::7","title":"SERVICE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); }","content":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); }"},{"id":"cli/breaking-changes/rules/service-no-delete::breaking::8","title":"SERVICE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) // OrderService удалён — BREAKING CHANGE! ```","content":"Плохой (Breaking) // OrderService удалён — BREAKING CHANGE! ```"},{"id":"cli/breaking-changes/rules/service-no-delete::top::9","title":"SERVICE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо удаления — отметьте service как deprecated:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо удаления — отметьте service как deprecated:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/service-no-delete::top::10","title":"SERVICE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/service-no-delete::top::11","title":"SERVICE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); }","content":"Хороший (Безопасный) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); }"},{"id":"cli/breaking-changes/rules/service-no-delete::top::12","title":"SERVICE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) service OrderService { option deprecated = true; // [!code focus] rpc GetOrder(GetOrderRequest) returns (GetOrderResponse) { option deprecated = true; // [!code focus] } } ```","content":"Хороший (Безопасный) 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::top::13","title":"SERVICE_NO_DELETE","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete","headings":["Влияние"],"excerpt":"Влияние **Generated Code:** Классы / интерфейсы сервиса исчезают — клиенты не компилируются **Client Applications:** Существующие вызовы к удалённому сервису падают на этапе сборки **Runtime:** gRPC клиенты теряют опреде","content":"Влияние **Generated Code:** Классы / интерфейсы сервиса исчезают — клиенты не компилируются **Client Applications:** Существующие вызовы к удалённому сервису падают на этапе сборки **Runtime:** gRPC клиенты теряют определение метода/сервиса"},{"id":"cli/breaking-changes/rules/service-no-delete::top::14","title":"SERVICE_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Сначала деприкация:**","content":"Стратегия миграции **Сначала деприкация:**"},{"id":"cli/breaking-changes/rules/service-no-delete::top::15","title":"SERVICE_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Уведомите клиентов** о сроках вывода из эксплуатации","content":"Стратегия миграции **Уведомите клиентов** о сроках вывода из эксплуатации"},{"id":"cli/breaking-changes/rules/service-no-delete::top::16","title":"SERVICE_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Удалите после периода миграции** в следующей major‑версии","content":"Стратегия миграции **Удалите после периода миграции** в следующей major‑версии"},{"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 Формат вывода для команд с поддержкой нескольких форматов (text/json) значение по умолчанию зависит от команды"},{"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 Базовая директория для поиска файлов Текущая рабочая дир","content":"Command-Specific Flags Flag Short Environment Description Default ------ ------- ------------- ------------- --------- --path -p Directory path to lint . --root -r Базовая директория для поиска файлов Текущая рабочая директория --format -f EASYP_FORMAT Использует глобальный флаг формата (text/json) Использует глобальное значение по умолчанию"},{"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 из поддиректории с правильным разрешением импортов easyp lint --root src/IPC/Contracts --path .","content":"Command-Specific Flags Lint из поддиректории с правильным разрешением импортов 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 # глобальный флаг","content":"Command-Specific Flags JSON output format easyp --format json lint # глобальный флаг"},{"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 Путь к директории с proto файлами для генерации . --root -r Базова","content":"Command-Specific Flags Flag Short Environment Description Default ------ ------- ------------- ------------- --------- --path -p EASYP_ROOT_GENERATE_PATH Путь к директории с proto файлами для генерации . --root -r Базовая директория для поиска файлов Текущая рабочая директория"},{"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 из поддиректории с правильным разрешением импортов easyp generate --root src/IPC/Contracts --path .","content":"Command-Specific Flags Generate из поддиректории с правильным разрешением импортов 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 Использует глобальный флаг формата (text/json) Использует глобальное значение по умолчанию"},{"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 # глобальный флаг ```","content":"Command-Specific Flags JSON output easyp --format json breaking --against main # глобальный флаг ```"},{"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 работает интерактивно: Если в корне целевой директории есть buf.yml/buf.yaml, команда предложит миграцию из Buf. Если easyp.yaml уже существует, команда запросит подтверждение на перезап","content":"Command-Specific Flags easyp init работает интерактивно: Если в корне целевой директории есть buf.yml/buf.yaml, команда предложит миграцию из Buf. Если easyp.yaml уже существует, команда запросит подтверждение на перезапись."},{"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 Путь до файла конфигурации easyp.yaml --format (global) -f EASYP_FORMAT Глобаль","content":"Command-Specific Flags Flag Short Environment Description Default ------ ------- ------------- ------------- --------- --config -c EASYP_CFG Путь до файла конфигурации easyp.yaml --format (global) -f EASYP_FORMAT Глобальный формат вывода для команд с несколькими форматами (json или text) зависит от команды (json для 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 Проверить конфиг по умолчанию с JSON выводом (статус 0 если ошибок нет) easyp validate-config","content":"Command-Specific Flags **Examples:** ```bash Проверить конфиг по умолчанию с JSON выводом (статус 0 если ошибок нет) 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 Проверить другой файл и вывести в текстовом формате (глобальный --format) easyp --format text validate-config --config example.easyp.yaml ```","content":"Command-Specific Flags Проверить другой файл и вывести в текстовом формате (глобальный --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 Формат вывода для поддерживаемых команд (text/json). Если не указан, каждая команда использует своё значение по умолчанию. значение по умолчанию зависит от команды 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::top::45","title":"EasyP Configuration Reference","section":"Переменные окружения в конфигурации","path":"/docs/guide/cli/configuration/configuration","headings":["Переменные окружения в конфигурации"],"excerpt":"Переменные окружения в конфигурации EasyP поддерживает расширение переменных окружения непосредственно в файле конфигурации easyp.yaml. Это позволяет использовать переменные окружения для динамических значений конфигурац","content":"Переменные окружения в конфигурации EasyP поддерживает расширение переменных окружения непосредственно в файле конфигурации easyp.yaml. Это позволяет использовать переменные окружения для динамических значений конфигурации."},{"id":"cli/configuration/configuration::top::46","title":"EasyP Configuration Reference","section":"Переменные окружения в конфигурации","path":"/docs/guide/cli/configuration/configuration","headings":["Переменные окружения в конфигурации"],"excerpt":"Переменные окружения в конфигурации **Пример со всеми поддерживаемыми возможностями:** ```yaml deps: # Базовое расширение: ${VAR} - расширяется в значение переменной VAR - ${GOOGLEAPIS_REPO}@${GOOGLEAPIS_VERSION} # Значе","content":"Переменные окружения в конфигурации **Пример со всеми поддерживаемыми возможностями:** ```yaml deps: # Базовое расширение: ${VAR} - расширяется в значение переменной VAR - ${GOOGLEAPIS_REPO}@${GOOGLEAPIS_VERSION} # Значение по умолчанию: ${VAR:-default} - использует default, если VAR не установлена или пустая - ${GNOSTIC_REPO:-github.com/google/gnostic}@${GNOSTIC_VERSION:-v0.7.0}"},{"id":"cli/configuration/configuration::top::47","title":"EasyP Configuration Reference","section":"Переменные окружения в конфигурации","path":"/docs/guide/cli/configuration/configuration","headings":["Переменные окружения в конфигурации"],"excerpt":"Переменные окружения в конфигурации generate: inputs: # Значение по умолчанию, если INPUT_DIR не установлена - directory: ${INPUT_DIR:-proto} plugins: - name: go # Базовое расширение out: ${OUTPUT_DIR} opts: # Значение п","content":"Переменные окружения в конфигурации generate: inputs: # Значение по умолчанию, если INPUT_DIR не установлена - directory: ${INPUT_DIR:-proto} plugins: - name: go # Базовое расширение out: ${OUTPUT_DIR} opts: # Значение по умолчанию module: ${MODULE_NAME:-github.com/example/project} timeout: ${TIMEOUT:-30} # Экранирование: $$ становится буквальным $, $${VAR} становится буквальным ${VAR} path: \"${BASE_DIR}/$${TEMP}/file\" # Результат: \"/tmp/${TEMP}/file\" (если BASE_DIR=/tmp) literal: \"$$\" # Результат: \"$\" ```"},{"id":"cli/configuration/configuration::top::48","title":"EasyP Configuration Reference","section":"Переменные окружения в конфигурации","path":"/docs/guide/cli/configuration/configuration","headings":["Переменные окружения в конфигурации"],"excerpt":"Переменные окружения в конфигурации **Поддерживаемый синтаксис:** ${VAR} - расширяется в значение переменной VAR ${VAR:-default} - использует default, если VAR не установлена или пустая ${VAR:=default} - использует defau","content":"Переменные окружения в конфигурации **Поддерживаемый синтаксис:** ${VAR} - расширяется в значение переменной VAR ${VAR:-default} - использует default, если VAR не установлена или пустая ${VAR:=default} - использует default, если VAR не установлена или пустая ${VAR-default} - использует default, если VAR не установлена (пустая строка сохраняется) $${VAR} или $$VAR - экранирует в буквальную строку ${VAR} или $VAR $$ - экранирует в буквальный символ $"},{"id":"cli/configuration/configuration::top::49","title":"EasyP Configuration Reference","section":"Переменные окружения в конфигурации","path":"/docs/guide/cli/configuration/configuration","headings":["Переменные окружения в конфигурации"],"excerpt":"Переменные окружения в конфигурации **Примечание:** Переменные окружения расширяются до парсинга YAML, поэтому любой паттерн ${STRING} будет обработан. Используйте $$ для экранирования символов доллара, когда нужны буква","content":"Переменные окружения в конфигурации **Примечание:** Переменные окружения расширяются до парсинга YAML, поэтому любой паттерн ${STRING} будет обработан. Используйте $$ для экранирования символов доллара, когда нужны буквальные значения."},{"id":"cli/configuration/configuration::version::50","title":"EasyP Configuration Reference","section":"version","path":"/docs/guide/cli/configuration/configuration#version","headings":["version"],"excerpt":"version **Опционально (legacy-совместимость).** Поле поддерживается для обратной совместимости и может быть опущено в новых конфигурациях.","content":"version **Опционально (legacy-совместимость).** Поле поддерживается для обратной совместимости и может быть опущено в новых конфигурациях."},{"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:** не задано **Рекомендация:** если сохраняете поле, используйте v1alpha","content":"version **Type:** string **Default:** не задано **Рекомендация:** если сохраняете поле, используйте v1alpha"},{"id":"cli/configuration/configuration::version::52","title":"EasyP Configuration Reference","section":"version","path":"/docs/guide/cli/configuration/configuration#version","headings":["version"],"excerpt":"version На поведение рантайма это поле не влияет.","content":"version На поведение рантайма это поле не влияет."},{"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, required) - Output directory for generated files opts (mapstring, optional) - Plugin-specific options; each key can be a single value or an array of 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::top::0","title":"Go","section":"Установка плагинов","path":"/docs/guide/cli/generator/examples/go","headings":["Установка плагинов"],"excerpt":"Установка плагинов Сначала установите необходимые плагины для работы с gRPC:","content":"Установка плагинов Сначала установите необходимые плагины для работы с gRPC:"},{"id":"cli/generator/examples/go::top::1","title":"Go","section":"Установка плагинов","path":"/docs/guide/cli/generator/examples/go","headings":["Установка плагинов"],"excerpt":"Установка плагинов Эти команды установят плагины protoc-gen-go и protoc-gen-go-grpc для использования с EasyP.","content":"Установка плагинов Эти команды установят плагины protoc-gen-go и protoc-gen-go-grpc для использования с EasyP."},{"id":"cli/generator/examples/go::proto::2","title":"Go","section":"Пример proto‑сервиса","path":"/docs/guide/cli/generator/examples/go#proto","headings":["Пример proto‑сервиса"],"excerpt":"Пример proto‑сервиса Ниже пример proto-файла для сервиса Echo:","content":"Пример proto‑сервиса Ниже пример proto-файла для сервиса Echo:"},{"id":"cli/generator/examples/go::proto::3","title":"Go","section":"Пример proto‑сервиса","path":"/docs/guide/cli/generator/examples/go#proto","headings":["Пример proto‑сервиса"],"excerpt":"Пример proto‑сервиса ```proto syntax = \"proto3\";","content":"Пример proto‑сервиса ```proto syntax = \"proto3\";"},{"id":"cli/generator/examples/go::proto::4","title":"Go","section":"Пример proto‑сервиса","path":"/docs/guide/cli/generator/examples/go#proto","headings":["Пример proto‑сервиса"],"excerpt":"Пример proto‑сервиса package api.echo.v1;","content":"Пример proto‑сервиса package api.echo.v1;"},{"id":"cli/generator/examples/go::proto::5","title":"Go","section":"Пример proto‑сервиса","path":"/docs/guide/cli/generator/examples/go#proto","headings":["Пример proto‑сервиса"],"excerpt":"Пример proto‑сервиса option go_package = \"github.com/easyp-tech/example/api/echo/v1;pb\";","content":"Пример proto‑сервиса option go_package = \"github.com/easyp-tech/example/api/echo/v1;pb\";"},{"id":"cli/generator/examples/go::proto::6","title":"Go","section":"Пример proto‑сервиса","path":"/docs/guide/cli/generator/examples/go#proto","headings":["Пример proto‑сервиса"],"excerpt":"Пример proto‑сервиса service EchoAPI { rpc Echo(EchoRequest) returns (EchoResponse); rpc EchoStream(EchoStreamRequest) returns (EchoResponse); }","content":"Пример proto‑сервиса service EchoAPI { rpc Echo(EchoRequest) returns (EchoResponse); rpc EchoStream(EchoStreamRequest) returns (EchoResponse); }"},{"id":"cli/generator/examples/go::proto::7","title":"Go","section":"Пример proto‑сервиса","path":"/docs/guide/cli/generator/examples/go#proto","headings":["Пример proto‑сервиса"],"excerpt":"Пример proto‑сервиса message EchoRequest { string payload = 1; }","content":"Пример proto‑сервиса message EchoRequest { string payload = 1; }"},{"id":"cli/generator/examples/go::proto::8","title":"Go","section":"Пример proto‑сервиса","path":"/docs/guide/cli/generator/examples/go#proto","headings":["Пример proto‑сервиса"],"excerpt":"Пример proto‑сервиса message EchoResponse { string payload = 2; }","content":"Пример proto‑сервиса message EchoResponse { string payload = 2; }"},{"id":"cli/generator/examples/go::proto::9","title":"Go","section":"Пример proto‑сервиса","path":"/docs/guide/cli/generator/examples/go#proto","headings":["Пример proto‑сервиса"],"excerpt":"Пример proto‑сервиса message EchoStreamRequest { string payload = 1; }","content":"Пример proto‑сервиса message EchoStreamRequest { string payload = 1; }"},{"id":"cli/generator/examples/go::proto::10","title":"Go","section":"Пример proto‑сервиса","path":"/docs/guide/cli/generator/examples/go#proto","headings":["Пример proto‑сервиса"],"excerpt":"Пример proto‑сервиса message EchoStreamResponse { string payload = 2; } ```","content":"Пример proto‑сервиса message EchoStreamResponse { string payload = 2; } ```"},{"id":"cli/generator/examples/go::top::11","title":"Go","section":"Настройка конфигурации","path":"/docs/guide/cli/generator/examples/go","headings":["Настройка конфигурации"],"excerpt":"Настройка конфигурации Создайте и настройте файл конфигурации easyp.yaml:","content":"Настройка конфигурации Создайте и настройте файл конфигурации easyp.yaml:"},{"id":"cli/generator/examples/go::top::12","title":"Go","section":"Настройка конфигурации","path":"/docs/guide/cli/generator/examples/go","headings":["Настройка конфигурации"],"excerpt":"Настройка конфигурации Этот файл указывает использование двух плагинов: go для генерации Go-кода и go-grpc для генерации gRPC-кода, вместе с их опциями.","content":"Настройка конфигурации Этот файл указывает использование двух плагинов: go для генерации Go-кода и go-grpc для генерации gRPC-кода, вместе с их опциями."},{"id":"cli/generator/examples/go::top::13","title":"Go","section":"Генерация кода","path":"/docs/guide/cli/generator/examples/go","headings":["Генерация кода"],"excerpt":"Генерация кода Чтобы сгенерировать код, выполните команду:","content":"Генерация кода Чтобы сгенерировать код, выполните команду:"},{"id":"cli/generator/examples/go::top::14","title":"Go","section":"Генерация кода","path":"/docs/guide/cli/generator/examples/go","headings":["Генерация кода"],"excerpt":"Генерация кода Если флаг --cfg не указан, по умолчанию используется файл easyp.yaml в текущей директории:","content":"Генерация кода Если флаг --cfg не указан, по умолчанию используется файл easyp.yaml в текущей директории:"},{"id":"cli/generator/examples/go::top::15","title":"Go","section":"Генерация кода","path":"/docs/guide/cli/generator/examples/go","headings":["Генерация кода"],"excerpt":"Генерация кода Теперь у вас есть сгенерированный Go‑код, с которым можно напрямую работать.","content":"Генерация кода Теперь у вас есть сгенерированный Go‑код, с которым можно напрямую работать."},{"id":"cli/generator/examples/grpc-gateway::top::0","title":"gRPC-Gateway","section":"Установка плагинов","path":"/docs/guide/cli/generator/examples/grpc-gateway","headings":["Установка плагинов"],"excerpt":"Установка плагинов В дополнение к плагинам для работы с gRPC, необходимо установить следующие плагины для gRPC-Gateway:","content":"Установка плагинов В дополнение к плагинам для работы с gRPC, необходимо установить следующие плагины для gRPC-Gateway:"},{"id":"cli/generator/examples/grpc-gateway::top::1","title":"gRPC-Gateway","section":"Установка плагинов","path":"/docs/guide/cli/generator/examples/grpc-gateway","headings":["Установка плагинов"],"excerpt":"Установка плагинов go install google.golang.org/protobuf/cmd/protoc-gen-go@latest go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest go install github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2@","content":"Установка плагинов go install google.golang.org/protobuf/cmd/protoc-gen-go@latest go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest go install github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2@latest go install github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway@latest"},{"id":"cli/generator/examples/grpc-gateway::top::2","title":"gRPC-Gateway","section":"Установка плагинов","path":"/docs/guide/cli/generator/examples/grpc-gateway","headings":["Установка плагинов"],"excerpt":"Установка плагинов Эти команды установят плагины protoc-gen-go, protoc-gen-go-grpc, protoc-gen-openapiv2 и protoc-gen-grpc-gateway для использования с EasyP.","content":"Установка плагинов Эти команды установят плагины protoc-gen-go, protoc-gen-go-grpc, protoc-gen-openapiv2 и protoc-gen-grpc-gateway для использования с EasyP."},{"id":"cli/generator/examples/grpc-gateway::proto::3","title":"gRPC-Gateway","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/grpc-gateway#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса Ниже — исходный proto‑файл для сервиса Echo:","content":"Пример Proto сервиса Ниже — исходный proto‑файл для сервиса Echo:"},{"id":"cli/generator/examples/grpc-gateway::proto::4","title":"gRPC-Gateway","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/grpc-gateway#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса syntax = \"proto3\";","content":"Пример Proto сервиса syntax = \"proto3\";"},{"id":"cli/generator/examples/grpc-gateway::proto::5","title":"gRPC-Gateway","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/grpc-gateway#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса package api.echo.v1;","content":"Пример Proto сервиса package api.echo.v1;"},{"id":"cli/generator/examples/grpc-gateway::proto::6","title":"gRPC-Gateway","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/grpc-gateway#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса option go_package = \"github.com/easyp-tech/example/api/echo/v1;pb\";","content":"Пример Proto сервиса option go_package = \"github.com/easyp-tech/example/api/echo/v1;pb\";"},{"id":"cli/generator/examples/grpc-gateway::proto::7","title":"gRPC-Gateway","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/grpc-gateway#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса service EchoAPI { rpc Echo(EchoRequest) returns (EchoResponse); }","content":"Пример Proto сервиса service EchoAPI { rpc Echo(EchoRequest) returns (EchoResponse); }"},{"id":"cli/generator/examples/grpc-gateway::proto::8","title":"gRPC-Gateway","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/grpc-gateway#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса message EchoRequest { string payload = 1; }","content":"Пример Proto сервиса message EchoRequest { string payload = 1; }"},{"id":"cli/generator/examples/grpc-gateway::proto::9","title":"gRPC-Gateway","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/grpc-gateway#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса message EchoResponse { string payload = 2; }","content":"Пример Proto сервиса message EchoResponse { string payload = 2; }"},{"id":"cli/generator/examples/grpc-gateway::proto::10","title":"gRPC-Gateway","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/grpc-gateway#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса Чтобы использовать gRPC-Gateway, обновите proto‑файл, добавив HTTP‑опции:","content":"Пример Proto сервиса Чтобы использовать gRPC-Gateway, обновите proto‑файл, добавив HTTP‑опции:"},{"id":"cli/generator/examples/grpc-gateway::proto::11","title":"gRPC-Gateway","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/grpc-gateway#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса syntax = \"proto3\"; import \"google/api/annotations.proto\";","content":"Пример Proto сервиса syntax = \"proto3\"; import \"google/api/annotations.proto\";"},{"id":"cli/generator/examples/grpc-gateway::proto::12","title":"gRPC-Gateway","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/grpc-gateway#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса package api.echo.v1;","content":"Пример Proto сервиса package api.echo.v1;"},{"id":"cli/generator/examples/grpc-gateway::proto::13","title":"gRPC-Gateway","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/grpc-gateway#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса option go_package = \"github.com/easyp-tech/example/api/echo/v1;pb\";","content":"Пример Proto сервиса option go_package = \"github.com/easyp-tech/example/api/echo/v1;pb\";"},{"id":"cli/generator/examples/grpc-gateway::proto::14","title":"gRPC-Gateway","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/grpc-gateway#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса service EchoAPI { rpc Echo(EchoRequest) returns (EchoResponse) { option (google.api.http) = { // [!code ++] post: \"/api/v1/echo\" // [!code ++] body: \"*\" // [!code ++] }; // [!code ++] } }","content":"Пример Proto сервиса 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::proto::15","title":"gRPC-Gateway","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/grpc-gateway#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса message EchoRequest { string payload = 1; }","content":"Пример Proto сервиса message EchoRequest { string payload = 1; }"},{"id":"cli/generator/examples/grpc-gateway::proto::16","title":"gRPC-Gateway","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/grpc-gateway#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса message EchoResponse { string payload = 2; }","content":"Пример Proto сервиса message EchoResponse { string payload = 2; }"},{"id":"cli/generator/examples/grpc-gateway::top::17","title":"gRPC-Gateway","section":"Настройка конфигурации","path":"/docs/guide/cli/generator/examples/grpc-gateway","headings":["Настройка конфигурации"],"excerpt":"Настройка конфигурации Обновите файл easyp.yaml, добавив необходимые зависимости и плагины: deps: # [!code ++] - github.com/googleapis/googleapis # [!code ++]","content":"Настройка конфигурации Обновите файл easyp.yaml, добавив необходимые зависимости и плагины: deps: # [!code ++] - github.com/googleapis/googleapis # [!code ++]"},{"id":"cli/generator/examples/grpc-gateway::top::18","title":"gRPC-Gateway","section":"Настройка конфигурации","path":"/docs/guide/cli/generator/examples/grpc-gateway","headings":["Настройка конфигурации"],"excerpt":"Настройка конфигурации 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":"Настройка конфигурации 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::top::19","title":"gRPC-Gateway","section":"Настройка конфигурации","path":"/docs/guide/cli/generator/examples/grpc-gateway","headings":["Настройка конфигурации"],"excerpt":"Настройка конфигурации Секция deps перечисляет зависимости, необходимые для импортов proto‑файлов. В данном случае добавляем github.com/googleapis/googleapis, поскольку там находится файл annotations.proto, используемый ","content":"Настройка конфигурации Секция deps перечисляет зависимости, необходимые для импортов proto‑файлов. В данном случае добавляем github.com/googleapis/googleapis, поскольку там находится файл annotations.proto, используемый в определении сервиса."},{"id":"cli/generator/examples/grpc-gateway::top::20","title":"gRPC-Gateway","section":"Обновление зависимостей","path":"/docs/guide/cli/generator/examples/grpc-gateway","headings":["Обновление зависимостей"],"excerpt":"Обновление зависимостей После обновления конфигурации выполните команду для загрузки указанных зависимостей:","content":"Обновление зависимостей После обновления конфигурации выполните команду для загрузки указанных зависимостей:"},{"id":"cli/generator/examples/grpc-gateway::top::21","title":"gRPC-Gateway","section":"Обновление зависимостей","path":"/docs/guide/cli/generator/examples/grpc-gateway","headings":["Обновление зависимостей"],"excerpt":"Обновление зависимостей easyp mod update","content":"Обновление зависимостей easyp mod update"},{"id":"cli/generator/examples/grpc-gateway::top::22","title":"gRPC-Gateway","section":"Обновление зависимостей","path":"/docs/guide/cli/generator/examples/grpc-gateway","headings":["Обновление зависимостей"],"excerpt":"Обновление зависимостей Больше деталей по управлению зависимостями см. в разделе Package Manager.","content":"Обновление зависимостей Больше деталей по управлению зависимостями см. в разделе Package Manager."},{"id":"cli/generator/examples/grpc-gateway::top::23","title":"gRPC-Gateway","section":"Генерация кода","path":"/docs/guide/cli/generator/examples/grpc-gateway","headings":["Генерация кода"],"excerpt":"Генерация кода Для генерации кода используйте:","content":"Генерация кода Для генерации кода используйте:"},{"id":"cli/generator/examples/grpc-gateway::top::24","title":"gRPC-Gateway","section":"Генерация кода","path":"/docs/guide/cli/generator/examples/grpc-gateway","headings":["Генерация кода"],"excerpt":"Генерация кода easyp --cfg easyp.yaml generate","content":"Генерация кода easyp --cfg easyp.yaml generate"},{"id":"cli/generator/examples/grpc-gateway::top::25","title":"gRPC-Gateway","section":"Генерация кода","path":"/docs/guide/cli/generator/examples/grpc-gateway","headings":["Генерация кода"],"excerpt":"Генерация кода Если флаг --cfg не указан, по умолчанию используется файл easyp.yaml из текущей директории:","content":"Генерация кода Если флаг --cfg не указан, по умолчанию используется файл easyp.yaml из текущей директории:"},{"id":"cli/generator/examples/grpc-gateway::top::26","title":"gRPC-Gateway","section":"Генерация кода","path":"/docs/guide/cli/generator/examples/grpc-gateway","headings":["Генерация кода"],"excerpt":"Генерация кода Теперь у вас сгенерированы Go‑код и код gRPC-Gateway, с которыми можно работать напрямую.","content":"Генерация кода Теперь у вас сгенерированы Go‑код и код gRPC-Gateway, с которыми можно работать напрямую."},{"id":"cli/generator/examples/validate::top::0","title":"Validate","section":"Установка плагинов","path":"/docs/guide/cli/generator/examples/validate","headings":["Установка плагинов"],"excerpt":"Установка плагинов Сначала установите необходимые плагины для работы с gRPC и проверок (validate):","content":"Установка плагинов Сначала установите необходимые плагины для работы с gRPC и проверок (validate):"},{"id":"cli/generator/examples/validate::top::1","title":"Validate","section":"Установка плагинов","path":"/docs/guide/cli/generator/examples/validate","headings":["Установка плагинов"],"excerpt":"Установка плагинов Эти команды установят плагины protoc-gen-go, protoc-gen-go-grpc и protoc-gen-validate для использования вместе с EasyP.","content":"Установка плагинов Эти команды установят плагины protoc-gen-go, protoc-gen-go-grpc и protoc-gen-validate для использования вместе с EasyP."},{"id":"cli/generator/examples/validate::proto::2","title":"Validate","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/validate#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса Ниже пример proto‑файла для сервиса Echo:","content":"Пример Proto сервиса Ниже пример proto‑файла для сервиса Echo:"},{"id":"cli/generator/examples/validate::proto::3","title":"Validate","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/validate#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса ```proto syntax = \"proto3\";","content":"Пример Proto сервиса ```proto syntax = \"proto3\";"},{"id":"cli/generator/examples/validate::proto::4","title":"Validate","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/validate#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса package api.echo.v1;","content":"Пример Proto сервиса package api.echo.v1;"},{"id":"cli/generator/examples/validate::proto::5","title":"Validate","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/validate#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса import \"validate/validate.proto\";","content":"Пример Proto сервиса import \"validate/validate.proto\";"},{"id":"cli/generator/examples/validate::proto::6","title":"Validate","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/validate#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса option go_package = \"github.com/easyp-tech/example/api/echo/v1;pb\";","content":"Пример Proto сервиса option go_package = \"github.com/easyp-tech/example/api/echo/v1;pb\";"},{"id":"cli/generator/examples/validate::proto::7","title":"Validate","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/validate#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса service EchoAPI { rpc Echo(EchoRequest) returns (EchoResponse); rpc EchoStream(EchoStreamRequest) returns (EchoResponse); }","content":"Пример Proto сервиса service EchoAPI { rpc Echo(EchoRequest) returns (EchoResponse); rpc EchoStream(EchoStreamRequest) returns (EchoResponse); }"},{"id":"cli/generator/examples/validate::proto::8","title":"Validate","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/validate#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса message EchoRequest { string payload = 1 [(validate.rules).string = {max_len: 200}]; }","content":"Пример Proto сервиса message EchoRequest { string payload = 1 [(validate.rules).string = {max_len: 200}]; }"},{"id":"cli/generator/examples/validate::proto::9","title":"Validate","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/validate#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса message EchoResponse { string payload = 2; }","content":"Пример Proto сервиса message EchoResponse { string payload = 2; }"},{"id":"cli/generator/examples/validate::proto::10","title":"Validate","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/validate#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса message EchoStreamRequest { string payload = 1 [(validate.rules).string = {max_len: 200}]; }","content":"Пример Proto сервиса message EchoStreamRequest { string payload = 1 [(validate.rules).string = {max_len: 200}]; }"},{"id":"cli/generator/examples/validate::proto::11","title":"Validate","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/validate#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса message EchoStreamResponse { string payload = 2; } ```","content":"Пример Proto сервиса message EchoStreamResponse { string payload = 2; } ```"},{"id":"cli/generator/examples/validate::top::12","title":"Validate","section":"Настройка конфигурации","path":"/docs/guide/cli/generator/examples/validate","headings":["Настройка конфигурации"],"excerpt":"Настройка конфигурации Создайте и настройте файл конфигурации easyp.yaml:","content":"Настройка конфигурации Создайте и настройте файл конфигурации easyp.yaml:"},{"id":"cli/generator/examples/validate::top::13","title":"Validate","section":"Настройка конфигурации","path":"/docs/guide/cli/generator/examples/validate","headings":["Настройка конфигурации"],"excerpt":"Настройка конфигурации ```yaml deps: # [!code ++] - github.com/bufbuild/protoc-gen-validate # [!code ++]","content":"Настройка конфигурации ```yaml deps: # [!code ++] - github.com/bufbuild/protoc-gen-validate # [!code ++]"},{"id":"cli/generator/examples/validate::top::14","title":"Validate","section":"Настройка конфигурации","path":"/docs/guide/cli/generator/examples/validate","headings":["Настройка конфигурации"],"excerpt":"Настройка конфигурации 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: sourc","content":"Настройка конфигурации 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::top::15","title":"Validate","section":"Генерация кода","path":"/docs/guide/cli/generator/examples/validate","headings":["Генерация кода"],"excerpt":"Генерация кода Чтобы сгенерировать код, выполните команду:","content":"Генерация кода Чтобы сгенерировать код, выполните команду:"},{"id":"cli/generator/examples/validate::top::16","title":"Validate","section":"Генерация кода","path":"/docs/guide/cli/generator/examples/validate","headings":["Генерация кода"],"excerpt":"Генерация кода Если флаг --cfg не указан, по умолчанию используется файл easyp.yaml из текущего каталога:","content":"Генерация кода Если флаг --cfg не указан, по умолчанию используется файл easyp.yaml из текущего каталога:"},{"id":"cli/generator/examples/validate::top::17","title":"Validate","section":"Генерация кода","path":"/docs/guide/cli/generator/examples/validate","headings":["Генерация кода"],"excerpt":"Генерация кода Теперь у вас есть сгенерированный Go‑код с поддержкой валидации, и вы можете напрямую использовать его в проекте.","content":"Генерация кода Теперь у вас есть сгенерированный Go‑код с поддержкой валидации, и вы можете напрямую использовать его в проекте."},{"id":"cli/generator/generator::top::0","title":"Генератор","path":"/docs/guide/cli/generator/generator","headings":[],"excerpt":"EasyP включает мощный генератор, который упрощает процесс получения кода из proto‑файлов. Благодаря YAML‑конфигурациям работа становится гораздо более удобной и интуитивной по сравнению с прямым использованием команды pr","content":"EasyP включает мощный генератор, который упрощает процесс получения кода из proto‑файлов. Благодаря YAML‑конфигурациям работа становится гораздо более удобной и интуитивной по сравнению с прямым использованием команды protoc."},{"id":"cli/generator/generator::top::1","title":"Генератор","section":"Ключевые особенности генератора","path":"/docs/guide/cli/generator/generator","headings":["Ключевые особенности генератора"],"excerpt":"Ключевые особенности генератора **Упрощённая генерация кода**: - Генерация кода из proto через декларативную YAML‑конфигурацию. - Избавляет от необходимости писать длинные и сложные команды protoc.","content":"Ключевые особенности генератора **Упрощённая генерация кода**: - Генерация кода из proto через декларативную YAML‑конфигурацию. - Избавляет от необходимости писать длинные и сложные команды protoc."},{"id":"cli/generator/generator::top::2","title":"Генератор","section":"Ключевые особенности генератора","path":"/docs/guide/cli/generator/generator","headings":["Ключевые особенности генератора"],"excerpt":"Ключевые особенности генератора **Обёртка над protoc**: - EasyP выступает как удобный слой над protoc, предоставляя декларативный API. - Поддерживает все опции и плагины, доступные protoc.","content":"Ключевые особенности генератора **Обёртка над protoc**: - EasyP выступает как удобный слой над protoc, предоставляя декларативный API. - Поддерживает все опции и плагины, доступные protoc."},{"id":"cli/generator/generator::top::3","title":"Генератор","section":"Ключевые особенности генератора","path":"/docs/guide/cli/generator/generator","headings":["Ключевые особенности генератора"],"excerpt":"Ключевые особенности генератора **Гибкость и кастомизация**: - Используются те же параметры, что и у плагинов protoc, прямо в конфиге. - Поддерживается множество плагинов и их параметры в одной конфигурации.","content":"Ключевые особенности генератора **Гибкость и кастомизация**: - Используются те же параметры, что и у плагинов protoc, прямо в конфиге. - Поддерживается множество плагинов и их параметры в одной конфигурации."},{"id":"cli/generator/generator::top::4","title":"Генератор","section":"Ключевые особенности генератора","path":"/docs/guide/cli/generator/generator","headings":["Ключевые особенности генератора"],"excerpt":"Ключевые особенности генератора **Генерация из нескольких источников**: - Локальные директории и удалённые Git‑репозитории одновременно. - Лёгкая интеграция с существующими проектами и репозиториями.","content":"Ключевые особенности генератора **Генерация из нескольких источников**: - Локальные директории и удалённые Git‑репозитории одновременно. - Лёгкая интеграция с существующими проектами и репозиториями."},{"id":"cli/generator/generator::top::5","title":"Генератор","section":"Ключевые особенности генератора","path":"/docs/guide/cli/generator/generator","headings":["Ключевые особенности генератора"],"excerpt":"Ключевые особенности генератора **Удалённая генерация**: - Генерация из удалённых Git репозиториев без локального checkout.","content":"Ключевые особенности генератора **Удалённая генерация**: - Генерация из удалённых Git репозиториев без локального checkout."},{"id":"cli/generator/generator::top::6","title":"Генератор","section":"Ключевые особенности генератора","path":"/docs/guide/cli/generator/generator","headings":["Ключевые особенности генератора"],"excerpt":"Ключевые особенности генератора **Интеграция с менеджером пакетов**: - Прозрачная работа с зависимостями через пакетный менеджер EasyP. - Автоматическое разрешение и подключение proto‑зависимостей.","content":"Ключевые особенности генератора **Интеграция с менеджером пакетов**: - Прозрачная работа с зависимостями через пакетный менеджер EasyP. - Автоматическое разрешение и подключение proto‑зависимостей."},{"id":"cli/generator/generator::complete-configuration-example::7","title":"Генератор","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":"Генератор","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":"Генератор","section":"Complete Configuration Example","path":"/docs/guide/cli/generator/generator#complete-configuration-example","headings":["Complete Configuration Example"],"excerpt":"Complete Configuration Example Managed mode - автоматическая установка file и field опций managed: enabled: true disable: - module: github.com/googleapis/googleapis # Отключить для конкретного модуля override: - file_opt","content":"Complete Configuration Example Managed mode - автоматическая установка file и field опций managed: enabled: true disable: - module: github.com/googleapis/googleapis # Отключить для конкретного модуля 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/ # Применить к конкретному пути"},{"id":"cli/generator/generator::complete-configuration-example::10","title":"Генератор","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":"Генератор","section":"Локальный ввод (Local Directory Input)","path":"/docs/guide/cli/generator/generator#local-directory-input","headings":["Локальный ввод (Local Directory Input)"],"excerpt":"Локальный ввод (Local Directory Input) Локальная директория — самый распространённый и простой способ указать откуда брать proto для генерации. Используйте этот вариант, если файлы уже находятся в репозитории проекта.","content":"Локальный ввод (Local Directory Input) Локальная директория — самый распространённый и простой способ указать откуда брать proto для генерации. Используйте этот вариант, если файлы уже находятся в репозитории проекта."},{"id":"cli/generator/generator::local-directory-input::12","title":"Генератор","section":"Локальный ввод (Local Directory Input)","path":"/docs/guide/cli/generator/generator#local-directory-input","headings":["Локальный ввод (Local Directory Input)"],"excerpt":"Локальный ввод (Local Directory Input) **Когда применять:** Proto файлы находятся в кодовой базе проекта Нужен полный контроль над структурой каталогов Проект — один сервис или приложение Файлы меняются не слишком часто","content":"Локальный ввод (Local Directory Input) **Когда применять:** Proto файлы находятся в кодовой базе проекта Нужен полный контроль над структурой каталогов Проект — один сервис или приложение Файлы меняются не слишком часто"},{"id":"cli/generator/generator::local-directory-input::13","title":"Генератор","section":"Локальный ввод (Local Directory Input)","path":"/docs/guide/cli/generator/generator#local-directory-input","headings":["Локальный ввод (Local Directory Input)"],"excerpt":"Локальный ввод (Local Directory Input)","content":"Локальный ввод (Local Directory Input)"},{"id":"cli/generator/generator::local-directory-input::14","title":"Генератор","section":"Локальный ввод (Local Directory Input)","path":"/docs/guide/cli/generator/generator#local-directory-input","headings":["Локальный ввод (Local Directory Input)"],"excerpt":"Локальный ввод (Local Directory Input) Параметр root особенно полезен в монорепозиториях: он позволяет управлять тем, откуда будут резолвиться пути импортов. Если указать родительскую директорию, импорты будут оцениватьс","content":"Локальный ввод (Local Directory Input) Параметр root особенно полезен в монорепозиториях: он позволяет управлять тем, откуда будут резолвиться пути импортов. Если указать родительскую директорию, импорты будут оцениваться относительно неё, а не текущего рабочего каталога."},{"id":"cli/generator/generator::local-directory-input::15","title":"Генератор","section":"Локальный ввод (Local Directory Input)","path":"/docs/guide/cli/generator/generator#local-directory-input","headings":["Локальный ввод (Local Directory Input)"],"excerpt":"Локальный ввод (Local Directory Input) **Параметры:**","content":"Локальный ввод (Local Directory Input) **Параметры:**"},{"id":"cli/generator/generator::local-directory-input::16","title":"Генератор","section":"Локальный ввод (Local Directory Input)","path":"/docs/guide/cli/generator/generator#local-directory-input","headings":["Локальный ввод (Local Directory Input)"],"excerpt":"Локальный ввод (Local Directory Input) Параметр Тип Обязателен Значение по умолчанию Описание ---------- ----- ------------ ----------------------- ---------- path string ✅ - Каталог, содержащий proto файлы root string ❌","content":"Локальный ввод (Local Directory Input) Параметр Тип Обязателен Значение по умолчанию Описание ---------- ----- ------------ ----------------------- ---------- path string ✅ - Каталог, содержащий proto файлы root string ❌ \".\" Корневая директория для разрешения import путей"},{"id":"cli/generator/generator::local-directory-input::17","title":"Генератор","section":"Локальный ввод (Local Directory Input)","path":"/docs/guide/cli/generator/generator#local-directory-input","headings":["Локальный ввод (Local Directory Input)"],"excerpt":"Локальный ввод (Local Directory Input) **Примеры:**","content":"Локальный ввод (Local Directory Input) **Примеры:**"},{"id":"cli/generator/generator::local-directory-input::18","title":"Генератор","section":"Локальный ввод (Local Directory Input)","path":"/docs/guide/cli/generator/generator#local-directory-input","headings":["Локальный ввод (Local Directory Input)"],"excerpt":"Локальный ввод (Local Directory Input) Ниже показана разница между базовым указанием директории и расширенной конфигурацией с пользовательским корнем импортов:","content":"Локальный ввод (Local Directory Input) Ниже показана разница между базовым указанием директории и расширенной конфигурацией с пользовательским корнем импортов:"},{"id":"cli/generator/generator::local-directory-input::19","title":"Генератор","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::20","title":"Генератор","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::git-remote-git-repository-input::21","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) Этот тип входных данных позволяет генерировать код из proto‑файлов, находящихся в удалённых репозиториях, без локального checkout. Особенно полезно при использовани","content":"Удалённый Git репозиторий (Remote Git Repository Input) Этот тип входных данных позволяет генерировать код из proto‑файлов, находящихся в удалённых репозиториях, без локального checkout. Особенно полезно при использовании API других команд или внешних поставщиков."},{"id":"cli/generator/generator::git-remote-git-repository-input::22","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) **Когда использовать:** Потребление proto определений из других сервисов/команд Интеграция с внешними вендорскими API Работа с общими библиотеками proto в нескольки","content":"Удалённый Git репозиторий (Remote Git Repository Input) **Когда использовать:** Потребление proto определений из других сервисов/команд Интеграция с внешними вендорскими API Работа с общими библиотеками proto в нескольких проектах Необходимо гарантировать корректную (зафиксированную) версию внешних API"},{"id":"cli/generator/generator::git-remote-git-repository-input::23","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) **Рекомендации:** В продакшене всегда фиксируйте версии (@v1.0.0, а не latest) Используйте семантические версии при наличии — проще сопровождать Предпочитайте публи","content":"Удалённый Git репозиторий (Remote Git Repository Input) **Рекомендации:** В продакшене всегда фиксируйте версии (@v1.0.0, а не latest) Используйте семантические версии при наличии — проще сопровождать Предпочитайте публичные теги вместо хеша коммита (лучше отслеживаемость)"},{"id":"cli/generator/generator::git-remote-git-repository-input::24","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input)","content":"Удалённый Git репозиторий (Remote Git Repository Input)"},{"id":"cli/generator/generator::git-remote-git-repository-input::25","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) Параметр root задаёт корень для разрешения импортов файлов из этого репозитория.","content":"Удалённый Git репозиторий (Remote Git Repository Input) Параметр root задаёт корень для разрешения импортов файлов из этого репозитория."},{"id":"cli/generator/generator::git-remote-git-repository-input::26","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) **Параметры:**","content":"Удалённый Git репозиторий (Remote Git Repository Input) **Параметры:**"},{"id":"cli/generator/generator::git-remote-git-repository-input::27","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) Параметр Тип Обязателен По умолчанию Описание ---------- ----- ------------ -------------- ---------- url string ✅ - URL Git репозитория с необязательной версией / ","content":"Удалённый Git репозиторий (Remote Git Repository Input) Параметр Тип Обязателен По умолчанию Описание ---------- ----- ------------ -------------- ---------- url string ✅ - URL Git репозитория с необязательной версией / тегом / коммитом sub_directory string ❌ \"\" Поддиректория внутри репозитория, где лежат proto root string ❌ \"\" Корневой путь для разрешения импортов"},{"id":"cli/generator/generator::git-remote-git-repository-input::28","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) **Варианты формата URL:**","content":"Удалённый Git репозиторий (Remote Git Repository Input) **Варианты формата URL:**"},{"id":"cli/generator/generator::git-remote-git-repository-input::29","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) EasyP поддерживает несколько форматов для ссылки на удалённые репозитории. Каждый подходит под разные требования по стабильности:","content":"Удалённый Git репозиторий (Remote Git Repository Input) EasyP поддерживает несколько форматов для ссылки на удалённые репозитории. Каждый подходит под разные требования по стабильности:"},{"id":"cli/generator/generator::git-remote-git-repository-input::30","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) **Tagged versions** — для продакшена, стабильные неизменяемые ссылки **Semantic versions** — читаемость и управление зависимостями **Commit hashes** — доступ к конк","content":"Удалённый Git репозиторий (Remote Git Repository Input) **Tagged versions** — для продакшена, стабильные неизменяемые ссылки **Semantic versions** — читаемость и управление зависимостями **Commit hashes** — доступ к конкретному коммиту, если нет тега **Latest** — только для разработки, непредсказуемо **Full HTTPS URLs** — приватные репозитории или нестандартный хостинг"},{"id":"cli/generator/generator::git-remote-git-repository-input::31","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) ```yaml Тег — стабильно для продакшена url: \"github.com/googleapis/googleapis@common-protos-1_3_1\"","content":"Удалённый Git репозиторий (Remote Git Repository Input) ```yaml Тег — стабильно для продакшена url: \"github.com/googleapis/googleapis@common-protos-1_3_1\""},{"id":"cli/generator/generator::git-remote-git-repository-input::32","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) Семантическая версия url: \"github.com/grpc-ecosystem/grpc-gateway@v2.19.1\"","content":"Удалённый Git репозиторий (Remote Git Repository Input) Семантическая версия url: \"github.com/grpc-ecosystem/grpc-gateway@v2.19.1\""},{"id":"cli/generator/generator::git-remote-git-repository-input::33","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) Хеш коммита — точечный фикс url: \"github.com/company/protos@abc123def456\"","content":"Удалённый Git репозиторий (Remote Git Repository Input) Хеш коммита — точечный фикс url: \"github.com/company/protos@abc123def456\""},{"id":"cli/generator/generator::git-remote-git-repository-input::34","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) Latest — только dev, НЕ для продакшена url: \"github.com/company/protos\"","content":"Удалённый Git репозиторий (Remote Git Repository Input) Latest — только dev, НЕ для продакшена url: \"github.com/company/protos\""},{"id":"cli/generator/generator::git-remote-git-repository-input::35","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) Полный HTTPS URL — приватный или кастомный Git url: \"https://github.com/company/private-protos.git\" ```","content":"Удалённый Git репозиторий (Remote Git Repository Input) Полный HTTPS URL — приватный или кастомный Git url: \"https://github.com/company/private-protos.git\" ```"},{"id":"cli/generator/generator::git-remote-git-repository-input::36","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) **Примеры:**","content":"Удалённый Git репозиторий (Remote Git Repository Input) **Примеры:**"},{"id":"cli/generator/generator::git-remote-git-repository-input::37","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) Ниже паттерны использования удалённых источников в разных сценариях:","content":"Удалённый Git репозиторий (Remote Git Repository Input) Ниже паттерны использования удалённых источников в разных сценариях:"},{"id":"cli/generator/generator::git-remote-git-repository-input::38","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input)","content":"Удалённый Git репозиторий (Remote Git Repository Input)"},{"id":"cli/generator/generator::top::39","title":"Генератор","section":"Конфигурация плагинов","path":"/docs/guide/cli/generator/generator","headings":["Конфигурация плагинов"],"excerpt":"Конфигурация плагинов Конфигурация плагинов определяет какие генераторы кода будут запущены и как они себя ведут. EasyP поддерживает любой плагин protoc, что делает его крайне гибким для разных языковых экосистем и сцена","content":"Конфигурация плагинов Конфигурация плагинов определяет какие генераторы кода будут запущены и как они себя ведут. EasyP поддерживает любой плагин protoc, что делает его крайне гибким для разных языковых экосистем и сценариев."},{"id":"cli/generator/generator::top::40","title":"Генератор","section":"Конфигурация плагинов","path":"/docs/guide/cli/generator/generator","headings":["Конфигурация плагинов"],"excerpt":"Конфигурация плагинов На верхнем уровне есть **четыре способа указать, как именно запускать плагин**:","content":"Конфигурация плагинов На верхнем уровне есть **четыре способа указать, как именно запускать плагин**:"},{"id":"cli/generator/generator::top::41","title":"Генератор","section":"Конфигурация плагинов","path":"/docs/guide/cli/generator/generator","headings":["Конфигурация плагинов"],"excerpt":"Конфигурация плагинов **name** – запуск плагина по имени из PATH или использование встроенного плагина. **path** – запуск плагина по абсолютному/относительному пути к исполняемому файлу. **remote** – удалённый плагин по ","content":"Конфигурация плагинов **name** – запуск плагина по имени из PATH или использование встроенного плагина. **path** – запуск плагина по абсолютному/относительному пути к исполняемому файлу. **remote** – удалённый плагин по URL (через remote‑executor EasyP). **command** – запуск плагина через произвольную команду (например, go run ...)."},{"id":"cli/generator/generator::top::42","title":"Генератор","section":"Конфигурация плагинов","path":"/docs/guide/cli/generator/generator","headings":["Конфигурация плагинов"],"excerpt":"Конфигурация плагинов Для каждого плагина должен быть указан **ровно один** из параметров name, path, remote или command.","content":"Конфигурация плагинов Для каждого плагина должен быть указан **ровно один** из параметров name, path, remote или command."},{"id":"cli/generator/generator::name::43","title":"Генератор","section":"Плагин по имени (name)","path":"/docs/guide/cli/generator/generator#name","headings":["Плагин по имени (name)"],"excerpt":"Плагин по имени (name) Локальный режим по имени — стандартный: плагины установлены в системе и запускаются напрямую через EasyP.","content":"Плагин по имени (name) Локальный режим по имени — стандартный: плагины установлены в системе и запускаются напрямую через EasyP."},{"id":"cli/generator/generator::name::44","title":"Генератор","section":"Плагин по имени (name)","path":"/docs/guide/cli/generator/generator#name","headings":["Плагин по имени (name)"],"excerpt":"Плагин по имени (name) **Когда использовать name:** Стандартные языки (Go, Python, TypeScript и т.д.) Есть контроль над окружением сборки Критична производительность (нет сетевых задержек) Хочется опираться на PATH или в","content":"Плагин по имени (name) **Когда использовать name:** Стандартные языки (Go, Python, TypeScript и т.д.) Есть контроль над окружением сборки Критична производительность (нет сетевых задержек) Хочется опираться на PATH или встроенные плагины"},{"id":"cli/generator/generator::name::45","title":"Генератор","section":"Плагин по имени (name)","path":"/docs/guide/cli/generator/generator#name","headings":["Плагин по имени (name)"],"excerpt":"Плагин по имени (name) **Требования к установке:** Плагины установлены и доступны в PATH (если не используются встроенные). Имена следуют шаблону protoc-gen-{name}. Установка через менеджеры пакетов (go install, npm inst","content":"Плагин по имени (name) **Требования к установке:** Плагины установлены и доступны в PATH (если не используются встроенные). Имена следуют шаблону protoc-gen-{name}. Установка через менеджеры пакетов (go install, npm install, pip install и т.п.)."},{"id":"cli/generator/generator::name::46","title":"Генератор","section":"Плагин по имени (name)","path":"/docs/guide/cli/generator/generator#name","headings":["Плагин по имени (name)"],"excerpt":"Плагин по имени (name) Параметр with_imports критичен при использовании зависимостей из пакетного менеджера: установите true, чтобы прототипы из секции deps попали в генерацию.","content":"Плагин по имени (name) Параметр with_imports критичен при использовании зависимостей из пакетного менеджера: установите true, чтобы прототипы из секции deps попали в генерацию."},{"id":"cli/generator/generator::path::47","title":"Генератор","section":"Плагин по пути (path)","path":"/docs/guide/cli/generator/generator#path","headings":["Плагин по пути (path)"],"excerpt":"Плагин по пути (path) Иногда нужно запускать плагин из конкретного бинарника, не добавляя его в PATH (например, бинарь в репозитории или в build‑директории). В этом случае можно указать явный путь:","content":"Плагин по пути (path) Иногда нужно запускать плагин из конкретного бинарника, не добавляя его в PATH (например, бинарь в репозитории или в build‑директории). В этом случае можно указать явный путь:"},{"id":"cli/generator/generator::path::48","title":"Генератор","section":"Плагин по пути (path)","path":"/docs/guide/cli/generator/generator#path","headings":["Плагин по пути (path)"],"excerpt":"Плагин по пути (path) **Когда использовать path:** Бинарники плагинов хранятся в репозитории (для воспроизводимых сборок). Используются несколько версий одного и того же плагина параллельно. Не хочется «загрязнять» глоба","content":"Плагин по пути (path) **Когда использовать path:** Бинарники плагинов хранятся в репозитории (для воспроизводимых сборок). Используются несколько версий одного и того же плагина параллельно. Не хочется «загрязнять» глобальный PATH."},{"id":"cli/generator/generator::remote::49","title":"Генератор","section":"Удалённый плагин (remote)","path":"/docs/guide/cli/generator/generator#remote","headings":["Удалённый плагин (remote)"],"excerpt":"Удалённый плагин (remote) Удалённые плагины выполняются по URL. EasyP отправляет на удалённую сторону CodeGeneratorRequest и получает обратно CodeGeneratorResponse.","content":"Удалённый плагин (remote) Удалённые плагины выполняются по URL. EasyP отправляет на удалённую сторону CodeGeneratorRequest и получает обратно CodeGeneratorResponse."},{"id":"cli/generator/generator::remote::50","title":"Генератор","section":"Удалённый плагин (remote)","path":"/docs/guide/cli/generator/generator#remote","headings":["Удалённый плагин (remote)"],"excerpt":"Удалённый плагин (remote) Ниже приведён реальный пример использования EasyP API Service как удалённого исполнителя плагинов (тот же формат используется в разделе про API Service):","content":"Удалённый плагин (remote) Ниже приведён реальный пример использования EasyP API Service как удалённого исполнителя плагинов (тот же формат используется в разделе про API Service):"},{"id":"cli/generator/generator::remote::51","title":"Генератор","section":"Удалённый плагин (remote)","path":"/docs/guide/cli/generator/generator#remote","headings":["Удалённый плагин (remote)"],"excerpt":"Удалённый плагин (remote) ```yaml generate: plugins: # Удалённое выполнение плагинов через EasyP API Service - remote: api.easyp.tech/protobuf/go:v1.36.10 out: . opts: paths: source_relative","content":"Удалённый плагин (remote) ```yaml generate: plugins: # Удалённое выполнение плагинов через EasyP API Service - remote: api.easyp.tech/protobuf/go:v1.36.10 out: . opts: paths: source_relative"},{"id":"cli/generator/generator::remote::52","title":"Генератор","section":"Удалённый плагин (remote)","path":"/docs/guide/cli/generator/generator#remote","headings":["Удалённый плагин (remote)"],"excerpt":"Удалённый плагин (remote) remote: api.easyp.tech/grpc/go:v1.5.1 out: . opts: paths: source_relative ```","content":"Удалённый плагин (remote) remote: api.easyp.tech/grpc/go:v1.5.1 out: . opts: paths: source_relative ```"},{"id":"cli/generator/generator::remote::53","title":"Генератор","section":"Удалённый плагин (remote)","path":"/docs/guide/cli/generator/generator#remote","headings":["Удалённый плагин (remote)"],"excerpt":"Удалённый плагин (remote) **Типичные сценарии для remote:** Централизованный сервис плагинов внутри компании (например, EasyP API Service). Запуск тяжёлых плагинов на выделенных машинах вместо CI‑агентов. Совместное испо","content":"Удалённый плагин (remote) **Типичные сценарии для remote:** Централизованный сервис плагинов внутри компании (например, EasyP API Service). Запуск тяжёлых плагинов на выделенных машинах вместо CI‑агентов. Совместное использование одной реализации плагина разными командами."},{"id":"cli/generator/generator::command::54","title":"Генератор","section":"Выполнение плагина через команду (command)","path":"/docs/guide/cli/generator/generator#command","headings":["Выполнение плагина через команду (command)"],"excerpt":"Выполнение плагина через команду (command) Вы можете указать плагин как массив команд для выполнения. Это полезно для запуска плагинов через go run или любые другие инструменты без предварительной установки бинарника пла","content":"Выполнение плагина через команду (command) Вы можете указать плагин как массив команд для выполнения. Это полезно для запуска плагинов через go run или любые другие инструменты без предварительной установки бинарника плагина:"},{"id":"cli/generator/generator::command::55","title":"Генератор","section":"Выполнение плагина через команду (command)","path":"/docs/guide/cli/generator/generator#command","headings":["Выполнение плагина через команду (command)"],"excerpt":"Выполнение плагина через команду (command)","content":"Выполнение плагина через команду (command)"},{"id":"cli/generator/generator::command::56","title":"Генератор","section":"Выполнение плагина через команду (command)","path":"/docs/guide/cli/generator/generator#command","headings":["Выполнение плагина через команду (command)"],"excerpt":"Выполнение плагина через команду (command) В этом режиме EasyP: **запускает указанную команду** как дочерний процесс; **пишет CodeGeneratorRequest в stdin** процесса; **читает CodeGeneratorResponse из stdout**, как и для","content":"Выполнение плагина через команду (command) В этом режиме EasyP: **запускает указанную команду** как дочерний процесс; **пишет CodeGeneratorRequest в stdin** процесса; **читает CodeGeneratorResponse из stdout**, как и для обычных плагинов protoc."},{"id":"cli/generator/generator::command::57","title":"Генератор","section":"Выполнение плагина через команду (command)","path":"/docs/guide/cli/generator/generator#command","headings":["Выполнение плагина через команду (command)"],"excerpt":"Выполнение плагина через команду (command) **Приоритет источников плагина:** command — выполнение через указанную команду (наивысший приоритет) remote — удалённый плагин через URL name — локальный плагин из PATH или встр","content":"Выполнение плагина через команду (command) **Приоритет источников плагина:** command — выполнение через указанную команду (наивысший приоритет) remote — удалённый плагин через URL name — локальный плагин из PATH или встроенный плагин path — путь к исполняемому файлу плагина"},{"id":"cli/generator/generator::command::58","title":"Генератор","section":"Выполнение плагина через команду (command)","path":"/docs/guide/cli/generator/generator#command","headings":["Выполнение плагина через команду (command)"],"excerpt":"Выполнение плагина через команду (command) **Параметры (источники и общие опции плагина):**","content":"Выполнение плагина через команду (command) **Параметры (источники и общие опции плагина):**"},{"id":"cli/generator/generator::command::59","title":"Генератор","section":"Выполнение плагина через команду (command)","path":"/docs/guide/cli/generator/generator#command","headings":["Выполнение плагина через команду (command)"],"excerpt":"Выполнение плагина через команду (command) Параметр Тип Обязателен По умолчанию Описание ---------- ----- ------------ -------------- ---------- name string ❌ - Имя / идентификатор плагина (например, go, go-grpc, grpc-ga","content":"Выполнение плагина через команду (command) Параметр Тип Обязателен По умолчанию Описание ---------- ----- ------------ -------------- ---------- name string ❌ - Имя / идентификатор плагина (например, go, go-grpc, grpc-gateway) command []string ❌ - Команда для выполнения плагина (например, [\"go\", \"run\", \"package\"]) remote string ❌ - URL удалённого плагина path string ❌ - Путь к исполняемому файлу плагина out string ✅ - Директория для сгенерированных файлов opts mapstring ❌ {} Специфичные опции плагина; значения-списки передаются как повторяющиеся key=value with_imports bool ❌ false Включать proto из зависимостей"},{"id":"cli/generator/generator::command::60","title":"Генератор","section":"Выполнение плагина через команду (command)","path":"/docs/guide/cli/generator/generator#command","headings":["Выполнение плагина через команду (command)"],"excerpt":"Выполнение плагина через команду (command) **Примечание:** Для каждого плагина должен быть указан ровно один источник (name, command, remote или path). Если opts.outputServices задан как [\"grpc-js\", \"generic-definitions\"","content":"Выполнение плагина через команду (command) **Примечание:** Для каждого плагина должен быть указан ровно один источник (name, command, remote или path). Если opts.outputServices задан как [\"grpc-js\", \"generic-definitions\"], EasyP передаст outputServices=grpc-js,outputServices=generic-definitions."},{"id":"cli/generator/generator::command::61","title":"Генератор","section":"Выполнение плагина через команду (command)","path":"/docs/guide/cli/generator/generator#command","headings":["Выполнение плагина через команду (command)"],"excerpt":"Выполнение плагина через команду (command) **Примеры использования источника command:**","content":"Выполнение плагина через команду (command) **Примеры использования источника command:**"},{"id":"cli/generator/generator::command::62","title":"Генератор","section":"Выполнение плагина через команду (command)","path":"/docs/guide/cli/generator/generator#command","headings":["Выполнение плагина через команду (command)"],"excerpt":"Выполнение плагина через команду (command) ```yaml generate: inputs: - directory: \"proto\"","content":"Выполнение плагина через команду (command) ```yaml generate: inputs: - directory: \"proto\""},{"id":"cli/generator/generator::command::63","title":"Генератор","section":"Выполнение плагина через команду (command)","path":"/docs/guide/cli/generator/generator#command","headings":["Выполнение плагина через команду (command)"],"excerpt":"Выполнение плагина через команду (command) plugins: # 1) gRPC-Gateway через go run (без предварительной установки бинарника) - command: [\"go\", \"run\", \"github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway@v2.","content":"Выполнение плагина через команду (command) plugins: # 1) gRPC-Gateway через go run (без предварительной установки бинарника) - 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::command::64","title":"Генератор","section":"Выполнение плагина через команду (command)","path":"/docs/guide/cli/generator/generator#command","headings":["Выполнение плагина через команду (command)"],"excerpt":"Выполнение плагина через команду (command) 2) protoc-gen-validate через go run - command: [\"go\", \"run\", \"github.com/bufbuild/protoc-gen-validate@v0.10.1\"] out: ./gen/go opts: paths: source_relative lang: go","content":"Выполнение плагина через команду (command) 2) protoc-gen-validate через 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::command::65","title":"Генератор","section":"Выполнение плагина через команду (command)","path":"/docs/guide/cli/generator/generator#command","headings":["Выполнение плагина через команду (command)"],"excerpt":"Выполнение плагина через команду (command) 3) Произвольный кастомный скрипт-обёртка - command: [\"bash\", \"./scripts/custom-protoc-plugin.sh\"] out: ./gen/custom opts: foo: bar ```","content":"Выполнение плагина через команду (command) 3) Произвольный кастомный скрипт-обёртка - command: [\"bash\", \"./scripts/custom-protoc-plugin.sh\"] out: ./gen/custom opts: foo: bar ```"},{"id":"cli/generator/generator::builtin-plugins::66","title":"Генератор","section":"Встроенные плагины (Builtin Plugins)","path":"/docs/guide/cli/generator/generator#builtin-plugins","headings":["Встроенные плагины (Builtin Plugins)"],"excerpt":"Встроенные плагины (Builtin Plugins) EasyP поддерживает встроенные плагины для базовых языков protobuf и gRPC. Эти плагины встроены в бинарник как WASM-модули и не требуют установки внешних зависимостей.","content":"Встроенные плагины (Builtin Plugins) EasyP поддерживает встроенные плагины для базовых языков protobuf и gRPC. Эти плагины встроены в бинарник как WASM-модули и не требуют установки внешних зависимостей."},{"id":"cli/generator/generator::builtin-plugins::67","title":"Генератор","section":"Встроенные плагины (Builtin Plugins)","path":"/docs/guide/cli/generator/generator#builtin-plugins","headings":["Встроенные плагины (Builtin Plugins)"],"excerpt":"Встроенные плагины (Builtin Plugins) **Преимущества встроенных плагинов:** **Портативность**: Один бинарник со всеми необходимыми плагинами **Удобство**: Не требуется установка внешних зависимостей **Стабильность**: Верс","content":"Встроенные плагины (Builtin Plugins) **Преимущества встроенных плагинов:** **Портативность**: Один бинарник со всеми необходимыми плагинами **Удобство**: Не требуется установка внешних зависимостей **Стабильность**: Версии плагинов зафиксированы в бинарнике **Изоляция**: Не зависит от системных установок плагинов"},{"id":"cli/generator/generator::builtin-plugins::68","title":"Генератор","section":"Встроенные плагины (Builtin Plugins)","path":"/docs/guide/cli/generator/generator#builtin-plugins","headings":["Встроенные плагины (Builtin Plugins)"],"excerpt":"Встроенные плагины (Builtin Plugins) **Поддерживаемые встроенные плагины:**","content":"Встроенные плагины (Builtin Plugins) **Поддерживаемые встроенные плагины:**"},{"id":"cli/generator/generator::protobuf::69","title":"Генератор","section":"Protobuf базовые плагины","path":"/docs/guide/cli/generator/generator#protobuf","headings":["Protobuf базовые плагины"],"excerpt":"Protobuf базовые плагины Следующие плагины встроены для генерации базового protobuf кода:","content":"Protobuf базовые плагины Следующие плагины встроены для генерации базового protobuf кода:"},{"id":"cli/generator/generator::protobuf::70","title":"Генератор","section":"Protobuf базовые плагины","path":"/docs/guide/cli/generator/generator#protobuf","headings":["Protobuf базовые плагины"],"excerpt":"Protobuf базовые плагины Имя плагина Описание Соответствующий protoc плагин ------------- ---------- ------------------------------- cpp Генерация C++ кода из proto файлов protoc-gen-cpp csharp Генерация C# кода из proto","content":"Protobuf базовые плагины Имя плагина Описание Соответствующий protoc плагин ------------- ---------- ------------------------------- cpp Генерация C++ кода из proto файлов protoc-gen-cpp csharp Генерация C# кода из proto файлов protoc-gen-csharp java Генерация Java кода из proto файлов protoc-gen-java kotlin Генерация Kotlin кода из proto файлов protoc-gen-kotlin objc Генерация Objective-C кода из proto файлов protoc-gen-objc php Генерация PHP кода из proto файлов protoc-gen-php python Генерация Python кода из proto файлов protoc-gen-python ruby Генерация Ruby кода из proto файлов protoc-gen-ruby"},{"id":"cli/generator/generator::grpc::71","title":"Генератор","section":"gRPC плагины","path":"/docs/guide/cli/generator/generator#grpc","headings":["gRPC плагины"],"excerpt":"gRPC плагины Следующие плагины встроены для генерации gRPC кода:","content":"gRPC плагины Следующие плагины встроены для генерации gRPC кода:"},{"id":"cli/generator/generator::grpc::72","title":"Генератор","section":"gRPC плагины","path":"/docs/guide/cli/generator/generator#grpc","headings":["gRPC плагины"],"excerpt":"gRPC плагины Имя плагина Описание Соответствующий protoc плагин ------------- ---------- ------------------------------- grpc_cpp Генерация gRPC кода для C++ grpc_cpp_plugin grpc_csharp Генерация gRPC кода для C# grpc_cs","content":"gRPC плагины Имя плагина Описание Соответствующий protoc плагин ------------- ---------- ------------------------------- grpc_cpp Генерация gRPC кода для C++ grpc_cpp_plugin grpc_csharp Генерация gRPC кода для C# grpc_csharp_plugin grpc_java Генерация gRPC кода для Java grpc_java_plugin grpc_node Генерация gRPC кода для Node.js grpc_node_plugin grpc_objc Генерация gRPC кода для Objective-C grpc_objective_c_plugin grpc_php Генерация gRPC кода для PHP grpc_php_plugin grpc_python Генерация gRPC кода для Python grpc_python_plugin grpc_ruby Генерация gRPC кода для Ruby grpc_ruby_plugin"},{"id":"cli/generator/generator::grpc::73","title":"Генератор","section":"gRPC плагины","path":"/docs/guide/cli/generator/generator#grpc","headings":["gRPC плагины"],"excerpt":"gRPC плагины **Логика выбора плагина:**","content":"gRPC плагины **Логика выбора плагина:**"},{"id":"cli/generator/generator::grpc::74","title":"Генератор","section":"gRPC плагины","path":"/docs/guide/cli/generator/generator#grpc","headings":["gRPC плагины"],"excerpt":"gRPC плагины EasyP использует следующий приоритет при выборе executor'а для плагина:","content":"gRPC плагины EasyP использует следующий приоритет при выборе executor'а для плагина:"},{"id":"cli/generator/generator::grpc::75","title":"Генератор","section":"gRPC плагины","path":"/docs/guide/cli/generator/generator#grpc","headings":["gRPC плагины"],"excerpt":"gRPC плагины **Удалённый плагин** (если указан url) — всегда имеет наивысший приоритет **Встроенный плагин** (если плагин встроен и не найден в PATH) — используется автоматически **Локальный плагин** (из PATH) — использу","content":"gRPC плагины **Удалённый плагин** (если указан url) — всегда имеет наивысший приоритет **Встроенный плагин** (если плагин встроен и не найден в PATH) — используется автоматически **Локальный плагин** (из PATH) — используется по умолчанию для обратной совместимости"},{"id":"cli/generator/generator::grpc::76","title":"Генератор","section":"gRPC плагины","path":"/docs/guide/cli/generator/generator#grpc","headings":["gRPC плагины"],"excerpt":"gRPC плагины **Пример использования:**","content":"gRPC плагины **Пример использования:**"},{"id":"cli/generator/generator::grpc::77","title":"Генератор","section":"gRPC плагины","path":"/docs/guide/cli/generator/generator#grpc","headings":["gRPC плагины"],"excerpt":"gRPC плагины Встроенные плагины включены в бинарник EasyP:","content":"gRPC плагины Встроенные плагины включены в бинарник EasyP:"},{"id":"cli/generator/generator::grpc::78","title":"Генератор","section":"gRPC плагины","path":"/docs/guide/cli/generator/generator#grpc","headings":["gRPC плагины"],"excerpt":"gRPC плагины ```bash Сборка go build ./cmd/easyp","content":"gRPC плагины ```bash Сборка go build ./cmd/easyp"},{"id":"cli/generator/generator::grpc::79","title":"Генератор","section":"gRPC плагины","path":"/docs/guide/cli/generator/generator#grpc","headings":["gRPC плагины"],"excerpt":"gRPC плагины Установка go install github.com/easyp-tech/easyp/cmd/easyp@latest ```","content":"gRPC плагины Установка go install github.com/easyp-tech/easyp/cmd/easyp@latest ```"},{"id":"cli/generator/generator::grpc::80","title":"Генератор","section":"gRPC плагины","path":"/docs/guide/cli/generator/generator#grpc","headings":["gRPC плагины"],"excerpt":"gRPC плагины **Обратная совместимость:**","content":"gRPC плагины **Обратная совместимость:**"},{"id":"cli/generator/generator::grpc::81","title":"Генератор","section":"gRPC плагины","path":"/docs/guide/cli/generator/generator#grpc","headings":["gRPC плагины"],"excerpt":"gRPC плагины Встроенные плагины полностью совместимы с существующими конфигурациями. Если плагин найден в PATH, он будет использован вместо встроенного. Это гарантирует, что:","content":"gRPC плагины Встроенные плагины полностью совместимы с существующими конфигурациями. Если плагин найден в PATH, он будет использован вместо встроенного. Это гарантирует, что:"},{"id":"cli/generator/generator::grpc::82","title":"Генератор","section":"gRPC плагины","path":"/docs/guide/cli/generator/generator#grpc","headings":["gRPC плагины"],"excerpt":"gRPC плагины Существующие конфигурации продолжают работать без изменений Можно переопределить встроенный плагин, установив его в системе Приоритет отдаётся локальным установкам для гибкости","content":"gRPC плагины Существующие конфигурации продолжают работать без изменений Можно переопределить встроенный плагин, установив его в системе Приоритет отдаётся локальным установкам для гибкости"},{"id":"cli/generator/generator::top::83","title":"Генератор","section":"Справочник опций плагинов","path":"/docs/guide/cli/generator/generator","headings":["Справочник опций плагинов"],"excerpt":"Справочник опций плагинов Ниже перечислены наиболее часто используемые плагины и их настройки. Каждый плагин имеет параметры, влияющие на результат генерации — понимание этих опций важно для получения нужного вывода.","content":"Справочник опций плагинов Ниже перечислены наиболее часто используемые плагины и их настройки. Каждый плагин имеет параметры, влияющие на результат генерации — понимание этих опций важно для получения нужного вывода."},{"id":"cli/generator/generator::go-plugins::84","title":"Генератор","section":"Go Plugins","path":"/docs/guide/cli/generator/generator#go-plugins","headings":["Go Plugins"],"excerpt":"Go Plugins Плагины для Go — самые зрелые и распространённые. Опция paths управляет тем, как формируются пути импортов; остальные опции дают тонкую настройку вывода.","content":"Go Plugins Плагины для Go — самые зрелые и распространённые. Опция paths управляет тем, как формируются пути импортов; остальные опции дают тонкую настройку вывода."},{"id":"cli/generator/generator::grpc-gateway-plugins::85","title":"Генератор","section":"gRPC-Gateway Plugins","path":"/docs/guide/cli/generator/generator#grpc-gateway-plugins","headings":["gRPC-Gateway Plugins"],"excerpt":"gRPC-Gateway Plugins Позволяют экспонировать gRPC сервисы как REST API и генерировать OpenAPI. Критично для HTTP/JSON поверх gRPC.","content":"gRPC-Gateway Plugins Позволяют экспонировать gRPC сервисы как REST API и генерировать OpenAPI. Критично для HTTP/JSON поверх gRPC."},{"id":"cli/generator/generator::validation-plugins::86","title":"Генератор","section":"Validation Plugins","path":"/docs/guide/cli/generator/generator#validation-plugins","headings":["Validation Plugins"],"excerpt":"Validation Plugins Генерируют код валидации на основе правил в proto, устраняя ручную проверку.","content":"Validation Plugins Генерируют код валидации на основе правил в proto, устраняя ручную проверку."},{"id":"cli/generator/generator::typescriptjavascript-plugins::87","title":"Генератор","section":"TypeScript/JavaScript Plugins","path":"/docs/guide/cli/generator/generator#typescriptjavascript-plugins","headings":["TypeScript/JavaScript Plugins"],"excerpt":"TypeScript/JavaScript Plugins TypeScript плагины нужны фронтенду: типобезопасные интерфейсы и клиенты.","content":"TypeScript/JavaScript Plugins TypeScript плагины нужны фронтенду: типобезопасные интерфейсы и клиенты."},{"id":"cli/generator/generator::managed-mode::88","title":"Генератор","section":"Managed Mode","path":"/docs/guide/cli/generator/generator#managed-mode","headings":["Managed Mode"],"excerpt":"Managed Mode Managed mode автоматически устанавливает file и field опции в protobuf дескрипторах во время генерации кода без изменения исходных .proto файлов. Эта функция совместима с managed mode в buf и обеспечивает ед","content":"Managed Mode Managed mode автоматически устанавливает file и field опции в protobuf дескрипторах во время генерации кода без изменения исходных .proto файлов. Эта функция совместима с managed mode в buf и обеспечивает единообразный способ управления языково-специфичными опциями в вашей кодовой базе."},{"id":"cli/generator/generator::managed-mode::89","title":"Генератор","section":"Managed Mode","path":"/docs/guide/cli/generator/generator#managed-mode","headings":["Managed Mode"],"excerpt":"Managed Mode **Ключевые преимущества:** **Без изменений proto файлов**: Опции применяются во время генерации, proto файлы остаются чистыми **Согласованные значения по умолчанию**: Автоматическое применение языковых согла","content":"Managed Mode **Ключевые преимущества:** **Без изменений proto файлов**: Опции применяются во время генерации, proto файлы остаются чистыми **Согласованные значения по умолчанию**: Автоматическое применение языковых соглашений об именовании **Централизованная конфигурация**: Управление всеми опциями в одном месте (easyp.yaml) **Правила для модулей**: Применение разных опций к разным модулям или путям **Совместимость с buf**: Работает так же, как managed mode в buf"},{"id":"cli/generator/generator::top::90","title":"Генератор","section":"Как это работает","path":"/docs/guide/cli/generator/generator","headings":["Как это работает"],"excerpt":"Как это работает Когда managed mode включён, EasyP автоматически применяет file и field опции к protobuf дескрипторам перед генерацией кода. Это происходит в памяти, поэтому исходные .proto файлы остаются неизменными.","content":"Как это работает Когда managed mode включён, EasyP автоматически применяет file и field опции к protobuf дескрипторам перед генерацией кода. Это происходит в памяти, поэтому исходные .proto файлы остаются неизменными."},{"id":"cli/generator/generator::top::91","title":"Генератор","section":"Как это работает","path":"/docs/guide/cli/generator/generator","headings":["Как это работает"],"excerpt":"Как это работает **Значения по умолчанию** применяются для определённых опций на основе языковых соглашений: Java: java_package_prefix по умолчанию \"com\", java_multiple_files по умолчанию true C#: csharp_namespace по умо","content":"Как это работает **Значения по умолчанию** применяются для определённых опций на основе языковых соглашений: Java: java_package_prefix по умолчанию \"com\", java_multiple_files по умолчанию true C#: csharp_namespace по умолчанию PascalCase имени пакета Ruby: ruby_package по умолчанию PascalCase с разделителем :: PHP: php_namespace по умолчанию PascalCase с разделителем \\ Objective-C: objc_class_prefix по умолчанию первые буквы частей пакета C++: cc_enable_arenas по умолчанию true"},{"id":"cli/generator/generator::top::92","title":"Генератор","section":"Как это работает","path":"/docs/guide/cli/generator/generator","headings":["Как это работает"],"excerpt":"Как это работает **Overrides** позволяют установить конкретные значения для опций с поддержкой фильтрации по модулю, пути или полю.","content":"Как это работает **Overrides** позволяют установить конкретные значения для опций с поддержкой фильтрации по модулю, пути или полю."},{"id":"cli/generator/generator::top::93","title":"Генератор","section":"Как это работает","path":"/docs/guide/cli/generator/generator","headings":["Как это работает"],"excerpt":"Как это работает **Disables** позволяют предотвратить изменение managed mode определённых опций или файлов.","content":"Как это работает **Disables** позволяют предотвратить изменение managed mode определённых опций или файлов."},{"id":"cli/generator/generator::file-options::94","title":"Генератор","section":"Поддерживаемые File Options","path":"/docs/guide/cli/generator/generator#file-options","headings":["Поддерживаемые File Options"],"excerpt":"Поддерживаемые File Options Опция Описание Есть значение по умолчанию? ------- ---------- ---------------------------- go_package Go import path ❌ go_package_prefix Префикс для Go import paths ❌ java_package Имя Java пак","content":"Поддерживаемые File Options Опция Описание Есть значение по умолчанию? ------- ---------- ---------------------------- go_package Go import path ❌ go_package_prefix Префикс для Go import paths ❌ java_package Имя Java пакета ❌ java_package_prefix Префикс для Java пакетов ✅ (\"com\") java_package_suffix Суффикс для Java пакетов ❌ java_multiple_files Генерировать несколько Java файлов ✅ (true) java_outer_classname Имя внешнего класса ✅ (PascalCase + \"Proto\") java_string_check_utf8 UTF-8 валидация ❌ csharp_namespace C# namespace ✅ (PascalCase) csharp_namespace_prefix Префикс для C# namespaces ❌ ruby_package Имя Ruby модуля ✅ (PascalCase с ::) ruby_package_suffix Суффикс для Ruby пакетов ❌ php_namespace PHP namespace ✅ (PascalCase с \\) php_metadata_namespace PHP metadata namespace ❌ php_metadata_namespace_suffix Суффикс для PHP metadata ❌ objc_class_prefix Objective-C префикс класса ✅ (Первые буквы) swift_prefix Swift префикс ❌ optimize_for Оптимизация генерации кода ❌ cc_enable_arenas C++ arena аллокация ✅ (true)"},{"id":"cli/generator/generator::field-options::95","title":"Генератор","section":"Поддерживаемые Field Options","path":"/docs/guide/cli/generator/generator#field-options","headings":["Поддерживаемые Field Options"],"excerpt":"Поддерживаемые Field Options Опция Описание Применяется к ------- ---------- --------------- jstype JavaScript тип для 64-битных целых чисел int64, uint64, sint64, fixed64, sfixed64","content":"Поддерживаемые Field Options Опция Описание Применяется к ------- ---------- --------------- jstype JavaScript тип для 64-битных целых чисел int64, uint64, sint64, fixed64, sfixed64"},{"id":"cli/generator/generator::top::96","title":"Генератор","section":"Базовая настройка со значениями по умолчанию","path":"/docs/guide/cli/generator/generator","headings":["Базовая настройка со значениями по умолчанию"],"excerpt":"Базовая настройка со значениями по умолчанию Включите managed mode для получения автоматических значений по умолчанию для всех поддерживаемых языков:","content":"Базовая настройка со значениями по умолчанию Включите managed mode для получения автоматических значений по умолчанию для всех поддерживаемых языков:"},{"id":"cli/generator/generator::top::97","title":"Генератор","section":"Базовая настройка со значениями по умолчанию","path":"/docs/guide/cli/generator/generator","headings":["Базовая настройка со значениями по умолчанию"],"excerpt":"Базовая настройка со значениями по умолчанию","content":"Базовая настройка со значениями по умолчанию"},{"id":"cli/generator/generator::top::98","title":"Генератор","section":"Базовая настройка со значениями по умолчанию","path":"/docs/guide/cli/generator/generator","headings":["Базовая настройка со значениями по умолчанию"],"excerpt":"Базовая настройка со значениями по умолчанию Это автоматически установит: java_package в com. для всех файлов java_multiple_files в true csharp_namespace в PascalCase имени пакета ruby_package в PascalCase с разделителем","content":"Базовая настройка со значениями по умолчанию Это автоматически установит: java_package в com. для всех файлов java_multiple_files в true csharp_namespace в PascalCase имени пакета ruby_package в PascalCase с разделителем :: И многое другое..."},{"id":"cli/generator/generator::go::99","title":"Генератор","section":"Кастомный префикс Go пакета","path":"/docs/guide/cli/generator/generator#go","headings":["Кастомный префикс Go пакета"],"excerpt":"Кастомный префикс Go пакета Переопределите префикс Go пакета для вашего проекта:","content":"Кастомный префикс Go пакета Переопределите префикс Go пакета для вашего проекта:"},{"id":"cli/generator/generator::go::100","title":"Генератор","section":"Кастомный префикс Go пакета","path":"/docs/guide/cli/generator/generator#go","headings":["Кастомный префикс Go пакета"],"excerpt":"Кастомный префикс Go пакета Это установит go_package в github.com/mycompany/myproject/gen/go/ для всех файлов.","content":"Кастомный префикс Go пакета Это установит go_package в github.com/mycompany/myproject/gen/go/ для всех файлов."},{"id":"cli/generator/generator::go::101","title":"Генератор","section":"Динамические пути Go пакетов с маркерами","path":"/docs/guide/cli/generator/generator#go","headings":["Динамические пути Go пакетов с маркерами"],"excerpt":"Динамические пути Go пакетов с маркерами Для более сложной генерации путей можно использовать маркеры в значениях go_package_prefix или go_package:","content":"Динамические пути Go пакетов с маркерами Для более сложной генерации путей можно использовать маркеры в значениях go_package_prefix или go_package:"},{"id":"cli/generator/generator::go::102","title":"Генератор","section":"Динамические пути Go пакетов с маркерами","path":"/docs/guide/cli/generator/generator#go","headings":["Динамические пути Go пакетов с маркерами"],"excerpt":"Динамические пути Go пакетов с маркерами","content":"Динамические пути Go пакетов с маркерами"},{"id":"cli/generator/generator::go::103","title":"Генератор","section":"Динамические пути Go пакетов с маркерами","path":"/docs/guide/cli/generator/generator#go","headings":["Динамические пути Go пакетов с маркерами"],"excerpt":"Динамические пути Go пакетов с маркерами **Доступные маркеры:** {{file_path}} - Полный путь файла без расширения .proto - Пример: internal/cms/as.proto → internal/cms/as {{file_dir}} - Только путь директории, без имени ф","content":"Динамические пути Go пакетов с маркерами **Доступные маркеры:** {{file_path}} - Полный путь файла без расширения .proto - Пример: internal/cms/as.proto → internal/cms/as {{file_dir}} - Только путь директории, без имени файла - Пример: internal/cms/as.proto → internal/cms {{file_dir_without:prefix/}} - Путь директории с удалением префикса и базового имени файла без суффиксов _service/_grpc - Пример: {{file_dir_without:internal/}} для internal/cms/as_service.proto → cms/as {{file_path_without:prefix/}} - Полный путь файла с удалением префикса - Пример: {{file_path_without:internal/}} для internal/cms/as.proto → cms/as"},{"id":"cli/generator/generator::top::104","title":"Генератор","section":"Переопределения для конкретных модулей","path":"/docs/guide/cli/generator/generator","headings":["Переопределения для конкретных модулей"],"excerpt":"Переопределения для конкретных модулей Примените разные опции к разным модулям:","content":"Переопределения для конкретных модулей Примените разные опции к разным модулям:"},{"id":"cli/generator/generator::top::105","title":"Генератор","section":"Переопределения для конкретных модулей","path":"/docs/guide/cli/generator/generator","headings":["Переопределения для конкретных модулей"],"excerpt":"Переопределения для конкретных модулей","content":"Переопределения для конкретных модулей"},{"id":"cli/generator/generator::top::106","title":"Генератор","section":"Отключение для внешних зависимостей","path":"/docs/guide/cli/generator/generator","headings":["Отключение для внешних зависимостей"],"excerpt":"Отключение для внешних зависимостей Отключите managed mode для внешних зависимостей, у которых уже установлены опции:","content":"Отключение для внешних зависимостей Отключите managed mode для внешних зависимостей, у которых уже установлены опции:"},{"id":"cli/generator/generator::top::107","title":"Генератор","section":"Отключение для внешних зависимостей","path":"/docs/guide/cli/generator/generator","headings":["Отключение для внешних зависимостей"],"excerpt":"Отключение для внешних зависимостей","content":"Отключение для внешних зависимостей"},{"id":"cli/generator/generator::javascript::108","title":"Генератор","section":"Типобезопасность JavaScript","path":"/docs/guide/cli/generator/generator#javascript","headings":["Типобезопасность JavaScript"],"excerpt":"Типобезопасность JavaScript Установите jstype в JS_STRING для всех 64-битных целочисленных полей, чтобы предотвратить потерю точности в JavaScript:","content":"Типобезопасность JavaScript Установите jstype в JS_STRING для всех 64-битных целочисленных полей, чтобы предотвратить потерю точности в JavaScript:"},{"id":"cli/generator/generator::top::109","title":"Генератор","section":"Совпадение путей","path":"/docs/guide/cli/generator/generator","headings":["Совпадение путей"],"excerpt":"Совпадение путей Совпадение путей в managed mode использует префиксное совпадение (как в buf):","content":"Совпадение путей Совпадение путей в managed mode использует префиксное совпадение (как в buf):"},{"id":"cli/generator/generator::top::110","title":"Генератор","section":"Совпадение путей","path":"/docs/guide/cli/generator/generator","headings":["Совпадение путей"],"excerpt":"Совпадение путей **Путь директории** (заканчивается на /): Совпадает со всеми файлами в этой директории и поддиректориях - Пример: path: \"internal/cms/\" совпадает с internal/cms/as.proto, internal/cms/node.proto, interna","content":"Совпадение путей **Путь директории** (заканчивается на /): Совпадает со всеми файлами в этой директории и поддиректориях - Пример: path: \"internal/cms/\" совпадает с internal/cms/as.proto, internal/cms/node.proto, internal/cms/v1/service.proto **Точный путь файла** (заканчивается на .proto): Совпадает только с этим конкретным файлом - Пример: path: \"internal/cms/as.proto\" совпадает только с internal/cms/as.proto **Префиксный путь** (без завершающего / или .proto): Использует префиксное совпадение (не директориально-осознанное) - Пример: path: \"internal/cms\" совпадает с internal/cms/as.proto, но также с internal/cmsv2/file.proto - **Совет**: Используйте префиксные пути для группировки нескольких файлов с одинаковым значением. Например, path: \"internal/cms/bmi\" совпадает и с internal/cms/bmi.proto, и с internal/cms/bmi_service.proto, что позволяет установить одно и то же значение go_package для обоих файлов одним правилом."},{"id":"cli/generator/generator::top::111","title":"Генератор","section":"Приоритет правил","path":"/docs/guide/cli/generator/generator","headings":["Приоритет правил"],"excerpt":"Приоритет правил Когда несколько правил соответствуют одному файлу или полю, применяется следующий приоритет:","content":"Приоритет правил Когда несколько правил соответствуют одному файлу или полю, применяется следующий приоритет:"},{"id":"cli/generator/generator::top::112","title":"Генератор","section":"Приоритет правил","path":"/docs/guide/cli/generator/generator","headings":["Приоритет правил"],"excerpt":"Приоритет правил **Disable правила** имеют приоритет — если опция отключена, она не будет применена **Override правила** применяются по порядку — последнее совпадающее правило побеждает **Значения по умолчанию** применяю","content":"Приоритет правил **Disable правила** имеют приоритет — если опция отключена, она не будет применена **Override правила** применяются по порядку — последнее совпадающее правило побеждает **Значения по умолчанию** применяются только если нет совпадающего override и опция не отключена"},{"id":"cli/generator/generator::buf::113","title":"Генератор","section":"Совместимость с buf","path":"/docs/guide/cli/generator/generator#buf","headings":["Совместимость с buf"],"excerpt":"Совместимость с buf Managed mode в EasyP совместим с managed mode в buf. Тот же формат конфигурации и поведение применяются, что упрощает миграцию между инструментами или использование обоих в одном workflow.","content":"Совместимость с buf Managed mode в EasyP совместим с managed mode в buf. Тот же формат конфигурации и поведение применяются, что упрощает миграцию между инструментами или использование обоих в одном workflow."},{"id":"cli/generator/generator::descriptor-set::114","title":"Генератор","section":"Генерация Descriptor Set","path":"/docs/guide/cli/generator/generator#descriptor-set","headings":["Генерация Descriptor Set"],"excerpt":"Генерация Descriptor Set **https://protobuf.dev/programming-guides/techniques/#self-description**","content":"Генерация Descriptor Set **https://protobuf.dev/programming-guides/techniques/#self-description**"},{"id":"cli/generator/generator::descriptor-set::115","title":"Генератор","section":"Генерация Descriptor Set","path":"/docs/guide/cli/generator/generator#descriptor-set","headings":["Генерация Descriptor Set"],"excerpt":"Генерация Descriptor Set EasyP поддерживает генерацию бинарных FileDescriptorSet файлов с помощью флага --descriptor_set_out. Это позволяет создавать самоописывающиеся protobuf сообщения, которые включают информацию о сх","content":"Генерация Descriptor Set EasyP поддерживает генерацию бинарных FileDescriptorSet файлов с помощью флага --descriptor_set_out. Это позволяет создавать самоописывающиеся protobuf сообщения, которые включают информацию о схеме вместе с данными."},{"id":"cli/generator/generator::descriptor-set::116","title":"Генератор","section":"Генерация Descriptor Set","path":"/docs/guide/cli/generator/generator#descriptor-set","headings":["Генерация Descriptor Set"],"excerpt":"Генерация Descriptor Set **Флаги CLI:**","content":"Генерация Descriptor Set **Флаги CLI:**"},{"id":"cli/generator/generator::descriptor-set::117","title":"Генератор","section":"Генерация Descriptor Set","path":"/docs/guide/cli/generator/generator#descriptor-set","headings":["Генерация Descriptor Set"],"excerpt":"Генерация Descriptor Set --descriptor_set_out - Путь для вывода бинарного FileDescriptorSet --include_imports - Включить все транзитивные зависимости в FileDescriptorSet","content":"Генерация Descriptor Set --descriptor_set_out - Путь для вывода бинарного FileDescriptorSet --include_imports - Включить все транзитивные зависимости в FileDescriptorSet"},{"id":"cli/generator/generator::descriptor-set::118","title":"Генератор","section":"Генерация Descriptor Set","path":"/docs/guide/cli/generator/generator#descriptor-set","headings":["Генерация Descriptor Set"],"excerpt":"Генерация Descriptor Set **Пример:**","content":"Генерация Descriptor Set **Пример:**"},{"id":"cli/generator/generator::descriptor-set::119","title":"Генератор","section":"Генерация Descriptor Set","path":"/docs/guide/cli/generator/generator#descriptor-set","headings":["Генерация Descriptor Set"],"excerpt":"Генерация Descriptor Set ```bash Генерация descriptor set только с целевыми файлами easyp generate --descriptor_set_out=./schema.pb","content":"Генерация Descriptor Set ```bash Генерация descriptor set только с целевыми файлами easyp generate --descriptor_set_out=./schema.pb"},{"id":"cli/generator/generator::descriptor-set::120","title":"Генератор","section":"Генерация Descriptor Set","path":"/docs/guide/cli/generator/generator#descriptor-set","headings":["Генерация Descriptor Set"],"excerpt":"Генерация Descriptor Set Генерация descriptor set со всеми зависимостями easyp generate --descriptor_set_out=./schema.pb --include_imports ```","content":"Генерация Descriptor Set Генерация descriptor set со всеми зависимостями easyp generate --descriptor_set_out=./schema.pb --include_imports ```"},{"id":"cli/generator/generator::descriptor-set::121","title":"Генератор","section":"Генерация Descriptor Set","path":"/docs/guide/cli/generator/generator#descriptor-set","headings":["Генерация Descriptor Set"],"excerpt":"Генерация Descriptor Set Самоописывающиеся сообщения полезны для динамического парсинга сообщений, валидации схемы во время выполнения, реестров схем и создания универсальных gRPC клиентов. Для получения дополнительной и","content":"Генерация Descriptor Set Самоописывающиеся сообщения полезны для динамического парсинга сообщений, валидации схемы во время выполнения, реестров схем и создания универсальных gRPC клиентов. Для получения дополнительной информации см. документацию Protocol Buffers о самоописании."},{"id":"cli/generator/generator::top::122","title":"Генератор","section":"Интеграция с менеджером пакетов","path":"/docs/guide/cli/generator/generator","headings":["Интеграция с менеджером пакетов"],"excerpt":"Интеграция с менеджером пакетов Одной из самых мощных возможностей EasyP является бесшовная интеграция генератора кода с менеджером пакетов. Это устраняет проблему ручного управления proto‑зависимостями и гарантирует, чт","content":"Интеграция с менеджером пакетов Одной из самых мощных возможностей EasyP является бесшовная интеграция генератора кода с менеджером пакетов. Это устраняет проблему ручного управления proto‑зависимостями и гарантирует, что при генерации используются корректные (зафиксированные) версии импортируемых файлов."},{"id":"cli/generator/generator::top::123","title":"Генератор","section":"Интеграция с менеджером пакетов","path":"/docs/guide/cli/generator/generator","headings":["Интеграция с менеджером пакетов"],"excerpt":"Интеграция с менеджером пакетов **Ключевые преимущества:** **Автоматическое разрешение зависимостей**: не нужно вручную прописывать пути импортов **Согласованность версий**: фиксация в easyp.lock гарантирует воспроизводи","content":"Интеграция с менеджером пакетов **Ключевые преимущества:** **Автоматическое разрешение зависимостей**: не нужно вручную прописывать пути импортов **Согласованность версий**: фиксация в easyp.lock гарантирует воспроизводимость **Транзитивные зависимости**: вложенные цепочки подтягиваются автоматически **Производительность**: локальный кеш — скачивание один раз и повторное использование"},{"id":"cli/generator/generator::top::124","title":"Генератор","section":"Автоматическое разрешение зависимостей","path":"/docs/guide/cli/generator/generator","headings":["Автоматическое разрешение зависимостей"],"excerpt":"Автоматическое разрешение зависимостей Когда вы указываете зависимости в секции deps, генератор автоматически добавляет их в путь импортов. Ваши proto‑файлы могут делать стандартные import из этих зависимостей без дополн","content":"Автоматическое разрешение зависимостей Когда вы указываете зависимости в секции deps, генератор автоматически добавляет их в путь импортов. Ваши proto‑файлы могут делать стандартные import из этих зависимостей без дополнительной настройки."},{"id":"cli/generator/generator::top::125","title":"Генератор","section":"Автоматическое разрешение зависимостей","path":"/docs/guide/cli/generator/generator","headings":["Автоматическое разрешение зависимостей"],"excerpt":"Автоматическое разрешение зависимостей **Как это работает:** EasyP скачивает и кеширует зависимости из deps Во время генерации кешированные файлы автоматически добавляются в import‑path protoc Ваши proto‑файлы используют","content":"Автоматическое разрешение зависимостей **Как это работает:** EasyP скачивает и кеширует зависимости из deps Во время генерации кешированные файлы автоматически добавляются в import‑path protoc Ваши proto‑файлы используют обычные import строки для обращения к зависимостям При with_imports: true в вывод попадают и локальные файлы, и файлы зависимостей"},{"id":"cli/generator/generator::top::126","title":"Генератор","section":"Автоматическое разрешение зависимостей","path":"/docs/guide/cli/generator/generator","headings":["Автоматическое разрешение зависимостей"],"excerpt":"Автоматическое разрешение зависимостей Ниже простой пример — зависимости указываются один раз в deps, далее они доступны при генерации автоматически:","content":"Автоматическое разрешение зависимостей Ниже простой пример — зависимости указываются один раз в deps, далее они доступны при генерации автоматически:"},{"id":"cli/generator/generator::top::127","title":"Генератор","section":"Автоматическое разрешение зависимостей","path":"/docs/guide/cli/generator/generator","headings":["Автоматическое разрешение зависимостей"],"excerpt":"Автоматическое разрешение зависимостей ```yaml deps: - github.com/googleapis/googleapis@common-protos-1_3_1 - github.com/grpc-ecosystem/grpc-gateway@v2.19.1","content":"Автоматическое разрешение зависимостей ```yaml deps: - github.com/googleapis/googleapis@common-protos-1_3_1 - github.com/grpc-ecosystem/grpc-gateway@v2.19.1"},{"id":"cli/generator/generator::top::128","title":"Генератор","section":"Автоматическое разрешение зависимостей","path":"/docs/guide/cli/generator/generator","headings":["Автоматическое разрешение зависимостей"],"excerpt":"Автоматическое разрешение зависимостей generate: inputs: - directory: \"proto\" plugins: - name: go out: ./gen/go opts: paths: source_relative with_imports: true # This automatically includes googleapis and grpc-gateway pr","content":"Автоматическое разрешение зависимостей 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::top::129","title":"Генератор","section":"Примеры использования зависимостей","path":"/docs/guide/cli/generator/generator","headings":["Примеры использования зависимостей"],"excerpt":"Примеры использования зависимостей Ниже показаны распространённые способы интеграции внешних proto‑зависимостей в процесс генерации.","content":"Примеры использования зависимостей Ниже показаны распространённые способы интеграции внешних proto‑зависимостей в процесс генерации."},{"id":"cli/generator/generator::google-apis::130","title":"Генератор","section":"Использование Google APIs","path":"/docs/guide/cli/generator/generator#google-apis","headings":["Использование Google APIs"],"excerpt":"Использование Google APIs Google APIs — одна из самых популярных коллекций зависимостей: стандартные типы, аннотации для REST, проверки и общие структуры данных.","content":"Использование Google APIs Google APIs — одна из самых популярных коллекций зависимостей: стандартные типы, аннотации для REST, проверки и общие структуры данных."},{"id":"cli/generator/generator::google-apis::131","title":"Генератор","section":"Использование Google APIs","path":"/docs/guide/cli/generator/generator#google-apis","headings":["Использование Google APIs"],"excerpt":"Использование Google APIs **Когда использовать Google APIs:** Построение REST поверх gRPC (gRPC-Gateway) Нужны стандартные типы (Timestamp, Duration, Any) Требуются аннотации поведения полей (field behavior) Интеграция с","content":"Использование Google APIs **Когда использовать Google APIs:** Построение REST поверх gRPC (gRPC-Gateway) Нужны стандартные типы (Timestamp, Duration, Any) Требуются аннотации поведения полей (field behavior) Интеграция с сервисами Google Cloud"},{"id":"cli/generator/generator::google-apis::132","title":"Генератор","section":"Использование Google APIs","path":"/docs/guide/cli/generator/generator#google-apis","headings":["Использование Google APIs"],"excerpt":"Использование Google APIs Минимальная конфигурация для подключения Google APIs:","content":"Использование Google APIs Минимальная конфигурация для подключения Google APIs:"},{"id":"cli/generator/generator::google-apis::133","title":"Генератор","section":"Использование Google APIs","path":"/docs/guide/cli/generator/generator#google-apis","headings":["Использование Google APIs"],"excerpt":"Использование Google APIs ```yaml deps: - github.com/googleapis/googleapis@common-protos-1_3_1","content":"Использование Google APIs ```yaml deps: - github.com/googleapis/googleapis@common-protos-1_3_1"},{"id":"cli/generator/generator::google-apis::134","title":"Генератор","section":"Использование Google APIs","path":"/docs/guide/cli/generator/generator#google-apis","headings":["Использование Google APIs"],"excerpt":"Использование Google APIs generate: inputs: - directory: \"api/proto\" plugins: - name: go out: ./gen/go opts: paths: source_relative with_imports: true ```","content":"Использование Google APIs generate: inputs: - directory: \"api/proto\" plugins: - name: go out: ./gen/go opts: paths: source_relative with_imports: true ```"},{"id":"cli/generator/generator::google-apis::135","title":"Генератор","section":"Использование Google APIs","path":"/docs/guide/cli/generator/generator#google-apis","headings":["Использование Google APIs"],"excerpt":"Использование Google APIs **Важно:** Всегда фиксируйте версию (например common-protos-1_3_1) — не используйте latest в продакшене.","content":"Использование Google APIs **Важно:** Всегда фиксируйте версию (например common-protos-1_3_1) — не используйте latest в продакшене."},{"id":"cli/generator/generator::google-apis::136","title":"Генератор","section":"Использование Google APIs","path":"/docs/guide/cli/generator/generator#google-apis","headings":["Использование Google APIs"],"excerpt":"Использование Google APIs После настройки ваши proto могут импортировать определения Google API. Ниже пример сервиса с HTTP аннотацией:","content":"Использование Google APIs После настройки ваши proto могут импортировать определения Google API. Ниже пример сервиса с HTTP аннотацией:"},{"id":"cli/generator/generator::google-apis::137","title":"Генератор","section":"Использование Google APIs","path":"/docs/guide/cli/generator/generator#google-apis","headings":["Использование Google APIs"],"excerpt":"Использование Google APIs ```proto // api/proto/service.proto syntax = \"proto3\";","content":"Использование Google APIs ```proto // api/proto/service.proto syntax = \"proto3\";"},{"id":"cli/generator/generator::google-apis::138","title":"Генератор","section":"Использование Google APIs","path":"/docs/guide/cli/generator/generator#google-apis","headings":["Использование Google APIs"],"excerpt":"Использование Google APIs import \"google/api/annotations.proto\"; import \"google/protobuf/timestamp.proto\";","content":"Использование Google APIs import \"google/api/annotations.proto\"; import \"google/protobuf/timestamp.proto\";"},{"id":"cli/generator/generator::google-apis::139","title":"Генератор","section":"Использование Google APIs","path":"/docs/guide/cli/generator/generator#google-apis","headings":["Использование Google APIs"],"excerpt":"Использование Google APIs service MyService { rpc GetData(GetDataRequest) returns (GetDataResponse) { option (google.api.http) = { get: \"/v1/data\" }; } } ```","content":"Использование Google APIs service MyService { rpc GetData(GetDataRequest) returns (GetDataResponse) { option (google.api.http) = { get: \"/v1/data\" }; } } ```"},{"id":"cli/generator/generator::top::140","title":"Генератор","section":"Использование правил валидации","path":"/docs/guide/cli/generator/generator","headings":["Использование правил валидации"],"excerpt":"Использование правил валидации protoc-gen-validate даёт мощную проверку полей прямо в определениях proto, устраняя необходимость писать отдельную логику валидации в приложении.","content":"Использование правил валидации protoc-gen-validate даёт мощную проверку полей прямо в определениях proto, устраняя необходимость писать отдельную логику валидации в приложении."},{"id":"cli/generator/generator::top::141","title":"Генератор","section":"Использование правил валидации","path":"/docs/guide/cli/generator/generator","headings":["Использование правил валидации"],"excerpt":"Использование правил валидации **Когда применять валидацию:** Проверка входных данных API Ограничения моделей БД Проверка конфигурационных файлов Любая ситуация, где критична целостность данных","content":"Использование правил валидации **Когда применять валидацию:** Проверка входных данных API Ограничения моделей БД Проверка конфигурационных файлов Любая ситуация, где критична целостность данных"},{"id":"cli/generator/generator::top::142","title":"Генератор","section":"Использование правил валидации","path":"/docs/guide/cli/generator/generator","headings":["Использование правил валидации"],"excerpt":"Использование правил валидации **Преимущества:** Правила валидации — часть proto (единый источник истины) Генерация создаёт функции проверки автоматически Единообразие проверок между языками Производительнее чем проверка","content":"Использование правил валидации **Преимущества:** Правила валидации — часть proto (единый источник истины) Генерация создаёт функции проверки автоматически Единообразие проверок между языками Производительнее чем проверка через runtime reflection"},{"id":"cli/generator/generator::top::143","title":"Генератор","section":"Использование правил валидации","path":"/docs/guide/cli/generator/generator","headings":["Использование правил валидации"],"excerpt":"Использование правил валидации ```yaml deps: - github.com/bufbuild/protoc-gen-validate@v0.10.1","content":"Использование правил валидации ```yaml deps: - github.com/bufbuild/protoc-gen-validate@v0.10.1"},{"id":"cli/generator/generator::top::144","title":"Генератор","section":"Использование правил валидации","path":"/docs/guide/cli/generator/generator","headings":["Использование правил валидации"],"excerpt":"Использование правил валидации 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":"Использование правил валидации 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::top::145","title":"Генератор","section":"Использование правил валидации","path":"/docs/guide/cli/generator/generator","headings":["Использование правил валидации"],"excerpt":"Использование правил валидации **Примечание:** Нужны одновременно зависимость (для импортов proto) и плагин (для генерации кода), чтобы получить полноценную поддержку валидации.","content":"Использование правил валидации **Примечание:** Нужны одновременно зависимость (для импортов proto) и плагин (для генерации кода), чтобы получить полноценную поддержку валидации."},{"id":"cli/generator/generator::top::146","title":"Генератор","section":"Использование правил валидации","path":"/docs/guide/cli/generator/generator","headings":["Использование правил валидации"],"excerpt":"Использование правил валидации Так выглядят правила валидации в proto — сгенерированный код будет автоматически их применять:","content":"Использование правил валидации Так выглядят правила валидации в proto — сгенерированный код будет автоматически их применять:"},{"id":"cli/generator/generator::top::147","title":"Генератор","section":"Использование правил валидации","path":"/docs/guide/cli/generator/generator","headings":["Использование правил валидации"],"excerpt":"Использование правил валидации ```proto // proto/user.proto syntax = \"proto3\";","content":"Использование правил валидации ```proto // proto/user.proto syntax = \"proto3\";"},{"id":"cli/generator/generator::top::148","title":"Генератор","section":"Использование правил валидации","path":"/docs/guide/cli/generator/generator","headings":["Использование правил валидации"],"excerpt":"Использование правил валидации import \"validate/validate.proto\";","content":"Использование правил валидации import \"validate/validate.proto\";"},{"id":"cli/generator/generator::top::149","title":"Генератор","section":"Использование правил валидации","path":"/docs/guide/cli/generator/generator","headings":["Использование правил валидации"],"excerpt":"Использование правил валидации message User { string email = 1 [(validate.rules).string.email = true]; int32 age = 2 [(validate.rules).int32.gte = 0]; } ```","content":"Использование правил валидации message User { string email = 1 [(validate.rules).string.email = true]; int32 age = 2 [(validate.rules).int32.gte = 0]; } ```"},{"id":"cli/generator/generator::top::150","title":"Генератор","section":"Комплексная конфигурация с несколькими зависимостями","path":"/docs/guide/cli/generator/generator","headings":["Комплексная конфигурация с несколькими зависимостями"],"excerpt":"Комплексная конфигурация с несколькими зависимостями Пример ниже показывает продакшен‑конфигурацию, объединяющую несколько зависимостей и плагины для полного цикла разработки API:","content":"Комплексная конфигурация с несколькими зависимостями Пример ниже показывает продакшен‑конфигурацию, объединяющую несколько зависимостей и плагины для полного цикла разработки API:"},{"id":"cli/generator/generator::top::151","title":"Генератор","section":"Комплексная конфигурация с несколькими зависимостями","path":"/docs/guide/cli/generator/generator","headings":["Комплексная конфигурация с несколькими зависимостями"],"excerpt":"Комплексная конфигурация с несколькими зависимостями ```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 HT","content":"Комплексная конфигурация с несколькими зависимостями ```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::top::152","title":"Генератор","section":"Комплексная конфигурация с несколькими зависимостями","path":"/docs/guide/cli/generator/generator","headings":["Комплексная конфигурация с несколькими зависимостями"],"excerpt":"Комплексная конфигурация с несколькими зависимостями generate: inputs: - directory: \"api/proto\" plugins: # Go code generation - Core protobuf structures - name: go out: ./gen/go opts: paths: source_relative module: githu","content":"Комплексная конфигурация с несколькими зависимостями 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::top::153","title":"Генератор","section":"Интеграция с кешем зависимостей","path":"/docs/guide/cli/generator/generator","headings":["Интеграция с кешем зависимостей"],"excerpt":"Интеграция с кешем зависимостей Генератор использует модульный кеш EasyP для ускорения сборок:","content":"Интеграция с кешем зависимостей Генератор использует модульный кеш EasyP для ускорения сборок:"},{"id":"cli/generator/generator::top::154","title":"Генератор","section":"Интеграция с кешем зависимостей","path":"/docs/guide/cli/generator/generator","headings":["Интеграция с кешем зависимостей"],"excerpt":"Интеграция с кешем зависимостей ```bash Download dependencies once easyp mod download","content":"Интеграция с кешем зависимостей ```bash Download dependencies once easyp mod download"},{"id":"cli/generator/generator::top::155","title":"Генератор","section":"Интеграция с кешем зависимостей","path":"/docs/guide/cli/generator/generator","headings":["Интеграция с кешем зависимостей"],"excerpt":"Интеграция с кешем зависимостей Generate code (uses cached dependencies) easyp generate","content":"Интеграция с кешем зависимостей Generate code (uses cached dependencies) easyp generate"},{"id":"cli/generator/generator::top::156","title":"Генератор","section":"Интеграция с кешем зависимостей","path":"/docs/guide/cli/generator/generator","headings":["Интеграция с кешем зависимостей"],"excerpt":"Интеграция с кешем зависимостей Dependencies are cached in ~/.easyp/mod/ ls ~/.easyp/mod/github.com/googleapis/googleapis/ ```","content":"Интеграция с кешем зависимостей Dependencies are cached in ~/.easyp/mod/ ls ~/.easyp/mod/github.com/googleapis/googleapis/ ```"},{"id":"cli/generator/generator::top::157","title":"Генератор","section":"Удалённая генерация","path":"/docs/guide/cli/generator/generator","headings":["Удалённая генерация"],"excerpt":"Удалённая генерация Удалённая генерация — мощная возможность, позволяющая генерировать код из proto‑файлов в удалённых Git‑репозиториях без локального checkout. Это поддерживает микросервисную архитектуру, где команды ис","content":"Удалённая генерация Удалённая генерация — мощная возможность, позволяющая генерировать код из proto‑файлов в удалённых Git‑репозиториях без локального checkout. Это поддерживает микросервисную архитектуру, где команды используют API друг друга без жёсткой связки."},{"id":"cli/generator/generator::top::158","title":"Генератор","section":"Удалённая генерация","path":"/docs/guide/cli/generator/generator","headings":["Удалённая генерация"],"excerpt":"Удалённая генерация **Преимущества:** **Развязка разработки**: Команды развиваются независимо, используя версии API друг друга **Контроль версий**: Фиксация внешних API гарантирует стабильность **Меньше размер репозитори","content":"Удалённая генерация **Преимущества:** **Развязка разработки**: Команды развиваются независимо, используя версии API друг друга **Контроль версий**: Фиксация внешних API гарантирует стабильность **Меньше размер репозитория**: Нет необходимости в vendoring/submodule внешних proto **Автоматические обновления**: Легко перейти на новую версию по готовности"},{"id":"cli/generator/generator::top::159","title":"Генератор","section":"Удалённая генерация","path":"/docs/guide/cli/generator/generator","headings":["Удалённая генерация"],"excerpt":"Удалённая генерация **Рекомендации:** В продакшене используйте только тегированные версии В разработке можно тестировать latest, но в проде фиксируйте При наличии используйте семантическое версионирование Учитывайте сете","content":"Удалённая генерация **Рекомендации:** В продакшене используйте только тегированные версии В разработке можно тестировать latest, но в проде фиксируйте При наличии используйте семантическое версионирование Учитывайте сетевые ограничения в CI/CD"},{"id":"cli/generator/generator::proto::160","title":"Генератор","section":"Источники удалённых proto","path":"/docs/guide/cli/generator/generator#proto","headings":["Источники удалённых proto"],"excerpt":"Источники удалённых proto Генерация напрямую из удалённых репозиториев — полезно в микросервисной архитектуре, где разные команды владеют разными proto.","content":"Источники удалённых proto Генерация напрямую из удалённых репозиториев — полезно в микросервисной архитектуре, где разные команды владеют разными proto."},{"id":"cli/generator/generator::proto::161","title":"Генератор","section":"Источники удалённых proto","path":"/docs/guide/cli/generator/generator#proto","headings":["Источники удалённых proto"],"excerpt":"Источники удалённых proto **Типовой workflow:** Команда A публикует proto с версиями в Git Команда B добавляет их в свой easyp.yaml При генерации EasyP скачивает и подключает удалённые proto Сгенерированный код содержит ","content":"Источники удалённых proto **Типовой workflow:** Команда A публикует proto с версиями в Git Команда B добавляет их в свой easyp.yaml При генерации EasyP скачивает и подключает удалённые proto Сгенерированный код содержит клиентские библиотеки сервисов команды A"},{"id":"cli/generator/generator::proto::162","title":"Генератор","section":"Источники удалённых proto","path":"/docs/guide/cli/generator/generator#proto","headings":["Источники удалённых proto"],"excerpt":"Источники удалённых proto Практический пример объединения локальных и удалённых источников в одной конфигурации генерации:","content":"Источники удалённых proto Практический пример объединения локальных и удалённых источников в одной конфигурации генерации:"},{"id":"cli/generator/generator::top::163","title":"Генератор","section":"Сценарии использования удалённой генерации","path":"/docs/guide/cli/generator/generator","headings":["Сценарии использования удалённой генерации"],"excerpt":"Сценарии использования удалённой генерации Примеры ниже показывают реальные ситуации, где удалённая генерация даёт ощутимую выгоду.","content":"Сценарии использования удалённой генерации Примеры ниже показывают реальные ситуации, где удалённая генерация даёт ощутимую выгоду."},{"id":"cli/generator/generator::multi-team-development::164","title":"Генератор","section":"Много команд (Multi-Team Development)","path":"/docs/guide/cli/generator/generator#multi-team-development","headings":["Много команд (Multi-Team Development)"],"excerpt":"Много команд (Multi-Team Development) Мультикомандная разработка особенно выигрывает: вместо координации общих репозиториев и сложного управления зависимостями — независимая эволюция API с контролируемыми обновлениями че","content":"Много команд (Multi-Team Development) Мультикомандная разработка особенно выигрывает: вместо координации общих репозиториев и сложного управления зависимостями — независимая эволюция API с контролируемыми обновлениями через версии."},{"id":"cli/generator/generator::multi-team-development::165","title":"Генератор","section":"Много команд (Multi-Team Development)","path":"/docs/guide/cli/generator/generator#multi-team-development","headings":["Много команд (Multi-Team Development)"],"excerpt":"Много команд (Multi-Team Development) Паттерн ценен в крупных организациях, где: Команды имеют разные циклы релизов и скорости разработки Владение API определено, потребление — массовое Нужно избежать overhead от координ","content":"Много команд (Multi-Team Development) Паттерн ценен в крупных организациях, где: Команды имеют разные циклы релизов и скорости разработки Владение API определено, потребление — массовое Нужно избежать overhead от координации общих proto репозиториев Команды используют разные стеки, но должны взаимодействовать"},{"id":"cli/generator/generator::multi-team-development::166","title":"Генератор","section":"Много команд (Multi-Team Development)","path":"/docs/guide/cli/generator/generator#multi-team-development","headings":["Много команд (Multi-Team Development)"],"excerpt":"Много команд (Multi-Team Development)","content":"Много команд (Multi-Team Development)"},{"id":"cli/generator/generator::api::167","title":"Генератор","section":"Интеграция с API вендоров","path":"/docs/guide/cli/generator/generator#api","headings":["Интеграция с API вендоров"],"excerpt":"Интеграция с API вендоров Многие вендоры публикуют proto для своих API, позволяя генерировать типобезопасных клиентов вместо ручных HTTP реализаций. Это повышает типовую строгость, автоматизирует сериализацию и часто уск","content":"Интеграция с API вендоров Многие вендоры публикуют proto для своих API, позволяя генерировать типобезопасных клиентов вместо ручных HTTP реализаций. Это повышает типовую строгость, автоматизирует сериализацию и часто ускоряет работу."},{"id":"cli/generator/generator::api::168","title":"Генератор","section":"Интеграция с API вендоров","path":"/docs/guide/cli/generator/generator#api","headings":["Интеграция с API вендоров"],"excerpt":"Интеграция с API вендоров Преимущества использования proto от вендоров: **Type safety**: Проверка типов на этапе компиляции **Automatic updates**: Новые возможности приходят с обновлением версии **Consistency**: Единые п","content":"Интеграция с API вендоров Преимущества использования proto от вендоров: **Type safety**: Проверка типов на этапе компиляции **Automatic updates**: Новые возможности приходят с обновлением версии **Consistency**: Единые паттерны интерфейсов между интеграциями **Performance**: Бинарная сериализация быстрее JSON **Documentation**: Proto выступают источником истины для API"},{"id":"cli/generator/generator::top::169","title":"Генератор","section":"Команды","path":"/docs/guide/cli/generator/generator","headings":["Команды"],"excerpt":"Команды CLI EasyP предоставляет гибкие варианты запуска генерации с разными конфигурациями и окружениями.","content":"Команды CLI EasyP предоставляет гибкие варианты запуска генерации с разными конфигурациями и окружениями."},{"id":"cli/generator/generator::top::170","title":"Генератор","section":"Базовая генерация","path":"/docs/guide/cli/generator/generator","headings":["Базовая генерация"],"excerpt":"Базовая генерация Ниже наиболее часто применяемые варианты команд для разработки и продакшена:","content":"Базовая генерация Ниже наиболее часто применяемые варианты команд для разработки и продакшена:"},{"id":"cli/generator/generator::top::171","title":"Генератор","section":"Базовая генерация","path":"/docs/guide/cli/generator/generator","headings":["Базовая генерация"],"excerpt":"Базовая генерация ```bash Use default easyp.yaml configuration - Most common for development easyp generate","content":"Базовая генерация ```bash Use default easyp.yaml configuration - Most common for development easyp generate"},{"id":"cli/generator/generator::top::172","title":"Генератор","section":"Базовая генерация","path":"/docs/guide/cli/generator/generator","headings":["Базовая генерация"],"excerpt":"Базовая генерация Use custom configuration file - Essential for multi-environment setups easyp --cfg production.easyp.yaml generate","content":"Базовая генерация Use custom configuration file - Essential for multi-environment setups easyp --cfg production.easyp.yaml generate"},{"id":"cli/generator/generator::top::173","title":"Генератор","section":"Базовая генерация","path":"/docs/guide/cli/generator/generator","headings":["Базовая генерация"],"excerpt":"Базовая генерация Generate with debug logs - Helpful for debugging and CI/CD easyp --debug generate","content":"Базовая генерация Generate with debug logs - Helpful for debugging and CI/CD easyp --debug generate"},{"id":"cli/generator/generator::top::174","title":"Генератор","section":"Базовая генерация","path":"/docs/guide/cli/generator/generator","headings":["Базовая генерация"],"excerpt":"Базовая генерация Generate with custom cache location - Useful for CI systems or shared environments EASYPPATH=/tmp/easyp-cache easyp generate ```","content":"Базовая генерация Generate with custom cache location - Useful for CI systems or shared environments EASYPPATH=/tmp/easyp-cache easyp generate ```"},{"id":"cli/generator/generator::top::175","title":"Генератор","section":"Интеграция с менеджером пакетов","path":"/docs/guide/cli/generator/generator","headings":["Интеграция с менеджером пакетов"],"excerpt":"Интеграция с менеджером пакетов Интеграция с менеджером пакетов позволяет либо явно управлять зависимостями, либо поручить это генератору. Явный путь даёт больше контроля, автоматический — больше удобства:","content":"Интеграция с менеджером пакетов Интеграция с менеджером пакетов позволяет либо явно управлять зависимостями, либо поручить это генератору. Явный путь даёт больше контроля, автоматический — больше удобства:"},{"id":"cli/generator/generator::top::176","title":"Генератор","section":"Интеграция с менеджером пакетов","path":"/docs/guide/cli/generator/generator","headings":["Интеграция с менеджером пакетов"],"excerpt":"Интеграция с менеджером пакетов ```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":"Интеграция с менеджером пакетов ```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::top::177","title":"Генератор","section":"Интеграция с менеджером пакетов","path":"/docs/guide/cli/generator/generator","headings":["Интеграция с менеджером пакетов"],"excerpt":"Интеграция с менеджером пакетов Automatic workflow - Convenient for development (generate downloads dependencies automatically) easyp generate ```","content":"Интеграция с менеджером пакетов Automatic workflow - Convenient for development (generate downloads dependencies automatically) easyp generate ```"},{"id":"cli/generator/generator::advanced-usage::178","title":"Генератор","section":"Расширенное использование (Advanced Usage)","path":"/docs/guide/cli/generator/generator#advanced-usage","headings":["Расширенное использование (Advanced Usage)"],"excerpt":"Расширенное использование (Advanced Usage) Эти варианты полезны для специфических сценариев деплоя, отладки или когда нужен более тонкий контроль процесса генерации:","content":"Расширенное использование (Advanced Usage) Эти варианты полезны для специфических сценариев деплоя, отладки или когда нужен более тонкий контроль процесса генерации:"},{"id":"cli/generator/generator::advanced-usage::179","title":"Генератор","section":"Расширенное использование (Advanced Usage)","path":"/docs/guide/cli/generator/generator#advanced-usage","headings":["Расширенное использование (Advanced Usage)"],"excerpt":"Расширенное использование (Advanced Usage) ```bash Генерация из конкретной директории (перекрывает настройку в файле конфигурации) easyp generate --path=./api/proto","content":"Расширенное использование (Advanced Usage) ```bash Генерация из конкретной директории (перекрывает настройку в файле конфигурации) easyp generate --path=./api/proto"},{"id":"cli/generator/generator::advanced-usage::180","title":"Генератор","section":"Расширенное использование (Advanced Usage)","path":"/docs/guide/cli/generator/generator#advanced-usage","headings":["Расширенное использование (Advanced Usage)"],"excerpt":"Расширенное использование (Advanced Usage) Генерация с vendored зависимостями (оффлайн / Docker контейнеры) easyp mod vendor easyp generate","content":"Расширенное использование (Advanced Usage) Генерация с vendored зависимостями (оффлайн / Docker контейнеры) easyp mod vendor easyp generate"},{"id":"cli/generator/generator::advanced-usage::181","title":"Генератор","section":"Расширенное использование (Advanced Usage)","path":"/docs/guide/cli/generator/generator#advanced-usage","headings":["Расширенное использование (Advanced Usage)"],"excerpt":"Расширенное использование (Advanced Usage) Генерация из кастомного project root (удобно для монореп и вложенных рабочих директорий) easyp generate --root=/usr/local/src/my-project --path=./api/proto ```","content":"Расширенное использование (Advanced Usage) Генерация из кастомного project root (удобно для монореп и вложенных рабочих директорий) easyp generate --root=/usr/local/src/my-project --path=./api/proto ```"},{"id":"cli/generator/generator::common-patterns::182","title":"Генератор","section":"Типовые паттерны (Common Patterns)","path":"/docs/guide/cli/generator/generator#common-patterns","headings":["Типовые паттерны (Common Patterns)"],"excerpt":"Типовые паттерны (Common Patterns) Эти схемы отражают реальные сценарии и лучшие практики организации генерации кода в разных структурах проектов.","content":"Типовые паттерны (Common Patterns) Эти схемы отражают реальные сценарии и лучшие практики организации генерации кода в разных структурах проектов."},{"id":"cli/generator/generator::multi-language-generation::183","title":"Генератор","section":"Мульти-языковая генерация (Multi-Language Generation)","path":"/docs/guide/cli/generator/generator#multi-language-generation","headings":["Мульти-языковая генерация (Multi-Language Generation)"],"excerpt":"Мульти-языковая генерация (Multi-Language Generation) Мульти-языковая генерация критична для компаний, использующих разные технологии в стеке. EasyP облегчает получение согласованных клиентских библиотек и типов для неск","content":"Мульти-языковая генерация (Multi-Language Generation) Мульти-языковая генерация критична для компаний, использующих разные технологии в стеке. EasyP облегчает получение согласованных клиентских библиотек и типов для нескольких языков из одного источника proto."},{"id":"cli/generator/generator::multi-language-generation::184","title":"Генератор","section":"Мульти-языковая генерация (Multi-Language Generation)","path":"/docs/guide/cli/generator/generator#multi-language-generation","headings":["Мульти-языковая генерация (Multi-Language Generation)"],"excerpt":"Мульти-языковая генерация (Multi-Language Generation) **Типовые сценарии:** **Full‑stack приложения**: backend на Go/Java + фронтенд на TypeScript **Платформы данных**: сервисы на Go + аналитика / ML на Python **Микросер","content":"Мульти-языковая генерация (Multi-Language Generation) **Типовые сценарии:** **Full‑stack приложения**: backend на Go/Java + фронтенд на TypeScript **Платформы данных**: сервисы на Go + аналитика / ML на Python **Микросервисы**: каждый сервис — оптимальный язык под задачу **Внешние SDK**: предоставление клиентских библиотек партнёрам **Интеграция с легаси**: современные gRPC сервисы + старые системы"},{"id":"cli/generator/generator::multi-language-generation::185","title":"Генератор","section":"Мульти-языковая генерация (Multi-Language Generation)","path":"/docs/guide/cli/generator/generator#multi-language-generation","headings":["Мульти-языковая генерация (Multi-Language Generation)"],"excerpt":"Мульти-языковая генерация (Multi-Language Generation) **Производительность:** Каждый плагин запускается отдельно — время растёт линейно от количества плагинов Для больших наборов используйте параллельный запуск (make -j4","content":"Мульти-языковая генерация (Multi-Language Generation) **Производительность:** Каждый плагин запускается отдельно — время растёт линейно от количества плагинов Для больших наборов используйте параллельный запуск (make -j4) Структурируйте выходные директории иерархически — меньше конфликтов Плагины имеют разную скорость — профилируйте сборку для поиска узких мест"},{"id":"cli/generator/generator::multi-language-generation::186","title":"Генератор","section":"Мульти-языковая генерация (Multi-Language Generation)","path":"/docs/guide/cli/generator/generator#multi-language-generation","headings":["Мульти-языковая генерация (Multi-Language Generation)"],"excerpt":"Мульти-языковая генерация (Multi-Language Generation) **Преимущества сопровождения:** Единый источник истины для API снижает риск расхождения схем Согласованные типы уменьшают интеграционные баги Автоматическая синхрониз","content":"Мульти-языковая генерация (Multi-Language Generation) **Преимущества сопровождения:** Единый источник истины для API снижает риск расхождения схем Согласованные типы уменьшают интеграционные баги Автоматическая синхронизация при изменении proto исключает ручные правки Меньше риска дрейфа API между реализациями на разных языках Рефакторинг упрощается — изменения транзитивно отражаются во всех артефактах"},{"id":"cli/generator/generator::multi-language-generation::187","title":"Генератор","section":"Мульти-языковая генерация (Multi-Language Generation)","path":"/docs/guide/cli/generator/generator#multi-language-generation","headings":["Мульти-языковая генерация (Multi-Language Generation)"],"excerpt":"Мульти-языковая генерация (Multi-Language Generation) Ниже пример типичной мульти-языковой конфигурации для full‑stack приложения: backend, веб‑клиент, аналитика и документация:","content":"Мульти-языковая генерация (Multi-Language Generation) Ниже пример типичной мульти-языковой конфигурации для full‑stack приложения: backend, веб‑клиент, аналитика и документация:"},{"id":"cli/generator/generator::multi-language-generation::188","title":"Генератор","section":"Мульти-языковая генерация (Multi-Language Generation)","path":"/docs/guide/cli/generator/generator#multi-language-generation","headings":["Мульти-языковая генерация (Multi-Language Generation)"],"excerpt":"Мульти-языковая генерация (Multi-Language Generation)","content":"Мульти-языковая генерация (Multi-Language Generation)"},{"id":"cli/generator/generator::multi-language-generation::189","title":"Генератор","section":"Мульти-языковая генерация (Multi-Language Generation)","path":"/docs/guide/cli/generator/generator#multi-language-generation","headings":["Мульти-языковая генерация (Multi-Language Generation)"],"excerpt":"Мульти-языковая генерация (Multi-Language Generation) **Совет по организации:** Используйте отдельные выходные директории для каждого языка, чтобы избежать конфликтов файлов и упростить интеграцию с языковыми сборочными ","content":"Мульти-языковая генерация (Multi-Language Generation) **Совет по организации:** Используйте отдельные выходные директории для каждого языка, чтобы избежать конфликтов файлов и упростить интеграцию с языковыми сборочными системами."},{"id":"cli/generator/generator::multi-language-generation::190","title":"Генератор","section":"Мульти-языковая генерация (Multi-Language Generation)","path":"/docs/guide/cli/generator/generator#multi-language-generation","headings":["Мульти-языковая генерация (Multi-Language Generation)"],"excerpt":"Мульти-языковая генерация (Multi-Language Generation) Генератор EasyP — комплексное решение для генерации кода из Protocol Buffers: от простой локальной разработки до сложных enterprise‑сценариев с удалёнными зависимостя","content":"Мульти-языковая генерация (Multi-Language Generation) Генератор EasyP — комплексное решение для генерации кода из Protocol Buffers: от простой локальной разработки до сложных enterprise‑сценариев с удалёнными зависимостями и мульти-языковым выводом."},{"id":"cli/linter/linter::proto::0","title":"Линтер","section":"Зачем нужен линтер для proto файлов?","path":"/docs/guide/cli/linter/linter#proto","headings":["Зачем нужен линтер для proto файлов?"],"excerpt":"Зачем нужен линтер для proto файлов? Линтеры играют ключевую роль в современной разработке, особенно когда речь о .proto файлах. Они обеспечивают единый стиль и структуру, помогают находить потенциальные ошибки на ранних","content":"Зачем нужен линтер для proto файлов? Линтеры играют ключевую роль в современной разработке, особенно когда речь о .proto файлах. Они обеспечивают единый стиль и структуру, помогают находить потенциальные ошибки на ранних этапах и поддерживают читаемость кода. Это даёт выгоды:"},{"id":"cli/linter/linter::proto::1","title":"Линтер","section":"Зачем нужен линтер для proto файлов?","path":"/docs/guide/cli/linter/linter#proto","headings":["Зачем нужен линтер для proto файлов?"],"excerpt":"Зачем нужен линтер для proto файлов? **Снижение затрат на разработку:** Ошибки ловятся раньше, меньше времени на отладку. **Улучшение командного взаимодействия:** Единообразный код легче понимать и сопровождать. **Бизнес","content":"Зачем нужен линтер для proto файлов? **Снижение затрат на разработку:** Ошибки ловятся раньше, меньше времени на отладку. **Улучшение командного взаимодействия:** Единообразный код легче понимать и сопровождать. **Бизнес-эффективность:** Более качественный код → меньше инцидентов в проде → ниже стоимость поддержки."},{"id":"cli/linter/linter::top::2","title":"Линтер","section":"Справочник по конфигурации","path":"/docs/guide/cli/linter/linter","headings":["Справочник по конфигурации"],"excerpt":"Справочник по конфигурации Конфигурация линтера настраивается в секции lint файла easyp.yaml.","content":"Справочник по конфигурации Конфигурация линтера настраивается в секции lint файла easyp.yaml."},{"id":"cli/linter/linter::use-string::3","title":"Линтер","section":"use ([]string)","path":"/docs/guide/cli/linter/linter#use-string","headings":["use ([]string)"],"excerpt":"use ([]string) Определяет набор правил или категорий для включения. Можно смешивать категории и конкретные правила.","content":"use ([]string) Определяет набор правил или категорий для включения. Можно смешивать категории и конкретные правила."},{"id":"cli/linter/linter::use-string::4","title":"Линтер","section":"use ([]string)","path":"/docs/guide/cli/linter/linter#use-string","headings":["use ([]string)"],"excerpt":"use ([]string) **Категории:** **MINIMAL**: Базовая согласованность пакетов **BASIC**: Соглашения по именованию и структуре **DEFAULT**: Рекомендованные правила для большинства проектов **COMMENTS**: Требования к коммента","content":"use ([]string) **Категории:** **MINIMAL**: Базовая согласованность пакетов **BASIC**: Соглашения по именованию и структуре **DEFAULT**: Рекомендованные правила для большинства проектов **COMMENTS**: Требования к комментариям **UNARY_RPC**: Ограничение на streaming RPC"},{"id":"cli/linter/linter::use-string::5","title":"Линтер","section":"use ([]string)","path":"/docs/guide/cli/linter/linter#use-string","headings":["use ([]string)"],"excerpt":"use ([]string) **Индивидуальные правила:** Любое имя правила (например ENUM_PASCAL_CASE, FIELD_LOWER_SNAKE_CASE)","content":"use ([]string) **Индивидуальные правила:** Любое имя правила (например ENUM_PASCAL_CASE, FIELD_LOWER_SNAKE_CASE)"},{"id":"cli/linter/linter::use-string::6","title":"Линтер","section":"use ([]string)","path":"/docs/guide/cli/linter/linter#use-string","headings":["use ([]string)"],"excerpt":"use ([]string) **Примеры:** ```yaml Только категории use: [MINIMAL, BASIC, DEFAULT]","content":"use ([]string) **Примеры:** ```yaml Только категории use: [MINIMAL, BASIC, DEFAULT]"},{"id":"cli/linter/linter::use-string::7","title":"Линтер","section":"use ([]string)","path":"/docs/guide/cli/linter/linter#use-string","headings":["use ([]string)"],"excerpt":"use ([]string) Смешивание use: - MINIMAL - COMMENT_SERVICE - COMMENT_RPC - ENUM_PASCAL_CASE","content":"use ([]string) Смешивание use: - MINIMAL - COMMENT_SERVICE - COMMENT_RPC - ENUM_PASCAL_CASE"},{"id":"cli/linter/linter::use-string::8","title":"Линтер","section":"use ([]string)","path":"/docs/guide/cli/linter/linter#use-string","headings":["use ([]string)"],"excerpt":"use ([]string) Точный набор use: - PACKAGE_DEFINED - SERVICE_PASCAL_CASE - FIELD_LOWER_SNAKE_CASE ```","content":"use ([]string) Точный набор use: - PACKAGE_DEFINED - SERVICE_PASCAL_CASE - FIELD_LOWER_SNAKE_CASE ```"},{"id":"cli/linter/linter::enum_zero_value_suffix-string::9","title":"Линтер","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) Обязывает нулевое значение enum иметь заданный суффикс.","content":"enum_zero_value_suffix (string) Обязывает нулевое значение enum иметь заданный суффикс."},{"id":"cli/linter/linter::enum_zero_value_suffix-string::10","title":"Линтер","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) **Обычно:** \"UNSPECIFIED\", \"UNKNOWN\", \"DEFAULT\"","content":"enum_zero_value_suffix (string) **Обычно:** \"UNSPECIFIED\", \"UNKNOWN\", \"DEFAULT\""},{"id":"cli/linter/linter::enum_zero_value_suffix-string::11","title":"Линтер","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)","content":"enum_zero_value_suffix (string)"},{"id":"cli/linter/linter::service_suffix-string::12","title":"Линтер","section":"service_suffix (string)","path":"/docs/guide/cli/linter/linter#service_suffix-string","headings":["service_suffix (string)"],"excerpt":"service_suffix (string) Требуемый суффикс для имён сервисов (унификация стиля).","content":"service_suffix (string) Требуемый суффикс для имён сервисов (унификация стиля)."},{"id":"cli/linter/linter::ignore-string::13","title":"Линтер","section":"ignore ([]string)","path":"/docs/guide/cli/linter/linter#ignore-string","headings":["ignore ([]string)"],"excerpt":"ignore ([]string) Полное исключение путей из линтинга.","content":"ignore ([]string) Полное исключение путей из линтинга."},{"id":"cli/linter/linter::ignore-string::14","title":"Линтер","section":"ignore ([]string)","path":"/docs/guide/cli/linter/linter#ignore-string","headings":["ignore ([]string)"],"excerpt":"ignore ([]string) **Use cases:** vendor / third_party сгенерированные файлы легаси подпакеты тестовые фикстуры","content":"ignore ([]string) **Use cases:** vendor / third_party сгенерированные файлы легаси подпакеты тестовые фикстуры"},{"id":"cli/linter/linter::except-string::15","title":"Линтер","section":"except ([]string)","path":"/docs/guide/cli/linter/linter#except-string","headings":["except ([]string)"],"excerpt":"except ([]string) Глобально отключает правила.","content":"except ([]string) Глобально отключает правила."},{"id":"cli/linter/linter::allow_comment_ignores-bool::16","title":"Линтер","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) Разрешает инлайн‑игнор правил комментариями.","content":"allow_comment_ignores (bool) Разрешает инлайн‑игнор правил комментариями."},{"id":"cli/linter/linter::ignore_only-mapstringstring::17","title":"Линтер","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) Таргетированное игнорирование конкретных правил для указанных путей.","content":"ignore_only (mapstringstring) Таргетированное игнорирование конкретных правил для указанных путей."},{"id":"cli/linter/linter::top::18","title":"Линтер","section":"Игнор правил комментариями","path":"/docs/guide/cli/linter/linter","headings":["Игнор правил комментариями"],"excerpt":"Игнор правил комментариями Если включён allow_comment_ignores, можно точечно отключать правила.","content":"Игнор правил комментариями Если включён allow_comment_ignores, можно точечно отключать правила."},{"id":"cli/linter/linter::top::19","title":"Линтер","section":"Несколько правил в одной строке","path":"/docs/guide/cli/linter/linter","headings":["Несколько правил в одной строке"],"excerpt":"Несколько правил в одной строке","content":"Несколько правил в одной строке"},{"id":"cli/linter/linter::top::20","title":"Линтер","section":"Используйте редко","path":"/docs/guide/cli/linter/linter","headings":["Используйте редко"],"excerpt":"Используйте редко Частое игнорирование = сигнал пересмотреть конфигурацию.","content":"Используйте редко Частое игнорирование = сигнал пересмотреть конфигурацию."},{"id":"cli/linter/linter::top::21","title":"Линтер","section":"Предпочитайте конфигурацию","path":"/docs/guide/cli/linter/linter","headings":["Предпочитайте конфигурацию"],"excerpt":"Предпочитайте конфигурацию Если нужно игнорировать правило в группе файлов — используйте ignore_only.","content":"Предпочитайте конфигурацию Если нужно игнорировать правило в группе файлов — используйте ignore_only."},{"id":"cli/linter/linter::top::22","title":"Линтер","section":"Категории линтера","path":"/docs/guide/cli/linter/linter","headings":["Категории линтера"],"excerpt":"Категории линтера Категории помогают быстро выбрать уровень строгости.","content":"Категории линтера Категории помогают быстро выбрать уровень строгости."},{"id":"cli/linter/linter::top::23","title":"Линтер","section":"Категории линтера","path":"/docs/guide/cli/linter/linter","headings":["Категории линтера"],"excerpt":"Категории линтера **Когда использовать:** **MINIMAL**: Минимальная базовая целостность **BASIC**: Частые соглашения имен **DEFAULT**: Дополнительные проверки качества **COMMENTS**: Обязательные комментарии (API, команды)","content":"Категории линтера **Когда использовать:** **MINIMAL**: Минимальная базовая целостность **BASIC**: Частые соглашения имен **DEFAULT**: Дополнительные проверки качества **COMMENTS**: Обязательные комментарии (API, команды) **UNARY_RPC**: Ограничить streaming RPC"},{"id":"cli/linter/linter::minimal::24","title":"Линтер","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::25","title":"Линтер","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::26","title":"Линтер","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::27","title":"Линтер","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::28","title":"Линтер","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::top::29","title":"Линтер","section":"Заключение","path":"/docs/guide/cli/linter/linter","headings":["Заключение"],"excerpt":"Заключение Внедрение EasyP линдера для ваших proto файлов заметно улучшит workflow, качество и поддерживаемость кода. Полная совместимость с Buf позволяет командам мигрировать без боли, используя гибкую конфигурацию и мо","content":"Заключение Внедрение EasyP линдера для ваших proto файлов заметно улучшит workflow, качество и поддерживаемость кода. Полная совместимость с Buf позволяет командам мигрировать без боли, используя гибкую конфигурацию и мощные возможности из коробки."},{"id":"cli/linter/rules/comment-enum-value::top::0","title":"COMMENT_ENUM_VALUE","path":"/docs/guide/cli/linter/rules/comment-enum-value","headings":[],"excerpt":"Это правило проверяет, что все значения enum имеют комментарий.","content":"Это правило проверяет, что все значения enum имеют комментарий."},{"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 ```proto syntax = \"proto3\";","content":"Good ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/comment-enum-value::good::4","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":"Это правило проверяет, что enum имеет комментарий.","content":"Это правило проверяет, что enum имеет комментарий."},{"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":"Это правило проверяет, что все поля сообщений имеют комментарий.","content":"Это правило проверяет, что все поля сообщений имеют комментарий."},{"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":"Это правило проверяет, что message имеет комментарий.","content":"Это правило проверяет, что message имеет комментарий."},{"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 ```proto syntax = \"proto3\";","content":"Bad ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/comment-message::bad::2","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::3","title":"COMMENT_MESSAGE","section":"Good","path":"/docs/guide/cli/linter/rules/comment-message#good","headings":["Good"],"excerpt":"Good ```proto syntax = \"proto3\";","content":"Good ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/comment-message::good::4","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":"Это правило проверяет, что oneof имеет комментарий.","content":"Это правило проверяет, что oneof имеет комментарий."},{"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":"Это правило проверяет, что сервис имеет комментарий.","content":"Это правило проверяет, что сервис имеет комментарий."},{"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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **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":"Это правило проверяет, что все файлы в заданной директории находятся в одном и том же package.","content":"Это правило проверяет, что все файлы в заданной директории находятся в одном и том же 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":"Это правило проверяет, что первое значение enum равно нулю.","content":"Это правило проверяет, что первое значение enum равно нулю."},{"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 ```proto syntax = \"proto3\";","content":"Bad ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/enum-first-value-zero::bad::3","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::4","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::5","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":"Это правило проверяет, что опция allow_alias не установлена в значение true внутри enum.","content":"Это правило проверяет, что опция allow_alias не установлена в значение true внутри 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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **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":"Это правило проверяет, что имена enum написаны в стиле PascalCase.","content":"Это правило проверяет, что имена enum написаны в стиле 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":"Это правило проверяет, что все значения enum имеют префикс, совпадающий с именем enum.","content":"Это правило проверяет, что все значения enum имеют префикс, совпадающий с именем enum."},{"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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **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":"Это правило проверяет, что значения enum записаны в стиле UPPER_SNAKE_CASE.","content":"Это правило проверяет, что значения enum записаны в стиле 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":"Это правило проверяет, что все нулевые значения enum имеют суффикс _NONE или ваш кастомный (пользовательский) суффикс.","content":"Это правило проверяет, что все нулевые значения enum имеют суффикс _NONE или ваш кастомный (пользовательский) суффикс."},{"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":"**MINIMAL** **BASIC** **DEFAULT**","content":"**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":"Это правило проверяет, что имена полей сообщений записаны в стиле lower_snake_case.","content":"Это правило проверяет, что имена полей сообщений записаны в стиле 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":"Это правило проверяет, что все файлы имеют имя в формате lower_snake_case (только строчные буквы, цифры и символ подчеркивания, без пробелов и заглавных букв).","content":"Это правило проверяет, что все файлы имеют имя в формате 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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **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":"Это правило проверяет, что в proto-файле не используются public импорты (оператор import public \"...\").","content":"Это правило проверяет, что в proto-файле не используются public импорты (оператор import public \"...\")."},{"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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **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":"Это правило проверяет, что в proto‑файле не используются weak‑импорты (import weak \"...\").","content":"Это правило проверяет, что в proto‑файле не используются weak‑импорты (import weak \"...\")."},{"id":"cli/linter/rules/import-no-weak::top::2","title":"IMPORT_NO_WEAK","path":"/docs/guide/cli/linter/rules/import-no-weak","headings":[],"excerpt":"Weak import (синтаксис import weak) допустим в proto2, но его использование усложняет анализ зависимостей и может приводить к неочевидным ошибкам при генерации кода. Рекомендуется всегда использовать обычный import.","content":"Weak import (синтаксис import weak) допустим в proto2, но его использование усложняет анализ зависимостей и может приводить к неочевидным ошибкам при генерации кода. Рекомендуется всегда использовать обычный import."},{"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 ```proto syntax = \"proto2\";","content":"Bad ```proto syntax = \"proto2\";"},{"id":"cli/linter/rules/import-no-weak::bad::4","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::5","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::6","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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **MINIMAL** **BASIC** **DEFAULT**"},{"id":"cli/linter/rules/import-used::top::1","title":"IMPORT_USED","path":"/docs/guide/cli/linter/rules/import-used","headings":[],"excerpt":"Это правило проверяет, что все импорты используются в proto-файле.","content":"Это правило проверяет, что все импорты используются в proto-файле."},{"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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **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":"Это правило проверяет, что имена сообщений (message) записаны в стиле PascalCase.","content":"Это правило проверяет, что имена сообщений (message) записаны в стиле 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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **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":"Это правило проверяет, что имена oneof записаны в стиле lower_snake_case.","content":"Это правило проверяет, что имена oneof записаны в стиле 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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **MINIMAL** **BASIC** **DEFAULT**"},{"id":"cli/linter/rules/package-defined::top::1","title":"PACKAGE_DEFINED","path":"/docs/guide/cli/linter/rules/package-defined","headings":[],"excerpt":"Это правило проверяет, что во всех файлах присутствует директива package.","content":"Это правило проверяет, что во всех файлах присутствует директива package."},{"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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **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":"Это правило проверяет, что все файлы находятся в директории, имя которой соответствует имени их пакета.","content":"Это правило проверяет, что все файлы находятся в директории, имя которой соответствует имени их пакета."},{"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":"Это правило проверяет, что имена package записаны в формате lower_snake_case (строчные буквы, при необходимости цифры и символ подчеркивания, без пробелов и заглавных букв).","content":"Это правило проверяет, что имена package записаны в формате 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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **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":"Это правило проверяет, что все файлы с заданным пакетом используют одно и то же пространство имён C# (csharp_namespace).","content":"Это правило проверяет, что все файлы с заданным пакетом используют одно и то же пространство имён C# (csharp_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\"; // [!code focus] ```","content":"Good option csharp_namespace = \"Foo.Bar\"; // [!code focus] ```"},{"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 ```proto // File: pkg/bar.proto","content":"Good ```proto // File: pkg/bar.proto"},{"id":"cli/linter/rules/package-same-csharp-namespace::good::9","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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **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":"Это правило проверяет, что все файлы с данным package находятся в одной директории.","content":"Это правило проверяет, что все файлы с данным package находятся в одной директории."},{"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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **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":"Это правило проверяет, что все файлы с одним и тем же package используют одно и то же значение опции go_package.","content":"Это правило проверяет, что все файлы с одним и тем же package используют одно и то же значение опции 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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **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":"Это правило проверяет, что все файлы с одним и тем же package используют одинаковое значение опции java_package.","content":"Это правило проверяет, что все файлы с одним и тем же package используют одинаковое значение опции 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 ```proto // File: pkg/bar.proto","content":"Bad ```proto // File: pkg/bar.proto"},{"id":"cli/linter/rules/package-same-java-multiple-files::bad::6","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::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 ```proto // File: pkg/foo.proto","content":"Good ```proto // File: pkg/foo.proto"},{"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 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::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 ```proto // File: pkg/bar.proto","content":"Good ```proto // File: pkg/bar.proto"},{"id":"cli/linter/rules/package-same-java-multiple-files::good::10","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":"Это правило проверяет, что все файлы с одним и тем же package используют одно и то же значение опции java_package.","content":"Это правило проверяет, что все файлы с одним и тем же package используют одно и то же значение опции 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":"Это правило проверяет, что все файлы с одним и тем же package используют одно и то же значение опции php_namespace.","content":"Это правило проверяет, что все файлы с одним и тем же package используют одно и то же значение опции 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":"Это правило проверяет, что все файлы с одним и тем же package используют один и тот же swift_prefix.","content":"Это правило проверяет, что все файлы с одним и тем же package используют один и тот же 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":"Это правило проверяет, что суффикс версии пакета имеет формат _vX, где X — числовая версия.","content":"Это правило проверяет, что суффикс версии пакета имеет формат _vX, где X — числовая версия."},{"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":"Это правило проверяет, что RPC не использует клиентский стриминг (запрос не является stream ...).","content":"Это правило проверяет, что RPC не использует клиентский стриминг (запрос не является stream ...)."},{"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":"Это правило проверяет, что RPC не использует серверный стриминг (ответ не является stream ...).","content":"Это правило проверяет, что RPC не использует серверный стриминг (ответ не является stream ...)."},{"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":"Это правило проверяет, что все имена RPC написаны в стиле PascalCase.","content":"Это правило проверяет, что все имена RPC написаны в стиле 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":"Это правило проверяет, что все сообщения запроса и ответа RPC уникальны: для каждого метода используются собственные (не переиспользуются одинаковые пары Request / Response у разных RPC).","content":"Это правило проверяет, что все сообщения запроса и ответа RPC уникальны: для каждого метода используются собственные (не переиспользуются одинаковые пары Request / Response у разных RPC)."},{"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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **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":"Это правило проверяет, что все сообщения запроса RPC названы в формате MethodRequest.","content":"Это правило проверяет, что все сообщения запроса RPC названы в формате 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":"Это правило проверяет, что все сообщения ответа RPC названы в формате MethodResponse.","content":"Это правило проверяет, что все сообщения ответа RPC названы в формате 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":"**MINIMAL** **BASIC** **DEFAULT**","content":"**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":"Это правило проверяет, что все имена сервисов написаны в стиле PascalCase.","content":"Это правило проверяет, что все имена сервисов написаны в стиле 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":"Это правило проверяет, что все сервисы имеют суффикс Service или ваш пользовательский суффикс.","content":"Это правило проверяет, что все сервисы имеют суффикс Service или ваш пользовательский суффикс."},{"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 против Buf: управление пакетами","path":"/docs/guide/cli/package-manager/easyp-vs-buf","headings":[],"excerpt":"EasyP против Buf: управление пакетами","content":"EasyP против Buf: управление пакетами"},{"id":"cli/package-manager/easyp-vs-buf::top::1","title":"EasyP против Buf: управление пакетами","path":"/docs/guide/cli/package-manager/easyp-vs-buf","headings":[],"excerpt":"Этот документ даёт подробное сравнение децентрализованного подхода EasyP к управлению пакетами и централизованной модели Buf через Buf Schema Registry (BSR), чтобы помочь понять ключевые различия и выбрать подходящее реш","content":"Этот документ даёт подробное сравнение децентрализованного подхода EasyP к управлению пакетами и централизованной модели Buf через Buf Schema Registry (BSR), чтобы помочь понять ключевые различия и выбрать подходящее решение для ваших задач."},{"id":"cli/package-manager/easyp-vs-buf::easyp-git::2","title":"EasyP против Buf: управление пакетами","section":"EasyP: децентрализованный подход на базе Git","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp-git","headings":["EasyP: децентрализованный подход на базе Git"],"excerpt":"EasyP: децентрализованный подход на базе Git","content":"EasyP: децентрализованный подход на базе Git"},{"id":"cli/package-manager/easyp-vs-buf::buf-bsr::3","title":"EasyP против Buf: управление пакетами","section":"Buf: централизованный реестр (BSR)","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf-bsr","headings":["Buf: централизованный реестр (BSR)"],"excerpt":"Buf: централизованный реестр (BSR)","content":"Buf: централизованный реестр (BSR)"},{"id":"cli/package-manager/easyp-vs-buf::top::4","title":"EasyP против Buf: управление пакетами","section":"Краткое резюме различий","path":"/docs/guide/cli/package-manager/easyp-vs-buf","headings":["Краткое резюме различий"],"excerpt":"Краткое резюме различий Аспект EasyP Buf -------- ------- ----- **Архитектура** Децентрализованная (Git) Централизованная (реестр BSR) **Источник зависимостей** Любой Git репозиторий Только модули BSR **Единая точка отка","content":"Краткое резюме различий Аспект EasyP Buf -------- ------- ----- **Архитектура** Децентрализованная (Git) Централизованная (реестр BSR) **Источник зависимостей** Любой Git репозиторий Только модули BSR **Единая точка отказа** Нет Да (buf.build) **Enterprise / air‑gapped** Полная поддержка Требует доступа к BSR или приватного BSR **Аутентификация** Git (SSH / HTTPS) Токены Buf + Git **Vendor lock‑in** Отсутствует Привязка к экосистеме Buf **Частные репозитории** Нативно через Git Нужно опубликовать в BSR **Оффлайн поддержка** Полная (через vendoring) Ограничена (кэшированные модули) **Стоимость** Бесплатно (использует существующий Git) Бесплатный тариф + платные планы **Сложность настройки** Минимальная Средняя (настройка BSR)"},{"id":"cli/package-manager/easyp-vs-buf::top::5","title":"EasyP против Buf: управление пакетами","section":"Подробное сравнение возможностей","path":"/docs/guide/cli/package-manager/easyp-vs-buf","headings":["Подробное сравнение возможностей"],"excerpt":"Подробное сравнение возможностей","content":"Подробное сравнение возможностей"},{"id":"cli/package-manager/easyp-vs-buf::1::6","title":"EasyP против Buf: управление пакетами","section":"1. Философия управления зависимостями","path":"/docs/guide/cli/package-manager/easyp-vs-buf#1","headings":["1. Философия управления зависимостями"],"excerpt":"Философия управления зависимостями","content":"Философия управления зависимостями"},{"id":"cli/package-manager/easyp-vs-buf::easyp-git::7","title":"EasyP против Buf: управление пакетами","section":"EasyP: «Любой Git репозиторий — это пакет»","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp-git","headings":["EasyP: «Любой Git репозиторий — это пакет»"],"excerpt":"EasyP: «Любой Git репозиторий — это пакет»","content":"EasyP: «Любой Git репозиторий — это пакет»"},{"id":"cli/package-manager/easyp-vs-buf::easyp-git::8","title":"EasyP против Buf: управление пакетами","section":"EasyP: «Любой Git репозиторий — это пакет»","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp-git","headings":["EasyP: «Любой Git репозиторий — это пакет»"],"excerpt":"EasyP: «Любой Git репозиторий — это пакет» **Преимущества:** ✅ Использование любого существующего репозитория сразу ✅ Не нужно «публиковать» в отдельный реестр ✅ Истинный источник версий — Git ✅ Работает с приватными сер","content":"EasyP: «Любой Git репозиторий — это пакет» **Преимущества:** ✅ Использование любого существующего репозитория сразу ✅ Не нужно «публиковать» в отдельный реестр ✅ Истинный источник версий — Git ✅ Работает с приватными серверами без доп. настроек"},{"id":"cli/package-manager/easyp-vs-buf::buf::9","title":"EasyP против Buf: управление пакетами","section":"Buf: «Сначала реестр»","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf","headings":["Buf: «Сначала реестр»"],"excerpt":"Buf: «Сначала реестр» **Преимущества:** ✅ Курируемые, проверенные модули ✅ Богатые метаданные и документация ✅ Визуализация графа зависимостей ✅ Принуждение семантического версионирования","content":"Buf: «Сначала реестр» **Преимущества:** ✅ Курируемые, проверенные модули ✅ Богатые метаданные и документация ✅ Визуализация графа зависимостей ✅ Принуждение семантического версионирования"},{"id":"cli/package-manager/easyp-vs-buf::buf::10","title":"EasyP против Buf: управление пакетами","section":"Buf: «Сначала реестр»","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf","headings":["Buf: «Сначала реестр»"],"excerpt":"Buf: «Сначала реестр» **Ограничения:** ❌ Нужно опубликовать в BSR перед использованием ❌ Требует аккаунт и аутентификацию ❌ Нельзя напрямую сослаться на произвольный Git репозиторий","content":"Buf: «Сначала реестр» **Ограничения:** ❌ Нужно опубликовать в BSR перед использованием ❌ Требует аккаунт и аутентификацию ❌ Нельзя напрямую сослаться на произвольный Git репозиторий"},{"id":"cli/package-manager/easyp-vs-buf::2-airgapped::11","title":"EasyP против Buf: управление пакетами","section":"2. Корпоративные и изолированные (air‑gapped) среды","path":"/docs/guide/cli/package-manager/easyp-vs-buf#2-airgapped","headings":["2. Корпоративные и изолированные (air‑gapped) среды"],"excerpt":"Корпоративные и изолированные (air‑gapped) среды","content":"Корпоративные и изолированные (air‑gapped) среды"},{"id":"cli/package-manager/easyp-vs-buf::easyp::12","title":"EasyP против Buf: управление пакетами","section":"EasyP: Полноценная оффлайн‑поддержка","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["EasyP: Полноценная оффлайн‑поддержка"],"excerpt":"EasyP: Полноценная оффлайн‑поддержка **Сценарий**: крупная компания со строгими сетевыми политиками","content":"EasyP: Полноценная оффлайн‑поддержка **Сценарий**: крупная компания со строгими сетевыми политиками"},{"id":"cli/package-manager/easyp-vs-buf::easyp::13","title":"EasyP против Buf: управление пакетами","section":"EasyP: Полноценная оффлайн‑поддержка","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["EasyP: Полноценная оффлайн‑поддержка"],"excerpt":"EasyP: Полноценная оффлайн‑поддержка ```bash Среда с доступом в интернет easyp mod download # Скачивает в ~/.easyp/ easyp mod vendor # Создает easyp_vendor/","content":"EasyP: Полноценная оффлайн‑поддержка ```bash Среда с доступом в интернет easyp mod download # Скачивает в ~/.easyp/ easyp mod vendor # Создает easyp_vendor/"},{"id":"cli/package-manager/easyp-vs-buf::easyp::14","title":"EasyP против Buf: управление пакетами","section":"EasyP: Полноценная оффлайн‑поддержка","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["EasyP: Полноценная оффлайн‑поддержка"],"excerpt":"EasyP: Полноценная оффлайн‑поддержка Перенос в изолированный сегмент tar -czf easyp-deps.tar.gz ~/.easyp easyp_vendor/ ... перенос архива ...","content":"EasyP: Полноценная оффлайн‑поддержка Перенос в изолированный сегмент tar -czf easyp-deps.tar.gz ~/.easyp easyp_vendor/ ... перенос архива ..."},{"id":"cli/package-manager/easyp-vs-buf::easyp::15","title":"EasyP против Buf: управление пакетами","section":"EasyP: Полноценная оффлайн‑поддержка","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["EasyP: Полноценная оффлайн‑поддержка"],"excerpt":"EasyP: Полноценная оффлайн‑поддержка В изолированной среде tar -xzf easyp-deps.tar.gz export EASYPPATH=$PWD/.easyp easyp generate # Работает оффлайн ```","content":"EasyP: Полноценная оффлайн‑поддержка В изолированной среде tar -xzf easyp-deps.tar.gz export EASYPPATH=$PWD/.easyp easyp generate # Работает оффлайн ```"},{"id":"cli/package-manager/easyp-vs-buf::easyp::16","title":"EasyP против Buf: управление пакетами","section":"EasyP: Полноценная оффлайн‑поддержка","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["EasyP: Полноценная оффлайн‑поддержка"],"excerpt":"EasyP: Полноценная оффлайн‑поддержка **Плюсы:** ✅ Не зависит от внешних сервисов ✅ Не нужен внутренний реестр ✅ Использует существующую Git инфраструктуру ✅ Простая файловая дистрибуция","content":"EasyP: Полноценная оффлайн‑поддержка **Плюсы:** ✅ Не зависит от внешних сервисов ✅ Не нужен внутренний реестр ✅ Использует существующую Git инфраструктуру ✅ Простая файловая дистрибуция"},{"id":"cli/package-manager/easyp-vs-buf::buf::17","title":"EasyP против Buf: управление пакетами","section":"Buf: Требует инфраструктуру реестра","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf","headings":["Buf: Требует инфраструктуру реестра"],"excerpt":"Buf: Требует инфраструктуру реестра ```bash Вариант 1: использовать buf.build (нужен интернет) buf mod download","content":"Buf: Требует инфраструктуру реестра ```bash Вариант 1: использовать buf.build (нужен интернет) buf mod download"},{"id":"cli/package-manager/easyp-vs-buf::buf::18","title":"EasyP против Buf: управление пакетами","section":"Buf: Требует инфраструктуру реестра","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf","headings":["Buf: Требует инфраструктуру реестра"],"excerpt":"Buf: Требует инфраструктуру реестра Вариант 2: поднимать приватный BSR (сложно) Развернуть сервер реестра Перепубликовать все модули внутрь Настроить доступы, аутентификацию Поддерживать работоспособность ```","content":"Buf: Требует инфраструктуру реестра Вариант 2: поднимать приватный BSR (сложно) Развернуть сервер реестра Перепубликовать все модули внутрь Настроить доступы, аутентификацию Поддерживать работоспособность ```"},{"id":"cli/package-manager/easyp-vs-buf::buf::19","title":"EasyP против Buf: управление пакетами","section":"Buf: Требует инфраструктуру реестра","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf","headings":["Buf: Требует инфраструктуру реестра"],"excerpt":"Buf: Требует инфраструктуру реестра **Минусы:** ❌ Постоянный интернет или дорогой приватный BSR ❌ Сложная инфраструктура для частных установок ❌ Все модули нужно републиковать ❌ Дополнительные операционные затраты","content":"Buf: Требует инфраструктуру реестра **Минусы:** ❌ Постоянный интернет или дорогой приватный BSR ❌ Сложная инфраструктура для частных установок ❌ Все модули нужно републиковать ❌ Дополнительные операционные затраты"},{"id":"cli/package-manager/easyp-vs-buf::easyp::20","title":"EasyP против Buf: управление пакетами","section":"EasyP: Прямой контроль","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["EasyP: Прямой контроль"],"excerpt":"EasyP: Прямой контроль ```yaml Полный контроль источников deps: # Публичный репозиторий — ваша конкретная версия - github.com/googleapis/googleapis@common-protos-1_3_1","content":"EasyP: Прямой контроль ```yaml Полный контроль источников deps: # Публичный репозиторий — ваша конкретная версия - github.com/googleapis/googleapis@common-protos-1_3_1"},{"id":"cli/package-manager/easyp-vs-buf::easyp::21","title":"EasyP против Buf: управление пакетами","section":"EasyP: Прямой контроль","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["EasyP: Прямой контроль"],"excerpt":"EasyP: Прямой контроль Внутренний репозиторий - gitlab.company.com/security/validated-protos@v1.0.0","content":"EasyP: Прямой контроль Внутренний репозиторий - gitlab.company.com/security/validated-protos@v1.0.0"},{"id":"cli/package-manager/easyp-vs-buf::easyp::22","title":"EasyP против Buf: управление пакетами","section":"EasyP: Прямой контроль","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["EasyP: Прямой контроль"],"excerpt":"EasyP: Прямой контроль Точный коммит (горячий фикс) - github.com/bufbuild/protoc-gen-validate@abc123def456 ```","content":"EasyP: Прямой контроль Точный коммит (горячий фикс) - github.com/bufbuild/protoc-gen-validate@abc123def456 ```"},{"id":"cli/package-manager/easyp-vs-buf::easyp::23","title":"EasyP против Buf: управление пакетами","section":"EasyP: Прямой контроль","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["EasyP: Прямой контроль"],"excerpt":"EasyP: Прямой контроль **Преимущества по безопасности:** ✅ Нет посредника — берём из исходного репозитория ✅ Аудит через историю Git ✅ Нельзя «забанить» доступ извне ✅ Свои процессы сканирования / валидации ✅ Можно форкн","content":"EasyP: Прямой контроль **Преимущества по безопасности:** ✅ Нет посредника — берём из исходного репозитория ✅ Аудит через историю Git ✅ Нельзя «забанить» доступ извне ✅ Свои процессы сканирования / валидации ✅ Можно форкнуть и удерживать критические версии"},{"id":"cli/package-manager/easyp-vs-buf::buf::24","title":"EasyP против Buf: управление пакетами","section":"Buf: Зависимость от реестра","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf","headings":["Buf: Зависимость от реестра"],"excerpt":"Buf: Зависимость от реестра **Риски:** ⚠️ Посредник контролирует доступность ⚠️ Возможны ограничения / санкции на аккаунт ⚠️ Модуль могут удалить или депрекейтнуть ⚠️ Политики обновлений диктуются стороной ⚠️ Нужно довер","content":"Buf: Зависимость от реестра **Риски:** ⚠️ Посредник контролирует доступность ⚠️ Возможны ограничения / санкции на аккаунт ⚠️ Модуль могут удалить или депрекейтнуть ⚠️ Политики обновлений диктуются стороной ⚠️ Нужно доверять внешней безопасности"},{"id":"cli/package-manager/easyp-vs-buf::1::25","title":"EasyP против Buf: управление пакетами","section":"Сценарий 1: Стартап с публичными зависимостями","path":"/docs/guide/cli/package-manager/easyp-vs-buf#1","headings":["Сценарий 1: Стартап с публичными зависимостями"],"excerpt":"Сценарий 1: Стартап с публичными зависимостями **EasyP:**","content":"Сценарий 1: Стартап с публичными зависимостями **EasyP:**"},{"id":"cli/package-manager/easyp-vs-buf::1::26","title":"EasyP против Buf: управление пакетами","section":"Сценарий 1: Стартап с публичными зависимостями","path":"/docs/guide/cli/package-manager/easyp-vs-buf#1","headings":["Сценарий 1: Стартап с публичными зависимостями"],"excerpt":"Сценарий 1: Стартап с публичными зависимостями **Buf:**","content":"Сценарий 1: Стартап с публичными зависимостями **Buf:**"},{"id":"cli/package-manager/easyp-vs-buf::1::27","title":"EasyP против Buf: управление пакетами","section":"Сценарий 1: Стартап с публичными зависимостями","path":"/docs/guide/cli/package-manager/easyp-vs-buf#1","headings":["Сценарий 1: Стартап с публичными зависимостями"],"excerpt":"Сценарий 1: Стартап с публичными зависимостями **Итог:** Паритет — оба хорошо подходят для публичных пакетов.","content":"Сценарий 1: Стартап с публичными зависимостями **Итог:** Паритет — оба хорошо подходят для публичных пакетов."},{"id":"cli/package-manager/easyp-vs-buf::2::28","title":"EasyP против Buf: управление пакетами","section":"Сценарий 2: Компания со смешанными публичными/приватными зависимостями","path":"/docs/guide/cli/package-manager/easyp-vs-buf#2","headings":["Сценарий 2: Компания со смешанными публичными/приватными зависимостями"],"excerpt":"Сценарий 2: Компания со смешанными публичными/приватными зависимостями **EasyP:**","content":"Сценарий 2: Компания со смешанными публичными/приватными зависимостями **EasyP:**"},{"id":"cli/package-manager/easyp-vs-buf::2::29","title":"EasyP против Buf: управление пакетами","section":"Сценарий 2: Компания со смешанными публичными/приватными зависимостями","path":"/docs/guide/cli/package-manager/easyp-vs-buf#2","headings":["Сценарий 2: Компания со смешанными публичными/приватными зависимостями"],"excerpt":"Сценарий 2: Компания со смешанными публичными/приватными зависимостями **Buf:**","content":"Сценарий 2: Компания со смешанными публичными/приватными зависимостями **Buf:**"},{"id":"cli/package-manager/easyp-vs-buf::2::30","title":"EasyP против Buf: управление пакетами","section":"Сценарий 2: Компания со смешанными публичными/приватными зависимостями","path":"/docs/guide/cli/package-manager/easyp-vs-buf#2","headings":["Сценарий 2: Компания со смешанными публичными/приватными зависимостями"],"excerpt":"Сценарий 2: Компания со смешанными публичными/приватными зависимостями **Итог:** **EasyP** — не требует публикации внутрь BSR.","content":"Сценарий 2: Компания со смешанными публичными/приватными зависимостями **Итог:** **EasyP** — не требует публикации внутрь BSR."},{"id":"cli/package-manager/easyp-vs-buf::3-airgap::31","title":"EasyP против Buf: управление пакетами","section":"Сценарий 3: Государственный / оборонный подрядчик (полный air‑gap)","path":"/docs/guide/cli/package-manager/easyp-vs-buf#3-airgap","headings":["Сценарий 3: Государственный / оборонный подрядчик (полный air‑gap)"],"excerpt":"Сценарий 3: Государственный / оборонный подрядчик (полный air‑gap) **EasyP:**","content":"Сценарий 3: Государственный / оборонный подрядчик (полный air‑gap) **EasyP:**"},{"id":"cli/package-manager/easyp-vs-buf::3-airgap::32","title":"EasyP против Buf: управление пакетами","section":"Сценарий 3: Государственный / оборонный подрядчик (полный air‑gap)","path":"/docs/guide/cli/package-manager/easyp-vs-buf#3-airgap","headings":["Сценарий 3: Государственный / оборонный подрядчик (полный air‑gap)"],"excerpt":"Сценарий 3: Государственный / оборонный подрядчик (полный air‑gap) **Buf:**","content":"Сценарий 3: Государственный / оборонный подрядчик (полный air‑gap) **Buf:**"},{"id":"cli/package-manager/easyp-vs-buf::3-airgap::33","title":"EasyP против Buf: управление пакетами","section":"Сценарий 3: Государственный / оборонный подрядчик (полный air‑gap)","path":"/docs/guide/cli/package-manager/easyp-vs-buf#3-airgap","headings":["Сценарий 3: Государственный / оборонный подрядчик (полный air‑gap)"],"excerpt":"Сценарий 3: Государственный / оборонный подрядчик (полный air‑gap) **Итог:** **EasyP** — значительно проще.","content":"Сценарий 3: Государственный / оборонный подрядчик (полный air‑gap) **Итог:** **EasyP** — значительно проще."},{"id":"cli/package-manager/easyp-vs-buf::4::34","title":"EasyP против Buf: управление пакетами","section":"Сценарий 4: Комплаенс и аудит","path":"/docs/guide/cli/package-manager/easyp-vs-buf#4","headings":["Сценарий 4: Комплаенс и аудит"],"excerpt":"Сценарий 4: Комплаенс и аудит **EasyP:** ✅ Прямой аудит изменений (коммиты) ✅ Нет внешних точек зависимости в проде ✅ Повторяемость через фиксированные коммиты / vendor ✅ Управление уязвимостями — в ваших руках","content":"Сценарий 4: Комплаенс и аудит **EasyP:** ✅ Прямой аудит изменений (коммиты) ✅ Нет внешних точек зависимости в проде ✅ Повторяемость через фиксированные коммиты / vendor ✅ Управление уязвимостями — в ваших руках"},{"id":"cli/package-manager/easyp-vs-buf::4::35","title":"EasyP против Buf: управление пакетами","section":"Сценарий 4: Комплаенс и аудит","path":"/docs/guide/cli/package-manager/easyp-vs-buf#4","headings":["Сценарий 4: Комплаенс и аудит"],"excerpt":"Сценарий 4: Комплаенс и аудит **Buf:** ⚠️ Нужно учитывать BSR в области аудита ⚠️ Дополнительный риск третьей стороны ⚠️ Модули — внешние контролируемые артефакты ⚠️ Сложнее трассировать от реестра к исходникам","content":"Сценарий 4: Комплаенс и аудит **Buf:** ⚠️ Нужно учитывать BSR в области аудита ⚠️ Дополнительный риск третьей стороны ⚠️ Модули — внешние контролируемые артефакты ⚠️ Сложнее трассировать от реестра к исходникам"},{"id":"cli/package-manager/easyp-vs-buf::4::36","title":"EasyP против Buf: управление пакетами","section":"Сценарий 4: Комплаенс и аудит","path":"/docs/guide/cli/package-manager/easyp-vs-buf#4","headings":["Сценарий 4: Комплаенс и аудит"],"excerpt":"Сценарий 4: Комплаенс и аудит **Итог:** **EasyP** — проще для комплаенса.","content":"Сценарий 4: Комплаенс и аудит **Итог:** **EasyP** — проще для комплаенса."},{"id":"cli/package-manager/easyp-vs-buf::easyp::37","title":"EasyP против Buf: управление пакетами","section":"EasyP: Нулевая дополнительная инфраструктура","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["EasyP: Нулевая дополнительная инфраструктура"],"excerpt":"EasyP: Нулевая дополнительная инфраструктура **Затраты:** ✅ $0 — используете существующий Git ✅ Нет дополнительных сервисов/серверов ✅ Нет лицензирования ✅ Масштабирование в рамках Git","content":"EasyP: Нулевая дополнительная инфраструктура **Затраты:** ✅ $0 — используете существующий Git ✅ Нет дополнительных сервисов/серверов ✅ Нет лицензирования ✅ Масштабирование в рамках Git"},{"id":"cli/package-manager/easyp-vs-buf::easyp::38","title":"EasyP против Buf: управление пакетами","section":"EasyP: Нулевая дополнительная инфраструктура","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["EasyP: Нулевая дополнительная инфраструктура"],"excerpt":"EasyP: Нулевая дополнительная инфраструктура **Инфраструктура:** Использует текущие репозитории (GitHub/GitLab/и т.д.) Аутентификация — штатная Резервирование/DR — как уже настроено для Git","content":"EasyP: Нулевая дополнительная инфраструктура **Инфраструктура:** Использует текущие репозитории (GitHub/GitLab/и т.д.) Аутентификация — штатная Резервирование/DR — как уже настроено для Git"},{"id":"cli/package-manager/easyp-vs-buf::buf::39","title":"EasyP против Buf: управление пакетами","section":"Buf: Затраты на реестр","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf","headings":["Buf: Затраты на реестр"],"excerpt":"Buf: Затраты на реестр **Hosted BSR (buf.build):** ✅ Бесплатный уровень ❌ Платные тарифы для приватного и расширенного использования ❌ Потенциальные изменения ценовой политики ❌ Вопросы локализации данных","content":"Buf: Затраты на реестр **Hosted BSR (buf.build):** ✅ Бесплатный уровень ❌ Платные тарифы для приватного и расширенного использования ❌ Потенциальные изменения ценовой политики ❌ Вопросы локализации данных"},{"id":"cli/package-manager/easyp-vs-buf::buf::40","title":"EasyP против Buf: управление пакетами","section":"Buf: Затраты на реестр","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf","headings":["Buf: Затраты на реестр"],"excerpt":"Buf: Затраты на реестр **Приватный BSR:** ❌ Серверы, БД, балансировка ❌ Мониторинг, обновления, бэкапы ❌ Лицензирование enterprise функционала ❌ Доп. планирование отказоустойчивости","content":"Buf: Затраты на реестр **Приватный BSR:** ❌ Серверы, БД, балансировка ❌ Мониторинг, обновления, бэкапы ❌ Лицензирование enterprise функционала ❌ Доп. планирование отказоустойчивости"},{"id":"cli/package-manager/easyp-vs-buf::easyp::41","title":"EasyP против Buf: управление пакетами","section":"EasyP: Нет привязки","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["EasyP: Нет привязки"],"excerpt":"EasyP: Нет привязки **Миграция ИЗ EasyP:** (Обычные Git ссылки — легко перенести в другой инструмент.)","content":"EasyP: Нет привязки **Миграция ИЗ EasyP:** (Обычные Git ссылки — легко перенести в другой инструмент.)"},{"id":"cli/package-manager/easyp-vs-buf::easyp::42","title":"EasyP против Buf: управление пакетами","section":"EasyP: Нет привязки","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["EasyP: Нет привязки"],"excerpt":"EasyP: Нет привязки **Миграция В EasyP:**","content":"EasyP: Нет привязки **Миграция В EasyP:**"},{"id":"cli/package-manager/easyp-vs-buf::buf-lockin::43","title":"EasyP против Buf: управление пакетами","section":"Buf: Потенциальный lock‑in","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf-lockin","headings":["Buf: Потенциальный lock‑in"],"excerpt":"Buf: Потенциальный lock‑in **Миграция ИЗ Buf:** ❌ Нужно сопоставить BSR модули с исходными Git репо ❌ Имена модулей BSR не совпадают с URL ❌ Возможна потеря удобных метаданных ❌ Сложно при глубокой интеграции с BSR","content":"Buf: Потенциальный lock‑in **Миграция ИЗ Buf:** ❌ Нужно сопоставить BSR модули с исходными Git репо ❌ Имена модулей BSR не совпадают с URL ❌ Возможна потеря удобных метаданных ❌ Сложно при глубокой интеграции с BSR"},{"id":"cli/package-manager/easyp-vs-buf::buf-lockin::44","title":"EasyP против Buf: управление пакетами","section":"Buf: Потенциальный lock‑in","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf-lockin","headings":["Buf: Потенциальный lock‑in"],"excerpt":"Buf: Потенциальный lock‑in **Миграция В Buf:** ❌ Нужно опубликовать всё в BSR ❌ Нельзя ссылаться напрямую на Git ❌ Принять workflow BSR (push/pull модулей)","content":"Buf: Потенциальный lock‑in **Миграция В Buf:** ❌ Нужно опубликовать всё в BSR ❌ Нельзя ссылаться напрямую на Git ❌ Принять workflow BSR (push/pull модулей)"},{"id":"cli/package-manager/easyp-vs-buf::easyp::45","title":"EasyP против Buf: управление пакетами","section":"Выберите EasyP, если:","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["Выберите EasyP, если:"],"excerpt":"Выберите EasyP, если: ✅ **Air‑gapped / закрытые среды** Нужна работа без внешних сервисов Строгий комплаенс / контроль цепочки поставок","content":"Выберите EasyP, если: ✅ **Air‑gapped / закрытые среды** Нужна работа без внешних сервисов Строгий комплаенс / контроль цепочки поставок"},{"id":"cli/package-manager/easyp-vs-buf::easyp::46","title":"EasyP против Buf: управление пакетами","section":"Выберите EasyP, если:","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["Выберите EasyP, если:"],"excerpt":"Выберите EasyP, если: ✅ **Фокус на безопасности** Контроль источников зависимостей Минимизация рисков третьих сторон","content":"Выберите EasyP, если: ✅ **Фокус на безопасности** Контроль источников зависимостей Минимизация рисков третьих сторон"},{"id":"cli/package-manager/easyp-vs-buf::easyp::47","title":"EasyP против Buf: управление пакетами","section":"Выберите EasyP, если:","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["Выберите EasyP, если:"],"excerpt":"Выберите EasyP, если: ✅ **Git‑центричная культура** Частные репозитории — норма Не хотите добавлять новый ключевой сервис","content":"Выберите EasyP, если: ✅ **Git‑центричная культура** Частные репозитории — норма Не хотите добавлять новый ключевой сервис"},{"id":"cli/package-manager/easyp-vs-buf::easyp::48","title":"EasyP против Buf: управление пакетами","section":"Выберите EasyP, если:","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["Выберите EasyP, если:"],"excerpt":"Выберите EasyP, если: ✅ **Ограниченный бюджет** Минимизация операционных расходов Предсказуемая стоимость = 0","content":"Выберите EasyP, если: ✅ **Ограниченный бюджет** Минимизация операционных расходов Предсказуемая стоимость = 0"},{"id":"cli/package-manager/easyp-vs-buf::easyp::49","title":"EasyP против Buf: управление пакетами","section":"Выберите EasyP, если:","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["Выберите EasyP, если:"],"excerpt":"Выберите EasyP, если: ✅ **Смешанные публичные/частные зависимости** Не хотите перекладывать всё в реестр Нужна гибкость форматов и размещения","content":"Выберите EasyP, если: ✅ **Смешанные публичные/частные зависимости** Не хотите перекладывать всё в реестр Нужна гибкость форматов и размещения"},{"id":"cli/package-manager/easyp-vs-buf::buf::50","title":"EasyP против Buf: управление пакетами","section":"Выберите Buf, если:","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf","headings":["Выберите Buf, если:"],"excerpt":"Выберите Buf, если: ✅ **Глубокая интеграция в экосистему BSR** Уже используете линтеры / генерацию Buf Нужны курируемые официальные модули Важны метаданные и граф зависимостей","content":"Выберите Buf, если: ✅ **Глубокая интеграция в экосистему BSR** Уже используете линтеры / генерацию Buf Нужны курируемые официальные модули Важны метаданные и граф зависимостей"},{"id":"cli/package-manager/easyp-vs-buf::buf::51","title":"EasyP против Buf: управление пакетами","section":"Выберите Buf, если:","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf","headings":["Выберите Buf, если:"],"excerpt":"Выберите Buf, если: ✅ **Сотрудничество и открытая разработка** Централизованное обнаружение модулей Совместная работа над общими пакетами","content":"Выберите Buf, если: ✅ **Сотрудничество и открытая разработка** Централизованное обнаружение модулей Совместная работа над общими пакетами"},{"id":"cli/package-manager/easyp-vs-buf::buf::52","title":"EasyP против Buf: управление пакетами","section":"Выберите Buf, если:","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf","headings":["Выберите Buf, если:"],"excerpt":"Выберите Buf, если: ✅ **Команда новичков в protobuf** Требуется «направляющая» структура Ценность документации внутри реестра","content":"Выберите Buf, если: ✅ **Команда новичков в protobuf** Требуется «направляющая» структура Ценность документации внутри реестра"},{"id":"cli/package-manager/easyp-vs-buf::buf::53","title":"EasyP против Buf: управление пакетами","section":"Выберите Buf, если:","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf","headings":["Выберите Buf, если:"],"excerpt":"Выберите Buf, если: ✅ **Небольшой набор публичных зависимостей** В основном используете популярные общие пакеты Вас устраивает зависимость от BSR","content":"Выберите Buf, если: ✅ **Небольшой набор публичных зависимостей** В основном используете популярные общие пакеты Вас устраивает зависимость от BSR"},{"id":"cli/package-manager/easyp-vs-buf::buf-easyp::54","title":"EasyP против Buf: управление пакетами","section":"Переход с Buf на EasyP","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf-easyp","headings":["Переход с Buf на EasyP"],"excerpt":"Переход с Buf на EasyP Найдите исходные Git репозитории для каждого модуля BSR Сопоставьте имена BSR → Git ссылки (с версиями/тегами) Обновите конфигурацию (easyp.yaml) Протестируйте генерацию и совместимость","content":"Переход с Buf на EasyP Найдите исходные Git репозитории для каждого модуля BSR Сопоставьте имена BSR → Git ссылки (с версиями/тегами) Обновите конфигурацию (easyp.yaml) Протестируйте генерацию и совместимость"},{"id":"cli/package-manager/easyp-vs-buf::buf-easyp::55","title":"EasyP против Buf: управление пакетами","section":"Переход с Buf на EasyP","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf-easyp","headings":["Переход с Buf на EasyP"],"excerpt":"Переход с Buf на EasyP ```yaml Было (buf.yaml) deps: - buf.build/googleapis/googleapis - buf.build/grpc/grpc","content":"Переход с Buf на EasyP ```yaml Было (buf.yaml) deps: - buf.build/googleapis/googleapis - buf.build/grpc/grpc"},{"id":"cli/package-manager/easyp-vs-buf::buf-easyp::56","title":"EasyP против Buf: управление пакетами","section":"Переход с Buf на EasyP","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf-easyp","headings":["Переход с Buf на EasyP"],"excerpt":"Переход с Buf на EasyP Стало (easyp.yaml) deps: - github.com/googleapis/googleapis@common-protos-1_3_1 - github.com/grpc/grpc@v1.50.0 ```","content":"Переход с Buf на EasyP Стало (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::easyp-buf::57","title":"EasyP против Buf: управление пакетами","section":"Переход с EasyP на Buf","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp-buf","headings":["Переход с EasyP на Buf"],"excerpt":"Переход с EasyP на Buf Опубликуйте используемые репозитории как модули BSR Настройте аутентификацию / организацию Buf Замените Git ссылки на BSR модули Перейдите к push/pull workflow Buf","content":"Переход с EasyP на Buf Опубликуйте используемые репозитории как модули BSR Настройте аутентификацию / организацию Buf Замените Git ссылки на BSR модули Перейдите к push/pull workflow Buf"},{"id":"cli/package-manager/easyp-vs-buf::top::58","title":"EasyP против Buf: управление пакетами","section":"Заключение","path":"/docs/guide/cli/package-manager/easyp-vs-buf","headings":["Заключение"],"excerpt":"Заключение Оба инструмента решают задачу управления зависимостями protobuf, но подходят под разные приоритеты:","content":"Заключение Оба инструмента решают задачу управления зависимостями protobuf, но подходят под разные приоритеты:"},{"id":"cli/package-manager/easyp-vs-buf::top::59","title":"EasyP против Buf: управление пакетами","section":"Заключение","path":"/docs/guide/cli/package-manager/easyp-vs-buf","headings":["Заключение"],"excerpt":"Заключение **Сильные стороны EasyP:** Корпоративные / изолированные среды Жёсткие требования безопасности и аудита Минимальные затраты и отсутствие доп. инфраструктуры Прямое использование Git (без промежуточного слоя) П","content":"Заключение **Сильные стороны EasyP:** Корпоративные / изолированные среды Жёсткие требования безопасности и аудита Минимальные затраты и отсутствие доп. инфраструктуры Прямое использование Git (без промежуточного слоя) Простота масштабирования"},{"id":"cli/package-manager/easyp-vs-buf::top::60","title":"EasyP против Buf: управление пакетами","section":"Заключение","path":"/docs/guide/cli/package-manager/easyp-vs-buf","headings":["Заключение"],"excerpt":"Заключение **Сильные стороны Buf:** Богатая экосистема вокруг реестра Курируемые и документированные модули Удобство для новых команд в protobuf Средства визуализации и централизованного обмена","content":"Заключение **Сильные стороны Buf:** Богатая экосистема вокруг реестра Курируемые и документированные модули Удобство для новых команд в protobuf Средства визуализации и централизованного обмена"},{"id":"cli/package-manager/easyp-vs-buf::top::61","title":"EasyP против Buf: управление пакетами","section":"Заключение","path":"/docs/guide/cli/package-manager/easyp-vs-buf","headings":["Заключение"],"excerpt":"Заключение Выбор часто сводится к балансу между **контролем vs. удобством**, **безопасностью vs. централизованными функциями**, и **стоимостью vs. managed‑сервисом**.","content":"Заключение Выбор часто сводится к балансу между **контролем vs. удобством**, **безопасностью vs. централизованными функциями**, и **стоимостью vs. managed‑сервисом**."},{"id":"cli/package-manager/easyp-vs-buf::top::62","title":"EasyP против Buf: управление пакетами","section":"Заключение","path":"/docs/guide/cli/package-manager/easyp-vs-buf","headings":["Заключение"],"excerpt":"Заключение Для большинства enterprise‑окружений децентрализованный Git‑подход EasyP обеспечивает нужные гибкость, безопасность и предсказуемость расходов, тогда как Buf отлично подходит командам, которым важна централизо","content":"Заключение Для большинства enterprise‑окружений децентрализованный Git‑подход EasyP обеспечивает нужные гибкость, безопасность и предсказуемость расходов, тогда как Buf отлично подходит командам, которым важна централизованная коллаборация и богатая экосистема вокруг реестра."},{"id":"cli/package-manager/package-manager::top::0","title":"Менеджер пакетов","path":"/docs/guide/cli/package-manager/package-manager","headings":[],"excerpt":"EasyP предоставляет мощный менеджер пакетов для protobuf‑зависимостей, упрощающий их управление за счёт децентрализованного подхода на базе Git. В отличие от централизованных решений, EasyP работает напрямую с Git‑репози","content":"EasyP предоставляет мощный менеджер пакетов для protobuf‑зависимостей, упрощающий их управление за счёт децентрализованного подхода на базе Git. В отличие от централизованных решений, EasyP работает напрямую с Git‑репозиториями, давая вам полный контроль."},{"id":"cli/package-manager/package-manager::top::1","title":"Менеджер пакетов","section":"Обзор","path":"/docs/guide/cli/package-manager/package-manager","headings":["Обзор"],"excerpt":"Обзор Менеджер пакетов EasyP следует философии **Go modules** — любой Git‑репозиторий может быть источником. Это даёт преимущества:","content":"Обзор Менеджер пакетов EasyP следует философии **Go modules** — любой Git‑репозиторий может быть источником. Это даёт преимущества:"},{"id":"cli/package-manager/package-manager::top::2","title":"Менеджер пакетов","section":"Обзор","path":"/docs/guide/cli/package-manager/package-manager","headings":["Обзор"],"excerpt":"Обзор **Децентрализация** — нет единой точки отказа или контроля **Безопасность** — прямой доступ к исходникам **Гибкость** — публичные, приватные и корпоративные репозитории **Воспроизводимость** — lock‑файлы обеспечива","content":"Обзор **Децентрализация** — нет единой точки отказа или контроля **Безопасность** — прямой доступ к исходникам **Гибкость** — публичные, приватные и корпоративные репозитории **Воспроизводимость** — lock‑файлы обеспечивают одинаковые сборки **Производительность** — локальный кеш сокращает сетевые запросы"},{"id":"cli/package-manager/package-manager::top::3","title":"Менеджер пакетов","section":"Основные возможности","path":"/docs/guide/cli/package-manager/package-manager","headings":["Основные возможности"],"excerpt":"Основные возможности Возможность Описание ------------- ---------- **Git-Native** Любой Git репозиторий, не нужен спец‑сервер **Множество форматов версий** Теги, коммиты, псевдо‑версии, latest **Lock Files** Воспроизводи","content":"Основные возможности Возможность Описание ------------- ---------- **Git-Native** Любой Git репозиторий, не нужен спец‑сервер **Множество форматов версий** Теги, коммиты, псевдо‑версии, latest **Lock Files** Воспроизводимые сборки через easyp.lock **Локальный кеш** Архитектура как у Go modules **Vendoring** Локальное копирование для оффлайн сборок **YAML конфигурация** Простые и читаемые декларации"},{"id":"cli/package-manager/package-manager::top::4","title":"Менеджер пакетов","section":"Архитектура","path":"/docs/guide/cli/package-manager/package-manager","headings":["Архитектура"],"excerpt":"Архитектура EasyP использует двухуровневый кеш, вдохновлённый Go modules:","content":"Архитектура EasyP использует двухуровневый кеш, вдохновлённый Go modules:"},{"id":"cli/package-manager/package-manager::top::5","title":"Менеджер пакетов","section":"Расположение кеша","path":"/docs/guide/cli/package-manager/package-manager","headings":["Расположение кеша"],"excerpt":"Расположение кеша Окружение Путь Как задать ----------- ------ ----------- **По умолчанию** $HOME/.easyp Автоматически **Свое** Любая директория Переменная EASYPPATH **CI/CD** В каталоге проекта export EASYPPATH=$CI_PROJ","content":"Расположение кеша Окружение Путь Как задать ----------- ------ ----------- **По умолчанию** $HOME/.easyp Автоматически **Свое** Любая директория Переменная EASYPPATH **CI/CD** В каталоге проекта export EASYPPATH=$CI_PROJECT_DIR/.easyp"},{"id":"cli/package-manager/package-manager::top::6","title":"Менеджер пакетов","section":"Базовая конфигурация","path":"/docs/guide/cli/package-manager/package-manager","headings":["Базовая конфигурация"],"excerpt":"Базовая конфигурация Зависимости описываются в easyp.yaml:","content":"Базовая конфигурация Зависимости описываются в easyp.yaml:"},{"id":"cli/package-manager/package-manager::multi-environment-setup::7","title":"Менеджер пакетов","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 # Последнее для разработки - github.com/mycompany/internal-protos # Внутренние изменения - github.com/bufbuild/protoc-gen-va","content":"Multi-Environment Setup ```yaml development.easyp.yaml deps: - github.com/googleapis/googleapis # Последнее для разработки - github.com/mycompany/internal-protos # Внутренние изменения - github.com/bufbuild/protoc-gen-validate # Новые фичи"},{"id":"cli/package-manager/package-manager::multi-environment-setup::8","title":"Менеджер пакетов","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 # Зафиксировано - github.com/mycompany/internal-protos@v2.1.0 # Стабильно - github.com/bufbuild/protoc-gen-valida","content":"Multi-Environment Setup production.easyp.yaml deps: - github.com/googleapis/googleapis@common-protos-1_3_1 # Зафиксировано - github.com/mycompany/internal-protos@v2.1.0 # Стабильно - github.com/bufbuild/protoc-gen-validate@v0.10.1 # Проверено ```"},{"id":"cli/package-manager/package-manager::top::9","title":"Менеджер пакетов","section":"Приватные репозитории","path":"/docs/guide/cli/package-manager/package-manager","headings":["Приватные репозитории"],"excerpt":"Приватные репозитории ```yaml deps: # Публичное - github.com/googleapis/googleapis@common-protos-1_3_1","content":"Приватные репозитории ```yaml deps: # Публичное - github.com/googleapis/googleapis@common-protos-1_3_1"},{"id":"cli/package-manager/package-manager::top::10","title":"Менеджер пакетов","section":"Приватные репозитории","path":"/docs/guide/cli/package-manager/package-manager","headings":["Приватные репозитории"],"excerpt":"Приватные репозитории Частные - github.com/mycompany/auth-protos@v1.5.0 - github.com/mycompany/common-types@v2.0.1","content":"Приватные репозитории Частные - github.com/mycompany/auth-protos@v1.5.0 - github.com/mycompany/common-types@v2.0.1"},{"id":"cli/package-manager/package-manager::top::11","title":"Менеджер пакетов","section":"Приватные репозитории","path":"/docs/guide/cli/package-manager/package-manager","headings":["Приватные репозитории"],"excerpt":"Приватные репозитории Внутренний GitLab - gitlab.company.com/platform/messaging-protos@v0.3.0 ```","content":"Приватные репозитории Внутренний GitLab - gitlab.company.com/platform/messaging-protos@v0.3.0 ```"},{"id":"cli/package-manager/package-manager::top::12","title":"Менеджер пакетов","section":"Стратегии версионирования","path":"/docs/guide/cli/package-manager/package-manager","headings":["Стратегии версионирования"],"excerpt":"Стратегии версионирования Поддерживаются разные способы фиксации версий:","content":"Стратегии версионирования Поддерживаются разные способы фиксации версий:"},{"id":"cli/package-manager/package-manager::1::13","title":"Менеджер пакетов","section":"1. Семантические теги (для продакшена)","path":"/docs/guide/cli/package-manager/package-manager#1","headings":["1. Семантические теги (для продакшена)"],"excerpt":"Семантические теги (для продакшена)","content":"Семантические теги (для продакшена)"},{"id":"cli/package-manager/package-manager::1::14","title":"Менеджер пакетов","section":"1. Семантические теги (для продакшена)","path":"/docs/guide/cli/package-manager/package-manager#1","headings":["1. Семантические теги (для продакшена)"],"excerpt":"Семантические теги (для продакшена) **Используйте когда:** Продакшен Стабильное потребление API Нужна воспроизводимость","content":"Семантические теги (для продакшена) **Используйте когда:** Продакшен Стабильное потребление API Нужна воспроизводимость"},{"id":"cli/package-manager/package-manager::2-development::15","title":"Менеджер пакетов","section":"2. Последний тег (development)","path":"/docs/guide/cli/package-manager/package-manager#2-development","headings":["2. Последний тег (development)"],"excerpt":"Последний тег (development) **Подходит для:** Активной разработки Получения свежих возможностей Тестирования совместимости","content":"Последний тег (development) **Подходит для:** Активной разработки Получения свежих возможностей Тестирования совместимости"},{"id":"cli/package-manager/package-manager::3-bleeding-edge::16","title":"Менеджер пакетов","section":"3. Хеш коммита (Bleeding Edge)","path":"/docs/guide/cli/package-manager/package-manager#3-bleeding-edge","headings":["3. Хеш коммита (Bleeding Edge)"],"excerpt":"Хеш коммита (Bleeding Edge) **Когда нужно:** Нерелизные фичи Тест конкретного фикса Вклад в upstream","content":"Хеш коммита (Bleeding Edge) **Когда нужно:** Нерелизные фичи Тест конкретного фикса Вклад в upstream"},{"id":"cli/package-manager/package-manager::4::17","title":"Менеджер пакетов","section":"4. Псевдо‑версии (автоматически)","path":"/docs/guide/cli/package-manager/package-manager#4","headings":["4. Псевдо‑версии (автоматически)"],"excerpt":"Псевдо‑версии (автоматически) Если нет подходящего тега — создаётся псевдо‑версия:","content":"Псевдо‑версии (автоматически) Если нет подходящего тега — создаётся псевдо‑версия:"},{"id":"cli/package-manager/package-manager::easyp-mod-download::18","title":"Менеджер пакетов","section":"easyp mod download","path":"/docs/guide/cli/package-manager/package-manager#easyp-mod-download","headings":["easyp mod download"],"excerpt":"easyp mod download Скачивает и устанавливает все объявленные зависимости.","content":"easyp mod download Скачивает и устанавливает все объявленные зависимости."},{"id":"cli/package-manager/package-manager::easyp-mod-download::19","title":"Менеджер пакетов","section":"easyp mod download","path":"/docs/guide/cli/package-manager/package-manager#easyp-mod-download","headings":["easyp mod download"],"excerpt":"easyp mod download **Что делает:** Разрешает версии (теги → коммиты) Скачивает архивы в cache/download Проверяет контрольные суммы Распаковывает в cache/mod Обновляет easyp.lock","content":"easyp mod download **Что делает:** Разрешает версии (теги → коммиты) Скачивает архивы в cache/download Проверяет контрольные суммы Распаковывает в cache/mod Обновляет easyp.lock"},{"id":"cli/package-manager/package-manager::easyp-mod-download::20","title":"Менеджер пакетов","section":"easyp mod download","path":"/docs/guide/cli/package-manager/package-manager#easyp-mod-download","headings":["easyp mod download"],"excerpt":"easyp mod download **Пример:**","content":"easyp mod download **Пример:**"},{"id":"cli/package-manager/package-manager::easyp-mod-vendor::21","title":"Менеджер пакетов","section":"easyp mod vendor","path":"/docs/guide/cli/package-manager/package-manager#easyp-mod-vendor","headings":["easyp mod vendor"],"excerpt":"easyp mod vendor Копирует все proto зависимости в локальный easyp_vendor/ для оффлайна.","content":"easyp mod vendor Копирует все proto зависимости в локальный easyp_vendor/ для оффлайна."},{"id":"cli/package-manager/package-manager::easyp-mod-vendor::22","title":"Менеджер пакетов","section":"easyp mod vendor","path":"/docs/guide/cli/package-manager/package-manager#easyp-mod-vendor","headings":["easyp mod vendor"],"excerpt":"easyp mod vendor **Сценарии:** Docker сборки Air-gapped окружения Воспроизводимость Ускорение","content":"easyp mod vendor **Сценарии:** Docker сборки Air-gapped окружения Воспроизводимость Ускорение"},{"id":"cli/package-manager/package-manager::easyp-mod-update::23","title":"Менеджер пакетов","section":"easyp mod update","path":"/docs/guide/cli/package-manager/package-manager#easyp-mod-update","headings":["easyp mod update"],"excerpt":"easyp mod update Обновляет версии согласно easyp.yaml, пересоздаёт lock.","content":"easyp mod update Обновляет версии согласно easyp.yaml, пересоздаёт lock."},{"id":"cli/package-manager/package-manager::lock::24","title":"Менеджер пакетов","section":"Lock файл","path":"/docs/guide/cli/package-manager/package-manager#lock","headings":["Lock файл"],"excerpt":"Lock файл easyp.lock фиксирует точные версии и хеш содержимого:","content":"Lock файл easyp.lock фиксирует точные версии и хеш содержимого:"},{"id":"cli/package-manager/package-manager::lock::25","title":"Менеджер пакетов","section":"Lock файл","path":"/docs/guide/cli/package-manager/package-manager#lock","headings":["Lock файл"],"excerpt":"Lock файл **Формат строки:** Путь модуля Версия (тег или псевдо) Хеш содержимого (h1:)","content":"Lock файл **Формат строки:** Путь модуля Версия (тег или псевдо) Хеш содержимого (h1:)"},{"id":"cli/package-manager/package-manager::lock::26","title":"Менеджер пакетов","section":"Lock файл","path":"/docs/guide/cli/package-manager/package-manager#lock","headings":["Lock файл"],"excerpt":"Lock файл **Практики:** ✅ Коммитить easyp.lock ✅ Осознанно обновлять mod update ✅ Ревью изменений версий ❌ Не редактировать вручную","content":"Lock файл **Практики:** ✅ Коммитить easyp.lock ✅ Осознанно обновлять mod update ✅ Ревью изменений версий ❌ Не редактировать вручную"},{"id":"cli/package-manager/package-manager::top::27","title":"Менеджер пакетов","section":"Публичные репозитории","path":"/docs/guide/cli/package-manager/package-manager","headings":["Публичные репозитории"],"excerpt":"Публичные репозитории Работают без настроек:","content":"Публичные репозитории Работают без настроек:"},{"id":"cli/package-manager/package-manager::ssh::28","title":"Менеджер пакетов","section":"SSH ключи (рекомендуется)","path":"/docs/guide/cli/package-manager/package-manager#ssh","headings":["SSH ключи (рекомендуется)"],"excerpt":"SSH ключи (рекомендуется) Конфиг остаётся с HTTPS URL:","content":"SSH ключи (рекомендуется) Конфиг остаётся с HTTPS URL:"},{"id":"cli/package-manager/package-manager::personal-access-tokens::29","title":"Менеджер пакетов","section":"Personal Access Tokens","path":"/docs/guide/cli/package-manager/package-manager#personal-access-tokens","headings":["Personal Access Tokens"],"excerpt":"Personal Access Tokens ```bash git config --global credential.helper store echo \"https://username:token@github.com\" >> ~/.git-credentials","content":"Personal Access Tokens ```bash git config --global credential.helper store echo \"https://username:token@github.com\" >> ~/.git-credentials"},{"id":"cli/package-manager/package-manager::personal-access-tokens::30","title":"Менеджер пакетов","section":"Personal Access Tokens","path":"/docs/guide/cli/package-manager/package-manager#personal-access-tokens","headings":["Personal Access Tokens"],"excerpt":"Personal Access Tokens git config --global url.\"https://username:token@github.com/mycompany\".insteadOf \"https://github.com/mycompany\" ```","content":"Personal Access Tokens git config --global url.\"https://username:token@github.com/mycompany\".insteadOf \"https://github.com/mycompany\" ```"},{"id":"cli/package-manager/package-manager::top::31","title":"Менеджер пакетов","section":"Инициализация проекта","path":"/docs/guide/cli/package-manager/package-manager","headings":["Инициализация проекта"],"excerpt":"Инициализация проекта ```bash cat > easyp.yaml << EOF deps: - github.com/googleapis/googleapis - github.com/grpc-ecosystem/grpc-gateway@v2.19.1 EOF","content":"Инициализация проекта ```bash 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::top::32","title":"Менеджер пакетов","section":"Инициализация проекта","path":"/docs/guide/cli/package-manager/package-manager","headings":["Инициализация проекта"],"excerpt":"Инициализация проекта easyp mod download ls ~/.easyp/mod/github.com/googleapis/googleapis/ ```","content":"Инициализация проекта easyp mod download ls ~/.easyp/mod/github.com/googleapis/googleapis/ ```"},{"id":"cli/package-manager/package-manager::repository-not-found-authentication-failed::33","title":"Менеджер пакетов","section":"\"Repository not found\" / \"Authentication failed\"","path":"/docs/guide/cli/package-manager/package-manager#repository-not-found-authentication-failed","headings":["\"Repository not found\" / \"Authentication failed\""],"excerpt":"\"Repository not found\" / \"Authentication failed\"","content":"\"Repository not found\" / \"Authentication failed\""},{"id":"cli/package-manager/package-manager::cache-corruption-checksum-mismatch::34","title":"Менеджер пакетов","section":"\"Cache corruption\" / \"Checksum mismatch\"","path":"/docs/guide/cli/package-manager/package-manager#cache-corruption-checksum-mismatch","headings":["\"Cache corruption\" / \"Checksum mismatch\""],"excerpt":"\"Cache corruption\" / \"Checksum mismatch\"","content":"\"Cache corruption\" / \"Checksum mismatch\""},{"id":"cli/package-manager/package-manager::docker-multi-stage::35","title":"Менеджер пакетов","section":"Docker multi-stage","path":"/docs/guide/cli/package-manager/package-manager#docker-multi-stage","headings":["Docker multi-stage"],"excerpt":"Docker multi-stage ```dockerfile FROM ghcr.io/easyp-tech/easyp:latest AS deps WORKDIR /workspace COPY easyp.yaml easyp.lock ./ RUN easyp mod vendor","content":"Docker multi-stage ```dockerfile 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::36","title":"Менеджер пакетов","section":"Docker multi-stage","path":"/docs/guide/cli/package-manager/package-manager#docker-multi-stage","headings":["Docker multi-stage"],"excerpt":"Docker multi-stage FROM alpine:latest AS build WORKDIR /app COPY --from=deps /workspace/easyp_vendor ./easyp_vendor COPY . . RUN easyp generate ```","content":"Docker multi-stage FROM alpine:latest AS build WORKDIR /app COPY --from=deps /workspace/easyp_vendor ./easyp_vendor COPY . . RUN easyp generate ```"},{"id":"cli/package-manager/package-manager::monorepo::37","title":"Менеджер пакетов","section":"Monorepo","path":"/docs/guide/cli/package-manager/package-manager#monorepo","headings":["Monorepo"],"excerpt":"Monorepo Каждый easyp.yaml может иметь свой набор зависимостей.","content":"Monorepo Каждый easyp.yaml может иметь свой набор зависимостей."},{"id":"cli/package-manager/package-manager::workflow::38","title":"Менеджер пакетов","section":"Workflow разработки","path":"/docs/guide/cli/package-manager/package-manager#workflow","headings":["Workflow разработки"],"excerpt":"Workflow разработки ✅ Latest теги в активной разработке ✅ Фиксация версий в продакшене ✅ Коммит lock файла ✅ Ревью обновлений ✅ Тест после обновления","content":"Workflow разработки ✅ Latest теги в активной разработке ✅ Фиксация версий в продакшене ✅ Коммит lock файла ✅ Ревью обновлений ✅ Тест после обновления"},{"id":"cli/package-manager/package-manager::top::39","title":"Менеджер пакетов","section":"Безопасность","path":"/docs/guide/cli/package-manager/package-manager","headings":["Безопасность"],"excerpt":"Безопасность ✅ Фиксируйте версии ✅ Используйте SSH ключи ✅ Оценивайте новые зависимости ✅ Следите за уязвимостями ❌ Не храните секреты в конфиге","content":"Безопасность ✅ Фиксируйте версии ✅ Используйте SSH ключи ✅ Оценивайте новые зависимости ✅ Следите за уязвимостями ❌ Не храните секреты в конфиге"},{"id":"cli/package-manager/package-manager::top::40","title":"Менеджер пакетов","section":"Производительность","path":"/docs/guide/cli/package-manager/package-manager","headings":["Производительность"],"excerpt":"Производительность ✅ Агрессивное кеширование в CI ✅ Vendoring для частых сборок ✅ Чистка старого кеша ✅ Общий кеш для команды","content":"Производительность ✅ Агрессивное кеширование в CI ✅ Vendoring для частых сборок ✅ Чистка старого кеша ✅ Общий кеш для команды"},{"id":"cli/package-manager/package-manager::top::41","title":"Менеджер пакетов","section":"Командная работа","path":"/docs/guide/cli/package-manager/package-manager","headings":["Командная работа"],"excerpt":"Командная работа ✅ Документация по аутентификации ✅ Единые инструменты ✅ Автоматизация обновлений с тестами ✅ Общий кеш при возможности","content":"Командная работа ✅ Документация по аутентификации ✅ Единые инструменты ✅ Автоматизация обновлений с тестами ✅ Общий кеш при возможности"},{"id":"cli/package-manager/package-manager::top::42","title":"Менеджер пакетов","section":"Командная работа","path":"/docs/guide/cli/package-manager/package-manager","headings":["Командная работа"],"excerpt":"Командная работа Менеджер пакетов EasyP — масштабируемое децентрализованное решение от одиночных проектов до enterprise, сохраняя простоту и надёжность.","content":"Командная работа Менеджер пакетов EasyP — масштабируемое децентрализованное решение от одиночных проектов до enterprise, сохраняя простоту и надёжность."},{"id":"introduction/install::top::0","title":"Установка EasyP CLI","section":"Установка через менеджер пакетов системы","path":"/docs/guide/introduction/install","headings":["Установка через менеджер пакетов системы"],"excerpt":"Установка через менеджер пакетов системы","content":"Установка через менеджер пакетов системы"},{"id":"introduction/install::top::1","title":"Установка EasyP CLI","section":"Рекомендуемый способ установки","path":"/docs/guide/introduction/install","headings":["Рекомендуемый способ установки"],"excerpt":"Рекомендуемый способ установки","content":"Рекомендуемый способ установки"},{"id":"introduction/install::homebrew::2","title":"Установка EasyP CLI","section":"Homebrew","path":"/docs/guide/introduction/install#homebrew","headings":["Homebrew"],"excerpt":"Homebrew Можно установить бинарный релиз в macOS через Homebrew:","content":"Homebrew Можно установить бинарный релиз в macOS через Homebrew:"},{"id":"introduction/install::homebrew::3","title":"Установка EasyP CLI","section":"Homebrew","path":"/docs/guide/introduction/install#homebrew","headings":["Homebrew"],"excerpt":"Homebrew Work in progress — поддержка других менеджеров (apt, yum, pacman и т.д.) в процессе.","content":"Homebrew Work in progress — поддержка других менеджеров (apt, yum, pacman и т.д.) в процессе."},{"id":"introduction/install::_-_::4","title":"Установка EasyP CLI","section":"_Не рекомендуется_","path":"/docs/guide/introduction/install#_-_","headings":["_Не рекомендуется_"],"excerpt":"_Не рекомендуется_ Локальная установка менее предпочтительна, потому что пакетные менеджеры обеспечивают: Автоматические обновления и патчи безопасности Лучшую интеграцию с системой Упрощённую установку и удаление Подпис","content":"_Не рекомендуется_ Локальная установка менее предпочтительна, потому что пакетные менеджеры обеспечивают: Автоматические обновления и патчи безопасности Лучшую интеграцию с системой Упрощённую установку и удаление Подписанные и проверенные бинарники"},{"id":"introduction/install::go-install::5","title":"Установка EasyP CLI","section":"Установка через go install","path":"/docs/guide/introduction/install#go-install","headings":["Установка через go install"],"excerpt":"Установка через go install Команда установит последнюю стабильную версию easyp:","content":"Установка через go install Команда установит последнюю стабильную версию easyp:"},{"id":"introduction/install::top::6","title":"Установка EasyP CLI","section":"Сборка из исходников","path":"/docs/guide/introduction/install","headings":["Сборка из исходников"],"excerpt":"Сборка из исходников Клонирование репозитория","content":"Сборка из исходников Клонирование репозитория"},{"id":"introduction/install::top::7","title":"Установка EasyP CLI","section":"Сборка из исходников","path":"/docs/guide/introduction/install","headings":["Сборка из исходников"],"excerpt":"Сборка из исходников Сборка с помощью Go","content":"Сборка из исходников Сборка с помощью Go"},{"id":"introduction/quickstart::top::0","title":"Быстрый старт (Quickstart)","path":"/docs/guide/introduction/quickstart","headings":[],"excerpt":"EasyP — современный toolkit для работы с файлами Protobuf. В этом кратком руководстве вы научитесь:","content":"EasyP — современный toolkit для работы с файлами Protobuf. В этом кратком руководстве вы научитесь:"},{"id":"introduction/quickstart::top::1","title":"Быстрый старт (Quickstart)","path":"/docs/guide/introduction/quickstart","headings":[],"excerpt":"**Инициализировать** проект с конфигурацией EasyP **Настраивать линтинг**, чтобы ловить ошибки и соблюдать лучшие практики **Управлять зависимостями** из Git‑репозиториев **Генерировать код** из ваших Protobuf файлов","content":"**Инициализировать** проект с конфигурацией EasyP **Настраивать линтинг**, чтобы ловить ошибки и соблюдать лучшие практики **Управлять зависимостями** из Git‑репозиториев **Генерировать код** из ваших Protobuf файлов"},{"id":"introduction/quickstart::top::2","title":"Быстрый старт (Quickstart)","section":"Предварительные требования","path":"/docs/guide/introduction/quickstart","headings":["Предварительные требования"],"excerpt":"Предварительные требования Перед началом убедитесь, что у вас установлены:","content":"Предварительные требования Перед началом убедитесь, что у вас установлены:"},{"id":"introduction/quickstart::top::3","title":"Быстрый старт (Quickstart)","section":"Предварительные требования","path":"/docs/guide/introduction/quickstart","headings":["Предварительные требования"],"excerpt":"Предварительные требования **EasyP CLI** — см. руководство по установке **Git** доступен в вашем $PATH **Файлы .proto** (или создайте их по ходу)","content":"Предварительные требования **EasyP CLI** — см. руководство по установке **Git** доступен в вашем $PATH **Файлы .proto** (или создайте их по ходу)"},{"id":"introduction/quickstart::top::4","title":"Быстрый старт (Quickstart)","section":"Предварительные требования","path":"/docs/guide/introduction/quickstart","headings":["Предварительные требования"],"excerpt":"Предварительные требования Проверить версию EasyP:","content":"Предварительные требования Проверить версию EasyP:"},{"id":"introduction/quickstart::top::5","title":"Быстрый старт (Quickstart)","section":"Инициализация проекта","path":"/docs/guide/introduction/quickstart","headings":["Инициализация проекта"],"excerpt":"Инициализация проекта Создайте базовый файл конфигурации easyp.yaml в корне проекта:","content":"Инициализация проекта Создайте базовый файл конфигурации easyp.yaml в корне проекта:"},{"id":"introduction/quickstart::top::6","title":"Быстрый старт (Quickstart)","section":"Инициализация проекта","path":"/docs/guide/introduction/quickstart","headings":["Инициализация проекта"],"excerpt":"Инициализация проекта Команда генерирует шаблон easyp.yaml с комментариями, дефолтными lint-правилами и настройками breaking-check. easyp init работает интерактивно: если в корне есть buf.yml/buf.yaml, EasyP предложит ми","content":"Инициализация проекта Команда генерирует шаблон easyp.yaml с комментариями, дефолтными lint-правилами и настройками breaking-check. easyp init работает интерактивно: если в корне есть buf.yml/buf.yaml, EasyP предложит миграцию; если easyp.yaml уже существует, попросит подтверждение перед перезаписью."},{"id":"introduction/quickstart::top::7","title":"Быстрый старт (Quickstart)","section":"Настройка линтинга","path":"/docs/guide/introduction/quickstart","headings":["Настройка линтинга"],"excerpt":"Настройка линтинга Линтинг помогает находить проблемы и поддерживать единый стиль. EasyP использует правила, совместимые с Buf.","content":"Настройка линтинга Линтинг помогает находить проблемы и поддерживать единый стиль. EasyP использует правила, совместимые с Buf."},{"id":"introduction/quickstart::top::8","title":"Быстрый старт (Quickstart)","section":"Настройка линтинга","path":"/docs/guide/introduction/quickstart","headings":["Настройка линтинга"],"excerpt":"Настройка линтинга Секция lint уже создаётся командой easyp init. При необходимости отредактируйте её, например так:","content":"Настройка линтинга Секция lint уже создаётся командой easyp init. При необходимости отредактируйте её, например так:"},{"id":"introduction/quickstart::top::9","title":"Быстрый старт (Quickstart)","section":"Настройка линтинга","path":"/docs/guide/introduction/quickstart","headings":["Настройка линтинга"],"excerpt":"Настройка линтинга Запустите линтер:","content":"Настройка линтинга Запустите линтер:"},{"id":"introduction/quickstart::top::10","title":"Быстрый старт (Quickstart)","section":"Настройка линтинга","path":"/docs/guide/introduction/quickstart","headings":["Настройка линтинга"],"excerpt":"Настройка линтинга Линтер проверит все .proto файлы и сообщит о найденных проблемах.","content":"Настройка линтинга Линтер проверит все .proto файлы и сообщит о найденных проблемах."},{"id":"introduction/quickstart::top::11","title":"Быстрый старт (Quickstart)","section":"Настройка линтинга","path":"/docs/guide/introduction/quickstart","headings":["Настройка линтинга"],"excerpt":"Настройка линтинга ::: tip Правила линтинга EasyP на 100% совместимы с Buf — мигрировать просто. :::","content":"Настройка линтинга ::: tip Правила линтинга EasyP на 100% совместимы с Buf — мигрировать просто. :::"},{"id":"introduction/quickstart::top::12","title":"Быстрый старт (Quickstart)","section":"Управление зависимостями","path":"/docs/guide/introduction/quickstart","headings":["Управление зависимостями"],"excerpt":"Управление зависимостями Если вы используете сторонние protobuf пакеты (например Google APIs или gRPC Gateway), EasyP упрощает их подключение.","content":"Управление зависимостями Если вы используете сторонние protobuf пакеты (например Google APIs или gRPC Gateway), EasyP упрощает их подключение."},{"id":"introduction/quickstart::top::13","title":"Быстрый старт (Quickstart)","section":"Формат зависимости","path":"/docs/guide/introduction/quickstart","headings":["Формат зависимости"],"excerpt":"Формат зависимости Запись: $GIT_LINK@$VERSION","content":"Формат зависимости Запись: $GIT_LINK@$VERSION"},{"id":"introduction/quickstart::top::14","title":"Быстрый старт (Quickstart)","section":"Формат зависимости","path":"/docs/guide/introduction/quickstart","headings":["Формат зависимости"],"excerpt":"Формат зависимости **$GIT_LINK** — URL любого Git‑репозитория (GitHub, GitLab и т.д.) **$VERSION** — тег или хеш коммита (опционально)","content":"Формат зависимости **$GIT_LINK** — URL любого Git‑репозитория (GitHub, GitLab и т.д.) **$VERSION** — тег или хеш коммита (опционально)"},{"id":"introduction/quickstart::top::15","title":"Быстрый старт (Quickstart)","section":"Формат зависимости","path":"/docs/guide/introduction/quickstart","headings":["Формат зависимости"],"excerpt":"Формат зависимости Если версия не указана — берётся последний коммит из основной ветки.","content":"Формат зависимости Если версия не указана — берётся последний коммит из основной ветки."},{"id":"introduction/quickstart::top::16","title":"Быстрый старт (Quickstart)","section":"Добавление зависимостей","path":"/docs/guide/introduction/quickstart","headings":["Добавление зависимостей"],"excerpt":"Добавление зависимостей Дополните easyp.yaml:","content":"Добавление зависимостей Дополните easyp.yaml:"},{"id":"introduction/quickstart::top::17","title":"Быстрый старт (Quickstart)","section":"Загрузка зависимостей","path":"/docs/guide/introduction/quickstart","headings":["Загрузка зависимостей"],"excerpt":"Загрузка зависимостей Команда: Скачивает версии из easyp.lock, если он существует Иначе — берёт из easyp.yaml и создаёт easyp.lock","content":"Загрузка зависимостей Команда: Скачивает версии из easyp.lock, если он существует Иначе — берёт из easyp.yaml и создаёт easyp.lock"},{"id":"introduction/quickstart::top::18","title":"Быстрый старт (Quickstart)","section":"Загрузка зависимостей","path":"/docs/guide/introduction/quickstart","headings":["Загрузка зависимостей"],"excerpt":"Загрузка зависимостей ::: info Совет: easyp mod update — игнорирует lock‑файл и подтягивает актуальные версии из easyp.yaml. :::","content":"Загрузка зависимостей ::: info Совет: easyp mod update — игнорирует lock‑файл и подтягивает актуальные версии из easyp.yaml. :::"},{"id":"introduction/quickstart::top::19","title":"Быстрый старт (Quickstart)","section":"Генерация кода","path":"/docs/guide/introduction/quickstart","headings":["Генерация кода"],"excerpt":"Генерация кода EasyP поддерживает все стандартные protoc‑плагины.","content":"Генерация кода EasyP поддерживает все стандартные protoc‑плагины."},{"id":"introduction/quickstart::top::20","title":"Быстрый старт (Quickstart)","section":"Конфигурация генерации","path":"/docs/guide/introduction/quickstart","headings":["Конфигурация генерации"],"excerpt":"Конфигурация генерации Добавьте плагины:","content":"Конфигурация генерации Добавьте плагины:"},{"id":"introduction/quickstart::top::21","title":"Быстрый старт (Quickstart)","section":"Запуск генерации","path":"/docs/guide/introduction/quickstart","headings":["Запуск генерации"],"excerpt":"Запуск генерации EasyP выполнит: Разрешение всех зависимостей Подключение к сервису EasyP (или локальный режим) Запуск указанных плагинов Вывод сгенерированного кода в нужные директории","content":"Запуск генерации EasyP выполнит: Разрешение всех зависимостей Подключение к сервису EasyP (или локальный режим) Запуск указанных плагинов Вывод сгенерированного кода в нужные директории"},{"id":"introduction/quickstart::top::22","title":"Быстрый старт (Quickstart)","section":"Запуск генерации","path":"/docs/guide/introduction/quickstart","headings":["Запуск генерации"],"excerpt":"Запуск генерации ::: tip Гибридный рантайм: WASM для скорости, Docker — для тяжёлых плагинов. :::","content":"Запуск генерации ::: tip Гибридный рантайм: WASM для скорости, Docker — для тяжёлых плагинов. :::"},{"id":"introduction/quickstart::top::23","title":"Быстрый старт (Quickstart)","section":"Следующие шаги","path":"/docs/guide/introduction/quickstart","headings":["Следующие шаги"],"excerpt":"Следующие шаги Поздравляем! 🎉 Вы успешно: ✅ Инициализировали проект EasyP ✅ Настроили линтинг ✅ Управляете внешними зависимостями ✅ Сгенерировали код из .proto","content":"Следующие шаги Поздравляем! 🎉 Вы успешно: ✅ Инициализировали проект EasyP ✅ Настроили линтинг ✅ Управляете внешними зависимостями ✅ Сгенерировали код из .proto"},{"id":"introduction/quickstart::top::24","title":"Быстрый старт (Quickstart)","section":"Узнать больше","path":"/docs/guide/introduction/quickstart","headings":["Узнать больше"],"excerpt":"Узнать больше **CLI Reference** — подробности по командам **API Service** — удалённая генерация **Configuration** — все опции конфигурации","content":"Узнать больше **CLI Reference** — подробности по командам **API Service** — удалённая генерация **Configuration** — все опции конфигурации"},{"id":"introduction/quickstart::top::25","title":"Быстрый старт (Quickstart)","section":"Узнать больше","path":"/docs/guide/introduction/quickstart","headings":["Узнать больше"],"excerpt":"Узнать больше *Приятной работы с Protobuf — без боли! 🚀*","content":"Узнать больше *Приятной работы с Protobuf — без боли! 🚀*"},{"id":"introduction/what-is::top::0","title":"Что такое EasyP?","path":"/docs/guide/introduction/what-is","headings":[],"excerpt":"EasyP — это современный инструментарий для работы с Protocol Buffers, который объединяет весь ваш protobuf‑workflow в один мощный CLI‑инструмент. Он совмещает линтинг, управление пакетами, генерацию кода и проверку совме","content":"EasyP — это современный инструментарий для работы с Protocol Buffers, который объединяет весь ваш protobuf‑workflow в один мощный CLI‑инструмент. Он совмещает линтинг, управление пакетами, генерацию кода и проверку совместимости в единой среде и устраняет сложность традиционной работы с protobuf."},{"id":"introduction/what-is::top::1","title":"Что такое EasyP?","path":"/docs/guide/introduction/what-is","headings":[],"excerpt":"Хотите просто попробовать? Перейдите сразу к разделу Quickstart.","content":"Хотите просто попробовать? Перейдите сразу к разделу Quickstart."},{"id":"introduction/what-is::protobuf::2","title":"Что такое EasyP?","section":"Проблема: фрагментированные protobuf‑процессы","path":"/docs/guide/introduction/what-is#protobuf","headings":["Проблема: фрагментированные protobuf‑процессы"],"excerpt":"Проблема: фрагментированные protobuf‑процессы Работа с Protocol Buffers в разных проектах часто создает лишнюю сложность и трение:","content":"Проблема: фрагментированные protobuf‑процессы Работа с Protocol Buffers в разных проектах часто создает лишнюю сложность и трение:"},{"id":"introduction/what-is::top::3","title":"Что такое EasyP?","section":"Хаос инструментов","path":"/docs/guide/introduction/what-is","headings":["Хаос инструментов"],"excerpt":"Хаос инструментов **Много отдельных утилит**: Отдельно для линтинга, генерации и управления зависимостями **Несогласованные конфигурации**: Разные форматы и правила в разных командах **Сложный онбординг**: Новым разработ","content":"Хаос инструментов **Много отдельных утилит**: Отдельно для линтинга, генерации и управления зависимостями **Несогласованные конфигурации**: Разные форматы и правила в разных командах **Сложный онбординг**: Новым разработчикам нужно долго вникать"},{"id":"introduction/what-is::top::4","title":"Что такое EasyP?","section":"Проблемы управления зависимостями","path":"/docs/guide/introduction/what-is","headings":["Проблемы управления зависимостями"],"excerpt":"Проблемы управления зависимостями **Нет стандартизированного подхода**: Каждый проект решает это по‑своему **Конфликты версий**: Трудно сводить разные версии одних и тех же proto‑библиотек **Неповторяемость сборок**: Сло","content":"Проблемы управления зависимостями **Нет стандартизированного подхода**: Каждый проект решает это по‑своему **Конфликты версий**: Трудно сводить разные версии одних и тех же proto‑библиотек **Неповторяемость сборок**: Сложно гарантировать одинаковый результат в разных окружениях"},{"id":"introduction/what-is::top::5","title":"Что такое EasyP?","section":"Трение в разработке","path":"/docs/guide/introduction/what-is","headings":["Трение в разработке"],"excerpt":"Трение в разработке **Ручные операции**: Много повторяющихся шагов **Разрастание конфигураций**: Множество файлов и форматов **Затратная проверка совместимости**: Часто вручную и постфактум","content":"Трение в разработке **Ручные операции**: Много повторяющихся шагов **Разрастание конфигураций**: Множество файлов и форматов **Затратная проверка совместимости**: Часто вручную и постфактум"},{"id":"introduction/what-is::protobuf::6","title":"Что такое EasyP?","section":"Решение: единый protobuf‑инструментарий","path":"/docs/guide/introduction/what-is#protobuf","headings":["Решение: единый protobuf‑инструментарий"],"excerpt":"Решение: единый protobuf‑инструментарий EasyP устраняет эти проблемы, предоставляя целостный opinionated‑подход и стандартизируя процессы:","content":"Решение: единый protobuf‑инструментарий EasyP устраняет эти проблемы, предоставляя целостный opinionated‑подход и стандартизируя процессы:"},{"id":"introduction/what-is::top::7","title":"Что такое EasyP?","section":"Один инструмент — все задачи","path":"/docs/guide/introduction/what-is","headings":["Один инструмент — все задачи"],"excerpt":"Один инструмент — все задачи Вместо жонглирования утилитами EasyP даёт: **Linting** с расширенными наборами правил **Package management** с Git‑нативными зависимостями **Code generation** локально и удалённо **Breaking c","content":"Один инструмент — все задачи Вместо жонглирования утилитами EasyP даёт: **Linting** с расширенными наборами правил **Package management** с Git‑нативными зависимостями **Code generation** локально и удалённо **Breaking change detection** для контроля совместимости API"},{"id":"introduction/what-is::top::8","title":"Что такое EasyP?","section":"Единая конфигурация","path":"/docs/guide/introduction/what-is","headings":["Единая конфигурация"],"excerpt":"Единая конфигурация Один файл easyp.yaml описывает весь workflow — меньше расхождений, проще сопровождать.","content":"Единая конфигурация Один файл easyp.yaml описывает весь workflow — меньше расхождений, проще сопровождать."},{"id":"introduction/what-is::gitnative::9","title":"Что такое EasyP?","section":"Git‑native зависимости","path":"/docs/guide/introduction/what-is#gitnative","headings":["Git‑native зависимости"],"excerpt":"Git‑native зависимости Прямое использование Git‑репозиториев вместо централизованных реестров: прозрачная история, контроль версий, воспроизводимые сборки.","content":"Git‑native зависимости Прямое использование Git‑репозиториев вместо централизованных реестров: прозрачная история, контроль версий, воспроизводимые сборки."},{"id":"introduction/what-is::top::10","title":"Что такое EasyP?","section":"Ключевые возможности","path":"/docs/guide/introduction/what-is","headings":["Ключевые возможности"],"excerpt":"Ключевые возможности Feature Description --------- ------------- 🔍 **Comprehensive Linting** Полная поддержка правил buf с настраиваемыми профилями для лучших практик API‑дизайна. 📦 **Smart Package Manager** Git‑ориент","content":"Ключевые возможности Feature Description --------- ------------- 🔍 **Comprehensive Linting** Полная поддержка правил buf с настраиваемыми профилями для лучших практик API‑дизайна. 📦 **Smart Package Manager** Git‑ориентированное управление зависимостями с lock‑файлом для воспроизводимости. ⚡ **Code Generation** Многозадачная генерация кода с поддержкой локальных и удалённых protoc‑плагинов. 🔄 **Breaking Change Detection** Автоматическая проверка совместимости API против веток Git. 🌐 **Remote Plugin Support** Выполнение плагинов через централизованный EasyP API сервис без локальных установок. 🎯 **Developer Experience** Автодополнение, понятные ошибки, единая структура и документация."},{"id":"introduction/what-is::top::11","title":"Что такое EasyP?","section":"Типы поддерживаемых плагинов","path":"/docs/guide/introduction/what-is","headings":["Типы поддерживаемых плагинов"],"excerpt":"Типы поддерживаемых плагинов EasyP гибко подходит к выполнению генерации:","content":"Типы поддерживаемых плагинов EasyP гибко подходит к выполнению генерации:"},{"id":"introduction/what-is::local-plugins::12","title":"Что такое EasyP?","section":"Local Plugins","path":"/docs/guide/introduction/what-is#local-plugins","headings":["Local Plugins"],"excerpt":"Local Plugins Стандартные установленные protoc‑плагины:","content":"Local Plugins Стандартные установленные protoc‑плагины:"},{"id":"introduction/what-is::remote-plugins::13","title":"Что такое EasyP?","section":"Remote Plugins","path":"/docs/guide/introduction/what-is#remote-plugins","headings":["Remote Plugins"],"excerpt":"Remote Plugins Плагины через EasyP API сервис для воспроизводимости:","content":"Remote Plugins Плагины через EasyP API сервис для воспроизводимости:"},{"id":"introduction/what-is::custom-plugins::14","title":"Что такое EasyP?","section":"Custom Plugins","path":"/docs/guide/introduction/what-is#custom-plugins","headings":["Custom Plugins"],"excerpt":"Custom Plugins Поддержка экосистемы пользовательских расширений.","content":"Custom Plugins Поддержка экосистемы пользовательских расширений."},{"id":"introduction/what-is::top::15","title":"Что такое EasyP?","section":"Децентрализованный менеджмент пакетов","path":"/docs/guide/introduction/what-is","headings":["Децентрализованный менеджмент пакетов"],"excerpt":"Децентрализованный менеджмент пакетов В отличие от других решений EasyP не требует централизованного реестра. Любой Git‑репозиторий может быть источником:","content":"Децентрализованный менеджмент пакетов В отличие от других решений EasyP не требует централизованного реестра. Любой Git‑репозиторий может быть источником:"},{"id":"introduction/what-is::top::16","title":"Что такое EasyP?","section":"Децентрализованный менеджмент пакетов","path":"/docs/guide/introduction/what-is","headings":["Децентрализованный менеджмент пакетов"],"excerpt":"Децентрализованный менеджмент пакетов **Гибкость**: Любой Git‑хостинг (GitHub, GitLab, self‑hosted) **Нет vendor lock‑in**: Зависимости не привязаны к одному провайдеру **Полная история**: Ветки, теги, ревью **Enterprise","content":"Децентрализованный менеджмент пакетов **Гибкость**: Любой Git‑хостинг (GitHub, GitLab, self‑hosted) **Нет vendor lock‑in**: Зависимости не привязаны к одному провайдеру **Полная история**: Ветки, теги, ревью **Enterprise‑совместимость**: Поддержка приватных репозиториев"},{"id":"introduction/what-is::buf::17","title":"Что такое EasyP?","section":"Бесшовная миграция с Buf","path":"/docs/guide/introduction/what-is#buf","headings":["Бесшовная миграция с Buf"],"excerpt":"Бесшовная миграция с Buf EasyP изначально совместим с экосистемой buf:","content":"Бесшовная миграция с Buf EasyP изначально совместим с экосистемой buf:"},{"id":"introduction/what-is::buf::18","title":"Что такое EasyP?","section":"Бесшовная миграция с Buf","path":"/docs/guide/introduction/what-is#buf","headings":["Бесшовная миграция с Buf"],"excerpt":"Бесшовная миграция с Buf **Совпадающие rule sets** **Похожая структура YAML** **Минимальные изменения для замены** **Постепенное внедрение** без ломки текущего пайплайна","content":"Бесшовная миграция с Buf **Совпадающие rule sets** **Похожая структура YAML** **Минимальные изменения для замены** **Постепенное внедрение** без ломки текущего пайплайна"},{"id":"introduction/what-is::easyp-vs-bufbuild::19","title":"Что такое EasyP?","section":"EasyP vs buf.build","path":"/docs/guide/introduction/what-is#easyp-vs-bufbuild","headings":["EasyP vs buf.build"],"excerpt":"EasyP vs buf.build Feature EasyP buf.build --------- -------- ----------- **Dependency Management** Git‑репозитории Buf Schema Registry (BSR) **Vendor Lock-in** Нет Привязка к BSR для полного функционала **Plugin Executi","content":"EasyP vs buf.build Feature EasyP buf.build --------- -------- ----------- **Dependency Management** Git‑репозитории Buf Schema Registry (BSR) **Vendor Lock-in** Нет Привязка к BSR для полного функционала **Plugin Execution** Local + Remote Local + BSR plugins **Private Dependencies** Любой Git провайдер BSR или ручное управление **Offline Development** Полная поддержка (mod vendor) Ограниченно без доступа к BSR **Enterprise Integration** Использует существующий Git Требует настройку BSR **Breaking Change Detection** Против любой Git ссылки Аналогично **Package Distribution** Любой Git Публикация через BSR **License** Apache 2.0 Apache 2.0 **Community** Growing Established"},{"id":"introduction/what-is::easyp-vs-bufbuild::20","title":"Что такое EasyP?","section":"EasyP vs buf.build","path":"/docs/guide/introduction/what-is#easyp-vs-bufbuild","headings":["EasyP vs buf.build"],"excerpt":"EasyP vs buf.build **Преимущества миграции:** Без изменения инфраструктуры Плавное принятие новых возможностей Гибрид локальных и удалённых плагинов Единая конфигурация вместо набора файлов","content":"EasyP vs buf.build **Преимущества миграции:** Без изменения инфраструктуры Плавное принятие новых возможностей Гибрид локальных и удалённых плагинов Единая конфигурация вместо набора файлов"},{"id":"introduction/what-is::protobuf::21","title":"Что такое EasyP?","section":"Наши цели для Protobuf","path":"/docs/guide/introduction/what-is#protobuf","headings":["Наши цели для Protobuf"],"excerpt":"Наши цели для Protobuf Миссия EasyP — ускорить принятие **schema‑driven API** через удобный, надёжный и прозрачный инструментарий.","content":"Наши цели для Protobuf Миссия EasyP — ускорить принятие **schema‑driven API** через удобный, надёжный и прозрачный инструментарий."},{"id":"introduction/what-is::top::22","title":"Что такое EasyP?","section":"Современная экосистема","path":"/docs/guide/introduction/what-is","headings":["Современная экосистема"],"excerpt":"Современная экосистема Повышаем DX вокруг protobuf, чтобы конкурентно выглядеть по простоте против REST/JSON, сохраняя типовую строгость и производительность.","content":"Современная экосистема Повышаем DX вокруг protobuf, чтобы конкурентно выглядеть по простоте против REST/JSON, сохраняя типовую строгость и производительность."},{"id":"introduction/what-is::developer-experience::23","title":"Что такое EasyP?","section":"Developer Experience прежде всего","path":"/docs/guide/introduction/what-is#developer-experience","headings":["Developer Experience прежде всего"],"excerpt":"Developer Experience прежде всего Интуитивный CLI, понятные ошибки, ясные сообщения, минимальная фрагментация.","content":"Developer Experience прежде всего Интуитивный CLI, понятные ошибки, ясные сообщения, минимальная фрагментация."},{"id":"introduction/what-is::enterprise::24","title":"Что такое EasyP?","section":"Готов к Enterprise","path":"/docs/guide/introduction/what-is#enterprise","headings":["Готов к Enterprise"],"excerpt":"Готов к Enterprise Воспроизводимые сборки, приватные репозитории, интеграция в CI/CD.","content":"Готов к Enterprise Воспроизводимые сборки, приватные репозитории, интеграция в CI/CD."},{"id":"introduction/what-is::top::25","title":"Что такое EasyP?","section":"Для индивидуальных разработчиков","path":"/docs/guide/introduction/what-is","headings":["Для индивидуальных разработчиков"],"excerpt":"Для индивидуальных разработчиков Быстрый старт за минуты Один инструмент — меньше когнитивной нагрузки Понятная документация","content":"Для индивидуальных разработчиков Быстрый старт за минуты Один инструмент — меньше когнитивной нагрузки Понятная документация"},{"id":"introduction/what-is::top::26","title":"Что такое EasyP?","section":"Для команд","path":"/docs/guide/introduction/what-is","headings":["Для команд"],"excerpt":"Для команд Единые стандарты Повторяемые сборки (lock‑файл) Ускоренный онбординг","content":"Для команд Единые стандарты Повторяемые сборки (lock‑файл) Ускоренный онбординг"},{"id":"introduction/what-is::top::27","title":"Что такое EasyP?","section":"Для организаций","path":"/docs/guide/introduction/what-is","headings":["Для организаций"],"excerpt":"Для организаций Нет vendor lock‑in Безопасность приватных репозиториев Лёгкая интеграция в существующие пайплайны","content":"Для организаций Нет vendor lock‑in Безопасность приватных репозиториев Лёгкая интеграция в существующие пайплайны"},{"id":"introduction/what-is::top::28","title":"Что такое EasyP?","section":"Что дальше?","path":"/docs/guide/introduction/what-is","headings":["Что дальше?"],"excerpt":"Что дальше? EasyP упрощает работу с protobuf — фокусируйтесь на API, а не на рутине. Хотите начать?","content":"Что дальше? EasyP упрощает работу с protobuf — фокусируйтесь на API, а не на рутине. Хотите начать?"},{"id":"introduction/what-is::top::29","title":"Что такое EasyP?","section":"Что дальше?","path":"/docs/guide/introduction/what-is","headings":["Что дальше?"],"excerpt":"Что дальше? Смотрите Installation Guide и Quickstart.","content":"Что дальше? Смотрите Installation Guide и Quickstart."},{"id":"introduction/what-is::stargazers-over-time::30","title":"Что такое 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 В работе","content":"Buf CLI В работе"},{"id":"migration/protoc::top::0","title":"Миграция с protoc на EasyP","path":"/docs/guide/migration/protoc","headings":[],"excerpt":"Исходная англоязычная версия файла содержала только заголовок и пометку “Work in progress”. Ниже — полноценный русскоязычный черновик раздела миграции. Уточни, если требуется сократить или изменить уровень детализации.","content":"Исходная англоязычная версия файла содержала только заголовок и пометку “Work in progress”. Ниже — полноценный русскоязычный черновик раздела миграции. Уточни, если требуется сократить или изменить уровень детализации."},{"id":"migration/protoc::1::1","title":"Миграция с protoc на EasyP","section":"1. Краткое сравнение","path":"/docs/guide/migration/protoc#1","headings":["1. Краткое сравнение"],"excerpt":"Краткое сравнение Аспект protoc EasyP -------- ---------- ------- Базовая роль Базовый компилятор .proto файлов Инструмент “всё в одном”: линтинг, проверка несовместимых изменений, менеджер пакетов, генерация Конфигураци","content":"Краткое сравнение Аспект protoc EasyP -------- ---------- ------- Базовая роль Базовый компилятор .proto файлов Инструмент “всё в одном”: линтинг, проверка несовместимых изменений, менеджер пакетов, генерация Конфигурация Чаще shell‑скрипты / Makefile / вручную передаваемые флаги Единый файл easyp.yaml (YAML или JSON) Управление зависимостями Ручной git clone, submodule, vendoring Секция deps с Git‑репозиториями Набор правил линтера Нет встроенного Встроенный линтер с правилами (можно включать/исключать) Проверка breaking changes Отсутствует из коробки Команда easyp breaking Расширенные плагины Установка и вызов через флаги --plugin Плагины через конфиг; поддержка удалённого выполнения (API Service) и стандартного локального Единообразие в CI Нужно собирать вручную Консистентные команды: lint, breaking, generate"},{"id":"migration/protoc::2::2","title":"Миграция с protoc на EasyP","section":"2. Когда имеет смысл мигрировать","path":"/docs/guide/migration/protoc#2","headings":["2. Когда имеет смысл мигрировать"],"excerpt":"Когда имеет смысл мигрировать Миграция на EasyP особенно полезна если: Есть потребность в автоматической проверке качества (стиль, именование) .proto файлов. Нужна защита от нелегитимных несовместимых изменений при эволю","content":"Когда имеет смысл мигрировать Миграция на EasyP особенно полезна если: Есть потребность в автоматической проверке качества (стиль, именование) .proto файлов. Нужна защита от нелегитимных несовместимых изменений при эволюции схем. В проекте используется несколько языков генерации и растёт число скриптов вокруг protoc. Вы хотите единый конфиг вместо множества shell/Makefile комбинаций. Планируется централизованное исполнение плагинов (через API Service) или унификация окружения в CI."},{"id":"migration/protoc::3-protoc::3","title":"Миграция с protoc на EasyP","section":"3. Типичный сценарий “до” (только protoc)","path":"/docs/guide/migration/protoc#3-protoc","headings":["3. Типичный сценарий “до” (только protoc)"],"excerpt":"Типичный сценарий “до” (только protoc) Пример: локальные скрипты / Makefile:","content":"Типичный сценарий “до” (только protoc) Пример: локальные скрипты / Makefile:"},{"id":"migration/protoc::3-protoc::4","title":"Миграция с protoc на EasyP","section":"3. Типичный сценарий “до” (только protoc)","path":"/docs/guide/migration/protoc#3-protoc","headings":["3. Типичный сценарий “до” (только protoc)"],"excerpt":"Типичный сценарий “до” (только protoc)","content":"Типичный сценарий “до” (только protoc)"},{"id":"migration/protoc::3-protoc::5","title":"Миграция с protoc на EasyP","section":"3. Типичный сценарий “до” (только protoc)","path":"/docs/guide/migration/protoc#3-protoc","headings":["3. Типичный сценарий “до” (только protoc)"],"excerpt":"Типичный сценарий “до” (только protoc) Дополнительные зависимости (googleapis, validate, grpc-gateway) скачиваются вручную или через submodules.","content":"Типичный сценарий “до” (только protoc) Дополнительные зависимости (googleapis, validate, grpc-gateway) скачиваются вручную или через submodules."},{"id":"migration/protoc::4-easyp::6","title":"Миграция с protoc на EasyP","section":"4. Типичный сценарий “после” (EasyP)","path":"/docs/guide/migration/protoc#4-easyp","headings":["4. Типичный сценарий “после” (EasyP)"],"excerpt":"Типичный сценарий “после” (EasyP) Единый файл easyp.yaml:","content":"Типичный сценарий “после” (EasyP) Единый файл easyp.yaml:"},{"id":"migration/protoc::4-easyp::7","title":"Миграция с protoc на EasyP","section":"4. Типичный сценарий “после” (EasyP)","path":"/docs/guide/migration/protoc#4-easyp","headings":["4. Типичный сценарий “после” (EasyP)"],"excerpt":"Типичный сценарий “после” (EasyP) ```yaml deps: - github.com/googleapis/googleapis - github.com/envoyproxy/protoc-gen-validate","content":"Типичный сценарий “после” (EasyP) ```yaml deps: - github.com/googleapis/googleapis - github.com/envoyproxy/protoc-gen-validate"},{"id":"migration/protoc::4-easyp::8","title":"Миграция с protoc на EasyP","section":"4. Типичный сценарий “после” (EasyP)","path":"/docs/guide/migration/protoc#4-easyp","headings":["4. Типичный сценарий “после” (EasyP)"],"excerpt":"Типичный сценарий “после” (EasyP) generate: plugins: - name: go out: gen/go opts: paths: source_relative - name: go-grpc out: gen/go opts: paths: source_relative require_unimplemented_servers: false - name: validate out:","content":"Типичный сценарий “после” (EasyP) generate: plugins: - name: go out: gen/go opts: paths: source_relative - name: go-grpc out: gen/go opts: paths: source_relative require_unimplemented_servers: false - name: validate out: gen/go opts: paths: source_relative lang: \"go\" ```"},{"id":"migration/protoc::4-easyp::9","title":"Миграция с protoc на EasyP","section":"4. Типичный сценарий “после” (EasyP)","path":"/docs/guide/migration/protoc#4-easyp","headings":["4. Типичный сценарий “после” (EasyP)"],"excerpt":"Типичный сценарий “после” (EasyP) Команды:","content":"Типичный сценарий “после” (EasyP) Команды:"},{"id":"migration/protoc::5::10","title":"Миграция с protoc на EasyP","section":"5. Пошаговая миграция","path":"/docs/guide/migration/protoc#5","headings":["5. Пошаговая миграция"],"excerpt":"Пошаговая миграция Инвентаризация: - Соберите список всех вызовов protoc (скрипты, Makefile, CI). - Зафиксируйте используемые плагины и их версии. Создание easyp.yaml: - Поле version не обязательно (можете оставить его т","content":"Пошаговая миграция Инвентаризация: - Соберите список всех вызовов protoc (скрипты, Makefile, CI). - Зафиксируйте используемые плагины и их версии. Создание easyp.yaml: - Поле version не обязательно (можете оставить его только для обратной совместимости). - Перенесите плагины в секцию generate.plugins. - Укажите опции, которые ранее передавались в командной строке. Зависимости: - Все внешние каталоги (googleapis, validate, grpc-gateway и т.п.) занесите в deps. - Удалите лишние submodules при необходимости. Линтер: - Запустите easyp lint и посмотрите на предупреждения. - При необходимости добавьте lint.use, lint.ignore, lint.except. Проверка breaking changes: - Выберите референс (обычно origin/main или предыдущий тег). - Запустите easyp breaking --against git-ref=origin/main. - Настройте игнорируемые изменения (breaking.ignore), если нужно. Обновление CI: - Замените прямые вызовы protoc на easyp generate. - Добавьте отдельные шаги lint и breaking. Очистка: - Удалите устаревшие генерационные скрипты, если они дублируют функционал EasyP. Документация: - Обновите README / CONTRIBUTING (новый способ генерации). Верификация: - Сравните результат генерации до и после (git diff). - Убедитесь, что имена файлов и пути совпадают или скорректируйте структуру."},{"id":"migration/protoc::6-ci-github-actions::11","title":"Миграция с protoc на EasyP","section":"6. Замена в CI (пример GitHub Actions)","path":"/docs/guide/migration/protoc#6-ci-github-actions","headings":["6. Замена в CI (пример GitHub Actions)"],"excerpt":"Замена в CI (пример GitHub Actions) ```yaml name: Install EasyP run: go install github.com/easyp-tech/easyp/cmd/easyp@latest","content":"Замена в CI (пример GitHub Actions) ```yaml name: Install EasyP run: go install github.com/easyp-tech/easyp/cmd/easyp@latest"},{"id":"migration/protoc::6-ci-github-actions::12","title":"Миграция с protoc на EasyP","section":"6. Замена в CI (пример GitHub Actions)","path":"/docs/guide/migration/protoc#6-ci-github-actions","headings":["6. Замена в CI (пример GitHub Actions)"],"excerpt":"Замена в CI (пример GitHub Actions) name: Lint run: easyp lint","content":"Замена в CI (пример GitHub Actions) name: Lint run: easyp lint"},{"id":"migration/protoc::6-ci-github-actions::13","title":"Миграция с protoc на EasyP","section":"6. Замена в CI (пример GitHub Actions)","path":"/docs/guide/migration/protoc#6-ci-github-actions","headings":["6. Замена в CI (пример GitHub Actions)"],"excerpt":"Замена в CI (пример GitHub Actions) name: Breaking run: easyp breaking --against git-ref=origin/main","content":"Замена в CI (пример GitHub Actions) name: Breaking run: easyp breaking --against git-ref=origin/main"},{"id":"migration/protoc::6-ci-github-actions::14","title":"Миграция с protoc на EasyP","section":"6. Замена в CI (пример GitHub Actions)","path":"/docs/guide/migration/protoc#6-ci-github-actions","headings":["6. Замена в CI (пример GitHub Actions)"],"excerpt":"Замена в CI (пример GitHub Actions) name: Generate run: easyp generate ```","content":"Замена в CI (пример GitHub Actions) name: Generate run: easyp generate ```"},{"id":"migration/protoc::7::15","title":"Миграция с protoc на EasyP","section":"7. Работа с плагинами","path":"/docs/guide/migration/protoc#7","headings":["7. Работа с плагинами"],"excerpt":"Работа с плагинами Тип В protoc В EasyP ----- ---------- --------- Стандартные (protoc-gen-go) Указание через --go_out plugins: - name: go ... gRPC --go-grpc_out Второй плагин go-grpc Validate Доп. установка + --validate","content":"Работа с плагинами Тип В protoc В EasyP ----- ---------- --------- Стандартные (protoc-gen-go) Указание через --go_out plugins: - name: go ... gRPC --go-grpc_out Второй плагин go-grpc Validate Доп. установка + --validate_out - name: validate с opts gRPC-Gateway / OpenAPI --grpc-gateway_out / --openapiv2_out Плагины grpc-gateway, openapiv2 Кастомные Путь к бинарю / --plugin=protoc-gen-xxx - name: xxx или удалённый remote: (если используется API Service)"},{"id":"migration/protoc::7::16","title":"Миграция с protoc на EasyP","section":"7. Работа с плагинами","path":"/docs/guide/migration/protoc#7","headings":["7. Работа с плагинами"],"excerpt":"Работа с плагинами Если вы переходите на удалённое выполнение (API Service), записи в конфиге могут выглядеть так:","content":"Работа с плагинами Если вы переходите на удалённое выполнение (API Service), записи в конфиге могут выглядеть так:"},{"id":"migration/protoc::8::17","title":"Миграция с protoc на EasyP","section":"8. Проверка корректности после миграции","path":"/docs/guide/migration/protoc#8","headings":["8. Проверка корректности после миграции"],"excerpt":"Проверка корректности после миграции git diff после easyp generate — не должно быть неожиданных изменений. Сравнить размер и содержимое каталога сгенерированных файлов. Запустить ваш потребляющий код (сборка, тесты). Про","content":"Проверка корректности после миграции git diff после easyp generate — не должно быть неожиданных изменений. Сравнить размер и содержимое каталога сгенерированных файлов. Запустить ваш потребляющий код (сборка, тесты). Проверить, что плагины (validate, grpc-gateway) продолжают вставлять необходимые аннотации / опции. Линт не должен выдавать критичных ошибок — скорректируйте стиль .proto, если требуется."},{"id":"migration/protoc::9::18","title":"Миграция с protoc на EasyP","section":"9. Частые проблемы","path":"/docs/guide/migration/protoc#9","headings":["9. Частые проблемы"],"excerpt":"Частые проблемы Проблема Причина Решение ---------- --------- --------- Плагин не найден Не установлен или не указан в PATH Выполнить go install ... или добавить в конфиг как remote Ошибка импорта .proto Отсутствует репо","content":"Частые проблемы Проблема Причина Решение ---------- --------- --------- Плагин не найден Не установлен или не указан в PATH Выполнить go install ... или добавить в конфиг как remote Ошибка импорта .proto Отсутствует репозиторий в deps Добавить адрес в секцию deps и easyp mod update Несовместимые изменения на каждом PR Отсутствует игнор/настройка сравнения Уточнить ветку/тег в --against или настроить breaking.ignore Локально работает, в CI падает В CI нет зависимостей (не вызван update) Добавить шаг easyp mod update перед generate Дубликаты сгенерированных файлов Изменена структура путей или out Синхронизировать out и paths: source_relative опции"},{"id":"migration/protoc::10-go::19","title":"Миграция с protoc на EasyP","section":"10. Минимальный пример конфигурации (только Go)","path":"/docs/guide/migration/protoc#10-go","headings":["10. Минимальный пример конфигурации (только Go)"],"excerpt":"Минимальный пример конфигурации (только Go)","content":"Минимальный пример конфигурации (только Go)"},{"id":"migration/protoc::10-go::20","title":"Миграция с protoc на EasyP","section":"10. Минимальный пример конфигурации (только Go)","path":"/docs/guide/migration/protoc#10-go","headings":["10. Минимальный пример конфигурации (только Go)"],"excerpt":"Минимальный пример конфигурации (только Go) Команды:","content":"Минимальный пример конфигурации (только Go) Команды:"},{"id":"migration/protoc::11-go-grpc-gateway-validate-breaking-lint::21","title":"Миграция с protoc на EasyP","section":"11. Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint)","path":"/docs/guide/migration/protoc#11-go-grpc-gateway-validate-breaking-lint","headings":["11. Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint)"],"excerpt":"Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint) ```yaml lint: use: - ENUM_FIRST_VALUE_ZERO - SERVICE_SUFFIX allow_comment_ignores: false enum_zero_value_suffix: _NONE service_suffix: Service","content":"Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint) ```yaml lint: use: - ENUM_FIRST_VALUE_ZERO - SERVICE_SUFFIX allow_comment_ignores: false enum_zero_value_suffix: _NONE service_suffix: Service"},{"id":"migration/protoc::11-go-grpc-gateway-validate-breaking-lint::22","title":"Миграция с protoc на EasyP","section":"11. Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint)","path":"/docs/guide/migration/protoc#11-go-grpc-gateway-validate-breaking-lint","headings":["11. Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint)"],"excerpt":"Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint) deps: - github.com/googleapis/googleapis - github.com/envoyproxy/protoc-gen-validate","content":"Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint) deps: - github.com/googleapis/googleapis - github.com/envoyproxy/protoc-gen-validate"},{"id":"migration/protoc::11-go-grpc-gateway-validate-breaking-lint::23","title":"Миграция с protoc на EasyP","section":"11. Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint)","path":"/docs/guide/migration/protoc#11-go-grpc-gateway-validate-breaking-lint","headings":["11. Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint)"],"excerpt":"Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint) generate: plugins: - name: go out: gen/go opts: paths: source_relative - name: go-grpc out: gen/go opts: paths: source_relative require_unimplemented_","content":"Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint) generate: plugins: - name: go out: gen/go opts: paths: source_relative - name: go-grpc out: gen/go opts: paths: source_relative require_unimplemented_servers: false - name: validate out: gen/go opts: paths: source_relative lang: \"go\" - name: grpc-gateway out: gen/go opts: paths: source_relative - name: openapiv2 out: gen/openapi opts: simple_operation_ids: true"},{"id":"migration/protoc::11-go-grpc-gateway-validate-breaking-lint::24","title":"Миграция с protoc на EasyP","section":"11. Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint)","path":"/docs/guide/migration/protoc#11-go-grpc-gateway-validate-breaking-lint","headings":["11. Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint)"],"excerpt":"Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint) breaking: against_git_ref: main ignore: - ENUM_VALUE_SAME_NAME ```","content":"Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint) breaking: against_git_ref: main ignore: - ENUM_VALUE_SAME_NAME ```"},{"id":"migration/protoc::12-checklist::25","title":"Миграция с protoc на EasyP","section":"12. Checklist миграции","path":"/docs/guide/migration/protoc#12-checklist","headings":["12. Checklist миграции"],"excerpt":"Checklist миграции [ ] Собраны все текущие вызовы protoc. [ ] Создан easyp.yaml с секциями generate и (опционально) lint, breaking. [ ] Добавлены все внешние зависимости в deps. [ ] Успешно выполнен easyp mod update. [ ]","content":"Checklist миграции [ ] Собраны все текущие вызовы protoc. [ ] Создан easyp.yaml с секциями generate и (опционально) lint, breaking. [ ] Добавлены все внешние зависимости в deps. [ ] Успешно выполнен easyp mod update. [ ] easyp generate даёт идентичный или ожидаемо обновлённый результат. [ ] easyp lint проходит без критичных ошибок (или ошибки обработаны). [ ] easyp breaking --against git-ref=origin/main не выдаёт неожиданных блокирующих нарушений. [ ] CI обновлён (заменены прямые вызовы protoc). [ ] Документация проекта обновлена (README: как генерировать)."},{"id":"migration/protoc::13::26","title":"Миграция с protoc на EasyP","section":"13. Дополнительные рекомендации","path":"/docs/guide/migration/protoc#13","headings":["13. Дополнительные рекомендации"],"excerpt":"Дополнительные рекомендации Сначала мигрируйте один сервис / пакет — снизит риск массовых конфликтов. Закоммитьте easyp.yaml отдельно, затем выполните генерацию и линт — проще ревью. Если нужны разные наборы плагинов для","content":"Дополнительные рекомендации Сначала мигрируйте один сервис / пакет — снизит риск массовых конфликтов. Закоммитьте easyp.yaml отдельно, затем выполните генерацию и линт — проще ревью. Если нужны разные наборы плагинов для разных микросервисов — используйте несколько конфигов (например: easyp.microservice-a.yaml + easyp.microservice-b.yaml). Внедрите проверку актуальности генерации: шаг CI, который валидирует отсутствие diff после easyp generate."},{"id":"migration/protoc::14::27","title":"Миграция с protoc на EasyP","section":"14. Статус","path":"/docs/guide/migration/protoc#14","headings":["14. Статус"],"excerpt":"Статус Этот файл — русская расширенная версия, заменяющая placeholder “Work in progress”. При появлении новых возможностей EasyP (дополнительные поля в конфиге, новые плагины, расширения breaking‑проверок) обновите соотв","content":"Статус Этот файл — русская расширенная версия, заменяющая placeholder “Work in progress”. При появлении новых возможностей EasyP (дополнительные поля в конфиге, новые плагины, расширения breaking‑проверок) обновите соответствующие разделы."},{"id":"migration/protoc::14::28","title":"Миграция с protoc на EasyP","section":"14. Статус","path":"/docs/guide/migration/protoc#14","headings":["14. Статус"],"excerpt":"Статус Если нужен упрощённый вариант (только перевод без расширения), сообщи — могу сократить до минимальных двух блоков.","content":"Статус Если нужен упрощённый вариант (только перевод без расширения), сообщи — могу сократить до минимальных двух блоков."},{"id":"migration/protolock::top::0","title":"Protolock","path":"/docs/guide/migration/protolock","headings":[],"excerpt":"Protolock В процессе разработки","content":"Protolock В процессе разработки"},{"id":"migration/prototool::top::0","title":"Prototool","section":"Состояние","path":"/docs/guide/migration/prototool","headings":["Состояние"],"excerpt":"Состояние Этот раздел был помечен как “Work in progress” в оригинальной английской версии. Ниже — переведённое и дополненное практическое руководство по миграции с Prototool на EasyP. Имя инструмента Prototool не перевод","content":"Состояние Этот раздел был помечен как “Work in progress” в оригинальной английской версии. Ниже — переведённое и дополненное практическое руководство по миграции с Prototool на EasyP. Имя инструмента Prototool не переводится."},{"id":"migration/prototool::top::1","title":"Prototool","section":"Цель миграции","path":"/docs/guide/migration/prototool","headings":["Цель миграции"],"excerpt":"Цель миграции Перейти от конфигурации и рабочих процессов Prototool к эквиваленту на EasyP с минимальными изменениями, сохранив: Линтинг .proto файлов. Генерацию кода через protoc-плагины. Управление зависимостями. Прове","content":"Цель миграции Перейти от конфигурации и рабочих процессов Prototool к эквиваленту на EasyP с минимальными изменениями, сохранив: Линтинг .proto файлов. Генерацию кода через protoc-плагины. Управление зависимостями. Проверку несовместимых изменений (в Prototool это приходилось реализовывать внешними инструментами; в EasyP встроено)."},{"id":"migration/prototool::top::2","title":"Prototool","section":"Кратко о различиях","path":"/docs/guide/migration/prototool","headings":["Кратко о различиях"],"excerpt":"Кратко о различиях Область Prototool EasyP Комментарий --------- ----------- ------- ------------- Конфигурация prototool.yaml easyp.yaml Форматы YAML/JSON поддерживаются; структура отличается. Линтинг Встроенные наборы ","content":"Кратко о различиях Область Prototool EasyP Комментарий --------- ----------- ------- ------------- Конфигурация prototool.yaml easyp.yaml Форматы YAML/JSON поддерживаются; структура отличается. Линтинг Встроенные наборы + кастомные правила Наборы через lint.use, тонкая настройка ignore/except EasyP даёт больше гибкости группировки. Генерация Раздел generate + плагины через Docker/локально generate.plugins (локальные/WASM/удалённые) EasyP может выполнять плагины удалённо (API Service). Зависимости Обычно через include-пути / внешние git clone вручную Секция deps (Git репозитории) + mod update Более декларативно. Breaking Changes Нет встроенного механизма Секция breaking + команда easyp breaking Из коробки. Lock-in Зависимость от модели Prototool Минималистичный формат, «любой Git — пакет» Облегчает выход / интеграцию с другими экосистемами."},{"id":"migration/prototool::prototool::3","title":"Prototool","section":"Типовая структура Prototool (упрощённо)","path":"/docs/guide/migration/prototool#prototool","headings":["Типовая структура Prototool (упрощённо)"],"excerpt":"Типовая структура Prototool (упрощённо)","content":"Типовая структура Prototool (упрощённо)"},{"id":"migration/prototool::prototool::4","title":"Prototool","section":"Типовая структура Prototool (упрощённо)","path":"/docs/guide/migration/prototool#prototool","headings":["Типовая структура Prototool (упрощённо)"],"excerpt":"Типовая структура Prototool (упрощённо) Особенности: include_paths задаёт пути поиска импортов. lint.group + rules.add/remove регулируют активные проверки. generate.plugins описывает плагины для protoc.","content":"Типовая структура Prototool (упрощённо) Особенности: include_paths задаёт пути поиска импортов. lint.group + rules.add/remove регулируют активные проверки. generate.plugins описывает плагины для protoc."},{"id":"migration/prototool::prototool::5","title":"Prototool","section":"Типовая структура Prototool (упрощённо)","path":"/docs/guide/migration/prototool#prototool","headings":["Типовая структура Prototool (упрощённо)"],"excerpt":"Типовая структура Prototool (упрощённо) ---","content":"Типовая структура Prototool (упрощённо) ---"},{"id":"migration/prototool::easyp::6","title":"Prototool","section":"Эквивалент на EasyP","path":"/docs/guide/migration/prototool#easyp","headings":["Эквивалент на EasyP"],"excerpt":"Эквивалент на EasyP ```yaml easyp.yaml (пример) deps: - github.com/org/common-protos # вместо manual include - github.com/org/third-party-protos","content":"Эквивалент на EasyP ```yaml easyp.yaml (пример) deps: - github.com/org/common-protos # вместо manual include - github.com/org/third-party-protos"},{"id":"migration/prototool::easyp::7","title":"Prototool","section":"Эквивалент на EasyP","path":"/docs/guide/migration/prototool#easyp","headings":["Эквивалент на EasyP"],"excerpt":"Эквивалент на EasyP lint: use: - MINIMAL - BASIC enum_zero_value_suffix: \"_NONE\" service_suffix: \"Service\" ignore: - COMMENT_FIELD except: - ENUM_VALUE_PREFIX allow_comment_ignores: true","content":"Эквивалент на EasyP lint: use: - MINIMAL - BASIC enum_zero_value_suffix: \"_NONE\" service_suffix: \"Service\" ignore: - COMMENT_FIELD except: - ENUM_VALUE_PREFIX allow_comment_ignores: true"},{"id":"migration/prototool::easyp::8","title":"Prototool","section":"Эквивалент на EasyP","path":"/docs/guide/migration/prototool#easyp","headings":["Эквивалент на EasyP"],"excerpt":"Эквивалент на EasyP generate: plugins: - name: go out: gen/go opts: paths: source_relative - name: go-grpc out: gen/go opts: paths: source_relative require_unimplemented_servers: false","content":"Эквивалент на EasyP generate: plugins: - name: go out: gen/go opts: paths: source_relative - name: go-grpc out: gen/go opts: paths: source_relative require_unimplemented_servers: false"},{"id":"migration/prototool::easyp::9","title":"Prototool","section":"Эквивалент на EasyP","path":"/docs/guide/migration/prototool#easyp","headings":["Эквивалент на EasyP"],"excerpt":"Эквивалент на EasyP breaking: against_git_ref: main ignore: - FIELD_SAME_TYPE ```","content":"Эквивалент на EasyP breaking: against_git_ref: main ignore: - FIELD_SAME_TYPE ```"},{"id":"migration/prototool::easyp::10","title":"Prototool","section":"Эквивалент на EasyP","path":"/docs/guide/migration/prototool#easyp","headings":["Эквивалент на EasyP"],"excerpt":"Эквивалент на EasyP Комментарии: deps заменяет необходимость вручную прописывать include paths: EasyP подтянет их через git. lint.use активирует наборы правил (MINIMAL/BASIC/DEFAULT и т.д.). Дополнительные настройки (enu","content":"Эквивалент на EasyP Комментарии: deps заменяет необходимость вручную прописывать include paths: EasyP подтянет их через git. lint.use активирует наборы правил (MINIMAL/BASIC/DEFAULT и т.д.). Дополнительные настройки (enum_zero_value_suffix, service_suffix) задают политики нейминга. breaking позволяет сразу контролировать несовместимые изменения."},{"id":"migration/prototool::top::11","title":"Prototool","section":"Шаги миграции","path":"/docs/guide/migration/prototool","headings":["Шаги миграции"],"excerpt":"Шаги миграции Инвентаризация: - Соберите текущий prototool.yaml, списки include paths и плагины. - Зафиксируйте используемые кастомные правила, если есть.","content":"Шаги миграции Инвентаризация: - Соберите текущий prototool.yaml, списки include paths и плагины. - Зафиксируйте используемые кастомные правила, если есть."},{"id":"migration/prototool::top::12","title":"Prototool","section":"Шаги миграции","path":"/docs/guide/migration/prototool","headings":["Шаги миграции"],"excerpt":"Шаги миграции Зависимости: - Любые каталоги, которые вы вручную добавляли в include_paths, преобразуйте в git-репозитории (если ещё нет). - Добавьте их в deps (формат: github.com/owner/repo или путь к вашей приватной сис","content":"Шаги миграции Зависимости: - Любые каталоги, которые вы вручную добавляли в include_paths, преобразуйте в git-репозитории (если ещё нет). - Добавьте их в deps (формат: github.com/owner/repo или путь к вашей приватной системе Git)."},{"id":"migration/prototool::top::13","title":"Prototool","section":"Шаги миграции","path":"/docs/guide/migration/prototool","headings":["Шаги миграции"],"excerpt":"Шаги миграции Линтинг: - Определите какой group использовался (basic, default, …) → сопоставьте с наборами EasyP (MINIMAL, BASIC, DEFAULT). - Индивидуальные добавления (rules.add) перенесите в lint.use или except/ignore:","content":"Шаги миграции Линтинг: - Определите какой group использовался (basic, default, …) → сопоставьте с наборами EasyP (MINIMAL, BASIC, DEFAULT). - Индивидуальные добавления (rules.add) перенесите в lint.use или except/ignore: - Если правило нужно активировать — включите через набор или явно. - Если нужно отключить — добавьте в ignore."},{"id":"migration/prototool::top::14","title":"Prototool","section":"Шаги миграции","path":"/docs/guide/migration/prototool","headings":["Шаги миграции"],"excerpt":"Шаги миграции Генерация: - Сохраните список плагинов. В большинстве случаев имена совпадут (go, go-grpc, др.). - Если раньше использовали Docker-окружение Prototool — проверьте поддержку удалённых плагинов через API Serv","content":"Шаги миграции Генерация: - Сохраните список плагинов. В большинстве случаев имена совпадут (go, go-grpc, др.). - Если раньше использовали Docker-окружение Prototool — проверьте поддержку удалённых плагинов через API Service EasyP (опционально). - Перепишите в секцию generate.plugins."},{"id":"migration/prototool::top::15","title":"Prototool","section":"Шаги миграции","path":"/docs/guide/migration/prototool","headings":["Шаги миграции"],"excerpt":"Шаги миграции Дополнительные опции: - Настройки нейминга enum/service перенести в enum_zero_value_suffix, service_suffix. - Если были внешние скрипты для проверки breaking changes — удалите их и включите breaking с again","content":"Шаги миграции Дополнительные опции: - Настройки нейминга enum/service перенести в enum_zero_value_suffix, service_suffix. - Если были внешние скрипты для проверки breaking changes — удалите их и включите breaking с against_git_ref."},{"id":"migration/prototool::top::16","title":"Prototool","section":"Шаги миграции","path":"/docs/guide/migration/prototool","headings":["Шаги миграции"],"excerpt":"Шаги миграции Верификация: - Запустите: easyp mod update (скачивание deps). - Затем: easyp lint. - Далее: easyp generate. - И, если нужно: easyp breaking --against git-ref=origin/main.","content":"Шаги миграции Верификация: - Запустите: easyp mod update (скачивание deps). - Затем: easyp lint. - Далее: easyp generate. - И, если нужно: easyp breaking --against git-ref=origin/main."},{"id":"migration/prototool::top::17","title":"Prototool","section":"Шаги миграции","path":"/docs/guide/migration/prototool","headings":["Шаги миграции"],"excerpt":"Шаги миграции CI/CD: - Обновите workflow (GitHub Actions / GitLab) — замените вызовы Prototool на EasyP команды. - Добавьте шаг проверки несовместимых изменений.","content":"Шаги миграции CI/CD: - Обновите workflow (GitHub Actions / GitLab) — замените вызовы Prototool на EasyP команды. - Добавьте шаг проверки несовместимых изменений."},{"id":"migration/prototool::top::18","title":"Prototool","section":"Сопоставление правил (общая идея)","path":"/docs/guide/migration/prototool","headings":["Сопоставление правил (общая идея)"],"excerpt":"Сопоставление правил (общая идея) Prototool концепт EasyP ------------------- ------ lint.group lint.use (наборы) rules.add/remove except / ignore include_paths deps (git источники) plugins generate.plugins (внешние скри","content":"Сопоставление правил (общая идея) Prototool концепт EasyP ------------------- ------ lint.group lint.use (наборы) rules.add/remove except / ignore include_paths deps (git источники) plugins generate.plugins (внешние скрипты для breaking) breaking секция + команда"},{"id":"migration/prototool::top::19","title":"Prototool","section":"Сопоставление правил (общая идея)","path":"/docs/guide/migration/prototool","headings":["Сопоставление правил (общая идея)"],"excerpt":"Сопоставление правил (общая идея) ---","content":"Сопоставление правил (общая идея) ---"},{"id":"migration/prototool::top::20","title":"Prototool","section":"Приватные репозитории","path":"/docs/guide/migration/prototool","headings":["Приватные репозитории"],"excerpt":"Приватные репозитории Если ранее Prototool просто видел локальные каталоги, теперь: Добавьте SSH ключи/токены в CI для доступа к приватным Git. Укажите их в deps как обычные git-URL (формат зависит от реализации EasyP; д","content":"Приватные репозитории Если ранее Prototool просто видел локальные каталоги, теперь: Добавьте SSH ключи/токены в CI для доступа к приватным Git. Укажите их в deps как обычные git-URL (формат зависит от реализации EasyP; для публичных — стандартный)."},{"id":"migration/prototool::top::21","title":"Prototool","section":"Типовые проблемы при миграции","path":"/docs/guide/migration/prototool","headings":["Типовые проблемы при миграции"],"excerpt":"Типовые проблемы при миграции Проблема Причина Решение ---------- --------- --------- Правила линтера не совпадают Неверное сопоставление групп Проверить документацию EasyP по наборам правил Импорты не находятся Забыли д","content":"Типовые проблемы при миграции Проблема Причина Решение ---------- --------- --------- Правила линтера не совпадают Неверное сопоставление групп Проверить документацию EasyP по наборам правил Импорты не находятся Забыли добавить репозиторий в deps Добавить в deps и выполнить easyp mod update Генерация падает на опциях Плагин требует другие flags Проверить opts и документацию плагина breaking сообщает слишком много Слишком строгий базовый набор Добавить конкретные правила в breaking.ignore Долгая генерация Нет кеша/много deps Включить кэширование в CI (vendor/.easyp/deps)"},{"id":"migration/prototool::top::22","title":"Prototool","section":"Типовые проблемы при миграции","path":"/docs/guide/migration/prototool","headings":["Типовые проблемы при миграции"],"excerpt":"Типовые проблемы при миграции ---","content":"Типовые проблемы при миграции ---"},{"id":"migration/prototool::top::23","title":"Prototool","section":"Минимальная конфигурация после миграции","path":"/docs/guide/migration/prototool","headings":["Минимальная конфигурация после миграции"],"excerpt":"Минимальная конфигурация после миграции","content":"Минимальная конфигурация после миграции"},{"id":"migration/prototool::top::24","title":"Prototool","section":"Минимальная конфигурация после миграции","path":"/docs/guide/migration/prototool","headings":["Минимальная конфигурация после миграции"],"excerpt":"Минимальная конфигурация после миграции ---","content":"Минимальная конфигурация после миграции ---"},{"id":"migration/prototool::top::25","title":"Prototool","section":"Рекомендации по упрощению","path":"/docs/guide/migration/prototool","headings":["Рекомендации по упрощению"],"excerpt":"Рекомендации по упрощению Начните с минимального lint.use (MINIMAL), затем постепенно включайте дополнительные наборы. Не переносите слепо все ignore — часть правил может уже быть улучшена в EasyP. Сначала настроить deps","content":"Рекомендации по упрощению Начните с минимального lint.use (MINIMAL), затем постепенно включайте дополнительные наборы. Не переносите слепо все ignore — часть правил может уже быть улучшена в EasyP. Сначала настроить deps и генерацию, затем усложнять линт/нейминг. Фиксируйте миграцию по шагам (коммиты: deps → lint → generate → breaking → CI)."},{"id":"migration/prototool::top::26","title":"Prototool","section":"Проверка результата","path":"/docs/guide/migration/prototool","headings":["Проверка результата"],"excerpt":"Проверка результата Скрипт локальной быстрой проверки (пример):","content":"Проверка результата Скрипт локальной быстрой проверки (пример):"},{"id":"migration/prototool::top::27","title":"Prototool","section":"Проверка результата","path":"/docs/guide/migration/prototool","headings":["Проверка результата"],"excerpt":"Проверка результата ```bash #!/usr/bin/env bash set -euo pipefail","content":"Проверка результата ```bash #!/usr/bin/env bash set -euo pipefail"},{"id":"migration/prototool::top::28","title":"Prototool","section":"Проверка результата","path":"/docs/guide/migration/prototool","headings":["Проверка результата"],"excerpt":"Проверка результата echo \"[1] deps update\" easyp mod update","content":"Проверка результата echo \"[1] deps update\" easyp mod update"},{"id":"migration/prototool::top::29","title":"Prototool","section":"Проверка результата","path":"/docs/guide/migration/prototool","headings":["Проверка результата"],"excerpt":"Проверка результата echo \"[2] lint\" easyp lint","content":"Проверка результата echo \"[2] lint\" easyp lint"},{"id":"migration/prototool::top::30","title":"Prototool","section":"Проверка результата","path":"/docs/guide/migration/prototool","headings":["Проверка результата"],"excerpt":"Проверка результата echo \"[3] breaking vs main\" easyp breaking --against git-ref=origin/main echo \"Breaking changes detected (review needed)\"","content":"Проверка результата echo \"[3] breaking vs main\" easyp breaking --against git-ref=origin/main echo \"Breaking changes detected (review needed)\""},{"id":"migration/prototool::top::31","title":"Prototool","section":"Проверка результата","path":"/docs/guide/migration/prototool","headings":["Проверка результата"],"excerpt":"Проверка результата echo \"[4] generate\" easyp generate","content":"Проверка результата echo \"[4] generate\" easyp generate"},{"id":"migration/prototool::top::32","title":"Prototool","section":"Проверка результата","path":"/docs/guide/migration/prototool","headings":["Проверка результата"],"excerpt":"Проверка результата echo \"Done.\" ```","content":"Проверка результата echo \"Done.\" ```"},{"id":"migration/prototool::top::33","title":"Prototool","section":"Заключение","path":"/docs/guide/migration/prototool","headings":["Заключение"],"excerpt":"Заключение Миграция с Prototool на EasyP сводится к: Переносу путей и внешних каталогов в декларативные deps. Переформатированию линта под lint.use + ignore/except. Переносу генерации в generate.plugins. Добавлению встро","content":"Заключение Миграция с Prototool на EasyP сводится к: Переносу путей и внешних каталогов в декларативные deps. Переформатированию линта под lint.use + ignore/except. Переносу генерации в generate.plugins. Добавлению встроенного механизма breaking. Адаптации CI."},{"id":"migration/prototool::top::34","title":"Prototool","section":"Заключение","path":"/docs/guide/migration/prototool","headings":["Заключение"],"excerpt":"Заключение После этого конфигурация становится более прозрачной, а проверка несовместимых изменений — из коробки.","content":"Заключение После этого конфигурация становится более прозрачной, а проверка несовместимых изменений — из коробки."},{"id":"migration/prototool::top::35","title":"Prototool","section":"Заключение","path":"/docs/guide/migration/prototool","headings":["Заключение"],"excerpt":"Заключение *Готово: базовый перевод и расширенное руководство по миграции с Prototool на EasyP.*","content":"Заключение *Готово: базовый перевод и расширенное руководство по миграции с Prototool на EasyP.*"},{"id":"TRANSLATION_STATUS::top::0","title":"Translation Status (ru-guide)","path":"/docs/guide/TRANSLATION_STATUS","headings":[],"excerpt":"Этот файл отслеживает прогресс перевода русской документации. Используемые статусы: TODO — требуется перевод IN_PROGRESS — перевод начат, требуется вычитка DONE — перевод завершён и вычитан SKIPPED — не требует перевода ","content":"Этот файл отслеживает прогресс перевода русской документации. Используемые статусы: TODO — требуется перевод IN_PROGRESS — перевод начат, требуется вычитка DONE — перевод завершён и вычитан SKIPPED — не требует перевода (намеренно оставлено на английском)"},{"id":"TRANSLATION_STATUS::top::1","title":"Translation Status (ru-guide)","path":"/docs/guide/TRANSLATION_STATUS","headings":[],"excerpt":"Правила: После полного перевода файла убрать исходный английский текст и маркер Термины протокола и ключевые идентификаторы (названия правил, CLI команды, YAML ключи) НЕ переводим. Если структура исходного файла изменила","content":"Правила: После полного перевода файла убрать исходный английский текст и маркер Термины протокола и ключевые идентификаторы (названия правил, CLI команды, YAML ключи) НЕ переводим. Если структура исходного файла изменилась — добавить в начало: Для больших изменений: сначала IN_PROGRESS, после вычитки менять на DONE."},{"id":"TRANSLATION_STATUS::summary::2","title":"Translation Status (ru-guide)","section":"Summary","path":"/docs/guide/TRANSLATION_STATUS#summary","headings":["Summary"],"excerpt":"Summary Итого файлов: 76 DONE: 76 IN_PROGRESS: 0 TODO: 0","content":"Summary Итого файлов: 76 DONE: 76 IN_PROGRESS: 0 TODO: 0"},{"id":"TRANSLATION_STATUS::priority-order::3","title":"Translation Status (ru-guide)","section":"Priority Order (рекомендованный)","path":"/docs/guide/TRANSLATION_STATUS#priority-order","headings":["Priority Order (рекомендованный)"],"excerpt":"Priority Order (рекомендованный) introduction/what-is.md introduction/quickstart.md introduction/install.md cli/linter/linter.md cli/generator/generator.md cli/package-manager/package-manager.md cli/breaking-changes/brea","content":"Priority Order (рекомендованный) introduction/what-is.md introduction/quickstart.md introduction/install.md cli/linter/linter.md cli/generator/generator.md cli/package-manager/package-manager.md cli/breaking-changes/breaking-changes.md api-service/overview.md migration/* (пакетом)"},{"id":"TRANSLATION_STATUS::priority-order::4","title":"Translation Status (ru-guide)","section":"Priority Order (рекомендованный)","path":"/docs/guide/TRANSLATION_STATUS#priority-order","headings":["Priority Order (рекомендованный)"],"excerpt":"Priority Order (рекомендованный) ---","content":"Priority Order (рекомендованный) ---"},{"id":"TRANSLATION_STATUS::file-status-table::5","title":"Translation Status (ru-guide)","section":"File Status Table","path":"/docs/guide/TRANSLATION_STATUS#file-status-table","headings":["File Status Table"],"excerpt":"File Status Table File Status Notes ------ -------- ------- introduction/what-is.md DONE Полный перевод выполнен introduction/quickstart.md DONE Структура сохранена, перевод вычитан introduction/install.md DONE Переведен","content":"File Status Table File Status Notes ------ -------- ------- introduction/what-is.md DONE Полный перевод выполнен introduction/quickstart.md DONE Структура сохранена, перевод вычитан introduction/install.md DONE Переведено, команды проверены api-service/overview.md DONE Переведено ci-cd/github-actions.md DONE Переведено ci-cd/gitlab.md DONE Переведено cli/auto-completion/auto-completion.md DONE Переведено cli/breaking-changes/breaking-changes.md DONE Переведено и вычитано cli/breaking-changes/rules/enum-no-delete.md DONE Переведено cli/breaking-changes/rules/enum-value-no-delete.md DONE Переведено cli/breaking-changes/rules/enum-value-same-name.md DONE Переведено cli/breaking-changes/rules/field-no-delete.md DONE Переведено cli/breaking-changes/rules/field-same-cardinality.md DONE Переведено cli/breaking-changes/rules/field-same-type.md DONE Переведено cli/breaking-changes/rules/import-no-delete.md DONE Переведено cli/breaking-changes/rules/message-no-delete.md DONE Переведено cli/breaking-changes/rules/oneof-field-no-delete.md DONE Переведено cli/breaking-changes/rules/oneof-field-same-type.md DONE Переведено cli/breaking-changes/rules/oneof-no-delete.md DONE Переведено cli/breaking-changes/rules/rpc-no-delete.md DONE Переведено cli/breaking-changes/rules/rpc-same-request-type.md DONE Переведено cli/breaking-changes/rules/rpc-same-response-type.md DONE Переведено cli/breaking-changes/rules/service-no-delete.md DONE Переведено cli/configuration/configuration.md DONE Переведено cli/generator/examples/go.md DONE Переведено cli/generator/examples/grpc-gateway.md DONE Переведено cli/generator/examples/validate.md DONE Переведено cli/generator/generator.md DONE Переведено и вычитано cli/linter/linter.md DONE Переведено и вычитано cli/linter/rules/comment-enum-value.md DONE Переведено cli/linter/rules/comment-enum.md DONE Переведено cli/linter/rules/comment-field.md DONE Переведено cli/linter/rules/comment-message.md DONE Переведено cli/linter/rules/comment-oneof.md DONE Переведено cli/linter/rules/comment-rpc.md DONE Переведено cli/linter/rules/comment-service.md DONE Переведено cli/linter/rules/directory-same-package.md DONE Переведено cli/linter/rules/enum-first-value-zero.md DONE Переведено cli/linter/rules/enum-no-allow-alias.md DONE Переведено cli/linter/rules/enum-pascal-case.md DONE Переведено cli/linter/rules/enum-value-prefix.md DONE Переведено cli/linter/rules/enum-value-upper-snake-case.md DONE Переведено cli/linter/rules/enum-zero-value-suffix.md DONE Переведено cli/linter/rules/field-lower-snake-case.md DONE Переведено cli/linter/rules/file-lower-snake-case.md DONE Переведено cli/linter/rules/import-no-public.md DONE Переведено cli/linter/rules/import-no-weak.md DONE Переведено cli/linter/rules/import-used.md DONE Переведено cli/linter/rules/message-pascal-case.md DONE Переведено cli/linter/rules/oneof-lower-snake-case.md DONE Переведено cli/linter/rules/package-defined.md DONE Переведено cli/linter/rules/package-directory-match.md DONE Переведено cli/linter/rules/package-lower-snake-case.md DONE Переведено cli/linter/rules/package-same-csharp-namespace.md DONE Переведено cli/linter/rules/package-same-directory.md DONE Переведено cli/linter/rules/package-same-go-package.md DONE Переведено cli/linter/rules/package-same-java-multiple-files.md DONE Переведено cli/linter/rules/package-same-java-package.md DONE Переведено cli/linter/rules/package-same-php-namespace.md DONE Переведено cli/linter/rules/package-same-ruby-package.md DONE Переведено cli/linter/rules/package-same-swift-prefix.md DONE Переведено cli/linter/rules/package-version-suffix.md DONE Переведено cli/linter/rules/rpc-no-client-streaming.md DONE Переведено cli/linter/rules/rpc-no-server-streaming.md DONE Переведено cli/linter/rules/rpc-pascal-case.md DONE Переведено cli/linter/rules/rpc-request-response-unique.md DONE Переведено cli/linter/rules/rpc-request-standard-name.md DONE Переведено cli/linter/rules/rpc-response-standard-name.md DONE Переведено cli/linter/rules/service-pascal-case.md DONE Переведено cli/linter/rules/service-suffix.md DONE Переведено cli/package-manager/easyp-vs-buf.md DONE Переведено cli/package-manager/package-manager.md DONE Переведено и вычитано migration/buf-cli.md DONE Переведено migration/protoc.md DONE Переведено migration/protolock.md DONE Переведено migration/prototool.md DONE Переведено"},{"id":"TRANSLATION_STATUS::workflow::6","title":"Translation Status (ru-guide)","section":"Workflow","path":"/docs/guide/TRANSLATION_STATUS#workflow","headings":["Workflow"],"excerpt":"Workflow Выбираем файл со статусом TODO. Меняем статус на IN_PROGRESS здесь. Переводим, проверяем терминологию (сверка с глоссарием — добавить позже). Меняем статус на DONE. Удаляем маркер внутри файла.","content":"Workflow Выбираем файл со статусом TODO. Меняем статус на IN_PROGRESS здесь. Переводим, проверяем терминологию (сверка с глоссарием — добавить позже). Меняем статус на DONE. Удаляем маркер внутри файла."},{"id":"TRANSLATION_STATUS::planned-terminology::7","title":"Translation Status (ru-guide)","section":"Planned Terminology (черновик)","path":"/docs/guide/TRANSLATION_STATUS#planned-terminology","headings":["Planned Terminology (черновик)"],"excerpt":"Planned Terminology (черновик) EN RU Notes ---- ---- ------- Linting Линтинг Транслитерация Breaking Changes Несовместимые изменения Название секции Dependency Зависимость Code Generation Генерация кода Lock file Lock-фа","content":"Planned Terminology (черновик) EN RU Notes ---- ---- ------- Linting Линтинг Транслитерация Breaking Changes Несовместимые изменения Название секции Dependency Зависимость Code Generation Генерация кода Lock file Lock-файл Remote Plugin Удалённый плагин Package Manager Менеджер пакетов"},{"id":"TRANSLATION_STATUS::planned-terminology::8","title":"Translation Status (ru-guide)","section":"Planned Terminology (черновик)","path":"/docs/guide/TRANSLATION_STATUS#planned-terminology","headings":["Planned Terminology (черновик)"],"excerpt":"Planned Terminology (черновик) (Будет дополнено.)","content":"Planned Terminology (черновик) (Будет дополнено.)"},{"id":"TRANSLATION_STATUS::planned-terminology::9","title":"Translation Status (ru-guide)","section":"Planned Terminology (черновик)","path":"/docs/guide/TRANSLATION_STATUS#planned-terminology","headings":["Planned Terminology (черновик)"],"excerpt":"Planned Terminology (черновик) ---","content":"Planned Terminology (черновик) ---"},{"id":"TRANSLATION_STATUS::top::10","title":"Translation Status (ru-guide)","section":"История обновлений","path":"/docs/guide/TRANSLATION_STATUS","headings":["История обновлений"],"excerpt":"История обновлений Initial file created: all statuses set (3 IN_PROGRESS, rest TODO). Marked breaking-changes page as DONE. Linter rules (41 файлов) переведены: статусы DONE. Breaking-changes rules (15 файлов) вычитаны и","content":"История обновлений Initial file created: all statuses set (3 IN_PROGRESS, rest TODO). Marked breaking-changes page as DONE. Linter rules (41 файлов) переведены: статусы DONE. Breaking-changes rules (15 файлов) вычитаны и помечены DONE. Все оставшиеся страницы переведены: итог DONE = 76."}] \ No newline at end of file +[{"id":"api-service/overview::top::0","title":"Обзор API Service","path":"/docs/guide/api-service/overview","headings":[],"excerpt":"**Централизованный сервис выполнения protobuf‑плагинов для консистентной изолированной генерации кода**","content":"**Централизованный сервис выполнения protobuf‑плагинов для консистентной изолированной генерации кода**"},{"id":"api-service/overview::top::1","title":"Обзор API Service","path":"/docs/guide/api-service/overview","headings":[],"excerpt":"EasyP API Service устраняет хаос управления плагинами, предоставляя централизованный запуск protobuf/gRPC плагинов в изолированных Docker‑контейнерах. Он даёт единую платформу, позволяющую командам стандартизировать проц","content":"EasyP API Service устраняет хаос управления плагинами, предоставляя централизованный запуск protobuf/gRPC плагинов в изолированных Docker‑контейнерах. Он даёт единую платформу, позволяющую командам стандартизировать процесс генерации кода без операционных затрат на установку и поддержку плагинов на машинах разработчиков."},{"id":"api-service/overview::easyp-api-service::2","title":"Обзор API Service","section":"Зачем нужен EasyP API Service?","path":"/docs/guide/api-service/overview#easyp-api-service","headings":["Зачем нужен EasyP API Service?"],"excerpt":"Зачем нужен EasyP API Service?","content":"Зачем нужен EasyP API Service?"},{"id":"api-service/overview::top::3","title":"Обзор API Service","section":"Проблема","path":"/docs/guide/api-service/overview","headings":["Проблема"],"excerpt":"Проблема Управление генерацией protobuf/gRPC кода в командах порождает существенную операционную сложность:","content":"Проблема Управление генерацией protobuf/gRPC кода в командах порождает существенную операционную сложность:"},{"id":"api-service/overview::top::4","title":"Обзор API Service","section":"Несогласованность версий","path":"/docs/guide/api-service/overview","headings":["Несогласованность версий"],"excerpt":"Несогласованность версий Разработчики локально используют разные версии плагинов → расхождения в генерированном коде и падения сборки Синдром «у меня работает» при различиях окружений Требуется ручная координация, чтобы ","content":"Несогласованность версий Разработчики локально используют разные версии плагинов → расхождения в генерированном коде и падения сборки Синдром «у меня работает» при различиях окружений Требуется ручная координация, чтобы вся команда была синхронизирована по версиям"},{"id":"api-service/overview::top::5","title":"Обзор API Service","section":"Операционные накладные расходы","path":"/docs/guide/api-service/overview","headings":["Операционные накладные расходы"],"excerpt":"Операционные накладные расходы DevOps тратят время на установку и обновление плагинов на рабочих станциях Новый разработчик — ручная настройка правильных версий Обновление плагинов требует коммуникации с каждым отдельно ","content":"Операционные накладные расходы DevOps тратят время на установку и обновление плагинов на рабочих станциях Новый разработчик — ручная настройка правильных версий Обновление плагинов требует коммуникации с каждым отдельно Нет централизованного контроля утверждённых версий"},{"id":"api-service/overview::top::6","title":"Обзор API Service","section":"Риски безопасности и комплаенса","path":"/docs/guide/api-service/overview","headings":["Риски безопасности и комплаенса"],"excerpt":"Риски безопасности и комплаенса Плагины ставятся из разных источников без валидации Нет аудита: какой плагин для какого билда использовался Сложно применять политики безопасности к инструментам генерации","content":"Риски безопасности и комплаенса Плагины ставятся из разных источников без валидации Нет аудита: какой плагин для какого билда использовался Сложно применять политики безопасности к инструментам генерации"},{"id":"api-service/overview::top::7","title":"Обзор API Service","section":"Решение: централизованный запуск плагинов","path":"/docs/guide/api-service/overview","headings":["Решение: централизованный запуск плагинов"],"excerpt":"Решение: централизованный запуск плагинов EasyP API Service решает эти проблемы за счёт централизованного управления:","content":"Решение: централизованный запуск плагинов EasyP API Service решает эти проблемы за счёт централизованного управления:"},{"id":"api-service/overview::top::8","title":"Обзор API Service","section":"Решение: централизованный запуск плагинов","path":"/docs/guide/api-service/overview","headings":["Решение: централизованный запуск плагинов"],"excerpt":"Решение: централизованный запуск плагинов Проблема Решение ---------- --------- **Контроль версий** Мгновенное распространение новых версий через Docker‑образы **Операции** Команда эксплуатации управляет конфигурациями б","content":"Решение: централизованный запуск плагинов Проблема Решение ---------- --------- **Контроль версий** Мгновенное распространение новых версий через Docker‑образы **Операции** Команда эксплуатации управляет конфигурациями без доступа на машины разработчиков **Безопасность** Все плагины запускаются в изолированных контейнерах с ограничениями ресурсов **Консистентность** Единая среда выполнения вне зависимости от локальной установки **Опыт разработчика** Не нужно устанавливать и сопровождать плагины локально"},{"id":"api-service/overview::top::9","title":"Обзор API Service","section":"Архитектура","path":"/docs/guide/api-service/overview","headings":["Архитектура"],"excerpt":"Архитектура Архитектура сервиса упрощена и сфокусирована на надёжном выполнении плагинов:","content":"Архитектура Архитектура сервиса упрощена и сфокусирована на надёжном выполнении плагинов:"},{"id":"api-service/overview::api-layer::10","title":"Обзор API Service","section":"API Layer","path":"/docs/guide/api-service/overview#api-layer","headings":["API Layer"],"excerpt":"API Layer **gRPC Server** — основной API для запросов генерации Каждый запуск плагина — отдельный gRPC‑запрос Получает CodeGeneratorRequest от CLI","content":"API Layer **gRPC Server** — основной API для запросов генерации Каждый запуск плагина — отдельный gRPC‑запрос Получает CodeGeneratorRequest от CLI"},{"id":"api-service/overview::execution-engine::11","title":"Обзор API Service","section":"Execution Engine","path":"/docs/guide/api-service/overview#execution-engine","headings":["Execution Engine"],"excerpt":"Execution Engine **Docker Runtime** — изолированный запуск плагинов Подтягивает образы из публичных реестров (Docker Hub и т.п.) Применяет лимиты CPU/памяти на плагин","content":"Execution Engine **Docker Runtime** — изолированный запуск плагинов Подтягивает образы из публичных реестров (Docker Hub и т.п.) Применяет лимиты CPU/памяти на плагин"},{"id":"api-service/overview::storage-layer::12","title":"Обзор API Service","section":"Storage Layer","path":"/docs/guide/api-service/overview#storage-layer","headings":["Storage Layer"],"excerpt":"Storage Layer **PostgreSQL** хранит параметры выполнения: - Ограничения ресурсов (CPU, память) - Конфигурацию и метаданные плагинов - Логи выполнения (аудит) - _Примечание: функциональность хранения будет расширяться_","content":"Storage Layer **PostgreSQL** хранит параметры выполнения: - Ограничения ресурсов (CPU, память) - Конфигурацию и метаданные плагинов - Логи выполнения (аудит) - _Примечание: функциональность хранения будет расширяться_"},{"id":"api-service/overview::monitoring::13","title":"Обзор API Service","section":"Monitoring","path":"/docs/guide/api-service/overview#monitoring","headings":["Monitoring"],"excerpt":"Monitoring **Prometheus** — сбор метрик Отслеживает время выполнения, успешность, использование ресурсов","content":"Monitoring **Prometheus** — сбор метрик Отслеживает время выполнения, успешность, использование ресурсов"},{"id":"api-service/overview::easyp-cli::14","title":"Обзор API Service","section":"Локальное выполнение (EasyP CLI)","path":"/docs/guide/api-service/overview#easyp-cli","headings":["Локальное выполнение (EasyP CLI)"],"excerpt":"Локальное выполнение (EasyP CLI) При локальном запуске CLI поддерживает: **Installed plugins**: системно установленные protoc плагины **WASM plugins**: лёгкие WebAssembly плагины","content":"Локальное выполнение (EasyP CLI) При локальном запуске CLI поддерживает: **Installed plugins**: системно установленные protoc плагины **WASM plugins**: лёгкие WebAssembly плагины"},{"id":"api-service/overview::api-service::15","title":"Обзор API Service","section":"Удалённое выполнение (API Service)","path":"/docs/guide/api-service/overview#api-service","headings":["Удалённое выполнение (API Service)"],"excerpt":"Удалённое выполнение (API Service) При работе через сервис: **Только Docker**: плагины запускаются как контейнеры **Центральный контроль**: операционная команда управляет доступными версиями **Консистентная среда**: один","content":"Удалённое выполнение (API Service) При работе через сервис: **Только Docker**: плагины запускаются как контейнеры **Центральный контроль**: операционная команда управляет доступными версиями **Консистентная среда**: одинаковое окружение для всех разработчиков"},{"id":"api-service/overview::top::16","title":"Обзор API Service","section":"Шаги выполнения","path":"/docs/guide/api-service/overview","headings":["Шаги выполнения"],"excerpt":"Шаги выполнения **CLI Parsing**: CLI парсит локальные .proto файлы **Request Sending**: Отправляет CodeGeneratorRequest в API Service (по одному на плагин) **Parameter Lookup**: Сервис получает параметры запуска из Postg","content":"Шаги выполнения **CLI Parsing**: CLI парсит локальные .proto файлы **Request Sending**: Отправляет CodeGeneratorRequest в API Service (по одному на плагин) **Parameter Lookup**: Сервис получает параметры запуска из PostgreSQL **Docker Execution**: Запускает плагин в изолированном контейнере **Metrics Recording**: Записывает метрики после завершения **Response**: Возвращает сгенерированный код обратно в CLI"},{"id":"api-service/overview::top::17","title":"Обзор API Service","section":"Ключевые возможности","path":"/docs/guide/api-service/overview","headings":["Ключевые возможности"],"excerpt":"Ключевые возможности Возможность Описание ------------- ---------- **🐳 Изоляция плагинов** Каждый плагин в отдельном безопасном контейнере **⚙️ Контроль ресурсов** Лимиты CPU и памяти на уровне контейнера **📊 Метрики &","content":"Ключевые возможности Возможность Описание ------------- ---------- **🐳 Изоляция плагинов** Каждый плагин в отдельном безопасном контейнере **⚙️ Контроль ресурсов** Лимиты CPU и памяти на уровне контейнера **📊 Метрики & мониторинг** Полный набор Prometheus метрик **🔄 Управление версиями** Централизованно через Docker‑образы **⚡ Простой протокол** Стандарт CodeGeneratorRequest/Response **🔒 Безопасность прежде всего** Изоляция + ограниченные ресурсы"},{"id":"api-service/overview::top::18","title":"Обзор API Service","section":"Конфигурация","path":"/docs/guide/api-service/overview","headings":["Конфигурация"],"excerpt":"Конфигурация Сервис настраивается через переменные окружения.","content":"Конфигурация Сервис настраивается через переменные окружения."},{"id":"api-service/overview::top::19","title":"Обзор API Service","section":"Хранение параметров плагинов","path":"/docs/guide/api-service/overview","headings":["Хранение параметров плагинов"],"excerpt":"Хранение параметров плагинов PostgreSQL хранит параметры выполнения для каждого плагина:","content":"Хранение параметров плагинов PostgreSQL хранит параметры выполнения для каждого плагина:"},{"id":"api-service/overview::top::20","title":"Обзор API Service","section":"Хранение параметров плагинов","path":"/docs/guide/api-service/overview","headings":["Хранение параметров плагинов"],"excerpt":"Хранение параметров плагинов ::: tip Схема хранения будет расширена — аудит логов, аналитика использования, кеширование плагинов. :::","content":"Хранение параметров плагинов ::: tip Схема хранения будет расширена — аудит логов, аналитика использования, кеширование плагинов. :::"},{"id":"api-service/overview::easyp-cli::21","title":"Обзор API Service","section":"Интеграция с EasyP CLI","path":"/docs/guide/api-service/overview#easyp-cli","headings":["Интеграция с EasyP CLI"],"excerpt":"Интеграция с EasyP CLI Пример easyp.yaml для удалённого запуска:","content":"Интеграция с EasyP CLI Пример easyp.yaml для удалённого запуска:"},{"id":"api-service/overview::easyp-cli::22","title":"Обзор API Service","section":"Интеграция с EasyP CLI","path":"/docs/guide/api-service/overview#easyp-cli","headings":["Интеграция с EasyP CLI"],"excerpt":"Интеграция с EasyP CLI Запуск генерации:","content":"Интеграция с EasyP CLI Запуск генерации:"},{"id":"api-service/overview::easyp-cli::23","title":"Обзор API Service","section":"Интеграция с EasyP CLI","path":"/docs/guide/api-service/overview#easyp-cli","headings":["Интеграция с EasyP CLI"],"excerpt":"Интеграция с EasyP CLI CLI: Парсит protobuf‑файлы Отправляет отдельные запросы в сервис для каждого плагина Получает ответы с кодом Записывает файлы в указанные директории","content":"Интеграция с EasyP CLI CLI: Парсит protobuf‑файлы Отправляет отдельные запросы в сервис для каждого плагина Получает ответы с кодом Записывает файлы в указанные директории"},{"id":"api-service/overview::top::24","title":"Обзор API Service","section":"Доступные метрики","path":"/docs/guide/api-service/overview","headings":["Доступные метрики"],"excerpt":"Доступные метрики Метрики Prometheus:","content":"Доступные метрики Метрики Prometheus:"},{"id":"api-service/overview::top::25","title":"Обзор API Service","section":"Доступные метрики","path":"/docs/guide/api-service/overview","headings":["Доступные метрики"],"excerpt":"Доступные метрики Метрика Описание --------- ---------- easyp_api_service_api_grpc_server_handled_total Общее число gRPC запросов по статусам easyp_api_service_api_grpc_server_handling_seconds Гистограмма задержек gRPC e","content":"Доступные метрики Метрика Описание --------- ---------- easyp_api_service_api_grpc_server_handled_total Общее число gRPC запросов по статусам easyp_api_service_api_grpc_server_handling_seconds Гистограмма задержек gRPC easyp_api_service_generated_plugin_code_total Выполнения плагинов по имени easyp_api_service_repo_call_duration_seconds Латентность запросов к БД easyp_api_service_repo_errors_total Количество ошибок доступа к БД easyp_api_service_standard_panics_total Число восстановленных паник"},{"id":"api-service/overview::top::26","title":"Обзор API Service","section":"Характеристики производительности","path":"/docs/guide/api-service/overview","headings":["Характеристики производительности"],"excerpt":"Характеристики производительности Показатель Типичное значение Примечания ----------- ------------------- ----------- **Cold Start** 2–5 сек Первая загрузка образа **Warm Start** 100–500 мс Образ закеширован **Throughput","content":"Характеристики производительности Показатель Типичное значение Примечания ----------- ------------------- ----------- **Cold Start** 2–5 сек Первая загрузка образа **Warm Start** 100–500 мс Образ закеширован **Throughput** 20–50 одновременных Зависит от ресурсов **Memory Usage** 50–200 MB На выполнение одного плагина"},{"id":"api-service/overview::top::27","title":"Обзор API Service","section":"Изоляция контейнеров","path":"/docs/guide/api-service/overview","headings":["Изоляция контейнеров"],"excerpt":"Изоляция контейнеров Каждый плагин в отдельном эфемерном контейнере Нет сетевого доступа в процессе выполнения Лимиты CPU/памяти через Docker Контейнер удаляется после завершения","content":"Изоляция контейнеров Каждый плагин в отдельном эфемерном контейнере Нет сетевого доступа в процессе выполнения Лимиты CPU/памяти через Docker Контейнер удаляется после завершения"},{"id":"api-service/overview::api::28","title":"Обзор API Service","section":"Безопасность API","path":"/docs/guide/api-service/overview#api","headings":["Безопасность API"],"excerpt":"Безопасность API gRPC транспорт Поддержка токенов аутентификации (в продакшн окружениях) Валидация входных данных Аудитные логи в PostgreSQL","content":"Безопасность API gRPC транспорт Поддержка токенов аутентификации (в продакшн окружениях) Валидация входных данных Аудитные логи в PostgreSQL"},{"id":"api-service/overview::top::29","title":"Обзор API Service","section":"Масштабирование","path":"/docs/guide/api-service/overview","headings":["Масштабирование"],"excerpt":"Масштабирование **Горизонтальное**: несколько инстансов за балансировщиком **Ресурсы**: настройка лимитов для тяжёлых плагинов **База данных**: репликация PostgreSQL для отказоустойчивости","content":"Масштабирование **Горизонтальное**: несколько инстансов за балансировщиком **Ресурсы**: настройка лимитов для тяжёлых плагинов **База данных**: репликация PostgreSQL для отказоустойчивости"},{"id":"api-service/overview::top::30","title":"Обзор API Service","section":"Мониторинг","path":"/docs/guide/api-service/overview","headings":["Мониторинг"],"excerpt":"Мониторинг **Метрики**: Prometheus **Алертинг**: оповещения на высокие ошибки/латентность **Логи**: структурированные для аудита и отладки","content":"Мониторинг **Метрики**: Prometheus **Алертинг**: оповещения на высокие ошибки/латентность **Логи**: структурированные для аудита и отладки"},{"id":"api-service/overview::top::31","title":"Обзор API Service","section":"План развития","path":"/docs/guide/api-service/overview","headings":["План развития"],"excerpt":"План развития Запланировано: Кеширование результатов генерации Расширенный аудит и аналитика использования Поддержка приватных реестров плагинов Более умное распределение ресурсов","content":"План развития Запланировано: Кеширование результатов генерации Расширенный аудит и аналитика использования Поддержка приватных реестров плагинов Более умное распределение ресурсов"},{"id":"api-service/overview::top::32","title":"Обзор API Service","section":"Сообщество и поддержка","path":"/docs/guide/api-service/overview","headings":["Сообщество и поддержка"],"excerpt":"Сообщество и поддержка **💬 Telegram чат** — обсуждения **🐛 GitHub Issues** — баги и запросы фич **📖 Документация** — полный набор материалов","content":"Сообщество и поддержка **💬 Telegram чат** — обсуждения **🐛 GitHub Issues** — баги и запросы фич **📖 Документация** — полный набор материалов"},{"id":"api-service/overview::top::33","title":"Обзор API Service","section":"Сообщество и поддержка","path":"/docs/guide/api-service/overview","headings":["Сообщество и поддержка"],"excerpt":"Сообщество и поддержка *Упростите свои protobuf‑воркфлоу с централизованным управлением выполнением плагинов.*","content":"Сообщество и поддержка *Упростите свои protobuf‑воркфлоу с централизованным управлением выполнением плагинов.*"},{"id":"ci-cd/github-actions::top::0","title":"GitHub Actions","path":"/docs/guide/ci-cd/github-actions","headings":[],"excerpt":"Полное руководство по интеграции EasyP в конвейеры GitHub Actions для линтинга, проверки несовместимых изменений, генерации кода и автоматизации релизов.","content":"Полное руководство по интеграции EasyP в конвейеры GitHub Actions для линтинга, проверки несовместимых изменений, генерации кода и автоматизации релизов."},{"id":"ci-cd/github-actions::easyp-ci::1","title":"GitHub Actions","section":"Зачем использовать EasyP в CI","path":"/docs/guide/ci-cd/github-actions#easyp-ci","headings":["Зачем использовать EasyP в CI"],"excerpt":"Зачем использовать EasyP в CI Встраивание EasyP в GitHub Actions даёт: Единообразие правил линтинга и генерации между разработчиками. Автоматическое выявление несовместимых изменений (breaking changes) до мержа. Гарантию","content":"Зачем использовать EasyP в CI Встраивание EasyP в GitHub Actions даёт: Единообразие правил линтинга и генерации между разработчиками. Автоматическое выявление несовместимых изменений (breaking changes) до мержа. Гарантию, что сгенерированный код не «устарел» относительно .proto. Возможность централизованной проверки зависимостей и версии конфигурации."},{"id":"ci-cd/github-actions::top::2","title":"GitHub Actions","section":"Предварительные требования","path":"/docs/guide/ci-cd/github-actions","headings":["Предварительные требования"],"excerpt":"Предварительные требования Репозиторий содержит файл конфигурации easyp.yaml (или находится в корне, если запускается без --cfg). Установлены / определены зависимости в секции deps (если нужны внешние импорты). Для прива","content":"Предварительные требования Репозиторий содержит файл конфигурации easyp.yaml (или находится в корне, если запускается без --cfg). Установлены / определены зависимости в секции deps (если нужны внешние импорты). Для приватных Git-репозиториев настроен доступ (SSH key / deploy key / токен). В workflow есть шаги по установке Go (если EasyP поставляется через go install) или заранее подготовленный бинарь."},{"id":"ci-cd/github-actions::top::3","title":"GitHub Actions","section":"Базовый пример (быстрый старт)","path":"/docs/guide/ci-cd/github-actions","headings":["Базовый пример (быстрый старт)"],"excerpt":"Базовый пример (быстрый старт) Минимальный workflow для проверки линта и несовместимых изменений при открытия Pull Request:","content":"Базовый пример (быстрый старт) Минимальный workflow для проверки линта и несовместимых изменений при открытия Pull Request:"},{"id":"ci-cd/github-actions::top::4","title":"GitHub Actions","section":"Базовый пример (быстрый старт)","path":"/docs/guide/ci-cd/github-actions","headings":["Базовый пример (быстрый старт)"],"excerpt":"Базовый пример (быстрый старт) ```yaml name: easyp-ci","content":"Базовый пример (быстрый старт) ```yaml name: easyp-ci"},{"id":"ci-cd/github-actions::top::5","title":"GitHub Actions","section":"Базовый пример (быстрый старт)","path":"/docs/guide/ci-cd/github-actions","headings":["Базовый пример (быстрый старт)"],"excerpt":"Базовый пример (быстрый старт) on: pull_request: paths: - '**/*.proto' - 'easyp.yaml'","content":"Базовый пример (быстрый старт) on: pull_request: paths: - '**/*.proto' - 'easyp.yaml'"},{"id":"ci-cd/github-actions::top::6","title":"GitHub Actions","section":"Базовый пример (быстрый старт)","path":"/docs/guide/ci-cd/github-actions","headings":["Базовый пример (быстрый старт)"],"excerpt":"Базовый пример (быстрый старт) jobs: lint-and-breaking: runs-on: ubuntu-latest","content":"Базовый пример (быстрый старт) jobs: lint-and-breaking: runs-on: ubuntu-latest"},{"id":"ci-cd/github-actions::top::7","title":"GitHub Actions","section":"Базовый пример (быстрый старт)","path":"/docs/guide/ci-cd/github-actions","headings":["Базовый пример (быстрый старт)"],"excerpt":"Базовый пример (быстрый старт) steps: - name: Checkout uses: actions/checkout@v4","content":"Базовый пример (быстрый старт) steps: - name: Checkout uses: actions/checkout@v4"},{"id":"ci-cd/github-actions::top::8","title":"GitHub Actions","section":"Базовый пример (быстрый старт)","path":"/docs/guide/ci-cd/github-actions","headings":["Базовый пример (быстрый старт)"],"excerpt":"Базовый пример (быстрый старт) name: Setup Go uses: actions/setup-go@v5 with: go-version: '1.22'","content":"Базовый пример (быстрый старт) name: Setup Go uses: actions/setup-go@v5 with: go-version: '1.22'"},{"id":"ci-cd/github-actions::top::9","title":"GitHub Actions","section":"Базовый пример (быстрый старт)","path":"/docs/guide/ci-cd/github-actions","headings":["Базовый пример (быстрый старт)"],"excerpt":"Базовый пример (быстрый старт) name: Install EasyP run: go install github.com/easyp-tech/easyp/cmd/easyp@latest","content":"Базовый пример (быстрый старт) name: Install EasyP run: go install github.com/easyp-tech/easyp/cmd/easyp@latest"},{"id":"ci-cd/github-actions::top::10","title":"GitHub Actions","section":"Базовый пример (быстрый старт)","path":"/docs/guide/ci-cd/github-actions","headings":["Базовый пример (быстрый старт)"],"excerpt":"Базовый пример (быстрый старт) name: Verify EasyP version run: which easyp easyp version","content":"Базовый пример (быстрый старт) name: Verify EasyP version run: which easyp easyp version"},{"id":"ci-cd/github-actions::top::11","title":"GitHub Actions","section":"Базовый пример (быстрый старт)","path":"/docs/guide/ci-cd/github-actions","headings":["Базовый пример (быстрый старт)"],"excerpt":"Базовый пример (быстрый старт) name: Lint run: easyp lint","content":"Базовый пример (быстрый старт) name: Lint run: easyp lint"},{"id":"ci-cd/github-actions::top::12","title":"GitHub Actions","section":"Базовый пример (быстрый старт)","path":"/docs/guide/ci-cd/github-actions","headings":["Базовый пример (быстрый старт)"],"excerpt":"Базовый пример (быстрый старт) name: Breaking changes check (against main) run: easyp breaking --against git-ref=origin/main ```","content":"Базовый пример (быстрый старт) name: Breaking changes check (against main) run: easyp breaking --against git-ref=origin/main ```"},{"id":"ci-cd/github-actions::easyp::13","title":"GitHub Actions","section":"Установка EasyP","path":"/docs/guide/ci-cd/github-actions#easyp","headings":["Установка EasyP"],"excerpt":"Установка EasyP Варианты: Через go install (как в примере выше). Использование заранее собранного бинаря (артефакт релиза).","content":"Установка EasyP Варианты: Через go install (как в примере выше). Использование заранее собранного бинаря (артефакт релиза)."},{"id":"ci-cd/github-actions::top::14","title":"GitHub Actions","section":"Кэширование","path":"/docs/guide/ci-cd/github-actions","headings":["Кэширование"],"excerpt":"Кэширование Для ускорения повторных сборок можно кэшировать: Go модульный кеш (если используете генерацию с плагинами Go). Внешние зависимые Git-клонирования (папки vendor или содержимое deps при использовании easyp mod ","content":"Кэширование Для ускорения повторных сборок можно кэшировать: Go модульный кеш (если используете генерацию с плагинами Go). Внешние зависимые Git-клонирования (папки vendor или содержимое deps при использовании easyp mod download / easyp mod update). Сгенерированный код (если он тяжёлый, но чаще генерируется заново)."},{"id":"ci-cd/github-actions::top::15","title":"GitHub Actions","section":"Кэширование","path":"/docs/guide/ci-cd/github-actions","headings":["Кэширование"],"excerpt":"Кэширование Пример кэширования Go:","content":"Кэширование Пример кэширования Go:"},{"id":"ci-cd/github-actions::top::16","title":"GitHub Actions","section":"Кэширование","path":"/docs/guide/ci-cd/github-actions","headings":["Кэширование"],"excerpt":"Кэширование Пример кэширования каталога зависимостей EasyP (если вы используете локальный vendor-подход):","content":"Кэширование Пример кэширования каталога зависимостей EasyP (если вы используете локальный vendor-подход):"},{"id":"ci-cd/github-actions::top::17","title":"GitHub Actions","section":"Кэширование","path":"/docs/guide/ci-cd/github-actions","headings":["Кэширование"],"excerpt":"Кэширование (Создайте .easyp/deps как целевой каталог, если ваша стратегия скачивания такова.)","content":"Кэширование (Создайте .easyp/deps как целевой каталог, если ваша стратегия скачивания такова.)"},{"id":"ci-cd/github-actions::top::18","title":"GitHub Actions","section":"Линтинг","path":"/docs/guide/ci-cd/github-actions","headings":["Линтинг"],"excerpt":"Линтинг Рекомендуется: В PR: всегда запускать. На main: можно запускать для верификации перед релизом.","content":"Линтинг Рекомендуется: В PR: всегда запускать. На main: можно запускать для верификации перед релизом."},{"id":"ci-cd/github-actions::top::19","title":"GitHub Actions","section":"Линтинг","path":"/docs/guide/ci-cd/github-actions","headings":["Линтинг"],"excerpt":"Линтинг Расширенный пример с выводом подробностей и игнорированием комментариев (если включено в конфиг):","content":"Линтинг Расширенный пример с выводом подробностей и игнорированием комментариев (если включено в конфиг):"},{"id":"ci-cd/github-actions::breaking-changes::20","title":"GitHub Actions","section":"Проверка несовместимых изменений (Breaking Changes)","path":"/docs/guide/ci-cd/github-actions#breaking-changes","headings":["Проверка несовместимых изменений (Breaking Changes)"],"excerpt":"Проверка несовместимых изменений (Breaking Changes) EasyP может сравнивать текущее состояние против ветки / коммита / тега.","content":"Проверка несовместимых изменений (Breaking Changes) EasyP может сравнивать текущее состояние против ветки / коммита / тега."},{"id":"ci-cd/github-actions::breaking-changes::21","title":"GitHub Actions","section":"Проверка несовместимых изменений (Breaking Changes)","path":"/docs/guide/ci-cd/github-actions#breaking-changes","headings":["Проверка несовместимых изменений (Breaking Changes)"],"excerpt":"Проверка несовместимых изменений (Breaking Changes) Примеры: ```bash Сравнить против origin/main easyp breaking --against git-ref=origin/main","content":"Проверка несовместимых изменений (Breaking Changes) Примеры: ```bash Сравнить против origin/main easyp breaking --against git-ref=origin/main"},{"id":"ci-cd/github-actions::breaking-changes::22","title":"GitHub Actions","section":"Проверка несовместимых изменений (Breaking Changes)","path":"/docs/guide/ci-cd/github-actions#breaking-changes","headings":["Проверка несовместимых изменений (Breaking Changes)"],"excerpt":"Проверка несовместимых изменений (Breaking Changes) Сравнить против тега релиза easyp breaking --against git-ref=v1.5.2","content":"Проверка несовместимых изменений (Breaking Changes) Сравнить против тега релиза easyp breaking --against git-ref=v1.5.2"},{"id":"ci-cd/github-actions::breaking-changes::23","title":"GitHub Actions","section":"Проверка несовместимых изменений (Breaking Changes)","path":"/docs/guide/ci-cd/github-actions#breaking-changes","headings":["Проверка несовместимых изменений (Breaking Changes)"],"excerpt":"Проверка несовместимых изменений (Breaking Changes) Игнорировать определённые правила (если у вас настроено в easyp.yaml) easyp breaking ```","content":"Проверка несовместимых изменений (Breaking Changes) Игнорировать определённые правила (если у вас настроено в easyp.yaml) easyp breaking ```"},{"id":"ci-cd/github-actions::breaking-changes::24","title":"GitHub Actions","section":"Проверка несовместимых изменений (Breaking Changes)","path":"/docs/guide/ci-cd/github-actions#breaking-changes","headings":["Проверка несовместимых изменений (Breaking Changes)"],"excerpt":"Проверка несовместимых изменений (Breaking Changes) Workflow шаг:","content":"Проверка несовместимых изменений (Breaking Changes) Workflow шаг:"},{"id":"ci-cd/github-actions::breaking-changes::25","title":"GitHub Actions","section":"Проверка несовместимых изменений (Breaking Changes)","path":"/docs/guide/ci-cd/github-actions#breaking-changes","headings":["Проверка несовместимых изменений (Breaking Changes)"],"excerpt":"Проверка несовместимых изменений (Breaking Changes)","content":"Проверка несовместимых изменений (Breaking Changes)"},{"id":"ci-cd/github-actions::breaking-changes::26","title":"GitHub Actions","section":"Проверка несовместимых изменений (Breaking Changes)","path":"/docs/guide/ci-cd/github-actions#breaking-changes","headings":["Проверка несовместимых изменений (Breaking Changes)"],"excerpt":"Проверка несовместимых изменений (Breaking Changes) Если нужно «мягко» пропустить (например, выводить предупреждения, но не падать билд):","content":"Проверка несовместимых изменений (Breaking Changes) Если нужно «мягко» пропустить (например, выводить предупреждения, но не падать билд):"},{"id":"ci-cd/github-actions::breaking-changes::27","title":"GitHub Actions","section":"Проверка несовместимых изменений (Breaking Changes)","path":"/docs/guide/ci-cd/github-actions#breaking-changes","headings":["Проверка несовместимых изменений (Breaking Changes)"],"excerpt":"Проверка несовместимых изменений (Breaking Changes)","content":"Проверка несовместимых изменений (Breaking Changes)"},{"id":"ci-cd/github-actions::top::28","title":"GitHub Actions","section":"Генерация кода","path":"/docs/guide/ci-cd/github-actions","headings":["Генерация кода"],"excerpt":"Генерация кода Обычно для генерации:","content":"Генерация кода Обычно для генерации:"},{"id":"ci-cd/github-actions::top::29","title":"GitHub Actions","section":"Генерация кода","path":"/docs/guide/ci-cd/github-actions","headings":["Генерация кода"],"excerpt":"Генерация кода Если нужно явно указать конфиг:","content":"Генерация кода Если нужно явно указать конфиг:"},{"id":"ci-cd/github-actions::top::30","title":"GitHub Actions","section":"Генерация кода","path":"/docs/guide/ci-cd/github-actions","headings":["Генерация кода"],"excerpt":"Генерация кода Можно добавить проверку «не осталось ли не закоммиченных изменений» (гарантия, что сгенерированный код актуален):","content":"Генерация кода Можно добавить проверку «не осталось ли не закоммиченных изменений» (гарантия, что сгенерированный код актуален):"},{"id":"ci-cd/github-actions::matrix-strategy::31","title":"GitHub Actions","section":"Матрица (Matrix strategy)","path":"/docs/guide/ci-cd/github-actions#matrix-strategy","headings":["Матрица (Matrix strategy)"],"excerpt":"Матрица (Matrix strategy) Если у вас несколько вариантов конфигураций или разных языков генерации (через плагины), можно использовать matrix:","content":"Матрица (Matrix strategy) Если у вас несколько вариантов конфигураций или разных языков генерации (через плагины), можно использовать matrix:"},{"id":"ci-cd/github-actions::matrix-strategy::32","title":"GitHub Actions","section":"Матрица (Matrix strategy)","path":"/docs/guide/ci-cd/github-actions#matrix-strategy","headings":["Матрица (Matrix strategy)"],"excerpt":"Матрица (Matrix strategy) ```yaml jobs: generate: runs-on: ubuntu-latest strategy: fail-fast: false matrix: lang: [go, python] steps: - uses: actions/checkout@v4","content":"Матрица (Matrix strategy) ```yaml jobs: generate: runs-on: ubuntu-latest strategy: fail-fast: false matrix: lang: [go, python] steps: - uses: actions/checkout@v4"},{"id":"ci-cd/github-actions::matrix-strategy::33","title":"GitHub Actions","section":"Матрица (Matrix strategy)","path":"/docs/guide/ci-cd/github-actions#matrix-strategy","headings":["Матрица (Matrix strategy)"],"excerpt":"Матрица (Matrix strategy) name: Setup Go (only for go) if: matrix.lang == 'go' uses: actions/setup-go@v5 with: go-version: '1.22'","content":"Матрица (Matrix strategy) name: Setup Go (only for go) if: matrix.lang == 'go' uses: actions/setup-go@v5 with: go-version: '1.22'"},{"id":"ci-cd/github-actions::matrix-strategy::34","title":"GitHub Actions","section":"Матрица (Matrix strategy)","path":"/docs/guide/ci-cd/github-actions#matrix-strategy","headings":["Матрица (Matrix strategy)"],"excerpt":"Матрица (Matrix strategy) name: Install EasyP run: go install github.com/easyp-tech/easyp/cmd/easyp@latest","content":"Матрица (Matrix strategy) name: Install EasyP run: go install github.com/easyp-tech/easyp/cmd/easyp@latest"},{"id":"ci-cd/github-actions::matrix-strategy::35","title":"GitHub Actions","section":"Матрица (Matrix strategy)","path":"/docs/guide/ci-cd/github-actions#matrix-strategy","headings":["Матрица (Matrix strategy)"],"excerpt":"Матрица (Matrix strategy) name: Generate run: if [ \"${{ matrix.lang }}\" = \"go\" ]; then easyp generate elif [ \"${{ matrix.lang }}\" = \"python\" ]; then easyp generate --plugin python fi ```","content":"Матрица (Matrix strategy) name: Generate run: if [ \"${{ matrix.lang }}\" = \"go\" ]; then easyp generate elif [ \"${{ matrix.lang }}\" = \"python\" ]; then easyp generate --plugin python fi ```"},{"id":"ci-cd/github-actions::deps::36","title":"GitHub Actions","section":"Работа с приватными репозиториями (deps)","path":"/docs/guide/ci-cd/github-actions#deps","headings":["Работа с приватными репозиториями (deps)"],"excerpt":"Работа с приватными репозиториями (deps) Если вы указываете приватные Git-пакеты в секции deps:","content":"Работа с приватными репозиториями (deps) Если вы указываете приватные Git-пакеты в секции deps:"},{"id":"ci-cd/github-actions::deps::37","title":"GitHub Actions","section":"Работа с приватными репозиториями (deps)","path":"/docs/guide/ci-cd/github-actions#deps","headings":["Работа с приватными репозиториями (deps)"],"excerpt":"Работа с приватными репозиториями (deps) Настройте deploy key или используйте GIT_SSH_COMMAND с токеном. Добавьте known_hosts (либо установите StrictHostKeyChecking=no для внутренних систем, но осознанно).","content":"Работа с приватными репозиториями (deps) Настройте deploy key или используйте GIT_SSH_COMMAND с токеном. Добавьте known_hosts (либо установите StrictHostKeyChecking=no для внутренних систем, но осознанно)."},{"id":"ci-cd/github-actions::deps::38","title":"GitHub Actions","section":"Работа с приватными репозиториями (deps)","path":"/docs/guide/ci-cd/github-actions#deps","headings":["Работа с приватными репозиториями (deps)"],"excerpt":"Работа с приватными репозиториями (deps) Пример:","content":"Работа с приватными репозиториями (deps) Пример:"},{"id":"ci-cd/github-actions::deps::39","title":"GitHub Actions","section":"Работа с приватными репозиториями (deps)","path":"/docs/guide/ci-cd/github-actions#deps","headings":["Работа с приватными репозиториями (deps)"],"excerpt":"Работа с приватными репозиториями (deps) ```yaml name: Prepare SSH run: mkdir -p ~/.ssh echo \"${{ secrets.DEPLOY_KEY }}\" > ~/.ssh/id_rsa chmod 600 ~/.ssh/id_rsa ssh-keyscan github.com >> ~/.ssh/known_hosts","content":"Работа с приватными репозиториями (deps) ```yaml name: Prepare SSH run: mkdir -p ~/.ssh echo \"${{ secrets.DEPLOY_KEY }}\" > ~/.ssh/id_rsa chmod 600 ~/.ssh/id_rsa ssh-keyscan github.com >> ~/.ssh/known_hosts"},{"id":"ci-cd/github-actions::deps::40","title":"GitHub Actions","section":"Работа с приватными репозиториями (deps)","path":"/docs/guide/ci-cd/github-actions#deps","headings":["Работа с приватными репозиториями (deps)"],"excerpt":"Работа с приватными репозиториями (deps) name: Update deps run: easyp mod update ```","content":"Работа с приватными репозиториями (deps) name: Update deps run: easyp mod update ```"},{"id":"ci-cd/github-actions::top::41","title":"GitHub Actions","section":"Оптимизация времени сборки","path":"/docs/guide/ci-cd/github-actions","headings":["Оптимизация времени сборки"],"excerpt":"Оптимизация времени сборки Используйте кэш для Go / deps. Запускайте линт/брейкинг только если изменились .proto или easyp.yaml (paths фильтр). Разделяйте workflow: быстрый линт в PR, тяжелая генерация в push на main. Вы","content":"Оптимизация времени сборки Используйте кэш для Go / deps. Запускайте линт/брейкинг только если изменились .proto или easyp.yaml (paths фильтр). Разделяйте workflow: быстрый линт в PR, тяжелая генерация в push на main. Выносите генерацию OpenAPI / gRPC-Gateway в отдельный job (параллелизм)."},{"id":"ci-cd/github-actions::workflow::42","title":"GitHub Actions","section":"Продвинутый workflow (многостадийный)","path":"/docs/guide/ci-cd/github-actions#workflow","headings":["Продвинутый workflow (многостадийный)"],"excerpt":"Продвинутый workflow (многостадийный) ```yaml name: easyp-pipeline","content":"Продвинутый workflow (многостадийный) ```yaml name: easyp-pipeline"},{"id":"ci-cd/github-actions::workflow::43","title":"GitHub Actions","section":"Продвинутый workflow (многостадийный)","path":"/docs/guide/ci-cd/github-actions#workflow","headings":["Продвинутый workflow (многостадийный)"],"excerpt":"Продвинутый workflow (многостадийный) on: pull_request: paths: - '**/*.proto' - 'easyp.yaml' push: branches: - main","content":"Продвинутый workflow (многостадийный) on: pull_request: paths: - '**/*.proto' - 'easyp.yaml' push: branches: - main"},{"id":"ci-cd/github-actions::workflow::44","title":"GitHub Actions","section":"Продвинутый workflow (многостадийный)","path":"/docs/guide/ci-cd/github-actions#workflow","headings":["Продвинутый workflow (многостадийный)"],"excerpt":"Продвинутый workflow (многостадийный) jobs: validate: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4","content":"Продвинутый workflow (многостадийный) jobs: validate: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4"},{"id":"ci-cd/github-actions::workflow::45","title":"GitHub Actions","section":"Продвинутый workflow (многостадийный)","path":"/docs/guide/ci-cd/github-actions#workflow","headings":["Продвинутый workflow (многостадийный)"],"excerpt":"Продвинутый workflow (многостадийный) uses: actions/setup-go@v5 with: go-version: '1.22'","content":"Продвинутый workflow (многостадийный) uses: actions/setup-go@v5 with: go-version: '1.22'"},{"id":"ci-cd/github-actions::workflow::46","title":"GitHub Actions","section":"Продвинутый workflow (многостадийный)","path":"/docs/guide/ci-cd/github-actions#workflow","headings":["Продвинутый workflow (многостадийный)"],"excerpt":"Продвинутый workflow (многостадийный) name: Install EasyP run: go install github.com/easyp-tech/easyp/cmd/easyp@latest","content":"Продвинутый workflow (многостадийный) name: Install EasyP run: go install github.com/easyp-tech/easyp/cmd/easyp@latest"},{"id":"ci-cd/github-actions::workflow::47","title":"GitHub Actions","section":"Продвинутый workflow (многостадийный)","path":"/docs/guide/ci-cd/github-actions#workflow","headings":["Продвинутый workflow (многостадийный)"],"excerpt":"Продвинутый workflow (многостадийный) name: Lint run: easyp lint","content":"Продвинутый workflow (многостадийный) name: Lint run: easyp lint"},{"id":"ci-cd/github-actions::workflow::48","title":"GitHub Actions","section":"Продвинутый workflow (многостадийный)","path":"/docs/guide/ci-cd/github-actions#workflow","headings":["Продвинутый workflow (многостадийный)"],"excerpt":"Продвинутый workflow (многостадийный) name: Breaking check (against main) if: github.event_name == 'pull_request' run: easyp breaking --against git-ref=origin/main","content":"Продвинутый workflow (многостадийный) name: Breaking check (against main) if: github.event_name == 'pull_request' run: easyp breaking --against git-ref=origin/main"},{"id":"ci-cd/github-actions::workflow::49","title":"GitHub Actions","section":"Продвинутый workflow (многостадийный)","path":"/docs/guide/ci-cd/github-actions#workflow","headings":["Продвинутый workflow (многостадийный)"],"excerpt":"Продвинутый workflow (многостадийный) generate: needs: validate if: github.event_name == 'push' runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-go@v5 with: go-version: '1.22' - name: Insta","content":"Продвинутый workflow (многостадийный) generate: needs: validate if: github.event_name == 'push' runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-go@v5 with: go-version: '1.22' - name: Install EasyP run: go install github.com/easyp-tech/easyp/cmd/easyp@latest - name: Generate Code run: easyp generate - name: Check diffs run: if [ -n \"$(git status --porcelain)\" ]; then echo \"Generated files changed after generate step.\" git diff --name-only exit 1 fi ```"},{"id":"ci-cd/github-actions::top::50","title":"GitHub Actions","section":"Автоматизация релиза (пример)","path":"/docs/guide/ci-cd/github-actions","headings":["Автоматизация релиза (пример)"],"excerpt":"Автоматизация релиза (пример) Можно добавить workflow, который по тегу создаёт релиз и валидирует proto:","content":"Автоматизация релиза (пример) Можно добавить workflow, который по тегу создаёт релиз и валидирует proto:"},{"id":"ci-cd/github-actions::top::51","title":"GitHub Actions","section":"Автоматизация релиза (пример)","path":"/docs/guide/ci-cd/github-actions","headings":["Автоматизация релиза (пример)"],"excerpt":"Автоматизация релиза (пример) ```yaml name: release-verify","content":"Автоматизация релиза (пример) ```yaml name: release-verify"},{"id":"ci-cd/github-actions::top::52","title":"GitHub Actions","section":"Автоматизация релиза (пример)","path":"/docs/guide/ci-cd/github-actions","headings":["Автоматизация релиза (пример)"],"excerpt":"Автоматизация релиза (пример) on: push: tags: - 'v*.*.*'","content":"Автоматизация релиза (пример) on: push: tags: - 'v*.*.*'"},{"id":"ci-cd/github-actions::top::53","title":"GitHub Actions","section":"Автоматизация релиза (пример)","path":"/docs/guide/ci-cd/github-actions","headings":["Автоматизация релиза (пример)"],"excerpt":"Автоматизация релиза (пример) jobs: release-check: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4","content":"Автоматизация релиза (пример) jobs: release-check: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4"},{"id":"ci-cd/github-actions::top::54","title":"GitHub Actions","section":"Автоматизация релиза (пример)","path":"/docs/guide/ci-cd/github-actions","headings":["Автоматизация релиза (пример)"],"excerpt":"Автоматизация релиза (пример) uses: actions/setup-go@v5 with: go-version: '1.22'","content":"Автоматизация релиза (пример) uses: actions/setup-go@v5 with: go-version: '1.22'"},{"id":"ci-cd/github-actions::top::55","title":"GitHub Actions","section":"Автоматизация релиза (пример)","path":"/docs/guide/ci-cd/github-actions","headings":["Автоматизация релиза (пример)"],"excerpt":"Автоматизация релиза (пример) name: Install EasyP run: go install github.com/easyp-tech/easyp/cmd/easyp@latest","content":"Автоматизация релиза (пример) name: Install EasyP run: go install github.com/easyp-tech/easyp/cmd/easyp@latest"},{"id":"ci-cd/github-actions::top::56","title":"GitHub Actions","section":"Автоматизация релиза (пример)","path":"/docs/guide/ci-cd/github-actions","headings":["Автоматизация релиза (пример)"],"excerpt":"Автоматизация релиза (пример) name: Lint run: easyp lint","content":"Автоматизация релиза (пример) name: Lint run: easyp lint"},{"id":"ci-cd/github-actions::top::57","title":"GitHub Actions","section":"Автоматизация релиза (пример)","path":"/docs/guide/ci-cd/github-actions","headings":["Автоматизация релиза (пример)"],"excerpt":"Автоматизация релиза (пример) name: Breaking vs previous tag run: PREV_TAG=$(git tag --sort=-creatordate grep -v \"${GITHUB_REF_NAME}\" head -n1 true) if [ -n \"$PREV_TAG\" ]; then echo \"Comparing against $PREV_TAG\" easyp br","content":"Автоматизация релиза (пример) name: Breaking vs previous tag run: PREV_TAG=$(git tag --sort=-creatordate grep -v \"${GITHUB_REF_NAME}\" head -n1 true) if [ -n \"$PREV_TAG\" ]; then echo \"Comparing against $PREV_TAG\" easyp breaking --against git-ref=$PREV_TAG else echo \"No previous tag, skipping breaking check\" fi"},{"id":"ci-cd/github-actions::top::58","title":"GitHub Actions","section":"Автоматизация релиза (пример)","path":"/docs/guide/ci-cd/github-actions","headings":["Автоматизация релиза (пример)"],"excerpt":"Автоматизация релиза (пример) name: Generate to ensure consistency run: easyp generate ```","content":"Автоматизация релиза (пример) name: Generate to ensure consistency run: easyp generate ```"},{"id":"ci-cd/github-actions::top::59","title":"GitHub Actions","section":"Отладка","path":"/docs/guide/ci-cd/github-actions","headings":["Отладка"],"excerpt":"Отладка Если нужно больше логов:","content":"Отладка Если нужно больше логов:"},{"id":"ci-cd/github-actions::top::60","title":"GitHub Actions","section":"Отладка","path":"/docs/guide/ci-cd/github-actions","headings":["Отладка"],"excerpt":"Отладка Добавьте вывод окружения для диагностики:","content":"Отладка Добавьте вывод окружения для диагностики:"},{"id":"ci-cd/github-actions::top::61","title":"GitHub Actions","section":"Переменные окружения (примерно)","path":"/docs/guide/ci-cd/github-actions","headings":["Переменные окружения (примерно)"],"excerpt":"Переменные окружения (примерно) Переменная Назначение ------------ ----------- EASYP_SERVICE_HOST Хост удалённого API Service (если используете удалённые плагины) EASYP_SERVICE_GRPC_PORT Порт удалённого сервиса GIT_SSH_C","content":"Переменные окружения (примерно) Переменная Назначение ------------ ----------- EASYP_SERVICE_HOST Хост удалённого API Service (если используете удалённые плагины) EASYP_SERVICE_GRPC_PORT Порт удалённого сервиса GIT_SSH_COMMAND Кастомная команда SSH (частные репозитории) GOFLAGS Можно выставить -mod=readonly для Go генерации"},{"id":"ci-cd/github-actions::top::62","title":"GitHub Actions","section":"Переменные окружения (примерно)","path":"/docs/guide/ci-cd/github-actions","headings":["Переменные окружения (примерно)"],"excerpt":"Переменные окружения (примерно) (Используйте только те, что действительно нужны вашему проекту.)","content":"Переменные окружения (примерно) (Используйте только те, что действительно нужны вашему проекту.)"},{"id":"ci-cd/github-actions::top::63","title":"GitHub Actions","section":"Частые ошибки","path":"/docs/guide/ci-cd/github-actions","headings":["Частые ошибки"],"excerpt":"Частые ошибки Симптом Причина Решение --------- --------- --------- Линт падает на неизвестных правилах Правила указаны в easyp.yaml, но версия EasyP их не поддерживает Обновить EasyP (go install ...@latest) breaking сра","content":"Частые ошибки Симптом Причина Решение --------- --------- --------- Линт падает на неизвестных правилах Правила указаны в easyp.yaml, но версия EasyP их не поддерживает Обновить EasyP (go install ...@latest) breaking сравнение ничего не находит Неверный --against (нет fetch удалённой ветки) Добавить шаг git fetch --all --tags Сгенерированный код в PR отличается от main Отсутствует проверка генерации в CI Добавить шаг «Ensure generated code is up-to-date» Приватные deps не скачиваются Нет SSH ключа или токена Настроить secrets + шаг подготовки SSH Долгое выполнение Отсутствует кеш Добавить кэширование модулей и deps"},{"id":"ci-cd/github-actions::top::64","title":"GitHub Actions","section":"Рекомендации по поддержке","path":"/docs/guide/ci-cd/github-actions","headings":["Рекомендации по поддержке"],"excerpt":"Рекомендации по поддержке Заготовить шаблон workflow и копировать между сервисами (DRY). Включить paths фильтры, чтобы не тратить минуты на нерелевантные изменения. Проверять easyp.yaml при изменениях отдельно — можно за","content":"Рекомендации по поддержке Заготовить шаблон workflow и копировать между сервисами (DRY). Включить paths фильтры, чтобы не тратить минуты на нерелевантные изменения. Проверять easyp.yaml при изменениях отдельно — можно запускать «конфигурационный тест» (например, easyp lint без файлов, чтобы убедиться, что конфиг валиден). При появлении новых правил линтера обновляйте конфиг и фиксируйте ошибки сразу в одной ветке."},{"id":"ci-cd/github-actions::top::65","title":"GitHub Actions","section":"Рекомендации по поддержке","path":"/docs/guide/ci-cd/github-actions","headings":["Рекомендации по поддержке"],"excerpt":"Рекомендации по поддержке Готово: вы можете расширять разделы генерации, добавлять OpenAPI / grpc-gateway / validate плагины, матрицы по языкам и интегрировать тесты поверх сгенерированного кода, если требуется.","content":"Рекомендации по поддержке Готово: вы можете расширять разделы генерации, добавлять OpenAPI / grpc-gateway / validate плагины, матрицы по языкам и интегрировать тесты поверх сгенерированного кода, если требуется."},{"id":"ci-cd/gitlab::top::0","title":"GitLab CI","section":"В процессе разработки","path":"/docs/guide/ci-cd/gitlab","headings":["В процессе разработки"],"excerpt":"В процессе разработки Документация по интеграции EasyP с GitLab CI находится в процессе подготовки. Планируемые разделы: Быстрый старт (пример .gitlab-ci.yml для линтинга и проверки несовместимых изменений) Кэширование з","content":"В процессе разработки Документация по интеграции EasyP с GitLab CI находится в процессе подготовки. Планируемые разделы: Быстрый старт (пример .gitlab-ci.yml для линтинга и проверки несовместимых изменений) Кэширование зависимостей и ускорение сборок Генерация кода и проверка актуальности артефактов Работа с приватными Git-репозиториями в deps Матрицы (parallel jobs) для разных языков и плагинов Автоматизация релизов по тегам"},{"id":"ci-cd/gitlab::top::1","title":"GitLab CI","section":"В процессе разработки","path":"/docs/guide/ci-cd/gitlab","headings":["В процессе разработки"],"excerpt":"В процессе разработки Если вам нужен пример прямо сейчас, базовый минимальный вариант может выглядеть так:","content":"В процессе разработки Если вам нужен пример прямо сейчас, базовый минимальный вариант может выглядеть так:"},{"id":"ci-cd/gitlab::top::2","title":"GitLab CI","section":"В процессе разработки","path":"/docs/guide/ci-cd/gitlab","headings":["В процессе разработки"],"excerpt":"В процессе разработки ```yaml stages: - validate - generate","content":"В процессе разработки ```yaml stages: - validate - generate"},{"id":"ci-cd/gitlab::top::3","title":"GitLab CI","section":"В процессе разработки","path":"/docs/guide/ci-cd/gitlab","headings":["В процессе разработки"],"excerpt":"В процессе разработки variables: GO_VERSION: \"1.22\"","content":"В процессе разработки variables: GO_VERSION: \"1.22\""},{"id":"ci-cd/gitlab::top::4","title":"GitLab CI","section":"В процессе разработки","path":"/docs/guide/ci-cd/gitlab","headings":["В процессе разработки"],"excerpt":"В процессе разработки validate: stage: validate image: golang:${GO_VERSION} before_script: - go install github.com/easyp-tech/easyp/cmd/easyp@latest - echo \"EasyP version:\" - easyp version # При необходимости: git fetch ","content":"В процессе разработки validate: stage: validate image: golang:${GO_VERSION} before_script: - go install github.com/easyp-tech/easyp/cmd/easyp@latest - echo \"EasyP version:\" - easyp version # При необходимости: git fetch --all --tags script: - easyp lint - easyp breaking --against git-ref=origin/main only: changes: - \"**/*.proto\" - \"easyp.yaml\""},{"id":"ci-cd/gitlab::top::5","title":"GitLab CI","section":"В процессе разработки","path":"/docs/guide/ci-cd/gitlab","headings":["В процессе разработки"],"excerpt":"В процессе разработки generate: stage: generate image: golang:${GO_VERSION} before_script: - go install github.com/easyp-tech/easyp/cmd/easyp@latest script: - easyp generate - if [ -n \"$(git status --porcelain)\" ]; then ","content":"В процессе разработки generate: stage: generate image: golang:${GO_VERSION} before_script: - go install github.com/easyp-tech/easyp/cmd/easyp@latest script: - easyp generate - if [ -n \"$(git status --porcelain)\" ]; then echo \"Сгенерированный код не актуален. Закоммитьте изменения локально.\" git diff --name-only exit 1 fi only: - main"},{"id":"ci-cd/gitlab::top::6","title":"GitLab CI","section":"В процессе разработки","path":"/docs/guide/ci-cd/gitlab","headings":["В процессе разработки"],"excerpt":"В процессе разработки Дополнительные рекомендации будут добавлены позже.","content":"В процессе разработки Дополнительные рекомендации будут добавлены позже."},{"id":"cli/auto-completion/auto-completion::zsh::0","title":"Автодополнение","section":"Автодополнение для zsh","path":"/docs/guide/cli/auto-completion/auto-completion#zsh","headings":["Автодополнение для zsh"],"excerpt":"Автодополнение для zsh Добавьте следующую строку в ваш файл запуска ~/.zshrc:","content":"Автодополнение для zsh Добавьте следующую строку в ваш файл запуска ~/.zshrc:"},{"id":"cli/auto-completion/auto-completion::zsh::1","title":"Автодополнение","section":"Автодополнение для zsh","path":"/docs/guide/cli/auto-completion/auto-completion#zsh","headings":["Автодополнение для zsh"],"excerpt":"Автодополнение для zsh Перезапустите оболочку или выполните:","content":"Автодополнение для zsh Перезапустите оболочку или выполните:"},{"id":"cli/auto-completion/auto-completion::bash::2","title":"Автодополнение","section":"Автодополнение для Bash","path":"/docs/guide/cli/auto-completion/auto-completion#bash","headings":["Автодополнение для Bash"],"excerpt":"Автодополнение для Bash Установите bash-completion и подключите его в ~/.bashrc. Добавьте следующую строку в файл запуска ~/.bashrc:","content":"Автодополнение для Bash Установите bash-completion и подключите его в ~/.bashrc. Добавьте следующую строку в файл запуска ~/.bashrc:"},{"id":"cli/auto-completion/auto-completion::bash::3","title":"Автодополнение","section":"Автодополнение для Bash","path":"/docs/guide/cli/auto-completion/auto-completion#bash","headings":["Автодополнение для Bash"],"excerpt":"Автодополнение для Bash Перезапустите оболочку или выполните:","content":"Автодополнение для Bash Перезапустите оболочку или выполните:"},{"id":"cli/auto-completion/auto-completion::top::4","title":"Автодополнение","section":"Примечания","path":"/docs/guide/cli/auto-completion/auto-completion","headings":["Примечания"],"excerpt":"Примечания Команда easyp completion выводит скрипт автодополнения для соответствующей оболочки. Если используете другую оболочку (например, fish), можно сгенерировать вывод и сохранить вручную: При обновлении версии Easy","content":"Примечания Команда easyp completion выводит скрипт автодополнения для соответствующей оболочки. Если используете другую оболочку (например, fish), можно сгенерировать вывод и сохранить вручную: При обновлении версии EasyP рекомендуется заново перезагрузить оболочку, чтобы подтянуть возможные изменения в автодополнении."},{"id":"cli/breaking-changes/breaking-changes::top::0","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":[],"excerpt":"Обнаружение несовместимых изменений (Breaking Changes Detection)","content":"Обнаружение несовместимых изменений (Breaking Changes Detection)"},{"id":"cli/breaking-changes/breaking-changes::top::1","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":[],"excerpt":"Механизм EasyP для обнаружения несовместимых (breaking) изменений помогает поддерживать обратную совместимость ваших protobuf API, автоматически выявляя изменения, способные сломать существующих клиентов. Это критично дл","content":"Механизм EasyP для обнаружения несовместимых (breaking) изменений помогает поддерживать обратную совместимость ваших protobuf API, автоматически выявляя изменения, способные сломать существующих клиентов. Это критично для стабильных API в продакшене."},{"id":"cli/breaking-changes/breaking-changes::top::2","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Обзор","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Обзор"],"excerpt":"Обзор Проверка несовместимых изменений сравнивает текущий набор protobuf‑файлов с предыдущей версией (обычно из другой Git ветки) и фиксирует модификации, которые могут вызвать проблемы совместимости для уже работающих к","content":"Обзор Проверка несовместимых изменений сравнивает текущий набор protobuf‑файлов с предыдущей версией (обычно из другой Git ветки) и фиксирует модификации, которые могут вызвать проблемы совместимости для уже работающих клиентов."},{"id":"cli/breaking-changes/breaking-changes::top::3","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Ключевые возможности","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Ключевые возможности"],"excerpt":"Ключевые возможности **Сравнение через Git**: Сопоставление с любой Git‑ссылкой (ветка, тег, commit) **Комплексный анализ**: Проверка сервисов, сообщений, enum'ов, полей и import'ов **Выборочное игнорирование**: Пропуск ","content":"Ключевые возможности **Сравнение через Git**: Сопоставление с любой Git‑ссылкой (ветка, тег, commit) **Комплексный анализ**: Проверка сервисов, сообщений, enum'ов, полей и import'ов **Выборочное игнорирование**: Пропуск указанных директорий из анализа **Детализированные отчёты**: Понятные ошибки с именами файлов, строками и позициями"},{"id":"cli/breaking-changes/breaking-changes::top::4","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Как работает","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Как работает"],"excerpt":"Как работает Детектор breaking changes выполняет следующие шаги:","content":"Как работает Детектор breaking changes выполняет следующие шаги:"},{"id":"cli/breaking-changes/breaking-changes::top::5","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Как работает","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Как работает"],"excerpt":"Как работает **Получение ветки сравнения**: Забирает proto-файлы из указанной Git‑ссылки **Парсинг обеих версий**: Анализирует структуру текущих и предыдущих файлов **Сравнение сущностей**: Последовательно проверяет все ","content":"Как работает **Получение ветки сравнения**: Забирает proto-файлы из указанной Git‑ссылки **Парсинг обеих версий**: Анализирует структуру текущих и предыдущих файлов **Сравнение сущностей**: Последовательно проверяет все элементы protobuf на breaking изменения **Формирование отчёта**: Генерирует подробные записи об ошибках с локациями и описаниями"},{"id":"cli/breaking-changes/breaking-changes::top::6","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Уровень проверки","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Уровень проверки"],"excerpt":"Уровень проверки EasyP реализует уровень проверки **WIRE+**: ✅ **Полная совместимость по wire‑формату** — старые и новые версии могут обмениваться данными ✅ **Обнаружение удалений элементов** — сервисы, сообщения, поля и","content":"Уровень проверки EasyP реализует уровень проверки **WIRE+**: ✅ **Полная совместимость по wire‑формату** — старые и новые версии могут обмениваться данными ✅ **Обнаружение удалений элементов** — сервисы, сообщения, поля и т.п. ✅ **Безопасность типов** — выявляет несовместимые изменения типов ❌ **Переименования полей/методов** — пока не детектируются (в планах) ❌ **Изменения на уровне файлов** — переносы пакетов, file options ещё не проверяются"},{"id":"cli/breaking-changes/breaking-changes::top::7","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Уровень проверки","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Уровень проверки"],"excerpt":"Уровень проверки Это даёт сильные гарантии совместимости и меньше ограничений, чем инструменты, требующие совместимости сгенерированного кода.","content":"Уровень проверки Это даёт сильные гарантии совместимости и меньше ограничений, чем инструменты, требующие совместимости сгенерированного кода."},{"id":"cli/breaking-changes/breaking-changes::top::8","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Конфигурация","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Конфигурация"],"excerpt":"Конфигурация Настройка в easyp.yaml:","content":"Конфигурация Настройка в easyp.yaml:"},{"id":"cli/breaking-changes/breaking-changes::top::9","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Параметры конфигурации","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Параметры конфигурации"],"excerpt":"Параметры конфигурации Option Description Default Required -------- ------------- --------- ---------- against_git_ref Git‑ссылка для сравнения \"master\" No ignore Список директорий для исключения из анализа [] No","content":"Параметры конфигурации Option Description Default Required -------- ------------- --------- ---------- against_git_ref Git‑ссылка для сравнения \"master\" No ignore Список директорий для исключения из анализа [] No"},{"id":"cli/breaking-changes/breaking-changes::top::10","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Базовый пример","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Базовый пример"],"excerpt":"Базовый пример Сравнение текущих изменений с веткой main:","content":"Базовый пример Сравнение текущих изменений с веткой main:"},{"id":"cli/breaking-changes/breaking-changes::top::11","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Использование файла конфигурации","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Использование файла конфигурации"],"excerpt":"Использование файла конфигурации","content":"Использование файла конфигурации"},{"id":"cli/breaking-changes/breaking-changes::top::12","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Уровень проверки","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Уровень проверки"],"excerpt":"Уровень проверки EasyP сейчас работает на уровне **WIRE+**, обеспечивая совместимость wire‑формата плюс защиту от удалений и изменения критичных типов.","content":"Уровень проверки EasyP сейчас работает на уровне **WIRE+**, обеспечивая совместимость wire‑формата плюс защиту от удалений и изменения критичных типов."},{"id":"cli/breaking-changes/breaking-changes::buf::13","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Сравнение с категориями Buf","path":"/docs/guide/cli/breaking-changes/breaking-changes#buf","headings":["Сравнение с категориями Buf"],"excerpt":"Сравнение с категориями Buf Check Type Buf WIRE Buf WIRE_JSON Buf FILE EasyP Current ------------ ---------- --------------- ---------- --------------- **Element Deletions** Service deletion ❌ ❌ ✅ ✅ RPC method deletion ❌","content":"Сравнение с категориями Buf 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::top::14","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Что это означает","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Что это означает"],"excerpt":"Что это означает **✅ EasyP обнаружит:** Все breaking изменения wire‑формата Удаления сервисов, методов, сообщений, полей Изменения типов, ломающие сериализацию Переименования enum‑значений (при сохранении номера)","content":"Что это означает **✅ EasyP обнаружит:** Все breaking изменения wire‑формата Удаления сервисов, методов, сообщений, полей Изменения типов, ломающие сериализацию Переименования enum‑значений (при сохранении номера)"},{"id":"cli/breaking-changes/breaking-changes::top::15","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Что это означает","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Что это означает"],"excerpt":"Что это означает **❌ EasyP НЕ обнаружит:** Переименование полей (с тем же номером) Изменение package File options (go_package, java_package, и т.п.) Перемещение типов между файлами в одном package","content":"Что это означает **❌ EasyP НЕ обнаружит:** Переименование полей (с тем же номером) Изменение package File options (go_package, java_package, и т.п.) Перемещение типов между файлами в одном package"},{"id":"cli/breaking-changes/breaking-changes::breaking-changes::16","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Правила Breaking Changes","path":"/docs/guide/cli/breaking-changes/breaking-changes#breaking-changes","headings":["Правила Breaking Changes"],"excerpt":"Правила Breaking Changes EasyP обнаруживает следующие типы breaking изменений:","content":"Правила Breaking Changes EasyP обнаруживает следующие типы breaking изменений:"},{"id":"cli/breaking-changes/breaking-changes::top::17","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Сравнение уровней","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Сравнение уровней"],"excerpt":"Сравнение уровней Detection Level Description EasyP Support ---------------- ------------- --------------- **WIRE** Совместимость только по wire‑формату ✅ **Full support** **WIRE+** Wire + обнаружение удалений ✅ **Curren","content":"Сравнение уровней Detection Level Description EasyP Support ---------------- ------------- --------------- **WIRE** Совместимость только по wire‑формату ✅ **Full support** **WIRE+** Wire + обнаружение удалений ✅ **Current level** **FILE** Совместимость сгенерированного кода ❌ Partial (planned)"},{"id":"cli/breaking-changes/breaking-changes::top::18","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Категории правил","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Категории правил"],"excerpt":"Категории правил Каждая категория имеет свою документацию с примерами:","content":"Категории правил Каждая категория имеет свою документацию с примерами:"},{"id":"cli/breaking-changes/breaking-changes::service-rpc::19","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"🚨 Изменения Service и RPC","path":"/docs/guide/cli/breaking-changes/breaking-changes#service-rpc","headings":["🚨 Изменения Service и RPC"],"excerpt":"🚨 Изменения Service и RPC 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 и RPC 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-field::20","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"📦 Изменения Message и Field","path":"/docs/guide/cli/breaking-changes/breaking-changes#message-field","headings":["📦 Изменения Message и Field"],"excerpt":"📦 Изменения Message и Field 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 и Field 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::21","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"🔢 Изменения Enum","path":"/docs/guide/cli/breaking-changes/breaking-changes#enum","headings":["🔢 Изменения Enum"],"excerpt":"🔢 Изменения Enum 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 val","content":"🔢 Изменения Enum 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::22","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"🔗 Изменения OneOf","path":"/docs/guide/cli/breaking-changes/breaking-changes#oneof","headings":["🔗 Изменения OneOf"],"excerpt":"🔗 Изменения OneOf Rule Description Status ------ ------------- --------- ONEOF_NO_DELETE OneOf fields cannot be deleted ✅ Implemented ONEOF_FIELD_NO_DELETE Fields within oneofs cannot be deleted ✅ Implemented ONEOF_FIEL","content":"🔗 Изменения OneOf 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::23","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"📥 Изменения Import","path":"/docs/guide/cli/breaking-changes/breaking-changes#import","headings":["📥 Изменения Import"],"excerpt":"📥 Изменения Import Rule Description Status ------ ------------- --------- IMPORT_NO_DELETE Import statements cannot be removed ✅ Implemented","content":"📥 Изменения Import Rule Description Status ------ ------------- --------- IMPORT_NO_DELETE Import statements cannot be removed ✅ Implemented"},{"id":"cli/breaking-changes/breaking-changes::top::24","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Не обнаруживается сейчас","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Не обнаруживается сейчас"],"excerpt":"Не обнаруживается сейчас Изменения ниже **НЕ детектируются** EasyP (могут ломать сгенерированный код):","content":"Не обнаруживается сейчас Изменения ниже **НЕ детектируются** EasyP (могут ломать сгенерированный код):"},{"id":"cli/breaking-changes/breaking-changes::top::25","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Не обнаруживается сейчас","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Не обнаруживается сейчас"],"excerpt":"Не обнаруживается сейчас Change Type Example Impact ------------- --------- -------- Field renaming string name = 1 → string full_name = 1 Ломает код Package changes package v1 → package v2 Меняются пути импорта File opt","content":"Не обнаруживается сейчас Change Type Example Impact ------------- --------- -------- Field renaming string name = 1 → string full_name = 1 Ломает код Package changes package v1 → package v2 Меняются пути импорта File options option go_package = \"old\" → option go_package = \"new\" Меняется расположение кода Moving between files Message перемещено в другой .proto Зависимости import'ов"},{"id":"cli/breaking-changes/breaking-changes::top::26","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Документация правил","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Документация правил"],"excerpt":"Документация правил См. подробные файлы правил для примеров и стратегий миграции:","content":"Документация правил См. подробные файлы правил для примеров и стратегий миграции:"},{"id":"cli/breaking-changes/breaking-changes::top::27","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Документация правил","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Документация правил"],"excerpt":"Документация правил Service: SERVICE_NO_DELETE, RPC_NO_DELETE, RPC_SAME_REQUEST_TYPE, RPC_SAME_RESPONSE_TYPE Message: MESSAGE_NO_DELETE, FIELD_NO_DELETE, FIELD_SAME_TYPE, FIELD_SAME_CARDINALITY Enum: ENUM_NO_DELETE, ENUM","content":"Документация правил Service: SERVICE_NO_DELETE, RPC_NO_DELETE, RPC_SAME_REQUEST_TYPE, RPC_SAME_RESPONSE_TYPE Message: MESSAGE_NO_DELETE, FIELD_NO_DELETE, FIELD_SAME_TYPE, FIELD_SAME_CARDINALITY Enum: ENUM_NO_DELETE, ENUM_VALUE_NO_DELETE, ENUM_VALUE_SAME_NAME OneOf: ONEOF_NO_DELETE, ONEOF_FIELD_NO_DELETE, ONEOF_FIELD_SAME_TYPE Import: IMPORT_NO_DELETE"},{"id":"cli/breaking-changes/breaking-changes::top::28","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Документация правил","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Документация правил"],"excerpt":"Документация правил Каждое правило содержит: ❌ Плохие примеры (breaking) ✅ Безопасные альтернативы 🔧 Стратегии миграции 📋 Реальные сообщения ошибок из EasyP","content":"Документация правил Каждое правило содержит: ❌ Плохие примеры (breaking) ✅ Безопасные альтернативы 🔧 Стратегии миграции 📋 Реальные сообщения ошибок из EasyP"},{"id":"cli/breaking-changes/breaking-changes::top::29","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"✅ Безопасные изменения (разрешены всегда)","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["✅ Безопасные изменения (разрешены всегда)"],"excerpt":"✅ Безопасные изменения (разрешены всегда) ```proto // Добавление новых элементов — безопасно message User { string name = 1; string email = 2; string phone = 3; // ✅ Новое поле }","content":"✅ Безопасные изменения (разрешены всегда) ```proto // Добавление новых элементов — безопасно message User { string name = 1; string email = 2; string phone = 3; // ✅ Новое поле }"},{"id":"cli/breaking-changes/breaking-changes::top::30","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"✅ Безопасные изменения (разрешены всегда)","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["✅ Безопасные изменения (разрешены всегда)"],"excerpt":"✅ Безопасные изменения (разрешены всегда) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc GetUserProfile(GetUserRequest) returns (UserProfile); // ✅ Новый RPC }","content":"✅ Безопасные изменения (разрешены всегда) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc GetUserProfile(GetUserRequest) returns (UserProfile); // ✅ Новый RPC }"},{"id":"cli/breaking-changes/breaking-changes::top::31","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"✅ Безопасные изменения (разрешены всегда)","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["✅ Безопасные изменения (разрешены всегда)"],"excerpt":"✅ Безопасные изменения (разрешены всегда) enum Status { STATUS_UNSPECIFIED = 0; STATUS_ACTIVE = 1; STATUS_PENDING = 2; // ✅ Новое enum значение } ```","content":"✅ Безопасные изменения (разрешены всегда) enum Status { STATUS_UNSPECIFIED = 0; STATUS_ACTIVE = 1; STATUS_PENDING = 2; // ✅ Новое enum значение } ```"},{"id":"cli/breaking-changes/breaking-changes::top::32","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"❌ Несовместимые изменения (обнаруживаются всегда)","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["❌ Несовместимые изменения (обнаруживаются всегда)"],"excerpt":"❌ Несовместимые изменения (обнаруживаются всегда) ```proto // Удаления и смена типов ломают совместимость message User { string name = 1; // ❌ Удалённое поле }","content":"❌ Несовместимые изменения (обнаруживаются всегда) ```proto // Удаления и смена типов ломают совместимость message User { string name = 1; // ❌ Удалённое поле }"},{"id":"cli/breaking-changes/breaking-changes::top::33","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"❌ Несовместимые изменения (обнаруживаются всегда)","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["❌ Несовместимые изменения (обнаруживаются всегда)"],"excerpt":"❌ Несовместимые изменения (обнаруживаются всегда) service UserService { // ❌ Удалённый RPC метод rpc GetUser(GetUserRequestV2) returns (GetUserResponse); // ❌ Изменён тип запроса } ```","content":"❌ Несовместимые изменения (обнаруживаются всегда) service UserService { // ❌ Удалённый RPC метод rpc GetUser(GetUserRequestV2) returns (GetUserResponse); // ❌ Изменён тип запроса } ```"},{"id":"cli/breaking-changes/breaking-changes::top::34","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Сценарий: Изменения пока не детектируются","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Сценарий: Изменения пока не детектируются"],"excerpt":"Сценарий: Изменения пока не детектируются ```proto // 🟡 Ломает сгенерированный код, но проходит проверки EasyP message User { string user_name = 1; // Переименовано с \"name\" string user_email = 2; // Переименовано с \"em","content":"Сценарий: Изменения пока не детектируются ```proto // 🟡 Ломает сгенерированный код, но проходит проверки EasyP message User { string user_name = 1; // Переименовано с \"name\" string user_email = 2; // Переименовано с \"email\" }"},{"id":"cli/breaking-changes/breaking-changes::top::35","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Сценарий: Изменения пока не детектируются","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Сценарий: Изменения пока не детектируются"],"excerpt":"Сценарий: Изменения пока не детектируются service UserService { rpc GetUserProfile(GetUserRequest) returns (GetUserResponse); // Переименовано с GetUser } ```","content":"Сценарий: Изменения пока не детектируются service UserService { rpc GetUserProfile(GetUserRequest) returns (GetUserResponse); // Переименовано с GetUser } ```"},{"id":"cli/breaking-changes/breaking-changes::top::36","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Текстовый формат (по умолчанию)","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Текстовый формат (по умолчанию)"],"excerpt":"Текстовый формат (по умолчанию)","content":"Текстовый формат (по умолчанию)"},{"id":"cli/breaking-changes/breaking-changes::1::37","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"1. Регулярный запуск","path":"/docs/guide/cli/breaking-changes/breaking-changes#1","headings":["1. Регулярный запуск"],"excerpt":"Регулярный запуск Добавьте проверку несовместимых изменений в CI/CD:","content":"Регулярный запуск Добавьте проверку несовместимых изменений в CI/CD:"},{"id":"cli/breaking-changes/breaking-changes::2::38","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"2. Защита веток","path":"/docs/guide/cli/breaking-changes/breaking-changes#2","headings":["2. Защита веток"],"excerpt":"Защита веток Блокируйте слияния с breaking изменениями:","content":"Защита веток Блокируйте слияния с breaking изменениями:"},{"id":"cli/breaking-changes/breaking-changes::3::39","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"3. Стратегия версионирования","path":"/docs/guide/cli/breaking-changes/breaking-changes#3","headings":["3. Стратегия версионирования"],"excerpt":"Стратегия версионирования При необходимости breaking изменений: Создайте новую версию пакета (myservice.v2) Поддерживайте старую версию в период миграции Добавляйте уведомления о деприкации","content":"Стратегия версионирования При необходимости breaking изменений: Создайте новую версию пакета (myservice.v2) Поддерживайте старую версию в период миграции Добавляйте уведомления о деприкации"},{"id":"cli/breaking-changes/breaking-changes::4::40","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"4. Игнорирование путей","path":"/docs/guide/cli/breaking-changes/breaking-changes#4","headings":["4. Игнорирование путей"],"excerpt":"Игнорирование путей Используйте ignore осознанно:","content":"Игнорирование путей Используйте ignore осознанно:"},{"id":"cli/breaking-changes/breaking-changes::repository-does-not-exist::41","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Проблема: \"Repository does not exist\"","path":"/docs/guide/cli/breaking-changes/breaking-changes#repository-does-not-exist","headings":["Проблема: \"Repository does not exist\""],"excerpt":"Проблема: \"Repository does not exist\" Решение: Выполняйте команду внутри Git репозитория с нужной веткой.","content":"Проблема: \"Repository does not exist\" Решение: Выполняйте команду внутри Git репозитория с нужной веткой."},{"id":"cli/breaking-changes/breaking-changes::cannot-find-git-ref::42","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Проблема: \"Cannot find git ref\"","path":"/docs/guide/cli/breaking-changes/breaking-changes#cannot-find-git-ref","headings":["Проблема: \"Cannot find git ref\""],"excerpt":"Проблема: \"Cannot find git ref\" Решение: Проверьте наличие ссылки:","content":"Проблема: \"Cannot find git ref\" Решение: Проверьте наличие ссылки:"},{"id":"cli/breaking-changes/breaking-changes::top::43","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Проблема: Ложные срабатывания на сгенерированный код","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Проблема: Ложные срабатывания на сгенерированный код"],"excerpt":"Проблема: Ложные срабатывания на сгенерированный код Решение: Исключите директории генерации:","content":"Проблема: Ложные срабатывания на сгенерированный код Решение: Исключите директории генерации:"},{"id":"cli/breaking-changes/breaking-changes::top::44","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Проблема: Очень много изменений","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Проблема: Очень много изменений"],"excerpt":"Проблема: Очень много изменений Решение: Создайте новую версию API Вносите изменения постепенно Используйте feature flags","content":"Проблема: Очень много изменений Решение: Создайте новую версию API Вносите изменения постепенно Используйте feature flags"},{"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 - name: Install EasyP run: curl -sSfL https://raw.githubusercontent.com/easyp-tech/easyp/main/install.","content":"GitHub Actions jobs: breaking-changes: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 with: fetch-depth: 0 - 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-pre-push-hook::48","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Pre-commit / pre-push hook","path":"/docs/guide/cli/breaking-changes/breaking-changes#pre-commit-pre-push-hook","headings":["Pre-commit / pre-push hook"],"excerpt":"Pre-commit / pre-push hook ```bash #!/bin/sh .git/hooks/pre-push","content":"Pre-commit / pre-push hook ```bash #!/bin/sh .git/hooks/pre-push"},{"id":"cli/breaking-changes/breaking-changes::pre-commit-pre-push-hook::49","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Pre-commit / pre-push hook","path":"/docs/guide/cli/breaking-changes/breaking-changes#pre-commit-pre-push-hook","headings":["Pre-commit / pre-push hook"],"excerpt":"Pre-commit / pre-push hook protected_branch='main' current_branch=$(git symbolic-ref HEAD sed -e 's,.*/\\(.*\\),\\1,')","content":"Pre-commit / pre-push hook protected_branch='main' current_branch=$(git symbolic-ref HEAD sed -e 's,.*/\\(.*\\),\\1,')"},{"id":"cli/breaking-changes/breaking-changes::pre-commit-pre-push-hook::50","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Pre-commit / pre-push hook","path":"/docs/guide/cli/breaking-changes/breaking-changes#pre-commit-pre-push-hook","headings":["Pre-commit / pre-push hook"],"excerpt":"Pre-commit / pre-push 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.","content":"Pre-commit / pre-push 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::top::51","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Режим отладки","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Режим отладки"],"excerpt":"Режим отладки Включите debug‑логирование:","content":"Режим отладки Включите debug‑логирование:"},{"id":"cli/breaking-changes/breaking-changes::top::52","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Ручное сравнение","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Ручное сравнение"],"excerpt":"Ручное сравнение Для сложных случаев:","content":"Ручное сравнение Для сложных случаев:"},{"id":"cli/breaking-changes/breaking-changes::top::53","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Оптимизация производительности","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Оптимизация производительности"],"excerpt":"Оптимизация производительности Ограничьте область:","content":"Оптимизация производительности Ограничьте область:"},{"id":"cli/breaking-changes/breaking-changes::top::54","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Оптимизация производительности","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Оптимизация производительности"],"excerpt":"Оптимизация производительности","content":"Оптимизация производительности"},{"id":"cli/breaking-changes/breaking-changes::top::55","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Оптимизация производительности","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Оптимизация производительности"],"excerpt":"Оптимизация производительности Механизм обнаружения несовместимых изменений в EasyP обеспечивает надёжную основу для безопасной эволюции protobuf‑схем при сохранении совместимости API.","content":"Оптимизация производительности Механизм обнаружения несовместимых изменений в EasyP обеспечивает надёжную основу для безопасной эволюции protobuf‑схем при сохранении совместимости API."},{"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":"Это правило проверяет, что ни один enum не был удалён из proto‑файлов. Удаление enum ломает совместимость по wire‑формату и сгенерированный код: сохранённые данные могут содержать удалённые значения, а клиентский код опи","content":"Это правило проверяет, что ни один enum не был удалён из proto‑файлов. Удаление enum ломает совместимость по wire‑формату и сгенерированный код: сохранённые данные могут содержать удалённые значения, а клиентский код опирается на сгенерированные типы и константы enum."},{"id":"cli/breaking-changes/rules/enum-no-delete::breaking::1","title":"ENUM_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-no-delete::breaking::2","title":"ENUM_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/enum-no-delete::breaking::3","title":"ENUM_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_CONFIRMED = 2; ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_DELIVERED = 4; }","content":"Плохой (Breaking) 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::breaking::4","title":"ENUM_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) enum UserRole { // [!code --] USER_ROLE_UNSPECIFIED = 0; // [!code --] USER_ROLE_ADMIN = 1; // [!code --] USER_ROLE_USER = 2; // [!code --] } // [!code --]","content":"Плохой (Breaking) 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::breaking::5","title":"ENUM_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message Order { string id = 1; OrderStatus status = 2; UserRole created_by_role = 3; } ```","content":"Плохой (Breaking) message Order { string id = 1; OrderStatus status = 2; UserRole created_by_role = 3; } ```"},{"id":"cli/breaking-changes/rules/enum-no-delete::breaking::6","title":"ENUM_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-no-delete::breaking::7","title":"ENUM_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/enum-no-delete::breaking::8","title":"ENUM_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_CONFIRMED = 2; ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_DELIVERED = 4; }","content":"Плохой (Breaking) 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::breaking::9","title":"ENUM_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) // UserRole enum удалён — BREAKING CHANGE!","content":"Плохой (Breaking) // UserRole enum удалён — BREAKING CHANGE!"},{"id":"cli/breaking-changes/rules/enum-no-delete::breaking::10","title":"ENUM_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message Order { string id = 1; OrderStatus status = 2; UserRole created_by_role = 3; // ERROR: UserRole больше не существует } ```","content":"Плохой (Breaking) message Order { string id = 1; OrderStatus status = 2; UserRole created_by_role = 3; // ERROR: UserRole больше не существует } ```"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::11","title":"ENUM_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры **Удаление вложенного enum:** ```proto // Before message User { string name = 1; Status status = 2; enum Status { // [!code --] STATUS_UNSPECIFIED = 0; // [!code --] STATUS_ACTIVE = 1; // [!code --","content":"Дополнительные примеры **Удаление вложенного enum:** ```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::top::12","title":"ENUM_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры // After - BREAKING CHANGE! message User { string name = 1; Status status = 2; // ERROR: Status удалён // Вложенный enum Status удалён } ```","content":"Дополнительные примеры // After - BREAKING CHANGE! message User { string name = 1; Status status = 2; // ERROR: Status удалён // Вложенный enum Status удалён } ```"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::13","title":"ENUM_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо удаления — пометить enum deprecated:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо удаления — пометить enum deprecated:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::14","title":"ENUM_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::15","title":"ENUM_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_CONFIRMED = 2; ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_DELIVERED = 4; }","content":"Хороший (Безопасный) 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::top::16","title":"ENUM_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) enum UserRole { option deprecated = true; // [!code focus] USER_ROLE_UNSPECIFIED = 0; USER_ROLE_ADMIN = 1; USER_ROLE_USER = 2; }","content":"Хороший (Безопасный) 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::top::17","title":"ENUM_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message Order { string id = 1; OrderStatus status = 2; UserRole created_by_role = 3 [deprecated = true]; // [!code focus] } ```","content":"Хороший (Безопасный) 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::top::18","title":"ENUM_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Или заменить новым enum:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Или заменить новым enum:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::19","title":"ENUM_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::20","title":"ENUM_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_CONFIRMED = 2; ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_DELIVERED = 4; }","content":"Хороший (Безопасный) 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::top::21","title":"ENUM_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) enum UserRole { option deprecated = true; // [!code focus] // Старый enum USER_ROLE_UNSPECIFIED = 0; USER_ROLE_ADMIN = 1; USER_ROLE_USER = 2; }","content":"Хороший (Безопасный) enum UserRole { option deprecated = true; // [!code focus] // Старый enum USER_ROLE_UNSPECIFIED = 0; USER_ROLE_ADMIN = 1; USER_ROLE_USER = 2; }"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::22","title":"ENUM_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) enum UserPermission { // [!code focus] // Новый enum USER_PERMISSION_UNSPECIFIED = 0; // [!code focus] USER_PERMISSION_READ = 1; // [!code focus] USER_PERMISSION_WRITE = 2; // [!code focus] USER_PERM","content":"Хороший (Безопасный) enum UserPermission { // [!code focus] // Новый enum 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::top::23","title":"ENUM_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message Order { string id = 1; OrderStatus status = 2; UserRole created_by_role = 3 [deprecated = true]; // [!code focus] UserPermission created_by_permission = 4; // [!code focus] } ```","content":"Хороший (Безопасный) message Order { string id = 1; OrderStatus status = 2; UserRole created_by_role = 3 [deprecated = true]; // [!code focus] UserPermission created_by_permission = 4; // [!code focus] } ```"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::24","title":"ENUM_NO_DELETE","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Влияние"],"excerpt":"Влияние **Wire Format:** Данные с удалённым enum не десериализуются корректно **Generated Code:** Тип и константы удаляются — компиляция клиентов ломается **Field References:** Поля с типом удалённого enum становятся нев","content":"Влияние **Wire Format:** Данные с удалённым enum не десериализуются корректно **Generated Code:** Тип и константы удаляются — компиляция клиентов ломается **Field References:** Поля с типом удалённого enum становятся невалидны **Switch Statements:** switch по enum ломается (неизвестные кейсы)"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::25","title":"ENUM_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Код клиента ломается:** ```go // Before order := &myapi.Order{ Id: \"order123\", Status: myapi.OrderStatus_ORDER_STATUS_PENDING, CreatedByRole: myapi.UserRole_USER_ROLE_ADMIN, // ERROR после удаления }","content":"Реальный пример **Код клиента ломается:** ```go // Before order := &myapi.Order{ Id: \"order123\", Status: myapi.OrderStatus_ORDER_STATUS_PENDING, CreatedByRole: myapi.UserRole_USER_ROLE_ADMIN, // ERROR после удаления }"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::26","title":"ENUM_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример switch order.CreatedByRole { case myapi.UserRole_USER_ROLE_ADMIN: // ERROR // Admin logic case myapi.UserRole_USER_ROLE_USER: // ERROR // User logic }","content":"Реальный пример switch order.CreatedByRole { case myapi.UserRole_USER_ROLE_ADMIN: // ERROR // Admin logic case myapi.UserRole_USER_ROLE_USER: // ERROR // User logic }"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::27","title":"ENUM_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример // undefined: myapi.UserRole // undefined: myapi.UserRole_USER_ROLE_ADMIN ```","content":"Реальный пример // undefined: myapi.UserRole // undefined: myapi.UserRole_USER_ROLE_ADMIN ```"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::28","title":"ENUM_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Старые данные становятся нечитаемыми:**","content":"Реальный пример **Старые данные становятся нечитаемыми:**"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::29","title":"ENUM_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Серверная логика ломается:**","content":"Реальный пример **Серверная логика ломается:**"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::30","title":"ENUM_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Депрецируйте enum:** **Пометьте поля со старым enum deprecated:** **Создайте новый enum:** **Сервер обрабатывает оба:** **Удалите старый enum в следующей major‑версии.**","content":"Стратегия миграции **Депрецируйте enum:** **Пометьте поля со старым enum deprecated:** **Создайте новый enum:** **Сервер обрабатывает оба:** **Удалите старый enum в следующей major‑версии.**"},{"id":"cli/breaking-changes/rules/enum-no-delete::enum::31","title":"ENUM_NO_DELETE","section":"Редизайн enum","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#enum","headings":["Редизайн enum"],"excerpt":"Редизайн enum ```proto enum Priority { option deprecated = true; PRIORITY_UNSPECIFIED = 0; PRIORITY_LOW = 1; PRIORITY_HIGH = 2; }","content":"Редизайн enum ```proto enum Priority { option deprecated = true; PRIORITY_UNSPECIFIED = 0; PRIORITY_LOW = 1; PRIORITY_HIGH = 2; }"},{"id":"cli/breaking-changes/rules/enum-no-delete::enum::32","title":"ENUM_NO_DELETE","section":"Редизайн enum","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#enum","headings":["Редизайн enum"],"excerpt":"Редизайн enum enum TaskPriority { TASK_PRIORITY_UNSPECIFIED = 0; TASK_PRIORITY_LOW = 1; TASK_PRIORITY_MEDIUM = 2; TASK_PRIORITY_HIGH = 3; TASK_PRIORITY_URGENT = 4; } ```","content":"Редизайн enum enum TaskPriority { 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::enum::33","title":"ENUM_NO_DELETE","section":"Консолидация enum","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#enum","headings":["Консолидация enum"],"excerpt":"Консолидация enum ```proto enum Status { option deprecated = true; STATUS_UNSPECIFIED = 0; STATUS_ACTIVE = 1; }","content":"Консолидация enum ```proto enum Status { option deprecated = true; STATUS_UNSPECIFIED = 0; STATUS_ACTIVE = 1; }"},{"id":"cli/breaking-changes/rules/enum-no-delete::enum::34","title":"ENUM_NO_DELETE","section":"Консолидация enum","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#enum","headings":["Консолидация enum"],"excerpt":"Консолидация enum enum State { option deprecated = true; STATE_UNSPECIFIED = 0; STATE_ENABLED = 1; }","content":"Консолидация enum enum State { option deprecated = true; STATE_UNSPECIFIED = 0; STATE_ENABLED = 1; }"},{"id":"cli/breaking-changes/rules/enum-no-delete::enum::35","title":"ENUM_NO_DELETE","section":"Консолидация enum","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#enum","headings":["Консолидация enum"],"excerpt":"Консолидация enum enum EntityStatus { ENTITY_STATUS_UNSPECIFIED = 0; ENTITY_STATUS_ACTIVE = 1; ENTITY_STATUS_INACTIVE = 2; ENTITY_STATUS_ENABLED = 3; ENTITY_STATUS_DISABLED = 4; } ```","content":"Консолидация enum enum EntityStatus { 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::enum::36","title":"ENUM_NO_DELETE","section":"Перемещение enum в новый пакет","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#enum","headings":["Перемещение enum в новый пакет"],"excerpt":"Перемещение enum в новый пакет ```proto enum UserRole { option deprecated = true; USER_ROLE_UNSPECIFIED = 0; USER_ROLE_ADMIN = 1; }","content":"Перемещение enum в новый пакет ```proto enum UserRole { option deprecated = true; USER_ROLE_UNSPECIFIED = 0; USER_ROLE_ADMIN = 1; }"},{"id":"cli/breaking-changes/rules/enum-no-delete::enum::37","title":"ENUM_NO_DELETE","section":"Перемещение enum в новый пакет","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#enum","headings":["Перемещение enum в новый пакет"],"excerpt":"Перемещение enum в новый пакет import \"common/roles.proto\";","content":"Перемещение enum в новый пакет import \"common/roles.proto\";"},{"id":"cli/breaking-changes/rules/enum-no-delete::enum::38","title":"ENUM_NO_DELETE","section":"Перемещение enum в новый пакет","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#enum","headings":["Перемещение enum в новый пакет"],"excerpt":"Перемещение enum в новый пакет message Order { UserRole old_role = 3 [deprecated = true]; common.UserRole new_role = 4; } ```","content":"Перемещение enum в новый пакет message Order { UserRole old_role = 3 [deprecated = true]; common.UserRole new_role = 4; } ```"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::39","title":"ENUM_NO_DELETE","section":"Версионирование / новая версия пакета","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Версионирование / новая версия пакета"],"excerpt":"Версионирование / новая версия пакета ```proto package myapi.v2;","content":"Версионирование / новая версия пакета ```proto package myapi.v2;"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::40","title":"ENUM_NO_DELETE","section":"Версионирование / новая версия пакета","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Версионирование / новая версия пакета"],"excerpt":"Версионирование / новая версия пакета enum UserPermission { USER_PERMISSION_UNSPECIFIED = 0; USER_PERMISSION_READ = 1; USER_PERMISSION_WRITE = 2; USER_PERMISSION_ADMIN = 3; }","content":"Версионирование / новая версия пакета 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::top::41","title":"ENUM_NO_DELETE","section":"Версионирование / новая версия пакета","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Версионирование / новая версия пакета"],"excerpt":"Версионирование / новая версия пакета message Order { string id = 1; UserPermission created_by_permission = 2; } ```","content":"Версионирование / новая версия пакета message Order { string id = 1; UserPermission created_by_permission = 2; } ```"},{"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":"Правило проверяет, что ни одно значение enum (enum value) не было удалено. Удаление значения ломает совместимость по wire‑формату и сгенерированный код: в уже сохранённых данных могут присутствовать удалённые значения, а","content":"Правило проверяет, что ни одно значение enum (enum value) не было удалено. Удаление значения ломает совместимость по wire‑формату и сгенерированный код: в уже сохранённых данных могут присутствовать удалённые значения, а клиентский код может ссылаться на соответствующие константы."},{"id":"cli/breaking-changes/rules/enum-value-no-delete::breaking::1","title":"ENUM_VALUE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::breaking::2","title":"ENUM_VALUE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::breaking::3","title":"ENUM_VALUE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) 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":"Плохой (Breaking) 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::breaking::4","title":"ENUM_VALUE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) enum Priority { PRIORITY_UNSPECIFIED = 0; PRIORITY_LOW = 1; PRIORITY_MEDIUM = 2; PRIORITY_HIGH = 3; PRIORITY_URGENT = 4; } ```","content":"Плохой (Breaking) 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::breaking::5","title":"ENUM_VALUE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::breaking::6","title":"ENUM_VALUE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::breaking::7","title":"ENUM_VALUE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) 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 --] ","content":"Плохой (Breaking) 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 --] Удалено значение enum — BREAKING! }"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::breaking::8","title":"ENUM_VALUE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) enum Priority { PRIORITY_UNSPECIFIED = 0; PRIORITY_LOW = 1; PRIORITY_MEDIUM = 2; PRIORITY_HIGH = 3; // PRIORITY_URGENT = 4; // [!code --] Удалено значение enum — BREAKING! } ```","content":"Плохой (Breaking) enum Priority { PRIORITY_UNSPECIFIED = 0; PRIORITY_LOW = 1; PRIORITY_MEDIUM = 2; PRIORITY_HIGH = 3; // PRIORITY_URGENT = 4; // [!code --] Удалено значение enum — BREAKING! } ```"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::9","title":"ENUM_VALUE_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры **Множественное удаление значений:** ```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_S","content":"Дополнительные примеры **Множественное удаление значений:** ```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::top::10","title":"ENUM_VALUE_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры // 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","content":"Дополнительные примеры // 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::top::11","title":"ENUM_VALUE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо удаления — пометить значения deprecated:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо удаления — пометить значения deprecated:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::12","title":"ENUM_VALUE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::13","title":"ENUM_VALUE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) 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 = t","content":"Хороший (Безопасный) 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::top::14","title":"ENUM_VALUE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) enum Priority { PRIORITY_UNSPECIFIED = 0; PRIORITY_LOW = 1; PRIORITY_MEDIUM = 2; PRIORITY_HIGH = 3; PRIORITY_URGENT = 4 [deprecated = true]; // [!code focus] } ```","content":"Хороший (Безопасный) 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::top::15","title":"ENUM_VALUE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Или зарезервировать номер и имя после удаления:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Или зарезервировать номер и имя после удаления:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::16","title":"ENUM_VALUE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::17","title":"ENUM_VALUE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) enum OrderStatus { reserved 5; // [!code focus] reserved \"ORDER_STATUS_CANCELLED\"; // [!code focus]","content":"Хороший (Безопасный) enum OrderStatus { reserved 5; // [!code focus] reserved \"ORDER_STATUS_CANCELLED\"; // [!code focus]"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::18","title":"ENUM_VALUE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_CONFIRMED = 2; ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_DELIVERED = 4; }","content":"Хороший (Безопасный) 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::top::19","title":"ENUM_VALUE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) enum Priority { reserved 4; // [!code focus] reserved \"PRIORITY_URGENT\"; // [!code focus]","content":"Хороший (Безопасный) enum Priority { reserved 4; // [!code focus] reserved \"PRIORITY_URGENT\"; // [!code focus]"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::20","title":"ENUM_VALUE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) PRIORITY_UNSPECIFIED = 0; PRIORITY_LOW = 1; PRIORITY_MEDIUM = 2; PRIORITY_HIGH = 3; } ```","content":"Хороший (Безопасный) PRIORITY_UNSPECIFIED = 0; PRIORITY_LOW = 1; PRIORITY_MEDIUM = 2; PRIORITY_HIGH = 3; } ```"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::21","title":"ENUM_VALUE_NO_DELETE","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Влияние"],"excerpt":"Влияние **Wire Format:** Данные с удалёнными значениями не десериализуются корректно **Generated Code:** Константы исчезают — клиентский код не компилируется **Client Applications:** Ссылки на удалённые значения вызывают","content":"Влияние **Wire Format:** Данные с удалёнными значениями не десериализуются корректно **Generated Code:** Константы исчезают — клиентский код не компилируется **Client Applications:** Ссылки на удалённые значения вызывают ошибки компиляции **Switch Statements:** switch по enum ломается (неизвестные case) **Default Handling:** Поведение при неизвестных значениях меняется"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::22","title":"ENUM_VALUE_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Код клиента ломается:** ```go order := &myapi.Order{ Status: myapi.OrderStatus_ORDER_STATUS_CANCELLED, // ERROR после удаления }","content":"Реальный пример **Код клиента ломается:** ```go order := &myapi.Order{ Status: myapi.OrderStatus_ORDER_STATUS_CANCELLED, // ERROR после удаления }"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::23","title":"ENUM_VALUE_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример switch order.Status { case myapi.OrderStatus_ORDER_STATUS_PENDING: // Pending case myapi.OrderStatus_ORDER_STATUS_CANCELLED: // ERROR: undefined // Cancellation default: // Unknown } // undefined: myapi.O","content":"Реальный пример switch order.Status { case myapi.OrderStatus_ORDER_STATUS_PENDING: // Pending case myapi.OrderStatus_ORDER_STATUS_CANCELLED: // ERROR: undefined // Cancellation default: // Unknown } // undefined: myapi.OrderStatus_ORDER_STATUS_CANCELLED ```"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::24","title":"ENUM_VALUE_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Проблемы с уже сохранёнными данными:**","content":"Реальный пример **Проблемы с уже сохранёнными данными:**"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::25","title":"ENUM_VALUE_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Валидация на сервере:** ```go func validateOrderStatus(status OrderStatus) error { switch status { case OrderStatus_ORDER_STATUS_PENDING, OrderStatus_ORDER_STATUS_CONFIRMED, OrderStatus_ORDER_STATUS_SHI","content":"Реальный пример **Валидация на сервере:** ```go 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 после удаления return nil default: return errors.New(\"invalid order status\") } }"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::26","title":"ENUM_VALUE_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример func canModifyOrder(order *Order) bool { return order.Status != OrderStatus_ORDER_STATUS_CANCELLED // ERROR } ```","content":"Реальный пример func canModifyOrder(order *Order) bool { return order.Status != OrderStatus_ORDER_STATUS_CANCELLED // ERROR } ```"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::27","title":"ENUM_VALUE_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Сначала пометить deprecated:** **Перестать использовать deprecated значение в новом коде:** **Обработка legacy в клиенте:** **Резервирование после миграции:** **Никогда не переиспользовать номера** —","content":"Стратегия миграции **Сначала пометить deprecated:** **Перестать использовать deprecated значение в новом коде:** **Обработка legacy в клиенте:** **Резервирование после миграции:** **Никогда не переиспользовать номера** — зарезервированы навсегда."},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::28","title":"ENUM_VALUE_NO_DELETE","section":"Предотвращение переиспользования номера","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Предотвращение переиспользования номера"],"excerpt":"Предотвращение переиспользования номера ```proto enum Status { reserved 2; reserved \"STATUS_DELETED\";","content":"Предотвращение переиспользования номера ```proto enum Status { reserved 2; reserved \"STATUS_DELETED\";"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::29","title":"ENUM_VALUE_NO_DELETE","section":"Предотвращение переиспользования номера","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Предотвращение переиспользования номера"],"excerpt":"Предотвращение переиспользования номера STATUS_UNSPECIFIED = 0; STATUS_ACTIVE = 1; STATUS_INACTIVE = 3; // STATUS_DELETED = 2; // Не переиспользуем } ```","content":"Предотвращение переиспользования номера STATUS_UNSPECIFIED = 0; STATUS_ACTIVE = 1; STATUS_INACTIVE = 3; // STATUS_DELETED = 2; // Не переиспользуем } ```"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::json::30","title":"ENUM_VALUE_NO_DELETE","section":"JSON совместимость","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#json","headings":["JSON совместимость"],"excerpt":"JSON совместимость ```proto enum Color { reserved 2; reserved \"RED\";","content":"JSON совместимость ```proto enum Color { reserved 2; reserved \"RED\";"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::json::31","title":"ENUM_VALUE_NO_DELETE","section":"JSON совместимость","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#json","headings":["JSON совместимость"],"excerpt":"JSON совместимость COLOR_UNSPECIFIED = 0; COLOR_BLUE = 1; COLOR_GREEN = 3; // COLOR_RED = 2; // Был удалён } ```","content":"JSON совместимость COLOR_UNSPECIFIED = 0; COLOR_BLUE = 1; COLOR_GREEN = 3; // COLOR_RED = 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":"Это правило проверяет, что имя enum значения для каждого номера (number) не изменилось. Переименование enum значения при сохранении его номера ломает совместимость JSON и сгенерированный код: клиенты ожидают конкретные и","content":"Это правило проверяет, что имя enum значения для каждого номера (number) не изменилось. Переименование enum значения при сохранении его номера ломает совместимость JSON и сгенерированный код: клиенты ожидают конкретные имена констант."},{"id":"cli/breaking-changes/rules/enum-value-same-name::breaking::1","title":"ENUM_VALUE_SAME_NAME","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-value-same-name::breaking::2","title":"ENUM_VALUE_SAME_NAME","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/enum-value-same-name::breaking::3","title":"ENUM_VALUE_SAME_NAME","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_CONFIRMED = 2; ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_DELIVERED = 4; } ```","content":"Плохой (Breaking) 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::breaking::4","title":"ENUM_VALUE_SAME_NAME","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-value-same-name::breaking::5","title":"ENUM_VALUE_SAME_NAME","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/enum-value-same-name::breaking::6","title":"ENUM_VALUE_SAME_NAME","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_APPROVED = 2; // [!code --] Было ORDER_STATUS_CONFIRMED ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_COMPLETED = 4; // [","content":"Плохой (Breaking) enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_APPROVED = 2; // [!code --] Было ORDER_STATUS_CONFIRMED ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_COMPLETED = 4; // [!code --] Было ORDER_STATUS_DELIVERED } ```"},{"id":"cli/breaking-changes/rules/enum-value-same-name::top::7","title":"ENUM_VALUE_SAME_NAME","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры **Множественные переименования:** ```proto // Before enum UserRole { USER_ROLE_UNSPECIFIED = 0; USER_ROLE_ADMIN = 1; USER_ROLE_MODERATOR = 2; USER_ROLE_USER = 3; }","content":"Дополнительные примеры **Множественные переименования:** ```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::top::8","title":"ENUM_VALUE_SAME_NAME","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры // After - ВСЁ BREAKING enum UserRole { USER_ROLE_UNSPECIFIED = 0; USER_ROLE_ADMINISTRATOR = 1; // BREAKING: ADMIN -> ADMINISTRATOR USER_ROLE_MOD = 2; // BREAKING: MODERATOR -> MOD USER_ROLE_MEMBER","content":"Дополнительные примеры // After - ВСЁ BREAKING 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::top::9","title":"ENUM_VALUE_SAME_NAME","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо переименования — добавить новые значения и пометить старые deprecated:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо переименования — добавить новые значения и пометить старые deprecated:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-value-same-name::top::10","title":"ENUM_VALUE_SAME_NAME","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/enum-value-same-name::top::11","title":"ENUM_VALUE_SAME_NAME","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) 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 [depre","content":"Хороший (Безопасный) 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] // Новое значение вместо переименования ORDER_STATUS_COMPLETED = 6; // [!code focus] } ```"},{"id":"cli/breaking-changes/rules/enum-value-same-name::top::12","title":"ENUM_VALUE_SAME_NAME","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Или создать новую версию enum:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Или создать новую версию enum:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-value-same-name::top::13","title":"ENUM_VALUE_SAME_NAME","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v2; // [!code focus]","content":"Хороший (Безопасный) package myapi.v2; // [!code focus]"},{"id":"cli/breaking-changes/rules/enum-value-same-name::top::14","title":"ENUM_VALUE_SAME_NAME","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_APPROVED = 2; // [!code focus] // «Чистые» имена в v2 ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_COMPLETED = 4; // ","content":"Хороший (Безопасный) enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_APPROVED = 2; // [!code focus] // «Чистые» имена в v2 ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_COMPLETED = 4; // [!code focus] } ```"},{"id":"cli/breaking-changes/rules/enum-value-same-name::top::15","title":"ENUM_VALUE_SAME_NAME","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Влияние"],"excerpt":"Влияние **Generated Code:** Меняются имена констант — компиляция клиентов ломается **JSON Compatibility:** JSON использует имена enum — старые документы не парсятся **Client Applications:** Код со старым именем константы","content":"Влияние **Generated Code:** Меняются имена констант — компиляция клиентов ломается **JSON Compatibility:** JSON использует имена enum — старые документы не парсятся **Client Applications:** Код со старым именем константы не компилируется **Documentation:** Документация устаревает с неправильными именами"},{"id":"cli/breaking-changes/rules/enum-value-same-name::top::16","title":"ENUM_VALUE_SAME_NAME","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Реальный пример"],"excerpt":"Реальный пример **Ломается код клиента:** ```go // Before status := myapi.OrderStatus_ORDER_STATUS_CONFIRMED if order.Status == myapi.OrderStatus_ORDER_STATUS_DELIVERED { // handle delivery }","content":"Реальный пример **Ломается код клиента:** ```go // Before 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::top::17","title":"ENUM_VALUE_SAME_NAME","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Реальный пример"],"excerpt":"Реальный пример // After (переименовано) — ошибки компиляции status := myapi.OrderStatus_ORDER_STATUS_CONFIRMED // ERROR: undefined if order.Status == myapi.OrderStatus_ORDER_STATUS_DELIVERED { // ERROR: undefined // han","content":"Реальный пример // After (переименовано) — ошибки компиляции status := myapi.OrderStatus_ORDER_STATUS_CONFIRMED // ERROR: undefined if order.Status == myapi.OrderStatus_ORDER_STATUS_DELIVERED { // ERROR: undefined // handle delivery } ```"},{"id":"cli/breaking-changes/rules/enum-value-same-name::top::18","title":"ENUM_VALUE_SAME_NAME","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Реальный пример"],"excerpt":"Реальный пример **JSON совместимость ломается:** ```json // Раньше { \"status\": \"ORDER_STATUS_CONFIRMED\" }","content":"Реальный пример **JSON совместимость ломается:** ```json // Раньше { \"status\": \"ORDER_STATUS_CONFIRMED\" }"},{"id":"cli/breaking-changes/rules/enum-value-same-name::top::19","title":"ENUM_VALUE_SAME_NAME","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Реальный пример"],"excerpt":"Реальный пример // После { \"status\": \"ORDER_STATUS_APPROVED\" // Старые JSON больше не парсятся } ```","content":"Реальный пример // После { \"status\": \"ORDER_STATUS_APPROVED\" // Старые JSON больше не парсятся } ```"},{"id":"cli/breaking-changes/rules/enum-value-same-name::top::20","title":"ENUM_VALUE_SAME_NAME","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Добавьте новое значение вместо переименования:**","content":"Стратегия миграции **Добавьте новое значение вместо переименования:**"},{"id":"cli/breaking-changes/rules/enum-value-same-name::top::21","title":"ENUM_VALUE_SAME_NAME","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Сервер обрабатывает оба значения на переходном этапе** **Мигрируйте клиентов** на новые значения **Удалите (reserve) старое имя и номер** в следующей major‑версии:","content":"Стратегия миграции **Сервер обрабатывает оба значения на переходном этапе** **Мигрируйте клиентов** на новые значения **Удалите (reserve) старое имя и номер** в следующей major‑версии:"},{"id":"cli/breaking-changes/rules/enum-value-same-name::allow-alias::22","title":"ENUM_VALUE_SAME_NAME","section":"Allow Alias (исключение)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name#allow-alias","headings":["Allow Alias (исключение)"],"excerpt":"Allow Alias (исключение) С allow_alias = true можно временно иметь два имени для одного номера:","content":"Allow Alias (исключение) С allow_alias = true можно временно иметь два имени для одного номера:"},{"id":"cli/breaking-changes/rules/enum-value-same-name::allow-alias::23","title":"ENUM_VALUE_SAME_NAME","section":"Allow Alias (исключение)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name#allow-alias","headings":["Allow Alias (исключение)"],"excerpt":"Allow Alias (исключение) Примечание: Сейчас EasyP всё равно считает это breaking (может измениться в будущем).","content":"Allow Alias (исключение) Примечание: Сейчас EasyP всё равно считает это breaking (может измениться в будущем)."},{"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":"Это правило проверяет, что ни одно поле сообщения (message field) не было удалено. Удаление поля ломает совместимость по wire‑формату и сгенерированный код: в существующих данных может присутствовать удалённое поле, а кл","content":"Это правило проверяет, что ни одно поле сообщения (message field) не было удалено. Удаление поля ломает совместимость по wire‑формату и сгенерированный код: в существующих данных может присутствовать удалённое поле, а клиентский код может ссылаться на него."},{"id":"cli/breaking-changes/rules/field-no-delete::breaking::1","title":"FIELD_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-no-delete::breaking::2","title":"FIELD_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/field-no-delete::breaking::3","title":"FIELD_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message User { string name = 1; string email = 2; int32 age = 3; string phone = 4; // [!code --] } ```","content":"Плохой (Breaking) message User { string name = 1; string email = 2; int32 age = 3; string phone = 4; // [!code --] } ```"},{"id":"cli/breaking-changes/rules/field-no-delete::breaking::4","title":"FIELD_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-no-delete::breaking::5","title":"FIELD_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/field-no-delete::breaking::6","title":"FIELD_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message User { string name = 1; string email = 2; int32 age = 3; // phone поле удалено — BREAKING CHANGE! } ```","content":"Плохой (Breaking) message User { string name = 1; string email = 2; int32 age = 3; // phone поле удалено — BREAKING CHANGE! } ```"},{"id":"cli/breaking-changes/rules/field-no-delete::top::7","title":"FIELD_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо удаления — пометить поле deprecated:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо удаления — пометить поле deprecated:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-no-delete::top::8","title":"FIELD_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/field-no-delete::top::9","title":"FIELD_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message User { string name = 1; string email = 2; int32 age = 3; string phone = 4 [deprecated = true]; // [!code focus] } ```","content":"Хороший (Безопасный) 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::top::10","title":"FIELD_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Или зарезервировать номер и имя поля после удаления:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Или зарезервировать номер и имя поля после удаления:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-no-delete::top::11","title":"FIELD_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/field-no-delete::top::12","title":"FIELD_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message User { reserved 4; // [!code focus] reserved \"phone\"; // [!code focus] string name = 1; string email = 2; int32 age = 3; } ```","content":"Хороший (Безопасный) 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::top::13","title":"FIELD_NO_DELETE","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete","headings":["Влияние"],"excerpt":"Влияние **Wire Format:** Старые сообщения с удалённым полем некорректно десериализуются **Generated Code:** Удаляются аксессоры (get/set), компиляция клиента ломается **Data Loss:** Потеря сохранённых данных, связанных с","content":"Влияние **Wire Format:** Старые сообщения с удалённым полем некорректно десериализуются **Generated Code:** Удаляются аксессоры (get/set), компиляция клиента ломается **Data Loss:** Потеря сохранённых данных, связанных с полем **JSON Compatibility:** JSON парсеры ожидают наличие поля и могут выдавать ошибки"},{"id":"cli/breaking-changes/rules/field-no-delete::top::14","title":"FIELD_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Сначала пометить deprecated:**","content":"Стратегия миграции **Сначала пометить deprecated:**"},{"id":"cli/breaking-changes/rules/field-no-delete::top::15","title":"FIELD_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Прекратить запись в поле** в прикладном коде","content":"Стратегия миграции **Прекратить запись в поле** в прикладном коде"},{"id":"cli/breaking-changes/rules/field-no-delete::top::16","title":"FIELD_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Зарезервировать поле** в следующей версии, чтобы избежать повторного использования:","content":"Стратегия миграции **Зарезервировать поле** в следующей версии, чтобы избежать повторного использования:"},{"id":"cli/breaking-changes/rules/field-no-delete::top::17","title":"FIELD_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Никогда не переиспользовать номер поля** — должен оставаться в reserved навсегда","content":"Стратегия миграции **Никогда не переиспользовать номер поля** — должен оставаться в reserved навсегда"},{"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":"Правило проверяет, что поля сообщений сохраняют ту же кардинальность (обязательность / optional). Изменение кардинальности поля ломает совместимость по wire‑формату и сгенерированный код: семантика присутствия и ожидания","content":"Правило проверяет, что поля сообщений сохраняют ту же кардинальность (обязательность / optional). Изменение кардинальности поля ломает совместимость по wire‑формату и сгенерированный код: семантика присутствия и ожидания клиентского кода отличаются для optional и required (implicit) полей."},{"id":"cli/breaking-changes/rules/field-same-cardinality::breaking::1","title":"FIELD_SAME_CARDINALITY","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-same-cardinality::breaking::2","title":"FIELD_SAME_CARDINALITY","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/field-same-cardinality::breaking::3","title":"FIELD_SAME_CARDINALITY","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message User { string name = 1; string email = 2; int32 age = 3; }","content":"Плохой (Breaking) message User { string name = 1; string email = 2; int32 age = 3; }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::breaking::4","title":"FIELD_SAME_CARDINALITY","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message CreateUserRequest { string name = 1; optional string email = 2; string phone = 3; } ```","content":"Плохой (Breaking) message CreateUserRequest { string name = 1; optional string email = 2; string phone = 3; } ```"},{"id":"cli/breaking-changes/rules/field-same-cardinality::breaking::5","title":"FIELD_SAME_CARDINALITY","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-same-cardinality::breaking::6","title":"FIELD_SAME_CARDINALITY","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/field-same-cardinality::breaking::7","title":"FIELD_SAME_CARDINALITY","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message User { string name = 1; optional string email = 2; // [!code --] Было required (implicit), стало optional int32 age = 3; }","content":"Плохой (Breaking) message User { string name = 1; optional string email = 2; // [!code --] Было required (implicit), стало optional int32 age = 3; }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::breaking::8","title":"FIELD_SAME_CARDINALITY","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message CreateUserRequest { string name = 1; string email = 2; // [!code --] Было optional, стало требуемым (implicit required) string phone = 3; } ```","content":"Плохой (Breaking) message CreateUserRequest { string name = 1; string email = 2; // [!code --] Было optional, стало требуемым (implicit required) string phone = 3; } ```"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::9","title":"FIELD_SAME_CARDINALITY","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры **Проблемы миграции Proto2 → Proto3:**","content":"Дополнительные примеры **Проблемы миграции Proto2 → Proto3:**"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::10","title":"FIELD_SAME_CARDINALITY","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры ```proto // Before (proto2) syntax = \"proto2\";","content":"Дополнительные примеры ```proto // Before (proto2) syntax = \"proto2\";"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::11","title":"FIELD_SAME_CARDINALITY","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры message Order { required string id = 1; optional string notes = 2; repeated string tags = 3; }","content":"Дополнительные примеры message Order { required string id = 1; optional string notes = 2; repeated string tags = 3; }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::12","title":"FIELD_SAME_CARDINALITY","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры // After (proto3) - BREAKING CHANGES! syntax = \"proto3\";","content":"Дополнительные примеры // After (proto3) - BREAKING CHANGES! syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::13","title":"FIELD_SAME_CARDINALITY","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры message Order { string id = 1; // BREAKING: required -> implicit optional string notes = 2; // BREAKING: explicit optional -> implicit optional repeated string tags = 3; // OK } ```","content":"Дополнительные примеры message Order { string id = 1; // BREAKING: required -> implicit optional string notes = 2; // BREAKING: explicit optional -> implicit optional repeated string tags = 3; // OK } ```"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::14","title":"FIELD_SAME_CARDINALITY","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо изменения кардинальности — добавьте новое поле:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо изменения кардинальности — добавьте новое поле:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::15","title":"FIELD_SAME_CARDINALITY","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::16","title":"FIELD_SAME_CARDINALITY","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message User { string name = 1; string email = 2 [deprecated = true]; // [!code focus] Сохраняем старую кардинальность int32 age = 3; optional string email_optional = 4; // [!code focus] Новое option","content":"Хороший (Безопасный) message User { string name = 1; string email = 2 [deprecated = true]; // [!code focus] Сохраняем старую кардинальность int32 age = 3; optional string email_optional = 4; // [!code focus] Новое optional поле }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::17","title":"FIELD_SAME_CARDINALITY","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message CreateUserRequest { string name = 1; optional string email = 2 [deprecated = true]; // [!code focus] string phone = 3; string email_required = 4; // [!code focus] Новое требуемое поле } ```","content":"Хороший (Безопасный) message CreateUserRequest { string name = 1; optional string email = 2 [deprecated = true]; // [!code focus] string phone = 3; string email_required = 4; // [!code focus] Новое требуемое поле } ```"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::18","title":"FIELD_SAME_CARDINALITY","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Или создайте новую версию сообщения:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Или создайте новую версию сообщения:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::19","title":"FIELD_SAME_CARDINALITY","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v2; // [!code focus]","content":"Хороший (Безопасный) package myapi.v2; // [!code focus]"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::20","title":"FIELD_SAME_CARDINALITY","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message User { string name = 1; optional string email = 2; // [!code focus] Чистая модель в v2 int32 age = 3; }","content":"Хороший (Безопасный) message User { string name = 1; optional string email = 2; // [!code focus] Чистая модель в v2 int32 age = 3; }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::21","title":"FIELD_SAME_CARDINALITY","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message CreateUserRequest { string name = 1; string email = 2; // [!code focus] Требуемое в v2 string phone = 3; } ```","content":"Хороший (Безопасный) message CreateUserRequest { string name = 1; string email = 2; // [!code focus] Требуемое в v2 string phone = 3; } ```"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::22","title":"FIELD_SAME_CARDINALITY","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Влияние"],"excerpt":"Влияние **Wire Format:** Меняется семантика присутствия — клиенты неправильно ожидают поля **Generated Code:** Меняются методы доступа / проверки (has, clear) **Validation:** Правила проверки обязательности переписываютс","content":"Влияние **Wire Format:** Меняется семантика присутствия — клиенты неправильно ожидают поля **Generated Code:** Меняются методы доступа / проверки (has, clear) **Validation:** Правила проверки обязательности переписываются **Default Values:** Optional и required по‑разному обрабатывают отсутствие значения"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::23","title":"FIELD_SAME_CARDINALITY","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Реальный пример"],"excerpt":"Реальный пример **Код клиента ломается при смене кардинальности:** ```go // Before - поле фактически требуется (implicit) user := &myapi.User{ Name: \"John\", Email: \"john@example.com\", Age: 30, }","content":"Реальный пример **Код клиента ломается при смене кардинальности:** ```go // Before - поле фактически требуется (implicit) user := &myapi.User{ Name: \"John\", Email: \"john@example.com\", Age: 30, }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::24","title":"FIELD_SAME_CARDINALITY","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Реальный пример"],"excerpt":"Реальный пример if user.Email != \"\" { // Есть значение }","content":"Реальный пример if user.Email != \"\" { // Есть значение }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::25","title":"FIELD_SAME_CARDINALITY","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Реальный пример"],"excerpt":"Реальный пример // After - поле стало optional (pointer) user := &myapi.User{ Name: \"John\", Age: 30, // Email может отсутствовать }","content":"Реальный пример // After - поле стало optional (pointer) user := &myapi.User{ Name: \"John\", Age: 30, // Email может отсутствовать }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::26","title":"FIELD_SAME_CARDINALITY","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Реальный пример"],"excerpt":"Реальный пример if user.Email != nil && *user.Email != \"\" { // Есть значение (новый способ) }","content":"Реальный пример if user.Email != nil && *user.Email != \"\" { // Есть значение (новый способ) }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::27","title":"FIELD_SAME_CARDINALITY","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Реальный пример"],"excerpt":"Реальный пример user.Email = &emailValue // Присваивание указателя вместо строки ```","content":"Реальный пример user.Email = &emailValue // Присваивание указателя вместо строки ```"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::28","title":"FIELD_SAME_CARDINALITY","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Реальный пример"],"excerpt":"Реальный пример **Валидация на сервере:** ```go // Before func validateUser(user *User) error { if user.Email == \"\" { return errors.New(\"email is required\") } return nil }","content":"Реальный пример **Валидация на сервере:** ```go // Before func validateUser(user *User) error { if user.Email == \"\" { return errors.New(\"email is required\") } return nil }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::29","title":"FIELD_SAME_CARDINALITY","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Реальный пример"],"excerpt":"Реальный пример // After func validateUser(user *User) error { if user.Email == nil { return errors.New(\"email is required\") } if *user.Email == \"\" { return errors.New(\"email cannot be empty\") } return nil } ```","content":"Реальный пример // After func validateUser(user *User) error { if user.Email == nil { return errors.New(\"email is required\") } if *user.Email == \"\" { return errors.New(\"email cannot be empty\") } return nil } ```"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::30","title":"FIELD_SAME_CARDINALITY","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Добавьте новое поле** с нужной кардинальностью:","content":"Стратегия миграции **Добавьте новое поле** с нужной кардинальностью:"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::31","title":"FIELD_SAME_CARDINALITY","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Период двойной записи** — заполняйте оба поля:","content":"Стратегия миграции **Период двойной записи** — заполняйте оба поля:"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::32","title":"FIELD_SAME_CARDINALITY","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Клиенты постепенно переходят**:","content":"Стратегия миграции **Клиенты постепенно переходят**:"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::33","title":"FIELD_SAME_CARDINALITY","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Удаление старого поля** в следующей major‑версии:","content":"Стратегия миграции **Удаление старого поля** в следующей major‑версии:"},{"id":"cli/breaking-changes/rules/field-same-cardinality::proto2-proto3::34","title":"FIELD_SAME_CARDINALITY","section":"Миграция Proto2 → Proto3","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#proto2-proto3","headings":["Миграция Proto2 → Proto3"],"excerpt":"Миграция Proto2 → Proto3 ```proto syntax = \"proto3\"; message Order { string id = 1; // BREAKING если был required }","content":"Миграция Proto2 → Proto3 ```proto syntax = \"proto3\"; message Order { string id = 1; // BREAKING если был required }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::proto2-proto3::35","title":"FIELD_SAME_CARDINALITY","section":"Миграция Proto2 → Proto3","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#proto2-proto3","headings":["Миграция Proto2 → Proto3"],"excerpt":"Миграция Proto2 → Proto3 // Сохранить семантику: syntax = \"proto3\"; message Order { string id = 1; optional string notes = 2; } ```","content":"Миграция Proto2 → Proto3 // Сохранить семантику: syntax = \"proto3\"; message Order { string id = 1; optional string notes = 2; } ```"},{"id":"cli/breaking-changes/rules/field-same-cardinality::optional-required::36","title":"FIELD_SAME_CARDINALITY","section":"Делать optional поле required","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#optional-required","headings":["Делать optional поле required"],"excerpt":"Делать optional поле required ```proto message CreateUserRequest { string name = 1; string email = 2; // BREAKING (раньше optional) }","content":"Делать optional поле required ```proto message CreateUserRequest { string name = 1; string email = 2; // BREAKING (раньше optional) }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::optional-required::37","title":"FIELD_SAME_CARDINALITY","section":"Делать optional поле required","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#optional-required","headings":["Делать optional поле required"],"excerpt":"Делать optional поле required message CreateUserRequest { string name = 1; optional string email = 2 [deprecated = true]; string required_email = 3; } ```","content":"Делать optional поле required message CreateUserRequest { string name = 1; optional string email = 2 [deprecated = true]; string required_email = 3; } ```"},{"id":"cli/breaking-changes/rules/field-same-cardinality::required-optional::38","title":"FIELD_SAME_CARDINALITY","section":"Делать required поле optional","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#required-optional","headings":["Делать required поле optional"],"excerpt":"Делать required поле optional ```proto message User { optional string phone = 3; // BREAKING (было implicit required) }","content":"Делать required поле optional ```proto message User { optional string phone = 3; // BREAKING (было implicit required) }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::required-optional::39","title":"FIELD_SAME_CARDINALITY","section":"Делать required поле optional","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#required-optional","headings":["Делать required поле optional"],"excerpt":"Делать required поле optional message User { string phone = 3 [deprecated = true]; optional string phone_optional = 4; } ```","content":"Делать required поле optional message User { string phone = 3 [deprecated = true]; optional string phone_optional = 4; } ```"},{"id":"cli/breaking-changes/rules/field-same-cardinality::protobuf::40","title":"FIELD_SAME_CARDINALITY","section":"Типы кардинальности в Protobuf","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#protobuf","headings":["Типы кардинальности в Protobuf"],"excerpt":"Типы кардинальности в Protobuf","content":"Типы кардинальности в Protobuf"},{"id":"cli/breaking-changes/rules/field-same-cardinality::proto3::41","title":"FIELD_SAME_CARDINALITY","section":"Proto3","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#proto3","headings":["Proto3"],"excerpt":"Proto3 **Implicit optional**: string name = 1; **Explicit optional**: optional string email = 2; **Repeated**: repeated string tags = 3; **Map**: map metadata = 4;","content":"Proto3 **Implicit optional**: string name = 1; **Explicit optional**: optional string email = 2; **Repeated**: repeated string tags = 3; **Map**: map metadata = 4;"},{"id":"cli/breaking-changes/rules/field-same-cardinality::proto2::42","title":"FIELD_SAME_CARDINALITY","section":"Proto2","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#proto2","headings":["Proto2"],"excerpt":"Proto2 **Required**: required string id = 1; **Optional**: optional string email = 2; **Repeated**: repeated string tags = 3;","content":"Proto2 **Required**: required string id = 1; **Optional**: optional string email = 2; **Repeated**: repeated string tags = 3;"},{"id":"cli/breaking-changes/rules/field-same-cardinality::breaking::43","title":"FIELD_SAME_CARDINALITY","section":"Матрица Breaking изменений","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#breaking","headings":["Матрица Breaking изменений"],"excerpt":"Матрица Breaking изменений From To Result ------ ---- -------- Required Optional ❌ BREAKING Optional Required ❌ BREAKING Implicit Explicit ❌ BREAKING Explicit Implicit ❌ BREAKING Single Repeated ❌ BREAKING Repeated Singl","content":"Матрица Breaking изменений 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":"Правило проверяет, что типы полей сообщений (message fields) не изменяются. Смена типа поля ломает совместимость по wire‑формату и сгенерированный код: бинарное представление и ожидания клиентского кода различаются для р","content":"Правило проверяет, что типы полей сообщений (message fields) не изменяются. Смена типа поля ломает совместимость по wire‑формату и сгенерированный код: бинарное представление и ожидания клиентского кода различаются для разных типов."},{"id":"cli/breaking-changes/rules/field-same-type::breaking::1","title":"FIELD_SAME_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-same-type::breaking::2","title":"FIELD_SAME_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/field-same-type::breaking::3","title":"FIELD_SAME_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message Product { string name = 1; int32 price = 2; bool available = 3; } ```","content":"Плохой (Breaking) message Product { string name = 1; int32 price = 2; bool available = 3; } ```"},{"id":"cli/breaking-changes/rules/field-same-type::breaking::4","title":"FIELD_SAME_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-same-type::breaking::5","title":"FIELD_SAME_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/field-same-type::breaking::6","title":"FIELD_SAME_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message Product { string name = 1; string price = 2; // [!code --] Changed from int32 to string (изменён тип) bool available = 3; } ```","content":"Плохой (Breaking) 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::top::7","title":"FIELD_SAME_TYPE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/field-same-type","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры **Несовместимые изменения типов:** ```proto // Before message Order { string id = 1; int64 timestamp = 2; repeated string tags = 3; OrderStatus status = 4; }","content":"Дополнительные примеры **Несовместимые изменения типов:** ```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::top::8","title":"FIELD_SAME_TYPE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/field-same-type","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры // After - ВСЁ BREAKING message Order { int32 id = 1; // string -> int32: BREAKING string timestamp = 2; // int64 -> string: BREAKING string tags = 3; // repeated -> singular: BREAKING int32 status","content":"Дополнительные примеры // After - ВСЁ BREAKING 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::top::9","title":"FIELD_SAME_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо смены типа — добавьте новое поле:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо смены типа — добавьте новое поле:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-same-type::top::10","title":"FIELD_SAME_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/field-same-type::top::11","title":"FIELD_SAME_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message Product { string name = 1; int32 price = 2 [deprecated = true]; // [!code focus] // Старое поле помечено deprecated bool available = 3; string price_formatted = 4; // [!code focus] // Новое п","content":"Хороший (Безопасный) message Product { string name = 1; int32 price = 2 [deprecated = true]; // [!code focus] // Старое поле помечено deprecated bool available = 3; string price_formatted = 4; // [!code focus] // Новое поле со строковым представлением } ```"},{"id":"cli/breaking-changes/rules/field-same-type::top::12","title":"FIELD_SAME_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Или создайте новую версию сообщения:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Или создайте новую версию сообщения:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-same-type::top::13","title":"FIELD_SAME_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v2; // [!code focus] // Новая версия package","content":"Хороший (Безопасный) package myapi.v2; // [!code focus] // Новая версия package"},{"id":"cli/breaking-changes/rules/field-same-type::top::14","title":"FIELD_SAME_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message Product { string name = 1; string price = 2; // [!code focus] // В v2 уже string bool available = 3; } ```","content":"Хороший (Безопасный) message Product { string name = 1; string price = 2; // [!code focus] // В v2 уже string bool available = 3; } ```"},{"id":"cli/breaking-changes/rules/field-same-type::top::15","title":"FIELD_SAME_TYPE","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/field-same-type","headings":["Влияние"],"excerpt":"Влияние **Wire Format:** Старые бинарные данные не десериализуются корректно **Generated Code:** Меняются типы в сгенерированном коде — клиенты не компилируются **Runtime Errors:** Ошибки парсинга при несовпадении ожидае","content":"Влияние **Wire Format:** Старые бинарные данные не десериализуются корректно **Generated Code:** Меняются типы в сгенерированном коде — клиенты не компилируются **Runtime Errors:** Ошибки парсинга при несовпадении ожидаемого типа **Data Corruption:** Неверная интерпретация байтов данных"},{"id":"cli/breaking-changes/rules/field-same-type::top::16","title":"FIELD_SAME_TYPE","section":"Типовые проблемы изменений типов","path":"/docs/guide/cli/breaking-changes/rules/field-same-type","headings":["Типовые проблемы изменений типов"],"excerpt":"Типовые проблемы изменений типов","content":"Типовые проблемы изменений типов"},{"id":"cli/breaking-changes/rules/field-same-type::top::17","title":"FIELD_SAME_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/field-same-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Добавьте новое поле** с нужным типом:","content":"Стратегия миграции **Добавьте новое поле** с нужным типом:"},{"id":"cli/breaking-changes/rules/field-same-type::top::18","title":"FIELD_SAME_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/field-same-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Период двойной записи** — заполняйте оба поля для совместимости","content":"Стратегия миграции **Период двойной записи** — заполняйте оба поля для совместимости"},{"id":"cli/breaking-changes/rules/field-same-type::top::19","title":"FIELD_SAME_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/field-same-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Мигрируйте клиентов** на новое поле постепенно","content":"Стратегия миграции **Мигрируйте клиентов** на новое поле постепенно"},{"id":"cli/breaking-changes/rules/field-same-type::top::20","title":"FIELD_SAME_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/field-same-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Удалите старое поле** в следующей major‑версии:","content":"Стратегия миграции **Удалите старое поле** в следующей major‑версии:"},{"id":"cli/breaking-changes/rules/field-same-type::wire::21","title":"FIELD_SAME_TYPE","section":"Безопасные изменения (Теоретически wire‑совместимые)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type#wire","headings":["Безопасные изменения (Теоретически wire‑совместимые)"],"excerpt":"Безопасные изменения (Теоретически wire‑совместимые) Примечание: EasyP сейчас считает ЛЮБУЮ смену типа breaking. Однако технически некоторые случаи совместимы:","content":"Безопасные изменения (Теоретически wire‑совместимые) Примечание: EasyP сейчас считает ЛЮБУЮ смену типа breaking. Однако технически некоторые случаи совместимы:"},{"id":"cli/breaking-changes/rules/field-same-type::wire::22","title":"FIELD_SAME_TYPE","section":"Безопасные изменения (Теоретически wire‑совместимые)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type#wire","headings":["Безопасные изменения (Теоретически wire‑совместимые)"],"excerpt":"Безопасные изменения (Теоретически wire‑совместимые) int32 ↔ uint32 (одно кодирование) int64 ↔ uint64 (одно кодирование) string → bytes (если все строки валидный UTF‑8)","content":"Безопасные изменения (Теоретически wire‑совместимые) int32 ↔ uint32 (одно кодирование) int64 ↔ uint64 (одно кодирование) string → bytes (если все строки валидный UTF‑8)"},{"id":"cli/breaking-changes/rules/field-same-type::wire::23","title":"FIELD_SAME_TYPE","section":"Безопасные изменения (Теоретически wire‑совместимые)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type#wire","headings":["Безопасные изменения (Теоретически wire‑совместимые)"],"excerpt":"Безопасные изменения (Теоретически wire‑совместимые) Эти исключения могут получить отдельную обработку в будущих версиях EasyP с более гибкими уровнями строгости.","content":"Безопасные изменения (Теоретически wire‑совместимые) Эти исключения могут получить отдельную обработку в будущих версиях EasyP с более гибкими уровнями строгости."},{"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":"Это правило проверяет, что ни одна инструкция import не была удалена из proto‑файла. Удаление import ломает совместимость по wire‑формату и сгенерированный код: типы из импортируемых файлов могли использоваться в текущем","content":"Это правило проверяет, что ни одна инструкция import не была удалена из proto‑файла. Удаление import ломает совместимость по wire‑формату и сгенерированный код: типы из импортируемых файлов могли использоваться в текущем файле, и их удаление делает эти типы недоступными."},{"id":"cli/breaking-changes/rules/import-no-delete::breaking::1","title":"IMPORT_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/import-no-delete::breaking::2","title":"IMPORT_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/import-no-delete::breaking::3","title":"IMPORT_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) import \"google/protobuf/timestamp.proto\"; import \"google/protobuf/duration.proto\"; import \"common/user.proto\"; import \"common/address.proto\";","content":"Плохой (Breaking) 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::breaking::4","title":"IMPORT_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) 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":"Плохой (Breaking) 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::breaking::5","title":"IMPORT_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/import-no-delete::breaking::6","title":"IMPORT_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/import-no-delete::breaking::7","title":"IMPORT_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) import \"google/protobuf/timestamp.proto\"; // import \"google/protobuf/duration.proto\"; // [!code --] Удалён import — BREAKING // import \"common/user.proto\"; // [!code --] Удалён import — BREAKING // impo","content":"Плохой (Breaking) import \"google/protobuf/timestamp.proto\"; // import \"google/protobuf/duration.proto\"; // [!code --] Удалён import — BREAKING // import \"common/user.proto\"; // [!code --] Удалён import — BREAKING // import \"common/address.proto\"; // [!code --] Удалён import — BREAKING"},{"id":"cli/breaking-changes/rules/import-no-delete::breaking::8","title":"IMPORT_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message Order { string id = 1; google.protobuf.Timestamp created_at = 2; google.protobuf.Duration processing_time = 3; // ERROR: Duration недоступен common.User customer = 4; // ERROR: User недоступен c","content":"Плохой (Breaking) message Order { string id = 1; google.protobuf.Timestamp created_at = 2; google.protobuf.Duration processing_time = 3; // ERROR: Duration недоступен common.User customer = 4; // ERROR: User недоступен common.Address shipping_address = 5; // ERROR: Address недоступен } ```"},{"id":"cli/breaking-changes/rules/import-no-delete::top::9","title":"IMPORT_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры **Сервис ломается при удалённых import:** ```proto // Before import \"google/api/annotations.proto\"; import \"google/protobuf/empty.proto\"; import \"common/auth.proto\";","content":"Дополнительные примеры **Сервис ломается при удалённых import:** ```proto // Before import \"google/api/annotations.proto\"; import \"google/protobuf/empty.proto\"; import \"common/auth.proto\";"},{"id":"cli/breaking-changes/rules/import-no-delete::top::10","title":"IMPORT_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры service OrderService { rpc GetOrder(GetOrderRequest) returns (Order) { option (google.api.http) = { get: \"/v1/orders/{id}\" }; } rpc DeleteOrder(common.AuthRequest) returns (google.protobuf.Empty); ","content":"Дополнительные примеры 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::top::11","title":"IMPORT_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры // After - BREAKING CHANGES! // import \"google/api/annotations.proto\"; // BREAKING: deleted // import \"google/protobuf/empty.proto\"; // BREAKING: deleted // import \"common/auth.proto\"; // BREAKING:","content":"Дополнительные примеры // 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::top::12","title":"IMPORT_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры service OrderService { rpc GetOrder(GetOrderRequest) returns (Order) { option (google.api.http) = { // ERROR: annotations недоступен get: \"/v1/orders/{id}\" }; } rpc DeleteOrder(common.AuthRequest) ","content":"Дополнительные примеры service OrderService { rpc GetOrder(GetOrderRequest) returns (Order) { option (google.api.http) = { // ERROR: annotations недоступен get: \"/v1/orders/{id}\" }; } rpc DeleteOrder(common.AuthRequest) returns (google.protobuf.Empty); // ERROR: типы недоступны } ```"},{"id":"cli/breaking-changes/rules/import-no-delete::top::13","title":"IMPORT_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо удаления оставьте неиспользуемые import:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо удаления оставьте неиспользуемые import:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/import-no-delete::top::14","title":"IMPORT_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/import-no-delete::top::15","title":"IMPORT_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) import \"google/protobuf/timestamp.proto\"; import \"google/protobuf/duration.proto\"; // [!code focus] // Оставляем даже если не используется import \"common/user.proto\"; // [!code focus] import \"common/","content":"Хороший (Безопасный) import \"google/protobuf/timestamp.proto\"; import \"google/protobuf/duration.proto\"; // [!code focus] // Оставляем даже если не используется import \"common/user.proto\"; // [!code focus] import \"common/address.proto\"; // [!code focus]"},{"id":"cli/breaking-changes/rules/import-no-delete::top::16","title":"IMPORT_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message Order { string id = 1; google.protobuf.Timestamp created_at = 2; // Поля, использовавшие Duration/User/Address, удалены — import оставлены } ```","content":"Хороший (Безопасный) message Order { string id = 1; google.protobuf.Timestamp created_at = 2; // Поля, использовавшие Duration/User/Address, удалены — import оставлены } ```"},{"id":"cli/breaking-changes/rules/import-no-delete::top::17","title":"IMPORT_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Или добавьте новые типы, сохранив старые import:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Или добавьте новые типы, сохранив старые import:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/import-no-delete::top::18","title":"IMPORT_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/import-no-delete::top::19","title":"IMPORT_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) import \"google/protobuf/timestamp.proto\"; import \"google/protobuf/duration.proto\"; // [!code focus] import \"common/user.proto\"; // [!code focus] import \"common/address.proto\"; // [!code focus] import","content":"Хороший (Безопасный) import \"google/protobuf/timestamp.proto\"; import \"google/protobuf/duration.proto\"; // [!code focus] import \"common/user.proto\"; // [!code focus] import \"common/address.proto\"; // [!code focus] import \"common/v2/user.proto\"; // [!code focus] // Новый import"},{"id":"cli/breaking-changes/rules/import-no-delete::top::20","title":"IMPORT_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message Order { string id = 1; google.protobuf.Timestamp created_at = 2; google.protobuf.Duration processing_time = 3 [deprecated = true]; // [!code focus] common.User customer = 4 [deprecated = true","content":"Хороший (Безопасный) message Order { string id = 1; google.protobuf.Timestamp created_at = 2; google.protobuf.Duration processing_time = 3 [deprecated = true]; // [!code focus] common.User customer = 4 [deprecated = true]; // [!code focus] common.Address shipping_address = 5 [deprecated = true]; // [!code focus] int32 processing_seconds = 6; common.v2.UserProfile customer_v2 = 7; string shipping_address_text = 8; } ```"},{"id":"cli/breaking-changes/rules/import-no-delete::top::21","title":"IMPORT_NO_DELETE","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Влияние"],"excerpt":"Влияние **Generated Code:** Типы пропадают → ошибка компиляции **Wire Format:** Сообщения с удалёнными типами не десериализуются **Field References:** Поля с этими типами становятся невалидны **Service Definitions:** RPC","content":"Влияние **Generated Code:** Типы пропадают → ошибка компиляции **Wire Format:** Сообщения с удалёнными типами не десериализуются **Field References:** Поля с этими типами становятся невалидны **Service Definitions:** RPC с типами из удалённых файлов ломаются **Options Usage:** Пользовательские опции из импортов недоступны"},{"id":"cli/breaking-changes/rules/import-no-delete::top::22","title":"IMPORT_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Код клиента ломается:**","content":"Реальный пример **Код клиента ломается:**"},{"id":"cli/breaking-changes/rules/import-no-delete::top::23","title":"IMPORT_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Серверная логика ломается:**","content":"Реальный пример **Серверная логика ломается:**"},{"id":"cli/breaking-changes/rules/import-no-delete::top::24","title":"IMPORT_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Компиляция proto ломается:**","content":"Реальный пример **Компиляция proto ломается:**"},{"id":"cli/breaking-changes/rules/import-no-delete::top::25","title":"IMPORT_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции Сохраняйте import даже если типы более не используются: Добавляйте новые import рядом со старыми: Депрецируйте поля со старыми типами постепенно: Сервер: поддерживайте оба варианта: Удаляйте import тол","content":"Стратегия миграции Сохраняйте import даже если типы более не используются: Добавляйте новые import рядом со старыми: Депрецируйте поля со старыми типами постепенно: Сервер: поддерживайте оба варианта: Удаляйте import только в следующей major‑версии после полной миграции."},{"id":"cli/breaking-changes/rules/import-no-delete::top::26","title":"IMPORT_NO_DELETE","section":"Замена зависимости","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Замена зависимости"],"excerpt":"Замена зависимости ```proto import \"old/user.proto\"; // Старый import \"new/user.proto\"; // Новый","content":"Замена зависимости ```proto import \"old/user.proto\"; // Старый import \"new/user.proto\"; // Новый"},{"id":"cli/breaking-changes/rules/import-no-delete::top::27","title":"IMPORT_NO_DELETE","section":"Замена зависимости","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Замена зависимости"],"excerpt":"Замена зависимости message Order { old.User customer = 4 [deprecated = true]; new.UserProfile customer_v2 = 5; } ```","content":"Замена зависимости message Order { old.User customer = 4 [deprecated = true]; new.UserProfile customer_v2 = 5; } ```"},{"id":"cli/breaking-changes/rules/import-no-delete::top::28","title":"IMPORT_NO_DELETE","section":"Удаление функционала","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Удаление функционала"],"excerpt":"Удаление функционала ```proto import \"feature/analytics.proto\"; // Оставить даже если поле удалено","content":"Удаление функционала ```proto import \"feature/analytics.proto\"; // Оставить даже если поле удалено"},{"id":"cli/breaking-changes/rules/import-no-delete::top::29","title":"IMPORT_NO_DELETE","section":"Удаление функционала","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Удаление функционала"],"excerpt":"Удаление функционала message Order { string id = 1; // feature.AnalyticsData analytics = 2; // Поле удалено, import остаётся } ```","content":"Удаление функционала message Order { string id = 1; // feature.AnalyticsData analytics = 2; // Поле удалено, import остаётся } ```"},{"id":"cli/breaking-changes/rules/import-no-delete::protobuf::30","title":"IMPORT_NO_DELETE","section":"Миграция версии protobuf","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#protobuf","headings":["Миграция версии protobuf"],"excerpt":"Миграция версии protobuf ```proto import \"google/protobuf/timestamp.proto\"; import \"google/protobuf/duration.proto\";","content":"Миграция версии protobuf ```proto import \"google/protobuf/timestamp.proto\"; import \"google/protobuf/duration.proto\";"},{"id":"cli/breaking-changes/rules/import-no-delete::protobuf::31","title":"IMPORT_NO_DELETE","section":"Миграция версии protobuf","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#protobuf","headings":["Миграция версии protobuf"],"excerpt":"Миграция версии protobuf message Event { google.protobuf.Timestamp timestamp = 1; int64 timestamp_millis = 2; } ```","content":"Миграция версии protobuf message Event { google.protobuf.Timestamp timestamp = 1; int64 timestamp_millis = 2; } ```"},{"id":"cli/breaking-changes/rules/import-no-delete::top::32","title":"IMPORT_NO_DELETE","section":"Упрощение сложных зависимостей","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Упрощение сложных зависимостей"],"excerpt":"Упрощение сложных зависимостей ```proto import \"complex/config.proto\";","content":"Упрощение сложных зависимостей ```proto import \"complex/config.proto\";"},{"id":"cli/breaking-changes/rules/import-no-delete::top::33","title":"IMPORT_NO_DELETE","section":"Упрощение сложных зависимостей","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Упрощение сложных зависимостей"],"excerpt":"Упрощение сложных зависимостей message Settings { complex.ConfigData config = 1 [deprecated = true]; string config_json = 2; } ```","content":"Упрощение сложных зависимостей message Settings { complex.ConfigData config = 1 [deprecated = true]; string config_json = 2; } ```"},{"id":"cli/breaking-changes/rules/import-no-delete::import-vs::34","title":"IMPORT_NO_DELETE","section":"Удаление import vs использование поля","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#import-vs","headings":["Удаление import vs использование поля"],"excerpt":"Удаление import vs использование поля","content":"Удаление import vs использование поля"},{"id":"cli/breaking-changes/rules/import-no-delete::import::35","title":"IMPORT_NO_DELETE","section":"Аудит import","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#import","headings":["Аудит import"],"excerpt":"Аудит import (Даже если не найдено — не удаляем.)","content":"Аудит 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":"Это правило проверяет, что ни одно сообщение (message) не было удалено из proto‑файлов. Удаление message ломает совместимость по wire‑формату и сгенерированный код: в существующих данных могут присутствовать экземпляры у","content":"Это правило проверяет, что ни одно сообщение (message) не было удалено из proto‑файлов. Удаление message ломает совместимость по wire‑формату и сгенерированный код: в существующих данных могут присутствовать экземпляры удалённого типа, а клиентский код зависит от сгенерированных структур и классов."},{"id":"cli/breaking-changes/rules/message-no-delete::breaking::1","title":"MESSAGE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/message-no-delete::breaking::2","title":"MESSAGE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/message-no-delete::breaking::3","title":"MESSAGE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message User { string name = 1; string email = 2; Address address = 3; }","content":"Плохой (Breaking) message User { string name = 1; string email = 2; Address address = 3; }"},{"id":"cli/breaking-changes/rules/message-no-delete::breaking::4","title":"MESSAGE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message Address { // [!code --] string street = 1; // [!code --] string city = 2; // [!code --] string country = 3; // [!code --] } // [!code --]","content":"Плохой (Breaking) message Address { // [!code --] string street = 1; // [!code --] string city = 2; // [!code --] string country = 3; // [!code --] } // [!code --]"},{"id":"cli/breaking-changes/rules/message-no-delete::breaking::5","title":"MESSAGE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message Order { string id = 1; User user = 2; } ```","content":"Плохой (Breaking) message Order { string id = 1; User user = 2; } ```"},{"id":"cli/breaking-changes/rules/message-no-delete::breaking::6","title":"MESSAGE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/message-no-delete::breaking::7","title":"MESSAGE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/message-no-delete::breaking::8","title":"MESSAGE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message User { string name = 1; string email = 2; Address address = 3; // ERROR: Address больше не существует }","content":"Плохой (Breaking) message User { string name = 1; string email = 2; Address address = 3; // ERROR: Address больше не существует }"},{"id":"cli/breaking-changes/rules/message-no-delete::breaking::9","title":"MESSAGE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) // Address удалён — BREAKING CHANGE!","content":"Плохой (Breaking) // Address удалён — BREAKING CHANGE!"},{"id":"cli/breaking-changes/rules/message-no-delete::breaking::10","title":"MESSAGE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message Order { string id = 1; User user = 2; } ```","content":"Плохой (Breaking) message Order { string id = 1; User user = 2; } ```"},{"id":"cli/breaking-changes/rules/message-no-delete::top::11","title":"MESSAGE_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры **Удаление вложенного сообщения:**","content":"Дополнительные примеры **Удаление вложенного сообщения:**"},{"id":"cli/breaking-changes/rules/message-no-delete::top::12","title":"MESSAGE_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры ```proto // Before message User { string name = 1; Profile profile = 2; message Profile { // [!code --] string bio = 1; // [!code --] string avatar_url = 2; // [!code --] } // [!code --] }","content":"Дополнительные примеры ```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::top::13","title":"MESSAGE_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры // After - BREAKING CHANGE! message User { string name = 1; Profile profile = 2; // ERROR: Profile удалён // Вложенное сообщение Profile удалено } ```","content":"Дополнительные примеры // After - BREAKING CHANGE! message User { string name = 1; Profile profile = 2; // ERROR: Profile удалён // Вложенное сообщение Profile удалено } ```"},{"id":"cli/breaking-changes/rules/message-no-delete::top::14","title":"MESSAGE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо удаления — пометить как deprecated:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо удаления — пометить как deprecated:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/message-no-delete::top::15","title":"MESSAGE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/message-no-delete::top::16","title":"MESSAGE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message User { string name = 1; string email = 2; Address address = 3 [deprecated = true]; // [!code focus] }","content":"Хороший (Безопасный) message User { string name = 1; string email = 2; Address address = 3 [deprecated = true]; // [!code focus] }"},{"id":"cli/breaking-changes/rules/message-no-delete::top::17","title":"MESSAGE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message Address { option deprecated = true; // [!code focus] string street = 1; string city = 2; string country = 3; }","content":"Хороший (Безопасный) message Address { option deprecated = true; // [!code focus] string street = 1; string city = 2; string country = 3; }"},{"id":"cli/breaking-changes/rules/message-no-delete::top::18","title":"MESSAGE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message Order { string id = 1; User user = 2; } ```","content":"Хороший (Безопасный) message Order { string id = 1; User user = 2; } ```"},{"id":"cli/breaking-changes/rules/message-no-delete::top::19","title":"MESSAGE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Или заменить новой версией сообщения:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Или заменить новой версией сообщения:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/message-no-delete::top::20","title":"MESSAGE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/message-no-delete::top::21","title":"MESSAGE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message User { string name = 1; string email = 2; Address address = 3 [deprecated = true]; // [!code focus] // Старое поле AddressV2 address_v2 = 4; // [!code focus] // Новая улучшенная структура }","content":"Хороший (Безопасный) message User { string name = 1; string email = 2; Address address = 3 [deprecated = true]; // [!code focus] // Старое поле AddressV2 address_v2 = 4; // [!code focus] // Новая улучшенная структура }"},{"id":"cli/breaking-changes/rules/message-no-delete::top::22","title":"MESSAGE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message Address { option deprecated = true; // [!code focus] string street = 1; string city = 2; string country = 3; }","content":"Хороший (Безопасный) message Address { option deprecated = true; // [!code focus] string street = 1; string city = 2; string country = 3; }"},{"id":"cli/breaking-changes/rules/message-no-delete::top::23","title":"MESSAGE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) 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 c","content":"Хороший (Безопасный) 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::top::24","title":"MESSAGE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message Order { string id = 1; User user = 2; } ```","content":"Хороший (Безопасный) message Order { string id = 1; User user = 2; } ```"},{"id":"cli/breaking-changes/rules/message-no-delete::top::25","title":"MESSAGE_NO_DELETE","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Влияние"],"excerpt":"Влияние **Wire Format:** Старые данные с удалённым сообщением не десериализуются **Generated Code:** Классы/структуры удаляются — компиляция клиента ломается **Field References:** Поля, использующие удалённый тип, станов","content":"Влияние **Wire Format:** Старые данные с удалённым сообщением не десериализуются **Generated Code:** Классы/структуры удаляются — компиляция клиента ломается **Field References:** Поля, использующие удалённый тип, становятся невалидны **Nested Dependencies:** Все сообщения, ссылающиеся на удалённый тип, ломаются"},{"id":"cli/breaking-changes/rules/message-no-delete::top::26","title":"MESSAGE_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Код клиента ломается:** ```go // Before user := &myapi.User{ Name: \"John Doe\", Email: \"john@example.com\", Address: &myapi.Address{ // ERROR после удаления Street: \"123 Main St\", City: \"New York\", Countr","content":"Реальный пример **Код клиента ломается:** ```go // Before user := &myapi.User{ Name: \"John Doe\", Email: \"john@example.com\", Address: &myapi.Address{ // ERROR после удаления Street: \"123 Main St\", City: \"New York\", Country: \"USA\", }, }"},{"id":"cli/breaking-changes/rules/message-no-delete::top::27","title":"MESSAGE_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример // undefined: myapi.Address ```","content":"Реальный пример // undefined: myapi.Address ```"},{"id":"cli/breaking-changes/rules/message-no-delete::top::28","title":"MESSAGE_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Старые данные становятся нечитаемыми:**","content":"Реальный пример **Старые данные становятся нечитаемыми:**"},{"id":"cli/breaking-changes/rules/message-no-delete::top::29","title":"MESSAGE_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Пометить как deprecated:** **Пометить поля, использующие его:** **Добавить замену при необходимости:** **Удалить в следующей major‑версии после периода миграции**","content":"Стратегия миграции **Пометить как deprecated:** **Пометить поля, использующие его:** **Добавить замену при необходимости:** **Удалить в следующей major‑версии после периода миграции**"},{"id":"cli/breaking-changes/rules/message-no-delete::top::30","title":"MESSAGE_NO_DELETE","section":"Рефакторинг структуры","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Рефакторинг структуры"],"excerpt":"Рефакторинг структуры ```proto message UserInfo { option deprecated = true; string name = 1; string email = 2; }","content":"Рефакторинг структуры ```proto message UserInfo { option deprecated = true; string name = 1; string email = 2; }"},{"id":"cli/breaking-changes/rules/message-no-delete::top::31","title":"MESSAGE_NO_DELETE","section":"Рефакторинг структуры","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Рефакторинг структуры"],"excerpt":"Рефакторинг структуры message UserProfile { string full_name = 1; string email_address = 2; string phone = 3; } ```","content":"Рефакторинг структуры message UserProfile { string full_name = 1; string email_address = 2; string phone = 3; } ```"},{"id":"cli/breaking-changes/rules/message-no-delete::top::32","title":"MESSAGE_NO_DELETE","section":"Удаление «неиспользуемых» сообщений","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Удаление «неиспользуемых» сообщений"],"excerpt":"Удаление «неиспользуемых» сообщений","content":"Удаление «неиспользуемых» сообщений"},{"id":"cli/breaking-changes/rules/message-no-delete::top::33","title":"MESSAGE_NO_DELETE","section":"Миграция версии","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Миграция версии"],"excerpt":"Миграция версии ```proto package myapi.v2;","content":"Миграция версии ```proto package myapi.v2;"},{"id":"cli/breaking-changes/rules/message-no-delete::top::34","title":"MESSAGE_NO_DELETE","section":"Миграция версии","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Миграция версии"],"excerpt":"Миграция версии message User { // Новая структура без устаревших ссылок } ```","content":"Миграция версии message User { // Новая структура без устаревших ссылок } ```"},{"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":"Правило проверяет, что ни одно поле внутри oneof группы не было удалено. Удаление поля из oneof ломает совместимость по wire‑формату и сгенерированный код: в сохранённых данных может присутствовать выбранный вариант, а к","content":"Правило проверяет, что ни одно поле внутри oneof группы не было удалено. Удаление поля из oneof ломает совместимость по wire‑формату и сгенерированный код: в сохранённых данных может присутствовать выбранный вариант, а клиентский код опирается на сгенерированные типы‑обёртки и методы доступа."},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::breaking::1","title":"ONEOF_FIELD_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::breaking::2","title":"ONEOF_FIELD_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::breaking::3","title":"ONEOF_FIELD_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message LoginRequest { string username = 1; oneof credentials { string password = 2; string api_key = 3; string oauth_token = 4; string certificate = 5; } }","content":"Плохой (Breaking) 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::breaking::4","title":"ONEOF_FIELD_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message SearchQuery { oneof filter { string text = 1; int32 user_id = 2; string category = 3; DateRange date_range = 4; } } ```","content":"Плохой (Breaking) 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::breaking::5","title":"ONEOF_FIELD_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::breaking::6","title":"ONEOF_FIELD_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::breaking::7","title":"ONEOF_FIELD_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message LoginRequest { string username = 1; oneof credentials { string password = 2; string api_key = 3; // string oauth_token = 4; // [!code --] Удалено поле oneof — BREAKING! // string certificate = 5","content":"Плохой (Breaking) message LoginRequest { string username = 1; oneof credentials { string password = 2; string api_key = 3; // string oauth_token = 4; // [!code --] Удалено поле oneof — BREAKING! // string certificate = 5; // [!code --] Удалено поле oneof — BREAKING! } }"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::breaking::8","title":"ONEOF_FIELD_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message SearchQuery { oneof filter { string text = 1; int32 user_id = 2; // string category = 3; // [!code --] Удалено поле oneof — BREAKING! // DateRange date_range = 4; // [!code --] Удалено поле oneo","content":"Плохой (Breaking) message SearchQuery { oneof filter { string text = 1; int32 user_id = 2; // string category = 3; // [!code --] Удалено поле oneof — BREAKING! // DateRange date_range = 4; // [!code --] Удалено поле oneof — BREAKING! } } ```"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::9","title":"ONEOF_FIELD_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры **Удаление вложенных oneof полей:** ```proto // Before message PaymentRequest { string order_id = 1; oneof payment_method { CreditCardPayment credit_card = 2; BankTransferPayment bank_transfer = 3;","content":"Дополнительные примеры **Удаление вложенных oneof полей:** ```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::top::10","title":"ONEOF_FIELD_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры // After - BREAKING CHANGES! message PaymentRequest { string order_id = 1; oneof payment_method { CreditCardPayment credit_card = 2; BankTransferPayment bank_transfer = 3; // CryptoPayment crypto =","content":"Дополнительные примеры // 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::top::11","title":"ONEOF_FIELD_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо удаления — пометить поля deprecated:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо удаления — пометить поля deprecated:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::12","title":"ONEOF_FIELD_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::13","title":"ONEOF_FIELD_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) 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 [deprecate","content":"Хороший (Безопасный) 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::top::14","title":"ONEOF_FIELD_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) 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":"Хороший (Безопасный) 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::top::15","title":"ONEOF_FIELD_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Или добавить новые поля, оставив старые:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Или добавить новые поля, оставив старые:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::16","title":"ONEOF_FIELD_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::17","title":"ONEOF_FIELD_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message LoginRequest { string username = 1; oneof credentials { string password = 2; string api_key = 3; string oauth_token = 4 [deprecated = true]; // [!code focus] // Старое поле string certificate","content":"Хороший (Безопасный) 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] OAuthCredentials oauth_v2 = 6; // [!code focus] // Новый структурированный вариант CertificateCredentials cert_v2 = 7; // [!code focus] } } ```"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::18","title":"ONEOF_FIELD_NO_DELETE","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Влияние"],"excerpt":"Влияние **Wire Format:** Данные, содержащие удалённый вариант, не десериализуются корректно **Generated Code:** Удаляются типы‑обёртки и accessor методы — компиляция клиентов ломается **Type Safety:** Логика switch по ти","content":"Влияние **Wire Format:** Данные, содержащие удалённый вариант, не десериализуются корректно **Generated Code:** Удаляются типы‑обёртки и accessor методы — компиляция клиентов ломается **Type Safety:** Логика switch по типам oneof разваливается **Business Logic:** Код, ожидающий конкретный вариант, перестаёт работать"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::19","title":"ONEOF_FIELD_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Код клиента ломается:** ```go // Before loginReq := &myapi.LoginRequest{ Username: \"user123\", }","content":"Реальный пример **Код клиента ломается:** ```go // Before loginReq := &myapi.LoginRequest{ Username: \"user123\", }"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::20","title":"ONEOF_FIELD_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример loginReq.Credentials = &myapi.LoginRequest_OauthToken{ OauthToken: \"token123\", // ERROR после удаления поля }","content":"Реальный пример loginReq.Credentials = &myapi.LoginRequest_OauthToken{ OauthToken: \"token123\", // ERROR после удаления поля }"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::21","title":"ONEOF_FIELD_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример switch cred := loginReq.Credentials.(type) { case *myapi.LoginRequest_Password: return authenticatePassword(cred.Password) case *myapi.LoginRequest_OauthToken: // ERROR: тип удалён return authenticateOAut","content":"Реальный пример switch cred := loginReq.Credentials.(type) { case *myapi.LoginRequest_Password: return authenticatePassword(cred.Password) case *myapi.LoginRequest_OauthToken: // ERROR: тип удалён return authenticateOAuth(cred.OauthToken) case *myapi.LoginRequest_Certificate: // ERROR: тип удалён return authenticateCert(cred.Certificate) default: return errors.New(\"unsupported credential type\") } // undefined: myapi.LoginRequest_OauthToken // undefined: myapi.LoginRequest_Certificate ```"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::22","title":"ONEOF_FIELD_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Серверная логика ломается:**","content":"Реальный пример **Серверная логика ломается:**"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::23","title":"ONEOF_FIELD_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Старые данные становятся нечитаемыми:**","content":"Реальный пример **Старые данные становятся нечитаемыми:**"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::24","title":"ONEOF_FIELD_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Депрецируйте сначала:** **Добавьте новые структурированные поля:** **Сервер: поддерживайте оба варианта:** **Мигрируйте клиентов на новое поле:** **Зарезервируйте номера удалённых полей в следующей m","content":"Стратегия миграции **Депрецируйте сначала:** **Добавьте новые структурированные поля:** **Сервер: поддерживайте оба варианта:** **Мигрируйте клиентов на новое поле:** **Зарезервируйте номера удалённых полей в следующей major‑версии:**"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::25","title":"ONEOF_FIELD_NO_DELETE","section":"Удаление неподдерживаемых методов аутентификации","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Удаление неподдерживаемых методов аутентификации"],"excerpt":"Удаление неподдерживаемых методов аутентификации","content":"Удаление неподдерживаемых методов аутентификации"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::26","title":"ONEOF_FIELD_NO_DELETE","section":"Изменения бизнес‑логики платежей","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Изменения бизнес‑логики платежей"],"excerpt":"Изменения бизнес‑логики платежей","content":"Изменения бизнес‑логики платежей"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::oneof-field-deletion-vs::27","title":"ONEOF_FIELD_NO_DELETE","section":"OneOf Field Deletion vs обычное удаление","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#oneof-field-deletion-vs","headings":["OneOf Field Deletion vs обычное удаление"],"excerpt":"OneOf Field Deletion vs обычное удаление","content":"OneOf Field Deletion vs обычное удаление"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::28","title":"ONEOF_FIELD_NO_DELETE","section":"Отличия от удаления обычного поля","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Отличия от удаления обычного поля"],"excerpt":"Отличия от удаления обычного поля ```proto message User { string name = 1; // string email = 2; // BREAKING: обычное поле }","content":"Отличия от удаления обычного поля ```proto message User { string name = 1; // string email = 2; // BREAKING: обычное поле }"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::29","title":"ONEOF_FIELD_NO_DELETE","section":"Отличия от удаления обычного поля","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Отличия от удаления обычного поля"],"excerpt":"Отличия от удаления обычного поля message User { oneof contact { string email = 1; // string phone = 2; // BREAKING: поле в oneof } } ```","content":"Отличия от удаления обычного поля message User { oneof contact { string email = 1; // string phone = 2; // BREAKING: поле в oneof } } ```"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::30","title":"ONEOF_FIELD_NO_DELETE","section":"Влияние на сгенерированный код","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Влияние на сгенерированный код"],"excerpt":"Влияние на сгенерированный код ```go // Обычное поле: удаляется простой геттер // user.GetEmail()","content":"Влияние на сгенерированный код ```go // Обычное поле: удаляется простой геттер // user.GetEmail()"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::31","title":"ONEOF_FIELD_NO_DELETE","section":"Влияние на сгенерированный код","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Влияние на сгенерированный код"],"excerpt":"Влияние на сгенерированный код // Поле в oneof: пропадает тип-обёртка, кейсы switch ломаются // *LoginRequest_OauthToken ```","content":"Влияние на сгенерированный код // Поле в oneof: пропадает тип-обёртка, кейсы switch ломаются // *LoginRequest_OauthToken ```"},{"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":"Это правило проверяет, что тип поля внутри oneof НЕ меняется. Смена типа любого варианта oneof — несовместимое (breaking) изменение: существующие данные сериализованы с прежним типом, а клиентский код ожидает конкретные ","content":"Это правило проверяет, что тип поля внутри oneof НЕ меняется. Смена типа любого варианта oneof — несовместимое (breaking) изменение: существующие данные сериализованы с прежним типом, а клиентский код ожидает конкретные типы-обёртки и методы доступа, сгенерированные для каждого варианта."},{"id":"cli/breaking-changes/rules/oneof-field-same-type::breaking::1","title":"ONEOF_FIELD_SAME_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::breaking::2","title":"ONEOF_FIELD_SAME_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::breaking::3","title":"ONEOF_FIELD_SAME_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message SearchRequest { string query = 1; oneof filter { string category = 2; int32 user_id = 3; bool is_premium = 4; DateRange date_range = 5; } }","content":"Плохой (Breaking) 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::breaking::4","title":"ONEOF_FIELD_SAME_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message NotificationSettings { oneof delivery { string email = 1; int64 phone_number = 2; WebhookConfig webhook = 3; } } ```","content":"Плохой (Breaking) message NotificationSettings { oneof delivery { string email = 1; int64 phone_number = 2; WebhookConfig webhook = 3; } } ```"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::breaking::5","title":"ONEOF_FIELD_SAME_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::breaking::6","title":"ONEOF_FIELD_SAME_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::breaking::7","title":"ONEOF_FIELD_SAME_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message SearchRequest { string query = 1; oneof filter { int32 category = 2; // [!code --] Было string -> стало int32 (BREAKING) string user_id = 3; // [!code --] Было int32 -> стало string (BREAKING) s","content":"Плохой (Breaking) message SearchRequest { string query = 1; oneof filter { int32 category = 2; // [!code --] Было string -> стало int32 (BREAKING) string user_id = 3; // [!code --] Было int32 -> стало string (BREAKING) string is_premium = 4; // [!code --] Было bool -> стало string (BREAKING) string date_range = 5; // [!code --] Было DateRange -> стало string (BREAKING) } }"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::breaking::8","title":"ONEOF_FIELD_SAME_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message NotificationSettings { oneof delivery { EmailConfig email = 1; // [!code --] Было string -> стало EmailConfig (BREAKING) string phone_number = 2; // [!code --] Было int64 -> стало string (BREAKI","content":"Плохой (Breaking) message NotificationSettings { oneof delivery { EmailConfig email = 1; // [!code --] Было string -> стало EmailConfig (BREAKING) string phone_number = 2; // [!code --] Было int64 -> стало string (BREAKING) string webhook = 3; // [!code --] Было WebhookConfig -> стало string (BREAKING) } } ```"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::9","title":"ONEOF_FIELD_SAME_TYPE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры **Комплексные изменения типов:** ```proto // Before message PaymentRequest { oneof payment_info { CreditCardInfo credit_card = 1; BankAccountInfo bank_account = 2; string paypal_email = 3; CryptoWa","content":"Дополнительные примеры **Комплексные изменения типов:** ```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::top::10","title":"ONEOF_FIELD_SAME_TYPE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры // After - ВСЁ BREAKING message PaymentRequest { oneof payment_info { string credit_card = 1; // CreditCardInfo -> string PayPalInfo bank_account = 2; // BankAccountInfo -> PayPalInfo PayPalInfo pa","content":"Дополнительные примеры // After - ВСЁ BREAKING message PaymentRequest { oneof payment_info { string credit_card = 1; // CreditCardInfo -> string PayPalInfo bank_account = 2; // BankAccountInfo -> PayPalInfo PayPalInfo paypal_email = 3; // string -> PayPalInfo string crypto = 4; // CryptoWalletInfo -> string } } ```"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::11","title":"ONEOF_FIELD_SAME_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо смены типа — добавьте новое поле в тот же oneof:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо смены типа — добавьте новое поле в тот же oneof:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::12","title":"ONEOF_FIELD_SAME_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::13","title":"ONEOF_FIELD_SAME_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message SearchRequest { string query = 1; oneof filter { string category = 2 [deprecated = true]; // Старый тип int32 user_id = 3 [deprecated = true]; bool is_premium = 4 [deprecated = true]; DateRan","content":"Хороший (Безопасный) message SearchRequest { string query = 1; oneof filter { string category = 2 [deprecated = true]; // Старый тип int32 user_id = 3 [deprecated = true]; bool is_premium = 4 [deprecated = true]; DateRange date_range = 5 [deprecated = true]; int32 category_id = 6; // Новая версия string user_identifier = 7; string premium_status = 8; string date_filter = 9; } } ```"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::14","title":"ONEOF_FIELD_SAME_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Или создайте новый oneof:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Или создайте новый oneof:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::15","title":"ONEOF_FIELD_SAME_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::16","title":"ONEOF_FIELD_SAME_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message SearchRequest { string query = 1; oneof filter { option deprecated = true; string category = 2 [deprecated = true]; int32 user_id = 3 [deprecated = true]; bool is_premium = 4 [deprecated = tr","content":"Хороший (Безопасный) message SearchRequest { string query = 1; oneof filter { option deprecated = true; string category = 2 [deprecated = true]; int32 user_id = 3 [deprecated = true]; bool is_premium = 4 [deprecated = true]; DateRange date_range = 5 [deprecated = true]; } oneof filter_v2 { int32 category_id = 6; string user_identifier = 7; PremiumFilter premium_filter = 8; TimeFilter time_filter = 9; } } ```"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::17","title":"ONEOF_FIELD_SAME_TYPE","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Влияние"],"excerpt":"Влияние **Wire Format:** Старые бинарные данные не читаются корректно **Generated Code:** Меняются типы-обёртки, код клиента не компилируется **Type Safety:** switch по варианту oneof ломается **Runtime Errors:** Ошибки ","content":"Влияние **Wire Format:** Старые бинарные данные не читаются корректно **Generated Code:** Меняются типы-обёртки, код клиента не компилируется **Type Safety:** switch по варианту oneof ломается **Runtime Errors:** Ошибки десериализации и логики при несовпадении типов"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::18","title":"ONEOF_FIELD_SAME_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Реальный пример"],"excerpt":"Реальный пример **Ломается клиентский код:** ```go // Before searchReq := &myapi.SearchRequest{ Query: \"golang jobs\", }","content":"Реальный пример **Ломается клиентский код:** ```go // Before searchReq := &myapi.SearchRequest{ Query: \"golang jobs\", }"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::19","title":"ONEOF_FIELD_SAME_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Реальный пример"],"excerpt":"Реальный пример // Устанавливаем вариант oneof searchReq.Filter = &myapi.SearchRequest_Category{ Category: \"engineering\", }","content":"Реальный пример // Устанавливаем вариант oneof searchReq.Filter = &myapi.SearchRequest_Category{ Category: \"engineering\", }"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::20","title":"ONEOF_FIELD_SAME_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Реальный пример"],"excerpt":"Реальный пример // Обработка вариантов switch filter := searchReq.Filter.(type) { case *myapi.SearchRequest_Category: return searchByCategory(filter.Category) case *myapi.SearchRequest_UserId: return searchByUserId(filte","content":"Реальный пример // Обработка вариантов switch filter := searchReq.Filter.(type) { case *myapi.SearchRequest_Category: return searchByCategory(filter.Category) case *myapi.SearchRequest_UserId: return searchByUserId(filter.UserId) default: return errors.New(\"unsupported filter\") }"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::21","title":"ONEOF_FIELD_SAME_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Реальный пример"],"excerpt":"Реальный пример // After — тип Category стал int32 searchReq.Filter = &myapi.SearchRequest_Category{ Category: \"engineering\", // ERROR }","content":"Реальный пример // After — тип Category стал int32 searchReq.Filter = &myapi.SearchRequest_Category{ Category: \"engineering\", // ERROR }"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::22","title":"ONEOF_FIELD_SAME_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Реальный пример"],"excerpt":"Реальный пример switch filter := searchReq.Filter.(type) { case *myapi.SearchRequest_Category: return searchByCategory(filter.Category) // ERROR case *myapi.SearchRequest_UserId: return searchByUserId(filter.UserId) // E","content":"Реальный пример switch filter := searchReq.Filter.(type) { case *myapi.SearchRequest_Category: return searchByCategory(filter.Category) // ERROR case *myapi.SearchRequest_UserId: return searchByUserId(filter.UserId) // ERROR: UserId теперь string } ```"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::23","title":"ONEOF_FIELD_SAME_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Реальный пример"],"excerpt":"Реальный пример **Ломается серверная логика:** ```go // Before func handleSearchFilter(req *SearchRequest) (*SearchResult, error) { switch filter := req.Filter.(type) { case *SearchRequest_Category: return searchDatabase","content":"Реальный пример **Ломается серверная логика:** ```go // Before func handleSearchFilter(req *SearchRequest) (*SearchResult, error) { switch filter := req.Filter.(type) { case *SearchRequest_Category: return searchDatabase(\"category\", filter.Category), nil case *SearchRequest_UserId: return searchDatabase(\"user_id\", strconv.Itoa(int(filter.UserId))), nil default: return nil, errors.New(\"no filter specified\") } }"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::24","title":"ONEOF_FIELD_SAME_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Реальный пример"],"excerpt":"Реальный пример // After — несовпадения типов func handleSearchFilter(req *SearchRequest) (*SearchResult, error) { switch filter := req.Filter.(type) { case *SearchRequest_Category: // filter.Category теперь int32, а код","content":"Реальный пример // After — несовпадения типов func handleSearchFilter(req *SearchRequest) (*SearchResult, error) { switch filter := req.Filter.(type) { case *SearchRequest_Category: // filter.Category теперь int32, а код ожидал string return searchDatabase(\"category\", filter.Category), nil // ERROR case *SearchRequest_UserId: userIdStr := filter.UserId // string вместо int32 userId, _ := strconv.Atoi(userIdStr) return searchDatabase(\"user_id\", strconv.Itoa(userId)), nil } } ```"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::25","title":"ONEOF_FIELD_SAME_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Реальный пример"],"excerpt":"Реальный пример **Порча данных:**","content":"Реальный пример **Порча данных:**"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::26","title":"ONEOF_FIELD_SAME_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции Добавьте новое поле: Сервер поддерживает оба: Клиенты переходят на category_id. Скрипты миграции преобразуют старые данные. В следующей major‑версии:","content":"Стратегия миграции Добавьте новое поле: Сервер поддерживает оба: Клиенты переходят на category_id. Скрипты миграции преобразуют старые данные. В следующей major‑версии:"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::27","title":"ONEOF_FIELD_SAME_TYPE","section":"Переход к структурированным типам","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Переход к структурированным типам"],"excerpt":"Переход к структурированным типам","content":"Переход к структурированным типам"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::28","title":"ONEOF_FIELD_SAME_TYPE","section":"Матрица совместимости","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Матрица совместимости"],"excerpt":"Матрица совместимости From Type To Type Результат ----------- --------- ----------- string int32/int64 ❌ BREAKING int32 string ❌ BREAKING bool string ❌ BREAKING message string ❌ BREAKING string message ❌ BREAKING enum in","content":"Матрица совместимости From Type To Type Результат ----------- --------- ----------- 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::top::29","title":"ONEOF_FIELD_SAME_TYPE","section":"Влияние на сгенерированный код","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Влияние на сгенерированный код"],"excerpt":"Влияние на сгенерированный код","content":"Влияние на сгенерированный код"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::30","title":"ONEOF_FIELD_SAME_TYPE","section":"Валидация","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Валидация"],"excerpt":"Валидация **После (сломано):**","content":"Валидация **После (сломано):**"},{"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":"Это правило проверяет, что ни один oneof блок не был удалён из сообщений. Удаление oneof ломает совместимость по wire‑формату и сгенерированный код: существующие данные могут содержать ранее выбранный вариант, а клиентск","content":"Это правило проверяет, что ни один oneof блок не был удалён из сообщений. Удаление oneof ломает совместимость по wire‑формату и сгенерированный код: существующие данные могут содержать ранее выбранный вариант, а клиентский код зависит от типов-обёрток и методов доступа, генерируемых для oneof."},{"id":"cli/breaking-changes/rules/oneof-no-delete::breaking::1","title":"ONEOF_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-no-delete::breaking::2","title":"ONEOF_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/oneof-no-delete::breaking::3","title":"ONEOF_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message LoginRequest { string username = 1; oneof credentials { string password = 2; string api_key = 3; string oauth_token = 4; } }","content":"Плохой (Breaking) 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::breaking::4","title":"ONEOF_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message PaymentMethod { // [!code --] oneof method { // [!code --] CreditCard credit_card = 1; // [!code --] BankAccount bank_account = 2; // [!code --] PayPal paypal = 3; // [!code --] } // [!code --] ","content":"Плохой (Breaking) 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::breaking::5","title":"ONEOF_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message Order { string id = 1; PaymentMethod payment = 2; } ```","content":"Плохой (Breaking) message Order { string id = 1; PaymentMethod payment = 2; } ```"},{"id":"cli/breaking-changes/rules/oneof-no-delete::breaking::6","title":"ONEOF_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-no-delete::breaking::7","title":"ONEOF_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/oneof-no-delete::breaking::8","title":"ONEOF_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message LoginRequest { string username = 1; // credentials oneof удалён — BREAKING CHANGE! string password = 2; // Теперь обычные поля string api_key = 3; // Потеряна взаимная исключаемость string oauth","content":"Плохой (Breaking) message LoginRequest { string username = 1; // credentials oneof удалён — BREAKING CHANGE! string password = 2; // Теперь обычные поля string api_key = 3; // Потеряна взаимная исключаемость string oauth_token = 4; }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::breaking::9","title":"ONEOF_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message PaymentMethod { // method oneof удалён — BREAKING CHANGE! CreditCard credit_card = 1; // Теперь можно установить все поля одновременно BankAccount bank_account = 2; PayPal paypal = 3; }","content":"Плохой (Breaking) message PaymentMethod { // method oneof удалён — BREAKING CHANGE! CreditCard credit_card = 1; // Теперь можно установить все поля одновременно BankAccount bank_account = 2; PayPal paypal = 3; }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::breaking::10","title":"ONEOF_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message Order { string id = 1; PaymentMethod payment = 2; } ```","content":"Плохой (Breaking) message Order { string id = 1; PaymentMethod payment = 2; } ```"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::11","title":"ONEOF_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры **Удаление вложенного oneof:** ```proto // Before message UserProfile { string name = 1; message ContactInfo { oneof contact_method { // [!code --] string email = 1; // [!code --] string phone = 2;","content":"Дополнительные примеры **Удаление вложенного oneof:** ```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::top::12","title":"ONEOF_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры // After - BREAKING CHANGE! message UserProfile { string name = 1; message ContactInfo { // contact_method oneof удалён string email = 1; // Больше не эксклюзивно string phone = 2; // Можно задать ","content":"Дополнительные примеры // After - BREAKING CHANGE! message UserProfile { string name = 1; message ContactInfo { // contact_method oneof удалён string email = 1; // Больше не эксклюзивно string phone = 2; // Можно задать всё сразу string slack_id = 3; } ContactInfo contact = 2; } ```"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::13","title":"ONEOF_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо удаления — депрецируйте oneof:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо удаления — депрецируйте oneof:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::14","title":"ONEOF_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::15","title":"ONEOF_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message LoginRequest { string username = 1; oneof credentials { option deprecated = true; // [!code focus] string password = 2 [deprecated = true]; // [!code focus] string api_key = 3 [deprecated = t","content":"Хороший (Безопасный) 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::top::16","title":"ONEOF_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message PaymentMethod { oneof method { option deprecated = true; // [!code focus] CreditCard credit_card = 1 [deprecated = true]; // [!code focus] BankAccount bank_account = 2 [deprecated = true]; //","content":"Хороший (Безопасный) 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::top::17","title":"ONEOF_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Или заменить новой структурой:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Или заменить новой структурой:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::18","title":"ONEOF_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::19","title":"ONEOF_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message LoginRequest { string username = 1; oneof credentials { option deprecated = true; // [!code focus] // Старый oneof string password = 2 [deprecated = true]; // [!code focus] string api_key = 3","content":"Хороший (Безопасный) message LoginRequest { string username = 1; oneof credentials { option deprecated = true; // [!code focus] // Старый 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] // Новый дизайн 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::top::20","title":"ONEOF_NO_DELETE","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Влияние"],"excerpt":"Влияние **Wire Format:** Теряются семантика взаимной исключаемости — больше одного поля может быть установлено **Generated Code:** Удаляются типы-обёртки и accessor методы — код клиента не компилируется **Business Logic:","content":"Влияние **Wire Format:** Теряются семантика взаимной исключаемости — больше одного поля может быть установлено **Generated Code:** Удаляются типы-обёртки и accessor методы — код клиента не компилируется **Business Logic:** Нарушаются инварианты «только один из» **Validation:** Логика проверок должна быть переписана вручную"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::21","title":"ONEOF_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Код клиента ломается:** ```go // Before - oneOf даёт взаимную исключаемость loginReq := &myapi.LoginRequest{ Username: \"user123\", }","content":"Реальный пример **Код клиента ломается:** ```go // Before - oneOf даёт взаимную исключаемость loginReq := &myapi.LoginRequest{ Username: \"user123\", }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::22","title":"ONEOF_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример loginReq.Credentials = &myapi.LoginRequest_Password{ Password: \"secret123\", }","content":"Реальный пример loginReq.Credentials = &myapi.LoginRequest_Password{ Password: \"secret123\", }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::23","title":"ONEOF_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример switch cred := loginReq.Credentials.(type) { case *myapi.LoginRequest_Password: // ERROR после удаления return authenticatePassword(cred.Password) case *myapi.LoginRequest_ApiKey: // ERROR после удаления ","content":"Реальный пример switch cred := loginReq.Credentials.(type) { case *myapi.LoginRequest_Password: // ERROR после удаления return authenticatePassword(cred.Password) case *myapi.LoginRequest_ApiKey: // ERROR после удаления return authenticateApiKey(cred.ApiKey) default: return errors.New(\"no credentials provided\") }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::24","title":"ONEOF_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример // Compilation errors: // undefined: myapi.LoginRequest_Password // undefined field: loginReq.Credentials ```","content":"Реальный пример // Compilation errors: // undefined: myapi.LoginRequest_Password // undefined field: loginReq.Credentials ```"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::25","title":"ONEOF_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Валидация на сервере ломается:** ```go // Before func validateLoginRequest(req *LoginRequest) error { if req.Credentials == nil { return errors.New(\"credentials required\") } switch req.Credentials.(type","content":"Реальный пример **Валидация на сервере ломается:** ```go // Before func validateLoginRequest(req *LoginRequest) error { if req.Credentials == nil { return errors.New(\"credentials required\") } 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::top::26","title":"ONEOF_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример // After func validateLoginRequest(req *LoginRequest) error { credCount := 0 if req.Password != \"\" { credCount++ } if req.ApiKey != \"\" { credCount++ } if req.OauthToken != \"\" { credCount++ }","content":"Реальный пример // After func validateLoginRequest(req *LoginRequest) error { credCount := 0 if req.Password != \"\" { credCount++ } if req.ApiKey != \"\" { credCount++ } if req.OauthToken != \"\" { credCount++ }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::27","title":"ONEOF_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример if credCount == 0 { return errors.New(\"no credentials provided\") } if credCount > 1 { return errors.New(\"multiple credentials provided\") }","content":"Реальный пример if credCount == 0 { return errors.New(\"no credentials provided\") } if credCount > 1 { return errors.New(\"multiple credentials provided\") }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::28","title":"ONEOF_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример if req.Password != \"\" { return validatePassword(req.Password) } // Дополнительные проверки вручную... return nil } ```","content":"Реальный пример if req.Password != \"\" { return validatePassword(req.Password) } // Дополнительные проверки вручную... return nil } ```"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::29","title":"ONEOF_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Проблемы бизнес‑логики:** ```go // Before payment := &PaymentMethod{ Method: &PaymentMethod_CreditCard{ CreditCard: &CreditCard{Number: \"1234\"}, }, }","content":"Реальный пример **Проблемы бизнес‑логики:** ```go // Before payment := &PaymentMethod{ Method: &PaymentMethod_CreditCard{ CreditCard: &CreditCard{Number: \"1234\"}, }, }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::30","title":"ONEOF_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример // After — можно задать несколько способов сразу payment := &PaymentMethod{ CreditCard: &CreditCard{Number: \"1234\"}, BankAccount: &BankAccount{Number: \"5678\"}, // Ломает бизнес-логику } ```","content":"Реальный пример // After — можно задать несколько способов сразу payment := &PaymentMethod{ CreditCard: &CreditCard{Number: \"1234\"}, BankAccount: &BankAccount{Number: \"5678\"}, // Ломает бизнес-логику } ```"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::31","title":"ONEOF_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Депрецируйте старый oneof и его поля:**","content":"Стратегия миграции **Депрецируйте старый oneof и его поля:**"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::32","title":"ONEOF_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Создайте новый блок при необходимости:**","content":"Стратегия миграции **Создайте новый блок при необходимости:**"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::33","title":"ONEOF_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Сервер: поддерживайте оба до миграции:**","content":"Стратегия миграции **Сервер: поддерживайте оба до миграции:**"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::34","title":"ONEOF_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Клиенты: переходите на новый oneof:**","content":"Стратегия миграции **Клиенты: переходите на новый oneof:**"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::35","title":"ONEOF_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Удалите старый oneof** в следующей major‑версии.","content":"Стратегия миграции **Удалите старый oneof** в следующей major‑версии."},{"id":"cli/breaking-changes/rules/oneof-no-delete::oneof::36","title":"ONEOF_NO_DELETE","section":"Замена oneof обычными полями","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#oneof","headings":["Замена oneof обычными полями"],"excerpt":"Замена oneof обычными полями ```proto message SearchRequest { // НЕЛЬЗЯ просто убрать oneof — ломает семантику string text_query = 1; // BREAKING int32 user_id = 2; // BREAKING string category = 3; // BREAKING }","content":"Замена oneof обычными полями ```proto message SearchRequest { // НЕЛЬЗЯ просто убрать oneof — ломает семантику string text_query = 1; // BREAKING int32 user_id = 2; // BREAKING string category = 3; // BREAKING }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::oneof::37","title":"ONEOF_NO_DELETE","section":"Замена oneof обычными полями","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#oneof","headings":["Замена oneof обычными полями"],"excerpt":"Замена oneof обычными полями message SearchRequest { oneof query { option deprecated = true; string text_query = 1 [deprecated = true]; int32 user_id = 2 [deprecated = true]; string category = 3 [deprecated = true]; } st","content":"Замена oneof обычными полями message SearchRequest { oneof query { option deprecated = true; string text_query = 1 [deprecated = true]; int32 user_id = 2 [deprecated = true]; string category = 3 [deprecated = true]; } string search_text = 4; repeated string filters = 5; } ```"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::38","title":"ONEOF_NO_DELETE","section":"Упрощение структуры сообщения","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Упрощение структуры сообщения"],"excerpt":"Упрощение структуры сообщения ```proto message NotificationSettings { string email = 1; // BREAKING: был в oneof string phone = 2; // BREAKING string webhook_url = 3; // BREAKING }","content":"Упрощение структуры сообщения ```proto message NotificationSettings { string email = 1; // BREAKING: был в oneof string phone = 2; // BREAKING string webhook_url = 3; // BREAKING }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::39","title":"ONEOF_NO_DELETE","section":"Упрощение структуры сообщения","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Упрощение структуры сообщения"],"excerpt":"Упрощение структуры сообщения message NotificationSettings { oneof delivery_method { EmailNotification email = 1; SmsNotification phone = 2; WebhookNotification webhook = 3; } } ```","content":"Упрощение структуры сообщения message NotificationSettings { oneof delivery_method { EmailNotification email = 1; SmsNotification phone = 2; WebhookNotification webhook = 3; } } ```"},{"id":"cli/breaking-changes/rules/oneof-no-delete::proto2-proto3::40","title":"ONEOF_NO_DELETE","section":"Миграция с proto2 на proto3","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#proto2-proto3","headings":["Миграция с proto2 на proto3"],"excerpt":"Миграция с proto2 на proto3 ```proto // proto2 message Request { optional string name = 1; oneof data { string text = 2; int32 number = 3; } }","content":"Миграция с proto2 на proto3 ```proto // proto2 message Request { optional string name = 1; oneof data { string text = 2; int32 number = 3; } }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::proto2-proto3::41","title":"ONEOF_NO_DELETE","section":"Миграция с proto2 на proto3","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#proto2-proto3","headings":["Миграция с proto2 на proto3"],"excerpt":"Миграция с proto2 на proto3 // proto3 — сохраняем oneof message Request { string name = 1; oneof data { string text = 2; int32 number = 3; } } ```","content":"Миграция с proto2 на proto3 // proto3 — сохраняем oneof message Request { string name = 1; oneof data { string text = 2; int32 number = 3; } } ```"},{"id":"cli/breaking-changes/rules/oneof-no-delete::oneof::42","title":"ONEOF_NO_DELETE","section":"Что даёт oneof","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#oneof","headings":["Что даёт oneof"],"excerpt":"Что даёт oneof Взаимная исключаемость Типобезопасность в коде Ясность намерения API («выбери один») Эффективная сериализация — кодируется только выбранный вариант","content":"Что даёт oneof Взаимная исключаемость Типобезопасность в коде Ясность намерения API («выбери один») Эффективная сериализация — кодируется только выбранный вариант"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::43","title":"ONEOF_NO_DELETE","section":"Что теряется при удалении","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Что теряется при удалении"],"excerpt":"Что теряется при удалении Инвариант «только один» Генерируемые wrapper-типы и методы Автоматическая валидация выбора Понятность контракта API","content":"Что теряется при удалении Инвариант «только один» Генерируемые wrapper-типы и методы Автоматическая валидация выбора Понятность контракта API"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::44","title":"ONEOF_NO_DELETE","section":"Влияние на код генерации","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Влияние на код генерации"],"excerpt":"Влияние на код генерации ```go // С oneof type LoginRequest struct { Username string Credentials isLoginRequest_Credentials }","content":"Влияние на код генерации ```go // С oneof type LoginRequest struct { Username string Credentials isLoginRequest_Credentials }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::45","title":"ONEOF_NO_DELETE","section":"Влияние на код генерации","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Влияние на код генерации"],"excerpt":"Влияние на код генерации // Без oneof type LoginRequest struct { Username string Password string ApiKey string OauthToken string // Возможны многозначные конфликтующие состояния } ```","content":"Влияние на код генерации // Без oneof type LoginRequest struct { Username string Password string ApiKey string 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":"Правило проверяет, что ни один RPC‑метод не был удалён из service. Удаление RPC ломает сгенерированный код и клиентские приложения, которые этот метод вызывают.","content":"Правило проверяет, что ни один RPC‑метод не был удалён из service. Удаление RPC ломает сгенерированный код и клиентские приложения, которые этот метод вызывают."},{"id":"cli/breaking-changes/rules/rpc-no-delete::breaking::1","title":"RPC_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/rpc-no-delete::breaking::2","title":"RPC_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/rpc-no-delete::breaking::3","title":"RPC_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); rpc DeleteUser(DeleteUserRequest) returns (DeleteUserResponse","content":"Плохой (Breaking) 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::breaking::4","title":"RPC_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/rpc-no-delete::breaking::5","title":"RPC_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/rpc-no-delete::breaking::6","title":"RPC_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); // DeleteUser RPC удалён — BREAKING CHANGE! } ```","content":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); // DeleteUser RPC удалён — BREAKING CHANGE! } ```"},{"id":"cli/breaking-changes/rules/rpc-no-delete::top::7","title":"RPC_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо удаления — пометить RPC deprecated:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо удаления — пометить RPC deprecated:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/rpc-no-delete::top::8","title":"RPC_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/rpc-no-delete::top::9","title":"RPC_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); rpc DeleteUser(DeleteUserRequest) returns (DeleteUserRespo","content":"Хороший (Безопасный) 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::top::10","title":"RPC_NO_DELETE","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete","headings":["Влияние"],"excerpt":"Влияние **Generated Code:** Stub/метод исчезает — клиенты не компилируются **Client Applications:** Существующие вызовы метода падают при сборке **Runtime:** gRPC клиенты теряют определение метода","content":"Влияние **Generated Code:** Stub/метод исчезает — клиенты не компилируются **Client Applications:** Существующие вызовы метода падают при сборке **Runtime:** gRPC клиенты теряют определение метода"},{"id":"cli/breaking-changes/rules/rpc-no-delete::top::11","title":"RPC_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Сначала деприкация:**","content":"Стратегия миграции **Сначала деприкация:**"},{"id":"cli/breaking-changes/rules/rpc-no-delete::top::12","title":"RPC_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Имплементация может возвращать ошибку**, указывая что метод устарел (например, INTERNAL / UNIMPLEMENTED)","content":"Стратегия миграции **Имплементация может возвращать ошибку**, указывая что метод устарел (например, INTERNAL / UNIMPLEMENTED)"},{"id":"cli/breaking-changes/rules/rpc-no-delete::top::13","title":"RPC_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Удалить в следующей major‑версии** после миграции всех клиентов","content":"Стратегия миграции **Удалить в следующей major‑версии** после миграции всех клиентов"},{"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":"Это правило проверяет, что RPC‑методы сохраняют прежний тип сообщения запроса (request message type). Изменение типа запроса RPC ломает совместимость по wire‑формату и сгенерированный код: клиенты ожидают конкретную стру","content":"Это правило проверяет, что RPC‑методы сохраняют прежний тип сообщения запроса (request message type). Изменение типа запроса RPC ломает совместимость по wire‑формату и сгенерированный код: клиенты ожидают конкретную структуру при вызове метода."},{"id":"cli/breaking-changes/rules/rpc-same-request-type::breaking::1","title":"RPC_SAME_REQUEST_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::breaking::2","title":"RPC_SAME_REQUEST_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::breaking::3","title":"RPC_SAME_REQUEST_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse); }","content":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse); }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::breaking::4","title":"RPC_SAME_REQUEST_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message GetUserRequest { string user_id = 1; }","content":"Плохой (Breaking) message GetUserRequest { string user_id = 1; }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::breaking::5","title":"RPC_SAME_REQUEST_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message UpdateUserRequest { string user_id = 1; string name = 2; string email = 3; } ```","content":"Плохой (Breaking) message UpdateUserRequest { string user_id = 1; string name = 2; string email = 3; } ```"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::breaking::6","title":"RPC_SAME_REQUEST_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::breaking::7","title":"RPC_SAME_REQUEST_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::breaking::8","title":"RPC_SAME_REQUEST_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequestV2) returns (GetUserResponse); // [!code --] Изменён тип запроса rpc UpdateUser(UserUpdateRequest) returns (UpdateUserResponse); // [!code --] Изменён тип","content":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequestV2) returns (GetUserResponse); // [!code --] Изменён тип запроса rpc UpdateUser(UserUpdateRequest) returns (UpdateUserResponse); // [!code --] Изменён тип запроса }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::breaking::9","title":"RPC_SAME_REQUEST_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message GetUserRequestV2 { // [!code --] Новый тип запроса string id = 1; bool include_profile = 2; }","content":"Плохой (Breaking) message GetUserRequestV2 { // [!code --] Новый тип запроса string id = 1; bool include_profile = 2; }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::breaking::10","title":"RPC_SAME_REQUEST_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message UserUpdateRequest { // [!code --] Новый тип запроса string id = 1; UserProfile profile = 2; } ```","content":"Плохой (Breaking) message UserUpdateRequest { // [!code --] Новый тип запроса string id = 1; UserProfile profile = 2; } ```"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::11","title":"RPC_SAME_REQUEST_TYPE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры **Смена типа из другого пакета:** ```proto // Before import \"common/user.proto\";","content":"Дополнительные примеры **Смена типа из другого пакета:** ```proto // Before import \"common/user.proto\";"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::12","title":"RPC_SAME_REQUEST_TYPE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры service UserService { rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); }","content":"Дополнительные примеры service UserService { rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::13","title":"RPC_SAME_REQUEST_TYPE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры // After - BREAKING CHANGE! import \"v2/user.proto\";","content":"Дополнительные примеры // After - BREAKING CHANGE! import \"v2/user.proto\";"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::14","title":"RPC_SAME_REQUEST_TYPE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры service UserService { rpc CreateUser(v2.CreateUserRequest) returns (CreateUserResponse); // Другой package } ```","content":"Дополнительные примеры service UserService { rpc CreateUser(v2.CreateUserRequest) returns (CreateUserResponse); // Другой package } ```"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::15","title":"RPC_SAME_REQUEST_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо изменения типа — версионируйте RPC:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо изменения типа — версионируйте RPC:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::16","title":"RPC_SAME_REQUEST_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::17","title":"RPC_SAME_REQUEST_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse) { option deprecated = true; // [!code focus] } rpc GetUserV2(GetUserRequestV2) returns (GetUserResponse); // [!code focus] ","content":"Хороший (Безопасный) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse) { option deprecated = true; // [!code focus] } rpc GetUserV2(GetUserRequestV2) returns (GetUserResponse); // [!code focus] // Новый метод rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse) { option deprecated = true; // [!code focus] } rpc UpdateUserV2(UserUpdateRequest) returns (UpdateUserResponse); // [!code focus] // Новый метод }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::18","title":"RPC_SAME_REQUEST_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) // Старые сообщения — для обратной совместимости message GetUserRequest { string user_id = 1; }","content":"Хороший (Безопасный) // Старые сообщения — для обратной совместимости message GetUserRequest { string user_id = 1; }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::19","title":"RPC_SAME_REQUEST_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) // Новая версия сообщения message GetUserRequestV2 { // [!code focus] string id = 1; // [!code focus] bool include_profile = 2; // [!code focus] } // [!code focus] ```","content":"Хороший (Безопасный) // Новая версия сообщения 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::top::20","title":"RPC_SAME_REQUEST_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Или создайте новую версию сервиса (package v2):** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Или создайте новую версию сервиса (package v2):** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::21","title":"RPC_SAME_REQUEST_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v2; // [!code focus]","content":"Хороший (Безопасный) package myapi.v2; // [!code focus]"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::22","title":"RPC_SAME_REQUEST_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); // [!code focus] rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse); // [!code focus] }","content":"Хороший (Безопасный) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); // [!code focus] rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse); // [!code focus] }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::23","title":"RPC_SAME_REQUEST_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message GetUserRequest { // [!code focus] string id = 1; // [!code focus] bool include_profile = 2; // [!code focus] } // [!code focus] ```","content":"Хороший (Безопасный) message GetUserRequest { // [!code focus] string id = 1; // [!code focus] bool include_profile = 2; // [!code focus] } // [!code focus] ```"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::24","title":"RPC_SAME_REQUEST_TYPE","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Влияние"],"excerpt":"Влияние **Wire Format:** Старые запросы клиентов не десериализуются новым сервером **Generated Code:** Сигнатуры методов в stubs меняются — компиляция клиентов падает **gRPC Calls:** Требуется использовать другую структу","content":"Влияние **Wire Format:** Старые запросы клиентов не десериализуются новым сервером **Generated Code:** Сигнатуры методов в stubs меняются — компиляция клиентов падает **gRPC Calls:** Требуется использовать другую структуру запроса **Runtime Errors:** Несоответствие типов вызывает ошибки выполнения"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::25","title":"RPC_SAME_REQUEST_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Реальный пример"],"excerpt":"Реальный пример **Код клиента ломается:** ```go // Before client := myapi.NewUserServiceClient(conn) resp, err := client.GetUser(ctx, &myapi.GetUserRequest{ UserId: \"user123\", })","content":"Реальный пример **Код клиента ломается:** ```go // Before client := myapi.NewUserServiceClient(conn) resp, err := client.GetUser(ctx, &myapi.GetUserRequest{ UserId: \"user123\", })"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::26","title":"RPC_SAME_REQUEST_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Реальный пример"],"excerpt":"Реальный пример // After (тип запроса изменён) client := myapi.NewUserServiceClient(conn) resp, err := client.GetUser(ctx, &myapi.GetUserRequest{ // ERROR: тип не найден UserId: \"user123\", // ERROR: поле не найдено })","content":"Реальный пример // After (тип запроса изменён) client := myapi.NewUserServiceClient(conn) resp, err := client.GetUser(ctx, &myapi.GetUserRequest{ // ERROR: тип не найден UserId: \"user123\", // ERROR: поле не найдено })"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::27","title":"RPC_SAME_REQUEST_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Реальный пример"],"excerpt":"Реальный пример // Новый корректный вызов: resp, err := client.GetUser(ctx, &myapi.GetUserRequestV2{ Id: \"user123\", IncludeProfile: true, }) ```","content":"Реальный пример // Новый корректный вызов: resp, err := client.GetUser(ctx, &myapi.GetUserRequestV2{ Id: \"user123\", IncludeProfile: true, }) ```"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::28","title":"RPC_SAME_REQUEST_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Реальный пример"],"excerpt":"Реальный пример **Серверная реализация ломается:** ```go // Before func (s *server) GetUser(ctx context.Context, req *GetUserRequest) (*GetUserResponse, error) { userID := req.UserId // ... }","content":"Реальный пример **Серверная реализация ломается:** ```go // Before func (s *server) GetUser(ctx context.Context, req *GetUserRequest) (*GetUserResponse, error) { userID := req.UserId // ... }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::29","title":"RPC_SAME_REQUEST_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Реальный пример"],"excerpt":"Реальный пример // After func (s *server) GetUser(ctx context.Context, req *GetUserRequestV2) (*GetUserResponse, error) { userID := req.Id include := req.IncludeProfile // ... новая логика } ```","content":"Реальный пример // After func (s *server) GetUser(ctx context.Context, req *GetUserRequestV2) (*GetUserResponse, error) { userID := req.Id include := req.IncludeProfile // ... новая логика } ```"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::30","title":"RPC_SAME_REQUEST_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Добавьте новый RPC с новым типом запроса:**","content":"Стратегия миграции **Добавьте новый RPC с новым типом запроса:**"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::31","title":"RPC_SAME_REQUEST_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Поддерживайте оба метода на сервере:** ```go func (s *server) GetUser(ctx context.Context, req *GetUserRequest) (*GetUserResponse, error) { return s.getUserInternal(req.UserId, false) }","content":"Стратегия миграции **Поддерживайте оба метода на сервере:** ```go func (s *server) GetUser(ctx context.Context, req *GetUserRequest) (*GetUserResponse, error) { return s.getUserInternal(req.UserId, false) }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::32","title":"RPC_SAME_REQUEST_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции func (s *server) GetUserV2(ctx context.Context, req *GetUserRequestV2) (*GetUserResponse, error) { return s.getUserInternal(req.Id, req.IncludeProfile) } ```","content":"Стратегия миграции func (s *server) GetUserV2(ctx context.Context, req *GetUserRequestV2) (*GetUserResponse, error) { return s.getUserInternal(req.Id, req.IncludeProfile) } ```"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::33","title":"RPC_SAME_REQUEST_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Мигрируйте клиентов на V2:**","content":"Стратегия миграции **Мигрируйте клиентов на V2:**"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::34","title":"RPC_SAME_REQUEST_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Удалите старый метод в следующей major‑версии:**","content":"Стратегия миграции **Удалите старый метод в следующей major‑версии:**"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::35","title":"RPC_SAME_REQUEST_TYPE","section":"Добавление обязательных полей","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Добавление обязательных полей"],"excerpt":"Добавление обязательных полей ```proto // ПЛОХО: меняем существующий запрос message GetUserRequest { string user_id = 1; bool include_deleted = 2; // BREAKING }","content":"Добавление обязательных полей ```proto // ПЛОХО: меняем существующий запрос message GetUserRequest { string user_id = 1; bool include_deleted = 2; // BREAKING }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::36","title":"RPC_SAME_REQUEST_TYPE","section":"Добавление обязательных полей","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Добавление обязательных полей"],"excerpt":"Добавление обязательных полей // Хорошо: новая версия message GetUserRequestV2 { string user_id = 1; bool include_deleted = 2; } ```","content":"Добавление обязательных полей // Хорошо: новая версия message GetUserRequestV2 { string user_id = 1; bool include_deleted = 2; } ```"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::37","title":"RPC_SAME_REQUEST_TYPE","section":"Реструктуризация данных запроса","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Реструктуризация данных запроса"],"excerpt":"Реструктуризация данных запроса ```proto // ПЛОХО: меняем структуру прямо message UpdateUserRequest { UserProfile profile = 1; // BREAKING }","content":"Реструктуризация данных запроса ```proto // ПЛОХО: меняем структуру прямо message UpdateUserRequest { UserProfile profile = 1; // BREAKING }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::38","title":"RPC_SAME_REQUEST_TYPE","section":"Реструктуризация данных запроса","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Реструктуризация данных запроса"],"excerpt":"Реструктуризация данных запроса // Хорошо: версионирование rpc UpdateUser(UpdateUserRequest) returns (...) { option deprecated = true; } rpc UpdateUserV2(UpdateUserRequestV2) returns (...); ```","content":"Реструктуризация данных запроса // Хорошо: версионирование rpc UpdateUser(UpdateUserRequest) returns (...) { option deprecated = true; } rpc UpdateUserV2(UpdateUserRequestV2) returns (...); ```"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::39","title":"RPC_SAME_REQUEST_TYPE","section":"Миграция пакета","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Миграция пакета"],"excerpt":"Миграция пакета ```proto // ПЛОХО: заменяем тип на пакет v2 прямо import \"v2/messages.proto\"; // BREAKING","content":"Миграция пакета ```proto // ПЛОХО: заменяем тип на пакет v2 прямо import \"v2/messages.proto\"; // BREAKING"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::40","title":"RPC_SAME_REQUEST_TYPE","section":"Миграция пакета","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Миграция пакета"],"excerpt":"Миграция пакета // Хорошо: добавляем новый RPC rpc OldMethod(v1.Request) returns (...) { option deprecated = true; } rpc NewMethod(v2.Request) returns (...); ```","content":"Миграция пакета // Хорошо: добавляем новый RPC 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":"Это правило проверяет, что RPC‑методы сохраняют тот же тип ответного сообщения (response message type). Изменение типа ответа RPC ломает совместимость по wire‑формату и сгенерированный код: клиенты ожидают конкретную стр","content":"Это правило проверяет, что RPC‑методы сохраняют тот же тип ответного сообщения (response message type). Изменение типа ответа RPC ломает совместимость по wire‑формату и сгенерированный код: клиенты ожидают конкретную структуру при получении ответа."},{"id":"cli/breaking-changes/rules/rpc-same-response-type::breaking::1","title":"RPC_SAME_RESPONSE_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::breaking::2","title":"RPC_SAME_RESPONSE_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::breaking::3","title":"RPC_SAME_RESPONSE_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse); }","content":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse); }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::breaking::4","title":"RPC_SAME_RESPONSE_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message GetUserResponse { string user_id = 1; string name = 2; string email = 3; }","content":"Плохой (Breaking) message GetUserResponse { string user_id = 1; string name = 2; string email = 3; }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::breaking::5","title":"RPC_SAME_RESPONSE_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message UpdateUserResponse { bool success = 1; string message = 2; } ```","content":"Плохой (Breaking) message UpdateUserResponse { bool success = 1; string message = 2; } ```"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::breaking::6","title":"RPC_SAME_RESPONSE_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::breaking::7","title":"RPC_SAME_RESPONSE_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::breaking::8","title":"RPC_SAME_RESPONSE_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponseV2); // [!code --] Изменён тип ответа rpc UpdateUser(UpdateUserRequest) returns (UserUpdateResponse); // [!code --] Изменён тип ","content":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponseV2); // [!code --] Изменён тип ответа rpc UpdateUser(UpdateUserRequest) returns (UserUpdateResponse); // [!code --] Изменён тип ответа }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::breaking::9","title":"RPC_SAME_RESPONSE_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message GetUserResponseV2 { // [!code --] Другой тип сообщения string id = 1; UserProfile profile = 2; repeated string permissions = 3; }","content":"Плохой (Breaking) message GetUserResponseV2 { // [!code --] Другой тип сообщения string id = 1; UserProfile profile = 2; repeated string permissions = 3; }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::breaking::10","title":"RPC_SAME_RESPONSE_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message UserUpdateResponse { // [!code --] Другой тип сообщения UpdateResult result = 1; UserProfile updated_profile = 2; } ```","content":"Плохой (Breaking) message UserUpdateResponse { // [!code --] Другой тип сообщения UpdateResult result = 1; UserProfile updated_profile = 2; } ```"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::11","title":"RPC_SAME_RESPONSE_TYPE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры **Смена типа из другого пакета:** ```proto // Before import \"common/responses.proto\";","content":"Дополнительные примеры **Смена типа из другого пакета:** ```proto // Before import \"common/responses.proto\";"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::12","title":"RPC_SAME_RESPONSE_TYPE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры service UserService { rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); }","content":"Дополнительные примеры service UserService { rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::13","title":"RPC_SAME_RESPONSE_TYPE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры // After - BREAKING CHANGE! import \"v2/responses.proto\";","content":"Дополнительные примеры // After - BREAKING CHANGE! import \"v2/responses.proto\";"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::14","title":"RPC_SAME_RESPONSE_TYPE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры service UserService { rpc CreateUser(CreateUserRequest) returns (v2.CreateUserResponse); // Другой package } ```","content":"Дополнительные примеры service UserService { rpc CreateUser(CreateUserRequest) returns (v2.CreateUserResponse); // Другой package } ```"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::15","title":"RPC_SAME_RESPONSE_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо изменения типа — версионируйте RPC:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо изменения типа — версионируйте RPC:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::16","title":"RPC_SAME_RESPONSE_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::17","title":"RPC_SAME_RESPONSE_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse) { option deprecated = true; // [!code focus] } rpc GetUserV2(GetUserRequest) returns (GetUserResponseV2); // [!code focus] ","content":"Хороший (Безопасный) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse) { option deprecated = true; // [!code focus] } rpc GetUserV2(GetUserRequest) returns (GetUserResponseV2); // [!code focus] // Новый метод rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse) { option deprecated = true; // [!code focus] } rpc UpdateUserV2(UpdateUserRequest) returns (UserUpdateResponse); // [!code focus] // Новый метод }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::18","title":"RPC_SAME_RESPONSE_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) // Старые сообщения сохраняем для обратной совместимости message GetUserResponse { string user_id = 1; string name = 2; string email = 3; }","content":"Хороший (Безопасный) // Старые сообщения сохраняем для обратной совместимости message GetUserResponse { string user_id = 1; string name = 2; string email = 3; }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::19","title":"RPC_SAME_RESPONSE_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) // Новая расширенная версия message GetUserResponseV2 { // [!code focus] string id = 1; // [!code focus] UserProfile profile = 2; // [!code focus] repeated string permissions = 3; // [!code focus] } ","content":"Хороший (Безопасный) // Новая расширенная версия 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::top::20","title":"RPC_SAME_RESPONSE_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Или создайте новую версию сервиса (package v2):** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Или создайте новую версию сервиса (package v2):** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::21","title":"RPC_SAME_RESPONSE_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v2; // [!code focus]","content":"Хороший (Безопасный) package myapi.v2; // [!code focus]"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::22","title":"RPC_SAME_RESPONSE_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); // [!code focus] rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse); // [!code focus] }","content":"Хороший (Безопасный) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); // [!code focus] rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse); // [!code focus] }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::23","title":"RPC_SAME_RESPONSE_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message GetUserResponse { // [!code focus] string id = 1; // [!code focus] UserProfile profile = 2; // [!code focus] repeated string permissions = 3; // [!code focus] } // [!code focus] ```","content":"Хороший (Безопасный) message GetUserResponse { // [!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::top::24","title":"RPC_SAME_RESPONSE_TYPE","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Влияние"],"excerpt":"Влияние **Wire Format:** Ответы сервера не десериализуются у старых клиентов **Generated Code:** Сигнатуры ожидают старый тип — компиляция падает **gRPC Calls:** Меняются типы в сгенерированных stub'ах **Runtime Errors:*","content":"Влияние **Wire Format:** Ответы сервера не десериализуются у старых клиентов **Generated Code:** Сигнатуры ожидают старый тип — компиляция падает **gRPC Calls:** Меняются типы в сгенерированных stub'ах **Runtime Errors:** Несоответствие типов ломает обработку ответа"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::25","title":"RPC_SAME_RESPONSE_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Реальный пример"],"excerpt":"Реальный пример **Код клиента ломается:** ```go // Before client := myapi.NewUserServiceClient(conn) resp, err := client.GetUser(ctx, &myapi.GetUserRequest{ UserId: \"user123\", }) if err != nil { return err }","content":"Реальный пример **Код клиента ломается:** ```go // Before 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::top::26","title":"RPC_SAME_RESPONSE_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Реальный пример"],"excerpt":"Реальный пример userID := resp.UserId name := resp.Name","content":"Реальный пример userID := resp.UserId name := resp.Name"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::27","title":"RPC_SAME_RESPONSE_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Реальный пример"],"excerpt":"Реальный пример // After (тип ответа изменён) client := myapi.NewUserServiceClient(conn) resp, err := client.GetUser(ctx, &myapi.GetUserRequest{ UserId: \"user123\", }) if err != nil { return err }","content":"Реальный пример // After (тип ответа изменён) 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::top::28","title":"RPC_SAME_RESPONSE_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Реальный пример"],"excerpt":"Реальный пример // Ошибки компиляции: userID := resp.UserId // ERROR name := resp.Name // ERROR","content":"Реальный пример // Ошибки компиляции: userID := resp.UserId // ERROR name := resp.Name // ERROR"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::29","title":"RPC_SAME_RESPONSE_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Реальный пример"],"excerpt":"Реальный пример // Новый способ: userID := resp.Id profile := resp.Profile permissions := resp.Permissions ```","content":"Реальный пример // Новый способ: userID := resp.Id profile := resp.Profile permissions := resp.Permissions ```"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::30","title":"RPC_SAME_RESPONSE_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Реальный пример"],"excerpt":"Реальный пример **Имплементация сервера также должна быть переписана:** ```go // Before func (s *server) GetUser(ctx context.Context, req *GetUserRequest) (*GetUserResponse, error) { return &GetUserResponse{ UserId: \"use","content":"Реальный пример **Имплементация сервера также должна быть переписана:** ```go // Before 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::top::31","title":"RPC_SAME_RESPONSE_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Реальный пример"],"excerpt":"Реальный пример // After func (s *server) GetUser(ctx context.Context, req *GetUserRequest) (*GetUserResponseV2, error) { return &GetUserResponseV2{ Id: \"user123\", Profile: &UserProfile{ Name: \"John Doe\", Email: \"john@ex","content":"Реальный пример // After func (s *server) GetUser(ctx context.Context, req *GetUserRequest) (*GetUserResponseV2, error) { return &GetUserResponseV2{ Id: \"user123\", Profile: &UserProfile{ Name: \"John Doe\", Email: \"john@example.com\", }, Permissions: []string{\"read\"}, }, nil } ```"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::32","title":"RPC_SAME_RESPONSE_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Добавьте новый RPC c новым типом ответа:**","content":"Стратегия миграции **Добавьте новый RPC c новым типом ответа:**"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::33","title":"RPC_SAME_RESPONSE_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Поддерживайте оба на сервере:** ```go func (s *server) GetUser(ctx context.Context, req *GetUserRequest) (*GetUserResponse, error) { user := s.getUserInternal(req.UserId) return &GetUserResponse{ Use","content":"Стратегия миграции **Поддерживайте оба на сервере:** ```go func (s *server) GetUser(ctx context.Context, req *GetUserRequest) (*GetUserResponse, error) { user := s.getUserInternal(req.UserId) return &GetUserResponse{ UserId: user.ID, Name: user.Name, Email: user.Email, }, nil }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::34","title":"RPC_SAME_RESPONSE_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции func (s *server) GetUserV2(ctx context.Context, req *GetUserRequest) (*GetUserResponseV2, error) { user := s.getUserInternal(req.UserId) return &GetUserResponseV2{ Id: user.ID, Profile: &UserProfile{ N","content":"Стратегия миграции func (s *server) GetUserV2(ctx context.Context, req *GetUserRequest) (*GetUserResponseV2, error) { user := s.getUserInternal(req.UserId) return &GetUserResponseV2{ Id: user.ID, Profile: &UserProfile{ Name: user.Name, Email: user.Email, }, Permissions: user.Permissions, }, nil } ```"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::35","title":"RPC_SAME_RESPONSE_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Мигрируйте клиентов на новый RPC:**","content":"Стратегия миграции **Мигрируйте клиентов на новый RPC:**"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::36","title":"RPC_SAME_RESPONSE_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Удалите старый RPC** в следующей major‑версии:","content":"Стратегия миграции **Удалите старый RPC** в следующей major‑версии:"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::37","title":"RPC_SAME_RESPONSE_TYPE","section":"Добавление новых обязательных полей","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Добавление новых обязательных полей"],"excerpt":"Добавление новых обязательных полей ```proto // ПЛОХО: меняем существующий тип message GetUserResponse { string user_id = 1; string name = 2; UserProfile profile = 3; // BREAKING }","content":"Добавление новых обязательных полей ```proto // ПЛОХО: меняем существующий тип message GetUserResponse { string user_id = 1; string name = 2; UserProfile profile = 3; // BREAKING }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::38","title":"RPC_SAME_RESPONSE_TYPE","section":"Добавление новых обязательных полей","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Добавление новых обязательных полей"],"excerpt":"Добавление новых обязательных полей // Хорошо: новая версия message GetUserResponseV2 { string user_id = 1; string name = 2; UserProfile profile = 3; } ```","content":"Добавление новых обязательных полей // Хорошо: новая версия message GetUserResponseV2 { string user_id = 1; string name = 2; UserProfile profile = 3; } ```"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::39","title":"RPC_SAME_RESPONSE_TYPE","section":"Реструктуризация ответа","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Реструктуризация ответа"],"excerpt":"Реструктуризация ответа ```proto // ПЛОХО: меняем структуру прямо message UpdateUserResponse { UserDetails details = 1; // BREAKING }","content":"Реструктуризация ответа ```proto // ПЛОХО: меняем структуру прямо message UpdateUserResponse { UserDetails details = 1; // BREAKING }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::40","title":"RPC_SAME_RESPONSE_TYPE","section":"Реструктуризация ответа","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Реструктуризация ответа"],"excerpt":"Реструктуризация ответа // Хорошо: версионирование rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse) { option deprecated = true; } rpc UpdateUserV2(UpdateUserRequest) returns (UpdateUserResponseV2); ```","content":"Реструктуризация ответа // Хорошо: версионирование rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse) { option deprecated = true; } rpc UpdateUserV2(UpdateUserRequest) returns (UpdateUserResponseV2); ```"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::41","title":"RPC_SAME_RESPONSE_TYPE","section":"Изменение формата ошибок","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Изменение формата ошибок"],"excerpt":"Изменение формата ошибок ```proto // ПЛОХО: меняем формат напрямую message CreateUserResponse { ErrorDetails error = 1; // BREAKING }","content":"Изменение формата ошибок ```proto // ПЛОХО: меняем формат напрямую message CreateUserResponse { ErrorDetails error = 1; // BREAKING }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::42","title":"RPC_SAME_RESPONSE_TYPE","section":"Изменение формата ошибок","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Изменение формата ошибок"],"excerpt":"Изменение формата ошибок // Хорошо: новая версия rpc CreateUser(CreateUserRequest) returns (CreateUserResponse) { option deprecated = true; } rpc CreateUserV2(CreateUserRequest) returns (CreateUserResponseV2); ```","content":"Изменение формата ошибок // Хорошо: новая версия rpc CreateUser(CreateUserRequest) returns (CreateUserResponse) { option deprecated = true; } rpc CreateUserV2(CreateUserRequest) returns (CreateUserResponseV2); ```"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::43","title":"RPC_SAME_RESPONSE_TYPE","section":"Миграция формата","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Миграция формата"],"excerpt":"Миграция формата ```proto // ПЛОХО: перевод простой структуры в сложную message GetUserResponse { UserData data = 1; // BREAKING }","content":"Миграция формата ```proto // ПЛОХО: перевод простой структуры в сложную message GetUserResponse { UserData data = 1; // BREAKING }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::44","title":"RPC_SAME_RESPONSE_TYPE","section":"Миграция формата","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Миграция формата"],"excerpt":"Миграция формата // Хорошо: предоставляем обе версии rpc GetUser(GetUserRequest) returns (GetUserResponse) { option deprecated = true; } rpc GetUserDetailed(GetUserRequest) returns (GetUserDetailedResponse); ```","content":"Миграция формата // Хорошо: предоставляем обе версии 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":"Данное правило проверяет, что ни один service не был удалён из proto‑файлов. Удаление service ломает сгенерированный код и клиентские приложения, которые на него опираются.","content":"Данное правило проверяет, что ни один service не был удалён из proto‑файлов. Удаление service ломает сгенерированный код и клиентские приложения, которые на него опираются."},{"id":"cli/breaking-changes/rules/service-no-delete::breaking::1","title":"SERVICE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/service-no-delete::breaking::2","title":"SERVICE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/service-no-delete::breaking::3","title":"SERVICE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); }","content":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); }"},{"id":"cli/breaking-changes/rules/service-no-delete::breaking::4","title":"SERVICE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) service OrderService { // [!code --] rpc GetOrder(GetOrderRequest) returns (GetOrderResponse); // [!code --] } // [!code --] ```","content":"Плохой (Breaking) service OrderService { // [!code --] rpc GetOrder(GetOrderRequest) returns (GetOrderResponse); // [!code --] } // [!code --] ```"},{"id":"cli/breaking-changes/rules/service-no-delete::breaking::5","title":"SERVICE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/service-no-delete::breaking::6","title":"SERVICE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/service-no-delete::breaking::7","title":"SERVICE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); }","content":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); }"},{"id":"cli/breaking-changes/rules/service-no-delete::breaking::8","title":"SERVICE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) // OrderService удалён — BREAKING CHANGE! ```","content":"Плохой (Breaking) // OrderService удалён — BREAKING CHANGE! ```"},{"id":"cli/breaking-changes/rules/service-no-delete::top::9","title":"SERVICE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо удаления — отметьте service как deprecated:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо удаления — отметьте service как deprecated:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/service-no-delete::top::10","title":"SERVICE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/service-no-delete::top::11","title":"SERVICE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); }","content":"Хороший (Безопасный) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); }"},{"id":"cli/breaking-changes/rules/service-no-delete::top::12","title":"SERVICE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) service OrderService { option deprecated = true; // [!code focus] rpc GetOrder(GetOrderRequest) returns (GetOrderResponse) { option deprecated = true; // [!code focus] } } ```","content":"Хороший (Безопасный) 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::top::13","title":"SERVICE_NO_DELETE","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete","headings":["Влияние"],"excerpt":"Влияние **Generated Code:** Классы / интерфейсы сервиса исчезают — клиенты не компилируются **Client Applications:** Существующие вызовы к удалённому сервису падают на этапе сборки **Runtime:** gRPC клиенты теряют опреде","content":"Влияние **Generated Code:** Классы / интерфейсы сервиса исчезают — клиенты не компилируются **Client Applications:** Существующие вызовы к удалённому сервису падают на этапе сборки **Runtime:** gRPC клиенты теряют определение метода/сервиса"},{"id":"cli/breaking-changes/rules/service-no-delete::top::14","title":"SERVICE_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Сначала деприкация:**","content":"Стратегия миграции **Сначала деприкация:**"},{"id":"cli/breaking-changes/rules/service-no-delete::top::15","title":"SERVICE_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Уведомите клиентов** о сроках вывода из эксплуатации","content":"Стратегия миграции **Уведомите клиентов** о сроках вывода из эксплуатации"},{"id":"cli/breaking-changes/rules/service-no-delete::top::16","title":"SERVICE_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Удалите после периода миграции** в следующей major‑версии","content":"Стратегия миграции **Удалите после периода миграции** в следующей major‑версии"},{"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 Формат вывода для команд с поддержкой нескольких форматов (text/json) значение по умолчанию зависит от команды"},{"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 Базовая директория для поиска файлов Текущая рабочая дир","content":"Command-Specific Flags Flag Short Environment Description Default ------ ------- ------------- ------------- --------- --path -p Directory path to lint . --root -r Базовая директория для поиска файлов Текущая рабочая директория --format -f EASYP_FORMAT Использует глобальный флаг формата (text/json) Использует глобальное значение по умолчанию"},{"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 из поддиректории с правильным разрешением импортов easyp lint --root src/IPC/Contracts --path .","content":"Command-Specific Flags Lint из поддиректории с правильным разрешением импортов 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 # глобальный флаг","content":"Command-Specific Flags JSON output format easyp --format json lint # глобальный флаг"},{"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 Путь к директории с proto файлами для генерации . --root -r Базова","content":"Command-Specific Flags Flag Short Environment Description Default ------ ------- ------------- ------------- --------- --path -p EASYP_ROOT_GENERATE_PATH Путь к директории с proto файлами для генерации . --root -r Базовая директория для поиска файлов Текущая рабочая директория"},{"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 из поддиректории с правильным разрешением импортов easyp generate --root src/IPC/Contracts --path .","content":"Command-Specific Flags Generate из поддиректории с правильным разрешением импортов 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 Использует глобальный флаг формата (text/json) Использует глобальное значение по умолчанию"},{"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 # глобальный флаг ```","content":"Command-Specific Flags JSON output easyp --format json breaking --against main # глобальный флаг ```"},{"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 работает интерактивно: Если в корне целевой директории есть buf.yml/buf.yaml, команда предложит миграцию из Buf. Если easyp.yaml уже существует, команда запросит подтверждение на перезап","content":"Command-Specific Flags easyp init работает интерактивно: Если в корне целевой директории есть buf.yml/buf.yaml, команда предложит миграцию из Buf. Если easyp.yaml уже существует, команда запросит подтверждение на перезапись."},{"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 Путь до файла конфигурации easyp.yaml --format (global) -f EASYP_FORMAT Глобаль","content":"Command-Specific Flags Flag Short Environment Description Default ------ ------- ------------- ------------- --------- --config -c EASYP_CFG Путь до файла конфигурации easyp.yaml --format (global) -f EASYP_FORMAT Глобальный формат вывода для команд с несколькими форматами (json или text) зависит от команды (json для 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 Проверить конфиг по умолчанию с JSON выводом (статус 0 если ошибок нет) easyp validate-config","content":"Command-Specific Flags **Examples:** ```bash Проверить конфиг по умолчанию с JSON выводом (статус 0 если ошибок нет) 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 Проверить другой файл и вывести в текстовом формате (глобальный --format) easyp --format text validate-config --config example.easyp.yaml ```","content":"Command-Specific Flags Проверить другой файл и вывести в текстовом формате (глобальный --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 Формат вывода для поддерживаемых команд (text/json). Если не указан, каждая команда использует своё значение по умолчанию. значение по умолчанию зависит от команды 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::top::45","title":"EasyP Configuration Reference","section":"Переменные окружения в конфигурации","path":"/docs/guide/cli/configuration/configuration","headings":["Переменные окружения в конфигурации"],"excerpt":"Переменные окружения в конфигурации EasyP поддерживает расширение переменных окружения непосредственно в файле конфигурации easyp.yaml. Это позволяет использовать переменные окружения для динамических значений конфигурац","content":"Переменные окружения в конфигурации EasyP поддерживает расширение переменных окружения непосредственно в файле конфигурации easyp.yaml. Это позволяет использовать переменные окружения для динамических значений конфигурации."},{"id":"cli/configuration/configuration::top::46","title":"EasyP Configuration Reference","section":"Переменные окружения в конфигурации","path":"/docs/guide/cli/configuration/configuration","headings":["Переменные окружения в конфигурации"],"excerpt":"Переменные окружения в конфигурации **Пример со всеми поддерживаемыми возможностями:** ```yaml deps: # Базовое расширение: ${VAR} - расширяется в значение переменной VAR - ${GOOGLEAPIS_REPO}@${GOOGLEAPIS_VERSION} # Значе","content":"Переменные окружения в конфигурации **Пример со всеми поддерживаемыми возможностями:** ```yaml deps: # Базовое расширение: ${VAR} - расширяется в значение переменной VAR - ${GOOGLEAPIS_REPO}@${GOOGLEAPIS_VERSION} # Значение по умолчанию: ${VAR:-default} - использует default, если VAR не установлена или пустая - ${GNOSTIC_REPO:-github.com/google/gnostic}@${GNOSTIC_VERSION:-v0.7.0}"},{"id":"cli/configuration/configuration::top::47","title":"EasyP Configuration Reference","section":"Переменные окружения в конфигурации","path":"/docs/guide/cli/configuration/configuration","headings":["Переменные окружения в конфигурации"],"excerpt":"Переменные окружения в конфигурации generate: inputs: # Значение по умолчанию, если INPUT_DIR не установлена - directory: ${INPUT_DIR:-proto} plugins: - name: go # Базовое расширение out: ${OUTPUT_DIR} opts: # Значение п","content":"Переменные окружения в конфигурации generate: inputs: # Значение по умолчанию, если INPUT_DIR не установлена - directory: ${INPUT_DIR:-proto} plugins: - name: go # Базовое расширение out: ${OUTPUT_DIR} opts: # Значение по умолчанию module: ${MODULE_NAME:-github.com/example/project} timeout: ${TIMEOUT:-30} # Экранирование: $$ становится буквальным $, $${VAR} становится буквальным ${VAR} path: \"${BASE_DIR}/$${TEMP}/file\" # Результат: \"/tmp/${TEMP}/file\" (если BASE_DIR=/tmp) literal: \"$$\" # Результат: \"$\" ```"},{"id":"cli/configuration/configuration::top::48","title":"EasyP Configuration Reference","section":"Переменные окружения в конфигурации","path":"/docs/guide/cli/configuration/configuration","headings":["Переменные окружения в конфигурации"],"excerpt":"Переменные окружения в конфигурации **Поддерживаемый синтаксис:** ${VAR} - расширяется в значение переменной VAR ${VAR:-default} - использует default, если VAR не установлена или пустая ${VAR:=default} - использует defau","content":"Переменные окружения в конфигурации **Поддерживаемый синтаксис:** ${VAR} - расширяется в значение переменной VAR ${VAR:-default} - использует default, если VAR не установлена или пустая ${VAR:=default} - использует default, если VAR не установлена или пустая ${VAR-default} - использует default, если VAR не установлена (пустая строка сохраняется) $${VAR} или $$VAR - экранирует в буквальную строку ${VAR} или $VAR $$ - экранирует в буквальный символ $"},{"id":"cli/configuration/configuration::top::49","title":"EasyP Configuration Reference","section":"Переменные окружения в конфигурации","path":"/docs/guide/cli/configuration/configuration","headings":["Переменные окружения в конфигурации"],"excerpt":"Переменные окружения в конфигурации **Примечание:** Переменные окружения расширяются до парсинга YAML, поэтому любой паттерн ${STRING} будет обработан. Используйте $$ для экранирования символов доллара, когда нужны буква","content":"Переменные окружения в конфигурации **Примечание:** Переменные окружения расширяются до парсинга YAML, поэтому любой паттерн ${STRING} будет обработан. Используйте $$ для экранирования символов доллара, когда нужны буквальные значения."},{"id":"cli/configuration/configuration::version::50","title":"EasyP Configuration Reference","section":"version","path":"/docs/guide/cli/configuration/configuration#version","headings":["version"],"excerpt":"version **Опционально (legacy-совместимость).** Поле поддерживается для обратной совместимости и может быть опущено в новых конфигурациях.","content":"version **Опционально (legacy-совместимость).** Поле поддерживается для обратной совместимости и может быть опущено в новых конфигурациях."},{"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:** не задано **Рекомендация:** если сохраняете поле, используйте v1alpha","content":"version **Type:** string **Default:** не задано **Рекомендация:** если сохраняете поле, используйте v1alpha"},{"id":"cli/configuration/configuration::version::52","title":"EasyP Configuration Reference","section":"version","path":"/docs/guide/cli/configuration/configuration#version","headings":["version"],"excerpt":"version На поведение рантайма это поле не влияет.","content":"version На поведение рантайма это поле не влияет."},{"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, required) - Output directory for generated files opts (mapstring, optional) - Plugin-specific options; each key can be a single value or an array of 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::top::0","title":"Go","section":"Установка плагинов","path":"/docs/guide/cli/generator/examples/go","headings":["Установка плагинов"],"excerpt":"Установка плагинов Сначала установите необходимые плагины для работы с gRPC:","content":"Установка плагинов Сначала установите необходимые плагины для работы с gRPC:"},{"id":"cli/generator/examples/go::top::1","title":"Go","section":"Установка плагинов","path":"/docs/guide/cli/generator/examples/go","headings":["Установка плагинов"],"excerpt":"Установка плагинов Эти команды установят плагины protoc-gen-go и protoc-gen-go-grpc для использования с EasyP.","content":"Установка плагинов Эти команды установят плагины protoc-gen-go и protoc-gen-go-grpc для использования с EasyP."},{"id":"cli/generator/examples/go::proto::2","title":"Go","section":"Пример proto‑сервиса","path":"/docs/guide/cli/generator/examples/go#proto","headings":["Пример proto‑сервиса"],"excerpt":"Пример proto‑сервиса Ниже пример proto-файла для сервиса Echo:","content":"Пример proto‑сервиса Ниже пример proto-файла для сервиса Echo:"},{"id":"cli/generator/examples/go::proto::3","title":"Go","section":"Пример proto‑сервиса","path":"/docs/guide/cli/generator/examples/go#proto","headings":["Пример proto‑сервиса"],"excerpt":"Пример proto‑сервиса ```proto syntax = \"proto3\";","content":"Пример proto‑сервиса ```proto syntax = \"proto3\";"},{"id":"cli/generator/examples/go::proto::4","title":"Go","section":"Пример proto‑сервиса","path":"/docs/guide/cli/generator/examples/go#proto","headings":["Пример proto‑сервиса"],"excerpt":"Пример proto‑сервиса package api.echo.v1;","content":"Пример proto‑сервиса package api.echo.v1;"},{"id":"cli/generator/examples/go::proto::5","title":"Go","section":"Пример proto‑сервиса","path":"/docs/guide/cli/generator/examples/go#proto","headings":["Пример proto‑сервиса"],"excerpt":"Пример proto‑сервиса option go_package = \"github.com/easyp-tech/example/api/echo/v1;pb\";","content":"Пример proto‑сервиса option go_package = \"github.com/easyp-tech/example/api/echo/v1;pb\";"},{"id":"cli/generator/examples/go::proto::6","title":"Go","section":"Пример proto‑сервиса","path":"/docs/guide/cli/generator/examples/go#proto","headings":["Пример proto‑сервиса"],"excerpt":"Пример proto‑сервиса service EchoAPI { rpc Echo(EchoRequest) returns (EchoResponse); rpc EchoStream(EchoStreamRequest) returns (EchoResponse); }","content":"Пример proto‑сервиса service EchoAPI { rpc Echo(EchoRequest) returns (EchoResponse); rpc EchoStream(EchoStreamRequest) returns (EchoResponse); }"},{"id":"cli/generator/examples/go::proto::7","title":"Go","section":"Пример proto‑сервиса","path":"/docs/guide/cli/generator/examples/go#proto","headings":["Пример proto‑сервиса"],"excerpt":"Пример proto‑сервиса message EchoRequest { string payload = 1; }","content":"Пример proto‑сервиса message EchoRequest { string payload = 1; }"},{"id":"cli/generator/examples/go::proto::8","title":"Go","section":"Пример proto‑сервиса","path":"/docs/guide/cli/generator/examples/go#proto","headings":["Пример proto‑сервиса"],"excerpt":"Пример proto‑сервиса message EchoResponse { string payload = 2; }","content":"Пример proto‑сервиса message EchoResponse { string payload = 2; }"},{"id":"cli/generator/examples/go::proto::9","title":"Go","section":"Пример proto‑сервиса","path":"/docs/guide/cli/generator/examples/go#proto","headings":["Пример proto‑сервиса"],"excerpt":"Пример proto‑сервиса message EchoStreamRequest { string payload = 1; }","content":"Пример proto‑сервиса message EchoStreamRequest { string payload = 1; }"},{"id":"cli/generator/examples/go::proto::10","title":"Go","section":"Пример proto‑сервиса","path":"/docs/guide/cli/generator/examples/go#proto","headings":["Пример proto‑сервиса"],"excerpt":"Пример proto‑сервиса message EchoStreamResponse { string payload = 2; } ```","content":"Пример proto‑сервиса message EchoStreamResponse { string payload = 2; } ```"},{"id":"cli/generator/examples/go::top::11","title":"Go","section":"Настройка конфигурации","path":"/docs/guide/cli/generator/examples/go","headings":["Настройка конфигурации"],"excerpt":"Настройка конфигурации Создайте и настройте файл конфигурации easyp.yaml:","content":"Настройка конфигурации Создайте и настройте файл конфигурации easyp.yaml:"},{"id":"cli/generator/examples/go::top::12","title":"Go","section":"Настройка конфигурации","path":"/docs/guide/cli/generator/examples/go","headings":["Настройка конфигурации"],"excerpt":"Настройка конфигурации Этот файл указывает использование двух плагинов: go для генерации Go-кода и go-grpc для генерации gRPC-кода, вместе с их опциями.","content":"Настройка конфигурации Этот файл указывает использование двух плагинов: go для генерации Go-кода и go-grpc для генерации gRPC-кода, вместе с их опциями."},{"id":"cli/generator/examples/go::top::13","title":"Go","section":"Генерация кода","path":"/docs/guide/cli/generator/examples/go","headings":["Генерация кода"],"excerpt":"Генерация кода Чтобы сгенерировать код, выполните команду:","content":"Генерация кода Чтобы сгенерировать код, выполните команду:"},{"id":"cli/generator/examples/go::top::14","title":"Go","section":"Генерация кода","path":"/docs/guide/cli/generator/examples/go","headings":["Генерация кода"],"excerpt":"Генерация кода Если флаг --cfg не указан, по умолчанию используется файл easyp.yaml в текущей директории:","content":"Генерация кода Если флаг --cfg не указан, по умолчанию используется файл easyp.yaml в текущей директории:"},{"id":"cli/generator/examples/go::top::15","title":"Go","section":"Генерация кода","path":"/docs/guide/cli/generator/examples/go","headings":["Генерация кода"],"excerpt":"Генерация кода Теперь у вас есть сгенерированный Go‑код, с которым можно напрямую работать.","content":"Генерация кода Теперь у вас есть сгенерированный Go‑код, с которым можно напрямую работать."},{"id":"cli/generator/examples/grpc-gateway::top::0","title":"gRPC-Gateway","section":"Установка плагинов","path":"/docs/guide/cli/generator/examples/grpc-gateway","headings":["Установка плагинов"],"excerpt":"Установка плагинов В дополнение к плагинам для работы с gRPC, необходимо установить следующие плагины для gRPC-Gateway:","content":"Установка плагинов В дополнение к плагинам для работы с gRPC, необходимо установить следующие плагины для gRPC-Gateway:"},{"id":"cli/generator/examples/grpc-gateway::top::1","title":"gRPC-Gateway","section":"Установка плагинов","path":"/docs/guide/cli/generator/examples/grpc-gateway","headings":["Установка плагинов"],"excerpt":"Установка плагинов go install google.golang.org/protobuf/cmd/protoc-gen-go@latest go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest go install github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2@","content":"Установка плагинов go install google.golang.org/protobuf/cmd/protoc-gen-go@latest go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest go install github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2@latest go install github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway@latest"},{"id":"cli/generator/examples/grpc-gateway::top::2","title":"gRPC-Gateway","section":"Установка плагинов","path":"/docs/guide/cli/generator/examples/grpc-gateway","headings":["Установка плагинов"],"excerpt":"Установка плагинов Эти команды установят плагины protoc-gen-go, protoc-gen-go-grpc, protoc-gen-openapiv2 и protoc-gen-grpc-gateway для использования с EasyP.","content":"Установка плагинов Эти команды установят плагины protoc-gen-go, protoc-gen-go-grpc, protoc-gen-openapiv2 и protoc-gen-grpc-gateway для использования с EasyP."},{"id":"cli/generator/examples/grpc-gateway::proto::3","title":"gRPC-Gateway","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/grpc-gateway#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса Ниже — исходный proto‑файл для сервиса Echo:","content":"Пример Proto сервиса Ниже — исходный proto‑файл для сервиса Echo:"},{"id":"cli/generator/examples/grpc-gateway::proto::4","title":"gRPC-Gateway","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/grpc-gateway#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса syntax = \"proto3\";","content":"Пример Proto сервиса syntax = \"proto3\";"},{"id":"cli/generator/examples/grpc-gateway::proto::5","title":"gRPC-Gateway","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/grpc-gateway#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса package api.echo.v1;","content":"Пример Proto сервиса package api.echo.v1;"},{"id":"cli/generator/examples/grpc-gateway::proto::6","title":"gRPC-Gateway","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/grpc-gateway#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса option go_package = \"github.com/easyp-tech/example/api/echo/v1;pb\";","content":"Пример Proto сервиса option go_package = \"github.com/easyp-tech/example/api/echo/v1;pb\";"},{"id":"cli/generator/examples/grpc-gateway::proto::7","title":"gRPC-Gateway","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/grpc-gateway#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса service EchoAPI { rpc Echo(EchoRequest) returns (EchoResponse); }","content":"Пример Proto сервиса service EchoAPI { rpc Echo(EchoRequest) returns (EchoResponse); }"},{"id":"cli/generator/examples/grpc-gateway::proto::8","title":"gRPC-Gateway","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/grpc-gateway#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса message EchoRequest { string payload = 1; }","content":"Пример Proto сервиса message EchoRequest { string payload = 1; }"},{"id":"cli/generator/examples/grpc-gateway::proto::9","title":"gRPC-Gateway","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/grpc-gateway#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса message EchoResponse { string payload = 2; }","content":"Пример Proto сервиса message EchoResponse { string payload = 2; }"},{"id":"cli/generator/examples/grpc-gateway::proto::10","title":"gRPC-Gateway","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/grpc-gateway#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса Чтобы использовать gRPC-Gateway, обновите proto‑файл, добавив HTTP‑опции:","content":"Пример Proto сервиса Чтобы использовать gRPC-Gateway, обновите proto‑файл, добавив HTTP‑опции:"},{"id":"cli/generator/examples/grpc-gateway::proto::11","title":"gRPC-Gateway","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/grpc-gateway#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса syntax = \"proto3\"; import \"google/api/annotations.proto\";","content":"Пример Proto сервиса syntax = \"proto3\"; import \"google/api/annotations.proto\";"},{"id":"cli/generator/examples/grpc-gateway::proto::12","title":"gRPC-Gateway","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/grpc-gateway#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса package api.echo.v1;","content":"Пример Proto сервиса package api.echo.v1;"},{"id":"cli/generator/examples/grpc-gateway::proto::13","title":"gRPC-Gateway","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/grpc-gateway#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса option go_package = \"github.com/easyp-tech/example/api/echo/v1;pb\";","content":"Пример Proto сервиса option go_package = \"github.com/easyp-tech/example/api/echo/v1;pb\";"},{"id":"cli/generator/examples/grpc-gateway::proto::14","title":"gRPC-Gateway","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/grpc-gateway#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса service EchoAPI { rpc Echo(EchoRequest) returns (EchoResponse) { option (google.api.http) = { // [!code ++] post: \"/api/v1/echo\" // [!code ++] body: \"*\" // [!code ++] }; // [!code ++] } }","content":"Пример Proto сервиса 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::proto::15","title":"gRPC-Gateway","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/grpc-gateway#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса message EchoRequest { string payload = 1; }","content":"Пример Proto сервиса message EchoRequest { string payload = 1; }"},{"id":"cli/generator/examples/grpc-gateway::proto::16","title":"gRPC-Gateway","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/grpc-gateway#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса message EchoResponse { string payload = 2; }","content":"Пример Proto сервиса message EchoResponse { string payload = 2; }"},{"id":"cli/generator/examples/grpc-gateway::top::17","title":"gRPC-Gateway","section":"Настройка конфигурации","path":"/docs/guide/cli/generator/examples/grpc-gateway","headings":["Настройка конфигурации"],"excerpt":"Настройка конфигурации Обновите файл easyp.yaml, добавив необходимые зависимости и плагины: deps: # [!code ++] - github.com/googleapis/googleapis # [!code ++]","content":"Настройка конфигурации Обновите файл easyp.yaml, добавив необходимые зависимости и плагины: deps: # [!code ++] - github.com/googleapis/googleapis # [!code ++]"},{"id":"cli/generator/examples/grpc-gateway::top::18","title":"gRPC-Gateway","section":"Настройка конфигурации","path":"/docs/guide/cli/generator/examples/grpc-gateway","headings":["Настройка конфигурации"],"excerpt":"Настройка конфигурации 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":"Настройка конфигурации 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::top::19","title":"gRPC-Gateway","section":"Настройка конфигурации","path":"/docs/guide/cli/generator/examples/grpc-gateway","headings":["Настройка конфигурации"],"excerpt":"Настройка конфигурации Секция deps перечисляет зависимости, необходимые для импортов proto‑файлов. В данном случае добавляем github.com/googleapis/googleapis, поскольку там находится файл annotations.proto, используемый ","content":"Настройка конфигурации Секция deps перечисляет зависимости, необходимые для импортов proto‑файлов. В данном случае добавляем github.com/googleapis/googleapis, поскольку там находится файл annotations.proto, используемый в определении сервиса."},{"id":"cli/generator/examples/grpc-gateway::top::20","title":"gRPC-Gateway","section":"Обновление зависимостей","path":"/docs/guide/cli/generator/examples/grpc-gateway","headings":["Обновление зависимостей"],"excerpt":"Обновление зависимостей После обновления конфигурации выполните команду для загрузки указанных зависимостей:","content":"Обновление зависимостей После обновления конфигурации выполните команду для загрузки указанных зависимостей:"},{"id":"cli/generator/examples/grpc-gateway::top::21","title":"gRPC-Gateway","section":"Обновление зависимостей","path":"/docs/guide/cli/generator/examples/grpc-gateway","headings":["Обновление зависимостей"],"excerpt":"Обновление зависимостей easyp mod update","content":"Обновление зависимостей easyp mod update"},{"id":"cli/generator/examples/grpc-gateway::top::22","title":"gRPC-Gateway","section":"Обновление зависимостей","path":"/docs/guide/cli/generator/examples/grpc-gateway","headings":["Обновление зависимостей"],"excerpt":"Обновление зависимостей Больше деталей по управлению зависимостями см. в разделе Package Manager.","content":"Обновление зависимостей Больше деталей по управлению зависимостями см. в разделе Package Manager."},{"id":"cli/generator/examples/grpc-gateway::top::23","title":"gRPC-Gateway","section":"Генерация кода","path":"/docs/guide/cli/generator/examples/grpc-gateway","headings":["Генерация кода"],"excerpt":"Генерация кода Для генерации кода используйте:","content":"Генерация кода Для генерации кода используйте:"},{"id":"cli/generator/examples/grpc-gateway::top::24","title":"gRPC-Gateway","section":"Генерация кода","path":"/docs/guide/cli/generator/examples/grpc-gateway","headings":["Генерация кода"],"excerpt":"Генерация кода easyp --cfg easyp.yaml generate","content":"Генерация кода easyp --cfg easyp.yaml generate"},{"id":"cli/generator/examples/grpc-gateway::top::25","title":"gRPC-Gateway","section":"Генерация кода","path":"/docs/guide/cli/generator/examples/grpc-gateway","headings":["Генерация кода"],"excerpt":"Генерация кода Если флаг --cfg не указан, по умолчанию используется файл easyp.yaml из текущей директории:","content":"Генерация кода Если флаг --cfg не указан, по умолчанию используется файл easyp.yaml из текущей директории:"},{"id":"cli/generator/examples/grpc-gateway::top::26","title":"gRPC-Gateway","section":"Генерация кода","path":"/docs/guide/cli/generator/examples/grpc-gateway","headings":["Генерация кода"],"excerpt":"Генерация кода Теперь у вас сгенерированы Go‑код и код gRPC-Gateway, с которыми можно работать напрямую.","content":"Генерация кода Теперь у вас сгенерированы Go‑код и код gRPC-Gateway, с которыми можно работать напрямую."},{"id":"cli/generator/examples/validate::top::0","title":"Validate","section":"Установка плагинов","path":"/docs/guide/cli/generator/examples/validate","headings":["Установка плагинов"],"excerpt":"Установка плагинов Сначала установите необходимые плагины для работы с gRPC и проверок (validate):","content":"Установка плагинов Сначала установите необходимые плагины для работы с gRPC и проверок (validate):"},{"id":"cli/generator/examples/validate::top::1","title":"Validate","section":"Установка плагинов","path":"/docs/guide/cli/generator/examples/validate","headings":["Установка плагинов"],"excerpt":"Установка плагинов Эти команды установят плагины protoc-gen-go, protoc-gen-go-grpc и protoc-gen-validate для использования вместе с EasyP.","content":"Установка плагинов Эти команды установят плагины protoc-gen-go, protoc-gen-go-grpc и protoc-gen-validate для использования вместе с EasyP."},{"id":"cli/generator/examples/validate::proto::2","title":"Validate","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/validate#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса Ниже пример proto‑файла для сервиса Echo:","content":"Пример Proto сервиса Ниже пример proto‑файла для сервиса Echo:"},{"id":"cli/generator/examples/validate::proto::3","title":"Validate","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/validate#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса ```proto syntax = \"proto3\";","content":"Пример Proto сервиса ```proto syntax = \"proto3\";"},{"id":"cli/generator/examples/validate::proto::4","title":"Validate","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/validate#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса package api.echo.v1;","content":"Пример Proto сервиса package api.echo.v1;"},{"id":"cli/generator/examples/validate::proto::5","title":"Validate","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/validate#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса import \"validate/validate.proto\";","content":"Пример Proto сервиса import \"validate/validate.proto\";"},{"id":"cli/generator/examples/validate::proto::6","title":"Validate","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/validate#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса option go_package = \"github.com/easyp-tech/example/api/echo/v1;pb\";","content":"Пример Proto сервиса option go_package = \"github.com/easyp-tech/example/api/echo/v1;pb\";"},{"id":"cli/generator/examples/validate::proto::7","title":"Validate","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/validate#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса service EchoAPI { rpc Echo(EchoRequest) returns (EchoResponse); rpc EchoStream(EchoStreamRequest) returns (EchoResponse); }","content":"Пример Proto сервиса service EchoAPI { rpc Echo(EchoRequest) returns (EchoResponse); rpc EchoStream(EchoStreamRequest) returns (EchoResponse); }"},{"id":"cli/generator/examples/validate::proto::8","title":"Validate","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/validate#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса message EchoRequest { string payload = 1 [(validate.rules).string = {max_len: 200}]; }","content":"Пример Proto сервиса message EchoRequest { string payload = 1 [(validate.rules).string = {max_len: 200}]; }"},{"id":"cli/generator/examples/validate::proto::9","title":"Validate","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/validate#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса message EchoResponse { string payload = 2; }","content":"Пример Proto сервиса message EchoResponse { string payload = 2; }"},{"id":"cli/generator/examples/validate::proto::10","title":"Validate","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/validate#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса message EchoStreamRequest { string payload = 1 [(validate.rules).string = {max_len: 200}]; }","content":"Пример Proto сервиса message EchoStreamRequest { string payload = 1 [(validate.rules).string = {max_len: 200}]; }"},{"id":"cli/generator/examples/validate::proto::11","title":"Validate","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/validate#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса message EchoStreamResponse { string payload = 2; } ```","content":"Пример Proto сервиса message EchoStreamResponse { string payload = 2; } ```"},{"id":"cli/generator/examples/validate::top::12","title":"Validate","section":"Настройка конфигурации","path":"/docs/guide/cli/generator/examples/validate","headings":["Настройка конфигурации"],"excerpt":"Настройка конфигурации Создайте и настройте файл конфигурации easyp.yaml:","content":"Настройка конфигурации Создайте и настройте файл конфигурации easyp.yaml:"},{"id":"cli/generator/examples/validate::top::13","title":"Validate","section":"Настройка конфигурации","path":"/docs/guide/cli/generator/examples/validate","headings":["Настройка конфигурации"],"excerpt":"Настройка конфигурации ```yaml deps: # [!code ++] - github.com/bufbuild/protoc-gen-validate # [!code ++]","content":"Настройка конфигурации ```yaml deps: # [!code ++] - github.com/bufbuild/protoc-gen-validate # [!code ++]"},{"id":"cli/generator/examples/validate::top::14","title":"Validate","section":"Настройка конфигурации","path":"/docs/guide/cli/generator/examples/validate","headings":["Настройка конфигурации"],"excerpt":"Настройка конфигурации 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: sourc","content":"Настройка конфигурации 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::top::15","title":"Validate","section":"Генерация кода","path":"/docs/guide/cli/generator/examples/validate","headings":["Генерация кода"],"excerpt":"Генерация кода Чтобы сгенерировать код, выполните команду:","content":"Генерация кода Чтобы сгенерировать код, выполните команду:"},{"id":"cli/generator/examples/validate::top::16","title":"Validate","section":"Генерация кода","path":"/docs/guide/cli/generator/examples/validate","headings":["Генерация кода"],"excerpt":"Генерация кода Если флаг --cfg не указан, по умолчанию используется файл easyp.yaml из текущего каталога:","content":"Генерация кода Если флаг --cfg не указан, по умолчанию используется файл easyp.yaml из текущего каталога:"},{"id":"cli/generator/examples/validate::top::17","title":"Validate","section":"Генерация кода","path":"/docs/guide/cli/generator/examples/validate","headings":["Генерация кода"],"excerpt":"Генерация кода Теперь у вас есть сгенерированный Go‑код с поддержкой валидации, и вы можете напрямую использовать его в проекте.","content":"Генерация кода Теперь у вас есть сгенерированный Go‑код с поддержкой валидации, и вы можете напрямую использовать его в проекте."},{"id":"cli/generator/generator::top::0","title":"Генератор","path":"/docs/guide/cli/generator/generator","headings":[],"excerpt":"EasyP включает мощный генератор, который упрощает процесс получения кода из proto‑файлов. Благодаря YAML‑конфигурациям работа становится гораздо более удобной и интуитивной по сравнению с прямым использованием команды pr","content":"EasyP включает мощный генератор, который упрощает процесс получения кода из proto‑файлов. Благодаря YAML‑конфигурациям работа становится гораздо более удобной и интуитивной по сравнению с прямым использованием команды protoc."},{"id":"cli/generator/generator::top::1","title":"Генератор","section":"Ключевые особенности генератора","path":"/docs/guide/cli/generator/generator","headings":["Ключевые особенности генератора"],"excerpt":"Ключевые особенности генератора **Упрощённая генерация кода**: - Генерация кода из proto через декларативную YAML‑конфигурацию. - Избавляет от необходимости писать длинные и сложные команды protoc.","content":"Ключевые особенности генератора **Упрощённая генерация кода**: - Генерация кода из proto через декларативную YAML‑конфигурацию. - Избавляет от необходимости писать длинные и сложные команды protoc."},{"id":"cli/generator/generator::top::2","title":"Генератор","section":"Ключевые особенности генератора","path":"/docs/guide/cli/generator/generator","headings":["Ключевые особенности генератора"],"excerpt":"Ключевые особенности генератора **Обёртка над protoc**: - EasyP выступает как удобный слой над protoc, предоставляя декларативный API. - Поддерживает все опции и плагины, доступные protoc.","content":"Ключевые особенности генератора **Обёртка над protoc**: - EasyP выступает как удобный слой над protoc, предоставляя декларативный API. - Поддерживает все опции и плагины, доступные protoc."},{"id":"cli/generator/generator::top::3","title":"Генератор","section":"Ключевые особенности генератора","path":"/docs/guide/cli/generator/generator","headings":["Ключевые особенности генератора"],"excerpt":"Ключевые особенности генератора **Гибкость и кастомизация**: - Используются те же параметры, что и у плагинов protoc, прямо в конфиге. - Поддерживается множество плагинов и их параметры в одной конфигурации.","content":"Ключевые особенности генератора **Гибкость и кастомизация**: - Используются те же параметры, что и у плагинов protoc, прямо в конфиге. - Поддерживается множество плагинов и их параметры в одной конфигурации."},{"id":"cli/generator/generator::top::4","title":"Генератор","section":"Ключевые особенности генератора","path":"/docs/guide/cli/generator/generator","headings":["Ключевые особенности генератора"],"excerpt":"Ключевые особенности генератора **Генерация из нескольких источников**: - Локальные директории и удалённые Git‑репозитории одновременно. - Лёгкая интеграция с существующими проектами и репозиториями.","content":"Ключевые особенности генератора **Генерация из нескольких источников**: - Локальные директории и удалённые Git‑репозитории одновременно. - Лёгкая интеграция с существующими проектами и репозиториями."},{"id":"cli/generator/generator::top::5","title":"Генератор","section":"Ключевые особенности генератора","path":"/docs/guide/cli/generator/generator","headings":["Ключевые особенности генератора"],"excerpt":"Ключевые особенности генератора **Удалённая генерация**: - Генерация из удалённых Git репозиториев без локального checkout.","content":"Ключевые особенности генератора **Удалённая генерация**: - Генерация из удалённых Git репозиториев без локального checkout."},{"id":"cli/generator/generator::top::6","title":"Генератор","section":"Ключевые особенности генератора","path":"/docs/guide/cli/generator/generator","headings":["Ключевые особенности генератора"],"excerpt":"Ключевые особенности генератора **Интеграция с менеджером пакетов**: - Прозрачная работа с зависимостями через пакетный менеджер EasyP. - Автоматическое разрешение и подключение proto‑зависимостей.","content":"Ключевые особенности генератора **Интеграция с менеджером пакетов**: - Прозрачная работа с зависимостями через пакетный менеджер EasyP. - Автоматическое разрешение и подключение proto‑зависимостей."},{"id":"cli/generator/generator::complete-configuration-example::7","title":"Генератор","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":"Генератор","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":"Генератор","section":"Complete Configuration Example","path":"/docs/guide/cli/generator/generator#complete-configuration-example","headings":["Complete Configuration Example"],"excerpt":"Complete Configuration Example Managed mode - автоматическая установка file и field опций managed: enabled: true disable: - module: github.com/googleapis/googleapis # Отключить для конкретного модуля override: - file_opt","content":"Complete Configuration Example Managed mode - автоматическая установка file и field опций managed: enabled: true disable: - module: github.com/googleapis/googleapis # Отключить для конкретного модуля 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/ # Применить к конкретному пути"},{"id":"cli/generator/generator::complete-configuration-example::10","title":"Генератор","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":"Генератор","section":"Локальный ввод (Local Directory Input)","path":"/docs/guide/cli/generator/generator#local-directory-input","headings":["Локальный ввод (Local Directory Input)"],"excerpt":"Локальный ввод (Local Directory Input) Локальная директория — самый распространённый и простой способ указать откуда брать proto для генерации. Используйте этот вариант, если файлы уже находятся в репозитории проекта.","content":"Локальный ввод (Local Directory Input) Локальная директория — самый распространённый и простой способ указать откуда брать proto для генерации. Используйте этот вариант, если файлы уже находятся в репозитории проекта."},{"id":"cli/generator/generator::local-directory-input::12","title":"Генератор","section":"Локальный ввод (Local Directory Input)","path":"/docs/guide/cli/generator/generator#local-directory-input","headings":["Локальный ввод (Local Directory Input)"],"excerpt":"Локальный ввод (Local Directory Input) **Когда применять:** Proto файлы находятся в кодовой базе проекта Нужен полный контроль над структурой каталогов Проект — один сервис или приложение Файлы меняются не слишком часто","content":"Локальный ввод (Local Directory Input) **Когда применять:** Proto файлы находятся в кодовой базе проекта Нужен полный контроль над структурой каталогов Проект — один сервис или приложение Файлы меняются не слишком часто"},{"id":"cli/generator/generator::local-directory-input::13","title":"Генератор","section":"Локальный ввод (Local Directory Input)","path":"/docs/guide/cli/generator/generator#local-directory-input","headings":["Локальный ввод (Local Directory Input)"],"excerpt":"Локальный ввод (Local Directory Input)","content":"Локальный ввод (Local Directory Input)"},{"id":"cli/generator/generator::local-directory-input::14","title":"Генератор","section":"Локальный ввод (Local Directory Input)","path":"/docs/guide/cli/generator/generator#local-directory-input","headings":["Локальный ввод (Local Directory Input)"],"excerpt":"Локальный ввод (Local Directory Input) Параметр root особенно полезен в монорепозиториях: он позволяет управлять тем, откуда будут резолвиться пути импортов. Если указать родительскую директорию, импорты будут оцениватьс","content":"Локальный ввод (Local Directory Input) Параметр root особенно полезен в монорепозиториях: он позволяет управлять тем, откуда будут резолвиться пути импортов. Если указать родительскую директорию, импорты будут оцениваться относительно неё, а не текущего рабочего каталога."},{"id":"cli/generator/generator::local-directory-input::15","title":"Генератор","section":"Локальный ввод (Local Directory Input)","path":"/docs/guide/cli/generator/generator#local-directory-input","headings":["Локальный ввод (Local Directory Input)"],"excerpt":"Локальный ввод (Local Directory Input) **Параметры:**","content":"Локальный ввод (Local Directory Input) **Параметры:**"},{"id":"cli/generator/generator::local-directory-input::16","title":"Генератор","section":"Локальный ввод (Local Directory Input)","path":"/docs/guide/cli/generator/generator#local-directory-input","headings":["Локальный ввод (Local Directory Input)"],"excerpt":"Локальный ввод (Local Directory Input) Параметр Тип Обязателен Значение по умолчанию Описание ---------- ----- ------------ ----------------------- ---------- path string ✅ - Каталог, содержащий proto файлы root string ❌","content":"Локальный ввод (Local Directory Input) Параметр Тип Обязателен Значение по умолчанию Описание ---------- ----- ------------ ----------------------- ---------- path string ✅ - Каталог, содержащий proto файлы root string ❌ \".\" Корневая директория для разрешения import путей"},{"id":"cli/generator/generator::local-directory-input::17","title":"Генератор","section":"Локальный ввод (Local Directory Input)","path":"/docs/guide/cli/generator/generator#local-directory-input","headings":["Локальный ввод (Local Directory Input)"],"excerpt":"Локальный ввод (Local Directory Input) **Примеры:**","content":"Локальный ввод (Local Directory Input) **Примеры:**"},{"id":"cli/generator/generator::local-directory-input::18","title":"Генератор","section":"Локальный ввод (Local Directory Input)","path":"/docs/guide/cli/generator/generator#local-directory-input","headings":["Локальный ввод (Local Directory Input)"],"excerpt":"Локальный ввод (Local Directory Input) Ниже показана разница между базовым указанием директории и расширенной конфигурацией с пользовательским корнем импортов:","content":"Локальный ввод (Local Directory Input) Ниже показана разница между базовым указанием директории и расширенной конфигурацией с пользовательским корнем импортов:"},{"id":"cli/generator/generator::local-directory-input::19","title":"Генератор","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::20","title":"Генератор","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::git-remote-git-repository-input::21","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) Этот тип входных данных позволяет генерировать код из proto‑файлов, находящихся в удалённых репозиториях, без локального checkout. Особенно полезно при использовани","content":"Удалённый Git репозиторий (Remote Git Repository Input) Этот тип входных данных позволяет генерировать код из proto‑файлов, находящихся в удалённых репозиториях, без локального checkout. Особенно полезно при использовании API других команд или внешних поставщиков."},{"id":"cli/generator/generator::git-remote-git-repository-input::22","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) **Когда использовать:** Потребление proto определений из других сервисов/команд Интеграция с внешними вендорскими API Работа с общими библиотеками proto в нескольки","content":"Удалённый Git репозиторий (Remote Git Repository Input) **Когда использовать:** Потребление proto определений из других сервисов/команд Интеграция с внешними вендорскими API Работа с общими библиотеками proto в нескольких проектах Необходимо гарантировать корректную (зафиксированную) версию внешних API"},{"id":"cli/generator/generator::git-remote-git-repository-input::23","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) **Рекомендации:** В продакшене всегда фиксируйте версии (@v1.0.0, а не latest) Используйте семантические версии при наличии — проще сопровождать Предпочитайте публи","content":"Удалённый Git репозиторий (Remote Git Repository Input) **Рекомендации:** В продакшене всегда фиксируйте версии (@v1.0.0, а не latest) Используйте семантические версии при наличии — проще сопровождать Предпочитайте публичные теги вместо хеша коммита (лучше отслеживаемость)"},{"id":"cli/generator/generator::git-remote-git-repository-input::24","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input)","content":"Удалённый Git репозиторий (Remote Git Repository Input)"},{"id":"cli/generator/generator::git-remote-git-repository-input::25","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) Параметр root задаёт корень для разрешения импортов файлов из этого репозитория.","content":"Удалённый Git репозиторий (Remote Git Repository Input) Параметр root задаёт корень для разрешения импортов файлов из этого репозитория."},{"id":"cli/generator/generator::git-remote-git-repository-input::26","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) **Параметры:**","content":"Удалённый Git репозиторий (Remote Git Repository Input) **Параметры:**"},{"id":"cli/generator/generator::git-remote-git-repository-input::27","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) Параметр Тип Обязателен По умолчанию Описание ---------- ----- ------------ -------------- ---------- url string ✅ - URL Git репозитория с необязательной версией / ","content":"Удалённый Git репозиторий (Remote Git Repository Input) Параметр Тип Обязателен По умолчанию Описание ---------- ----- ------------ -------------- ---------- url string ✅ - URL Git репозитория с необязательной версией / тегом / коммитом sub_directory string ❌ \"\" Поддиректория внутри репозитория, где лежат proto root string ❌ \"\" Корневой путь для разрешения импортов"},{"id":"cli/generator/generator::git-remote-git-repository-input::28","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) **Варианты формата URL:**","content":"Удалённый Git репозиторий (Remote Git Repository Input) **Варианты формата URL:**"},{"id":"cli/generator/generator::git-remote-git-repository-input::29","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) EasyP поддерживает несколько форматов для ссылки на удалённые репозитории. Каждый подходит под разные требования по стабильности:","content":"Удалённый Git репозиторий (Remote Git Repository Input) EasyP поддерживает несколько форматов для ссылки на удалённые репозитории. Каждый подходит под разные требования по стабильности:"},{"id":"cli/generator/generator::git-remote-git-repository-input::30","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) **Tagged versions** — для продакшена, стабильные неизменяемые ссылки **Semantic versions** — читаемость и управление зависимостями **Commit hashes** — доступ к конк","content":"Удалённый Git репозиторий (Remote Git Repository Input) **Tagged versions** — для продакшена, стабильные неизменяемые ссылки **Semantic versions** — читаемость и управление зависимостями **Commit hashes** — доступ к конкретному коммиту, если нет тега **Latest** — только для разработки, непредсказуемо **Full HTTPS URLs** — приватные репозитории или нестандартный хостинг"},{"id":"cli/generator/generator::git-remote-git-repository-input::31","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) ```yaml Тег — стабильно для продакшена url: \"github.com/googleapis/googleapis@common-protos-1_3_1\"","content":"Удалённый Git репозиторий (Remote Git Repository Input) ```yaml Тег — стабильно для продакшена url: \"github.com/googleapis/googleapis@common-protos-1_3_1\""},{"id":"cli/generator/generator::git-remote-git-repository-input::32","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) Семантическая версия url: \"github.com/grpc-ecosystem/grpc-gateway@v2.19.1\"","content":"Удалённый Git репозиторий (Remote Git Repository Input) Семантическая версия url: \"github.com/grpc-ecosystem/grpc-gateway@v2.19.1\""},{"id":"cli/generator/generator::git-remote-git-repository-input::33","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) Хеш коммита — точечный фикс url: \"github.com/company/protos@abc123def456\"","content":"Удалённый Git репозиторий (Remote Git Repository Input) Хеш коммита — точечный фикс url: \"github.com/company/protos@abc123def456\""},{"id":"cli/generator/generator::git-remote-git-repository-input::34","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) Latest — только dev, НЕ для продакшена url: \"github.com/company/protos\"","content":"Удалённый Git репозиторий (Remote Git Repository Input) Latest — только dev, НЕ для продакшена url: \"github.com/company/protos\""},{"id":"cli/generator/generator::git-remote-git-repository-input::35","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) Полный HTTPS URL — приватный или кастомный Git url: \"https://github.com/company/private-protos.git\" ```","content":"Удалённый Git репозиторий (Remote Git Repository Input) Полный HTTPS URL — приватный или кастомный Git url: \"https://github.com/company/private-protos.git\" ```"},{"id":"cli/generator/generator::git-remote-git-repository-input::36","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) **Примеры:**","content":"Удалённый Git репозиторий (Remote Git Repository Input) **Примеры:**"},{"id":"cli/generator/generator::git-remote-git-repository-input::37","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) Ниже паттерны использования удалённых источников в разных сценариях:","content":"Удалённый Git репозиторий (Remote Git Repository Input) Ниже паттерны использования удалённых источников в разных сценариях:"},{"id":"cli/generator/generator::git-remote-git-repository-input::38","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input)","content":"Удалённый Git репозиторий (Remote Git Repository Input)"},{"id":"cli/generator/generator::top::39","title":"Генератор","section":"Конфигурация плагинов","path":"/docs/guide/cli/generator/generator","headings":["Конфигурация плагинов"],"excerpt":"Конфигурация плагинов Конфигурация плагинов определяет какие генераторы кода будут запущены и как они себя ведут. EasyP поддерживает любой плагин protoc, что делает его крайне гибким для разных языковых экосистем и сцена","content":"Конфигурация плагинов Конфигурация плагинов определяет какие генераторы кода будут запущены и как они себя ведут. EasyP поддерживает любой плагин protoc, что делает его крайне гибким для разных языковых экосистем и сценариев."},{"id":"cli/generator/generator::top::40","title":"Генератор","section":"Конфигурация плагинов","path":"/docs/guide/cli/generator/generator","headings":["Конфигурация плагинов"],"excerpt":"Конфигурация плагинов На верхнем уровне есть **четыре способа указать, как именно запускать плагин**:","content":"Конфигурация плагинов На верхнем уровне есть **четыре способа указать, как именно запускать плагин**:"},{"id":"cli/generator/generator::top::41","title":"Генератор","section":"Конфигурация плагинов","path":"/docs/guide/cli/generator/generator","headings":["Конфигурация плагинов"],"excerpt":"Конфигурация плагинов **name** – запуск плагина по имени из PATH или использование встроенного плагина. **path** – запуск плагина по абсолютному/относительному пути к исполняемому файлу. **remote** – удалённый плагин по ","content":"Конфигурация плагинов **name** – запуск плагина по имени из PATH или использование встроенного плагина. **path** – запуск плагина по абсолютному/относительному пути к исполняемому файлу. **remote** – удалённый плагин по URL (через remote‑executor EasyP). **command** – запуск плагина через произвольную команду (например, go run ...)."},{"id":"cli/generator/generator::top::42","title":"Генератор","section":"Конфигурация плагинов","path":"/docs/guide/cli/generator/generator","headings":["Конфигурация плагинов"],"excerpt":"Конфигурация плагинов Для каждого плагина должен быть указан **ровно один** из параметров name, path, remote или command.","content":"Конфигурация плагинов Для каждого плагина должен быть указан **ровно один** из параметров name, path, remote или command."},{"id":"cli/generator/generator::name::43","title":"Генератор","section":"Плагин по имени (name)","path":"/docs/guide/cli/generator/generator#name","headings":["Плагин по имени (name)"],"excerpt":"Плагин по имени (name) Локальный режим по имени — стандартный: плагины установлены в системе и запускаются напрямую через EasyP.","content":"Плагин по имени (name) Локальный режим по имени — стандартный: плагины установлены в системе и запускаются напрямую через EasyP."},{"id":"cli/generator/generator::name::44","title":"Генератор","section":"Плагин по имени (name)","path":"/docs/guide/cli/generator/generator#name","headings":["Плагин по имени (name)"],"excerpt":"Плагин по имени (name) **Когда использовать name:** Стандартные языки (Go, Python, TypeScript и т.д.) Есть контроль над окружением сборки Критична производительность (нет сетевых задержек) Хочется опираться на PATH или в","content":"Плагин по имени (name) **Когда использовать name:** Стандартные языки (Go, Python, TypeScript и т.д.) Есть контроль над окружением сборки Критична производительность (нет сетевых задержек) Хочется опираться на PATH или встроенные плагины"},{"id":"cli/generator/generator::name::45","title":"Генератор","section":"Плагин по имени (name)","path":"/docs/guide/cli/generator/generator#name","headings":["Плагин по имени (name)"],"excerpt":"Плагин по имени (name) **Требования к установке:** Плагины установлены и доступны в PATH (если не используются встроенные). Имена следуют шаблону protoc-gen-{name}. Установка через менеджеры пакетов (go install, npm inst","content":"Плагин по имени (name) **Требования к установке:** Плагины установлены и доступны в PATH (если не используются встроенные). Имена следуют шаблону protoc-gen-{name}. Установка через менеджеры пакетов (go install, npm install, pip install и т.п.)."},{"id":"cli/generator/generator::name::46","title":"Генератор","section":"Плагин по имени (name)","path":"/docs/guide/cli/generator/generator#name","headings":["Плагин по имени (name)"],"excerpt":"Плагин по имени (name) Параметр with_imports критичен при использовании зависимостей из пакетного менеджера: установите true, чтобы прототипы из секции deps попали в генерацию.","content":"Плагин по имени (name) Параметр with_imports критичен при использовании зависимостей из пакетного менеджера: установите true, чтобы прототипы из секции deps попали в генерацию."},{"id":"cli/generator/generator::path::47","title":"Генератор","section":"Плагин по пути (path)","path":"/docs/guide/cli/generator/generator#path","headings":["Плагин по пути (path)"],"excerpt":"Плагин по пути (path) Иногда нужно запускать плагин из конкретного бинарника, не добавляя его в PATH (например, бинарь в репозитории или в build‑директории). В этом случае можно указать явный путь:","content":"Плагин по пути (path) Иногда нужно запускать плагин из конкретного бинарника, не добавляя его в PATH (например, бинарь в репозитории или в build‑директории). В этом случае можно указать явный путь:"},{"id":"cli/generator/generator::path::48","title":"Генератор","section":"Плагин по пути (path)","path":"/docs/guide/cli/generator/generator#path","headings":["Плагин по пути (path)"],"excerpt":"Плагин по пути (path) **Когда использовать path:** Бинарники плагинов хранятся в репозитории (для воспроизводимых сборок). Используются несколько версий одного и того же плагина параллельно. Не хочется «загрязнять» глоба","content":"Плагин по пути (path) **Когда использовать path:** Бинарники плагинов хранятся в репозитории (для воспроизводимых сборок). Используются несколько версий одного и того же плагина параллельно. Не хочется «загрязнять» глобальный PATH."},{"id":"cli/generator/generator::remote::49","title":"Генератор","section":"Удалённый плагин (remote)","path":"/docs/guide/cli/generator/generator#remote","headings":["Удалённый плагин (remote)"],"excerpt":"Удалённый плагин (remote) Удалённые плагины выполняются по URL. EasyP отправляет на удалённую сторону CodeGeneratorRequest и получает обратно CodeGeneratorResponse.","content":"Удалённый плагин (remote) Удалённые плагины выполняются по URL. EasyP отправляет на удалённую сторону CodeGeneratorRequest и получает обратно CodeGeneratorResponse."},{"id":"cli/generator/generator::remote::50","title":"Генератор","section":"Удалённый плагин (remote)","path":"/docs/guide/cli/generator/generator#remote","headings":["Удалённый плагин (remote)"],"excerpt":"Удалённый плагин (remote) Ниже приведён реальный пример использования EasyP API Service как удалённого исполнителя плагинов (тот же формат используется в разделе про API Service):","content":"Удалённый плагин (remote) Ниже приведён реальный пример использования EasyP API Service как удалённого исполнителя плагинов (тот же формат используется в разделе про API Service):"},{"id":"cli/generator/generator::remote::51","title":"Генератор","section":"Удалённый плагин (remote)","path":"/docs/guide/cli/generator/generator#remote","headings":["Удалённый плагин (remote)"],"excerpt":"Удалённый плагин (remote) ```yaml generate: plugins: # Удалённое выполнение плагинов через EasyP API Service - remote: api.easyp.tech/protobuf/go:v1.36.10 out: . opts: paths: source_relative","content":"Удалённый плагин (remote) ```yaml generate: plugins: # Удалённое выполнение плагинов через EasyP API Service - remote: api.easyp.tech/protobuf/go:v1.36.10 out: . opts: paths: source_relative"},{"id":"cli/generator/generator::remote::52","title":"Генератор","section":"Удалённый плагин (remote)","path":"/docs/guide/cli/generator/generator#remote","headings":["Удалённый плагин (remote)"],"excerpt":"Удалённый плагин (remote) remote: api.easyp.tech/grpc/go:v1.5.1 out: . opts: paths: source_relative ```","content":"Удалённый плагин (remote) remote: api.easyp.tech/grpc/go:v1.5.1 out: . opts: paths: source_relative ```"},{"id":"cli/generator/generator::remote::53","title":"Генератор","section":"Удалённый плагин (remote)","path":"/docs/guide/cli/generator/generator#remote","headings":["Удалённый плагин (remote)"],"excerpt":"Удалённый плагин (remote) **Типичные сценарии для remote:** Централизованный сервис плагинов внутри компании (например, EasyP API Service). Запуск тяжёлых плагинов на выделенных машинах вместо CI‑агентов. Совместное испо","content":"Удалённый плагин (remote) **Типичные сценарии для remote:** Централизованный сервис плагинов внутри компании (например, EasyP API Service). Запуск тяжёлых плагинов на выделенных машинах вместо CI‑агентов. Совместное использование одной реализации плагина разными командами."},{"id":"cli/generator/generator::command::54","title":"Генератор","section":"Выполнение плагина через команду (command)","path":"/docs/guide/cli/generator/generator#command","headings":["Выполнение плагина через команду (command)"],"excerpt":"Выполнение плагина через команду (command) Вы можете указать плагин как массив команд для выполнения. Это полезно для запуска плагинов через go run или любые другие инструменты без предварительной установки бинарника пла","content":"Выполнение плагина через команду (command) Вы можете указать плагин как массив команд для выполнения. Это полезно для запуска плагинов через go run или любые другие инструменты без предварительной установки бинарника плагина:"},{"id":"cli/generator/generator::command::55","title":"Генератор","section":"Выполнение плагина через команду (command)","path":"/docs/guide/cli/generator/generator#command","headings":["Выполнение плагина через команду (command)"],"excerpt":"Выполнение плагина через команду (command)","content":"Выполнение плагина через команду (command)"},{"id":"cli/generator/generator::command::56","title":"Генератор","section":"Выполнение плагина через команду (command)","path":"/docs/guide/cli/generator/generator#command","headings":["Выполнение плагина через команду (command)"],"excerpt":"Выполнение плагина через команду (command) В этом режиме EasyP: **запускает указанную команду** как дочерний процесс; **пишет CodeGeneratorRequest в stdin** процесса; **читает CodeGeneratorResponse из stdout**, как и для","content":"Выполнение плагина через команду (command) В этом режиме EasyP: **запускает указанную команду** как дочерний процесс; **пишет CodeGeneratorRequest в stdin** процесса; **читает CodeGeneratorResponse из stdout**, как и для обычных плагинов protoc."},{"id":"cli/generator/generator::command::57","title":"Генератор","section":"Выполнение плагина через команду (command)","path":"/docs/guide/cli/generator/generator#command","headings":["Выполнение плагина через команду (command)"],"excerpt":"Выполнение плагина через команду (command) **Приоритет источников плагина:** command — выполнение через указанную команду (наивысший приоритет) remote — удалённый плагин через URL name — локальный плагин из PATH или встр","content":"Выполнение плагина через команду (command) **Приоритет источников плагина:** command — выполнение через указанную команду (наивысший приоритет) remote — удалённый плагин через URL name — локальный плагин из PATH или встроенный плагин path — путь к исполняемому файлу плагина"},{"id":"cli/generator/generator::command::58","title":"Генератор","section":"Выполнение плагина через команду (command)","path":"/docs/guide/cli/generator/generator#command","headings":["Выполнение плагина через команду (command)"],"excerpt":"Выполнение плагина через команду (command) **Параметры (источники и общие опции плагина):**","content":"Выполнение плагина через команду (command) **Параметры (источники и общие опции плагина):**"},{"id":"cli/generator/generator::command::59","title":"Генератор","section":"Выполнение плагина через команду (command)","path":"/docs/guide/cli/generator/generator#command","headings":["Выполнение плагина через команду (command)"],"excerpt":"Выполнение плагина через команду (command) Параметр Тип Обязателен По умолчанию Описание ---------- ----- ------------ -------------- ---------- name string ❌ - Имя / идентификатор плагина (например, go, go-grpc, grpc-ga","content":"Выполнение плагина через команду (command) Параметр Тип Обязателен По умолчанию Описание ---------- ----- ------------ -------------- ---------- name string ❌ - Имя / идентификатор плагина (например, go, go-grpc, grpc-gateway) command []string ❌ - Команда для выполнения плагина (например, [\"go\", \"run\", \"package\"]) remote string ❌ - URL удалённого плагина path string ❌ - Путь к исполняемому файлу плагина out string ✅ - Директория для сгенерированных файлов opts mapstring ❌ {} Специфичные опции плагина; значения-списки передаются как повторяющиеся key=value with_imports bool ❌ false Включать proto из зависимостей"},{"id":"cli/generator/generator::command::60","title":"Генератор","section":"Выполнение плагина через команду (command)","path":"/docs/guide/cli/generator/generator#command","headings":["Выполнение плагина через команду (command)"],"excerpt":"Выполнение плагина через команду (command) **Примечание:** Для каждого плагина должен быть указан ровно один источник (name, command, remote или path). Если opts.outputServices задан как [\"grpc-js\", \"generic-definitions\"","content":"Выполнение плагина через команду (command) **Примечание:** Для каждого плагина должен быть указан ровно один источник (name, command, remote или path). Если opts.outputServices задан как [\"grpc-js\", \"generic-definitions\"], EasyP передаст outputServices=grpc-js,outputServices=generic-definitions."},{"id":"cli/generator/generator::command::61","title":"Генератор","section":"Выполнение плагина через команду (command)","path":"/docs/guide/cli/generator/generator#command","headings":["Выполнение плагина через команду (command)"],"excerpt":"Выполнение плагина через команду (command) **Примеры использования источника command:**","content":"Выполнение плагина через команду (command) **Примеры использования источника command:**"},{"id":"cli/generator/generator::command::62","title":"Генератор","section":"Выполнение плагина через команду (command)","path":"/docs/guide/cli/generator/generator#command","headings":["Выполнение плагина через команду (command)"],"excerpt":"Выполнение плагина через команду (command) ```yaml generate: inputs: - directory: \"proto\"","content":"Выполнение плагина через команду (command) ```yaml generate: inputs: - directory: \"proto\""},{"id":"cli/generator/generator::command::63","title":"Генератор","section":"Выполнение плагина через команду (command)","path":"/docs/guide/cli/generator/generator#command","headings":["Выполнение плагина через команду (command)"],"excerpt":"Выполнение плагина через команду (command) plugins: # 1) gRPC-Gateway через go run (без предварительной установки бинарника) - command: [\"go\", \"run\", \"github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway@v2.","content":"Выполнение плагина через команду (command) plugins: # 1) gRPC-Gateway через go run (без предварительной установки бинарника) - 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::command::64","title":"Генератор","section":"Выполнение плагина через команду (command)","path":"/docs/guide/cli/generator/generator#command","headings":["Выполнение плагина через команду (command)"],"excerpt":"Выполнение плагина через команду (command) 2) protoc-gen-validate через go run - command: [\"go\", \"run\", \"github.com/bufbuild/protoc-gen-validate@v0.10.1\"] out: ./gen/go opts: paths: source_relative lang: go","content":"Выполнение плагина через команду (command) 2) protoc-gen-validate через 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::command::65","title":"Генератор","section":"Выполнение плагина через команду (command)","path":"/docs/guide/cli/generator/generator#command","headings":["Выполнение плагина через команду (command)"],"excerpt":"Выполнение плагина через команду (command) 3) Произвольный кастомный скрипт-обёртка - command: [\"bash\", \"./scripts/custom-protoc-plugin.sh\"] out: ./gen/custom opts: foo: bar ```","content":"Выполнение плагина через команду (command) 3) Произвольный кастомный скрипт-обёртка - command: [\"bash\", \"./scripts/custom-protoc-plugin.sh\"] out: ./gen/custom opts: foo: bar ```"},{"id":"cli/generator/generator::builtin-plugins::66","title":"Генератор","section":"Встроенные плагины (Builtin Plugins)","path":"/docs/guide/cli/generator/generator#builtin-plugins","headings":["Встроенные плагины (Builtin Plugins)"],"excerpt":"Встроенные плагины (Builtin Plugins) EasyP поддерживает встроенные плагины для базовых языков protobuf и gRPC. Эти плагины встроены в бинарник как WASM-модули и не требуют установки внешних зависимостей.","content":"Встроенные плагины (Builtin Plugins) EasyP поддерживает встроенные плагины для базовых языков protobuf и gRPC. Эти плагины встроены в бинарник как WASM-модули и не требуют установки внешних зависимостей."},{"id":"cli/generator/generator::builtin-plugins::67","title":"Генератор","section":"Встроенные плагины (Builtin Plugins)","path":"/docs/guide/cli/generator/generator#builtin-plugins","headings":["Встроенные плагины (Builtin Plugins)"],"excerpt":"Встроенные плагины (Builtin Plugins) **Преимущества встроенных плагинов:** **Портативность**: Один бинарник со всеми необходимыми плагинами **Удобство**: Не требуется установка внешних зависимостей **Стабильность**: Верс","content":"Встроенные плагины (Builtin Plugins) **Преимущества встроенных плагинов:** **Портативность**: Один бинарник со всеми необходимыми плагинами **Удобство**: Не требуется установка внешних зависимостей **Стабильность**: Версии плагинов зафиксированы в бинарнике **Изоляция**: Не зависит от системных установок плагинов"},{"id":"cli/generator/generator::builtin-plugins::68","title":"Генератор","section":"Встроенные плагины (Builtin Plugins)","path":"/docs/guide/cli/generator/generator#builtin-plugins","headings":["Встроенные плагины (Builtin Plugins)"],"excerpt":"Встроенные плагины (Builtin Plugins) **Поддерживаемые встроенные плагины:**","content":"Встроенные плагины (Builtin Plugins) **Поддерживаемые встроенные плагины:**"},{"id":"cli/generator/generator::protobuf::69","title":"Генератор","section":"Protobuf базовые плагины","path":"/docs/guide/cli/generator/generator#protobuf","headings":["Protobuf базовые плагины"],"excerpt":"Protobuf базовые плагины Следующие плагины встроены для генерации базового protobuf кода:","content":"Protobuf базовые плагины Следующие плагины встроены для генерации базового protobuf кода:"},{"id":"cli/generator/generator::protobuf::70","title":"Генератор","section":"Protobuf базовые плагины","path":"/docs/guide/cli/generator/generator#protobuf","headings":["Protobuf базовые плагины"],"excerpt":"Protobuf базовые плагины Имя плагина Описание Соответствующий protoc плагин ------------- ---------- ------------------------------- cpp Генерация C++ кода из proto файлов protoc-gen-cpp csharp Генерация C# кода из proto","content":"Protobuf базовые плагины Имя плагина Описание Соответствующий protoc плагин ------------- ---------- ------------------------------- cpp Генерация C++ кода из proto файлов protoc-gen-cpp csharp Генерация C# кода из proto файлов protoc-gen-csharp java Генерация Java кода из proto файлов protoc-gen-java kotlin Генерация Kotlin кода из proto файлов protoc-gen-kotlin objc Генерация Objective-C кода из proto файлов protoc-gen-objc php Генерация PHP кода из proto файлов protoc-gen-php python Генерация Python кода из proto файлов protoc-gen-python ruby Генерация Ruby кода из proto файлов protoc-gen-ruby"},{"id":"cli/generator/generator::grpc::71","title":"Генератор","section":"gRPC плагины","path":"/docs/guide/cli/generator/generator#grpc","headings":["gRPC плагины"],"excerpt":"gRPC плагины Следующие плагины встроены для генерации gRPC кода:","content":"gRPC плагины Следующие плагины встроены для генерации gRPC кода:"},{"id":"cli/generator/generator::grpc::72","title":"Генератор","section":"gRPC плагины","path":"/docs/guide/cli/generator/generator#grpc","headings":["gRPC плагины"],"excerpt":"gRPC плагины Имя плагина Описание Соответствующий protoc плагин ------------- ---------- ------------------------------- grpc_cpp Генерация gRPC кода для C++ grpc_cpp_plugin grpc_csharp Генерация gRPC кода для C# grpc_cs","content":"gRPC плагины Имя плагина Описание Соответствующий protoc плагин ------------- ---------- ------------------------------- grpc_cpp Генерация gRPC кода для C++ grpc_cpp_plugin grpc_csharp Генерация gRPC кода для C# grpc_csharp_plugin grpc_java Генерация gRPC кода для Java grpc_java_plugin grpc_node Генерация gRPC кода для Node.js grpc_node_plugin grpc_objc Генерация gRPC кода для Objective-C grpc_objective_c_plugin grpc_php Генерация gRPC кода для PHP grpc_php_plugin grpc_python Генерация gRPC кода для Python grpc_python_plugin grpc_ruby Генерация gRPC кода для Ruby grpc_ruby_plugin"},{"id":"cli/generator/generator::grpc::73","title":"Генератор","section":"gRPC плагины","path":"/docs/guide/cli/generator/generator#grpc","headings":["gRPC плагины"],"excerpt":"gRPC плагины **Логика выбора плагина:**","content":"gRPC плагины **Логика выбора плагина:**"},{"id":"cli/generator/generator::grpc::74","title":"Генератор","section":"gRPC плагины","path":"/docs/guide/cli/generator/generator#grpc","headings":["gRPC плагины"],"excerpt":"gRPC плагины EasyP использует следующий приоритет при выборе executor'а для плагина:","content":"gRPC плагины EasyP использует следующий приоритет при выборе executor'а для плагина:"},{"id":"cli/generator/generator::grpc::75","title":"Генератор","section":"gRPC плагины","path":"/docs/guide/cli/generator/generator#grpc","headings":["gRPC плагины"],"excerpt":"gRPC плагины **Удалённый плагин** (если указан url) — всегда имеет наивысший приоритет **Встроенный плагин** (если плагин встроен и не найден в PATH) — используется автоматически **Локальный плагин** (из PATH) — использу","content":"gRPC плагины **Удалённый плагин** (если указан url) — всегда имеет наивысший приоритет **Встроенный плагин** (если плагин встроен и не найден в PATH) — используется автоматически **Локальный плагин** (из PATH) — используется по умолчанию для обратной совместимости"},{"id":"cli/generator/generator::grpc::76","title":"Генератор","section":"gRPC плагины","path":"/docs/guide/cli/generator/generator#grpc","headings":["gRPC плагины"],"excerpt":"gRPC плагины **Пример использования:**","content":"gRPC плагины **Пример использования:**"},{"id":"cli/generator/generator::grpc::77","title":"Генератор","section":"gRPC плагины","path":"/docs/guide/cli/generator/generator#grpc","headings":["gRPC плагины"],"excerpt":"gRPC плагины Встроенные плагины включены в бинарник EasyP:","content":"gRPC плагины Встроенные плагины включены в бинарник EasyP:"},{"id":"cli/generator/generator::grpc::78","title":"Генератор","section":"gRPC плагины","path":"/docs/guide/cli/generator/generator#grpc","headings":["gRPC плагины"],"excerpt":"gRPC плагины ```bash Сборка go build ./cmd/easyp","content":"gRPC плагины ```bash Сборка go build ./cmd/easyp"},{"id":"cli/generator/generator::grpc::79","title":"Генератор","section":"gRPC плагины","path":"/docs/guide/cli/generator/generator#grpc","headings":["gRPC плагины"],"excerpt":"gRPC плагины Установка go install github.com/easyp-tech/easyp/cmd/easyp@latest ```","content":"gRPC плагины Установка go install github.com/easyp-tech/easyp/cmd/easyp@latest ```"},{"id":"cli/generator/generator::grpc::80","title":"Генератор","section":"gRPC плагины","path":"/docs/guide/cli/generator/generator#grpc","headings":["gRPC плагины"],"excerpt":"gRPC плагины **Обратная совместимость:**","content":"gRPC плагины **Обратная совместимость:**"},{"id":"cli/generator/generator::grpc::81","title":"Генератор","section":"gRPC плагины","path":"/docs/guide/cli/generator/generator#grpc","headings":["gRPC плагины"],"excerpt":"gRPC плагины Встроенные плагины полностью совместимы с существующими конфигурациями. Если плагин найден в PATH, он будет использован вместо встроенного. Это гарантирует, что:","content":"gRPC плагины Встроенные плагины полностью совместимы с существующими конфигурациями. Если плагин найден в PATH, он будет использован вместо встроенного. Это гарантирует, что:"},{"id":"cli/generator/generator::grpc::82","title":"Генератор","section":"gRPC плагины","path":"/docs/guide/cli/generator/generator#grpc","headings":["gRPC плагины"],"excerpt":"gRPC плагины Существующие конфигурации продолжают работать без изменений Можно переопределить встроенный плагин, установив его в системе Приоритет отдаётся локальным установкам для гибкости","content":"gRPC плагины Существующие конфигурации продолжают работать без изменений Можно переопределить встроенный плагин, установив его в системе Приоритет отдаётся локальным установкам для гибкости"},{"id":"cli/generator/generator::top::83","title":"Генератор","section":"Справочник опций плагинов","path":"/docs/guide/cli/generator/generator","headings":["Справочник опций плагинов"],"excerpt":"Справочник опций плагинов Ниже перечислены наиболее часто используемые плагины и их настройки. Каждый плагин имеет параметры, влияющие на результат генерации — понимание этих опций важно для получения нужного вывода.","content":"Справочник опций плагинов Ниже перечислены наиболее часто используемые плагины и их настройки. Каждый плагин имеет параметры, влияющие на результат генерации — понимание этих опций важно для получения нужного вывода."},{"id":"cli/generator/generator::go-plugins::84","title":"Генератор","section":"Go Plugins","path":"/docs/guide/cli/generator/generator#go-plugins","headings":["Go Plugins"],"excerpt":"Go Plugins Плагины для Go — самые зрелые и распространённые. Опция paths управляет тем, как формируются пути импортов; остальные опции дают тонкую настройку вывода.","content":"Go Plugins Плагины для Go — самые зрелые и распространённые. Опция paths управляет тем, как формируются пути импортов; остальные опции дают тонкую настройку вывода."},{"id":"cli/generator/generator::grpc-gateway-plugins::85","title":"Генератор","section":"gRPC-Gateway Plugins","path":"/docs/guide/cli/generator/generator#grpc-gateway-plugins","headings":["gRPC-Gateway Plugins"],"excerpt":"gRPC-Gateway Plugins Позволяют экспонировать gRPC сервисы как REST API и генерировать OpenAPI. Критично для HTTP/JSON поверх gRPC.","content":"gRPC-Gateway Plugins Позволяют экспонировать gRPC сервисы как REST API и генерировать OpenAPI. Критично для HTTP/JSON поверх gRPC."},{"id":"cli/generator/generator::validation-plugins::86","title":"Генератор","section":"Validation Plugins","path":"/docs/guide/cli/generator/generator#validation-plugins","headings":["Validation Plugins"],"excerpt":"Validation Plugins Генерируют код валидации на основе правил в proto, устраняя ручную проверку.","content":"Validation Plugins Генерируют код валидации на основе правил в proto, устраняя ручную проверку."},{"id":"cli/generator/generator::typescriptjavascript-plugins::87","title":"Генератор","section":"TypeScript/JavaScript Plugins","path":"/docs/guide/cli/generator/generator#typescriptjavascript-plugins","headings":["TypeScript/JavaScript Plugins"],"excerpt":"TypeScript/JavaScript Plugins TypeScript плагины нужны фронтенду: типобезопасные интерфейсы и клиенты.","content":"TypeScript/JavaScript Plugins TypeScript плагины нужны фронтенду: типобезопасные интерфейсы и клиенты."},{"id":"cli/generator/generator::managed-mode::88","title":"Генератор","section":"Managed Mode","path":"/docs/guide/cli/generator/generator#managed-mode","headings":["Managed Mode"],"excerpt":"Managed Mode Managed mode автоматически устанавливает file и field опции в protobuf дескрипторах во время генерации кода без изменения исходных .proto файлов. Эта функция совместима с managed mode в buf и обеспечивает ед","content":"Managed Mode Managed mode автоматически устанавливает file и field опции в protobuf дескрипторах во время генерации кода без изменения исходных .proto файлов. Эта функция совместима с managed mode в buf и обеспечивает единообразный способ управления языково-специфичными опциями в вашей кодовой базе."},{"id":"cli/generator/generator::managed-mode::89","title":"Генератор","section":"Managed Mode","path":"/docs/guide/cli/generator/generator#managed-mode","headings":["Managed Mode"],"excerpt":"Managed Mode **Ключевые преимущества:** **Без изменений proto файлов**: Опции применяются во время генерации, proto файлы остаются чистыми **Согласованные значения по умолчанию**: Автоматическое применение языковых согла","content":"Managed Mode **Ключевые преимущества:** **Без изменений proto файлов**: Опции применяются во время генерации, proto файлы остаются чистыми **Согласованные значения по умолчанию**: Автоматическое применение языковых соглашений об именовании **Централизованная конфигурация**: Управление всеми опциями в одном месте (easyp.yaml) **Правила для модулей**: Применение разных опций к разным модулям или путям **Совместимость с buf**: Работает так же, как managed mode в buf"},{"id":"cli/generator/generator::top::90","title":"Генератор","section":"Как это работает","path":"/docs/guide/cli/generator/generator","headings":["Как это работает"],"excerpt":"Как это работает Когда managed mode включён, EasyP автоматически применяет file и field опции к protobuf дескрипторам перед генерацией кода. Это происходит в памяти, поэтому исходные .proto файлы остаются неизменными.","content":"Как это работает Когда managed mode включён, EasyP автоматически применяет file и field опции к protobuf дескрипторам перед генерацией кода. Это происходит в памяти, поэтому исходные .proto файлы остаются неизменными."},{"id":"cli/generator/generator::top::91","title":"Генератор","section":"Как это работает","path":"/docs/guide/cli/generator/generator","headings":["Как это работает"],"excerpt":"Как это работает **Значения по умолчанию** применяются для определённых опций на основе языковых соглашений: Java: java_package_prefix по умолчанию \"com\", java_multiple_files по умолчанию true C#: csharp_namespace по умо","content":"Как это работает **Значения по умолчанию** применяются для определённых опций на основе языковых соглашений: Java: java_package_prefix по умолчанию \"com\", java_multiple_files по умолчанию true C#: csharp_namespace по умолчанию PascalCase имени пакета Ruby: ruby_package по умолчанию PascalCase с разделителем :: PHP: php_namespace по умолчанию PascalCase с разделителем \\ Objective-C: objc_class_prefix по умолчанию первые буквы частей пакета C++: cc_enable_arenas по умолчанию true"},{"id":"cli/generator/generator::top::92","title":"Генератор","section":"Как это работает","path":"/docs/guide/cli/generator/generator","headings":["Как это работает"],"excerpt":"Как это работает **Overrides** позволяют установить конкретные значения для опций с поддержкой фильтрации по модулю, пути или полю. Если не указаны module и path, override применяется ко всем файлам в запросе генерации, ","content":"Как это работает **Overrides** позволяют установить конкретные значения для опций с поддержкой фильтрации по модулю, пути или полю. Если не указаны module и path, override применяется ко всем файлам в запросе генерации, включая зависимости и git_repo inputs."},{"id":"cli/generator/generator::top::93","title":"Генератор","section":"Как это работает","path":"/docs/guide/cli/generator/generator","headings":["Как это работает"],"excerpt":"Как это работает **Disables** позволяют предотвратить изменение managed mode определённых опций или файлов. Это рекомендуемый способ исключить внешние зависимости, у которых свои опции уже заданы.","content":"Как это работает **Disables** позволяют предотвратить изменение managed mode определённых опций или файлов. Это рекомендуемый способ исключить внешние зависимости, у которых свои опции уже заданы."},{"id":"cli/generator/generator::file-options::94","title":"Генератор","section":"Поддерживаемые File Options","path":"/docs/guide/cli/generator/generator#file-options","headings":["Поддерживаемые File Options"],"excerpt":"Поддерживаемые File Options Опция Описание Есть значение по умолчанию? ------- ---------- ---------------------------- go_package Go import path ❌ go_package_prefix Префикс для Go import paths ❌ java_package Имя Java пак","content":"Поддерживаемые File Options Опция Описание Есть значение по умолчанию? ------- ---------- ---------------------------- go_package Go import path ❌ go_package_prefix Префикс для Go import paths ❌ java_package Имя Java пакета ❌ java_package_prefix Префикс для Java пакетов ✅ (\"com\") java_package_suffix Суффикс для Java пакетов ❌ java_multiple_files Генерировать несколько Java файлов ✅ (true) java_outer_classname Имя внешнего класса ✅ (PascalCase + \"Proto\") java_string_check_utf8 UTF-8 валидация ❌ csharp_namespace C# namespace ✅ (PascalCase) csharp_namespace_prefix Префикс для C# namespaces ❌ ruby_package Имя Ruby модуля ✅ (PascalCase с ::) ruby_package_suffix Суффикс для Ruby пакетов ❌ php_namespace PHP namespace ✅ (PascalCase с \\) php_metadata_namespace PHP metadata namespace ❌ php_metadata_namespace_suffix Суффикс для PHP metadata ❌ objc_class_prefix Objective-C префикс класса ✅ (Первые буквы) swift_prefix Swift префикс ❌ optimize_for Оптимизация генерации кода ❌ cc_enable_arenas C++ arena аллокация ✅ (true)"},{"id":"cli/generator/generator::field-options::95","title":"Генератор","section":"Поддерживаемые Field Options","path":"/docs/guide/cli/generator/generator#field-options","headings":["Поддерживаемые Field Options"],"excerpt":"Поддерживаемые Field Options Опция Описание Применяется к ------- ---------- --------------- jstype JavaScript тип для 64-битных целых чисел int64, uint64, sint64, fixed64, sfixed64","content":"Поддерживаемые Field Options Опция Описание Применяется к ------- ---------- --------------- jstype JavaScript тип для 64-битных целых чисел int64, uint64, sint64, fixed64, sfixed64"},{"id":"cli/generator/generator::top::96","title":"Генератор","section":"Базовая настройка со значениями по умолчанию","path":"/docs/guide/cli/generator/generator","headings":["Базовая настройка со значениями по умолчанию"],"excerpt":"Базовая настройка со значениями по умолчанию Включите managed mode для получения автоматических значений по умолчанию для всех поддерживаемых языков:","content":"Базовая настройка со значениями по умолчанию Включите managed mode для получения автоматических значений по умолчанию для всех поддерживаемых языков:"},{"id":"cli/generator/generator::top::97","title":"Генератор","section":"Базовая настройка со значениями по умолчанию","path":"/docs/guide/cli/generator/generator","headings":["Базовая настройка со значениями по умолчанию"],"excerpt":"Базовая настройка со значениями по умолчанию","content":"Базовая настройка со значениями по умолчанию"},{"id":"cli/generator/generator::top::98","title":"Генератор","section":"Базовая настройка со значениями по умолчанию","path":"/docs/guide/cli/generator/generator","headings":["Базовая настройка со значениями по умолчанию"],"excerpt":"Базовая настройка со значениями по умолчанию Это автоматически установит: java_package в com. для всех файлов java_multiple_files в true csharp_namespace в PascalCase имени пакета ruby_package в PascalCase с разделителем","content":"Базовая настройка со значениями по умолчанию Это автоматически установит: java_package в com. для всех файлов java_multiple_files в true csharp_namespace в PascalCase имени пакета ruby_package в PascalCase с разделителем :: И многое другое..."},{"id":"cli/generator/generator::go::99","title":"Генератор","section":"Кастомный префикс Go пакета","path":"/docs/guide/cli/generator/generator#go","headings":["Кастомный префикс Go пакета"],"excerpt":"Кастомный префикс Go пакета Переопределите префикс Go пакета для вашего проекта:","content":"Кастомный префикс Go пакета Переопределите префикс Go пакета для вашего проекта:"},{"id":"cli/generator/generator::go::100","title":"Генератор","section":"Кастомный префикс Go пакета","path":"/docs/guide/cli/generator/generator#go","headings":["Кастомный префикс Go пакета"],"excerpt":"Кастомный префикс Go пакета Это установит go_package в github.com/mycompany/myproject/gen/go/ для всех файлов.","content":"Кастомный префикс Go пакета Это установит go_package в github.com/mycompany/myproject/gen/go/ для всех файлов."},{"id":"cli/generator/generator::go::101","title":"Генератор","section":"Динамические пути Go пакетов с маркерами","path":"/docs/guide/cli/generator/generator#go","headings":["Динамические пути Go пакетов с маркерами"],"excerpt":"Динамические пути Go пакетов с маркерами Для более сложной генерации путей можно использовать маркеры в значениях go_package_prefix или go_package:","content":"Динамические пути Go пакетов с маркерами Для более сложной генерации путей можно использовать маркеры в значениях go_package_prefix или go_package:"},{"id":"cli/generator/generator::go::102","title":"Генератор","section":"Динамические пути Go пакетов с маркерами","path":"/docs/guide/cli/generator/generator#go","headings":["Динамические пути Go пакетов с маркерами"],"excerpt":"Динамические пути Go пакетов с маркерами","content":"Динамические пути Go пакетов с маркерами"},{"id":"cli/generator/generator::go::103","title":"Генератор","section":"Динамические пути Go пакетов с маркерами","path":"/docs/guide/cli/generator/generator#go","headings":["Динамические пути Go пакетов с маркерами"],"excerpt":"Динамические пути Go пакетов с маркерами **Доступные маркеры:** {{file_path}} - Полный путь файла без расширения .proto - Пример: internal/cms/as.proto → internal/cms/as {{file_dir}} - Только путь директории, без имени ф","content":"Динамические пути Go пакетов с маркерами **Доступные маркеры:** {{file_path}} - Полный путь файла без расширения .proto - Пример: internal/cms/as.proto → internal/cms/as {{file_dir}} - Только путь директории, без имени файла - Пример: internal/cms/as.proto → internal/cms {{file_dir_without:prefix/}} - Путь директории с удалением префикса и базового имени файла без суффиксов _service/_grpc - Пример: {{file_dir_without:internal/}} для internal/cms/as_service.proto → cms/as {{file_path_without:prefix/}} - Полный путь файла с удалением префикса - Пример: {{file_path_without:internal/}} для internal/cms/as.proto → cms/as"},{"id":"cli/generator/generator::top::104","title":"Генератор","section":"Переопределения для конкретных модулей","path":"/docs/guide/cli/generator/generator","headings":["Переопределения для конкретных модулей"],"excerpt":"Переопределения для конкретных модулей Примените разные опции к разным модулям:","content":"Переопределения для конкретных модулей Примените разные опции к разным модулям:"},{"id":"cli/generator/generator::top::105","title":"Генератор","section":"Переопределения для конкретных модулей","path":"/docs/guide/cli/generator/generator","headings":["Переопределения для конкретных модулей"],"excerpt":"Переопределения для конкретных модулей","content":"Переопределения для конкретных модулей"},{"id":"cli/generator/generator::top::106","title":"Генератор","section":"Переопределения для конкретных модулей","path":"/docs/guide/cli/generator/generator","headings":["Переопределения для конкретных модулей"],"excerpt":"Переопределения для конкретных модулей module должен точно совпадать с источником модуля в EasyP: это значение из deps или git_repo.url до @version (например, github.com/mycompany/internal-protos или https://github.com/m","content":"Переопределения для конкретных модулей module должен точно совпадать с источником модуля в EasyP: это значение из deps или git_repo.url до @version (например, github.com/mycompany/internal-protos или https://github.com/mycompany/internal-protos). Это не Go module path из go.mod."},{"id":"cli/generator/generator::top::107","title":"Генератор","section":"Отключение для внешних зависимостей","path":"/docs/guide/cli/generator/generator","headings":["Отключение для внешних зависимостей"],"excerpt":"Отключение для внешних зависимостей Отключите managed mode для внешних зависимостей, у которых уже установлены опции:","content":"Отключение для внешних зависимостей Отключите managed mode для внешних зависимостей, у которых уже установлены опции:"},{"id":"cli/generator/generator::top::108","title":"Генератор","section":"Отключение для внешних зависимостей","path":"/docs/guide/cli/generator/generator","headings":["Отключение для внешних зависимостей"],"excerpt":"Отключение для внешних зависимостей","content":"Отключение для внешних зависимостей"},{"id":"cli/generator/generator::javascript::109","title":"Генератор","section":"Типобезопасность JavaScript","path":"/docs/guide/cli/generator/generator#javascript","headings":["Типобезопасность JavaScript"],"excerpt":"Типобезопасность JavaScript Установите jstype в JS_STRING для всех 64-битных целочисленных полей, чтобы предотвратить потерю точности в JavaScript:","content":"Типобезопасность JavaScript Установите jstype в JS_STRING для всех 64-битных целочисленных полей, чтобы предотвратить потерю точности в JavaScript:"},{"id":"cli/generator/generator::top::110","title":"Генератор","section":"Совпадение путей","path":"/docs/guide/cli/generator/generator","headings":["Совпадение путей"],"excerpt":"Совпадение путей Совпадение путей в managed mode использует префиксное совпадение (как в buf):","content":"Совпадение путей Совпадение путей в managed mode использует префиксное совпадение (как в buf):"},{"id":"cli/generator/generator::top::111","title":"Генератор","section":"Совпадение путей","path":"/docs/guide/cli/generator/generator","headings":["Совпадение путей"],"excerpt":"Совпадение путей **Путь директории** (заканчивается на /): Совпадает со всеми файлами в этой директории и поддиректориях - Пример: path: \"internal/cms/\" совпадает с internal/cms/as.proto, internal/cms/node.proto, interna","content":"Совпадение путей **Путь директории** (заканчивается на /): Совпадает со всеми файлами в этой директории и поддиректориях - Пример: path: \"internal/cms/\" совпадает с internal/cms/as.proto, internal/cms/node.proto, internal/cms/v1/service.proto **Точный путь файла** (заканчивается на .proto): Совпадает только с этим конкретным файлом - Пример: path: \"internal/cms/as.proto\" совпадает только с internal/cms/as.proto **Префиксный путь** (без завершающего / или .proto): Использует префиксное совпадение (не директориально-осознанное) - Пример: path: \"internal/cms\" совпадает с internal/cms/as.proto, но также с internal/cmsv2/file.proto - **Совет**: Используйте префиксные пути для группировки нескольких файлов с одинаковым значением. Например, path: \"internal/cms/bmi\" совпадает и с internal/cms/bmi.proto, и с internal/cms/bmi_service.proto, что позволяет установить одно и то же значение go_package для обоих файлов одним правилом."},{"id":"cli/generator/generator::top::112","title":"Генератор","section":"Приоритет правил","path":"/docs/guide/cli/generator/generator","headings":["Приоритет правил"],"excerpt":"Приоритет правил Когда несколько правил соответствуют одному файлу или полю, применяется следующий приоритет:","content":"Приоритет правил Когда несколько правил соответствуют одному файлу или полю, применяется следующий приоритет:"},{"id":"cli/generator/generator::top::113","title":"Генератор","section":"Приоритет правил","path":"/docs/guide/cli/generator/generator","headings":["Приоритет правил"],"excerpt":"Приоритет правил **Disable правила** имеют приоритет — если опция отключена, она не будет применена **Override правила** применяются по порядку — последнее совпадающее правило побеждает **Значения по умолчанию** применяю","content":"Приоритет правил **Disable правила** имеют приоритет — если опция отключена, она не будет применена **Override правила** применяются по порядку — последнее совпадающее правило побеждает **Значения по умолчанию** применяются только если нет совпадающего override и опция не отключена"},{"id":"cli/generator/generator::buf::114","title":"Генератор","section":"Совместимость с buf","path":"/docs/guide/cli/generator/generator#buf","headings":["Совместимость с buf"],"excerpt":"Совместимость с buf Managed mode в EasyP совместим с managed mode в buf. Тот же формат конфигурации и поведение применяются, что упрощает миграцию между инструментами или использование обоих в одном workflow.","content":"Совместимость с buf Managed mode в EasyP совместим с managed mode в buf. Тот же формат конфигурации и поведение применяются, что упрощает миграцию между инструментами или использование обоих в одном workflow."},{"id":"cli/generator/generator::descriptor-set::115","title":"Генератор","section":"Генерация Descriptor Set","path":"/docs/guide/cli/generator/generator#descriptor-set","headings":["Генерация Descriptor Set"],"excerpt":"Генерация Descriptor Set **https://protobuf.dev/programming-guides/techniques/#self-description**","content":"Генерация Descriptor Set **https://protobuf.dev/programming-guides/techniques/#self-description**"},{"id":"cli/generator/generator::descriptor-set::116","title":"Генератор","section":"Генерация Descriptor Set","path":"/docs/guide/cli/generator/generator#descriptor-set","headings":["Генерация Descriptor Set"],"excerpt":"Генерация Descriptor Set EasyP поддерживает генерацию бинарных FileDescriptorSet файлов с помощью флага --descriptor_set_out. Это позволяет создавать самоописывающиеся protobuf сообщения, которые включают информацию о сх","content":"Генерация Descriptor Set EasyP поддерживает генерацию бинарных FileDescriptorSet файлов с помощью флага --descriptor_set_out. Это позволяет создавать самоописывающиеся protobuf сообщения, которые включают информацию о схеме вместе с данными."},{"id":"cli/generator/generator::descriptor-set::117","title":"Генератор","section":"Генерация Descriptor Set","path":"/docs/guide/cli/generator/generator#descriptor-set","headings":["Генерация Descriptor Set"],"excerpt":"Генерация Descriptor Set **Флаги CLI:**","content":"Генерация Descriptor Set **Флаги CLI:**"},{"id":"cli/generator/generator::descriptor-set::118","title":"Генератор","section":"Генерация Descriptor Set","path":"/docs/guide/cli/generator/generator#descriptor-set","headings":["Генерация Descriptor Set"],"excerpt":"Генерация Descriptor Set --descriptor_set_out - Путь для вывода бинарного FileDescriptorSet --include_imports - Включить все транзитивные зависимости в FileDescriptorSet","content":"Генерация Descriptor Set --descriptor_set_out - Путь для вывода бинарного FileDescriptorSet --include_imports - Включить все транзитивные зависимости в FileDescriptorSet"},{"id":"cli/generator/generator::descriptor-set::119","title":"Генератор","section":"Генерация Descriptor Set","path":"/docs/guide/cli/generator/generator#descriptor-set","headings":["Генерация Descriptor Set"],"excerpt":"Генерация Descriptor Set **Пример:**","content":"Генерация Descriptor Set **Пример:**"},{"id":"cli/generator/generator::descriptor-set::120","title":"Генератор","section":"Генерация Descriptor Set","path":"/docs/guide/cli/generator/generator#descriptor-set","headings":["Генерация Descriptor Set"],"excerpt":"Генерация Descriptor Set ```bash Генерация descriptor set только с целевыми файлами easyp generate --descriptor_set_out=./schema.pb","content":"Генерация Descriptor Set ```bash Генерация descriptor set только с целевыми файлами easyp generate --descriptor_set_out=./schema.pb"},{"id":"cli/generator/generator::descriptor-set::121","title":"Генератор","section":"Генерация Descriptor Set","path":"/docs/guide/cli/generator/generator#descriptor-set","headings":["Генерация Descriptor Set"],"excerpt":"Генерация Descriptor Set Генерация descriptor set со всеми зависимостями easyp generate --descriptor_set_out=./schema.pb --include_imports ```","content":"Генерация Descriptor Set Генерация descriptor set со всеми зависимостями easyp generate --descriptor_set_out=./schema.pb --include_imports ```"},{"id":"cli/generator/generator::descriptor-set::122","title":"Генератор","section":"Генерация Descriptor Set","path":"/docs/guide/cli/generator/generator#descriptor-set","headings":["Генерация Descriptor Set"],"excerpt":"Генерация Descriptor Set Самоописывающиеся сообщения полезны для динамического парсинга сообщений, валидации схемы во время выполнения, реестров схем и создания универсальных gRPC клиентов. Для получения дополнительной и","content":"Генерация Descriptor Set Самоописывающиеся сообщения полезны для динамического парсинга сообщений, валидации схемы во время выполнения, реестров схем и создания универсальных gRPC клиентов. Для получения дополнительной информации см. документацию Protocol Buffers о самоописании."},{"id":"cli/generator/generator::top::123","title":"Генератор","section":"Интеграция с менеджером пакетов","path":"/docs/guide/cli/generator/generator","headings":["Интеграция с менеджером пакетов"],"excerpt":"Интеграция с менеджером пакетов Одной из самых мощных возможностей EasyP является бесшовная интеграция генератора кода с менеджером пакетов. Это устраняет проблему ручного управления proto‑зависимостями и гарантирует, чт","content":"Интеграция с менеджером пакетов Одной из самых мощных возможностей EasyP является бесшовная интеграция генератора кода с менеджером пакетов. Это устраняет проблему ручного управления proto‑зависимостями и гарантирует, что при генерации используются корректные (зафиксированные) версии импортируемых файлов."},{"id":"cli/generator/generator::top::124","title":"Генератор","section":"Интеграция с менеджером пакетов","path":"/docs/guide/cli/generator/generator","headings":["Интеграция с менеджером пакетов"],"excerpt":"Интеграция с менеджером пакетов **Ключевые преимущества:** **Автоматическое разрешение зависимостей**: не нужно вручную прописывать пути импортов **Согласованность версий**: фиксация в easyp.lock гарантирует воспроизводи","content":"Интеграция с менеджером пакетов **Ключевые преимущества:** **Автоматическое разрешение зависимостей**: не нужно вручную прописывать пути импортов **Согласованность версий**: фиксация в easyp.lock гарантирует воспроизводимость **Транзитивные зависимости**: вложенные цепочки подтягиваются автоматически **Производительность**: локальный кеш — скачивание один раз и повторное использование"},{"id":"cli/generator/generator::top::125","title":"Генератор","section":"Автоматическое разрешение зависимостей","path":"/docs/guide/cli/generator/generator","headings":["Автоматическое разрешение зависимостей"],"excerpt":"Автоматическое разрешение зависимостей Когда вы указываете зависимости в секции deps, генератор автоматически добавляет их в путь импортов. Ваши proto‑файлы могут делать стандартные import из этих зависимостей без дополн","content":"Автоматическое разрешение зависимостей Когда вы указываете зависимости в секции deps, генератор автоматически добавляет их в путь импортов. Ваши proto‑файлы могут делать стандартные import из этих зависимостей без дополнительной настройки."},{"id":"cli/generator/generator::top::126","title":"Генератор","section":"Автоматическое разрешение зависимостей","path":"/docs/guide/cli/generator/generator","headings":["Автоматическое разрешение зависимостей"],"excerpt":"Автоматическое разрешение зависимостей **Как это работает:** EasyP скачивает и кеширует зависимости из deps Во время генерации кешированные файлы автоматически добавляются в import‑path protoc Ваши proto‑файлы используют","content":"Автоматическое разрешение зависимостей **Как это работает:** EasyP скачивает и кеширует зависимости из deps Во время генерации кешированные файлы автоматически добавляются в import‑path protoc Ваши proto‑файлы используют обычные import строки для обращения к зависимостям При with_imports: true в вывод попадают и локальные файлы, и файлы зависимостей"},{"id":"cli/generator/generator::top::127","title":"Генератор","section":"Автоматическое разрешение зависимостей","path":"/docs/guide/cli/generator/generator","headings":["Автоматическое разрешение зависимостей"],"excerpt":"Автоматическое разрешение зависимостей Ниже простой пример — зависимости указываются один раз в deps, далее они доступны при генерации автоматически:","content":"Автоматическое разрешение зависимостей Ниже простой пример — зависимости указываются один раз в deps, далее они доступны при генерации автоматически:"},{"id":"cli/generator/generator::top::128","title":"Генератор","section":"Автоматическое разрешение зависимостей","path":"/docs/guide/cli/generator/generator","headings":["Автоматическое разрешение зависимостей"],"excerpt":"Автоматическое разрешение зависимостей ```yaml deps: - github.com/googleapis/googleapis@common-protos-1_3_1 - github.com/grpc-ecosystem/grpc-gateway@v2.19.1","content":"Автоматическое разрешение зависимостей ```yaml deps: - github.com/googleapis/googleapis@common-protos-1_3_1 - github.com/grpc-ecosystem/grpc-gateway@v2.19.1"},{"id":"cli/generator/generator::top::129","title":"Генератор","section":"Автоматическое разрешение зависимостей","path":"/docs/guide/cli/generator/generator","headings":["Автоматическое разрешение зависимостей"],"excerpt":"Автоматическое разрешение зависимостей generate: inputs: - directory: \"proto\" plugins: - name: go out: ./gen/go opts: paths: source_relative with_imports: true # This automatically includes googleapis and grpc-gateway pr","content":"Автоматическое разрешение зависимостей 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::top::130","title":"Генератор","section":"Примеры использования зависимостей","path":"/docs/guide/cli/generator/generator","headings":["Примеры использования зависимостей"],"excerpt":"Примеры использования зависимостей Ниже показаны распространённые способы интеграции внешних proto‑зависимостей в процесс генерации.","content":"Примеры использования зависимостей Ниже показаны распространённые способы интеграции внешних proto‑зависимостей в процесс генерации."},{"id":"cli/generator/generator::google-apis::131","title":"Генератор","section":"Использование Google APIs","path":"/docs/guide/cli/generator/generator#google-apis","headings":["Использование Google APIs"],"excerpt":"Использование Google APIs Google APIs — одна из самых популярных коллекций зависимостей: стандартные типы, аннотации для REST, проверки и общие структуры данных.","content":"Использование Google APIs Google APIs — одна из самых популярных коллекций зависимостей: стандартные типы, аннотации для REST, проверки и общие структуры данных."},{"id":"cli/generator/generator::google-apis::132","title":"Генератор","section":"Использование Google APIs","path":"/docs/guide/cli/generator/generator#google-apis","headings":["Использование Google APIs"],"excerpt":"Использование Google APIs **Когда использовать Google APIs:** Построение REST поверх gRPC (gRPC-Gateway) Нужны стандартные типы (Timestamp, Duration, Any) Требуются аннотации поведения полей (field behavior) Интеграция с","content":"Использование Google APIs **Когда использовать Google APIs:** Построение REST поверх gRPC (gRPC-Gateway) Нужны стандартные типы (Timestamp, Duration, Any) Требуются аннотации поведения полей (field behavior) Интеграция с сервисами Google Cloud"},{"id":"cli/generator/generator::google-apis::133","title":"Генератор","section":"Использование Google APIs","path":"/docs/guide/cli/generator/generator#google-apis","headings":["Использование Google APIs"],"excerpt":"Использование Google APIs Минимальная конфигурация для подключения Google APIs:","content":"Использование Google APIs Минимальная конфигурация для подключения Google APIs:"},{"id":"cli/generator/generator::google-apis::134","title":"Генератор","section":"Использование Google APIs","path":"/docs/guide/cli/generator/generator#google-apis","headings":["Использование Google APIs"],"excerpt":"Использование Google APIs ```yaml deps: - github.com/googleapis/googleapis@common-protos-1_3_1","content":"Использование Google APIs ```yaml deps: - github.com/googleapis/googleapis@common-protos-1_3_1"},{"id":"cli/generator/generator::google-apis::135","title":"Генератор","section":"Использование Google APIs","path":"/docs/guide/cli/generator/generator#google-apis","headings":["Использование Google APIs"],"excerpt":"Использование Google APIs generate: inputs: - directory: \"api/proto\" plugins: - name: go out: ./gen/go opts: paths: source_relative with_imports: true ```","content":"Использование Google APIs generate: inputs: - directory: \"api/proto\" plugins: - name: go out: ./gen/go opts: paths: source_relative with_imports: true ```"},{"id":"cli/generator/generator::google-apis::136","title":"Генератор","section":"Использование Google APIs","path":"/docs/guide/cli/generator/generator#google-apis","headings":["Использование Google APIs"],"excerpt":"Использование Google APIs **Важно:** Всегда фиксируйте версию (например common-protos-1_3_1) — не используйте latest в продакшене.","content":"Использование Google APIs **Важно:** Всегда фиксируйте версию (например common-protos-1_3_1) — не используйте latest в продакшене."},{"id":"cli/generator/generator::google-apis::137","title":"Генератор","section":"Использование Google APIs","path":"/docs/guide/cli/generator/generator#google-apis","headings":["Использование Google APIs"],"excerpt":"Использование Google APIs После настройки ваши proto могут импортировать определения Google API. Ниже пример сервиса с HTTP аннотацией:","content":"Использование Google APIs После настройки ваши proto могут импортировать определения Google API. Ниже пример сервиса с HTTP аннотацией:"},{"id":"cli/generator/generator::google-apis::138","title":"Генератор","section":"Использование Google APIs","path":"/docs/guide/cli/generator/generator#google-apis","headings":["Использование Google APIs"],"excerpt":"Использование Google APIs ```proto // api/proto/service.proto syntax = \"proto3\";","content":"Использование Google APIs ```proto // api/proto/service.proto syntax = \"proto3\";"},{"id":"cli/generator/generator::google-apis::139","title":"Генератор","section":"Использование Google APIs","path":"/docs/guide/cli/generator/generator#google-apis","headings":["Использование Google APIs"],"excerpt":"Использование Google APIs import \"google/api/annotations.proto\"; import \"google/protobuf/timestamp.proto\";","content":"Использование Google APIs import \"google/api/annotations.proto\"; import \"google/protobuf/timestamp.proto\";"},{"id":"cli/generator/generator::google-apis::140","title":"Генератор","section":"Использование Google APIs","path":"/docs/guide/cli/generator/generator#google-apis","headings":["Использование Google APIs"],"excerpt":"Использование Google APIs service MyService { rpc GetData(GetDataRequest) returns (GetDataResponse) { option (google.api.http) = { get: \"/v1/data\" }; } } ```","content":"Использование Google APIs service MyService { rpc GetData(GetDataRequest) returns (GetDataResponse) { option (google.api.http) = { get: \"/v1/data\" }; } } ```"},{"id":"cli/generator/generator::top::141","title":"Генератор","section":"Использование правил валидации","path":"/docs/guide/cli/generator/generator","headings":["Использование правил валидации"],"excerpt":"Использование правил валидации protoc-gen-validate даёт мощную проверку полей прямо в определениях proto, устраняя необходимость писать отдельную логику валидации в приложении.","content":"Использование правил валидации protoc-gen-validate даёт мощную проверку полей прямо в определениях proto, устраняя необходимость писать отдельную логику валидации в приложении."},{"id":"cli/generator/generator::top::142","title":"Генератор","section":"Использование правил валидации","path":"/docs/guide/cli/generator/generator","headings":["Использование правил валидации"],"excerpt":"Использование правил валидации **Когда применять валидацию:** Проверка входных данных API Ограничения моделей БД Проверка конфигурационных файлов Любая ситуация, где критична целостность данных","content":"Использование правил валидации **Когда применять валидацию:** Проверка входных данных API Ограничения моделей БД Проверка конфигурационных файлов Любая ситуация, где критична целостность данных"},{"id":"cli/generator/generator::top::143","title":"Генератор","section":"Использование правил валидации","path":"/docs/guide/cli/generator/generator","headings":["Использование правил валидации"],"excerpt":"Использование правил валидации **Преимущества:** Правила валидации — часть proto (единый источник истины) Генерация создаёт функции проверки автоматически Единообразие проверок между языками Производительнее чем проверка","content":"Использование правил валидации **Преимущества:** Правила валидации — часть proto (единый источник истины) Генерация создаёт функции проверки автоматически Единообразие проверок между языками Производительнее чем проверка через runtime reflection"},{"id":"cli/generator/generator::top::144","title":"Генератор","section":"Использование правил валидации","path":"/docs/guide/cli/generator/generator","headings":["Использование правил валидации"],"excerpt":"Использование правил валидации ```yaml deps: - github.com/bufbuild/protoc-gen-validate@v0.10.1","content":"Использование правил валидации ```yaml deps: - github.com/bufbuild/protoc-gen-validate@v0.10.1"},{"id":"cli/generator/generator::top::145","title":"Генератор","section":"Использование правил валидации","path":"/docs/guide/cli/generator/generator","headings":["Использование правил валидации"],"excerpt":"Использование правил валидации 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":"Использование правил валидации 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::top::146","title":"Генератор","section":"Использование правил валидации","path":"/docs/guide/cli/generator/generator","headings":["Использование правил валидации"],"excerpt":"Использование правил валидации **Примечание:** Нужны одновременно зависимость (для импортов proto) и плагин (для генерации кода), чтобы получить полноценную поддержку валидации.","content":"Использование правил валидации **Примечание:** Нужны одновременно зависимость (для импортов proto) и плагин (для генерации кода), чтобы получить полноценную поддержку валидации."},{"id":"cli/generator/generator::top::147","title":"Генератор","section":"Использование правил валидации","path":"/docs/guide/cli/generator/generator","headings":["Использование правил валидации"],"excerpt":"Использование правил валидации Так выглядят правила валидации в proto — сгенерированный код будет автоматически их применять:","content":"Использование правил валидации Так выглядят правила валидации в proto — сгенерированный код будет автоматически их применять:"},{"id":"cli/generator/generator::top::148","title":"Генератор","section":"Использование правил валидации","path":"/docs/guide/cli/generator/generator","headings":["Использование правил валидации"],"excerpt":"Использование правил валидации ```proto // proto/user.proto syntax = \"proto3\";","content":"Использование правил валидации ```proto // proto/user.proto syntax = \"proto3\";"},{"id":"cli/generator/generator::top::149","title":"Генератор","section":"Использование правил валидации","path":"/docs/guide/cli/generator/generator","headings":["Использование правил валидации"],"excerpt":"Использование правил валидации import \"validate/validate.proto\";","content":"Использование правил валидации import \"validate/validate.proto\";"},{"id":"cli/generator/generator::top::150","title":"Генератор","section":"Использование правил валидации","path":"/docs/guide/cli/generator/generator","headings":["Использование правил валидации"],"excerpt":"Использование правил валидации message User { string email = 1 [(validate.rules).string.email = true]; int32 age = 2 [(validate.rules).int32.gte = 0]; } ```","content":"Использование правил валидации message User { string email = 1 [(validate.rules).string.email = true]; int32 age = 2 [(validate.rules).int32.gte = 0]; } ```"},{"id":"cli/generator/generator::top::151","title":"Генератор","section":"Комплексная конфигурация с несколькими зависимостями","path":"/docs/guide/cli/generator/generator","headings":["Комплексная конфигурация с несколькими зависимостями"],"excerpt":"Комплексная конфигурация с несколькими зависимостями Пример ниже показывает продакшен‑конфигурацию, объединяющую несколько зависимостей и плагины для полного цикла разработки API:","content":"Комплексная конфигурация с несколькими зависимостями Пример ниже показывает продакшен‑конфигурацию, объединяющую несколько зависимостей и плагины для полного цикла разработки API:"},{"id":"cli/generator/generator::top::152","title":"Генератор","section":"Комплексная конфигурация с несколькими зависимостями","path":"/docs/guide/cli/generator/generator","headings":["Комплексная конфигурация с несколькими зависимостями"],"excerpt":"Комплексная конфигурация с несколькими зависимостями ```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 HT","content":"Комплексная конфигурация с несколькими зависимостями ```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::top::153","title":"Генератор","section":"Комплексная конфигурация с несколькими зависимостями","path":"/docs/guide/cli/generator/generator","headings":["Комплексная конфигурация с несколькими зависимостями"],"excerpt":"Комплексная конфигурация с несколькими зависимостями generate: inputs: - directory: \"api/proto\" plugins: # Go code generation - Core protobuf structures - name: go out: ./gen/go opts: paths: source_relative module: githu","content":"Комплексная конфигурация с несколькими зависимостями 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::top::154","title":"Генератор","section":"Интеграция с кешем зависимостей","path":"/docs/guide/cli/generator/generator","headings":["Интеграция с кешем зависимостей"],"excerpt":"Интеграция с кешем зависимостей Генератор использует модульный кеш EasyP для ускорения сборок:","content":"Интеграция с кешем зависимостей Генератор использует модульный кеш EasyP для ускорения сборок:"},{"id":"cli/generator/generator::top::155","title":"Генератор","section":"Интеграция с кешем зависимостей","path":"/docs/guide/cli/generator/generator","headings":["Интеграция с кешем зависимостей"],"excerpt":"Интеграция с кешем зависимостей ```bash Download dependencies once easyp mod download","content":"Интеграция с кешем зависимостей ```bash Download dependencies once easyp mod download"},{"id":"cli/generator/generator::top::156","title":"Генератор","section":"Интеграция с кешем зависимостей","path":"/docs/guide/cli/generator/generator","headings":["Интеграция с кешем зависимостей"],"excerpt":"Интеграция с кешем зависимостей Generate code (uses cached dependencies) easyp generate","content":"Интеграция с кешем зависимостей Generate code (uses cached dependencies) easyp generate"},{"id":"cli/generator/generator::top::157","title":"Генератор","section":"Интеграция с кешем зависимостей","path":"/docs/guide/cli/generator/generator","headings":["Интеграция с кешем зависимостей"],"excerpt":"Интеграция с кешем зависимостей Dependencies are cached in ~/.easyp/mod/ ls ~/.easyp/mod/github.com/googleapis/googleapis/ ```","content":"Интеграция с кешем зависимостей Dependencies are cached in ~/.easyp/mod/ ls ~/.easyp/mod/github.com/googleapis/googleapis/ ```"},{"id":"cli/generator/generator::top::158","title":"Генератор","section":"Удалённая генерация","path":"/docs/guide/cli/generator/generator","headings":["Удалённая генерация"],"excerpt":"Удалённая генерация Удалённая генерация — мощная возможность, позволяющая генерировать код из proto‑файлов в удалённых Git‑репозиториях без локального checkout. Это поддерживает микросервисную архитектуру, где команды ис","content":"Удалённая генерация Удалённая генерация — мощная возможность, позволяющая генерировать код из proto‑файлов в удалённых Git‑репозиториях без локального checkout. Это поддерживает микросервисную архитектуру, где команды используют API друг друга без жёсткой связки."},{"id":"cli/generator/generator::top::159","title":"Генератор","section":"Удалённая генерация","path":"/docs/guide/cli/generator/generator","headings":["Удалённая генерация"],"excerpt":"Удалённая генерация **Преимущества:** **Развязка разработки**: Команды развиваются независимо, используя версии API друг друга **Контроль версий**: Фиксация внешних API гарантирует стабильность **Меньше размер репозитори","content":"Удалённая генерация **Преимущества:** **Развязка разработки**: Команды развиваются независимо, используя версии API друг друга **Контроль версий**: Фиксация внешних API гарантирует стабильность **Меньше размер репозитория**: Нет необходимости в vendoring/submodule внешних proto **Автоматические обновления**: Легко перейти на новую версию по готовности"},{"id":"cli/generator/generator::top::160","title":"Генератор","section":"Удалённая генерация","path":"/docs/guide/cli/generator/generator","headings":["Удалённая генерация"],"excerpt":"Удалённая генерация **Рекомендации:** В продакшене используйте только тегированные версии В разработке можно тестировать latest, но в проде фиксируйте При наличии используйте семантическое версионирование Учитывайте сете","content":"Удалённая генерация **Рекомендации:** В продакшене используйте только тегированные версии В разработке можно тестировать latest, но в проде фиксируйте При наличии используйте семантическое версионирование Учитывайте сетевые ограничения в CI/CD"},{"id":"cli/generator/generator::proto::161","title":"Генератор","section":"Источники удалённых proto","path":"/docs/guide/cli/generator/generator#proto","headings":["Источники удалённых proto"],"excerpt":"Источники удалённых proto Генерация напрямую из удалённых репозиториев — полезно в микросервисной архитектуре, где разные команды владеют разными proto.","content":"Источники удалённых proto Генерация напрямую из удалённых репозиториев — полезно в микросервисной архитектуре, где разные команды владеют разными proto."},{"id":"cli/generator/generator::proto::162","title":"Генератор","section":"Источники удалённых proto","path":"/docs/guide/cli/generator/generator#proto","headings":["Источники удалённых proto"],"excerpt":"Источники удалённых proto **Типовой workflow:** Команда A публикует proto с версиями в Git Команда B добавляет их в свой easyp.yaml При генерации EasyP скачивает и подключает удалённые proto Сгенерированный код содержит ","content":"Источники удалённых proto **Типовой workflow:** Команда A публикует proto с версиями в Git Команда B добавляет их в свой easyp.yaml При генерации EasyP скачивает и подключает удалённые proto Сгенерированный код содержит клиентские библиотеки сервисов команды A"},{"id":"cli/generator/generator::proto::163","title":"Генератор","section":"Источники удалённых proto","path":"/docs/guide/cli/generator/generator#proto","headings":["Источники удалённых proto"],"excerpt":"Источники удалённых proto Практический пример объединения локальных и удалённых источников в одной конфигурации генерации:","content":"Источники удалённых proto Практический пример объединения локальных и удалённых источников в одной конфигурации генерации:"},{"id":"cli/generator/generator::top::164","title":"Генератор","section":"Сценарии использования удалённой генерации","path":"/docs/guide/cli/generator/generator","headings":["Сценарии использования удалённой генерации"],"excerpt":"Сценарии использования удалённой генерации Примеры ниже показывают реальные ситуации, где удалённая генерация даёт ощутимую выгоду.","content":"Сценарии использования удалённой генерации Примеры ниже показывают реальные ситуации, где удалённая генерация даёт ощутимую выгоду."},{"id":"cli/generator/generator::multi-team-development::165","title":"Генератор","section":"Много команд (Multi-Team Development)","path":"/docs/guide/cli/generator/generator#multi-team-development","headings":["Много команд (Multi-Team Development)"],"excerpt":"Много команд (Multi-Team Development) Мультикомандная разработка особенно выигрывает: вместо координации общих репозиториев и сложного управления зависимостями — независимая эволюция API с контролируемыми обновлениями че","content":"Много команд (Multi-Team Development) Мультикомандная разработка особенно выигрывает: вместо координации общих репозиториев и сложного управления зависимостями — независимая эволюция API с контролируемыми обновлениями через версии."},{"id":"cli/generator/generator::multi-team-development::166","title":"Генератор","section":"Много команд (Multi-Team Development)","path":"/docs/guide/cli/generator/generator#multi-team-development","headings":["Много команд (Multi-Team Development)"],"excerpt":"Много команд (Multi-Team Development) Паттерн ценен в крупных организациях, где: Команды имеют разные циклы релизов и скорости разработки Владение API определено, потребление — массовое Нужно избежать overhead от координ","content":"Много команд (Multi-Team Development) Паттерн ценен в крупных организациях, где: Команды имеют разные циклы релизов и скорости разработки Владение API определено, потребление — массовое Нужно избежать overhead от координации общих proto репозиториев Команды используют разные стеки, но должны взаимодействовать"},{"id":"cli/generator/generator::multi-team-development::167","title":"Генератор","section":"Много команд (Multi-Team Development)","path":"/docs/guide/cli/generator/generator#multi-team-development","headings":["Много команд (Multi-Team Development)"],"excerpt":"Много команд (Multi-Team Development)","content":"Много команд (Multi-Team Development)"},{"id":"cli/generator/generator::api::168","title":"Генератор","section":"Интеграция с API вендоров","path":"/docs/guide/cli/generator/generator#api","headings":["Интеграция с API вендоров"],"excerpt":"Интеграция с API вендоров Многие вендоры публикуют proto для своих API, позволяя генерировать типобезопасных клиентов вместо ручных HTTP реализаций. Это повышает типовую строгость, автоматизирует сериализацию и часто уск","content":"Интеграция с API вендоров Многие вендоры публикуют proto для своих API, позволяя генерировать типобезопасных клиентов вместо ручных HTTP реализаций. Это повышает типовую строгость, автоматизирует сериализацию и часто ускоряет работу."},{"id":"cli/generator/generator::api::169","title":"Генератор","section":"Интеграция с API вендоров","path":"/docs/guide/cli/generator/generator#api","headings":["Интеграция с API вендоров"],"excerpt":"Интеграция с API вендоров Преимущества использования proto от вендоров: **Type safety**: Проверка типов на этапе компиляции **Automatic updates**: Новые возможности приходят с обновлением версии **Consistency**: Единые п","content":"Интеграция с API вендоров Преимущества использования proto от вендоров: **Type safety**: Проверка типов на этапе компиляции **Automatic updates**: Новые возможности приходят с обновлением версии **Consistency**: Единые паттерны интерфейсов между интеграциями **Performance**: Бинарная сериализация быстрее JSON **Documentation**: Proto выступают источником истины для API"},{"id":"cli/generator/generator::top::170","title":"Генератор","section":"Команды","path":"/docs/guide/cli/generator/generator","headings":["Команды"],"excerpt":"Команды CLI EasyP предоставляет гибкие варианты запуска генерации с разными конфигурациями и окружениями.","content":"Команды CLI EasyP предоставляет гибкие варианты запуска генерации с разными конфигурациями и окружениями."},{"id":"cli/generator/generator::top::171","title":"Генератор","section":"Базовая генерация","path":"/docs/guide/cli/generator/generator","headings":["Базовая генерация"],"excerpt":"Базовая генерация Ниже наиболее часто применяемые варианты команд для разработки и продакшена:","content":"Базовая генерация Ниже наиболее часто применяемые варианты команд для разработки и продакшена:"},{"id":"cli/generator/generator::top::172","title":"Генератор","section":"Базовая генерация","path":"/docs/guide/cli/generator/generator","headings":["Базовая генерация"],"excerpt":"Базовая генерация ```bash Use default easyp.yaml configuration - Most common for development easyp generate","content":"Базовая генерация ```bash Use default easyp.yaml configuration - Most common for development easyp generate"},{"id":"cli/generator/generator::top::173","title":"Генератор","section":"Базовая генерация","path":"/docs/guide/cli/generator/generator","headings":["Базовая генерация"],"excerpt":"Базовая генерация Use custom configuration file - Essential for multi-environment setups easyp --cfg production.easyp.yaml generate","content":"Базовая генерация Use custom configuration file - Essential for multi-environment setups easyp --cfg production.easyp.yaml generate"},{"id":"cli/generator/generator::top::174","title":"Генератор","section":"Базовая генерация","path":"/docs/guide/cli/generator/generator","headings":["Базовая генерация"],"excerpt":"Базовая генерация Generate with debug logs - Helpful for debugging and CI/CD easyp --debug generate","content":"Базовая генерация Generate with debug logs - Helpful for debugging and CI/CD easyp --debug generate"},{"id":"cli/generator/generator::top::175","title":"Генератор","section":"Базовая генерация","path":"/docs/guide/cli/generator/generator","headings":["Базовая генерация"],"excerpt":"Базовая генерация Generate with custom cache location - Useful for CI systems or shared environments EASYPPATH=/tmp/easyp-cache easyp generate ```","content":"Базовая генерация Generate with custom cache location - Useful for CI systems or shared environments EASYPPATH=/tmp/easyp-cache easyp generate ```"},{"id":"cli/generator/generator::top::176","title":"Генератор","section":"Интеграция с менеджером пакетов","path":"/docs/guide/cli/generator/generator","headings":["Интеграция с менеджером пакетов"],"excerpt":"Интеграция с менеджером пакетов Интеграция с менеджером пакетов позволяет либо явно управлять зависимостями, либо поручить это генератору. Явный путь даёт больше контроля, автоматический — больше удобства:","content":"Интеграция с менеджером пакетов Интеграция с менеджером пакетов позволяет либо явно управлять зависимостями, либо поручить это генератору. Явный путь даёт больше контроля, автоматический — больше удобства:"},{"id":"cli/generator/generator::top::177","title":"Генератор","section":"Интеграция с менеджером пакетов","path":"/docs/guide/cli/generator/generator","headings":["Интеграция с менеджером пакетов"],"excerpt":"Интеграция с менеджером пакетов ```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":"Интеграция с менеджером пакетов ```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::top::178","title":"Генератор","section":"Интеграция с менеджером пакетов","path":"/docs/guide/cli/generator/generator","headings":["Интеграция с менеджером пакетов"],"excerpt":"Интеграция с менеджером пакетов Automatic workflow - Convenient for development (generate downloads dependencies automatically) easyp generate ```","content":"Интеграция с менеджером пакетов Automatic workflow - Convenient for development (generate downloads dependencies automatically) easyp generate ```"},{"id":"cli/generator/generator::advanced-usage::179","title":"Генератор","section":"Расширенное использование (Advanced Usage)","path":"/docs/guide/cli/generator/generator#advanced-usage","headings":["Расширенное использование (Advanced Usage)"],"excerpt":"Расширенное использование (Advanced Usage) Эти варианты полезны для специфических сценариев деплоя, отладки или когда нужен более тонкий контроль процесса генерации:","content":"Расширенное использование (Advanced Usage) Эти варианты полезны для специфических сценариев деплоя, отладки или когда нужен более тонкий контроль процесса генерации:"},{"id":"cli/generator/generator::advanced-usage::180","title":"Генератор","section":"Расширенное использование (Advanced Usage)","path":"/docs/guide/cli/generator/generator#advanced-usage","headings":["Расширенное использование (Advanced Usage)"],"excerpt":"Расширенное использование (Advanced Usage) ```bash Генерация из конкретной директории (перекрывает настройку в файле конфигурации) easyp generate --path=./api/proto","content":"Расширенное использование (Advanced Usage) ```bash Генерация из конкретной директории (перекрывает настройку в файле конфигурации) easyp generate --path=./api/proto"},{"id":"cli/generator/generator::advanced-usage::181","title":"Генератор","section":"Расширенное использование (Advanced Usage)","path":"/docs/guide/cli/generator/generator#advanced-usage","headings":["Расширенное использование (Advanced Usage)"],"excerpt":"Расширенное использование (Advanced Usage) Генерация с vendored зависимостями (оффлайн / Docker контейнеры) easyp mod vendor easyp generate","content":"Расширенное использование (Advanced Usage) Генерация с vendored зависимостями (оффлайн / Docker контейнеры) easyp mod vendor easyp generate"},{"id":"cli/generator/generator::advanced-usage::182","title":"Генератор","section":"Расширенное использование (Advanced Usage)","path":"/docs/guide/cli/generator/generator#advanced-usage","headings":["Расширенное использование (Advanced Usage)"],"excerpt":"Расширенное использование (Advanced Usage) Генерация из кастомного project root (удобно для монореп и вложенных рабочих директорий) easyp generate --root=/usr/local/src/my-project --path=./api/proto ```","content":"Расширенное использование (Advanced Usage) Генерация из кастомного project root (удобно для монореп и вложенных рабочих директорий) easyp generate --root=/usr/local/src/my-project --path=./api/proto ```"},{"id":"cli/generator/generator::common-patterns::183","title":"Генератор","section":"Типовые паттерны (Common Patterns)","path":"/docs/guide/cli/generator/generator#common-patterns","headings":["Типовые паттерны (Common Patterns)"],"excerpt":"Типовые паттерны (Common Patterns) Эти схемы отражают реальные сценарии и лучшие практики организации генерации кода в разных структурах проектов.","content":"Типовые паттерны (Common Patterns) Эти схемы отражают реальные сценарии и лучшие практики организации генерации кода в разных структурах проектов."},{"id":"cli/generator/generator::multi-language-generation::184","title":"Генератор","section":"Мульти-языковая генерация (Multi-Language Generation)","path":"/docs/guide/cli/generator/generator#multi-language-generation","headings":["Мульти-языковая генерация (Multi-Language Generation)"],"excerpt":"Мульти-языковая генерация (Multi-Language Generation) Мульти-языковая генерация критична для компаний, использующих разные технологии в стеке. EasyP облегчает получение согласованных клиентских библиотек и типов для неск","content":"Мульти-языковая генерация (Multi-Language Generation) Мульти-языковая генерация критична для компаний, использующих разные технологии в стеке. EasyP облегчает получение согласованных клиентских библиотек и типов для нескольких языков из одного источника proto."},{"id":"cli/generator/generator::multi-language-generation::185","title":"Генератор","section":"Мульти-языковая генерация (Multi-Language Generation)","path":"/docs/guide/cli/generator/generator#multi-language-generation","headings":["Мульти-языковая генерация (Multi-Language Generation)"],"excerpt":"Мульти-языковая генерация (Multi-Language Generation) **Типовые сценарии:** **Full‑stack приложения**: backend на Go/Java + фронтенд на TypeScript **Платформы данных**: сервисы на Go + аналитика / ML на Python **Микросер","content":"Мульти-языковая генерация (Multi-Language Generation) **Типовые сценарии:** **Full‑stack приложения**: backend на Go/Java + фронтенд на TypeScript **Платформы данных**: сервисы на Go + аналитика / ML на Python **Микросервисы**: каждый сервис — оптимальный язык под задачу **Внешние SDK**: предоставление клиентских библиотек партнёрам **Интеграция с легаси**: современные gRPC сервисы + старые системы"},{"id":"cli/generator/generator::multi-language-generation::186","title":"Генератор","section":"Мульти-языковая генерация (Multi-Language Generation)","path":"/docs/guide/cli/generator/generator#multi-language-generation","headings":["Мульти-языковая генерация (Multi-Language Generation)"],"excerpt":"Мульти-языковая генерация (Multi-Language Generation) **Производительность:** Каждый плагин запускается отдельно — время растёт линейно от количества плагинов Для больших наборов используйте параллельный запуск (make -j4","content":"Мульти-языковая генерация (Multi-Language Generation) **Производительность:** Каждый плагин запускается отдельно — время растёт линейно от количества плагинов Для больших наборов используйте параллельный запуск (make -j4) Структурируйте выходные директории иерархически — меньше конфликтов Плагины имеют разную скорость — профилируйте сборку для поиска узких мест"},{"id":"cli/generator/generator::multi-language-generation::187","title":"Генератор","section":"Мульти-языковая генерация (Multi-Language Generation)","path":"/docs/guide/cli/generator/generator#multi-language-generation","headings":["Мульти-языковая генерация (Multi-Language Generation)"],"excerpt":"Мульти-языковая генерация (Multi-Language Generation) **Преимущества сопровождения:** Единый источник истины для API снижает риск расхождения схем Согласованные типы уменьшают интеграционные баги Автоматическая синхрониз","content":"Мульти-языковая генерация (Multi-Language Generation) **Преимущества сопровождения:** Единый источник истины для API снижает риск расхождения схем Согласованные типы уменьшают интеграционные баги Автоматическая синхронизация при изменении proto исключает ручные правки Меньше риска дрейфа API между реализациями на разных языках Рефакторинг упрощается — изменения транзитивно отражаются во всех артефактах"},{"id":"cli/generator/generator::multi-language-generation::188","title":"Генератор","section":"Мульти-языковая генерация (Multi-Language Generation)","path":"/docs/guide/cli/generator/generator#multi-language-generation","headings":["Мульти-языковая генерация (Multi-Language Generation)"],"excerpt":"Мульти-языковая генерация (Multi-Language Generation) Ниже пример типичной мульти-языковой конфигурации для full‑stack приложения: backend, веб‑клиент, аналитика и документация:","content":"Мульти-языковая генерация (Multi-Language Generation) Ниже пример типичной мульти-языковой конфигурации для full‑stack приложения: backend, веб‑клиент, аналитика и документация:"},{"id":"cli/generator/generator::multi-language-generation::189","title":"Генератор","section":"Мульти-языковая генерация (Multi-Language Generation)","path":"/docs/guide/cli/generator/generator#multi-language-generation","headings":["Мульти-языковая генерация (Multi-Language Generation)"],"excerpt":"Мульти-языковая генерация (Multi-Language Generation)","content":"Мульти-языковая генерация (Multi-Language Generation)"},{"id":"cli/generator/generator::multi-language-generation::190","title":"Генератор","section":"Мульти-языковая генерация (Multi-Language Generation)","path":"/docs/guide/cli/generator/generator#multi-language-generation","headings":["Мульти-языковая генерация (Multi-Language Generation)"],"excerpt":"Мульти-языковая генерация (Multi-Language Generation) **Совет по организации:** Используйте отдельные выходные директории для каждого языка, чтобы избежать конфликтов файлов и упростить интеграцию с языковыми сборочными ","content":"Мульти-языковая генерация (Multi-Language Generation) **Совет по организации:** Используйте отдельные выходные директории для каждого языка, чтобы избежать конфликтов файлов и упростить интеграцию с языковыми сборочными системами."},{"id":"cli/generator/generator::multi-language-generation::191","title":"Генератор","section":"Мульти-языковая генерация (Multi-Language Generation)","path":"/docs/guide/cli/generator/generator#multi-language-generation","headings":["Мульти-языковая генерация (Multi-Language Generation)"],"excerpt":"Мульти-языковая генерация (Multi-Language Generation) Генератор EasyP — комплексное решение для генерации кода из Protocol Buffers: от простой локальной разработки до сложных enterprise‑сценариев с удалёнными зависимостя","content":"Мульти-языковая генерация (Multi-Language Generation) Генератор EasyP — комплексное решение для генерации кода из Protocol Buffers: от простой локальной разработки до сложных enterprise‑сценариев с удалёнными зависимостями и мульти-языковым выводом."},{"id":"cli/linter/linter::proto::0","title":"Линтер","section":"Зачем нужен линтер для proto файлов?","path":"/docs/guide/cli/linter/linter#proto","headings":["Зачем нужен линтер для proto файлов?"],"excerpt":"Зачем нужен линтер для proto файлов? Линтеры играют ключевую роль в современной разработке, особенно когда речь о .proto файлах. Они обеспечивают единый стиль и структуру, помогают находить потенциальные ошибки на ранних","content":"Зачем нужен линтер для proto файлов? Линтеры играют ключевую роль в современной разработке, особенно когда речь о .proto файлах. Они обеспечивают единый стиль и структуру, помогают находить потенциальные ошибки на ранних этапах и поддерживают читаемость кода. Это даёт выгоды:"},{"id":"cli/linter/linter::proto::1","title":"Линтер","section":"Зачем нужен линтер для proto файлов?","path":"/docs/guide/cli/linter/linter#proto","headings":["Зачем нужен линтер для proto файлов?"],"excerpt":"Зачем нужен линтер для proto файлов? **Снижение затрат на разработку:** Ошибки ловятся раньше, меньше времени на отладку. **Улучшение командного взаимодействия:** Единообразный код легче понимать и сопровождать. **Бизнес","content":"Зачем нужен линтер для proto файлов? **Снижение затрат на разработку:** Ошибки ловятся раньше, меньше времени на отладку. **Улучшение командного взаимодействия:** Единообразный код легче понимать и сопровождать. **Бизнес-эффективность:** Более качественный код → меньше инцидентов в проде → ниже стоимость поддержки."},{"id":"cli/linter/linter::top::2","title":"Линтер","section":"Справочник по конфигурации","path":"/docs/guide/cli/linter/linter","headings":["Справочник по конфигурации"],"excerpt":"Справочник по конфигурации Конфигурация линтера настраивается в секции lint файла easyp.yaml.","content":"Справочник по конфигурации Конфигурация линтера настраивается в секции lint файла easyp.yaml."},{"id":"cli/linter/linter::use-string::3","title":"Линтер","section":"use ([]string)","path":"/docs/guide/cli/linter/linter#use-string","headings":["use ([]string)"],"excerpt":"use ([]string) Определяет набор правил или категорий для включения. Можно смешивать категории и конкретные правила.","content":"use ([]string) Определяет набор правил или категорий для включения. Можно смешивать категории и конкретные правила."},{"id":"cli/linter/linter::use-string::4","title":"Линтер","section":"use ([]string)","path":"/docs/guide/cli/linter/linter#use-string","headings":["use ([]string)"],"excerpt":"use ([]string) **Категории:** **MINIMAL**: Базовая согласованность пакетов **BASIC**: Соглашения по именованию и структуре **DEFAULT**: Рекомендованные правила для большинства проектов **COMMENTS**: Требования к коммента","content":"use ([]string) **Категории:** **MINIMAL**: Базовая согласованность пакетов **BASIC**: Соглашения по именованию и структуре **DEFAULT**: Рекомендованные правила для большинства проектов **COMMENTS**: Требования к комментариям **UNARY_RPC**: Ограничение на streaming RPC"},{"id":"cli/linter/linter::use-string::5","title":"Линтер","section":"use ([]string)","path":"/docs/guide/cli/linter/linter#use-string","headings":["use ([]string)"],"excerpt":"use ([]string) **Индивидуальные правила:** Любое имя правила (например ENUM_PASCAL_CASE, FIELD_LOWER_SNAKE_CASE)","content":"use ([]string) **Индивидуальные правила:** Любое имя правила (например ENUM_PASCAL_CASE, FIELD_LOWER_SNAKE_CASE)"},{"id":"cli/linter/linter::use-string::6","title":"Линтер","section":"use ([]string)","path":"/docs/guide/cli/linter/linter#use-string","headings":["use ([]string)"],"excerpt":"use ([]string) **Примеры:** ```yaml Только категории use: [MINIMAL, BASIC, DEFAULT]","content":"use ([]string) **Примеры:** ```yaml Только категории use: [MINIMAL, BASIC, DEFAULT]"},{"id":"cli/linter/linter::use-string::7","title":"Линтер","section":"use ([]string)","path":"/docs/guide/cli/linter/linter#use-string","headings":["use ([]string)"],"excerpt":"use ([]string) Смешивание use: - MINIMAL - COMMENT_SERVICE - COMMENT_RPC - ENUM_PASCAL_CASE","content":"use ([]string) Смешивание use: - MINIMAL - COMMENT_SERVICE - COMMENT_RPC - ENUM_PASCAL_CASE"},{"id":"cli/linter/linter::use-string::8","title":"Линтер","section":"use ([]string)","path":"/docs/guide/cli/linter/linter#use-string","headings":["use ([]string)"],"excerpt":"use ([]string) Точный набор use: - PACKAGE_DEFINED - SERVICE_PASCAL_CASE - FIELD_LOWER_SNAKE_CASE ```","content":"use ([]string) Точный набор use: - PACKAGE_DEFINED - SERVICE_PASCAL_CASE - FIELD_LOWER_SNAKE_CASE ```"},{"id":"cli/linter/linter::enum_zero_value_suffix-string::9","title":"Линтер","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) Обязывает нулевое значение enum иметь заданный суффикс.","content":"enum_zero_value_suffix (string) Обязывает нулевое значение enum иметь заданный суффикс."},{"id":"cli/linter/linter::enum_zero_value_suffix-string::10","title":"Линтер","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) **Обычно:** \"UNSPECIFIED\", \"UNKNOWN\", \"DEFAULT\"","content":"enum_zero_value_suffix (string) **Обычно:** \"UNSPECIFIED\", \"UNKNOWN\", \"DEFAULT\""},{"id":"cli/linter/linter::enum_zero_value_suffix-string::11","title":"Линтер","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)","content":"enum_zero_value_suffix (string)"},{"id":"cli/linter/linter::service_suffix-string::12","title":"Линтер","section":"service_suffix (string)","path":"/docs/guide/cli/linter/linter#service_suffix-string","headings":["service_suffix (string)"],"excerpt":"service_suffix (string) Требуемый суффикс для имён сервисов (унификация стиля).","content":"service_suffix (string) Требуемый суффикс для имён сервисов (унификация стиля)."},{"id":"cli/linter/linter::ignore-string::13","title":"Линтер","section":"ignore ([]string)","path":"/docs/guide/cli/linter/linter#ignore-string","headings":["ignore ([]string)"],"excerpt":"ignore ([]string) Полное исключение путей из линтинга.","content":"ignore ([]string) Полное исключение путей из линтинга."},{"id":"cli/linter/linter::ignore-string::14","title":"Линтер","section":"ignore ([]string)","path":"/docs/guide/cli/linter/linter#ignore-string","headings":["ignore ([]string)"],"excerpt":"ignore ([]string) **Use cases:** vendor / third_party сгенерированные файлы легаси подпакеты тестовые фикстуры","content":"ignore ([]string) **Use cases:** vendor / third_party сгенерированные файлы легаси подпакеты тестовые фикстуры"},{"id":"cli/linter/linter::except-string::15","title":"Линтер","section":"except ([]string)","path":"/docs/guide/cli/linter/linter#except-string","headings":["except ([]string)"],"excerpt":"except ([]string) Глобально отключает правила.","content":"except ([]string) Глобально отключает правила."},{"id":"cli/linter/linter::allow_comment_ignores-bool::16","title":"Линтер","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) Разрешает инлайн‑игнор правил комментариями.","content":"allow_comment_ignores (bool) Разрешает инлайн‑игнор правил комментариями."},{"id":"cli/linter/linter::ignore_only-mapstringstring::17","title":"Линтер","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) Таргетированное игнорирование конкретных правил для указанных путей.","content":"ignore_only (mapstringstring) Таргетированное игнорирование конкретных правил для указанных путей."},{"id":"cli/linter/linter::top::18","title":"Линтер","section":"Игнор правил комментариями","path":"/docs/guide/cli/linter/linter","headings":["Игнор правил комментариями"],"excerpt":"Игнор правил комментариями Если включён allow_comment_ignores, можно точечно отключать правила.","content":"Игнор правил комментариями Если включён allow_comment_ignores, можно точечно отключать правила."},{"id":"cli/linter/linter::top::19","title":"Линтер","section":"Несколько правил в одной строке","path":"/docs/guide/cli/linter/linter","headings":["Несколько правил в одной строке"],"excerpt":"Несколько правил в одной строке","content":"Несколько правил в одной строке"},{"id":"cli/linter/linter::top::20","title":"Линтер","section":"Используйте редко","path":"/docs/guide/cli/linter/linter","headings":["Используйте редко"],"excerpt":"Используйте редко Частое игнорирование = сигнал пересмотреть конфигурацию.","content":"Используйте редко Частое игнорирование = сигнал пересмотреть конфигурацию."},{"id":"cli/linter/linter::top::21","title":"Линтер","section":"Предпочитайте конфигурацию","path":"/docs/guide/cli/linter/linter","headings":["Предпочитайте конфигурацию"],"excerpt":"Предпочитайте конфигурацию Если нужно игнорировать правило в группе файлов — используйте ignore_only.","content":"Предпочитайте конфигурацию Если нужно игнорировать правило в группе файлов — используйте ignore_only."},{"id":"cli/linter/linter::top::22","title":"Линтер","section":"Категории линтера","path":"/docs/guide/cli/linter/linter","headings":["Категории линтера"],"excerpt":"Категории линтера Категории помогают быстро выбрать уровень строгости.","content":"Категории линтера Категории помогают быстро выбрать уровень строгости."},{"id":"cli/linter/linter::top::23","title":"Линтер","section":"Категории линтера","path":"/docs/guide/cli/linter/linter","headings":["Категории линтера"],"excerpt":"Категории линтера **Когда использовать:** **MINIMAL**: Минимальная базовая целостность **BASIC**: Частые соглашения имен **DEFAULT**: Дополнительные проверки качества **COMMENTS**: Обязательные комментарии (API, команды)","content":"Категории линтера **Когда использовать:** **MINIMAL**: Минимальная базовая целостность **BASIC**: Частые соглашения имен **DEFAULT**: Дополнительные проверки качества **COMMENTS**: Обязательные комментарии (API, команды) **UNARY_RPC**: Ограничить streaming RPC"},{"id":"cli/linter/linter::minimal::24","title":"Линтер","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::25","title":"Линтер","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::26","title":"Линтер","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::27","title":"Линтер","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::28","title":"Линтер","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::top::29","title":"Линтер","section":"Заключение","path":"/docs/guide/cli/linter/linter","headings":["Заключение"],"excerpt":"Заключение Внедрение EasyP линдера для ваших proto файлов заметно улучшит workflow, качество и поддерживаемость кода. Полная совместимость с Buf позволяет командам мигрировать без боли, используя гибкую конфигурацию и мо","content":"Заключение Внедрение EasyP линдера для ваших proto файлов заметно улучшит workflow, качество и поддерживаемость кода. Полная совместимость с Buf позволяет командам мигрировать без боли, используя гибкую конфигурацию и мощные возможности из коробки."},{"id":"cli/linter/rules/comment-enum-value::top::0","title":"COMMENT_ENUM_VALUE","path":"/docs/guide/cli/linter/rules/comment-enum-value","headings":[],"excerpt":"Это правило проверяет, что все значения enum имеют комментарий.","content":"Это правило проверяет, что все значения enum имеют комментарий."},{"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 ```proto syntax = \"proto3\";","content":"Good ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/comment-enum-value::good::4","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":"Это правило проверяет, что enum имеет комментарий.","content":"Это правило проверяет, что enum имеет комментарий."},{"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":"Это правило проверяет, что все поля сообщений имеют комментарий.","content":"Это правило проверяет, что все поля сообщений имеют комментарий."},{"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":"Это правило проверяет, что message имеет комментарий.","content":"Это правило проверяет, что message имеет комментарий."},{"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 ```proto syntax = \"proto3\";","content":"Bad ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/comment-message::bad::2","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::3","title":"COMMENT_MESSAGE","section":"Good","path":"/docs/guide/cli/linter/rules/comment-message#good","headings":["Good"],"excerpt":"Good ```proto syntax = \"proto3\";","content":"Good ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/comment-message::good::4","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":"Это правило проверяет, что oneof имеет комментарий.","content":"Это правило проверяет, что oneof имеет комментарий."},{"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":"Это правило проверяет, что сервис имеет комментарий.","content":"Это правило проверяет, что сервис имеет комментарий."},{"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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **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":"Это правило проверяет, что все файлы в заданной директории находятся в одном и том же package.","content":"Это правило проверяет, что все файлы в заданной директории находятся в одном и том же 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":"Это правило проверяет, что первое значение enum равно нулю.","content":"Это правило проверяет, что первое значение enum равно нулю."},{"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 ```proto syntax = \"proto3\";","content":"Bad ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/enum-first-value-zero::bad::3","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::4","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::5","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":"Это правило проверяет, что опция allow_alias не установлена в значение true внутри enum.","content":"Это правило проверяет, что опция allow_alias не установлена в значение true внутри 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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **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":"Это правило проверяет, что имена enum написаны в стиле PascalCase.","content":"Это правило проверяет, что имена enum написаны в стиле 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":"Это правило проверяет, что все значения enum имеют префикс, совпадающий с именем enum.","content":"Это правило проверяет, что все значения enum имеют префикс, совпадающий с именем enum."},{"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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **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":"Это правило проверяет, что значения enum записаны в стиле UPPER_SNAKE_CASE.","content":"Это правило проверяет, что значения enum записаны в стиле 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":"Это правило проверяет, что все нулевые значения enum имеют суффикс _NONE или ваш кастомный (пользовательский) суффикс.","content":"Это правило проверяет, что все нулевые значения enum имеют суффикс _NONE или ваш кастомный (пользовательский) суффикс."},{"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":"**MINIMAL** **BASIC** **DEFAULT**","content":"**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":"Это правило проверяет, что имена полей сообщений записаны в стиле lower_snake_case.","content":"Это правило проверяет, что имена полей сообщений записаны в стиле 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":"Это правило проверяет, что все файлы имеют имя в формате lower_snake_case (только строчные буквы, цифры и символ подчеркивания, без пробелов и заглавных букв).","content":"Это правило проверяет, что все файлы имеют имя в формате 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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **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":"Это правило проверяет, что в proto-файле не используются public импорты (оператор import public \"...\").","content":"Это правило проверяет, что в proto-файле не используются public импорты (оператор import public \"...\")."},{"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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **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":"Это правило проверяет, что в proto‑файле не используются weak‑импорты (import weak \"...\").","content":"Это правило проверяет, что в proto‑файле не используются weak‑импорты (import weak \"...\")."},{"id":"cli/linter/rules/import-no-weak::top::2","title":"IMPORT_NO_WEAK","path":"/docs/guide/cli/linter/rules/import-no-weak","headings":[],"excerpt":"Weak import (синтаксис import weak) допустим в proto2, но его использование усложняет анализ зависимостей и может приводить к неочевидным ошибкам при генерации кода. Рекомендуется всегда использовать обычный import.","content":"Weak import (синтаксис import weak) допустим в proto2, но его использование усложняет анализ зависимостей и может приводить к неочевидным ошибкам при генерации кода. Рекомендуется всегда использовать обычный import."},{"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 ```proto syntax = \"proto2\";","content":"Bad ```proto syntax = \"proto2\";"},{"id":"cli/linter/rules/import-no-weak::bad::4","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::5","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::6","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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **MINIMAL** **BASIC** **DEFAULT**"},{"id":"cli/linter/rules/import-used::top::1","title":"IMPORT_USED","path":"/docs/guide/cli/linter/rules/import-used","headings":[],"excerpt":"Это правило проверяет, что все импорты используются в proto-файле.","content":"Это правило проверяет, что все импорты используются в proto-файле."},{"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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **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":"Это правило проверяет, что имена сообщений (message) записаны в стиле PascalCase.","content":"Это правило проверяет, что имена сообщений (message) записаны в стиле 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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **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":"Это правило проверяет, что имена oneof записаны в стиле lower_snake_case.","content":"Это правило проверяет, что имена oneof записаны в стиле 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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **MINIMAL** **BASIC** **DEFAULT**"},{"id":"cli/linter/rules/package-defined::top::1","title":"PACKAGE_DEFINED","path":"/docs/guide/cli/linter/rules/package-defined","headings":[],"excerpt":"Это правило проверяет, что во всех файлах присутствует директива package.","content":"Это правило проверяет, что во всех файлах присутствует директива package."},{"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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **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":"Это правило проверяет, что все файлы находятся в директории, имя которой соответствует имени их пакета.","content":"Это правило проверяет, что все файлы находятся в директории, имя которой соответствует имени их пакета."},{"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":"Это правило проверяет, что имена package записаны в формате lower_snake_case (строчные буквы, при необходимости цифры и символ подчеркивания, без пробелов и заглавных букв).","content":"Это правило проверяет, что имена package записаны в формате 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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **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":"Это правило проверяет, что все файлы с заданным пакетом используют одно и то же пространство имён C# (csharp_namespace).","content":"Это правило проверяет, что все файлы с заданным пакетом используют одно и то же пространство имён C# (csharp_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\"; // [!code focus] ```","content":"Good option csharp_namespace = \"Foo.Bar\"; // [!code focus] ```"},{"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 ```proto // File: pkg/bar.proto","content":"Good ```proto // File: pkg/bar.proto"},{"id":"cli/linter/rules/package-same-csharp-namespace::good::9","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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **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":"Это правило проверяет, что все файлы с данным package находятся в одной директории.","content":"Это правило проверяет, что все файлы с данным package находятся в одной директории."},{"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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **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":"Это правило проверяет, что все файлы с одним и тем же package используют одно и то же значение опции go_package.","content":"Это правило проверяет, что все файлы с одним и тем же package используют одно и то же значение опции 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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **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":"Это правило проверяет, что все файлы с одним и тем же package используют одинаковое значение опции java_package.","content":"Это правило проверяет, что все файлы с одним и тем же package используют одинаковое значение опции 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 ```proto // File: pkg/bar.proto","content":"Bad ```proto // File: pkg/bar.proto"},{"id":"cli/linter/rules/package-same-java-multiple-files::bad::6","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::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 ```proto // File: pkg/foo.proto","content":"Good ```proto // File: pkg/foo.proto"},{"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 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::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 ```proto // File: pkg/bar.proto","content":"Good ```proto // File: pkg/bar.proto"},{"id":"cli/linter/rules/package-same-java-multiple-files::good::10","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":"Это правило проверяет, что все файлы с одним и тем же package используют одно и то же значение опции java_package.","content":"Это правило проверяет, что все файлы с одним и тем же package используют одно и то же значение опции 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":"Это правило проверяет, что все файлы с одним и тем же package используют одно и то же значение опции php_namespace.","content":"Это правило проверяет, что все файлы с одним и тем же package используют одно и то же значение опции 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":"Это правило проверяет, что все файлы с одним и тем же package используют один и тот же swift_prefix.","content":"Это правило проверяет, что все файлы с одним и тем же package используют один и тот же 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":"Это правило проверяет, что суффикс версии пакета имеет формат _vX, где X — числовая версия.","content":"Это правило проверяет, что суффикс версии пакета имеет формат _vX, где X — числовая версия."},{"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":"Это правило проверяет, что RPC не использует клиентский стриминг (запрос не является stream ...).","content":"Это правило проверяет, что RPC не использует клиентский стриминг (запрос не является stream ...)."},{"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":"Это правило проверяет, что RPC не использует серверный стриминг (ответ не является stream ...).","content":"Это правило проверяет, что RPC не использует серверный стриминг (ответ не является stream ...)."},{"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":"Это правило проверяет, что все имена RPC написаны в стиле PascalCase.","content":"Это правило проверяет, что все имена RPC написаны в стиле 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":"Это правило проверяет, что все сообщения запроса и ответа RPC уникальны: для каждого метода используются собственные (не переиспользуются одинаковые пары Request / Response у разных RPC).","content":"Это правило проверяет, что все сообщения запроса и ответа RPC уникальны: для каждого метода используются собственные (не переиспользуются одинаковые пары Request / Response у разных RPC)."},{"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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **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":"Это правило проверяет, что все сообщения запроса RPC названы в формате MethodRequest.","content":"Это правило проверяет, что все сообщения запроса RPC названы в формате 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":"Это правило проверяет, что все сообщения ответа RPC названы в формате MethodResponse.","content":"Это правило проверяет, что все сообщения ответа RPC названы в формате 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":"**MINIMAL** **BASIC** **DEFAULT**","content":"**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":"Это правило проверяет, что все имена сервисов написаны в стиле PascalCase.","content":"Это правило проверяет, что все имена сервисов написаны в стиле 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":"Это правило проверяет, что все сервисы имеют суффикс Service или ваш пользовательский суффикс.","content":"Это правило проверяет, что все сервисы имеют суффикс Service или ваш пользовательский суффикс."},{"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 против Buf: управление пакетами","path":"/docs/guide/cli/package-manager/easyp-vs-buf","headings":[],"excerpt":"EasyP против Buf: управление пакетами","content":"EasyP против Buf: управление пакетами"},{"id":"cli/package-manager/easyp-vs-buf::top::1","title":"EasyP против Buf: управление пакетами","path":"/docs/guide/cli/package-manager/easyp-vs-buf","headings":[],"excerpt":"Этот документ даёт подробное сравнение децентрализованного подхода EasyP к управлению пакетами и централизованной модели Buf через Buf Schema Registry (BSR), чтобы помочь понять ключевые различия и выбрать подходящее реш","content":"Этот документ даёт подробное сравнение децентрализованного подхода EasyP к управлению пакетами и централизованной модели Buf через Buf Schema Registry (BSR), чтобы помочь понять ключевые различия и выбрать подходящее решение для ваших задач."},{"id":"cli/package-manager/easyp-vs-buf::easyp-git::2","title":"EasyP против Buf: управление пакетами","section":"EasyP: децентрализованный подход на базе Git","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp-git","headings":["EasyP: децентрализованный подход на базе Git"],"excerpt":"EasyP: децентрализованный подход на базе Git","content":"EasyP: децентрализованный подход на базе Git"},{"id":"cli/package-manager/easyp-vs-buf::buf-bsr::3","title":"EasyP против Buf: управление пакетами","section":"Buf: централизованный реестр (BSR)","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf-bsr","headings":["Buf: централизованный реестр (BSR)"],"excerpt":"Buf: централизованный реестр (BSR)","content":"Buf: централизованный реестр (BSR)"},{"id":"cli/package-manager/easyp-vs-buf::top::4","title":"EasyP против Buf: управление пакетами","section":"Краткое резюме различий","path":"/docs/guide/cli/package-manager/easyp-vs-buf","headings":["Краткое резюме различий"],"excerpt":"Краткое резюме различий Аспект EasyP Buf -------- ------- ----- **Архитектура** Децентрализованная (Git) Централизованная (реестр BSR) **Источник зависимостей** Любой Git репозиторий Только модули BSR **Единая точка отка","content":"Краткое резюме различий Аспект EasyP Buf -------- ------- ----- **Архитектура** Децентрализованная (Git) Централизованная (реестр BSR) **Источник зависимостей** Любой Git репозиторий Только модули BSR **Единая точка отказа** Нет Да (buf.build) **Enterprise / air‑gapped** Полная поддержка Требует доступа к BSR или приватного BSR **Аутентификация** Git (SSH / HTTPS) Токены Buf + Git **Vendor lock‑in** Отсутствует Привязка к экосистеме Buf **Частные репозитории** Нативно через Git Нужно опубликовать в BSR **Оффлайн поддержка** Полная (через vendoring) Ограничена (кэшированные модули) **Стоимость** Бесплатно (использует существующий Git) Бесплатный тариф + платные планы **Сложность настройки** Минимальная Средняя (настройка BSR)"},{"id":"cli/package-manager/easyp-vs-buf::top::5","title":"EasyP против Buf: управление пакетами","section":"Подробное сравнение возможностей","path":"/docs/guide/cli/package-manager/easyp-vs-buf","headings":["Подробное сравнение возможностей"],"excerpt":"Подробное сравнение возможностей","content":"Подробное сравнение возможностей"},{"id":"cli/package-manager/easyp-vs-buf::1::6","title":"EasyP против Buf: управление пакетами","section":"1. Философия управления зависимостями","path":"/docs/guide/cli/package-manager/easyp-vs-buf#1","headings":["1. Философия управления зависимостями"],"excerpt":"Философия управления зависимостями","content":"Философия управления зависимостями"},{"id":"cli/package-manager/easyp-vs-buf::easyp-git::7","title":"EasyP против Buf: управление пакетами","section":"EasyP: «Любой Git репозиторий — это пакет»","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp-git","headings":["EasyP: «Любой Git репозиторий — это пакет»"],"excerpt":"EasyP: «Любой Git репозиторий — это пакет»","content":"EasyP: «Любой Git репозиторий — это пакет»"},{"id":"cli/package-manager/easyp-vs-buf::easyp-git::8","title":"EasyP против Buf: управление пакетами","section":"EasyP: «Любой Git репозиторий — это пакет»","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp-git","headings":["EasyP: «Любой Git репозиторий — это пакет»"],"excerpt":"EasyP: «Любой Git репозиторий — это пакет» **Преимущества:** ✅ Использование любого существующего репозитория сразу ✅ Не нужно «публиковать» в отдельный реестр ✅ Истинный источник версий — Git ✅ Работает с приватными сер","content":"EasyP: «Любой Git репозиторий — это пакет» **Преимущества:** ✅ Использование любого существующего репозитория сразу ✅ Не нужно «публиковать» в отдельный реестр ✅ Истинный источник версий — Git ✅ Работает с приватными серверами без доп. настроек"},{"id":"cli/package-manager/easyp-vs-buf::buf::9","title":"EasyP против Buf: управление пакетами","section":"Buf: «Сначала реестр»","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf","headings":["Buf: «Сначала реестр»"],"excerpt":"Buf: «Сначала реестр» **Преимущества:** ✅ Курируемые, проверенные модули ✅ Богатые метаданные и документация ✅ Визуализация графа зависимостей ✅ Принуждение семантического версионирования","content":"Buf: «Сначала реестр» **Преимущества:** ✅ Курируемые, проверенные модули ✅ Богатые метаданные и документация ✅ Визуализация графа зависимостей ✅ Принуждение семантического версионирования"},{"id":"cli/package-manager/easyp-vs-buf::buf::10","title":"EasyP против Buf: управление пакетами","section":"Buf: «Сначала реестр»","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf","headings":["Buf: «Сначала реестр»"],"excerpt":"Buf: «Сначала реестр» **Ограничения:** ❌ Нужно опубликовать в BSR перед использованием ❌ Требует аккаунт и аутентификацию ❌ Нельзя напрямую сослаться на произвольный Git репозиторий","content":"Buf: «Сначала реестр» **Ограничения:** ❌ Нужно опубликовать в BSR перед использованием ❌ Требует аккаунт и аутентификацию ❌ Нельзя напрямую сослаться на произвольный Git репозиторий"},{"id":"cli/package-manager/easyp-vs-buf::2-airgapped::11","title":"EasyP против Buf: управление пакетами","section":"2. Корпоративные и изолированные (air‑gapped) среды","path":"/docs/guide/cli/package-manager/easyp-vs-buf#2-airgapped","headings":["2. Корпоративные и изолированные (air‑gapped) среды"],"excerpt":"Корпоративные и изолированные (air‑gapped) среды","content":"Корпоративные и изолированные (air‑gapped) среды"},{"id":"cli/package-manager/easyp-vs-buf::easyp::12","title":"EasyP против Buf: управление пакетами","section":"EasyP: Полноценная оффлайн‑поддержка","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["EasyP: Полноценная оффлайн‑поддержка"],"excerpt":"EasyP: Полноценная оффлайн‑поддержка **Сценарий**: крупная компания со строгими сетевыми политиками","content":"EasyP: Полноценная оффлайн‑поддержка **Сценарий**: крупная компания со строгими сетевыми политиками"},{"id":"cli/package-manager/easyp-vs-buf::easyp::13","title":"EasyP против Buf: управление пакетами","section":"EasyP: Полноценная оффлайн‑поддержка","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["EasyP: Полноценная оффлайн‑поддержка"],"excerpt":"EasyP: Полноценная оффлайн‑поддержка ```bash Среда с доступом в интернет easyp mod download # Скачивает в ~/.easyp/ easyp mod vendor # Создает easyp_vendor/","content":"EasyP: Полноценная оффлайн‑поддержка ```bash Среда с доступом в интернет easyp mod download # Скачивает в ~/.easyp/ easyp mod vendor # Создает easyp_vendor/"},{"id":"cli/package-manager/easyp-vs-buf::easyp::14","title":"EasyP против Buf: управление пакетами","section":"EasyP: Полноценная оффлайн‑поддержка","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["EasyP: Полноценная оффлайн‑поддержка"],"excerpt":"EasyP: Полноценная оффлайн‑поддержка Перенос в изолированный сегмент tar -czf easyp-deps.tar.gz ~/.easyp easyp_vendor/ ... перенос архива ...","content":"EasyP: Полноценная оффлайн‑поддержка Перенос в изолированный сегмент tar -czf easyp-deps.tar.gz ~/.easyp easyp_vendor/ ... перенос архива ..."},{"id":"cli/package-manager/easyp-vs-buf::easyp::15","title":"EasyP против Buf: управление пакетами","section":"EasyP: Полноценная оффлайн‑поддержка","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["EasyP: Полноценная оффлайн‑поддержка"],"excerpt":"EasyP: Полноценная оффлайн‑поддержка В изолированной среде tar -xzf easyp-deps.tar.gz export EASYPPATH=$PWD/.easyp easyp generate # Работает оффлайн ```","content":"EasyP: Полноценная оффлайн‑поддержка В изолированной среде tar -xzf easyp-deps.tar.gz export EASYPPATH=$PWD/.easyp easyp generate # Работает оффлайн ```"},{"id":"cli/package-manager/easyp-vs-buf::easyp::16","title":"EasyP против Buf: управление пакетами","section":"EasyP: Полноценная оффлайн‑поддержка","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["EasyP: Полноценная оффлайн‑поддержка"],"excerpt":"EasyP: Полноценная оффлайн‑поддержка **Плюсы:** ✅ Не зависит от внешних сервисов ✅ Не нужен внутренний реестр ✅ Использует существующую Git инфраструктуру ✅ Простая файловая дистрибуция","content":"EasyP: Полноценная оффлайн‑поддержка **Плюсы:** ✅ Не зависит от внешних сервисов ✅ Не нужен внутренний реестр ✅ Использует существующую Git инфраструктуру ✅ Простая файловая дистрибуция"},{"id":"cli/package-manager/easyp-vs-buf::buf::17","title":"EasyP против Buf: управление пакетами","section":"Buf: Требует инфраструктуру реестра","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf","headings":["Buf: Требует инфраструктуру реестра"],"excerpt":"Buf: Требует инфраструктуру реестра ```bash Вариант 1: использовать buf.build (нужен интернет) buf mod download","content":"Buf: Требует инфраструктуру реестра ```bash Вариант 1: использовать buf.build (нужен интернет) buf mod download"},{"id":"cli/package-manager/easyp-vs-buf::buf::18","title":"EasyP против Buf: управление пакетами","section":"Buf: Требует инфраструктуру реестра","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf","headings":["Buf: Требует инфраструктуру реестра"],"excerpt":"Buf: Требует инфраструктуру реестра Вариант 2: поднимать приватный BSR (сложно) Развернуть сервер реестра Перепубликовать все модули внутрь Настроить доступы, аутентификацию Поддерживать работоспособность ```","content":"Buf: Требует инфраструктуру реестра Вариант 2: поднимать приватный BSR (сложно) Развернуть сервер реестра Перепубликовать все модули внутрь Настроить доступы, аутентификацию Поддерживать работоспособность ```"},{"id":"cli/package-manager/easyp-vs-buf::buf::19","title":"EasyP против Buf: управление пакетами","section":"Buf: Требует инфраструктуру реестра","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf","headings":["Buf: Требует инфраструктуру реестра"],"excerpt":"Buf: Требует инфраструктуру реестра **Минусы:** ❌ Постоянный интернет или дорогой приватный BSR ❌ Сложная инфраструктура для частных установок ❌ Все модули нужно републиковать ❌ Дополнительные операционные затраты","content":"Buf: Требует инфраструктуру реестра **Минусы:** ❌ Постоянный интернет или дорогой приватный BSR ❌ Сложная инфраструктура для частных установок ❌ Все модули нужно републиковать ❌ Дополнительные операционные затраты"},{"id":"cli/package-manager/easyp-vs-buf::easyp::20","title":"EasyP против Buf: управление пакетами","section":"EasyP: Прямой контроль","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["EasyP: Прямой контроль"],"excerpt":"EasyP: Прямой контроль ```yaml Полный контроль источников deps: # Публичный репозиторий — ваша конкретная версия - github.com/googleapis/googleapis@common-protos-1_3_1","content":"EasyP: Прямой контроль ```yaml Полный контроль источников deps: # Публичный репозиторий — ваша конкретная версия - github.com/googleapis/googleapis@common-protos-1_3_1"},{"id":"cli/package-manager/easyp-vs-buf::easyp::21","title":"EasyP против Buf: управление пакетами","section":"EasyP: Прямой контроль","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["EasyP: Прямой контроль"],"excerpt":"EasyP: Прямой контроль Внутренний репозиторий - gitlab.company.com/security/validated-protos@v1.0.0","content":"EasyP: Прямой контроль Внутренний репозиторий - gitlab.company.com/security/validated-protos@v1.0.0"},{"id":"cli/package-manager/easyp-vs-buf::easyp::22","title":"EasyP против Buf: управление пакетами","section":"EasyP: Прямой контроль","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["EasyP: Прямой контроль"],"excerpt":"EasyP: Прямой контроль Точный коммит (горячий фикс) - github.com/bufbuild/protoc-gen-validate@abc123def456 ```","content":"EasyP: Прямой контроль Точный коммит (горячий фикс) - github.com/bufbuild/protoc-gen-validate@abc123def456 ```"},{"id":"cli/package-manager/easyp-vs-buf::easyp::23","title":"EasyP против Buf: управление пакетами","section":"EasyP: Прямой контроль","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["EasyP: Прямой контроль"],"excerpt":"EasyP: Прямой контроль **Преимущества по безопасности:** ✅ Нет посредника — берём из исходного репозитория ✅ Аудит через историю Git ✅ Нельзя «забанить» доступ извне ✅ Свои процессы сканирования / валидации ✅ Можно форкн","content":"EasyP: Прямой контроль **Преимущества по безопасности:** ✅ Нет посредника — берём из исходного репозитория ✅ Аудит через историю Git ✅ Нельзя «забанить» доступ извне ✅ Свои процессы сканирования / валидации ✅ Можно форкнуть и удерживать критические версии"},{"id":"cli/package-manager/easyp-vs-buf::buf::24","title":"EasyP против Buf: управление пакетами","section":"Buf: Зависимость от реестра","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf","headings":["Buf: Зависимость от реестра"],"excerpt":"Buf: Зависимость от реестра **Риски:** ⚠️ Посредник контролирует доступность ⚠️ Возможны ограничения / санкции на аккаунт ⚠️ Модуль могут удалить или депрекейтнуть ⚠️ Политики обновлений диктуются стороной ⚠️ Нужно довер","content":"Buf: Зависимость от реестра **Риски:** ⚠️ Посредник контролирует доступность ⚠️ Возможны ограничения / санкции на аккаунт ⚠️ Модуль могут удалить или депрекейтнуть ⚠️ Политики обновлений диктуются стороной ⚠️ Нужно доверять внешней безопасности"},{"id":"cli/package-manager/easyp-vs-buf::1::25","title":"EasyP против Buf: управление пакетами","section":"Сценарий 1: Стартап с публичными зависимостями","path":"/docs/guide/cli/package-manager/easyp-vs-buf#1","headings":["Сценарий 1: Стартап с публичными зависимостями"],"excerpt":"Сценарий 1: Стартап с публичными зависимостями **EasyP:**","content":"Сценарий 1: Стартап с публичными зависимостями **EasyP:**"},{"id":"cli/package-manager/easyp-vs-buf::1::26","title":"EasyP против Buf: управление пакетами","section":"Сценарий 1: Стартап с публичными зависимостями","path":"/docs/guide/cli/package-manager/easyp-vs-buf#1","headings":["Сценарий 1: Стартап с публичными зависимостями"],"excerpt":"Сценарий 1: Стартап с публичными зависимостями **Buf:**","content":"Сценарий 1: Стартап с публичными зависимостями **Buf:**"},{"id":"cli/package-manager/easyp-vs-buf::1::27","title":"EasyP против Buf: управление пакетами","section":"Сценарий 1: Стартап с публичными зависимостями","path":"/docs/guide/cli/package-manager/easyp-vs-buf#1","headings":["Сценарий 1: Стартап с публичными зависимостями"],"excerpt":"Сценарий 1: Стартап с публичными зависимостями **Итог:** Паритет — оба хорошо подходят для публичных пакетов.","content":"Сценарий 1: Стартап с публичными зависимостями **Итог:** Паритет — оба хорошо подходят для публичных пакетов."},{"id":"cli/package-manager/easyp-vs-buf::2::28","title":"EasyP против Buf: управление пакетами","section":"Сценарий 2: Компания со смешанными публичными/приватными зависимостями","path":"/docs/guide/cli/package-manager/easyp-vs-buf#2","headings":["Сценарий 2: Компания со смешанными публичными/приватными зависимостями"],"excerpt":"Сценарий 2: Компания со смешанными публичными/приватными зависимостями **EasyP:**","content":"Сценарий 2: Компания со смешанными публичными/приватными зависимостями **EasyP:**"},{"id":"cli/package-manager/easyp-vs-buf::2::29","title":"EasyP против Buf: управление пакетами","section":"Сценарий 2: Компания со смешанными публичными/приватными зависимостями","path":"/docs/guide/cli/package-manager/easyp-vs-buf#2","headings":["Сценарий 2: Компания со смешанными публичными/приватными зависимостями"],"excerpt":"Сценарий 2: Компания со смешанными публичными/приватными зависимостями **Buf:**","content":"Сценарий 2: Компания со смешанными публичными/приватными зависимостями **Buf:**"},{"id":"cli/package-manager/easyp-vs-buf::2::30","title":"EasyP против Buf: управление пакетами","section":"Сценарий 2: Компания со смешанными публичными/приватными зависимостями","path":"/docs/guide/cli/package-manager/easyp-vs-buf#2","headings":["Сценарий 2: Компания со смешанными публичными/приватными зависимостями"],"excerpt":"Сценарий 2: Компания со смешанными публичными/приватными зависимостями **Итог:** **EasyP** — не требует публикации внутрь BSR.","content":"Сценарий 2: Компания со смешанными публичными/приватными зависимостями **Итог:** **EasyP** — не требует публикации внутрь BSR."},{"id":"cli/package-manager/easyp-vs-buf::3-airgap::31","title":"EasyP против Buf: управление пакетами","section":"Сценарий 3: Государственный / оборонный подрядчик (полный air‑gap)","path":"/docs/guide/cli/package-manager/easyp-vs-buf#3-airgap","headings":["Сценарий 3: Государственный / оборонный подрядчик (полный air‑gap)"],"excerpt":"Сценарий 3: Государственный / оборонный подрядчик (полный air‑gap) **EasyP:**","content":"Сценарий 3: Государственный / оборонный подрядчик (полный air‑gap) **EasyP:**"},{"id":"cli/package-manager/easyp-vs-buf::3-airgap::32","title":"EasyP против Buf: управление пакетами","section":"Сценарий 3: Государственный / оборонный подрядчик (полный air‑gap)","path":"/docs/guide/cli/package-manager/easyp-vs-buf#3-airgap","headings":["Сценарий 3: Государственный / оборонный подрядчик (полный air‑gap)"],"excerpt":"Сценарий 3: Государственный / оборонный подрядчик (полный air‑gap) **Buf:**","content":"Сценарий 3: Государственный / оборонный подрядчик (полный air‑gap) **Buf:**"},{"id":"cli/package-manager/easyp-vs-buf::3-airgap::33","title":"EasyP против Buf: управление пакетами","section":"Сценарий 3: Государственный / оборонный подрядчик (полный air‑gap)","path":"/docs/guide/cli/package-manager/easyp-vs-buf#3-airgap","headings":["Сценарий 3: Государственный / оборонный подрядчик (полный air‑gap)"],"excerpt":"Сценарий 3: Государственный / оборонный подрядчик (полный air‑gap) **Итог:** **EasyP** — значительно проще.","content":"Сценарий 3: Государственный / оборонный подрядчик (полный air‑gap) **Итог:** **EasyP** — значительно проще."},{"id":"cli/package-manager/easyp-vs-buf::4::34","title":"EasyP против Buf: управление пакетами","section":"Сценарий 4: Комплаенс и аудит","path":"/docs/guide/cli/package-manager/easyp-vs-buf#4","headings":["Сценарий 4: Комплаенс и аудит"],"excerpt":"Сценарий 4: Комплаенс и аудит **EasyP:** ✅ Прямой аудит изменений (коммиты) ✅ Нет внешних точек зависимости в проде ✅ Повторяемость через фиксированные коммиты / vendor ✅ Управление уязвимостями — в ваших руках","content":"Сценарий 4: Комплаенс и аудит **EasyP:** ✅ Прямой аудит изменений (коммиты) ✅ Нет внешних точек зависимости в проде ✅ Повторяемость через фиксированные коммиты / vendor ✅ Управление уязвимостями — в ваших руках"},{"id":"cli/package-manager/easyp-vs-buf::4::35","title":"EasyP против Buf: управление пакетами","section":"Сценарий 4: Комплаенс и аудит","path":"/docs/guide/cli/package-manager/easyp-vs-buf#4","headings":["Сценарий 4: Комплаенс и аудит"],"excerpt":"Сценарий 4: Комплаенс и аудит **Buf:** ⚠️ Нужно учитывать BSR в области аудита ⚠️ Дополнительный риск третьей стороны ⚠️ Модули — внешние контролируемые артефакты ⚠️ Сложнее трассировать от реестра к исходникам","content":"Сценарий 4: Комплаенс и аудит **Buf:** ⚠️ Нужно учитывать BSR в области аудита ⚠️ Дополнительный риск третьей стороны ⚠️ Модули — внешние контролируемые артефакты ⚠️ Сложнее трассировать от реестра к исходникам"},{"id":"cli/package-manager/easyp-vs-buf::4::36","title":"EasyP против Buf: управление пакетами","section":"Сценарий 4: Комплаенс и аудит","path":"/docs/guide/cli/package-manager/easyp-vs-buf#4","headings":["Сценарий 4: Комплаенс и аудит"],"excerpt":"Сценарий 4: Комплаенс и аудит **Итог:** **EasyP** — проще для комплаенса.","content":"Сценарий 4: Комплаенс и аудит **Итог:** **EasyP** — проще для комплаенса."},{"id":"cli/package-manager/easyp-vs-buf::easyp::37","title":"EasyP против Buf: управление пакетами","section":"EasyP: Нулевая дополнительная инфраструктура","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["EasyP: Нулевая дополнительная инфраструктура"],"excerpt":"EasyP: Нулевая дополнительная инфраструктура **Затраты:** ✅ $0 — используете существующий Git ✅ Нет дополнительных сервисов/серверов ✅ Нет лицензирования ✅ Масштабирование в рамках Git","content":"EasyP: Нулевая дополнительная инфраструктура **Затраты:** ✅ $0 — используете существующий Git ✅ Нет дополнительных сервисов/серверов ✅ Нет лицензирования ✅ Масштабирование в рамках Git"},{"id":"cli/package-manager/easyp-vs-buf::easyp::38","title":"EasyP против Buf: управление пакетами","section":"EasyP: Нулевая дополнительная инфраструктура","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["EasyP: Нулевая дополнительная инфраструктура"],"excerpt":"EasyP: Нулевая дополнительная инфраструктура **Инфраструктура:** Использует текущие репозитории (GitHub/GitLab/и т.д.) Аутентификация — штатная Резервирование/DR — как уже настроено для Git","content":"EasyP: Нулевая дополнительная инфраструктура **Инфраструктура:** Использует текущие репозитории (GitHub/GitLab/и т.д.) Аутентификация — штатная Резервирование/DR — как уже настроено для Git"},{"id":"cli/package-manager/easyp-vs-buf::buf::39","title":"EasyP против Buf: управление пакетами","section":"Buf: Затраты на реестр","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf","headings":["Buf: Затраты на реестр"],"excerpt":"Buf: Затраты на реестр **Hosted BSR (buf.build):** ✅ Бесплатный уровень ❌ Платные тарифы для приватного и расширенного использования ❌ Потенциальные изменения ценовой политики ❌ Вопросы локализации данных","content":"Buf: Затраты на реестр **Hosted BSR (buf.build):** ✅ Бесплатный уровень ❌ Платные тарифы для приватного и расширенного использования ❌ Потенциальные изменения ценовой политики ❌ Вопросы локализации данных"},{"id":"cli/package-manager/easyp-vs-buf::buf::40","title":"EasyP против Buf: управление пакетами","section":"Buf: Затраты на реестр","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf","headings":["Buf: Затраты на реестр"],"excerpt":"Buf: Затраты на реестр **Приватный BSR:** ❌ Серверы, БД, балансировка ❌ Мониторинг, обновления, бэкапы ❌ Лицензирование enterprise функционала ❌ Доп. планирование отказоустойчивости","content":"Buf: Затраты на реестр **Приватный BSR:** ❌ Серверы, БД, балансировка ❌ Мониторинг, обновления, бэкапы ❌ Лицензирование enterprise функционала ❌ Доп. планирование отказоустойчивости"},{"id":"cli/package-manager/easyp-vs-buf::easyp::41","title":"EasyP против Buf: управление пакетами","section":"EasyP: Нет привязки","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["EasyP: Нет привязки"],"excerpt":"EasyP: Нет привязки **Миграция ИЗ EasyP:** (Обычные Git ссылки — легко перенести в другой инструмент.)","content":"EasyP: Нет привязки **Миграция ИЗ EasyP:** (Обычные Git ссылки — легко перенести в другой инструмент.)"},{"id":"cli/package-manager/easyp-vs-buf::easyp::42","title":"EasyP против Buf: управление пакетами","section":"EasyP: Нет привязки","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["EasyP: Нет привязки"],"excerpt":"EasyP: Нет привязки **Миграция В EasyP:**","content":"EasyP: Нет привязки **Миграция В EasyP:**"},{"id":"cli/package-manager/easyp-vs-buf::buf-lockin::43","title":"EasyP против Buf: управление пакетами","section":"Buf: Потенциальный lock‑in","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf-lockin","headings":["Buf: Потенциальный lock‑in"],"excerpt":"Buf: Потенциальный lock‑in **Миграция ИЗ Buf:** ❌ Нужно сопоставить BSR модули с исходными Git репо ❌ Имена модулей BSR не совпадают с URL ❌ Возможна потеря удобных метаданных ❌ Сложно при глубокой интеграции с BSR","content":"Buf: Потенциальный lock‑in **Миграция ИЗ Buf:** ❌ Нужно сопоставить BSR модули с исходными Git репо ❌ Имена модулей BSR не совпадают с URL ❌ Возможна потеря удобных метаданных ❌ Сложно при глубокой интеграции с BSR"},{"id":"cli/package-manager/easyp-vs-buf::buf-lockin::44","title":"EasyP против Buf: управление пакетами","section":"Buf: Потенциальный lock‑in","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf-lockin","headings":["Buf: Потенциальный lock‑in"],"excerpt":"Buf: Потенциальный lock‑in **Миграция В Buf:** ❌ Нужно опубликовать всё в BSR ❌ Нельзя ссылаться напрямую на Git ❌ Принять workflow BSR (push/pull модулей)","content":"Buf: Потенциальный lock‑in **Миграция В Buf:** ❌ Нужно опубликовать всё в BSR ❌ Нельзя ссылаться напрямую на Git ❌ Принять workflow BSR (push/pull модулей)"},{"id":"cli/package-manager/easyp-vs-buf::easyp::45","title":"EasyP против Buf: управление пакетами","section":"Выберите EasyP, если:","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["Выберите EasyP, если:"],"excerpt":"Выберите EasyP, если: ✅ **Air‑gapped / закрытые среды** Нужна работа без внешних сервисов Строгий комплаенс / контроль цепочки поставок","content":"Выберите EasyP, если: ✅ **Air‑gapped / закрытые среды** Нужна работа без внешних сервисов Строгий комплаенс / контроль цепочки поставок"},{"id":"cli/package-manager/easyp-vs-buf::easyp::46","title":"EasyP против Buf: управление пакетами","section":"Выберите EasyP, если:","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["Выберите EasyP, если:"],"excerpt":"Выберите EasyP, если: ✅ **Фокус на безопасности** Контроль источников зависимостей Минимизация рисков третьих сторон","content":"Выберите EasyP, если: ✅ **Фокус на безопасности** Контроль источников зависимостей Минимизация рисков третьих сторон"},{"id":"cli/package-manager/easyp-vs-buf::easyp::47","title":"EasyP против Buf: управление пакетами","section":"Выберите EasyP, если:","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["Выберите EasyP, если:"],"excerpt":"Выберите EasyP, если: ✅ **Git‑центричная культура** Частные репозитории — норма Не хотите добавлять новый ключевой сервис","content":"Выберите EasyP, если: ✅ **Git‑центричная культура** Частные репозитории — норма Не хотите добавлять новый ключевой сервис"},{"id":"cli/package-manager/easyp-vs-buf::easyp::48","title":"EasyP против Buf: управление пакетами","section":"Выберите EasyP, если:","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["Выберите EasyP, если:"],"excerpt":"Выберите EasyP, если: ✅ **Ограниченный бюджет** Минимизация операционных расходов Предсказуемая стоимость = 0","content":"Выберите EasyP, если: ✅ **Ограниченный бюджет** Минимизация операционных расходов Предсказуемая стоимость = 0"},{"id":"cli/package-manager/easyp-vs-buf::easyp::49","title":"EasyP против Buf: управление пакетами","section":"Выберите EasyP, если:","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["Выберите EasyP, если:"],"excerpt":"Выберите EasyP, если: ✅ **Смешанные публичные/частные зависимости** Не хотите перекладывать всё в реестр Нужна гибкость форматов и размещения","content":"Выберите EasyP, если: ✅ **Смешанные публичные/частные зависимости** Не хотите перекладывать всё в реестр Нужна гибкость форматов и размещения"},{"id":"cli/package-manager/easyp-vs-buf::buf::50","title":"EasyP против Buf: управление пакетами","section":"Выберите Buf, если:","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf","headings":["Выберите Buf, если:"],"excerpt":"Выберите Buf, если: ✅ **Глубокая интеграция в экосистему BSR** Уже используете линтеры / генерацию Buf Нужны курируемые официальные модули Важны метаданные и граф зависимостей","content":"Выберите Buf, если: ✅ **Глубокая интеграция в экосистему BSR** Уже используете линтеры / генерацию Buf Нужны курируемые официальные модули Важны метаданные и граф зависимостей"},{"id":"cli/package-manager/easyp-vs-buf::buf::51","title":"EasyP против Buf: управление пакетами","section":"Выберите Buf, если:","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf","headings":["Выберите Buf, если:"],"excerpt":"Выберите Buf, если: ✅ **Сотрудничество и открытая разработка** Централизованное обнаружение модулей Совместная работа над общими пакетами","content":"Выберите Buf, если: ✅ **Сотрудничество и открытая разработка** Централизованное обнаружение модулей Совместная работа над общими пакетами"},{"id":"cli/package-manager/easyp-vs-buf::buf::52","title":"EasyP против Buf: управление пакетами","section":"Выберите Buf, если:","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf","headings":["Выберите Buf, если:"],"excerpt":"Выберите Buf, если: ✅ **Команда новичков в protobuf** Требуется «направляющая» структура Ценность документации внутри реестра","content":"Выберите Buf, если: ✅ **Команда новичков в protobuf** Требуется «направляющая» структура Ценность документации внутри реестра"},{"id":"cli/package-manager/easyp-vs-buf::buf::53","title":"EasyP против Buf: управление пакетами","section":"Выберите Buf, если:","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf","headings":["Выберите Buf, если:"],"excerpt":"Выберите Buf, если: ✅ **Небольшой набор публичных зависимостей** В основном используете популярные общие пакеты Вас устраивает зависимость от BSR","content":"Выберите Buf, если: ✅ **Небольшой набор публичных зависимостей** В основном используете популярные общие пакеты Вас устраивает зависимость от BSR"},{"id":"cli/package-manager/easyp-vs-buf::buf-easyp::54","title":"EasyP против Buf: управление пакетами","section":"Переход с Buf на EasyP","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf-easyp","headings":["Переход с Buf на EasyP"],"excerpt":"Переход с Buf на EasyP Найдите исходные Git репозитории для каждого модуля BSR Сопоставьте имена BSR → Git ссылки (с версиями/тегами) Обновите конфигурацию (easyp.yaml) Протестируйте генерацию и совместимость","content":"Переход с Buf на EasyP Найдите исходные Git репозитории для каждого модуля BSR Сопоставьте имена BSR → Git ссылки (с версиями/тегами) Обновите конфигурацию (easyp.yaml) Протестируйте генерацию и совместимость"},{"id":"cli/package-manager/easyp-vs-buf::buf-easyp::55","title":"EasyP против Buf: управление пакетами","section":"Переход с Buf на EasyP","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf-easyp","headings":["Переход с Buf на EasyP"],"excerpt":"Переход с Buf на EasyP ```yaml Было (buf.yaml) deps: - buf.build/googleapis/googleapis - buf.build/grpc/grpc","content":"Переход с Buf на EasyP ```yaml Было (buf.yaml) deps: - buf.build/googleapis/googleapis - buf.build/grpc/grpc"},{"id":"cli/package-manager/easyp-vs-buf::buf-easyp::56","title":"EasyP против Buf: управление пакетами","section":"Переход с Buf на EasyP","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf-easyp","headings":["Переход с Buf на EasyP"],"excerpt":"Переход с Buf на EasyP Стало (easyp.yaml) deps: - github.com/googleapis/googleapis@common-protos-1_3_1 - github.com/grpc/grpc@v1.50.0 ```","content":"Переход с Buf на EasyP Стало (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::easyp-buf::57","title":"EasyP против Buf: управление пакетами","section":"Переход с EasyP на Buf","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp-buf","headings":["Переход с EasyP на Buf"],"excerpt":"Переход с EasyP на Buf Опубликуйте используемые репозитории как модули BSR Настройте аутентификацию / организацию Buf Замените Git ссылки на BSR модули Перейдите к push/pull workflow Buf","content":"Переход с EasyP на Buf Опубликуйте используемые репозитории как модули BSR Настройте аутентификацию / организацию Buf Замените Git ссылки на BSR модули Перейдите к push/pull workflow Buf"},{"id":"cli/package-manager/easyp-vs-buf::top::58","title":"EasyP против Buf: управление пакетами","section":"Заключение","path":"/docs/guide/cli/package-manager/easyp-vs-buf","headings":["Заключение"],"excerpt":"Заключение Оба инструмента решают задачу управления зависимостями protobuf, но подходят под разные приоритеты:","content":"Заключение Оба инструмента решают задачу управления зависимостями protobuf, но подходят под разные приоритеты:"},{"id":"cli/package-manager/easyp-vs-buf::top::59","title":"EasyP против Buf: управление пакетами","section":"Заключение","path":"/docs/guide/cli/package-manager/easyp-vs-buf","headings":["Заключение"],"excerpt":"Заключение **Сильные стороны EasyP:** Корпоративные / изолированные среды Жёсткие требования безопасности и аудита Минимальные затраты и отсутствие доп. инфраструктуры Прямое использование Git (без промежуточного слоя) П","content":"Заключение **Сильные стороны EasyP:** Корпоративные / изолированные среды Жёсткие требования безопасности и аудита Минимальные затраты и отсутствие доп. инфраструктуры Прямое использование Git (без промежуточного слоя) Простота масштабирования"},{"id":"cli/package-manager/easyp-vs-buf::top::60","title":"EasyP против Buf: управление пакетами","section":"Заключение","path":"/docs/guide/cli/package-manager/easyp-vs-buf","headings":["Заключение"],"excerpt":"Заключение **Сильные стороны Buf:** Богатая экосистема вокруг реестра Курируемые и документированные модули Удобство для новых команд в protobuf Средства визуализации и централизованного обмена","content":"Заключение **Сильные стороны Buf:** Богатая экосистема вокруг реестра Курируемые и документированные модули Удобство для новых команд в protobuf Средства визуализации и централизованного обмена"},{"id":"cli/package-manager/easyp-vs-buf::top::61","title":"EasyP против Buf: управление пакетами","section":"Заключение","path":"/docs/guide/cli/package-manager/easyp-vs-buf","headings":["Заключение"],"excerpt":"Заключение Выбор часто сводится к балансу между **контролем vs. удобством**, **безопасностью vs. централизованными функциями**, и **стоимостью vs. managed‑сервисом**.","content":"Заключение Выбор часто сводится к балансу между **контролем vs. удобством**, **безопасностью vs. централизованными функциями**, и **стоимостью vs. managed‑сервисом**."},{"id":"cli/package-manager/easyp-vs-buf::top::62","title":"EasyP против Buf: управление пакетами","section":"Заключение","path":"/docs/guide/cli/package-manager/easyp-vs-buf","headings":["Заключение"],"excerpt":"Заключение Для большинства enterprise‑окружений децентрализованный Git‑подход EasyP обеспечивает нужные гибкость, безопасность и предсказуемость расходов, тогда как Buf отлично подходит командам, которым важна централизо","content":"Заключение Для большинства enterprise‑окружений децентрализованный Git‑подход EasyP обеспечивает нужные гибкость, безопасность и предсказуемость расходов, тогда как Buf отлично подходит командам, которым важна централизованная коллаборация и богатая экосистема вокруг реестра."},{"id":"cli/package-manager/package-manager::top::0","title":"Менеджер пакетов","path":"/docs/guide/cli/package-manager/package-manager","headings":[],"excerpt":"EasyP предоставляет мощный менеджер пакетов для protobuf‑зависимостей, упрощающий их управление за счёт децентрализованного подхода на базе Git. В отличие от централизованных решений, EasyP работает напрямую с Git‑репози","content":"EasyP предоставляет мощный менеджер пакетов для protobuf‑зависимостей, упрощающий их управление за счёт децентрализованного подхода на базе Git. В отличие от централизованных решений, EasyP работает напрямую с Git‑репозиториями, давая вам полный контроль."},{"id":"cli/package-manager/package-manager::top::1","title":"Менеджер пакетов","section":"Обзор","path":"/docs/guide/cli/package-manager/package-manager","headings":["Обзор"],"excerpt":"Обзор Менеджер пакетов EasyP следует философии **Go modules** — любой Git‑репозиторий может быть источником. Это даёт преимущества:","content":"Обзор Менеджер пакетов EasyP следует философии **Go modules** — любой Git‑репозиторий может быть источником. Это даёт преимущества:"},{"id":"cli/package-manager/package-manager::top::2","title":"Менеджер пакетов","section":"Обзор","path":"/docs/guide/cli/package-manager/package-manager","headings":["Обзор"],"excerpt":"Обзор **Децентрализация** — нет единой точки отказа или контроля **Безопасность** — прямой доступ к исходникам **Гибкость** — публичные, приватные и корпоративные репозитории **Воспроизводимость** — lock‑файлы обеспечива","content":"Обзор **Децентрализация** — нет единой точки отказа или контроля **Безопасность** — прямой доступ к исходникам **Гибкость** — публичные, приватные и корпоративные репозитории **Воспроизводимость** — lock‑файлы обеспечивают одинаковые сборки **Производительность** — локальный кеш сокращает сетевые запросы"},{"id":"cli/package-manager/package-manager::top::3","title":"Менеджер пакетов","section":"Основные возможности","path":"/docs/guide/cli/package-manager/package-manager","headings":["Основные возможности"],"excerpt":"Основные возможности Возможность Описание ------------- ---------- **Git-Native** Любой Git репозиторий, не нужен спец‑сервер **Множество форматов версий** Теги, коммиты, псевдо‑версии, latest **Lock Files** Воспроизводи","content":"Основные возможности Возможность Описание ------------- ---------- **Git-Native** Любой Git репозиторий, не нужен спец‑сервер **Множество форматов версий** Теги, коммиты, псевдо‑версии, latest **Lock Files** Воспроизводимые сборки через easyp.lock **Локальный кеш** Архитектура как у Go modules **Vendoring** Локальное копирование для оффлайн сборок **YAML конфигурация** Простые и читаемые декларации"},{"id":"cli/package-manager/package-manager::top::4","title":"Менеджер пакетов","section":"Архитектура","path":"/docs/guide/cli/package-manager/package-manager","headings":["Архитектура"],"excerpt":"Архитектура EasyP использует двухуровневый кеш, вдохновлённый Go modules:","content":"Архитектура EasyP использует двухуровневый кеш, вдохновлённый Go modules:"},{"id":"cli/package-manager/package-manager::top::5","title":"Менеджер пакетов","section":"Расположение кеша","path":"/docs/guide/cli/package-manager/package-manager","headings":["Расположение кеша"],"excerpt":"Расположение кеша Окружение Путь Как задать ----------- ------ ----------- **По умолчанию** $HOME/.easyp Автоматически **Свое** Любая директория Переменная EASYPPATH **CI/CD** В каталоге проекта export EASYPPATH=$CI_PROJ","content":"Расположение кеша Окружение Путь Как задать ----------- ------ ----------- **По умолчанию** $HOME/.easyp Автоматически **Свое** Любая директория Переменная EASYPPATH **CI/CD** В каталоге проекта export EASYPPATH=$CI_PROJECT_DIR/.easyp"},{"id":"cli/package-manager/package-manager::top::6","title":"Менеджер пакетов","section":"Базовая конфигурация","path":"/docs/guide/cli/package-manager/package-manager","headings":["Базовая конфигурация"],"excerpt":"Базовая конфигурация Зависимости описываются в easyp.yaml:","content":"Базовая конфигурация Зависимости описываются в easyp.yaml:"},{"id":"cli/package-manager/package-manager::multi-environment-setup::7","title":"Менеджер пакетов","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 # Последнее для разработки - github.com/mycompany/internal-protos # Внутренние изменения - github.com/bufbuild/protoc-gen-va","content":"Multi-Environment Setup ```yaml development.easyp.yaml deps: - github.com/googleapis/googleapis # Последнее для разработки - github.com/mycompany/internal-protos # Внутренние изменения - github.com/bufbuild/protoc-gen-validate # Новые фичи"},{"id":"cli/package-manager/package-manager::multi-environment-setup::8","title":"Менеджер пакетов","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 # Зафиксировано - github.com/mycompany/internal-protos@v2.1.0 # Стабильно - github.com/bufbuild/protoc-gen-valida","content":"Multi-Environment Setup production.easyp.yaml deps: - github.com/googleapis/googleapis@common-protos-1_3_1 # Зафиксировано - github.com/mycompany/internal-protos@v2.1.0 # Стабильно - github.com/bufbuild/protoc-gen-validate@v0.10.1 # Проверено ```"},{"id":"cli/package-manager/package-manager::top::9","title":"Менеджер пакетов","section":"Приватные репозитории","path":"/docs/guide/cli/package-manager/package-manager","headings":["Приватные репозитории"],"excerpt":"Приватные репозитории ```yaml deps: # Публичное - github.com/googleapis/googleapis@common-protos-1_3_1","content":"Приватные репозитории ```yaml deps: # Публичное - github.com/googleapis/googleapis@common-protos-1_3_1"},{"id":"cli/package-manager/package-manager::top::10","title":"Менеджер пакетов","section":"Приватные репозитории","path":"/docs/guide/cli/package-manager/package-manager","headings":["Приватные репозитории"],"excerpt":"Приватные репозитории Частные - github.com/mycompany/auth-protos@v1.5.0 - github.com/mycompany/common-types@v2.0.1","content":"Приватные репозитории Частные - github.com/mycompany/auth-protos@v1.5.0 - github.com/mycompany/common-types@v2.0.1"},{"id":"cli/package-manager/package-manager::top::11","title":"Менеджер пакетов","section":"Приватные репозитории","path":"/docs/guide/cli/package-manager/package-manager","headings":["Приватные репозитории"],"excerpt":"Приватные репозитории Внутренний GitLab - gitlab.company.com/platform/messaging-protos@v0.3.0 ```","content":"Приватные репозитории Внутренний GitLab - gitlab.company.com/platform/messaging-protos@v0.3.0 ```"},{"id":"cli/package-manager/package-manager::top::12","title":"Менеджер пакетов","section":"Стратегии версионирования","path":"/docs/guide/cli/package-manager/package-manager","headings":["Стратегии версионирования"],"excerpt":"Стратегии версионирования Поддерживаются разные способы фиксации версий:","content":"Стратегии версионирования Поддерживаются разные способы фиксации версий:"},{"id":"cli/package-manager/package-manager::1::13","title":"Менеджер пакетов","section":"1. Семантические теги (для продакшена)","path":"/docs/guide/cli/package-manager/package-manager#1","headings":["1. Семантические теги (для продакшена)"],"excerpt":"Семантические теги (для продакшена)","content":"Семантические теги (для продакшена)"},{"id":"cli/package-manager/package-manager::1::14","title":"Менеджер пакетов","section":"1. Семантические теги (для продакшена)","path":"/docs/guide/cli/package-manager/package-manager#1","headings":["1. Семантические теги (для продакшена)"],"excerpt":"Семантические теги (для продакшена) **Используйте когда:** Продакшен Стабильное потребление API Нужна воспроизводимость","content":"Семантические теги (для продакшена) **Используйте когда:** Продакшен Стабильное потребление API Нужна воспроизводимость"},{"id":"cli/package-manager/package-manager::2-development::15","title":"Менеджер пакетов","section":"2. Последний тег (development)","path":"/docs/guide/cli/package-manager/package-manager#2-development","headings":["2. Последний тег (development)"],"excerpt":"Последний тег (development) **Подходит для:** Активной разработки Получения свежих возможностей Тестирования совместимости","content":"Последний тег (development) **Подходит для:** Активной разработки Получения свежих возможностей Тестирования совместимости"},{"id":"cli/package-manager/package-manager::3-bleeding-edge::16","title":"Менеджер пакетов","section":"3. Хеш коммита (Bleeding Edge)","path":"/docs/guide/cli/package-manager/package-manager#3-bleeding-edge","headings":["3. Хеш коммита (Bleeding Edge)"],"excerpt":"Хеш коммита (Bleeding Edge) **Когда нужно:** Нерелизные фичи Тест конкретного фикса Вклад в upstream","content":"Хеш коммита (Bleeding Edge) **Когда нужно:** Нерелизные фичи Тест конкретного фикса Вклад в upstream"},{"id":"cli/package-manager/package-manager::4::17","title":"Менеджер пакетов","section":"4. Псевдо‑версии (автоматически)","path":"/docs/guide/cli/package-manager/package-manager#4","headings":["4. Псевдо‑версии (автоматически)"],"excerpt":"Псевдо‑версии (автоматически) Если нет подходящего тега — создаётся псевдо‑версия:","content":"Псевдо‑версии (автоматически) Если нет подходящего тега — создаётся псевдо‑версия:"},{"id":"cli/package-manager/package-manager::easyp-mod-download::18","title":"Менеджер пакетов","section":"easyp mod download","path":"/docs/guide/cli/package-manager/package-manager#easyp-mod-download","headings":["easyp mod download"],"excerpt":"easyp mod download Скачивает и устанавливает все объявленные зависимости.","content":"easyp mod download Скачивает и устанавливает все объявленные зависимости."},{"id":"cli/package-manager/package-manager::easyp-mod-download::19","title":"Менеджер пакетов","section":"easyp mod download","path":"/docs/guide/cli/package-manager/package-manager#easyp-mod-download","headings":["easyp mod download"],"excerpt":"easyp mod download **Что делает:** Разрешает версии (теги → коммиты) Скачивает архивы в cache/download Проверяет контрольные суммы Распаковывает в cache/mod Обновляет easyp.lock","content":"easyp mod download **Что делает:** Разрешает версии (теги → коммиты) Скачивает архивы в cache/download Проверяет контрольные суммы Распаковывает в cache/mod Обновляет easyp.lock"},{"id":"cli/package-manager/package-manager::easyp-mod-download::20","title":"Менеджер пакетов","section":"easyp mod download","path":"/docs/guide/cli/package-manager/package-manager#easyp-mod-download","headings":["easyp mod download"],"excerpt":"easyp mod download **Пример:**","content":"easyp mod download **Пример:**"},{"id":"cli/package-manager/package-manager::easyp-mod-vendor::21","title":"Менеджер пакетов","section":"easyp mod vendor","path":"/docs/guide/cli/package-manager/package-manager#easyp-mod-vendor","headings":["easyp mod vendor"],"excerpt":"easyp mod vendor Копирует все proto зависимости в локальный easyp_vendor/ для оффлайна.","content":"easyp mod vendor Копирует все proto зависимости в локальный easyp_vendor/ для оффлайна."},{"id":"cli/package-manager/package-manager::easyp-mod-vendor::22","title":"Менеджер пакетов","section":"easyp mod vendor","path":"/docs/guide/cli/package-manager/package-manager#easyp-mod-vendor","headings":["easyp mod vendor"],"excerpt":"easyp mod vendor **Сценарии:** Docker сборки Air-gapped окружения Воспроизводимость Ускорение","content":"easyp mod vendor **Сценарии:** Docker сборки Air-gapped окружения Воспроизводимость Ускорение"},{"id":"cli/package-manager/package-manager::easyp-mod-update::23","title":"Менеджер пакетов","section":"easyp mod update","path":"/docs/guide/cli/package-manager/package-manager#easyp-mod-update","headings":["easyp mod update"],"excerpt":"easyp mod update Обновляет версии согласно easyp.yaml, пересоздаёт lock.","content":"easyp mod update Обновляет версии согласно easyp.yaml, пересоздаёт lock."},{"id":"cli/package-manager/package-manager::lock::24","title":"Менеджер пакетов","section":"Lock файл","path":"/docs/guide/cli/package-manager/package-manager#lock","headings":["Lock файл"],"excerpt":"Lock файл easyp.lock фиксирует точные версии и хеш содержимого:","content":"Lock файл easyp.lock фиксирует точные версии и хеш содержимого:"},{"id":"cli/package-manager/package-manager::lock::25","title":"Менеджер пакетов","section":"Lock файл","path":"/docs/guide/cli/package-manager/package-manager#lock","headings":["Lock файл"],"excerpt":"Lock файл **Формат строки:** Путь модуля Версия (тег или псевдо) Хеш содержимого (h1:)","content":"Lock файл **Формат строки:** Путь модуля Версия (тег или псевдо) Хеш содержимого (h1:)"},{"id":"cli/package-manager/package-manager::lock::26","title":"Менеджер пакетов","section":"Lock файл","path":"/docs/guide/cli/package-manager/package-manager#lock","headings":["Lock файл"],"excerpt":"Lock файл **Практики:** ✅ Коммитить easyp.lock ✅ Осознанно обновлять mod update ✅ Ревью изменений версий ❌ Не редактировать вручную","content":"Lock файл **Практики:** ✅ Коммитить easyp.lock ✅ Осознанно обновлять mod update ✅ Ревью изменений версий ❌ Не редактировать вручную"},{"id":"cli/package-manager/package-manager::top::27","title":"Менеджер пакетов","section":"Публичные репозитории","path":"/docs/guide/cli/package-manager/package-manager","headings":["Публичные репозитории"],"excerpt":"Публичные репозитории Работают без настроек:","content":"Публичные репозитории Работают без настроек:"},{"id":"cli/package-manager/package-manager::ssh::28","title":"Менеджер пакетов","section":"SSH ключи (рекомендуется)","path":"/docs/guide/cli/package-manager/package-manager#ssh","headings":["SSH ключи (рекомендуется)"],"excerpt":"SSH ключи (рекомендуется) Конфиг остаётся с HTTPS URL:","content":"SSH ключи (рекомендуется) Конфиг остаётся с HTTPS URL:"},{"id":"cli/package-manager/package-manager::personal-access-tokens::29","title":"Менеджер пакетов","section":"Personal Access Tokens","path":"/docs/guide/cli/package-manager/package-manager#personal-access-tokens","headings":["Personal Access Tokens"],"excerpt":"Personal Access Tokens ```bash git config --global credential.helper store echo \"https://username:token@github.com\" >> ~/.git-credentials","content":"Personal Access Tokens ```bash git config --global credential.helper store echo \"https://username:token@github.com\" >> ~/.git-credentials"},{"id":"cli/package-manager/package-manager::personal-access-tokens::30","title":"Менеджер пакетов","section":"Personal Access Tokens","path":"/docs/guide/cli/package-manager/package-manager#personal-access-tokens","headings":["Personal Access Tokens"],"excerpt":"Personal Access Tokens git config --global url.\"https://username:token@github.com/mycompany\".insteadOf \"https://github.com/mycompany\" ```","content":"Personal Access Tokens git config --global url.\"https://username:token@github.com/mycompany\".insteadOf \"https://github.com/mycompany\" ```"},{"id":"cli/package-manager/package-manager::top::31","title":"Менеджер пакетов","section":"Инициализация проекта","path":"/docs/guide/cli/package-manager/package-manager","headings":["Инициализация проекта"],"excerpt":"Инициализация проекта ```bash cat > easyp.yaml << EOF deps: - github.com/googleapis/googleapis - github.com/grpc-ecosystem/grpc-gateway@v2.19.1 EOF","content":"Инициализация проекта ```bash 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::top::32","title":"Менеджер пакетов","section":"Инициализация проекта","path":"/docs/guide/cli/package-manager/package-manager","headings":["Инициализация проекта"],"excerpt":"Инициализация проекта easyp mod download ls ~/.easyp/mod/github.com/googleapis/googleapis/ ```","content":"Инициализация проекта easyp mod download ls ~/.easyp/mod/github.com/googleapis/googleapis/ ```"},{"id":"cli/package-manager/package-manager::repository-not-found-authentication-failed::33","title":"Менеджер пакетов","section":"\"Repository not found\" / \"Authentication failed\"","path":"/docs/guide/cli/package-manager/package-manager#repository-not-found-authentication-failed","headings":["\"Repository not found\" / \"Authentication failed\""],"excerpt":"\"Repository not found\" / \"Authentication failed\"","content":"\"Repository not found\" / \"Authentication failed\""},{"id":"cli/package-manager/package-manager::cache-corruption-checksum-mismatch::34","title":"Менеджер пакетов","section":"\"Cache corruption\" / \"Checksum mismatch\"","path":"/docs/guide/cli/package-manager/package-manager#cache-corruption-checksum-mismatch","headings":["\"Cache corruption\" / \"Checksum mismatch\""],"excerpt":"\"Cache corruption\" / \"Checksum mismatch\"","content":"\"Cache corruption\" / \"Checksum mismatch\""},{"id":"cli/package-manager/package-manager::docker-multi-stage::35","title":"Менеджер пакетов","section":"Docker multi-stage","path":"/docs/guide/cli/package-manager/package-manager#docker-multi-stage","headings":["Docker multi-stage"],"excerpt":"Docker multi-stage ```dockerfile FROM ghcr.io/easyp-tech/easyp:latest AS deps WORKDIR /workspace COPY easyp.yaml easyp.lock ./ RUN easyp mod vendor","content":"Docker multi-stage ```dockerfile 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::36","title":"Менеджер пакетов","section":"Docker multi-stage","path":"/docs/guide/cli/package-manager/package-manager#docker-multi-stage","headings":["Docker multi-stage"],"excerpt":"Docker multi-stage FROM alpine:latest AS build WORKDIR /app COPY --from=deps /workspace/easyp_vendor ./easyp_vendor COPY . . RUN easyp generate ```","content":"Docker multi-stage FROM alpine:latest AS build WORKDIR /app COPY --from=deps /workspace/easyp_vendor ./easyp_vendor COPY . . RUN easyp generate ```"},{"id":"cli/package-manager/package-manager::monorepo::37","title":"Менеджер пакетов","section":"Monorepo","path":"/docs/guide/cli/package-manager/package-manager#monorepo","headings":["Monorepo"],"excerpt":"Monorepo Каждый easyp.yaml может иметь свой набор зависимостей.","content":"Monorepo Каждый easyp.yaml может иметь свой набор зависимостей."},{"id":"cli/package-manager/package-manager::workflow::38","title":"Менеджер пакетов","section":"Workflow разработки","path":"/docs/guide/cli/package-manager/package-manager#workflow","headings":["Workflow разработки"],"excerpt":"Workflow разработки ✅ Latest теги в активной разработке ✅ Фиксация версий в продакшене ✅ Коммит lock файла ✅ Ревью обновлений ✅ Тест после обновления","content":"Workflow разработки ✅ Latest теги в активной разработке ✅ Фиксация версий в продакшене ✅ Коммит lock файла ✅ Ревью обновлений ✅ Тест после обновления"},{"id":"cli/package-manager/package-manager::top::39","title":"Менеджер пакетов","section":"Безопасность","path":"/docs/guide/cli/package-manager/package-manager","headings":["Безопасность"],"excerpt":"Безопасность ✅ Фиксируйте версии ✅ Используйте SSH ключи ✅ Оценивайте новые зависимости ✅ Следите за уязвимостями ❌ Не храните секреты в конфиге","content":"Безопасность ✅ Фиксируйте версии ✅ Используйте SSH ключи ✅ Оценивайте новые зависимости ✅ Следите за уязвимостями ❌ Не храните секреты в конфиге"},{"id":"cli/package-manager/package-manager::top::40","title":"Менеджер пакетов","section":"Производительность","path":"/docs/guide/cli/package-manager/package-manager","headings":["Производительность"],"excerpt":"Производительность ✅ Агрессивное кеширование в CI ✅ Vendoring для частых сборок ✅ Чистка старого кеша ✅ Общий кеш для команды","content":"Производительность ✅ Агрессивное кеширование в CI ✅ Vendoring для частых сборок ✅ Чистка старого кеша ✅ Общий кеш для команды"},{"id":"cli/package-manager/package-manager::top::41","title":"Менеджер пакетов","section":"Командная работа","path":"/docs/guide/cli/package-manager/package-manager","headings":["Командная работа"],"excerpt":"Командная работа ✅ Документация по аутентификации ✅ Единые инструменты ✅ Автоматизация обновлений с тестами ✅ Общий кеш при возможности","content":"Командная работа ✅ Документация по аутентификации ✅ Единые инструменты ✅ Автоматизация обновлений с тестами ✅ Общий кеш при возможности"},{"id":"cli/package-manager/package-manager::top::42","title":"Менеджер пакетов","section":"Командная работа","path":"/docs/guide/cli/package-manager/package-manager","headings":["Командная работа"],"excerpt":"Командная работа Менеджер пакетов EasyP — масштабируемое децентрализованное решение от одиночных проектов до enterprise, сохраняя простоту и надёжность.","content":"Командная работа Менеджер пакетов EasyP — масштабируемое децентрализованное решение от одиночных проектов до enterprise, сохраняя простоту и надёжность."},{"id":"introduction/install::top::0","title":"Установка EasyP CLI","section":"Установка через менеджер пакетов системы","path":"/docs/guide/introduction/install","headings":["Установка через менеджер пакетов системы"],"excerpt":"Установка через менеджер пакетов системы","content":"Установка через менеджер пакетов системы"},{"id":"introduction/install::top::1","title":"Установка EasyP CLI","section":"Рекомендуемый способ установки","path":"/docs/guide/introduction/install","headings":["Рекомендуемый способ установки"],"excerpt":"Рекомендуемый способ установки","content":"Рекомендуемый способ установки"},{"id":"introduction/install::homebrew::2","title":"Установка EasyP CLI","section":"Homebrew","path":"/docs/guide/introduction/install#homebrew","headings":["Homebrew"],"excerpt":"Homebrew Можно установить бинарный релиз в macOS через Homebrew:","content":"Homebrew Можно установить бинарный релиз в macOS через Homebrew:"},{"id":"introduction/install::homebrew::3","title":"Установка EasyP CLI","section":"Homebrew","path":"/docs/guide/introduction/install#homebrew","headings":["Homebrew"],"excerpt":"Homebrew Work in progress — поддержка других менеджеров (apt, yum, pacman и т.д.) в процессе.","content":"Homebrew Work in progress — поддержка других менеджеров (apt, yum, pacman и т.д.) в процессе."},{"id":"introduction/install::_-_::4","title":"Установка EasyP CLI","section":"_Не рекомендуется_","path":"/docs/guide/introduction/install#_-_","headings":["_Не рекомендуется_"],"excerpt":"_Не рекомендуется_ Локальная установка менее предпочтительна, потому что пакетные менеджеры обеспечивают: Автоматические обновления и патчи безопасности Лучшую интеграцию с системой Упрощённую установку и удаление Подпис","content":"_Не рекомендуется_ Локальная установка менее предпочтительна, потому что пакетные менеджеры обеспечивают: Автоматические обновления и патчи безопасности Лучшую интеграцию с системой Упрощённую установку и удаление Подписанные и проверенные бинарники"},{"id":"introduction/install::go-install::5","title":"Установка EasyP CLI","section":"Установка через go install","path":"/docs/guide/introduction/install#go-install","headings":["Установка через go install"],"excerpt":"Установка через go install Команда установит последнюю стабильную версию easyp:","content":"Установка через go install Команда установит последнюю стабильную версию easyp:"},{"id":"introduction/install::top::6","title":"Установка EasyP CLI","section":"Сборка из исходников","path":"/docs/guide/introduction/install","headings":["Сборка из исходников"],"excerpt":"Сборка из исходников Клонирование репозитория","content":"Сборка из исходников Клонирование репозитория"},{"id":"introduction/install::top::7","title":"Установка EasyP CLI","section":"Сборка из исходников","path":"/docs/guide/introduction/install","headings":["Сборка из исходников"],"excerpt":"Сборка из исходников Сборка с помощью Go","content":"Сборка из исходников Сборка с помощью Go"},{"id":"introduction/quickstart::top::0","title":"Быстрый старт (Quickstart)","path":"/docs/guide/introduction/quickstart","headings":[],"excerpt":"EasyP — современный toolkit для работы с файлами Protobuf. В этом кратком руководстве вы научитесь:","content":"EasyP — современный toolkit для работы с файлами Protobuf. В этом кратком руководстве вы научитесь:"},{"id":"introduction/quickstart::top::1","title":"Быстрый старт (Quickstart)","path":"/docs/guide/introduction/quickstart","headings":[],"excerpt":"**Инициализировать** проект с конфигурацией EasyP **Настраивать линтинг**, чтобы ловить ошибки и соблюдать лучшие практики **Управлять зависимостями** из Git‑репозиториев **Генерировать код** из ваших Protobuf файлов","content":"**Инициализировать** проект с конфигурацией EasyP **Настраивать линтинг**, чтобы ловить ошибки и соблюдать лучшие практики **Управлять зависимостями** из Git‑репозиториев **Генерировать код** из ваших Protobuf файлов"},{"id":"introduction/quickstart::top::2","title":"Быстрый старт (Quickstart)","section":"Предварительные требования","path":"/docs/guide/introduction/quickstart","headings":["Предварительные требования"],"excerpt":"Предварительные требования Перед началом убедитесь, что у вас установлены:","content":"Предварительные требования Перед началом убедитесь, что у вас установлены:"},{"id":"introduction/quickstart::top::3","title":"Быстрый старт (Quickstart)","section":"Предварительные требования","path":"/docs/guide/introduction/quickstart","headings":["Предварительные требования"],"excerpt":"Предварительные требования **EasyP CLI** — см. руководство по установке **Git** доступен в вашем $PATH **Файлы .proto** (или создайте их по ходу)","content":"Предварительные требования **EasyP CLI** — см. руководство по установке **Git** доступен в вашем $PATH **Файлы .proto** (или создайте их по ходу)"},{"id":"introduction/quickstart::top::4","title":"Быстрый старт (Quickstart)","section":"Предварительные требования","path":"/docs/guide/introduction/quickstart","headings":["Предварительные требования"],"excerpt":"Предварительные требования Проверить версию EasyP:","content":"Предварительные требования Проверить версию EasyP:"},{"id":"introduction/quickstart::top::5","title":"Быстрый старт (Quickstart)","section":"Инициализация проекта","path":"/docs/guide/introduction/quickstart","headings":["Инициализация проекта"],"excerpt":"Инициализация проекта Создайте базовый файл конфигурации easyp.yaml в корне проекта:","content":"Инициализация проекта Создайте базовый файл конфигурации easyp.yaml в корне проекта:"},{"id":"introduction/quickstart::top::6","title":"Быстрый старт (Quickstart)","section":"Инициализация проекта","path":"/docs/guide/introduction/quickstart","headings":["Инициализация проекта"],"excerpt":"Инициализация проекта Команда генерирует шаблон easyp.yaml с комментариями, дефолтными lint-правилами и настройками breaking-check. easyp init работает интерактивно: если в корне есть buf.yml/buf.yaml, EasyP предложит ми","content":"Инициализация проекта Команда генерирует шаблон easyp.yaml с комментариями, дефолтными lint-правилами и настройками breaking-check. easyp init работает интерактивно: если в корне есть buf.yml/buf.yaml, EasyP предложит миграцию; если easyp.yaml уже существует, попросит подтверждение перед перезаписью."},{"id":"introduction/quickstart::top::7","title":"Быстрый старт (Quickstart)","section":"Настройка линтинга","path":"/docs/guide/introduction/quickstart","headings":["Настройка линтинга"],"excerpt":"Настройка линтинга Линтинг помогает находить проблемы и поддерживать единый стиль. EasyP использует правила, совместимые с Buf.","content":"Настройка линтинга Линтинг помогает находить проблемы и поддерживать единый стиль. EasyP использует правила, совместимые с Buf."},{"id":"introduction/quickstart::top::8","title":"Быстрый старт (Quickstart)","section":"Настройка линтинга","path":"/docs/guide/introduction/quickstart","headings":["Настройка линтинга"],"excerpt":"Настройка линтинга Секция lint уже создаётся командой easyp init. При необходимости отредактируйте её, например так:","content":"Настройка линтинга Секция lint уже создаётся командой easyp init. При необходимости отредактируйте её, например так:"},{"id":"introduction/quickstart::top::9","title":"Быстрый старт (Quickstart)","section":"Настройка линтинга","path":"/docs/guide/introduction/quickstart","headings":["Настройка линтинга"],"excerpt":"Настройка линтинга Запустите линтер:","content":"Настройка линтинга Запустите линтер:"},{"id":"introduction/quickstart::top::10","title":"Быстрый старт (Quickstart)","section":"Настройка линтинга","path":"/docs/guide/introduction/quickstart","headings":["Настройка линтинга"],"excerpt":"Настройка линтинга Линтер проверит все .proto файлы и сообщит о найденных проблемах.","content":"Настройка линтинга Линтер проверит все .proto файлы и сообщит о найденных проблемах."},{"id":"introduction/quickstart::top::11","title":"Быстрый старт (Quickstart)","section":"Настройка линтинга","path":"/docs/guide/introduction/quickstart","headings":["Настройка линтинга"],"excerpt":"Настройка линтинга ::: tip Правила линтинга EasyP на 100% совместимы с Buf — мигрировать просто. :::","content":"Настройка линтинга ::: tip Правила линтинга EasyP на 100% совместимы с Buf — мигрировать просто. :::"},{"id":"introduction/quickstart::top::12","title":"Быстрый старт (Quickstart)","section":"Управление зависимостями","path":"/docs/guide/introduction/quickstart","headings":["Управление зависимостями"],"excerpt":"Управление зависимостями Если вы используете сторонние protobuf пакеты (например Google APIs или gRPC Gateway), EasyP упрощает их подключение.","content":"Управление зависимостями Если вы используете сторонние protobuf пакеты (например Google APIs или gRPC Gateway), EasyP упрощает их подключение."},{"id":"introduction/quickstart::top::13","title":"Быстрый старт (Quickstart)","section":"Формат зависимости","path":"/docs/guide/introduction/quickstart","headings":["Формат зависимости"],"excerpt":"Формат зависимости Запись: $GIT_LINK@$VERSION","content":"Формат зависимости Запись: $GIT_LINK@$VERSION"},{"id":"introduction/quickstart::top::14","title":"Быстрый старт (Quickstart)","section":"Формат зависимости","path":"/docs/guide/introduction/quickstart","headings":["Формат зависимости"],"excerpt":"Формат зависимости **$GIT_LINK** — URL любого Git‑репозитория (GitHub, GitLab и т.д.) **$VERSION** — тег или хеш коммита (опционально)","content":"Формат зависимости **$GIT_LINK** — URL любого Git‑репозитория (GitHub, GitLab и т.д.) **$VERSION** — тег или хеш коммита (опционально)"},{"id":"introduction/quickstart::top::15","title":"Быстрый старт (Quickstart)","section":"Формат зависимости","path":"/docs/guide/introduction/quickstart","headings":["Формат зависимости"],"excerpt":"Формат зависимости Если версия не указана — берётся последний коммит из основной ветки.","content":"Формат зависимости Если версия не указана — берётся последний коммит из основной ветки."},{"id":"introduction/quickstart::top::16","title":"Быстрый старт (Quickstart)","section":"Добавление зависимостей","path":"/docs/guide/introduction/quickstart","headings":["Добавление зависимостей"],"excerpt":"Добавление зависимостей Дополните easyp.yaml:","content":"Добавление зависимостей Дополните easyp.yaml:"},{"id":"introduction/quickstart::top::17","title":"Быстрый старт (Quickstart)","section":"Загрузка зависимостей","path":"/docs/guide/introduction/quickstart","headings":["Загрузка зависимостей"],"excerpt":"Загрузка зависимостей Команда: Скачивает версии из easyp.lock, если он существует Иначе — берёт из easyp.yaml и создаёт easyp.lock","content":"Загрузка зависимостей Команда: Скачивает версии из easyp.lock, если он существует Иначе — берёт из easyp.yaml и создаёт easyp.lock"},{"id":"introduction/quickstart::top::18","title":"Быстрый старт (Quickstart)","section":"Загрузка зависимостей","path":"/docs/guide/introduction/quickstart","headings":["Загрузка зависимостей"],"excerpt":"Загрузка зависимостей ::: info Совет: easyp mod update — игнорирует lock‑файл и подтягивает актуальные версии из easyp.yaml. :::","content":"Загрузка зависимостей ::: info Совет: easyp mod update — игнорирует lock‑файл и подтягивает актуальные версии из easyp.yaml. :::"},{"id":"introduction/quickstart::top::19","title":"Быстрый старт (Quickstart)","section":"Генерация кода","path":"/docs/guide/introduction/quickstart","headings":["Генерация кода"],"excerpt":"Генерация кода EasyP поддерживает все стандартные protoc‑плагины.","content":"Генерация кода EasyP поддерживает все стандартные protoc‑плагины."},{"id":"introduction/quickstart::top::20","title":"Быстрый старт (Quickstart)","section":"Конфигурация генерации","path":"/docs/guide/introduction/quickstart","headings":["Конфигурация генерации"],"excerpt":"Конфигурация генерации Добавьте плагины:","content":"Конфигурация генерации Добавьте плагины:"},{"id":"introduction/quickstart::top::21","title":"Быстрый старт (Quickstart)","section":"Запуск генерации","path":"/docs/guide/introduction/quickstart","headings":["Запуск генерации"],"excerpt":"Запуск генерации EasyP выполнит: Разрешение всех зависимостей Подключение к сервису EasyP (или локальный режим) Запуск указанных плагинов Вывод сгенерированного кода в нужные директории","content":"Запуск генерации EasyP выполнит: Разрешение всех зависимостей Подключение к сервису EasyP (или локальный режим) Запуск указанных плагинов Вывод сгенерированного кода в нужные директории"},{"id":"introduction/quickstart::top::22","title":"Быстрый старт (Quickstart)","section":"Запуск генерации","path":"/docs/guide/introduction/quickstart","headings":["Запуск генерации"],"excerpt":"Запуск генерации ::: tip Гибридный рантайм: WASM для скорости, Docker — для тяжёлых плагинов. :::","content":"Запуск генерации ::: tip Гибридный рантайм: WASM для скорости, Docker — для тяжёлых плагинов. :::"},{"id":"introduction/quickstart::top::23","title":"Быстрый старт (Quickstart)","section":"Следующие шаги","path":"/docs/guide/introduction/quickstart","headings":["Следующие шаги"],"excerpt":"Следующие шаги Поздравляем! 🎉 Вы успешно: ✅ Инициализировали проект EasyP ✅ Настроили линтинг ✅ Управляете внешними зависимостями ✅ Сгенерировали код из .proto","content":"Следующие шаги Поздравляем! 🎉 Вы успешно: ✅ Инициализировали проект EasyP ✅ Настроили линтинг ✅ Управляете внешними зависимостями ✅ Сгенерировали код из .proto"},{"id":"introduction/quickstart::top::24","title":"Быстрый старт (Quickstart)","section":"Узнать больше","path":"/docs/guide/introduction/quickstart","headings":["Узнать больше"],"excerpt":"Узнать больше **CLI Reference** — подробности по командам **API Service** — удалённая генерация **Configuration** — все опции конфигурации","content":"Узнать больше **CLI Reference** — подробности по командам **API Service** — удалённая генерация **Configuration** — все опции конфигурации"},{"id":"introduction/quickstart::top::25","title":"Быстрый старт (Quickstart)","section":"Узнать больше","path":"/docs/guide/introduction/quickstart","headings":["Узнать больше"],"excerpt":"Узнать больше *Приятной работы с Protobuf — без боли! 🚀*","content":"Узнать больше *Приятной работы с Protobuf — без боли! 🚀*"},{"id":"introduction/what-is::top::0","title":"Что такое EasyP?","path":"/docs/guide/introduction/what-is","headings":[],"excerpt":"EasyP — это современный инструментарий для работы с Protocol Buffers, который объединяет весь ваш protobuf‑workflow в один мощный CLI‑инструмент. Он совмещает линтинг, управление пакетами, генерацию кода и проверку совме","content":"EasyP — это современный инструментарий для работы с Protocol Buffers, который объединяет весь ваш protobuf‑workflow в один мощный CLI‑инструмент. Он совмещает линтинг, управление пакетами, генерацию кода и проверку совместимости в единой среде и устраняет сложность традиционной работы с protobuf."},{"id":"introduction/what-is::top::1","title":"Что такое EasyP?","path":"/docs/guide/introduction/what-is","headings":[],"excerpt":"Хотите просто попробовать? Перейдите сразу к разделу Quickstart.","content":"Хотите просто попробовать? Перейдите сразу к разделу Quickstart."},{"id":"introduction/what-is::protobuf::2","title":"Что такое EasyP?","section":"Проблема: фрагментированные protobuf‑процессы","path":"/docs/guide/introduction/what-is#protobuf","headings":["Проблема: фрагментированные protobuf‑процессы"],"excerpt":"Проблема: фрагментированные protobuf‑процессы Работа с Protocol Buffers в разных проектах часто создает лишнюю сложность и трение:","content":"Проблема: фрагментированные protobuf‑процессы Работа с Protocol Buffers в разных проектах часто создает лишнюю сложность и трение:"},{"id":"introduction/what-is::top::3","title":"Что такое EasyP?","section":"Хаос инструментов","path":"/docs/guide/introduction/what-is","headings":["Хаос инструментов"],"excerpt":"Хаос инструментов **Много отдельных утилит**: Отдельно для линтинга, генерации и управления зависимостями **Несогласованные конфигурации**: Разные форматы и правила в разных командах **Сложный онбординг**: Новым разработ","content":"Хаос инструментов **Много отдельных утилит**: Отдельно для линтинга, генерации и управления зависимостями **Несогласованные конфигурации**: Разные форматы и правила в разных командах **Сложный онбординг**: Новым разработчикам нужно долго вникать"},{"id":"introduction/what-is::top::4","title":"Что такое EasyP?","section":"Проблемы управления зависимостями","path":"/docs/guide/introduction/what-is","headings":["Проблемы управления зависимостями"],"excerpt":"Проблемы управления зависимостями **Нет стандартизированного подхода**: Каждый проект решает это по‑своему **Конфликты версий**: Трудно сводить разные версии одних и тех же proto‑библиотек **Неповторяемость сборок**: Сло","content":"Проблемы управления зависимостями **Нет стандартизированного подхода**: Каждый проект решает это по‑своему **Конфликты версий**: Трудно сводить разные версии одних и тех же proto‑библиотек **Неповторяемость сборок**: Сложно гарантировать одинаковый результат в разных окружениях"},{"id":"introduction/what-is::top::5","title":"Что такое EasyP?","section":"Трение в разработке","path":"/docs/guide/introduction/what-is","headings":["Трение в разработке"],"excerpt":"Трение в разработке **Ручные операции**: Много повторяющихся шагов **Разрастание конфигураций**: Множество файлов и форматов **Затратная проверка совместимости**: Часто вручную и постфактум","content":"Трение в разработке **Ручные операции**: Много повторяющихся шагов **Разрастание конфигураций**: Множество файлов и форматов **Затратная проверка совместимости**: Часто вручную и постфактум"},{"id":"introduction/what-is::protobuf::6","title":"Что такое EasyP?","section":"Решение: единый protobuf‑инструментарий","path":"/docs/guide/introduction/what-is#protobuf","headings":["Решение: единый protobuf‑инструментарий"],"excerpt":"Решение: единый protobuf‑инструментарий EasyP устраняет эти проблемы, предоставляя целостный opinionated‑подход и стандартизируя процессы:","content":"Решение: единый protobuf‑инструментарий EasyP устраняет эти проблемы, предоставляя целостный opinionated‑подход и стандартизируя процессы:"},{"id":"introduction/what-is::top::7","title":"Что такое EasyP?","section":"Один инструмент — все задачи","path":"/docs/guide/introduction/what-is","headings":["Один инструмент — все задачи"],"excerpt":"Один инструмент — все задачи Вместо жонглирования утилитами EasyP даёт: **Linting** с расширенными наборами правил **Package management** с Git‑нативными зависимостями **Code generation** локально и удалённо **Breaking c","content":"Один инструмент — все задачи Вместо жонглирования утилитами EasyP даёт: **Linting** с расширенными наборами правил **Package management** с Git‑нативными зависимостями **Code generation** локально и удалённо **Breaking change detection** для контроля совместимости API"},{"id":"introduction/what-is::top::8","title":"Что такое EasyP?","section":"Единая конфигурация","path":"/docs/guide/introduction/what-is","headings":["Единая конфигурация"],"excerpt":"Единая конфигурация Один файл easyp.yaml описывает весь workflow — меньше расхождений, проще сопровождать.","content":"Единая конфигурация Один файл easyp.yaml описывает весь workflow — меньше расхождений, проще сопровождать."},{"id":"introduction/what-is::gitnative::9","title":"Что такое EasyP?","section":"Git‑native зависимости","path":"/docs/guide/introduction/what-is#gitnative","headings":["Git‑native зависимости"],"excerpt":"Git‑native зависимости Прямое использование Git‑репозиториев вместо централизованных реестров: прозрачная история, контроль версий, воспроизводимые сборки.","content":"Git‑native зависимости Прямое использование Git‑репозиториев вместо централизованных реестров: прозрачная история, контроль версий, воспроизводимые сборки."},{"id":"introduction/what-is::top::10","title":"Что такое EasyP?","section":"Ключевые возможности","path":"/docs/guide/introduction/what-is","headings":["Ключевые возможности"],"excerpt":"Ключевые возможности Feature Description --------- ------------- 🔍 **Comprehensive Linting** Полная поддержка правил buf с настраиваемыми профилями для лучших практик API‑дизайна. 📦 **Smart Package Manager** Git‑ориент","content":"Ключевые возможности Feature Description --------- ------------- 🔍 **Comprehensive Linting** Полная поддержка правил buf с настраиваемыми профилями для лучших практик API‑дизайна. 📦 **Smart Package Manager** Git‑ориентированное управление зависимостями с lock‑файлом для воспроизводимости. ⚡ **Code Generation** Многозадачная генерация кода с поддержкой локальных и удалённых protoc‑плагинов. 🔄 **Breaking Change Detection** Автоматическая проверка совместимости API против веток Git. 🌐 **Remote Plugin Support** Выполнение плагинов через централизованный EasyP API сервис без локальных установок. 🎯 **Developer Experience** Автодополнение, понятные ошибки, единая структура и документация."},{"id":"introduction/what-is::top::11","title":"Что такое EasyP?","section":"Типы поддерживаемых плагинов","path":"/docs/guide/introduction/what-is","headings":["Типы поддерживаемых плагинов"],"excerpt":"Типы поддерживаемых плагинов EasyP гибко подходит к выполнению генерации:","content":"Типы поддерживаемых плагинов EasyP гибко подходит к выполнению генерации:"},{"id":"introduction/what-is::local-plugins::12","title":"Что такое EasyP?","section":"Local Plugins","path":"/docs/guide/introduction/what-is#local-plugins","headings":["Local Plugins"],"excerpt":"Local Plugins Стандартные установленные protoc‑плагины:","content":"Local Plugins Стандартные установленные protoc‑плагины:"},{"id":"introduction/what-is::remote-plugins::13","title":"Что такое EasyP?","section":"Remote Plugins","path":"/docs/guide/introduction/what-is#remote-plugins","headings":["Remote Plugins"],"excerpt":"Remote Plugins Плагины через EasyP API сервис для воспроизводимости:","content":"Remote Plugins Плагины через EasyP API сервис для воспроизводимости:"},{"id":"introduction/what-is::custom-plugins::14","title":"Что такое EasyP?","section":"Custom Plugins","path":"/docs/guide/introduction/what-is#custom-plugins","headings":["Custom Plugins"],"excerpt":"Custom Plugins Поддержка экосистемы пользовательских расширений.","content":"Custom Plugins Поддержка экосистемы пользовательских расширений."},{"id":"introduction/what-is::top::15","title":"Что такое EasyP?","section":"Децентрализованный менеджмент пакетов","path":"/docs/guide/introduction/what-is","headings":["Децентрализованный менеджмент пакетов"],"excerpt":"Децентрализованный менеджмент пакетов В отличие от других решений EasyP не требует централизованного реестра. Любой Git‑репозиторий может быть источником:","content":"Децентрализованный менеджмент пакетов В отличие от других решений EasyP не требует централизованного реестра. Любой Git‑репозиторий может быть источником:"},{"id":"introduction/what-is::top::16","title":"Что такое EasyP?","section":"Децентрализованный менеджмент пакетов","path":"/docs/guide/introduction/what-is","headings":["Децентрализованный менеджмент пакетов"],"excerpt":"Децентрализованный менеджмент пакетов **Гибкость**: Любой Git‑хостинг (GitHub, GitLab, self‑hosted) **Нет vendor lock‑in**: Зависимости не привязаны к одному провайдеру **Полная история**: Ветки, теги, ревью **Enterprise","content":"Децентрализованный менеджмент пакетов **Гибкость**: Любой Git‑хостинг (GitHub, GitLab, self‑hosted) **Нет vendor lock‑in**: Зависимости не привязаны к одному провайдеру **Полная история**: Ветки, теги, ревью **Enterprise‑совместимость**: Поддержка приватных репозиториев"},{"id":"introduction/what-is::buf::17","title":"Что такое EasyP?","section":"Бесшовная миграция с Buf","path":"/docs/guide/introduction/what-is#buf","headings":["Бесшовная миграция с Buf"],"excerpt":"Бесшовная миграция с Buf EasyP изначально совместим с экосистемой buf:","content":"Бесшовная миграция с Buf EasyP изначально совместим с экосистемой buf:"},{"id":"introduction/what-is::buf::18","title":"Что такое EasyP?","section":"Бесшовная миграция с Buf","path":"/docs/guide/introduction/what-is#buf","headings":["Бесшовная миграция с Buf"],"excerpt":"Бесшовная миграция с Buf **Совпадающие rule sets** **Похожая структура YAML** **Минимальные изменения для замены** **Постепенное внедрение** без ломки текущего пайплайна","content":"Бесшовная миграция с Buf **Совпадающие rule sets** **Похожая структура YAML** **Минимальные изменения для замены** **Постепенное внедрение** без ломки текущего пайплайна"},{"id":"introduction/what-is::easyp-vs-bufbuild::19","title":"Что такое EasyP?","section":"EasyP vs buf.build","path":"/docs/guide/introduction/what-is#easyp-vs-bufbuild","headings":["EasyP vs buf.build"],"excerpt":"EasyP vs buf.build Feature EasyP buf.build --------- -------- ----------- **Dependency Management** Git‑репозитории Buf Schema Registry (BSR) **Vendor Lock-in** Нет Привязка к BSR для полного функционала **Plugin Executi","content":"EasyP vs buf.build Feature EasyP buf.build --------- -------- ----------- **Dependency Management** Git‑репозитории Buf Schema Registry (BSR) **Vendor Lock-in** Нет Привязка к BSR для полного функционала **Plugin Execution** Local + Remote Local + BSR plugins **Private Dependencies** Любой Git провайдер BSR или ручное управление **Offline Development** Полная поддержка (mod vendor) Ограниченно без доступа к BSR **Enterprise Integration** Использует существующий Git Требует настройку BSR **Breaking Change Detection** Против любой Git ссылки Аналогично **Package Distribution** Любой Git Публикация через BSR **License** Apache 2.0 Apache 2.0 **Community** Growing Established"},{"id":"introduction/what-is::easyp-vs-bufbuild::20","title":"Что такое EasyP?","section":"EasyP vs buf.build","path":"/docs/guide/introduction/what-is#easyp-vs-bufbuild","headings":["EasyP vs buf.build"],"excerpt":"EasyP vs buf.build **Преимущества миграции:** Без изменения инфраструктуры Плавное принятие новых возможностей Гибрид локальных и удалённых плагинов Единая конфигурация вместо набора файлов","content":"EasyP vs buf.build **Преимущества миграции:** Без изменения инфраструктуры Плавное принятие новых возможностей Гибрид локальных и удалённых плагинов Единая конфигурация вместо набора файлов"},{"id":"introduction/what-is::protobuf::21","title":"Что такое EasyP?","section":"Наши цели для Protobuf","path":"/docs/guide/introduction/what-is#protobuf","headings":["Наши цели для Protobuf"],"excerpt":"Наши цели для Protobuf Миссия EasyP — ускорить принятие **schema‑driven API** через удобный, надёжный и прозрачный инструментарий.","content":"Наши цели для Protobuf Миссия EasyP — ускорить принятие **schema‑driven API** через удобный, надёжный и прозрачный инструментарий."},{"id":"introduction/what-is::top::22","title":"Что такое EasyP?","section":"Современная экосистема","path":"/docs/guide/introduction/what-is","headings":["Современная экосистема"],"excerpt":"Современная экосистема Повышаем DX вокруг protobuf, чтобы конкурентно выглядеть по простоте против REST/JSON, сохраняя типовую строгость и производительность.","content":"Современная экосистема Повышаем DX вокруг protobuf, чтобы конкурентно выглядеть по простоте против REST/JSON, сохраняя типовую строгость и производительность."},{"id":"introduction/what-is::developer-experience::23","title":"Что такое EasyP?","section":"Developer Experience прежде всего","path":"/docs/guide/introduction/what-is#developer-experience","headings":["Developer Experience прежде всего"],"excerpt":"Developer Experience прежде всего Интуитивный CLI, понятные ошибки, ясные сообщения, минимальная фрагментация.","content":"Developer Experience прежде всего Интуитивный CLI, понятные ошибки, ясные сообщения, минимальная фрагментация."},{"id":"introduction/what-is::enterprise::24","title":"Что такое EasyP?","section":"Готов к Enterprise","path":"/docs/guide/introduction/what-is#enterprise","headings":["Готов к Enterprise"],"excerpt":"Готов к Enterprise Воспроизводимые сборки, приватные репозитории, интеграция в CI/CD.","content":"Готов к Enterprise Воспроизводимые сборки, приватные репозитории, интеграция в CI/CD."},{"id":"introduction/what-is::top::25","title":"Что такое EasyP?","section":"Для индивидуальных разработчиков","path":"/docs/guide/introduction/what-is","headings":["Для индивидуальных разработчиков"],"excerpt":"Для индивидуальных разработчиков Быстрый старт за минуты Один инструмент — меньше когнитивной нагрузки Понятная документация","content":"Для индивидуальных разработчиков Быстрый старт за минуты Один инструмент — меньше когнитивной нагрузки Понятная документация"},{"id":"introduction/what-is::top::26","title":"Что такое EasyP?","section":"Для команд","path":"/docs/guide/introduction/what-is","headings":["Для команд"],"excerpt":"Для команд Единые стандарты Повторяемые сборки (lock‑файл) Ускоренный онбординг","content":"Для команд Единые стандарты Повторяемые сборки (lock‑файл) Ускоренный онбординг"},{"id":"introduction/what-is::top::27","title":"Что такое EasyP?","section":"Для организаций","path":"/docs/guide/introduction/what-is","headings":["Для организаций"],"excerpt":"Для организаций Нет vendor lock‑in Безопасность приватных репозиториев Лёгкая интеграция в существующие пайплайны","content":"Для организаций Нет vendor lock‑in Безопасность приватных репозиториев Лёгкая интеграция в существующие пайплайны"},{"id":"introduction/what-is::top::28","title":"Что такое EasyP?","section":"Что дальше?","path":"/docs/guide/introduction/what-is","headings":["Что дальше?"],"excerpt":"Что дальше? EasyP упрощает работу с protobuf — фокусируйтесь на API, а не на рутине. Хотите начать?","content":"Что дальше? EasyP упрощает работу с protobuf — фокусируйтесь на API, а не на рутине. Хотите начать?"},{"id":"introduction/what-is::top::29","title":"Что такое EasyP?","section":"Что дальше?","path":"/docs/guide/introduction/what-is","headings":["Что дальше?"],"excerpt":"Что дальше? Смотрите Installation Guide и Quickstart.","content":"Что дальше? Смотрите Installation Guide и Quickstart."},{"id":"introduction/what-is::stargazers-over-time::30","title":"Что такое 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 В работе","content":"Buf CLI В работе"},{"id":"migration/protoc::top::0","title":"Миграция с protoc на EasyP","path":"/docs/guide/migration/protoc","headings":[],"excerpt":"Исходная англоязычная версия файла содержала только заголовок и пометку “Work in progress”. Ниже — полноценный русскоязычный черновик раздела миграции. Уточни, если требуется сократить или изменить уровень детализации.","content":"Исходная англоязычная версия файла содержала только заголовок и пометку “Work in progress”. Ниже — полноценный русскоязычный черновик раздела миграции. Уточни, если требуется сократить или изменить уровень детализации."},{"id":"migration/protoc::1::1","title":"Миграция с protoc на EasyP","section":"1. Краткое сравнение","path":"/docs/guide/migration/protoc#1","headings":["1. Краткое сравнение"],"excerpt":"Краткое сравнение Аспект protoc EasyP -------- ---------- ------- Базовая роль Базовый компилятор .proto файлов Инструмент “всё в одном”: линтинг, проверка несовместимых изменений, менеджер пакетов, генерация Конфигураци","content":"Краткое сравнение Аспект protoc EasyP -------- ---------- ------- Базовая роль Базовый компилятор .proto файлов Инструмент “всё в одном”: линтинг, проверка несовместимых изменений, менеджер пакетов, генерация Конфигурация Чаще shell‑скрипты / Makefile / вручную передаваемые флаги Единый файл easyp.yaml (YAML или JSON) Управление зависимостями Ручной git clone, submodule, vendoring Секция deps с Git‑репозиториями Набор правил линтера Нет встроенного Встроенный линтер с правилами (можно включать/исключать) Проверка breaking changes Отсутствует из коробки Команда easyp breaking Расширенные плагины Установка и вызов через флаги --plugin Плагины через конфиг; поддержка удалённого выполнения (API Service) и стандартного локального Единообразие в CI Нужно собирать вручную Консистентные команды: lint, breaking, generate"},{"id":"migration/protoc::2::2","title":"Миграция с protoc на EasyP","section":"2. Когда имеет смысл мигрировать","path":"/docs/guide/migration/protoc#2","headings":["2. Когда имеет смысл мигрировать"],"excerpt":"Когда имеет смысл мигрировать Миграция на EasyP особенно полезна если: Есть потребность в автоматической проверке качества (стиль, именование) .proto файлов. Нужна защита от нелегитимных несовместимых изменений при эволю","content":"Когда имеет смысл мигрировать Миграция на EasyP особенно полезна если: Есть потребность в автоматической проверке качества (стиль, именование) .proto файлов. Нужна защита от нелегитимных несовместимых изменений при эволюции схем. В проекте используется несколько языков генерации и растёт число скриптов вокруг protoc. Вы хотите единый конфиг вместо множества shell/Makefile комбинаций. Планируется централизованное исполнение плагинов (через API Service) или унификация окружения в CI."},{"id":"migration/protoc::3-protoc::3","title":"Миграция с protoc на EasyP","section":"3. Типичный сценарий “до” (только protoc)","path":"/docs/guide/migration/protoc#3-protoc","headings":["3. Типичный сценарий “до” (только protoc)"],"excerpt":"Типичный сценарий “до” (только protoc) Пример: локальные скрипты / Makefile:","content":"Типичный сценарий “до” (только protoc) Пример: локальные скрипты / Makefile:"},{"id":"migration/protoc::3-protoc::4","title":"Миграция с protoc на EasyP","section":"3. Типичный сценарий “до” (только protoc)","path":"/docs/guide/migration/protoc#3-protoc","headings":["3. Типичный сценарий “до” (только protoc)"],"excerpt":"Типичный сценарий “до” (только protoc)","content":"Типичный сценарий “до” (только protoc)"},{"id":"migration/protoc::3-protoc::5","title":"Миграция с protoc на EasyP","section":"3. Типичный сценарий “до” (только protoc)","path":"/docs/guide/migration/protoc#3-protoc","headings":["3. Типичный сценарий “до” (только protoc)"],"excerpt":"Типичный сценарий “до” (только protoc) Дополнительные зависимости (googleapis, validate, grpc-gateway) скачиваются вручную или через submodules.","content":"Типичный сценарий “до” (только protoc) Дополнительные зависимости (googleapis, validate, grpc-gateway) скачиваются вручную или через submodules."},{"id":"migration/protoc::4-easyp::6","title":"Миграция с protoc на EasyP","section":"4. Типичный сценарий “после” (EasyP)","path":"/docs/guide/migration/protoc#4-easyp","headings":["4. Типичный сценарий “после” (EasyP)"],"excerpt":"Типичный сценарий “после” (EasyP) Единый файл easyp.yaml:","content":"Типичный сценарий “после” (EasyP) Единый файл easyp.yaml:"},{"id":"migration/protoc::4-easyp::7","title":"Миграция с protoc на EasyP","section":"4. Типичный сценарий “после” (EasyP)","path":"/docs/guide/migration/protoc#4-easyp","headings":["4. Типичный сценарий “после” (EasyP)"],"excerpt":"Типичный сценарий “после” (EasyP) ```yaml deps: - github.com/googleapis/googleapis - github.com/envoyproxy/protoc-gen-validate","content":"Типичный сценарий “после” (EasyP) ```yaml deps: - github.com/googleapis/googleapis - github.com/envoyproxy/protoc-gen-validate"},{"id":"migration/protoc::4-easyp::8","title":"Миграция с protoc на EasyP","section":"4. Типичный сценарий “после” (EasyP)","path":"/docs/guide/migration/protoc#4-easyp","headings":["4. Типичный сценарий “после” (EasyP)"],"excerpt":"Типичный сценарий “после” (EasyP) generate: plugins: - name: go out: gen/go opts: paths: source_relative - name: go-grpc out: gen/go opts: paths: source_relative require_unimplemented_servers: false - name: validate out:","content":"Типичный сценарий “после” (EasyP) generate: plugins: - name: go out: gen/go opts: paths: source_relative - name: go-grpc out: gen/go opts: paths: source_relative require_unimplemented_servers: false - name: validate out: gen/go opts: paths: source_relative lang: \"go\" ```"},{"id":"migration/protoc::4-easyp::9","title":"Миграция с protoc на EasyP","section":"4. Типичный сценарий “после” (EasyP)","path":"/docs/guide/migration/protoc#4-easyp","headings":["4. Типичный сценарий “после” (EasyP)"],"excerpt":"Типичный сценарий “после” (EasyP) Команды:","content":"Типичный сценарий “после” (EasyP) Команды:"},{"id":"migration/protoc::5::10","title":"Миграция с protoc на EasyP","section":"5. Пошаговая миграция","path":"/docs/guide/migration/protoc#5","headings":["5. Пошаговая миграция"],"excerpt":"Пошаговая миграция Инвентаризация: - Соберите список всех вызовов protoc (скрипты, Makefile, CI). - Зафиксируйте используемые плагины и их версии. Создание easyp.yaml: - Поле version не обязательно (можете оставить его т","content":"Пошаговая миграция Инвентаризация: - Соберите список всех вызовов protoc (скрипты, Makefile, CI). - Зафиксируйте используемые плагины и их версии. Создание easyp.yaml: - Поле version не обязательно (можете оставить его только для обратной совместимости). - Перенесите плагины в секцию generate.plugins. - Укажите опции, которые ранее передавались в командной строке. Зависимости: - Все внешние каталоги (googleapis, validate, grpc-gateway и т.п.) занесите в deps. - Удалите лишние submodules при необходимости. Линтер: - Запустите easyp lint и посмотрите на предупреждения. - При необходимости добавьте lint.use, lint.ignore, lint.except. Проверка breaking changes: - Выберите референс (обычно origin/main или предыдущий тег). - Запустите easyp breaking --against git-ref=origin/main. - Настройте игнорируемые изменения (breaking.ignore), если нужно. Обновление CI: - Замените прямые вызовы protoc на easyp generate. - Добавьте отдельные шаги lint и breaking. Очистка: - Удалите устаревшие генерационные скрипты, если они дублируют функционал EasyP. Документация: - Обновите README / CONTRIBUTING (новый способ генерации). Верификация: - Сравните результат генерации до и после (git diff). - Убедитесь, что имена файлов и пути совпадают или скорректируйте структуру."},{"id":"migration/protoc::6-ci-github-actions::11","title":"Миграция с protoc на EasyP","section":"6. Замена в CI (пример GitHub Actions)","path":"/docs/guide/migration/protoc#6-ci-github-actions","headings":["6. Замена в CI (пример GitHub Actions)"],"excerpt":"Замена в CI (пример GitHub Actions) ```yaml name: Install EasyP run: go install github.com/easyp-tech/easyp/cmd/easyp@latest","content":"Замена в CI (пример GitHub Actions) ```yaml name: Install EasyP run: go install github.com/easyp-tech/easyp/cmd/easyp@latest"},{"id":"migration/protoc::6-ci-github-actions::12","title":"Миграция с protoc на EasyP","section":"6. Замена в CI (пример GitHub Actions)","path":"/docs/guide/migration/protoc#6-ci-github-actions","headings":["6. Замена в CI (пример GitHub Actions)"],"excerpt":"Замена в CI (пример GitHub Actions) name: Lint run: easyp lint","content":"Замена в CI (пример GitHub Actions) name: Lint run: easyp lint"},{"id":"migration/protoc::6-ci-github-actions::13","title":"Миграция с protoc на EasyP","section":"6. Замена в CI (пример GitHub Actions)","path":"/docs/guide/migration/protoc#6-ci-github-actions","headings":["6. Замена в CI (пример GitHub Actions)"],"excerpt":"Замена в CI (пример GitHub Actions) name: Breaking run: easyp breaking --against git-ref=origin/main","content":"Замена в CI (пример GitHub Actions) name: Breaking run: easyp breaking --against git-ref=origin/main"},{"id":"migration/protoc::6-ci-github-actions::14","title":"Миграция с protoc на EasyP","section":"6. Замена в CI (пример GitHub Actions)","path":"/docs/guide/migration/protoc#6-ci-github-actions","headings":["6. Замена в CI (пример GitHub Actions)"],"excerpt":"Замена в CI (пример GitHub Actions) name: Generate run: easyp generate ```","content":"Замена в CI (пример GitHub Actions) name: Generate run: easyp generate ```"},{"id":"migration/protoc::7::15","title":"Миграция с protoc на EasyP","section":"7. Работа с плагинами","path":"/docs/guide/migration/protoc#7","headings":["7. Работа с плагинами"],"excerpt":"Работа с плагинами Тип В protoc В EasyP ----- ---------- --------- Стандартные (protoc-gen-go) Указание через --go_out plugins: - name: go ... gRPC --go-grpc_out Второй плагин go-grpc Validate Доп. установка + --validate","content":"Работа с плагинами Тип В protoc В EasyP ----- ---------- --------- Стандартные (protoc-gen-go) Указание через --go_out plugins: - name: go ... gRPC --go-grpc_out Второй плагин go-grpc Validate Доп. установка + --validate_out - name: validate с opts gRPC-Gateway / OpenAPI --grpc-gateway_out / --openapiv2_out Плагины grpc-gateway, openapiv2 Кастомные Путь к бинарю / --plugin=protoc-gen-xxx - name: xxx или удалённый remote: (если используется API Service)"},{"id":"migration/protoc::7::16","title":"Миграция с protoc на EasyP","section":"7. Работа с плагинами","path":"/docs/guide/migration/protoc#7","headings":["7. Работа с плагинами"],"excerpt":"Работа с плагинами Если вы переходите на удалённое выполнение (API Service), записи в конфиге могут выглядеть так:","content":"Работа с плагинами Если вы переходите на удалённое выполнение (API Service), записи в конфиге могут выглядеть так:"},{"id":"migration/protoc::8::17","title":"Миграция с protoc на EasyP","section":"8. Проверка корректности после миграции","path":"/docs/guide/migration/protoc#8","headings":["8. Проверка корректности после миграции"],"excerpt":"Проверка корректности после миграции git diff после easyp generate — не должно быть неожиданных изменений. Сравнить размер и содержимое каталога сгенерированных файлов. Запустить ваш потребляющий код (сборка, тесты). Про","content":"Проверка корректности после миграции git diff после easyp generate — не должно быть неожиданных изменений. Сравнить размер и содержимое каталога сгенерированных файлов. Запустить ваш потребляющий код (сборка, тесты). Проверить, что плагины (validate, grpc-gateway) продолжают вставлять необходимые аннотации / опции. Линт не должен выдавать критичных ошибок — скорректируйте стиль .proto, если требуется."},{"id":"migration/protoc::9::18","title":"Миграция с protoc на EasyP","section":"9. Частые проблемы","path":"/docs/guide/migration/protoc#9","headings":["9. Частые проблемы"],"excerpt":"Частые проблемы Проблема Причина Решение ---------- --------- --------- Плагин не найден Не установлен или не указан в PATH Выполнить go install ... или добавить в конфиг как remote Ошибка импорта .proto Отсутствует репо","content":"Частые проблемы Проблема Причина Решение ---------- --------- --------- Плагин не найден Не установлен или не указан в PATH Выполнить go install ... или добавить в конфиг как remote Ошибка импорта .proto Отсутствует репозиторий в deps Добавить адрес в секцию deps и easyp mod update Несовместимые изменения на каждом PR Отсутствует игнор/настройка сравнения Уточнить ветку/тег в --against или настроить breaking.ignore Локально работает, в CI падает В CI нет зависимостей (не вызван update) Добавить шаг easyp mod update перед generate Дубликаты сгенерированных файлов Изменена структура путей или out Синхронизировать out и paths: source_relative опции"},{"id":"migration/protoc::10-go::19","title":"Миграция с protoc на EasyP","section":"10. Минимальный пример конфигурации (только Go)","path":"/docs/guide/migration/protoc#10-go","headings":["10. Минимальный пример конфигурации (только Go)"],"excerpt":"Минимальный пример конфигурации (только Go)","content":"Минимальный пример конфигурации (только Go)"},{"id":"migration/protoc::10-go::20","title":"Миграция с protoc на EasyP","section":"10. Минимальный пример конфигурации (только Go)","path":"/docs/guide/migration/protoc#10-go","headings":["10. Минимальный пример конфигурации (только Go)"],"excerpt":"Минимальный пример конфигурации (только Go) Команды:","content":"Минимальный пример конфигурации (только Go) Команды:"},{"id":"migration/protoc::11-go-grpc-gateway-validate-breaking-lint::21","title":"Миграция с protoc на EasyP","section":"11. Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint)","path":"/docs/guide/migration/protoc#11-go-grpc-gateway-validate-breaking-lint","headings":["11. Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint)"],"excerpt":"Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint) ```yaml lint: use: - ENUM_FIRST_VALUE_ZERO - SERVICE_SUFFIX allow_comment_ignores: false enum_zero_value_suffix: _NONE service_suffix: Service","content":"Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint) ```yaml lint: use: - ENUM_FIRST_VALUE_ZERO - SERVICE_SUFFIX allow_comment_ignores: false enum_zero_value_suffix: _NONE service_suffix: Service"},{"id":"migration/protoc::11-go-grpc-gateway-validate-breaking-lint::22","title":"Миграция с protoc на EasyP","section":"11. Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint)","path":"/docs/guide/migration/protoc#11-go-grpc-gateway-validate-breaking-lint","headings":["11. Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint)"],"excerpt":"Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint) deps: - github.com/googleapis/googleapis - github.com/envoyproxy/protoc-gen-validate","content":"Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint) deps: - github.com/googleapis/googleapis - github.com/envoyproxy/protoc-gen-validate"},{"id":"migration/protoc::11-go-grpc-gateway-validate-breaking-lint::23","title":"Миграция с protoc на EasyP","section":"11. Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint)","path":"/docs/guide/migration/protoc#11-go-grpc-gateway-validate-breaking-lint","headings":["11. Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint)"],"excerpt":"Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint) generate: plugins: - name: go out: gen/go opts: paths: source_relative - name: go-grpc out: gen/go opts: paths: source_relative require_unimplemented_","content":"Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint) generate: plugins: - name: go out: gen/go opts: paths: source_relative - name: go-grpc out: gen/go opts: paths: source_relative require_unimplemented_servers: false - name: validate out: gen/go opts: paths: source_relative lang: \"go\" - name: grpc-gateway out: gen/go opts: paths: source_relative - name: openapiv2 out: gen/openapi opts: simple_operation_ids: true"},{"id":"migration/protoc::11-go-grpc-gateway-validate-breaking-lint::24","title":"Миграция с protoc на EasyP","section":"11. Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint)","path":"/docs/guide/migration/protoc#11-go-grpc-gateway-validate-breaking-lint","headings":["11. Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint)"],"excerpt":"Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint) breaking: against_git_ref: main ignore: - ENUM_VALUE_SAME_NAME ```","content":"Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint) breaking: against_git_ref: main ignore: - ENUM_VALUE_SAME_NAME ```"},{"id":"migration/protoc::12-checklist::25","title":"Миграция с protoc на EasyP","section":"12. Checklist миграции","path":"/docs/guide/migration/protoc#12-checklist","headings":["12. Checklist миграции"],"excerpt":"Checklist миграции [ ] Собраны все текущие вызовы protoc. [ ] Создан easyp.yaml с секциями generate и (опционально) lint, breaking. [ ] Добавлены все внешние зависимости в deps. [ ] Успешно выполнен easyp mod update. [ ]","content":"Checklist миграции [ ] Собраны все текущие вызовы protoc. [ ] Создан easyp.yaml с секциями generate и (опционально) lint, breaking. [ ] Добавлены все внешние зависимости в deps. [ ] Успешно выполнен easyp mod update. [ ] easyp generate даёт идентичный или ожидаемо обновлённый результат. [ ] easyp lint проходит без критичных ошибок (или ошибки обработаны). [ ] easyp breaking --against git-ref=origin/main не выдаёт неожиданных блокирующих нарушений. [ ] CI обновлён (заменены прямые вызовы protoc). [ ] Документация проекта обновлена (README: как генерировать)."},{"id":"migration/protoc::13::26","title":"Миграция с protoc на EasyP","section":"13. Дополнительные рекомендации","path":"/docs/guide/migration/protoc#13","headings":["13. Дополнительные рекомендации"],"excerpt":"Дополнительные рекомендации Сначала мигрируйте один сервис / пакет — снизит риск массовых конфликтов. Закоммитьте easyp.yaml отдельно, затем выполните генерацию и линт — проще ревью. Если нужны разные наборы плагинов для","content":"Дополнительные рекомендации Сначала мигрируйте один сервис / пакет — снизит риск массовых конфликтов. Закоммитьте easyp.yaml отдельно, затем выполните генерацию и линт — проще ревью. Если нужны разные наборы плагинов для разных микросервисов — используйте несколько конфигов (например: easyp.microservice-a.yaml + easyp.microservice-b.yaml). Внедрите проверку актуальности генерации: шаг CI, который валидирует отсутствие diff после easyp generate."},{"id":"migration/protoc::14::27","title":"Миграция с protoc на EasyP","section":"14. Статус","path":"/docs/guide/migration/protoc#14","headings":["14. Статус"],"excerpt":"Статус Этот файл — русская расширенная версия, заменяющая placeholder “Work in progress”. При появлении новых возможностей EasyP (дополнительные поля в конфиге, новые плагины, расширения breaking‑проверок) обновите соотв","content":"Статус Этот файл — русская расширенная версия, заменяющая placeholder “Work in progress”. При появлении новых возможностей EasyP (дополнительные поля в конфиге, новые плагины, расширения breaking‑проверок) обновите соответствующие разделы."},{"id":"migration/protoc::14::28","title":"Миграция с protoc на EasyP","section":"14. Статус","path":"/docs/guide/migration/protoc#14","headings":["14. Статус"],"excerpt":"Статус Если нужен упрощённый вариант (только перевод без расширения), сообщи — могу сократить до минимальных двух блоков.","content":"Статус Если нужен упрощённый вариант (только перевод без расширения), сообщи — могу сократить до минимальных двух блоков."},{"id":"migration/protolock::top::0","title":"Protolock","path":"/docs/guide/migration/protolock","headings":[],"excerpt":"Protolock В процессе разработки","content":"Protolock В процессе разработки"},{"id":"migration/prototool::top::0","title":"Prototool","section":"Состояние","path":"/docs/guide/migration/prototool","headings":["Состояние"],"excerpt":"Состояние Этот раздел был помечен как “Work in progress” в оригинальной английской версии. Ниже — переведённое и дополненное практическое руководство по миграции с Prototool на EasyP. Имя инструмента Prototool не перевод","content":"Состояние Этот раздел был помечен как “Work in progress” в оригинальной английской версии. Ниже — переведённое и дополненное практическое руководство по миграции с Prototool на EasyP. Имя инструмента Prototool не переводится."},{"id":"migration/prototool::top::1","title":"Prototool","section":"Цель миграции","path":"/docs/guide/migration/prototool","headings":["Цель миграции"],"excerpt":"Цель миграции Перейти от конфигурации и рабочих процессов Prototool к эквиваленту на EasyP с минимальными изменениями, сохранив: Линтинг .proto файлов. Генерацию кода через protoc-плагины. Управление зависимостями. Прове","content":"Цель миграции Перейти от конфигурации и рабочих процессов Prototool к эквиваленту на EasyP с минимальными изменениями, сохранив: Линтинг .proto файлов. Генерацию кода через protoc-плагины. Управление зависимостями. Проверку несовместимых изменений (в Prototool это приходилось реализовывать внешними инструментами; в EasyP встроено)."},{"id":"migration/prototool::top::2","title":"Prototool","section":"Кратко о различиях","path":"/docs/guide/migration/prototool","headings":["Кратко о различиях"],"excerpt":"Кратко о различиях Область Prototool EasyP Комментарий --------- ----------- ------- ------------- Конфигурация prototool.yaml easyp.yaml Форматы YAML/JSON поддерживаются; структура отличается. Линтинг Встроенные наборы ","content":"Кратко о различиях Область Prototool EasyP Комментарий --------- ----------- ------- ------------- Конфигурация prototool.yaml easyp.yaml Форматы YAML/JSON поддерживаются; структура отличается. Линтинг Встроенные наборы + кастомные правила Наборы через lint.use, тонкая настройка ignore/except EasyP даёт больше гибкости группировки. Генерация Раздел generate + плагины через Docker/локально generate.plugins (локальные/WASM/удалённые) EasyP может выполнять плагины удалённо (API Service). Зависимости Обычно через include-пути / внешние git clone вручную Секция deps (Git репозитории) + mod update Более декларативно. Breaking Changes Нет встроенного механизма Секция breaking + команда easyp breaking Из коробки. Lock-in Зависимость от модели Prototool Минималистичный формат, «любой Git — пакет» Облегчает выход / интеграцию с другими экосистемами."},{"id":"migration/prototool::prototool::3","title":"Prototool","section":"Типовая структура Prototool (упрощённо)","path":"/docs/guide/migration/prototool#prototool","headings":["Типовая структура Prototool (упрощённо)"],"excerpt":"Типовая структура Prototool (упрощённо)","content":"Типовая структура Prototool (упрощённо)"},{"id":"migration/prototool::prototool::4","title":"Prototool","section":"Типовая структура Prototool (упрощённо)","path":"/docs/guide/migration/prototool#prototool","headings":["Типовая структура Prototool (упрощённо)"],"excerpt":"Типовая структура Prototool (упрощённо) Особенности: include_paths задаёт пути поиска импортов. lint.group + rules.add/remove регулируют активные проверки. generate.plugins описывает плагины для protoc.","content":"Типовая структура Prototool (упрощённо) Особенности: include_paths задаёт пути поиска импортов. lint.group + rules.add/remove регулируют активные проверки. generate.plugins описывает плагины для protoc."},{"id":"migration/prototool::prototool::5","title":"Prototool","section":"Типовая структура Prototool (упрощённо)","path":"/docs/guide/migration/prototool#prototool","headings":["Типовая структура Prototool (упрощённо)"],"excerpt":"Типовая структура Prototool (упрощённо) ---","content":"Типовая структура Prototool (упрощённо) ---"},{"id":"migration/prototool::easyp::6","title":"Prototool","section":"Эквивалент на EasyP","path":"/docs/guide/migration/prototool#easyp","headings":["Эквивалент на EasyP"],"excerpt":"Эквивалент на EasyP ```yaml easyp.yaml (пример) deps: - github.com/org/common-protos # вместо manual include - github.com/org/third-party-protos","content":"Эквивалент на EasyP ```yaml easyp.yaml (пример) deps: - github.com/org/common-protos # вместо manual include - github.com/org/third-party-protos"},{"id":"migration/prototool::easyp::7","title":"Prototool","section":"Эквивалент на EasyP","path":"/docs/guide/migration/prototool#easyp","headings":["Эквивалент на EasyP"],"excerpt":"Эквивалент на EasyP lint: use: - MINIMAL - BASIC enum_zero_value_suffix: \"_NONE\" service_suffix: \"Service\" ignore: - COMMENT_FIELD except: - ENUM_VALUE_PREFIX allow_comment_ignores: true","content":"Эквивалент на EasyP lint: use: - MINIMAL - BASIC enum_zero_value_suffix: \"_NONE\" service_suffix: \"Service\" ignore: - COMMENT_FIELD except: - ENUM_VALUE_PREFIX allow_comment_ignores: true"},{"id":"migration/prototool::easyp::8","title":"Prototool","section":"Эквивалент на EasyP","path":"/docs/guide/migration/prototool#easyp","headings":["Эквивалент на EasyP"],"excerpt":"Эквивалент на EasyP generate: plugins: - name: go out: gen/go opts: paths: source_relative - name: go-grpc out: gen/go opts: paths: source_relative require_unimplemented_servers: false","content":"Эквивалент на EasyP generate: plugins: - name: go out: gen/go opts: paths: source_relative - name: go-grpc out: gen/go opts: paths: source_relative require_unimplemented_servers: false"},{"id":"migration/prototool::easyp::9","title":"Prototool","section":"Эквивалент на EasyP","path":"/docs/guide/migration/prototool#easyp","headings":["Эквивалент на EasyP"],"excerpt":"Эквивалент на EasyP breaking: against_git_ref: main ignore: - FIELD_SAME_TYPE ```","content":"Эквивалент на EasyP breaking: against_git_ref: main ignore: - FIELD_SAME_TYPE ```"},{"id":"migration/prototool::easyp::10","title":"Prototool","section":"Эквивалент на EasyP","path":"/docs/guide/migration/prototool#easyp","headings":["Эквивалент на EasyP"],"excerpt":"Эквивалент на EasyP Комментарии: deps заменяет необходимость вручную прописывать include paths: EasyP подтянет их через git. lint.use активирует наборы правил (MINIMAL/BASIC/DEFAULT и т.д.). Дополнительные настройки (enu","content":"Эквивалент на EasyP Комментарии: deps заменяет необходимость вручную прописывать include paths: EasyP подтянет их через git. lint.use активирует наборы правил (MINIMAL/BASIC/DEFAULT и т.д.). Дополнительные настройки (enum_zero_value_suffix, service_suffix) задают политики нейминга. breaking позволяет сразу контролировать несовместимые изменения."},{"id":"migration/prototool::top::11","title":"Prototool","section":"Шаги миграции","path":"/docs/guide/migration/prototool","headings":["Шаги миграции"],"excerpt":"Шаги миграции Инвентаризация: - Соберите текущий prototool.yaml, списки include paths и плагины. - Зафиксируйте используемые кастомные правила, если есть.","content":"Шаги миграции Инвентаризация: - Соберите текущий prototool.yaml, списки include paths и плагины. - Зафиксируйте используемые кастомные правила, если есть."},{"id":"migration/prototool::top::12","title":"Prototool","section":"Шаги миграции","path":"/docs/guide/migration/prototool","headings":["Шаги миграции"],"excerpt":"Шаги миграции Зависимости: - Любые каталоги, которые вы вручную добавляли в include_paths, преобразуйте в git-репозитории (если ещё нет). - Добавьте их в deps (формат: github.com/owner/repo или путь к вашей приватной сис","content":"Шаги миграции Зависимости: - Любые каталоги, которые вы вручную добавляли в include_paths, преобразуйте в git-репозитории (если ещё нет). - Добавьте их в deps (формат: github.com/owner/repo или путь к вашей приватной системе Git)."},{"id":"migration/prototool::top::13","title":"Prototool","section":"Шаги миграции","path":"/docs/guide/migration/prototool","headings":["Шаги миграции"],"excerpt":"Шаги миграции Линтинг: - Определите какой group использовался (basic, default, …) → сопоставьте с наборами EasyP (MINIMAL, BASIC, DEFAULT). - Индивидуальные добавления (rules.add) перенесите в lint.use или except/ignore:","content":"Шаги миграции Линтинг: - Определите какой group использовался (basic, default, …) → сопоставьте с наборами EasyP (MINIMAL, BASIC, DEFAULT). - Индивидуальные добавления (rules.add) перенесите в lint.use или except/ignore: - Если правило нужно активировать — включите через набор или явно. - Если нужно отключить — добавьте в ignore."},{"id":"migration/prototool::top::14","title":"Prototool","section":"Шаги миграции","path":"/docs/guide/migration/prototool","headings":["Шаги миграции"],"excerpt":"Шаги миграции Генерация: - Сохраните список плагинов. В большинстве случаев имена совпадут (go, go-grpc, др.). - Если раньше использовали Docker-окружение Prototool — проверьте поддержку удалённых плагинов через API Serv","content":"Шаги миграции Генерация: - Сохраните список плагинов. В большинстве случаев имена совпадут (go, go-grpc, др.). - Если раньше использовали Docker-окружение Prototool — проверьте поддержку удалённых плагинов через API Service EasyP (опционально). - Перепишите в секцию generate.plugins."},{"id":"migration/prototool::top::15","title":"Prototool","section":"Шаги миграции","path":"/docs/guide/migration/prototool","headings":["Шаги миграции"],"excerpt":"Шаги миграции Дополнительные опции: - Настройки нейминга enum/service перенести в enum_zero_value_suffix, service_suffix. - Если были внешние скрипты для проверки breaking changes — удалите их и включите breaking с again","content":"Шаги миграции Дополнительные опции: - Настройки нейминга enum/service перенести в enum_zero_value_suffix, service_suffix. - Если были внешние скрипты для проверки breaking changes — удалите их и включите breaking с against_git_ref."},{"id":"migration/prototool::top::16","title":"Prototool","section":"Шаги миграции","path":"/docs/guide/migration/prototool","headings":["Шаги миграции"],"excerpt":"Шаги миграции Верификация: - Запустите: easyp mod update (скачивание deps). - Затем: easyp lint. - Далее: easyp generate. - И, если нужно: easyp breaking --against git-ref=origin/main.","content":"Шаги миграции Верификация: - Запустите: easyp mod update (скачивание deps). - Затем: easyp lint. - Далее: easyp generate. - И, если нужно: easyp breaking --against git-ref=origin/main."},{"id":"migration/prototool::top::17","title":"Prototool","section":"Шаги миграции","path":"/docs/guide/migration/prototool","headings":["Шаги миграции"],"excerpt":"Шаги миграции CI/CD: - Обновите workflow (GitHub Actions / GitLab) — замените вызовы Prototool на EasyP команды. - Добавьте шаг проверки несовместимых изменений.","content":"Шаги миграции CI/CD: - Обновите workflow (GitHub Actions / GitLab) — замените вызовы Prototool на EasyP команды. - Добавьте шаг проверки несовместимых изменений."},{"id":"migration/prototool::top::18","title":"Prototool","section":"Сопоставление правил (общая идея)","path":"/docs/guide/migration/prototool","headings":["Сопоставление правил (общая идея)"],"excerpt":"Сопоставление правил (общая идея) Prototool концепт EasyP ------------------- ------ lint.group lint.use (наборы) rules.add/remove except / ignore include_paths deps (git источники) plugins generate.plugins (внешние скри","content":"Сопоставление правил (общая идея) Prototool концепт EasyP ------------------- ------ lint.group lint.use (наборы) rules.add/remove except / ignore include_paths deps (git источники) plugins generate.plugins (внешние скрипты для breaking) breaking секция + команда"},{"id":"migration/prototool::top::19","title":"Prototool","section":"Сопоставление правил (общая идея)","path":"/docs/guide/migration/prototool","headings":["Сопоставление правил (общая идея)"],"excerpt":"Сопоставление правил (общая идея) ---","content":"Сопоставление правил (общая идея) ---"},{"id":"migration/prototool::top::20","title":"Prototool","section":"Приватные репозитории","path":"/docs/guide/migration/prototool","headings":["Приватные репозитории"],"excerpt":"Приватные репозитории Если ранее Prototool просто видел локальные каталоги, теперь: Добавьте SSH ключи/токены в CI для доступа к приватным Git. Укажите их в deps как обычные git-URL (формат зависит от реализации EasyP; д","content":"Приватные репозитории Если ранее Prototool просто видел локальные каталоги, теперь: Добавьте SSH ключи/токены в CI для доступа к приватным Git. Укажите их в deps как обычные git-URL (формат зависит от реализации EasyP; для публичных — стандартный)."},{"id":"migration/prototool::top::21","title":"Prototool","section":"Типовые проблемы при миграции","path":"/docs/guide/migration/prototool","headings":["Типовые проблемы при миграции"],"excerpt":"Типовые проблемы при миграции Проблема Причина Решение ---------- --------- --------- Правила линтера не совпадают Неверное сопоставление групп Проверить документацию EasyP по наборам правил Импорты не находятся Забыли д","content":"Типовые проблемы при миграции Проблема Причина Решение ---------- --------- --------- Правила линтера не совпадают Неверное сопоставление групп Проверить документацию EasyP по наборам правил Импорты не находятся Забыли добавить репозиторий в deps Добавить в deps и выполнить easyp mod update Генерация падает на опциях Плагин требует другие flags Проверить opts и документацию плагина breaking сообщает слишком много Слишком строгий базовый набор Добавить конкретные правила в breaking.ignore Долгая генерация Нет кеша/много deps Включить кэширование в CI (vendor/.easyp/deps)"},{"id":"migration/prototool::top::22","title":"Prototool","section":"Типовые проблемы при миграции","path":"/docs/guide/migration/prototool","headings":["Типовые проблемы при миграции"],"excerpt":"Типовые проблемы при миграции ---","content":"Типовые проблемы при миграции ---"},{"id":"migration/prototool::top::23","title":"Prototool","section":"Минимальная конфигурация после миграции","path":"/docs/guide/migration/prototool","headings":["Минимальная конфигурация после миграции"],"excerpt":"Минимальная конфигурация после миграции","content":"Минимальная конфигурация после миграции"},{"id":"migration/prototool::top::24","title":"Prototool","section":"Минимальная конфигурация после миграции","path":"/docs/guide/migration/prototool","headings":["Минимальная конфигурация после миграции"],"excerpt":"Минимальная конфигурация после миграции ---","content":"Минимальная конфигурация после миграции ---"},{"id":"migration/prototool::top::25","title":"Prototool","section":"Рекомендации по упрощению","path":"/docs/guide/migration/prototool","headings":["Рекомендации по упрощению"],"excerpt":"Рекомендации по упрощению Начните с минимального lint.use (MINIMAL), затем постепенно включайте дополнительные наборы. Не переносите слепо все ignore — часть правил может уже быть улучшена в EasyP. Сначала настроить deps","content":"Рекомендации по упрощению Начните с минимального lint.use (MINIMAL), затем постепенно включайте дополнительные наборы. Не переносите слепо все ignore — часть правил может уже быть улучшена в EasyP. Сначала настроить deps и генерацию, затем усложнять линт/нейминг. Фиксируйте миграцию по шагам (коммиты: deps → lint → generate → breaking → CI)."},{"id":"migration/prototool::top::26","title":"Prototool","section":"Проверка результата","path":"/docs/guide/migration/prototool","headings":["Проверка результата"],"excerpt":"Проверка результата Скрипт локальной быстрой проверки (пример):","content":"Проверка результата Скрипт локальной быстрой проверки (пример):"},{"id":"migration/prototool::top::27","title":"Prototool","section":"Проверка результата","path":"/docs/guide/migration/prototool","headings":["Проверка результата"],"excerpt":"Проверка результата ```bash #!/usr/bin/env bash set -euo pipefail","content":"Проверка результата ```bash #!/usr/bin/env bash set -euo pipefail"},{"id":"migration/prototool::top::28","title":"Prototool","section":"Проверка результата","path":"/docs/guide/migration/prototool","headings":["Проверка результата"],"excerpt":"Проверка результата echo \"[1] deps update\" easyp mod update","content":"Проверка результата echo \"[1] deps update\" easyp mod update"},{"id":"migration/prototool::top::29","title":"Prototool","section":"Проверка результата","path":"/docs/guide/migration/prototool","headings":["Проверка результата"],"excerpt":"Проверка результата echo \"[2] lint\" easyp lint","content":"Проверка результата echo \"[2] lint\" easyp lint"},{"id":"migration/prototool::top::30","title":"Prototool","section":"Проверка результата","path":"/docs/guide/migration/prototool","headings":["Проверка результата"],"excerpt":"Проверка результата echo \"[3] breaking vs main\" easyp breaking --against git-ref=origin/main echo \"Breaking changes detected (review needed)\"","content":"Проверка результата echo \"[3] breaking vs main\" easyp breaking --against git-ref=origin/main echo \"Breaking changes detected (review needed)\""},{"id":"migration/prototool::top::31","title":"Prototool","section":"Проверка результата","path":"/docs/guide/migration/prototool","headings":["Проверка результата"],"excerpt":"Проверка результата echo \"[4] generate\" easyp generate","content":"Проверка результата echo \"[4] generate\" easyp generate"},{"id":"migration/prototool::top::32","title":"Prototool","section":"Проверка результата","path":"/docs/guide/migration/prototool","headings":["Проверка результата"],"excerpt":"Проверка результата echo \"Done.\" ```","content":"Проверка результата echo \"Done.\" ```"},{"id":"migration/prototool::top::33","title":"Prototool","section":"Заключение","path":"/docs/guide/migration/prototool","headings":["Заключение"],"excerpt":"Заключение Миграция с Prototool на EasyP сводится к: Переносу путей и внешних каталогов в декларативные deps. Переформатированию линта под lint.use + ignore/except. Переносу генерации в generate.plugins. Добавлению встро","content":"Заключение Миграция с Prototool на EasyP сводится к: Переносу путей и внешних каталогов в декларативные deps. Переформатированию линта под lint.use + ignore/except. Переносу генерации в generate.plugins. Добавлению встроенного механизма breaking. Адаптации CI."},{"id":"migration/prototool::top::34","title":"Prototool","section":"Заключение","path":"/docs/guide/migration/prototool","headings":["Заключение"],"excerpt":"Заключение После этого конфигурация становится более прозрачной, а проверка несовместимых изменений — из коробки.","content":"Заключение После этого конфигурация становится более прозрачной, а проверка несовместимых изменений — из коробки."},{"id":"migration/prototool::top::35","title":"Prototool","section":"Заключение","path":"/docs/guide/migration/prototool","headings":["Заключение"],"excerpt":"Заключение *Готово: базовый перевод и расширенное руководство по миграции с Prototool на EasyP.*","content":"Заключение *Готово: базовый перевод и расширенное руководство по миграции с Prototool на EasyP.*"},{"id":"TRANSLATION_STATUS::top::0","title":"Translation Status (ru-guide)","path":"/docs/guide/TRANSLATION_STATUS","headings":[],"excerpt":"Этот файл отслеживает прогресс перевода русской документации. Используемые статусы: TODO — требуется перевод IN_PROGRESS — перевод начат, требуется вычитка DONE — перевод завершён и вычитан SKIPPED — не требует перевода ","content":"Этот файл отслеживает прогресс перевода русской документации. Используемые статусы: TODO — требуется перевод IN_PROGRESS — перевод начат, требуется вычитка DONE — перевод завершён и вычитан SKIPPED — не требует перевода (намеренно оставлено на английском)"},{"id":"TRANSLATION_STATUS::top::1","title":"Translation Status (ru-guide)","path":"/docs/guide/TRANSLATION_STATUS","headings":[],"excerpt":"Правила: После полного перевода файла убрать исходный английский текст и маркер Термины протокола и ключевые идентификаторы (названия правил, CLI команды, YAML ключи) НЕ переводим. Если структура исходного файла изменила","content":"Правила: После полного перевода файла убрать исходный английский текст и маркер Термины протокола и ключевые идентификаторы (названия правил, CLI команды, YAML ключи) НЕ переводим. Если структура исходного файла изменилась — добавить в начало: Для больших изменений: сначала IN_PROGRESS, после вычитки менять на DONE."},{"id":"TRANSLATION_STATUS::summary::2","title":"Translation Status (ru-guide)","section":"Summary","path":"/docs/guide/TRANSLATION_STATUS#summary","headings":["Summary"],"excerpt":"Summary Итого файлов: 76 DONE: 76 IN_PROGRESS: 0 TODO: 0","content":"Summary Итого файлов: 76 DONE: 76 IN_PROGRESS: 0 TODO: 0"},{"id":"TRANSLATION_STATUS::priority-order::3","title":"Translation Status (ru-guide)","section":"Priority Order (рекомендованный)","path":"/docs/guide/TRANSLATION_STATUS#priority-order","headings":["Priority Order (рекомендованный)"],"excerpt":"Priority Order (рекомендованный) introduction/what-is.md introduction/quickstart.md introduction/install.md cli/linter/linter.md cli/generator/generator.md cli/package-manager/package-manager.md cli/breaking-changes/brea","content":"Priority Order (рекомендованный) introduction/what-is.md introduction/quickstart.md introduction/install.md cli/linter/linter.md cli/generator/generator.md cli/package-manager/package-manager.md cli/breaking-changes/breaking-changes.md api-service/overview.md migration/* (пакетом)"},{"id":"TRANSLATION_STATUS::priority-order::4","title":"Translation Status (ru-guide)","section":"Priority Order (рекомендованный)","path":"/docs/guide/TRANSLATION_STATUS#priority-order","headings":["Priority Order (рекомендованный)"],"excerpt":"Priority Order (рекомендованный) ---","content":"Priority Order (рекомендованный) ---"},{"id":"TRANSLATION_STATUS::file-status-table::5","title":"Translation Status (ru-guide)","section":"File Status Table","path":"/docs/guide/TRANSLATION_STATUS#file-status-table","headings":["File Status Table"],"excerpt":"File Status Table File Status Notes ------ -------- ------- introduction/what-is.md DONE Полный перевод выполнен introduction/quickstart.md DONE Структура сохранена, перевод вычитан introduction/install.md DONE Переведен","content":"File Status Table File Status Notes ------ -------- ------- introduction/what-is.md DONE Полный перевод выполнен introduction/quickstart.md DONE Структура сохранена, перевод вычитан introduction/install.md DONE Переведено, команды проверены api-service/overview.md DONE Переведено ci-cd/github-actions.md DONE Переведено ci-cd/gitlab.md DONE Переведено cli/auto-completion/auto-completion.md DONE Переведено cli/breaking-changes/breaking-changes.md DONE Переведено и вычитано cli/breaking-changes/rules/enum-no-delete.md DONE Переведено cli/breaking-changes/rules/enum-value-no-delete.md DONE Переведено cli/breaking-changes/rules/enum-value-same-name.md DONE Переведено cli/breaking-changes/rules/field-no-delete.md DONE Переведено cli/breaking-changes/rules/field-same-cardinality.md DONE Переведено cli/breaking-changes/rules/field-same-type.md DONE Переведено cli/breaking-changes/rules/import-no-delete.md DONE Переведено cli/breaking-changes/rules/message-no-delete.md DONE Переведено cli/breaking-changes/rules/oneof-field-no-delete.md DONE Переведено cli/breaking-changes/rules/oneof-field-same-type.md DONE Переведено cli/breaking-changes/rules/oneof-no-delete.md DONE Переведено cli/breaking-changes/rules/rpc-no-delete.md DONE Переведено cli/breaking-changes/rules/rpc-same-request-type.md DONE Переведено cli/breaking-changes/rules/rpc-same-response-type.md DONE Переведено cli/breaking-changes/rules/service-no-delete.md DONE Переведено cli/configuration/configuration.md DONE Переведено cli/generator/examples/go.md DONE Переведено cli/generator/examples/grpc-gateway.md DONE Переведено cli/generator/examples/validate.md DONE Переведено cli/generator/generator.md DONE Переведено и вычитано cli/linter/linter.md DONE Переведено и вычитано cli/linter/rules/comment-enum-value.md DONE Переведено cli/linter/rules/comment-enum.md DONE Переведено cli/linter/rules/comment-field.md DONE Переведено cli/linter/rules/comment-message.md DONE Переведено cli/linter/rules/comment-oneof.md DONE Переведено cli/linter/rules/comment-rpc.md DONE Переведено cli/linter/rules/comment-service.md DONE Переведено cli/linter/rules/directory-same-package.md DONE Переведено cli/linter/rules/enum-first-value-zero.md DONE Переведено cli/linter/rules/enum-no-allow-alias.md DONE Переведено cli/linter/rules/enum-pascal-case.md DONE Переведено cli/linter/rules/enum-value-prefix.md DONE Переведено cli/linter/rules/enum-value-upper-snake-case.md DONE Переведено cli/linter/rules/enum-zero-value-suffix.md DONE Переведено cli/linter/rules/field-lower-snake-case.md DONE Переведено cli/linter/rules/file-lower-snake-case.md DONE Переведено cli/linter/rules/import-no-public.md DONE Переведено cli/linter/rules/import-no-weak.md DONE Переведено cli/linter/rules/import-used.md DONE Переведено cli/linter/rules/message-pascal-case.md DONE Переведено cli/linter/rules/oneof-lower-snake-case.md DONE Переведено cli/linter/rules/package-defined.md DONE Переведено cli/linter/rules/package-directory-match.md DONE Переведено cli/linter/rules/package-lower-snake-case.md DONE Переведено cli/linter/rules/package-same-csharp-namespace.md DONE Переведено cli/linter/rules/package-same-directory.md DONE Переведено cli/linter/rules/package-same-go-package.md DONE Переведено cli/linter/rules/package-same-java-multiple-files.md DONE Переведено cli/linter/rules/package-same-java-package.md DONE Переведено cli/linter/rules/package-same-php-namespace.md DONE Переведено cli/linter/rules/package-same-ruby-package.md DONE Переведено cli/linter/rules/package-same-swift-prefix.md DONE Переведено cli/linter/rules/package-version-suffix.md DONE Переведено cli/linter/rules/rpc-no-client-streaming.md DONE Переведено cli/linter/rules/rpc-no-server-streaming.md DONE Переведено cli/linter/rules/rpc-pascal-case.md DONE Переведено cli/linter/rules/rpc-request-response-unique.md DONE Переведено cli/linter/rules/rpc-request-standard-name.md DONE Переведено cli/linter/rules/rpc-response-standard-name.md DONE Переведено cli/linter/rules/service-pascal-case.md DONE Переведено cli/linter/rules/service-suffix.md DONE Переведено cli/package-manager/easyp-vs-buf.md DONE Переведено cli/package-manager/package-manager.md DONE Переведено и вычитано migration/buf-cli.md DONE Переведено migration/protoc.md DONE Переведено migration/protolock.md DONE Переведено migration/prototool.md DONE Переведено"},{"id":"TRANSLATION_STATUS::workflow::6","title":"Translation Status (ru-guide)","section":"Workflow","path":"/docs/guide/TRANSLATION_STATUS#workflow","headings":["Workflow"],"excerpt":"Workflow Выбираем файл со статусом TODO. Меняем статус на IN_PROGRESS здесь. Переводим, проверяем терминологию (сверка с глоссарием — добавить позже). Меняем статус на DONE. Удаляем маркер внутри файла.","content":"Workflow Выбираем файл со статусом TODO. Меняем статус на IN_PROGRESS здесь. Переводим, проверяем терминологию (сверка с глоссарием — добавить позже). Меняем статус на DONE. Удаляем маркер внутри файла."},{"id":"TRANSLATION_STATUS::planned-terminology::7","title":"Translation Status (ru-guide)","section":"Planned Terminology (черновик)","path":"/docs/guide/TRANSLATION_STATUS#planned-terminology","headings":["Planned Terminology (черновик)"],"excerpt":"Planned Terminology (черновик) EN RU Notes ---- ---- ------- Linting Линтинг Транслитерация Breaking Changes Несовместимые изменения Название секции Dependency Зависимость Code Generation Генерация кода Lock file Lock-фа","content":"Planned Terminology (черновик) EN RU Notes ---- ---- ------- Linting Линтинг Транслитерация Breaking Changes Несовместимые изменения Название секции Dependency Зависимость Code Generation Генерация кода Lock file Lock-файл Remote Plugin Удалённый плагин Package Manager Менеджер пакетов"},{"id":"TRANSLATION_STATUS::planned-terminology::8","title":"Translation Status (ru-guide)","section":"Planned Terminology (черновик)","path":"/docs/guide/TRANSLATION_STATUS#planned-terminology","headings":["Planned Terminology (черновик)"],"excerpt":"Planned Terminology (черновик) (Будет дополнено.)","content":"Planned Terminology (черновик) (Будет дополнено.)"},{"id":"TRANSLATION_STATUS::planned-terminology::9","title":"Translation Status (ru-guide)","section":"Planned Terminology (черновик)","path":"/docs/guide/TRANSLATION_STATUS#planned-terminology","headings":["Planned Terminology (черновик)"],"excerpt":"Planned Terminology (черновик) ---","content":"Planned Terminology (черновик) ---"},{"id":"TRANSLATION_STATUS::top::10","title":"Translation Status (ru-guide)","section":"История обновлений","path":"/docs/guide/TRANSLATION_STATUS","headings":["История обновлений"],"excerpt":"История обновлений Initial file created: all statuses set (3 IN_PROGRESS, rest TODO). Marked breaking-changes page as DONE. Linter rules (41 файлов) переведены: статусы DONE. Breaking-changes rules (15 файлов) вычитаны и","content":"История обновлений Initial file created: all statuses set (3 IN_PROGRESS, rest TODO). Marked breaking-changes page as DONE. Linter rules (41 файлов) переведены: статусы DONE. Breaking-changes rules (15 файлов) вычитаны и помечены DONE. Все оставшиеся страницы переведены: итог DONE = 76."}] \ No newline at end of file diff --git a/internal/core/generate_managed_mode_test.go b/internal/core/generate_managed_mode_test.go new file mode 100644 index 00000000..a886963c --- /dev/null +++ b/internal/core/generate_managed_mode_test.go @@ -0,0 +1,102 @@ +package core + +import ( + "context" + "os" + "path/filepath" + "testing" + + "github.com/easyp-tech/easyp/internal/core/models" + "github.com/easyp-tech/easyp/internal/logger" + "github.com/stretchr/testify/require" + "google.golang.org/protobuf/types/descriptorpb" +) + +func TestGenerateManagedModeAppliesToGitRepoInputs(t *testing.T) { + t.Parallel() + + workspaceRoot := t.TempDir() + gitRepoRoot := t.TempDir() + writeProtoWithoutGoPackage(t, gitRepoRoot, "pinger/v1/service.proto") + + executor := &captureExecutor{} + + moduleName := "http://gitlab.com/foo/contracts" + moduleVersion := "v0.0.1" + lockInfo := models.LockFileInfo{ + Name: moduleName, + Version: moduleVersion, + } + + storage := &StorageMock{} + lockFile := &LockFileMock{} + + lockFile.EXPECT().DepsIter().Return(func(yield func(models.LockFileInfo) bool) {}).Once() + lockFile.EXPECT().Read(moduleName).Return(lockInfo, nil).Twice() + storage.EXPECT().GetInstallDir(moduleName, moduleVersion).Return(gitRepoRoot).Twice() + + app := &Core{ + logger: logger.NewNop(), + plugins: []Plugin{ + { + Source: PluginSource{Name: "custom-plugin"}, + Out: ".", + }, + }, + inputs: Inputs{ + InputGitRepos: []InputGitRepo{ + { + URL: moduleName + "@" + moduleVersion, + SubDirectory: "pinger/v1", + }, + }, + }, + storage: storage, + lockFile: lockFile, + managedMode: ManagedModeConfig{Enabled: true, Override: []ManagedOverrideRule{{FileOption: FileOptionGoPackagePrefix, Value: "pinger-service/internal/grpc/gen"}}}, + localExecutor: executor, + remoteExecutor: executor, + builtinExecutor: executor, + commandExecutor: executor, + } + + err := app.Generate(context.Background(), workspaceRoot, ".", "", false) + require.NoError(t, err) + require.Len(t, executor.requests, 1) + + req := executor.requests[0] + require.Equal(t, []string{"pinger/v1/service.proto"}, req.GetFileToGenerate()) + + target := findFileDescriptor(t, req.GetProtoFile(), "pinger/v1/service.proto") + require.Equal(t, "pinger-service/internal/grpc/gen/pinger/v1;pingerv1", target.GetOptions().GetGoPackage()) +} + +func writeProtoWithoutGoPackage(t *testing.T, root string, relPath string) { + t.Helper() + + fullPath := filepath.Join(root, relPath) + err := os.MkdirAll(filepath.Dir(fullPath), 0755) + require.NoError(t, err) + + protoContent := `syntax = "proto3"; +package pinger.v1; + +message PingRequest {} +` + + err = os.WriteFile(fullPath, []byte(protoContent), 0644) + require.NoError(t, err) +} + +func findFileDescriptor(t *testing.T, files []*descriptorpb.FileDescriptorProto, name string) *descriptorpb.FileDescriptorProto { + t.Helper() + + for _, file := range files { + if file.GetName() == name { + return file + } + } + + t.Fatalf("file descriptor %q not found", name) + return nil +} diff --git a/internal/core/lockfile_mock_test.go b/internal/core/lockfile_mock_test.go new file mode 100644 index 00000000..d438d18f --- /dev/null +++ b/internal/core/lockfile_mock_test.go @@ -0,0 +1,233 @@ +// Code generated by mockery. DO NOT EDIT. + +package core + +import ( + iter "iter" + + models "github.com/easyp-tech/easyp/internal/core/models" + mock "github.com/stretchr/testify/mock" +) + +// LockFileMock is an autogenerated mock type for the LockFile type +type LockFileMock struct { + mock.Mock +} + +type LockFileMock_Expecter struct { + mock *mock.Mock +} + +func (_m *LockFileMock) EXPECT() *LockFileMock_Expecter { + return &LockFileMock_Expecter{mock: &_m.Mock} +} + +// DepsIter provides a mock function with no fields +func (_m *LockFileMock) DepsIter() iter.Seq[models.LockFileInfo] { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for DepsIter") + } + + var r0 iter.Seq[models.LockFileInfo] + if rf, ok := ret.Get(0).(func() iter.Seq[models.LockFileInfo]); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(iter.Seq[models.LockFileInfo]) + } + } + + return r0 +} + +// LockFileMock_DepsIter_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'DepsIter' +type LockFileMock_DepsIter_Call struct { + *mock.Call +} + +// DepsIter is a helper method to define mock.On call +func (_e *LockFileMock_Expecter) DepsIter() *LockFileMock_DepsIter_Call { + return &LockFileMock_DepsIter_Call{Call: _e.mock.On("DepsIter")} +} + +func (_c *LockFileMock_DepsIter_Call) Run(run func()) *LockFileMock_DepsIter_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *LockFileMock_DepsIter_Call) Return(_a0 iter.Seq[models.LockFileInfo]) *LockFileMock_DepsIter_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *LockFileMock_DepsIter_Call) RunAndReturn(run func() iter.Seq[models.LockFileInfo]) *LockFileMock_DepsIter_Call { + _c.Call.Return(run) + return _c +} + +// IsEmpty provides a mock function with no fields +func (_m *LockFileMock) IsEmpty() bool { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for IsEmpty") + } + + var r0 bool + if rf, ok := ret.Get(0).(func() bool); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(bool) + } + + return r0 +} + +// LockFileMock_IsEmpty_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'IsEmpty' +type LockFileMock_IsEmpty_Call struct { + *mock.Call +} + +// IsEmpty is a helper method to define mock.On call +func (_e *LockFileMock_Expecter) IsEmpty() *LockFileMock_IsEmpty_Call { + return &LockFileMock_IsEmpty_Call{Call: _e.mock.On("IsEmpty")} +} + +func (_c *LockFileMock_IsEmpty_Call) Run(run func()) *LockFileMock_IsEmpty_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *LockFileMock_IsEmpty_Call) Return(_a0 bool) *LockFileMock_IsEmpty_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *LockFileMock_IsEmpty_Call) RunAndReturn(run func() bool) *LockFileMock_IsEmpty_Call { + _c.Call.Return(run) + return _c +} + +// Read provides a mock function with given fields: moduleName +func (_m *LockFileMock) Read(moduleName string) (models.LockFileInfo, error) { + ret := _m.Called(moduleName) + + if len(ret) == 0 { + panic("no return value specified for Read") + } + + var r0 models.LockFileInfo + var r1 error + if rf, ok := ret.Get(0).(func(string) (models.LockFileInfo, error)); ok { + return rf(moduleName) + } + if rf, ok := ret.Get(0).(func(string) models.LockFileInfo); ok { + r0 = rf(moduleName) + } else { + r0 = ret.Get(0).(models.LockFileInfo) + } + + if rf, ok := ret.Get(1).(func(string) error); ok { + r1 = rf(moduleName) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// LockFileMock_Read_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Read' +type LockFileMock_Read_Call struct { + *mock.Call +} + +// Read is a helper method to define mock.On call +// - moduleName string +func (_e *LockFileMock_Expecter) Read(moduleName interface{}) *LockFileMock_Read_Call { + return &LockFileMock_Read_Call{Call: _e.mock.On("Read", moduleName)} +} + +func (_c *LockFileMock_Read_Call) Run(run func(moduleName string)) *LockFileMock_Read_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(string)) + }) + return _c +} + +func (_c *LockFileMock_Read_Call) Return(_a0 models.LockFileInfo, _a1 error) *LockFileMock_Read_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *LockFileMock_Read_Call) RunAndReturn(run func(string) (models.LockFileInfo, error)) *LockFileMock_Read_Call { + _c.Call.Return(run) + return _c +} + +// Write provides a mock function with given fields: moduleName, revisionVersion, installedPackageHash +func (_m *LockFileMock) Write(moduleName string, revisionVersion string, installedPackageHash models.ModuleHash) error { + ret := _m.Called(moduleName, revisionVersion, installedPackageHash) + + if len(ret) == 0 { + panic("no return value specified for Write") + } + + var r0 error + if rf, ok := ret.Get(0).(func(string, string, models.ModuleHash) error); ok { + r0 = rf(moduleName, revisionVersion, installedPackageHash) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// LockFileMock_Write_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Write' +type LockFileMock_Write_Call struct { + *mock.Call +} + +// Write is a helper method to define mock.On call +// - moduleName string +// - revisionVersion string +// - installedPackageHash models.ModuleHash +func (_e *LockFileMock_Expecter) Write(moduleName interface{}, revisionVersion interface{}, installedPackageHash interface{}) *LockFileMock_Write_Call { + return &LockFileMock_Write_Call{Call: _e.mock.On("Write", moduleName, revisionVersion, installedPackageHash)} +} + +func (_c *LockFileMock_Write_Call) Run(run func(moduleName string, revisionVersion string, installedPackageHash models.ModuleHash)) *LockFileMock_Write_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(string), args[1].(string), args[2].(models.ModuleHash)) + }) + return _c +} + +func (_c *LockFileMock_Write_Call) Return(_a0 error) *LockFileMock_Write_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *LockFileMock_Write_Call) RunAndReturn(run func(string, string, models.ModuleHash) error) *LockFileMock_Write_Call { + _c.Call.Return(run) + return _c +} + +// NewLockFileMock creates a new instance of LockFileMock. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewLockFileMock(t interface { + mock.TestingT + Cleanup(func()) +}) *LockFileMock { + mock := &LockFileMock{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/internal/core/managed_mode.go b/internal/core/managed_mode.go index 2b2fc122..fbbf4eed 100644 --- a/internal/core/managed_mode.go +++ b/internal/core/managed_mode.go @@ -676,12 +676,8 @@ func ApplyManagedMode( module := fileToModule[filePath] pkg := fd.GetPackage() - // For files from external dependencies (module != ""), managed mode should - // only be applied if there's an explicit rule for that module. - // Local project files (module == "") are always processed. - if module != "" && !hasModuleRule(config, module) { - continue - } + // Managed mode applies to all files. Module/path selectors are used only + // to narrow disable/override rules, matching buf's managed mode behavior. // Ensure Options is initialized if fd.Options == nil { @@ -698,25 +694,6 @@ func ApplyManagedMode( return nil } -// hasModuleRule checks if there are any disable or override rules for the given module. -func hasModuleRule(config ManagedModeConfig, module string) bool { - // Check disable rules - for _, rule := range config.Disable { - if rule.Module == module { - return true - } - } - - // Check override rules - for _, rule := range config.Override { - if rule.Module == module { - return true - } - } - - return false -} - // applyFileOptions applies all registered file options. // The logic follows buf's managed mode behavior: // 1. First, apply all overrides in order (last matching rule wins) diff --git a/internal/core/managed_mode_test.go b/internal/core/managed_mode_test.go index 5e286bf1..d6e921a3 100644 --- a/internal/core/managed_mode_test.go +++ b/internal/core/managed_mode_test.go @@ -212,7 +212,7 @@ func TestApplyManagedMode_OverrideForModule(t *testing.T) { }, { FileOption: FileOptionGoPackagePrefix, - Module: "buf.build/acme/petapis", + Module: "https://github.com/acme/petapis", Value: "github.com/acme/pet/gen/go", }, }, @@ -220,7 +220,7 @@ func TestApplyManagedMode_OverrideForModule(t *testing.T) { fileToModule := map[string]string{ "acme/weather/v1/weather.proto": "", - "acme/pet/v1/pet.proto": "buf.build/acme/petapis", + "acme/pet/v1/pet.proto": "https://github.com/acme/petapis", } err := ApplyManagedMode([]*descriptorpb.FileDescriptorProto{fd1, fd2}, config, fileToModule) @@ -514,7 +514,7 @@ func TestApplyManagedMode_FieldOptions(t *testing.T) { } func TestApplyManagedMode_ExternalModules(t *testing.T) { - // Files from external modules should only be processed if there's an explicit rule + // Global rules should apply to all files, including external modules. localFile := &descriptorpb.FileDescriptorProto{ Name: strPtr("api/v1/service.proto"), Package: strPtr("api.v1"), @@ -547,28 +547,33 @@ func TestApplyManagedMode_ExternalModules(t *testing.T) { err := ApplyManagedMode([]*descriptorpb.FileDescriptorProto{localFile, externalFile}, config, fileToModule) require.NoError(t, err) - // Local file should get go_package from managed mode + // Local file should get go_package from managed mode. assert.Equal(t, "github.com/example/ec-code/gen/go/api/v1;apiv1", localFile.Options.GetGoPackage()) - // External file should keep its original go_package (no rule for this module) - assert.Equal(t, "google.golang.org/genproto/googleapis/api/annotations", externalFile.Options.GetGoPackage()) + // External file should also be rewritten by the global override. + assert.Equal(t, "github.com/example/ec-code/gen/go/google/api;googleapi", externalFile.Options.GetGoPackage()) } -func TestApplyManagedMode_ExternalModuleWithRule(t *testing.T) { - // External module file should be processed if there's an explicit rule +func TestApplyManagedMode_DisableExternalModule(t *testing.T) { externalFile := &descriptorpb.FileDescriptorProto{ Name: strPtr("google/api/annotations.proto"), Package: strPtr("google.api"), - Options: &descriptorpb.FileOptions{}, + Options: &descriptorpb.FileOptions{ + GoPackage: strPtr("google.golang.org/genproto/googleapis/api/annotations"), + }, } config := ManagedModeConfig{ Enabled: true, + Disable: []ManagedDisableRule{ + { + Module: "github.com/googleapis/googleapis", + }, + }, Override: []ManagedOverrideRule{ { FileOption: FileOptionGoPackagePrefix, Value: "github.com/example/ec-code/gen/go", - Module: "github.com/googleapis/googleapis", // Explicit rule for this module }, }, } @@ -580,9 +585,8 @@ func TestApplyManagedMode_ExternalModuleWithRule(t *testing.T) { err := ApplyManagedMode([]*descriptorpb.FileDescriptorProto{externalFile}, config, fileToModule) require.NoError(t, err) - // External file should get go_package from managed mode because there's a rule for its module - // Package: google.api -> take last 2 segments -> googleapi - assert.Equal(t, "github.com/example/ec-code/gen/go/google/api;googleapi", externalFile.Options.GetGoPackage()) + // Disabled modules should keep their original options even when global overrides exist. + assert.Equal(t, "google.golang.org/genproto/googleapis/api/annotations", externalFile.Options.GetGoPackage()) } // Test cleanPackageName function diff --git a/internal/core/mod.go b/internal/core/mod.go index 6752d03d..9e62730b 100644 --- a/internal/core/mod.go +++ b/internal/core/mod.go @@ -1,5 +1,8 @@ package core +//go:generate mockery --name Storage --dir . --output . --outpkg core --filename storage_mock_test.go --structname StorageMock --inpackage --testonly +//go:generate mockery --name LockFile --dir . --output . --outpkg core --filename lockfile_mock_test.go --structname LockFileMock --inpackage --testonly + import ( "context" "iter" diff --git a/internal/core/storage_mock_test.go b/internal/core/storage_mock_test.go new file mode 100644 index 00000000..56e28e9d --- /dev/null +++ b/internal/core/storage_mock_test.go @@ -0,0 +1,453 @@ +// Code generated by mockery. DO NOT EDIT. + +package core + +import ( + context "context" + + models "github.com/easyp-tech/easyp/internal/core/models" + mock "github.com/stretchr/testify/mock" +) + +// StorageMock is an autogenerated mock type for the Storage type +type StorageMock struct { + mock.Mock +} + +type StorageMock_Expecter struct { + mock *mock.Mock +} + +func (_m *StorageMock) EXPECT() *StorageMock_Expecter { + return &StorageMock_Expecter{mock: &_m.Mock} +} + +// CreateCacheDownloadDir provides a mock function with given fields: _a0 +func (_m *StorageMock) CreateCacheDownloadDir(_a0 models.CacheDownloadPaths) error { + ret := _m.Called(_a0) + + if len(ret) == 0 { + panic("no return value specified for CreateCacheDownloadDir") + } + + var r0 error + if rf, ok := ret.Get(0).(func(models.CacheDownloadPaths) error); ok { + r0 = rf(_a0) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// StorageMock_CreateCacheDownloadDir_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'CreateCacheDownloadDir' +type StorageMock_CreateCacheDownloadDir_Call struct { + *mock.Call +} + +// CreateCacheDownloadDir is a helper method to define mock.On call +// - _a0 models.CacheDownloadPaths +func (_e *StorageMock_Expecter) CreateCacheDownloadDir(_a0 interface{}) *StorageMock_CreateCacheDownloadDir_Call { + return &StorageMock_CreateCacheDownloadDir_Call{Call: _e.mock.On("CreateCacheDownloadDir", _a0)} +} + +func (_c *StorageMock_CreateCacheDownloadDir_Call) Run(run func(_a0 models.CacheDownloadPaths)) *StorageMock_CreateCacheDownloadDir_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(models.CacheDownloadPaths)) + }) + return _c +} + +func (_c *StorageMock_CreateCacheDownloadDir_Call) Return(_a0 error) *StorageMock_CreateCacheDownloadDir_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *StorageMock_CreateCacheDownloadDir_Call) RunAndReturn(run func(models.CacheDownloadPaths) error) *StorageMock_CreateCacheDownloadDir_Call { + _c.Call.Return(run) + return _c +} + +// CreateCacheRepositoryDir provides a mock function with given fields: name +func (_m *StorageMock) CreateCacheRepositoryDir(name string) (string, error) { + ret := _m.Called(name) + + if len(ret) == 0 { + panic("no return value specified for CreateCacheRepositoryDir") + } + + var r0 string + var r1 error + if rf, ok := ret.Get(0).(func(string) (string, error)); ok { + return rf(name) + } + if rf, ok := ret.Get(0).(func(string) string); ok { + r0 = rf(name) + } else { + r0 = ret.Get(0).(string) + } + + if rf, ok := ret.Get(1).(func(string) error); ok { + r1 = rf(name) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// StorageMock_CreateCacheRepositoryDir_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'CreateCacheRepositoryDir' +type StorageMock_CreateCacheRepositoryDir_Call struct { + *mock.Call +} + +// CreateCacheRepositoryDir is a helper method to define mock.On call +// - name string +func (_e *StorageMock_Expecter) CreateCacheRepositoryDir(name interface{}) *StorageMock_CreateCacheRepositoryDir_Call { + return &StorageMock_CreateCacheRepositoryDir_Call{Call: _e.mock.On("CreateCacheRepositoryDir", name)} +} + +func (_c *StorageMock_CreateCacheRepositoryDir_Call) Run(run func(name string)) *StorageMock_CreateCacheRepositoryDir_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(string)) + }) + return _c +} + +func (_c *StorageMock_CreateCacheRepositoryDir_Call) Return(_a0 string, _a1 error) *StorageMock_CreateCacheRepositoryDir_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *StorageMock_CreateCacheRepositoryDir_Call) RunAndReturn(run func(string) (string, error)) *StorageMock_CreateCacheRepositoryDir_Call { + _c.Call.Return(run) + return _c +} + +// GetCacheDownloadPaths provides a mock function with given fields: moduleName, version +func (_m *StorageMock) GetCacheDownloadPaths(moduleName string, version string) models.CacheDownloadPaths { + ret := _m.Called(moduleName, version) + + if len(ret) == 0 { + panic("no return value specified for GetCacheDownloadPaths") + } + + var r0 models.CacheDownloadPaths + if rf, ok := ret.Get(0).(func(string, string) models.CacheDownloadPaths); ok { + r0 = rf(moduleName, version) + } else { + r0 = ret.Get(0).(models.CacheDownloadPaths) + } + + return r0 +} + +// StorageMock_GetCacheDownloadPaths_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetCacheDownloadPaths' +type StorageMock_GetCacheDownloadPaths_Call struct { + *mock.Call +} + +// GetCacheDownloadPaths is a helper method to define mock.On call +// - moduleName string +// - version string +func (_e *StorageMock_Expecter) GetCacheDownloadPaths(moduleName interface{}, version interface{}) *StorageMock_GetCacheDownloadPaths_Call { + return &StorageMock_GetCacheDownloadPaths_Call{Call: _e.mock.On("GetCacheDownloadPaths", moduleName, version)} +} + +func (_c *StorageMock_GetCacheDownloadPaths_Call) Run(run func(moduleName string, version string)) *StorageMock_GetCacheDownloadPaths_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(string), args[1].(string)) + }) + return _c +} + +func (_c *StorageMock_GetCacheDownloadPaths_Call) Return(_a0 models.CacheDownloadPaths) *StorageMock_GetCacheDownloadPaths_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *StorageMock_GetCacheDownloadPaths_Call) RunAndReturn(run func(string, string) models.CacheDownloadPaths) *StorageMock_GetCacheDownloadPaths_Call { + _c.Call.Return(run) + return _c +} + +// GetInstallDir provides a mock function with given fields: moduleName, revisionVersion +func (_m *StorageMock) GetInstallDir(moduleName string, revisionVersion string) string { + ret := _m.Called(moduleName, revisionVersion) + + if len(ret) == 0 { + panic("no return value specified for GetInstallDir") + } + + var r0 string + if rf, ok := ret.Get(0).(func(string, string) string); ok { + r0 = rf(moduleName, revisionVersion) + } else { + r0 = ret.Get(0).(string) + } + + return r0 +} + +// StorageMock_GetInstallDir_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetInstallDir' +type StorageMock_GetInstallDir_Call struct { + *mock.Call +} + +// GetInstallDir is a helper method to define mock.On call +// - moduleName string +// - revisionVersion string +func (_e *StorageMock_Expecter) GetInstallDir(moduleName interface{}, revisionVersion interface{}) *StorageMock_GetInstallDir_Call { + return &StorageMock_GetInstallDir_Call{Call: _e.mock.On("GetInstallDir", moduleName, revisionVersion)} +} + +func (_c *StorageMock_GetInstallDir_Call) Run(run func(moduleName string, revisionVersion string)) *StorageMock_GetInstallDir_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(string), args[1].(string)) + }) + return _c +} + +func (_c *StorageMock_GetInstallDir_Call) Return(_a0 string) *StorageMock_GetInstallDir_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *StorageMock_GetInstallDir_Call) RunAndReturn(run func(string, string) string) *StorageMock_GetInstallDir_Call { + _c.Call.Return(run) + return _c +} + +// GetInstalledModuleHash provides a mock function with given fields: moduleName, revisionVersion +func (_m *StorageMock) GetInstalledModuleHash(moduleName string, revisionVersion string) (models.ModuleHash, error) { + ret := _m.Called(moduleName, revisionVersion) + + if len(ret) == 0 { + panic("no return value specified for GetInstalledModuleHash") + } + + var r0 models.ModuleHash + var r1 error + if rf, ok := ret.Get(0).(func(string, string) (models.ModuleHash, error)); ok { + return rf(moduleName, revisionVersion) + } + if rf, ok := ret.Get(0).(func(string, string) models.ModuleHash); ok { + r0 = rf(moduleName, revisionVersion) + } else { + r0 = ret.Get(0).(models.ModuleHash) + } + + if rf, ok := ret.Get(1).(func(string, string) error); ok { + r1 = rf(moduleName, revisionVersion) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// StorageMock_GetInstalledModuleHash_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetInstalledModuleHash' +type StorageMock_GetInstalledModuleHash_Call struct { + *mock.Call +} + +// GetInstalledModuleHash is a helper method to define mock.On call +// - moduleName string +// - revisionVersion string +func (_e *StorageMock_Expecter) GetInstalledModuleHash(moduleName interface{}, revisionVersion interface{}) *StorageMock_GetInstalledModuleHash_Call { + return &StorageMock_GetInstalledModuleHash_Call{Call: _e.mock.On("GetInstalledModuleHash", moduleName, revisionVersion)} +} + +func (_c *StorageMock_GetInstalledModuleHash_Call) Run(run func(moduleName string, revisionVersion string)) *StorageMock_GetInstalledModuleHash_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(string), args[1].(string)) + }) + return _c +} + +func (_c *StorageMock_GetInstalledModuleHash_Call) Return(_a0 models.ModuleHash, _a1 error) *StorageMock_GetInstalledModuleHash_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *StorageMock_GetInstalledModuleHash_Call) RunAndReturn(run func(string, string) (models.ModuleHash, error)) *StorageMock_GetInstalledModuleHash_Call { + _c.Call.Return(run) + return _c +} + +// Install provides a mock function with given fields: ctx, cacheDownloadPaths, module, revision, moduleConfig +func (_m *StorageMock) Install(ctx context.Context, cacheDownloadPaths models.CacheDownloadPaths, module models.Module, revision models.Revision, moduleConfig models.ModuleConfig) (models.ModuleHash, error) { + ret := _m.Called(ctx, cacheDownloadPaths, module, revision, moduleConfig) + + if len(ret) == 0 { + panic("no return value specified for Install") + } + + var r0 models.ModuleHash + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, models.CacheDownloadPaths, models.Module, models.Revision, models.ModuleConfig) (models.ModuleHash, error)); ok { + return rf(ctx, cacheDownloadPaths, module, revision, moduleConfig) + } + if rf, ok := ret.Get(0).(func(context.Context, models.CacheDownloadPaths, models.Module, models.Revision, models.ModuleConfig) models.ModuleHash); ok { + r0 = rf(ctx, cacheDownloadPaths, module, revision, moduleConfig) + } else { + r0 = ret.Get(0).(models.ModuleHash) + } + + if rf, ok := ret.Get(1).(func(context.Context, models.CacheDownloadPaths, models.Module, models.Revision, models.ModuleConfig) error); ok { + r1 = rf(ctx, cacheDownloadPaths, module, revision, moduleConfig) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// StorageMock_Install_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Install' +type StorageMock_Install_Call struct { + *mock.Call +} + +// Install is a helper method to define mock.On call +// - ctx context.Context +// - cacheDownloadPaths models.CacheDownloadPaths +// - module models.Module +// - revision models.Revision +// - moduleConfig models.ModuleConfig +func (_e *StorageMock_Expecter) Install(ctx interface{}, cacheDownloadPaths interface{}, module interface{}, revision interface{}, moduleConfig interface{}) *StorageMock_Install_Call { + return &StorageMock_Install_Call{Call: _e.mock.On("Install", ctx, cacheDownloadPaths, module, revision, moduleConfig)} +} + +func (_c *StorageMock_Install_Call) Run(run func(ctx context.Context, cacheDownloadPaths models.CacheDownloadPaths, module models.Module, revision models.Revision, moduleConfig models.ModuleConfig)) *StorageMock_Install_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(models.CacheDownloadPaths), args[2].(models.Module), args[3].(models.Revision), args[4].(models.ModuleConfig)) + }) + return _c +} + +func (_c *StorageMock_Install_Call) Return(_a0 models.ModuleHash, _a1 error) *StorageMock_Install_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *StorageMock_Install_Call) RunAndReturn(run func(context.Context, models.CacheDownloadPaths, models.Module, models.Revision, models.ModuleConfig) (models.ModuleHash, error)) *StorageMock_Install_Call { + _c.Call.Return(run) + return _c +} + +// ReadInstalledModuleInfo provides a mock function with given fields: cacheDownloadPaths +func (_m *StorageMock) ReadInstalledModuleInfo(cacheDownloadPaths models.CacheDownloadPaths) (models.InstalledModuleInfo, error) { + ret := _m.Called(cacheDownloadPaths) + + if len(ret) == 0 { + panic("no return value specified for ReadInstalledModuleInfo") + } + + var r0 models.InstalledModuleInfo + var r1 error + if rf, ok := ret.Get(0).(func(models.CacheDownloadPaths) (models.InstalledModuleInfo, error)); ok { + return rf(cacheDownloadPaths) + } + if rf, ok := ret.Get(0).(func(models.CacheDownloadPaths) models.InstalledModuleInfo); ok { + r0 = rf(cacheDownloadPaths) + } else { + r0 = ret.Get(0).(models.InstalledModuleInfo) + } + + if rf, ok := ret.Get(1).(func(models.CacheDownloadPaths) error); ok { + r1 = rf(cacheDownloadPaths) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// StorageMock_ReadInstalledModuleInfo_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ReadInstalledModuleInfo' +type StorageMock_ReadInstalledModuleInfo_Call struct { + *mock.Call +} + +// ReadInstalledModuleInfo is a helper method to define mock.On call +// - cacheDownloadPaths models.CacheDownloadPaths +func (_e *StorageMock_Expecter) ReadInstalledModuleInfo(cacheDownloadPaths interface{}) *StorageMock_ReadInstalledModuleInfo_Call { + return &StorageMock_ReadInstalledModuleInfo_Call{Call: _e.mock.On("ReadInstalledModuleInfo", cacheDownloadPaths)} +} + +func (_c *StorageMock_ReadInstalledModuleInfo_Call) Run(run func(cacheDownloadPaths models.CacheDownloadPaths)) *StorageMock_ReadInstalledModuleInfo_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(models.CacheDownloadPaths)) + }) + return _c +} + +func (_c *StorageMock_ReadInstalledModuleInfo_Call) Return(_a0 models.InstalledModuleInfo, _a1 error) *StorageMock_ReadInstalledModuleInfo_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *StorageMock_ReadInstalledModuleInfo_Call) RunAndReturn(run func(models.CacheDownloadPaths) (models.InstalledModuleInfo, error)) *StorageMock_ReadInstalledModuleInfo_Call { + _c.Call.Return(run) + return _c +} + +// WriteInstalledModuleInfo provides a mock function with given fields: cacheDownloadPaths, installedModuleInfo +func (_m *StorageMock) WriteInstalledModuleInfo(cacheDownloadPaths models.CacheDownloadPaths, installedModuleInfo models.InstalledModuleInfo) error { + ret := _m.Called(cacheDownloadPaths, installedModuleInfo) + + if len(ret) == 0 { + panic("no return value specified for WriteInstalledModuleInfo") + } + + var r0 error + if rf, ok := ret.Get(0).(func(models.CacheDownloadPaths, models.InstalledModuleInfo) error); ok { + r0 = rf(cacheDownloadPaths, installedModuleInfo) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// StorageMock_WriteInstalledModuleInfo_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'WriteInstalledModuleInfo' +type StorageMock_WriteInstalledModuleInfo_Call struct { + *mock.Call +} + +// WriteInstalledModuleInfo is a helper method to define mock.On call +// - cacheDownloadPaths models.CacheDownloadPaths +// - installedModuleInfo models.InstalledModuleInfo +func (_e *StorageMock_Expecter) WriteInstalledModuleInfo(cacheDownloadPaths interface{}, installedModuleInfo interface{}) *StorageMock_WriteInstalledModuleInfo_Call { + return &StorageMock_WriteInstalledModuleInfo_Call{Call: _e.mock.On("WriteInstalledModuleInfo", cacheDownloadPaths, installedModuleInfo)} +} + +func (_c *StorageMock_WriteInstalledModuleInfo_Call) Run(run func(cacheDownloadPaths models.CacheDownloadPaths, installedModuleInfo models.InstalledModuleInfo)) *StorageMock_WriteInstalledModuleInfo_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(models.CacheDownloadPaths), args[1].(models.InstalledModuleInfo)) + }) + return _c +} + +func (_c *StorageMock_WriteInstalledModuleInfo_Call) Return(_a0 error) *StorageMock_WriteInstalledModuleInfo_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *StorageMock_WriteInstalledModuleInfo_Call) RunAndReturn(run func(models.CacheDownloadPaths, models.InstalledModuleInfo) error) *StorageMock_WriteInstalledModuleInfo_Call { + _c.Call.Return(run) + return _c +} + +// NewStorageMock creates a new instance of StorageMock. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewStorageMock(t interface { + mock.TestingT + Cleanup(func()) +}) *StorageMock { + mock := &StorageMock{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/mcp/easypconfig/spec_docs.go b/mcp/easypconfig/spec_docs.go index f894d7f2..6bef9660 100644 --- a/mcp/easypconfig/spec_docs.go +++ b/mcp/easypconfig/spec_docs.go @@ -20,7 +20,7 @@ func docsByPath() map[string]nodeDoc { { Title: "full_config_reference", Description: "Reference config touching all top-level sections.", - YAML: "version: v1alpha\nlint:\n use:\n - DEFAULT\n enum_zero_value_suffix: _UNSPECIFIED\n service_suffix: Service\n ignore:\n - vendor\n ignore_only:\n RPC_REQUEST_STANDARD_NAME:\n - proto/legacy\ndeps:\n - github.com/googleapis/googleapis@common-protos-1_3_1\ngenerate:\n inputs:\n - directory:\n path: api\n root: .\n - git_repo:\n url: github.com/acme/contracts@v1.2.3\n sub_directory: proto\n root: .\n plugins:\n - name: go\n out: gen/go\n opts:\n paths: source_relative\n - remote: api.easyp.tech/grpc/go:v1.5.1\n out: gen/go\n with_imports: true\n managed:\n enabled: true\n disable:\n - module: buf.build/googleapis/googleapis\n override:\n - file_option: go_package_prefix\n value: github.com/acme/contracts/gen/go\nbreaking:\n against_git_ref: main\n ignore:\n - proto/legacy\n", + YAML: "version: v1alpha\nlint:\n use:\n - DEFAULT\n enum_zero_value_suffix: _UNSPECIFIED\n service_suffix: Service\n ignore:\n - vendor\n ignore_only:\n RPC_REQUEST_STANDARD_NAME:\n - proto/legacy\ndeps:\n - github.com/googleapis/googleapis@common-protos-1_3_1\ngenerate:\n inputs:\n - directory:\n path: api\n root: .\n - git_repo:\n url: github.com/acme/contracts@v1.2.3\n sub_directory: proto\n root: .\n plugins:\n - name: go\n out: gen/go\n opts:\n paths: source_relative\n - remote: api.easyp.tech/grpc/go:v1.5.1\n out: gen/go\n with_imports: true\n managed:\n enabled: true\n disable:\n - module: github.com/googleapis/googleapis\n override:\n - file_option: go_package_prefix\n value: github.com/acme/contracts/gen/go\nbreaking:\n against_git_ref: main\n ignore:\n - proto/legacy\n", Paths: []string{"$", "lint", "deps", "generate", "breaking"}, }, }, @@ -79,7 +79,7 @@ func docsByPath() map[string]nodeDoc { { Title: "generate_all_sections", Description: "Generate section with local+git inputs, multiple plugin styles, and managed mode.", - YAML: "generate:\n inputs:\n - directory: proto\n - git_repo:\n url: github.com/acme/contracts@v1.2.3\n sub_directory: api\n plugins:\n - name: go\n out: gen/go\n - command: [\"go\", \"run\", \"example.com/protoc-gen-custom@latest\"]\n out: gen/custom\n with_imports: true\n managed:\n enabled: true\n disable:\n - module: buf.build/googleapis/googleapis\n override:\n - file_option: go_package_prefix\n value: github.com/acme/contracts/gen/go\n", + YAML: "generate:\n inputs:\n - directory: proto\n - git_repo:\n url: github.com/acme/contracts@v1.2.3\n sub_directory: api\n plugins:\n - name: go\n out: gen/go\n - command: [\"go\", \"run\", \"example.com/protoc-gen-custom@latest\"]\n out: gen/custom\n with_imports: true\n managed:\n enabled: true\n disable:\n - module: github.com/googleapis/googleapis\n override:\n - file_option: go_package_prefix\n value: github.com/acme/contracts/gen/go\n", Paths: []string{"generate", "generate.inputs", "generate.plugins", "generate.managed"}, }, }, @@ -201,21 +201,21 @@ func docsByPath() map[string]nodeDoc { "generate.managed": { Fields: []FieldDoc{ {Path: "generate.managed.enabled", Type: "boolean", Required: false, Description: "Enable managed mode option rewriting.", DefaultValue: "false"}, - {Path: "generate.managed.disable", Type: "array", Required: false, Description: "Disable managed mode per module/path/option."}, - {Path: "generate.managed.override", Type: "array", Required: false, Description: "Override file/field options with values."}, + {Path: "generate.managed.disable", Type: "array", Required: false, Description: "Disable managed mode for matching modules, paths, or options."}, + {Path: "generate.managed.override", Type: "array", Required: false, Description: "Override file/field options with values. Without module/path, applies to all files."}, }, Examples: []Example{ { Title: "managed_mode_full", Description: "Managed mode with both disable and override rules.", - YAML: "generate:\n managed:\n enabled: true\n disable:\n - module: buf.build/googleapis/googleapis\n - field_option: jstype\n field: acme.v1.Message.count\n override:\n - file_option: go_package_prefix\n value: github.com/acme/contracts/gen/go\n - field_option: jstype\n field: acme.v1.Message.count\n value: JS_STRING\n", + YAML: "generate:\n managed:\n enabled: true\n disable:\n - module: github.com/googleapis/googleapis\n - field_option: jstype\n field: acme.v1.Message.count\n override:\n - file_option: go_package_prefix\n value: github.com/acme/contracts/gen/go\n - field_option: jstype\n field: acme.v1.Message.count\n value: JS_STRING\n", Paths: []string{"generate.managed"}, }, }, }, "generate.managed.disable": { Fields: []FieldDoc{ - {Path: "generate.managed.disable[].module", Type: "string", Required: false, Description: "Apply disable to module."}, + {Path: "generate.managed.disable[].module", Type: "string", Required: false, Description: "Apply disable to an exact EasyP module source (dependency/git_repo URL without @version)."}, {Path: "generate.managed.disable[].path", Type: "string", Required: false, Description: "Apply disable to path."}, {Path: "generate.managed.disable[].file_option", Type: "string", Required: false, Description: "Disable this file option."}, {Path: "generate.managed.disable[].field_option", Type: "string", Required: false, Description: "Disable this field option."}, @@ -240,7 +240,7 @@ func docsByPath() map[string]nodeDoc { {Path: "generate.managed.override[].file_option", Type: "string", Required: false, Description: "Target file option to override."}, {Path: "generate.managed.override[].field_option", Type: "string", Required: false, Description: "Target field option to override."}, {Path: "generate.managed.override[].value", Type: "any", Required: true, Description: "Override value."}, - {Path: "generate.managed.override[].module", Type: "string", Required: false, Description: "Optional module selector."}, + {Path: "generate.managed.override[].module", Type: "string", Required: false, Description: "Optional exact EasyP module selector (dependency/git_repo URL without @version)."}, {Path: "generate.managed.override[].path", Type: "string", Required: false, Description: "Optional path selector."}, {Path: "generate.managed.override[].field", Type: "string", Required: false, Description: "Optional field selector (for field_option)."}, }, From 15e3b5a7cada42b2a10d7cc2b5aacd9f6086364b Mon Sep 17 00:00:00 2001 From: Khasbulat Abdullin Date: Mon, 9 Mar 2026 01:51:00 +0300 Subject: [PATCH 2/2] feat: support protobuf package selectors in managed mode Add exact package-based matching for managed mode disable and override rules, wire it through config parsing, runtime conversion, JSON schema, MCP docs, and user guides, and cover the new behavior with runtime/config/schema tests. --- .../docs/guide/cli/generator/generator.md | 29 ++++++- .../docs/ru-guide/cli/generator/generator.md | 29 ++++++- docs/dist/search/index.en.json | 2 +- docs/dist/search/index.ru.json | 2 +- .../docs/guide/cli/generator/generator.md | 29 ++++++- .../docs/ru-guide/cli/generator/generator.md | 29 ++++++- docs/public/search/index.en.json | 2 +- docs/public/search/index.ru.json | 2 +- internal/api/temporaly_helper.go | 2 + internal/config/config.go | 6 +- internal/config/managed_mode_test.go | 41 ++++++++++ internal/config/validate_raw.go | 4 +- internal/config/validate_raw_test.go | 26 +++++++ internal/config/yaml_validators.go | 14 ++-- internal/core/managed_mode.go | 70 ++++++++++------- internal/core/managed_mode_test.go | 77 ++++++++++++++++++- mcp/easypconfig/easypconfig_test.go | 12 +++ mcp/easypconfig/schema_model.go | 3 + mcp/easypconfig/spec_docs.go | 14 ++-- schemas/easyp-config-v1.schema.json | 11 +++ schemas/easyp-config.schema.json | 11 +++ 21 files changed, 363 insertions(+), 52 deletions(-) create mode 100644 internal/config/managed_mode_test.go diff --git a/docs/dist/docs/guide/cli/generator/generator.md b/docs/dist/docs/guide/cli/generator/generator.md index fa04560d..94b16fdd 100644 --- a/docs/dist/docs/guide/cli/generator/generator.md +++ b/docs/dist/docs/guide/cli/generator/generator.md @@ -574,7 +574,7 @@ When managed mode is enabled, EasyP automatically applies file and field options - Objective-C: `objc_class_prefix` defaults to first letters of package parts - C++: `cc_enable_arenas` defaults to `true` -**Overrides** allow you to set specific values for options, with support for filtering by module, path, or field. Without `module` or `path`, an override applies to all files in the generation request, including dependencies and `git_repo` inputs. +**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. **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. @@ -590,6 +590,10 @@ generate: # Disable specific option globally - file_option: java_package_prefix + + # Disable for specific protobuf package + - package: acme.weather.v1 + file_option: java_package # Disable for specific path - path: legacy/ @@ -608,6 +612,11 @@ generate: - file_option: java_package_prefix value: com.mycompany module: github.com/mycompany/internal-protos + + # 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 @@ -761,6 +770,24 @@ generate: `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`. +`package` matches the protobuf `package` declaration exactly, for example `acme.weather.v1`. + +#### Package-Specific Overrides + +Apply different options to files from a specific protobuf package: + +```yaml +generate: + managed: + enabled: true + override: + - file_option: go_package_prefix + value: github.com/mycompany/myproject/gen/go + - file_option: go_package + package: acme.weather.v1 + value: github.com/mycompany/myproject/gen/go/acme/weather/v1 +``` + #### Disabling for External Dependencies Disable managed mode for external dependencies that already have their options set: diff --git a/docs/dist/docs/ru-guide/cli/generator/generator.md b/docs/dist/docs/ru-guide/cli/generator/generator.md index 6b17395f..16afe1fd 100644 --- a/docs/dist/docs/ru-guide/cli/generator/generator.md +++ b/docs/dist/docs/ru-guide/cli/generator/generator.md @@ -574,7 +574,7 @@ Managed mode автоматически устанавливает file и field - Objective-C: `objc_class_prefix` по умолчанию первые буквы частей пакета - C++: `cc_enable_arenas` по умолчанию `true` -**Overrides** позволяют установить конкретные значения для опций с поддержкой фильтрации по модулю, пути или полю. Если не указаны `module` и `path`, override применяется ко всем файлам в запросе генерации, включая зависимости и `git_repo` inputs. +**Overrides** позволяют установить конкретные значения для опций с поддержкой фильтрации по модулю, protobuf package, пути или полю. Если не указаны `module`, `package` и `path`, override применяется ко всем файлам в запросе генерации, включая зависимости и `git_repo` inputs. **Disables** позволяют предотвратить изменение managed mode определённых опций или файлов. Это рекомендуемый способ исключить внешние зависимости, у которых свои опции уже заданы. @@ -590,6 +590,10 @@ generate: # Отключить конкретную опцию глобально - file_option: java_package_prefix + + # Отключить для конкретного protobuf package + - package: acme.weather.v1 + file_option: java_package # Отключить для конкретного пути - path: legacy/ @@ -608,6 +612,11 @@ generate: - file_option: java_package_prefix value: com.mycompany module: github.com/mycompany/internal-protos + + # Переопределить для конкретного protobuf package + - file_option: go_package_prefix + value: github.com/mycompany/myproject/gen/go + package: acme.weather.v1 # Переопределить для конкретного пути - file_option: csharp_namespace_prefix @@ -761,6 +770,24 @@ generate: `module` должен точно совпадать с источником модуля в EasyP: это значение из `deps` или `git_repo.url` до `@version` (например, `github.com/mycompany/internal-protos` или `https://github.com/mycompany/internal-protos`). Это не Go module path из `go.mod`. +`package` должен точно совпадать со значением `package` в `.proto` файле, например `acme.weather.v1`. + +#### Переопределения для конкретного protobuf package + +Примените отдельные опции к файлам из конкретного protobuf package: + +```yaml +generate: + managed: + enabled: true + override: + - file_option: go_package_prefix + value: github.com/mycompany/myproject/gen/go + - file_option: go_package + package: acme.weather.v1 + value: github.com/mycompany/myproject/gen/go/acme/weather/v1 +``` + #### Отключение для внешних зависимостей Отключите managed mode для внешних зависимостей, у которых уже установлены опции: diff --git a/docs/dist/search/index.en.json b/docs/dist/search/index.en.json index 853e288a..c3308632 100644 --- a/docs/dist/search/index.en.json +++ b/docs/dist/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, required) - Output directory for generated files opts (mapstring, optional) - Plugin-specific options; each key can be a single value or an array of 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 ✅ - 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, path, or field. Without module or path, an override applies to all files in the generation request, including","content":"How It Works **Overrides** allow you to set specific values for options, with support for filtering by module, path, or field. Without module 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::supported-file-options::92","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::93","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::94","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::95","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::96","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::97","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::98","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::99","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::100","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::101","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::102","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::disabling-for-external-dependencies::103","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::104","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::105","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::106","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::107","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::108","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::109","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::110","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::111","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::112","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::113","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::114","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::115","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::116","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::117","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::118","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::119","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::120","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::121","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::122","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::123","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::124","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::125","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::126","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::127","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::128","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::129","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::130","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::131","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::132","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::133","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::134","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::135","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::136","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::137","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::138","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::139","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::140","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::141","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::142","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::143","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::144","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::145","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::146","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::147","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::148","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::149","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::150","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::151","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::152","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::153","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::154","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::155","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::156","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::157","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::158","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::159","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::160","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::161","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::162","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::163","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::164","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::165","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::166","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::167","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::168","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::169","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::170","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::171","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::172","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::173","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::174","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::175","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::176","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::177","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::178","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::179","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::180","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::181","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::182","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::183","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::184","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::185","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-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, required) - Output directory for generated files opts (mapstring, optional) - Plugin-specific options; each key can be a single value or an array of 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 ✅ - 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/docs/dist/search/index.ru.json b/docs/dist/search/index.ru.json index 6434c044..b7eac7ec 100644 --- a/docs/dist/search/index.ru.json +++ b/docs/dist/search/index.ru.json @@ -1 +1 @@ -[{"id":"api-service/overview::top::0","title":"Обзор API Service","path":"/docs/guide/api-service/overview","headings":[],"excerpt":"**Централизованный сервис выполнения protobuf‑плагинов для консистентной изолированной генерации кода**","content":"**Централизованный сервис выполнения protobuf‑плагинов для консистентной изолированной генерации кода**"},{"id":"api-service/overview::top::1","title":"Обзор API Service","path":"/docs/guide/api-service/overview","headings":[],"excerpt":"EasyP API Service устраняет хаос управления плагинами, предоставляя централизованный запуск protobuf/gRPC плагинов в изолированных Docker‑контейнерах. Он даёт единую платформу, позволяющую командам стандартизировать проц","content":"EasyP API Service устраняет хаос управления плагинами, предоставляя централизованный запуск protobuf/gRPC плагинов в изолированных Docker‑контейнерах. Он даёт единую платформу, позволяющую командам стандартизировать процесс генерации кода без операционных затрат на установку и поддержку плагинов на машинах разработчиков."},{"id":"api-service/overview::easyp-api-service::2","title":"Обзор API Service","section":"Зачем нужен EasyP API Service?","path":"/docs/guide/api-service/overview#easyp-api-service","headings":["Зачем нужен EasyP API Service?"],"excerpt":"Зачем нужен EasyP API Service?","content":"Зачем нужен EasyP API Service?"},{"id":"api-service/overview::top::3","title":"Обзор API Service","section":"Проблема","path":"/docs/guide/api-service/overview","headings":["Проблема"],"excerpt":"Проблема Управление генерацией protobuf/gRPC кода в командах порождает существенную операционную сложность:","content":"Проблема Управление генерацией protobuf/gRPC кода в командах порождает существенную операционную сложность:"},{"id":"api-service/overview::top::4","title":"Обзор API Service","section":"Несогласованность версий","path":"/docs/guide/api-service/overview","headings":["Несогласованность версий"],"excerpt":"Несогласованность версий Разработчики локально используют разные версии плагинов → расхождения в генерированном коде и падения сборки Синдром «у меня работает» при различиях окружений Требуется ручная координация, чтобы ","content":"Несогласованность версий Разработчики локально используют разные версии плагинов → расхождения в генерированном коде и падения сборки Синдром «у меня работает» при различиях окружений Требуется ручная координация, чтобы вся команда была синхронизирована по версиям"},{"id":"api-service/overview::top::5","title":"Обзор API Service","section":"Операционные накладные расходы","path":"/docs/guide/api-service/overview","headings":["Операционные накладные расходы"],"excerpt":"Операционные накладные расходы DevOps тратят время на установку и обновление плагинов на рабочих станциях Новый разработчик — ручная настройка правильных версий Обновление плагинов требует коммуникации с каждым отдельно ","content":"Операционные накладные расходы DevOps тратят время на установку и обновление плагинов на рабочих станциях Новый разработчик — ручная настройка правильных версий Обновление плагинов требует коммуникации с каждым отдельно Нет централизованного контроля утверждённых версий"},{"id":"api-service/overview::top::6","title":"Обзор API Service","section":"Риски безопасности и комплаенса","path":"/docs/guide/api-service/overview","headings":["Риски безопасности и комплаенса"],"excerpt":"Риски безопасности и комплаенса Плагины ставятся из разных источников без валидации Нет аудита: какой плагин для какого билда использовался Сложно применять политики безопасности к инструментам генерации","content":"Риски безопасности и комплаенса Плагины ставятся из разных источников без валидации Нет аудита: какой плагин для какого билда использовался Сложно применять политики безопасности к инструментам генерации"},{"id":"api-service/overview::top::7","title":"Обзор API Service","section":"Решение: централизованный запуск плагинов","path":"/docs/guide/api-service/overview","headings":["Решение: централизованный запуск плагинов"],"excerpt":"Решение: централизованный запуск плагинов EasyP API Service решает эти проблемы за счёт централизованного управления:","content":"Решение: централизованный запуск плагинов EasyP API Service решает эти проблемы за счёт централизованного управления:"},{"id":"api-service/overview::top::8","title":"Обзор API Service","section":"Решение: централизованный запуск плагинов","path":"/docs/guide/api-service/overview","headings":["Решение: централизованный запуск плагинов"],"excerpt":"Решение: централизованный запуск плагинов Проблема Решение ---------- --------- **Контроль версий** Мгновенное распространение новых версий через Docker‑образы **Операции** Команда эксплуатации управляет конфигурациями б","content":"Решение: централизованный запуск плагинов Проблема Решение ---------- --------- **Контроль версий** Мгновенное распространение новых версий через Docker‑образы **Операции** Команда эксплуатации управляет конфигурациями без доступа на машины разработчиков **Безопасность** Все плагины запускаются в изолированных контейнерах с ограничениями ресурсов **Консистентность** Единая среда выполнения вне зависимости от локальной установки **Опыт разработчика** Не нужно устанавливать и сопровождать плагины локально"},{"id":"api-service/overview::top::9","title":"Обзор API Service","section":"Архитектура","path":"/docs/guide/api-service/overview","headings":["Архитектура"],"excerpt":"Архитектура Архитектура сервиса упрощена и сфокусирована на надёжном выполнении плагинов:","content":"Архитектура Архитектура сервиса упрощена и сфокусирована на надёжном выполнении плагинов:"},{"id":"api-service/overview::api-layer::10","title":"Обзор API Service","section":"API Layer","path":"/docs/guide/api-service/overview#api-layer","headings":["API Layer"],"excerpt":"API Layer **gRPC Server** — основной API для запросов генерации Каждый запуск плагина — отдельный gRPC‑запрос Получает CodeGeneratorRequest от CLI","content":"API Layer **gRPC Server** — основной API для запросов генерации Каждый запуск плагина — отдельный gRPC‑запрос Получает CodeGeneratorRequest от CLI"},{"id":"api-service/overview::execution-engine::11","title":"Обзор API Service","section":"Execution Engine","path":"/docs/guide/api-service/overview#execution-engine","headings":["Execution Engine"],"excerpt":"Execution Engine **Docker Runtime** — изолированный запуск плагинов Подтягивает образы из публичных реестров (Docker Hub и т.п.) Применяет лимиты CPU/памяти на плагин","content":"Execution Engine **Docker Runtime** — изолированный запуск плагинов Подтягивает образы из публичных реестров (Docker Hub и т.п.) Применяет лимиты CPU/памяти на плагин"},{"id":"api-service/overview::storage-layer::12","title":"Обзор API Service","section":"Storage Layer","path":"/docs/guide/api-service/overview#storage-layer","headings":["Storage Layer"],"excerpt":"Storage Layer **PostgreSQL** хранит параметры выполнения: - Ограничения ресурсов (CPU, память) - Конфигурацию и метаданные плагинов - Логи выполнения (аудит) - _Примечание: функциональность хранения будет расширяться_","content":"Storage Layer **PostgreSQL** хранит параметры выполнения: - Ограничения ресурсов (CPU, память) - Конфигурацию и метаданные плагинов - Логи выполнения (аудит) - _Примечание: функциональность хранения будет расширяться_"},{"id":"api-service/overview::monitoring::13","title":"Обзор API Service","section":"Monitoring","path":"/docs/guide/api-service/overview#monitoring","headings":["Monitoring"],"excerpt":"Monitoring **Prometheus** — сбор метрик Отслеживает время выполнения, успешность, использование ресурсов","content":"Monitoring **Prometheus** — сбор метрик Отслеживает время выполнения, успешность, использование ресурсов"},{"id":"api-service/overview::easyp-cli::14","title":"Обзор API Service","section":"Локальное выполнение (EasyP CLI)","path":"/docs/guide/api-service/overview#easyp-cli","headings":["Локальное выполнение (EasyP CLI)"],"excerpt":"Локальное выполнение (EasyP CLI) При локальном запуске CLI поддерживает: **Installed plugins**: системно установленные protoc плагины **WASM plugins**: лёгкие WebAssembly плагины","content":"Локальное выполнение (EasyP CLI) При локальном запуске CLI поддерживает: **Installed plugins**: системно установленные protoc плагины **WASM plugins**: лёгкие WebAssembly плагины"},{"id":"api-service/overview::api-service::15","title":"Обзор API Service","section":"Удалённое выполнение (API Service)","path":"/docs/guide/api-service/overview#api-service","headings":["Удалённое выполнение (API Service)"],"excerpt":"Удалённое выполнение (API Service) При работе через сервис: **Только Docker**: плагины запускаются как контейнеры **Центральный контроль**: операционная команда управляет доступными версиями **Консистентная среда**: один","content":"Удалённое выполнение (API Service) При работе через сервис: **Только Docker**: плагины запускаются как контейнеры **Центральный контроль**: операционная команда управляет доступными версиями **Консистентная среда**: одинаковое окружение для всех разработчиков"},{"id":"api-service/overview::top::16","title":"Обзор API Service","section":"Шаги выполнения","path":"/docs/guide/api-service/overview","headings":["Шаги выполнения"],"excerpt":"Шаги выполнения **CLI Parsing**: CLI парсит локальные .proto файлы **Request Sending**: Отправляет CodeGeneratorRequest в API Service (по одному на плагин) **Parameter Lookup**: Сервис получает параметры запуска из Postg","content":"Шаги выполнения **CLI Parsing**: CLI парсит локальные .proto файлы **Request Sending**: Отправляет CodeGeneratorRequest в API Service (по одному на плагин) **Parameter Lookup**: Сервис получает параметры запуска из PostgreSQL **Docker Execution**: Запускает плагин в изолированном контейнере **Metrics Recording**: Записывает метрики после завершения **Response**: Возвращает сгенерированный код обратно в CLI"},{"id":"api-service/overview::top::17","title":"Обзор API Service","section":"Ключевые возможности","path":"/docs/guide/api-service/overview","headings":["Ключевые возможности"],"excerpt":"Ключевые возможности Возможность Описание ------------- ---------- **🐳 Изоляция плагинов** Каждый плагин в отдельном безопасном контейнере **⚙️ Контроль ресурсов** Лимиты CPU и памяти на уровне контейнера **📊 Метрики &","content":"Ключевые возможности Возможность Описание ------------- ---------- **🐳 Изоляция плагинов** Каждый плагин в отдельном безопасном контейнере **⚙️ Контроль ресурсов** Лимиты CPU и памяти на уровне контейнера **📊 Метрики & мониторинг** Полный набор Prometheus метрик **🔄 Управление версиями** Централизованно через Docker‑образы **⚡ Простой протокол** Стандарт CodeGeneratorRequest/Response **🔒 Безопасность прежде всего** Изоляция + ограниченные ресурсы"},{"id":"api-service/overview::top::18","title":"Обзор API Service","section":"Конфигурация","path":"/docs/guide/api-service/overview","headings":["Конфигурация"],"excerpt":"Конфигурация Сервис настраивается через переменные окружения.","content":"Конфигурация Сервис настраивается через переменные окружения."},{"id":"api-service/overview::top::19","title":"Обзор API Service","section":"Хранение параметров плагинов","path":"/docs/guide/api-service/overview","headings":["Хранение параметров плагинов"],"excerpt":"Хранение параметров плагинов PostgreSQL хранит параметры выполнения для каждого плагина:","content":"Хранение параметров плагинов PostgreSQL хранит параметры выполнения для каждого плагина:"},{"id":"api-service/overview::top::20","title":"Обзор API Service","section":"Хранение параметров плагинов","path":"/docs/guide/api-service/overview","headings":["Хранение параметров плагинов"],"excerpt":"Хранение параметров плагинов ::: tip Схема хранения будет расширена — аудит логов, аналитика использования, кеширование плагинов. :::","content":"Хранение параметров плагинов ::: tip Схема хранения будет расширена — аудит логов, аналитика использования, кеширование плагинов. :::"},{"id":"api-service/overview::easyp-cli::21","title":"Обзор API Service","section":"Интеграция с EasyP CLI","path":"/docs/guide/api-service/overview#easyp-cli","headings":["Интеграция с EasyP CLI"],"excerpt":"Интеграция с EasyP CLI Пример easyp.yaml для удалённого запуска:","content":"Интеграция с EasyP CLI Пример easyp.yaml для удалённого запуска:"},{"id":"api-service/overview::easyp-cli::22","title":"Обзор API Service","section":"Интеграция с EasyP CLI","path":"/docs/guide/api-service/overview#easyp-cli","headings":["Интеграция с EasyP CLI"],"excerpt":"Интеграция с EasyP CLI Запуск генерации:","content":"Интеграция с EasyP CLI Запуск генерации:"},{"id":"api-service/overview::easyp-cli::23","title":"Обзор API Service","section":"Интеграция с EasyP CLI","path":"/docs/guide/api-service/overview#easyp-cli","headings":["Интеграция с EasyP CLI"],"excerpt":"Интеграция с EasyP CLI CLI: Парсит protobuf‑файлы Отправляет отдельные запросы в сервис для каждого плагина Получает ответы с кодом Записывает файлы в указанные директории","content":"Интеграция с EasyP CLI CLI: Парсит protobuf‑файлы Отправляет отдельные запросы в сервис для каждого плагина Получает ответы с кодом Записывает файлы в указанные директории"},{"id":"api-service/overview::top::24","title":"Обзор API Service","section":"Доступные метрики","path":"/docs/guide/api-service/overview","headings":["Доступные метрики"],"excerpt":"Доступные метрики Метрики Prometheus:","content":"Доступные метрики Метрики Prometheus:"},{"id":"api-service/overview::top::25","title":"Обзор API Service","section":"Доступные метрики","path":"/docs/guide/api-service/overview","headings":["Доступные метрики"],"excerpt":"Доступные метрики Метрика Описание --------- ---------- easyp_api_service_api_grpc_server_handled_total Общее число gRPC запросов по статусам easyp_api_service_api_grpc_server_handling_seconds Гистограмма задержек gRPC e","content":"Доступные метрики Метрика Описание --------- ---------- easyp_api_service_api_grpc_server_handled_total Общее число gRPC запросов по статусам easyp_api_service_api_grpc_server_handling_seconds Гистограмма задержек gRPC easyp_api_service_generated_plugin_code_total Выполнения плагинов по имени easyp_api_service_repo_call_duration_seconds Латентность запросов к БД easyp_api_service_repo_errors_total Количество ошибок доступа к БД easyp_api_service_standard_panics_total Число восстановленных паник"},{"id":"api-service/overview::top::26","title":"Обзор API Service","section":"Характеристики производительности","path":"/docs/guide/api-service/overview","headings":["Характеристики производительности"],"excerpt":"Характеристики производительности Показатель Типичное значение Примечания ----------- ------------------- ----------- **Cold Start** 2–5 сек Первая загрузка образа **Warm Start** 100–500 мс Образ закеширован **Throughput","content":"Характеристики производительности Показатель Типичное значение Примечания ----------- ------------------- ----------- **Cold Start** 2–5 сек Первая загрузка образа **Warm Start** 100–500 мс Образ закеширован **Throughput** 20–50 одновременных Зависит от ресурсов **Memory Usage** 50–200 MB На выполнение одного плагина"},{"id":"api-service/overview::top::27","title":"Обзор API Service","section":"Изоляция контейнеров","path":"/docs/guide/api-service/overview","headings":["Изоляция контейнеров"],"excerpt":"Изоляция контейнеров Каждый плагин в отдельном эфемерном контейнере Нет сетевого доступа в процессе выполнения Лимиты CPU/памяти через Docker Контейнер удаляется после завершения","content":"Изоляция контейнеров Каждый плагин в отдельном эфемерном контейнере Нет сетевого доступа в процессе выполнения Лимиты CPU/памяти через Docker Контейнер удаляется после завершения"},{"id":"api-service/overview::api::28","title":"Обзор API Service","section":"Безопасность API","path":"/docs/guide/api-service/overview#api","headings":["Безопасность API"],"excerpt":"Безопасность API gRPC транспорт Поддержка токенов аутентификации (в продакшн окружениях) Валидация входных данных Аудитные логи в PostgreSQL","content":"Безопасность API gRPC транспорт Поддержка токенов аутентификации (в продакшн окружениях) Валидация входных данных Аудитные логи в PostgreSQL"},{"id":"api-service/overview::top::29","title":"Обзор API Service","section":"Масштабирование","path":"/docs/guide/api-service/overview","headings":["Масштабирование"],"excerpt":"Масштабирование **Горизонтальное**: несколько инстансов за балансировщиком **Ресурсы**: настройка лимитов для тяжёлых плагинов **База данных**: репликация PostgreSQL для отказоустойчивости","content":"Масштабирование **Горизонтальное**: несколько инстансов за балансировщиком **Ресурсы**: настройка лимитов для тяжёлых плагинов **База данных**: репликация PostgreSQL для отказоустойчивости"},{"id":"api-service/overview::top::30","title":"Обзор API Service","section":"Мониторинг","path":"/docs/guide/api-service/overview","headings":["Мониторинг"],"excerpt":"Мониторинг **Метрики**: Prometheus **Алертинг**: оповещения на высокие ошибки/латентность **Логи**: структурированные для аудита и отладки","content":"Мониторинг **Метрики**: Prometheus **Алертинг**: оповещения на высокие ошибки/латентность **Логи**: структурированные для аудита и отладки"},{"id":"api-service/overview::top::31","title":"Обзор API Service","section":"План развития","path":"/docs/guide/api-service/overview","headings":["План развития"],"excerpt":"План развития Запланировано: Кеширование результатов генерации Расширенный аудит и аналитика использования Поддержка приватных реестров плагинов Более умное распределение ресурсов","content":"План развития Запланировано: Кеширование результатов генерации Расширенный аудит и аналитика использования Поддержка приватных реестров плагинов Более умное распределение ресурсов"},{"id":"api-service/overview::top::32","title":"Обзор API Service","section":"Сообщество и поддержка","path":"/docs/guide/api-service/overview","headings":["Сообщество и поддержка"],"excerpt":"Сообщество и поддержка **💬 Telegram чат** — обсуждения **🐛 GitHub Issues** — баги и запросы фич **📖 Документация** — полный набор материалов","content":"Сообщество и поддержка **💬 Telegram чат** — обсуждения **🐛 GitHub Issues** — баги и запросы фич **📖 Документация** — полный набор материалов"},{"id":"api-service/overview::top::33","title":"Обзор API Service","section":"Сообщество и поддержка","path":"/docs/guide/api-service/overview","headings":["Сообщество и поддержка"],"excerpt":"Сообщество и поддержка *Упростите свои protobuf‑воркфлоу с централизованным управлением выполнением плагинов.*","content":"Сообщество и поддержка *Упростите свои protobuf‑воркфлоу с централизованным управлением выполнением плагинов.*"},{"id":"ci-cd/github-actions::top::0","title":"GitHub Actions","path":"/docs/guide/ci-cd/github-actions","headings":[],"excerpt":"Полное руководство по интеграции EasyP в конвейеры GitHub Actions для линтинга, проверки несовместимых изменений, генерации кода и автоматизации релизов.","content":"Полное руководство по интеграции EasyP в конвейеры GitHub Actions для линтинга, проверки несовместимых изменений, генерации кода и автоматизации релизов."},{"id":"ci-cd/github-actions::easyp-ci::1","title":"GitHub Actions","section":"Зачем использовать EasyP в CI","path":"/docs/guide/ci-cd/github-actions#easyp-ci","headings":["Зачем использовать EasyP в CI"],"excerpt":"Зачем использовать EasyP в CI Встраивание EasyP в GitHub Actions даёт: Единообразие правил линтинга и генерации между разработчиками. Автоматическое выявление несовместимых изменений (breaking changes) до мержа. Гарантию","content":"Зачем использовать EasyP в CI Встраивание EasyP в GitHub Actions даёт: Единообразие правил линтинга и генерации между разработчиками. Автоматическое выявление несовместимых изменений (breaking changes) до мержа. Гарантию, что сгенерированный код не «устарел» относительно .proto. Возможность централизованной проверки зависимостей и версии конфигурации."},{"id":"ci-cd/github-actions::top::2","title":"GitHub Actions","section":"Предварительные требования","path":"/docs/guide/ci-cd/github-actions","headings":["Предварительные требования"],"excerpt":"Предварительные требования Репозиторий содержит файл конфигурации easyp.yaml (или находится в корне, если запускается без --cfg). Установлены / определены зависимости в секции deps (если нужны внешние импорты). Для прива","content":"Предварительные требования Репозиторий содержит файл конфигурации easyp.yaml (или находится в корне, если запускается без --cfg). Установлены / определены зависимости в секции deps (если нужны внешние импорты). Для приватных Git-репозиториев настроен доступ (SSH key / deploy key / токен). В workflow есть шаги по установке Go (если EasyP поставляется через go install) или заранее подготовленный бинарь."},{"id":"ci-cd/github-actions::top::3","title":"GitHub Actions","section":"Базовый пример (быстрый старт)","path":"/docs/guide/ci-cd/github-actions","headings":["Базовый пример (быстрый старт)"],"excerpt":"Базовый пример (быстрый старт) Минимальный workflow для проверки линта и несовместимых изменений при открытия Pull Request:","content":"Базовый пример (быстрый старт) Минимальный workflow для проверки линта и несовместимых изменений при открытия Pull Request:"},{"id":"ci-cd/github-actions::top::4","title":"GitHub Actions","section":"Базовый пример (быстрый старт)","path":"/docs/guide/ci-cd/github-actions","headings":["Базовый пример (быстрый старт)"],"excerpt":"Базовый пример (быстрый старт) ```yaml name: easyp-ci","content":"Базовый пример (быстрый старт) ```yaml name: easyp-ci"},{"id":"ci-cd/github-actions::top::5","title":"GitHub Actions","section":"Базовый пример (быстрый старт)","path":"/docs/guide/ci-cd/github-actions","headings":["Базовый пример (быстрый старт)"],"excerpt":"Базовый пример (быстрый старт) on: pull_request: paths: - '**/*.proto' - 'easyp.yaml'","content":"Базовый пример (быстрый старт) on: pull_request: paths: - '**/*.proto' - 'easyp.yaml'"},{"id":"ci-cd/github-actions::top::6","title":"GitHub Actions","section":"Базовый пример (быстрый старт)","path":"/docs/guide/ci-cd/github-actions","headings":["Базовый пример (быстрый старт)"],"excerpt":"Базовый пример (быстрый старт) jobs: lint-and-breaking: runs-on: ubuntu-latest","content":"Базовый пример (быстрый старт) jobs: lint-and-breaking: runs-on: ubuntu-latest"},{"id":"ci-cd/github-actions::top::7","title":"GitHub Actions","section":"Базовый пример (быстрый старт)","path":"/docs/guide/ci-cd/github-actions","headings":["Базовый пример (быстрый старт)"],"excerpt":"Базовый пример (быстрый старт) steps: - name: Checkout uses: actions/checkout@v4","content":"Базовый пример (быстрый старт) steps: - name: Checkout uses: actions/checkout@v4"},{"id":"ci-cd/github-actions::top::8","title":"GitHub Actions","section":"Базовый пример (быстрый старт)","path":"/docs/guide/ci-cd/github-actions","headings":["Базовый пример (быстрый старт)"],"excerpt":"Базовый пример (быстрый старт) name: Setup Go uses: actions/setup-go@v5 with: go-version: '1.22'","content":"Базовый пример (быстрый старт) name: Setup Go uses: actions/setup-go@v5 with: go-version: '1.22'"},{"id":"ci-cd/github-actions::top::9","title":"GitHub Actions","section":"Базовый пример (быстрый старт)","path":"/docs/guide/ci-cd/github-actions","headings":["Базовый пример (быстрый старт)"],"excerpt":"Базовый пример (быстрый старт) name: Install EasyP run: go install github.com/easyp-tech/easyp/cmd/easyp@latest","content":"Базовый пример (быстрый старт) name: Install EasyP run: go install github.com/easyp-tech/easyp/cmd/easyp@latest"},{"id":"ci-cd/github-actions::top::10","title":"GitHub Actions","section":"Базовый пример (быстрый старт)","path":"/docs/guide/ci-cd/github-actions","headings":["Базовый пример (быстрый старт)"],"excerpt":"Базовый пример (быстрый старт) name: Verify EasyP version run: which easyp easyp version","content":"Базовый пример (быстрый старт) name: Verify EasyP version run: which easyp easyp version"},{"id":"ci-cd/github-actions::top::11","title":"GitHub Actions","section":"Базовый пример (быстрый старт)","path":"/docs/guide/ci-cd/github-actions","headings":["Базовый пример (быстрый старт)"],"excerpt":"Базовый пример (быстрый старт) name: Lint run: easyp lint","content":"Базовый пример (быстрый старт) name: Lint run: easyp lint"},{"id":"ci-cd/github-actions::top::12","title":"GitHub Actions","section":"Базовый пример (быстрый старт)","path":"/docs/guide/ci-cd/github-actions","headings":["Базовый пример (быстрый старт)"],"excerpt":"Базовый пример (быстрый старт) name: Breaking changes check (against main) run: easyp breaking --against git-ref=origin/main ```","content":"Базовый пример (быстрый старт) name: Breaking changes check (against main) run: easyp breaking --against git-ref=origin/main ```"},{"id":"ci-cd/github-actions::easyp::13","title":"GitHub Actions","section":"Установка EasyP","path":"/docs/guide/ci-cd/github-actions#easyp","headings":["Установка EasyP"],"excerpt":"Установка EasyP Варианты: Через go install (как в примере выше). Использование заранее собранного бинаря (артефакт релиза).","content":"Установка EasyP Варианты: Через go install (как в примере выше). Использование заранее собранного бинаря (артефакт релиза)."},{"id":"ci-cd/github-actions::top::14","title":"GitHub Actions","section":"Кэширование","path":"/docs/guide/ci-cd/github-actions","headings":["Кэширование"],"excerpt":"Кэширование Для ускорения повторных сборок можно кэшировать: Go модульный кеш (если используете генерацию с плагинами Go). Внешние зависимые Git-клонирования (папки vendor или содержимое deps при использовании easyp mod ","content":"Кэширование Для ускорения повторных сборок можно кэшировать: Go модульный кеш (если используете генерацию с плагинами Go). Внешние зависимые Git-клонирования (папки vendor или содержимое deps при использовании easyp mod download / easyp mod update). Сгенерированный код (если он тяжёлый, но чаще генерируется заново)."},{"id":"ci-cd/github-actions::top::15","title":"GitHub Actions","section":"Кэширование","path":"/docs/guide/ci-cd/github-actions","headings":["Кэширование"],"excerpt":"Кэширование Пример кэширования Go:","content":"Кэширование Пример кэширования Go:"},{"id":"ci-cd/github-actions::top::16","title":"GitHub Actions","section":"Кэширование","path":"/docs/guide/ci-cd/github-actions","headings":["Кэширование"],"excerpt":"Кэширование Пример кэширования каталога зависимостей EasyP (если вы используете локальный vendor-подход):","content":"Кэширование Пример кэширования каталога зависимостей EasyP (если вы используете локальный vendor-подход):"},{"id":"ci-cd/github-actions::top::17","title":"GitHub Actions","section":"Кэширование","path":"/docs/guide/ci-cd/github-actions","headings":["Кэширование"],"excerpt":"Кэширование (Создайте .easyp/deps как целевой каталог, если ваша стратегия скачивания такова.)","content":"Кэширование (Создайте .easyp/deps как целевой каталог, если ваша стратегия скачивания такова.)"},{"id":"ci-cd/github-actions::top::18","title":"GitHub Actions","section":"Линтинг","path":"/docs/guide/ci-cd/github-actions","headings":["Линтинг"],"excerpt":"Линтинг Рекомендуется: В PR: всегда запускать. На main: можно запускать для верификации перед релизом.","content":"Линтинг Рекомендуется: В PR: всегда запускать. На main: можно запускать для верификации перед релизом."},{"id":"ci-cd/github-actions::top::19","title":"GitHub Actions","section":"Линтинг","path":"/docs/guide/ci-cd/github-actions","headings":["Линтинг"],"excerpt":"Линтинг Расширенный пример с выводом подробностей и игнорированием комментариев (если включено в конфиг):","content":"Линтинг Расширенный пример с выводом подробностей и игнорированием комментариев (если включено в конфиг):"},{"id":"ci-cd/github-actions::breaking-changes::20","title":"GitHub Actions","section":"Проверка несовместимых изменений (Breaking Changes)","path":"/docs/guide/ci-cd/github-actions#breaking-changes","headings":["Проверка несовместимых изменений (Breaking Changes)"],"excerpt":"Проверка несовместимых изменений (Breaking Changes) EasyP может сравнивать текущее состояние против ветки / коммита / тега.","content":"Проверка несовместимых изменений (Breaking Changes) EasyP может сравнивать текущее состояние против ветки / коммита / тега."},{"id":"ci-cd/github-actions::breaking-changes::21","title":"GitHub Actions","section":"Проверка несовместимых изменений (Breaking Changes)","path":"/docs/guide/ci-cd/github-actions#breaking-changes","headings":["Проверка несовместимых изменений (Breaking Changes)"],"excerpt":"Проверка несовместимых изменений (Breaking Changes) Примеры: ```bash Сравнить против origin/main easyp breaking --against git-ref=origin/main","content":"Проверка несовместимых изменений (Breaking Changes) Примеры: ```bash Сравнить против origin/main easyp breaking --against git-ref=origin/main"},{"id":"ci-cd/github-actions::breaking-changes::22","title":"GitHub Actions","section":"Проверка несовместимых изменений (Breaking Changes)","path":"/docs/guide/ci-cd/github-actions#breaking-changes","headings":["Проверка несовместимых изменений (Breaking Changes)"],"excerpt":"Проверка несовместимых изменений (Breaking Changes) Сравнить против тега релиза easyp breaking --against git-ref=v1.5.2","content":"Проверка несовместимых изменений (Breaking Changes) Сравнить против тега релиза easyp breaking --against git-ref=v1.5.2"},{"id":"ci-cd/github-actions::breaking-changes::23","title":"GitHub Actions","section":"Проверка несовместимых изменений (Breaking Changes)","path":"/docs/guide/ci-cd/github-actions#breaking-changes","headings":["Проверка несовместимых изменений (Breaking Changes)"],"excerpt":"Проверка несовместимых изменений (Breaking Changes) Игнорировать определённые правила (если у вас настроено в easyp.yaml) easyp breaking ```","content":"Проверка несовместимых изменений (Breaking Changes) Игнорировать определённые правила (если у вас настроено в easyp.yaml) easyp breaking ```"},{"id":"ci-cd/github-actions::breaking-changes::24","title":"GitHub Actions","section":"Проверка несовместимых изменений (Breaking Changes)","path":"/docs/guide/ci-cd/github-actions#breaking-changes","headings":["Проверка несовместимых изменений (Breaking Changes)"],"excerpt":"Проверка несовместимых изменений (Breaking Changes) Workflow шаг:","content":"Проверка несовместимых изменений (Breaking Changes) Workflow шаг:"},{"id":"ci-cd/github-actions::breaking-changes::25","title":"GitHub Actions","section":"Проверка несовместимых изменений (Breaking Changes)","path":"/docs/guide/ci-cd/github-actions#breaking-changes","headings":["Проверка несовместимых изменений (Breaking Changes)"],"excerpt":"Проверка несовместимых изменений (Breaking Changes)","content":"Проверка несовместимых изменений (Breaking Changes)"},{"id":"ci-cd/github-actions::breaking-changes::26","title":"GitHub Actions","section":"Проверка несовместимых изменений (Breaking Changes)","path":"/docs/guide/ci-cd/github-actions#breaking-changes","headings":["Проверка несовместимых изменений (Breaking Changes)"],"excerpt":"Проверка несовместимых изменений (Breaking Changes) Если нужно «мягко» пропустить (например, выводить предупреждения, но не падать билд):","content":"Проверка несовместимых изменений (Breaking Changes) Если нужно «мягко» пропустить (например, выводить предупреждения, но не падать билд):"},{"id":"ci-cd/github-actions::breaking-changes::27","title":"GitHub Actions","section":"Проверка несовместимых изменений (Breaking Changes)","path":"/docs/guide/ci-cd/github-actions#breaking-changes","headings":["Проверка несовместимых изменений (Breaking Changes)"],"excerpt":"Проверка несовместимых изменений (Breaking Changes)","content":"Проверка несовместимых изменений (Breaking Changes)"},{"id":"ci-cd/github-actions::top::28","title":"GitHub Actions","section":"Генерация кода","path":"/docs/guide/ci-cd/github-actions","headings":["Генерация кода"],"excerpt":"Генерация кода Обычно для генерации:","content":"Генерация кода Обычно для генерации:"},{"id":"ci-cd/github-actions::top::29","title":"GitHub Actions","section":"Генерация кода","path":"/docs/guide/ci-cd/github-actions","headings":["Генерация кода"],"excerpt":"Генерация кода Если нужно явно указать конфиг:","content":"Генерация кода Если нужно явно указать конфиг:"},{"id":"ci-cd/github-actions::top::30","title":"GitHub Actions","section":"Генерация кода","path":"/docs/guide/ci-cd/github-actions","headings":["Генерация кода"],"excerpt":"Генерация кода Можно добавить проверку «не осталось ли не закоммиченных изменений» (гарантия, что сгенерированный код актуален):","content":"Генерация кода Можно добавить проверку «не осталось ли не закоммиченных изменений» (гарантия, что сгенерированный код актуален):"},{"id":"ci-cd/github-actions::matrix-strategy::31","title":"GitHub Actions","section":"Матрица (Matrix strategy)","path":"/docs/guide/ci-cd/github-actions#matrix-strategy","headings":["Матрица (Matrix strategy)"],"excerpt":"Матрица (Matrix strategy) Если у вас несколько вариантов конфигураций или разных языков генерации (через плагины), можно использовать matrix:","content":"Матрица (Matrix strategy) Если у вас несколько вариантов конфигураций или разных языков генерации (через плагины), можно использовать matrix:"},{"id":"ci-cd/github-actions::matrix-strategy::32","title":"GitHub Actions","section":"Матрица (Matrix strategy)","path":"/docs/guide/ci-cd/github-actions#matrix-strategy","headings":["Матрица (Matrix strategy)"],"excerpt":"Матрица (Matrix strategy) ```yaml jobs: generate: runs-on: ubuntu-latest strategy: fail-fast: false matrix: lang: [go, python] steps: - uses: actions/checkout@v4","content":"Матрица (Matrix strategy) ```yaml jobs: generate: runs-on: ubuntu-latest strategy: fail-fast: false matrix: lang: [go, python] steps: - uses: actions/checkout@v4"},{"id":"ci-cd/github-actions::matrix-strategy::33","title":"GitHub Actions","section":"Матрица (Matrix strategy)","path":"/docs/guide/ci-cd/github-actions#matrix-strategy","headings":["Матрица (Matrix strategy)"],"excerpt":"Матрица (Matrix strategy) name: Setup Go (only for go) if: matrix.lang == 'go' uses: actions/setup-go@v5 with: go-version: '1.22'","content":"Матрица (Matrix strategy) name: Setup Go (only for go) if: matrix.lang == 'go' uses: actions/setup-go@v5 with: go-version: '1.22'"},{"id":"ci-cd/github-actions::matrix-strategy::34","title":"GitHub Actions","section":"Матрица (Matrix strategy)","path":"/docs/guide/ci-cd/github-actions#matrix-strategy","headings":["Матрица (Matrix strategy)"],"excerpt":"Матрица (Matrix strategy) name: Install EasyP run: go install github.com/easyp-tech/easyp/cmd/easyp@latest","content":"Матрица (Matrix strategy) name: Install EasyP run: go install github.com/easyp-tech/easyp/cmd/easyp@latest"},{"id":"ci-cd/github-actions::matrix-strategy::35","title":"GitHub Actions","section":"Матрица (Matrix strategy)","path":"/docs/guide/ci-cd/github-actions#matrix-strategy","headings":["Матрица (Matrix strategy)"],"excerpt":"Матрица (Matrix strategy) name: Generate run: if [ \"${{ matrix.lang }}\" = \"go\" ]; then easyp generate elif [ \"${{ matrix.lang }}\" = \"python\" ]; then easyp generate --plugin python fi ```","content":"Матрица (Matrix strategy) name: Generate run: if [ \"${{ matrix.lang }}\" = \"go\" ]; then easyp generate elif [ \"${{ matrix.lang }}\" = \"python\" ]; then easyp generate --plugin python fi ```"},{"id":"ci-cd/github-actions::deps::36","title":"GitHub Actions","section":"Работа с приватными репозиториями (deps)","path":"/docs/guide/ci-cd/github-actions#deps","headings":["Работа с приватными репозиториями (deps)"],"excerpt":"Работа с приватными репозиториями (deps) Если вы указываете приватные Git-пакеты в секции deps:","content":"Работа с приватными репозиториями (deps) Если вы указываете приватные Git-пакеты в секции deps:"},{"id":"ci-cd/github-actions::deps::37","title":"GitHub Actions","section":"Работа с приватными репозиториями (deps)","path":"/docs/guide/ci-cd/github-actions#deps","headings":["Работа с приватными репозиториями (deps)"],"excerpt":"Работа с приватными репозиториями (deps) Настройте deploy key или используйте GIT_SSH_COMMAND с токеном. Добавьте known_hosts (либо установите StrictHostKeyChecking=no для внутренних систем, но осознанно).","content":"Работа с приватными репозиториями (deps) Настройте deploy key или используйте GIT_SSH_COMMAND с токеном. Добавьте known_hosts (либо установите StrictHostKeyChecking=no для внутренних систем, но осознанно)."},{"id":"ci-cd/github-actions::deps::38","title":"GitHub Actions","section":"Работа с приватными репозиториями (deps)","path":"/docs/guide/ci-cd/github-actions#deps","headings":["Работа с приватными репозиториями (deps)"],"excerpt":"Работа с приватными репозиториями (deps) Пример:","content":"Работа с приватными репозиториями (deps) Пример:"},{"id":"ci-cd/github-actions::deps::39","title":"GitHub Actions","section":"Работа с приватными репозиториями (deps)","path":"/docs/guide/ci-cd/github-actions#deps","headings":["Работа с приватными репозиториями (deps)"],"excerpt":"Работа с приватными репозиториями (deps) ```yaml name: Prepare SSH run: mkdir -p ~/.ssh echo \"${{ secrets.DEPLOY_KEY }}\" > ~/.ssh/id_rsa chmod 600 ~/.ssh/id_rsa ssh-keyscan github.com >> ~/.ssh/known_hosts","content":"Работа с приватными репозиториями (deps) ```yaml name: Prepare SSH run: mkdir -p ~/.ssh echo \"${{ secrets.DEPLOY_KEY }}\" > ~/.ssh/id_rsa chmod 600 ~/.ssh/id_rsa ssh-keyscan github.com >> ~/.ssh/known_hosts"},{"id":"ci-cd/github-actions::deps::40","title":"GitHub Actions","section":"Работа с приватными репозиториями (deps)","path":"/docs/guide/ci-cd/github-actions#deps","headings":["Работа с приватными репозиториями (deps)"],"excerpt":"Работа с приватными репозиториями (deps) name: Update deps run: easyp mod update ```","content":"Работа с приватными репозиториями (deps) name: Update deps run: easyp mod update ```"},{"id":"ci-cd/github-actions::top::41","title":"GitHub Actions","section":"Оптимизация времени сборки","path":"/docs/guide/ci-cd/github-actions","headings":["Оптимизация времени сборки"],"excerpt":"Оптимизация времени сборки Используйте кэш для Go / deps. Запускайте линт/брейкинг только если изменились .proto или easyp.yaml (paths фильтр). Разделяйте workflow: быстрый линт в PR, тяжелая генерация в push на main. Вы","content":"Оптимизация времени сборки Используйте кэш для Go / deps. Запускайте линт/брейкинг только если изменились .proto или easyp.yaml (paths фильтр). Разделяйте workflow: быстрый линт в PR, тяжелая генерация в push на main. Выносите генерацию OpenAPI / gRPC-Gateway в отдельный job (параллелизм)."},{"id":"ci-cd/github-actions::workflow::42","title":"GitHub Actions","section":"Продвинутый workflow (многостадийный)","path":"/docs/guide/ci-cd/github-actions#workflow","headings":["Продвинутый workflow (многостадийный)"],"excerpt":"Продвинутый workflow (многостадийный) ```yaml name: easyp-pipeline","content":"Продвинутый workflow (многостадийный) ```yaml name: easyp-pipeline"},{"id":"ci-cd/github-actions::workflow::43","title":"GitHub Actions","section":"Продвинутый workflow (многостадийный)","path":"/docs/guide/ci-cd/github-actions#workflow","headings":["Продвинутый workflow (многостадийный)"],"excerpt":"Продвинутый workflow (многостадийный) on: pull_request: paths: - '**/*.proto' - 'easyp.yaml' push: branches: - main","content":"Продвинутый workflow (многостадийный) on: pull_request: paths: - '**/*.proto' - 'easyp.yaml' push: branches: - main"},{"id":"ci-cd/github-actions::workflow::44","title":"GitHub Actions","section":"Продвинутый workflow (многостадийный)","path":"/docs/guide/ci-cd/github-actions#workflow","headings":["Продвинутый workflow (многостадийный)"],"excerpt":"Продвинутый workflow (многостадийный) jobs: validate: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4","content":"Продвинутый workflow (многостадийный) jobs: validate: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4"},{"id":"ci-cd/github-actions::workflow::45","title":"GitHub Actions","section":"Продвинутый workflow (многостадийный)","path":"/docs/guide/ci-cd/github-actions#workflow","headings":["Продвинутый workflow (многостадийный)"],"excerpt":"Продвинутый workflow (многостадийный) uses: actions/setup-go@v5 with: go-version: '1.22'","content":"Продвинутый workflow (многостадийный) uses: actions/setup-go@v5 with: go-version: '1.22'"},{"id":"ci-cd/github-actions::workflow::46","title":"GitHub Actions","section":"Продвинутый workflow (многостадийный)","path":"/docs/guide/ci-cd/github-actions#workflow","headings":["Продвинутый workflow (многостадийный)"],"excerpt":"Продвинутый workflow (многостадийный) name: Install EasyP run: go install github.com/easyp-tech/easyp/cmd/easyp@latest","content":"Продвинутый workflow (многостадийный) name: Install EasyP run: go install github.com/easyp-tech/easyp/cmd/easyp@latest"},{"id":"ci-cd/github-actions::workflow::47","title":"GitHub Actions","section":"Продвинутый workflow (многостадийный)","path":"/docs/guide/ci-cd/github-actions#workflow","headings":["Продвинутый workflow (многостадийный)"],"excerpt":"Продвинутый workflow (многостадийный) name: Lint run: easyp lint","content":"Продвинутый workflow (многостадийный) name: Lint run: easyp lint"},{"id":"ci-cd/github-actions::workflow::48","title":"GitHub Actions","section":"Продвинутый workflow (многостадийный)","path":"/docs/guide/ci-cd/github-actions#workflow","headings":["Продвинутый workflow (многостадийный)"],"excerpt":"Продвинутый workflow (многостадийный) name: Breaking check (against main) if: github.event_name == 'pull_request' run: easyp breaking --against git-ref=origin/main","content":"Продвинутый workflow (многостадийный) name: Breaking check (against main) if: github.event_name == 'pull_request' run: easyp breaking --against git-ref=origin/main"},{"id":"ci-cd/github-actions::workflow::49","title":"GitHub Actions","section":"Продвинутый workflow (многостадийный)","path":"/docs/guide/ci-cd/github-actions#workflow","headings":["Продвинутый workflow (многостадийный)"],"excerpt":"Продвинутый workflow (многостадийный) generate: needs: validate if: github.event_name == 'push' runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-go@v5 with: go-version: '1.22' - name: Insta","content":"Продвинутый workflow (многостадийный) generate: needs: validate if: github.event_name == 'push' runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-go@v5 with: go-version: '1.22' - name: Install EasyP run: go install github.com/easyp-tech/easyp/cmd/easyp@latest - name: Generate Code run: easyp generate - name: Check diffs run: if [ -n \"$(git status --porcelain)\" ]; then echo \"Generated files changed after generate step.\" git diff --name-only exit 1 fi ```"},{"id":"ci-cd/github-actions::top::50","title":"GitHub Actions","section":"Автоматизация релиза (пример)","path":"/docs/guide/ci-cd/github-actions","headings":["Автоматизация релиза (пример)"],"excerpt":"Автоматизация релиза (пример) Можно добавить workflow, который по тегу создаёт релиз и валидирует proto:","content":"Автоматизация релиза (пример) Можно добавить workflow, который по тегу создаёт релиз и валидирует proto:"},{"id":"ci-cd/github-actions::top::51","title":"GitHub Actions","section":"Автоматизация релиза (пример)","path":"/docs/guide/ci-cd/github-actions","headings":["Автоматизация релиза (пример)"],"excerpt":"Автоматизация релиза (пример) ```yaml name: release-verify","content":"Автоматизация релиза (пример) ```yaml name: release-verify"},{"id":"ci-cd/github-actions::top::52","title":"GitHub Actions","section":"Автоматизация релиза (пример)","path":"/docs/guide/ci-cd/github-actions","headings":["Автоматизация релиза (пример)"],"excerpt":"Автоматизация релиза (пример) on: push: tags: - 'v*.*.*'","content":"Автоматизация релиза (пример) on: push: tags: - 'v*.*.*'"},{"id":"ci-cd/github-actions::top::53","title":"GitHub Actions","section":"Автоматизация релиза (пример)","path":"/docs/guide/ci-cd/github-actions","headings":["Автоматизация релиза (пример)"],"excerpt":"Автоматизация релиза (пример) jobs: release-check: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4","content":"Автоматизация релиза (пример) jobs: release-check: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4"},{"id":"ci-cd/github-actions::top::54","title":"GitHub Actions","section":"Автоматизация релиза (пример)","path":"/docs/guide/ci-cd/github-actions","headings":["Автоматизация релиза (пример)"],"excerpt":"Автоматизация релиза (пример) uses: actions/setup-go@v5 with: go-version: '1.22'","content":"Автоматизация релиза (пример) uses: actions/setup-go@v5 with: go-version: '1.22'"},{"id":"ci-cd/github-actions::top::55","title":"GitHub Actions","section":"Автоматизация релиза (пример)","path":"/docs/guide/ci-cd/github-actions","headings":["Автоматизация релиза (пример)"],"excerpt":"Автоматизация релиза (пример) name: Install EasyP run: go install github.com/easyp-tech/easyp/cmd/easyp@latest","content":"Автоматизация релиза (пример) name: Install EasyP run: go install github.com/easyp-tech/easyp/cmd/easyp@latest"},{"id":"ci-cd/github-actions::top::56","title":"GitHub Actions","section":"Автоматизация релиза (пример)","path":"/docs/guide/ci-cd/github-actions","headings":["Автоматизация релиза (пример)"],"excerpt":"Автоматизация релиза (пример) name: Lint run: easyp lint","content":"Автоматизация релиза (пример) name: Lint run: easyp lint"},{"id":"ci-cd/github-actions::top::57","title":"GitHub Actions","section":"Автоматизация релиза (пример)","path":"/docs/guide/ci-cd/github-actions","headings":["Автоматизация релиза (пример)"],"excerpt":"Автоматизация релиза (пример) name: Breaking vs previous tag run: PREV_TAG=$(git tag --sort=-creatordate grep -v \"${GITHUB_REF_NAME}\" head -n1 true) if [ -n \"$PREV_TAG\" ]; then echo \"Comparing against $PREV_TAG\" easyp br","content":"Автоматизация релиза (пример) name: Breaking vs previous tag run: PREV_TAG=$(git tag --sort=-creatordate grep -v \"${GITHUB_REF_NAME}\" head -n1 true) if [ -n \"$PREV_TAG\" ]; then echo \"Comparing against $PREV_TAG\" easyp breaking --against git-ref=$PREV_TAG else echo \"No previous tag, skipping breaking check\" fi"},{"id":"ci-cd/github-actions::top::58","title":"GitHub Actions","section":"Автоматизация релиза (пример)","path":"/docs/guide/ci-cd/github-actions","headings":["Автоматизация релиза (пример)"],"excerpt":"Автоматизация релиза (пример) name: Generate to ensure consistency run: easyp generate ```","content":"Автоматизация релиза (пример) name: Generate to ensure consistency run: easyp generate ```"},{"id":"ci-cd/github-actions::top::59","title":"GitHub Actions","section":"Отладка","path":"/docs/guide/ci-cd/github-actions","headings":["Отладка"],"excerpt":"Отладка Если нужно больше логов:","content":"Отладка Если нужно больше логов:"},{"id":"ci-cd/github-actions::top::60","title":"GitHub Actions","section":"Отладка","path":"/docs/guide/ci-cd/github-actions","headings":["Отладка"],"excerpt":"Отладка Добавьте вывод окружения для диагностики:","content":"Отладка Добавьте вывод окружения для диагностики:"},{"id":"ci-cd/github-actions::top::61","title":"GitHub Actions","section":"Переменные окружения (примерно)","path":"/docs/guide/ci-cd/github-actions","headings":["Переменные окружения (примерно)"],"excerpt":"Переменные окружения (примерно) Переменная Назначение ------------ ----------- EASYP_SERVICE_HOST Хост удалённого API Service (если используете удалённые плагины) EASYP_SERVICE_GRPC_PORT Порт удалённого сервиса GIT_SSH_C","content":"Переменные окружения (примерно) Переменная Назначение ------------ ----------- EASYP_SERVICE_HOST Хост удалённого API Service (если используете удалённые плагины) EASYP_SERVICE_GRPC_PORT Порт удалённого сервиса GIT_SSH_COMMAND Кастомная команда SSH (частные репозитории) GOFLAGS Можно выставить -mod=readonly для Go генерации"},{"id":"ci-cd/github-actions::top::62","title":"GitHub Actions","section":"Переменные окружения (примерно)","path":"/docs/guide/ci-cd/github-actions","headings":["Переменные окружения (примерно)"],"excerpt":"Переменные окружения (примерно) (Используйте только те, что действительно нужны вашему проекту.)","content":"Переменные окружения (примерно) (Используйте только те, что действительно нужны вашему проекту.)"},{"id":"ci-cd/github-actions::top::63","title":"GitHub Actions","section":"Частые ошибки","path":"/docs/guide/ci-cd/github-actions","headings":["Частые ошибки"],"excerpt":"Частые ошибки Симптом Причина Решение --------- --------- --------- Линт падает на неизвестных правилах Правила указаны в easyp.yaml, но версия EasyP их не поддерживает Обновить EasyP (go install ...@latest) breaking сра","content":"Частые ошибки Симптом Причина Решение --------- --------- --------- Линт падает на неизвестных правилах Правила указаны в easyp.yaml, но версия EasyP их не поддерживает Обновить EasyP (go install ...@latest) breaking сравнение ничего не находит Неверный --against (нет fetch удалённой ветки) Добавить шаг git fetch --all --tags Сгенерированный код в PR отличается от main Отсутствует проверка генерации в CI Добавить шаг «Ensure generated code is up-to-date» Приватные deps не скачиваются Нет SSH ключа или токена Настроить secrets + шаг подготовки SSH Долгое выполнение Отсутствует кеш Добавить кэширование модулей и deps"},{"id":"ci-cd/github-actions::top::64","title":"GitHub Actions","section":"Рекомендации по поддержке","path":"/docs/guide/ci-cd/github-actions","headings":["Рекомендации по поддержке"],"excerpt":"Рекомендации по поддержке Заготовить шаблон workflow и копировать между сервисами (DRY). Включить paths фильтры, чтобы не тратить минуты на нерелевантные изменения. Проверять easyp.yaml при изменениях отдельно — можно за","content":"Рекомендации по поддержке Заготовить шаблон workflow и копировать между сервисами (DRY). Включить paths фильтры, чтобы не тратить минуты на нерелевантные изменения. Проверять easyp.yaml при изменениях отдельно — можно запускать «конфигурационный тест» (например, easyp lint без файлов, чтобы убедиться, что конфиг валиден). При появлении новых правил линтера обновляйте конфиг и фиксируйте ошибки сразу в одной ветке."},{"id":"ci-cd/github-actions::top::65","title":"GitHub Actions","section":"Рекомендации по поддержке","path":"/docs/guide/ci-cd/github-actions","headings":["Рекомендации по поддержке"],"excerpt":"Рекомендации по поддержке Готово: вы можете расширять разделы генерации, добавлять OpenAPI / grpc-gateway / validate плагины, матрицы по языкам и интегрировать тесты поверх сгенерированного кода, если требуется.","content":"Рекомендации по поддержке Готово: вы можете расширять разделы генерации, добавлять OpenAPI / grpc-gateway / validate плагины, матрицы по языкам и интегрировать тесты поверх сгенерированного кода, если требуется."},{"id":"ci-cd/gitlab::top::0","title":"GitLab CI","section":"В процессе разработки","path":"/docs/guide/ci-cd/gitlab","headings":["В процессе разработки"],"excerpt":"В процессе разработки Документация по интеграции EasyP с GitLab CI находится в процессе подготовки. Планируемые разделы: Быстрый старт (пример .gitlab-ci.yml для линтинга и проверки несовместимых изменений) Кэширование з","content":"В процессе разработки Документация по интеграции EasyP с GitLab CI находится в процессе подготовки. Планируемые разделы: Быстрый старт (пример .gitlab-ci.yml для линтинга и проверки несовместимых изменений) Кэширование зависимостей и ускорение сборок Генерация кода и проверка актуальности артефактов Работа с приватными Git-репозиториями в deps Матрицы (parallel jobs) для разных языков и плагинов Автоматизация релизов по тегам"},{"id":"ci-cd/gitlab::top::1","title":"GitLab CI","section":"В процессе разработки","path":"/docs/guide/ci-cd/gitlab","headings":["В процессе разработки"],"excerpt":"В процессе разработки Если вам нужен пример прямо сейчас, базовый минимальный вариант может выглядеть так:","content":"В процессе разработки Если вам нужен пример прямо сейчас, базовый минимальный вариант может выглядеть так:"},{"id":"ci-cd/gitlab::top::2","title":"GitLab CI","section":"В процессе разработки","path":"/docs/guide/ci-cd/gitlab","headings":["В процессе разработки"],"excerpt":"В процессе разработки ```yaml stages: - validate - generate","content":"В процессе разработки ```yaml stages: - validate - generate"},{"id":"ci-cd/gitlab::top::3","title":"GitLab CI","section":"В процессе разработки","path":"/docs/guide/ci-cd/gitlab","headings":["В процессе разработки"],"excerpt":"В процессе разработки variables: GO_VERSION: \"1.22\"","content":"В процессе разработки variables: GO_VERSION: \"1.22\""},{"id":"ci-cd/gitlab::top::4","title":"GitLab CI","section":"В процессе разработки","path":"/docs/guide/ci-cd/gitlab","headings":["В процессе разработки"],"excerpt":"В процессе разработки validate: stage: validate image: golang:${GO_VERSION} before_script: - go install github.com/easyp-tech/easyp/cmd/easyp@latest - echo \"EasyP version:\" - easyp version # При необходимости: git fetch ","content":"В процессе разработки validate: stage: validate image: golang:${GO_VERSION} before_script: - go install github.com/easyp-tech/easyp/cmd/easyp@latest - echo \"EasyP version:\" - easyp version # При необходимости: git fetch --all --tags script: - easyp lint - easyp breaking --against git-ref=origin/main only: changes: - \"**/*.proto\" - \"easyp.yaml\""},{"id":"ci-cd/gitlab::top::5","title":"GitLab CI","section":"В процессе разработки","path":"/docs/guide/ci-cd/gitlab","headings":["В процессе разработки"],"excerpt":"В процессе разработки generate: stage: generate image: golang:${GO_VERSION} before_script: - go install github.com/easyp-tech/easyp/cmd/easyp@latest script: - easyp generate - if [ -n \"$(git status --porcelain)\" ]; then ","content":"В процессе разработки generate: stage: generate image: golang:${GO_VERSION} before_script: - go install github.com/easyp-tech/easyp/cmd/easyp@latest script: - easyp generate - if [ -n \"$(git status --porcelain)\" ]; then echo \"Сгенерированный код не актуален. Закоммитьте изменения локально.\" git diff --name-only exit 1 fi only: - main"},{"id":"ci-cd/gitlab::top::6","title":"GitLab CI","section":"В процессе разработки","path":"/docs/guide/ci-cd/gitlab","headings":["В процессе разработки"],"excerpt":"В процессе разработки Дополнительные рекомендации будут добавлены позже.","content":"В процессе разработки Дополнительные рекомендации будут добавлены позже."},{"id":"cli/auto-completion/auto-completion::zsh::0","title":"Автодополнение","section":"Автодополнение для zsh","path":"/docs/guide/cli/auto-completion/auto-completion#zsh","headings":["Автодополнение для zsh"],"excerpt":"Автодополнение для zsh Добавьте следующую строку в ваш файл запуска ~/.zshrc:","content":"Автодополнение для zsh Добавьте следующую строку в ваш файл запуска ~/.zshrc:"},{"id":"cli/auto-completion/auto-completion::zsh::1","title":"Автодополнение","section":"Автодополнение для zsh","path":"/docs/guide/cli/auto-completion/auto-completion#zsh","headings":["Автодополнение для zsh"],"excerpt":"Автодополнение для zsh Перезапустите оболочку или выполните:","content":"Автодополнение для zsh Перезапустите оболочку или выполните:"},{"id":"cli/auto-completion/auto-completion::bash::2","title":"Автодополнение","section":"Автодополнение для Bash","path":"/docs/guide/cli/auto-completion/auto-completion#bash","headings":["Автодополнение для Bash"],"excerpt":"Автодополнение для Bash Установите bash-completion и подключите его в ~/.bashrc. Добавьте следующую строку в файл запуска ~/.bashrc:","content":"Автодополнение для Bash Установите bash-completion и подключите его в ~/.bashrc. Добавьте следующую строку в файл запуска ~/.bashrc:"},{"id":"cli/auto-completion/auto-completion::bash::3","title":"Автодополнение","section":"Автодополнение для Bash","path":"/docs/guide/cli/auto-completion/auto-completion#bash","headings":["Автодополнение для Bash"],"excerpt":"Автодополнение для Bash Перезапустите оболочку или выполните:","content":"Автодополнение для Bash Перезапустите оболочку или выполните:"},{"id":"cli/auto-completion/auto-completion::top::4","title":"Автодополнение","section":"Примечания","path":"/docs/guide/cli/auto-completion/auto-completion","headings":["Примечания"],"excerpt":"Примечания Команда easyp completion выводит скрипт автодополнения для соответствующей оболочки. Если используете другую оболочку (например, fish), можно сгенерировать вывод и сохранить вручную: При обновлении версии Easy","content":"Примечания Команда easyp completion выводит скрипт автодополнения для соответствующей оболочки. Если используете другую оболочку (например, fish), можно сгенерировать вывод и сохранить вручную: При обновлении версии EasyP рекомендуется заново перезагрузить оболочку, чтобы подтянуть возможные изменения в автодополнении."},{"id":"cli/breaking-changes/breaking-changes::top::0","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":[],"excerpt":"Обнаружение несовместимых изменений (Breaking Changes Detection)","content":"Обнаружение несовместимых изменений (Breaking Changes Detection)"},{"id":"cli/breaking-changes/breaking-changes::top::1","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":[],"excerpt":"Механизм EasyP для обнаружения несовместимых (breaking) изменений помогает поддерживать обратную совместимость ваших protobuf API, автоматически выявляя изменения, способные сломать существующих клиентов. Это критично дл","content":"Механизм EasyP для обнаружения несовместимых (breaking) изменений помогает поддерживать обратную совместимость ваших protobuf API, автоматически выявляя изменения, способные сломать существующих клиентов. Это критично для стабильных API в продакшене."},{"id":"cli/breaking-changes/breaking-changes::top::2","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Обзор","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Обзор"],"excerpt":"Обзор Проверка несовместимых изменений сравнивает текущий набор protobuf‑файлов с предыдущей версией (обычно из другой Git ветки) и фиксирует модификации, которые могут вызвать проблемы совместимости для уже работающих к","content":"Обзор Проверка несовместимых изменений сравнивает текущий набор protobuf‑файлов с предыдущей версией (обычно из другой Git ветки) и фиксирует модификации, которые могут вызвать проблемы совместимости для уже работающих клиентов."},{"id":"cli/breaking-changes/breaking-changes::top::3","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Ключевые возможности","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Ключевые возможности"],"excerpt":"Ключевые возможности **Сравнение через Git**: Сопоставление с любой Git‑ссылкой (ветка, тег, commit) **Комплексный анализ**: Проверка сервисов, сообщений, enum'ов, полей и import'ов **Выборочное игнорирование**: Пропуск ","content":"Ключевые возможности **Сравнение через Git**: Сопоставление с любой Git‑ссылкой (ветка, тег, commit) **Комплексный анализ**: Проверка сервисов, сообщений, enum'ов, полей и import'ов **Выборочное игнорирование**: Пропуск указанных директорий из анализа **Детализированные отчёты**: Понятные ошибки с именами файлов, строками и позициями"},{"id":"cli/breaking-changes/breaking-changes::top::4","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Как работает","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Как работает"],"excerpt":"Как работает Детектор breaking changes выполняет следующие шаги:","content":"Как работает Детектор breaking changes выполняет следующие шаги:"},{"id":"cli/breaking-changes/breaking-changes::top::5","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Как работает","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Как работает"],"excerpt":"Как работает **Получение ветки сравнения**: Забирает proto-файлы из указанной Git‑ссылки **Парсинг обеих версий**: Анализирует структуру текущих и предыдущих файлов **Сравнение сущностей**: Последовательно проверяет все ","content":"Как работает **Получение ветки сравнения**: Забирает proto-файлы из указанной Git‑ссылки **Парсинг обеих версий**: Анализирует структуру текущих и предыдущих файлов **Сравнение сущностей**: Последовательно проверяет все элементы protobuf на breaking изменения **Формирование отчёта**: Генерирует подробные записи об ошибках с локациями и описаниями"},{"id":"cli/breaking-changes/breaking-changes::top::6","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Уровень проверки","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Уровень проверки"],"excerpt":"Уровень проверки EasyP реализует уровень проверки **WIRE+**: ✅ **Полная совместимость по wire‑формату** — старые и новые версии могут обмениваться данными ✅ **Обнаружение удалений элементов** — сервисы, сообщения, поля и","content":"Уровень проверки EasyP реализует уровень проверки **WIRE+**: ✅ **Полная совместимость по wire‑формату** — старые и новые версии могут обмениваться данными ✅ **Обнаружение удалений элементов** — сервисы, сообщения, поля и т.п. ✅ **Безопасность типов** — выявляет несовместимые изменения типов ❌ **Переименования полей/методов** — пока не детектируются (в планах) ❌ **Изменения на уровне файлов** — переносы пакетов, file options ещё не проверяются"},{"id":"cli/breaking-changes/breaking-changes::top::7","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Уровень проверки","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Уровень проверки"],"excerpt":"Уровень проверки Это даёт сильные гарантии совместимости и меньше ограничений, чем инструменты, требующие совместимости сгенерированного кода.","content":"Уровень проверки Это даёт сильные гарантии совместимости и меньше ограничений, чем инструменты, требующие совместимости сгенерированного кода."},{"id":"cli/breaking-changes/breaking-changes::top::8","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Конфигурация","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Конфигурация"],"excerpt":"Конфигурация Настройка в easyp.yaml:","content":"Конфигурация Настройка в easyp.yaml:"},{"id":"cli/breaking-changes/breaking-changes::top::9","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Параметры конфигурации","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Параметры конфигурации"],"excerpt":"Параметры конфигурации Option Description Default Required -------- ------------- --------- ---------- against_git_ref Git‑ссылка для сравнения \"master\" No ignore Список директорий для исключения из анализа [] No","content":"Параметры конфигурации Option Description Default Required -------- ------------- --------- ---------- against_git_ref Git‑ссылка для сравнения \"master\" No ignore Список директорий для исключения из анализа [] No"},{"id":"cli/breaking-changes/breaking-changes::top::10","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Базовый пример","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Базовый пример"],"excerpt":"Базовый пример Сравнение текущих изменений с веткой main:","content":"Базовый пример Сравнение текущих изменений с веткой main:"},{"id":"cli/breaking-changes/breaking-changes::top::11","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Использование файла конфигурации","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Использование файла конфигурации"],"excerpt":"Использование файла конфигурации","content":"Использование файла конфигурации"},{"id":"cli/breaking-changes/breaking-changes::top::12","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Уровень проверки","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Уровень проверки"],"excerpt":"Уровень проверки EasyP сейчас работает на уровне **WIRE+**, обеспечивая совместимость wire‑формата плюс защиту от удалений и изменения критичных типов.","content":"Уровень проверки EasyP сейчас работает на уровне **WIRE+**, обеспечивая совместимость wire‑формата плюс защиту от удалений и изменения критичных типов."},{"id":"cli/breaking-changes/breaking-changes::buf::13","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Сравнение с категориями Buf","path":"/docs/guide/cli/breaking-changes/breaking-changes#buf","headings":["Сравнение с категориями Buf"],"excerpt":"Сравнение с категориями Buf Check Type Buf WIRE Buf WIRE_JSON Buf FILE EasyP Current ------------ ---------- --------------- ---------- --------------- **Element Deletions** Service deletion ❌ ❌ ✅ ✅ RPC method deletion ❌","content":"Сравнение с категориями Buf 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::top::14","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Что это означает","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Что это означает"],"excerpt":"Что это означает **✅ EasyP обнаружит:** Все breaking изменения wire‑формата Удаления сервисов, методов, сообщений, полей Изменения типов, ломающие сериализацию Переименования enum‑значений (при сохранении номера)","content":"Что это означает **✅ EasyP обнаружит:** Все breaking изменения wire‑формата Удаления сервисов, методов, сообщений, полей Изменения типов, ломающие сериализацию Переименования enum‑значений (при сохранении номера)"},{"id":"cli/breaking-changes/breaking-changes::top::15","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Что это означает","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Что это означает"],"excerpt":"Что это означает **❌ EasyP НЕ обнаружит:** Переименование полей (с тем же номером) Изменение package File options (go_package, java_package, и т.п.) Перемещение типов между файлами в одном package","content":"Что это означает **❌ EasyP НЕ обнаружит:** Переименование полей (с тем же номером) Изменение package File options (go_package, java_package, и т.п.) Перемещение типов между файлами в одном package"},{"id":"cli/breaking-changes/breaking-changes::breaking-changes::16","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Правила Breaking Changes","path":"/docs/guide/cli/breaking-changes/breaking-changes#breaking-changes","headings":["Правила Breaking Changes"],"excerpt":"Правила Breaking Changes EasyP обнаруживает следующие типы breaking изменений:","content":"Правила Breaking Changes EasyP обнаруживает следующие типы breaking изменений:"},{"id":"cli/breaking-changes/breaking-changes::top::17","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Сравнение уровней","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Сравнение уровней"],"excerpt":"Сравнение уровней Detection Level Description EasyP Support ---------------- ------------- --------------- **WIRE** Совместимость только по wire‑формату ✅ **Full support** **WIRE+** Wire + обнаружение удалений ✅ **Curren","content":"Сравнение уровней Detection Level Description EasyP Support ---------------- ------------- --------------- **WIRE** Совместимость только по wire‑формату ✅ **Full support** **WIRE+** Wire + обнаружение удалений ✅ **Current level** **FILE** Совместимость сгенерированного кода ❌ Partial (planned)"},{"id":"cli/breaking-changes/breaking-changes::top::18","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Категории правил","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Категории правил"],"excerpt":"Категории правил Каждая категория имеет свою документацию с примерами:","content":"Категории правил Каждая категория имеет свою документацию с примерами:"},{"id":"cli/breaking-changes/breaking-changes::service-rpc::19","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"🚨 Изменения Service и RPC","path":"/docs/guide/cli/breaking-changes/breaking-changes#service-rpc","headings":["🚨 Изменения Service и RPC"],"excerpt":"🚨 Изменения Service и RPC 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 и RPC 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-field::20","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"📦 Изменения Message и Field","path":"/docs/guide/cli/breaking-changes/breaking-changes#message-field","headings":["📦 Изменения Message и Field"],"excerpt":"📦 Изменения Message и Field 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 и Field 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::21","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"🔢 Изменения Enum","path":"/docs/guide/cli/breaking-changes/breaking-changes#enum","headings":["🔢 Изменения Enum"],"excerpt":"🔢 Изменения Enum 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 val","content":"🔢 Изменения Enum 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::22","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"🔗 Изменения OneOf","path":"/docs/guide/cli/breaking-changes/breaking-changes#oneof","headings":["🔗 Изменения OneOf"],"excerpt":"🔗 Изменения OneOf Rule Description Status ------ ------------- --------- ONEOF_NO_DELETE OneOf fields cannot be deleted ✅ Implemented ONEOF_FIELD_NO_DELETE Fields within oneofs cannot be deleted ✅ Implemented ONEOF_FIEL","content":"🔗 Изменения OneOf 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::23","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"📥 Изменения Import","path":"/docs/guide/cli/breaking-changes/breaking-changes#import","headings":["📥 Изменения Import"],"excerpt":"📥 Изменения Import Rule Description Status ------ ------------- --------- IMPORT_NO_DELETE Import statements cannot be removed ✅ Implemented","content":"📥 Изменения Import Rule Description Status ------ ------------- --------- IMPORT_NO_DELETE Import statements cannot be removed ✅ Implemented"},{"id":"cli/breaking-changes/breaking-changes::top::24","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Не обнаруживается сейчас","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Не обнаруживается сейчас"],"excerpt":"Не обнаруживается сейчас Изменения ниже **НЕ детектируются** EasyP (могут ломать сгенерированный код):","content":"Не обнаруживается сейчас Изменения ниже **НЕ детектируются** EasyP (могут ломать сгенерированный код):"},{"id":"cli/breaking-changes/breaking-changes::top::25","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Не обнаруживается сейчас","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Не обнаруживается сейчас"],"excerpt":"Не обнаруживается сейчас Change Type Example Impact ------------- --------- -------- Field renaming string name = 1 → string full_name = 1 Ломает код Package changes package v1 → package v2 Меняются пути импорта File opt","content":"Не обнаруживается сейчас Change Type Example Impact ------------- --------- -------- Field renaming string name = 1 → string full_name = 1 Ломает код Package changes package v1 → package v2 Меняются пути импорта File options option go_package = \"old\" → option go_package = \"new\" Меняется расположение кода Moving between files Message перемещено в другой .proto Зависимости import'ов"},{"id":"cli/breaking-changes/breaking-changes::top::26","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Документация правил","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Документация правил"],"excerpt":"Документация правил См. подробные файлы правил для примеров и стратегий миграции:","content":"Документация правил См. подробные файлы правил для примеров и стратегий миграции:"},{"id":"cli/breaking-changes/breaking-changes::top::27","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Документация правил","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Документация правил"],"excerpt":"Документация правил Service: SERVICE_NO_DELETE, RPC_NO_DELETE, RPC_SAME_REQUEST_TYPE, RPC_SAME_RESPONSE_TYPE Message: MESSAGE_NO_DELETE, FIELD_NO_DELETE, FIELD_SAME_TYPE, FIELD_SAME_CARDINALITY Enum: ENUM_NO_DELETE, ENUM","content":"Документация правил Service: SERVICE_NO_DELETE, RPC_NO_DELETE, RPC_SAME_REQUEST_TYPE, RPC_SAME_RESPONSE_TYPE Message: MESSAGE_NO_DELETE, FIELD_NO_DELETE, FIELD_SAME_TYPE, FIELD_SAME_CARDINALITY Enum: ENUM_NO_DELETE, ENUM_VALUE_NO_DELETE, ENUM_VALUE_SAME_NAME OneOf: ONEOF_NO_DELETE, ONEOF_FIELD_NO_DELETE, ONEOF_FIELD_SAME_TYPE Import: IMPORT_NO_DELETE"},{"id":"cli/breaking-changes/breaking-changes::top::28","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Документация правил","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Документация правил"],"excerpt":"Документация правил Каждое правило содержит: ❌ Плохие примеры (breaking) ✅ Безопасные альтернативы 🔧 Стратегии миграции 📋 Реальные сообщения ошибок из EasyP","content":"Документация правил Каждое правило содержит: ❌ Плохие примеры (breaking) ✅ Безопасные альтернативы 🔧 Стратегии миграции 📋 Реальные сообщения ошибок из EasyP"},{"id":"cli/breaking-changes/breaking-changes::top::29","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"✅ Безопасные изменения (разрешены всегда)","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["✅ Безопасные изменения (разрешены всегда)"],"excerpt":"✅ Безопасные изменения (разрешены всегда) ```proto // Добавление новых элементов — безопасно message User { string name = 1; string email = 2; string phone = 3; // ✅ Новое поле }","content":"✅ Безопасные изменения (разрешены всегда) ```proto // Добавление новых элементов — безопасно message User { string name = 1; string email = 2; string phone = 3; // ✅ Новое поле }"},{"id":"cli/breaking-changes/breaking-changes::top::30","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"✅ Безопасные изменения (разрешены всегда)","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["✅ Безопасные изменения (разрешены всегда)"],"excerpt":"✅ Безопасные изменения (разрешены всегда) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc GetUserProfile(GetUserRequest) returns (UserProfile); // ✅ Новый RPC }","content":"✅ Безопасные изменения (разрешены всегда) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc GetUserProfile(GetUserRequest) returns (UserProfile); // ✅ Новый RPC }"},{"id":"cli/breaking-changes/breaking-changes::top::31","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"✅ Безопасные изменения (разрешены всегда)","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["✅ Безопасные изменения (разрешены всегда)"],"excerpt":"✅ Безопасные изменения (разрешены всегда) enum Status { STATUS_UNSPECIFIED = 0; STATUS_ACTIVE = 1; STATUS_PENDING = 2; // ✅ Новое enum значение } ```","content":"✅ Безопасные изменения (разрешены всегда) enum Status { STATUS_UNSPECIFIED = 0; STATUS_ACTIVE = 1; STATUS_PENDING = 2; // ✅ Новое enum значение } ```"},{"id":"cli/breaking-changes/breaking-changes::top::32","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"❌ Несовместимые изменения (обнаруживаются всегда)","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["❌ Несовместимые изменения (обнаруживаются всегда)"],"excerpt":"❌ Несовместимые изменения (обнаруживаются всегда) ```proto // Удаления и смена типов ломают совместимость message User { string name = 1; // ❌ Удалённое поле }","content":"❌ Несовместимые изменения (обнаруживаются всегда) ```proto // Удаления и смена типов ломают совместимость message User { string name = 1; // ❌ Удалённое поле }"},{"id":"cli/breaking-changes/breaking-changes::top::33","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"❌ Несовместимые изменения (обнаруживаются всегда)","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["❌ Несовместимые изменения (обнаруживаются всегда)"],"excerpt":"❌ Несовместимые изменения (обнаруживаются всегда) service UserService { // ❌ Удалённый RPC метод rpc GetUser(GetUserRequestV2) returns (GetUserResponse); // ❌ Изменён тип запроса } ```","content":"❌ Несовместимые изменения (обнаруживаются всегда) service UserService { // ❌ Удалённый RPC метод rpc GetUser(GetUserRequestV2) returns (GetUserResponse); // ❌ Изменён тип запроса } ```"},{"id":"cli/breaking-changes/breaking-changes::top::34","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Сценарий: Изменения пока не детектируются","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Сценарий: Изменения пока не детектируются"],"excerpt":"Сценарий: Изменения пока не детектируются ```proto // 🟡 Ломает сгенерированный код, но проходит проверки EasyP message User { string user_name = 1; // Переименовано с \"name\" string user_email = 2; // Переименовано с \"em","content":"Сценарий: Изменения пока не детектируются ```proto // 🟡 Ломает сгенерированный код, но проходит проверки EasyP message User { string user_name = 1; // Переименовано с \"name\" string user_email = 2; // Переименовано с \"email\" }"},{"id":"cli/breaking-changes/breaking-changes::top::35","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Сценарий: Изменения пока не детектируются","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Сценарий: Изменения пока не детектируются"],"excerpt":"Сценарий: Изменения пока не детектируются service UserService { rpc GetUserProfile(GetUserRequest) returns (GetUserResponse); // Переименовано с GetUser } ```","content":"Сценарий: Изменения пока не детектируются service UserService { rpc GetUserProfile(GetUserRequest) returns (GetUserResponse); // Переименовано с GetUser } ```"},{"id":"cli/breaking-changes/breaking-changes::top::36","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Текстовый формат (по умолчанию)","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Текстовый формат (по умолчанию)"],"excerpt":"Текстовый формат (по умолчанию)","content":"Текстовый формат (по умолчанию)"},{"id":"cli/breaking-changes/breaking-changes::1::37","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"1. Регулярный запуск","path":"/docs/guide/cli/breaking-changes/breaking-changes#1","headings":["1. Регулярный запуск"],"excerpt":"Регулярный запуск Добавьте проверку несовместимых изменений в CI/CD:","content":"Регулярный запуск Добавьте проверку несовместимых изменений в CI/CD:"},{"id":"cli/breaking-changes/breaking-changes::2::38","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"2. Защита веток","path":"/docs/guide/cli/breaking-changes/breaking-changes#2","headings":["2. Защита веток"],"excerpt":"Защита веток Блокируйте слияния с breaking изменениями:","content":"Защита веток Блокируйте слияния с breaking изменениями:"},{"id":"cli/breaking-changes/breaking-changes::3::39","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"3. Стратегия версионирования","path":"/docs/guide/cli/breaking-changes/breaking-changes#3","headings":["3. Стратегия версионирования"],"excerpt":"Стратегия версионирования При необходимости breaking изменений: Создайте новую версию пакета (myservice.v2) Поддерживайте старую версию в период миграции Добавляйте уведомления о деприкации","content":"Стратегия версионирования При необходимости breaking изменений: Создайте новую версию пакета (myservice.v2) Поддерживайте старую версию в период миграции Добавляйте уведомления о деприкации"},{"id":"cli/breaking-changes/breaking-changes::4::40","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"4. Игнорирование путей","path":"/docs/guide/cli/breaking-changes/breaking-changes#4","headings":["4. Игнорирование путей"],"excerpt":"Игнорирование путей Используйте ignore осознанно:","content":"Игнорирование путей Используйте ignore осознанно:"},{"id":"cli/breaking-changes/breaking-changes::repository-does-not-exist::41","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Проблема: \"Repository does not exist\"","path":"/docs/guide/cli/breaking-changes/breaking-changes#repository-does-not-exist","headings":["Проблема: \"Repository does not exist\""],"excerpt":"Проблема: \"Repository does not exist\" Решение: Выполняйте команду внутри Git репозитория с нужной веткой.","content":"Проблема: \"Repository does not exist\" Решение: Выполняйте команду внутри Git репозитория с нужной веткой."},{"id":"cli/breaking-changes/breaking-changes::cannot-find-git-ref::42","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Проблема: \"Cannot find git ref\"","path":"/docs/guide/cli/breaking-changes/breaking-changes#cannot-find-git-ref","headings":["Проблема: \"Cannot find git ref\""],"excerpt":"Проблема: \"Cannot find git ref\" Решение: Проверьте наличие ссылки:","content":"Проблема: \"Cannot find git ref\" Решение: Проверьте наличие ссылки:"},{"id":"cli/breaking-changes/breaking-changes::top::43","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Проблема: Ложные срабатывания на сгенерированный код","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Проблема: Ложные срабатывания на сгенерированный код"],"excerpt":"Проблема: Ложные срабатывания на сгенерированный код Решение: Исключите директории генерации:","content":"Проблема: Ложные срабатывания на сгенерированный код Решение: Исключите директории генерации:"},{"id":"cli/breaking-changes/breaking-changes::top::44","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Проблема: Очень много изменений","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Проблема: Очень много изменений"],"excerpt":"Проблема: Очень много изменений Решение: Создайте новую версию API Вносите изменения постепенно Используйте feature flags","content":"Проблема: Очень много изменений Решение: Создайте новую версию API Вносите изменения постепенно Используйте feature flags"},{"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 - name: Install EasyP run: curl -sSfL https://raw.githubusercontent.com/easyp-tech/easyp/main/install.","content":"GitHub Actions jobs: breaking-changes: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 with: fetch-depth: 0 - 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-pre-push-hook::48","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Pre-commit / pre-push hook","path":"/docs/guide/cli/breaking-changes/breaking-changes#pre-commit-pre-push-hook","headings":["Pre-commit / pre-push hook"],"excerpt":"Pre-commit / pre-push hook ```bash #!/bin/sh .git/hooks/pre-push","content":"Pre-commit / pre-push hook ```bash #!/bin/sh .git/hooks/pre-push"},{"id":"cli/breaking-changes/breaking-changes::pre-commit-pre-push-hook::49","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Pre-commit / pre-push hook","path":"/docs/guide/cli/breaking-changes/breaking-changes#pre-commit-pre-push-hook","headings":["Pre-commit / pre-push hook"],"excerpt":"Pre-commit / pre-push hook protected_branch='main' current_branch=$(git symbolic-ref HEAD sed -e 's,.*/\\(.*\\),\\1,')","content":"Pre-commit / pre-push hook protected_branch='main' current_branch=$(git symbolic-ref HEAD sed -e 's,.*/\\(.*\\),\\1,')"},{"id":"cli/breaking-changes/breaking-changes::pre-commit-pre-push-hook::50","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Pre-commit / pre-push hook","path":"/docs/guide/cli/breaking-changes/breaking-changes#pre-commit-pre-push-hook","headings":["Pre-commit / pre-push hook"],"excerpt":"Pre-commit / pre-push 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.","content":"Pre-commit / pre-push 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::top::51","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Режим отладки","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Режим отладки"],"excerpt":"Режим отладки Включите debug‑логирование:","content":"Режим отладки Включите debug‑логирование:"},{"id":"cli/breaking-changes/breaking-changes::top::52","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Ручное сравнение","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Ручное сравнение"],"excerpt":"Ручное сравнение Для сложных случаев:","content":"Ручное сравнение Для сложных случаев:"},{"id":"cli/breaking-changes/breaking-changes::top::53","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Оптимизация производительности","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Оптимизация производительности"],"excerpt":"Оптимизация производительности Ограничьте область:","content":"Оптимизация производительности Ограничьте область:"},{"id":"cli/breaking-changes/breaking-changes::top::54","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Оптимизация производительности","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Оптимизация производительности"],"excerpt":"Оптимизация производительности","content":"Оптимизация производительности"},{"id":"cli/breaking-changes/breaking-changes::top::55","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Оптимизация производительности","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Оптимизация производительности"],"excerpt":"Оптимизация производительности Механизм обнаружения несовместимых изменений в EasyP обеспечивает надёжную основу для безопасной эволюции protobuf‑схем при сохранении совместимости API.","content":"Оптимизация производительности Механизм обнаружения несовместимых изменений в EasyP обеспечивает надёжную основу для безопасной эволюции protobuf‑схем при сохранении совместимости API."},{"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":"Это правило проверяет, что ни один enum не был удалён из proto‑файлов. Удаление enum ломает совместимость по wire‑формату и сгенерированный код: сохранённые данные могут содержать удалённые значения, а клиентский код опи","content":"Это правило проверяет, что ни один enum не был удалён из proto‑файлов. Удаление enum ломает совместимость по wire‑формату и сгенерированный код: сохранённые данные могут содержать удалённые значения, а клиентский код опирается на сгенерированные типы и константы enum."},{"id":"cli/breaking-changes/rules/enum-no-delete::breaking::1","title":"ENUM_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-no-delete::breaking::2","title":"ENUM_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/enum-no-delete::breaking::3","title":"ENUM_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_CONFIRMED = 2; ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_DELIVERED = 4; }","content":"Плохой (Breaking) 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::breaking::4","title":"ENUM_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) enum UserRole { // [!code --] USER_ROLE_UNSPECIFIED = 0; // [!code --] USER_ROLE_ADMIN = 1; // [!code --] USER_ROLE_USER = 2; // [!code --] } // [!code --]","content":"Плохой (Breaking) 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::breaking::5","title":"ENUM_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message Order { string id = 1; OrderStatus status = 2; UserRole created_by_role = 3; } ```","content":"Плохой (Breaking) message Order { string id = 1; OrderStatus status = 2; UserRole created_by_role = 3; } ```"},{"id":"cli/breaking-changes/rules/enum-no-delete::breaking::6","title":"ENUM_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-no-delete::breaking::7","title":"ENUM_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/enum-no-delete::breaking::8","title":"ENUM_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_CONFIRMED = 2; ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_DELIVERED = 4; }","content":"Плохой (Breaking) 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::breaking::9","title":"ENUM_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) // UserRole enum удалён — BREAKING CHANGE!","content":"Плохой (Breaking) // UserRole enum удалён — BREAKING CHANGE!"},{"id":"cli/breaking-changes/rules/enum-no-delete::breaking::10","title":"ENUM_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message Order { string id = 1; OrderStatus status = 2; UserRole created_by_role = 3; // ERROR: UserRole больше не существует } ```","content":"Плохой (Breaking) message Order { string id = 1; OrderStatus status = 2; UserRole created_by_role = 3; // ERROR: UserRole больше не существует } ```"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::11","title":"ENUM_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры **Удаление вложенного enum:** ```proto // Before message User { string name = 1; Status status = 2; enum Status { // [!code --] STATUS_UNSPECIFIED = 0; // [!code --] STATUS_ACTIVE = 1; // [!code --","content":"Дополнительные примеры **Удаление вложенного enum:** ```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::top::12","title":"ENUM_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры // After - BREAKING CHANGE! message User { string name = 1; Status status = 2; // ERROR: Status удалён // Вложенный enum Status удалён } ```","content":"Дополнительные примеры // After - BREAKING CHANGE! message User { string name = 1; Status status = 2; // ERROR: Status удалён // Вложенный enum Status удалён } ```"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::13","title":"ENUM_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо удаления — пометить enum deprecated:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо удаления — пометить enum deprecated:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::14","title":"ENUM_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::15","title":"ENUM_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_CONFIRMED = 2; ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_DELIVERED = 4; }","content":"Хороший (Безопасный) 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::top::16","title":"ENUM_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) enum UserRole { option deprecated = true; // [!code focus] USER_ROLE_UNSPECIFIED = 0; USER_ROLE_ADMIN = 1; USER_ROLE_USER = 2; }","content":"Хороший (Безопасный) 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::top::17","title":"ENUM_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message Order { string id = 1; OrderStatus status = 2; UserRole created_by_role = 3 [deprecated = true]; // [!code focus] } ```","content":"Хороший (Безопасный) 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::top::18","title":"ENUM_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Или заменить новым enum:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Или заменить новым enum:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::19","title":"ENUM_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::20","title":"ENUM_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_CONFIRMED = 2; ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_DELIVERED = 4; }","content":"Хороший (Безопасный) 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::top::21","title":"ENUM_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) enum UserRole { option deprecated = true; // [!code focus] // Старый enum USER_ROLE_UNSPECIFIED = 0; USER_ROLE_ADMIN = 1; USER_ROLE_USER = 2; }","content":"Хороший (Безопасный) enum UserRole { option deprecated = true; // [!code focus] // Старый enum USER_ROLE_UNSPECIFIED = 0; USER_ROLE_ADMIN = 1; USER_ROLE_USER = 2; }"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::22","title":"ENUM_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) enum UserPermission { // [!code focus] // Новый enum USER_PERMISSION_UNSPECIFIED = 0; // [!code focus] USER_PERMISSION_READ = 1; // [!code focus] USER_PERMISSION_WRITE = 2; // [!code focus] USER_PERM","content":"Хороший (Безопасный) enum UserPermission { // [!code focus] // Новый enum 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::top::23","title":"ENUM_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message Order { string id = 1; OrderStatus status = 2; UserRole created_by_role = 3 [deprecated = true]; // [!code focus] UserPermission created_by_permission = 4; // [!code focus] } ```","content":"Хороший (Безопасный) message Order { string id = 1; OrderStatus status = 2; UserRole created_by_role = 3 [deprecated = true]; // [!code focus] UserPermission created_by_permission = 4; // [!code focus] } ```"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::24","title":"ENUM_NO_DELETE","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Влияние"],"excerpt":"Влияние **Wire Format:** Данные с удалённым enum не десериализуются корректно **Generated Code:** Тип и константы удаляются — компиляция клиентов ломается **Field References:** Поля с типом удалённого enum становятся нев","content":"Влияние **Wire Format:** Данные с удалённым enum не десериализуются корректно **Generated Code:** Тип и константы удаляются — компиляция клиентов ломается **Field References:** Поля с типом удалённого enum становятся невалидны **Switch Statements:** switch по enum ломается (неизвестные кейсы)"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::25","title":"ENUM_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Код клиента ломается:** ```go // Before order := &myapi.Order{ Id: \"order123\", Status: myapi.OrderStatus_ORDER_STATUS_PENDING, CreatedByRole: myapi.UserRole_USER_ROLE_ADMIN, // ERROR после удаления }","content":"Реальный пример **Код клиента ломается:** ```go // Before order := &myapi.Order{ Id: \"order123\", Status: myapi.OrderStatus_ORDER_STATUS_PENDING, CreatedByRole: myapi.UserRole_USER_ROLE_ADMIN, // ERROR после удаления }"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::26","title":"ENUM_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример switch order.CreatedByRole { case myapi.UserRole_USER_ROLE_ADMIN: // ERROR // Admin logic case myapi.UserRole_USER_ROLE_USER: // ERROR // User logic }","content":"Реальный пример switch order.CreatedByRole { case myapi.UserRole_USER_ROLE_ADMIN: // ERROR // Admin logic case myapi.UserRole_USER_ROLE_USER: // ERROR // User logic }"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::27","title":"ENUM_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример // undefined: myapi.UserRole // undefined: myapi.UserRole_USER_ROLE_ADMIN ```","content":"Реальный пример // undefined: myapi.UserRole // undefined: myapi.UserRole_USER_ROLE_ADMIN ```"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::28","title":"ENUM_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Старые данные становятся нечитаемыми:**","content":"Реальный пример **Старые данные становятся нечитаемыми:**"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::29","title":"ENUM_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Серверная логика ломается:**","content":"Реальный пример **Серверная логика ломается:**"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::30","title":"ENUM_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Депрецируйте enum:** **Пометьте поля со старым enum deprecated:** **Создайте новый enum:** **Сервер обрабатывает оба:** **Удалите старый enum в следующей major‑версии.**","content":"Стратегия миграции **Депрецируйте enum:** **Пометьте поля со старым enum deprecated:** **Создайте новый enum:** **Сервер обрабатывает оба:** **Удалите старый enum в следующей major‑версии.**"},{"id":"cli/breaking-changes/rules/enum-no-delete::enum::31","title":"ENUM_NO_DELETE","section":"Редизайн enum","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#enum","headings":["Редизайн enum"],"excerpt":"Редизайн enum ```proto enum Priority { option deprecated = true; PRIORITY_UNSPECIFIED = 0; PRIORITY_LOW = 1; PRIORITY_HIGH = 2; }","content":"Редизайн enum ```proto enum Priority { option deprecated = true; PRIORITY_UNSPECIFIED = 0; PRIORITY_LOW = 1; PRIORITY_HIGH = 2; }"},{"id":"cli/breaking-changes/rules/enum-no-delete::enum::32","title":"ENUM_NO_DELETE","section":"Редизайн enum","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#enum","headings":["Редизайн enum"],"excerpt":"Редизайн enum enum TaskPriority { TASK_PRIORITY_UNSPECIFIED = 0; TASK_PRIORITY_LOW = 1; TASK_PRIORITY_MEDIUM = 2; TASK_PRIORITY_HIGH = 3; TASK_PRIORITY_URGENT = 4; } ```","content":"Редизайн enum enum TaskPriority { 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::enum::33","title":"ENUM_NO_DELETE","section":"Консолидация enum","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#enum","headings":["Консолидация enum"],"excerpt":"Консолидация enum ```proto enum Status { option deprecated = true; STATUS_UNSPECIFIED = 0; STATUS_ACTIVE = 1; }","content":"Консолидация enum ```proto enum Status { option deprecated = true; STATUS_UNSPECIFIED = 0; STATUS_ACTIVE = 1; }"},{"id":"cli/breaking-changes/rules/enum-no-delete::enum::34","title":"ENUM_NO_DELETE","section":"Консолидация enum","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#enum","headings":["Консолидация enum"],"excerpt":"Консолидация enum enum State { option deprecated = true; STATE_UNSPECIFIED = 0; STATE_ENABLED = 1; }","content":"Консолидация enum enum State { option deprecated = true; STATE_UNSPECIFIED = 0; STATE_ENABLED = 1; }"},{"id":"cli/breaking-changes/rules/enum-no-delete::enum::35","title":"ENUM_NO_DELETE","section":"Консолидация enum","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#enum","headings":["Консолидация enum"],"excerpt":"Консолидация enum enum EntityStatus { ENTITY_STATUS_UNSPECIFIED = 0; ENTITY_STATUS_ACTIVE = 1; ENTITY_STATUS_INACTIVE = 2; ENTITY_STATUS_ENABLED = 3; ENTITY_STATUS_DISABLED = 4; } ```","content":"Консолидация enum enum EntityStatus { 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::enum::36","title":"ENUM_NO_DELETE","section":"Перемещение enum в новый пакет","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#enum","headings":["Перемещение enum в новый пакет"],"excerpt":"Перемещение enum в новый пакет ```proto enum UserRole { option deprecated = true; USER_ROLE_UNSPECIFIED = 0; USER_ROLE_ADMIN = 1; }","content":"Перемещение enum в новый пакет ```proto enum UserRole { option deprecated = true; USER_ROLE_UNSPECIFIED = 0; USER_ROLE_ADMIN = 1; }"},{"id":"cli/breaking-changes/rules/enum-no-delete::enum::37","title":"ENUM_NO_DELETE","section":"Перемещение enum в новый пакет","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#enum","headings":["Перемещение enum в новый пакет"],"excerpt":"Перемещение enum в новый пакет import \"common/roles.proto\";","content":"Перемещение enum в новый пакет import \"common/roles.proto\";"},{"id":"cli/breaking-changes/rules/enum-no-delete::enum::38","title":"ENUM_NO_DELETE","section":"Перемещение enum в новый пакет","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#enum","headings":["Перемещение enum в новый пакет"],"excerpt":"Перемещение enum в новый пакет message Order { UserRole old_role = 3 [deprecated = true]; common.UserRole new_role = 4; } ```","content":"Перемещение enum в новый пакет message Order { UserRole old_role = 3 [deprecated = true]; common.UserRole new_role = 4; } ```"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::39","title":"ENUM_NO_DELETE","section":"Версионирование / новая версия пакета","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Версионирование / новая версия пакета"],"excerpt":"Версионирование / новая версия пакета ```proto package myapi.v2;","content":"Версионирование / новая версия пакета ```proto package myapi.v2;"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::40","title":"ENUM_NO_DELETE","section":"Версионирование / новая версия пакета","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Версионирование / новая версия пакета"],"excerpt":"Версионирование / новая версия пакета enum UserPermission { USER_PERMISSION_UNSPECIFIED = 0; USER_PERMISSION_READ = 1; USER_PERMISSION_WRITE = 2; USER_PERMISSION_ADMIN = 3; }","content":"Версионирование / новая версия пакета 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::top::41","title":"ENUM_NO_DELETE","section":"Версионирование / новая версия пакета","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Версионирование / новая версия пакета"],"excerpt":"Версионирование / новая версия пакета message Order { string id = 1; UserPermission created_by_permission = 2; } ```","content":"Версионирование / новая версия пакета message Order { string id = 1; UserPermission created_by_permission = 2; } ```"},{"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":"Правило проверяет, что ни одно значение enum (enum value) не было удалено. Удаление значения ломает совместимость по wire‑формату и сгенерированный код: в уже сохранённых данных могут присутствовать удалённые значения, а","content":"Правило проверяет, что ни одно значение enum (enum value) не было удалено. Удаление значения ломает совместимость по wire‑формату и сгенерированный код: в уже сохранённых данных могут присутствовать удалённые значения, а клиентский код может ссылаться на соответствующие константы."},{"id":"cli/breaking-changes/rules/enum-value-no-delete::breaking::1","title":"ENUM_VALUE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::breaking::2","title":"ENUM_VALUE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::breaking::3","title":"ENUM_VALUE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) 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":"Плохой (Breaking) 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::breaking::4","title":"ENUM_VALUE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) enum Priority { PRIORITY_UNSPECIFIED = 0; PRIORITY_LOW = 1; PRIORITY_MEDIUM = 2; PRIORITY_HIGH = 3; PRIORITY_URGENT = 4; } ```","content":"Плохой (Breaking) 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::breaking::5","title":"ENUM_VALUE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::breaking::6","title":"ENUM_VALUE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::breaking::7","title":"ENUM_VALUE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) 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 --] ","content":"Плохой (Breaking) 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 --] Удалено значение enum — BREAKING! }"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::breaking::8","title":"ENUM_VALUE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) enum Priority { PRIORITY_UNSPECIFIED = 0; PRIORITY_LOW = 1; PRIORITY_MEDIUM = 2; PRIORITY_HIGH = 3; // PRIORITY_URGENT = 4; // [!code --] Удалено значение enum — BREAKING! } ```","content":"Плохой (Breaking) enum Priority { PRIORITY_UNSPECIFIED = 0; PRIORITY_LOW = 1; PRIORITY_MEDIUM = 2; PRIORITY_HIGH = 3; // PRIORITY_URGENT = 4; // [!code --] Удалено значение enum — BREAKING! } ```"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::9","title":"ENUM_VALUE_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры **Множественное удаление значений:** ```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_S","content":"Дополнительные примеры **Множественное удаление значений:** ```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::top::10","title":"ENUM_VALUE_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры // 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","content":"Дополнительные примеры // 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::top::11","title":"ENUM_VALUE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо удаления — пометить значения deprecated:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо удаления — пометить значения deprecated:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::12","title":"ENUM_VALUE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::13","title":"ENUM_VALUE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) 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 = t","content":"Хороший (Безопасный) 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::top::14","title":"ENUM_VALUE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) enum Priority { PRIORITY_UNSPECIFIED = 0; PRIORITY_LOW = 1; PRIORITY_MEDIUM = 2; PRIORITY_HIGH = 3; PRIORITY_URGENT = 4 [deprecated = true]; // [!code focus] } ```","content":"Хороший (Безопасный) 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::top::15","title":"ENUM_VALUE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Или зарезервировать номер и имя после удаления:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Или зарезервировать номер и имя после удаления:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::16","title":"ENUM_VALUE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::17","title":"ENUM_VALUE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) enum OrderStatus { reserved 5; // [!code focus] reserved \"ORDER_STATUS_CANCELLED\"; // [!code focus]","content":"Хороший (Безопасный) enum OrderStatus { reserved 5; // [!code focus] reserved \"ORDER_STATUS_CANCELLED\"; // [!code focus]"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::18","title":"ENUM_VALUE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_CONFIRMED = 2; ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_DELIVERED = 4; }","content":"Хороший (Безопасный) 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::top::19","title":"ENUM_VALUE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) enum Priority { reserved 4; // [!code focus] reserved \"PRIORITY_URGENT\"; // [!code focus]","content":"Хороший (Безопасный) enum Priority { reserved 4; // [!code focus] reserved \"PRIORITY_URGENT\"; // [!code focus]"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::20","title":"ENUM_VALUE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) PRIORITY_UNSPECIFIED = 0; PRIORITY_LOW = 1; PRIORITY_MEDIUM = 2; PRIORITY_HIGH = 3; } ```","content":"Хороший (Безопасный) PRIORITY_UNSPECIFIED = 0; PRIORITY_LOW = 1; PRIORITY_MEDIUM = 2; PRIORITY_HIGH = 3; } ```"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::21","title":"ENUM_VALUE_NO_DELETE","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Влияние"],"excerpt":"Влияние **Wire Format:** Данные с удалёнными значениями не десериализуются корректно **Generated Code:** Константы исчезают — клиентский код не компилируется **Client Applications:** Ссылки на удалённые значения вызывают","content":"Влияние **Wire Format:** Данные с удалёнными значениями не десериализуются корректно **Generated Code:** Константы исчезают — клиентский код не компилируется **Client Applications:** Ссылки на удалённые значения вызывают ошибки компиляции **Switch Statements:** switch по enum ломается (неизвестные case) **Default Handling:** Поведение при неизвестных значениях меняется"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::22","title":"ENUM_VALUE_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Код клиента ломается:** ```go order := &myapi.Order{ Status: myapi.OrderStatus_ORDER_STATUS_CANCELLED, // ERROR после удаления }","content":"Реальный пример **Код клиента ломается:** ```go order := &myapi.Order{ Status: myapi.OrderStatus_ORDER_STATUS_CANCELLED, // ERROR после удаления }"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::23","title":"ENUM_VALUE_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример switch order.Status { case myapi.OrderStatus_ORDER_STATUS_PENDING: // Pending case myapi.OrderStatus_ORDER_STATUS_CANCELLED: // ERROR: undefined // Cancellation default: // Unknown } // undefined: myapi.O","content":"Реальный пример switch order.Status { case myapi.OrderStatus_ORDER_STATUS_PENDING: // Pending case myapi.OrderStatus_ORDER_STATUS_CANCELLED: // ERROR: undefined // Cancellation default: // Unknown } // undefined: myapi.OrderStatus_ORDER_STATUS_CANCELLED ```"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::24","title":"ENUM_VALUE_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Проблемы с уже сохранёнными данными:**","content":"Реальный пример **Проблемы с уже сохранёнными данными:**"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::25","title":"ENUM_VALUE_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Валидация на сервере:** ```go func validateOrderStatus(status OrderStatus) error { switch status { case OrderStatus_ORDER_STATUS_PENDING, OrderStatus_ORDER_STATUS_CONFIRMED, OrderStatus_ORDER_STATUS_SHI","content":"Реальный пример **Валидация на сервере:** ```go 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 после удаления return nil default: return errors.New(\"invalid order status\") } }"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::26","title":"ENUM_VALUE_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример func canModifyOrder(order *Order) bool { return order.Status != OrderStatus_ORDER_STATUS_CANCELLED // ERROR } ```","content":"Реальный пример func canModifyOrder(order *Order) bool { return order.Status != OrderStatus_ORDER_STATUS_CANCELLED // ERROR } ```"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::27","title":"ENUM_VALUE_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Сначала пометить deprecated:** **Перестать использовать deprecated значение в новом коде:** **Обработка legacy в клиенте:** **Резервирование после миграции:** **Никогда не переиспользовать номера** —","content":"Стратегия миграции **Сначала пометить deprecated:** **Перестать использовать deprecated значение в новом коде:** **Обработка legacy в клиенте:** **Резервирование после миграции:** **Никогда не переиспользовать номера** — зарезервированы навсегда."},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::28","title":"ENUM_VALUE_NO_DELETE","section":"Предотвращение переиспользования номера","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Предотвращение переиспользования номера"],"excerpt":"Предотвращение переиспользования номера ```proto enum Status { reserved 2; reserved \"STATUS_DELETED\";","content":"Предотвращение переиспользования номера ```proto enum Status { reserved 2; reserved \"STATUS_DELETED\";"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::29","title":"ENUM_VALUE_NO_DELETE","section":"Предотвращение переиспользования номера","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Предотвращение переиспользования номера"],"excerpt":"Предотвращение переиспользования номера STATUS_UNSPECIFIED = 0; STATUS_ACTIVE = 1; STATUS_INACTIVE = 3; // STATUS_DELETED = 2; // Не переиспользуем } ```","content":"Предотвращение переиспользования номера STATUS_UNSPECIFIED = 0; STATUS_ACTIVE = 1; STATUS_INACTIVE = 3; // STATUS_DELETED = 2; // Не переиспользуем } ```"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::json::30","title":"ENUM_VALUE_NO_DELETE","section":"JSON совместимость","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#json","headings":["JSON совместимость"],"excerpt":"JSON совместимость ```proto enum Color { reserved 2; reserved \"RED\";","content":"JSON совместимость ```proto enum Color { reserved 2; reserved \"RED\";"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::json::31","title":"ENUM_VALUE_NO_DELETE","section":"JSON совместимость","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#json","headings":["JSON совместимость"],"excerpt":"JSON совместимость COLOR_UNSPECIFIED = 0; COLOR_BLUE = 1; COLOR_GREEN = 3; // COLOR_RED = 2; // Был удалён } ```","content":"JSON совместимость COLOR_UNSPECIFIED = 0; COLOR_BLUE = 1; COLOR_GREEN = 3; // COLOR_RED = 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":"Это правило проверяет, что имя enum значения для каждого номера (number) не изменилось. Переименование enum значения при сохранении его номера ломает совместимость JSON и сгенерированный код: клиенты ожидают конкретные и","content":"Это правило проверяет, что имя enum значения для каждого номера (number) не изменилось. Переименование enum значения при сохранении его номера ломает совместимость JSON и сгенерированный код: клиенты ожидают конкретные имена констант."},{"id":"cli/breaking-changes/rules/enum-value-same-name::breaking::1","title":"ENUM_VALUE_SAME_NAME","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-value-same-name::breaking::2","title":"ENUM_VALUE_SAME_NAME","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/enum-value-same-name::breaking::3","title":"ENUM_VALUE_SAME_NAME","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_CONFIRMED = 2; ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_DELIVERED = 4; } ```","content":"Плохой (Breaking) 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::breaking::4","title":"ENUM_VALUE_SAME_NAME","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-value-same-name::breaking::5","title":"ENUM_VALUE_SAME_NAME","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/enum-value-same-name::breaking::6","title":"ENUM_VALUE_SAME_NAME","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_APPROVED = 2; // [!code --] Было ORDER_STATUS_CONFIRMED ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_COMPLETED = 4; // [","content":"Плохой (Breaking) enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_APPROVED = 2; // [!code --] Было ORDER_STATUS_CONFIRMED ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_COMPLETED = 4; // [!code --] Было ORDER_STATUS_DELIVERED } ```"},{"id":"cli/breaking-changes/rules/enum-value-same-name::top::7","title":"ENUM_VALUE_SAME_NAME","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры **Множественные переименования:** ```proto // Before enum UserRole { USER_ROLE_UNSPECIFIED = 0; USER_ROLE_ADMIN = 1; USER_ROLE_MODERATOR = 2; USER_ROLE_USER = 3; }","content":"Дополнительные примеры **Множественные переименования:** ```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::top::8","title":"ENUM_VALUE_SAME_NAME","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры // After - ВСЁ BREAKING enum UserRole { USER_ROLE_UNSPECIFIED = 0; USER_ROLE_ADMINISTRATOR = 1; // BREAKING: ADMIN -> ADMINISTRATOR USER_ROLE_MOD = 2; // BREAKING: MODERATOR -> MOD USER_ROLE_MEMBER","content":"Дополнительные примеры // After - ВСЁ BREAKING 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::top::9","title":"ENUM_VALUE_SAME_NAME","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо переименования — добавить новые значения и пометить старые deprecated:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо переименования — добавить новые значения и пометить старые deprecated:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-value-same-name::top::10","title":"ENUM_VALUE_SAME_NAME","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/enum-value-same-name::top::11","title":"ENUM_VALUE_SAME_NAME","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) 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 [depre","content":"Хороший (Безопасный) 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] // Новое значение вместо переименования ORDER_STATUS_COMPLETED = 6; // [!code focus] } ```"},{"id":"cli/breaking-changes/rules/enum-value-same-name::top::12","title":"ENUM_VALUE_SAME_NAME","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Или создать новую версию enum:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Или создать новую версию enum:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-value-same-name::top::13","title":"ENUM_VALUE_SAME_NAME","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v2; // [!code focus]","content":"Хороший (Безопасный) package myapi.v2; // [!code focus]"},{"id":"cli/breaking-changes/rules/enum-value-same-name::top::14","title":"ENUM_VALUE_SAME_NAME","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_APPROVED = 2; // [!code focus] // «Чистые» имена в v2 ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_COMPLETED = 4; // ","content":"Хороший (Безопасный) enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_APPROVED = 2; // [!code focus] // «Чистые» имена в v2 ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_COMPLETED = 4; // [!code focus] } ```"},{"id":"cli/breaking-changes/rules/enum-value-same-name::top::15","title":"ENUM_VALUE_SAME_NAME","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Влияние"],"excerpt":"Влияние **Generated Code:** Меняются имена констант — компиляция клиентов ломается **JSON Compatibility:** JSON использует имена enum — старые документы не парсятся **Client Applications:** Код со старым именем константы","content":"Влияние **Generated Code:** Меняются имена констант — компиляция клиентов ломается **JSON Compatibility:** JSON использует имена enum — старые документы не парсятся **Client Applications:** Код со старым именем константы не компилируется **Documentation:** Документация устаревает с неправильными именами"},{"id":"cli/breaking-changes/rules/enum-value-same-name::top::16","title":"ENUM_VALUE_SAME_NAME","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Реальный пример"],"excerpt":"Реальный пример **Ломается код клиента:** ```go // Before status := myapi.OrderStatus_ORDER_STATUS_CONFIRMED if order.Status == myapi.OrderStatus_ORDER_STATUS_DELIVERED { // handle delivery }","content":"Реальный пример **Ломается код клиента:** ```go // Before 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::top::17","title":"ENUM_VALUE_SAME_NAME","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Реальный пример"],"excerpt":"Реальный пример // After (переименовано) — ошибки компиляции status := myapi.OrderStatus_ORDER_STATUS_CONFIRMED // ERROR: undefined if order.Status == myapi.OrderStatus_ORDER_STATUS_DELIVERED { // ERROR: undefined // han","content":"Реальный пример // After (переименовано) — ошибки компиляции status := myapi.OrderStatus_ORDER_STATUS_CONFIRMED // ERROR: undefined if order.Status == myapi.OrderStatus_ORDER_STATUS_DELIVERED { // ERROR: undefined // handle delivery } ```"},{"id":"cli/breaking-changes/rules/enum-value-same-name::top::18","title":"ENUM_VALUE_SAME_NAME","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Реальный пример"],"excerpt":"Реальный пример **JSON совместимость ломается:** ```json // Раньше { \"status\": \"ORDER_STATUS_CONFIRMED\" }","content":"Реальный пример **JSON совместимость ломается:** ```json // Раньше { \"status\": \"ORDER_STATUS_CONFIRMED\" }"},{"id":"cli/breaking-changes/rules/enum-value-same-name::top::19","title":"ENUM_VALUE_SAME_NAME","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Реальный пример"],"excerpt":"Реальный пример // После { \"status\": \"ORDER_STATUS_APPROVED\" // Старые JSON больше не парсятся } ```","content":"Реальный пример // После { \"status\": \"ORDER_STATUS_APPROVED\" // Старые JSON больше не парсятся } ```"},{"id":"cli/breaking-changes/rules/enum-value-same-name::top::20","title":"ENUM_VALUE_SAME_NAME","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Добавьте новое значение вместо переименования:**","content":"Стратегия миграции **Добавьте новое значение вместо переименования:**"},{"id":"cli/breaking-changes/rules/enum-value-same-name::top::21","title":"ENUM_VALUE_SAME_NAME","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Сервер обрабатывает оба значения на переходном этапе** **Мигрируйте клиентов** на новые значения **Удалите (reserve) старое имя и номер** в следующей major‑версии:","content":"Стратегия миграции **Сервер обрабатывает оба значения на переходном этапе** **Мигрируйте клиентов** на новые значения **Удалите (reserve) старое имя и номер** в следующей major‑версии:"},{"id":"cli/breaking-changes/rules/enum-value-same-name::allow-alias::22","title":"ENUM_VALUE_SAME_NAME","section":"Allow Alias (исключение)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name#allow-alias","headings":["Allow Alias (исключение)"],"excerpt":"Allow Alias (исключение) С allow_alias = true можно временно иметь два имени для одного номера:","content":"Allow Alias (исключение) С allow_alias = true можно временно иметь два имени для одного номера:"},{"id":"cli/breaking-changes/rules/enum-value-same-name::allow-alias::23","title":"ENUM_VALUE_SAME_NAME","section":"Allow Alias (исключение)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name#allow-alias","headings":["Allow Alias (исключение)"],"excerpt":"Allow Alias (исключение) Примечание: Сейчас EasyP всё равно считает это breaking (может измениться в будущем).","content":"Allow Alias (исключение) Примечание: Сейчас EasyP всё равно считает это breaking (может измениться в будущем)."},{"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":"Это правило проверяет, что ни одно поле сообщения (message field) не было удалено. Удаление поля ломает совместимость по wire‑формату и сгенерированный код: в существующих данных может присутствовать удалённое поле, а кл","content":"Это правило проверяет, что ни одно поле сообщения (message field) не было удалено. Удаление поля ломает совместимость по wire‑формату и сгенерированный код: в существующих данных может присутствовать удалённое поле, а клиентский код может ссылаться на него."},{"id":"cli/breaking-changes/rules/field-no-delete::breaking::1","title":"FIELD_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-no-delete::breaking::2","title":"FIELD_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/field-no-delete::breaking::3","title":"FIELD_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message User { string name = 1; string email = 2; int32 age = 3; string phone = 4; // [!code --] } ```","content":"Плохой (Breaking) message User { string name = 1; string email = 2; int32 age = 3; string phone = 4; // [!code --] } ```"},{"id":"cli/breaking-changes/rules/field-no-delete::breaking::4","title":"FIELD_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-no-delete::breaking::5","title":"FIELD_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/field-no-delete::breaking::6","title":"FIELD_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message User { string name = 1; string email = 2; int32 age = 3; // phone поле удалено — BREAKING CHANGE! } ```","content":"Плохой (Breaking) message User { string name = 1; string email = 2; int32 age = 3; // phone поле удалено — BREAKING CHANGE! } ```"},{"id":"cli/breaking-changes/rules/field-no-delete::top::7","title":"FIELD_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо удаления — пометить поле deprecated:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо удаления — пометить поле deprecated:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-no-delete::top::8","title":"FIELD_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/field-no-delete::top::9","title":"FIELD_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message User { string name = 1; string email = 2; int32 age = 3; string phone = 4 [deprecated = true]; // [!code focus] } ```","content":"Хороший (Безопасный) 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::top::10","title":"FIELD_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Или зарезервировать номер и имя поля после удаления:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Или зарезервировать номер и имя поля после удаления:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-no-delete::top::11","title":"FIELD_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/field-no-delete::top::12","title":"FIELD_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message User { reserved 4; // [!code focus] reserved \"phone\"; // [!code focus] string name = 1; string email = 2; int32 age = 3; } ```","content":"Хороший (Безопасный) 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::top::13","title":"FIELD_NO_DELETE","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete","headings":["Влияние"],"excerpt":"Влияние **Wire Format:** Старые сообщения с удалённым полем некорректно десериализуются **Generated Code:** Удаляются аксессоры (get/set), компиляция клиента ломается **Data Loss:** Потеря сохранённых данных, связанных с","content":"Влияние **Wire Format:** Старые сообщения с удалённым полем некорректно десериализуются **Generated Code:** Удаляются аксессоры (get/set), компиляция клиента ломается **Data Loss:** Потеря сохранённых данных, связанных с полем **JSON Compatibility:** JSON парсеры ожидают наличие поля и могут выдавать ошибки"},{"id":"cli/breaking-changes/rules/field-no-delete::top::14","title":"FIELD_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Сначала пометить deprecated:**","content":"Стратегия миграции **Сначала пометить deprecated:**"},{"id":"cli/breaking-changes/rules/field-no-delete::top::15","title":"FIELD_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Прекратить запись в поле** в прикладном коде","content":"Стратегия миграции **Прекратить запись в поле** в прикладном коде"},{"id":"cli/breaking-changes/rules/field-no-delete::top::16","title":"FIELD_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Зарезервировать поле** в следующей версии, чтобы избежать повторного использования:","content":"Стратегия миграции **Зарезервировать поле** в следующей версии, чтобы избежать повторного использования:"},{"id":"cli/breaking-changes/rules/field-no-delete::top::17","title":"FIELD_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Никогда не переиспользовать номер поля** — должен оставаться в reserved навсегда","content":"Стратегия миграции **Никогда не переиспользовать номер поля** — должен оставаться в reserved навсегда"},{"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":"Правило проверяет, что поля сообщений сохраняют ту же кардинальность (обязательность / optional). Изменение кардинальности поля ломает совместимость по wire‑формату и сгенерированный код: семантика присутствия и ожидания","content":"Правило проверяет, что поля сообщений сохраняют ту же кардинальность (обязательность / optional). Изменение кардинальности поля ломает совместимость по wire‑формату и сгенерированный код: семантика присутствия и ожидания клиентского кода отличаются для optional и required (implicit) полей."},{"id":"cli/breaking-changes/rules/field-same-cardinality::breaking::1","title":"FIELD_SAME_CARDINALITY","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-same-cardinality::breaking::2","title":"FIELD_SAME_CARDINALITY","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/field-same-cardinality::breaking::3","title":"FIELD_SAME_CARDINALITY","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message User { string name = 1; string email = 2; int32 age = 3; }","content":"Плохой (Breaking) message User { string name = 1; string email = 2; int32 age = 3; }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::breaking::4","title":"FIELD_SAME_CARDINALITY","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message CreateUserRequest { string name = 1; optional string email = 2; string phone = 3; } ```","content":"Плохой (Breaking) message CreateUserRequest { string name = 1; optional string email = 2; string phone = 3; } ```"},{"id":"cli/breaking-changes/rules/field-same-cardinality::breaking::5","title":"FIELD_SAME_CARDINALITY","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-same-cardinality::breaking::6","title":"FIELD_SAME_CARDINALITY","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/field-same-cardinality::breaking::7","title":"FIELD_SAME_CARDINALITY","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message User { string name = 1; optional string email = 2; // [!code --] Было required (implicit), стало optional int32 age = 3; }","content":"Плохой (Breaking) message User { string name = 1; optional string email = 2; // [!code --] Было required (implicit), стало optional int32 age = 3; }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::breaking::8","title":"FIELD_SAME_CARDINALITY","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message CreateUserRequest { string name = 1; string email = 2; // [!code --] Было optional, стало требуемым (implicit required) string phone = 3; } ```","content":"Плохой (Breaking) message CreateUserRequest { string name = 1; string email = 2; // [!code --] Было optional, стало требуемым (implicit required) string phone = 3; } ```"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::9","title":"FIELD_SAME_CARDINALITY","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры **Проблемы миграции Proto2 → Proto3:**","content":"Дополнительные примеры **Проблемы миграции Proto2 → Proto3:**"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::10","title":"FIELD_SAME_CARDINALITY","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры ```proto // Before (proto2) syntax = \"proto2\";","content":"Дополнительные примеры ```proto // Before (proto2) syntax = \"proto2\";"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::11","title":"FIELD_SAME_CARDINALITY","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры message Order { required string id = 1; optional string notes = 2; repeated string tags = 3; }","content":"Дополнительные примеры message Order { required string id = 1; optional string notes = 2; repeated string tags = 3; }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::12","title":"FIELD_SAME_CARDINALITY","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры // After (proto3) - BREAKING CHANGES! syntax = \"proto3\";","content":"Дополнительные примеры // After (proto3) - BREAKING CHANGES! syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::13","title":"FIELD_SAME_CARDINALITY","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры message Order { string id = 1; // BREAKING: required -> implicit optional string notes = 2; // BREAKING: explicit optional -> implicit optional repeated string tags = 3; // OK } ```","content":"Дополнительные примеры message Order { string id = 1; // BREAKING: required -> implicit optional string notes = 2; // BREAKING: explicit optional -> implicit optional repeated string tags = 3; // OK } ```"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::14","title":"FIELD_SAME_CARDINALITY","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо изменения кардинальности — добавьте новое поле:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо изменения кардинальности — добавьте новое поле:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::15","title":"FIELD_SAME_CARDINALITY","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::16","title":"FIELD_SAME_CARDINALITY","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message User { string name = 1; string email = 2 [deprecated = true]; // [!code focus] Сохраняем старую кардинальность int32 age = 3; optional string email_optional = 4; // [!code focus] Новое option","content":"Хороший (Безопасный) message User { string name = 1; string email = 2 [deprecated = true]; // [!code focus] Сохраняем старую кардинальность int32 age = 3; optional string email_optional = 4; // [!code focus] Новое optional поле }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::17","title":"FIELD_SAME_CARDINALITY","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message CreateUserRequest { string name = 1; optional string email = 2 [deprecated = true]; // [!code focus] string phone = 3; string email_required = 4; // [!code focus] Новое требуемое поле } ```","content":"Хороший (Безопасный) message CreateUserRequest { string name = 1; optional string email = 2 [deprecated = true]; // [!code focus] string phone = 3; string email_required = 4; // [!code focus] Новое требуемое поле } ```"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::18","title":"FIELD_SAME_CARDINALITY","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Или создайте новую версию сообщения:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Или создайте новую версию сообщения:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::19","title":"FIELD_SAME_CARDINALITY","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v2; // [!code focus]","content":"Хороший (Безопасный) package myapi.v2; // [!code focus]"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::20","title":"FIELD_SAME_CARDINALITY","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message User { string name = 1; optional string email = 2; // [!code focus] Чистая модель в v2 int32 age = 3; }","content":"Хороший (Безопасный) message User { string name = 1; optional string email = 2; // [!code focus] Чистая модель в v2 int32 age = 3; }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::21","title":"FIELD_SAME_CARDINALITY","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message CreateUserRequest { string name = 1; string email = 2; // [!code focus] Требуемое в v2 string phone = 3; } ```","content":"Хороший (Безопасный) message CreateUserRequest { string name = 1; string email = 2; // [!code focus] Требуемое в v2 string phone = 3; } ```"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::22","title":"FIELD_SAME_CARDINALITY","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Влияние"],"excerpt":"Влияние **Wire Format:** Меняется семантика присутствия — клиенты неправильно ожидают поля **Generated Code:** Меняются методы доступа / проверки (has, clear) **Validation:** Правила проверки обязательности переписываютс","content":"Влияние **Wire Format:** Меняется семантика присутствия — клиенты неправильно ожидают поля **Generated Code:** Меняются методы доступа / проверки (has, clear) **Validation:** Правила проверки обязательности переписываются **Default Values:** Optional и required по‑разному обрабатывают отсутствие значения"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::23","title":"FIELD_SAME_CARDINALITY","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Реальный пример"],"excerpt":"Реальный пример **Код клиента ломается при смене кардинальности:** ```go // Before - поле фактически требуется (implicit) user := &myapi.User{ Name: \"John\", Email: \"john@example.com\", Age: 30, }","content":"Реальный пример **Код клиента ломается при смене кардинальности:** ```go // Before - поле фактически требуется (implicit) user := &myapi.User{ Name: \"John\", Email: \"john@example.com\", Age: 30, }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::24","title":"FIELD_SAME_CARDINALITY","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Реальный пример"],"excerpt":"Реальный пример if user.Email != \"\" { // Есть значение }","content":"Реальный пример if user.Email != \"\" { // Есть значение }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::25","title":"FIELD_SAME_CARDINALITY","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Реальный пример"],"excerpt":"Реальный пример // After - поле стало optional (pointer) user := &myapi.User{ Name: \"John\", Age: 30, // Email может отсутствовать }","content":"Реальный пример // After - поле стало optional (pointer) user := &myapi.User{ Name: \"John\", Age: 30, // Email может отсутствовать }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::26","title":"FIELD_SAME_CARDINALITY","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Реальный пример"],"excerpt":"Реальный пример if user.Email != nil && *user.Email != \"\" { // Есть значение (новый способ) }","content":"Реальный пример if user.Email != nil && *user.Email != \"\" { // Есть значение (новый способ) }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::27","title":"FIELD_SAME_CARDINALITY","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Реальный пример"],"excerpt":"Реальный пример user.Email = &emailValue // Присваивание указателя вместо строки ```","content":"Реальный пример user.Email = &emailValue // Присваивание указателя вместо строки ```"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::28","title":"FIELD_SAME_CARDINALITY","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Реальный пример"],"excerpt":"Реальный пример **Валидация на сервере:** ```go // Before func validateUser(user *User) error { if user.Email == \"\" { return errors.New(\"email is required\") } return nil }","content":"Реальный пример **Валидация на сервере:** ```go // Before func validateUser(user *User) error { if user.Email == \"\" { return errors.New(\"email is required\") } return nil }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::29","title":"FIELD_SAME_CARDINALITY","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Реальный пример"],"excerpt":"Реальный пример // After func validateUser(user *User) error { if user.Email == nil { return errors.New(\"email is required\") } if *user.Email == \"\" { return errors.New(\"email cannot be empty\") } return nil } ```","content":"Реальный пример // After func validateUser(user *User) error { if user.Email == nil { return errors.New(\"email is required\") } if *user.Email == \"\" { return errors.New(\"email cannot be empty\") } return nil } ```"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::30","title":"FIELD_SAME_CARDINALITY","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Добавьте новое поле** с нужной кардинальностью:","content":"Стратегия миграции **Добавьте новое поле** с нужной кардинальностью:"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::31","title":"FIELD_SAME_CARDINALITY","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Период двойной записи** — заполняйте оба поля:","content":"Стратегия миграции **Период двойной записи** — заполняйте оба поля:"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::32","title":"FIELD_SAME_CARDINALITY","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Клиенты постепенно переходят**:","content":"Стратегия миграции **Клиенты постепенно переходят**:"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::33","title":"FIELD_SAME_CARDINALITY","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Удаление старого поля** в следующей major‑версии:","content":"Стратегия миграции **Удаление старого поля** в следующей major‑версии:"},{"id":"cli/breaking-changes/rules/field-same-cardinality::proto2-proto3::34","title":"FIELD_SAME_CARDINALITY","section":"Миграция Proto2 → Proto3","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#proto2-proto3","headings":["Миграция Proto2 → Proto3"],"excerpt":"Миграция Proto2 → Proto3 ```proto syntax = \"proto3\"; message Order { string id = 1; // BREAKING если был required }","content":"Миграция Proto2 → Proto3 ```proto syntax = \"proto3\"; message Order { string id = 1; // BREAKING если был required }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::proto2-proto3::35","title":"FIELD_SAME_CARDINALITY","section":"Миграция Proto2 → Proto3","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#proto2-proto3","headings":["Миграция Proto2 → Proto3"],"excerpt":"Миграция Proto2 → Proto3 // Сохранить семантику: syntax = \"proto3\"; message Order { string id = 1; optional string notes = 2; } ```","content":"Миграция Proto2 → Proto3 // Сохранить семантику: syntax = \"proto3\"; message Order { string id = 1; optional string notes = 2; } ```"},{"id":"cli/breaking-changes/rules/field-same-cardinality::optional-required::36","title":"FIELD_SAME_CARDINALITY","section":"Делать optional поле required","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#optional-required","headings":["Делать optional поле required"],"excerpt":"Делать optional поле required ```proto message CreateUserRequest { string name = 1; string email = 2; // BREAKING (раньше optional) }","content":"Делать optional поле required ```proto message CreateUserRequest { string name = 1; string email = 2; // BREAKING (раньше optional) }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::optional-required::37","title":"FIELD_SAME_CARDINALITY","section":"Делать optional поле required","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#optional-required","headings":["Делать optional поле required"],"excerpt":"Делать optional поле required message CreateUserRequest { string name = 1; optional string email = 2 [deprecated = true]; string required_email = 3; } ```","content":"Делать optional поле required message CreateUserRequest { string name = 1; optional string email = 2 [deprecated = true]; string required_email = 3; } ```"},{"id":"cli/breaking-changes/rules/field-same-cardinality::required-optional::38","title":"FIELD_SAME_CARDINALITY","section":"Делать required поле optional","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#required-optional","headings":["Делать required поле optional"],"excerpt":"Делать required поле optional ```proto message User { optional string phone = 3; // BREAKING (было implicit required) }","content":"Делать required поле optional ```proto message User { optional string phone = 3; // BREAKING (было implicit required) }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::required-optional::39","title":"FIELD_SAME_CARDINALITY","section":"Делать required поле optional","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#required-optional","headings":["Делать required поле optional"],"excerpt":"Делать required поле optional message User { string phone = 3 [deprecated = true]; optional string phone_optional = 4; } ```","content":"Делать required поле optional message User { string phone = 3 [deprecated = true]; optional string phone_optional = 4; } ```"},{"id":"cli/breaking-changes/rules/field-same-cardinality::protobuf::40","title":"FIELD_SAME_CARDINALITY","section":"Типы кардинальности в Protobuf","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#protobuf","headings":["Типы кардинальности в Protobuf"],"excerpt":"Типы кардинальности в Protobuf","content":"Типы кардинальности в Protobuf"},{"id":"cli/breaking-changes/rules/field-same-cardinality::proto3::41","title":"FIELD_SAME_CARDINALITY","section":"Proto3","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#proto3","headings":["Proto3"],"excerpt":"Proto3 **Implicit optional**: string name = 1; **Explicit optional**: optional string email = 2; **Repeated**: repeated string tags = 3; **Map**: map metadata = 4;","content":"Proto3 **Implicit optional**: string name = 1; **Explicit optional**: optional string email = 2; **Repeated**: repeated string tags = 3; **Map**: map metadata = 4;"},{"id":"cli/breaking-changes/rules/field-same-cardinality::proto2::42","title":"FIELD_SAME_CARDINALITY","section":"Proto2","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#proto2","headings":["Proto2"],"excerpt":"Proto2 **Required**: required string id = 1; **Optional**: optional string email = 2; **Repeated**: repeated string tags = 3;","content":"Proto2 **Required**: required string id = 1; **Optional**: optional string email = 2; **Repeated**: repeated string tags = 3;"},{"id":"cli/breaking-changes/rules/field-same-cardinality::breaking::43","title":"FIELD_SAME_CARDINALITY","section":"Матрица Breaking изменений","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#breaking","headings":["Матрица Breaking изменений"],"excerpt":"Матрица Breaking изменений From To Result ------ ---- -------- Required Optional ❌ BREAKING Optional Required ❌ BREAKING Implicit Explicit ❌ BREAKING Explicit Implicit ❌ BREAKING Single Repeated ❌ BREAKING Repeated Singl","content":"Матрица Breaking изменений 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":"Правило проверяет, что типы полей сообщений (message fields) не изменяются. Смена типа поля ломает совместимость по wire‑формату и сгенерированный код: бинарное представление и ожидания клиентского кода различаются для р","content":"Правило проверяет, что типы полей сообщений (message fields) не изменяются. Смена типа поля ломает совместимость по wire‑формату и сгенерированный код: бинарное представление и ожидания клиентского кода различаются для разных типов."},{"id":"cli/breaking-changes/rules/field-same-type::breaking::1","title":"FIELD_SAME_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-same-type::breaking::2","title":"FIELD_SAME_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/field-same-type::breaking::3","title":"FIELD_SAME_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message Product { string name = 1; int32 price = 2; bool available = 3; } ```","content":"Плохой (Breaking) message Product { string name = 1; int32 price = 2; bool available = 3; } ```"},{"id":"cli/breaking-changes/rules/field-same-type::breaking::4","title":"FIELD_SAME_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-same-type::breaking::5","title":"FIELD_SAME_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/field-same-type::breaking::6","title":"FIELD_SAME_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message Product { string name = 1; string price = 2; // [!code --] Changed from int32 to string (изменён тип) bool available = 3; } ```","content":"Плохой (Breaking) 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::top::7","title":"FIELD_SAME_TYPE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/field-same-type","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры **Несовместимые изменения типов:** ```proto // Before message Order { string id = 1; int64 timestamp = 2; repeated string tags = 3; OrderStatus status = 4; }","content":"Дополнительные примеры **Несовместимые изменения типов:** ```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::top::8","title":"FIELD_SAME_TYPE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/field-same-type","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры // After - ВСЁ BREAKING message Order { int32 id = 1; // string -> int32: BREAKING string timestamp = 2; // int64 -> string: BREAKING string tags = 3; // repeated -> singular: BREAKING int32 status","content":"Дополнительные примеры // After - ВСЁ BREAKING 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::top::9","title":"FIELD_SAME_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо смены типа — добавьте новое поле:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо смены типа — добавьте новое поле:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-same-type::top::10","title":"FIELD_SAME_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/field-same-type::top::11","title":"FIELD_SAME_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message Product { string name = 1; int32 price = 2 [deprecated = true]; // [!code focus] // Старое поле помечено deprecated bool available = 3; string price_formatted = 4; // [!code focus] // Новое п","content":"Хороший (Безопасный) message Product { string name = 1; int32 price = 2 [deprecated = true]; // [!code focus] // Старое поле помечено deprecated bool available = 3; string price_formatted = 4; // [!code focus] // Новое поле со строковым представлением } ```"},{"id":"cli/breaking-changes/rules/field-same-type::top::12","title":"FIELD_SAME_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Или создайте новую версию сообщения:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Или создайте новую версию сообщения:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-same-type::top::13","title":"FIELD_SAME_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v2; // [!code focus] // Новая версия package","content":"Хороший (Безопасный) package myapi.v2; // [!code focus] // Новая версия package"},{"id":"cli/breaking-changes/rules/field-same-type::top::14","title":"FIELD_SAME_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message Product { string name = 1; string price = 2; // [!code focus] // В v2 уже string bool available = 3; } ```","content":"Хороший (Безопасный) message Product { string name = 1; string price = 2; // [!code focus] // В v2 уже string bool available = 3; } ```"},{"id":"cli/breaking-changes/rules/field-same-type::top::15","title":"FIELD_SAME_TYPE","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/field-same-type","headings":["Влияние"],"excerpt":"Влияние **Wire Format:** Старые бинарные данные не десериализуются корректно **Generated Code:** Меняются типы в сгенерированном коде — клиенты не компилируются **Runtime Errors:** Ошибки парсинга при несовпадении ожидае","content":"Влияние **Wire Format:** Старые бинарные данные не десериализуются корректно **Generated Code:** Меняются типы в сгенерированном коде — клиенты не компилируются **Runtime Errors:** Ошибки парсинга при несовпадении ожидаемого типа **Data Corruption:** Неверная интерпретация байтов данных"},{"id":"cli/breaking-changes/rules/field-same-type::top::16","title":"FIELD_SAME_TYPE","section":"Типовые проблемы изменений типов","path":"/docs/guide/cli/breaking-changes/rules/field-same-type","headings":["Типовые проблемы изменений типов"],"excerpt":"Типовые проблемы изменений типов","content":"Типовые проблемы изменений типов"},{"id":"cli/breaking-changes/rules/field-same-type::top::17","title":"FIELD_SAME_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/field-same-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Добавьте новое поле** с нужным типом:","content":"Стратегия миграции **Добавьте новое поле** с нужным типом:"},{"id":"cli/breaking-changes/rules/field-same-type::top::18","title":"FIELD_SAME_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/field-same-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Период двойной записи** — заполняйте оба поля для совместимости","content":"Стратегия миграции **Период двойной записи** — заполняйте оба поля для совместимости"},{"id":"cli/breaking-changes/rules/field-same-type::top::19","title":"FIELD_SAME_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/field-same-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Мигрируйте клиентов** на новое поле постепенно","content":"Стратегия миграции **Мигрируйте клиентов** на новое поле постепенно"},{"id":"cli/breaking-changes/rules/field-same-type::top::20","title":"FIELD_SAME_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/field-same-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Удалите старое поле** в следующей major‑версии:","content":"Стратегия миграции **Удалите старое поле** в следующей major‑версии:"},{"id":"cli/breaking-changes/rules/field-same-type::wire::21","title":"FIELD_SAME_TYPE","section":"Безопасные изменения (Теоретически wire‑совместимые)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type#wire","headings":["Безопасные изменения (Теоретически wire‑совместимые)"],"excerpt":"Безопасные изменения (Теоретически wire‑совместимые) Примечание: EasyP сейчас считает ЛЮБУЮ смену типа breaking. Однако технически некоторые случаи совместимы:","content":"Безопасные изменения (Теоретически wire‑совместимые) Примечание: EasyP сейчас считает ЛЮБУЮ смену типа breaking. Однако технически некоторые случаи совместимы:"},{"id":"cli/breaking-changes/rules/field-same-type::wire::22","title":"FIELD_SAME_TYPE","section":"Безопасные изменения (Теоретически wire‑совместимые)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type#wire","headings":["Безопасные изменения (Теоретически wire‑совместимые)"],"excerpt":"Безопасные изменения (Теоретически wire‑совместимые) int32 ↔ uint32 (одно кодирование) int64 ↔ uint64 (одно кодирование) string → bytes (если все строки валидный UTF‑8)","content":"Безопасные изменения (Теоретически wire‑совместимые) int32 ↔ uint32 (одно кодирование) int64 ↔ uint64 (одно кодирование) string → bytes (если все строки валидный UTF‑8)"},{"id":"cli/breaking-changes/rules/field-same-type::wire::23","title":"FIELD_SAME_TYPE","section":"Безопасные изменения (Теоретически wire‑совместимые)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type#wire","headings":["Безопасные изменения (Теоретически wire‑совместимые)"],"excerpt":"Безопасные изменения (Теоретически wire‑совместимые) Эти исключения могут получить отдельную обработку в будущих версиях EasyP с более гибкими уровнями строгости.","content":"Безопасные изменения (Теоретически wire‑совместимые) Эти исключения могут получить отдельную обработку в будущих версиях EasyP с более гибкими уровнями строгости."},{"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":"Это правило проверяет, что ни одна инструкция import не была удалена из proto‑файла. Удаление import ломает совместимость по wire‑формату и сгенерированный код: типы из импортируемых файлов могли использоваться в текущем","content":"Это правило проверяет, что ни одна инструкция import не была удалена из proto‑файла. Удаление import ломает совместимость по wire‑формату и сгенерированный код: типы из импортируемых файлов могли использоваться в текущем файле, и их удаление делает эти типы недоступными."},{"id":"cli/breaking-changes/rules/import-no-delete::breaking::1","title":"IMPORT_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/import-no-delete::breaking::2","title":"IMPORT_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/import-no-delete::breaking::3","title":"IMPORT_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) import \"google/protobuf/timestamp.proto\"; import \"google/protobuf/duration.proto\"; import \"common/user.proto\"; import \"common/address.proto\";","content":"Плохой (Breaking) 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::breaking::4","title":"IMPORT_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) 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":"Плохой (Breaking) 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::breaking::5","title":"IMPORT_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/import-no-delete::breaking::6","title":"IMPORT_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/import-no-delete::breaking::7","title":"IMPORT_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) import \"google/protobuf/timestamp.proto\"; // import \"google/protobuf/duration.proto\"; // [!code --] Удалён import — BREAKING // import \"common/user.proto\"; // [!code --] Удалён import — BREAKING // impo","content":"Плохой (Breaking) import \"google/protobuf/timestamp.proto\"; // import \"google/protobuf/duration.proto\"; // [!code --] Удалён import — BREAKING // import \"common/user.proto\"; // [!code --] Удалён import — BREAKING // import \"common/address.proto\"; // [!code --] Удалён import — BREAKING"},{"id":"cli/breaking-changes/rules/import-no-delete::breaking::8","title":"IMPORT_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message Order { string id = 1; google.protobuf.Timestamp created_at = 2; google.protobuf.Duration processing_time = 3; // ERROR: Duration недоступен common.User customer = 4; // ERROR: User недоступен c","content":"Плохой (Breaking) message Order { string id = 1; google.protobuf.Timestamp created_at = 2; google.protobuf.Duration processing_time = 3; // ERROR: Duration недоступен common.User customer = 4; // ERROR: User недоступен common.Address shipping_address = 5; // ERROR: Address недоступен } ```"},{"id":"cli/breaking-changes/rules/import-no-delete::top::9","title":"IMPORT_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры **Сервис ломается при удалённых import:** ```proto // Before import \"google/api/annotations.proto\"; import \"google/protobuf/empty.proto\"; import \"common/auth.proto\";","content":"Дополнительные примеры **Сервис ломается при удалённых import:** ```proto // Before import \"google/api/annotations.proto\"; import \"google/protobuf/empty.proto\"; import \"common/auth.proto\";"},{"id":"cli/breaking-changes/rules/import-no-delete::top::10","title":"IMPORT_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры service OrderService { rpc GetOrder(GetOrderRequest) returns (Order) { option (google.api.http) = { get: \"/v1/orders/{id}\" }; } rpc DeleteOrder(common.AuthRequest) returns (google.protobuf.Empty); ","content":"Дополнительные примеры 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::top::11","title":"IMPORT_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры // After - BREAKING CHANGES! // import \"google/api/annotations.proto\"; // BREAKING: deleted // import \"google/protobuf/empty.proto\"; // BREAKING: deleted // import \"common/auth.proto\"; // BREAKING:","content":"Дополнительные примеры // 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::top::12","title":"IMPORT_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры service OrderService { rpc GetOrder(GetOrderRequest) returns (Order) { option (google.api.http) = { // ERROR: annotations недоступен get: \"/v1/orders/{id}\" }; } rpc DeleteOrder(common.AuthRequest) ","content":"Дополнительные примеры service OrderService { rpc GetOrder(GetOrderRequest) returns (Order) { option (google.api.http) = { // ERROR: annotations недоступен get: \"/v1/orders/{id}\" }; } rpc DeleteOrder(common.AuthRequest) returns (google.protobuf.Empty); // ERROR: типы недоступны } ```"},{"id":"cli/breaking-changes/rules/import-no-delete::top::13","title":"IMPORT_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо удаления оставьте неиспользуемые import:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо удаления оставьте неиспользуемые import:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/import-no-delete::top::14","title":"IMPORT_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/import-no-delete::top::15","title":"IMPORT_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) import \"google/protobuf/timestamp.proto\"; import \"google/protobuf/duration.proto\"; // [!code focus] // Оставляем даже если не используется import \"common/user.proto\"; // [!code focus] import \"common/","content":"Хороший (Безопасный) import \"google/protobuf/timestamp.proto\"; import \"google/protobuf/duration.proto\"; // [!code focus] // Оставляем даже если не используется import \"common/user.proto\"; // [!code focus] import \"common/address.proto\"; // [!code focus]"},{"id":"cli/breaking-changes/rules/import-no-delete::top::16","title":"IMPORT_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message Order { string id = 1; google.protobuf.Timestamp created_at = 2; // Поля, использовавшие Duration/User/Address, удалены — import оставлены } ```","content":"Хороший (Безопасный) message Order { string id = 1; google.protobuf.Timestamp created_at = 2; // Поля, использовавшие Duration/User/Address, удалены — import оставлены } ```"},{"id":"cli/breaking-changes/rules/import-no-delete::top::17","title":"IMPORT_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Или добавьте новые типы, сохранив старые import:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Или добавьте новые типы, сохранив старые import:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/import-no-delete::top::18","title":"IMPORT_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/import-no-delete::top::19","title":"IMPORT_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) import \"google/protobuf/timestamp.proto\"; import \"google/protobuf/duration.proto\"; // [!code focus] import \"common/user.proto\"; // [!code focus] import \"common/address.proto\"; // [!code focus] import","content":"Хороший (Безопасный) import \"google/protobuf/timestamp.proto\"; import \"google/protobuf/duration.proto\"; // [!code focus] import \"common/user.proto\"; // [!code focus] import \"common/address.proto\"; // [!code focus] import \"common/v2/user.proto\"; // [!code focus] // Новый import"},{"id":"cli/breaking-changes/rules/import-no-delete::top::20","title":"IMPORT_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message Order { string id = 1; google.protobuf.Timestamp created_at = 2; google.protobuf.Duration processing_time = 3 [deprecated = true]; // [!code focus] common.User customer = 4 [deprecated = true","content":"Хороший (Безопасный) message Order { string id = 1; google.protobuf.Timestamp created_at = 2; google.protobuf.Duration processing_time = 3 [deprecated = true]; // [!code focus] common.User customer = 4 [deprecated = true]; // [!code focus] common.Address shipping_address = 5 [deprecated = true]; // [!code focus] int32 processing_seconds = 6; common.v2.UserProfile customer_v2 = 7; string shipping_address_text = 8; } ```"},{"id":"cli/breaking-changes/rules/import-no-delete::top::21","title":"IMPORT_NO_DELETE","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Влияние"],"excerpt":"Влияние **Generated Code:** Типы пропадают → ошибка компиляции **Wire Format:** Сообщения с удалёнными типами не десериализуются **Field References:** Поля с этими типами становятся невалидны **Service Definitions:** RPC","content":"Влияние **Generated Code:** Типы пропадают → ошибка компиляции **Wire Format:** Сообщения с удалёнными типами не десериализуются **Field References:** Поля с этими типами становятся невалидны **Service Definitions:** RPC с типами из удалённых файлов ломаются **Options Usage:** Пользовательские опции из импортов недоступны"},{"id":"cli/breaking-changes/rules/import-no-delete::top::22","title":"IMPORT_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Код клиента ломается:**","content":"Реальный пример **Код клиента ломается:**"},{"id":"cli/breaking-changes/rules/import-no-delete::top::23","title":"IMPORT_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Серверная логика ломается:**","content":"Реальный пример **Серверная логика ломается:**"},{"id":"cli/breaking-changes/rules/import-no-delete::top::24","title":"IMPORT_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Компиляция proto ломается:**","content":"Реальный пример **Компиляция proto ломается:**"},{"id":"cli/breaking-changes/rules/import-no-delete::top::25","title":"IMPORT_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции Сохраняйте import даже если типы более не используются: Добавляйте новые import рядом со старыми: Депрецируйте поля со старыми типами постепенно: Сервер: поддерживайте оба варианта: Удаляйте import тол","content":"Стратегия миграции Сохраняйте import даже если типы более не используются: Добавляйте новые import рядом со старыми: Депрецируйте поля со старыми типами постепенно: Сервер: поддерживайте оба варианта: Удаляйте import только в следующей major‑версии после полной миграции."},{"id":"cli/breaking-changes/rules/import-no-delete::top::26","title":"IMPORT_NO_DELETE","section":"Замена зависимости","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Замена зависимости"],"excerpt":"Замена зависимости ```proto import \"old/user.proto\"; // Старый import \"new/user.proto\"; // Новый","content":"Замена зависимости ```proto import \"old/user.proto\"; // Старый import \"new/user.proto\"; // Новый"},{"id":"cli/breaking-changes/rules/import-no-delete::top::27","title":"IMPORT_NO_DELETE","section":"Замена зависимости","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Замена зависимости"],"excerpt":"Замена зависимости message Order { old.User customer = 4 [deprecated = true]; new.UserProfile customer_v2 = 5; } ```","content":"Замена зависимости message Order { old.User customer = 4 [deprecated = true]; new.UserProfile customer_v2 = 5; } ```"},{"id":"cli/breaking-changes/rules/import-no-delete::top::28","title":"IMPORT_NO_DELETE","section":"Удаление функционала","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Удаление функционала"],"excerpt":"Удаление функционала ```proto import \"feature/analytics.proto\"; // Оставить даже если поле удалено","content":"Удаление функционала ```proto import \"feature/analytics.proto\"; // Оставить даже если поле удалено"},{"id":"cli/breaking-changes/rules/import-no-delete::top::29","title":"IMPORT_NO_DELETE","section":"Удаление функционала","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Удаление функционала"],"excerpt":"Удаление функционала message Order { string id = 1; // feature.AnalyticsData analytics = 2; // Поле удалено, import остаётся } ```","content":"Удаление функционала message Order { string id = 1; // feature.AnalyticsData analytics = 2; // Поле удалено, import остаётся } ```"},{"id":"cli/breaking-changes/rules/import-no-delete::protobuf::30","title":"IMPORT_NO_DELETE","section":"Миграция версии protobuf","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#protobuf","headings":["Миграция версии protobuf"],"excerpt":"Миграция версии protobuf ```proto import \"google/protobuf/timestamp.proto\"; import \"google/protobuf/duration.proto\";","content":"Миграция версии protobuf ```proto import \"google/protobuf/timestamp.proto\"; import \"google/protobuf/duration.proto\";"},{"id":"cli/breaking-changes/rules/import-no-delete::protobuf::31","title":"IMPORT_NO_DELETE","section":"Миграция версии protobuf","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#protobuf","headings":["Миграция версии protobuf"],"excerpt":"Миграция версии protobuf message Event { google.protobuf.Timestamp timestamp = 1; int64 timestamp_millis = 2; } ```","content":"Миграция версии protobuf message Event { google.protobuf.Timestamp timestamp = 1; int64 timestamp_millis = 2; } ```"},{"id":"cli/breaking-changes/rules/import-no-delete::top::32","title":"IMPORT_NO_DELETE","section":"Упрощение сложных зависимостей","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Упрощение сложных зависимостей"],"excerpt":"Упрощение сложных зависимостей ```proto import \"complex/config.proto\";","content":"Упрощение сложных зависимостей ```proto import \"complex/config.proto\";"},{"id":"cli/breaking-changes/rules/import-no-delete::top::33","title":"IMPORT_NO_DELETE","section":"Упрощение сложных зависимостей","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Упрощение сложных зависимостей"],"excerpt":"Упрощение сложных зависимостей message Settings { complex.ConfigData config = 1 [deprecated = true]; string config_json = 2; } ```","content":"Упрощение сложных зависимостей message Settings { complex.ConfigData config = 1 [deprecated = true]; string config_json = 2; } ```"},{"id":"cli/breaking-changes/rules/import-no-delete::import-vs::34","title":"IMPORT_NO_DELETE","section":"Удаление import vs использование поля","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#import-vs","headings":["Удаление import vs использование поля"],"excerpt":"Удаление import vs использование поля","content":"Удаление import vs использование поля"},{"id":"cli/breaking-changes/rules/import-no-delete::import::35","title":"IMPORT_NO_DELETE","section":"Аудит import","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#import","headings":["Аудит import"],"excerpt":"Аудит import (Даже если не найдено — не удаляем.)","content":"Аудит 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":"Это правило проверяет, что ни одно сообщение (message) не было удалено из proto‑файлов. Удаление message ломает совместимость по wire‑формату и сгенерированный код: в существующих данных могут присутствовать экземпляры у","content":"Это правило проверяет, что ни одно сообщение (message) не было удалено из proto‑файлов. Удаление message ломает совместимость по wire‑формату и сгенерированный код: в существующих данных могут присутствовать экземпляры удалённого типа, а клиентский код зависит от сгенерированных структур и классов."},{"id":"cli/breaking-changes/rules/message-no-delete::breaking::1","title":"MESSAGE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/message-no-delete::breaking::2","title":"MESSAGE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/message-no-delete::breaking::3","title":"MESSAGE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message User { string name = 1; string email = 2; Address address = 3; }","content":"Плохой (Breaking) message User { string name = 1; string email = 2; Address address = 3; }"},{"id":"cli/breaking-changes/rules/message-no-delete::breaking::4","title":"MESSAGE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message Address { // [!code --] string street = 1; // [!code --] string city = 2; // [!code --] string country = 3; // [!code --] } // [!code --]","content":"Плохой (Breaking) message Address { // [!code --] string street = 1; // [!code --] string city = 2; // [!code --] string country = 3; // [!code --] } // [!code --]"},{"id":"cli/breaking-changes/rules/message-no-delete::breaking::5","title":"MESSAGE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message Order { string id = 1; User user = 2; } ```","content":"Плохой (Breaking) message Order { string id = 1; User user = 2; } ```"},{"id":"cli/breaking-changes/rules/message-no-delete::breaking::6","title":"MESSAGE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/message-no-delete::breaking::7","title":"MESSAGE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/message-no-delete::breaking::8","title":"MESSAGE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message User { string name = 1; string email = 2; Address address = 3; // ERROR: Address больше не существует }","content":"Плохой (Breaking) message User { string name = 1; string email = 2; Address address = 3; // ERROR: Address больше не существует }"},{"id":"cli/breaking-changes/rules/message-no-delete::breaking::9","title":"MESSAGE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) // Address удалён — BREAKING CHANGE!","content":"Плохой (Breaking) // Address удалён — BREAKING CHANGE!"},{"id":"cli/breaking-changes/rules/message-no-delete::breaking::10","title":"MESSAGE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message Order { string id = 1; User user = 2; } ```","content":"Плохой (Breaking) message Order { string id = 1; User user = 2; } ```"},{"id":"cli/breaking-changes/rules/message-no-delete::top::11","title":"MESSAGE_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры **Удаление вложенного сообщения:**","content":"Дополнительные примеры **Удаление вложенного сообщения:**"},{"id":"cli/breaking-changes/rules/message-no-delete::top::12","title":"MESSAGE_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры ```proto // Before message User { string name = 1; Profile profile = 2; message Profile { // [!code --] string bio = 1; // [!code --] string avatar_url = 2; // [!code --] } // [!code --] }","content":"Дополнительные примеры ```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::top::13","title":"MESSAGE_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры // After - BREAKING CHANGE! message User { string name = 1; Profile profile = 2; // ERROR: Profile удалён // Вложенное сообщение Profile удалено } ```","content":"Дополнительные примеры // After - BREAKING CHANGE! message User { string name = 1; Profile profile = 2; // ERROR: Profile удалён // Вложенное сообщение Profile удалено } ```"},{"id":"cli/breaking-changes/rules/message-no-delete::top::14","title":"MESSAGE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо удаления — пометить как deprecated:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо удаления — пометить как deprecated:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/message-no-delete::top::15","title":"MESSAGE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/message-no-delete::top::16","title":"MESSAGE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message User { string name = 1; string email = 2; Address address = 3 [deprecated = true]; // [!code focus] }","content":"Хороший (Безопасный) message User { string name = 1; string email = 2; Address address = 3 [deprecated = true]; // [!code focus] }"},{"id":"cli/breaking-changes/rules/message-no-delete::top::17","title":"MESSAGE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message Address { option deprecated = true; // [!code focus] string street = 1; string city = 2; string country = 3; }","content":"Хороший (Безопасный) message Address { option deprecated = true; // [!code focus] string street = 1; string city = 2; string country = 3; }"},{"id":"cli/breaking-changes/rules/message-no-delete::top::18","title":"MESSAGE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message Order { string id = 1; User user = 2; } ```","content":"Хороший (Безопасный) message Order { string id = 1; User user = 2; } ```"},{"id":"cli/breaking-changes/rules/message-no-delete::top::19","title":"MESSAGE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Или заменить новой версией сообщения:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Или заменить новой версией сообщения:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/message-no-delete::top::20","title":"MESSAGE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/message-no-delete::top::21","title":"MESSAGE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message User { string name = 1; string email = 2; Address address = 3 [deprecated = true]; // [!code focus] // Старое поле AddressV2 address_v2 = 4; // [!code focus] // Новая улучшенная структура }","content":"Хороший (Безопасный) message User { string name = 1; string email = 2; Address address = 3 [deprecated = true]; // [!code focus] // Старое поле AddressV2 address_v2 = 4; // [!code focus] // Новая улучшенная структура }"},{"id":"cli/breaking-changes/rules/message-no-delete::top::22","title":"MESSAGE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message Address { option deprecated = true; // [!code focus] string street = 1; string city = 2; string country = 3; }","content":"Хороший (Безопасный) message Address { option deprecated = true; // [!code focus] string street = 1; string city = 2; string country = 3; }"},{"id":"cli/breaking-changes/rules/message-no-delete::top::23","title":"MESSAGE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) 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 c","content":"Хороший (Безопасный) 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::top::24","title":"MESSAGE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message Order { string id = 1; User user = 2; } ```","content":"Хороший (Безопасный) message Order { string id = 1; User user = 2; } ```"},{"id":"cli/breaking-changes/rules/message-no-delete::top::25","title":"MESSAGE_NO_DELETE","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Влияние"],"excerpt":"Влияние **Wire Format:** Старые данные с удалённым сообщением не десериализуются **Generated Code:** Классы/структуры удаляются — компиляция клиента ломается **Field References:** Поля, использующие удалённый тип, станов","content":"Влияние **Wire Format:** Старые данные с удалённым сообщением не десериализуются **Generated Code:** Классы/структуры удаляются — компиляция клиента ломается **Field References:** Поля, использующие удалённый тип, становятся невалидны **Nested Dependencies:** Все сообщения, ссылающиеся на удалённый тип, ломаются"},{"id":"cli/breaking-changes/rules/message-no-delete::top::26","title":"MESSAGE_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Код клиента ломается:** ```go // Before user := &myapi.User{ Name: \"John Doe\", Email: \"john@example.com\", Address: &myapi.Address{ // ERROR после удаления Street: \"123 Main St\", City: \"New York\", Countr","content":"Реальный пример **Код клиента ломается:** ```go // Before user := &myapi.User{ Name: \"John Doe\", Email: \"john@example.com\", Address: &myapi.Address{ // ERROR после удаления Street: \"123 Main St\", City: \"New York\", Country: \"USA\", }, }"},{"id":"cli/breaking-changes/rules/message-no-delete::top::27","title":"MESSAGE_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример // undefined: myapi.Address ```","content":"Реальный пример // undefined: myapi.Address ```"},{"id":"cli/breaking-changes/rules/message-no-delete::top::28","title":"MESSAGE_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Старые данные становятся нечитаемыми:**","content":"Реальный пример **Старые данные становятся нечитаемыми:**"},{"id":"cli/breaking-changes/rules/message-no-delete::top::29","title":"MESSAGE_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Пометить как deprecated:** **Пометить поля, использующие его:** **Добавить замену при необходимости:** **Удалить в следующей major‑версии после периода миграции**","content":"Стратегия миграции **Пометить как deprecated:** **Пометить поля, использующие его:** **Добавить замену при необходимости:** **Удалить в следующей major‑версии после периода миграции**"},{"id":"cli/breaking-changes/rules/message-no-delete::top::30","title":"MESSAGE_NO_DELETE","section":"Рефакторинг структуры","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Рефакторинг структуры"],"excerpt":"Рефакторинг структуры ```proto message UserInfo { option deprecated = true; string name = 1; string email = 2; }","content":"Рефакторинг структуры ```proto message UserInfo { option deprecated = true; string name = 1; string email = 2; }"},{"id":"cli/breaking-changes/rules/message-no-delete::top::31","title":"MESSAGE_NO_DELETE","section":"Рефакторинг структуры","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Рефакторинг структуры"],"excerpt":"Рефакторинг структуры message UserProfile { string full_name = 1; string email_address = 2; string phone = 3; } ```","content":"Рефакторинг структуры message UserProfile { string full_name = 1; string email_address = 2; string phone = 3; } ```"},{"id":"cli/breaking-changes/rules/message-no-delete::top::32","title":"MESSAGE_NO_DELETE","section":"Удаление «неиспользуемых» сообщений","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Удаление «неиспользуемых» сообщений"],"excerpt":"Удаление «неиспользуемых» сообщений","content":"Удаление «неиспользуемых» сообщений"},{"id":"cli/breaking-changes/rules/message-no-delete::top::33","title":"MESSAGE_NO_DELETE","section":"Миграция версии","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Миграция версии"],"excerpt":"Миграция версии ```proto package myapi.v2;","content":"Миграция версии ```proto package myapi.v2;"},{"id":"cli/breaking-changes/rules/message-no-delete::top::34","title":"MESSAGE_NO_DELETE","section":"Миграция версии","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Миграция версии"],"excerpt":"Миграция версии message User { // Новая структура без устаревших ссылок } ```","content":"Миграция версии message User { // Новая структура без устаревших ссылок } ```"},{"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":"Правило проверяет, что ни одно поле внутри oneof группы не было удалено. Удаление поля из oneof ломает совместимость по wire‑формату и сгенерированный код: в сохранённых данных может присутствовать выбранный вариант, а к","content":"Правило проверяет, что ни одно поле внутри oneof группы не было удалено. Удаление поля из oneof ломает совместимость по wire‑формату и сгенерированный код: в сохранённых данных может присутствовать выбранный вариант, а клиентский код опирается на сгенерированные типы‑обёртки и методы доступа."},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::breaking::1","title":"ONEOF_FIELD_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::breaking::2","title":"ONEOF_FIELD_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::breaking::3","title":"ONEOF_FIELD_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message LoginRequest { string username = 1; oneof credentials { string password = 2; string api_key = 3; string oauth_token = 4; string certificate = 5; } }","content":"Плохой (Breaking) 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::breaking::4","title":"ONEOF_FIELD_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message SearchQuery { oneof filter { string text = 1; int32 user_id = 2; string category = 3; DateRange date_range = 4; } } ```","content":"Плохой (Breaking) 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::breaking::5","title":"ONEOF_FIELD_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::breaking::6","title":"ONEOF_FIELD_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::breaking::7","title":"ONEOF_FIELD_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message LoginRequest { string username = 1; oneof credentials { string password = 2; string api_key = 3; // string oauth_token = 4; // [!code --] Удалено поле oneof — BREAKING! // string certificate = 5","content":"Плохой (Breaking) message LoginRequest { string username = 1; oneof credentials { string password = 2; string api_key = 3; // string oauth_token = 4; // [!code --] Удалено поле oneof — BREAKING! // string certificate = 5; // [!code --] Удалено поле oneof — BREAKING! } }"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::breaking::8","title":"ONEOF_FIELD_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message SearchQuery { oneof filter { string text = 1; int32 user_id = 2; // string category = 3; // [!code --] Удалено поле oneof — BREAKING! // DateRange date_range = 4; // [!code --] Удалено поле oneo","content":"Плохой (Breaking) message SearchQuery { oneof filter { string text = 1; int32 user_id = 2; // string category = 3; // [!code --] Удалено поле oneof — BREAKING! // DateRange date_range = 4; // [!code --] Удалено поле oneof — BREAKING! } } ```"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::9","title":"ONEOF_FIELD_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры **Удаление вложенных oneof полей:** ```proto // Before message PaymentRequest { string order_id = 1; oneof payment_method { CreditCardPayment credit_card = 2; BankTransferPayment bank_transfer = 3;","content":"Дополнительные примеры **Удаление вложенных oneof полей:** ```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::top::10","title":"ONEOF_FIELD_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры // After - BREAKING CHANGES! message PaymentRequest { string order_id = 1; oneof payment_method { CreditCardPayment credit_card = 2; BankTransferPayment bank_transfer = 3; // CryptoPayment crypto =","content":"Дополнительные примеры // 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::top::11","title":"ONEOF_FIELD_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо удаления — пометить поля deprecated:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо удаления — пометить поля deprecated:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::12","title":"ONEOF_FIELD_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::13","title":"ONEOF_FIELD_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) 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 [deprecate","content":"Хороший (Безопасный) 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::top::14","title":"ONEOF_FIELD_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) 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":"Хороший (Безопасный) 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::top::15","title":"ONEOF_FIELD_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Или добавить новые поля, оставив старые:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Или добавить новые поля, оставив старые:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::16","title":"ONEOF_FIELD_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::17","title":"ONEOF_FIELD_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message LoginRequest { string username = 1; oneof credentials { string password = 2; string api_key = 3; string oauth_token = 4 [deprecated = true]; // [!code focus] // Старое поле string certificate","content":"Хороший (Безопасный) 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] OAuthCredentials oauth_v2 = 6; // [!code focus] // Новый структурированный вариант CertificateCredentials cert_v2 = 7; // [!code focus] } } ```"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::18","title":"ONEOF_FIELD_NO_DELETE","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Влияние"],"excerpt":"Влияние **Wire Format:** Данные, содержащие удалённый вариант, не десериализуются корректно **Generated Code:** Удаляются типы‑обёртки и accessor методы — компиляция клиентов ломается **Type Safety:** Логика switch по ти","content":"Влияние **Wire Format:** Данные, содержащие удалённый вариант, не десериализуются корректно **Generated Code:** Удаляются типы‑обёртки и accessor методы — компиляция клиентов ломается **Type Safety:** Логика switch по типам oneof разваливается **Business Logic:** Код, ожидающий конкретный вариант, перестаёт работать"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::19","title":"ONEOF_FIELD_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Код клиента ломается:** ```go // Before loginReq := &myapi.LoginRequest{ Username: \"user123\", }","content":"Реальный пример **Код клиента ломается:** ```go // Before loginReq := &myapi.LoginRequest{ Username: \"user123\", }"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::20","title":"ONEOF_FIELD_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример loginReq.Credentials = &myapi.LoginRequest_OauthToken{ OauthToken: \"token123\", // ERROR после удаления поля }","content":"Реальный пример loginReq.Credentials = &myapi.LoginRequest_OauthToken{ OauthToken: \"token123\", // ERROR после удаления поля }"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::21","title":"ONEOF_FIELD_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример switch cred := loginReq.Credentials.(type) { case *myapi.LoginRequest_Password: return authenticatePassword(cred.Password) case *myapi.LoginRequest_OauthToken: // ERROR: тип удалён return authenticateOAut","content":"Реальный пример switch cred := loginReq.Credentials.(type) { case *myapi.LoginRequest_Password: return authenticatePassword(cred.Password) case *myapi.LoginRequest_OauthToken: // ERROR: тип удалён return authenticateOAuth(cred.OauthToken) case *myapi.LoginRequest_Certificate: // ERROR: тип удалён return authenticateCert(cred.Certificate) default: return errors.New(\"unsupported credential type\") } // undefined: myapi.LoginRequest_OauthToken // undefined: myapi.LoginRequest_Certificate ```"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::22","title":"ONEOF_FIELD_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Серверная логика ломается:**","content":"Реальный пример **Серверная логика ломается:**"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::23","title":"ONEOF_FIELD_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Старые данные становятся нечитаемыми:**","content":"Реальный пример **Старые данные становятся нечитаемыми:**"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::24","title":"ONEOF_FIELD_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Депрецируйте сначала:** **Добавьте новые структурированные поля:** **Сервер: поддерживайте оба варианта:** **Мигрируйте клиентов на новое поле:** **Зарезервируйте номера удалённых полей в следующей m","content":"Стратегия миграции **Депрецируйте сначала:** **Добавьте новые структурированные поля:** **Сервер: поддерживайте оба варианта:** **Мигрируйте клиентов на новое поле:** **Зарезервируйте номера удалённых полей в следующей major‑версии:**"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::25","title":"ONEOF_FIELD_NO_DELETE","section":"Удаление неподдерживаемых методов аутентификации","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Удаление неподдерживаемых методов аутентификации"],"excerpt":"Удаление неподдерживаемых методов аутентификации","content":"Удаление неподдерживаемых методов аутентификации"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::26","title":"ONEOF_FIELD_NO_DELETE","section":"Изменения бизнес‑логики платежей","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Изменения бизнес‑логики платежей"],"excerpt":"Изменения бизнес‑логики платежей","content":"Изменения бизнес‑логики платежей"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::oneof-field-deletion-vs::27","title":"ONEOF_FIELD_NO_DELETE","section":"OneOf Field Deletion vs обычное удаление","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#oneof-field-deletion-vs","headings":["OneOf Field Deletion vs обычное удаление"],"excerpt":"OneOf Field Deletion vs обычное удаление","content":"OneOf Field Deletion vs обычное удаление"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::28","title":"ONEOF_FIELD_NO_DELETE","section":"Отличия от удаления обычного поля","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Отличия от удаления обычного поля"],"excerpt":"Отличия от удаления обычного поля ```proto message User { string name = 1; // string email = 2; // BREAKING: обычное поле }","content":"Отличия от удаления обычного поля ```proto message User { string name = 1; // string email = 2; // BREAKING: обычное поле }"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::29","title":"ONEOF_FIELD_NO_DELETE","section":"Отличия от удаления обычного поля","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Отличия от удаления обычного поля"],"excerpt":"Отличия от удаления обычного поля message User { oneof contact { string email = 1; // string phone = 2; // BREAKING: поле в oneof } } ```","content":"Отличия от удаления обычного поля message User { oneof contact { string email = 1; // string phone = 2; // BREAKING: поле в oneof } } ```"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::30","title":"ONEOF_FIELD_NO_DELETE","section":"Влияние на сгенерированный код","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Влияние на сгенерированный код"],"excerpt":"Влияние на сгенерированный код ```go // Обычное поле: удаляется простой геттер // user.GetEmail()","content":"Влияние на сгенерированный код ```go // Обычное поле: удаляется простой геттер // user.GetEmail()"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::31","title":"ONEOF_FIELD_NO_DELETE","section":"Влияние на сгенерированный код","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Влияние на сгенерированный код"],"excerpt":"Влияние на сгенерированный код // Поле в oneof: пропадает тип-обёртка, кейсы switch ломаются // *LoginRequest_OauthToken ```","content":"Влияние на сгенерированный код // Поле в oneof: пропадает тип-обёртка, кейсы switch ломаются // *LoginRequest_OauthToken ```"},{"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":"Это правило проверяет, что тип поля внутри oneof НЕ меняется. Смена типа любого варианта oneof — несовместимое (breaking) изменение: существующие данные сериализованы с прежним типом, а клиентский код ожидает конкретные ","content":"Это правило проверяет, что тип поля внутри oneof НЕ меняется. Смена типа любого варианта oneof — несовместимое (breaking) изменение: существующие данные сериализованы с прежним типом, а клиентский код ожидает конкретные типы-обёртки и методы доступа, сгенерированные для каждого варианта."},{"id":"cli/breaking-changes/rules/oneof-field-same-type::breaking::1","title":"ONEOF_FIELD_SAME_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::breaking::2","title":"ONEOF_FIELD_SAME_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::breaking::3","title":"ONEOF_FIELD_SAME_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message SearchRequest { string query = 1; oneof filter { string category = 2; int32 user_id = 3; bool is_premium = 4; DateRange date_range = 5; } }","content":"Плохой (Breaking) 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::breaking::4","title":"ONEOF_FIELD_SAME_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message NotificationSettings { oneof delivery { string email = 1; int64 phone_number = 2; WebhookConfig webhook = 3; } } ```","content":"Плохой (Breaking) message NotificationSettings { oneof delivery { string email = 1; int64 phone_number = 2; WebhookConfig webhook = 3; } } ```"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::breaking::5","title":"ONEOF_FIELD_SAME_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::breaking::6","title":"ONEOF_FIELD_SAME_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::breaking::7","title":"ONEOF_FIELD_SAME_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message SearchRequest { string query = 1; oneof filter { int32 category = 2; // [!code --] Было string -> стало int32 (BREAKING) string user_id = 3; // [!code --] Было int32 -> стало string (BREAKING) s","content":"Плохой (Breaking) message SearchRequest { string query = 1; oneof filter { int32 category = 2; // [!code --] Было string -> стало int32 (BREAKING) string user_id = 3; // [!code --] Было int32 -> стало string (BREAKING) string is_premium = 4; // [!code --] Было bool -> стало string (BREAKING) string date_range = 5; // [!code --] Было DateRange -> стало string (BREAKING) } }"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::breaking::8","title":"ONEOF_FIELD_SAME_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message NotificationSettings { oneof delivery { EmailConfig email = 1; // [!code --] Было string -> стало EmailConfig (BREAKING) string phone_number = 2; // [!code --] Было int64 -> стало string (BREAKI","content":"Плохой (Breaking) message NotificationSettings { oneof delivery { EmailConfig email = 1; // [!code --] Было string -> стало EmailConfig (BREAKING) string phone_number = 2; // [!code --] Было int64 -> стало string (BREAKING) string webhook = 3; // [!code --] Было WebhookConfig -> стало string (BREAKING) } } ```"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::9","title":"ONEOF_FIELD_SAME_TYPE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры **Комплексные изменения типов:** ```proto // Before message PaymentRequest { oneof payment_info { CreditCardInfo credit_card = 1; BankAccountInfo bank_account = 2; string paypal_email = 3; CryptoWa","content":"Дополнительные примеры **Комплексные изменения типов:** ```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::top::10","title":"ONEOF_FIELD_SAME_TYPE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры // After - ВСЁ BREAKING message PaymentRequest { oneof payment_info { string credit_card = 1; // CreditCardInfo -> string PayPalInfo bank_account = 2; // BankAccountInfo -> PayPalInfo PayPalInfo pa","content":"Дополнительные примеры // After - ВСЁ BREAKING message PaymentRequest { oneof payment_info { string credit_card = 1; // CreditCardInfo -> string PayPalInfo bank_account = 2; // BankAccountInfo -> PayPalInfo PayPalInfo paypal_email = 3; // string -> PayPalInfo string crypto = 4; // CryptoWalletInfo -> string } } ```"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::11","title":"ONEOF_FIELD_SAME_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо смены типа — добавьте новое поле в тот же oneof:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо смены типа — добавьте новое поле в тот же oneof:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::12","title":"ONEOF_FIELD_SAME_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::13","title":"ONEOF_FIELD_SAME_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message SearchRequest { string query = 1; oneof filter { string category = 2 [deprecated = true]; // Старый тип int32 user_id = 3 [deprecated = true]; bool is_premium = 4 [deprecated = true]; DateRan","content":"Хороший (Безопасный) message SearchRequest { string query = 1; oneof filter { string category = 2 [deprecated = true]; // Старый тип int32 user_id = 3 [deprecated = true]; bool is_premium = 4 [deprecated = true]; DateRange date_range = 5 [deprecated = true]; int32 category_id = 6; // Новая версия string user_identifier = 7; string premium_status = 8; string date_filter = 9; } } ```"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::14","title":"ONEOF_FIELD_SAME_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Или создайте новый oneof:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Или создайте новый oneof:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::15","title":"ONEOF_FIELD_SAME_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::16","title":"ONEOF_FIELD_SAME_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message SearchRequest { string query = 1; oneof filter { option deprecated = true; string category = 2 [deprecated = true]; int32 user_id = 3 [deprecated = true]; bool is_premium = 4 [deprecated = tr","content":"Хороший (Безопасный) message SearchRequest { string query = 1; oneof filter { option deprecated = true; string category = 2 [deprecated = true]; int32 user_id = 3 [deprecated = true]; bool is_premium = 4 [deprecated = true]; DateRange date_range = 5 [deprecated = true]; } oneof filter_v2 { int32 category_id = 6; string user_identifier = 7; PremiumFilter premium_filter = 8; TimeFilter time_filter = 9; } } ```"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::17","title":"ONEOF_FIELD_SAME_TYPE","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Влияние"],"excerpt":"Влияние **Wire Format:** Старые бинарные данные не читаются корректно **Generated Code:** Меняются типы-обёртки, код клиента не компилируется **Type Safety:** switch по варианту oneof ломается **Runtime Errors:** Ошибки ","content":"Влияние **Wire Format:** Старые бинарные данные не читаются корректно **Generated Code:** Меняются типы-обёртки, код клиента не компилируется **Type Safety:** switch по варианту oneof ломается **Runtime Errors:** Ошибки десериализации и логики при несовпадении типов"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::18","title":"ONEOF_FIELD_SAME_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Реальный пример"],"excerpt":"Реальный пример **Ломается клиентский код:** ```go // Before searchReq := &myapi.SearchRequest{ Query: \"golang jobs\", }","content":"Реальный пример **Ломается клиентский код:** ```go // Before searchReq := &myapi.SearchRequest{ Query: \"golang jobs\", }"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::19","title":"ONEOF_FIELD_SAME_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Реальный пример"],"excerpt":"Реальный пример // Устанавливаем вариант oneof searchReq.Filter = &myapi.SearchRequest_Category{ Category: \"engineering\", }","content":"Реальный пример // Устанавливаем вариант oneof searchReq.Filter = &myapi.SearchRequest_Category{ Category: \"engineering\", }"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::20","title":"ONEOF_FIELD_SAME_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Реальный пример"],"excerpt":"Реальный пример // Обработка вариантов switch filter := searchReq.Filter.(type) { case *myapi.SearchRequest_Category: return searchByCategory(filter.Category) case *myapi.SearchRequest_UserId: return searchByUserId(filte","content":"Реальный пример // Обработка вариантов switch filter := searchReq.Filter.(type) { case *myapi.SearchRequest_Category: return searchByCategory(filter.Category) case *myapi.SearchRequest_UserId: return searchByUserId(filter.UserId) default: return errors.New(\"unsupported filter\") }"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::21","title":"ONEOF_FIELD_SAME_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Реальный пример"],"excerpt":"Реальный пример // After — тип Category стал int32 searchReq.Filter = &myapi.SearchRequest_Category{ Category: \"engineering\", // ERROR }","content":"Реальный пример // After — тип Category стал int32 searchReq.Filter = &myapi.SearchRequest_Category{ Category: \"engineering\", // ERROR }"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::22","title":"ONEOF_FIELD_SAME_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Реальный пример"],"excerpt":"Реальный пример switch filter := searchReq.Filter.(type) { case *myapi.SearchRequest_Category: return searchByCategory(filter.Category) // ERROR case *myapi.SearchRequest_UserId: return searchByUserId(filter.UserId) // E","content":"Реальный пример switch filter := searchReq.Filter.(type) { case *myapi.SearchRequest_Category: return searchByCategory(filter.Category) // ERROR case *myapi.SearchRequest_UserId: return searchByUserId(filter.UserId) // ERROR: UserId теперь string } ```"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::23","title":"ONEOF_FIELD_SAME_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Реальный пример"],"excerpt":"Реальный пример **Ломается серверная логика:** ```go // Before func handleSearchFilter(req *SearchRequest) (*SearchResult, error) { switch filter := req.Filter.(type) { case *SearchRequest_Category: return searchDatabase","content":"Реальный пример **Ломается серверная логика:** ```go // Before func handleSearchFilter(req *SearchRequest) (*SearchResult, error) { switch filter := req.Filter.(type) { case *SearchRequest_Category: return searchDatabase(\"category\", filter.Category), nil case *SearchRequest_UserId: return searchDatabase(\"user_id\", strconv.Itoa(int(filter.UserId))), nil default: return nil, errors.New(\"no filter specified\") } }"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::24","title":"ONEOF_FIELD_SAME_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Реальный пример"],"excerpt":"Реальный пример // After — несовпадения типов func handleSearchFilter(req *SearchRequest) (*SearchResult, error) { switch filter := req.Filter.(type) { case *SearchRequest_Category: // filter.Category теперь int32, а код","content":"Реальный пример // After — несовпадения типов func handleSearchFilter(req *SearchRequest) (*SearchResult, error) { switch filter := req.Filter.(type) { case *SearchRequest_Category: // filter.Category теперь int32, а код ожидал string return searchDatabase(\"category\", filter.Category), nil // ERROR case *SearchRequest_UserId: userIdStr := filter.UserId // string вместо int32 userId, _ := strconv.Atoi(userIdStr) return searchDatabase(\"user_id\", strconv.Itoa(userId)), nil } } ```"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::25","title":"ONEOF_FIELD_SAME_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Реальный пример"],"excerpt":"Реальный пример **Порча данных:**","content":"Реальный пример **Порча данных:**"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::26","title":"ONEOF_FIELD_SAME_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции Добавьте новое поле: Сервер поддерживает оба: Клиенты переходят на category_id. Скрипты миграции преобразуют старые данные. В следующей major‑версии:","content":"Стратегия миграции Добавьте новое поле: Сервер поддерживает оба: Клиенты переходят на category_id. Скрипты миграции преобразуют старые данные. В следующей major‑версии:"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::27","title":"ONEOF_FIELD_SAME_TYPE","section":"Переход к структурированным типам","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Переход к структурированным типам"],"excerpt":"Переход к структурированным типам","content":"Переход к структурированным типам"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::28","title":"ONEOF_FIELD_SAME_TYPE","section":"Матрица совместимости","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Матрица совместимости"],"excerpt":"Матрица совместимости From Type To Type Результат ----------- --------- ----------- string int32/int64 ❌ BREAKING int32 string ❌ BREAKING bool string ❌ BREAKING message string ❌ BREAKING string message ❌ BREAKING enum in","content":"Матрица совместимости From Type To Type Результат ----------- --------- ----------- 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::top::29","title":"ONEOF_FIELD_SAME_TYPE","section":"Влияние на сгенерированный код","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Влияние на сгенерированный код"],"excerpt":"Влияние на сгенерированный код","content":"Влияние на сгенерированный код"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::30","title":"ONEOF_FIELD_SAME_TYPE","section":"Валидация","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Валидация"],"excerpt":"Валидация **После (сломано):**","content":"Валидация **После (сломано):**"},{"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":"Это правило проверяет, что ни один oneof блок не был удалён из сообщений. Удаление oneof ломает совместимость по wire‑формату и сгенерированный код: существующие данные могут содержать ранее выбранный вариант, а клиентск","content":"Это правило проверяет, что ни один oneof блок не был удалён из сообщений. Удаление oneof ломает совместимость по wire‑формату и сгенерированный код: существующие данные могут содержать ранее выбранный вариант, а клиентский код зависит от типов-обёрток и методов доступа, генерируемых для oneof."},{"id":"cli/breaking-changes/rules/oneof-no-delete::breaking::1","title":"ONEOF_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-no-delete::breaking::2","title":"ONEOF_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/oneof-no-delete::breaking::3","title":"ONEOF_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message LoginRequest { string username = 1; oneof credentials { string password = 2; string api_key = 3; string oauth_token = 4; } }","content":"Плохой (Breaking) 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::breaking::4","title":"ONEOF_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message PaymentMethod { // [!code --] oneof method { // [!code --] CreditCard credit_card = 1; // [!code --] BankAccount bank_account = 2; // [!code --] PayPal paypal = 3; // [!code --] } // [!code --] ","content":"Плохой (Breaking) 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::breaking::5","title":"ONEOF_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message Order { string id = 1; PaymentMethod payment = 2; } ```","content":"Плохой (Breaking) message Order { string id = 1; PaymentMethod payment = 2; } ```"},{"id":"cli/breaking-changes/rules/oneof-no-delete::breaking::6","title":"ONEOF_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-no-delete::breaking::7","title":"ONEOF_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/oneof-no-delete::breaking::8","title":"ONEOF_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message LoginRequest { string username = 1; // credentials oneof удалён — BREAKING CHANGE! string password = 2; // Теперь обычные поля string api_key = 3; // Потеряна взаимная исключаемость string oauth","content":"Плохой (Breaking) message LoginRequest { string username = 1; // credentials oneof удалён — BREAKING CHANGE! string password = 2; // Теперь обычные поля string api_key = 3; // Потеряна взаимная исключаемость string oauth_token = 4; }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::breaking::9","title":"ONEOF_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message PaymentMethod { // method oneof удалён — BREAKING CHANGE! CreditCard credit_card = 1; // Теперь можно установить все поля одновременно BankAccount bank_account = 2; PayPal paypal = 3; }","content":"Плохой (Breaking) message PaymentMethod { // method oneof удалён — BREAKING CHANGE! CreditCard credit_card = 1; // Теперь можно установить все поля одновременно BankAccount bank_account = 2; PayPal paypal = 3; }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::breaking::10","title":"ONEOF_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message Order { string id = 1; PaymentMethod payment = 2; } ```","content":"Плохой (Breaking) message Order { string id = 1; PaymentMethod payment = 2; } ```"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::11","title":"ONEOF_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры **Удаление вложенного oneof:** ```proto // Before message UserProfile { string name = 1; message ContactInfo { oneof contact_method { // [!code --] string email = 1; // [!code --] string phone = 2;","content":"Дополнительные примеры **Удаление вложенного oneof:** ```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::top::12","title":"ONEOF_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры // After - BREAKING CHANGE! message UserProfile { string name = 1; message ContactInfo { // contact_method oneof удалён string email = 1; // Больше не эксклюзивно string phone = 2; // Можно задать ","content":"Дополнительные примеры // After - BREAKING CHANGE! message UserProfile { string name = 1; message ContactInfo { // contact_method oneof удалён string email = 1; // Больше не эксклюзивно string phone = 2; // Можно задать всё сразу string slack_id = 3; } ContactInfo contact = 2; } ```"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::13","title":"ONEOF_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо удаления — депрецируйте oneof:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо удаления — депрецируйте oneof:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::14","title":"ONEOF_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::15","title":"ONEOF_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message LoginRequest { string username = 1; oneof credentials { option deprecated = true; // [!code focus] string password = 2 [deprecated = true]; // [!code focus] string api_key = 3 [deprecated = t","content":"Хороший (Безопасный) 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::top::16","title":"ONEOF_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message PaymentMethod { oneof method { option deprecated = true; // [!code focus] CreditCard credit_card = 1 [deprecated = true]; // [!code focus] BankAccount bank_account = 2 [deprecated = true]; //","content":"Хороший (Безопасный) 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::top::17","title":"ONEOF_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Или заменить новой структурой:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Или заменить новой структурой:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::18","title":"ONEOF_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::19","title":"ONEOF_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message LoginRequest { string username = 1; oneof credentials { option deprecated = true; // [!code focus] // Старый oneof string password = 2 [deprecated = true]; // [!code focus] string api_key = 3","content":"Хороший (Безопасный) message LoginRequest { string username = 1; oneof credentials { option deprecated = true; // [!code focus] // Старый 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] // Новый дизайн 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::top::20","title":"ONEOF_NO_DELETE","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Влияние"],"excerpt":"Влияние **Wire Format:** Теряются семантика взаимной исключаемости — больше одного поля может быть установлено **Generated Code:** Удаляются типы-обёртки и accessor методы — код клиента не компилируется **Business Logic:","content":"Влияние **Wire Format:** Теряются семантика взаимной исключаемости — больше одного поля может быть установлено **Generated Code:** Удаляются типы-обёртки и accessor методы — код клиента не компилируется **Business Logic:** Нарушаются инварианты «только один из» **Validation:** Логика проверок должна быть переписана вручную"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::21","title":"ONEOF_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Код клиента ломается:** ```go // Before - oneOf даёт взаимную исключаемость loginReq := &myapi.LoginRequest{ Username: \"user123\", }","content":"Реальный пример **Код клиента ломается:** ```go // Before - oneOf даёт взаимную исключаемость loginReq := &myapi.LoginRequest{ Username: \"user123\", }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::22","title":"ONEOF_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример loginReq.Credentials = &myapi.LoginRequest_Password{ Password: \"secret123\", }","content":"Реальный пример loginReq.Credentials = &myapi.LoginRequest_Password{ Password: \"secret123\", }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::23","title":"ONEOF_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример switch cred := loginReq.Credentials.(type) { case *myapi.LoginRequest_Password: // ERROR после удаления return authenticatePassword(cred.Password) case *myapi.LoginRequest_ApiKey: // ERROR после удаления ","content":"Реальный пример switch cred := loginReq.Credentials.(type) { case *myapi.LoginRequest_Password: // ERROR после удаления return authenticatePassword(cred.Password) case *myapi.LoginRequest_ApiKey: // ERROR после удаления return authenticateApiKey(cred.ApiKey) default: return errors.New(\"no credentials provided\") }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::24","title":"ONEOF_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример // Compilation errors: // undefined: myapi.LoginRequest_Password // undefined field: loginReq.Credentials ```","content":"Реальный пример // Compilation errors: // undefined: myapi.LoginRequest_Password // undefined field: loginReq.Credentials ```"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::25","title":"ONEOF_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Валидация на сервере ломается:** ```go // Before func validateLoginRequest(req *LoginRequest) error { if req.Credentials == nil { return errors.New(\"credentials required\") } switch req.Credentials.(type","content":"Реальный пример **Валидация на сервере ломается:** ```go // Before func validateLoginRequest(req *LoginRequest) error { if req.Credentials == nil { return errors.New(\"credentials required\") } 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::top::26","title":"ONEOF_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример // After func validateLoginRequest(req *LoginRequest) error { credCount := 0 if req.Password != \"\" { credCount++ } if req.ApiKey != \"\" { credCount++ } if req.OauthToken != \"\" { credCount++ }","content":"Реальный пример // After func validateLoginRequest(req *LoginRequest) error { credCount := 0 if req.Password != \"\" { credCount++ } if req.ApiKey != \"\" { credCount++ } if req.OauthToken != \"\" { credCount++ }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::27","title":"ONEOF_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример if credCount == 0 { return errors.New(\"no credentials provided\") } if credCount > 1 { return errors.New(\"multiple credentials provided\") }","content":"Реальный пример if credCount == 0 { return errors.New(\"no credentials provided\") } if credCount > 1 { return errors.New(\"multiple credentials provided\") }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::28","title":"ONEOF_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример if req.Password != \"\" { return validatePassword(req.Password) } // Дополнительные проверки вручную... return nil } ```","content":"Реальный пример if req.Password != \"\" { return validatePassword(req.Password) } // Дополнительные проверки вручную... return nil } ```"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::29","title":"ONEOF_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Проблемы бизнес‑логики:** ```go // Before payment := &PaymentMethod{ Method: &PaymentMethod_CreditCard{ CreditCard: &CreditCard{Number: \"1234\"}, }, }","content":"Реальный пример **Проблемы бизнес‑логики:** ```go // Before payment := &PaymentMethod{ Method: &PaymentMethod_CreditCard{ CreditCard: &CreditCard{Number: \"1234\"}, }, }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::30","title":"ONEOF_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример // After — можно задать несколько способов сразу payment := &PaymentMethod{ CreditCard: &CreditCard{Number: \"1234\"}, BankAccount: &BankAccount{Number: \"5678\"}, // Ломает бизнес-логику } ```","content":"Реальный пример // After — можно задать несколько способов сразу payment := &PaymentMethod{ CreditCard: &CreditCard{Number: \"1234\"}, BankAccount: &BankAccount{Number: \"5678\"}, // Ломает бизнес-логику } ```"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::31","title":"ONEOF_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Депрецируйте старый oneof и его поля:**","content":"Стратегия миграции **Депрецируйте старый oneof и его поля:**"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::32","title":"ONEOF_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Создайте новый блок при необходимости:**","content":"Стратегия миграции **Создайте новый блок при необходимости:**"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::33","title":"ONEOF_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Сервер: поддерживайте оба до миграции:**","content":"Стратегия миграции **Сервер: поддерживайте оба до миграции:**"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::34","title":"ONEOF_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Клиенты: переходите на новый oneof:**","content":"Стратегия миграции **Клиенты: переходите на новый oneof:**"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::35","title":"ONEOF_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Удалите старый oneof** в следующей major‑версии.","content":"Стратегия миграции **Удалите старый oneof** в следующей major‑версии."},{"id":"cli/breaking-changes/rules/oneof-no-delete::oneof::36","title":"ONEOF_NO_DELETE","section":"Замена oneof обычными полями","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#oneof","headings":["Замена oneof обычными полями"],"excerpt":"Замена oneof обычными полями ```proto message SearchRequest { // НЕЛЬЗЯ просто убрать oneof — ломает семантику string text_query = 1; // BREAKING int32 user_id = 2; // BREAKING string category = 3; // BREAKING }","content":"Замена oneof обычными полями ```proto message SearchRequest { // НЕЛЬЗЯ просто убрать oneof — ломает семантику string text_query = 1; // BREAKING int32 user_id = 2; // BREAKING string category = 3; // BREAKING }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::oneof::37","title":"ONEOF_NO_DELETE","section":"Замена oneof обычными полями","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#oneof","headings":["Замена oneof обычными полями"],"excerpt":"Замена oneof обычными полями message SearchRequest { oneof query { option deprecated = true; string text_query = 1 [deprecated = true]; int32 user_id = 2 [deprecated = true]; string category = 3 [deprecated = true]; } st","content":"Замена oneof обычными полями message SearchRequest { oneof query { option deprecated = true; string text_query = 1 [deprecated = true]; int32 user_id = 2 [deprecated = true]; string category = 3 [deprecated = true]; } string search_text = 4; repeated string filters = 5; } ```"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::38","title":"ONEOF_NO_DELETE","section":"Упрощение структуры сообщения","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Упрощение структуры сообщения"],"excerpt":"Упрощение структуры сообщения ```proto message NotificationSettings { string email = 1; // BREAKING: был в oneof string phone = 2; // BREAKING string webhook_url = 3; // BREAKING }","content":"Упрощение структуры сообщения ```proto message NotificationSettings { string email = 1; // BREAKING: был в oneof string phone = 2; // BREAKING string webhook_url = 3; // BREAKING }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::39","title":"ONEOF_NO_DELETE","section":"Упрощение структуры сообщения","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Упрощение структуры сообщения"],"excerpt":"Упрощение структуры сообщения message NotificationSettings { oneof delivery_method { EmailNotification email = 1; SmsNotification phone = 2; WebhookNotification webhook = 3; } } ```","content":"Упрощение структуры сообщения message NotificationSettings { oneof delivery_method { EmailNotification email = 1; SmsNotification phone = 2; WebhookNotification webhook = 3; } } ```"},{"id":"cli/breaking-changes/rules/oneof-no-delete::proto2-proto3::40","title":"ONEOF_NO_DELETE","section":"Миграция с proto2 на proto3","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#proto2-proto3","headings":["Миграция с proto2 на proto3"],"excerpt":"Миграция с proto2 на proto3 ```proto // proto2 message Request { optional string name = 1; oneof data { string text = 2; int32 number = 3; } }","content":"Миграция с proto2 на proto3 ```proto // proto2 message Request { optional string name = 1; oneof data { string text = 2; int32 number = 3; } }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::proto2-proto3::41","title":"ONEOF_NO_DELETE","section":"Миграция с proto2 на proto3","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#proto2-proto3","headings":["Миграция с proto2 на proto3"],"excerpt":"Миграция с proto2 на proto3 // proto3 — сохраняем oneof message Request { string name = 1; oneof data { string text = 2; int32 number = 3; } } ```","content":"Миграция с proto2 на proto3 // proto3 — сохраняем oneof message Request { string name = 1; oneof data { string text = 2; int32 number = 3; } } ```"},{"id":"cli/breaking-changes/rules/oneof-no-delete::oneof::42","title":"ONEOF_NO_DELETE","section":"Что даёт oneof","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#oneof","headings":["Что даёт oneof"],"excerpt":"Что даёт oneof Взаимная исключаемость Типобезопасность в коде Ясность намерения API («выбери один») Эффективная сериализация — кодируется только выбранный вариант","content":"Что даёт oneof Взаимная исключаемость Типобезопасность в коде Ясность намерения API («выбери один») Эффективная сериализация — кодируется только выбранный вариант"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::43","title":"ONEOF_NO_DELETE","section":"Что теряется при удалении","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Что теряется при удалении"],"excerpt":"Что теряется при удалении Инвариант «только один» Генерируемые wrapper-типы и методы Автоматическая валидация выбора Понятность контракта API","content":"Что теряется при удалении Инвариант «только один» Генерируемые wrapper-типы и методы Автоматическая валидация выбора Понятность контракта API"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::44","title":"ONEOF_NO_DELETE","section":"Влияние на код генерации","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Влияние на код генерации"],"excerpt":"Влияние на код генерации ```go // С oneof type LoginRequest struct { Username string Credentials isLoginRequest_Credentials }","content":"Влияние на код генерации ```go // С oneof type LoginRequest struct { Username string Credentials isLoginRequest_Credentials }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::45","title":"ONEOF_NO_DELETE","section":"Влияние на код генерации","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Влияние на код генерации"],"excerpt":"Влияние на код генерации // Без oneof type LoginRequest struct { Username string Password string ApiKey string OauthToken string // Возможны многозначные конфликтующие состояния } ```","content":"Влияние на код генерации // Без oneof type LoginRequest struct { Username string Password string ApiKey string 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":"Правило проверяет, что ни один RPC‑метод не был удалён из service. Удаление RPC ломает сгенерированный код и клиентские приложения, которые этот метод вызывают.","content":"Правило проверяет, что ни один RPC‑метод не был удалён из service. Удаление RPC ломает сгенерированный код и клиентские приложения, которые этот метод вызывают."},{"id":"cli/breaking-changes/rules/rpc-no-delete::breaking::1","title":"RPC_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/rpc-no-delete::breaking::2","title":"RPC_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/rpc-no-delete::breaking::3","title":"RPC_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); rpc DeleteUser(DeleteUserRequest) returns (DeleteUserResponse","content":"Плохой (Breaking) 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::breaking::4","title":"RPC_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/rpc-no-delete::breaking::5","title":"RPC_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/rpc-no-delete::breaking::6","title":"RPC_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); // DeleteUser RPC удалён — BREAKING CHANGE! } ```","content":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); // DeleteUser RPC удалён — BREAKING CHANGE! } ```"},{"id":"cli/breaking-changes/rules/rpc-no-delete::top::7","title":"RPC_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо удаления — пометить RPC deprecated:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо удаления — пометить RPC deprecated:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/rpc-no-delete::top::8","title":"RPC_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/rpc-no-delete::top::9","title":"RPC_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); rpc DeleteUser(DeleteUserRequest) returns (DeleteUserRespo","content":"Хороший (Безопасный) 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::top::10","title":"RPC_NO_DELETE","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete","headings":["Влияние"],"excerpt":"Влияние **Generated Code:** Stub/метод исчезает — клиенты не компилируются **Client Applications:** Существующие вызовы метода падают при сборке **Runtime:** gRPC клиенты теряют определение метода","content":"Влияние **Generated Code:** Stub/метод исчезает — клиенты не компилируются **Client Applications:** Существующие вызовы метода падают при сборке **Runtime:** gRPC клиенты теряют определение метода"},{"id":"cli/breaking-changes/rules/rpc-no-delete::top::11","title":"RPC_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Сначала деприкация:**","content":"Стратегия миграции **Сначала деприкация:**"},{"id":"cli/breaking-changes/rules/rpc-no-delete::top::12","title":"RPC_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Имплементация может возвращать ошибку**, указывая что метод устарел (например, INTERNAL / UNIMPLEMENTED)","content":"Стратегия миграции **Имплементация может возвращать ошибку**, указывая что метод устарел (например, INTERNAL / UNIMPLEMENTED)"},{"id":"cli/breaking-changes/rules/rpc-no-delete::top::13","title":"RPC_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Удалить в следующей major‑версии** после миграции всех клиентов","content":"Стратегия миграции **Удалить в следующей major‑версии** после миграции всех клиентов"},{"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":"Это правило проверяет, что RPC‑методы сохраняют прежний тип сообщения запроса (request message type). Изменение типа запроса RPC ломает совместимость по wire‑формату и сгенерированный код: клиенты ожидают конкретную стру","content":"Это правило проверяет, что RPC‑методы сохраняют прежний тип сообщения запроса (request message type). Изменение типа запроса RPC ломает совместимость по wire‑формату и сгенерированный код: клиенты ожидают конкретную структуру при вызове метода."},{"id":"cli/breaking-changes/rules/rpc-same-request-type::breaking::1","title":"RPC_SAME_REQUEST_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::breaking::2","title":"RPC_SAME_REQUEST_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::breaking::3","title":"RPC_SAME_REQUEST_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse); }","content":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse); }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::breaking::4","title":"RPC_SAME_REQUEST_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message GetUserRequest { string user_id = 1; }","content":"Плохой (Breaking) message GetUserRequest { string user_id = 1; }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::breaking::5","title":"RPC_SAME_REQUEST_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message UpdateUserRequest { string user_id = 1; string name = 2; string email = 3; } ```","content":"Плохой (Breaking) message UpdateUserRequest { string user_id = 1; string name = 2; string email = 3; } ```"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::breaking::6","title":"RPC_SAME_REQUEST_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::breaking::7","title":"RPC_SAME_REQUEST_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::breaking::8","title":"RPC_SAME_REQUEST_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequestV2) returns (GetUserResponse); // [!code --] Изменён тип запроса rpc UpdateUser(UserUpdateRequest) returns (UpdateUserResponse); // [!code --] Изменён тип","content":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequestV2) returns (GetUserResponse); // [!code --] Изменён тип запроса rpc UpdateUser(UserUpdateRequest) returns (UpdateUserResponse); // [!code --] Изменён тип запроса }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::breaking::9","title":"RPC_SAME_REQUEST_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message GetUserRequestV2 { // [!code --] Новый тип запроса string id = 1; bool include_profile = 2; }","content":"Плохой (Breaking) message GetUserRequestV2 { // [!code --] Новый тип запроса string id = 1; bool include_profile = 2; }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::breaking::10","title":"RPC_SAME_REQUEST_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message UserUpdateRequest { // [!code --] Новый тип запроса string id = 1; UserProfile profile = 2; } ```","content":"Плохой (Breaking) message UserUpdateRequest { // [!code --] Новый тип запроса string id = 1; UserProfile profile = 2; } ```"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::11","title":"RPC_SAME_REQUEST_TYPE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры **Смена типа из другого пакета:** ```proto // Before import \"common/user.proto\";","content":"Дополнительные примеры **Смена типа из другого пакета:** ```proto // Before import \"common/user.proto\";"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::12","title":"RPC_SAME_REQUEST_TYPE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры service UserService { rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); }","content":"Дополнительные примеры service UserService { rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::13","title":"RPC_SAME_REQUEST_TYPE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры // After - BREAKING CHANGE! import \"v2/user.proto\";","content":"Дополнительные примеры // After - BREAKING CHANGE! import \"v2/user.proto\";"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::14","title":"RPC_SAME_REQUEST_TYPE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры service UserService { rpc CreateUser(v2.CreateUserRequest) returns (CreateUserResponse); // Другой package } ```","content":"Дополнительные примеры service UserService { rpc CreateUser(v2.CreateUserRequest) returns (CreateUserResponse); // Другой package } ```"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::15","title":"RPC_SAME_REQUEST_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо изменения типа — версионируйте RPC:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо изменения типа — версионируйте RPC:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::16","title":"RPC_SAME_REQUEST_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::17","title":"RPC_SAME_REQUEST_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse) { option deprecated = true; // [!code focus] } rpc GetUserV2(GetUserRequestV2) returns (GetUserResponse); // [!code focus] ","content":"Хороший (Безопасный) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse) { option deprecated = true; // [!code focus] } rpc GetUserV2(GetUserRequestV2) returns (GetUserResponse); // [!code focus] // Новый метод rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse) { option deprecated = true; // [!code focus] } rpc UpdateUserV2(UserUpdateRequest) returns (UpdateUserResponse); // [!code focus] // Новый метод }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::18","title":"RPC_SAME_REQUEST_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) // Старые сообщения — для обратной совместимости message GetUserRequest { string user_id = 1; }","content":"Хороший (Безопасный) // Старые сообщения — для обратной совместимости message GetUserRequest { string user_id = 1; }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::19","title":"RPC_SAME_REQUEST_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) // Новая версия сообщения message GetUserRequestV2 { // [!code focus] string id = 1; // [!code focus] bool include_profile = 2; // [!code focus] } // [!code focus] ```","content":"Хороший (Безопасный) // Новая версия сообщения 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::top::20","title":"RPC_SAME_REQUEST_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Или создайте новую версию сервиса (package v2):** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Или создайте новую версию сервиса (package v2):** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::21","title":"RPC_SAME_REQUEST_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v2; // [!code focus]","content":"Хороший (Безопасный) package myapi.v2; // [!code focus]"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::22","title":"RPC_SAME_REQUEST_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); // [!code focus] rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse); // [!code focus] }","content":"Хороший (Безопасный) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); // [!code focus] rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse); // [!code focus] }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::23","title":"RPC_SAME_REQUEST_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message GetUserRequest { // [!code focus] string id = 1; // [!code focus] bool include_profile = 2; // [!code focus] } // [!code focus] ```","content":"Хороший (Безопасный) message GetUserRequest { // [!code focus] string id = 1; // [!code focus] bool include_profile = 2; // [!code focus] } // [!code focus] ```"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::24","title":"RPC_SAME_REQUEST_TYPE","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Влияние"],"excerpt":"Влияние **Wire Format:** Старые запросы клиентов не десериализуются новым сервером **Generated Code:** Сигнатуры методов в stubs меняются — компиляция клиентов падает **gRPC Calls:** Требуется использовать другую структу","content":"Влияние **Wire Format:** Старые запросы клиентов не десериализуются новым сервером **Generated Code:** Сигнатуры методов в stubs меняются — компиляция клиентов падает **gRPC Calls:** Требуется использовать другую структуру запроса **Runtime Errors:** Несоответствие типов вызывает ошибки выполнения"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::25","title":"RPC_SAME_REQUEST_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Реальный пример"],"excerpt":"Реальный пример **Код клиента ломается:** ```go // Before client := myapi.NewUserServiceClient(conn) resp, err := client.GetUser(ctx, &myapi.GetUserRequest{ UserId: \"user123\", })","content":"Реальный пример **Код клиента ломается:** ```go // Before client := myapi.NewUserServiceClient(conn) resp, err := client.GetUser(ctx, &myapi.GetUserRequest{ UserId: \"user123\", })"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::26","title":"RPC_SAME_REQUEST_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Реальный пример"],"excerpt":"Реальный пример // After (тип запроса изменён) client := myapi.NewUserServiceClient(conn) resp, err := client.GetUser(ctx, &myapi.GetUserRequest{ // ERROR: тип не найден UserId: \"user123\", // ERROR: поле не найдено })","content":"Реальный пример // After (тип запроса изменён) client := myapi.NewUserServiceClient(conn) resp, err := client.GetUser(ctx, &myapi.GetUserRequest{ // ERROR: тип не найден UserId: \"user123\", // ERROR: поле не найдено })"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::27","title":"RPC_SAME_REQUEST_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Реальный пример"],"excerpt":"Реальный пример // Новый корректный вызов: resp, err := client.GetUser(ctx, &myapi.GetUserRequestV2{ Id: \"user123\", IncludeProfile: true, }) ```","content":"Реальный пример // Новый корректный вызов: resp, err := client.GetUser(ctx, &myapi.GetUserRequestV2{ Id: \"user123\", IncludeProfile: true, }) ```"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::28","title":"RPC_SAME_REQUEST_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Реальный пример"],"excerpt":"Реальный пример **Серверная реализация ломается:** ```go // Before func (s *server) GetUser(ctx context.Context, req *GetUserRequest) (*GetUserResponse, error) { userID := req.UserId // ... }","content":"Реальный пример **Серверная реализация ломается:** ```go // Before func (s *server) GetUser(ctx context.Context, req *GetUserRequest) (*GetUserResponse, error) { userID := req.UserId // ... }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::29","title":"RPC_SAME_REQUEST_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Реальный пример"],"excerpt":"Реальный пример // After func (s *server) GetUser(ctx context.Context, req *GetUserRequestV2) (*GetUserResponse, error) { userID := req.Id include := req.IncludeProfile // ... новая логика } ```","content":"Реальный пример // After func (s *server) GetUser(ctx context.Context, req *GetUserRequestV2) (*GetUserResponse, error) { userID := req.Id include := req.IncludeProfile // ... новая логика } ```"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::30","title":"RPC_SAME_REQUEST_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Добавьте новый RPC с новым типом запроса:**","content":"Стратегия миграции **Добавьте новый RPC с новым типом запроса:**"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::31","title":"RPC_SAME_REQUEST_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Поддерживайте оба метода на сервере:** ```go func (s *server) GetUser(ctx context.Context, req *GetUserRequest) (*GetUserResponse, error) { return s.getUserInternal(req.UserId, false) }","content":"Стратегия миграции **Поддерживайте оба метода на сервере:** ```go func (s *server) GetUser(ctx context.Context, req *GetUserRequest) (*GetUserResponse, error) { return s.getUserInternal(req.UserId, false) }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::32","title":"RPC_SAME_REQUEST_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции func (s *server) GetUserV2(ctx context.Context, req *GetUserRequestV2) (*GetUserResponse, error) { return s.getUserInternal(req.Id, req.IncludeProfile) } ```","content":"Стратегия миграции func (s *server) GetUserV2(ctx context.Context, req *GetUserRequestV2) (*GetUserResponse, error) { return s.getUserInternal(req.Id, req.IncludeProfile) } ```"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::33","title":"RPC_SAME_REQUEST_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Мигрируйте клиентов на V2:**","content":"Стратегия миграции **Мигрируйте клиентов на V2:**"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::34","title":"RPC_SAME_REQUEST_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Удалите старый метод в следующей major‑версии:**","content":"Стратегия миграции **Удалите старый метод в следующей major‑версии:**"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::35","title":"RPC_SAME_REQUEST_TYPE","section":"Добавление обязательных полей","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Добавление обязательных полей"],"excerpt":"Добавление обязательных полей ```proto // ПЛОХО: меняем существующий запрос message GetUserRequest { string user_id = 1; bool include_deleted = 2; // BREAKING }","content":"Добавление обязательных полей ```proto // ПЛОХО: меняем существующий запрос message GetUserRequest { string user_id = 1; bool include_deleted = 2; // BREAKING }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::36","title":"RPC_SAME_REQUEST_TYPE","section":"Добавление обязательных полей","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Добавление обязательных полей"],"excerpt":"Добавление обязательных полей // Хорошо: новая версия message GetUserRequestV2 { string user_id = 1; bool include_deleted = 2; } ```","content":"Добавление обязательных полей // Хорошо: новая версия message GetUserRequestV2 { string user_id = 1; bool include_deleted = 2; } ```"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::37","title":"RPC_SAME_REQUEST_TYPE","section":"Реструктуризация данных запроса","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Реструктуризация данных запроса"],"excerpt":"Реструктуризация данных запроса ```proto // ПЛОХО: меняем структуру прямо message UpdateUserRequest { UserProfile profile = 1; // BREAKING }","content":"Реструктуризация данных запроса ```proto // ПЛОХО: меняем структуру прямо message UpdateUserRequest { UserProfile profile = 1; // BREAKING }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::38","title":"RPC_SAME_REQUEST_TYPE","section":"Реструктуризация данных запроса","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Реструктуризация данных запроса"],"excerpt":"Реструктуризация данных запроса // Хорошо: версионирование rpc UpdateUser(UpdateUserRequest) returns (...) { option deprecated = true; } rpc UpdateUserV2(UpdateUserRequestV2) returns (...); ```","content":"Реструктуризация данных запроса // Хорошо: версионирование rpc UpdateUser(UpdateUserRequest) returns (...) { option deprecated = true; } rpc UpdateUserV2(UpdateUserRequestV2) returns (...); ```"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::39","title":"RPC_SAME_REQUEST_TYPE","section":"Миграция пакета","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Миграция пакета"],"excerpt":"Миграция пакета ```proto // ПЛОХО: заменяем тип на пакет v2 прямо import \"v2/messages.proto\"; // BREAKING","content":"Миграция пакета ```proto // ПЛОХО: заменяем тип на пакет v2 прямо import \"v2/messages.proto\"; // BREAKING"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::40","title":"RPC_SAME_REQUEST_TYPE","section":"Миграция пакета","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Миграция пакета"],"excerpt":"Миграция пакета // Хорошо: добавляем новый RPC rpc OldMethod(v1.Request) returns (...) { option deprecated = true; } rpc NewMethod(v2.Request) returns (...); ```","content":"Миграция пакета // Хорошо: добавляем новый RPC 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":"Это правило проверяет, что RPC‑методы сохраняют тот же тип ответного сообщения (response message type). Изменение типа ответа RPC ломает совместимость по wire‑формату и сгенерированный код: клиенты ожидают конкретную стр","content":"Это правило проверяет, что RPC‑методы сохраняют тот же тип ответного сообщения (response message type). Изменение типа ответа RPC ломает совместимость по wire‑формату и сгенерированный код: клиенты ожидают конкретную структуру при получении ответа."},{"id":"cli/breaking-changes/rules/rpc-same-response-type::breaking::1","title":"RPC_SAME_RESPONSE_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::breaking::2","title":"RPC_SAME_RESPONSE_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::breaking::3","title":"RPC_SAME_RESPONSE_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse); }","content":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse); }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::breaking::4","title":"RPC_SAME_RESPONSE_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message GetUserResponse { string user_id = 1; string name = 2; string email = 3; }","content":"Плохой (Breaking) message GetUserResponse { string user_id = 1; string name = 2; string email = 3; }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::breaking::5","title":"RPC_SAME_RESPONSE_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message UpdateUserResponse { bool success = 1; string message = 2; } ```","content":"Плохой (Breaking) message UpdateUserResponse { bool success = 1; string message = 2; } ```"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::breaking::6","title":"RPC_SAME_RESPONSE_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::breaking::7","title":"RPC_SAME_RESPONSE_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::breaking::8","title":"RPC_SAME_RESPONSE_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponseV2); // [!code --] Изменён тип ответа rpc UpdateUser(UpdateUserRequest) returns (UserUpdateResponse); // [!code --] Изменён тип ","content":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponseV2); // [!code --] Изменён тип ответа rpc UpdateUser(UpdateUserRequest) returns (UserUpdateResponse); // [!code --] Изменён тип ответа }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::breaking::9","title":"RPC_SAME_RESPONSE_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message GetUserResponseV2 { // [!code --] Другой тип сообщения string id = 1; UserProfile profile = 2; repeated string permissions = 3; }","content":"Плохой (Breaking) message GetUserResponseV2 { // [!code --] Другой тип сообщения string id = 1; UserProfile profile = 2; repeated string permissions = 3; }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::breaking::10","title":"RPC_SAME_RESPONSE_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message UserUpdateResponse { // [!code --] Другой тип сообщения UpdateResult result = 1; UserProfile updated_profile = 2; } ```","content":"Плохой (Breaking) message UserUpdateResponse { // [!code --] Другой тип сообщения UpdateResult result = 1; UserProfile updated_profile = 2; } ```"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::11","title":"RPC_SAME_RESPONSE_TYPE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры **Смена типа из другого пакета:** ```proto // Before import \"common/responses.proto\";","content":"Дополнительные примеры **Смена типа из другого пакета:** ```proto // Before import \"common/responses.proto\";"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::12","title":"RPC_SAME_RESPONSE_TYPE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры service UserService { rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); }","content":"Дополнительные примеры service UserService { rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::13","title":"RPC_SAME_RESPONSE_TYPE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры // After - BREAKING CHANGE! import \"v2/responses.proto\";","content":"Дополнительные примеры // After - BREAKING CHANGE! import \"v2/responses.proto\";"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::14","title":"RPC_SAME_RESPONSE_TYPE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры service UserService { rpc CreateUser(CreateUserRequest) returns (v2.CreateUserResponse); // Другой package } ```","content":"Дополнительные примеры service UserService { rpc CreateUser(CreateUserRequest) returns (v2.CreateUserResponse); // Другой package } ```"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::15","title":"RPC_SAME_RESPONSE_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо изменения типа — версионируйте RPC:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо изменения типа — версионируйте RPC:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::16","title":"RPC_SAME_RESPONSE_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::17","title":"RPC_SAME_RESPONSE_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse) { option deprecated = true; // [!code focus] } rpc GetUserV2(GetUserRequest) returns (GetUserResponseV2); // [!code focus] ","content":"Хороший (Безопасный) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse) { option deprecated = true; // [!code focus] } rpc GetUserV2(GetUserRequest) returns (GetUserResponseV2); // [!code focus] // Новый метод rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse) { option deprecated = true; // [!code focus] } rpc UpdateUserV2(UpdateUserRequest) returns (UserUpdateResponse); // [!code focus] // Новый метод }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::18","title":"RPC_SAME_RESPONSE_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) // Старые сообщения сохраняем для обратной совместимости message GetUserResponse { string user_id = 1; string name = 2; string email = 3; }","content":"Хороший (Безопасный) // Старые сообщения сохраняем для обратной совместимости message GetUserResponse { string user_id = 1; string name = 2; string email = 3; }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::19","title":"RPC_SAME_RESPONSE_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) // Новая расширенная версия message GetUserResponseV2 { // [!code focus] string id = 1; // [!code focus] UserProfile profile = 2; // [!code focus] repeated string permissions = 3; // [!code focus] } ","content":"Хороший (Безопасный) // Новая расширенная версия 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::top::20","title":"RPC_SAME_RESPONSE_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Или создайте новую версию сервиса (package v2):** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Или создайте новую версию сервиса (package v2):** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::21","title":"RPC_SAME_RESPONSE_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v2; // [!code focus]","content":"Хороший (Безопасный) package myapi.v2; // [!code focus]"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::22","title":"RPC_SAME_RESPONSE_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); // [!code focus] rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse); // [!code focus] }","content":"Хороший (Безопасный) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); // [!code focus] rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse); // [!code focus] }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::23","title":"RPC_SAME_RESPONSE_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message GetUserResponse { // [!code focus] string id = 1; // [!code focus] UserProfile profile = 2; // [!code focus] repeated string permissions = 3; // [!code focus] } // [!code focus] ```","content":"Хороший (Безопасный) message GetUserResponse { // [!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::top::24","title":"RPC_SAME_RESPONSE_TYPE","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Влияние"],"excerpt":"Влияние **Wire Format:** Ответы сервера не десериализуются у старых клиентов **Generated Code:** Сигнатуры ожидают старый тип — компиляция падает **gRPC Calls:** Меняются типы в сгенерированных stub'ах **Runtime Errors:*","content":"Влияние **Wire Format:** Ответы сервера не десериализуются у старых клиентов **Generated Code:** Сигнатуры ожидают старый тип — компиляция падает **gRPC Calls:** Меняются типы в сгенерированных stub'ах **Runtime Errors:** Несоответствие типов ломает обработку ответа"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::25","title":"RPC_SAME_RESPONSE_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Реальный пример"],"excerpt":"Реальный пример **Код клиента ломается:** ```go // Before client := myapi.NewUserServiceClient(conn) resp, err := client.GetUser(ctx, &myapi.GetUserRequest{ UserId: \"user123\", }) if err != nil { return err }","content":"Реальный пример **Код клиента ломается:** ```go // Before 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::top::26","title":"RPC_SAME_RESPONSE_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Реальный пример"],"excerpt":"Реальный пример userID := resp.UserId name := resp.Name","content":"Реальный пример userID := resp.UserId name := resp.Name"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::27","title":"RPC_SAME_RESPONSE_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Реальный пример"],"excerpt":"Реальный пример // After (тип ответа изменён) client := myapi.NewUserServiceClient(conn) resp, err := client.GetUser(ctx, &myapi.GetUserRequest{ UserId: \"user123\", }) if err != nil { return err }","content":"Реальный пример // After (тип ответа изменён) 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::top::28","title":"RPC_SAME_RESPONSE_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Реальный пример"],"excerpt":"Реальный пример // Ошибки компиляции: userID := resp.UserId // ERROR name := resp.Name // ERROR","content":"Реальный пример // Ошибки компиляции: userID := resp.UserId // ERROR name := resp.Name // ERROR"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::29","title":"RPC_SAME_RESPONSE_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Реальный пример"],"excerpt":"Реальный пример // Новый способ: userID := resp.Id profile := resp.Profile permissions := resp.Permissions ```","content":"Реальный пример // Новый способ: userID := resp.Id profile := resp.Profile permissions := resp.Permissions ```"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::30","title":"RPC_SAME_RESPONSE_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Реальный пример"],"excerpt":"Реальный пример **Имплементация сервера также должна быть переписана:** ```go // Before func (s *server) GetUser(ctx context.Context, req *GetUserRequest) (*GetUserResponse, error) { return &GetUserResponse{ UserId: \"use","content":"Реальный пример **Имплементация сервера также должна быть переписана:** ```go // Before 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::top::31","title":"RPC_SAME_RESPONSE_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Реальный пример"],"excerpt":"Реальный пример // After func (s *server) GetUser(ctx context.Context, req *GetUserRequest) (*GetUserResponseV2, error) { return &GetUserResponseV2{ Id: \"user123\", Profile: &UserProfile{ Name: \"John Doe\", Email: \"john@ex","content":"Реальный пример // After func (s *server) GetUser(ctx context.Context, req *GetUserRequest) (*GetUserResponseV2, error) { return &GetUserResponseV2{ Id: \"user123\", Profile: &UserProfile{ Name: \"John Doe\", Email: \"john@example.com\", }, Permissions: []string{\"read\"}, }, nil } ```"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::32","title":"RPC_SAME_RESPONSE_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Добавьте новый RPC c новым типом ответа:**","content":"Стратегия миграции **Добавьте новый RPC c новым типом ответа:**"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::33","title":"RPC_SAME_RESPONSE_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Поддерживайте оба на сервере:** ```go func (s *server) GetUser(ctx context.Context, req *GetUserRequest) (*GetUserResponse, error) { user := s.getUserInternal(req.UserId) return &GetUserResponse{ Use","content":"Стратегия миграции **Поддерживайте оба на сервере:** ```go func (s *server) GetUser(ctx context.Context, req *GetUserRequest) (*GetUserResponse, error) { user := s.getUserInternal(req.UserId) return &GetUserResponse{ UserId: user.ID, Name: user.Name, Email: user.Email, }, nil }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::34","title":"RPC_SAME_RESPONSE_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции func (s *server) GetUserV2(ctx context.Context, req *GetUserRequest) (*GetUserResponseV2, error) { user := s.getUserInternal(req.UserId) return &GetUserResponseV2{ Id: user.ID, Profile: &UserProfile{ N","content":"Стратегия миграции func (s *server) GetUserV2(ctx context.Context, req *GetUserRequest) (*GetUserResponseV2, error) { user := s.getUserInternal(req.UserId) return &GetUserResponseV2{ Id: user.ID, Profile: &UserProfile{ Name: user.Name, Email: user.Email, }, Permissions: user.Permissions, }, nil } ```"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::35","title":"RPC_SAME_RESPONSE_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Мигрируйте клиентов на новый RPC:**","content":"Стратегия миграции **Мигрируйте клиентов на новый RPC:**"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::36","title":"RPC_SAME_RESPONSE_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Удалите старый RPC** в следующей major‑версии:","content":"Стратегия миграции **Удалите старый RPC** в следующей major‑версии:"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::37","title":"RPC_SAME_RESPONSE_TYPE","section":"Добавление новых обязательных полей","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Добавление новых обязательных полей"],"excerpt":"Добавление новых обязательных полей ```proto // ПЛОХО: меняем существующий тип message GetUserResponse { string user_id = 1; string name = 2; UserProfile profile = 3; // BREAKING }","content":"Добавление новых обязательных полей ```proto // ПЛОХО: меняем существующий тип message GetUserResponse { string user_id = 1; string name = 2; UserProfile profile = 3; // BREAKING }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::38","title":"RPC_SAME_RESPONSE_TYPE","section":"Добавление новых обязательных полей","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Добавление новых обязательных полей"],"excerpt":"Добавление новых обязательных полей // Хорошо: новая версия message GetUserResponseV2 { string user_id = 1; string name = 2; UserProfile profile = 3; } ```","content":"Добавление новых обязательных полей // Хорошо: новая версия message GetUserResponseV2 { string user_id = 1; string name = 2; UserProfile profile = 3; } ```"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::39","title":"RPC_SAME_RESPONSE_TYPE","section":"Реструктуризация ответа","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Реструктуризация ответа"],"excerpt":"Реструктуризация ответа ```proto // ПЛОХО: меняем структуру прямо message UpdateUserResponse { UserDetails details = 1; // BREAKING }","content":"Реструктуризация ответа ```proto // ПЛОХО: меняем структуру прямо message UpdateUserResponse { UserDetails details = 1; // BREAKING }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::40","title":"RPC_SAME_RESPONSE_TYPE","section":"Реструктуризация ответа","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Реструктуризация ответа"],"excerpt":"Реструктуризация ответа // Хорошо: версионирование rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse) { option deprecated = true; } rpc UpdateUserV2(UpdateUserRequest) returns (UpdateUserResponseV2); ```","content":"Реструктуризация ответа // Хорошо: версионирование rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse) { option deprecated = true; } rpc UpdateUserV2(UpdateUserRequest) returns (UpdateUserResponseV2); ```"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::41","title":"RPC_SAME_RESPONSE_TYPE","section":"Изменение формата ошибок","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Изменение формата ошибок"],"excerpt":"Изменение формата ошибок ```proto // ПЛОХО: меняем формат напрямую message CreateUserResponse { ErrorDetails error = 1; // BREAKING }","content":"Изменение формата ошибок ```proto // ПЛОХО: меняем формат напрямую message CreateUserResponse { ErrorDetails error = 1; // BREAKING }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::42","title":"RPC_SAME_RESPONSE_TYPE","section":"Изменение формата ошибок","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Изменение формата ошибок"],"excerpt":"Изменение формата ошибок // Хорошо: новая версия rpc CreateUser(CreateUserRequest) returns (CreateUserResponse) { option deprecated = true; } rpc CreateUserV2(CreateUserRequest) returns (CreateUserResponseV2); ```","content":"Изменение формата ошибок // Хорошо: новая версия rpc CreateUser(CreateUserRequest) returns (CreateUserResponse) { option deprecated = true; } rpc CreateUserV2(CreateUserRequest) returns (CreateUserResponseV2); ```"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::43","title":"RPC_SAME_RESPONSE_TYPE","section":"Миграция формата","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Миграция формата"],"excerpt":"Миграция формата ```proto // ПЛОХО: перевод простой структуры в сложную message GetUserResponse { UserData data = 1; // BREAKING }","content":"Миграция формата ```proto // ПЛОХО: перевод простой структуры в сложную message GetUserResponse { UserData data = 1; // BREAKING }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::44","title":"RPC_SAME_RESPONSE_TYPE","section":"Миграция формата","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Миграция формата"],"excerpt":"Миграция формата // Хорошо: предоставляем обе версии rpc GetUser(GetUserRequest) returns (GetUserResponse) { option deprecated = true; } rpc GetUserDetailed(GetUserRequest) returns (GetUserDetailedResponse); ```","content":"Миграция формата // Хорошо: предоставляем обе версии 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":"Данное правило проверяет, что ни один service не был удалён из proto‑файлов. Удаление service ломает сгенерированный код и клиентские приложения, которые на него опираются.","content":"Данное правило проверяет, что ни один service не был удалён из proto‑файлов. Удаление service ломает сгенерированный код и клиентские приложения, которые на него опираются."},{"id":"cli/breaking-changes/rules/service-no-delete::breaking::1","title":"SERVICE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/service-no-delete::breaking::2","title":"SERVICE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/service-no-delete::breaking::3","title":"SERVICE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); }","content":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); }"},{"id":"cli/breaking-changes/rules/service-no-delete::breaking::4","title":"SERVICE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) service OrderService { // [!code --] rpc GetOrder(GetOrderRequest) returns (GetOrderResponse); // [!code --] } // [!code --] ```","content":"Плохой (Breaking) service OrderService { // [!code --] rpc GetOrder(GetOrderRequest) returns (GetOrderResponse); // [!code --] } // [!code --] ```"},{"id":"cli/breaking-changes/rules/service-no-delete::breaking::5","title":"SERVICE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/service-no-delete::breaking::6","title":"SERVICE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/service-no-delete::breaking::7","title":"SERVICE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); }","content":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); }"},{"id":"cli/breaking-changes/rules/service-no-delete::breaking::8","title":"SERVICE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) // OrderService удалён — BREAKING CHANGE! ```","content":"Плохой (Breaking) // OrderService удалён — BREAKING CHANGE! ```"},{"id":"cli/breaking-changes/rules/service-no-delete::top::9","title":"SERVICE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо удаления — отметьте service как deprecated:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо удаления — отметьте service как deprecated:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/service-no-delete::top::10","title":"SERVICE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/service-no-delete::top::11","title":"SERVICE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); }","content":"Хороший (Безопасный) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); }"},{"id":"cli/breaking-changes/rules/service-no-delete::top::12","title":"SERVICE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) service OrderService { option deprecated = true; // [!code focus] rpc GetOrder(GetOrderRequest) returns (GetOrderResponse) { option deprecated = true; // [!code focus] } } ```","content":"Хороший (Безопасный) 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::top::13","title":"SERVICE_NO_DELETE","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete","headings":["Влияние"],"excerpt":"Влияние **Generated Code:** Классы / интерфейсы сервиса исчезают — клиенты не компилируются **Client Applications:** Существующие вызовы к удалённому сервису падают на этапе сборки **Runtime:** gRPC клиенты теряют опреде","content":"Влияние **Generated Code:** Классы / интерфейсы сервиса исчезают — клиенты не компилируются **Client Applications:** Существующие вызовы к удалённому сервису падают на этапе сборки **Runtime:** gRPC клиенты теряют определение метода/сервиса"},{"id":"cli/breaking-changes/rules/service-no-delete::top::14","title":"SERVICE_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Сначала деприкация:**","content":"Стратегия миграции **Сначала деприкация:**"},{"id":"cli/breaking-changes/rules/service-no-delete::top::15","title":"SERVICE_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Уведомите клиентов** о сроках вывода из эксплуатации","content":"Стратегия миграции **Уведомите клиентов** о сроках вывода из эксплуатации"},{"id":"cli/breaking-changes/rules/service-no-delete::top::16","title":"SERVICE_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Удалите после периода миграции** в следующей major‑версии","content":"Стратегия миграции **Удалите после периода миграции** в следующей major‑версии"},{"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 Формат вывода для команд с поддержкой нескольких форматов (text/json) значение по умолчанию зависит от команды"},{"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 Базовая директория для поиска файлов Текущая рабочая дир","content":"Command-Specific Flags Flag Short Environment Description Default ------ ------- ------------- ------------- --------- --path -p Directory path to lint . --root -r Базовая директория для поиска файлов Текущая рабочая директория --format -f EASYP_FORMAT Использует глобальный флаг формата (text/json) Использует глобальное значение по умолчанию"},{"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 из поддиректории с правильным разрешением импортов easyp lint --root src/IPC/Contracts --path .","content":"Command-Specific Flags Lint из поддиректории с правильным разрешением импортов 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 # глобальный флаг","content":"Command-Specific Flags JSON output format easyp --format json lint # глобальный флаг"},{"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 Путь к директории с proto файлами для генерации . --root -r Базова","content":"Command-Specific Flags Flag Short Environment Description Default ------ ------- ------------- ------------- --------- --path -p EASYP_ROOT_GENERATE_PATH Путь к директории с proto файлами для генерации . --root -r Базовая директория для поиска файлов Текущая рабочая директория"},{"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 из поддиректории с правильным разрешением импортов easyp generate --root src/IPC/Contracts --path .","content":"Command-Specific Flags Generate из поддиректории с правильным разрешением импортов 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 Использует глобальный флаг формата (text/json) Использует глобальное значение по умолчанию"},{"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 # глобальный флаг ```","content":"Command-Specific Flags JSON output easyp --format json breaking --against main # глобальный флаг ```"},{"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 работает интерактивно: Если в корне целевой директории есть buf.yml/buf.yaml, команда предложит миграцию из Buf. Если easyp.yaml уже существует, команда запросит подтверждение на перезап","content":"Command-Specific Flags easyp init работает интерактивно: Если в корне целевой директории есть buf.yml/buf.yaml, команда предложит миграцию из Buf. Если easyp.yaml уже существует, команда запросит подтверждение на перезапись."},{"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 Путь до файла конфигурации easyp.yaml --format (global) -f EASYP_FORMAT Глобаль","content":"Command-Specific Flags Flag Short Environment Description Default ------ ------- ------------- ------------- --------- --config -c EASYP_CFG Путь до файла конфигурации easyp.yaml --format (global) -f EASYP_FORMAT Глобальный формат вывода для команд с несколькими форматами (json или text) зависит от команды (json для 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 Проверить конфиг по умолчанию с JSON выводом (статус 0 если ошибок нет) easyp validate-config","content":"Command-Specific Flags **Examples:** ```bash Проверить конфиг по умолчанию с JSON выводом (статус 0 если ошибок нет) 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 Проверить другой файл и вывести в текстовом формате (глобальный --format) easyp --format text validate-config --config example.easyp.yaml ```","content":"Command-Specific Flags Проверить другой файл и вывести в текстовом формате (глобальный --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 Формат вывода для поддерживаемых команд (text/json). Если не указан, каждая команда использует своё значение по умолчанию. значение по умолчанию зависит от команды 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::top::45","title":"EasyP Configuration Reference","section":"Переменные окружения в конфигурации","path":"/docs/guide/cli/configuration/configuration","headings":["Переменные окружения в конфигурации"],"excerpt":"Переменные окружения в конфигурации EasyP поддерживает расширение переменных окружения непосредственно в файле конфигурации easyp.yaml. Это позволяет использовать переменные окружения для динамических значений конфигурац","content":"Переменные окружения в конфигурации EasyP поддерживает расширение переменных окружения непосредственно в файле конфигурации easyp.yaml. Это позволяет использовать переменные окружения для динамических значений конфигурации."},{"id":"cli/configuration/configuration::top::46","title":"EasyP Configuration Reference","section":"Переменные окружения в конфигурации","path":"/docs/guide/cli/configuration/configuration","headings":["Переменные окружения в конфигурации"],"excerpt":"Переменные окружения в конфигурации **Пример со всеми поддерживаемыми возможностями:** ```yaml deps: # Базовое расширение: ${VAR} - расширяется в значение переменной VAR - ${GOOGLEAPIS_REPO}@${GOOGLEAPIS_VERSION} # Значе","content":"Переменные окружения в конфигурации **Пример со всеми поддерживаемыми возможностями:** ```yaml deps: # Базовое расширение: ${VAR} - расширяется в значение переменной VAR - ${GOOGLEAPIS_REPO}@${GOOGLEAPIS_VERSION} # Значение по умолчанию: ${VAR:-default} - использует default, если VAR не установлена или пустая - ${GNOSTIC_REPO:-github.com/google/gnostic}@${GNOSTIC_VERSION:-v0.7.0}"},{"id":"cli/configuration/configuration::top::47","title":"EasyP Configuration Reference","section":"Переменные окружения в конфигурации","path":"/docs/guide/cli/configuration/configuration","headings":["Переменные окружения в конфигурации"],"excerpt":"Переменные окружения в конфигурации generate: inputs: # Значение по умолчанию, если INPUT_DIR не установлена - directory: ${INPUT_DIR:-proto} plugins: - name: go # Базовое расширение out: ${OUTPUT_DIR} opts: # Значение п","content":"Переменные окружения в конфигурации generate: inputs: # Значение по умолчанию, если INPUT_DIR не установлена - directory: ${INPUT_DIR:-proto} plugins: - name: go # Базовое расширение out: ${OUTPUT_DIR} opts: # Значение по умолчанию module: ${MODULE_NAME:-github.com/example/project} timeout: ${TIMEOUT:-30} # Экранирование: $$ становится буквальным $, $${VAR} становится буквальным ${VAR} path: \"${BASE_DIR}/$${TEMP}/file\" # Результат: \"/tmp/${TEMP}/file\" (если BASE_DIR=/tmp) literal: \"$$\" # Результат: \"$\" ```"},{"id":"cli/configuration/configuration::top::48","title":"EasyP Configuration Reference","section":"Переменные окружения в конфигурации","path":"/docs/guide/cli/configuration/configuration","headings":["Переменные окружения в конфигурации"],"excerpt":"Переменные окружения в конфигурации **Поддерживаемый синтаксис:** ${VAR} - расширяется в значение переменной VAR ${VAR:-default} - использует default, если VAR не установлена или пустая ${VAR:=default} - использует defau","content":"Переменные окружения в конфигурации **Поддерживаемый синтаксис:** ${VAR} - расширяется в значение переменной VAR ${VAR:-default} - использует default, если VAR не установлена или пустая ${VAR:=default} - использует default, если VAR не установлена или пустая ${VAR-default} - использует default, если VAR не установлена (пустая строка сохраняется) $${VAR} или $$VAR - экранирует в буквальную строку ${VAR} или $VAR $$ - экранирует в буквальный символ $"},{"id":"cli/configuration/configuration::top::49","title":"EasyP Configuration Reference","section":"Переменные окружения в конфигурации","path":"/docs/guide/cli/configuration/configuration","headings":["Переменные окружения в конфигурации"],"excerpt":"Переменные окружения в конфигурации **Примечание:** Переменные окружения расширяются до парсинга YAML, поэтому любой паттерн ${STRING} будет обработан. Используйте $$ для экранирования символов доллара, когда нужны буква","content":"Переменные окружения в конфигурации **Примечание:** Переменные окружения расширяются до парсинга YAML, поэтому любой паттерн ${STRING} будет обработан. Используйте $$ для экранирования символов доллара, когда нужны буквальные значения."},{"id":"cli/configuration/configuration::version::50","title":"EasyP Configuration Reference","section":"version","path":"/docs/guide/cli/configuration/configuration#version","headings":["version"],"excerpt":"version **Опционально (legacy-совместимость).** Поле поддерживается для обратной совместимости и может быть опущено в новых конфигурациях.","content":"version **Опционально (legacy-совместимость).** Поле поддерживается для обратной совместимости и может быть опущено в новых конфигурациях."},{"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:** не задано **Рекомендация:** если сохраняете поле, используйте v1alpha","content":"version **Type:** string **Default:** не задано **Рекомендация:** если сохраняете поле, используйте v1alpha"},{"id":"cli/configuration/configuration::version::52","title":"EasyP Configuration Reference","section":"version","path":"/docs/guide/cli/configuration/configuration#version","headings":["version"],"excerpt":"version На поведение рантайма это поле не влияет.","content":"version На поведение рантайма это поле не влияет."},{"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, required) - Output directory for generated files opts (mapstring, optional) - Plugin-specific options; each key can be a single value or an array of 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::top::0","title":"Go","section":"Установка плагинов","path":"/docs/guide/cli/generator/examples/go","headings":["Установка плагинов"],"excerpt":"Установка плагинов Сначала установите необходимые плагины для работы с gRPC:","content":"Установка плагинов Сначала установите необходимые плагины для работы с gRPC:"},{"id":"cli/generator/examples/go::top::1","title":"Go","section":"Установка плагинов","path":"/docs/guide/cli/generator/examples/go","headings":["Установка плагинов"],"excerpt":"Установка плагинов Эти команды установят плагины protoc-gen-go и protoc-gen-go-grpc для использования с EasyP.","content":"Установка плагинов Эти команды установят плагины protoc-gen-go и protoc-gen-go-grpc для использования с EasyP."},{"id":"cli/generator/examples/go::proto::2","title":"Go","section":"Пример proto‑сервиса","path":"/docs/guide/cli/generator/examples/go#proto","headings":["Пример proto‑сервиса"],"excerpt":"Пример proto‑сервиса Ниже пример proto-файла для сервиса Echo:","content":"Пример proto‑сервиса Ниже пример proto-файла для сервиса Echo:"},{"id":"cli/generator/examples/go::proto::3","title":"Go","section":"Пример proto‑сервиса","path":"/docs/guide/cli/generator/examples/go#proto","headings":["Пример proto‑сервиса"],"excerpt":"Пример proto‑сервиса ```proto syntax = \"proto3\";","content":"Пример proto‑сервиса ```proto syntax = \"proto3\";"},{"id":"cli/generator/examples/go::proto::4","title":"Go","section":"Пример proto‑сервиса","path":"/docs/guide/cli/generator/examples/go#proto","headings":["Пример proto‑сервиса"],"excerpt":"Пример proto‑сервиса package api.echo.v1;","content":"Пример proto‑сервиса package api.echo.v1;"},{"id":"cli/generator/examples/go::proto::5","title":"Go","section":"Пример proto‑сервиса","path":"/docs/guide/cli/generator/examples/go#proto","headings":["Пример proto‑сервиса"],"excerpt":"Пример proto‑сервиса option go_package = \"github.com/easyp-tech/example/api/echo/v1;pb\";","content":"Пример proto‑сервиса option go_package = \"github.com/easyp-tech/example/api/echo/v1;pb\";"},{"id":"cli/generator/examples/go::proto::6","title":"Go","section":"Пример proto‑сервиса","path":"/docs/guide/cli/generator/examples/go#proto","headings":["Пример proto‑сервиса"],"excerpt":"Пример proto‑сервиса service EchoAPI { rpc Echo(EchoRequest) returns (EchoResponse); rpc EchoStream(EchoStreamRequest) returns (EchoResponse); }","content":"Пример proto‑сервиса service EchoAPI { rpc Echo(EchoRequest) returns (EchoResponse); rpc EchoStream(EchoStreamRequest) returns (EchoResponse); }"},{"id":"cli/generator/examples/go::proto::7","title":"Go","section":"Пример proto‑сервиса","path":"/docs/guide/cli/generator/examples/go#proto","headings":["Пример proto‑сервиса"],"excerpt":"Пример proto‑сервиса message EchoRequest { string payload = 1; }","content":"Пример proto‑сервиса message EchoRequest { string payload = 1; }"},{"id":"cli/generator/examples/go::proto::8","title":"Go","section":"Пример proto‑сервиса","path":"/docs/guide/cli/generator/examples/go#proto","headings":["Пример proto‑сервиса"],"excerpt":"Пример proto‑сервиса message EchoResponse { string payload = 2; }","content":"Пример proto‑сервиса message EchoResponse { string payload = 2; }"},{"id":"cli/generator/examples/go::proto::9","title":"Go","section":"Пример proto‑сервиса","path":"/docs/guide/cli/generator/examples/go#proto","headings":["Пример proto‑сервиса"],"excerpt":"Пример proto‑сервиса message EchoStreamRequest { string payload = 1; }","content":"Пример proto‑сервиса message EchoStreamRequest { string payload = 1; }"},{"id":"cli/generator/examples/go::proto::10","title":"Go","section":"Пример proto‑сервиса","path":"/docs/guide/cli/generator/examples/go#proto","headings":["Пример proto‑сервиса"],"excerpt":"Пример proto‑сервиса message EchoStreamResponse { string payload = 2; } ```","content":"Пример proto‑сервиса message EchoStreamResponse { string payload = 2; } ```"},{"id":"cli/generator/examples/go::top::11","title":"Go","section":"Настройка конфигурации","path":"/docs/guide/cli/generator/examples/go","headings":["Настройка конфигурации"],"excerpt":"Настройка конфигурации Создайте и настройте файл конфигурации easyp.yaml:","content":"Настройка конфигурации Создайте и настройте файл конфигурации easyp.yaml:"},{"id":"cli/generator/examples/go::top::12","title":"Go","section":"Настройка конфигурации","path":"/docs/guide/cli/generator/examples/go","headings":["Настройка конфигурации"],"excerpt":"Настройка конфигурации Этот файл указывает использование двух плагинов: go для генерации Go-кода и go-grpc для генерации gRPC-кода, вместе с их опциями.","content":"Настройка конфигурации Этот файл указывает использование двух плагинов: go для генерации Go-кода и go-grpc для генерации gRPC-кода, вместе с их опциями."},{"id":"cli/generator/examples/go::top::13","title":"Go","section":"Генерация кода","path":"/docs/guide/cli/generator/examples/go","headings":["Генерация кода"],"excerpt":"Генерация кода Чтобы сгенерировать код, выполните команду:","content":"Генерация кода Чтобы сгенерировать код, выполните команду:"},{"id":"cli/generator/examples/go::top::14","title":"Go","section":"Генерация кода","path":"/docs/guide/cli/generator/examples/go","headings":["Генерация кода"],"excerpt":"Генерация кода Если флаг --cfg не указан, по умолчанию используется файл easyp.yaml в текущей директории:","content":"Генерация кода Если флаг --cfg не указан, по умолчанию используется файл easyp.yaml в текущей директории:"},{"id":"cli/generator/examples/go::top::15","title":"Go","section":"Генерация кода","path":"/docs/guide/cli/generator/examples/go","headings":["Генерация кода"],"excerpt":"Генерация кода Теперь у вас есть сгенерированный Go‑код, с которым можно напрямую работать.","content":"Генерация кода Теперь у вас есть сгенерированный Go‑код, с которым можно напрямую работать."},{"id":"cli/generator/examples/grpc-gateway::top::0","title":"gRPC-Gateway","section":"Установка плагинов","path":"/docs/guide/cli/generator/examples/grpc-gateway","headings":["Установка плагинов"],"excerpt":"Установка плагинов В дополнение к плагинам для работы с gRPC, необходимо установить следующие плагины для gRPC-Gateway:","content":"Установка плагинов В дополнение к плагинам для работы с gRPC, необходимо установить следующие плагины для gRPC-Gateway:"},{"id":"cli/generator/examples/grpc-gateway::top::1","title":"gRPC-Gateway","section":"Установка плагинов","path":"/docs/guide/cli/generator/examples/grpc-gateway","headings":["Установка плагинов"],"excerpt":"Установка плагинов go install google.golang.org/protobuf/cmd/protoc-gen-go@latest go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest go install github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2@","content":"Установка плагинов go install google.golang.org/protobuf/cmd/protoc-gen-go@latest go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest go install github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2@latest go install github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway@latest"},{"id":"cli/generator/examples/grpc-gateway::top::2","title":"gRPC-Gateway","section":"Установка плагинов","path":"/docs/guide/cli/generator/examples/grpc-gateway","headings":["Установка плагинов"],"excerpt":"Установка плагинов Эти команды установят плагины protoc-gen-go, protoc-gen-go-grpc, protoc-gen-openapiv2 и protoc-gen-grpc-gateway для использования с EasyP.","content":"Установка плагинов Эти команды установят плагины protoc-gen-go, protoc-gen-go-grpc, protoc-gen-openapiv2 и protoc-gen-grpc-gateway для использования с EasyP."},{"id":"cli/generator/examples/grpc-gateway::proto::3","title":"gRPC-Gateway","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/grpc-gateway#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса Ниже — исходный proto‑файл для сервиса Echo:","content":"Пример Proto сервиса Ниже — исходный proto‑файл для сервиса Echo:"},{"id":"cli/generator/examples/grpc-gateway::proto::4","title":"gRPC-Gateway","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/grpc-gateway#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса syntax = \"proto3\";","content":"Пример Proto сервиса syntax = \"proto3\";"},{"id":"cli/generator/examples/grpc-gateway::proto::5","title":"gRPC-Gateway","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/grpc-gateway#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса package api.echo.v1;","content":"Пример Proto сервиса package api.echo.v1;"},{"id":"cli/generator/examples/grpc-gateway::proto::6","title":"gRPC-Gateway","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/grpc-gateway#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса option go_package = \"github.com/easyp-tech/example/api/echo/v1;pb\";","content":"Пример Proto сервиса option go_package = \"github.com/easyp-tech/example/api/echo/v1;pb\";"},{"id":"cli/generator/examples/grpc-gateway::proto::7","title":"gRPC-Gateway","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/grpc-gateway#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса service EchoAPI { rpc Echo(EchoRequest) returns (EchoResponse); }","content":"Пример Proto сервиса service EchoAPI { rpc Echo(EchoRequest) returns (EchoResponse); }"},{"id":"cli/generator/examples/grpc-gateway::proto::8","title":"gRPC-Gateway","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/grpc-gateway#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса message EchoRequest { string payload = 1; }","content":"Пример Proto сервиса message EchoRequest { string payload = 1; }"},{"id":"cli/generator/examples/grpc-gateway::proto::9","title":"gRPC-Gateway","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/grpc-gateway#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса message EchoResponse { string payload = 2; }","content":"Пример Proto сервиса message EchoResponse { string payload = 2; }"},{"id":"cli/generator/examples/grpc-gateway::proto::10","title":"gRPC-Gateway","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/grpc-gateway#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса Чтобы использовать gRPC-Gateway, обновите proto‑файл, добавив HTTP‑опции:","content":"Пример Proto сервиса Чтобы использовать gRPC-Gateway, обновите proto‑файл, добавив HTTP‑опции:"},{"id":"cli/generator/examples/grpc-gateway::proto::11","title":"gRPC-Gateway","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/grpc-gateway#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса syntax = \"proto3\"; import \"google/api/annotations.proto\";","content":"Пример Proto сервиса syntax = \"proto3\"; import \"google/api/annotations.proto\";"},{"id":"cli/generator/examples/grpc-gateway::proto::12","title":"gRPC-Gateway","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/grpc-gateway#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса package api.echo.v1;","content":"Пример Proto сервиса package api.echo.v1;"},{"id":"cli/generator/examples/grpc-gateway::proto::13","title":"gRPC-Gateway","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/grpc-gateway#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса option go_package = \"github.com/easyp-tech/example/api/echo/v1;pb\";","content":"Пример Proto сервиса option go_package = \"github.com/easyp-tech/example/api/echo/v1;pb\";"},{"id":"cli/generator/examples/grpc-gateway::proto::14","title":"gRPC-Gateway","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/grpc-gateway#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса service EchoAPI { rpc Echo(EchoRequest) returns (EchoResponse) { option (google.api.http) = { // [!code ++] post: \"/api/v1/echo\" // [!code ++] body: \"*\" // [!code ++] }; // [!code ++] } }","content":"Пример Proto сервиса 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::proto::15","title":"gRPC-Gateway","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/grpc-gateway#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса message EchoRequest { string payload = 1; }","content":"Пример Proto сервиса message EchoRequest { string payload = 1; }"},{"id":"cli/generator/examples/grpc-gateway::proto::16","title":"gRPC-Gateway","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/grpc-gateway#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса message EchoResponse { string payload = 2; }","content":"Пример Proto сервиса message EchoResponse { string payload = 2; }"},{"id":"cli/generator/examples/grpc-gateway::top::17","title":"gRPC-Gateway","section":"Настройка конфигурации","path":"/docs/guide/cli/generator/examples/grpc-gateway","headings":["Настройка конфигурации"],"excerpt":"Настройка конфигурации Обновите файл easyp.yaml, добавив необходимые зависимости и плагины: deps: # [!code ++] - github.com/googleapis/googleapis # [!code ++]","content":"Настройка конфигурации Обновите файл easyp.yaml, добавив необходимые зависимости и плагины: deps: # [!code ++] - github.com/googleapis/googleapis # [!code ++]"},{"id":"cli/generator/examples/grpc-gateway::top::18","title":"gRPC-Gateway","section":"Настройка конфигурации","path":"/docs/guide/cli/generator/examples/grpc-gateway","headings":["Настройка конфигурации"],"excerpt":"Настройка конфигурации 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":"Настройка конфигурации 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::top::19","title":"gRPC-Gateway","section":"Настройка конфигурации","path":"/docs/guide/cli/generator/examples/grpc-gateway","headings":["Настройка конфигурации"],"excerpt":"Настройка конфигурации Секция deps перечисляет зависимости, необходимые для импортов proto‑файлов. В данном случае добавляем github.com/googleapis/googleapis, поскольку там находится файл annotations.proto, используемый ","content":"Настройка конфигурации Секция deps перечисляет зависимости, необходимые для импортов proto‑файлов. В данном случае добавляем github.com/googleapis/googleapis, поскольку там находится файл annotations.proto, используемый в определении сервиса."},{"id":"cli/generator/examples/grpc-gateway::top::20","title":"gRPC-Gateway","section":"Обновление зависимостей","path":"/docs/guide/cli/generator/examples/grpc-gateway","headings":["Обновление зависимостей"],"excerpt":"Обновление зависимостей После обновления конфигурации выполните команду для загрузки указанных зависимостей:","content":"Обновление зависимостей После обновления конфигурации выполните команду для загрузки указанных зависимостей:"},{"id":"cli/generator/examples/grpc-gateway::top::21","title":"gRPC-Gateway","section":"Обновление зависимостей","path":"/docs/guide/cli/generator/examples/grpc-gateway","headings":["Обновление зависимостей"],"excerpt":"Обновление зависимостей easyp mod update","content":"Обновление зависимостей easyp mod update"},{"id":"cli/generator/examples/grpc-gateway::top::22","title":"gRPC-Gateway","section":"Обновление зависимостей","path":"/docs/guide/cli/generator/examples/grpc-gateway","headings":["Обновление зависимостей"],"excerpt":"Обновление зависимостей Больше деталей по управлению зависимостями см. в разделе Package Manager.","content":"Обновление зависимостей Больше деталей по управлению зависимостями см. в разделе Package Manager."},{"id":"cli/generator/examples/grpc-gateway::top::23","title":"gRPC-Gateway","section":"Генерация кода","path":"/docs/guide/cli/generator/examples/grpc-gateway","headings":["Генерация кода"],"excerpt":"Генерация кода Для генерации кода используйте:","content":"Генерация кода Для генерации кода используйте:"},{"id":"cli/generator/examples/grpc-gateway::top::24","title":"gRPC-Gateway","section":"Генерация кода","path":"/docs/guide/cli/generator/examples/grpc-gateway","headings":["Генерация кода"],"excerpt":"Генерация кода easyp --cfg easyp.yaml generate","content":"Генерация кода easyp --cfg easyp.yaml generate"},{"id":"cli/generator/examples/grpc-gateway::top::25","title":"gRPC-Gateway","section":"Генерация кода","path":"/docs/guide/cli/generator/examples/grpc-gateway","headings":["Генерация кода"],"excerpt":"Генерация кода Если флаг --cfg не указан, по умолчанию используется файл easyp.yaml из текущей директории:","content":"Генерация кода Если флаг --cfg не указан, по умолчанию используется файл easyp.yaml из текущей директории:"},{"id":"cli/generator/examples/grpc-gateway::top::26","title":"gRPC-Gateway","section":"Генерация кода","path":"/docs/guide/cli/generator/examples/grpc-gateway","headings":["Генерация кода"],"excerpt":"Генерация кода Теперь у вас сгенерированы Go‑код и код gRPC-Gateway, с которыми можно работать напрямую.","content":"Генерация кода Теперь у вас сгенерированы Go‑код и код gRPC-Gateway, с которыми можно работать напрямую."},{"id":"cli/generator/examples/validate::top::0","title":"Validate","section":"Установка плагинов","path":"/docs/guide/cli/generator/examples/validate","headings":["Установка плагинов"],"excerpt":"Установка плагинов Сначала установите необходимые плагины для работы с gRPC и проверок (validate):","content":"Установка плагинов Сначала установите необходимые плагины для работы с gRPC и проверок (validate):"},{"id":"cli/generator/examples/validate::top::1","title":"Validate","section":"Установка плагинов","path":"/docs/guide/cli/generator/examples/validate","headings":["Установка плагинов"],"excerpt":"Установка плагинов Эти команды установят плагины protoc-gen-go, protoc-gen-go-grpc и protoc-gen-validate для использования вместе с EasyP.","content":"Установка плагинов Эти команды установят плагины protoc-gen-go, protoc-gen-go-grpc и protoc-gen-validate для использования вместе с EasyP."},{"id":"cli/generator/examples/validate::proto::2","title":"Validate","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/validate#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса Ниже пример proto‑файла для сервиса Echo:","content":"Пример Proto сервиса Ниже пример proto‑файла для сервиса Echo:"},{"id":"cli/generator/examples/validate::proto::3","title":"Validate","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/validate#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса ```proto syntax = \"proto3\";","content":"Пример Proto сервиса ```proto syntax = \"proto3\";"},{"id":"cli/generator/examples/validate::proto::4","title":"Validate","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/validate#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса package api.echo.v1;","content":"Пример Proto сервиса package api.echo.v1;"},{"id":"cli/generator/examples/validate::proto::5","title":"Validate","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/validate#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса import \"validate/validate.proto\";","content":"Пример Proto сервиса import \"validate/validate.proto\";"},{"id":"cli/generator/examples/validate::proto::6","title":"Validate","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/validate#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса option go_package = \"github.com/easyp-tech/example/api/echo/v1;pb\";","content":"Пример Proto сервиса option go_package = \"github.com/easyp-tech/example/api/echo/v1;pb\";"},{"id":"cli/generator/examples/validate::proto::7","title":"Validate","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/validate#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса service EchoAPI { rpc Echo(EchoRequest) returns (EchoResponse); rpc EchoStream(EchoStreamRequest) returns (EchoResponse); }","content":"Пример Proto сервиса service EchoAPI { rpc Echo(EchoRequest) returns (EchoResponse); rpc EchoStream(EchoStreamRequest) returns (EchoResponse); }"},{"id":"cli/generator/examples/validate::proto::8","title":"Validate","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/validate#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса message EchoRequest { string payload = 1 [(validate.rules).string = {max_len: 200}]; }","content":"Пример Proto сервиса message EchoRequest { string payload = 1 [(validate.rules).string = {max_len: 200}]; }"},{"id":"cli/generator/examples/validate::proto::9","title":"Validate","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/validate#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса message EchoResponse { string payload = 2; }","content":"Пример Proto сервиса message EchoResponse { string payload = 2; }"},{"id":"cli/generator/examples/validate::proto::10","title":"Validate","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/validate#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса message EchoStreamRequest { string payload = 1 [(validate.rules).string = {max_len: 200}]; }","content":"Пример Proto сервиса message EchoStreamRequest { string payload = 1 [(validate.rules).string = {max_len: 200}]; }"},{"id":"cli/generator/examples/validate::proto::11","title":"Validate","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/validate#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса message EchoStreamResponse { string payload = 2; } ```","content":"Пример Proto сервиса message EchoStreamResponse { string payload = 2; } ```"},{"id":"cli/generator/examples/validate::top::12","title":"Validate","section":"Настройка конфигурации","path":"/docs/guide/cli/generator/examples/validate","headings":["Настройка конфигурации"],"excerpt":"Настройка конфигурации Создайте и настройте файл конфигурации easyp.yaml:","content":"Настройка конфигурации Создайте и настройте файл конфигурации easyp.yaml:"},{"id":"cli/generator/examples/validate::top::13","title":"Validate","section":"Настройка конфигурации","path":"/docs/guide/cli/generator/examples/validate","headings":["Настройка конфигурации"],"excerpt":"Настройка конфигурации ```yaml deps: # [!code ++] - github.com/bufbuild/protoc-gen-validate # [!code ++]","content":"Настройка конфигурации ```yaml deps: # [!code ++] - github.com/bufbuild/protoc-gen-validate # [!code ++]"},{"id":"cli/generator/examples/validate::top::14","title":"Validate","section":"Настройка конфигурации","path":"/docs/guide/cli/generator/examples/validate","headings":["Настройка конфигурации"],"excerpt":"Настройка конфигурации 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: sourc","content":"Настройка конфигурации 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::top::15","title":"Validate","section":"Генерация кода","path":"/docs/guide/cli/generator/examples/validate","headings":["Генерация кода"],"excerpt":"Генерация кода Чтобы сгенерировать код, выполните команду:","content":"Генерация кода Чтобы сгенерировать код, выполните команду:"},{"id":"cli/generator/examples/validate::top::16","title":"Validate","section":"Генерация кода","path":"/docs/guide/cli/generator/examples/validate","headings":["Генерация кода"],"excerpt":"Генерация кода Если флаг --cfg не указан, по умолчанию используется файл easyp.yaml из текущего каталога:","content":"Генерация кода Если флаг --cfg не указан, по умолчанию используется файл easyp.yaml из текущего каталога:"},{"id":"cli/generator/examples/validate::top::17","title":"Validate","section":"Генерация кода","path":"/docs/guide/cli/generator/examples/validate","headings":["Генерация кода"],"excerpt":"Генерация кода Теперь у вас есть сгенерированный Go‑код с поддержкой валидации, и вы можете напрямую использовать его в проекте.","content":"Генерация кода Теперь у вас есть сгенерированный Go‑код с поддержкой валидации, и вы можете напрямую использовать его в проекте."},{"id":"cli/generator/generator::top::0","title":"Генератор","path":"/docs/guide/cli/generator/generator","headings":[],"excerpt":"EasyP включает мощный генератор, который упрощает процесс получения кода из proto‑файлов. Благодаря YAML‑конфигурациям работа становится гораздо более удобной и интуитивной по сравнению с прямым использованием команды pr","content":"EasyP включает мощный генератор, который упрощает процесс получения кода из proto‑файлов. Благодаря YAML‑конфигурациям работа становится гораздо более удобной и интуитивной по сравнению с прямым использованием команды protoc."},{"id":"cli/generator/generator::top::1","title":"Генератор","section":"Ключевые особенности генератора","path":"/docs/guide/cli/generator/generator","headings":["Ключевые особенности генератора"],"excerpt":"Ключевые особенности генератора **Упрощённая генерация кода**: - Генерация кода из proto через декларативную YAML‑конфигурацию. - Избавляет от необходимости писать длинные и сложные команды protoc.","content":"Ключевые особенности генератора **Упрощённая генерация кода**: - Генерация кода из proto через декларативную YAML‑конфигурацию. - Избавляет от необходимости писать длинные и сложные команды protoc."},{"id":"cli/generator/generator::top::2","title":"Генератор","section":"Ключевые особенности генератора","path":"/docs/guide/cli/generator/generator","headings":["Ключевые особенности генератора"],"excerpt":"Ключевые особенности генератора **Обёртка над protoc**: - EasyP выступает как удобный слой над protoc, предоставляя декларативный API. - Поддерживает все опции и плагины, доступные protoc.","content":"Ключевые особенности генератора **Обёртка над protoc**: - EasyP выступает как удобный слой над protoc, предоставляя декларативный API. - Поддерживает все опции и плагины, доступные protoc."},{"id":"cli/generator/generator::top::3","title":"Генератор","section":"Ключевые особенности генератора","path":"/docs/guide/cli/generator/generator","headings":["Ключевые особенности генератора"],"excerpt":"Ключевые особенности генератора **Гибкость и кастомизация**: - Используются те же параметры, что и у плагинов protoc, прямо в конфиге. - Поддерживается множество плагинов и их параметры в одной конфигурации.","content":"Ключевые особенности генератора **Гибкость и кастомизация**: - Используются те же параметры, что и у плагинов protoc, прямо в конфиге. - Поддерживается множество плагинов и их параметры в одной конфигурации."},{"id":"cli/generator/generator::top::4","title":"Генератор","section":"Ключевые особенности генератора","path":"/docs/guide/cli/generator/generator","headings":["Ключевые особенности генератора"],"excerpt":"Ключевые особенности генератора **Генерация из нескольких источников**: - Локальные директории и удалённые Git‑репозитории одновременно. - Лёгкая интеграция с существующими проектами и репозиториями.","content":"Ключевые особенности генератора **Генерация из нескольких источников**: - Локальные директории и удалённые Git‑репозитории одновременно. - Лёгкая интеграция с существующими проектами и репозиториями."},{"id":"cli/generator/generator::top::5","title":"Генератор","section":"Ключевые особенности генератора","path":"/docs/guide/cli/generator/generator","headings":["Ключевые особенности генератора"],"excerpt":"Ключевые особенности генератора **Удалённая генерация**: - Генерация из удалённых Git репозиториев без локального checkout.","content":"Ключевые особенности генератора **Удалённая генерация**: - Генерация из удалённых Git репозиториев без локального checkout."},{"id":"cli/generator/generator::top::6","title":"Генератор","section":"Ключевые особенности генератора","path":"/docs/guide/cli/generator/generator","headings":["Ключевые особенности генератора"],"excerpt":"Ключевые особенности генератора **Интеграция с менеджером пакетов**: - Прозрачная работа с зависимостями через пакетный менеджер EasyP. - Автоматическое разрешение и подключение proto‑зависимостей.","content":"Ключевые особенности генератора **Интеграция с менеджером пакетов**: - Прозрачная работа с зависимостями через пакетный менеджер EasyP. - Автоматическое разрешение и подключение proto‑зависимостей."},{"id":"cli/generator/generator::complete-configuration-example::7","title":"Генератор","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":"Генератор","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":"Генератор","section":"Complete Configuration Example","path":"/docs/guide/cli/generator/generator#complete-configuration-example","headings":["Complete Configuration Example"],"excerpt":"Complete Configuration Example Managed mode - автоматическая установка file и field опций managed: enabled: true disable: - module: github.com/googleapis/googleapis # Отключить для конкретного модуля override: - file_opt","content":"Complete Configuration Example Managed mode - автоматическая установка file и field опций managed: enabled: true disable: - module: github.com/googleapis/googleapis # Отключить для конкретного модуля 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/ # Применить к конкретному пути"},{"id":"cli/generator/generator::complete-configuration-example::10","title":"Генератор","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":"Генератор","section":"Локальный ввод (Local Directory Input)","path":"/docs/guide/cli/generator/generator#local-directory-input","headings":["Локальный ввод (Local Directory Input)"],"excerpt":"Локальный ввод (Local Directory Input) Локальная директория — самый распространённый и простой способ указать откуда брать proto для генерации. Используйте этот вариант, если файлы уже находятся в репозитории проекта.","content":"Локальный ввод (Local Directory Input) Локальная директория — самый распространённый и простой способ указать откуда брать proto для генерации. Используйте этот вариант, если файлы уже находятся в репозитории проекта."},{"id":"cli/generator/generator::local-directory-input::12","title":"Генератор","section":"Локальный ввод (Local Directory Input)","path":"/docs/guide/cli/generator/generator#local-directory-input","headings":["Локальный ввод (Local Directory Input)"],"excerpt":"Локальный ввод (Local Directory Input) **Когда применять:** Proto файлы находятся в кодовой базе проекта Нужен полный контроль над структурой каталогов Проект — один сервис или приложение Файлы меняются не слишком часто","content":"Локальный ввод (Local Directory Input) **Когда применять:** Proto файлы находятся в кодовой базе проекта Нужен полный контроль над структурой каталогов Проект — один сервис или приложение Файлы меняются не слишком часто"},{"id":"cli/generator/generator::local-directory-input::13","title":"Генератор","section":"Локальный ввод (Local Directory Input)","path":"/docs/guide/cli/generator/generator#local-directory-input","headings":["Локальный ввод (Local Directory Input)"],"excerpt":"Локальный ввод (Local Directory Input)","content":"Локальный ввод (Local Directory Input)"},{"id":"cli/generator/generator::local-directory-input::14","title":"Генератор","section":"Локальный ввод (Local Directory Input)","path":"/docs/guide/cli/generator/generator#local-directory-input","headings":["Локальный ввод (Local Directory Input)"],"excerpt":"Локальный ввод (Local Directory Input) Параметр root особенно полезен в монорепозиториях: он позволяет управлять тем, откуда будут резолвиться пути импортов. Если указать родительскую директорию, импорты будут оцениватьс","content":"Локальный ввод (Local Directory Input) Параметр root особенно полезен в монорепозиториях: он позволяет управлять тем, откуда будут резолвиться пути импортов. Если указать родительскую директорию, импорты будут оцениваться относительно неё, а не текущего рабочего каталога."},{"id":"cli/generator/generator::local-directory-input::15","title":"Генератор","section":"Локальный ввод (Local Directory Input)","path":"/docs/guide/cli/generator/generator#local-directory-input","headings":["Локальный ввод (Local Directory Input)"],"excerpt":"Локальный ввод (Local Directory Input) **Параметры:**","content":"Локальный ввод (Local Directory Input) **Параметры:**"},{"id":"cli/generator/generator::local-directory-input::16","title":"Генератор","section":"Локальный ввод (Local Directory Input)","path":"/docs/guide/cli/generator/generator#local-directory-input","headings":["Локальный ввод (Local Directory Input)"],"excerpt":"Локальный ввод (Local Directory Input) Параметр Тип Обязателен Значение по умолчанию Описание ---------- ----- ------------ ----------------------- ---------- path string ✅ - Каталог, содержащий proto файлы root string ❌","content":"Локальный ввод (Local Directory Input) Параметр Тип Обязателен Значение по умолчанию Описание ---------- ----- ------------ ----------------------- ---------- path string ✅ - Каталог, содержащий proto файлы root string ❌ \".\" Корневая директория для разрешения import путей"},{"id":"cli/generator/generator::local-directory-input::17","title":"Генератор","section":"Локальный ввод (Local Directory Input)","path":"/docs/guide/cli/generator/generator#local-directory-input","headings":["Локальный ввод (Local Directory Input)"],"excerpt":"Локальный ввод (Local Directory Input) **Примеры:**","content":"Локальный ввод (Local Directory Input) **Примеры:**"},{"id":"cli/generator/generator::local-directory-input::18","title":"Генератор","section":"Локальный ввод (Local Directory Input)","path":"/docs/guide/cli/generator/generator#local-directory-input","headings":["Локальный ввод (Local Directory Input)"],"excerpt":"Локальный ввод (Local Directory Input) Ниже показана разница между базовым указанием директории и расширенной конфигурацией с пользовательским корнем импортов:","content":"Локальный ввод (Local Directory Input) Ниже показана разница между базовым указанием директории и расширенной конфигурацией с пользовательским корнем импортов:"},{"id":"cli/generator/generator::local-directory-input::19","title":"Генератор","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::20","title":"Генератор","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::git-remote-git-repository-input::21","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) Этот тип входных данных позволяет генерировать код из proto‑файлов, находящихся в удалённых репозиториях, без локального checkout. Особенно полезно при использовани","content":"Удалённый Git репозиторий (Remote Git Repository Input) Этот тип входных данных позволяет генерировать код из proto‑файлов, находящихся в удалённых репозиториях, без локального checkout. Особенно полезно при использовании API других команд или внешних поставщиков."},{"id":"cli/generator/generator::git-remote-git-repository-input::22","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) **Когда использовать:** Потребление proto определений из других сервисов/команд Интеграция с внешними вендорскими API Работа с общими библиотеками proto в нескольки","content":"Удалённый Git репозиторий (Remote Git Repository Input) **Когда использовать:** Потребление proto определений из других сервисов/команд Интеграция с внешними вендорскими API Работа с общими библиотеками proto в нескольких проектах Необходимо гарантировать корректную (зафиксированную) версию внешних API"},{"id":"cli/generator/generator::git-remote-git-repository-input::23","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) **Рекомендации:** В продакшене всегда фиксируйте версии (@v1.0.0, а не latest) Используйте семантические версии при наличии — проще сопровождать Предпочитайте публи","content":"Удалённый Git репозиторий (Remote Git Repository Input) **Рекомендации:** В продакшене всегда фиксируйте версии (@v1.0.0, а не latest) Используйте семантические версии при наличии — проще сопровождать Предпочитайте публичные теги вместо хеша коммита (лучше отслеживаемость)"},{"id":"cli/generator/generator::git-remote-git-repository-input::24","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input)","content":"Удалённый Git репозиторий (Remote Git Repository Input)"},{"id":"cli/generator/generator::git-remote-git-repository-input::25","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) Параметр root задаёт корень для разрешения импортов файлов из этого репозитория.","content":"Удалённый Git репозиторий (Remote Git Repository Input) Параметр root задаёт корень для разрешения импортов файлов из этого репозитория."},{"id":"cli/generator/generator::git-remote-git-repository-input::26","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) **Параметры:**","content":"Удалённый Git репозиторий (Remote Git Repository Input) **Параметры:**"},{"id":"cli/generator/generator::git-remote-git-repository-input::27","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) Параметр Тип Обязателен По умолчанию Описание ---------- ----- ------------ -------------- ---------- url string ✅ - URL Git репозитория с необязательной версией / ","content":"Удалённый Git репозиторий (Remote Git Repository Input) Параметр Тип Обязателен По умолчанию Описание ---------- ----- ------------ -------------- ---------- url string ✅ - URL Git репозитория с необязательной версией / тегом / коммитом sub_directory string ❌ \"\" Поддиректория внутри репозитория, где лежат proto root string ❌ \"\" Корневой путь для разрешения импортов"},{"id":"cli/generator/generator::git-remote-git-repository-input::28","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) **Варианты формата URL:**","content":"Удалённый Git репозиторий (Remote Git Repository Input) **Варианты формата URL:**"},{"id":"cli/generator/generator::git-remote-git-repository-input::29","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) EasyP поддерживает несколько форматов для ссылки на удалённые репозитории. Каждый подходит под разные требования по стабильности:","content":"Удалённый Git репозиторий (Remote Git Repository Input) EasyP поддерживает несколько форматов для ссылки на удалённые репозитории. Каждый подходит под разные требования по стабильности:"},{"id":"cli/generator/generator::git-remote-git-repository-input::30","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) **Tagged versions** — для продакшена, стабильные неизменяемые ссылки **Semantic versions** — читаемость и управление зависимостями **Commit hashes** — доступ к конк","content":"Удалённый Git репозиторий (Remote Git Repository Input) **Tagged versions** — для продакшена, стабильные неизменяемые ссылки **Semantic versions** — читаемость и управление зависимостями **Commit hashes** — доступ к конкретному коммиту, если нет тега **Latest** — только для разработки, непредсказуемо **Full HTTPS URLs** — приватные репозитории или нестандартный хостинг"},{"id":"cli/generator/generator::git-remote-git-repository-input::31","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) ```yaml Тег — стабильно для продакшена url: \"github.com/googleapis/googleapis@common-protos-1_3_1\"","content":"Удалённый Git репозиторий (Remote Git Repository Input) ```yaml Тег — стабильно для продакшена url: \"github.com/googleapis/googleapis@common-protos-1_3_1\""},{"id":"cli/generator/generator::git-remote-git-repository-input::32","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) Семантическая версия url: \"github.com/grpc-ecosystem/grpc-gateway@v2.19.1\"","content":"Удалённый Git репозиторий (Remote Git Repository Input) Семантическая версия url: \"github.com/grpc-ecosystem/grpc-gateway@v2.19.1\""},{"id":"cli/generator/generator::git-remote-git-repository-input::33","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) Хеш коммита — точечный фикс url: \"github.com/company/protos@abc123def456\"","content":"Удалённый Git репозиторий (Remote Git Repository Input) Хеш коммита — точечный фикс url: \"github.com/company/protos@abc123def456\""},{"id":"cli/generator/generator::git-remote-git-repository-input::34","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) Latest — только dev, НЕ для продакшена url: \"github.com/company/protos\"","content":"Удалённый Git репозиторий (Remote Git Repository Input) Latest — только dev, НЕ для продакшена url: \"github.com/company/protos\""},{"id":"cli/generator/generator::git-remote-git-repository-input::35","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) Полный HTTPS URL — приватный или кастомный Git url: \"https://github.com/company/private-protos.git\" ```","content":"Удалённый Git репозиторий (Remote Git Repository Input) Полный HTTPS URL — приватный или кастомный Git url: \"https://github.com/company/private-protos.git\" ```"},{"id":"cli/generator/generator::git-remote-git-repository-input::36","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) **Примеры:**","content":"Удалённый Git репозиторий (Remote Git Repository Input) **Примеры:**"},{"id":"cli/generator/generator::git-remote-git-repository-input::37","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) Ниже паттерны использования удалённых источников в разных сценариях:","content":"Удалённый Git репозиторий (Remote Git Repository Input) Ниже паттерны использования удалённых источников в разных сценариях:"},{"id":"cli/generator/generator::git-remote-git-repository-input::38","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input)","content":"Удалённый Git репозиторий (Remote Git Repository Input)"},{"id":"cli/generator/generator::top::39","title":"Генератор","section":"Конфигурация плагинов","path":"/docs/guide/cli/generator/generator","headings":["Конфигурация плагинов"],"excerpt":"Конфигурация плагинов Конфигурация плагинов определяет какие генераторы кода будут запущены и как они себя ведут. EasyP поддерживает любой плагин protoc, что делает его крайне гибким для разных языковых экосистем и сцена","content":"Конфигурация плагинов Конфигурация плагинов определяет какие генераторы кода будут запущены и как они себя ведут. EasyP поддерживает любой плагин protoc, что делает его крайне гибким для разных языковых экосистем и сценариев."},{"id":"cli/generator/generator::top::40","title":"Генератор","section":"Конфигурация плагинов","path":"/docs/guide/cli/generator/generator","headings":["Конфигурация плагинов"],"excerpt":"Конфигурация плагинов На верхнем уровне есть **четыре способа указать, как именно запускать плагин**:","content":"Конфигурация плагинов На верхнем уровне есть **четыре способа указать, как именно запускать плагин**:"},{"id":"cli/generator/generator::top::41","title":"Генератор","section":"Конфигурация плагинов","path":"/docs/guide/cli/generator/generator","headings":["Конфигурация плагинов"],"excerpt":"Конфигурация плагинов **name** – запуск плагина по имени из PATH или использование встроенного плагина. **path** – запуск плагина по абсолютному/относительному пути к исполняемому файлу. **remote** – удалённый плагин по ","content":"Конфигурация плагинов **name** – запуск плагина по имени из PATH или использование встроенного плагина. **path** – запуск плагина по абсолютному/относительному пути к исполняемому файлу. **remote** – удалённый плагин по URL (через remote‑executor EasyP). **command** – запуск плагина через произвольную команду (например, go run ...)."},{"id":"cli/generator/generator::top::42","title":"Генератор","section":"Конфигурация плагинов","path":"/docs/guide/cli/generator/generator","headings":["Конфигурация плагинов"],"excerpt":"Конфигурация плагинов Для каждого плагина должен быть указан **ровно один** из параметров name, path, remote или command.","content":"Конфигурация плагинов Для каждого плагина должен быть указан **ровно один** из параметров name, path, remote или command."},{"id":"cli/generator/generator::name::43","title":"Генератор","section":"Плагин по имени (name)","path":"/docs/guide/cli/generator/generator#name","headings":["Плагин по имени (name)"],"excerpt":"Плагин по имени (name) Локальный режим по имени — стандартный: плагины установлены в системе и запускаются напрямую через EasyP.","content":"Плагин по имени (name) Локальный режим по имени — стандартный: плагины установлены в системе и запускаются напрямую через EasyP."},{"id":"cli/generator/generator::name::44","title":"Генератор","section":"Плагин по имени (name)","path":"/docs/guide/cli/generator/generator#name","headings":["Плагин по имени (name)"],"excerpt":"Плагин по имени (name) **Когда использовать name:** Стандартные языки (Go, Python, TypeScript и т.д.) Есть контроль над окружением сборки Критична производительность (нет сетевых задержек) Хочется опираться на PATH или в","content":"Плагин по имени (name) **Когда использовать name:** Стандартные языки (Go, Python, TypeScript и т.д.) Есть контроль над окружением сборки Критична производительность (нет сетевых задержек) Хочется опираться на PATH или встроенные плагины"},{"id":"cli/generator/generator::name::45","title":"Генератор","section":"Плагин по имени (name)","path":"/docs/guide/cli/generator/generator#name","headings":["Плагин по имени (name)"],"excerpt":"Плагин по имени (name) **Требования к установке:** Плагины установлены и доступны в PATH (если не используются встроенные). Имена следуют шаблону protoc-gen-{name}. Установка через менеджеры пакетов (go install, npm inst","content":"Плагин по имени (name) **Требования к установке:** Плагины установлены и доступны в PATH (если не используются встроенные). Имена следуют шаблону protoc-gen-{name}. Установка через менеджеры пакетов (go install, npm install, pip install и т.п.)."},{"id":"cli/generator/generator::name::46","title":"Генератор","section":"Плагин по имени (name)","path":"/docs/guide/cli/generator/generator#name","headings":["Плагин по имени (name)"],"excerpt":"Плагин по имени (name) Параметр with_imports критичен при использовании зависимостей из пакетного менеджера: установите true, чтобы прототипы из секции deps попали в генерацию.","content":"Плагин по имени (name) Параметр with_imports критичен при использовании зависимостей из пакетного менеджера: установите true, чтобы прототипы из секции deps попали в генерацию."},{"id":"cli/generator/generator::path::47","title":"Генератор","section":"Плагин по пути (path)","path":"/docs/guide/cli/generator/generator#path","headings":["Плагин по пути (path)"],"excerpt":"Плагин по пути (path) Иногда нужно запускать плагин из конкретного бинарника, не добавляя его в PATH (например, бинарь в репозитории или в build‑директории). В этом случае можно указать явный путь:","content":"Плагин по пути (path) Иногда нужно запускать плагин из конкретного бинарника, не добавляя его в PATH (например, бинарь в репозитории или в build‑директории). В этом случае можно указать явный путь:"},{"id":"cli/generator/generator::path::48","title":"Генератор","section":"Плагин по пути (path)","path":"/docs/guide/cli/generator/generator#path","headings":["Плагин по пути (path)"],"excerpt":"Плагин по пути (path) **Когда использовать path:** Бинарники плагинов хранятся в репозитории (для воспроизводимых сборок). Используются несколько версий одного и того же плагина параллельно. Не хочется «загрязнять» глоба","content":"Плагин по пути (path) **Когда использовать path:** Бинарники плагинов хранятся в репозитории (для воспроизводимых сборок). Используются несколько версий одного и того же плагина параллельно. Не хочется «загрязнять» глобальный PATH."},{"id":"cli/generator/generator::remote::49","title":"Генератор","section":"Удалённый плагин (remote)","path":"/docs/guide/cli/generator/generator#remote","headings":["Удалённый плагин (remote)"],"excerpt":"Удалённый плагин (remote) Удалённые плагины выполняются по URL. EasyP отправляет на удалённую сторону CodeGeneratorRequest и получает обратно CodeGeneratorResponse.","content":"Удалённый плагин (remote) Удалённые плагины выполняются по URL. EasyP отправляет на удалённую сторону CodeGeneratorRequest и получает обратно CodeGeneratorResponse."},{"id":"cli/generator/generator::remote::50","title":"Генератор","section":"Удалённый плагин (remote)","path":"/docs/guide/cli/generator/generator#remote","headings":["Удалённый плагин (remote)"],"excerpt":"Удалённый плагин (remote) Ниже приведён реальный пример использования EasyP API Service как удалённого исполнителя плагинов (тот же формат используется в разделе про API Service):","content":"Удалённый плагин (remote) Ниже приведён реальный пример использования EasyP API Service как удалённого исполнителя плагинов (тот же формат используется в разделе про API Service):"},{"id":"cli/generator/generator::remote::51","title":"Генератор","section":"Удалённый плагин (remote)","path":"/docs/guide/cli/generator/generator#remote","headings":["Удалённый плагин (remote)"],"excerpt":"Удалённый плагин (remote) ```yaml generate: plugins: # Удалённое выполнение плагинов через EasyP API Service - remote: api.easyp.tech/protobuf/go:v1.36.10 out: . opts: paths: source_relative","content":"Удалённый плагин (remote) ```yaml generate: plugins: # Удалённое выполнение плагинов через EasyP API Service - remote: api.easyp.tech/protobuf/go:v1.36.10 out: . opts: paths: source_relative"},{"id":"cli/generator/generator::remote::52","title":"Генератор","section":"Удалённый плагин (remote)","path":"/docs/guide/cli/generator/generator#remote","headings":["Удалённый плагин (remote)"],"excerpt":"Удалённый плагин (remote) remote: api.easyp.tech/grpc/go:v1.5.1 out: . opts: paths: source_relative ```","content":"Удалённый плагин (remote) remote: api.easyp.tech/grpc/go:v1.5.1 out: . opts: paths: source_relative ```"},{"id":"cli/generator/generator::remote::53","title":"Генератор","section":"Удалённый плагин (remote)","path":"/docs/guide/cli/generator/generator#remote","headings":["Удалённый плагин (remote)"],"excerpt":"Удалённый плагин (remote) **Типичные сценарии для remote:** Централизованный сервис плагинов внутри компании (например, EasyP API Service). Запуск тяжёлых плагинов на выделенных машинах вместо CI‑агентов. Совместное испо","content":"Удалённый плагин (remote) **Типичные сценарии для remote:** Централизованный сервис плагинов внутри компании (например, EasyP API Service). Запуск тяжёлых плагинов на выделенных машинах вместо CI‑агентов. Совместное использование одной реализации плагина разными командами."},{"id":"cli/generator/generator::command::54","title":"Генератор","section":"Выполнение плагина через команду (command)","path":"/docs/guide/cli/generator/generator#command","headings":["Выполнение плагина через команду (command)"],"excerpt":"Выполнение плагина через команду (command) Вы можете указать плагин как массив команд для выполнения. Это полезно для запуска плагинов через go run или любые другие инструменты без предварительной установки бинарника пла","content":"Выполнение плагина через команду (command) Вы можете указать плагин как массив команд для выполнения. Это полезно для запуска плагинов через go run или любые другие инструменты без предварительной установки бинарника плагина:"},{"id":"cli/generator/generator::command::55","title":"Генератор","section":"Выполнение плагина через команду (command)","path":"/docs/guide/cli/generator/generator#command","headings":["Выполнение плагина через команду (command)"],"excerpt":"Выполнение плагина через команду (command)","content":"Выполнение плагина через команду (command)"},{"id":"cli/generator/generator::command::56","title":"Генератор","section":"Выполнение плагина через команду (command)","path":"/docs/guide/cli/generator/generator#command","headings":["Выполнение плагина через команду (command)"],"excerpt":"Выполнение плагина через команду (command) В этом режиме EasyP: **запускает указанную команду** как дочерний процесс; **пишет CodeGeneratorRequest в stdin** процесса; **читает CodeGeneratorResponse из stdout**, как и для","content":"Выполнение плагина через команду (command) В этом режиме EasyP: **запускает указанную команду** как дочерний процесс; **пишет CodeGeneratorRequest в stdin** процесса; **читает CodeGeneratorResponse из stdout**, как и для обычных плагинов protoc."},{"id":"cli/generator/generator::command::57","title":"Генератор","section":"Выполнение плагина через команду (command)","path":"/docs/guide/cli/generator/generator#command","headings":["Выполнение плагина через команду (command)"],"excerpt":"Выполнение плагина через команду (command) **Приоритет источников плагина:** command — выполнение через указанную команду (наивысший приоритет) remote — удалённый плагин через URL name — локальный плагин из PATH или встр","content":"Выполнение плагина через команду (command) **Приоритет источников плагина:** command — выполнение через указанную команду (наивысший приоритет) remote — удалённый плагин через URL name — локальный плагин из PATH или встроенный плагин path — путь к исполняемому файлу плагина"},{"id":"cli/generator/generator::command::58","title":"Генератор","section":"Выполнение плагина через команду (command)","path":"/docs/guide/cli/generator/generator#command","headings":["Выполнение плагина через команду (command)"],"excerpt":"Выполнение плагина через команду (command) **Параметры (источники и общие опции плагина):**","content":"Выполнение плагина через команду (command) **Параметры (источники и общие опции плагина):**"},{"id":"cli/generator/generator::command::59","title":"Генератор","section":"Выполнение плагина через команду (command)","path":"/docs/guide/cli/generator/generator#command","headings":["Выполнение плагина через команду (command)"],"excerpt":"Выполнение плагина через команду (command) Параметр Тип Обязателен По умолчанию Описание ---------- ----- ------------ -------------- ---------- name string ❌ - Имя / идентификатор плагина (например, go, go-grpc, grpc-ga","content":"Выполнение плагина через команду (command) Параметр Тип Обязателен По умолчанию Описание ---------- ----- ------------ -------------- ---------- name string ❌ - Имя / идентификатор плагина (например, go, go-grpc, grpc-gateway) command []string ❌ - Команда для выполнения плагина (например, [\"go\", \"run\", \"package\"]) remote string ❌ - URL удалённого плагина path string ❌ - Путь к исполняемому файлу плагина out string ✅ - Директория для сгенерированных файлов opts mapstring ❌ {} Специфичные опции плагина; значения-списки передаются как повторяющиеся key=value with_imports bool ❌ false Включать proto из зависимостей"},{"id":"cli/generator/generator::command::60","title":"Генератор","section":"Выполнение плагина через команду (command)","path":"/docs/guide/cli/generator/generator#command","headings":["Выполнение плагина через команду (command)"],"excerpt":"Выполнение плагина через команду (command) **Примечание:** Для каждого плагина должен быть указан ровно один источник (name, command, remote или path). Если opts.outputServices задан как [\"grpc-js\", \"generic-definitions\"","content":"Выполнение плагина через команду (command) **Примечание:** Для каждого плагина должен быть указан ровно один источник (name, command, remote или path). Если opts.outputServices задан как [\"grpc-js\", \"generic-definitions\"], EasyP передаст outputServices=grpc-js,outputServices=generic-definitions."},{"id":"cli/generator/generator::command::61","title":"Генератор","section":"Выполнение плагина через команду (command)","path":"/docs/guide/cli/generator/generator#command","headings":["Выполнение плагина через команду (command)"],"excerpt":"Выполнение плагина через команду (command) **Примеры использования источника command:**","content":"Выполнение плагина через команду (command) **Примеры использования источника command:**"},{"id":"cli/generator/generator::command::62","title":"Генератор","section":"Выполнение плагина через команду (command)","path":"/docs/guide/cli/generator/generator#command","headings":["Выполнение плагина через команду (command)"],"excerpt":"Выполнение плагина через команду (command) ```yaml generate: inputs: - directory: \"proto\"","content":"Выполнение плагина через команду (command) ```yaml generate: inputs: - directory: \"proto\""},{"id":"cli/generator/generator::command::63","title":"Генератор","section":"Выполнение плагина через команду (command)","path":"/docs/guide/cli/generator/generator#command","headings":["Выполнение плагина через команду (command)"],"excerpt":"Выполнение плагина через команду (command) plugins: # 1) gRPC-Gateway через go run (без предварительной установки бинарника) - command: [\"go\", \"run\", \"github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway@v2.","content":"Выполнение плагина через команду (command) plugins: # 1) gRPC-Gateway через go run (без предварительной установки бинарника) - 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::command::64","title":"Генератор","section":"Выполнение плагина через команду (command)","path":"/docs/guide/cli/generator/generator#command","headings":["Выполнение плагина через команду (command)"],"excerpt":"Выполнение плагина через команду (command) 2) protoc-gen-validate через go run - command: [\"go\", \"run\", \"github.com/bufbuild/protoc-gen-validate@v0.10.1\"] out: ./gen/go opts: paths: source_relative lang: go","content":"Выполнение плагина через команду (command) 2) protoc-gen-validate через 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::command::65","title":"Генератор","section":"Выполнение плагина через команду (command)","path":"/docs/guide/cli/generator/generator#command","headings":["Выполнение плагина через команду (command)"],"excerpt":"Выполнение плагина через команду (command) 3) Произвольный кастомный скрипт-обёртка - command: [\"bash\", \"./scripts/custom-protoc-plugin.sh\"] out: ./gen/custom opts: foo: bar ```","content":"Выполнение плагина через команду (command) 3) Произвольный кастомный скрипт-обёртка - command: [\"bash\", \"./scripts/custom-protoc-plugin.sh\"] out: ./gen/custom opts: foo: bar ```"},{"id":"cli/generator/generator::builtin-plugins::66","title":"Генератор","section":"Встроенные плагины (Builtin Plugins)","path":"/docs/guide/cli/generator/generator#builtin-plugins","headings":["Встроенные плагины (Builtin Plugins)"],"excerpt":"Встроенные плагины (Builtin Plugins) EasyP поддерживает встроенные плагины для базовых языков protobuf и gRPC. Эти плагины встроены в бинарник как WASM-модули и не требуют установки внешних зависимостей.","content":"Встроенные плагины (Builtin Plugins) EasyP поддерживает встроенные плагины для базовых языков protobuf и gRPC. Эти плагины встроены в бинарник как WASM-модули и не требуют установки внешних зависимостей."},{"id":"cli/generator/generator::builtin-plugins::67","title":"Генератор","section":"Встроенные плагины (Builtin Plugins)","path":"/docs/guide/cli/generator/generator#builtin-plugins","headings":["Встроенные плагины (Builtin Plugins)"],"excerpt":"Встроенные плагины (Builtin Plugins) **Преимущества встроенных плагинов:** **Портативность**: Один бинарник со всеми необходимыми плагинами **Удобство**: Не требуется установка внешних зависимостей **Стабильность**: Верс","content":"Встроенные плагины (Builtin Plugins) **Преимущества встроенных плагинов:** **Портативность**: Один бинарник со всеми необходимыми плагинами **Удобство**: Не требуется установка внешних зависимостей **Стабильность**: Версии плагинов зафиксированы в бинарнике **Изоляция**: Не зависит от системных установок плагинов"},{"id":"cli/generator/generator::builtin-plugins::68","title":"Генератор","section":"Встроенные плагины (Builtin Plugins)","path":"/docs/guide/cli/generator/generator#builtin-plugins","headings":["Встроенные плагины (Builtin Plugins)"],"excerpt":"Встроенные плагины (Builtin Plugins) **Поддерживаемые встроенные плагины:**","content":"Встроенные плагины (Builtin Plugins) **Поддерживаемые встроенные плагины:**"},{"id":"cli/generator/generator::protobuf::69","title":"Генератор","section":"Protobuf базовые плагины","path":"/docs/guide/cli/generator/generator#protobuf","headings":["Protobuf базовые плагины"],"excerpt":"Protobuf базовые плагины Следующие плагины встроены для генерации базового protobuf кода:","content":"Protobuf базовые плагины Следующие плагины встроены для генерации базового protobuf кода:"},{"id":"cli/generator/generator::protobuf::70","title":"Генератор","section":"Protobuf базовые плагины","path":"/docs/guide/cli/generator/generator#protobuf","headings":["Protobuf базовые плагины"],"excerpt":"Protobuf базовые плагины Имя плагина Описание Соответствующий protoc плагин ------------- ---------- ------------------------------- cpp Генерация C++ кода из proto файлов protoc-gen-cpp csharp Генерация C# кода из proto","content":"Protobuf базовые плагины Имя плагина Описание Соответствующий protoc плагин ------------- ---------- ------------------------------- cpp Генерация C++ кода из proto файлов protoc-gen-cpp csharp Генерация C# кода из proto файлов protoc-gen-csharp java Генерация Java кода из proto файлов protoc-gen-java kotlin Генерация Kotlin кода из proto файлов protoc-gen-kotlin objc Генерация Objective-C кода из proto файлов protoc-gen-objc php Генерация PHP кода из proto файлов protoc-gen-php python Генерация Python кода из proto файлов protoc-gen-python ruby Генерация Ruby кода из proto файлов protoc-gen-ruby"},{"id":"cli/generator/generator::grpc::71","title":"Генератор","section":"gRPC плагины","path":"/docs/guide/cli/generator/generator#grpc","headings":["gRPC плагины"],"excerpt":"gRPC плагины Следующие плагины встроены для генерации gRPC кода:","content":"gRPC плагины Следующие плагины встроены для генерации gRPC кода:"},{"id":"cli/generator/generator::grpc::72","title":"Генератор","section":"gRPC плагины","path":"/docs/guide/cli/generator/generator#grpc","headings":["gRPC плагины"],"excerpt":"gRPC плагины Имя плагина Описание Соответствующий protoc плагин ------------- ---------- ------------------------------- grpc_cpp Генерация gRPC кода для C++ grpc_cpp_plugin grpc_csharp Генерация gRPC кода для C# grpc_cs","content":"gRPC плагины Имя плагина Описание Соответствующий protoc плагин ------------- ---------- ------------------------------- grpc_cpp Генерация gRPC кода для C++ grpc_cpp_plugin grpc_csharp Генерация gRPC кода для C# grpc_csharp_plugin grpc_java Генерация gRPC кода для Java grpc_java_plugin grpc_node Генерация gRPC кода для Node.js grpc_node_plugin grpc_objc Генерация gRPC кода для Objective-C grpc_objective_c_plugin grpc_php Генерация gRPC кода для PHP grpc_php_plugin grpc_python Генерация gRPC кода для Python grpc_python_plugin grpc_ruby Генерация gRPC кода для Ruby grpc_ruby_plugin"},{"id":"cli/generator/generator::grpc::73","title":"Генератор","section":"gRPC плагины","path":"/docs/guide/cli/generator/generator#grpc","headings":["gRPC плагины"],"excerpt":"gRPC плагины **Логика выбора плагина:**","content":"gRPC плагины **Логика выбора плагина:**"},{"id":"cli/generator/generator::grpc::74","title":"Генератор","section":"gRPC плагины","path":"/docs/guide/cli/generator/generator#grpc","headings":["gRPC плагины"],"excerpt":"gRPC плагины EasyP использует следующий приоритет при выборе executor'а для плагина:","content":"gRPC плагины EasyP использует следующий приоритет при выборе executor'а для плагина:"},{"id":"cli/generator/generator::grpc::75","title":"Генератор","section":"gRPC плагины","path":"/docs/guide/cli/generator/generator#grpc","headings":["gRPC плагины"],"excerpt":"gRPC плагины **Удалённый плагин** (если указан url) — всегда имеет наивысший приоритет **Встроенный плагин** (если плагин встроен и не найден в PATH) — используется автоматически **Локальный плагин** (из PATH) — использу","content":"gRPC плагины **Удалённый плагин** (если указан url) — всегда имеет наивысший приоритет **Встроенный плагин** (если плагин встроен и не найден в PATH) — используется автоматически **Локальный плагин** (из PATH) — используется по умолчанию для обратной совместимости"},{"id":"cli/generator/generator::grpc::76","title":"Генератор","section":"gRPC плагины","path":"/docs/guide/cli/generator/generator#grpc","headings":["gRPC плагины"],"excerpt":"gRPC плагины **Пример использования:**","content":"gRPC плагины **Пример использования:**"},{"id":"cli/generator/generator::grpc::77","title":"Генератор","section":"gRPC плагины","path":"/docs/guide/cli/generator/generator#grpc","headings":["gRPC плагины"],"excerpt":"gRPC плагины Встроенные плагины включены в бинарник EasyP:","content":"gRPC плагины Встроенные плагины включены в бинарник EasyP:"},{"id":"cli/generator/generator::grpc::78","title":"Генератор","section":"gRPC плагины","path":"/docs/guide/cli/generator/generator#grpc","headings":["gRPC плагины"],"excerpt":"gRPC плагины ```bash Сборка go build ./cmd/easyp","content":"gRPC плагины ```bash Сборка go build ./cmd/easyp"},{"id":"cli/generator/generator::grpc::79","title":"Генератор","section":"gRPC плагины","path":"/docs/guide/cli/generator/generator#grpc","headings":["gRPC плагины"],"excerpt":"gRPC плагины Установка go install github.com/easyp-tech/easyp/cmd/easyp@latest ```","content":"gRPC плагины Установка go install github.com/easyp-tech/easyp/cmd/easyp@latest ```"},{"id":"cli/generator/generator::grpc::80","title":"Генератор","section":"gRPC плагины","path":"/docs/guide/cli/generator/generator#grpc","headings":["gRPC плагины"],"excerpt":"gRPC плагины **Обратная совместимость:**","content":"gRPC плагины **Обратная совместимость:**"},{"id":"cli/generator/generator::grpc::81","title":"Генератор","section":"gRPC плагины","path":"/docs/guide/cli/generator/generator#grpc","headings":["gRPC плагины"],"excerpt":"gRPC плагины Встроенные плагины полностью совместимы с существующими конфигурациями. Если плагин найден в PATH, он будет использован вместо встроенного. Это гарантирует, что:","content":"gRPC плагины Встроенные плагины полностью совместимы с существующими конфигурациями. Если плагин найден в PATH, он будет использован вместо встроенного. Это гарантирует, что:"},{"id":"cli/generator/generator::grpc::82","title":"Генератор","section":"gRPC плагины","path":"/docs/guide/cli/generator/generator#grpc","headings":["gRPC плагины"],"excerpt":"gRPC плагины Существующие конфигурации продолжают работать без изменений Можно переопределить встроенный плагин, установив его в системе Приоритет отдаётся локальным установкам для гибкости","content":"gRPC плагины Существующие конфигурации продолжают работать без изменений Можно переопределить встроенный плагин, установив его в системе Приоритет отдаётся локальным установкам для гибкости"},{"id":"cli/generator/generator::top::83","title":"Генератор","section":"Справочник опций плагинов","path":"/docs/guide/cli/generator/generator","headings":["Справочник опций плагинов"],"excerpt":"Справочник опций плагинов Ниже перечислены наиболее часто используемые плагины и их настройки. Каждый плагин имеет параметры, влияющие на результат генерации — понимание этих опций важно для получения нужного вывода.","content":"Справочник опций плагинов Ниже перечислены наиболее часто используемые плагины и их настройки. Каждый плагин имеет параметры, влияющие на результат генерации — понимание этих опций важно для получения нужного вывода."},{"id":"cli/generator/generator::go-plugins::84","title":"Генератор","section":"Go Plugins","path":"/docs/guide/cli/generator/generator#go-plugins","headings":["Go Plugins"],"excerpt":"Go Plugins Плагины для Go — самые зрелые и распространённые. Опция paths управляет тем, как формируются пути импортов; остальные опции дают тонкую настройку вывода.","content":"Go Plugins Плагины для Go — самые зрелые и распространённые. Опция paths управляет тем, как формируются пути импортов; остальные опции дают тонкую настройку вывода."},{"id":"cli/generator/generator::grpc-gateway-plugins::85","title":"Генератор","section":"gRPC-Gateway Plugins","path":"/docs/guide/cli/generator/generator#grpc-gateway-plugins","headings":["gRPC-Gateway Plugins"],"excerpt":"gRPC-Gateway Plugins Позволяют экспонировать gRPC сервисы как REST API и генерировать OpenAPI. Критично для HTTP/JSON поверх gRPC.","content":"gRPC-Gateway Plugins Позволяют экспонировать gRPC сервисы как REST API и генерировать OpenAPI. Критично для HTTP/JSON поверх gRPC."},{"id":"cli/generator/generator::validation-plugins::86","title":"Генератор","section":"Validation Plugins","path":"/docs/guide/cli/generator/generator#validation-plugins","headings":["Validation Plugins"],"excerpt":"Validation Plugins Генерируют код валидации на основе правил в proto, устраняя ручную проверку.","content":"Validation Plugins Генерируют код валидации на основе правил в proto, устраняя ручную проверку."},{"id":"cli/generator/generator::typescriptjavascript-plugins::87","title":"Генератор","section":"TypeScript/JavaScript Plugins","path":"/docs/guide/cli/generator/generator#typescriptjavascript-plugins","headings":["TypeScript/JavaScript Plugins"],"excerpt":"TypeScript/JavaScript Plugins TypeScript плагины нужны фронтенду: типобезопасные интерфейсы и клиенты.","content":"TypeScript/JavaScript Plugins TypeScript плагины нужны фронтенду: типобезопасные интерфейсы и клиенты."},{"id":"cli/generator/generator::managed-mode::88","title":"Генератор","section":"Managed Mode","path":"/docs/guide/cli/generator/generator#managed-mode","headings":["Managed Mode"],"excerpt":"Managed Mode Managed mode автоматически устанавливает file и field опции в protobuf дескрипторах во время генерации кода без изменения исходных .proto файлов. Эта функция совместима с managed mode в buf и обеспечивает ед","content":"Managed Mode Managed mode автоматически устанавливает file и field опции в protobuf дескрипторах во время генерации кода без изменения исходных .proto файлов. Эта функция совместима с managed mode в buf и обеспечивает единообразный способ управления языково-специфичными опциями в вашей кодовой базе."},{"id":"cli/generator/generator::managed-mode::89","title":"Генератор","section":"Managed Mode","path":"/docs/guide/cli/generator/generator#managed-mode","headings":["Managed Mode"],"excerpt":"Managed Mode **Ключевые преимущества:** **Без изменений proto файлов**: Опции применяются во время генерации, proto файлы остаются чистыми **Согласованные значения по умолчанию**: Автоматическое применение языковых согла","content":"Managed Mode **Ключевые преимущества:** **Без изменений proto файлов**: Опции применяются во время генерации, proto файлы остаются чистыми **Согласованные значения по умолчанию**: Автоматическое применение языковых соглашений об именовании **Централизованная конфигурация**: Управление всеми опциями в одном месте (easyp.yaml) **Правила для модулей**: Применение разных опций к разным модулям или путям **Совместимость с buf**: Работает так же, как managed mode в buf"},{"id":"cli/generator/generator::top::90","title":"Генератор","section":"Как это работает","path":"/docs/guide/cli/generator/generator","headings":["Как это работает"],"excerpt":"Как это работает Когда managed mode включён, EasyP автоматически применяет file и field опции к protobuf дескрипторам перед генерацией кода. Это происходит в памяти, поэтому исходные .proto файлы остаются неизменными.","content":"Как это работает Когда managed mode включён, EasyP автоматически применяет file и field опции к protobuf дескрипторам перед генерацией кода. Это происходит в памяти, поэтому исходные .proto файлы остаются неизменными."},{"id":"cli/generator/generator::top::91","title":"Генератор","section":"Как это работает","path":"/docs/guide/cli/generator/generator","headings":["Как это работает"],"excerpt":"Как это работает **Значения по умолчанию** применяются для определённых опций на основе языковых соглашений: Java: java_package_prefix по умолчанию \"com\", java_multiple_files по умолчанию true C#: csharp_namespace по умо","content":"Как это работает **Значения по умолчанию** применяются для определённых опций на основе языковых соглашений: Java: java_package_prefix по умолчанию \"com\", java_multiple_files по умолчанию true C#: csharp_namespace по умолчанию PascalCase имени пакета Ruby: ruby_package по умолчанию PascalCase с разделителем :: PHP: php_namespace по умолчанию PascalCase с разделителем \\ Objective-C: objc_class_prefix по умолчанию первые буквы частей пакета C++: cc_enable_arenas по умолчанию true"},{"id":"cli/generator/generator::top::92","title":"Генератор","section":"Как это работает","path":"/docs/guide/cli/generator/generator","headings":["Как это работает"],"excerpt":"Как это работает **Overrides** позволяют установить конкретные значения для опций с поддержкой фильтрации по модулю, пути или полю. Если не указаны module и path, override применяется ко всем файлам в запросе генерации, ","content":"Как это работает **Overrides** позволяют установить конкретные значения для опций с поддержкой фильтрации по модулю, пути или полю. Если не указаны module и path, override применяется ко всем файлам в запросе генерации, включая зависимости и git_repo inputs."},{"id":"cli/generator/generator::top::93","title":"Генератор","section":"Как это работает","path":"/docs/guide/cli/generator/generator","headings":["Как это работает"],"excerpt":"Как это работает **Disables** позволяют предотвратить изменение managed mode определённых опций или файлов. Это рекомендуемый способ исключить внешние зависимости, у которых свои опции уже заданы.","content":"Как это работает **Disables** позволяют предотвратить изменение managed mode определённых опций или файлов. Это рекомендуемый способ исключить внешние зависимости, у которых свои опции уже заданы."},{"id":"cli/generator/generator::file-options::94","title":"Генератор","section":"Поддерживаемые File Options","path":"/docs/guide/cli/generator/generator#file-options","headings":["Поддерживаемые File Options"],"excerpt":"Поддерживаемые File Options Опция Описание Есть значение по умолчанию? ------- ---------- ---------------------------- go_package Go import path ❌ go_package_prefix Префикс для Go import paths ❌ java_package Имя Java пак","content":"Поддерживаемые File Options Опция Описание Есть значение по умолчанию? ------- ---------- ---------------------------- go_package Go import path ❌ go_package_prefix Префикс для Go import paths ❌ java_package Имя Java пакета ❌ java_package_prefix Префикс для Java пакетов ✅ (\"com\") java_package_suffix Суффикс для Java пакетов ❌ java_multiple_files Генерировать несколько Java файлов ✅ (true) java_outer_classname Имя внешнего класса ✅ (PascalCase + \"Proto\") java_string_check_utf8 UTF-8 валидация ❌ csharp_namespace C# namespace ✅ (PascalCase) csharp_namespace_prefix Префикс для C# namespaces ❌ ruby_package Имя Ruby модуля ✅ (PascalCase с ::) ruby_package_suffix Суффикс для Ruby пакетов ❌ php_namespace PHP namespace ✅ (PascalCase с \\) php_metadata_namespace PHP metadata namespace ❌ php_metadata_namespace_suffix Суффикс для PHP metadata ❌ objc_class_prefix Objective-C префикс класса ✅ (Первые буквы) swift_prefix Swift префикс ❌ optimize_for Оптимизация генерации кода ❌ cc_enable_arenas C++ arena аллокация ✅ (true)"},{"id":"cli/generator/generator::field-options::95","title":"Генератор","section":"Поддерживаемые Field Options","path":"/docs/guide/cli/generator/generator#field-options","headings":["Поддерживаемые Field Options"],"excerpt":"Поддерживаемые Field Options Опция Описание Применяется к ------- ---------- --------------- jstype JavaScript тип для 64-битных целых чисел int64, uint64, sint64, fixed64, sfixed64","content":"Поддерживаемые Field Options Опция Описание Применяется к ------- ---------- --------------- jstype JavaScript тип для 64-битных целых чисел int64, uint64, sint64, fixed64, sfixed64"},{"id":"cli/generator/generator::top::96","title":"Генератор","section":"Базовая настройка со значениями по умолчанию","path":"/docs/guide/cli/generator/generator","headings":["Базовая настройка со значениями по умолчанию"],"excerpt":"Базовая настройка со значениями по умолчанию Включите managed mode для получения автоматических значений по умолчанию для всех поддерживаемых языков:","content":"Базовая настройка со значениями по умолчанию Включите managed mode для получения автоматических значений по умолчанию для всех поддерживаемых языков:"},{"id":"cli/generator/generator::top::97","title":"Генератор","section":"Базовая настройка со значениями по умолчанию","path":"/docs/guide/cli/generator/generator","headings":["Базовая настройка со значениями по умолчанию"],"excerpt":"Базовая настройка со значениями по умолчанию","content":"Базовая настройка со значениями по умолчанию"},{"id":"cli/generator/generator::top::98","title":"Генератор","section":"Базовая настройка со значениями по умолчанию","path":"/docs/guide/cli/generator/generator","headings":["Базовая настройка со значениями по умолчанию"],"excerpt":"Базовая настройка со значениями по умолчанию Это автоматически установит: java_package в com. для всех файлов java_multiple_files в true csharp_namespace в PascalCase имени пакета ruby_package в PascalCase с разделителем","content":"Базовая настройка со значениями по умолчанию Это автоматически установит: java_package в com. для всех файлов java_multiple_files в true csharp_namespace в PascalCase имени пакета ruby_package в PascalCase с разделителем :: И многое другое..."},{"id":"cli/generator/generator::go::99","title":"Генератор","section":"Кастомный префикс Go пакета","path":"/docs/guide/cli/generator/generator#go","headings":["Кастомный префикс Go пакета"],"excerpt":"Кастомный префикс Go пакета Переопределите префикс Go пакета для вашего проекта:","content":"Кастомный префикс Go пакета Переопределите префикс Go пакета для вашего проекта:"},{"id":"cli/generator/generator::go::100","title":"Генератор","section":"Кастомный префикс Go пакета","path":"/docs/guide/cli/generator/generator#go","headings":["Кастомный префикс Go пакета"],"excerpt":"Кастомный префикс Go пакета Это установит go_package в github.com/mycompany/myproject/gen/go/ для всех файлов.","content":"Кастомный префикс Go пакета Это установит go_package в github.com/mycompany/myproject/gen/go/ для всех файлов."},{"id":"cli/generator/generator::go::101","title":"Генератор","section":"Динамические пути Go пакетов с маркерами","path":"/docs/guide/cli/generator/generator#go","headings":["Динамические пути Go пакетов с маркерами"],"excerpt":"Динамические пути Go пакетов с маркерами Для более сложной генерации путей можно использовать маркеры в значениях go_package_prefix или go_package:","content":"Динамические пути Go пакетов с маркерами Для более сложной генерации путей можно использовать маркеры в значениях go_package_prefix или go_package:"},{"id":"cli/generator/generator::go::102","title":"Генератор","section":"Динамические пути Go пакетов с маркерами","path":"/docs/guide/cli/generator/generator#go","headings":["Динамические пути Go пакетов с маркерами"],"excerpt":"Динамические пути Go пакетов с маркерами","content":"Динамические пути Go пакетов с маркерами"},{"id":"cli/generator/generator::go::103","title":"Генератор","section":"Динамические пути Go пакетов с маркерами","path":"/docs/guide/cli/generator/generator#go","headings":["Динамические пути Go пакетов с маркерами"],"excerpt":"Динамические пути Go пакетов с маркерами **Доступные маркеры:** {{file_path}} - Полный путь файла без расширения .proto - Пример: internal/cms/as.proto → internal/cms/as {{file_dir}} - Только путь директории, без имени ф","content":"Динамические пути Go пакетов с маркерами **Доступные маркеры:** {{file_path}} - Полный путь файла без расширения .proto - Пример: internal/cms/as.proto → internal/cms/as {{file_dir}} - Только путь директории, без имени файла - Пример: internal/cms/as.proto → internal/cms {{file_dir_without:prefix/}} - Путь директории с удалением префикса и базового имени файла без суффиксов _service/_grpc - Пример: {{file_dir_without:internal/}} для internal/cms/as_service.proto → cms/as {{file_path_without:prefix/}} - Полный путь файла с удалением префикса - Пример: {{file_path_without:internal/}} для internal/cms/as.proto → cms/as"},{"id":"cli/generator/generator::top::104","title":"Генератор","section":"Переопределения для конкретных модулей","path":"/docs/guide/cli/generator/generator","headings":["Переопределения для конкретных модулей"],"excerpt":"Переопределения для конкретных модулей Примените разные опции к разным модулям:","content":"Переопределения для конкретных модулей Примените разные опции к разным модулям:"},{"id":"cli/generator/generator::top::105","title":"Генератор","section":"Переопределения для конкретных модулей","path":"/docs/guide/cli/generator/generator","headings":["Переопределения для конкретных модулей"],"excerpt":"Переопределения для конкретных модулей","content":"Переопределения для конкретных модулей"},{"id":"cli/generator/generator::top::106","title":"Генератор","section":"Переопределения для конкретных модулей","path":"/docs/guide/cli/generator/generator","headings":["Переопределения для конкретных модулей"],"excerpt":"Переопределения для конкретных модулей module должен точно совпадать с источником модуля в EasyP: это значение из deps или git_repo.url до @version (например, github.com/mycompany/internal-protos или https://github.com/m","content":"Переопределения для конкретных модулей module должен точно совпадать с источником модуля в EasyP: это значение из deps или git_repo.url до @version (например, github.com/mycompany/internal-protos или https://github.com/mycompany/internal-protos). Это не Go module path из go.mod."},{"id":"cli/generator/generator::top::107","title":"Генератор","section":"Отключение для внешних зависимостей","path":"/docs/guide/cli/generator/generator","headings":["Отключение для внешних зависимостей"],"excerpt":"Отключение для внешних зависимостей Отключите managed mode для внешних зависимостей, у которых уже установлены опции:","content":"Отключение для внешних зависимостей Отключите managed mode для внешних зависимостей, у которых уже установлены опции:"},{"id":"cli/generator/generator::top::108","title":"Генератор","section":"Отключение для внешних зависимостей","path":"/docs/guide/cli/generator/generator","headings":["Отключение для внешних зависимостей"],"excerpt":"Отключение для внешних зависимостей","content":"Отключение для внешних зависимостей"},{"id":"cli/generator/generator::javascript::109","title":"Генератор","section":"Типобезопасность JavaScript","path":"/docs/guide/cli/generator/generator#javascript","headings":["Типобезопасность JavaScript"],"excerpt":"Типобезопасность JavaScript Установите jstype в JS_STRING для всех 64-битных целочисленных полей, чтобы предотвратить потерю точности в JavaScript:","content":"Типобезопасность JavaScript Установите jstype в JS_STRING для всех 64-битных целочисленных полей, чтобы предотвратить потерю точности в JavaScript:"},{"id":"cli/generator/generator::top::110","title":"Генератор","section":"Совпадение путей","path":"/docs/guide/cli/generator/generator","headings":["Совпадение путей"],"excerpt":"Совпадение путей Совпадение путей в managed mode использует префиксное совпадение (как в buf):","content":"Совпадение путей Совпадение путей в managed mode использует префиксное совпадение (как в buf):"},{"id":"cli/generator/generator::top::111","title":"Генератор","section":"Совпадение путей","path":"/docs/guide/cli/generator/generator","headings":["Совпадение путей"],"excerpt":"Совпадение путей **Путь директории** (заканчивается на /): Совпадает со всеми файлами в этой директории и поддиректориях - Пример: path: \"internal/cms/\" совпадает с internal/cms/as.proto, internal/cms/node.proto, interna","content":"Совпадение путей **Путь директории** (заканчивается на /): Совпадает со всеми файлами в этой директории и поддиректориях - Пример: path: \"internal/cms/\" совпадает с internal/cms/as.proto, internal/cms/node.proto, internal/cms/v1/service.proto **Точный путь файла** (заканчивается на .proto): Совпадает только с этим конкретным файлом - Пример: path: \"internal/cms/as.proto\" совпадает только с internal/cms/as.proto **Префиксный путь** (без завершающего / или .proto): Использует префиксное совпадение (не директориально-осознанное) - Пример: path: \"internal/cms\" совпадает с internal/cms/as.proto, но также с internal/cmsv2/file.proto - **Совет**: Используйте префиксные пути для группировки нескольких файлов с одинаковым значением. Например, path: \"internal/cms/bmi\" совпадает и с internal/cms/bmi.proto, и с internal/cms/bmi_service.proto, что позволяет установить одно и то же значение go_package для обоих файлов одним правилом."},{"id":"cli/generator/generator::top::112","title":"Генератор","section":"Приоритет правил","path":"/docs/guide/cli/generator/generator","headings":["Приоритет правил"],"excerpt":"Приоритет правил Когда несколько правил соответствуют одному файлу или полю, применяется следующий приоритет:","content":"Приоритет правил Когда несколько правил соответствуют одному файлу или полю, применяется следующий приоритет:"},{"id":"cli/generator/generator::top::113","title":"Генератор","section":"Приоритет правил","path":"/docs/guide/cli/generator/generator","headings":["Приоритет правил"],"excerpt":"Приоритет правил **Disable правила** имеют приоритет — если опция отключена, она не будет применена **Override правила** применяются по порядку — последнее совпадающее правило побеждает **Значения по умолчанию** применяю","content":"Приоритет правил **Disable правила** имеют приоритет — если опция отключена, она не будет применена **Override правила** применяются по порядку — последнее совпадающее правило побеждает **Значения по умолчанию** применяются только если нет совпадающего override и опция не отключена"},{"id":"cli/generator/generator::buf::114","title":"Генератор","section":"Совместимость с buf","path":"/docs/guide/cli/generator/generator#buf","headings":["Совместимость с buf"],"excerpt":"Совместимость с buf Managed mode в EasyP совместим с managed mode в buf. Тот же формат конфигурации и поведение применяются, что упрощает миграцию между инструментами или использование обоих в одном workflow.","content":"Совместимость с buf Managed mode в EasyP совместим с managed mode в buf. Тот же формат конфигурации и поведение применяются, что упрощает миграцию между инструментами или использование обоих в одном workflow."},{"id":"cli/generator/generator::descriptor-set::115","title":"Генератор","section":"Генерация Descriptor Set","path":"/docs/guide/cli/generator/generator#descriptor-set","headings":["Генерация Descriptor Set"],"excerpt":"Генерация Descriptor Set **https://protobuf.dev/programming-guides/techniques/#self-description**","content":"Генерация Descriptor Set **https://protobuf.dev/programming-guides/techniques/#self-description**"},{"id":"cli/generator/generator::descriptor-set::116","title":"Генератор","section":"Генерация Descriptor Set","path":"/docs/guide/cli/generator/generator#descriptor-set","headings":["Генерация Descriptor Set"],"excerpt":"Генерация Descriptor Set EasyP поддерживает генерацию бинарных FileDescriptorSet файлов с помощью флага --descriptor_set_out. Это позволяет создавать самоописывающиеся protobuf сообщения, которые включают информацию о сх","content":"Генерация Descriptor Set EasyP поддерживает генерацию бинарных FileDescriptorSet файлов с помощью флага --descriptor_set_out. Это позволяет создавать самоописывающиеся protobuf сообщения, которые включают информацию о схеме вместе с данными."},{"id":"cli/generator/generator::descriptor-set::117","title":"Генератор","section":"Генерация Descriptor Set","path":"/docs/guide/cli/generator/generator#descriptor-set","headings":["Генерация Descriptor Set"],"excerpt":"Генерация Descriptor Set **Флаги CLI:**","content":"Генерация Descriptor Set **Флаги CLI:**"},{"id":"cli/generator/generator::descriptor-set::118","title":"Генератор","section":"Генерация Descriptor Set","path":"/docs/guide/cli/generator/generator#descriptor-set","headings":["Генерация Descriptor Set"],"excerpt":"Генерация Descriptor Set --descriptor_set_out - Путь для вывода бинарного FileDescriptorSet --include_imports - Включить все транзитивные зависимости в FileDescriptorSet","content":"Генерация Descriptor Set --descriptor_set_out - Путь для вывода бинарного FileDescriptorSet --include_imports - Включить все транзитивные зависимости в FileDescriptorSet"},{"id":"cli/generator/generator::descriptor-set::119","title":"Генератор","section":"Генерация Descriptor Set","path":"/docs/guide/cli/generator/generator#descriptor-set","headings":["Генерация Descriptor Set"],"excerpt":"Генерация Descriptor Set **Пример:**","content":"Генерация Descriptor Set **Пример:**"},{"id":"cli/generator/generator::descriptor-set::120","title":"Генератор","section":"Генерация Descriptor Set","path":"/docs/guide/cli/generator/generator#descriptor-set","headings":["Генерация Descriptor Set"],"excerpt":"Генерация Descriptor Set ```bash Генерация descriptor set только с целевыми файлами easyp generate --descriptor_set_out=./schema.pb","content":"Генерация Descriptor Set ```bash Генерация descriptor set только с целевыми файлами easyp generate --descriptor_set_out=./schema.pb"},{"id":"cli/generator/generator::descriptor-set::121","title":"Генератор","section":"Генерация Descriptor Set","path":"/docs/guide/cli/generator/generator#descriptor-set","headings":["Генерация Descriptor Set"],"excerpt":"Генерация Descriptor Set Генерация descriptor set со всеми зависимостями easyp generate --descriptor_set_out=./schema.pb --include_imports ```","content":"Генерация Descriptor Set Генерация descriptor set со всеми зависимостями easyp generate --descriptor_set_out=./schema.pb --include_imports ```"},{"id":"cli/generator/generator::descriptor-set::122","title":"Генератор","section":"Генерация Descriptor Set","path":"/docs/guide/cli/generator/generator#descriptor-set","headings":["Генерация Descriptor Set"],"excerpt":"Генерация Descriptor Set Самоописывающиеся сообщения полезны для динамического парсинга сообщений, валидации схемы во время выполнения, реестров схем и создания универсальных gRPC клиентов. Для получения дополнительной и","content":"Генерация Descriptor Set Самоописывающиеся сообщения полезны для динамического парсинга сообщений, валидации схемы во время выполнения, реестров схем и создания универсальных gRPC клиентов. Для получения дополнительной информации см. документацию Protocol Buffers о самоописании."},{"id":"cli/generator/generator::top::123","title":"Генератор","section":"Интеграция с менеджером пакетов","path":"/docs/guide/cli/generator/generator","headings":["Интеграция с менеджером пакетов"],"excerpt":"Интеграция с менеджером пакетов Одной из самых мощных возможностей EasyP является бесшовная интеграция генератора кода с менеджером пакетов. Это устраняет проблему ручного управления proto‑зависимостями и гарантирует, чт","content":"Интеграция с менеджером пакетов Одной из самых мощных возможностей EasyP является бесшовная интеграция генератора кода с менеджером пакетов. Это устраняет проблему ручного управления proto‑зависимостями и гарантирует, что при генерации используются корректные (зафиксированные) версии импортируемых файлов."},{"id":"cli/generator/generator::top::124","title":"Генератор","section":"Интеграция с менеджером пакетов","path":"/docs/guide/cli/generator/generator","headings":["Интеграция с менеджером пакетов"],"excerpt":"Интеграция с менеджером пакетов **Ключевые преимущества:** **Автоматическое разрешение зависимостей**: не нужно вручную прописывать пути импортов **Согласованность версий**: фиксация в easyp.lock гарантирует воспроизводи","content":"Интеграция с менеджером пакетов **Ключевые преимущества:** **Автоматическое разрешение зависимостей**: не нужно вручную прописывать пути импортов **Согласованность версий**: фиксация в easyp.lock гарантирует воспроизводимость **Транзитивные зависимости**: вложенные цепочки подтягиваются автоматически **Производительность**: локальный кеш — скачивание один раз и повторное использование"},{"id":"cli/generator/generator::top::125","title":"Генератор","section":"Автоматическое разрешение зависимостей","path":"/docs/guide/cli/generator/generator","headings":["Автоматическое разрешение зависимостей"],"excerpt":"Автоматическое разрешение зависимостей Когда вы указываете зависимости в секции deps, генератор автоматически добавляет их в путь импортов. Ваши proto‑файлы могут делать стандартные import из этих зависимостей без дополн","content":"Автоматическое разрешение зависимостей Когда вы указываете зависимости в секции deps, генератор автоматически добавляет их в путь импортов. Ваши proto‑файлы могут делать стандартные import из этих зависимостей без дополнительной настройки."},{"id":"cli/generator/generator::top::126","title":"Генератор","section":"Автоматическое разрешение зависимостей","path":"/docs/guide/cli/generator/generator","headings":["Автоматическое разрешение зависимостей"],"excerpt":"Автоматическое разрешение зависимостей **Как это работает:** EasyP скачивает и кеширует зависимости из deps Во время генерации кешированные файлы автоматически добавляются в import‑path protoc Ваши proto‑файлы используют","content":"Автоматическое разрешение зависимостей **Как это работает:** EasyP скачивает и кеширует зависимости из deps Во время генерации кешированные файлы автоматически добавляются в import‑path protoc Ваши proto‑файлы используют обычные import строки для обращения к зависимостям При with_imports: true в вывод попадают и локальные файлы, и файлы зависимостей"},{"id":"cli/generator/generator::top::127","title":"Генератор","section":"Автоматическое разрешение зависимостей","path":"/docs/guide/cli/generator/generator","headings":["Автоматическое разрешение зависимостей"],"excerpt":"Автоматическое разрешение зависимостей Ниже простой пример — зависимости указываются один раз в deps, далее они доступны при генерации автоматически:","content":"Автоматическое разрешение зависимостей Ниже простой пример — зависимости указываются один раз в deps, далее они доступны при генерации автоматически:"},{"id":"cli/generator/generator::top::128","title":"Генератор","section":"Автоматическое разрешение зависимостей","path":"/docs/guide/cli/generator/generator","headings":["Автоматическое разрешение зависимостей"],"excerpt":"Автоматическое разрешение зависимостей ```yaml deps: - github.com/googleapis/googleapis@common-protos-1_3_1 - github.com/grpc-ecosystem/grpc-gateway@v2.19.1","content":"Автоматическое разрешение зависимостей ```yaml deps: - github.com/googleapis/googleapis@common-protos-1_3_1 - github.com/grpc-ecosystem/grpc-gateway@v2.19.1"},{"id":"cli/generator/generator::top::129","title":"Генератор","section":"Автоматическое разрешение зависимостей","path":"/docs/guide/cli/generator/generator","headings":["Автоматическое разрешение зависимостей"],"excerpt":"Автоматическое разрешение зависимостей generate: inputs: - directory: \"proto\" plugins: - name: go out: ./gen/go opts: paths: source_relative with_imports: true # This automatically includes googleapis and grpc-gateway pr","content":"Автоматическое разрешение зависимостей 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::top::130","title":"Генератор","section":"Примеры использования зависимостей","path":"/docs/guide/cli/generator/generator","headings":["Примеры использования зависимостей"],"excerpt":"Примеры использования зависимостей Ниже показаны распространённые способы интеграции внешних proto‑зависимостей в процесс генерации.","content":"Примеры использования зависимостей Ниже показаны распространённые способы интеграции внешних proto‑зависимостей в процесс генерации."},{"id":"cli/generator/generator::google-apis::131","title":"Генератор","section":"Использование Google APIs","path":"/docs/guide/cli/generator/generator#google-apis","headings":["Использование Google APIs"],"excerpt":"Использование Google APIs Google APIs — одна из самых популярных коллекций зависимостей: стандартные типы, аннотации для REST, проверки и общие структуры данных.","content":"Использование Google APIs Google APIs — одна из самых популярных коллекций зависимостей: стандартные типы, аннотации для REST, проверки и общие структуры данных."},{"id":"cli/generator/generator::google-apis::132","title":"Генератор","section":"Использование Google APIs","path":"/docs/guide/cli/generator/generator#google-apis","headings":["Использование Google APIs"],"excerpt":"Использование Google APIs **Когда использовать Google APIs:** Построение REST поверх gRPC (gRPC-Gateway) Нужны стандартные типы (Timestamp, Duration, Any) Требуются аннотации поведения полей (field behavior) Интеграция с","content":"Использование Google APIs **Когда использовать Google APIs:** Построение REST поверх gRPC (gRPC-Gateway) Нужны стандартные типы (Timestamp, Duration, Any) Требуются аннотации поведения полей (field behavior) Интеграция с сервисами Google Cloud"},{"id":"cli/generator/generator::google-apis::133","title":"Генератор","section":"Использование Google APIs","path":"/docs/guide/cli/generator/generator#google-apis","headings":["Использование Google APIs"],"excerpt":"Использование Google APIs Минимальная конфигурация для подключения Google APIs:","content":"Использование Google APIs Минимальная конфигурация для подключения Google APIs:"},{"id":"cli/generator/generator::google-apis::134","title":"Генератор","section":"Использование Google APIs","path":"/docs/guide/cli/generator/generator#google-apis","headings":["Использование Google APIs"],"excerpt":"Использование Google APIs ```yaml deps: - github.com/googleapis/googleapis@common-protos-1_3_1","content":"Использование Google APIs ```yaml deps: - github.com/googleapis/googleapis@common-protos-1_3_1"},{"id":"cli/generator/generator::google-apis::135","title":"Генератор","section":"Использование Google APIs","path":"/docs/guide/cli/generator/generator#google-apis","headings":["Использование Google APIs"],"excerpt":"Использование Google APIs generate: inputs: - directory: \"api/proto\" plugins: - name: go out: ./gen/go opts: paths: source_relative with_imports: true ```","content":"Использование Google APIs generate: inputs: - directory: \"api/proto\" plugins: - name: go out: ./gen/go opts: paths: source_relative with_imports: true ```"},{"id":"cli/generator/generator::google-apis::136","title":"Генератор","section":"Использование Google APIs","path":"/docs/guide/cli/generator/generator#google-apis","headings":["Использование Google APIs"],"excerpt":"Использование Google APIs **Важно:** Всегда фиксируйте версию (например common-protos-1_3_1) — не используйте latest в продакшене.","content":"Использование Google APIs **Важно:** Всегда фиксируйте версию (например common-protos-1_3_1) — не используйте latest в продакшене."},{"id":"cli/generator/generator::google-apis::137","title":"Генератор","section":"Использование Google APIs","path":"/docs/guide/cli/generator/generator#google-apis","headings":["Использование Google APIs"],"excerpt":"Использование Google APIs После настройки ваши proto могут импортировать определения Google API. Ниже пример сервиса с HTTP аннотацией:","content":"Использование Google APIs После настройки ваши proto могут импортировать определения Google API. Ниже пример сервиса с HTTP аннотацией:"},{"id":"cli/generator/generator::google-apis::138","title":"Генератор","section":"Использование Google APIs","path":"/docs/guide/cli/generator/generator#google-apis","headings":["Использование Google APIs"],"excerpt":"Использование Google APIs ```proto // api/proto/service.proto syntax = \"proto3\";","content":"Использование Google APIs ```proto // api/proto/service.proto syntax = \"proto3\";"},{"id":"cli/generator/generator::google-apis::139","title":"Генератор","section":"Использование Google APIs","path":"/docs/guide/cli/generator/generator#google-apis","headings":["Использование Google APIs"],"excerpt":"Использование Google APIs import \"google/api/annotations.proto\"; import \"google/protobuf/timestamp.proto\";","content":"Использование Google APIs import \"google/api/annotations.proto\"; import \"google/protobuf/timestamp.proto\";"},{"id":"cli/generator/generator::google-apis::140","title":"Генератор","section":"Использование Google APIs","path":"/docs/guide/cli/generator/generator#google-apis","headings":["Использование Google APIs"],"excerpt":"Использование Google APIs service MyService { rpc GetData(GetDataRequest) returns (GetDataResponse) { option (google.api.http) = { get: \"/v1/data\" }; } } ```","content":"Использование Google APIs service MyService { rpc GetData(GetDataRequest) returns (GetDataResponse) { option (google.api.http) = { get: \"/v1/data\" }; } } ```"},{"id":"cli/generator/generator::top::141","title":"Генератор","section":"Использование правил валидации","path":"/docs/guide/cli/generator/generator","headings":["Использование правил валидации"],"excerpt":"Использование правил валидации protoc-gen-validate даёт мощную проверку полей прямо в определениях proto, устраняя необходимость писать отдельную логику валидации в приложении.","content":"Использование правил валидации protoc-gen-validate даёт мощную проверку полей прямо в определениях proto, устраняя необходимость писать отдельную логику валидации в приложении."},{"id":"cli/generator/generator::top::142","title":"Генератор","section":"Использование правил валидации","path":"/docs/guide/cli/generator/generator","headings":["Использование правил валидации"],"excerpt":"Использование правил валидации **Когда применять валидацию:** Проверка входных данных API Ограничения моделей БД Проверка конфигурационных файлов Любая ситуация, где критична целостность данных","content":"Использование правил валидации **Когда применять валидацию:** Проверка входных данных API Ограничения моделей БД Проверка конфигурационных файлов Любая ситуация, где критична целостность данных"},{"id":"cli/generator/generator::top::143","title":"Генератор","section":"Использование правил валидации","path":"/docs/guide/cli/generator/generator","headings":["Использование правил валидации"],"excerpt":"Использование правил валидации **Преимущества:** Правила валидации — часть proto (единый источник истины) Генерация создаёт функции проверки автоматически Единообразие проверок между языками Производительнее чем проверка","content":"Использование правил валидации **Преимущества:** Правила валидации — часть proto (единый источник истины) Генерация создаёт функции проверки автоматически Единообразие проверок между языками Производительнее чем проверка через runtime reflection"},{"id":"cli/generator/generator::top::144","title":"Генератор","section":"Использование правил валидации","path":"/docs/guide/cli/generator/generator","headings":["Использование правил валидации"],"excerpt":"Использование правил валидации ```yaml deps: - github.com/bufbuild/protoc-gen-validate@v0.10.1","content":"Использование правил валидации ```yaml deps: - github.com/bufbuild/protoc-gen-validate@v0.10.1"},{"id":"cli/generator/generator::top::145","title":"Генератор","section":"Использование правил валидации","path":"/docs/guide/cli/generator/generator","headings":["Использование правил валидации"],"excerpt":"Использование правил валидации 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":"Использование правил валидации 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::top::146","title":"Генератор","section":"Использование правил валидации","path":"/docs/guide/cli/generator/generator","headings":["Использование правил валидации"],"excerpt":"Использование правил валидации **Примечание:** Нужны одновременно зависимость (для импортов proto) и плагин (для генерации кода), чтобы получить полноценную поддержку валидации.","content":"Использование правил валидации **Примечание:** Нужны одновременно зависимость (для импортов proto) и плагин (для генерации кода), чтобы получить полноценную поддержку валидации."},{"id":"cli/generator/generator::top::147","title":"Генератор","section":"Использование правил валидации","path":"/docs/guide/cli/generator/generator","headings":["Использование правил валидации"],"excerpt":"Использование правил валидации Так выглядят правила валидации в proto — сгенерированный код будет автоматически их применять:","content":"Использование правил валидации Так выглядят правила валидации в proto — сгенерированный код будет автоматически их применять:"},{"id":"cli/generator/generator::top::148","title":"Генератор","section":"Использование правил валидации","path":"/docs/guide/cli/generator/generator","headings":["Использование правил валидации"],"excerpt":"Использование правил валидации ```proto // proto/user.proto syntax = \"proto3\";","content":"Использование правил валидации ```proto // proto/user.proto syntax = \"proto3\";"},{"id":"cli/generator/generator::top::149","title":"Генератор","section":"Использование правил валидации","path":"/docs/guide/cli/generator/generator","headings":["Использование правил валидации"],"excerpt":"Использование правил валидации import \"validate/validate.proto\";","content":"Использование правил валидации import \"validate/validate.proto\";"},{"id":"cli/generator/generator::top::150","title":"Генератор","section":"Использование правил валидации","path":"/docs/guide/cli/generator/generator","headings":["Использование правил валидации"],"excerpt":"Использование правил валидации message User { string email = 1 [(validate.rules).string.email = true]; int32 age = 2 [(validate.rules).int32.gte = 0]; } ```","content":"Использование правил валидации message User { string email = 1 [(validate.rules).string.email = true]; int32 age = 2 [(validate.rules).int32.gte = 0]; } ```"},{"id":"cli/generator/generator::top::151","title":"Генератор","section":"Комплексная конфигурация с несколькими зависимостями","path":"/docs/guide/cli/generator/generator","headings":["Комплексная конфигурация с несколькими зависимостями"],"excerpt":"Комплексная конфигурация с несколькими зависимостями Пример ниже показывает продакшен‑конфигурацию, объединяющую несколько зависимостей и плагины для полного цикла разработки API:","content":"Комплексная конфигурация с несколькими зависимостями Пример ниже показывает продакшен‑конфигурацию, объединяющую несколько зависимостей и плагины для полного цикла разработки API:"},{"id":"cli/generator/generator::top::152","title":"Генератор","section":"Комплексная конфигурация с несколькими зависимостями","path":"/docs/guide/cli/generator/generator","headings":["Комплексная конфигурация с несколькими зависимостями"],"excerpt":"Комплексная конфигурация с несколькими зависимостями ```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 HT","content":"Комплексная конфигурация с несколькими зависимостями ```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::top::153","title":"Генератор","section":"Комплексная конфигурация с несколькими зависимостями","path":"/docs/guide/cli/generator/generator","headings":["Комплексная конфигурация с несколькими зависимостями"],"excerpt":"Комплексная конфигурация с несколькими зависимостями generate: inputs: - directory: \"api/proto\" plugins: # Go code generation - Core protobuf structures - name: go out: ./gen/go opts: paths: source_relative module: githu","content":"Комплексная конфигурация с несколькими зависимостями 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::top::154","title":"Генератор","section":"Интеграция с кешем зависимостей","path":"/docs/guide/cli/generator/generator","headings":["Интеграция с кешем зависимостей"],"excerpt":"Интеграция с кешем зависимостей Генератор использует модульный кеш EasyP для ускорения сборок:","content":"Интеграция с кешем зависимостей Генератор использует модульный кеш EasyP для ускорения сборок:"},{"id":"cli/generator/generator::top::155","title":"Генератор","section":"Интеграция с кешем зависимостей","path":"/docs/guide/cli/generator/generator","headings":["Интеграция с кешем зависимостей"],"excerpt":"Интеграция с кешем зависимостей ```bash Download dependencies once easyp mod download","content":"Интеграция с кешем зависимостей ```bash Download dependencies once easyp mod download"},{"id":"cli/generator/generator::top::156","title":"Генератор","section":"Интеграция с кешем зависимостей","path":"/docs/guide/cli/generator/generator","headings":["Интеграция с кешем зависимостей"],"excerpt":"Интеграция с кешем зависимостей Generate code (uses cached dependencies) easyp generate","content":"Интеграция с кешем зависимостей Generate code (uses cached dependencies) easyp generate"},{"id":"cli/generator/generator::top::157","title":"Генератор","section":"Интеграция с кешем зависимостей","path":"/docs/guide/cli/generator/generator","headings":["Интеграция с кешем зависимостей"],"excerpt":"Интеграция с кешем зависимостей Dependencies are cached in ~/.easyp/mod/ ls ~/.easyp/mod/github.com/googleapis/googleapis/ ```","content":"Интеграция с кешем зависимостей Dependencies are cached in ~/.easyp/mod/ ls ~/.easyp/mod/github.com/googleapis/googleapis/ ```"},{"id":"cli/generator/generator::top::158","title":"Генератор","section":"Удалённая генерация","path":"/docs/guide/cli/generator/generator","headings":["Удалённая генерация"],"excerpt":"Удалённая генерация Удалённая генерация — мощная возможность, позволяющая генерировать код из proto‑файлов в удалённых Git‑репозиториях без локального checkout. Это поддерживает микросервисную архитектуру, где команды ис","content":"Удалённая генерация Удалённая генерация — мощная возможность, позволяющая генерировать код из proto‑файлов в удалённых Git‑репозиториях без локального checkout. Это поддерживает микросервисную архитектуру, где команды используют API друг друга без жёсткой связки."},{"id":"cli/generator/generator::top::159","title":"Генератор","section":"Удалённая генерация","path":"/docs/guide/cli/generator/generator","headings":["Удалённая генерация"],"excerpt":"Удалённая генерация **Преимущества:** **Развязка разработки**: Команды развиваются независимо, используя версии API друг друга **Контроль версий**: Фиксация внешних API гарантирует стабильность **Меньше размер репозитори","content":"Удалённая генерация **Преимущества:** **Развязка разработки**: Команды развиваются независимо, используя версии API друг друга **Контроль версий**: Фиксация внешних API гарантирует стабильность **Меньше размер репозитория**: Нет необходимости в vendoring/submodule внешних proto **Автоматические обновления**: Легко перейти на новую версию по готовности"},{"id":"cli/generator/generator::top::160","title":"Генератор","section":"Удалённая генерация","path":"/docs/guide/cli/generator/generator","headings":["Удалённая генерация"],"excerpt":"Удалённая генерация **Рекомендации:** В продакшене используйте только тегированные версии В разработке можно тестировать latest, но в проде фиксируйте При наличии используйте семантическое версионирование Учитывайте сете","content":"Удалённая генерация **Рекомендации:** В продакшене используйте только тегированные версии В разработке можно тестировать latest, но в проде фиксируйте При наличии используйте семантическое версионирование Учитывайте сетевые ограничения в CI/CD"},{"id":"cli/generator/generator::proto::161","title":"Генератор","section":"Источники удалённых proto","path":"/docs/guide/cli/generator/generator#proto","headings":["Источники удалённых proto"],"excerpt":"Источники удалённых proto Генерация напрямую из удалённых репозиториев — полезно в микросервисной архитектуре, где разные команды владеют разными proto.","content":"Источники удалённых proto Генерация напрямую из удалённых репозиториев — полезно в микросервисной архитектуре, где разные команды владеют разными proto."},{"id":"cli/generator/generator::proto::162","title":"Генератор","section":"Источники удалённых proto","path":"/docs/guide/cli/generator/generator#proto","headings":["Источники удалённых proto"],"excerpt":"Источники удалённых proto **Типовой workflow:** Команда A публикует proto с версиями в Git Команда B добавляет их в свой easyp.yaml При генерации EasyP скачивает и подключает удалённые proto Сгенерированный код содержит ","content":"Источники удалённых proto **Типовой workflow:** Команда A публикует proto с версиями в Git Команда B добавляет их в свой easyp.yaml При генерации EasyP скачивает и подключает удалённые proto Сгенерированный код содержит клиентские библиотеки сервисов команды A"},{"id":"cli/generator/generator::proto::163","title":"Генератор","section":"Источники удалённых proto","path":"/docs/guide/cli/generator/generator#proto","headings":["Источники удалённых proto"],"excerpt":"Источники удалённых proto Практический пример объединения локальных и удалённых источников в одной конфигурации генерации:","content":"Источники удалённых proto Практический пример объединения локальных и удалённых источников в одной конфигурации генерации:"},{"id":"cli/generator/generator::top::164","title":"Генератор","section":"Сценарии использования удалённой генерации","path":"/docs/guide/cli/generator/generator","headings":["Сценарии использования удалённой генерации"],"excerpt":"Сценарии использования удалённой генерации Примеры ниже показывают реальные ситуации, где удалённая генерация даёт ощутимую выгоду.","content":"Сценарии использования удалённой генерации Примеры ниже показывают реальные ситуации, где удалённая генерация даёт ощутимую выгоду."},{"id":"cli/generator/generator::multi-team-development::165","title":"Генератор","section":"Много команд (Multi-Team Development)","path":"/docs/guide/cli/generator/generator#multi-team-development","headings":["Много команд (Multi-Team Development)"],"excerpt":"Много команд (Multi-Team Development) Мультикомандная разработка особенно выигрывает: вместо координации общих репозиториев и сложного управления зависимостями — независимая эволюция API с контролируемыми обновлениями че","content":"Много команд (Multi-Team Development) Мультикомандная разработка особенно выигрывает: вместо координации общих репозиториев и сложного управления зависимостями — независимая эволюция API с контролируемыми обновлениями через версии."},{"id":"cli/generator/generator::multi-team-development::166","title":"Генератор","section":"Много команд (Multi-Team Development)","path":"/docs/guide/cli/generator/generator#multi-team-development","headings":["Много команд (Multi-Team Development)"],"excerpt":"Много команд (Multi-Team Development) Паттерн ценен в крупных организациях, где: Команды имеют разные циклы релизов и скорости разработки Владение API определено, потребление — массовое Нужно избежать overhead от координ","content":"Много команд (Multi-Team Development) Паттерн ценен в крупных организациях, где: Команды имеют разные циклы релизов и скорости разработки Владение API определено, потребление — массовое Нужно избежать overhead от координации общих proto репозиториев Команды используют разные стеки, но должны взаимодействовать"},{"id":"cli/generator/generator::multi-team-development::167","title":"Генератор","section":"Много команд (Multi-Team Development)","path":"/docs/guide/cli/generator/generator#multi-team-development","headings":["Много команд (Multi-Team Development)"],"excerpt":"Много команд (Multi-Team Development)","content":"Много команд (Multi-Team Development)"},{"id":"cli/generator/generator::api::168","title":"Генератор","section":"Интеграция с API вендоров","path":"/docs/guide/cli/generator/generator#api","headings":["Интеграция с API вендоров"],"excerpt":"Интеграция с API вендоров Многие вендоры публикуют proto для своих API, позволяя генерировать типобезопасных клиентов вместо ручных HTTP реализаций. Это повышает типовую строгость, автоматизирует сериализацию и часто уск","content":"Интеграция с API вендоров Многие вендоры публикуют proto для своих API, позволяя генерировать типобезопасных клиентов вместо ручных HTTP реализаций. Это повышает типовую строгость, автоматизирует сериализацию и часто ускоряет работу."},{"id":"cli/generator/generator::api::169","title":"Генератор","section":"Интеграция с API вендоров","path":"/docs/guide/cli/generator/generator#api","headings":["Интеграция с API вендоров"],"excerpt":"Интеграция с API вендоров Преимущества использования proto от вендоров: **Type safety**: Проверка типов на этапе компиляции **Automatic updates**: Новые возможности приходят с обновлением версии **Consistency**: Единые п","content":"Интеграция с API вендоров Преимущества использования proto от вендоров: **Type safety**: Проверка типов на этапе компиляции **Automatic updates**: Новые возможности приходят с обновлением версии **Consistency**: Единые паттерны интерфейсов между интеграциями **Performance**: Бинарная сериализация быстрее JSON **Documentation**: Proto выступают источником истины для API"},{"id":"cli/generator/generator::top::170","title":"Генератор","section":"Команды","path":"/docs/guide/cli/generator/generator","headings":["Команды"],"excerpt":"Команды CLI EasyP предоставляет гибкие варианты запуска генерации с разными конфигурациями и окружениями.","content":"Команды CLI EasyP предоставляет гибкие варианты запуска генерации с разными конфигурациями и окружениями."},{"id":"cli/generator/generator::top::171","title":"Генератор","section":"Базовая генерация","path":"/docs/guide/cli/generator/generator","headings":["Базовая генерация"],"excerpt":"Базовая генерация Ниже наиболее часто применяемые варианты команд для разработки и продакшена:","content":"Базовая генерация Ниже наиболее часто применяемые варианты команд для разработки и продакшена:"},{"id":"cli/generator/generator::top::172","title":"Генератор","section":"Базовая генерация","path":"/docs/guide/cli/generator/generator","headings":["Базовая генерация"],"excerpt":"Базовая генерация ```bash Use default easyp.yaml configuration - Most common for development easyp generate","content":"Базовая генерация ```bash Use default easyp.yaml configuration - Most common for development easyp generate"},{"id":"cli/generator/generator::top::173","title":"Генератор","section":"Базовая генерация","path":"/docs/guide/cli/generator/generator","headings":["Базовая генерация"],"excerpt":"Базовая генерация Use custom configuration file - Essential for multi-environment setups easyp --cfg production.easyp.yaml generate","content":"Базовая генерация Use custom configuration file - Essential for multi-environment setups easyp --cfg production.easyp.yaml generate"},{"id":"cli/generator/generator::top::174","title":"Генератор","section":"Базовая генерация","path":"/docs/guide/cli/generator/generator","headings":["Базовая генерация"],"excerpt":"Базовая генерация Generate with debug logs - Helpful for debugging and CI/CD easyp --debug generate","content":"Базовая генерация Generate with debug logs - Helpful for debugging and CI/CD easyp --debug generate"},{"id":"cli/generator/generator::top::175","title":"Генератор","section":"Базовая генерация","path":"/docs/guide/cli/generator/generator","headings":["Базовая генерация"],"excerpt":"Базовая генерация Generate with custom cache location - Useful for CI systems or shared environments EASYPPATH=/tmp/easyp-cache easyp generate ```","content":"Базовая генерация Generate with custom cache location - Useful for CI systems or shared environments EASYPPATH=/tmp/easyp-cache easyp generate ```"},{"id":"cli/generator/generator::top::176","title":"Генератор","section":"Интеграция с менеджером пакетов","path":"/docs/guide/cli/generator/generator","headings":["Интеграция с менеджером пакетов"],"excerpt":"Интеграция с менеджером пакетов Интеграция с менеджером пакетов позволяет либо явно управлять зависимостями, либо поручить это генератору. Явный путь даёт больше контроля, автоматический — больше удобства:","content":"Интеграция с менеджером пакетов Интеграция с менеджером пакетов позволяет либо явно управлять зависимостями, либо поручить это генератору. Явный путь даёт больше контроля, автоматический — больше удобства:"},{"id":"cli/generator/generator::top::177","title":"Генератор","section":"Интеграция с менеджером пакетов","path":"/docs/guide/cli/generator/generator","headings":["Интеграция с менеджером пакетов"],"excerpt":"Интеграция с менеджером пакетов ```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":"Интеграция с менеджером пакетов ```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::top::178","title":"Генератор","section":"Интеграция с менеджером пакетов","path":"/docs/guide/cli/generator/generator","headings":["Интеграция с менеджером пакетов"],"excerpt":"Интеграция с менеджером пакетов Automatic workflow - Convenient for development (generate downloads dependencies automatically) easyp generate ```","content":"Интеграция с менеджером пакетов Automatic workflow - Convenient for development (generate downloads dependencies automatically) easyp generate ```"},{"id":"cli/generator/generator::advanced-usage::179","title":"Генератор","section":"Расширенное использование (Advanced Usage)","path":"/docs/guide/cli/generator/generator#advanced-usage","headings":["Расширенное использование (Advanced Usage)"],"excerpt":"Расширенное использование (Advanced Usage) Эти варианты полезны для специфических сценариев деплоя, отладки или когда нужен более тонкий контроль процесса генерации:","content":"Расширенное использование (Advanced Usage) Эти варианты полезны для специфических сценариев деплоя, отладки или когда нужен более тонкий контроль процесса генерации:"},{"id":"cli/generator/generator::advanced-usage::180","title":"Генератор","section":"Расширенное использование (Advanced Usage)","path":"/docs/guide/cli/generator/generator#advanced-usage","headings":["Расширенное использование (Advanced Usage)"],"excerpt":"Расширенное использование (Advanced Usage) ```bash Генерация из конкретной директории (перекрывает настройку в файле конфигурации) easyp generate --path=./api/proto","content":"Расширенное использование (Advanced Usage) ```bash Генерация из конкретной директории (перекрывает настройку в файле конфигурации) easyp generate --path=./api/proto"},{"id":"cli/generator/generator::advanced-usage::181","title":"Генератор","section":"Расширенное использование (Advanced Usage)","path":"/docs/guide/cli/generator/generator#advanced-usage","headings":["Расширенное использование (Advanced Usage)"],"excerpt":"Расширенное использование (Advanced Usage) Генерация с vendored зависимостями (оффлайн / Docker контейнеры) easyp mod vendor easyp generate","content":"Расширенное использование (Advanced Usage) Генерация с vendored зависимостями (оффлайн / Docker контейнеры) easyp mod vendor easyp generate"},{"id":"cli/generator/generator::advanced-usage::182","title":"Генератор","section":"Расширенное использование (Advanced Usage)","path":"/docs/guide/cli/generator/generator#advanced-usage","headings":["Расширенное использование (Advanced Usage)"],"excerpt":"Расширенное использование (Advanced Usage) Генерация из кастомного project root (удобно для монореп и вложенных рабочих директорий) easyp generate --root=/usr/local/src/my-project --path=./api/proto ```","content":"Расширенное использование (Advanced Usage) Генерация из кастомного project root (удобно для монореп и вложенных рабочих директорий) easyp generate --root=/usr/local/src/my-project --path=./api/proto ```"},{"id":"cli/generator/generator::common-patterns::183","title":"Генератор","section":"Типовые паттерны (Common Patterns)","path":"/docs/guide/cli/generator/generator#common-patterns","headings":["Типовые паттерны (Common Patterns)"],"excerpt":"Типовые паттерны (Common Patterns) Эти схемы отражают реальные сценарии и лучшие практики организации генерации кода в разных структурах проектов.","content":"Типовые паттерны (Common Patterns) Эти схемы отражают реальные сценарии и лучшие практики организации генерации кода в разных структурах проектов."},{"id":"cli/generator/generator::multi-language-generation::184","title":"Генератор","section":"Мульти-языковая генерация (Multi-Language Generation)","path":"/docs/guide/cli/generator/generator#multi-language-generation","headings":["Мульти-языковая генерация (Multi-Language Generation)"],"excerpt":"Мульти-языковая генерация (Multi-Language Generation) Мульти-языковая генерация критична для компаний, использующих разные технологии в стеке. EasyP облегчает получение согласованных клиентских библиотек и типов для неск","content":"Мульти-языковая генерация (Multi-Language Generation) Мульти-языковая генерация критична для компаний, использующих разные технологии в стеке. EasyP облегчает получение согласованных клиентских библиотек и типов для нескольких языков из одного источника proto."},{"id":"cli/generator/generator::multi-language-generation::185","title":"Генератор","section":"Мульти-языковая генерация (Multi-Language Generation)","path":"/docs/guide/cli/generator/generator#multi-language-generation","headings":["Мульти-языковая генерация (Multi-Language Generation)"],"excerpt":"Мульти-языковая генерация (Multi-Language Generation) **Типовые сценарии:** **Full‑stack приложения**: backend на Go/Java + фронтенд на TypeScript **Платформы данных**: сервисы на Go + аналитика / ML на Python **Микросер","content":"Мульти-языковая генерация (Multi-Language Generation) **Типовые сценарии:** **Full‑stack приложения**: backend на Go/Java + фронтенд на TypeScript **Платформы данных**: сервисы на Go + аналитика / ML на Python **Микросервисы**: каждый сервис — оптимальный язык под задачу **Внешние SDK**: предоставление клиентских библиотек партнёрам **Интеграция с легаси**: современные gRPC сервисы + старые системы"},{"id":"cli/generator/generator::multi-language-generation::186","title":"Генератор","section":"Мульти-языковая генерация (Multi-Language Generation)","path":"/docs/guide/cli/generator/generator#multi-language-generation","headings":["Мульти-языковая генерация (Multi-Language Generation)"],"excerpt":"Мульти-языковая генерация (Multi-Language Generation) **Производительность:** Каждый плагин запускается отдельно — время растёт линейно от количества плагинов Для больших наборов используйте параллельный запуск (make -j4","content":"Мульти-языковая генерация (Multi-Language Generation) **Производительность:** Каждый плагин запускается отдельно — время растёт линейно от количества плагинов Для больших наборов используйте параллельный запуск (make -j4) Структурируйте выходные директории иерархически — меньше конфликтов Плагины имеют разную скорость — профилируйте сборку для поиска узких мест"},{"id":"cli/generator/generator::multi-language-generation::187","title":"Генератор","section":"Мульти-языковая генерация (Multi-Language Generation)","path":"/docs/guide/cli/generator/generator#multi-language-generation","headings":["Мульти-языковая генерация (Multi-Language Generation)"],"excerpt":"Мульти-языковая генерация (Multi-Language Generation) **Преимущества сопровождения:** Единый источник истины для API снижает риск расхождения схем Согласованные типы уменьшают интеграционные баги Автоматическая синхрониз","content":"Мульти-языковая генерация (Multi-Language Generation) **Преимущества сопровождения:** Единый источник истины для API снижает риск расхождения схем Согласованные типы уменьшают интеграционные баги Автоматическая синхронизация при изменении proto исключает ручные правки Меньше риска дрейфа API между реализациями на разных языках Рефакторинг упрощается — изменения транзитивно отражаются во всех артефактах"},{"id":"cli/generator/generator::multi-language-generation::188","title":"Генератор","section":"Мульти-языковая генерация (Multi-Language Generation)","path":"/docs/guide/cli/generator/generator#multi-language-generation","headings":["Мульти-языковая генерация (Multi-Language Generation)"],"excerpt":"Мульти-языковая генерация (Multi-Language Generation) Ниже пример типичной мульти-языковой конфигурации для full‑stack приложения: backend, веб‑клиент, аналитика и документация:","content":"Мульти-языковая генерация (Multi-Language Generation) Ниже пример типичной мульти-языковой конфигурации для full‑stack приложения: backend, веб‑клиент, аналитика и документация:"},{"id":"cli/generator/generator::multi-language-generation::189","title":"Генератор","section":"Мульти-языковая генерация (Multi-Language Generation)","path":"/docs/guide/cli/generator/generator#multi-language-generation","headings":["Мульти-языковая генерация (Multi-Language Generation)"],"excerpt":"Мульти-языковая генерация (Multi-Language Generation)","content":"Мульти-языковая генерация (Multi-Language Generation)"},{"id":"cli/generator/generator::multi-language-generation::190","title":"Генератор","section":"Мульти-языковая генерация (Multi-Language Generation)","path":"/docs/guide/cli/generator/generator#multi-language-generation","headings":["Мульти-языковая генерация (Multi-Language Generation)"],"excerpt":"Мульти-языковая генерация (Multi-Language Generation) **Совет по организации:** Используйте отдельные выходные директории для каждого языка, чтобы избежать конфликтов файлов и упростить интеграцию с языковыми сборочными ","content":"Мульти-языковая генерация (Multi-Language Generation) **Совет по организации:** Используйте отдельные выходные директории для каждого языка, чтобы избежать конфликтов файлов и упростить интеграцию с языковыми сборочными системами."},{"id":"cli/generator/generator::multi-language-generation::191","title":"Генератор","section":"Мульти-языковая генерация (Multi-Language Generation)","path":"/docs/guide/cli/generator/generator#multi-language-generation","headings":["Мульти-языковая генерация (Multi-Language Generation)"],"excerpt":"Мульти-языковая генерация (Multi-Language Generation) Генератор EasyP — комплексное решение для генерации кода из Protocol Buffers: от простой локальной разработки до сложных enterprise‑сценариев с удалёнными зависимостя","content":"Мульти-языковая генерация (Multi-Language Generation) Генератор EasyP — комплексное решение для генерации кода из Protocol Buffers: от простой локальной разработки до сложных enterprise‑сценариев с удалёнными зависимостями и мульти-языковым выводом."},{"id":"cli/linter/linter::proto::0","title":"Линтер","section":"Зачем нужен линтер для proto файлов?","path":"/docs/guide/cli/linter/linter#proto","headings":["Зачем нужен линтер для proto файлов?"],"excerpt":"Зачем нужен линтер для proto файлов? Линтеры играют ключевую роль в современной разработке, особенно когда речь о .proto файлах. Они обеспечивают единый стиль и структуру, помогают находить потенциальные ошибки на ранних","content":"Зачем нужен линтер для proto файлов? Линтеры играют ключевую роль в современной разработке, особенно когда речь о .proto файлах. Они обеспечивают единый стиль и структуру, помогают находить потенциальные ошибки на ранних этапах и поддерживают читаемость кода. Это даёт выгоды:"},{"id":"cli/linter/linter::proto::1","title":"Линтер","section":"Зачем нужен линтер для proto файлов?","path":"/docs/guide/cli/linter/linter#proto","headings":["Зачем нужен линтер для proto файлов?"],"excerpt":"Зачем нужен линтер для proto файлов? **Снижение затрат на разработку:** Ошибки ловятся раньше, меньше времени на отладку. **Улучшение командного взаимодействия:** Единообразный код легче понимать и сопровождать. **Бизнес","content":"Зачем нужен линтер для proto файлов? **Снижение затрат на разработку:** Ошибки ловятся раньше, меньше времени на отладку. **Улучшение командного взаимодействия:** Единообразный код легче понимать и сопровождать. **Бизнес-эффективность:** Более качественный код → меньше инцидентов в проде → ниже стоимость поддержки."},{"id":"cli/linter/linter::top::2","title":"Линтер","section":"Справочник по конфигурации","path":"/docs/guide/cli/linter/linter","headings":["Справочник по конфигурации"],"excerpt":"Справочник по конфигурации Конфигурация линтера настраивается в секции lint файла easyp.yaml.","content":"Справочник по конфигурации Конфигурация линтера настраивается в секции lint файла easyp.yaml."},{"id":"cli/linter/linter::use-string::3","title":"Линтер","section":"use ([]string)","path":"/docs/guide/cli/linter/linter#use-string","headings":["use ([]string)"],"excerpt":"use ([]string) Определяет набор правил или категорий для включения. Можно смешивать категории и конкретные правила.","content":"use ([]string) Определяет набор правил или категорий для включения. Можно смешивать категории и конкретные правила."},{"id":"cli/linter/linter::use-string::4","title":"Линтер","section":"use ([]string)","path":"/docs/guide/cli/linter/linter#use-string","headings":["use ([]string)"],"excerpt":"use ([]string) **Категории:** **MINIMAL**: Базовая согласованность пакетов **BASIC**: Соглашения по именованию и структуре **DEFAULT**: Рекомендованные правила для большинства проектов **COMMENTS**: Требования к коммента","content":"use ([]string) **Категории:** **MINIMAL**: Базовая согласованность пакетов **BASIC**: Соглашения по именованию и структуре **DEFAULT**: Рекомендованные правила для большинства проектов **COMMENTS**: Требования к комментариям **UNARY_RPC**: Ограничение на streaming RPC"},{"id":"cli/linter/linter::use-string::5","title":"Линтер","section":"use ([]string)","path":"/docs/guide/cli/linter/linter#use-string","headings":["use ([]string)"],"excerpt":"use ([]string) **Индивидуальные правила:** Любое имя правила (например ENUM_PASCAL_CASE, FIELD_LOWER_SNAKE_CASE)","content":"use ([]string) **Индивидуальные правила:** Любое имя правила (например ENUM_PASCAL_CASE, FIELD_LOWER_SNAKE_CASE)"},{"id":"cli/linter/linter::use-string::6","title":"Линтер","section":"use ([]string)","path":"/docs/guide/cli/linter/linter#use-string","headings":["use ([]string)"],"excerpt":"use ([]string) **Примеры:** ```yaml Только категории use: [MINIMAL, BASIC, DEFAULT]","content":"use ([]string) **Примеры:** ```yaml Только категории use: [MINIMAL, BASIC, DEFAULT]"},{"id":"cli/linter/linter::use-string::7","title":"Линтер","section":"use ([]string)","path":"/docs/guide/cli/linter/linter#use-string","headings":["use ([]string)"],"excerpt":"use ([]string) Смешивание use: - MINIMAL - COMMENT_SERVICE - COMMENT_RPC - ENUM_PASCAL_CASE","content":"use ([]string) Смешивание use: - MINIMAL - COMMENT_SERVICE - COMMENT_RPC - ENUM_PASCAL_CASE"},{"id":"cli/linter/linter::use-string::8","title":"Линтер","section":"use ([]string)","path":"/docs/guide/cli/linter/linter#use-string","headings":["use ([]string)"],"excerpt":"use ([]string) Точный набор use: - PACKAGE_DEFINED - SERVICE_PASCAL_CASE - FIELD_LOWER_SNAKE_CASE ```","content":"use ([]string) Точный набор use: - PACKAGE_DEFINED - SERVICE_PASCAL_CASE - FIELD_LOWER_SNAKE_CASE ```"},{"id":"cli/linter/linter::enum_zero_value_suffix-string::9","title":"Линтер","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) Обязывает нулевое значение enum иметь заданный суффикс.","content":"enum_zero_value_suffix (string) Обязывает нулевое значение enum иметь заданный суффикс."},{"id":"cli/linter/linter::enum_zero_value_suffix-string::10","title":"Линтер","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) **Обычно:** \"UNSPECIFIED\", \"UNKNOWN\", \"DEFAULT\"","content":"enum_zero_value_suffix (string) **Обычно:** \"UNSPECIFIED\", \"UNKNOWN\", \"DEFAULT\""},{"id":"cli/linter/linter::enum_zero_value_suffix-string::11","title":"Линтер","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)","content":"enum_zero_value_suffix (string)"},{"id":"cli/linter/linter::service_suffix-string::12","title":"Линтер","section":"service_suffix (string)","path":"/docs/guide/cli/linter/linter#service_suffix-string","headings":["service_suffix (string)"],"excerpt":"service_suffix (string) Требуемый суффикс для имён сервисов (унификация стиля).","content":"service_suffix (string) Требуемый суффикс для имён сервисов (унификация стиля)."},{"id":"cli/linter/linter::ignore-string::13","title":"Линтер","section":"ignore ([]string)","path":"/docs/guide/cli/linter/linter#ignore-string","headings":["ignore ([]string)"],"excerpt":"ignore ([]string) Полное исключение путей из линтинга.","content":"ignore ([]string) Полное исключение путей из линтинга."},{"id":"cli/linter/linter::ignore-string::14","title":"Линтер","section":"ignore ([]string)","path":"/docs/guide/cli/linter/linter#ignore-string","headings":["ignore ([]string)"],"excerpt":"ignore ([]string) **Use cases:** vendor / third_party сгенерированные файлы легаси подпакеты тестовые фикстуры","content":"ignore ([]string) **Use cases:** vendor / third_party сгенерированные файлы легаси подпакеты тестовые фикстуры"},{"id":"cli/linter/linter::except-string::15","title":"Линтер","section":"except ([]string)","path":"/docs/guide/cli/linter/linter#except-string","headings":["except ([]string)"],"excerpt":"except ([]string) Глобально отключает правила.","content":"except ([]string) Глобально отключает правила."},{"id":"cli/linter/linter::allow_comment_ignores-bool::16","title":"Линтер","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) Разрешает инлайн‑игнор правил комментариями.","content":"allow_comment_ignores (bool) Разрешает инлайн‑игнор правил комментариями."},{"id":"cli/linter/linter::ignore_only-mapstringstring::17","title":"Линтер","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) Таргетированное игнорирование конкретных правил для указанных путей.","content":"ignore_only (mapstringstring) Таргетированное игнорирование конкретных правил для указанных путей."},{"id":"cli/linter/linter::top::18","title":"Линтер","section":"Игнор правил комментариями","path":"/docs/guide/cli/linter/linter","headings":["Игнор правил комментариями"],"excerpt":"Игнор правил комментариями Если включён allow_comment_ignores, можно точечно отключать правила.","content":"Игнор правил комментариями Если включён allow_comment_ignores, можно точечно отключать правила."},{"id":"cli/linter/linter::top::19","title":"Линтер","section":"Несколько правил в одной строке","path":"/docs/guide/cli/linter/linter","headings":["Несколько правил в одной строке"],"excerpt":"Несколько правил в одной строке","content":"Несколько правил в одной строке"},{"id":"cli/linter/linter::top::20","title":"Линтер","section":"Используйте редко","path":"/docs/guide/cli/linter/linter","headings":["Используйте редко"],"excerpt":"Используйте редко Частое игнорирование = сигнал пересмотреть конфигурацию.","content":"Используйте редко Частое игнорирование = сигнал пересмотреть конфигурацию."},{"id":"cli/linter/linter::top::21","title":"Линтер","section":"Предпочитайте конфигурацию","path":"/docs/guide/cli/linter/linter","headings":["Предпочитайте конфигурацию"],"excerpt":"Предпочитайте конфигурацию Если нужно игнорировать правило в группе файлов — используйте ignore_only.","content":"Предпочитайте конфигурацию Если нужно игнорировать правило в группе файлов — используйте ignore_only."},{"id":"cli/linter/linter::top::22","title":"Линтер","section":"Категории линтера","path":"/docs/guide/cli/linter/linter","headings":["Категории линтера"],"excerpt":"Категории линтера Категории помогают быстро выбрать уровень строгости.","content":"Категории линтера Категории помогают быстро выбрать уровень строгости."},{"id":"cli/linter/linter::top::23","title":"Линтер","section":"Категории линтера","path":"/docs/guide/cli/linter/linter","headings":["Категории линтера"],"excerpt":"Категории линтера **Когда использовать:** **MINIMAL**: Минимальная базовая целостность **BASIC**: Частые соглашения имен **DEFAULT**: Дополнительные проверки качества **COMMENTS**: Обязательные комментарии (API, команды)","content":"Категории линтера **Когда использовать:** **MINIMAL**: Минимальная базовая целостность **BASIC**: Частые соглашения имен **DEFAULT**: Дополнительные проверки качества **COMMENTS**: Обязательные комментарии (API, команды) **UNARY_RPC**: Ограничить streaming RPC"},{"id":"cli/linter/linter::minimal::24","title":"Линтер","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::25","title":"Линтер","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::26","title":"Линтер","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::27","title":"Линтер","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::28","title":"Линтер","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::top::29","title":"Линтер","section":"Заключение","path":"/docs/guide/cli/linter/linter","headings":["Заключение"],"excerpt":"Заключение Внедрение EasyP линдера для ваших proto файлов заметно улучшит workflow, качество и поддерживаемость кода. Полная совместимость с Buf позволяет командам мигрировать без боли, используя гибкую конфигурацию и мо","content":"Заключение Внедрение EasyP линдера для ваших proto файлов заметно улучшит workflow, качество и поддерживаемость кода. Полная совместимость с Buf позволяет командам мигрировать без боли, используя гибкую конфигурацию и мощные возможности из коробки."},{"id":"cli/linter/rules/comment-enum-value::top::0","title":"COMMENT_ENUM_VALUE","path":"/docs/guide/cli/linter/rules/comment-enum-value","headings":[],"excerpt":"Это правило проверяет, что все значения enum имеют комментарий.","content":"Это правило проверяет, что все значения enum имеют комментарий."},{"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 ```proto syntax = \"proto3\";","content":"Good ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/comment-enum-value::good::4","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":"Это правило проверяет, что enum имеет комментарий.","content":"Это правило проверяет, что enum имеет комментарий."},{"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":"Это правило проверяет, что все поля сообщений имеют комментарий.","content":"Это правило проверяет, что все поля сообщений имеют комментарий."},{"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":"Это правило проверяет, что message имеет комментарий.","content":"Это правило проверяет, что message имеет комментарий."},{"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 ```proto syntax = \"proto3\";","content":"Bad ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/comment-message::bad::2","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::3","title":"COMMENT_MESSAGE","section":"Good","path":"/docs/guide/cli/linter/rules/comment-message#good","headings":["Good"],"excerpt":"Good ```proto syntax = \"proto3\";","content":"Good ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/comment-message::good::4","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":"Это правило проверяет, что oneof имеет комментарий.","content":"Это правило проверяет, что oneof имеет комментарий."},{"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":"Это правило проверяет, что сервис имеет комментарий.","content":"Это правило проверяет, что сервис имеет комментарий."},{"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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **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":"Это правило проверяет, что все файлы в заданной директории находятся в одном и том же package.","content":"Это правило проверяет, что все файлы в заданной директории находятся в одном и том же 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":"Это правило проверяет, что первое значение enum равно нулю.","content":"Это правило проверяет, что первое значение enum равно нулю."},{"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 ```proto syntax = \"proto3\";","content":"Bad ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/enum-first-value-zero::bad::3","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::4","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::5","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":"Это правило проверяет, что опция allow_alias не установлена в значение true внутри enum.","content":"Это правило проверяет, что опция allow_alias не установлена в значение true внутри 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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **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":"Это правило проверяет, что имена enum написаны в стиле PascalCase.","content":"Это правило проверяет, что имена enum написаны в стиле 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":"Это правило проверяет, что все значения enum имеют префикс, совпадающий с именем enum.","content":"Это правило проверяет, что все значения enum имеют префикс, совпадающий с именем enum."},{"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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **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":"Это правило проверяет, что значения enum записаны в стиле UPPER_SNAKE_CASE.","content":"Это правило проверяет, что значения enum записаны в стиле 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":"Это правило проверяет, что все нулевые значения enum имеют суффикс _NONE или ваш кастомный (пользовательский) суффикс.","content":"Это правило проверяет, что все нулевые значения enum имеют суффикс _NONE или ваш кастомный (пользовательский) суффикс."},{"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":"**MINIMAL** **BASIC** **DEFAULT**","content":"**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":"Это правило проверяет, что имена полей сообщений записаны в стиле lower_snake_case.","content":"Это правило проверяет, что имена полей сообщений записаны в стиле 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":"Это правило проверяет, что все файлы имеют имя в формате lower_snake_case (только строчные буквы, цифры и символ подчеркивания, без пробелов и заглавных букв).","content":"Это правило проверяет, что все файлы имеют имя в формате 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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **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":"Это правило проверяет, что в proto-файле не используются public импорты (оператор import public \"...\").","content":"Это правило проверяет, что в proto-файле не используются public импорты (оператор import public \"...\")."},{"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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **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":"Это правило проверяет, что в proto‑файле не используются weak‑импорты (import weak \"...\").","content":"Это правило проверяет, что в proto‑файле не используются weak‑импорты (import weak \"...\")."},{"id":"cli/linter/rules/import-no-weak::top::2","title":"IMPORT_NO_WEAK","path":"/docs/guide/cli/linter/rules/import-no-weak","headings":[],"excerpt":"Weak import (синтаксис import weak) допустим в proto2, но его использование усложняет анализ зависимостей и может приводить к неочевидным ошибкам при генерации кода. Рекомендуется всегда использовать обычный import.","content":"Weak import (синтаксис import weak) допустим в proto2, но его использование усложняет анализ зависимостей и может приводить к неочевидным ошибкам при генерации кода. Рекомендуется всегда использовать обычный import."},{"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 ```proto syntax = \"proto2\";","content":"Bad ```proto syntax = \"proto2\";"},{"id":"cli/linter/rules/import-no-weak::bad::4","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::5","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::6","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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **MINIMAL** **BASIC** **DEFAULT**"},{"id":"cli/linter/rules/import-used::top::1","title":"IMPORT_USED","path":"/docs/guide/cli/linter/rules/import-used","headings":[],"excerpt":"Это правило проверяет, что все импорты используются в proto-файле.","content":"Это правило проверяет, что все импорты используются в proto-файле."},{"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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **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":"Это правило проверяет, что имена сообщений (message) записаны в стиле PascalCase.","content":"Это правило проверяет, что имена сообщений (message) записаны в стиле 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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **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":"Это правило проверяет, что имена oneof записаны в стиле lower_snake_case.","content":"Это правило проверяет, что имена oneof записаны в стиле 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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **MINIMAL** **BASIC** **DEFAULT**"},{"id":"cli/linter/rules/package-defined::top::1","title":"PACKAGE_DEFINED","path":"/docs/guide/cli/linter/rules/package-defined","headings":[],"excerpt":"Это правило проверяет, что во всех файлах присутствует директива package.","content":"Это правило проверяет, что во всех файлах присутствует директива package."},{"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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **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":"Это правило проверяет, что все файлы находятся в директории, имя которой соответствует имени их пакета.","content":"Это правило проверяет, что все файлы находятся в директории, имя которой соответствует имени их пакета."},{"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":"Это правило проверяет, что имена package записаны в формате lower_snake_case (строчные буквы, при необходимости цифры и символ подчеркивания, без пробелов и заглавных букв).","content":"Это правило проверяет, что имена package записаны в формате 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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **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":"Это правило проверяет, что все файлы с заданным пакетом используют одно и то же пространство имён C# (csharp_namespace).","content":"Это правило проверяет, что все файлы с заданным пакетом используют одно и то же пространство имён C# (csharp_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\"; // [!code focus] ```","content":"Good option csharp_namespace = \"Foo.Bar\"; // [!code focus] ```"},{"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 ```proto // File: pkg/bar.proto","content":"Good ```proto // File: pkg/bar.proto"},{"id":"cli/linter/rules/package-same-csharp-namespace::good::9","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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **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":"Это правило проверяет, что все файлы с данным package находятся в одной директории.","content":"Это правило проверяет, что все файлы с данным package находятся в одной директории."},{"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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **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":"Это правило проверяет, что все файлы с одним и тем же package используют одно и то же значение опции go_package.","content":"Это правило проверяет, что все файлы с одним и тем же package используют одно и то же значение опции 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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **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":"Это правило проверяет, что все файлы с одним и тем же package используют одинаковое значение опции java_package.","content":"Это правило проверяет, что все файлы с одним и тем же package используют одинаковое значение опции 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 ```proto // File: pkg/bar.proto","content":"Bad ```proto // File: pkg/bar.proto"},{"id":"cli/linter/rules/package-same-java-multiple-files::bad::6","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::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 ```proto // File: pkg/foo.proto","content":"Good ```proto // File: pkg/foo.proto"},{"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 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::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 ```proto // File: pkg/bar.proto","content":"Good ```proto // File: pkg/bar.proto"},{"id":"cli/linter/rules/package-same-java-multiple-files::good::10","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":"Это правило проверяет, что все файлы с одним и тем же package используют одно и то же значение опции java_package.","content":"Это правило проверяет, что все файлы с одним и тем же package используют одно и то же значение опции 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":"Это правило проверяет, что все файлы с одним и тем же package используют одно и то же значение опции php_namespace.","content":"Это правило проверяет, что все файлы с одним и тем же package используют одно и то же значение опции 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":"Это правило проверяет, что все файлы с одним и тем же package используют один и тот же swift_prefix.","content":"Это правило проверяет, что все файлы с одним и тем же package используют один и тот же 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":"Это правило проверяет, что суффикс версии пакета имеет формат _vX, где X — числовая версия.","content":"Это правило проверяет, что суффикс версии пакета имеет формат _vX, где X — числовая версия."},{"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":"Это правило проверяет, что RPC не использует клиентский стриминг (запрос не является stream ...).","content":"Это правило проверяет, что RPC не использует клиентский стриминг (запрос не является stream ...)."},{"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":"Это правило проверяет, что RPC не использует серверный стриминг (ответ не является stream ...).","content":"Это правило проверяет, что RPC не использует серверный стриминг (ответ не является stream ...)."},{"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":"Это правило проверяет, что все имена RPC написаны в стиле PascalCase.","content":"Это правило проверяет, что все имена RPC написаны в стиле 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":"Это правило проверяет, что все сообщения запроса и ответа RPC уникальны: для каждого метода используются собственные (не переиспользуются одинаковые пары Request / Response у разных RPC).","content":"Это правило проверяет, что все сообщения запроса и ответа RPC уникальны: для каждого метода используются собственные (не переиспользуются одинаковые пары Request / Response у разных RPC)."},{"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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **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":"Это правило проверяет, что все сообщения запроса RPC названы в формате MethodRequest.","content":"Это правило проверяет, что все сообщения запроса RPC названы в формате 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":"Это правило проверяет, что все сообщения ответа RPC названы в формате MethodResponse.","content":"Это правило проверяет, что все сообщения ответа RPC названы в формате 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":"**MINIMAL** **BASIC** **DEFAULT**","content":"**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":"Это правило проверяет, что все имена сервисов написаны в стиле PascalCase.","content":"Это правило проверяет, что все имена сервисов написаны в стиле 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":"Это правило проверяет, что все сервисы имеют суффикс Service или ваш пользовательский суффикс.","content":"Это правило проверяет, что все сервисы имеют суффикс Service или ваш пользовательский суффикс."},{"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 против Buf: управление пакетами","path":"/docs/guide/cli/package-manager/easyp-vs-buf","headings":[],"excerpt":"EasyP против Buf: управление пакетами","content":"EasyP против Buf: управление пакетами"},{"id":"cli/package-manager/easyp-vs-buf::top::1","title":"EasyP против Buf: управление пакетами","path":"/docs/guide/cli/package-manager/easyp-vs-buf","headings":[],"excerpt":"Этот документ даёт подробное сравнение децентрализованного подхода EasyP к управлению пакетами и централизованной модели Buf через Buf Schema Registry (BSR), чтобы помочь понять ключевые различия и выбрать подходящее реш","content":"Этот документ даёт подробное сравнение децентрализованного подхода EasyP к управлению пакетами и централизованной модели Buf через Buf Schema Registry (BSR), чтобы помочь понять ключевые различия и выбрать подходящее решение для ваших задач."},{"id":"cli/package-manager/easyp-vs-buf::easyp-git::2","title":"EasyP против Buf: управление пакетами","section":"EasyP: децентрализованный подход на базе Git","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp-git","headings":["EasyP: децентрализованный подход на базе Git"],"excerpt":"EasyP: децентрализованный подход на базе Git","content":"EasyP: децентрализованный подход на базе Git"},{"id":"cli/package-manager/easyp-vs-buf::buf-bsr::3","title":"EasyP против Buf: управление пакетами","section":"Buf: централизованный реестр (BSR)","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf-bsr","headings":["Buf: централизованный реестр (BSR)"],"excerpt":"Buf: централизованный реестр (BSR)","content":"Buf: централизованный реестр (BSR)"},{"id":"cli/package-manager/easyp-vs-buf::top::4","title":"EasyP против Buf: управление пакетами","section":"Краткое резюме различий","path":"/docs/guide/cli/package-manager/easyp-vs-buf","headings":["Краткое резюме различий"],"excerpt":"Краткое резюме различий Аспект EasyP Buf -------- ------- ----- **Архитектура** Децентрализованная (Git) Централизованная (реестр BSR) **Источник зависимостей** Любой Git репозиторий Только модули BSR **Единая точка отка","content":"Краткое резюме различий Аспект EasyP Buf -------- ------- ----- **Архитектура** Децентрализованная (Git) Централизованная (реестр BSR) **Источник зависимостей** Любой Git репозиторий Только модули BSR **Единая точка отказа** Нет Да (buf.build) **Enterprise / air‑gapped** Полная поддержка Требует доступа к BSR или приватного BSR **Аутентификация** Git (SSH / HTTPS) Токены Buf + Git **Vendor lock‑in** Отсутствует Привязка к экосистеме Buf **Частные репозитории** Нативно через Git Нужно опубликовать в BSR **Оффлайн поддержка** Полная (через vendoring) Ограничена (кэшированные модули) **Стоимость** Бесплатно (использует существующий Git) Бесплатный тариф + платные планы **Сложность настройки** Минимальная Средняя (настройка BSR)"},{"id":"cli/package-manager/easyp-vs-buf::top::5","title":"EasyP против Buf: управление пакетами","section":"Подробное сравнение возможностей","path":"/docs/guide/cli/package-manager/easyp-vs-buf","headings":["Подробное сравнение возможностей"],"excerpt":"Подробное сравнение возможностей","content":"Подробное сравнение возможностей"},{"id":"cli/package-manager/easyp-vs-buf::1::6","title":"EasyP против Buf: управление пакетами","section":"1. Философия управления зависимостями","path":"/docs/guide/cli/package-manager/easyp-vs-buf#1","headings":["1. Философия управления зависимостями"],"excerpt":"Философия управления зависимостями","content":"Философия управления зависимостями"},{"id":"cli/package-manager/easyp-vs-buf::easyp-git::7","title":"EasyP против Buf: управление пакетами","section":"EasyP: «Любой Git репозиторий — это пакет»","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp-git","headings":["EasyP: «Любой Git репозиторий — это пакет»"],"excerpt":"EasyP: «Любой Git репозиторий — это пакет»","content":"EasyP: «Любой Git репозиторий — это пакет»"},{"id":"cli/package-manager/easyp-vs-buf::easyp-git::8","title":"EasyP против Buf: управление пакетами","section":"EasyP: «Любой Git репозиторий — это пакет»","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp-git","headings":["EasyP: «Любой Git репозиторий — это пакет»"],"excerpt":"EasyP: «Любой Git репозиторий — это пакет» **Преимущества:** ✅ Использование любого существующего репозитория сразу ✅ Не нужно «публиковать» в отдельный реестр ✅ Истинный источник версий — Git ✅ Работает с приватными сер","content":"EasyP: «Любой Git репозиторий — это пакет» **Преимущества:** ✅ Использование любого существующего репозитория сразу ✅ Не нужно «публиковать» в отдельный реестр ✅ Истинный источник версий — Git ✅ Работает с приватными серверами без доп. настроек"},{"id":"cli/package-manager/easyp-vs-buf::buf::9","title":"EasyP против Buf: управление пакетами","section":"Buf: «Сначала реестр»","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf","headings":["Buf: «Сначала реестр»"],"excerpt":"Buf: «Сначала реестр» **Преимущества:** ✅ Курируемые, проверенные модули ✅ Богатые метаданные и документация ✅ Визуализация графа зависимостей ✅ Принуждение семантического версионирования","content":"Buf: «Сначала реестр» **Преимущества:** ✅ Курируемые, проверенные модули ✅ Богатые метаданные и документация ✅ Визуализация графа зависимостей ✅ Принуждение семантического версионирования"},{"id":"cli/package-manager/easyp-vs-buf::buf::10","title":"EasyP против Buf: управление пакетами","section":"Buf: «Сначала реестр»","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf","headings":["Buf: «Сначала реестр»"],"excerpt":"Buf: «Сначала реестр» **Ограничения:** ❌ Нужно опубликовать в BSR перед использованием ❌ Требует аккаунт и аутентификацию ❌ Нельзя напрямую сослаться на произвольный Git репозиторий","content":"Buf: «Сначала реестр» **Ограничения:** ❌ Нужно опубликовать в BSR перед использованием ❌ Требует аккаунт и аутентификацию ❌ Нельзя напрямую сослаться на произвольный Git репозиторий"},{"id":"cli/package-manager/easyp-vs-buf::2-airgapped::11","title":"EasyP против Buf: управление пакетами","section":"2. Корпоративные и изолированные (air‑gapped) среды","path":"/docs/guide/cli/package-manager/easyp-vs-buf#2-airgapped","headings":["2. Корпоративные и изолированные (air‑gapped) среды"],"excerpt":"Корпоративные и изолированные (air‑gapped) среды","content":"Корпоративные и изолированные (air‑gapped) среды"},{"id":"cli/package-manager/easyp-vs-buf::easyp::12","title":"EasyP против Buf: управление пакетами","section":"EasyP: Полноценная оффлайн‑поддержка","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["EasyP: Полноценная оффлайн‑поддержка"],"excerpt":"EasyP: Полноценная оффлайн‑поддержка **Сценарий**: крупная компания со строгими сетевыми политиками","content":"EasyP: Полноценная оффлайн‑поддержка **Сценарий**: крупная компания со строгими сетевыми политиками"},{"id":"cli/package-manager/easyp-vs-buf::easyp::13","title":"EasyP против Buf: управление пакетами","section":"EasyP: Полноценная оффлайн‑поддержка","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["EasyP: Полноценная оффлайн‑поддержка"],"excerpt":"EasyP: Полноценная оффлайн‑поддержка ```bash Среда с доступом в интернет easyp mod download # Скачивает в ~/.easyp/ easyp mod vendor # Создает easyp_vendor/","content":"EasyP: Полноценная оффлайн‑поддержка ```bash Среда с доступом в интернет easyp mod download # Скачивает в ~/.easyp/ easyp mod vendor # Создает easyp_vendor/"},{"id":"cli/package-manager/easyp-vs-buf::easyp::14","title":"EasyP против Buf: управление пакетами","section":"EasyP: Полноценная оффлайн‑поддержка","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["EasyP: Полноценная оффлайн‑поддержка"],"excerpt":"EasyP: Полноценная оффлайн‑поддержка Перенос в изолированный сегмент tar -czf easyp-deps.tar.gz ~/.easyp easyp_vendor/ ... перенос архива ...","content":"EasyP: Полноценная оффлайн‑поддержка Перенос в изолированный сегмент tar -czf easyp-deps.tar.gz ~/.easyp easyp_vendor/ ... перенос архива ..."},{"id":"cli/package-manager/easyp-vs-buf::easyp::15","title":"EasyP против Buf: управление пакетами","section":"EasyP: Полноценная оффлайн‑поддержка","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["EasyP: Полноценная оффлайн‑поддержка"],"excerpt":"EasyP: Полноценная оффлайн‑поддержка В изолированной среде tar -xzf easyp-deps.tar.gz export EASYPPATH=$PWD/.easyp easyp generate # Работает оффлайн ```","content":"EasyP: Полноценная оффлайн‑поддержка В изолированной среде tar -xzf easyp-deps.tar.gz export EASYPPATH=$PWD/.easyp easyp generate # Работает оффлайн ```"},{"id":"cli/package-manager/easyp-vs-buf::easyp::16","title":"EasyP против Buf: управление пакетами","section":"EasyP: Полноценная оффлайн‑поддержка","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["EasyP: Полноценная оффлайн‑поддержка"],"excerpt":"EasyP: Полноценная оффлайн‑поддержка **Плюсы:** ✅ Не зависит от внешних сервисов ✅ Не нужен внутренний реестр ✅ Использует существующую Git инфраструктуру ✅ Простая файловая дистрибуция","content":"EasyP: Полноценная оффлайн‑поддержка **Плюсы:** ✅ Не зависит от внешних сервисов ✅ Не нужен внутренний реестр ✅ Использует существующую Git инфраструктуру ✅ Простая файловая дистрибуция"},{"id":"cli/package-manager/easyp-vs-buf::buf::17","title":"EasyP против Buf: управление пакетами","section":"Buf: Требует инфраструктуру реестра","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf","headings":["Buf: Требует инфраструктуру реестра"],"excerpt":"Buf: Требует инфраструктуру реестра ```bash Вариант 1: использовать buf.build (нужен интернет) buf mod download","content":"Buf: Требует инфраструктуру реестра ```bash Вариант 1: использовать buf.build (нужен интернет) buf mod download"},{"id":"cli/package-manager/easyp-vs-buf::buf::18","title":"EasyP против Buf: управление пакетами","section":"Buf: Требует инфраструктуру реестра","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf","headings":["Buf: Требует инфраструктуру реестра"],"excerpt":"Buf: Требует инфраструктуру реестра Вариант 2: поднимать приватный BSR (сложно) Развернуть сервер реестра Перепубликовать все модули внутрь Настроить доступы, аутентификацию Поддерживать работоспособность ```","content":"Buf: Требует инфраструктуру реестра Вариант 2: поднимать приватный BSR (сложно) Развернуть сервер реестра Перепубликовать все модули внутрь Настроить доступы, аутентификацию Поддерживать работоспособность ```"},{"id":"cli/package-manager/easyp-vs-buf::buf::19","title":"EasyP против Buf: управление пакетами","section":"Buf: Требует инфраструктуру реестра","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf","headings":["Buf: Требует инфраструктуру реестра"],"excerpt":"Buf: Требует инфраструктуру реестра **Минусы:** ❌ Постоянный интернет или дорогой приватный BSR ❌ Сложная инфраструктура для частных установок ❌ Все модули нужно републиковать ❌ Дополнительные операционные затраты","content":"Buf: Требует инфраструктуру реестра **Минусы:** ❌ Постоянный интернет или дорогой приватный BSR ❌ Сложная инфраструктура для частных установок ❌ Все модули нужно републиковать ❌ Дополнительные операционные затраты"},{"id":"cli/package-manager/easyp-vs-buf::easyp::20","title":"EasyP против Buf: управление пакетами","section":"EasyP: Прямой контроль","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["EasyP: Прямой контроль"],"excerpt":"EasyP: Прямой контроль ```yaml Полный контроль источников deps: # Публичный репозиторий — ваша конкретная версия - github.com/googleapis/googleapis@common-protos-1_3_1","content":"EasyP: Прямой контроль ```yaml Полный контроль источников deps: # Публичный репозиторий — ваша конкретная версия - github.com/googleapis/googleapis@common-protos-1_3_1"},{"id":"cli/package-manager/easyp-vs-buf::easyp::21","title":"EasyP против Buf: управление пакетами","section":"EasyP: Прямой контроль","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["EasyP: Прямой контроль"],"excerpt":"EasyP: Прямой контроль Внутренний репозиторий - gitlab.company.com/security/validated-protos@v1.0.0","content":"EasyP: Прямой контроль Внутренний репозиторий - gitlab.company.com/security/validated-protos@v1.0.0"},{"id":"cli/package-manager/easyp-vs-buf::easyp::22","title":"EasyP против Buf: управление пакетами","section":"EasyP: Прямой контроль","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["EasyP: Прямой контроль"],"excerpt":"EasyP: Прямой контроль Точный коммит (горячий фикс) - github.com/bufbuild/protoc-gen-validate@abc123def456 ```","content":"EasyP: Прямой контроль Точный коммит (горячий фикс) - github.com/bufbuild/protoc-gen-validate@abc123def456 ```"},{"id":"cli/package-manager/easyp-vs-buf::easyp::23","title":"EasyP против Buf: управление пакетами","section":"EasyP: Прямой контроль","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["EasyP: Прямой контроль"],"excerpt":"EasyP: Прямой контроль **Преимущества по безопасности:** ✅ Нет посредника — берём из исходного репозитория ✅ Аудит через историю Git ✅ Нельзя «забанить» доступ извне ✅ Свои процессы сканирования / валидации ✅ Можно форкн","content":"EasyP: Прямой контроль **Преимущества по безопасности:** ✅ Нет посредника — берём из исходного репозитория ✅ Аудит через историю Git ✅ Нельзя «забанить» доступ извне ✅ Свои процессы сканирования / валидации ✅ Можно форкнуть и удерживать критические версии"},{"id":"cli/package-manager/easyp-vs-buf::buf::24","title":"EasyP против Buf: управление пакетами","section":"Buf: Зависимость от реестра","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf","headings":["Buf: Зависимость от реестра"],"excerpt":"Buf: Зависимость от реестра **Риски:** ⚠️ Посредник контролирует доступность ⚠️ Возможны ограничения / санкции на аккаунт ⚠️ Модуль могут удалить или депрекейтнуть ⚠️ Политики обновлений диктуются стороной ⚠️ Нужно довер","content":"Buf: Зависимость от реестра **Риски:** ⚠️ Посредник контролирует доступность ⚠️ Возможны ограничения / санкции на аккаунт ⚠️ Модуль могут удалить или депрекейтнуть ⚠️ Политики обновлений диктуются стороной ⚠️ Нужно доверять внешней безопасности"},{"id":"cli/package-manager/easyp-vs-buf::1::25","title":"EasyP против Buf: управление пакетами","section":"Сценарий 1: Стартап с публичными зависимостями","path":"/docs/guide/cli/package-manager/easyp-vs-buf#1","headings":["Сценарий 1: Стартап с публичными зависимостями"],"excerpt":"Сценарий 1: Стартап с публичными зависимостями **EasyP:**","content":"Сценарий 1: Стартап с публичными зависимостями **EasyP:**"},{"id":"cli/package-manager/easyp-vs-buf::1::26","title":"EasyP против Buf: управление пакетами","section":"Сценарий 1: Стартап с публичными зависимостями","path":"/docs/guide/cli/package-manager/easyp-vs-buf#1","headings":["Сценарий 1: Стартап с публичными зависимостями"],"excerpt":"Сценарий 1: Стартап с публичными зависимостями **Buf:**","content":"Сценарий 1: Стартап с публичными зависимостями **Buf:**"},{"id":"cli/package-manager/easyp-vs-buf::1::27","title":"EasyP против Buf: управление пакетами","section":"Сценарий 1: Стартап с публичными зависимостями","path":"/docs/guide/cli/package-manager/easyp-vs-buf#1","headings":["Сценарий 1: Стартап с публичными зависимостями"],"excerpt":"Сценарий 1: Стартап с публичными зависимостями **Итог:** Паритет — оба хорошо подходят для публичных пакетов.","content":"Сценарий 1: Стартап с публичными зависимостями **Итог:** Паритет — оба хорошо подходят для публичных пакетов."},{"id":"cli/package-manager/easyp-vs-buf::2::28","title":"EasyP против Buf: управление пакетами","section":"Сценарий 2: Компания со смешанными публичными/приватными зависимостями","path":"/docs/guide/cli/package-manager/easyp-vs-buf#2","headings":["Сценарий 2: Компания со смешанными публичными/приватными зависимостями"],"excerpt":"Сценарий 2: Компания со смешанными публичными/приватными зависимостями **EasyP:**","content":"Сценарий 2: Компания со смешанными публичными/приватными зависимостями **EasyP:**"},{"id":"cli/package-manager/easyp-vs-buf::2::29","title":"EasyP против Buf: управление пакетами","section":"Сценарий 2: Компания со смешанными публичными/приватными зависимостями","path":"/docs/guide/cli/package-manager/easyp-vs-buf#2","headings":["Сценарий 2: Компания со смешанными публичными/приватными зависимостями"],"excerpt":"Сценарий 2: Компания со смешанными публичными/приватными зависимостями **Buf:**","content":"Сценарий 2: Компания со смешанными публичными/приватными зависимостями **Buf:**"},{"id":"cli/package-manager/easyp-vs-buf::2::30","title":"EasyP против Buf: управление пакетами","section":"Сценарий 2: Компания со смешанными публичными/приватными зависимостями","path":"/docs/guide/cli/package-manager/easyp-vs-buf#2","headings":["Сценарий 2: Компания со смешанными публичными/приватными зависимостями"],"excerpt":"Сценарий 2: Компания со смешанными публичными/приватными зависимостями **Итог:** **EasyP** — не требует публикации внутрь BSR.","content":"Сценарий 2: Компания со смешанными публичными/приватными зависимостями **Итог:** **EasyP** — не требует публикации внутрь BSR."},{"id":"cli/package-manager/easyp-vs-buf::3-airgap::31","title":"EasyP против Buf: управление пакетами","section":"Сценарий 3: Государственный / оборонный подрядчик (полный air‑gap)","path":"/docs/guide/cli/package-manager/easyp-vs-buf#3-airgap","headings":["Сценарий 3: Государственный / оборонный подрядчик (полный air‑gap)"],"excerpt":"Сценарий 3: Государственный / оборонный подрядчик (полный air‑gap) **EasyP:**","content":"Сценарий 3: Государственный / оборонный подрядчик (полный air‑gap) **EasyP:**"},{"id":"cli/package-manager/easyp-vs-buf::3-airgap::32","title":"EasyP против Buf: управление пакетами","section":"Сценарий 3: Государственный / оборонный подрядчик (полный air‑gap)","path":"/docs/guide/cli/package-manager/easyp-vs-buf#3-airgap","headings":["Сценарий 3: Государственный / оборонный подрядчик (полный air‑gap)"],"excerpt":"Сценарий 3: Государственный / оборонный подрядчик (полный air‑gap) **Buf:**","content":"Сценарий 3: Государственный / оборонный подрядчик (полный air‑gap) **Buf:**"},{"id":"cli/package-manager/easyp-vs-buf::3-airgap::33","title":"EasyP против Buf: управление пакетами","section":"Сценарий 3: Государственный / оборонный подрядчик (полный air‑gap)","path":"/docs/guide/cli/package-manager/easyp-vs-buf#3-airgap","headings":["Сценарий 3: Государственный / оборонный подрядчик (полный air‑gap)"],"excerpt":"Сценарий 3: Государственный / оборонный подрядчик (полный air‑gap) **Итог:** **EasyP** — значительно проще.","content":"Сценарий 3: Государственный / оборонный подрядчик (полный air‑gap) **Итог:** **EasyP** — значительно проще."},{"id":"cli/package-manager/easyp-vs-buf::4::34","title":"EasyP против Buf: управление пакетами","section":"Сценарий 4: Комплаенс и аудит","path":"/docs/guide/cli/package-manager/easyp-vs-buf#4","headings":["Сценарий 4: Комплаенс и аудит"],"excerpt":"Сценарий 4: Комплаенс и аудит **EasyP:** ✅ Прямой аудит изменений (коммиты) ✅ Нет внешних точек зависимости в проде ✅ Повторяемость через фиксированные коммиты / vendor ✅ Управление уязвимостями — в ваших руках","content":"Сценарий 4: Комплаенс и аудит **EasyP:** ✅ Прямой аудит изменений (коммиты) ✅ Нет внешних точек зависимости в проде ✅ Повторяемость через фиксированные коммиты / vendor ✅ Управление уязвимостями — в ваших руках"},{"id":"cli/package-manager/easyp-vs-buf::4::35","title":"EasyP против Buf: управление пакетами","section":"Сценарий 4: Комплаенс и аудит","path":"/docs/guide/cli/package-manager/easyp-vs-buf#4","headings":["Сценарий 4: Комплаенс и аудит"],"excerpt":"Сценарий 4: Комплаенс и аудит **Buf:** ⚠️ Нужно учитывать BSR в области аудита ⚠️ Дополнительный риск третьей стороны ⚠️ Модули — внешние контролируемые артефакты ⚠️ Сложнее трассировать от реестра к исходникам","content":"Сценарий 4: Комплаенс и аудит **Buf:** ⚠️ Нужно учитывать BSR в области аудита ⚠️ Дополнительный риск третьей стороны ⚠️ Модули — внешние контролируемые артефакты ⚠️ Сложнее трассировать от реестра к исходникам"},{"id":"cli/package-manager/easyp-vs-buf::4::36","title":"EasyP против Buf: управление пакетами","section":"Сценарий 4: Комплаенс и аудит","path":"/docs/guide/cli/package-manager/easyp-vs-buf#4","headings":["Сценарий 4: Комплаенс и аудит"],"excerpt":"Сценарий 4: Комплаенс и аудит **Итог:** **EasyP** — проще для комплаенса.","content":"Сценарий 4: Комплаенс и аудит **Итог:** **EasyP** — проще для комплаенса."},{"id":"cli/package-manager/easyp-vs-buf::easyp::37","title":"EasyP против Buf: управление пакетами","section":"EasyP: Нулевая дополнительная инфраструктура","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["EasyP: Нулевая дополнительная инфраструктура"],"excerpt":"EasyP: Нулевая дополнительная инфраструктура **Затраты:** ✅ $0 — используете существующий Git ✅ Нет дополнительных сервисов/серверов ✅ Нет лицензирования ✅ Масштабирование в рамках Git","content":"EasyP: Нулевая дополнительная инфраструктура **Затраты:** ✅ $0 — используете существующий Git ✅ Нет дополнительных сервисов/серверов ✅ Нет лицензирования ✅ Масштабирование в рамках Git"},{"id":"cli/package-manager/easyp-vs-buf::easyp::38","title":"EasyP против Buf: управление пакетами","section":"EasyP: Нулевая дополнительная инфраструктура","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["EasyP: Нулевая дополнительная инфраструктура"],"excerpt":"EasyP: Нулевая дополнительная инфраструктура **Инфраструктура:** Использует текущие репозитории (GitHub/GitLab/и т.д.) Аутентификация — штатная Резервирование/DR — как уже настроено для Git","content":"EasyP: Нулевая дополнительная инфраструктура **Инфраструктура:** Использует текущие репозитории (GitHub/GitLab/и т.д.) Аутентификация — штатная Резервирование/DR — как уже настроено для Git"},{"id":"cli/package-manager/easyp-vs-buf::buf::39","title":"EasyP против Buf: управление пакетами","section":"Buf: Затраты на реестр","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf","headings":["Buf: Затраты на реестр"],"excerpt":"Buf: Затраты на реестр **Hosted BSR (buf.build):** ✅ Бесплатный уровень ❌ Платные тарифы для приватного и расширенного использования ❌ Потенциальные изменения ценовой политики ❌ Вопросы локализации данных","content":"Buf: Затраты на реестр **Hosted BSR (buf.build):** ✅ Бесплатный уровень ❌ Платные тарифы для приватного и расширенного использования ❌ Потенциальные изменения ценовой политики ❌ Вопросы локализации данных"},{"id":"cli/package-manager/easyp-vs-buf::buf::40","title":"EasyP против Buf: управление пакетами","section":"Buf: Затраты на реестр","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf","headings":["Buf: Затраты на реестр"],"excerpt":"Buf: Затраты на реестр **Приватный BSR:** ❌ Серверы, БД, балансировка ❌ Мониторинг, обновления, бэкапы ❌ Лицензирование enterprise функционала ❌ Доп. планирование отказоустойчивости","content":"Buf: Затраты на реестр **Приватный BSR:** ❌ Серверы, БД, балансировка ❌ Мониторинг, обновления, бэкапы ❌ Лицензирование enterprise функционала ❌ Доп. планирование отказоустойчивости"},{"id":"cli/package-manager/easyp-vs-buf::easyp::41","title":"EasyP против Buf: управление пакетами","section":"EasyP: Нет привязки","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["EasyP: Нет привязки"],"excerpt":"EasyP: Нет привязки **Миграция ИЗ EasyP:** (Обычные Git ссылки — легко перенести в другой инструмент.)","content":"EasyP: Нет привязки **Миграция ИЗ EasyP:** (Обычные Git ссылки — легко перенести в другой инструмент.)"},{"id":"cli/package-manager/easyp-vs-buf::easyp::42","title":"EasyP против Buf: управление пакетами","section":"EasyP: Нет привязки","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["EasyP: Нет привязки"],"excerpt":"EasyP: Нет привязки **Миграция В EasyP:**","content":"EasyP: Нет привязки **Миграция В EasyP:**"},{"id":"cli/package-manager/easyp-vs-buf::buf-lockin::43","title":"EasyP против Buf: управление пакетами","section":"Buf: Потенциальный lock‑in","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf-lockin","headings":["Buf: Потенциальный lock‑in"],"excerpt":"Buf: Потенциальный lock‑in **Миграция ИЗ Buf:** ❌ Нужно сопоставить BSR модули с исходными Git репо ❌ Имена модулей BSR не совпадают с URL ❌ Возможна потеря удобных метаданных ❌ Сложно при глубокой интеграции с BSR","content":"Buf: Потенциальный lock‑in **Миграция ИЗ Buf:** ❌ Нужно сопоставить BSR модули с исходными Git репо ❌ Имена модулей BSR не совпадают с URL ❌ Возможна потеря удобных метаданных ❌ Сложно при глубокой интеграции с BSR"},{"id":"cli/package-manager/easyp-vs-buf::buf-lockin::44","title":"EasyP против Buf: управление пакетами","section":"Buf: Потенциальный lock‑in","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf-lockin","headings":["Buf: Потенциальный lock‑in"],"excerpt":"Buf: Потенциальный lock‑in **Миграция В Buf:** ❌ Нужно опубликовать всё в BSR ❌ Нельзя ссылаться напрямую на Git ❌ Принять workflow BSR (push/pull модулей)","content":"Buf: Потенциальный lock‑in **Миграция В Buf:** ❌ Нужно опубликовать всё в BSR ❌ Нельзя ссылаться напрямую на Git ❌ Принять workflow BSR (push/pull модулей)"},{"id":"cli/package-manager/easyp-vs-buf::easyp::45","title":"EasyP против Buf: управление пакетами","section":"Выберите EasyP, если:","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["Выберите EasyP, если:"],"excerpt":"Выберите EasyP, если: ✅ **Air‑gapped / закрытые среды** Нужна работа без внешних сервисов Строгий комплаенс / контроль цепочки поставок","content":"Выберите EasyP, если: ✅ **Air‑gapped / закрытые среды** Нужна работа без внешних сервисов Строгий комплаенс / контроль цепочки поставок"},{"id":"cli/package-manager/easyp-vs-buf::easyp::46","title":"EasyP против Buf: управление пакетами","section":"Выберите EasyP, если:","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["Выберите EasyP, если:"],"excerpt":"Выберите EasyP, если: ✅ **Фокус на безопасности** Контроль источников зависимостей Минимизация рисков третьих сторон","content":"Выберите EasyP, если: ✅ **Фокус на безопасности** Контроль источников зависимостей Минимизация рисков третьих сторон"},{"id":"cli/package-manager/easyp-vs-buf::easyp::47","title":"EasyP против Buf: управление пакетами","section":"Выберите EasyP, если:","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["Выберите EasyP, если:"],"excerpt":"Выберите EasyP, если: ✅ **Git‑центричная культура** Частные репозитории — норма Не хотите добавлять новый ключевой сервис","content":"Выберите EasyP, если: ✅ **Git‑центричная культура** Частные репозитории — норма Не хотите добавлять новый ключевой сервис"},{"id":"cli/package-manager/easyp-vs-buf::easyp::48","title":"EasyP против Buf: управление пакетами","section":"Выберите EasyP, если:","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["Выберите EasyP, если:"],"excerpt":"Выберите EasyP, если: ✅ **Ограниченный бюджет** Минимизация операционных расходов Предсказуемая стоимость = 0","content":"Выберите EasyP, если: ✅ **Ограниченный бюджет** Минимизация операционных расходов Предсказуемая стоимость = 0"},{"id":"cli/package-manager/easyp-vs-buf::easyp::49","title":"EasyP против Buf: управление пакетами","section":"Выберите EasyP, если:","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["Выберите EasyP, если:"],"excerpt":"Выберите EasyP, если: ✅ **Смешанные публичные/частные зависимости** Не хотите перекладывать всё в реестр Нужна гибкость форматов и размещения","content":"Выберите EasyP, если: ✅ **Смешанные публичные/частные зависимости** Не хотите перекладывать всё в реестр Нужна гибкость форматов и размещения"},{"id":"cli/package-manager/easyp-vs-buf::buf::50","title":"EasyP против Buf: управление пакетами","section":"Выберите Buf, если:","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf","headings":["Выберите Buf, если:"],"excerpt":"Выберите Buf, если: ✅ **Глубокая интеграция в экосистему BSR** Уже используете линтеры / генерацию Buf Нужны курируемые официальные модули Важны метаданные и граф зависимостей","content":"Выберите Buf, если: ✅ **Глубокая интеграция в экосистему BSR** Уже используете линтеры / генерацию Buf Нужны курируемые официальные модули Важны метаданные и граф зависимостей"},{"id":"cli/package-manager/easyp-vs-buf::buf::51","title":"EasyP против Buf: управление пакетами","section":"Выберите Buf, если:","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf","headings":["Выберите Buf, если:"],"excerpt":"Выберите Buf, если: ✅ **Сотрудничество и открытая разработка** Централизованное обнаружение модулей Совместная работа над общими пакетами","content":"Выберите Buf, если: ✅ **Сотрудничество и открытая разработка** Централизованное обнаружение модулей Совместная работа над общими пакетами"},{"id":"cli/package-manager/easyp-vs-buf::buf::52","title":"EasyP против Buf: управление пакетами","section":"Выберите Buf, если:","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf","headings":["Выберите Buf, если:"],"excerpt":"Выберите Buf, если: ✅ **Команда новичков в protobuf** Требуется «направляющая» структура Ценность документации внутри реестра","content":"Выберите Buf, если: ✅ **Команда новичков в protobuf** Требуется «направляющая» структура Ценность документации внутри реестра"},{"id":"cli/package-manager/easyp-vs-buf::buf::53","title":"EasyP против Buf: управление пакетами","section":"Выберите Buf, если:","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf","headings":["Выберите Buf, если:"],"excerpt":"Выберите Buf, если: ✅ **Небольшой набор публичных зависимостей** В основном используете популярные общие пакеты Вас устраивает зависимость от BSR","content":"Выберите Buf, если: ✅ **Небольшой набор публичных зависимостей** В основном используете популярные общие пакеты Вас устраивает зависимость от BSR"},{"id":"cli/package-manager/easyp-vs-buf::buf-easyp::54","title":"EasyP против Buf: управление пакетами","section":"Переход с Buf на EasyP","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf-easyp","headings":["Переход с Buf на EasyP"],"excerpt":"Переход с Buf на EasyP Найдите исходные Git репозитории для каждого модуля BSR Сопоставьте имена BSR → Git ссылки (с версиями/тегами) Обновите конфигурацию (easyp.yaml) Протестируйте генерацию и совместимость","content":"Переход с Buf на EasyP Найдите исходные Git репозитории для каждого модуля BSR Сопоставьте имена BSR → Git ссылки (с версиями/тегами) Обновите конфигурацию (easyp.yaml) Протестируйте генерацию и совместимость"},{"id":"cli/package-manager/easyp-vs-buf::buf-easyp::55","title":"EasyP против Buf: управление пакетами","section":"Переход с Buf на EasyP","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf-easyp","headings":["Переход с Buf на EasyP"],"excerpt":"Переход с Buf на EasyP ```yaml Было (buf.yaml) deps: - buf.build/googleapis/googleapis - buf.build/grpc/grpc","content":"Переход с Buf на EasyP ```yaml Было (buf.yaml) deps: - buf.build/googleapis/googleapis - buf.build/grpc/grpc"},{"id":"cli/package-manager/easyp-vs-buf::buf-easyp::56","title":"EasyP против Buf: управление пакетами","section":"Переход с Buf на EasyP","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf-easyp","headings":["Переход с Buf на EasyP"],"excerpt":"Переход с Buf на EasyP Стало (easyp.yaml) deps: - github.com/googleapis/googleapis@common-protos-1_3_1 - github.com/grpc/grpc@v1.50.0 ```","content":"Переход с Buf на EasyP Стало (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::easyp-buf::57","title":"EasyP против Buf: управление пакетами","section":"Переход с EasyP на Buf","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp-buf","headings":["Переход с EasyP на Buf"],"excerpt":"Переход с EasyP на Buf Опубликуйте используемые репозитории как модули BSR Настройте аутентификацию / организацию Buf Замените Git ссылки на BSR модули Перейдите к push/pull workflow Buf","content":"Переход с EasyP на Buf Опубликуйте используемые репозитории как модули BSR Настройте аутентификацию / организацию Buf Замените Git ссылки на BSR модули Перейдите к push/pull workflow Buf"},{"id":"cli/package-manager/easyp-vs-buf::top::58","title":"EasyP против Buf: управление пакетами","section":"Заключение","path":"/docs/guide/cli/package-manager/easyp-vs-buf","headings":["Заключение"],"excerpt":"Заключение Оба инструмента решают задачу управления зависимостями protobuf, но подходят под разные приоритеты:","content":"Заключение Оба инструмента решают задачу управления зависимостями protobuf, но подходят под разные приоритеты:"},{"id":"cli/package-manager/easyp-vs-buf::top::59","title":"EasyP против Buf: управление пакетами","section":"Заключение","path":"/docs/guide/cli/package-manager/easyp-vs-buf","headings":["Заключение"],"excerpt":"Заключение **Сильные стороны EasyP:** Корпоративные / изолированные среды Жёсткие требования безопасности и аудита Минимальные затраты и отсутствие доп. инфраструктуры Прямое использование Git (без промежуточного слоя) П","content":"Заключение **Сильные стороны EasyP:** Корпоративные / изолированные среды Жёсткие требования безопасности и аудита Минимальные затраты и отсутствие доп. инфраструктуры Прямое использование Git (без промежуточного слоя) Простота масштабирования"},{"id":"cli/package-manager/easyp-vs-buf::top::60","title":"EasyP против Buf: управление пакетами","section":"Заключение","path":"/docs/guide/cli/package-manager/easyp-vs-buf","headings":["Заключение"],"excerpt":"Заключение **Сильные стороны Buf:** Богатая экосистема вокруг реестра Курируемые и документированные модули Удобство для новых команд в protobuf Средства визуализации и централизованного обмена","content":"Заключение **Сильные стороны Buf:** Богатая экосистема вокруг реестра Курируемые и документированные модули Удобство для новых команд в protobuf Средства визуализации и централизованного обмена"},{"id":"cli/package-manager/easyp-vs-buf::top::61","title":"EasyP против Buf: управление пакетами","section":"Заключение","path":"/docs/guide/cli/package-manager/easyp-vs-buf","headings":["Заключение"],"excerpt":"Заключение Выбор часто сводится к балансу между **контролем vs. удобством**, **безопасностью vs. централизованными функциями**, и **стоимостью vs. managed‑сервисом**.","content":"Заключение Выбор часто сводится к балансу между **контролем vs. удобством**, **безопасностью vs. централизованными функциями**, и **стоимостью vs. managed‑сервисом**."},{"id":"cli/package-manager/easyp-vs-buf::top::62","title":"EasyP против Buf: управление пакетами","section":"Заключение","path":"/docs/guide/cli/package-manager/easyp-vs-buf","headings":["Заключение"],"excerpt":"Заключение Для большинства enterprise‑окружений децентрализованный Git‑подход EasyP обеспечивает нужные гибкость, безопасность и предсказуемость расходов, тогда как Buf отлично подходит командам, которым важна централизо","content":"Заключение Для большинства enterprise‑окружений децентрализованный Git‑подход EasyP обеспечивает нужные гибкость, безопасность и предсказуемость расходов, тогда как Buf отлично подходит командам, которым важна централизованная коллаборация и богатая экосистема вокруг реестра."},{"id":"cli/package-manager/package-manager::top::0","title":"Менеджер пакетов","path":"/docs/guide/cli/package-manager/package-manager","headings":[],"excerpt":"EasyP предоставляет мощный менеджер пакетов для protobuf‑зависимостей, упрощающий их управление за счёт децентрализованного подхода на базе Git. В отличие от централизованных решений, EasyP работает напрямую с Git‑репози","content":"EasyP предоставляет мощный менеджер пакетов для protobuf‑зависимостей, упрощающий их управление за счёт децентрализованного подхода на базе Git. В отличие от централизованных решений, EasyP работает напрямую с Git‑репозиториями, давая вам полный контроль."},{"id":"cli/package-manager/package-manager::top::1","title":"Менеджер пакетов","section":"Обзор","path":"/docs/guide/cli/package-manager/package-manager","headings":["Обзор"],"excerpt":"Обзор Менеджер пакетов EasyP следует философии **Go modules** — любой Git‑репозиторий может быть источником. Это даёт преимущества:","content":"Обзор Менеджер пакетов EasyP следует философии **Go modules** — любой Git‑репозиторий может быть источником. Это даёт преимущества:"},{"id":"cli/package-manager/package-manager::top::2","title":"Менеджер пакетов","section":"Обзор","path":"/docs/guide/cli/package-manager/package-manager","headings":["Обзор"],"excerpt":"Обзор **Децентрализация** — нет единой точки отказа или контроля **Безопасность** — прямой доступ к исходникам **Гибкость** — публичные, приватные и корпоративные репозитории **Воспроизводимость** — lock‑файлы обеспечива","content":"Обзор **Децентрализация** — нет единой точки отказа или контроля **Безопасность** — прямой доступ к исходникам **Гибкость** — публичные, приватные и корпоративные репозитории **Воспроизводимость** — lock‑файлы обеспечивают одинаковые сборки **Производительность** — локальный кеш сокращает сетевые запросы"},{"id":"cli/package-manager/package-manager::top::3","title":"Менеджер пакетов","section":"Основные возможности","path":"/docs/guide/cli/package-manager/package-manager","headings":["Основные возможности"],"excerpt":"Основные возможности Возможность Описание ------------- ---------- **Git-Native** Любой Git репозиторий, не нужен спец‑сервер **Множество форматов версий** Теги, коммиты, псевдо‑версии, latest **Lock Files** Воспроизводи","content":"Основные возможности Возможность Описание ------------- ---------- **Git-Native** Любой Git репозиторий, не нужен спец‑сервер **Множество форматов версий** Теги, коммиты, псевдо‑версии, latest **Lock Files** Воспроизводимые сборки через easyp.lock **Локальный кеш** Архитектура как у Go modules **Vendoring** Локальное копирование для оффлайн сборок **YAML конфигурация** Простые и читаемые декларации"},{"id":"cli/package-manager/package-manager::top::4","title":"Менеджер пакетов","section":"Архитектура","path":"/docs/guide/cli/package-manager/package-manager","headings":["Архитектура"],"excerpt":"Архитектура EasyP использует двухуровневый кеш, вдохновлённый Go modules:","content":"Архитектура EasyP использует двухуровневый кеш, вдохновлённый Go modules:"},{"id":"cli/package-manager/package-manager::top::5","title":"Менеджер пакетов","section":"Расположение кеша","path":"/docs/guide/cli/package-manager/package-manager","headings":["Расположение кеша"],"excerpt":"Расположение кеша Окружение Путь Как задать ----------- ------ ----------- **По умолчанию** $HOME/.easyp Автоматически **Свое** Любая директория Переменная EASYPPATH **CI/CD** В каталоге проекта export EASYPPATH=$CI_PROJ","content":"Расположение кеша Окружение Путь Как задать ----------- ------ ----------- **По умолчанию** $HOME/.easyp Автоматически **Свое** Любая директория Переменная EASYPPATH **CI/CD** В каталоге проекта export EASYPPATH=$CI_PROJECT_DIR/.easyp"},{"id":"cli/package-manager/package-manager::top::6","title":"Менеджер пакетов","section":"Базовая конфигурация","path":"/docs/guide/cli/package-manager/package-manager","headings":["Базовая конфигурация"],"excerpt":"Базовая конфигурация Зависимости описываются в easyp.yaml:","content":"Базовая конфигурация Зависимости описываются в easyp.yaml:"},{"id":"cli/package-manager/package-manager::multi-environment-setup::7","title":"Менеджер пакетов","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 # Последнее для разработки - github.com/mycompany/internal-protos # Внутренние изменения - github.com/bufbuild/protoc-gen-va","content":"Multi-Environment Setup ```yaml development.easyp.yaml deps: - github.com/googleapis/googleapis # Последнее для разработки - github.com/mycompany/internal-protos # Внутренние изменения - github.com/bufbuild/protoc-gen-validate # Новые фичи"},{"id":"cli/package-manager/package-manager::multi-environment-setup::8","title":"Менеджер пакетов","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 # Зафиксировано - github.com/mycompany/internal-protos@v2.1.0 # Стабильно - github.com/bufbuild/protoc-gen-valida","content":"Multi-Environment Setup production.easyp.yaml deps: - github.com/googleapis/googleapis@common-protos-1_3_1 # Зафиксировано - github.com/mycompany/internal-protos@v2.1.0 # Стабильно - github.com/bufbuild/protoc-gen-validate@v0.10.1 # Проверено ```"},{"id":"cli/package-manager/package-manager::top::9","title":"Менеджер пакетов","section":"Приватные репозитории","path":"/docs/guide/cli/package-manager/package-manager","headings":["Приватные репозитории"],"excerpt":"Приватные репозитории ```yaml deps: # Публичное - github.com/googleapis/googleapis@common-protos-1_3_1","content":"Приватные репозитории ```yaml deps: # Публичное - github.com/googleapis/googleapis@common-protos-1_3_1"},{"id":"cli/package-manager/package-manager::top::10","title":"Менеджер пакетов","section":"Приватные репозитории","path":"/docs/guide/cli/package-manager/package-manager","headings":["Приватные репозитории"],"excerpt":"Приватные репозитории Частные - github.com/mycompany/auth-protos@v1.5.0 - github.com/mycompany/common-types@v2.0.1","content":"Приватные репозитории Частные - github.com/mycompany/auth-protos@v1.5.0 - github.com/mycompany/common-types@v2.0.1"},{"id":"cli/package-manager/package-manager::top::11","title":"Менеджер пакетов","section":"Приватные репозитории","path":"/docs/guide/cli/package-manager/package-manager","headings":["Приватные репозитории"],"excerpt":"Приватные репозитории Внутренний GitLab - gitlab.company.com/platform/messaging-protos@v0.3.0 ```","content":"Приватные репозитории Внутренний GitLab - gitlab.company.com/platform/messaging-protos@v0.3.0 ```"},{"id":"cli/package-manager/package-manager::top::12","title":"Менеджер пакетов","section":"Стратегии версионирования","path":"/docs/guide/cli/package-manager/package-manager","headings":["Стратегии версионирования"],"excerpt":"Стратегии версионирования Поддерживаются разные способы фиксации версий:","content":"Стратегии версионирования Поддерживаются разные способы фиксации версий:"},{"id":"cli/package-manager/package-manager::1::13","title":"Менеджер пакетов","section":"1. Семантические теги (для продакшена)","path":"/docs/guide/cli/package-manager/package-manager#1","headings":["1. Семантические теги (для продакшена)"],"excerpt":"Семантические теги (для продакшена)","content":"Семантические теги (для продакшена)"},{"id":"cli/package-manager/package-manager::1::14","title":"Менеджер пакетов","section":"1. Семантические теги (для продакшена)","path":"/docs/guide/cli/package-manager/package-manager#1","headings":["1. Семантические теги (для продакшена)"],"excerpt":"Семантические теги (для продакшена) **Используйте когда:** Продакшен Стабильное потребление API Нужна воспроизводимость","content":"Семантические теги (для продакшена) **Используйте когда:** Продакшен Стабильное потребление API Нужна воспроизводимость"},{"id":"cli/package-manager/package-manager::2-development::15","title":"Менеджер пакетов","section":"2. Последний тег (development)","path":"/docs/guide/cli/package-manager/package-manager#2-development","headings":["2. Последний тег (development)"],"excerpt":"Последний тег (development) **Подходит для:** Активной разработки Получения свежих возможностей Тестирования совместимости","content":"Последний тег (development) **Подходит для:** Активной разработки Получения свежих возможностей Тестирования совместимости"},{"id":"cli/package-manager/package-manager::3-bleeding-edge::16","title":"Менеджер пакетов","section":"3. Хеш коммита (Bleeding Edge)","path":"/docs/guide/cli/package-manager/package-manager#3-bleeding-edge","headings":["3. Хеш коммита (Bleeding Edge)"],"excerpt":"Хеш коммита (Bleeding Edge) **Когда нужно:** Нерелизные фичи Тест конкретного фикса Вклад в upstream","content":"Хеш коммита (Bleeding Edge) **Когда нужно:** Нерелизные фичи Тест конкретного фикса Вклад в upstream"},{"id":"cli/package-manager/package-manager::4::17","title":"Менеджер пакетов","section":"4. Псевдо‑версии (автоматически)","path":"/docs/guide/cli/package-manager/package-manager#4","headings":["4. Псевдо‑версии (автоматически)"],"excerpt":"Псевдо‑версии (автоматически) Если нет подходящего тега — создаётся псевдо‑версия:","content":"Псевдо‑версии (автоматически) Если нет подходящего тега — создаётся псевдо‑версия:"},{"id":"cli/package-manager/package-manager::easyp-mod-download::18","title":"Менеджер пакетов","section":"easyp mod download","path":"/docs/guide/cli/package-manager/package-manager#easyp-mod-download","headings":["easyp mod download"],"excerpt":"easyp mod download Скачивает и устанавливает все объявленные зависимости.","content":"easyp mod download Скачивает и устанавливает все объявленные зависимости."},{"id":"cli/package-manager/package-manager::easyp-mod-download::19","title":"Менеджер пакетов","section":"easyp mod download","path":"/docs/guide/cli/package-manager/package-manager#easyp-mod-download","headings":["easyp mod download"],"excerpt":"easyp mod download **Что делает:** Разрешает версии (теги → коммиты) Скачивает архивы в cache/download Проверяет контрольные суммы Распаковывает в cache/mod Обновляет easyp.lock","content":"easyp mod download **Что делает:** Разрешает версии (теги → коммиты) Скачивает архивы в cache/download Проверяет контрольные суммы Распаковывает в cache/mod Обновляет easyp.lock"},{"id":"cli/package-manager/package-manager::easyp-mod-download::20","title":"Менеджер пакетов","section":"easyp mod download","path":"/docs/guide/cli/package-manager/package-manager#easyp-mod-download","headings":["easyp mod download"],"excerpt":"easyp mod download **Пример:**","content":"easyp mod download **Пример:**"},{"id":"cli/package-manager/package-manager::easyp-mod-vendor::21","title":"Менеджер пакетов","section":"easyp mod vendor","path":"/docs/guide/cli/package-manager/package-manager#easyp-mod-vendor","headings":["easyp mod vendor"],"excerpt":"easyp mod vendor Копирует все proto зависимости в локальный easyp_vendor/ для оффлайна.","content":"easyp mod vendor Копирует все proto зависимости в локальный easyp_vendor/ для оффлайна."},{"id":"cli/package-manager/package-manager::easyp-mod-vendor::22","title":"Менеджер пакетов","section":"easyp mod vendor","path":"/docs/guide/cli/package-manager/package-manager#easyp-mod-vendor","headings":["easyp mod vendor"],"excerpt":"easyp mod vendor **Сценарии:** Docker сборки Air-gapped окружения Воспроизводимость Ускорение","content":"easyp mod vendor **Сценарии:** Docker сборки Air-gapped окружения Воспроизводимость Ускорение"},{"id":"cli/package-manager/package-manager::easyp-mod-update::23","title":"Менеджер пакетов","section":"easyp mod update","path":"/docs/guide/cli/package-manager/package-manager#easyp-mod-update","headings":["easyp mod update"],"excerpt":"easyp mod update Обновляет версии согласно easyp.yaml, пересоздаёт lock.","content":"easyp mod update Обновляет версии согласно easyp.yaml, пересоздаёт lock."},{"id":"cli/package-manager/package-manager::lock::24","title":"Менеджер пакетов","section":"Lock файл","path":"/docs/guide/cli/package-manager/package-manager#lock","headings":["Lock файл"],"excerpt":"Lock файл easyp.lock фиксирует точные версии и хеш содержимого:","content":"Lock файл easyp.lock фиксирует точные версии и хеш содержимого:"},{"id":"cli/package-manager/package-manager::lock::25","title":"Менеджер пакетов","section":"Lock файл","path":"/docs/guide/cli/package-manager/package-manager#lock","headings":["Lock файл"],"excerpt":"Lock файл **Формат строки:** Путь модуля Версия (тег или псевдо) Хеш содержимого (h1:)","content":"Lock файл **Формат строки:** Путь модуля Версия (тег или псевдо) Хеш содержимого (h1:)"},{"id":"cli/package-manager/package-manager::lock::26","title":"Менеджер пакетов","section":"Lock файл","path":"/docs/guide/cli/package-manager/package-manager#lock","headings":["Lock файл"],"excerpt":"Lock файл **Практики:** ✅ Коммитить easyp.lock ✅ Осознанно обновлять mod update ✅ Ревью изменений версий ❌ Не редактировать вручную","content":"Lock файл **Практики:** ✅ Коммитить easyp.lock ✅ Осознанно обновлять mod update ✅ Ревью изменений версий ❌ Не редактировать вручную"},{"id":"cli/package-manager/package-manager::top::27","title":"Менеджер пакетов","section":"Публичные репозитории","path":"/docs/guide/cli/package-manager/package-manager","headings":["Публичные репозитории"],"excerpt":"Публичные репозитории Работают без настроек:","content":"Публичные репозитории Работают без настроек:"},{"id":"cli/package-manager/package-manager::ssh::28","title":"Менеджер пакетов","section":"SSH ключи (рекомендуется)","path":"/docs/guide/cli/package-manager/package-manager#ssh","headings":["SSH ключи (рекомендуется)"],"excerpt":"SSH ключи (рекомендуется) Конфиг остаётся с HTTPS URL:","content":"SSH ключи (рекомендуется) Конфиг остаётся с HTTPS URL:"},{"id":"cli/package-manager/package-manager::personal-access-tokens::29","title":"Менеджер пакетов","section":"Personal Access Tokens","path":"/docs/guide/cli/package-manager/package-manager#personal-access-tokens","headings":["Personal Access Tokens"],"excerpt":"Personal Access Tokens ```bash git config --global credential.helper store echo \"https://username:token@github.com\" >> ~/.git-credentials","content":"Personal Access Tokens ```bash git config --global credential.helper store echo \"https://username:token@github.com\" >> ~/.git-credentials"},{"id":"cli/package-manager/package-manager::personal-access-tokens::30","title":"Менеджер пакетов","section":"Personal Access Tokens","path":"/docs/guide/cli/package-manager/package-manager#personal-access-tokens","headings":["Personal Access Tokens"],"excerpt":"Personal Access Tokens git config --global url.\"https://username:token@github.com/mycompany\".insteadOf \"https://github.com/mycompany\" ```","content":"Personal Access Tokens git config --global url.\"https://username:token@github.com/mycompany\".insteadOf \"https://github.com/mycompany\" ```"},{"id":"cli/package-manager/package-manager::top::31","title":"Менеджер пакетов","section":"Инициализация проекта","path":"/docs/guide/cli/package-manager/package-manager","headings":["Инициализация проекта"],"excerpt":"Инициализация проекта ```bash cat > easyp.yaml << EOF deps: - github.com/googleapis/googleapis - github.com/grpc-ecosystem/grpc-gateway@v2.19.1 EOF","content":"Инициализация проекта ```bash 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::top::32","title":"Менеджер пакетов","section":"Инициализация проекта","path":"/docs/guide/cli/package-manager/package-manager","headings":["Инициализация проекта"],"excerpt":"Инициализация проекта easyp mod download ls ~/.easyp/mod/github.com/googleapis/googleapis/ ```","content":"Инициализация проекта easyp mod download ls ~/.easyp/mod/github.com/googleapis/googleapis/ ```"},{"id":"cli/package-manager/package-manager::repository-not-found-authentication-failed::33","title":"Менеджер пакетов","section":"\"Repository not found\" / \"Authentication failed\"","path":"/docs/guide/cli/package-manager/package-manager#repository-not-found-authentication-failed","headings":["\"Repository not found\" / \"Authentication failed\""],"excerpt":"\"Repository not found\" / \"Authentication failed\"","content":"\"Repository not found\" / \"Authentication failed\""},{"id":"cli/package-manager/package-manager::cache-corruption-checksum-mismatch::34","title":"Менеджер пакетов","section":"\"Cache corruption\" / \"Checksum mismatch\"","path":"/docs/guide/cli/package-manager/package-manager#cache-corruption-checksum-mismatch","headings":["\"Cache corruption\" / \"Checksum mismatch\""],"excerpt":"\"Cache corruption\" / \"Checksum mismatch\"","content":"\"Cache corruption\" / \"Checksum mismatch\""},{"id":"cli/package-manager/package-manager::docker-multi-stage::35","title":"Менеджер пакетов","section":"Docker multi-stage","path":"/docs/guide/cli/package-manager/package-manager#docker-multi-stage","headings":["Docker multi-stage"],"excerpt":"Docker multi-stage ```dockerfile FROM ghcr.io/easyp-tech/easyp:latest AS deps WORKDIR /workspace COPY easyp.yaml easyp.lock ./ RUN easyp mod vendor","content":"Docker multi-stage ```dockerfile 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::36","title":"Менеджер пакетов","section":"Docker multi-stage","path":"/docs/guide/cli/package-manager/package-manager#docker-multi-stage","headings":["Docker multi-stage"],"excerpt":"Docker multi-stage FROM alpine:latest AS build WORKDIR /app COPY --from=deps /workspace/easyp_vendor ./easyp_vendor COPY . . RUN easyp generate ```","content":"Docker multi-stage FROM alpine:latest AS build WORKDIR /app COPY --from=deps /workspace/easyp_vendor ./easyp_vendor COPY . . RUN easyp generate ```"},{"id":"cli/package-manager/package-manager::monorepo::37","title":"Менеджер пакетов","section":"Monorepo","path":"/docs/guide/cli/package-manager/package-manager#monorepo","headings":["Monorepo"],"excerpt":"Monorepo Каждый easyp.yaml может иметь свой набор зависимостей.","content":"Monorepo Каждый easyp.yaml может иметь свой набор зависимостей."},{"id":"cli/package-manager/package-manager::workflow::38","title":"Менеджер пакетов","section":"Workflow разработки","path":"/docs/guide/cli/package-manager/package-manager#workflow","headings":["Workflow разработки"],"excerpt":"Workflow разработки ✅ Latest теги в активной разработке ✅ Фиксация версий в продакшене ✅ Коммит lock файла ✅ Ревью обновлений ✅ Тест после обновления","content":"Workflow разработки ✅ Latest теги в активной разработке ✅ Фиксация версий в продакшене ✅ Коммит lock файла ✅ Ревью обновлений ✅ Тест после обновления"},{"id":"cli/package-manager/package-manager::top::39","title":"Менеджер пакетов","section":"Безопасность","path":"/docs/guide/cli/package-manager/package-manager","headings":["Безопасность"],"excerpt":"Безопасность ✅ Фиксируйте версии ✅ Используйте SSH ключи ✅ Оценивайте новые зависимости ✅ Следите за уязвимостями ❌ Не храните секреты в конфиге","content":"Безопасность ✅ Фиксируйте версии ✅ Используйте SSH ключи ✅ Оценивайте новые зависимости ✅ Следите за уязвимостями ❌ Не храните секреты в конфиге"},{"id":"cli/package-manager/package-manager::top::40","title":"Менеджер пакетов","section":"Производительность","path":"/docs/guide/cli/package-manager/package-manager","headings":["Производительность"],"excerpt":"Производительность ✅ Агрессивное кеширование в CI ✅ Vendoring для частых сборок ✅ Чистка старого кеша ✅ Общий кеш для команды","content":"Производительность ✅ Агрессивное кеширование в CI ✅ Vendoring для частых сборок ✅ Чистка старого кеша ✅ Общий кеш для команды"},{"id":"cli/package-manager/package-manager::top::41","title":"Менеджер пакетов","section":"Командная работа","path":"/docs/guide/cli/package-manager/package-manager","headings":["Командная работа"],"excerpt":"Командная работа ✅ Документация по аутентификации ✅ Единые инструменты ✅ Автоматизация обновлений с тестами ✅ Общий кеш при возможности","content":"Командная работа ✅ Документация по аутентификации ✅ Единые инструменты ✅ Автоматизация обновлений с тестами ✅ Общий кеш при возможности"},{"id":"cli/package-manager/package-manager::top::42","title":"Менеджер пакетов","section":"Командная работа","path":"/docs/guide/cli/package-manager/package-manager","headings":["Командная работа"],"excerpt":"Командная работа Менеджер пакетов EasyP — масштабируемое децентрализованное решение от одиночных проектов до enterprise, сохраняя простоту и надёжность.","content":"Командная работа Менеджер пакетов EasyP — масштабируемое децентрализованное решение от одиночных проектов до enterprise, сохраняя простоту и надёжность."},{"id":"introduction/install::top::0","title":"Установка EasyP CLI","section":"Установка через менеджер пакетов системы","path":"/docs/guide/introduction/install","headings":["Установка через менеджер пакетов системы"],"excerpt":"Установка через менеджер пакетов системы","content":"Установка через менеджер пакетов системы"},{"id":"introduction/install::top::1","title":"Установка EasyP CLI","section":"Рекомендуемый способ установки","path":"/docs/guide/introduction/install","headings":["Рекомендуемый способ установки"],"excerpt":"Рекомендуемый способ установки","content":"Рекомендуемый способ установки"},{"id":"introduction/install::homebrew::2","title":"Установка EasyP CLI","section":"Homebrew","path":"/docs/guide/introduction/install#homebrew","headings":["Homebrew"],"excerpt":"Homebrew Можно установить бинарный релиз в macOS через Homebrew:","content":"Homebrew Можно установить бинарный релиз в macOS через Homebrew:"},{"id":"introduction/install::homebrew::3","title":"Установка EasyP CLI","section":"Homebrew","path":"/docs/guide/introduction/install#homebrew","headings":["Homebrew"],"excerpt":"Homebrew Work in progress — поддержка других менеджеров (apt, yum, pacman и т.д.) в процессе.","content":"Homebrew Work in progress — поддержка других менеджеров (apt, yum, pacman и т.д.) в процессе."},{"id":"introduction/install::_-_::4","title":"Установка EasyP CLI","section":"_Не рекомендуется_","path":"/docs/guide/introduction/install#_-_","headings":["_Не рекомендуется_"],"excerpt":"_Не рекомендуется_ Локальная установка менее предпочтительна, потому что пакетные менеджеры обеспечивают: Автоматические обновления и патчи безопасности Лучшую интеграцию с системой Упрощённую установку и удаление Подпис","content":"_Не рекомендуется_ Локальная установка менее предпочтительна, потому что пакетные менеджеры обеспечивают: Автоматические обновления и патчи безопасности Лучшую интеграцию с системой Упрощённую установку и удаление Подписанные и проверенные бинарники"},{"id":"introduction/install::go-install::5","title":"Установка EasyP CLI","section":"Установка через go install","path":"/docs/guide/introduction/install#go-install","headings":["Установка через go install"],"excerpt":"Установка через go install Команда установит последнюю стабильную версию easyp:","content":"Установка через go install Команда установит последнюю стабильную версию easyp:"},{"id":"introduction/install::top::6","title":"Установка EasyP CLI","section":"Сборка из исходников","path":"/docs/guide/introduction/install","headings":["Сборка из исходников"],"excerpt":"Сборка из исходников Клонирование репозитория","content":"Сборка из исходников Клонирование репозитория"},{"id":"introduction/install::top::7","title":"Установка EasyP CLI","section":"Сборка из исходников","path":"/docs/guide/introduction/install","headings":["Сборка из исходников"],"excerpt":"Сборка из исходников Сборка с помощью Go","content":"Сборка из исходников Сборка с помощью Go"},{"id":"introduction/quickstart::top::0","title":"Быстрый старт (Quickstart)","path":"/docs/guide/introduction/quickstart","headings":[],"excerpt":"EasyP — современный toolkit для работы с файлами Protobuf. В этом кратком руководстве вы научитесь:","content":"EasyP — современный toolkit для работы с файлами Protobuf. В этом кратком руководстве вы научитесь:"},{"id":"introduction/quickstart::top::1","title":"Быстрый старт (Quickstart)","path":"/docs/guide/introduction/quickstart","headings":[],"excerpt":"**Инициализировать** проект с конфигурацией EasyP **Настраивать линтинг**, чтобы ловить ошибки и соблюдать лучшие практики **Управлять зависимостями** из Git‑репозиториев **Генерировать код** из ваших Protobuf файлов","content":"**Инициализировать** проект с конфигурацией EasyP **Настраивать линтинг**, чтобы ловить ошибки и соблюдать лучшие практики **Управлять зависимостями** из Git‑репозиториев **Генерировать код** из ваших Protobuf файлов"},{"id":"introduction/quickstart::top::2","title":"Быстрый старт (Quickstart)","section":"Предварительные требования","path":"/docs/guide/introduction/quickstart","headings":["Предварительные требования"],"excerpt":"Предварительные требования Перед началом убедитесь, что у вас установлены:","content":"Предварительные требования Перед началом убедитесь, что у вас установлены:"},{"id":"introduction/quickstart::top::3","title":"Быстрый старт (Quickstart)","section":"Предварительные требования","path":"/docs/guide/introduction/quickstart","headings":["Предварительные требования"],"excerpt":"Предварительные требования **EasyP CLI** — см. руководство по установке **Git** доступен в вашем $PATH **Файлы .proto** (или создайте их по ходу)","content":"Предварительные требования **EasyP CLI** — см. руководство по установке **Git** доступен в вашем $PATH **Файлы .proto** (или создайте их по ходу)"},{"id":"introduction/quickstart::top::4","title":"Быстрый старт (Quickstart)","section":"Предварительные требования","path":"/docs/guide/introduction/quickstart","headings":["Предварительные требования"],"excerpt":"Предварительные требования Проверить версию EasyP:","content":"Предварительные требования Проверить версию EasyP:"},{"id":"introduction/quickstart::top::5","title":"Быстрый старт (Quickstart)","section":"Инициализация проекта","path":"/docs/guide/introduction/quickstart","headings":["Инициализация проекта"],"excerpt":"Инициализация проекта Создайте базовый файл конфигурации easyp.yaml в корне проекта:","content":"Инициализация проекта Создайте базовый файл конфигурации easyp.yaml в корне проекта:"},{"id":"introduction/quickstart::top::6","title":"Быстрый старт (Quickstart)","section":"Инициализация проекта","path":"/docs/guide/introduction/quickstart","headings":["Инициализация проекта"],"excerpt":"Инициализация проекта Команда генерирует шаблон easyp.yaml с комментариями, дефолтными lint-правилами и настройками breaking-check. easyp init работает интерактивно: если в корне есть buf.yml/buf.yaml, EasyP предложит ми","content":"Инициализация проекта Команда генерирует шаблон easyp.yaml с комментариями, дефолтными lint-правилами и настройками breaking-check. easyp init работает интерактивно: если в корне есть buf.yml/buf.yaml, EasyP предложит миграцию; если easyp.yaml уже существует, попросит подтверждение перед перезаписью."},{"id":"introduction/quickstart::top::7","title":"Быстрый старт (Quickstart)","section":"Настройка линтинга","path":"/docs/guide/introduction/quickstart","headings":["Настройка линтинга"],"excerpt":"Настройка линтинга Линтинг помогает находить проблемы и поддерживать единый стиль. EasyP использует правила, совместимые с Buf.","content":"Настройка линтинга Линтинг помогает находить проблемы и поддерживать единый стиль. EasyP использует правила, совместимые с Buf."},{"id":"introduction/quickstart::top::8","title":"Быстрый старт (Quickstart)","section":"Настройка линтинга","path":"/docs/guide/introduction/quickstart","headings":["Настройка линтинга"],"excerpt":"Настройка линтинга Секция lint уже создаётся командой easyp init. При необходимости отредактируйте её, например так:","content":"Настройка линтинга Секция lint уже создаётся командой easyp init. При необходимости отредактируйте её, например так:"},{"id":"introduction/quickstart::top::9","title":"Быстрый старт (Quickstart)","section":"Настройка линтинга","path":"/docs/guide/introduction/quickstart","headings":["Настройка линтинга"],"excerpt":"Настройка линтинга Запустите линтер:","content":"Настройка линтинга Запустите линтер:"},{"id":"introduction/quickstart::top::10","title":"Быстрый старт (Quickstart)","section":"Настройка линтинга","path":"/docs/guide/introduction/quickstart","headings":["Настройка линтинга"],"excerpt":"Настройка линтинга Линтер проверит все .proto файлы и сообщит о найденных проблемах.","content":"Настройка линтинга Линтер проверит все .proto файлы и сообщит о найденных проблемах."},{"id":"introduction/quickstart::top::11","title":"Быстрый старт (Quickstart)","section":"Настройка линтинга","path":"/docs/guide/introduction/quickstart","headings":["Настройка линтинга"],"excerpt":"Настройка линтинга ::: tip Правила линтинга EasyP на 100% совместимы с Buf — мигрировать просто. :::","content":"Настройка линтинга ::: tip Правила линтинга EasyP на 100% совместимы с Buf — мигрировать просто. :::"},{"id":"introduction/quickstart::top::12","title":"Быстрый старт (Quickstart)","section":"Управление зависимостями","path":"/docs/guide/introduction/quickstart","headings":["Управление зависимостями"],"excerpt":"Управление зависимостями Если вы используете сторонние protobuf пакеты (например Google APIs или gRPC Gateway), EasyP упрощает их подключение.","content":"Управление зависимостями Если вы используете сторонние protobuf пакеты (например Google APIs или gRPC Gateway), EasyP упрощает их подключение."},{"id":"introduction/quickstart::top::13","title":"Быстрый старт (Quickstart)","section":"Формат зависимости","path":"/docs/guide/introduction/quickstart","headings":["Формат зависимости"],"excerpt":"Формат зависимости Запись: $GIT_LINK@$VERSION","content":"Формат зависимости Запись: $GIT_LINK@$VERSION"},{"id":"introduction/quickstart::top::14","title":"Быстрый старт (Quickstart)","section":"Формат зависимости","path":"/docs/guide/introduction/quickstart","headings":["Формат зависимости"],"excerpt":"Формат зависимости **$GIT_LINK** — URL любого Git‑репозитория (GitHub, GitLab и т.д.) **$VERSION** — тег или хеш коммита (опционально)","content":"Формат зависимости **$GIT_LINK** — URL любого Git‑репозитория (GitHub, GitLab и т.д.) **$VERSION** — тег или хеш коммита (опционально)"},{"id":"introduction/quickstart::top::15","title":"Быстрый старт (Quickstart)","section":"Формат зависимости","path":"/docs/guide/introduction/quickstart","headings":["Формат зависимости"],"excerpt":"Формат зависимости Если версия не указана — берётся последний коммит из основной ветки.","content":"Формат зависимости Если версия не указана — берётся последний коммит из основной ветки."},{"id":"introduction/quickstart::top::16","title":"Быстрый старт (Quickstart)","section":"Добавление зависимостей","path":"/docs/guide/introduction/quickstart","headings":["Добавление зависимостей"],"excerpt":"Добавление зависимостей Дополните easyp.yaml:","content":"Добавление зависимостей Дополните easyp.yaml:"},{"id":"introduction/quickstart::top::17","title":"Быстрый старт (Quickstart)","section":"Загрузка зависимостей","path":"/docs/guide/introduction/quickstart","headings":["Загрузка зависимостей"],"excerpt":"Загрузка зависимостей Команда: Скачивает версии из easyp.lock, если он существует Иначе — берёт из easyp.yaml и создаёт easyp.lock","content":"Загрузка зависимостей Команда: Скачивает версии из easyp.lock, если он существует Иначе — берёт из easyp.yaml и создаёт easyp.lock"},{"id":"introduction/quickstart::top::18","title":"Быстрый старт (Quickstart)","section":"Загрузка зависимостей","path":"/docs/guide/introduction/quickstart","headings":["Загрузка зависимостей"],"excerpt":"Загрузка зависимостей ::: info Совет: easyp mod update — игнорирует lock‑файл и подтягивает актуальные версии из easyp.yaml. :::","content":"Загрузка зависимостей ::: info Совет: easyp mod update — игнорирует lock‑файл и подтягивает актуальные версии из easyp.yaml. :::"},{"id":"introduction/quickstart::top::19","title":"Быстрый старт (Quickstart)","section":"Генерация кода","path":"/docs/guide/introduction/quickstart","headings":["Генерация кода"],"excerpt":"Генерация кода EasyP поддерживает все стандартные protoc‑плагины.","content":"Генерация кода EasyP поддерживает все стандартные protoc‑плагины."},{"id":"introduction/quickstart::top::20","title":"Быстрый старт (Quickstart)","section":"Конфигурация генерации","path":"/docs/guide/introduction/quickstart","headings":["Конфигурация генерации"],"excerpt":"Конфигурация генерации Добавьте плагины:","content":"Конфигурация генерации Добавьте плагины:"},{"id":"introduction/quickstart::top::21","title":"Быстрый старт (Quickstart)","section":"Запуск генерации","path":"/docs/guide/introduction/quickstart","headings":["Запуск генерации"],"excerpt":"Запуск генерации EasyP выполнит: Разрешение всех зависимостей Подключение к сервису EasyP (или локальный режим) Запуск указанных плагинов Вывод сгенерированного кода в нужные директории","content":"Запуск генерации EasyP выполнит: Разрешение всех зависимостей Подключение к сервису EasyP (или локальный режим) Запуск указанных плагинов Вывод сгенерированного кода в нужные директории"},{"id":"introduction/quickstart::top::22","title":"Быстрый старт (Quickstart)","section":"Запуск генерации","path":"/docs/guide/introduction/quickstart","headings":["Запуск генерации"],"excerpt":"Запуск генерации ::: tip Гибридный рантайм: WASM для скорости, Docker — для тяжёлых плагинов. :::","content":"Запуск генерации ::: tip Гибридный рантайм: WASM для скорости, Docker — для тяжёлых плагинов. :::"},{"id":"introduction/quickstart::top::23","title":"Быстрый старт (Quickstart)","section":"Следующие шаги","path":"/docs/guide/introduction/quickstart","headings":["Следующие шаги"],"excerpt":"Следующие шаги Поздравляем! 🎉 Вы успешно: ✅ Инициализировали проект EasyP ✅ Настроили линтинг ✅ Управляете внешними зависимостями ✅ Сгенерировали код из .proto","content":"Следующие шаги Поздравляем! 🎉 Вы успешно: ✅ Инициализировали проект EasyP ✅ Настроили линтинг ✅ Управляете внешними зависимостями ✅ Сгенерировали код из .proto"},{"id":"introduction/quickstart::top::24","title":"Быстрый старт (Quickstart)","section":"Узнать больше","path":"/docs/guide/introduction/quickstart","headings":["Узнать больше"],"excerpt":"Узнать больше **CLI Reference** — подробности по командам **API Service** — удалённая генерация **Configuration** — все опции конфигурации","content":"Узнать больше **CLI Reference** — подробности по командам **API Service** — удалённая генерация **Configuration** — все опции конфигурации"},{"id":"introduction/quickstart::top::25","title":"Быстрый старт (Quickstart)","section":"Узнать больше","path":"/docs/guide/introduction/quickstart","headings":["Узнать больше"],"excerpt":"Узнать больше *Приятной работы с Protobuf — без боли! 🚀*","content":"Узнать больше *Приятной работы с Protobuf — без боли! 🚀*"},{"id":"introduction/what-is::top::0","title":"Что такое EasyP?","path":"/docs/guide/introduction/what-is","headings":[],"excerpt":"EasyP — это современный инструментарий для работы с Protocol Buffers, который объединяет весь ваш protobuf‑workflow в один мощный CLI‑инструмент. Он совмещает линтинг, управление пакетами, генерацию кода и проверку совме","content":"EasyP — это современный инструментарий для работы с Protocol Buffers, который объединяет весь ваш protobuf‑workflow в один мощный CLI‑инструмент. Он совмещает линтинг, управление пакетами, генерацию кода и проверку совместимости в единой среде и устраняет сложность традиционной работы с protobuf."},{"id":"introduction/what-is::top::1","title":"Что такое EasyP?","path":"/docs/guide/introduction/what-is","headings":[],"excerpt":"Хотите просто попробовать? Перейдите сразу к разделу Quickstart.","content":"Хотите просто попробовать? Перейдите сразу к разделу Quickstart."},{"id":"introduction/what-is::protobuf::2","title":"Что такое EasyP?","section":"Проблема: фрагментированные protobuf‑процессы","path":"/docs/guide/introduction/what-is#protobuf","headings":["Проблема: фрагментированные protobuf‑процессы"],"excerpt":"Проблема: фрагментированные protobuf‑процессы Работа с Protocol Buffers в разных проектах часто создает лишнюю сложность и трение:","content":"Проблема: фрагментированные protobuf‑процессы Работа с Protocol Buffers в разных проектах часто создает лишнюю сложность и трение:"},{"id":"introduction/what-is::top::3","title":"Что такое EasyP?","section":"Хаос инструментов","path":"/docs/guide/introduction/what-is","headings":["Хаос инструментов"],"excerpt":"Хаос инструментов **Много отдельных утилит**: Отдельно для линтинга, генерации и управления зависимостями **Несогласованные конфигурации**: Разные форматы и правила в разных командах **Сложный онбординг**: Новым разработ","content":"Хаос инструментов **Много отдельных утилит**: Отдельно для линтинга, генерации и управления зависимостями **Несогласованные конфигурации**: Разные форматы и правила в разных командах **Сложный онбординг**: Новым разработчикам нужно долго вникать"},{"id":"introduction/what-is::top::4","title":"Что такое EasyP?","section":"Проблемы управления зависимостями","path":"/docs/guide/introduction/what-is","headings":["Проблемы управления зависимостями"],"excerpt":"Проблемы управления зависимостями **Нет стандартизированного подхода**: Каждый проект решает это по‑своему **Конфликты версий**: Трудно сводить разные версии одних и тех же proto‑библиотек **Неповторяемость сборок**: Сло","content":"Проблемы управления зависимостями **Нет стандартизированного подхода**: Каждый проект решает это по‑своему **Конфликты версий**: Трудно сводить разные версии одних и тех же proto‑библиотек **Неповторяемость сборок**: Сложно гарантировать одинаковый результат в разных окружениях"},{"id":"introduction/what-is::top::5","title":"Что такое EasyP?","section":"Трение в разработке","path":"/docs/guide/introduction/what-is","headings":["Трение в разработке"],"excerpt":"Трение в разработке **Ручные операции**: Много повторяющихся шагов **Разрастание конфигураций**: Множество файлов и форматов **Затратная проверка совместимости**: Часто вручную и постфактум","content":"Трение в разработке **Ручные операции**: Много повторяющихся шагов **Разрастание конфигураций**: Множество файлов и форматов **Затратная проверка совместимости**: Часто вручную и постфактум"},{"id":"introduction/what-is::protobuf::6","title":"Что такое EasyP?","section":"Решение: единый protobuf‑инструментарий","path":"/docs/guide/introduction/what-is#protobuf","headings":["Решение: единый protobuf‑инструментарий"],"excerpt":"Решение: единый protobuf‑инструментарий EasyP устраняет эти проблемы, предоставляя целостный opinionated‑подход и стандартизируя процессы:","content":"Решение: единый protobuf‑инструментарий EasyP устраняет эти проблемы, предоставляя целостный opinionated‑подход и стандартизируя процессы:"},{"id":"introduction/what-is::top::7","title":"Что такое EasyP?","section":"Один инструмент — все задачи","path":"/docs/guide/introduction/what-is","headings":["Один инструмент — все задачи"],"excerpt":"Один инструмент — все задачи Вместо жонглирования утилитами EasyP даёт: **Linting** с расширенными наборами правил **Package management** с Git‑нативными зависимостями **Code generation** локально и удалённо **Breaking c","content":"Один инструмент — все задачи Вместо жонглирования утилитами EasyP даёт: **Linting** с расширенными наборами правил **Package management** с Git‑нативными зависимостями **Code generation** локально и удалённо **Breaking change detection** для контроля совместимости API"},{"id":"introduction/what-is::top::8","title":"Что такое EasyP?","section":"Единая конфигурация","path":"/docs/guide/introduction/what-is","headings":["Единая конфигурация"],"excerpt":"Единая конфигурация Один файл easyp.yaml описывает весь workflow — меньше расхождений, проще сопровождать.","content":"Единая конфигурация Один файл easyp.yaml описывает весь workflow — меньше расхождений, проще сопровождать."},{"id":"introduction/what-is::gitnative::9","title":"Что такое EasyP?","section":"Git‑native зависимости","path":"/docs/guide/introduction/what-is#gitnative","headings":["Git‑native зависимости"],"excerpt":"Git‑native зависимости Прямое использование Git‑репозиториев вместо централизованных реестров: прозрачная история, контроль версий, воспроизводимые сборки.","content":"Git‑native зависимости Прямое использование Git‑репозиториев вместо централизованных реестров: прозрачная история, контроль версий, воспроизводимые сборки."},{"id":"introduction/what-is::top::10","title":"Что такое EasyP?","section":"Ключевые возможности","path":"/docs/guide/introduction/what-is","headings":["Ключевые возможности"],"excerpt":"Ключевые возможности Feature Description --------- ------------- 🔍 **Comprehensive Linting** Полная поддержка правил buf с настраиваемыми профилями для лучших практик API‑дизайна. 📦 **Smart Package Manager** Git‑ориент","content":"Ключевые возможности Feature Description --------- ------------- 🔍 **Comprehensive Linting** Полная поддержка правил buf с настраиваемыми профилями для лучших практик API‑дизайна. 📦 **Smart Package Manager** Git‑ориентированное управление зависимостями с lock‑файлом для воспроизводимости. ⚡ **Code Generation** Многозадачная генерация кода с поддержкой локальных и удалённых protoc‑плагинов. 🔄 **Breaking Change Detection** Автоматическая проверка совместимости API против веток Git. 🌐 **Remote Plugin Support** Выполнение плагинов через централизованный EasyP API сервис без локальных установок. 🎯 **Developer Experience** Автодополнение, понятные ошибки, единая структура и документация."},{"id":"introduction/what-is::top::11","title":"Что такое EasyP?","section":"Типы поддерживаемых плагинов","path":"/docs/guide/introduction/what-is","headings":["Типы поддерживаемых плагинов"],"excerpt":"Типы поддерживаемых плагинов EasyP гибко подходит к выполнению генерации:","content":"Типы поддерживаемых плагинов EasyP гибко подходит к выполнению генерации:"},{"id":"introduction/what-is::local-plugins::12","title":"Что такое EasyP?","section":"Local Plugins","path":"/docs/guide/introduction/what-is#local-plugins","headings":["Local Plugins"],"excerpt":"Local Plugins Стандартные установленные protoc‑плагины:","content":"Local Plugins Стандартные установленные protoc‑плагины:"},{"id":"introduction/what-is::remote-plugins::13","title":"Что такое EasyP?","section":"Remote Plugins","path":"/docs/guide/introduction/what-is#remote-plugins","headings":["Remote Plugins"],"excerpt":"Remote Plugins Плагины через EasyP API сервис для воспроизводимости:","content":"Remote Plugins Плагины через EasyP API сервис для воспроизводимости:"},{"id":"introduction/what-is::custom-plugins::14","title":"Что такое EasyP?","section":"Custom Plugins","path":"/docs/guide/introduction/what-is#custom-plugins","headings":["Custom Plugins"],"excerpt":"Custom Plugins Поддержка экосистемы пользовательских расширений.","content":"Custom Plugins Поддержка экосистемы пользовательских расширений."},{"id":"introduction/what-is::top::15","title":"Что такое EasyP?","section":"Децентрализованный менеджмент пакетов","path":"/docs/guide/introduction/what-is","headings":["Децентрализованный менеджмент пакетов"],"excerpt":"Децентрализованный менеджмент пакетов В отличие от других решений EasyP не требует централизованного реестра. Любой Git‑репозиторий может быть источником:","content":"Децентрализованный менеджмент пакетов В отличие от других решений EasyP не требует централизованного реестра. Любой Git‑репозиторий может быть источником:"},{"id":"introduction/what-is::top::16","title":"Что такое EasyP?","section":"Децентрализованный менеджмент пакетов","path":"/docs/guide/introduction/what-is","headings":["Децентрализованный менеджмент пакетов"],"excerpt":"Децентрализованный менеджмент пакетов **Гибкость**: Любой Git‑хостинг (GitHub, GitLab, self‑hosted) **Нет vendor lock‑in**: Зависимости не привязаны к одному провайдеру **Полная история**: Ветки, теги, ревью **Enterprise","content":"Децентрализованный менеджмент пакетов **Гибкость**: Любой Git‑хостинг (GitHub, GitLab, self‑hosted) **Нет vendor lock‑in**: Зависимости не привязаны к одному провайдеру **Полная история**: Ветки, теги, ревью **Enterprise‑совместимость**: Поддержка приватных репозиториев"},{"id":"introduction/what-is::buf::17","title":"Что такое EasyP?","section":"Бесшовная миграция с Buf","path":"/docs/guide/introduction/what-is#buf","headings":["Бесшовная миграция с Buf"],"excerpt":"Бесшовная миграция с Buf EasyP изначально совместим с экосистемой buf:","content":"Бесшовная миграция с Buf EasyP изначально совместим с экосистемой buf:"},{"id":"introduction/what-is::buf::18","title":"Что такое EasyP?","section":"Бесшовная миграция с Buf","path":"/docs/guide/introduction/what-is#buf","headings":["Бесшовная миграция с Buf"],"excerpt":"Бесшовная миграция с Buf **Совпадающие rule sets** **Похожая структура YAML** **Минимальные изменения для замены** **Постепенное внедрение** без ломки текущего пайплайна","content":"Бесшовная миграция с Buf **Совпадающие rule sets** **Похожая структура YAML** **Минимальные изменения для замены** **Постепенное внедрение** без ломки текущего пайплайна"},{"id":"introduction/what-is::easyp-vs-bufbuild::19","title":"Что такое EasyP?","section":"EasyP vs buf.build","path":"/docs/guide/introduction/what-is#easyp-vs-bufbuild","headings":["EasyP vs buf.build"],"excerpt":"EasyP vs buf.build Feature EasyP buf.build --------- -------- ----------- **Dependency Management** Git‑репозитории Buf Schema Registry (BSR) **Vendor Lock-in** Нет Привязка к BSR для полного функционала **Plugin Executi","content":"EasyP vs buf.build Feature EasyP buf.build --------- -------- ----------- **Dependency Management** Git‑репозитории Buf Schema Registry (BSR) **Vendor Lock-in** Нет Привязка к BSR для полного функционала **Plugin Execution** Local + Remote Local + BSR plugins **Private Dependencies** Любой Git провайдер BSR или ручное управление **Offline Development** Полная поддержка (mod vendor) Ограниченно без доступа к BSR **Enterprise Integration** Использует существующий Git Требует настройку BSR **Breaking Change Detection** Против любой Git ссылки Аналогично **Package Distribution** Любой Git Публикация через BSR **License** Apache 2.0 Apache 2.0 **Community** Growing Established"},{"id":"introduction/what-is::easyp-vs-bufbuild::20","title":"Что такое EasyP?","section":"EasyP vs buf.build","path":"/docs/guide/introduction/what-is#easyp-vs-bufbuild","headings":["EasyP vs buf.build"],"excerpt":"EasyP vs buf.build **Преимущества миграции:** Без изменения инфраструктуры Плавное принятие новых возможностей Гибрид локальных и удалённых плагинов Единая конфигурация вместо набора файлов","content":"EasyP vs buf.build **Преимущества миграции:** Без изменения инфраструктуры Плавное принятие новых возможностей Гибрид локальных и удалённых плагинов Единая конфигурация вместо набора файлов"},{"id":"introduction/what-is::protobuf::21","title":"Что такое EasyP?","section":"Наши цели для Protobuf","path":"/docs/guide/introduction/what-is#protobuf","headings":["Наши цели для Protobuf"],"excerpt":"Наши цели для Protobuf Миссия EasyP — ускорить принятие **schema‑driven API** через удобный, надёжный и прозрачный инструментарий.","content":"Наши цели для Protobuf Миссия EasyP — ускорить принятие **schema‑driven API** через удобный, надёжный и прозрачный инструментарий."},{"id":"introduction/what-is::top::22","title":"Что такое EasyP?","section":"Современная экосистема","path":"/docs/guide/introduction/what-is","headings":["Современная экосистема"],"excerpt":"Современная экосистема Повышаем DX вокруг protobuf, чтобы конкурентно выглядеть по простоте против REST/JSON, сохраняя типовую строгость и производительность.","content":"Современная экосистема Повышаем DX вокруг protobuf, чтобы конкурентно выглядеть по простоте против REST/JSON, сохраняя типовую строгость и производительность."},{"id":"introduction/what-is::developer-experience::23","title":"Что такое EasyP?","section":"Developer Experience прежде всего","path":"/docs/guide/introduction/what-is#developer-experience","headings":["Developer Experience прежде всего"],"excerpt":"Developer Experience прежде всего Интуитивный CLI, понятные ошибки, ясные сообщения, минимальная фрагментация.","content":"Developer Experience прежде всего Интуитивный CLI, понятные ошибки, ясные сообщения, минимальная фрагментация."},{"id":"introduction/what-is::enterprise::24","title":"Что такое EasyP?","section":"Готов к Enterprise","path":"/docs/guide/introduction/what-is#enterprise","headings":["Готов к Enterprise"],"excerpt":"Готов к Enterprise Воспроизводимые сборки, приватные репозитории, интеграция в CI/CD.","content":"Готов к Enterprise Воспроизводимые сборки, приватные репозитории, интеграция в CI/CD."},{"id":"introduction/what-is::top::25","title":"Что такое EasyP?","section":"Для индивидуальных разработчиков","path":"/docs/guide/introduction/what-is","headings":["Для индивидуальных разработчиков"],"excerpt":"Для индивидуальных разработчиков Быстрый старт за минуты Один инструмент — меньше когнитивной нагрузки Понятная документация","content":"Для индивидуальных разработчиков Быстрый старт за минуты Один инструмент — меньше когнитивной нагрузки Понятная документация"},{"id":"introduction/what-is::top::26","title":"Что такое EasyP?","section":"Для команд","path":"/docs/guide/introduction/what-is","headings":["Для команд"],"excerpt":"Для команд Единые стандарты Повторяемые сборки (lock‑файл) Ускоренный онбординг","content":"Для команд Единые стандарты Повторяемые сборки (lock‑файл) Ускоренный онбординг"},{"id":"introduction/what-is::top::27","title":"Что такое EasyP?","section":"Для организаций","path":"/docs/guide/introduction/what-is","headings":["Для организаций"],"excerpt":"Для организаций Нет vendor lock‑in Безопасность приватных репозиториев Лёгкая интеграция в существующие пайплайны","content":"Для организаций Нет vendor lock‑in Безопасность приватных репозиториев Лёгкая интеграция в существующие пайплайны"},{"id":"introduction/what-is::top::28","title":"Что такое EasyP?","section":"Что дальше?","path":"/docs/guide/introduction/what-is","headings":["Что дальше?"],"excerpt":"Что дальше? EasyP упрощает работу с protobuf — фокусируйтесь на API, а не на рутине. Хотите начать?","content":"Что дальше? EasyP упрощает работу с protobuf — фокусируйтесь на API, а не на рутине. Хотите начать?"},{"id":"introduction/what-is::top::29","title":"Что такое EasyP?","section":"Что дальше?","path":"/docs/guide/introduction/what-is","headings":["Что дальше?"],"excerpt":"Что дальше? Смотрите Installation Guide и Quickstart.","content":"Что дальше? Смотрите Installation Guide и Quickstart."},{"id":"introduction/what-is::stargazers-over-time::30","title":"Что такое 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 В работе","content":"Buf CLI В работе"},{"id":"migration/protoc::top::0","title":"Миграция с protoc на EasyP","path":"/docs/guide/migration/protoc","headings":[],"excerpt":"Исходная англоязычная версия файла содержала только заголовок и пометку “Work in progress”. Ниже — полноценный русскоязычный черновик раздела миграции. Уточни, если требуется сократить или изменить уровень детализации.","content":"Исходная англоязычная версия файла содержала только заголовок и пометку “Work in progress”. Ниже — полноценный русскоязычный черновик раздела миграции. Уточни, если требуется сократить или изменить уровень детализации."},{"id":"migration/protoc::1::1","title":"Миграция с protoc на EasyP","section":"1. Краткое сравнение","path":"/docs/guide/migration/protoc#1","headings":["1. Краткое сравнение"],"excerpt":"Краткое сравнение Аспект protoc EasyP -------- ---------- ------- Базовая роль Базовый компилятор .proto файлов Инструмент “всё в одном”: линтинг, проверка несовместимых изменений, менеджер пакетов, генерация Конфигураци","content":"Краткое сравнение Аспект protoc EasyP -------- ---------- ------- Базовая роль Базовый компилятор .proto файлов Инструмент “всё в одном”: линтинг, проверка несовместимых изменений, менеджер пакетов, генерация Конфигурация Чаще shell‑скрипты / Makefile / вручную передаваемые флаги Единый файл easyp.yaml (YAML или JSON) Управление зависимостями Ручной git clone, submodule, vendoring Секция deps с Git‑репозиториями Набор правил линтера Нет встроенного Встроенный линтер с правилами (можно включать/исключать) Проверка breaking changes Отсутствует из коробки Команда easyp breaking Расширенные плагины Установка и вызов через флаги --plugin Плагины через конфиг; поддержка удалённого выполнения (API Service) и стандартного локального Единообразие в CI Нужно собирать вручную Консистентные команды: lint, breaking, generate"},{"id":"migration/protoc::2::2","title":"Миграция с protoc на EasyP","section":"2. Когда имеет смысл мигрировать","path":"/docs/guide/migration/protoc#2","headings":["2. Когда имеет смысл мигрировать"],"excerpt":"Когда имеет смысл мигрировать Миграция на EasyP особенно полезна если: Есть потребность в автоматической проверке качества (стиль, именование) .proto файлов. Нужна защита от нелегитимных несовместимых изменений при эволю","content":"Когда имеет смысл мигрировать Миграция на EasyP особенно полезна если: Есть потребность в автоматической проверке качества (стиль, именование) .proto файлов. Нужна защита от нелегитимных несовместимых изменений при эволюции схем. В проекте используется несколько языков генерации и растёт число скриптов вокруг protoc. Вы хотите единый конфиг вместо множества shell/Makefile комбинаций. Планируется централизованное исполнение плагинов (через API Service) или унификация окружения в CI."},{"id":"migration/protoc::3-protoc::3","title":"Миграция с protoc на EasyP","section":"3. Типичный сценарий “до” (только protoc)","path":"/docs/guide/migration/protoc#3-protoc","headings":["3. Типичный сценарий “до” (только protoc)"],"excerpt":"Типичный сценарий “до” (только protoc) Пример: локальные скрипты / Makefile:","content":"Типичный сценарий “до” (только protoc) Пример: локальные скрипты / Makefile:"},{"id":"migration/protoc::3-protoc::4","title":"Миграция с protoc на EasyP","section":"3. Типичный сценарий “до” (только protoc)","path":"/docs/guide/migration/protoc#3-protoc","headings":["3. Типичный сценарий “до” (только protoc)"],"excerpt":"Типичный сценарий “до” (только protoc)","content":"Типичный сценарий “до” (только protoc)"},{"id":"migration/protoc::3-protoc::5","title":"Миграция с protoc на EasyP","section":"3. Типичный сценарий “до” (только protoc)","path":"/docs/guide/migration/protoc#3-protoc","headings":["3. Типичный сценарий “до” (только protoc)"],"excerpt":"Типичный сценарий “до” (только protoc) Дополнительные зависимости (googleapis, validate, grpc-gateway) скачиваются вручную или через submodules.","content":"Типичный сценарий “до” (только protoc) Дополнительные зависимости (googleapis, validate, grpc-gateway) скачиваются вручную или через submodules."},{"id":"migration/protoc::4-easyp::6","title":"Миграция с protoc на EasyP","section":"4. Типичный сценарий “после” (EasyP)","path":"/docs/guide/migration/protoc#4-easyp","headings":["4. Типичный сценарий “после” (EasyP)"],"excerpt":"Типичный сценарий “после” (EasyP) Единый файл easyp.yaml:","content":"Типичный сценарий “после” (EasyP) Единый файл easyp.yaml:"},{"id":"migration/protoc::4-easyp::7","title":"Миграция с protoc на EasyP","section":"4. Типичный сценарий “после” (EasyP)","path":"/docs/guide/migration/protoc#4-easyp","headings":["4. Типичный сценарий “после” (EasyP)"],"excerpt":"Типичный сценарий “после” (EasyP) ```yaml deps: - github.com/googleapis/googleapis - github.com/envoyproxy/protoc-gen-validate","content":"Типичный сценарий “после” (EasyP) ```yaml deps: - github.com/googleapis/googleapis - github.com/envoyproxy/protoc-gen-validate"},{"id":"migration/protoc::4-easyp::8","title":"Миграция с protoc на EasyP","section":"4. Типичный сценарий “после” (EasyP)","path":"/docs/guide/migration/protoc#4-easyp","headings":["4. Типичный сценарий “после” (EasyP)"],"excerpt":"Типичный сценарий “после” (EasyP) generate: plugins: - name: go out: gen/go opts: paths: source_relative - name: go-grpc out: gen/go opts: paths: source_relative require_unimplemented_servers: false - name: validate out:","content":"Типичный сценарий “после” (EasyP) generate: plugins: - name: go out: gen/go opts: paths: source_relative - name: go-grpc out: gen/go opts: paths: source_relative require_unimplemented_servers: false - name: validate out: gen/go opts: paths: source_relative lang: \"go\" ```"},{"id":"migration/protoc::4-easyp::9","title":"Миграция с protoc на EasyP","section":"4. Типичный сценарий “после” (EasyP)","path":"/docs/guide/migration/protoc#4-easyp","headings":["4. Типичный сценарий “после” (EasyP)"],"excerpt":"Типичный сценарий “после” (EasyP) Команды:","content":"Типичный сценарий “после” (EasyP) Команды:"},{"id":"migration/protoc::5::10","title":"Миграция с protoc на EasyP","section":"5. Пошаговая миграция","path":"/docs/guide/migration/protoc#5","headings":["5. Пошаговая миграция"],"excerpt":"Пошаговая миграция Инвентаризация: - Соберите список всех вызовов protoc (скрипты, Makefile, CI). - Зафиксируйте используемые плагины и их версии. Создание easyp.yaml: - Поле version не обязательно (можете оставить его т","content":"Пошаговая миграция Инвентаризация: - Соберите список всех вызовов protoc (скрипты, Makefile, CI). - Зафиксируйте используемые плагины и их версии. Создание easyp.yaml: - Поле version не обязательно (можете оставить его только для обратной совместимости). - Перенесите плагины в секцию generate.plugins. - Укажите опции, которые ранее передавались в командной строке. Зависимости: - Все внешние каталоги (googleapis, validate, grpc-gateway и т.п.) занесите в deps. - Удалите лишние submodules при необходимости. Линтер: - Запустите easyp lint и посмотрите на предупреждения. - При необходимости добавьте lint.use, lint.ignore, lint.except. Проверка breaking changes: - Выберите референс (обычно origin/main или предыдущий тег). - Запустите easyp breaking --against git-ref=origin/main. - Настройте игнорируемые изменения (breaking.ignore), если нужно. Обновление CI: - Замените прямые вызовы protoc на easyp generate. - Добавьте отдельные шаги lint и breaking. Очистка: - Удалите устаревшие генерационные скрипты, если они дублируют функционал EasyP. Документация: - Обновите README / CONTRIBUTING (новый способ генерации). Верификация: - Сравните результат генерации до и после (git diff). - Убедитесь, что имена файлов и пути совпадают или скорректируйте структуру."},{"id":"migration/protoc::6-ci-github-actions::11","title":"Миграция с protoc на EasyP","section":"6. Замена в CI (пример GitHub Actions)","path":"/docs/guide/migration/protoc#6-ci-github-actions","headings":["6. Замена в CI (пример GitHub Actions)"],"excerpt":"Замена в CI (пример GitHub Actions) ```yaml name: Install EasyP run: go install github.com/easyp-tech/easyp/cmd/easyp@latest","content":"Замена в CI (пример GitHub Actions) ```yaml name: Install EasyP run: go install github.com/easyp-tech/easyp/cmd/easyp@latest"},{"id":"migration/protoc::6-ci-github-actions::12","title":"Миграция с protoc на EasyP","section":"6. Замена в CI (пример GitHub Actions)","path":"/docs/guide/migration/protoc#6-ci-github-actions","headings":["6. Замена в CI (пример GitHub Actions)"],"excerpt":"Замена в CI (пример GitHub Actions) name: Lint run: easyp lint","content":"Замена в CI (пример GitHub Actions) name: Lint run: easyp lint"},{"id":"migration/protoc::6-ci-github-actions::13","title":"Миграция с protoc на EasyP","section":"6. Замена в CI (пример GitHub Actions)","path":"/docs/guide/migration/protoc#6-ci-github-actions","headings":["6. Замена в CI (пример GitHub Actions)"],"excerpt":"Замена в CI (пример GitHub Actions) name: Breaking run: easyp breaking --against git-ref=origin/main","content":"Замена в CI (пример GitHub Actions) name: Breaking run: easyp breaking --against git-ref=origin/main"},{"id":"migration/protoc::6-ci-github-actions::14","title":"Миграция с protoc на EasyP","section":"6. Замена в CI (пример GitHub Actions)","path":"/docs/guide/migration/protoc#6-ci-github-actions","headings":["6. Замена в CI (пример GitHub Actions)"],"excerpt":"Замена в CI (пример GitHub Actions) name: Generate run: easyp generate ```","content":"Замена в CI (пример GitHub Actions) name: Generate run: easyp generate ```"},{"id":"migration/protoc::7::15","title":"Миграция с protoc на EasyP","section":"7. Работа с плагинами","path":"/docs/guide/migration/protoc#7","headings":["7. Работа с плагинами"],"excerpt":"Работа с плагинами Тип В protoc В EasyP ----- ---------- --------- Стандартные (protoc-gen-go) Указание через --go_out plugins: - name: go ... gRPC --go-grpc_out Второй плагин go-grpc Validate Доп. установка + --validate","content":"Работа с плагинами Тип В protoc В EasyP ----- ---------- --------- Стандартные (protoc-gen-go) Указание через --go_out plugins: - name: go ... gRPC --go-grpc_out Второй плагин go-grpc Validate Доп. установка + --validate_out - name: validate с opts gRPC-Gateway / OpenAPI --grpc-gateway_out / --openapiv2_out Плагины grpc-gateway, openapiv2 Кастомные Путь к бинарю / --plugin=protoc-gen-xxx - name: xxx или удалённый remote: (если используется API Service)"},{"id":"migration/protoc::7::16","title":"Миграция с protoc на EasyP","section":"7. Работа с плагинами","path":"/docs/guide/migration/protoc#7","headings":["7. Работа с плагинами"],"excerpt":"Работа с плагинами Если вы переходите на удалённое выполнение (API Service), записи в конфиге могут выглядеть так:","content":"Работа с плагинами Если вы переходите на удалённое выполнение (API Service), записи в конфиге могут выглядеть так:"},{"id":"migration/protoc::8::17","title":"Миграция с protoc на EasyP","section":"8. Проверка корректности после миграции","path":"/docs/guide/migration/protoc#8","headings":["8. Проверка корректности после миграции"],"excerpt":"Проверка корректности после миграции git diff после easyp generate — не должно быть неожиданных изменений. Сравнить размер и содержимое каталога сгенерированных файлов. Запустить ваш потребляющий код (сборка, тесты). Про","content":"Проверка корректности после миграции git diff после easyp generate — не должно быть неожиданных изменений. Сравнить размер и содержимое каталога сгенерированных файлов. Запустить ваш потребляющий код (сборка, тесты). Проверить, что плагины (validate, grpc-gateway) продолжают вставлять необходимые аннотации / опции. Линт не должен выдавать критичных ошибок — скорректируйте стиль .proto, если требуется."},{"id":"migration/protoc::9::18","title":"Миграция с protoc на EasyP","section":"9. Частые проблемы","path":"/docs/guide/migration/protoc#9","headings":["9. Частые проблемы"],"excerpt":"Частые проблемы Проблема Причина Решение ---------- --------- --------- Плагин не найден Не установлен или не указан в PATH Выполнить go install ... или добавить в конфиг как remote Ошибка импорта .proto Отсутствует репо","content":"Частые проблемы Проблема Причина Решение ---------- --------- --------- Плагин не найден Не установлен или не указан в PATH Выполнить go install ... или добавить в конфиг как remote Ошибка импорта .proto Отсутствует репозиторий в deps Добавить адрес в секцию deps и easyp mod update Несовместимые изменения на каждом PR Отсутствует игнор/настройка сравнения Уточнить ветку/тег в --against или настроить breaking.ignore Локально работает, в CI падает В CI нет зависимостей (не вызван update) Добавить шаг easyp mod update перед generate Дубликаты сгенерированных файлов Изменена структура путей или out Синхронизировать out и paths: source_relative опции"},{"id":"migration/protoc::10-go::19","title":"Миграция с protoc на EasyP","section":"10. Минимальный пример конфигурации (только Go)","path":"/docs/guide/migration/protoc#10-go","headings":["10. Минимальный пример конфигурации (только Go)"],"excerpt":"Минимальный пример конфигурации (только Go)","content":"Минимальный пример конфигурации (только Go)"},{"id":"migration/protoc::10-go::20","title":"Миграция с protoc на EasyP","section":"10. Минимальный пример конфигурации (только Go)","path":"/docs/guide/migration/protoc#10-go","headings":["10. Минимальный пример конфигурации (только Go)"],"excerpt":"Минимальный пример конфигурации (только Go) Команды:","content":"Минимальный пример конфигурации (только Go) Команды:"},{"id":"migration/protoc::11-go-grpc-gateway-validate-breaking-lint::21","title":"Миграция с protoc на EasyP","section":"11. Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint)","path":"/docs/guide/migration/protoc#11-go-grpc-gateway-validate-breaking-lint","headings":["11. Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint)"],"excerpt":"Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint) ```yaml lint: use: - ENUM_FIRST_VALUE_ZERO - SERVICE_SUFFIX allow_comment_ignores: false enum_zero_value_suffix: _NONE service_suffix: Service","content":"Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint) ```yaml lint: use: - ENUM_FIRST_VALUE_ZERO - SERVICE_SUFFIX allow_comment_ignores: false enum_zero_value_suffix: _NONE service_suffix: Service"},{"id":"migration/protoc::11-go-grpc-gateway-validate-breaking-lint::22","title":"Миграция с protoc на EasyP","section":"11. Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint)","path":"/docs/guide/migration/protoc#11-go-grpc-gateway-validate-breaking-lint","headings":["11. Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint)"],"excerpt":"Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint) deps: - github.com/googleapis/googleapis - github.com/envoyproxy/protoc-gen-validate","content":"Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint) deps: - github.com/googleapis/googleapis - github.com/envoyproxy/protoc-gen-validate"},{"id":"migration/protoc::11-go-grpc-gateway-validate-breaking-lint::23","title":"Миграция с protoc на EasyP","section":"11. Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint)","path":"/docs/guide/migration/protoc#11-go-grpc-gateway-validate-breaking-lint","headings":["11. Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint)"],"excerpt":"Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint) generate: plugins: - name: go out: gen/go opts: paths: source_relative - name: go-grpc out: gen/go opts: paths: source_relative require_unimplemented_","content":"Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint) generate: plugins: - name: go out: gen/go opts: paths: source_relative - name: go-grpc out: gen/go opts: paths: source_relative require_unimplemented_servers: false - name: validate out: gen/go opts: paths: source_relative lang: \"go\" - name: grpc-gateway out: gen/go opts: paths: source_relative - name: openapiv2 out: gen/openapi opts: simple_operation_ids: true"},{"id":"migration/protoc::11-go-grpc-gateway-validate-breaking-lint::24","title":"Миграция с protoc на EasyP","section":"11. Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint)","path":"/docs/guide/migration/protoc#11-go-grpc-gateway-validate-breaking-lint","headings":["11. Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint)"],"excerpt":"Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint) breaking: against_git_ref: main ignore: - ENUM_VALUE_SAME_NAME ```","content":"Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint) breaking: against_git_ref: main ignore: - ENUM_VALUE_SAME_NAME ```"},{"id":"migration/protoc::12-checklist::25","title":"Миграция с protoc на EasyP","section":"12. Checklist миграции","path":"/docs/guide/migration/protoc#12-checklist","headings":["12. Checklist миграции"],"excerpt":"Checklist миграции [ ] Собраны все текущие вызовы protoc. [ ] Создан easyp.yaml с секциями generate и (опционально) lint, breaking. [ ] Добавлены все внешние зависимости в deps. [ ] Успешно выполнен easyp mod update. [ ]","content":"Checklist миграции [ ] Собраны все текущие вызовы protoc. [ ] Создан easyp.yaml с секциями generate и (опционально) lint, breaking. [ ] Добавлены все внешние зависимости в deps. [ ] Успешно выполнен easyp mod update. [ ] easyp generate даёт идентичный или ожидаемо обновлённый результат. [ ] easyp lint проходит без критичных ошибок (или ошибки обработаны). [ ] easyp breaking --against git-ref=origin/main не выдаёт неожиданных блокирующих нарушений. [ ] CI обновлён (заменены прямые вызовы protoc). [ ] Документация проекта обновлена (README: как генерировать)."},{"id":"migration/protoc::13::26","title":"Миграция с protoc на EasyP","section":"13. Дополнительные рекомендации","path":"/docs/guide/migration/protoc#13","headings":["13. Дополнительные рекомендации"],"excerpt":"Дополнительные рекомендации Сначала мигрируйте один сервис / пакет — снизит риск массовых конфликтов. Закоммитьте easyp.yaml отдельно, затем выполните генерацию и линт — проще ревью. Если нужны разные наборы плагинов для","content":"Дополнительные рекомендации Сначала мигрируйте один сервис / пакет — снизит риск массовых конфликтов. Закоммитьте easyp.yaml отдельно, затем выполните генерацию и линт — проще ревью. Если нужны разные наборы плагинов для разных микросервисов — используйте несколько конфигов (например: easyp.microservice-a.yaml + easyp.microservice-b.yaml). Внедрите проверку актуальности генерации: шаг CI, который валидирует отсутствие diff после easyp generate."},{"id":"migration/protoc::14::27","title":"Миграция с protoc на EasyP","section":"14. Статус","path":"/docs/guide/migration/protoc#14","headings":["14. Статус"],"excerpt":"Статус Этот файл — русская расширенная версия, заменяющая placeholder “Work in progress”. При появлении новых возможностей EasyP (дополнительные поля в конфиге, новые плагины, расширения breaking‑проверок) обновите соотв","content":"Статус Этот файл — русская расширенная версия, заменяющая placeholder “Work in progress”. При появлении новых возможностей EasyP (дополнительные поля в конфиге, новые плагины, расширения breaking‑проверок) обновите соответствующие разделы."},{"id":"migration/protoc::14::28","title":"Миграция с protoc на EasyP","section":"14. Статус","path":"/docs/guide/migration/protoc#14","headings":["14. Статус"],"excerpt":"Статус Если нужен упрощённый вариант (только перевод без расширения), сообщи — могу сократить до минимальных двух блоков.","content":"Статус Если нужен упрощённый вариант (только перевод без расширения), сообщи — могу сократить до минимальных двух блоков."},{"id":"migration/protolock::top::0","title":"Protolock","path":"/docs/guide/migration/protolock","headings":[],"excerpt":"Protolock В процессе разработки","content":"Protolock В процессе разработки"},{"id":"migration/prototool::top::0","title":"Prototool","section":"Состояние","path":"/docs/guide/migration/prototool","headings":["Состояние"],"excerpt":"Состояние Этот раздел был помечен как “Work in progress” в оригинальной английской версии. Ниже — переведённое и дополненное практическое руководство по миграции с Prototool на EasyP. Имя инструмента Prototool не перевод","content":"Состояние Этот раздел был помечен как “Work in progress” в оригинальной английской версии. Ниже — переведённое и дополненное практическое руководство по миграции с Prototool на EasyP. Имя инструмента Prototool не переводится."},{"id":"migration/prototool::top::1","title":"Prototool","section":"Цель миграции","path":"/docs/guide/migration/prototool","headings":["Цель миграции"],"excerpt":"Цель миграции Перейти от конфигурации и рабочих процессов Prototool к эквиваленту на EasyP с минимальными изменениями, сохранив: Линтинг .proto файлов. Генерацию кода через protoc-плагины. Управление зависимостями. Прове","content":"Цель миграции Перейти от конфигурации и рабочих процессов Prototool к эквиваленту на EasyP с минимальными изменениями, сохранив: Линтинг .proto файлов. Генерацию кода через protoc-плагины. Управление зависимостями. Проверку несовместимых изменений (в Prototool это приходилось реализовывать внешними инструментами; в EasyP встроено)."},{"id":"migration/prototool::top::2","title":"Prototool","section":"Кратко о различиях","path":"/docs/guide/migration/prototool","headings":["Кратко о различиях"],"excerpt":"Кратко о различиях Область Prototool EasyP Комментарий --------- ----------- ------- ------------- Конфигурация prototool.yaml easyp.yaml Форматы YAML/JSON поддерживаются; структура отличается. Линтинг Встроенные наборы ","content":"Кратко о различиях Область Prototool EasyP Комментарий --------- ----------- ------- ------------- Конфигурация prototool.yaml easyp.yaml Форматы YAML/JSON поддерживаются; структура отличается. Линтинг Встроенные наборы + кастомные правила Наборы через lint.use, тонкая настройка ignore/except EasyP даёт больше гибкости группировки. Генерация Раздел generate + плагины через Docker/локально generate.plugins (локальные/WASM/удалённые) EasyP может выполнять плагины удалённо (API Service). Зависимости Обычно через include-пути / внешние git clone вручную Секция deps (Git репозитории) + mod update Более декларативно. Breaking Changes Нет встроенного механизма Секция breaking + команда easyp breaking Из коробки. Lock-in Зависимость от модели Prototool Минималистичный формат, «любой Git — пакет» Облегчает выход / интеграцию с другими экосистемами."},{"id":"migration/prototool::prototool::3","title":"Prototool","section":"Типовая структура Prototool (упрощённо)","path":"/docs/guide/migration/prototool#prototool","headings":["Типовая структура Prototool (упрощённо)"],"excerpt":"Типовая структура Prototool (упрощённо)","content":"Типовая структура Prototool (упрощённо)"},{"id":"migration/prototool::prototool::4","title":"Prototool","section":"Типовая структура Prototool (упрощённо)","path":"/docs/guide/migration/prototool#prototool","headings":["Типовая структура Prototool (упрощённо)"],"excerpt":"Типовая структура Prototool (упрощённо) Особенности: include_paths задаёт пути поиска импортов. lint.group + rules.add/remove регулируют активные проверки. generate.plugins описывает плагины для protoc.","content":"Типовая структура Prototool (упрощённо) Особенности: include_paths задаёт пути поиска импортов. lint.group + rules.add/remove регулируют активные проверки. generate.plugins описывает плагины для protoc."},{"id":"migration/prototool::prototool::5","title":"Prototool","section":"Типовая структура Prototool (упрощённо)","path":"/docs/guide/migration/prototool#prototool","headings":["Типовая структура Prototool (упрощённо)"],"excerpt":"Типовая структура Prototool (упрощённо) ---","content":"Типовая структура Prototool (упрощённо) ---"},{"id":"migration/prototool::easyp::6","title":"Prototool","section":"Эквивалент на EasyP","path":"/docs/guide/migration/prototool#easyp","headings":["Эквивалент на EasyP"],"excerpt":"Эквивалент на EasyP ```yaml easyp.yaml (пример) deps: - github.com/org/common-protos # вместо manual include - github.com/org/third-party-protos","content":"Эквивалент на EasyP ```yaml easyp.yaml (пример) deps: - github.com/org/common-protos # вместо manual include - github.com/org/third-party-protos"},{"id":"migration/prototool::easyp::7","title":"Prototool","section":"Эквивалент на EasyP","path":"/docs/guide/migration/prototool#easyp","headings":["Эквивалент на EasyP"],"excerpt":"Эквивалент на EasyP lint: use: - MINIMAL - BASIC enum_zero_value_suffix: \"_NONE\" service_suffix: \"Service\" ignore: - COMMENT_FIELD except: - ENUM_VALUE_PREFIX allow_comment_ignores: true","content":"Эквивалент на EasyP lint: use: - MINIMAL - BASIC enum_zero_value_suffix: \"_NONE\" service_suffix: \"Service\" ignore: - COMMENT_FIELD except: - ENUM_VALUE_PREFIX allow_comment_ignores: true"},{"id":"migration/prototool::easyp::8","title":"Prototool","section":"Эквивалент на EasyP","path":"/docs/guide/migration/prototool#easyp","headings":["Эквивалент на EasyP"],"excerpt":"Эквивалент на EasyP generate: plugins: - name: go out: gen/go opts: paths: source_relative - name: go-grpc out: gen/go opts: paths: source_relative require_unimplemented_servers: false","content":"Эквивалент на EasyP generate: plugins: - name: go out: gen/go opts: paths: source_relative - name: go-grpc out: gen/go opts: paths: source_relative require_unimplemented_servers: false"},{"id":"migration/prototool::easyp::9","title":"Prototool","section":"Эквивалент на EasyP","path":"/docs/guide/migration/prototool#easyp","headings":["Эквивалент на EasyP"],"excerpt":"Эквивалент на EasyP breaking: against_git_ref: main ignore: - FIELD_SAME_TYPE ```","content":"Эквивалент на EasyP breaking: against_git_ref: main ignore: - FIELD_SAME_TYPE ```"},{"id":"migration/prototool::easyp::10","title":"Prototool","section":"Эквивалент на EasyP","path":"/docs/guide/migration/prototool#easyp","headings":["Эквивалент на EasyP"],"excerpt":"Эквивалент на EasyP Комментарии: deps заменяет необходимость вручную прописывать include paths: EasyP подтянет их через git. lint.use активирует наборы правил (MINIMAL/BASIC/DEFAULT и т.д.). Дополнительные настройки (enu","content":"Эквивалент на EasyP Комментарии: deps заменяет необходимость вручную прописывать include paths: EasyP подтянет их через git. lint.use активирует наборы правил (MINIMAL/BASIC/DEFAULT и т.д.). Дополнительные настройки (enum_zero_value_suffix, service_suffix) задают политики нейминга. breaking позволяет сразу контролировать несовместимые изменения."},{"id":"migration/prototool::top::11","title":"Prototool","section":"Шаги миграции","path":"/docs/guide/migration/prototool","headings":["Шаги миграции"],"excerpt":"Шаги миграции Инвентаризация: - Соберите текущий prototool.yaml, списки include paths и плагины. - Зафиксируйте используемые кастомные правила, если есть.","content":"Шаги миграции Инвентаризация: - Соберите текущий prototool.yaml, списки include paths и плагины. - Зафиксируйте используемые кастомные правила, если есть."},{"id":"migration/prototool::top::12","title":"Prototool","section":"Шаги миграции","path":"/docs/guide/migration/prototool","headings":["Шаги миграции"],"excerpt":"Шаги миграции Зависимости: - Любые каталоги, которые вы вручную добавляли в include_paths, преобразуйте в git-репозитории (если ещё нет). - Добавьте их в deps (формат: github.com/owner/repo или путь к вашей приватной сис","content":"Шаги миграции Зависимости: - Любые каталоги, которые вы вручную добавляли в include_paths, преобразуйте в git-репозитории (если ещё нет). - Добавьте их в deps (формат: github.com/owner/repo или путь к вашей приватной системе Git)."},{"id":"migration/prototool::top::13","title":"Prototool","section":"Шаги миграции","path":"/docs/guide/migration/prototool","headings":["Шаги миграции"],"excerpt":"Шаги миграции Линтинг: - Определите какой group использовался (basic, default, …) → сопоставьте с наборами EasyP (MINIMAL, BASIC, DEFAULT). - Индивидуальные добавления (rules.add) перенесите в lint.use или except/ignore:","content":"Шаги миграции Линтинг: - Определите какой group использовался (basic, default, …) → сопоставьте с наборами EasyP (MINIMAL, BASIC, DEFAULT). - Индивидуальные добавления (rules.add) перенесите в lint.use или except/ignore: - Если правило нужно активировать — включите через набор или явно. - Если нужно отключить — добавьте в ignore."},{"id":"migration/prototool::top::14","title":"Prototool","section":"Шаги миграции","path":"/docs/guide/migration/prototool","headings":["Шаги миграции"],"excerpt":"Шаги миграции Генерация: - Сохраните список плагинов. В большинстве случаев имена совпадут (go, go-grpc, др.). - Если раньше использовали Docker-окружение Prototool — проверьте поддержку удалённых плагинов через API Serv","content":"Шаги миграции Генерация: - Сохраните список плагинов. В большинстве случаев имена совпадут (go, go-grpc, др.). - Если раньше использовали Docker-окружение Prototool — проверьте поддержку удалённых плагинов через API Service EasyP (опционально). - Перепишите в секцию generate.plugins."},{"id":"migration/prototool::top::15","title":"Prototool","section":"Шаги миграции","path":"/docs/guide/migration/prototool","headings":["Шаги миграции"],"excerpt":"Шаги миграции Дополнительные опции: - Настройки нейминга enum/service перенести в enum_zero_value_suffix, service_suffix. - Если были внешние скрипты для проверки breaking changes — удалите их и включите breaking с again","content":"Шаги миграции Дополнительные опции: - Настройки нейминга enum/service перенести в enum_zero_value_suffix, service_suffix. - Если были внешние скрипты для проверки breaking changes — удалите их и включите breaking с against_git_ref."},{"id":"migration/prototool::top::16","title":"Prototool","section":"Шаги миграции","path":"/docs/guide/migration/prototool","headings":["Шаги миграции"],"excerpt":"Шаги миграции Верификация: - Запустите: easyp mod update (скачивание deps). - Затем: easyp lint. - Далее: easyp generate. - И, если нужно: easyp breaking --against git-ref=origin/main.","content":"Шаги миграции Верификация: - Запустите: easyp mod update (скачивание deps). - Затем: easyp lint. - Далее: easyp generate. - И, если нужно: easyp breaking --against git-ref=origin/main."},{"id":"migration/prototool::top::17","title":"Prototool","section":"Шаги миграции","path":"/docs/guide/migration/prototool","headings":["Шаги миграции"],"excerpt":"Шаги миграции CI/CD: - Обновите workflow (GitHub Actions / GitLab) — замените вызовы Prototool на EasyP команды. - Добавьте шаг проверки несовместимых изменений.","content":"Шаги миграции CI/CD: - Обновите workflow (GitHub Actions / GitLab) — замените вызовы Prototool на EasyP команды. - Добавьте шаг проверки несовместимых изменений."},{"id":"migration/prototool::top::18","title":"Prototool","section":"Сопоставление правил (общая идея)","path":"/docs/guide/migration/prototool","headings":["Сопоставление правил (общая идея)"],"excerpt":"Сопоставление правил (общая идея) Prototool концепт EasyP ------------------- ------ lint.group lint.use (наборы) rules.add/remove except / ignore include_paths deps (git источники) plugins generate.plugins (внешние скри","content":"Сопоставление правил (общая идея) Prototool концепт EasyP ------------------- ------ lint.group lint.use (наборы) rules.add/remove except / ignore include_paths deps (git источники) plugins generate.plugins (внешние скрипты для breaking) breaking секция + команда"},{"id":"migration/prototool::top::19","title":"Prototool","section":"Сопоставление правил (общая идея)","path":"/docs/guide/migration/prototool","headings":["Сопоставление правил (общая идея)"],"excerpt":"Сопоставление правил (общая идея) ---","content":"Сопоставление правил (общая идея) ---"},{"id":"migration/prototool::top::20","title":"Prototool","section":"Приватные репозитории","path":"/docs/guide/migration/prototool","headings":["Приватные репозитории"],"excerpt":"Приватные репозитории Если ранее Prototool просто видел локальные каталоги, теперь: Добавьте SSH ключи/токены в CI для доступа к приватным Git. Укажите их в deps как обычные git-URL (формат зависит от реализации EasyP; д","content":"Приватные репозитории Если ранее Prototool просто видел локальные каталоги, теперь: Добавьте SSH ключи/токены в CI для доступа к приватным Git. Укажите их в deps как обычные git-URL (формат зависит от реализации EasyP; для публичных — стандартный)."},{"id":"migration/prototool::top::21","title":"Prototool","section":"Типовые проблемы при миграции","path":"/docs/guide/migration/prototool","headings":["Типовые проблемы при миграции"],"excerpt":"Типовые проблемы при миграции Проблема Причина Решение ---------- --------- --------- Правила линтера не совпадают Неверное сопоставление групп Проверить документацию EasyP по наборам правил Импорты не находятся Забыли д","content":"Типовые проблемы при миграции Проблема Причина Решение ---------- --------- --------- Правила линтера не совпадают Неверное сопоставление групп Проверить документацию EasyP по наборам правил Импорты не находятся Забыли добавить репозиторий в deps Добавить в deps и выполнить easyp mod update Генерация падает на опциях Плагин требует другие flags Проверить opts и документацию плагина breaking сообщает слишком много Слишком строгий базовый набор Добавить конкретные правила в breaking.ignore Долгая генерация Нет кеша/много deps Включить кэширование в CI (vendor/.easyp/deps)"},{"id":"migration/prototool::top::22","title":"Prototool","section":"Типовые проблемы при миграции","path":"/docs/guide/migration/prototool","headings":["Типовые проблемы при миграции"],"excerpt":"Типовые проблемы при миграции ---","content":"Типовые проблемы при миграции ---"},{"id":"migration/prototool::top::23","title":"Prototool","section":"Минимальная конфигурация после миграции","path":"/docs/guide/migration/prototool","headings":["Минимальная конфигурация после миграции"],"excerpt":"Минимальная конфигурация после миграции","content":"Минимальная конфигурация после миграции"},{"id":"migration/prototool::top::24","title":"Prototool","section":"Минимальная конфигурация после миграции","path":"/docs/guide/migration/prototool","headings":["Минимальная конфигурация после миграции"],"excerpt":"Минимальная конфигурация после миграции ---","content":"Минимальная конфигурация после миграции ---"},{"id":"migration/prototool::top::25","title":"Prototool","section":"Рекомендации по упрощению","path":"/docs/guide/migration/prototool","headings":["Рекомендации по упрощению"],"excerpt":"Рекомендации по упрощению Начните с минимального lint.use (MINIMAL), затем постепенно включайте дополнительные наборы. Не переносите слепо все ignore — часть правил может уже быть улучшена в EasyP. Сначала настроить deps","content":"Рекомендации по упрощению Начните с минимального lint.use (MINIMAL), затем постепенно включайте дополнительные наборы. Не переносите слепо все ignore — часть правил может уже быть улучшена в EasyP. Сначала настроить deps и генерацию, затем усложнять линт/нейминг. Фиксируйте миграцию по шагам (коммиты: deps → lint → generate → breaking → CI)."},{"id":"migration/prototool::top::26","title":"Prototool","section":"Проверка результата","path":"/docs/guide/migration/prototool","headings":["Проверка результата"],"excerpt":"Проверка результата Скрипт локальной быстрой проверки (пример):","content":"Проверка результата Скрипт локальной быстрой проверки (пример):"},{"id":"migration/prototool::top::27","title":"Prototool","section":"Проверка результата","path":"/docs/guide/migration/prototool","headings":["Проверка результата"],"excerpt":"Проверка результата ```bash #!/usr/bin/env bash set -euo pipefail","content":"Проверка результата ```bash #!/usr/bin/env bash set -euo pipefail"},{"id":"migration/prototool::top::28","title":"Prototool","section":"Проверка результата","path":"/docs/guide/migration/prototool","headings":["Проверка результата"],"excerpt":"Проверка результата echo \"[1] deps update\" easyp mod update","content":"Проверка результата echo \"[1] deps update\" easyp mod update"},{"id":"migration/prototool::top::29","title":"Prototool","section":"Проверка результата","path":"/docs/guide/migration/prototool","headings":["Проверка результата"],"excerpt":"Проверка результата echo \"[2] lint\" easyp lint","content":"Проверка результата echo \"[2] lint\" easyp lint"},{"id":"migration/prototool::top::30","title":"Prototool","section":"Проверка результата","path":"/docs/guide/migration/prototool","headings":["Проверка результата"],"excerpt":"Проверка результата echo \"[3] breaking vs main\" easyp breaking --against git-ref=origin/main echo \"Breaking changes detected (review needed)\"","content":"Проверка результата echo \"[3] breaking vs main\" easyp breaking --against git-ref=origin/main echo \"Breaking changes detected (review needed)\""},{"id":"migration/prototool::top::31","title":"Prototool","section":"Проверка результата","path":"/docs/guide/migration/prototool","headings":["Проверка результата"],"excerpt":"Проверка результата echo \"[4] generate\" easyp generate","content":"Проверка результата echo \"[4] generate\" easyp generate"},{"id":"migration/prototool::top::32","title":"Prototool","section":"Проверка результата","path":"/docs/guide/migration/prototool","headings":["Проверка результата"],"excerpt":"Проверка результата echo \"Done.\" ```","content":"Проверка результата echo \"Done.\" ```"},{"id":"migration/prototool::top::33","title":"Prototool","section":"Заключение","path":"/docs/guide/migration/prototool","headings":["Заключение"],"excerpt":"Заключение Миграция с Prototool на EasyP сводится к: Переносу путей и внешних каталогов в декларативные deps. Переформатированию линта под lint.use + ignore/except. Переносу генерации в generate.plugins. Добавлению встро","content":"Заключение Миграция с Prototool на EasyP сводится к: Переносу путей и внешних каталогов в декларативные deps. Переформатированию линта под lint.use + ignore/except. Переносу генерации в generate.plugins. Добавлению встроенного механизма breaking. Адаптации CI."},{"id":"migration/prototool::top::34","title":"Prototool","section":"Заключение","path":"/docs/guide/migration/prototool","headings":["Заключение"],"excerpt":"Заключение После этого конфигурация становится более прозрачной, а проверка несовместимых изменений — из коробки.","content":"Заключение После этого конфигурация становится более прозрачной, а проверка несовместимых изменений — из коробки."},{"id":"migration/prototool::top::35","title":"Prototool","section":"Заключение","path":"/docs/guide/migration/prototool","headings":["Заключение"],"excerpt":"Заключение *Готово: базовый перевод и расширенное руководство по миграции с Prototool на EasyP.*","content":"Заключение *Готово: базовый перевод и расширенное руководство по миграции с Prototool на EasyP.*"},{"id":"TRANSLATION_STATUS::top::0","title":"Translation Status (ru-guide)","path":"/docs/guide/TRANSLATION_STATUS","headings":[],"excerpt":"Этот файл отслеживает прогресс перевода русской документации. Используемые статусы: TODO — требуется перевод IN_PROGRESS — перевод начат, требуется вычитка DONE — перевод завершён и вычитан SKIPPED — не требует перевода ","content":"Этот файл отслеживает прогресс перевода русской документации. Используемые статусы: TODO — требуется перевод IN_PROGRESS — перевод начат, требуется вычитка DONE — перевод завершён и вычитан SKIPPED — не требует перевода (намеренно оставлено на английском)"},{"id":"TRANSLATION_STATUS::top::1","title":"Translation Status (ru-guide)","path":"/docs/guide/TRANSLATION_STATUS","headings":[],"excerpt":"Правила: После полного перевода файла убрать исходный английский текст и маркер Термины протокола и ключевые идентификаторы (названия правил, CLI команды, YAML ключи) НЕ переводим. Если структура исходного файла изменила","content":"Правила: После полного перевода файла убрать исходный английский текст и маркер Термины протокола и ключевые идентификаторы (названия правил, CLI команды, YAML ключи) НЕ переводим. Если структура исходного файла изменилась — добавить в начало: Для больших изменений: сначала IN_PROGRESS, после вычитки менять на DONE."},{"id":"TRANSLATION_STATUS::summary::2","title":"Translation Status (ru-guide)","section":"Summary","path":"/docs/guide/TRANSLATION_STATUS#summary","headings":["Summary"],"excerpt":"Summary Итого файлов: 76 DONE: 76 IN_PROGRESS: 0 TODO: 0","content":"Summary Итого файлов: 76 DONE: 76 IN_PROGRESS: 0 TODO: 0"},{"id":"TRANSLATION_STATUS::priority-order::3","title":"Translation Status (ru-guide)","section":"Priority Order (рекомендованный)","path":"/docs/guide/TRANSLATION_STATUS#priority-order","headings":["Priority Order (рекомендованный)"],"excerpt":"Priority Order (рекомендованный) introduction/what-is.md introduction/quickstart.md introduction/install.md cli/linter/linter.md cli/generator/generator.md cli/package-manager/package-manager.md cli/breaking-changes/brea","content":"Priority Order (рекомендованный) introduction/what-is.md introduction/quickstart.md introduction/install.md cli/linter/linter.md cli/generator/generator.md cli/package-manager/package-manager.md cli/breaking-changes/breaking-changes.md api-service/overview.md migration/* (пакетом)"},{"id":"TRANSLATION_STATUS::priority-order::4","title":"Translation Status (ru-guide)","section":"Priority Order (рекомендованный)","path":"/docs/guide/TRANSLATION_STATUS#priority-order","headings":["Priority Order (рекомендованный)"],"excerpt":"Priority Order (рекомендованный) ---","content":"Priority Order (рекомендованный) ---"},{"id":"TRANSLATION_STATUS::file-status-table::5","title":"Translation Status (ru-guide)","section":"File Status Table","path":"/docs/guide/TRANSLATION_STATUS#file-status-table","headings":["File Status Table"],"excerpt":"File Status Table File Status Notes ------ -------- ------- introduction/what-is.md DONE Полный перевод выполнен introduction/quickstart.md DONE Структура сохранена, перевод вычитан introduction/install.md DONE Переведен","content":"File Status Table File Status Notes ------ -------- ------- introduction/what-is.md DONE Полный перевод выполнен introduction/quickstart.md DONE Структура сохранена, перевод вычитан introduction/install.md DONE Переведено, команды проверены api-service/overview.md DONE Переведено ci-cd/github-actions.md DONE Переведено ci-cd/gitlab.md DONE Переведено cli/auto-completion/auto-completion.md DONE Переведено cli/breaking-changes/breaking-changes.md DONE Переведено и вычитано cli/breaking-changes/rules/enum-no-delete.md DONE Переведено cli/breaking-changes/rules/enum-value-no-delete.md DONE Переведено cli/breaking-changes/rules/enum-value-same-name.md DONE Переведено cli/breaking-changes/rules/field-no-delete.md DONE Переведено cli/breaking-changes/rules/field-same-cardinality.md DONE Переведено cli/breaking-changes/rules/field-same-type.md DONE Переведено cli/breaking-changes/rules/import-no-delete.md DONE Переведено cli/breaking-changes/rules/message-no-delete.md DONE Переведено cli/breaking-changes/rules/oneof-field-no-delete.md DONE Переведено cli/breaking-changes/rules/oneof-field-same-type.md DONE Переведено cli/breaking-changes/rules/oneof-no-delete.md DONE Переведено cli/breaking-changes/rules/rpc-no-delete.md DONE Переведено cli/breaking-changes/rules/rpc-same-request-type.md DONE Переведено cli/breaking-changes/rules/rpc-same-response-type.md DONE Переведено cli/breaking-changes/rules/service-no-delete.md DONE Переведено cli/configuration/configuration.md DONE Переведено cli/generator/examples/go.md DONE Переведено cli/generator/examples/grpc-gateway.md DONE Переведено cli/generator/examples/validate.md DONE Переведено cli/generator/generator.md DONE Переведено и вычитано cli/linter/linter.md DONE Переведено и вычитано cli/linter/rules/comment-enum-value.md DONE Переведено cli/linter/rules/comment-enum.md DONE Переведено cli/linter/rules/comment-field.md DONE Переведено cli/linter/rules/comment-message.md DONE Переведено cli/linter/rules/comment-oneof.md DONE Переведено cli/linter/rules/comment-rpc.md DONE Переведено cli/linter/rules/comment-service.md DONE Переведено cli/linter/rules/directory-same-package.md DONE Переведено cli/linter/rules/enum-first-value-zero.md DONE Переведено cli/linter/rules/enum-no-allow-alias.md DONE Переведено cli/linter/rules/enum-pascal-case.md DONE Переведено cli/linter/rules/enum-value-prefix.md DONE Переведено cli/linter/rules/enum-value-upper-snake-case.md DONE Переведено cli/linter/rules/enum-zero-value-suffix.md DONE Переведено cli/linter/rules/field-lower-snake-case.md DONE Переведено cli/linter/rules/file-lower-snake-case.md DONE Переведено cli/linter/rules/import-no-public.md DONE Переведено cli/linter/rules/import-no-weak.md DONE Переведено cli/linter/rules/import-used.md DONE Переведено cli/linter/rules/message-pascal-case.md DONE Переведено cli/linter/rules/oneof-lower-snake-case.md DONE Переведено cli/linter/rules/package-defined.md DONE Переведено cli/linter/rules/package-directory-match.md DONE Переведено cli/linter/rules/package-lower-snake-case.md DONE Переведено cli/linter/rules/package-same-csharp-namespace.md DONE Переведено cli/linter/rules/package-same-directory.md DONE Переведено cli/linter/rules/package-same-go-package.md DONE Переведено cli/linter/rules/package-same-java-multiple-files.md DONE Переведено cli/linter/rules/package-same-java-package.md DONE Переведено cli/linter/rules/package-same-php-namespace.md DONE Переведено cli/linter/rules/package-same-ruby-package.md DONE Переведено cli/linter/rules/package-same-swift-prefix.md DONE Переведено cli/linter/rules/package-version-suffix.md DONE Переведено cli/linter/rules/rpc-no-client-streaming.md DONE Переведено cli/linter/rules/rpc-no-server-streaming.md DONE Переведено cli/linter/rules/rpc-pascal-case.md DONE Переведено cli/linter/rules/rpc-request-response-unique.md DONE Переведено cli/linter/rules/rpc-request-standard-name.md DONE Переведено cli/linter/rules/rpc-response-standard-name.md DONE Переведено cli/linter/rules/service-pascal-case.md DONE Переведено cli/linter/rules/service-suffix.md DONE Переведено cli/package-manager/easyp-vs-buf.md DONE Переведено cli/package-manager/package-manager.md DONE Переведено и вычитано migration/buf-cli.md DONE Переведено migration/protoc.md DONE Переведено migration/protolock.md DONE Переведено migration/prototool.md DONE Переведено"},{"id":"TRANSLATION_STATUS::workflow::6","title":"Translation Status (ru-guide)","section":"Workflow","path":"/docs/guide/TRANSLATION_STATUS#workflow","headings":["Workflow"],"excerpt":"Workflow Выбираем файл со статусом TODO. Меняем статус на IN_PROGRESS здесь. Переводим, проверяем терминологию (сверка с глоссарием — добавить позже). Меняем статус на DONE. Удаляем маркер внутри файла.","content":"Workflow Выбираем файл со статусом TODO. Меняем статус на IN_PROGRESS здесь. Переводим, проверяем терминологию (сверка с глоссарием — добавить позже). Меняем статус на DONE. Удаляем маркер внутри файла."},{"id":"TRANSLATION_STATUS::planned-terminology::7","title":"Translation Status (ru-guide)","section":"Planned Terminology (черновик)","path":"/docs/guide/TRANSLATION_STATUS#planned-terminology","headings":["Planned Terminology (черновик)"],"excerpt":"Planned Terminology (черновик) EN RU Notes ---- ---- ------- Linting Линтинг Транслитерация Breaking Changes Несовместимые изменения Название секции Dependency Зависимость Code Generation Генерация кода Lock file Lock-фа","content":"Planned Terminology (черновик) EN RU Notes ---- ---- ------- Linting Линтинг Транслитерация Breaking Changes Несовместимые изменения Название секции Dependency Зависимость Code Generation Генерация кода Lock file Lock-файл Remote Plugin Удалённый плагин Package Manager Менеджер пакетов"},{"id":"TRANSLATION_STATUS::planned-terminology::8","title":"Translation Status (ru-guide)","section":"Planned Terminology (черновик)","path":"/docs/guide/TRANSLATION_STATUS#planned-terminology","headings":["Planned Terminology (черновик)"],"excerpt":"Planned Terminology (черновик) (Будет дополнено.)","content":"Planned Terminology (черновик) (Будет дополнено.)"},{"id":"TRANSLATION_STATUS::planned-terminology::9","title":"Translation Status (ru-guide)","section":"Planned Terminology (черновик)","path":"/docs/guide/TRANSLATION_STATUS#planned-terminology","headings":["Planned Terminology (черновик)"],"excerpt":"Planned Terminology (черновик) ---","content":"Planned Terminology (черновик) ---"},{"id":"TRANSLATION_STATUS::top::10","title":"Translation Status (ru-guide)","section":"История обновлений","path":"/docs/guide/TRANSLATION_STATUS","headings":["История обновлений"],"excerpt":"История обновлений Initial file created: all statuses set (3 IN_PROGRESS, rest TODO). Marked breaking-changes page as DONE. Linter rules (41 файлов) переведены: статусы DONE. Breaking-changes rules (15 файлов) вычитаны и","content":"История обновлений Initial file created: all statuses set (3 IN_PROGRESS, rest TODO). Marked breaking-changes page as DONE. Linter rules (41 файлов) переведены: статусы DONE. Breaking-changes rules (15 файлов) вычитаны и помечены DONE. Все оставшиеся страницы переведены: итог DONE = 76."}] \ No newline at end of file +[{"id":"api-service/overview::top::0","title":"Обзор API Service","path":"/docs/guide/api-service/overview","headings":[],"excerpt":"**Централизованный сервис выполнения protobuf‑плагинов для консистентной изолированной генерации кода**","content":"**Централизованный сервис выполнения protobuf‑плагинов для консистентной изолированной генерации кода**"},{"id":"api-service/overview::top::1","title":"Обзор API Service","path":"/docs/guide/api-service/overview","headings":[],"excerpt":"EasyP API Service устраняет хаос управления плагинами, предоставляя централизованный запуск protobuf/gRPC плагинов в изолированных Docker‑контейнерах. Он даёт единую платформу, позволяющую командам стандартизировать проц","content":"EasyP API Service устраняет хаос управления плагинами, предоставляя централизованный запуск protobuf/gRPC плагинов в изолированных Docker‑контейнерах. Он даёт единую платформу, позволяющую командам стандартизировать процесс генерации кода без операционных затрат на установку и поддержку плагинов на машинах разработчиков."},{"id":"api-service/overview::easyp-api-service::2","title":"Обзор API Service","section":"Зачем нужен EasyP API Service?","path":"/docs/guide/api-service/overview#easyp-api-service","headings":["Зачем нужен EasyP API Service?"],"excerpt":"Зачем нужен EasyP API Service?","content":"Зачем нужен EasyP API Service?"},{"id":"api-service/overview::top::3","title":"Обзор API Service","section":"Проблема","path":"/docs/guide/api-service/overview","headings":["Проблема"],"excerpt":"Проблема Управление генерацией protobuf/gRPC кода в командах порождает существенную операционную сложность:","content":"Проблема Управление генерацией protobuf/gRPC кода в командах порождает существенную операционную сложность:"},{"id":"api-service/overview::top::4","title":"Обзор API Service","section":"Несогласованность версий","path":"/docs/guide/api-service/overview","headings":["Несогласованность версий"],"excerpt":"Несогласованность версий Разработчики локально используют разные версии плагинов → расхождения в генерированном коде и падения сборки Синдром «у меня работает» при различиях окружений Требуется ручная координация, чтобы ","content":"Несогласованность версий Разработчики локально используют разные версии плагинов → расхождения в генерированном коде и падения сборки Синдром «у меня работает» при различиях окружений Требуется ручная координация, чтобы вся команда была синхронизирована по версиям"},{"id":"api-service/overview::top::5","title":"Обзор API Service","section":"Операционные накладные расходы","path":"/docs/guide/api-service/overview","headings":["Операционные накладные расходы"],"excerpt":"Операционные накладные расходы DevOps тратят время на установку и обновление плагинов на рабочих станциях Новый разработчик — ручная настройка правильных версий Обновление плагинов требует коммуникации с каждым отдельно ","content":"Операционные накладные расходы DevOps тратят время на установку и обновление плагинов на рабочих станциях Новый разработчик — ручная настройка правильных версий Обновление плагинов требует коммуникации с каждым отдельно Нет централизованного контроля утверждённых версий"},{"id":"api-service/overview::top::6","title":"Обзор API Service","section":"Риски безопасности и комплаенса","path":"/docs/guide/api-service/overview","headings":["Риски безопасности и комплаенса"],"excerpt":"Риски безопасности и комплаенса Плагины ставятся из разных источников без валидации Нет аудита: какой плагин для какого билда использовался Сложно применять политики безопасности к инструментам генерации","content":"Риски безопасности и комплаенса Плагины ставятся из разных источников без валидации Нет аудита: какой плагин для какого билда использовался Сложно применять политики безопасности к инструментам генерации"},{"id":"api-service/overview::top::7","title":"Обзор API Service","section":"Решение: централизованный запуск плагинов","path":"/docs/guide/api-service/overview","headings":["Решение: централизованный запуск плагинов"],"excerpt":"Решение: централизованный запуск плагинов EasyP API Service решает эти проблемы за счёт централизованного управления:","content":"Решение: централизованный запуск плагинов EasyP API Service решает эти проблемы за счёт централизованного управления:"},{"id":"api-service/overview::top::8","title":"Обзор API Service","section":"Решение: централизованный запуск плагинов","path":"/docs/guide/api-service/overview","headings":["Решение: централизованный запуск плагинов"],"excerpt":"Решение: централизованный запуск плагинов Проблема Решение ---------- --------- **Контроль версий** Мгновенное распространение новых версий через Docker‑образы **Операции** Команда эксплуатации управляет конфигурациями б","content":"Решение: централизованный запуск плагинов Проблема Решение ---------- --------- **Контроль версий** Мгновенное распространение новых версий через Docker‑образы **Операции** Команда эксплуатации управляет конфигурациями без доступа на машины разработчиков **Безопасность** Все плагины запускаются в изолированных контейнерах с ограничениями ресурсов **Консистентность** Единая среда выполнения вне зависимости от локальной установки **Опыт разработчика** Не нужно устанавливать и сопровождать плагины локально"},{"id":"api-service/overview::top::9","title":"Обзор API Service","section":"Архитектура","path":"/docs/guide/api-service/overview","headings":["Архитектура"],"excerpt":"Архитектура Архитектура сервиса упрощена и сфокусирована на надёжном выполнении плагинов:","content":"Архитектура Архитектура сервиса упрощена и сфокусирована на надёжном выполнении плагинов:"},{"id":"api-service/overview::api-layer::10","title":"Обзор API Service","section":"API Layer","path":"/docs/guide/api-service/overview#api-layer","headings":["API Layer"],"excerpt":"API Layer **gRPC Server** — основной API для запросов генерации Каждый запуск плагина — отдельный gRPC‑запрос Получает CodeGeneratorRequest от CLI","content":"API Layer **gRPC Server** — основной API для запросов генерации Каждый запуск плагина — отдельный gRPC‑запрос Получает CodeGeneratorRequest от CLI"},{"id":"api-service/overview::execution-engine::11","title":"Обзор API Service","section":"Execution Engine","path":"/docs/guide/api-service/overview#execution-engine","headings":["Execution Engine"],"excerpt":"Execution Engine **Docker Runtime** — изолированный запуск плагинов Подтягивает образы из публичных реестров (Docker Hub и т.п.) Применяет лимиты CPU/памяти на плагин","content":"Execution Engine **Docker Runtime** — изолированный запуск плагинов Подтягивает образы из публичных реестров (Docker Hub и т.п.) Применяет лимиты CPU/памяти на плагин"},{"id":"api-service/overview::storage-layer::12","title":"Обзор API Service","section":"Storage Layer","path":"/docs/guide/api-service/overview#storage-layer","headings":["Storage Layer"],"excerpt":"Storage Layer **PostgreSQL** хранит параметры выполнения: - Ограничения ресурсов (CPU, память) - Конфигурацию и метаданные плагинов - Логи выполнения (аудит) - _Примечание: функциональность хранения будет расширяться_","content":"Storage Layer **PostgreSQL** хранит параметры выполнения: - Ограничения ресурсов (CPU, память) - Конфигурацию и метаданные плагинов - Логи выполнения (аудит) - _Примечание: функциональность хранения будет расширяться_"},{"id":"api-service/overview::monitoring::13","title":"Обзор API Service","section":"Monitoring","path":"/docs/guide/api-service/overview#monitoring","headings":["Monitoring"],"excerpt":"Monitoring **Prometheus** — сбор метрик Отслеживает время выполнения, успешность, использование ресурсов","content":"Monitoring **Prometheus** — сбор метрик Отслеживает время выполнения, успешность, использование ресурсов"},{"id":"api-service/overview::easyp-cli::14","title":"Обзор API Service","section":"Локальное выполнение (EasyP CLI)","path":"/docs/guide/api-service/overview#easyp-cli","headings":["Локальное выполнение (EasyP CLI)"],"excerpt":"Локальное выполнение (EasyP CLI) При локальном запуске CLI поддерживает: **Installed plugins**: системно установленные protoc плагины **WASM plugins**: лёгкие WebAssembly плагины","content":"Локальное выполнение (EasyP CLI) При локальном запуске CLI поддерживает: **Installed plugins**: системно установленные protoc плагины **WASM plugins**: лёгкие WebAssembly плагины"},{"id":"api-service/overview::api-service::15","title":"Обзор API Service","section":"Удалённое выполнение (API Service)","path":"/docs/guide/api-service/overview#api-service","headings":["Удалённое выполнение (API Service)"],"excerpt":"Удалённое выполнение (API Service) При работе через сервис: **Только Docker**: плагины запускаются как контейнеры **Центральный контроль**: операционная команда управляет доступными версиями **Консистентная среда**: один","content":"Удалённое выполнение (API Service) При работе через сервис: **Только Docker**: плагины запускаются как контейнеры **Центральный контроль**: операционная команда управляет доступными версиями **Консистентная среда**: одинаковое окружение для всех разработчиков"},{"id":"api-service/overview::top::16","title":"Обзор API Service","section":"Шаги выполнения","path":"/docs/guide/api-service/overview","headings":["Шаги выполнения"],"excerpt":"Шаги выполнения **CLI Parsing**: CLI парсит локальные .proto файлы **Request Sending**: Отправляет CodeGeneratorRequest в API Service (по одному на плагин) **Parameter Lookup**: Сервис получает параметры запуска из Postg","content":"Шаги выполнения **CLI Parsing**: CLI парсит локальные .proto файлы **Request Sending**: Отправляет CodeGeneratorRequest в API Service (по одному на плагин) **Parameter Lookup**: Сервис получает параметры запуска из PostgreSQL **Docker Execution**: Запускает плагин в изолированном контейнере **Metrics Recording**: Записывает метрики после завершения **Response**: Возвращает сгенерированный код обратно в CLI"},{"id":"api-service/overview::top::17","title":"Обзор API Service","section":"Ключевые возможности","path":"/docs/guide/api-service/overview","headings":["Ключевые возможности"],"excerpt":"Ключевые возможности Возможность Описание ------------- ---------- **🐳 Изоляция плагинов** Каждый плагин в отдельном безопасном контейнере **⚙️ Контроль ресурсов** Лимиты CPU и памяти на уровне контейнера **📊 Метрики &","content":"Ключевые возможности Возможность Описание ------------- ---------- **🐳 Изоляция плагинов** Каждый плагин в отдельном безопасном контейнере **⚙️ Контроль ресурсов** Лимиты CPU и памяти на уровне контейнера **📊 Метрики & мониторинг** Полный набор Prometheus метрик **🔄 Управление версиями** Централизованно через Docker‑образы **⚡ Простой протокол** Стандарт CodeGeneratorRequest/Response **🔒 Безопасность прежде всего** Изоляция + ограниченные ресурсы"},{"id":"api-service/overview::top::18","title":"Обзор API Service","section":"Конфигурация","path":"/docs/guide/api-service/overview","headings":["Конфигурация"],"excerpt":"Конфигурация Сервис настраивается через переменные окружения.","content":"Конфигурация Сервис настраивается через переменные окружения."},{"id":"api-service/overview::top::19","title":"Обзор API Service","section":"Хранение параметров плагинов","path":"/docs/guide/api-service/overview","headings":["Хранение параметров плагинов"],"excerpt":"Хранение параметров плагинов PostgreSQL хранит параметры выполнения для каждого плагина:","content":"Хранение параметров плагинов PostgreSQL хранит параметры выполнения для каждого плагина:"},{"id":"api-service/overview::top::20","title":"Обзор API Service","section":"Хранение параметров плагинов","path":"/docs/guide/api-service/overview","headings":["Хранение параметров плагинов"],"excerpt":"Хранение параметров плагинов ::: tip Схема хранения будет расширена — аудит логов, аналитика использования, кеширование плагинов. :::","content":"Хранение параметров плагинов ::: tip Схема хранения будет расширена — аудит логов, аналитика использования, кеширование плагинов. :::"},{"id":"api-service/overview::easyp-cli::21","title":"Обзор API Service","section":"Интеграция с EasyP CLI","path":"/docs/guide/api-service/overview#easyp-cli","headings":["Интеграция с EasyP CLI"],"excerpt":"Интеграция с EasyP CLI Пример easyp.yaml для удалённого запуска:","content":"Интеграция с EasyP CLI Пример easyp.yaml для удалённого запуска:"},{"id":"api-service/overview::easyp-cli::22","title":"Обзор API Service","section":"Интеграция с EasyP CLI","path":"/docs/guide/api-service/overview#easyp-cli","headings":["Интеграция с EasyP CLI"],"excerpt":"Интеграция с EasyP CLI Запуск генерации:","content":"Интеграция с EasyP CLI Запуск генерации:"},{"id":"api-service/overview::easyp-cli::23","title":"Обзор API Service","section":"Интеграция с EasyP CLI","path":"/docs/guide/api-service/overview#easyp-cli","headings":["Интеграция с EasyP CLI"],"excerpt":"Интеграция с EasyP CLI CLI: Парсит protobuf‑файлы Отправляет отдельные запросы в сервис для каждого плагина Получает ответы с кодом Записывает файлы в указанные директории","content":"Интеграция с EasyP CLI CLI: Парсит protobuf‑файлы Отправляет отдельные запросы в сервис для каждого плагина Получает ответы с кодом Записывает файлы в указанные директории"},{"id":"api-service/overview::top::24","title":"Обзор API Service","section":"Доступные метрики","path":"/docs/guide/api-service/overview","headings":["Доступные метрики"],"excerpt":"Доступные метрики Метрики Prometheus:","content":"Доступные метрики Метрики Prometheus:"},{"id":"api-service/overview::top::25","title":"Обзор API Service","section":"Доступные метрики","path":"/docs/guide/api-service/overview","headings":["Доступные метрики"],"excerpt":"Доступные метрики Метрика Описание --------- ---------- easyp_api_service_api_grpc_server_handled_total Общее число gRPC запросов по статусам easyp_api_service_api_grpc_server_handling_seconds Гистограмма задержек gRPC e","content":"Доступные метрики Метрика Описание --------- ---------- easyp_api_service_api_grpc_server_handled_total Общее число gRPC запросов по статусам easyp_api_service_api_grpc_server_handling_seconds Гистограмма задержек gRPC easyp_api_service_generated_plugin_code_total Выполнения плагинов по имени easyp_api_service_repo_call_duration_seconds Латентность запросов к БД easyp_api_service_repo_errors_total Количество ошибок доступа к БД easyp_api_service_standard_panics_total Число восстановленных паник"},{"id":"api-service/overview::top::26","title":"Обзор API Service","section":"Характеристики производительности","path":"/docs/guide/api-service/overview","headings":["Характеристики производительности"],"excerpt":"Характеристики производительности Показатель Типичное значение Примечания ----------- ------------------- ----------- **Cold Start** 2–5 сек Первая загрузка образа **Warm Start** 100–500 мс Образ закеширован **Throughput","content":"Характеристики производительности Показатель Типичное значение Примечания ----------- ------------------- ----------- **Cold Start** 2–5 сек Первая загрузка образа **Warm Start** 100–500 мс Образ закеширован **Throughput** 20–50 одновременных Зависит от ресурсов **Memory Usage** 50–200 MB На выполнение одного плагина"},{"id":"api-service/overview::top::27","title":"Обзор API Service","section":"Изоляция контейнеров","path":"/docs/guide/api-service/overview","headings":["Изоляция контейнеров"],"excerpt":"Изоляция контейнеров Каждый плагин в отдельном эфемерном контейнере Нет сетевого доступа в процессе выполнения Лимиты CPU/памяти через Docker Контейнер удаляется после завершения","content":"Изоляция контейнеров Каждый плагин в отдельном эфемерном контейнере Нет сетевого доступа в процессе выполнения Лимиты CPU/памяти через Docker Контейнер удаляется после завершения"},{"id":"api-service/overview::api::28","title":"Обзор API Service","section":"Безопасность API","path":"/docs/guide/api-service/overview#api","headings":["Безопасность API"],"excerpt":"Безопасность API gRPC транспорт Поддержка токенов аутентификации (в продакшн окружениях) Валидация входных данных Аудитные логи в PostgreSQL","content":"Безопасность API gRPC транспорт Поддержка токенов аутентификации (в продакшн окружениях) Валидация входных данных Аудитные логи в PostgreSQL"},{"id":"api-service/overview::top::29","title":"Обзор API Service","section":"Масштабирование","path":"/docs/guide/api-service/overview","headings":["Масштабирование"],"excerpt":"Масштабирование **Горизонтальное**: несколько инстансов за балансировщиком **Ресурсы**: настройка лимитов для тяжёлых плагинов **База данных**: репликация PostgreSQL для отказоустойчивости","content":"Масштабирование **Горизонтальное**: несколько инстансов за балансировщиком **Ресурсы**: настройка лимитов для тяжёлых плагинов **База данных**: репликация PostgreSQL для отказоустойчивости"},{"id":"api-service/overview::top::30","title":"Обзор API Service","section":"Мониторинг","path":"/docs/guide/api-service/overview","headings":["Мониторинг"],"excerpt":"Мониторинг **Метрики**: Prometheus **Алертинг**: оповещения на высокие ошибки/латентность **Логи**: структурированные для аудита и отладки","content":"Мониторинг **Метрики**: Prometheus **Алертинг**: оповещения на высокие ошибки/латентность **Логи**: структурированные для аудита и отладки"},{"id":"api-service/overview::top::31","title":"Обзор API Service","section":"План развития","path":"/docs/guide/api-service/overview","headings":["План развития"],"excerpt":"План развития Запланировано: Кеширование результатов генерации Расширенный аудит и аналитика использования Поддержка приватных реестров плагинов Более умное распределение ресурсов","content":"План развития Запланировано: Кеширование результатов генерации Расширенный аудит и аналитика использования Поддержка приватных реестров плагинов Более умное распределение ресурсов"},{"id":"api-service/overview::top::32","title":"Обзор API Service","section":"Сообщество и поддержка","path":"/docs/guide/api-service/overview","headings":["Сообщество и поддержка"],"excerpt":"Сообщество и поддержка **💬 Telegram чат** — обсуждения **🐛 GitHub Issues** — баги и запросы фич **📖 Документация** — полный набор материалов","content":"Сообщество и поддержка **💬 Telegram чат** — обсуждения **🐛 GitHub Issues** — баги и запросы фич **📖 Документация** — полный набор материалов"},{"id":"api-service/overview::top::33","title":"Обзор API Service","section":"Сообщество и поддержка","path":"/docs/guide/api-service/overview","headings":["Сообщество и поддержка"],"excerpt":"Сообщество и поддержка *Упростите свои protobuf‑воркфлоу с централизованным управлением выполнением плагинов.*","content":"Сообщество и поддержка *Упростите свои protobuf‑воркфлоу с централизованным управлением выполнением плагинов.*"},{"id":"ci-cd/github-actions::top::0","title":"GitHub Actions","path":"/docs/guide/ci-cd/github-actions","headings":[],"excerpt":"Полное руководство по интеграции EasyP в конвейеры GitHub Actions для линтинга, проверки несовместимых изменений, генерации кода и автоматизации релизов.","content":"Полное руководство по интеграции EasyP в конвейеры GitHub Actions для линтинга, проверки несовместимых изменений, генерации кода и автоматизации релизов."},{"id":"ci-cd/github-actions::easyp-ci::1","title":"GitHub Actions","section":"Зачем использовать EasyP в CI","path":"/docs/guide/ci-cd/github-actions#easyp-ci","headings":["Зачем использовать EasyP в CI"],"excerpt":"Зачем использовать EasyP в CI Встраивание EasyP в GitHub Actions даёт: Единообразие правил линтинга и генерации между разработчиками. Автоматическое выявление несовместимых изменений (breaking changes) до мержа. Гарантию","content":"Зачем использовать EasyP в CI Встраивание EasyP в GitHub Actions даёт: Единообразие правил линтинга и генерации между разработчиками. Автоматическое выявление несовместимых изменений (breaking changes) до мержа. Гарантию, что сгенерированный код не «устарел» относительно .proto. Возможность централизованной проверки зависимостей и версии конфигурации."},{"id":"ci-cd/github-actions::top::2","title":"GitHub Actions","section":"Предварительные требования","path":"/docs/guide/ci-cd/github-actions","headings":["Предварительные требования"],"excerpt":"Предварительные требования Репозиторий содержит файл конфигурации easyp.yaml (или находится в корне, если запускается без --cfg). Установлены / определены зависимости в секции deps (если нужны внешние импорты). Для прива","content":"Предварительные требования Репозиторий содержит файл конфигурации easyp.yaml (или находится в корне, если запускается без --cfg). Установлены / определены зависимости в секции deps (если нужны внешние импорты). Для приватных Git-репозиториев настроен доступ (SSH key / deploy key / токен). В workflow есть шаги по установке Go (если EasyP поставляется через go install) или заранее подготовленный бинарь."},{"id":"ci-cd/github-actions::top::3","title":"GitHub Actions","section":"Базовый пример (быстрый старт)","path":"/docs/guide/ci-cd/github-actions","headings":["Базовый пример (быстрый старт)"],"excerpt":"Базовый пример (быстрый старт) Минимальный workflow для проверки линта и несовместимых изменений при открытия Pull Request:","content":"Базовый пример (быстрый старт) Минимальный workflow для проверки линта и несовместимых изменений при открытия Pull Request:"},{"id":"ci-cd/github-actions::top::4","title":"GitHub Actions","section":"Базовый пример (быстрый старт)","path":"/docs/guide/ci-cd/github-actions","headings":["Базовый пример (быстрый старт)"],"excerpt":"Базовый пример (быстрый старт) ```yaml name: easyp-ci","content":"Базовый пример (быстрый старт) ```yaml name: easyp-ci"},{"id":"ci-cd/github-actions::top::5","title":"GitHub Actions","section":"Базовый пример (быстрый старт)","path":"/docs/guide/ci-cd/github-actions","headings":["Базовый пример (быстрый старт)"],"excerpt":"Базовый пример (быстрый старт) on: pull_request: paths: - '**/*.proto' - 'easyp.yaml'","content":"Базовый пример (быстрый старт) on: pull_request: paths: - '**/*.proto' - 'easyp.yaml'"},{"id":"ci-cd/github-actions::top::6","title":"GitHub Actions","section":"Базовый пример (быстрый старт)","path":"/docs/guide/ci-cd/github-actions","headings":["Базовый пример (быстрый старт)"],"excerpt":"Базовый пример (быстрый старт) jobs: lint-and-breaking: runs-on: ubuntu-latest","content":"Базовый пример (быстрый старт) jobs: lint-and-breaking: runs-on: ubuntu-latest"},{"id":"ci-cd/github-actions::top::7","title":"GitHub Actions","section":"Базовый пример (быстрый старт)","path":"/docs/guide/ci-cd/github-actions","headings":["Базовый пример (быстрый старт)"],"excerpt":"Базовый пример (быстрый старт) steps: - name: Checkout uses: actions/checkout@v4","content":"Базовый пример (быстрый старт) steps: - name: Checkout uses: actions/checkout@v4"},{"id":"ci-cd/github-actions::top::8","title":"GitHub Actions","section":"Базовый пример (быстрый старт)","path":"/docs/guide/ci-cd/github-actions","headings":["Базовый пример (быстрый старт)"],"excerpt":"Базовый пример (быстрый старт) name: Setup Go uses: actions/setup-go@v5 with: go-version: '1.22'","content":"Базовый пример (быстрый старт) name: Setup Go uses: actions/setup-go@v5 with: go-version: '1.22'"},{"id":"ci-cd/github-actions::top::9","title":"GitHub Actions","section":"Базовый пример (быстрый старт)","path":"/docs/guide/ci-cd/github-actions","headings":["Базовый пример (быстрый старт)"],"excerpt":"Базовый пример (быстрый старт) name: Install EasyP run: go install github.com/easyp-tech/easyp/cmd/easyp@latest","content":"Базовый пример (быстрый старт) name: Install EasyP run: go install github.com/easyp-tech/easyp/cmd/easyp@latest"},{"id":"ci-cd/github-actions::top::10","title":"GitHub Actions","section":"Базовый пример (быстрый старт)","path":"/docs/guide/ci-cd/github-actions","headings":["Базовый пример (быстрый старт)"],"excerpt":"Базовый пример (быстрый старт) name: Verify EasyP version run: which easyp easyp version","content":"Базовый пример (быстрый старт) name: Verify EasyP version run: which easyp easyp version"},{"id":"ci-cd/github-actions::top::11","title":"GitHub Actions","section":"Базовый пример (быстрый старт)","path":"/docs/guide/ci-cd/github-actions","headings":["Базовый пример (быстрый старт)"],"excerpt":"Базовый пример (быстрый старт) name: Lint run: easyp lint","content":"Базовый пример (быстрый старт) name: Lint run: easyp lint"},{"id":"ci-cd/github-actions::top::12","title":"GitHub Actions","section":"Базовый пример (быстрый старт)","path":"/docs/guide/ci-cd/github-actions","headings":["Базовый пример (быстрый старт)"],"excerpt":"Базовый пример (быстрый старт) name: Breaking changes check (against main) run: easyp breaking --against git-ref=origin/main ```","content":"Базовый пример (быстрый старт) name: Breaking changes check (against main) run: easyp breaking --against git-ref=origin/main ```"},{"id":"ci-cd/github-actions::easyp::13","title":"GitHub Actions","section":"Установка EasyP","path":"/docs/guide/ci-cd/github-actions#easyp","headings":["Установка EasyP"],"excerpt":"Установка EasyP Варианты: Через go install (как в примере выше). Использование заранее собранного бинаря (артефакт релиза).","content":"Установка EasyP Варианты: Через go install (как в примере выше). Использование заранее собранного бинаря (артефакт релиза)."},{"id":"ci-cd/github-actions::top::14","title":"GitHub Actions","section":"Кэширование","path":"/docs/guide/ci-cd/github-actions","headings":["Кэширование"],"excerpt":"Кэширование Для ускорения повторных сборок можно кэшировать: Go модульный кеш (если используете генерацию с плагинами Go). Внешние зависимые Git-клонирования (папки vendor или содержимое deps при использовании easyp mod ","content":"Кэширование Для ускорения повторных сборок можно кэшировать: Go модульный кеш (если используете генерацию с плагинами Go). Внешние зависимые Git-клонирования (папки vendor или содержимое deps при использовании easyp mod download / easyp mod update). Сгенерированный код (если он тяжёлый, но чаще генерируется заново)."},{"id":"ci-cd/github-actions::top::15","title":"GitHub Actions","section":"Кэширование","path":"/docs/guide/ci-cd/github-actions","headings":["Кэширование"],"excerpt":"Кэширование Пример кэширования Go:","content":"Кэширование Пример кэширования Go:"},{"id":"ci-cd/github-actions::top::16","title":"GitHub Actions","section":"Кэширование","path":"/docs/guide/ci-cd/github-actions","headings":["Кэширование"],"excerpt":"Кэширование Пример кэширования каталога зависимостей EasyP (если вы используете локальный vendor-подход):","content":"Кэширование Пример кэширования каталога зависимостей EasyP (если вы используете локальный vendor-подход):"},{"id":"ci-cd/github-actions::top::17","title":"GitHub Actions","section":"Кэширование","path":"/docs/guide/ci-cd/github-actions","headings":["Кэширование"],"excerpt":"Кэширование (Создайте .easyp/deps как целевой каталог, если ваша стратегия скачивания такова.)","content":"Кэширование (Создайте .easyp/deps как целевой каталог, если ваша стратегия скачивания такова.)"},{"id":"ci-cd/github-actions::top::18","title":"GitHub Actions","section":"Линтинг","path":"/docs/guide/ci-cd/github-actions","headings":["Линтинг"],"excerpt":"Линтинг Рекомендуется: В PR: всегда запускать. На main: можно запускать для верификации перед релизом.","content":"Линтинг Рекомендуется: В PR: всегда запускать. На main: можно запускать для верификации перед релизом."},{"id":"ci-cd/github-actions::top::19","title":"GitHub Actions","section":"Линтинг","path":"/docs/guide/ci-cd/github-actions","headings":["Линтинг"],"excerpt":"Линтинг Расширенный пример с выводом подробностей и игнорированием комментариев (если включено в конфиг):","content":"Линтинг Расширенный пример с выводом подробностей и игнорированием комментариев (если включено в конфиг):"},{"id":"ci-cd/github-actions::breaking-changes::20","title":"GitHub Actions","section":"Проверка несовместимых изменений (Breaking Changes)","path":"/docs/guide/ci-cd/github-actions#breaking-changes","headings":["Проверка несовместимых изменений (Breaking Changes)"],"excerpt":"Проверка несовместимых изменений (Breaking Changes) EasyP может сравнивать текущее состояние против ветки / коммита / тега.","content":"Проверка несовместимых изменений (Breaking Changes) EasyP может сравнивать текущее состояние против ветки / коммита / тега."},{"id":"ci-cd/github-actions::breaking-changes::21","title":"GitHub Actions","section":"Проверка несовместимых изменений (Breaking Changes)","path":"/docs/guide/ci-cd/github-actions#breaking-changes","headings":["Проверка несовместимых изменений (Breaking Changes)"],"excerpt":"Проверка несовместимых изменений (Breaking Changes) Примеры: ```bash Сравнить против origin/main easyp breaking --against git-ref=origin/main","content":"Проверка несовместимых изменений (Breaking Changes) Примеры: ```bash Сравнить против origin/main easyp breaking --against git-ref=origin/main"},{"id":"ci-cd/github-actions::breaking-changes::22","title":"GitHub Actions","section":"Проверка несовместимых изменений (Breaking Changes)","path":"/docs/guide/ci-cd/github-actions#breaking-changes","headings":["Проверка несовместимых изменений (Breaking Changes)"],"excerpt":"Проверка несовместимых изменений (Breaking Changes) Сравнить против тега релиза easyp breaking --against git-ref=v1.5.2","content":"Проверка несовместимых изменений (Breaking Changes) Сравнить против тега релиза easyp breaking --against git-ref=v1.5.2"},{"id":"ci-cd/github-actions::breaking-changes::23","title":"GitHub Actions","section":"Проверка несовместимых изменений (Breaking Changes)","path":"/docs/guide/ci-cd/github-actions#breaking-changes","headings":["Проверка несовместимых изменений (Breaking Changes)"],"excerpt":"Проверка несовместимых изменений (Breaking Changes) Игнорировать определённые правила (если у вас настроено в easyp.yaml) easyp breaking ```","content":"Проверка несовместимых изменений (Breaking Changes) Игнорировать определённые правила (если у вас настроено в easyp.yaml) easyp breaking ```"},{"id":"ci-cd/github-actions::breaking-changes::24","title":"GitHub Actions","section":"Проверка несовместимых изменений (Breaking Changes)","path":"/docs/guide/ci-cd/github-actions#breaking-changes","headings":["Проверка несовместимых изменений (Breaking Changes)"],"excerpt":"Проверка несовместимых изменений (Breaking Changes) Workflow шаг:","content":"Проверка несовместимых изменений (Breaking Changes) Workflow шаг:"},{"id":"ci-cd/github-actions::breaking-changes::25","title":"GitHub Actions","section":"Проверка несовместимых изменений (Breaking Changes)","path":"/docs/guide/ci-cd/github-actions#breaking-changes","headings":["Проверка несовместимых изменений (Breaking Changes)"],"excerpt":"Проверка несовместимых изменений (Breaking Changes)","content":"Проверка несовместимых изменений (Breaking Changes)"},{"id":"ci-cd/github-actions::breaking-changes::26","title":"GitHub Actions","section":"Проверка несовместимых изменений (Breaking Changes)","path":"/docs/guide/ci-cd/github-actions#breaking-changes","headings":["Проверка несовместимых изменений (Breaking Changes)"],"excerpt":"Проверка несовместимых изменений (Breaking Changes) Если нужно «мягко» пропустить (например, выводить предупреждения, но не падать билд):","content":"Проверка несовместимых изменений (Breaking Changes) Если нужно «мягко» пропустить (например, выводить предупреждения, но не падать билд):"},{"id":"ci-cd/github-actions::breaking-changes::27","title":"GitHub Actions","section":"Проверка несовместимых изменений (Breaking Changes)","path":"/docs/guide/ci-cd/github-actions#breaking-changes","headings":["Проверка несовместимых изменений (Breaking Changes)"],"excerpt":"Проверка несовместимых изменений (Breaking Changes)","content":"Проверка несовместимых изменений (Breaking Changes)"},{"id":"ci-cd/github-actions::top::28","title":"GitHub Actions","section":"Генерация кода","path":"/docs/guide/ci-cd/github-actions","headings":["Генерация кода"],"excerpt":"Генерация кода Обычно для генерации:","content":"Генерация кода Обычно для генерации:"},{"id":"ci-cd/github-actions::top::29","title":"GitHub Actions","section":"Генерация кода","path":"/docs/guide/ci-cd/github-actions","headings":["Генерация кода"],"excerpt":"Генерация кода Если нужно явно указать конфиг:","content":"Генерация кода Если нужно явно указать конфиг:"},{"id":"ci-cd/github-actions::top::30","title":"GitHub Actions","section":"Генерация кода","path":"/docs/guide/ci-cd/github-actions","headings":["Генерация кода"],"excerpt":"Генерация кода Можно добавить проверку «не осталось ли не закоммиченных изменений» (гарантия, что сгенерированный код актуален):","content":"Генерация кода Можно добавить проверку «не осталось ли не закоммиченных изменений» (гарантия, что сгенерированный код актуален):"},{"id":"ci-cd/github-actions::matrix-strategy::31","title":"GitHub Actions","section":"Матрица (Matrix strategy)","path":"/docs/guide/ci-cd/github-actions#matrix-strategy","headings":["Матрица (Matrix strategy)"],"excerpt":"Матрица (Matrix strategy) Если у вас несколько вариантов конфигураций или разных языков генерации (через плагины), можно использовать matrix:","content":"Матрица (Matrix strategy) Если у вас несколько вариантов конфигураций или разных языков генерации (через плагины), можно использовать matrix:"},{"id":"ci-cd/github-actions::matrix-strategy::32","title":"GitHub Actions","section":"Матрица (Matrix strategy)","path":"/docs/guide/ci-cd/github-actions#matrix-strategy","headings":["Матрица (Matrix strategy)"],"excerpt":"Матрица (Matrix strategy) ```yaml jobs: generate: runs-on: ubuntu-latest strategy: fail-fast: false matrix: lang: [go, python] steps: - uses: actions/checkout@v4","content":"Матрица (Matrix strategy) ```yaml jobs: generate: runs-on: ubuntu-latest strategy: fail-fast: false matrix: lang: [go, python] steps: - uses: actions/checkout@v4"},{"id":"ci-cd/github-actions::matrix-strategy::33","title":"GitHub Actions","section":"Матрица (Matrix strategy)","path":"/docs/guide/ci-cd/github-actions#matrix-strategy","headings":["Матрица (Matrix strategy)"],"excerpt":"Матрица (Matrix strategy) name: Setup Go (only for go) if: matrix.lang == 'go' uses: actions/setup-go@v5 with: go-version: '1.22'","content":"Матрица (Matrix strategy) name: Setup Go (only for go) if: matrix.lang == 'go' uses: actions/setup-go@v5 with: go-version: '1.22'"},{"id":"ci-cd/github-actions::matrix-strategy::34","title":"GitHub Actions","section":"Матрица (Matrix strategy)","path":"/docs/guide/ci-cd/github-actions#matrix-strategy","headings":["Матрица (Matrix strategy)"],"excerpt":"Матрица (Matrix strategy) name: Install EasyP run: go install github.com/easyp-tech/easyp/cmd/easyp@latest","content":"Матрица (Matrix strategy) name: Install EasyP run: go install github.com/easyp-tech/easyp/cmd/easyp@latest"},{"id":"ci-cd/github-actions::matrix-strategy::35","title":"GitHub Actions","section":"Матрица (Matrix strategy)","path":"/docs/guide/ci-cd/github-actions#matrix-strategy","headings":["Матрица (Matrix strategy)"],"excerpt":"Матрица (Matrix strategy) name: Generate run: if [ \"${{ matrix.lang }}\" = \"go\" ]; then easyp generate elif [ \"${{ matrix.lang }}\" = \"python\" ]; then easyp generate --plugin python fi ```","content":"Матрица (Matrix strategy) name: Generate run: if [ \"${{ matrix.lang }}\" = \"go\" ]; then easyp generate elif [ \"${{ matrix.lang }}\" = \"python\" ]; then easyp generate --plugin python fi ```"},{"id":"ci-cd/github-actions::deps::36","title":"GitHub Actions","section":"Работа с приватными репозиториями (deps)","path":"/docs/guide/ci-cd/github-actions#deps","headings":["Работа с приватными репозиториями (deps)"],"excerpt":"Работа с приватными репозиториями (deps) Если вы указываете приватные Git-пакеты в секции deps:","content":"Работа с приватными репозиториями (deps) Если вы указываете приватные Git-пакеты в секции deps:"},{"id":"ci-cd/github-actions::deps::37","title":"GitHub Actions","section":"Работа с приватными репозиториями (deps)","path":"/docs/guide/ci-cd/github-actions#deps","headings":["Работа с приватными репозиториями (deps)"],"excerpt":"Работа с приватными репозиториями (deps) Настройте deploy key или используйте GIT_SSH_COMMAND с токеном. Добавьте known_hosts (либо установите StrictHostKeyChecking=no для внутренних систем, но осознанно).","content":"Работа с приватными репозиториями (deps) Настройте deploy key или используйте GIT_SSH_COMMAND с токеном. Добавьте known_hosts (либо установите StrictHostKeyChecking=no для внутренних систем, но осознанно)."},{"id":"ci-cd/github-actions::deps::38","title":"GitHub Actions","section":"Работа с приватными репозиториями (deps)","path":"/docs/guide/ci-cd/github-actions#deps","headings":["Работа с приватными репозиториями (deps)"],"excerpt":"Работа с приватными репозиториями (deps) Пример:","content":"Работа с приватными репозиториями (deps) Пример:"},{"id":"ci-cd/github-actions::deps::39","title":"GitHub Actions","section":"Работа с приватными репозиториями (deps)","path":"/docs/guide/ci-cd/github-actions#deps","headings":["Работа с приватными репозиториями (deps)"],"excerpt":"Работа с приватными репозиториями (deps) ```yaml name: Prepare SSH run: mkdir -p ~/.ssh echo \"${{ secrets.DEPLOY_KEY }}\" > ~/.ssh/id_rsa chmod 600 ~/.ssh/id_rsa ssh-keyscan github.com >> ~/.ssh/known_hosts","content":"Работа с приватными репозиториями (deps) ```yaml name: Prepare SSH run: mkdir -p ~/.ssh echo \"${{ secrets.DEPLOY_KEY }}\" > ~/.ssh/id_rsa chmod 600 ~/.ssh/id_rsa ssh-keyscan github.com >> ~/.ssh/known_hosts"},{"id":"ci-cd/github-actions::deps::40","title":"GitHub Actions","section":"Работа с приватными репозиториями (deps)","path":"/docs/guide/ci-cd/github-actions#deps","headings":["Работа с приватными репозиториями (deps)"],"excerpt":"Работа с приватными репозиториями (deps) name: Update deps run: easyp mod update ```","content":"Работа с приватными репозиториями (deps) name: Update deps run: easyp mod update ```"},{"id":"ci-cd/github-actions::top::41","title":"GitHub Actions","section":"Оптимизация времени сборки","path":"/docs/guide/ci-cd/github-actions","headings":["Оптимизация времени сборки"],"excerpt":"Оптимизация времени сборки Используйте кэш для Go / deps. Запускайте линт/брейкинг только если изменились .proto или easyp.yaml (paths фильтр). Разделяйте workflow: быстрый линт в PR, тяжелая генерация в push на main. Вы","content":"Оптимизация времени сборки Используйте кэш для Go / deps. Запускайте линт/брейкинг только если изменились .proto или easyp.yaml (paths фильтр). Разделяйте workflow: быстрый линт в PR, тяжелая генерация в push на main. Выносите генерацию OpenAPI / gRPC-Gateway в отдельный job (параллелизм)."},{"id":"ci-cd/github-actions::workflow::42","title":"GitHub Actions","section":"Продвинутый workflow (многостадийный)","path":"/docs/guide/ci-cd/github-actions#workflow","headings":["Продвинутый workflow (многостадийный)"],"excerpt":"Продвинутый workflow (многостадийный) ```yaml name: easyp-pipeline","content":"Продвинутый workflow (многостадийный) ```yaml name: easyp-pipeline"},{"id":"ci-cd/github-actions::workflow::43","title":"GitHub Actions","section":"Продвинутый workflow (многостадийный)","path":"/docs/guide/ci-cd/github-actions#workflow","headings":["Продвинутый workflow (многостадийный)"],"excerpt":"Продвинутый workflow (многостадийный) on: pull_request: paths: - '**/*.proto' - 'easyp.yaml' push: branches: - main","content":"Продвинутый workflow (многостадийный) on: pull_request: paths: - '**/*.proto' - 'easyp.yaml' push: branches: - main"},{"id":"ci-cd/github-actions::workflow::44","title":"GitHub Actions","section":"Продвинутый workflow (многостадийный)","path":"/docs/guide/ci-cd/github-actions#workflow","headings":["Продвинутый workflow (многостадийный)"],"excerpt":"Продвинутый workflow (многостадийный) jobs: validate: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4","content":"Продвинутый workflow (многостадийный) jobs: validate: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4"},{"id":"ci-cd/github-actions::workflow::45","title":"GitHub Actions","section":"Продвинутый workflow (многостадийный)","path":"/docs/guide/ci-cd/github-actions#workflow","headings":["Продвинутый workflow (многостадийный)"],"excerpt":"Продвинутый workflow (многостадийный) uses: actions/setup-go@v5 with: go-version: '1.22'","content":"Продвинутый workflow (многостадийный) uses: actions/setup-go@v5 with: go-version: '1.22'"},{"id":"ci-cd/github-actions::workflow::46","title":"GitHub Actions","section":"Продвинутый workflow (многостадийный)","path":"/docs/guide/ci-cd/github-actions#workflow","headings":["Продвинутый workflow (многостадийный)"],"excerpt":"Продвинутый workflow (многостадийный) name: Install EasyP run: go install github.com/easyp-tech/easyp/cmd/easyp@latest","content":"Продвинутый workflow (многостадийный) name: Install EasyP run: go install github.com/easyp-tech/easyp/cmd/easyp@latest"},{"id":"ci-cd/github-actions::workflow::47","title":"GitHub Actions","section":"Продвинутый workflow (многостадийный)","path":"/docs/guide/ci-cd/github-actions#workflow","headings":["Продвинутый workflow (многостадийный)"],"excerpt":"Продвинутый workflow (многостадийный) name: Lint run: easyp lint","content":"Продвинутый workflow (многостадийный) name: Lint run: easyp lint"},{"id":"ci-cd/github-actions::workflow::48","title":"GitHub Actions","section":"Продвинутый workflow (многостадийный)","path":"/docs/guide/ci-cd/github-actions#workflow","headings":["Продвинутый workflow (многостадийный)"],"excerpt":"Продвинутый workflow (многостадийный) name: Breaking check (against main) if: github.event_name == 'pull_request' run: easyp breaking --against git-ref=origin/main","content":"Продвинутый workflow (многостадийный) name: Breaking check (against main) if: github.event_name == 'pull_request' run: easyp breaking --against git-ref=origin/main"},{"id":"ci-cd/github-actions::workflow::49","title":"GitHub Actions","section":"Продвинутый workflow (многостадийный)","path":"/docs/guide/ci-cd/github-actions#workflow","headings":["Продвинутый workflow (многостадийный)"],"excerpt":"Продвинутый workflow (многостадийный) generate: needs: validate if: github.event_name == 'push' runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-go@v5 with: go-version: '1.22' - name: Insta","content":"Продвинутый workflow (многостадийный) generate: needs: validate if: github.event_name == 'push' runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-go@v5 with: go-version: '1.22' - name: Install EasyP run: go install github.com/easyp-tech/easyp/cmd/easyp@latest - name: Generate Code run: easyp generate - name: Check diffs run: if [ -n \"$(git status --porcelain)\" ]; then echo \"Generated files changed after generate step.\" git diff --name-only exit 1 fi ```"},{"id":"ci-cd/github-actions::top::50","title":"GitHub Actions","section":"Автоматизация релиза (пример)","path":"/docs/guide/ci-cd/github-actions","headings":["Автоматизация релиза (пример)"],"excerpt":"Автоматизация релиза (пример) Можно добавить workflow, который по тегу создаёт релиз и валидирует proto:","content":"Автоматизация релиза (пример) Можно добавить workflow, который по тегу создаёт релиз и валидирует proto:"},{"id":"ci-cd/github-actions::top::51","title":"GitHub Actions","section":"Автоматизация релиза (пример)","path":"/docs/guide/ci-cd/github-actions","headings":["Автоматизация релиза (пример)"],"excerpt":"Автоматизация релиза (пример) ```yaml name: release-verify","content":"Автоматизация релиза (пример) ```yaml name: release-verify"},{"id":"ci-cd/github-actions::top::52","title":"GitHub Actions","section":"Автоматизация релиза (пример)","path":"/docs/guide/ci-cd/github-actions","headings":["Автоматизация релиза (пример)"],"excerpt":"Автоматизация релиза (пример) on: push: tags: - 'v*.*.*'","content":"Автоматизация релиза (пример) on: push: tags: - 'v*.*.*'"},{"id":"ci-cd/github-actions::top::53","title":"GitHub Actions","section":"Автоматизация релиза (пример)","path":"/docs/guide/ci-cd/github-actions","headings":["Автоматизация релиза (пример)"],"excerpt":"Автоматизация релиза (пример) jobs: release-check: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4","content":"Автоматизация релиза (пример) jobs: release-check: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4"},{"id":"ci-cd/github-actions::top::54","title":"GitHub Actions","section":"Автоматизация релиза (пример)","path":"/docs/guide/ci-cd/github-actions","headings":["Автоматизация релиза (пример)"],"excerpt":"Автоматизация релиза (пример) uses: actions/setup-go@v5 with: go-version: '1.22'","content":"Автоматизация релиза (пример) uses: actions/setup-go@v5 with: go-version: '1.22'"},{"id":"ci-cd/github-actions::top::55","title":"GitHub Actions","section":"Автоматизация релиза (пример)","path":"/docs/guide/ci-cd/github-actions","headings":["Автоматизация релиза (пример)"],"excerpt":"Автоматизация релиза (пример) name: Install EasyP run: go install github.com/easyp-tech/easyp/cmd/easyp@latest","content":"Автоматизация релиза (пример) name: Install EasyP run: go install github.com/easyp-tech/easyp/cmd/easyp@latest"},{"id":"ci-cd/github-actions::top::56","title":"GitHub Actions","section":"Автоматизация релиза (пример)","path":"/docs/guide/ci-cd/github-actions","headings":["Автоматизация релиза (пример)"],"excerpt":"Автоматизация релиза (пример) name: Lint run: easyp lint","content":"Автоматизация релиза (пример) name: Lint run: easyp lint"},{"id":"ci-cd/github-actions::top::57","title":"GitHub Actions","section":"Автоматизация релиза (пример)","path":"/docs/guide/ci-cd/github-actions","headings":["Автоматизация релиза (пример)"],"excerpt":"Автоматизация релиза (пример) name: Breaking vs previous tag run: PREV_TAG=$(git tag --sort=-creatordate grep -v \"${GITHUB_REF_NAME}\" head -n1 true) if [ -n \"$PREV_TAG\" ]; then echo \"Comparing against $PREV_TAG\" easyp br","content":"Автоматизация релиза (пример) name: Breaking vs previous tag run: PREV_TAG=$(git tag --sort=-creatordate grep -v \"${GITHUB_REF_NAME}\" head -n1 true) if [ -n \"$PREV_TAG\" ]; then echo \"Comparing against $PREV_TAG\" easyp breaking --against git-ref=$PREV_TAG else echo \"No previous tag, skipping breaking check\" fi"},{"id":"ci-cd/github-actions::top::58","title":"GitHub Actions","section":"Автоматизация релиза (пример)","path":"/docs/guide/ci-cd/github-actions","headings":["Автоматизация релиза (пример)"],"excerpt":"Автоматизация релиза (пример) name: Generate to ensure consistency run: easyp generate ```","content":"Автоматизация релиза (пример) name: Generate to ensure consistency run: easyp generate ```"},{"id":"ci-cd/github-actions::top::59","title":"GitHub Actions","section":"Отладка","path":"/docs/guide/ci-cd/github-actions","headings":["Отладка"],"excerpt":"Отладка Если нужно больше логов:","content":"Отладка Если нужно больше логов:"},{"id":"ci-cd/github-actions::top::60","title":"GitHub Actions","section":"Отладка","path":"/docs/guide/ci-cd/github-actions","headings":["Отладка"],"excerpt":"Отладка Добавьте вывод окружения для диагностики:","content":"Отладка Добавьте вывод окружения для диагностики:"},{"id":"ci-cd/github-actions::top::61","title":"GitHub Actions","section":"Переменные окружения (примерно)","path":"/docs/guide/ci-cd/github-actions","headings":["Переменные окружения (примерно)"],"excerpt":"Переменные окружения (примерно) Переменная Назначение ------------ ----------- EASYP_SERVICE_HOST Хост удалённого API Service (если используете удалённые плагины) EASYP_SERVICE_GRPC_PORT Порт удалённого сервиса GIT_SSH_C","content":"Переменные окружения (примерно) Переменная Назначение ------------ ----------- EASYP_SERVICE_HOST Хост удалённого API Service (если используете удалённые плагины) EASYP_SERVICE_GRPC_PORT Порт удалённого сервиса GIT_SSH_COMMAND Кастомная команда SSH (частные репозитории) GOFLAGS Можно выставить -mod=readonly для Go генерации"},{"id":"ci-cd/github-actions::top::62","title":"GitHub Actions","section":"Переменные окружения (примерно)","path":"/docs/guide/ci-cd/github-actions","headings":["Переменные окружения (примерно)"],"excerpt":"Переменные окружения (примерно) (Используйте только те, что действительно нужны вашему проекту.)","content":"Переменные окружения (примерно) (Используйте только те, что действительно нужны вашему проекту.)"},{"id":"ci-cd/github-actions::top::63","title":"GitHub Actions","section":"Частые ошибки","path":"/docs/guide/ci-cd/github-actions","headings":["Частые ошибки"],"excerpt":"Частые ошибки Симптом Причина Решение --------- --------- --------- Линт падает на неизвестных правилах Правила указаны в easyp.yaml, но версия EasyP их не поддерживает Обновить EasyP (go install ...@latest) breaking сра","content":"Частые ошибки Симптом Причина Решение --------- --------- --------- Линт падает на неизвестных правилах Правила указаны в easyp.yaml, но версия EasyP их не поддерживает Обновить EasyP (go install ...@latest) breaking сравнение ничего не находит Неверный --against (нет fetch удалённой ветки) Добавить шаг git fetch --all --tags Сгенерированный код в PR отличается от main Отсутствует проверка генерации в CI Добавить шаг «Ensure generated code is up-to-date» Приватные deps не скачиваются Нет SSH ключа или токена Настроить secrets + шаг подготовки SSH Долгое выполнение Отсутствует кеш Добавить кэширование модулей и deps"},{"id":"ci-cd/github-actions::top::64","title":"GitHub Actions","section":"Рекомендации по поддержке","path":"/docs/guide/ci-cd/github-actions","headings":["Рекомендации по поддержке"],"excerpt":"Рекомендации по поддержке Заготовить шаблон workflow и копировать между сервисами (DRY). Включить paths фильтры, чтобы не тратить минуты на нерелевантные изменения. Проверять easyp.yaml при изменениях отдельно — можно за","content":"Рекомендации по поддержке Заготовить шаблон workflow и копировать между сервисами (DRY). Включить paths фильтры, чтобы не тратить минуты на нерелевантные изменения. Проверять easyp.yaml при изменениях отдельно — можно запускать «конфигурационный тест» (например, easyp lint без файлов, чтобы убедиться, что конфиг валиден). При появлении новых правил линтера обновляйте конфиг и фиксируйте ошибки сразу в одной ветке."},{"id":"ci-cd/github-actions::top::65","title":"GitHub Actions","section":"Рекомендации по поддержке","path":"/docs/guide/ci-cd/github-actions","headings":["Рекомендации по поддержке"],"excerpt":"Рекомендации по поддержке Готово: вы можете расширять разделы генерации, добавлять OpenAPI / grpc-gateway / validate плагины, матрицы по языкам и интегрировать тесты поверх сгенерированного кода, если требуется.","content":"Рекомендации по поддержке Готово: вы можете расширять разделы генерации, добавлять OpenAPI / grpc-gateway / validate плагины, матрицы по языкам и интегрировать тесты поверх сгенерированного кода, если требуется."},{"id":"ci-cd/gitlab::top::0","title":"GitLab CI","section":"В процессе разработки","path":"/docs/guide/ci-cd/gitlab","headings":["В процессе разработки"],"excerpt":"В процессе разработки Документация по интеграции EasyP с GitLab CI находится в процессе подготовки. Планируемые разделы: Быстрый старт (пример .gitlab-ci.yml для линтинга и проверки несовместимых изменений) Кэширование з","content":"В процессе разработки Документация по интеграции EasyP с GitLab CI находится в процессе подготовки. Планируемые разделы: Быстрый старт (пример .gitlab-ci.yml для линтинга и проверки несовместимых изменений) Кэширование зависимостей и ускорение сборок Генерация кода и проверка актуальности артефактов Работа с приватными Git-репозиториями в deps Матрицы (parallel jobs) для разных языков и плагинов Автоматизация релизов по тегам"},{"id":"ci-cd/gitlab::top::1","title":"GitLab CI","section":"В процессе разработки","path":"/docs/guide/ci-cd/gitlab","headings":["В процессе разработки"],"excerpt":"В процессе разработки Если вам нужен пример прямо сейчас, базовый минимальный вариант может выглядеть так:","content":"В процессе разработки Если вам нужен пример прямо сейчас, базовый минимальный вариант может выглядеть так:"},{"id":"ci-cd/gitlab::top::2","title":"GitLab CI","section":"В процессе разработки","path":"/docs/guide/ci-cd/gitlab","headings":["В процессе разработки"],"excerpt":"В процессе разработки ```yaml stages: - validate - generate","content":"В процессе разработки ```yaml stages: - validate - generate"},{"id":"ci-cd/gitlab::top::3","title":"GitLab CI","section":"В процессе разработки","path":"/docs/guide/ci-cd/gitlab","headings":["В процессе разработки"],"excerpt":"В процессе разработки variables: GO_VERSION: \"1.22\"","content":"В процессе разработки variables: GO_VERSION: \"1.22\""},{"id":"ci-cd/gitlab::top::4","title":"GitLab CI","section":"В процессе разработки","path":"/docs/guide/ci-cd/gitlab","headings":["В процессе разработки"],"excerpt":"В процессе разработки validate: stage: validate image: golang:${GO_VERSION} before_script: - go install github.com/easyp-tech/easyp/cmd/easyp@latest - echo \"EasyP version:\" - easyp version # При необходимости: git fetch ","content":"В процессе разработки validate: stage: validate image: golang:${GO_VERSION} before_script: - go install github.com/easyp-tech/easyp/cmd/easyp@latest - echo \"EasyP version:\" - easyp version # При необходимости: git fetch --all --tags script: - easyp lint - easyp breaking --against git-ref=origin/main only: changes: - \"**/*.proto\" - \"easyp.yaml\""},{"id":"ci-cd/gitlab::top::5","title":"GitLab CI","section":"В процессе разработки","path":"/docs/guide/ci-cd/gitlab","headings":["В процессе разработки"],"excerpt":"В процессе разработки generate: stage: generate image: golang:${GO_VERSION} before_script: - go install github.com/easyp-tech/easyp/cmd/easyp@latest script: - easyp generate - if [ -n \"$(git status --porcelain)\" ]; then ","content":"В процессе разработки generate: stage: generate image: golang:${GO_VERSION} before_script: - go install github.com/easyp-tech/easyp/cmd/easyp@latest script: - easyp generate - if [ -n \"$(git status --porcelain)\" ]; then echo \"Сгенерированный код не актуален. Закоммитьте изменения локально.\" git diff --name-only exit 1 fi only: - main"},{"id":"ci-cd/gitlab::top::6","title":"GitLab CI","section":"В процессе разработки","path":"/docs/guide/ci-cd/gitlab","headings":["В процессе разработки"],"excerpt":"В процессе разработки Дополнительные рекомендации будут добавлены позже.","content":"В процессе разработки Дополнительные рекомендации будут добавлены позже."},{"id":"cli/auto-completion/auto-completion::zsh::0","title":"Автодополнение","section":"Автодополнение для zsh","path":"/docs/guide/cli/auto-completion/auto-completion#zsh","headings":["Автодополнение для zsh"],"excerpt":"Автодополнение для zsh Добавьте следующую строку в ваш файл запуска ~/.zshrc:","content":"Автодополнение для zsh Добавьте следующую строку в ваш файл запуска ~/.zshrc:"},{"id":"cli/auto-completion/auto-completion::zsh::1","title":"Автодополнение","section":"Автодополнение для zsh","path":"/docs/guide/cli/auto-completion/auto-completion#zsh","headings":["Автодополнение для zsh"],"excerpt":"Автодополнение для zsh Перезапустите оболочку или выполните:","content":"Автодополнение для zsh Перезапустите оболочку или выполните:"},{"id":"cli/auto-completion/auto-completion::bash::2","title":"Автодополнение","section":"Автодополнение для Bash","path":"/docs/guide/cli/auto-completion/auto-completion#bash","headings":["Автодополнение для Bash"],"excerpt":"Автодополнение для Bash Установите bash-completion и подключите его в ~/.bashrc. Добавьте следующую строку в файл запуска ~/.bashrc:","content":"Автодополнение для Bash Установите bash-completion и подключите его в ~/.bashrc. Добавьте следующую строку в файл запуска ~/.bashrc:"},{"id":"cli/auto-completion/auto-completion::bash::3","title":"Автодополнение","section":"Автодополнение для Bash","path":"/docs/guide/cli/auto-completion/auto-completion#bash","headings":["Автодополнение для Bash"],"excerpt":"Автодополнение для Bash Перезапустите оболочку или выполните:","content":"Автодополнение для Bash Перезапустите оболочку или выполните:"},{"id":"cli/auto-completion/auto-completion::top::4","title":"Автодополнение","section":"Примечания","path":"/docs/guide/cli/auto-completion/auto-completion","headings":["Примечания"],"excerpt":"Примечания Команда easyp completion выводит скрипт автодополнения для соответствующей оболочки. Если используете другую оболочку (например, fish), можно сгенерировать вывод и сохранить вручную: При обновлении версии Easy","content":"Примечания Команда easyp completion выводит скрипт автодополнения для соответствующей оболочки. Если используете другую оболочку (например, fish), можно сгенерировать вывод и сохранить вручную: При обновлении версии EasyP рекомендуется заново перезагрузить оболочку, чтобы подтянуть возможные изменения в автодополнении."},{"id":"cli/breaking-changes/breaking-changes::top::0","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":[],"excerpt":"Обнаружение несовместимых изменений (Breaking Changes Detection)","content":"Обнаружение несовместимых изменений (Breaking Changes Detection)"},{"id":"cli/breaking-changes/breaking-changes::top::1","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":[],"excerpt":"Механизм EasyP для обнаружения несовместимых (breaking) изменений помогает поддерживать обратную совместимость ваших protobuf API, автоматически выявляя изменения, способные сломать существующих клиентов. Это критично дл","content":"Механизм EasyP для обнаружения несовместимых (breaking) изменений помогает поддерживать обратную совместимость ваших protobuf API, автоматически выявляя изменения, способные сломать существующих клиентов. Это критично для стабильных API в продакшене."},{"id":"cli/breaking-changes/breaking-changes::top::2","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Обзор","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Обзор"],"excerpt":"Обзор Проверка несовместимых изменений сравнивает текущий набор protobuf‑файлов с предыдущей версией (обычно из другой Git ветки) и фиксирует модификации, которые могут вызвать проблемы совместимости для уже работающих к","content":"Обзор Проверка несовместимых изменений сравнивает текущий набор protobuf‑файлов с предыдущей версией (обычно из другой Git ветки) и фиксирует модификации, которые могут вызвать проблемы совместимости для уже работающих клиентов."},{"id":"cli/breaking-changes/breaking-changes::top::3","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Ключевые возможности","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Ключевые возможности"],"excerpt":"Ключевые возможности **Сравнение через Git**: Сопоставление с любой Git‑ссылкой (ветка, тег, commit) **Комплексный анализ**: Проверка сервисов, сообщений, enum'ов, полей и import'ов **Выборочное игнорирование**: Пропуск ","content":"Ключевые возможности **Сравнение через Git**: Сопоставление с любой Git‑ссылкой (ветка, тег, commit) **Комплексный анализ**: Проверка сервисов, сообщений, enum'ов, полей и import'ов **Выборочное игнорирование**: Пропуск указанных директорий из анализа **Детализированные отчёты**: Понятные ошибки с именами файлов, строками и позициями"},{"id":"cli/breaking-changes/breaking-changes::top::4","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Как работает","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Как работает"],"excerpt":"Как работает Детектор breaking changes выполняет следующие шаги:","content":"Как работает Детектор breaking changes выполняет следующие шаги:"},{"id":"cli/breaking-changes/breaking-changes::top::5","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Как работает","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Как работает"],"excerpt":"Как работает **Получение ветки сравнения**: Забирает proto-файлы из указанной Git‑ссылки **Парсинг обеих версий**: Анализирует структуру текущих и предыдущих файлов **Сравнение сущностей**: Последовательно проверяет все ","content":"Как работает **Получение ветки сравнения**: Забирает proto-файлы из указанной Git‑ссылки **Парсинг обеих версий**: Анализирует структуру текущих и предыдущих файлов **Сравнение сущностей**: Последовательно проверяет все элементы protobuf на breaking изменения **Формирование отчёта**: Генерирует подробные записи об ошибках с локациями и описаниями"},{"id":"cli/breaking-changes/breaking-changes::top::6","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Уровень проверки","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Уровень проверки"],"excerpt":"Уровень проверки EasyP реализует уровень проверки **WIRE+**: ✅ **Полная совместимость по wire‑формату** — старые и новые версии могут обмениваться данными ✅ **Обнаружение удалений элементов** — сервисы, сообщения, поля и","content":"Уровень проверки EasyP реализует уровень проверки **WIRE+**: ✅ **Полная совместимость по wire‑формату** — старые и новые версии могут обмениваться данными ✅ **Обнаружение удалений элементов** — сервисы, сообщения, поля и т.п. ✅ **Безопасность типов** — выявляет несовместимые изменения типов ❌ **Переименования полей/методов** — пока не детектируются (в планах) ❌ **Изменения на уровне файлов** — переносы пакетов, file options ещё не проверяются"},{"id":"cli/breaking-changes/breaking-changes::top::7","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Уровень проверки","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Уровень проверки"],"excerpt":"Уровень проверки Это даёт сильные гарантии совместимости и меньше ограничений, чем инструменты, требующие совместимости сгенерированного кода.","content":"Уровень проверки Это даёт сильные гарантии совместимости и меньше ограничений, чем инструменты, требующие совместимости сгенерированного кода."},{"id":"cli/breaking-changes/breaking-changes::top::8","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Конфигурация","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Конфигурация"],"excerpt":"Конфигурация Настройка в easyp.yaml:","content":"Конфигурация Настройка в easyp.yaml:"},{"id":"cli/breaking-changes/breaking-changes::top::9","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Параметры конфигурации","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Параметры конфигурации"],"excerpt":"Параметры конфигурации Option Description Default Required -------- ------------- --------- ---------- against_git_ref Git‑ссылка для сравнения \"master\" No ignore Список директорий для исключения из анализа [] No","content":"Параметры конфигурации Option Description Default Required -------- ------------- --------- ---------- against_git_ref Git‑ссылка для сравнения \"master\" No ignore Список директорий для исключения из анализа [] No"},{"id":"cli/breaking-changes/breaking-changes::top::10","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Базовый пример","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Базовый пример"],"excerpt":"Базовый пример Сравнение текущих изменений с веткой main:","content":"Базовый пример Сравнение текущих изменений с веткой main:"},{"id":"cli/breaking-changes/breaking-changes::top::11","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Использование файла конфигурации","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Использование файла конфигурации"],"excerpt":"Использование файла конфигурации","content":"Использование файла конфигурации"},{"id":"cli/breaking-changes/breaking-changes::top::12","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Уровень проверки","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Уровень проверки"],"excerpt":"Уровень проверки EasyP сейчас работает на уровне **WIRE+**, обеспечивая совместимость wire‑формата плюс защиту от удалений и изменения критичных типов.","content":"Уровень проверки EasyP сейчас работает на уровне **WIRE+**, обеспечивая совместимость wire‑формата плюс защиту от удалений и изменения критичных типов."},{"id":"cli/breaking-changes/breaking-changes::buf::13","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Сравнение с категориями Buf","path":"/docs/guide/cli/breaking-changes/breaking-changes#buf","headings":["Сравнение с категориями Buf"],"excerpt":"Сравнение с категориями Buf Check Type Buf WIRE Buf WIRE_JSON Buf FILE EasyP Current ------------ ---------- --------------- ---------- --------------- **Element Deletions** Service deletion ❌ ❌ ✅ ✅ RPC method deletion ❌","content":"Сравнение с категориями Buf 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::top::14","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Что это означает","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Что это означает"],"excerpt":"Что это означает **✅ EasyP обнаружит:** Все breaking изменения wire‑формата Удаления сервисов, методов, сообщений, полей Изменения типов, ломающие сериализацию Переименования enum‑значений (при сохранении номера)","content":"Что это означает **✅ EasyP обнаружит:** Все breaking изменения wire‑формата Удаления сервисов, методов, сообщений, полей Изменения типов, ломающие сериализацию Переименования enum‑значений (при сохранении номера)"},{"id":"cli/breaking-changes/breaking-changes::top::15","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Что это означает","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Что это означает"],"excerpt":"Что это означает **❌ EasyP НЕ обнаружит:** Переименование полей (с тем же номером) Изменение package File options (go_package, java_package, и т.п.) Перемещение типов между файлами в одном package","content":"Что это означает **❌ EasyP НЕ обнаружит:** Переименование полей (с тем же номером) Изменение package File options (go_package, java_package, и т.п.) Перемещение типов между файлами в одном package"},{"id":"cli/breaking-changes/breaking-changes::breaking-changes::16","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Правила Breaking Changes","path":"/docs/guide/cli/breaking-changes/breaking-changes#breaking-changes","headings":["Правила Breaking Changes"],"excerpt":"Правила Breaking Changes EasyP обнаруживает следующие типы breaking изменений:","content":"Правила Breaking Changes EasyP обнаруживает следующие типы breaking изменений:"},{"id":"cli/breaking-changes/breaking-changes::top::17","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Сравнение уровней","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Сравнение уровней"],"excerpt":"Сравнение уровней Detection Level Description EasyP Support ---------------- ------------- --------------- **WIRE** Совместимость только по wire‑формату ✅ **Full support** **WIRE+** Wire + обнаружение удалений ✅ **Curren","content":"Сравнение уровней Detection Level Description EasyP Support ---------------- ------------- --------------- **WIRE** Совместимость только по wire‑формату ✅ **Full support** **WIRE+** Wire + обнаружение удалений ✅ **Current level** **FILE** Совместимость сгенерированного кода ❌ Partial (planned)"},{"id":"cli/breaking-changes/breaking-changes::top::18","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Категории правил","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Категории правил"],"excerpt":"Категории правил Каждая категория имеет свою документацию с примерами:","content":"Категории правил Каждая категория имеет свою документацию с примерами:"},{"id":"cli/breaking-changes/breaking-changes::service-rpc::19","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"🚨 Изменения Service и RPC","path":"/docs/guide/cli/breaking-changes/breaking-changes#service-rpc","headings":["🚨 Изменения Service и RPC"],"excerpt":"🚨 Изменения Service и RPC 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 и RPC 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-field::20","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"📦 Изменения Message и Field","path":"/docs/guide/cli/breaking-changes/breaking-changes#message-field","headings":["📦 Изменения Message и Field"],"excerpt":"📦 Изменения Message и Field 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 и Field 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::21","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"🔢 Изменения Enum","path":"/docs/guide/cli/breaking-changes/breaking-changes#enum","headings":["🔢 Изменения Enum"],"excerpt":"🔢 Изменения Enum 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 val","content":"🔢 Изменения Enum 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::22","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"🔗 Изменения OneOf","path":"/docs/guide/cli/breaking-changes/breaking-changes#oneof","headings":["🔗 Изменения OneOf"],"excerpt":"🔗 Изменения OneOf Rule Description Status ------ ------------- --------- ONEOF_NO_DELETE OneOf fields cannot be deleted ✅ Implemented ONEOF_FIELD_NO_DELETE Fields within oneofs cannot be deleted ✅ Implemented ONEOF_FIEL","content":"🔗 Изменения OneOf 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::23","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"📥 Изменения Import","path":"/docs/guide/cli/breaking-changes/breaking-changes#import","headings":["📥 Изменения Import"],"excerpt":"📥 Изменения Import Rule Description Status ------ ------------- --------- IMPORT_NO_DELETE Import statements cannot be removed ✅ Implemented","content":"📥 Изменения Import Rule Description Status ------ ------------- --------- IMPORT_NO_DELETE Import statements cannot be removed ✅ Implemented"},{"id":"cli/breaking-changes/breaking-changes::top::24","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Не обнаруживается сейчас","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Не обнаруживается сейчас"],"excerpt":"Не обнаруживается сейчас Изменения ниже **НЕ детектируются** EasyP (могут ломать сгенерированный код):","content":"Не обнаруживается сейчас Изменения ниже **НЕ детектируются** EasyP (могут ломать сгенерированный код):"},{"id":"cli/breaking-changes/breaking-changes::top::25","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Не обнаруживается сейчас","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Не обнаруживается сейчас"],"excerpt":"Не обнаруживается сейчас Change Type Example Impact ------------- --------- -------- Field renaming string name = 1 → string full_name = 1 Ломает код Package changes package v1 → package v2 Меняются пути импорта File opt","content":"Не обнаруживается сейчас Change Type Example Impact ------------- --------- -------- Field renaming string name = 1 → string full_name = 1 Ломает код Package changes package v1 → package v2 Меняются пути импорта File options option go_package = \"old\" → option go_package = \"new\" Меняется расположение кода Moving between files Message перемещено в другой .proto Зависимости import'ов"},{"id":"cli/breaking-changes/breaking-changes::top::26","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Документация правил","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Документация правил"],"excerpt":"Документация правил См. подробные файлы правил для примеров и стратегий миграции:","content":"Документация правил См. подробные файлы правил для примеров и стратегий миграции:"},{"id":"cli/breaking-changes/breaking-changes::top::27","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Документация правил","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Документация правил"],"excerpt":"Документация правил Service: SERVICE_NO_DELETE, RPC_NO_DELETE, RPC_SAME_REQUEST_TYPE, RPC_SAME_RESPONSE_TYPE Message: MESSAGE_NO_DELETE, FIELD_NO_DELETE, FIELD_SAME_TYPE, FIELD_SAME_CARDINALITY Enum: ENUM_NO_DELETE, ENUM","content":"Документация правил Service: SERVICE_NO_DELETE, RPC_NO_DELETE, RPC_SAME_REQUEST_TYPE, RPC_SAME_RESPONSE_TYPE Message: MESSAGE_NO_DELETE, FIELD_NO_DELETE, FIELD_SAME_TYPE, FIELD_SAME_CARDINALITY Enum: ENUM_NO_DELETE, ENUM_VALUE_NO_DELETE, ENUM_VALUE_SAME_NAME OneOf: ONEOF_NO_DELETE, ONEOF_FIELD_NO_DELETE, ONEOF_FIELD_SAME_TYPE Import: IMPORT_NO_DELETE"},{"id":"cli/breaking-changes/breaking-changes::top::28","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Документация правил","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Документация правил"],"excerpt":"Документация правил Каждое правило содержит: ❌ Плохие примеры (breaking) ✅ Безопасные альтернативы 🔧 Стратегии миграции 📋 Реальные сообщения ошибок из EasyP","content":"Документация правил Каждое правило содержит: ❌ Плохие примеры (breaking) ✅ Безопасные альтернативы 🔧 Стратегии миграции 📋 Реальные сообщения ошибок из EasyP"},{"id":"cli/breaking-changes/breaking-changes::top::29","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"✅ Безопасные изменения (разрешены всегда)","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["✅ Безопасные изменения (разрешены всегда)"],"excerpt":"✅ Безопасные изменения (разрешены всегда) ```proto // Добавление новых элементов — безопасно message User { string name = 1; string email = 2; string phone = 3; // ✅ Новое поле }","content":"✅ Безопасные изменения (разрешены всегда) ```proto // Добавление новых элементов — безопасно message User { string name = 1; string email = 2; string phone = 3; // ✅ Новое поле }"},{"id":"cli/breaking-changes/breaking-changes::top::30","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"✅ Безопасные изменения (разрешены всегда)","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["✅ Безопасные изменения (разрешены всегда)"],"excerpt":"✅ Безопасные изменения (разрешены всегда) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc GetUserProfile(GetUserRequest) returns (UserProfile); // ✅ Новый RPC }","content":"✅ Безопасные изменения (разрешены всегда) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc GetUserProfile(GetUserRequest) returns (UserProfile); // ✅ Новый RPC }"},{"id":"cli/breaking-changes/breaking-changes::top::31","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"✅ Безопасные изменения (разрешены всегда)","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["✅ Безопасные изменения (разрешены всегда)"],"excerpt":"✅ Безопасные изменения (разрешены всегда) enum Status { STATUS_UNSPECIFIED = 0; STATUS_ACTIVE = 1; STATUS_PENDING = 2; // ✅ Новое enum значение } ```","content":"✅ Безопасные изменения (разрешены всегда) enum Status { STATUS_UNSPECIFIED = 0; STATUS_ACTIVE = 1; STATUS_PENDING = 2; // ✅ Новое enum значение } ```"},{"id":"cli/breaking-changes/breaking-changes::top::32","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"❌ Несовместимые изменения (обнаруживаются всегда)","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["❌ Несовместимые изменения (обнаруживаются всегда)"],"excerpt":"❌ Несовместимые изменения (обнаруживаются всегда) ```proto // Удаления и смена типов ломают совместимость message User { string name = 1; // ❌ Удалённое поле }","content":"❌ Несовместимые изменения (обнаруживаются всегда) ```proto // Удаления и смена типов ломают совместимость message User { string name = 1; // ❌ Удалённое поле }"},{"id":"cli/breaking-changes/breaking-changes::top::33","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"❌ Несовместимые изменения (обнаруживаются всегда)","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["❌ Несовместимые изменения (обнаруживаются всегда)"],"excerpt":"❌ Несовместимые изменения (обнаруживаются всегда) service UserService { // ❌ Удалённый RPC метод rpc GetUser(GetUserRequestV2) returns (GetUserResponse); // ❌ Изменён тип запроса } ```","content":"❌ Несовместимые изменения (обнаруживаются всегда) service UserService { // ❌ Удалённый RPC метод rpc GetUser(GetUserRequestV2) returns (GetUserResponse); // ❌ Изменён тип запроса } ```"},{"id":"cli/breaking-changes/breaking-changes::top::34","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Сценарий: Изменения пока не детектируются","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Сценарий: Изменения пока не детектируются"],"excerpt":"Сценарий: Изменения пока не детектируются ```proto // 🟡 Ломает сгенерированный код, но проходит проверки EasyP message User { string user_name = 1; // Переименовано с \"name\" string user_email = 2; // Переименовано с \"em","content":"Сценарий: Изменения пока не детектируются ```proto // 🟡 Ломает сгенерированный код, но проходит проверки EasyP message User { string user_name = 1; // Переименовано с \"name\" string user_email = 2; // Переименовано с \"email\" }"},{"id":"cli/breaking-changes/breaking-changes::top::35","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Сценарий: Изменения пока не детектируются","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Сценарий: Изменения пока не детектируются"],"excerpt":"Сценарий: Изменения пока не детектируются service UserService { rpc GetUserProfile(GetUserRequest) returns (GetUserResponse); // Переименовано с GetUser } ```","content":"Сценарий: Изменения пока не детектируются service UserService { rpc GetUserProfile(GetUserRequest) returns (GetUserResponse); // Переименовано с GetUser } ```"},{"id":"cli/breaking-changes/breaking-changes::top::36","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Текстовый формат (по умолчанию)","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Текстовый формат (по умолчанию)"],"excerpt":"Текстовый формат (по умолчанию)","content":"Текстовый формат (по умолчанию)"},{"id":"cli/breaking-changes/breaking-changes::1::37","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"1. Регулярный запуск","path":"/docs/guide/cli/breaking-changes/breaking-changes#1","headings":["1. Регулярный запуск"],"excerpt":"Регулярный запуск Добавьте проверку несовместимых изменений в CI/CD:","content":"Регулярный запуск Добавьте проверку несовместимых изменений в CI/CD:"},{"id":"cli/breaking-changes/breaking-changes::2::38","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"2. Защита веток","path":"/docs/guide/cli/breaking-changes/breaking-changes#2","headings":["2. Защита веток"],"excerpt":"Защита веток Блокируйте слияния с breaking изменениями:","content":"Защита веток Блокируйте слияния с breaking изменениями:"},{"id":"cli/breaking-changes/breaking-changes::3::39","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"3. Стратегия версионирования","path":"/docs/guide/cli/breaking-changes/breaking-changes#3","headings":["3. Стратегия версионирования"],"excerpt":"Стратегия версионирования При необходимости breaking изменений: Создайте новую версию пакета (myservice.v2) Поддерживайте старую версию в период миграции Добавляйте уведомления о деприкации","content":"Стратегия версионирования При необходимости breaking изменений: Создайте новую версию пакета (myservice.v2) Поддерживайте старую версию в период миграции Добавляйте уведомления о деприкации"},{"id":"cli/breaking-changes/breaking-changes::4::40","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"4. Игнорирование путей","path":"/docs/guide/cli/breaking-changes/breaking-changes#4","headings":["4. Игнорирование путей"],"excerpt":"Игнорирование путей Используйте ignore осознанно:","content":"Игнорирование путей Используйте ignore осознанно:"},{"id":"cli/breaking-changes/breaking-changes::repository-does-not-exist::41","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Проблема: \"Repository does not exist\"","path":"/docs/guide/cli/breaking-changes/breaking-changes#repository-does-not-exist","headings":["Проблема: \"Repository does not exist\""],"excerpt":"Проблема: \"Repository does not exist\" Решение: Выполняйте команду внутри Git репозитория с нужной веткой.","content":"Проблема: \"Repository does not exist\" Решение: Выполняйте команду внутри Git репозитория с нужной веткой."},{"id":"cli/breaking-changes/breaking-changes::cannot-find-git-ref::42","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Проблема: \"Cannot find git ref\"","path":"/docs/guide/cli/breaking-changes/breaking-changes#cannot-find-git-ref","headings":["Проблема: \"Cannot find git ref\""],"excerpt":"Проблема: \"Cannot find git ref\" Решение: Проверьте наличие ссылки:","content":"Проблема: \"Cannot find git ref\" Решение: Проверьте наличие ссылки:"},{"id":"cli/breaking-changes/breaking-changes::top::43","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Проблема: Ложные срабатывания на сгенерированный код","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Проблема: Ложные срабатывания на сгенерированный код"],"excerpt":"Проблема: Ложные срабатывания на сгенерированный код Решение: Исключите директории генерации:","content":"Проблема: Ложные срабатывания на сгенерированный код Решение: Исключите директории генерации:"},{"id":"cli/breaking-changes/breaking-changes::top::44","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Проблема: Очень много изменений","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Проблема: Очень много изменений"],"excerpt":"Проблема: Очень много изменений Решение: Создайте новую версию API Вносите изменения постепенно Используйте feature flags","content":"Проблема: Очень много изменений Решение: Создайте новую версию API Вносите изменения постепенно Используйте feature flags"},{"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 - name: Install EasyP run: curl -sSfL https://raw.githubusercontent.com/easyp-tech/easyp/main/install.","content":"GitHub Actions jobs: breaking-changes: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 with: fetch-depth: 0 - 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-pre-push-hook::48","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Pre-commit / pre-push hook","path":"/docs/guide/cli/breaking-changes/breaking-changes#pre-commit-pre-push-hook","headings":["Pre-commit / pre-push hook"],"excerpt":"Pre-commit / pre-push hook ```bash #!/bin/sh .git/hooks/pre-push","content":"Pre-commit / pre-push hook ```bash #!/bin/sh .git/hooks/pre-push"},{"id":"cli/breaking-changes/breaking-changes::pre-commit-pre-push-hook::49","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Pre-commit / pre-push hook","path":"/docs/guide/cli/breaking-changes/breaking-changes#pre-commit-pre-push-hook","headings":["Pre-commit / pre-push hook"],"excerpt":"Pre-commit / pre-push hook protected_branch='main' current_branch=$(git symbolic-ref HEAD sed -e 's,.*/\\(.*\\),\\1,')","content":"Pre-commit / pre-push hook protected_branch='main' current_branch=$(git symbolic-ref HEAD sed -e 's,.*/\\(.*\\),\\1,')"},{"id":"cli/breaking-changes/breaking-changes::pre-commit-pre-push-hook::50","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Pre-commit / pre-push hook","path":"/docs/guide/cli/breaking-changes/breaking-changes#pre-commit-pre-push-hook","headings":["Pre-commit / pre-push hook"],"excerpt":"Pre-commit / pre-push 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.","content":"Pre-commit / pre-push 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::top::51","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Режим отладки","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Режим отладки"],"excerpt":"Режим отладки Включите debug‑логирование:","content":"Режим отладки Включите debug‑логирование:"},{"id":"cli/breaking-changes/breaking-changes::top::52","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Ручное сравнение","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Ручное сравнение"],"excerpt":"Ручное сравнение Для сложных случаев:","content":"Ручное сравнение Для сложных случаев:"},{"id":"cli/breaking-changes/breaking-changes::top::53","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Оптимизация производительности","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Оптимизация производительности"],"excerpt":"Оптимизация производительности Ограничьте область:","content":"Оптимизация производительности Ограничьте область:"},{"id":"cli/breaking-changes/breaking-changes::top::54","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Оптимизация производительности","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Оптимизация производительности"],"excerpt":"Оптимизация производительности","content":"Оптимизация производительности"},{"id":"cli/breaking-changes/breaking-changes::top::55","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Оптимизация производительности","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Оптимизация производительности"],"excerpt":"Оптимизация производительности Механизм обнаружения несовместимых изменений в EasyP обеспечивает надёжную основу для безопасной эволюции protobuf‑схем при сохранении совместимости API.","content":"Оптимизация производительности Механизм обнаружения несовместимых изменений в EasyP обеспечивает надёжную основу для безопасной эволюции protobuf‑схем при сохранении совместимости API."},{"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":"Это правило проверяет, что ни один enum не был удалён из proto‑файлов. Удаление enum ломает совместимость по wire‑формату и сгенерированный код: сохранённые данные могут содержать удалённые значения, а клиентский код опи","content":"Это правило проверяет, что ни один enum не был удалён из proto‑файлов. Удаление enum ломает совместимость по wire‑формату и сгенерированный код: сохранённые данные могут содержать удалённые значения, а клиентский код опирается на сгенерированные типы и константы enum."},{"id":"cli/breaking-changes/rules/enum-no-delete::breaking::1","title":"ENUM_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-no-delete::breaking::2","title":"ENUM_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/enum-no-delete::breaking::3","title":"ENUM_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_CONFIRMED = 2; ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_DELIVERED = 4; }","content":"Плохой (Breaking) 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::breaking::4","title":"ENUM_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) enum UserRole { // [!code --] USER_ROLE_UNSPECIFIED = 0; // [!code --] USER_ROLE_ADMIN = 1; // [!code --] USER_ROLE_USER = 2; // [!code --] } // [!code --]","content":"Плохой (Breaking) 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::breaking::5","title":"ENUM_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message Order { string id = 1; OrderStatus status = 2; UserRole created_by_role = 3; } ```","content":"Плохой (Breaking) message Order { string id = 1; OrderStatus status = 2; UserRole created_by_role = 3; } ```"},{"id":"cli/breaking-changes/rules/enum-no-delete::breaking::6","title":"ENUM_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-no-delete::breaking::7","title":"ENUM_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/enum-no-delete::breaking::8","title":"ENUM_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_CONFIRMED = 2; ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_DELIVERED = 4; }","content":"Плохой (Breaking) 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::breaking::9","title":"ENUM_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) // UserRole enum удалён — BREAKING CHANGE!","content":"Плохой (Breaking) // UserRole enum удалён — BREAKING CHANGE!"},{"id":"cli/breaking-changes/rules/enum-no-delete::breaking::10","title":"ENUM_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message Order { string id = 1; OrderStatus status = 2; UserRole created_by_role = 3; // ERROR: UserRole больше не существует } ```","content":"Плохой (Breaking) message Order { string id = 1; OrderStatus status = 2; UserRole created_by_role = 3; // ERROR: UserRole больше не существует } ```"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::11","title":"ENUM_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры **Удаление вложенного enum:** ```proto // Before message User { string name = 1; Status status = 2; enum Status { // [!code --] STATUS_UNSPECIFIED = 0; // [!code --] STATUS_ACTIVE = 1; // [!code --","content":"Дополнительные примеры **Удаление вложенного enum:** ```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::top::12","title":"ENUM_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры // After - BREAKING CHANGE! message User { string name = 1; Status status = 2; // ERROR: Status удалён // Вложенный enum Status удалён } ```","content":"Дополнительные примеры // After - BREAKING CHANGE! message User { string name = 1; Status status = 2; // ERROR: Status удалён // Вложенный enum Status удалён } ```"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::13","title":"ENUM_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо удаления — пометить enum deprecated:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо удаления — пометить enum deprecated:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::14","title":"ENUM_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::15","title":"ENUM_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_CONFIRMED = 2; ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_DELIVERED = 4; }","content":"Хороший (Безопасный) 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::top::16","title":"ENUM_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) enum UserRole { option deprecated = true; // [!code focus] USER_ROLE_UNSPECIFIED = 0; USER_ROLE_ADMIN = 1; USER_ROLE_USER = 2; }","content":"Хороший (Безопасный) 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::top::17","title":"ENUM_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message Order { string id = 1; OrderStatus status = 2; UserRole created_by_role = 3 [deprecated = true]; // [!code focus] } ```","content":"Хороший (Безопасный) 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::top::18","title":"ENUM_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Или заменить новым enum:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Или заменить новым enum:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::19","title":"ENUM_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::20","title":"ENUM_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_CONFIRMED = 2; ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_DELIVERED = 4; }","content":"Хороший (Безопасный) 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::top::21","title":"ENUM_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) enum UserRole { option deprecated = true; // [!code focus] // Старый enum USER_ROLE_UNSPECIFIED = 0; USER_ROLE_ADMIN = 1; USER_ROLE_USER = 2; }","content":"Хороший (Безопасный) enum UserRole { option deprecated = true; // [!code focus] // Старый enum USER_ROLE_UNSPECIFIED = 0; USER_ROLE_ADMIN = 1; USER_ROLE_USER = 2; }"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::22","title":"ENUM_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) enum UserPermission { // [!code focus] // Новый enum USER_PERMISSION_UNSPECIFIED = 0; // [!code focus] USER_PERMISSION_READ = 1; // [!code focus] USER_PERMISSION_WRITE = 2; // [!code focus] USER_PERM","content":"Хороший (Безопасный) enum UserPermission { // [!code focus] // Новый enum 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::top::23","title":"ENUM_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message Order { string id = 1; OrderStatus status = 2; UserRole created_by_role = 3 [deprecated = true]; // [!code focus] UserPermission created_by_permission = 4; // [!code focus] } ```","content":"Хороший (Безопасный) message Order { string id = 1; OrderStatus status = 2; UserRole created_by_role = 3 [deprecated = true]; // [!code focus] UserPermission created_by_permission = 4; // [!code focus] } ```"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::24","title":"ENUM_NO_DELETE","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Влияние"],"excerpt":"Влияние **Wire Format:** Данные с удалённым enum не десериализуются корректно **Generated Code:** Тип и константы удаляются — компиляция клиентов ломается **Field References:** Поля с типом удалённого enum становятся нев","content":"Влияние **Wire Format:** Данные с удалённым enum не десериализуются корректно **Generated Code:** Тип и константы удаляются — компиляция клиентов ломается **Field References:** Поля с типом удалённого enum становятся невалидны **Switch Statements:** switch по enum ломается (неизвестные кейсы)"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::25","title":"ENUM_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Код клиента ломается:** ```go // Before order := &myapi.Order{ Id: \"order123\", Status: myapi.OrderStatus_ORDER_STATUS_PENDING, CreatedByRole: myapi.UserRole_USER_ROLE_ADMIN, // ERROR после удаления }","content":"Реальный пример **Код клиента ломается:** ```go // Before order := &myapi.Order{ Id: \"order123\", Status: myapi.OrderStatus_ORDER_STATUS_PENDING, CreatedByRole: myapi.UserRole_USER_ROLE_ADMIN, // ERROR после удаления }"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::26","title":"ENUM_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример switch order.CreatedByRole { case myapi.UserRole_USER_ROLE_ADMIN: // ERROR // Admin logic case myapi.UserRole_USER_ROLE_USER: // ERROR // User logic }","content":"Реальный пример switch order.CreatedByRole { case myapi.UserRole_USER_ROLE_ADMIN: // ERROR // Admin logic case myapi.UserRole_USER_ROLE_USER: // ERROR // User logic }"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::27","title":"ENUM_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример // undefined: myapi.UserRole // undefined: myapi.UserRole_USER_ROLE_ADMIN ```","content":"Реальный пример // undefined: myapi.UserRole // undefined: myapi.UserRole_USER_ROLE_ADMIN ```"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::28","title":"ENUM_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Старые данные становятся нечитаемыми:**","content":"Реальный пример **Старые данные становятся нечитаемыми:**"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::29","title":"ENUM_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Серверная логика ломается:**","content":"Реальный пример **Серверная логика ломается:**"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::30","title":"ENUM_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Депрецируйте enum:** **Пометьте поля со старым enum deprecated:** **Создайте новый enum:** **Сервер обрабатывает оба:** **Удалите старый enum в следующей major‑версии.**","content":"Стратегия миграции **Депрецируйте enum:** **Пометьте поля со старым enum deprecated:** **Создайте новый enum:** **Сервер обрабатывает оба:** **Удалите старый enum в следующей major‑версии.**"},{"id":"cli/breaking-changes/rules/enum-no-delete::enum::31","title":"ENUM_NO_DELETE","section":"Редизайн enum","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#enum","headings":["Редизайн enum"],"excerpt":"Редизайн enum ```proto enum Priority { option deprecated = true; PRIORITY_UNSPECIFIED = 0; PRIORITY_LOW = 1; PRIORITY_HIGH = 2; }","content":"Редизайн enum ```proto enum Priority { option deprecated = true; PRIORITY_UNSPECIFIED = 0; PRIORITY_LOW = 1; PRIORITY_HIGH = 2; }"},{"id":"cli/breaking-changes/rules/enum-no-delete::enum::32","title":"ENUM_NO_DELETE","section":"Редизайн enum","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#enum","headings":["Редизайн enum"],"excerpt":"Редизайн enum enum TaskPriority { TASK_PRIORITY_UNSPECIFIED = 0; TASK_PRIORITY_LOW = 1; TASK_PRIORITY_MEDIUM = 2; TASK_PRIORITY_HIGH = 3; TASK_PRIORITY_URGENT = 4; } ```","content":"Редизайн enum enum TaskPriority { 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::enum::33","title":"ENUM_NO_DELETE","section":"Консолидация enum","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#enum","headings":["Консолидация enum"],"excerpt":"Консолидация enum ```proto enum Status { option deprecated = true; STATUS_UNSPECIFIED = 0; STATUS_ACTIVE = 1; }","content":"Консолидация enum ```proto enum Status { option deprecated = true; STATUS_UNSPECIFIED = 0; STATUS_ACTIVE = 1; }"},{"id":"cli/breaking-changes/rules/enum-no-delete::enum::34","title":"ENUM_NO_DELETE","section":"Консолидация enum","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#enum","headings":["Консолидация enum"],"excerpt":"Консолидация enum enum State { option deprecated = true; STATE_UNSPECIFIED = 0; STATE_ENABLED = 1; }","content":"Консолидация enum enum State { option deprecated = true; STATE_UNSPECIFIED = 0; STATE_ENABLED = 1; }"},{"id":"cli/breaking-changes/rules/enum-no-delete::enum::35","title":"ENUM_NO_DELETE","section":"Консолидация enum","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#enum","headings":["Консолидация enum"],"excerpt":"Консолидация enum enum EntityStatus { ENTITY_STATUS_UNSPECIFIED = 0; ENTITY_STATUS_ACTIVE = 1; ENTITY_STATUS_INACTIVE = 2; ENTITY_STATUS_ENABLED = 3; ENTITY_STATUS_DISABLED = 4; } ```","content":"Консолидация enum enum EntityStatus { 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::enum::36","title":"ENUM_NO_DELETE","section":"Перемещение enum в новый пакет","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#enum","headings":["Перемещение enum в новый пакет"],"excerpt":"Перемещение enum в новый пакет ```proto enum UserRole { option deprecated = true; USER_ROLE_UNSPECIFIED = 0; USER_ROLE_ADMIN = 1; }","content":"Перемещение enum в новый пакет ```proto enum UserRole { option deprecated = true; USER_ROLE_UNSPECIFIED = 0; USER_ROLE_ADMIN = 1; }"},{"id":"cli/breaking-changes/rules/enum-no-delete::enum::37","title":"ENUM_NO_DELETE","section":"Перемещение enum в новый пакет","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#enum","headings":["Перемещение enum в новый пакет"],"excerpt":"Перемещение enum в новый пакет import \"common/roles.proto\";","content":"Перемещение enum в новый пакет import \"common/roles.proto\";"},{"id":"cli/breaking-changes/rules/enum-no-delete::enum::38","title":"ENUM_NO_DELETE","section":"Перемещение enum в новый пакет","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#enum","headings":["Перемещение enum в новый пакет"],"excerpt":"Перемещение enum в новый пакет message Order { UserRole old_role = 3 [deprecated = true]; common.UserRole new_role = 4; } ```","content":"Перемещение enum в новый пакет message Order { UserRole old_role = 3 [deprecated = true]; common.UserRole new_role = 4; } ```"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::39","title":"ENUM_NO_DELETE","section":"Версионирование / новая версия пакета","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Версионирование / новая версия пакета"],"excerpt":"Версионирование / новая версия пакета ```proto package myapi.v2;","content":"Версионирование / новая версия пакета ```proto package myapi.v2;"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::40","title":"ENUM_NO_DELETE","section":"Версионирование / новая версия пакета","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Версионирование / новая версия пакета"],"excerpt":"Версионирование / новая версия пакета enum UserPermission { USER_PERMISSION_UNSPECIFIED = 0; USER_PERMISSION_READ = 1; USER_PERMISSION_WRITE = 2; USER_PERMISSION_ADMIN = 3; }","content":"Версионирование / новая версия пакета 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::top::41","title":"ENUM_NO_DELETE","section":"Версионирование / новая версия пакета","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Версионирование / новая версия пакета"],"excerpt":"Версионирование / новая версия пакета message Order { string id = 1; UserPermission created_by_permission = 2; } ```","content":"Версионирование / новая версия пакета message Order { string id = 1; UserPermission created_by_permission = 2; } ```"},{"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":"Правило проверяет, что ни одно значение enum (enum value) не было удалено. Удаление значения ломает совместимость по wire‑формату и сгенерированный код: в уже сохранённых данных могут присутствовать удалённые значения, а","content":"Правило проверяет, что ни одно значение enum (enum value) не было удалено. Удаление значения ломает совместимость по wire‑формату и сгенерированный код: в уже сохранённых данных могут присутствовать удалённые значения, а клиентский код может ссылаться на соответствующие константы."},{"id":"cli/breaking-changes/rules/enum-value-no-delete::breaking::1","title":"ENUM_VALUE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::breaking::2","title":"ENUM_VALUE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::breaking::3","title":"ENUM_VALUE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) 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":"Плохой (Breaking) 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::breaking::4","title":"ENUM_VALUE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) enum Priority { PRIORITY_UNSPECIFIED = 0; PRIORITY_LOW = 1; PRIORITY_MEDIUM = 2; PRIORITY_HIGH = 3; PRIORITY_URGENT = 4; } ```","content":"Плохой (Breaking) 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::breaking::5","title":"ENUM_VALUE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::breaking::6","title":"ENUM_VALUE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::breaking::7","title":"ENUM_VALUE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) 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 --] ","content":"Плохой (Breaking) 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 --] Удалено значение enum — BREAKING! }"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::breaking::8","title":"ENUM_VALUE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) enum Priority { PRIORITY_UNSPECIFIED = 0; PRIORITY_LOW = 1; PRIORITY_MEDIUM = 2; PRIORITY_HIGH = 3; // PRIORITY_URGENT = 4; // [!code --] Удалено значение enum — BREAKING! } ```","content":"Плохой (Breaking) enum Priority { PRIORITY_UNSPECIFIED = 0; PRIORITY_LOW = 1; PRIORITY_MEDIUM = 2; PRIORITY_HIGH = 3; // PRIORITY_URGENT = 4; // [!code --] Удалено значение enum — BREAKING! } ```"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::9","title":"ENUM_VALUE_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры **Множественное удаление значений:** ```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_S","content":"Дополнительные примеры **Множественное удаление значений:** ```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::top::10","title":"ENUM_VALUE_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры // 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","content":"Дополнительные примеры // 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::top::11","title":"ENUM_VALUE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо удаления — пометить значения deprecated:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо удаления — пометить значения deprecated:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::12","title":"ENUM_VALUE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::13","title":"ENUM_VALUE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) 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 = t","content":"Хороший (Безопасный) 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::top::14","title":"ENUM_VALUE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) enum Priority { PRIORITY_UNSPECIFIED = 0; PRIORITY_LOW = 1; PRIORITY_MEDIUM = 2; PRIORITY_HIGH = 3; PRIORITY_URGENT = 4 [deprecated = true]; // [!code focus] } ```","content":"Хороший (Безопасный) 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::top::15","title":"ENUM_VALUE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Или зарезервировать номер и имя после удаления:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Или зарезервировать номер и имя после удаления:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::16","title":"ENUM_VALUE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::17","title":"ENUM_VALUE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) enum OrderStatus { reserved 5; // [!code focus] reserved \"ORDER_STATUS_CANCELLED\"; // [!code focus]","content":"Хороший (Безопасный) enum OrderStatus { reserved 5; // [!code focus] reserved \"ORDER_STATUS_CANCELLED\"; // [!code focus]"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::18","title":"ENUM_VALUE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_CONFIRMED = 2; ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_DELIVERED = 4; }","content":"Хороший (Безопасный) 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::top::19","title":"ENUM_VALUE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) enum Priority { reserved 4; // [!code focus] reserved \"PRIORITY_URGENT\"; // [!code focus]","content":"Хороший (Безопасный) enum Priority { reserved 4; // [!code focus] reserved \"PRIORITY_URGENT\"; // [!code focus]"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::20","title":"ENUM_VALUE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) PRIORITY_UNSPECIFIED = 0; PRIORITY_LOW = 1; PRIORITY_MEDIUM = 2; PRIORITY_HIGH = 3; } ```","content":"Хороший (Безопасный) PRIORITY_UNSPECIFIED = 0; PRIORITY_LOW = 1; PRIORITY_MEDIUM = 2; PRIORITY_HIGH = 3; } ```"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::21","title":"ENUM_VALUE_NO_DELETE","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Влияние"],"excerpt":"Влияние **Wire Format:** Данные с удалёнными значениями не десериализуются корректно **Generated Code:** Константы исчезают — клиентский код не компилируется **Client Applications:** Ссылки на удалённые значения вызывают","content":"Влияние **Wire Format:** Данные с удалёнными значениями не десериализуются корректно **Generated Code:** Константы исчезают — клиентский код не компилируется **Client Applications:** Ссылки на удалённые значения вызывают ошибки компиляции **Switch Statements:** switch по enum ломается (неизвестные case) **Default Handling:** Поведение при неизвестных значениях меняется"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::22","title":"ENUM_VALUE_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Код клиента ломается:** ```go order := &myapi.Order{ Status: myapi.OrderStatus_ORDER_STATUS_CANCELLED, // ERROR после удаления }","content":"Реальный пример **Код клиента ломается:** ```go order := &myapi.Order{ Status: myapi.OrderStatus_ORDER_STATUS_CANCELLED, // ERROR после удаления }"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::23","title":"ENUM_VALUE_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример switch order.Status { case myapi.OrderStatus_ORDER_STATUS_PENDING: // Pending case myapi.OrderStatus_ORDER_STATUS_CANCELLED: // ERROR: undefined // Cancellation default: // Unknown } // undefined: myapi.O","content":"Реальный пример switch order.Status { case myapi.OrderStatus_ORDER_STATUS_PENDING: // Pending case myapi.OrderStatus_ORDER_STATUS_CANCELLED: // ERROR: undefined // Cancellation default: // Unknown } // undefined: myapi.OrderStatus_ORDER_STATUS_CANCELLED ```"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::24","title":"ENUM_VALUE_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Проблемы с уже сохранёнными данными:**","content":"Реальный пример **Проблемы с уже сохранёнными данными:**"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::25","title":"ENUM_VALUE_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Валидация на сервере:** ```go func validateOrderStatus(status OrderStatus) error { switch status { case OrderStatus_ORDER_STATUS_PENDING, OrderStatus_ORDER_STATUS_CONFIRMED, OrderStatus_ORDER_STATUS_SHI","content":"Реальный пример **Валидация на сервере:** ```go 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 после удаления return nil default: return errors.New(\"invalid order status\") } }"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::26","title":"ENUM_VALUE_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример func canModifyOrder(order *Order) bool { return order.Status != OrderStatus_ORDER_STATUS_CANCELLED // ERROR } ```","content":"Реальный пример func canModifyOrder(order *Order) bool { return order.Status != OrderStatus_ORDER_STATUS_CANCELLED // ERROR } ```"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::27","title":"ENUM_VALUE_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Сначала пометить deprecated:** **Перестать использовать deprecated значение в новом коде:** **Обработка legacy в клиенте:** **Резервирование после миграции:** **Никогда не переиспользовать номера** —","content":"Стратегия миграции **Сначала пометить deprecated:** **Перестать использовать deprecated значение в новом коде:** **Обработка legacy в клиенте:** **Резервирование после миграции:** **Никогда не переиспользовать номера** — зарезервированы навсегда."},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::28","title":"ENUM_VALUE_NO_DELETE","section":"Предотвращение переиспользования номера","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Предотвращение переиспользования номера"],"excerpt":"Предотвращение переиспользования номера ```proto enum Status { reserved 2; reserved \"STATUS_DELETED\";","content":"Предотвращение переиспользования номера ```proto enum Status { reserved 2; reserved \"STATUS_DELETED\";"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::29","title":"ENUM_VALUE_NO_DELETE","section":"Предотвращение переиспользования номера","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Предотвращение переиспользования номера"],"excerpt":"Предотвращение переиспользования номера STATUS_UNSPECIFIED = 0; STATUS_ACTIVE = 1; STATUS_INACTIVE = 3; // STATUS_DELETED = 2; // Не переиспользуем } ```","content":"Предотвращение переиспользования номера STATUS_UNSPECIFIED = 0; STATUS_ACTIVE = 1; STATUS_INACTIVE = 3; // STATUS_DELETED = 2; // Не переиспользуем } ```"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::json::30","title":"ENUM_VALUE_NO_DELETE","section":"JSON совместимость","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#json","headings":["JSON совместимость"],"excerpt":"JSON совместимость ```proto enum Color { reserved 2; reserved \"RED\";","content":"JSON совместимость ```proto enum Color { reserved 2; reserved \"RED\";"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::json::31","title":"ENUM_VALUE_NO_DELETE","section":"JSON совместимость","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#json","headings":["JSON совместимость"],"excerpt":"JSON совместимость COLOR_UNSPECIFIED = 0; COLOR_BLUE = 1; COLOR_GREEN = 3; // COLOR_RED = 2; // Был удалён } ```","content":"JSON совместимость COLOR_UNSPECIFIED = 0; COLOR_BLUE = 1; COLOR_GREEN = 3; // COLOR_RED = 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":"Это правило проверяет, что имя enum значения для каждого номера (number) не изменилось. Переименование enum значения при сохранении его номера ломает совместимость JSON и сгенерированный код: клиенты ожидают конкретные и","content":"Это правило проверяет, что имя enum значения для каждого номера (number) не изменилось. Переименование enum значения при сохранении его номера ломает совместимость JSON и сгенерированный код: клиенты ожидают конкретные имена констант."},{"id":"cli/breaking-changes/rules/enum-value-same-name::breaking::1","title":"ENUM_VALUE_SAME_NAME","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-value-same-name::breaking::2","title":"ENUM_VALUE_SAME_NAME","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/enum-value-same-name::breaking::3","title":"ENUM_VALUE_SAME_NAME","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_CONFIRMED = 2; ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_DELIVERED = 4; } ```","content":"Плохой (Breaking) 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::breaking::4","title":"ENUM_VALUE_SAME_NAME","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-value-same-name::breaking::5","title":"ENUM_VALUE_SAME_NAME","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/enum-value-same-name::breaking::6","title":"ENUM_VALUE_SAME_NAME","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_APPROVED = 2; // [!code --] Было ORDER_STATUS_CONFIRMED ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_COMPLETED = 4; // [","content":"Плохой (Breaking) enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_APPROVED = 2; // [!code --] Было ORDER_STATUS_CONFIRMED ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_COMPLETED = 4; // [!code --] Было ORDER_STATUS_DELIVERED } ```"},{"id":"cli/breaking-changes/rules/enum-value-same-name::top::7","title":"ENUM_VALUE_SAME_NAME","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры **Множественные переименования:** ```proto // Before enum UserRole { USER_ROLE_UNSPECIFIED = 0; USER_ROLE_ADMIN = 1; USER_ROLE_MODERATOR = 2; USER_ROLE_USER = 3; }","content":"Дополнительные примеры **Множественные переименования:** ```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::top::8","title":"ENUM_VALUE_SAME_NAME","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры // After - ВСЁ BREAKING enum UserRole { USER_ROLE_UNSPECIFIED = 0; USER_ROLE_ADMINISTRATOR = 1; // BREAKING: ADMIN -> ADMINISTRATOR USER_ROLE_MOD = 2; // BREAKING: MODERATOR -> MOD USER_ROLE_MEMBER","content":"Дополнительные примеры // After - ВСЁ BREAKING 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::top::9","title":"ENUM_VALUE_SAME_NAME","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо переименования — добавить новые значения и пометить старые deprecated:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо переименования — добавить новые значения и пометить старые deprecated:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-value-same-name::top::10","title":"ENUM_VALUE_SAME_NAME","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/enum-value-same-name::top::11","title":"ENUM_VALUE_SAME_NAME","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) 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 [depre","content":"Хороший (Безопасный) 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] // Новое значение вместо переименования ORDER_STATUS_COMPLETED = 6; // [!code focus] } ```"},{"id":"cli/breaking-changes/rules/enum-value-same-name::top::12","title":"ENUM_VALUE_SAME_NAME","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Или создать новую версию enum:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Или создать новую версию enum:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-value-same-name::top::13","title":"ENUM_VALUE_SAME_NAME","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v2; // [!code focus]","content":"Хороший (Безопасный) package myapi.v2; // [!code focus]"},{"id":"cli/breaking-changes/rules/enum-value-same-name::top::14","title":"ENUM_VALUE_SAME_NAME","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_APPROVED = 2; // [!code focus] // «Чистые» имена в v2 ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_COMPLETED = 4; // ","content":"Хороший (Безопасный) enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_APPROVED = 2; // [!code focus] // «Чистые» имена в v2 ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_COMPLETED = 4; // [!code focus] } ```"},{"id":"cli/breaking-changes/rules/enum-value-same-name::top::15","title":"ENUM_VALUE_SAME_NAME","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Влияние"],"excerpt":"Влияние **Generated Code:** Меняются имена констант — компиляция клиентов ломается **JSON Compatibility:** JSON использует имена enum — старые документы не парсятся **Client Applications:** Код со старым именем константы","content":"Влияние **Generated Code:** Меняются имена констант — компиляция клиентов ломается **JSON Compatibility:** JSON использует имена enum — старые документы не парсятся **Client Applications:** Код со старым именем константы не компилируется **Documentation:** Документация устаревает с неправильными именами"},{"id":"cli/breaking-changes/rules/enum-value-same-name::top::16","title":"ENUM_VALUE_SAME_NAME","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Реальный пример"],"excerpt":"Реальный пример **Ломается код клиента:** ```go // Before status := myapi.OrderStatus_ORDER_STATUS_CONFIRMED if order.Status == myapi.OrderStatus_ORDER_STATUS_DELIVERED { // handle delivery }","content":"Реальный пример **Ломается код клиента:** ```go // Before 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::top::17","title":"ENUM_VALUE_SAME_NAME","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Реальный пример"],"excerpt":"Реальный пример // After (переименовано) — ошибки компиляции status := myapi.OrderStatus_ORDER_STATUS_CONFIRMED // ERROR: undefined if order.Status == myapi.OrderStatus_ORDER_STATUS_DELIVERED { // ERROR: undefined // han","content":"Реальный пример // After (переименовано) — ошибки компиляции status := myapi.OrderStatus_ORDER_STATUS_CONFIRMED // ERROR: undefined if order.Status == myapi.OrderStatus_ORDER_STATUS_DELIVERED { // ERROR: undefined // handle delivery } ```"},{"id":"cli/breaking-changes/rules/enum-value-same-name::top::18","title":"ENUM_VALUE_SAME_NAME","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Реальный пример"],"excerpt":"Реальный пример **JSON совместимость ломается:** ```json // Раньше { \"status\": \"ORDER_STATUS_CONFIRMED\" }","content":"Реальный пример **JSON совместимость ломается:** ```json // Раньше { \"status\": \"ORDER_STATUS_CONFIRMED\" }"},{"id":"cli/breaking-changes/rules/enum-value-same-name::top::19","title":"ENUM_VALUE_SAME_NAME","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Реальный пример"],"excerpt":"Реальный пример // После { \"status\": \"ORDER_STATUS_APPROVED\" // Старые JSON больше не парсятся } ```","content":"Реальный пример // После { \"status\": \"ORDER_STATUS_APPROVED\" // Старые JSON больше не парсятся } ```"},{"id":"cli/breaking-changes/rules/enum-value-same-name::top::20","title":"ENUM_VALUE_SAME_NAME","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Добавьте новое значение вместо переименования:**","content":"Стратегия миграции **Добавьте новое значение вместо переименования:**"},{"id":"cli/breaking-changes/rules/enum-value-same-name::top::21","title":"ENUM_VALUE_SAME_NAME","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Сервер обрабатывает оба значения на переходном этапе** **Мигрируйте клиентов** на новые значения **Удалите (reserve) старое имя и номер** в следующей major‑версии:","content":"Стратегия миграции **Сервер обрабатывает оба значения на переходном этапе** **Мигрируйте клиентов** на новые значения **Удалите (reserve) старое имя и номер** в следующей major‑версии:"},{"id":"cli/breaking-changes/rules/enum-value-same-name::allow-alias::22","title":"ENUM_VALUE_SAME_NAME","section":"Allow Alias (исключение)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name#allow-alias","headings":["Allow Alias (исключение)"],"excerpt":"Allow Alias (исключение) С allow_alias = true можно временно иметь два имени для одного номера:","content":"Allow Alias (исключение) С allow_alias = true можно временно иметь два имени для одного номера:"},{"id":"cli/breaking-changes/rules/enum-value-same-name::allow-alias::23","title":"ENUM_VALUE_SAME_NAME","section":"Allow Alias (исключение)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name#allow-alias","headings":["Allow Alias (исключение)"],"excerpt":"Allow Alias (исключение) Примечание: Сейчас EasyP всё равно считает это breaking (может измениться в будущем).","content":"Allow Alias (исключение) Примечание: Сейчас EasyP всё равно считает это breaking (может измениться в будущем)."},{"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":"Это правило проверяет, что ни одно поле сообщения (message field) не было удалено. Удаление поля ломает совместимость по wire‑формату и сгенерированный код: в существующих данных может присутствовать удалённое поле, а кл","content":"Это правило проверяет, что ни одно поле сообщения (message field) не было удалено. Удаление поля ломает совместимость по wire‑формату и сгенерированный код: в существующих данных может присутствовать удалённое поле, а клиентский код может ссылаться на него."},{"id":"cli/breaking-changes/rules/field-no-delete::breaking::1","title":"FIELD_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-no-delete::breaking::2","title":"FIELD_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/field-no-delete::breaking::3","title":"FIELD_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message User { string name = 1; string email = 2; int32 age = 3; string phone = 4; // [!code --] } ```","content":"Плохой (Breaking) message User { string name = 1; string email = 2; int32 age = 3; string phone = 4; // [!code --] } ```"},{"id":"cli/breaking-changes/rules/field-no-delete::breaking::4","title":"FIELD_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-no-delete::breaking::5","title":"FIELD_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/field-no-delete::breaking::6","title":"FIELD_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message User { string name = 1; string email = 2; int32 age = 3; // phone поле удалено — BREAKING CHANGE! } ```","content":"Плохой (Breaking) message User { string name = 1; string email = 2; int32 age = 3; // phone поле удалено — BREAKING CHANGE! } ```"},{"id":"cli/breaking-changes/rules/field-no-delete::top::7","title":"FIELD_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо удаления — пометить поле deprecated:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо удаления — пометить поле deprecated:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-no-delete::top::8","title":"FIELD_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/field-no-delete::top::9","title":"FIELD_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message User { string name = 1; string email = 2; int32 age = 3; string phone = 4 [deprecated = true]; // [!code focus] } ```","content":"Хороший (Безопасный) 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::top::10","title":"FIELD_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Или зарезервировать номер и имя поля после удаления:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Или зарезервировать номер и имя поля после удаления:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-no-delete::top::11","title":"FIELD_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/field-no-delete::top::12","title":"FIELD_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message User { reserved 4; // [!code focus] reserved \"phone\"; // [!code focus] string name = 1; string email = 2; int32 age = 3; } ```","content":"Хороший (Безопасный) 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::top::13","title":"FIELD_NO_DELETE","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete","headings":["Влияние"],"excerpt":"Влияние **Wire Format:** Старые сообщения с удалённым полем некорректно десериализуются **Generated Code:** Удаляются аксессоры (get/set), компиляция клиента ломается **Data Loss:** Потеря сохранённых данных, связанных с","content":"Влияние **Wire Format:** Старые сообщения с удалённым полем некорректно десериализуются **Generated Code:** Удаляются аксессоры (get/set), компиляция клиента ломается **Data Loss:** Потеря сохранённых данных, связанных с полем **JSON Compatibility:** JSON парсеры ожидают наличие поля и могут выдавать ошибки"},{"id":"cli/breaking-changes/rules/field-no-delete::top::14","title":"FIELD_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Сначала пометить deprecated:**","content":"Стратегия миграции **Сначала пометить deprecated:**"},{"id":"cli/breaking-changes/rules/field-no-delete::top::15","title":"FIELD_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Прекратить запись в поле** в прикладном коде","content":"Стратегия миграции **Прекратить запись в поле** в прикладном коде"},{"id":"cli/breaking-changes/rules/field-no-delete::top::16","title":"FIELD_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Зарезервировать поле** в следующей версии, чтобы избежать повторного использования:","content":"Стратегия миграции **Зарезервировать поле** в следующей версии, чтобы избежать повторного использования:"},{"id":"cli/breaking-changes/rules/field-no-delete::top::17","title":"FIELD_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Никогда не переиспользовать номер поля** — должен оставаться в reserved навсегда","content":"Стратегия миграции **Никогда не переиспользовать номер поля** — должен оставаться в reserved навсегда"},{"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":"Правило проверяет, что поля сообщений сохраняют ту же кардинальность (обязательность / optional). Изменение кардинальности поля ломает совместимость по wire‑формату и сгенерированный код: семантика присутствия и ожидания","content":"Правило проверяет, что поля сообщений сохраняют ту же кардинальность (обязательность / optional). Изменение кардинальности поля ломает совместимость по wire‑формату и сгенерированный код: семантика присутствия и ожидания клиентского кода отличаются для optional и required (implicit) полей."},{"id":"cli/breaking-changes/rules/field-same-cardinality::breaking::1","title":"FIELD_SAME_CARDINALITY","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-same-cardinality::breaking::2","title":"FIELD_SAME_CARDINALITY","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/field-same-cardinality::breaking::3","title":"FIELD_SAME_CARDINALITY","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message User { string name = 1; string email = 2; int32 age = 3; }","content":"Плохой (Breaking) message User { string name = 1; string email = 2; int32 age = 3; }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::breaking::4","title":"FIELD_SAME_CARDINALITY","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message CreateUserRequest { string name = 1; optional string email = 2; string phone = 3; } ```","content":"Плохой (Breaking) message CreateUserRequest { string name = 1; optional string email = 2; string phone = 3; } ```"},{"id":"cli/breaking-changes/rules/field-same-cardinality::breaking::5","title":"FIELD_SAME_CARDINALITY","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-same-cardinality::breaking::6","title":"FIELD_SAME_CARDINALITY","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/field-same-cardinality::breaking::7","title":"FIELD_SAME_CARDINALITY","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message User { string name = 1; optional string email = 2; // [!code --] Было required (implicit), стало optional int32 age = 3; }","content":"Плохой (Breaking) message User { string name = 1; optional string email = 2; // [!code --] Было required (implicit), стало optional int32 age = 3; }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::breaking::8","title":"FIELD_SAME_CARDINALITY","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message CreateUserRequest { string name = 1; string email = 2; // [!code --] Было optional, стало требуемым (implicit required) string phone = 3; } ```","content":"Плохой (Breaking) message CreateUserRequest { string name = 1; string email = 2; // [!code --] Было optional, стало требуемым (implicit required) string phone = 3; } ```"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::9","title":"FIELD_SAME_CARDINALITY","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры **Проблемы миграции Proto2 → Proto3:**","content":"Дополнительные примеры **Проблемы миграции Proto2 → Proto3:**"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::10","title":"FIELD_SAME_CARDINALITY","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры ```proto // Before (proto2) syntax = \"proto2\";","content":"Дополнительные примеры ```proto // Before (proto2) syntax = \"proto2\";"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::11","title":"FIELD_SAME_CARDINALITY","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры message Order { required string id = 1; optional string notes = 2; repeated string tags = 3; }","content":"Дополнительные примеры message Order { required string id = 1; optional string notes = 2; repeated string tags = 3; }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::12","title":"FIELD_SAME_CARDINALITY","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры // After (proto3) - BREAKING CHANGES! syntax = \"proto3\";","content":"Дополнительные примеры // After (proto3) - BREAKING CHANGES! syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::13","title":"FIELD_SAME_CARDINALITY","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры message Order { string id = 1; // BREAKING: required -> implicit optional string notes = 2; // BREAKING: explicit optional -> implicit optional repeated string tags = 3; // OK } ```","content":"Дополнительные примеры message Order { string id = 1; // BREAKING: required -> implicit optional string notes = 2; // BREAKING: explicit optional -> implicit optional repeated string tags = 3; // OK } ```"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::14","title":"FIELD_SAME_CARDINALITY","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо изменения кардинальности — добавьте новое поле:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо изменения кардинальности — добавьте новое поле:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::15","title":"FIELD_SAME_CARDINALITY","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::16","title":"FIELD_SAME_CARDINALITY","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message User { string name = 1; string email = 2 [deprecated = true]; // [!code focus] Сохраняем старую кардинальность int32 age = 3; optional string email_optional = 4; // [!code focus] Новое option","content":"Хороший (Безопасный) message User { string name = 1; string email = 2 [deprecated = true]; // [!code focus] Сохраняем старую кардинальность int32 age = 3; optional string email_optional = 4; // [!code focus] Новое optional поле }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::17","title":"FIELD_SAME_CARDINALITY","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message CreateUserRequest { string name = 1; optional string email = 2 [deprecated = true]; // [!code focus] string phone = 3; string email_required = 4; // [!code focus] Новое требуемое поле } ```","content":"Хороший (Безопасный) message CreateUserRequest { string name = 1; optional string email = 2 [deprecated = true]; // [!code focus] string phone = 3; string email_required = 4; // [!code focus] Новое требуемое поле } ```"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::18","title":"FIELD_SAME_CARDINALITY","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Или создайте новую версию сообщения:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Или создайте новую версию сообщения:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::19","title":"FIELD_SAME_CARDINALITY","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v2; // [!code focus]","content":"Хороший (Безопасный) package myapi.v2; // [!code focus]"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::20","title":"FIELD_SAME_CARDINALITY","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message User { string name = 1; optional string email = 2; // [!code focus] Чистая модель в v2 int32 age = 3; }","content":"Хороший (Безопасный) message User { string name = 1; optional string email = 2; // [!code focus] Чистая модель в v2 int32 age = 3; }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::21","title":"FIELD_SAME_CARDINALITY","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message CreateUserRequest { string name = 1; string email = 2; // [!code focus] Требуемое в v2 string phone = 3; } ```","content":"Хороший (Безопасный) message CreateUserRequest { string name = 1; string email = 2; // [!code focus] Требуемое в v2 string phone = 3; } ```"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::22","title":"FIELD_SAME_CARDINALITY","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Влияние"],"excerpt":"Влияние **Wire Format:** Меняется семантика присутствия — клиенты неправильно ожидают поля **Generated Code:** Меняются методы доступа / проверки (has, clear) **Validation:** Правила проверки обязательности переписываютс","content":"Влияние **Wire Format:** Меняется семантика присутствия — клиенты неправильно ожидают поля **Generated Code:** Меняются методы доступа / проверки (has, clear) **Validation:** Правила проверки обязательности переписываются **Default Values:** Optional и required по‑разному обрабатывают отсутствие значения"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::23","title":"FIELD_SAME_CARDINALITY","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Реальный пример"],"excerpt":"Реальный пример **Код клиента ломается при смене кардинальности:** ```go // Before - поле фактически требуется (implicit) user := &myapi.User{ Name: \"John\", Email: \"john@example.com\", Age: 30, }","content":"Реальный пример **Код клиента ломается при смене кардинальности:** ```go // Before - поле фактически требуется (implicit) user := &myapi.User{ Name: \"John\", Email: \"john@example.com\", Age: 30, }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::24","title":"FIELD_SAME_CARDINALITY","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Реальный пример"],"excerpt":"Реальный пример if user.Email != \"\" { // Есть значение }","content":"Реальный пример if user.Email != \"\" { // Есть значение }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::25","title":"FIELD_SAME_CARDINALITY","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Реальный пример"],"excerpt":"Реальный пример // After - поле стало optional (pointer) user := &myapi.User{ Name: \"John\", Age: 30, // Email может отсутствовать }","content":"Реальный пример // After - поле стало optional (pointer) user := &myapi.User{ Name: \"John\", Age: 30, // Email может отсутствовать }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::26","title":"FIELD_SAME_CARDINALITY","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Реальный пример"],"excerpt":"Реальный пример if user.Email != nil && *user.Email != \"\" { // Есть значение (новый способ) }","content":"Реальный пример if user.Email != nil && *user.Email != \"\" { // Есть значение (новый способ) }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::27","title":"FIELD_SAME_CARDINALITY","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Реальный пример"],"excerpt":"Реальный пример user.Email = &emailValue // Присваивание указателя вместо строки ```","content":"Реальный пример user.Email = &emailValue // Присваивание указателя вместо строки ```"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::28","title":"FIELD_SAME_CARDINALITY","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Реальный пример"],"excerpt":"Реальный пример **Валидация на сервере:** ```go // Before func validateUser(user *User) error { if user.Email == \"\" { return errors.New(\"email is required\") } return nil }","content":"Реальный пример **Валидация на сервере:** ```go // Before func validateUser(user *User) error { if user.Email == \"\" { return errors.New(\"email is required\") } return nil }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::29","title":"FIELD_SAME_CARDINALITY","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Реальный пример"],"excerpt":"Реальный пример // After func validateUser(user *User) error { if user.Email == nil { return errors.New(\"email is required\") } if *user.Email == \"\" { return errors.New(\"email cannot be empty\") } return nil } ```","content":"Реальный пример // After func validateUser(user *User) error { if user.Email == nil { return errors.New(\"email is required\") } if *user.Email == \"\" { return errors.New(\"email cannot be empty\") } return nil } ```"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::30","title":"FIELD_SAME_CARDINALITY","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Добавьте новое поле** с нужной кардинальностью:","content":"Стратегия миграции **Добавьте новое поле** с нужной кардинальностью:"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::31","title":"FIELD_SAME_CARDINALITY","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Период двойной записи** — заполняйте оба поля:","content":"Стратегия миграции **Период двойной записи** — заполняйте оба поля:"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::32","title":"FIELD_SAME_CARDINALITY","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Клиенты постепенно переходят**:","content":"Стратегия миграции **Клиенты постепенно переходят**:"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::33","title":"FIELD_SAME_CARDINALITY","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Удаление старого поля** в следующей major‑версии:","content":"Стратегия миграции **Удаление старого поля** в следующей major‑версии:"},{"id":"cli/breaking-changes/rules/field-same-cardinality::proto2-proto3::34","title":"FIELD_SAME_CARDINALITY","section":"Миграция Proto2 → Proto3","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#proto2-proto3","headings":["Миграция Proto2 → Proto3"],"excerpt":"Миграция Proto2 → Proto3 ```proto syntax = \"proto3\"; message Order { string id = 1; // BREAKING если был required }","content":"Миграция Proto2 → Proto3 ```proto syntax = \"proto3\"; message Order { string id = 1; // BREAKING если был required }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::proto2-proto3::35","title":"FIELD_SAME_CARDINALITY","section":"Миграция Proto2 → Proto3","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#proto2-proto3","headings":["Миграция Proto2 → Proto3"],"excerpt":"Миграция Proto2 → Proto3 // Сохранить семантику: syntax = \"proto3\"; message Order { string id = 1; optional string notes = 2; } ```","content":"Миграция Proto2 → Proto3 // Сохранить семантику: syntax = \"proto3\"; message Order { string id = 1; optional string notes = 2; } ```"},{"id":"cli/breaking-changes/rules/field-same-cardinality::optional-required::36","title":"FIELD_SAME_CARDINALITY","section":"Делать optional поле required","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#optional-required","headings":["Делать optional поле required"],"excerpt":"Делать optional поле required ```proto message CreateUserRequest { string name = 1; string email = 2; // BREAKING (раньше optional) }","content":"Делать optional поле required ```proto message CreateUserRequest { string name = 1; string email = 2; // BREAKING (раньше optional) }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::optional-required::37","title":"FIELD_SAME_CARDINALITY","section":"Делать optional поле required","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#optional-required","headings":["Делать optional поле required"],"excerpt":"Делать optional поле required message CreateUserRequest { string name = 1; optional string email = 2 [deprecated = true]; string required_email = 3; } ```","content":"Делать optional поле required message CreateUserRequest { string name = 1; optional string email = 2 [deprecated = true]; string required_email = 3; } ```"},{"id":"cli/breaking-changes/rules/field-same-cardinality::required-optional::38","title":"FIELD_SAME_CARDINALITY","section":"Делать required поле optional","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#required-optional","headings":["Делать required поле optional"],"excerpt":"Делать required поле optional ```proto message User { optional string phone = 3; // BREAKING (было implicit required) }","content":"Делать required поле optional ```proto message User { optional string phone = 3; // BREAKING (было implicit required) }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::required-optional::39","title":"FIELD_SAME_CARDINALITY","section":"Делать required поле optional","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#required-optional","headings":["Делать required поле optional"],"excerpt":"Делать required поле optional message User { string phone = 3 [deprecated = true]; optional string phone_optional = 4; } ```","content":"Делать required поле optional message User { string phone = 3 [deprecated = true]; optional string phone_optional = 4; } ```"},{"id":"cli/breaking-changes/rules/field-same-cardinality::protobuf::40","title":"FIELD_SAME_CARDINALITY","section":"Типы кардинальности в Protobuf","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#protobuf","headings":["Типы кардинальности в Protobuf"],"excerpt":"Типы кардинальности в Protobuf","content":"Типы кардинальности в Protobuf"},{"id":"cli/breaking-changes/rules/field-same-cardinality::proto3::41","title":"FIELD_SAME_CARDINALITY","section":"Proto3","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#proto3","headings":["Proto3"],"excerpt":"Proto3 **Implicit optional**: string name = 1; **Explicit optional**: optional string email = 2; **Repeated**: repeated string tags = 3; **Map**: map metadata = 4;","content":"Proto3 **Implicit optional**: string name = 1; **Explicit optional**: optional string email = 2; **Repeated**: repeated string tags = 3; **Map**: map metadata = 4;"},{"id":"cli/breaking-changes/rules/field-same-cardinality::proto2::42","title":"FIELD_SAME_CARDINALITY","section":"Proto2","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#proto2","headings":["Proto2"],"excerpt":"Proto2 **Required**: required string id = 1; **Optional**: optional string email = 2; **Repeated**: repeated string tags = 3;","content":"Proto2 **Required**: required string id = 1; **Optional**: optional string email = 2; **Repeated**: repeated string tags = 3;"},{"id":"cli/breaking-changes/rules/field-same-cardinality::breaking::43","title":"FIELD_SAME_CARDINALITY","section":"Матрица Breaking изменений","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#breaking","headings":["Матрица Breaking изменений"],"excerpt":"Матрица Breaking изменений From To Result ------ ---- -------- Required Optional ❌ BREAKING Optional Required ❌ BREAKING Implicit Explicit ❌ BREAKING Explicit Implicit ❌ BREAKING Single Repeated ❌ BREAKING Repeated Singl","content":"Матрица Breaking изменений 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":"Правило проверяет, что типы полей сообщений (message fields) не изменяются. Смена типа поля ломает совместимость по wire‑формату и сгенерированный код: бинарное представление и ожидания клиентского кода различаются для р","content":"Правило проверяет, что типы полей сообщений (message fields) не изменяются. Смена типа поля ломает совместимость по wire‑формату и сгенерированный код: бинарное представление и ожидания клиентского кода различаются для разных типов."},{"id":"cli/breaking-changes/rules/field-same-type::breaking::1","title":"FIELD_SAME_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-same-type::breaking::2","title":"FIELD_SAME_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/field-same-type::breaking::3","title":"FIELD_SAME_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message Product { string name = 1; int32 price = 2; bool available = 3; } ```","content":"Плохой (Breaking) message Product { string name = 1; int32 price = 2; bool available = 3; } ```"},{"id":"cli/breaking-changes/rules/field-same-type::breaking::4","title":"FIELD_SAME_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-same-type::breaking::5","title":"FIELD_SAME_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/field-same-type::breaking::6","title":"FIELD_SAME_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message Product { string name = 1; string price = 2; // [!code --] Changed from int32 to string (изменён тип) bool available = 3; } ```","content":"Плохой (Breaking) 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::top::7","title":"FIELD_SAME_TYPE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/field-same-type","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры **Несовместимые изменения типов:** ```proto // Before message Order { string id = 1; int64 timestamp = 2; repeated string tags = 3; OrderStatus status = 4; }","content":"Дополнительные примеры **Несовместимые изменения типов:** ```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::top::8","title":"FIELD_SAME_TYPE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/field-same-type","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры // After - ВСЁ BREAKING message Order { int32 id = 1; // string -> int32: BREAKING string timestamp = 2; // int64 -> string: BREAKING string tags = 3; // repeated -> singular: BREAKING int32 status","content":"Дополнительные примеры // After - ВСЁ BREAKING 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::top::9","title":"FIELD_SAME_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо смены типа — добавьте новое поле:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо смены типа — добавьте новое поле:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-same-type::top::10","title":"FIELD_SAME_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/field-same-type::top::11","title":"FIELD_SAME_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message Product { string name = 1; int32 price = 2 [deprecated = true]; // [!code focus] // Старое поле помечено deprecated bool available = 3; string price_formatted = 4; // [!code focus] // Новое п","content":"Хороший (Безопасный) message Product { string name = 1; int32 price = 2 [deprecated = true]; // [!code focus] // Старое поле помечено deprecated bool available = 3; string price_formatted = 4; // [!code focus] // Новое поле со строковым представлением } ```"},{"id":"cli/breaking-changes/rules/field-same-type::top::12","title":"FIELD_SAME_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Или создайте новую версию сообщения:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Или создайте новую версию сообщения:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-same-type::top::13","title":"FIELD_SAME_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v2; // [!code focus] // Новая версия package","content":"Хороший (Безопасный) package myapi.v2; // [!code focus] // Новая версия package"},{"id":"cli/breaking-changes/rules/field-same-type::top::14","title":"FIELD_SAME_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message Product { string name = 1; string price = 2; // [!code focus] // В v2 уже string bool available = 3; } ```","content":"Хороший (Безопасный) message Product { string name = 1; string price = 2; // [!code focus] // В v2 уже string bool available = 3; } ```"},{"id":"cli/breaking-changes/rules/field-same-type::top::15","title":"FIELD_SAME_TYPE","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/field-same-type","headings":["Влияние"],"excerpt":"Влияние **Wire Format:** Старые бинарные данные не десериализуются корректно **Generated Code:** Меняются типы в сгенерированном коде — клиенты не компилируются **Runtime Errors:** Ошибки парсинга при несовпадении ожидае","content":"Влияние **Wire Format:** Старые бинарные данные не десериализуются корректно **Generated Code:** Меняются типы в сгенерированном коде — клиенты не компилируются **Runtime Errors:** Ошибки парсинга при несовпадении ожидаемого типа **Data Corruption:** Неверная интерпретация байтов данных"},{"id":"cli/breaking-changes/rules/field-same-type::top::16","title":"FIELD_SAME_TYPE","section":"Типовые проблемы изменений типов","path":"/docs/guide/cli/breaking-changes/rules/field-same-type","headings":["Типовые проблемы изменений типов"],"excerpt":"Типовые проблемы изменений типов","content":"Типовые проблемы изменений типов"},{"id":"cli/breaking-changes/rules/field-same-type::top::17","title":"FIELD_SAME_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/field-same-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Добавьте новое поле** с нужным типом:","content":"Стратегия миграции **Добавьте новое поле** с нужным типом:"},{"id":"cli/breaking-changes/rules/field-same-type::top::18","title":"FIELD_SAME_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/field-same-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Период двойной записи** — заполняйте оба поля для совместимости","content":"Стратегия миграции **Период двойной записи** — заполняйте оба поля для совместимости"},{"id":"cli/breaking-changes/rules/field-same-type::top::19","title":"FIELD_SAME_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/field-same-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Мигрируйте клиентов** на новое поле постепенно","content":"Стратегия миграции **Мигрируйте клиентов** на новое поле постепенно"},{"id":"cli/breaking-changes/rules/field-same-type::top::20","title":"FIELD_SAME_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/field-same-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Удалите старое поле** в следующей major‑версии:","content":"Стратегия миграции **Удалите старое поле** в следующей major‑версии:"},{"id":"cli/breaking-changes/rules/field-same-type::wire::21","title":"FIELD_SAME_TYPE","section":"Безопасные изменения (Теоретически wire‑совместимые)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type#wire","headings":["Безопасные изменения (Теоретически wire‑совместимые)"],"excerpt":"Безопасные изменения (Теоретически wire‑совместимые) Примечание: EasyP сейчас считает ЛЮБУЮ смену типа breaking. Однако технически некоторые случаи совместимы:","content":"Безопасные изменения (Теоретически wire‑совместимые) Примечание: EasyP сейчас считает ЛЮБУЮ смену типа breaking. Однако технически некоторые случаи совместимы:"},{"id":"cli/breaking-changes/rules/field-same-type::wire::22","title":"FIELD_SAME_TYPE","section":"Безопасные изменения (Теоретически wire‑совместимые)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type#wire","headings":["Безопасные изменения (Теоретически wire‑совместимые)"],"excerpt":"Безопасные изменения (Теоретически wire‑совместимые) int32 ↔ uint32 (одно кодирование) int64 ↔ uint64 (одно кодирование) string → bytes (если все строки валидный UTF‑8)","content":"Безопасные изменения (Теоретически wire‑совместимые) int32 ↔ uint32 (одно кодирование) int64 ↔ uint64 (одно кодирование) string → bytes (если все строки валидный UTF‑8)"},{"id":"cli/breaking-changes/rules/field-same-type::wire::23","title":"FIELD_SAME_TYPE","section":"Безопасные изменения (Теоретически wire‑совместимые)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type#wire","headings":["Безопасные изменения (Теоретически wire‑совместимые)"],"excerpt":"Безопасные изменения (Теоретически wire‑совместимые) Эти исключения могут получить отдельную обработку в будущих версиях EasyP с более гибкими уровнями строгости.","content":"Безопасные изменения (Теоретически wire‑совместимые) Эти исключения могут получить отдельную обработку в будущих версиях EasyP с более гибкими уровнями строгости."},{"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":"Это правило проверяет, что ни одна инструкция import не была удалена из proto‑файла. Удаление import ломает совместимость по wire‑формату и сгенерированный код: типы из импортируемых файлов могли использоваться в текущем","content":"Это правило проверяет, что ни одна инструкция import не была удалена из proto‑файла. Удаление import ломает совместимость по wire‑формату и сгенерированный код: типы из импортируемых файлов могли использоваться в текущем файле, и их удаление делает эти типы недоступными."},{"id":"cli/breaking-changes/rules/import-no-delete::breaking::1","title":"IMPORT_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/import-no-delete::breaking::2","title":"IMPORT_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/import-no-delete::breaking::3","title":"IMPORT_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) import \"google/protobuf/timestamp.proto\"; import \"google/protobuf/duration.proto\"; import \"common/user.proto\"; import \"common/address.proto\";","content":"Плохой (Breaking) 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::breaking::4","title":"IMPORT_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) 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":"Плохой (Breaking) 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::breaking::5","title":"IMPORT_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/import-no-delete::breaking::6","title":"IMPORT_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/import-no-delete::breaking::7","title":"IMPORT_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) import \"google/protobuf/timestamp.proto\"; // import \"google/protobuf/duration.proto\"; // [!code --] Удалён import — BREAKING // import \"common/user.proto\"; // [!code --] Удалён import — BREAKING // impo","content":"Плохой (Breaking) import \"google/protobuf/timestamp.proto\"; // import \"google/protobuf/duration.proto\"; // [!code --] Удалён import — BREAKING // import \"common/user.proto\"; // [!code --] Удалён import — BREAKING // import \"common/address.proto\"; // [!code --] Удалён import — BREAKING"},{"id":"cli/breaking-changes/rules/import-no-delete::breaking::8","title":"IMPORT_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message Order { string id = 1; google.protobuf.Timestamp created_at = 2; google.protobuf.Duration processing_time = 3; // ERROR: Duration недоступен common.User customer = 4; // ERROR: User недоступен c","content":"Плохой (Breaking) message Order { string id = 1; google.protobuf.Timestamp created_at = 2; google.protobuf.Duration processing_time = 3; // ERROR: Duration недоступен common.User customer = 4; // ERROR: User недоступен common.Address shipping_address = 5; // ERROR: Address недоступен } ```"},{"id":"cli/breaking-changes/rules/import-no-delete::top::9","title":"IMPORT_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры **Сервис ломается при удалённых import:** ```proto // Before import \"google/api/annotations.proto\"; import \"google/protobuf/empty.proto\"; import \"common/auth.proto\";","content":"Дополнительные примеры **Сервис ломается при удалённых import:** ```proto // Before import \"google/api/annotations.proto\"; import \"google/protobuf/empty.proto\"; import \"common/auth.proto\";"},{"id":"cli/breaking-changes/rules/import-no-delete::top::10","title":"IMPORT_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры service OrderService { rpc GetOrder(GetOrderRequest) returns (Order) { option (google.api.http) = { get: \"/v1/orders/{id}\" }; } rpc DeleteOrder(common.AuthRequest) returns (google.protobuf.Empty); ","content":"Дополнительные примеры 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::top::11","title":"IMPORT_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры // After - BREAKING CHANGES! // import \"google/api/annotations.proto\"; // BREAKING: deleted // import \"google/protobuf/empty.proto\"; // BREAKING: deleted // import \"common/auth.proto\"; // BREAKING:","content":"Дополнительные примеры // 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::top::12","title":"IMPORT_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры service OrderService { rpc GetOrder(GetOrderRequest) returns (Order) { option (google.api.http) = { // ERROR: annotations недоступен get: \"/v1/orders/{id}\" }; } rpc DeleteOrder(common.AuthRequest) ","content":"Дополнительные примеры service OrderService { rpc GetOrder(GetOrderRequest) returns (Order) { option (google.api.http) = { // ERROR: annotations недоступен get: \"/v1/orders/{id}\" }; } rpc DeleteOrder(common.AuthRequest) returns (google.protobuf.Empty); // ERROR: типы недоступны } ```"},{"id":"cli/breaking-changes/rules/import-no-delete::top::13","title":"IMPORT_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо удаления оставьте неиспользуемые import:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо удаления оставьте неиспользуемые import:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/import-no-delete::top::14","title":"IMPORT_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/import-no-delete::top::15","title":"IMPORT_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) import \"google/protobuf/timestamp.proto\"; import \"google/protobuf/duration.proto\"; // [!code focus] // Оставляем даже если не используется import \"common/user.proto\"; // [!code focus] import \"common/","content":"Хороший (Безопасный) import \"google/protobuf/timestamp.proto\"; import \"google/protobuf/duration.proto\"; // [!code focus] // Оставляем даже если не используется import \"common/user.proto\"; // [!code focus] import \"common/address.proto\"; // [!code focus]"},{"id":"cli/breaking-changes/rules/import-no-delete::top::16","title":"IMPORT_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message Order { string id = 1; google.protobuf.Timestamp created_at = 2; // Поля, использовавшие Duration/User/Address, удалены — import оставлены } ```","content":"Хороший (Безопасный) message Order { string id = 1; google.protobuf.Timestamp created_at = 2; // Поля, использовавшие Duration/User/Address, удалены — import оставлены } ```"},{"id":"cli/breaking-changes/rules/import-no-delete::top::17","title":"IMPORT_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Или добавьте новые типы, сохранив старые import:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Или добавьте новые типы, сохранив старые import:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/import-no-delete::top::18","title":"IMPORT_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/import-no-delete::top::19","title":"IMPORT_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) import \"google/protobuf/timestamp.proto\"; import \"google/protobuf/duration.proto\"; // [!code focus] import \"common/user.proto\"; // [!code focus] import \"common/address.proto\"; // [!code focus] import","content":"Хороший (Безопасный) import \"google/protobuf/timestamp.proto\"; import \"google/protobuf/duration.proto\"; // [!code focus] import \"common/user.proto\"; // [!code focus] import \"common/address.proto\"; // [!code focus] import \"common/v2/user.proto\"; // [!code focus] // Новый import"},{"id":"cli/breaking-changes/rules/import-no-delete::top::20","title":"IMPORT_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message Order { string id = 1; google.protobuf.Timestamp created_at = 2; google.protobuf.Duration processing_time = 3 [deprecated = true]; // [!code focus] common.User customer = 4 [deprecated = true","content":"Хороший (Безопасный) message Order { string id = 1; google.protobuf.Timestamp created_at = 2; google.protobuf.Duration processing_time = 3 [deprecated = true]; // [!code focus] common.User customer = 4 [deprecated = true]; // [!code focus] common.Address shipping_address = 5 [deprecated = true]; // [!code focus] int32 processing_seconds = 6; common.v2.UserProfile customer_v2 = 7; string shipping_address_text = 8; } ```"},{"id":"cli/breaking-changes/rules/import-no-delete::top::21","title":"IMPORT_NO_DELETE","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Влияние"],"excerpt":"Влияние **Generated Code:** Типы пропадают → ошибка компиляции **Wire Format:** Сообщения с удалёнными типами не десериализуются **Field References:** Поля с этими типами становятся невалидны **Service Definitions:** RPC","content":"Влияние **Generated Code:** Типы пропадают → ошибка компиляции **Wire Format:** Сообщения с удалёнными типами не десериализуются **Field References:** Поля с этими типами становятся невалидны **Service Definitions:** RPC с типами из удалённых файлов ломаются **Options Usage:** Пользовательские опции из импортов недоступны"},{"id":"cli/breaking-changes/rules/import-no-delete::top::22","title":"IMPORT_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Код клиента ломается:**","content":"Реальный пример **Код клиента ломается:**"},{"id":"cli/breaking-changes/rules/import-no-delete::top::23","title":"IMPORT_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Серверная логика ломается:**","content":"Реальный пример **Серверная логика ломается:**"},{"id":"cli/breaking-changes/rules/import-no-delete::top::24","title":"IMPORT_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Компиляция proto ломается:**","content":"Реальный пример **Компиляция proto ломается:**"},{"id":"cli/breaking-changes/rules/import-no-delete::top::25","title":"IMPORT_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции Сохраняйте import даже если типы более не используются: Добавляйте новые import рядом со старыми: Депрецируйте поля со старыми типами постепенно: Сервер: поддерживайте оба варианта: Удаляйте import тол","content":"Стратегия миграции Сохраняйте import даже если типы более не используются: Добавляйте новые import рядом со старыми: Депрецируйте поля со старыми типами постепенно: Сервер: поддерживайте оба варианта: Удаляйте import только в следующей major‑версии после полной миграции."},{"id":"cli/breaking-changes/rules/import-no-delete::top::26","title":"IMPORT_NO_DELETE","section":"Замена зависимости","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Замена зависимости"],"excerpt":"Замена зависимости ```proto import \"old/user.proto\"; // Старый import \"new/user.proto\"; // Новый","content":"Замена зависимости ```proto import \"old/user.proto\"; // Старый import \"new/user.proto\"; // Новый"},{"id":"cli/breaking-changes/rules/import-no-delete::top::27","title":"IMPORT_NO_DELETE","section":"Замена зависимости","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Замена зависимости"],"excerpt":"Замена зависимости message Order { old.User customer = 4 [deprecated = true]; new.UserProfile customer_v2 = 5; } ```","content":"Замена зависимости message Order { old.User customer = 4 [deprecated = true]; new.UserProfile customer_v2 = 5; } ```"},{"id":"cli/breaking-changes/rules/import-no-delete::top::28","title":"IMPORT_NO_DELETE","section":"Удаление функционала","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Удаление функционала"],"excerpt":"Удаление функционала ```proto import \"feature/analytics.proto\"; // Оставить даже если поле удалено","content":"Удаление функционала ```proto import \"feature/analytics.proto\"; // Оставить даже если поле удалено"},{"id":"cli/breaking-changes/rules/import-no-delete::top::29","title":"IMPORT_NO_DELETE","section":"Удаление функционала","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Удаление функционала"],"excerpt":"Удаление функционала message Order { string id = 1; // feature.AnalyticsData analytics = 2; // Поле удалено, import остаётся } ```","content":"Удаление функционала message Order { string id = 1; // feature.AnalyticsData analytics = 2; // Поле удалено, import остаётся } ```"},{"id":"cli/breaking-changes/rules/import-no-delete::protobuf::30","title":"IMPORT_NO_DELETE","section":"Миграция версии protobuf","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#protobuf","headings":["Миграция версии protobuf"],"excerpt":"Миграция версии protobuf ```proto import \"google/protobuf/timestamp.proto\"; import \"google/protobuf/duration.proto\";","content":"Миграция версии protobuf ```proto import \"google/protobuf/timestamp.proto\"; import \"google/protobuf/duration.proto\";"},{"id":"cli/breaking-changes/rules/import-no-delete::protobuf::31","title":"IMPORT_NO_DELETE","section":"Миграция версии protobuf","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#protobuf","headings":["Миграция версии protobuf"],"excerpt":"Миграция версии protobuf message Event { google.protobuf.Timestamp timestamp = 1; int64 timestamp_millis = 2; } ```","content":"Миграция версии protobuf message Event { google.protobuf.Timestamp timestamp = 1; int64 timestamp_millis = 2; } ```"},{"id":"cli/breaking-changes/rules/import-no-delete::top::32","title":"IMPORT_NO_DELETE","section":"Упрощение сложных зависимостей","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Упрощение сложных зависимостей"],"excerpt":"Упрощение сложных зависимостей ```proto import \"complex/config.proto\";","content":"Упрощение сложных зависимостей ```proto import \"complex/config.proto\";"},{"id":"cli/breaking-changes/rules/import-no-delete::top::33","title":"IMPORT_NO_DELETE","section":"Упрощение сложных зависимостей","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Упрощение сложных зависимостей"],"excerpt":"Упрощение сложных зависимостей message Settings { complex.ConfigData config = 1 [deprecated = true]; string config_json = 2; } ```","content":"Упрощение сложных зависимостей message Settings { complex.ConfigData config = 1 [deprecated = true]; string config_json = 2; } ```"},{"id":"cli/breaking-changes/rules/import-no-delete::import-vs::34","title":"IMPORT_NO_DELETE","section":"Удаление import vs использование поля","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#import-vs","headings":["Удаление import vs использование поля"],"excerpt":"Удаление import vs использование поля","content":"Удаление import vs использование поля"},{"id":"cli/breaking-changes/rules/import-no-delete::import::35","title":"IMPORT_NO_DELETE","section":"Аудит import","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#import","headings":["Аудит import"],"excerpt":"Аудит import (Даже если не найдено — не удаляем.)","content":"Аудит 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":"Это правило проверяет, что ни одно сообщение (message) не было удалено из proto‑файлов. Удаление message ломает совместимость по wire‑формату и сгенерированный код: в существующих данных могут присутствовать экземпляры у","content":"Это правило проверяет, что ни одно сообщение (message) не было удалено из proto‑файлов. Удаление message ломает совместимость по wire‑формату и сгенерированный код: в существующих данных могут присутствовать экземпляры удалённого типа, а клиентский код зависит от сгенерированных структур и классов."},{"id":"cli/breaking-changes/rules/message-no-delete::breaking::1","title":"MESSAGE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/message-no-delete::breaking::2","title":"MESSAGE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/message-no-delete::breaking::3","title":"MESSAGE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message User { string name = 1; string email = 2; Address address = 3; }","content":"Плохой (Breaking) message User { string name = 1; string email = 2; Address address = 3; }"},{"id":"cli/breaking-changes/rules/message-no-delete::breaking::4","title":"MESSAGE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message Address { // [!code --] string street = 1; // [!code --] string city = 2; // [!code --] string country = 3; // [!code --] } // [!code --]","content":"Плохой (Breaking) message Address { // [!code --] string street = 1; // [!code --] string city = 2; // [!code --] string country = 3; // [!code --] } // [!code --]"},{"id":"cli/breaking-changes/rules/message-no-delete::breaking::5","title":"MESSAGE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message Order { string id = 1; User user = 2; } ```","content":"Плохой (Breaking) message Order { string id = 1; User user = 2; } ```"},{"id":"cli/breaking-changes/rules/message-no-delete::breaking::6","title":"MESSAGE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/message-no-delete::breaking::7","title":"MESSAGE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/message-no-delete::breaking::8","title":"MESSAGE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message User { string name = 1; string email = 2; Address address = 3; // ERROR: Address больше не существует }","content":"Плохой (Breaking) message User { string name = 1; string email = 2; Address address = 3; // ERROR: Address больше не существует }"},{"id":"cli/breaking-changes/rules/message-no-delete::breaking::9","title":"MESSAGE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) // Address удалён — BREAKING CHANGE!","content":"Плохой (Breaking) // Address удалён — BREAKING CHANGE!"},{"id":"cli/breaking-changes/rules/message-no-delete::breaking::10","title":"MESSAGE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message Order { string id = 1; User user = 2; } ```","content":"Плохой (Breaking) message Order { string id = 1; User user = 2; } ```"},{"id":"cli/breaking-changes/rules/message-no-delete::top::11","title":"MESSAGE_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры **Удаление вложенного сообщения:**","content":"Дополнительные примеры **Удаление вложенного сообщения:**"},{"id":"cli/breaking-changes/rules/message-no-delete::top::12","title":"MESSAGE_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры ```proto // Before message User { string name = 1; Profile profile = 2; message Profile { // [!code --] string bio = 1; // [!code --] string avatar_url = 2; // [!code --] } // [!code --] }","content":"Дополнительные примеры ```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::top::13","title":"MESSAGE_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры // After - BREAKING CHANGE! message User { string name = 1; Profile profile = 2; // ERROR: Profile удалён // Вложенное сообщение Profile удалено } ```","content":"Дополнительные примеры // After - BREAKING CHANGE! message User { string name = 1; Profile profile = 2; // ERROR: Profile удалён // Вложенное сообщение Profile удалено } ```"},{"id":"cli/breaking-changes/rules/message-no-delete::top::14","title":"MESSAGE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо удаления — пометить как deprecated:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо удаления — пометить как deprecated:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/message-no-delete::top::15","title":"MESSAGE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/message-no-delete::top::16","title":"MESSAGE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message User { string name = 1; string email = 2; Address address = 3 [deprecated = true]; // [!code focus] }","content":"Хороший (Безопасный) message User { string name = 1; string email = 2; Address address = 3 [deprecated = true]; // [!code focus] }"},{"id":"cli/breaking-changes/rules/message-no-delete::top::17","title":"MESSAGE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message Address { option deprecated = true; // [!code focus] string street = 1; string city = 2; string country = 3; }","content":"Хороший (Безопасный) message Address { option deprecated = true; // [!code focus] string street = 1; string city = 2; string country = 3; }"},{"id":"cli/breaking-changes/rules/message-no-delete::top::18","title":"MESSAGE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message Order { string id = 1; User user = 2; } ```","content":"Хороший (Безопасный) message Order { string id = 1; User user = 2; } ```"},{"id":"cli/breaking-changes/rules/message-no-delete::top::19","title":"MESSAGE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Или заменить новой версией сообщения:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Или заменить новой версией сообщения:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/message-no-delete::top::20","title":"MESSAGE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/message-no-delete::top::21","title":"MESSAGE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message User { string name = 1; string email = 2; Address address = 3 [deprecated = true]; // [!code focus] // Старое поле AddressV2 address_v2 = 4; // [!code focus] // Новая улучшенная структура }","content":"Хороший (Безопасный) message User { string name = 1; string email = 2; Address address = 3 [deprecated = true]; // [!code focus] // Старое поле AddressV2 address_v2 = 4; // [!code focus] // Новая улучшенная структура }"},{"id":"cli/breaking-changes/rules/message-no-delete::top::22","title":"MESSAGE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message Address { option deprecated = true; // [!code focus] string street = 1; string city = 2; string country = 3; }","content":"Хороший (Безопасный) message Address { option deprecated = true; // [!code focus] string street = 1; string city = 2; string country = 3; }"},{"id":"cli/breaking-changes/rules/message-no-delete::top::23","title":"MESSAGE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) 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 c","content":"Хороший (Безопасный) 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::top::24","title":"MESSAGE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message Order { string id = 1; User user = 2; } ```","content":"Хороший (Безопасный) message Order { string id = 1; User user = 2; } ```"},{"id":"cli/breaking-changes/rules/message-no-delete::top::25","title":"MESSAGE_NO_DELETE","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Влияние"],"excerpt":"Влияние **Wire Format:** Старые данные с удалённым сообщением не десериализуются **Generated Code:** Классы/структуры удаляются — компиляция клиента ломается **Field References:** Поля, использующие удалённый тип, станов","content":"Влияние **Wire Format:** Старые данные с удалённым сообщением не десериализуются **Generated Code:** Классы/структуры удаляются — компиляция клиента ломается **Field References:** Поля, использующие удалённый тип, становятся невалидны **Nested Dependencies:** Все сообщения, ссылающиеся на удалённый тип, ломаются"},{"id":"cli/breaking-changes/rules/message-no-delete::top::26","title":"MESSAGE_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Код клиента ломается:** ```go // Before user := &myapi.User{ Name: \"John Doe\", Email: \"john@example.com\", Address: &myapi.Address{ // ERROR после удаления Street: \"123 Main St\", City: \"New York\", Countr","content":"Реальный пример **Код клиента ломается:** ```go // Before user := &myapi.User{ Name: \"John Doe\", Email: \"john@example.com\", Address: &myapi.Address{ // ERROR после удаления Street: \"123 Main St\", City: \"New York\", Country: \"USA\", }, }"},{"id":"cli/breaking-changes/rules/message-no-delete::top::27","title":"MESSAGE_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример // undefined: myapi.Address ```","content":"Реальный пример // undefined: myapi.Address ```"},{"id":"cli/breaking-changes/rules/message-no-delete::top::28","title":"MESSAGE_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Старые данные становятся нечитаемыми:**","content":"Реальный пример **Старые данные становятся нечитаемыми:**"},{"id":"cli/breaking-changes/rules/message-no-delete::top::29","title":"MESSAGE_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Пометить как deprecated:** **Пометить поля, использующие его:** **Добавить замену при необходимости:** **Удалить в следующей major‑версии после периода миграции**","content":"Стратегия миграции **Пометить как deprecated:** **Пометить поля, использующие его:** **Добавить замену при необходимости:** **Удалить в следующей major‑версии после периода миграции**"},{"id":"cli/breaking-changes/rules/message-no-delete::top::30","title":"MESSAGE_NO_DELETE","section":"Рефакторинг структуры","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Рефакторинг структуры"],"excerpt":"Рефакторинг структуры ```proto message UserInfo { option deprecated = true; string name = 1; string email = 2; }","content":"Рефакторинг структуры ```proto message UserInfo { option deprecated = true; string name = 1; string email = 2; }"},{"id":"cli/breaking-changes/rules/message-no-delete::top::31","title":"MESSAGE_NO_DELETE","section":"Рефакторинг структуры","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Рефакторинг структуры"],"excerpt":"Рефакторинг структуры message UserProfile { string full_name = 1; string email_address = 2; string phone = 3; } ```","content":"Рефакторинг структуры message UserProfile { string full_name = 1; string email_address = 2; string phone = 3; } ```"},{"id":"cli/breaking-changes/rules/message-no-delete::top::32","title":"MESSAGE_NO_DELETE","section":"Удаление «неиспользуемых» сообщений","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Удаление «неиспользуемых» сообщений"],"excerpt":"Удаление «неиспользуемых» сообщений","content":"Удаление «неиспользуемых» сообщений"},{"id":"cli/breaking-changes/rules/message-no-delete::top::33","title":"MESSAGE_NO_DELETE","section":"Миграция версии","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Миграция версии"],"excerpt":"Миграция версии ```proto package myapi.v2;","content":"Миграция версии ```proto package myapi.v2;"},{"id":"cli/breaking-changes/rules/message-no-delete::top::34","title":"MESSAGE_NO_DELETE","section":"Миграция версии","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Миграция версии"],"excerpt":"Миграция версии message User { // Новая структура без устаревших ссылок } ```","content":"Миграция версии message User { // Новая структура без устаревших ссылок } ```"},{"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":"Правило проверяет, что ни одно поле внутри oneof группы не было удалено. Удаление поля из oneof ломает совместимость по wire‑формату и сгенерированный код: в сохранённых данных может присутствовать выбранный вариант, а к","content":"Правило проверяет, что ни одно поле внутри oneof группы не было удалено. Удаление поля из oneof ломает совместимость по wire‑формату и сгенерированный код: в сохранённых данных может присутствовать выбранный вариант, а клиентский код опирается на сгенерированные типы‑обёртки и методы доступа."},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::breaking::1","title":"ONEOF_FIELD_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::breaking::2","title":"ONEOF_FIELD_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::breaking::3","title":"ONEOF_FIELD_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message LoginRequest { string username = 1; oneof credentials { string password = 2; string api_key = 3; string oauth_token = 4; string certificate = 5; } }","content":"Плохой (Breaking) 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::breaking::4","title":"ONEOF_FIELD_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message SearchQuery { oneof filter { string text = 1; int32 user_id = 2; string category = 3; DateRange date_range = 4; } } ```","content":"Плохой (Breaking) 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::breaking::5","title":"ONEOF_FIELD_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::breaking::6","title":"ONEOF_FIELD_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::breaking::7","title":"ONEOF_FIELD_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message LoginRequest { string username = 1; oneof credentials { string password = 2; string api_key = 3; // string oauth_token = 4; // [!code --] Удалено поле oneof — BREAKING! // string certificate = 5","content":"Плохой (Breaking) message LoginRequest { string username = 1; oneof credentials { string password = 2; string api_key = 3; // string oauth_token = 4; // [!code --] Удалено поле oneof — BREAKING! // string certificate = 5; // [!code --] Удалено поле oneof — BREAKING! } }"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::breaking::8","title":"ONEOF_FIELD_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message SearchQuery { oneof filter { string text = 1; int32 user_id = 2; // string category = 3; // [!code --] Удалено поле oneof — BREAKING! // DateRange date_range = 4; // [!code --] Удалено поле oneo","content":"Плохой (Breaking) message SearchQuery { oneof filter { string text = 1; int32 user_id = 2; // string category = 3; // [!code --] Удалено поле oneof — BREAKING! // DateRange date_range = 4; // [!code --] Удалено поле oneof — BREAKING! } } ```"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::9","title":"ONEOF_FIELD_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры **Удаление вложенных oneof полей:** ```proto // Before message PaymentRequest { string order_id = 1; oneof payment_method { CreditCardPayment credit_card = 2; BankTransferPayment bank_transfer = 3;","content":"Дополнительные примеры **Удаление вложенных oneof полей:** ```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::top::10","title":"ONEOF_FIELD_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры // After - BREAKING CHANGES! message PaymentRequest { string order_id = 1; oneof payment_method { CreditCardPayment credit_card = 2; BankTransferPayment bank_transfer = 3; // CryptoPayment crypto =","content":"Дополнительные примеры // 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::top::11","title":"ONEOF_FIELD_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо удаления — пометить поля deprecated:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо удаления — пометить поля deprecated:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::12","title":"ONEOF_FIELD_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::13","title":"ONEOF_FIELD_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) 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 [deprecate","content":"Хороший (Безопасный) 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::top::14","title":"ONEOF_FIELD_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) 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":"Хороший (Безопасный) 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::top::15","title":"ONEOF_FIELD_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Или добавить новые поля, оставив старые:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Или добавить новые поля, оставив старые:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::16","title":"ONEOF_FIELD_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::17","title":"ONEOF_FIELD_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message LoginRequest { string username = 1; oneof credentials { string password = 2; string api_key = 3; string oauth_token = 4 [deprecated = true]; // [!code focus] // Старое поле string certificate","content":"Хороший (Безопасный) 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] OAuthCredentials oauth_v2 = 6; // [!code focus] // Новый структурированный вариант CertificateCredentials cert_v2 = 7; // [!code focus] } } ```"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::18","title":"ONEOF_FIELD_NO_DELETE","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Влияние"],"excerpt":"Влияние **Wire Format:** Данные, содержащие удалённый вариант, не десериализуются корректно **Generated Code:** Удаляются типы‑обёртки и accessor методы — компиляция клиентов ломается **Type Safety:** Логика switch по ти","content":"Влияние **Wire Format:** Данные, содержащие удалённый вариант, не десериализуются корректно **Generated Code:** Удаляются типы‑обёртки и accessor методы — компиляция клиентов ломается **Type Safety:** Логика switch по типам oneof разваливается **Business Logic:** Код, ожидающий конкретный вариант, перестаёт работать"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::19","title":"ONEOF_FIELD_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Код клиента ломается:** ```go // Before loginReq := &myapi.LoginRequest{ Username: \"user123\", }","content":"Реальный пример **Код клиента ломается:** ```go // Before loginReq := &myapi.LoginRequest{ Username: \"user123\", }"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::20","title":"ONEOF_FIELD_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример loginReq.Credentials = &myapi.LoginRequest_OauthToken{ OauthToken: \"token123\", // ERROR после удаления поля }","content":"Реальный пример loginReq.Credentials = &myapi.LoginRequest_OauthToken{ OauthToken: \"token123\", // ERROR после удаления поля }"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::21","title":"ONEOF_FIELD_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример switch cred := loginReq.Credentials.(type) { case *myapi.LoginRequest_Password: return authenticatePassword(cred.Password) case *myapi.LoginRequest_OauthToken: // ERROR: тип удалён return authenticateOAut","content":"Реальный пример switch cred := loginReq.Credentials.(type) { case *myapi.LoginRequest_Password: return authenticatePassword(cred.Password) case *myapi.LoginRequest_OauthToken: // ERROR: тип удалён return authenticateOAuth(cred.OauthToken) case *myapi.LoginRequest_Certificate: // ERROR: тип удалён return authenticateCert(cred.Certificate) default: return errors.New(\"unsupported credential type\") } // undefined: myapi.LoginRequest_OauthToken // undefined: myapi.LoginRequest_Certificate ```"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::22","title":"ONEOF_FIELD_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Серверная логика ломается:**","content":"Реальный пример **Серверная логика ломается:**"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::23","title":"ONEOF_FIELD_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Старые данные становятся нечитаемыми:**","content":"Реальный пример **Старые данные становятся нечитаемыми:**"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::24","title":"ONEOF_FIELD_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Депрецируйте сначала:** **Добавьте новые структурированные поля:** **Сервер: поддерживайте оба варианта:** **Мигрируйте клиентов на новое поле:** **Зарезервируйте номера удалённых полей в следующей m","content":"Стратегия миграции **Депрецируйте сначала:** **Добавьте новые структурированные поля:** **Сервер: поддерживайте оба варианта:** **Мигрируйте клиентов на новое поле:** **Зарезервируйте номера удалённых полей в следующей major‑версии:**"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::25","title":"ONEOF_FIELD_NO_DELETE","section":"Удаление неподдерживаемых методов аутентификации","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Удаление неподдерживаемых методов аутентификации"],"excerpt":"Удаление неподдерживаемых методов аутентификации","content":"Удаление неподдерживаемых методов аутентификации"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::26","title":"ONEOF_FIELD_NO_DELETE","section":"Изменения бизнес‑логики платежей","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Изменения бизнес‑логики платежей"],"excerpt":"Изменения бизнес‑логики платежей","content":"Изменения бизнес‑логики платежей"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::oneof-field-deletion-vs::27","title":"ONEOF_FIELD_NO_DELETE","section":"OneOf Field Deletion vs обычное удаление","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#oneof-field-deletion-vs","headings":["OneOf Field Deletion vs обычное удаление"],"excerpt":"OneOf Field Deletion vs обычное удаление","content":"OneOf Field Deletion vs обычное удаление"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::28","title":"ONEOF_FIELD_NO_DELETE","section":"Отличия от удаления обычного поля","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Отличия от удаления обычного поля"],"excerpt":"Отличия от удаления обычного поля ```proto message User { string name = 1; // string email = 2; // BREAKING: обычное поле }","content":"Отличия от удаления обычного поля ```proto message User { string name = 1; // string email = 2; // BREAKING: обычное поле }"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::29","title":"ONEOF_FIELD_NO_DELETE","section":"Отличия от удаления обычного поля","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Отличия от удаления обычного поля"],"excerpt":"Отличия от удаления обычного поля message User { oneof contact { string email = 1; // string phone = 2; // BREAKING: поле в oneof } } ```","content":"Отличия от удаления обычного поля message User { oneof contact { string email = 1; // string phone = 2; // BREAKING: поле в oneof } } ```"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::30","title":"ONEOF_FIELD_NO_DELETE","section":"Влияние на сгенерированный код","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Влияние на сгенерированный код"],"excerpt":"Влияние на сгенерированный код ```go // Обычное поле: удаляется простой геттер // user.GetEmail()","content":"Влияние на сгенерированный код ```go // Обычное поле: удаляется простой геттер // user.GetEmail()"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::31","title":"ONEOF_FIELD_NO_DELETE","section":"Влияние на сгенерированный код","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Влияние на сгенерированный код"],"excerpt":"Влияние на сгенерированный код // Поле в oneof: пропадает тип-обёртка, кейсы switch ломаются // *LoginRequest_OauthToken ```","content":"Влияние на сгенерированный код // Поле в oneof: пропадает тип-обёртка, кейсы switch ломаются // *LoginRequest_OauthToken ```"},{"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":"Это правило проверяет, что тип поля внутри oneof НЕ меняется. Смена типа любого варианта oneof — несовместимое (breaking) изменение: существующие данные сериализованы с прежним типом, а клиентский код ожидает конкретные ","content":"Это правило проверяет, что тип поля внутри oneof НЕ меняется. Смена типа любого варианта oneof — несовместимое (breaking) изменение: существующие данные сериализованы с прежним типом, а клиентский код ожидает конкретные типы-обёртки и методы доступа, сгенерированные для каждого варианта."},{"id":"cli/breaking-changes/rules/oneof-field-same-type::breaking::1","title":"ONEOF_FIELD_SAME_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::breaking::2","title":"ONEOF_FIELD_SAME_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::breaking::3","title":"ONEOF_FIELD_SAME_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message SearchRequest { string query = 1; oneof filter { string category = 2; int32 user_id = 3; bool is_premium = 4; DateRange date_range = 5; } }","content":"Плохой (Breaking) 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::breaking::4","title":"ONEOF_FIELD_SAME_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message NotificationSettings { oneof delivery { string email = 1; int64 phone_number = 2; WebhookConfig webhook = 3; } } ```","content":"Плохой (Breaking) message NotificationSettings { oneof delivery { string email = 1; int64 phone_number = 2; WebhookConfig webhook = 3; } } ```"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::breaking::5","title":"ONEOF_FIELD_SAME_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::breaking::6","title":"ONEOF_FIELD_SAME_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::breaking::7","title":"ONEOF_FIELD_SAME_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message SearchRequest { string query = 1; oneof filter { int32 category = 2; // [!code --] Было string -> стало int32 (BREAKING) string user_id = 3; // [!code --] Было int32 -> стало string (BREAKING) s","content":"Плохой (Breaking) message SearchRequest { string query = 1; oneof filter { int32 category = 2; // [!code --] Было string -> стало int32 (BREAKING) string user_id = 3; // [!code --] Было int32 -> стало string (BREAKING) string is_premium = 4; // [!code --] Было bool -> стало string (BREAKING) string date_range = 5; // [!code --] Было DateRange -> стало string (BREAKING) } }"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::breaking::8","title":"ONEOF_FIELD_SAME_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message NotificationSettings { oneof delivery { EmailConfig email = 1; // [!code --] Было string -> стало EmailConfig (BREAKING) string phone_number = 2; // [!code --] Было int64 -> стало string (BREAKI","content":"Плохой (Breaking) message NotificationSettings { oneof delivery { EmailConfig email = 1; // [!code --] Было string -> стало EmailConfig (BREAKING) string phone_number = 2; // [!code --] Было int64 -> стало string (BREAKING) string webhook = 3; // [!code --] Было WebhookConfig -> стало string (BREAKING) } } ```"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::9","title":"ONEOF_FIELD_SAME_TYPE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры **Комплексные изменения типов:** ```proto // Before message PaymentRequest { oneof payment_info { CreditCardInfo credit_card = 1; BankAccountInfo bank_account = 2; string paypal_email = 3; CryptoWa","content":"Дополнительные примеры **Комплексные изменения типов:** ```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::top::10","title":"ONEOF_FIELD_SAME_TYPE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры // After - ВСЁ BREAKING message PaymentRequest { oneof payment_info { string credit_card = 1; // CreditCardInfo -> string PayPalInfo bank_account = 2; // BankAccountInfo -> PayPalInfo PayPalInfo pa","content":"Дополнительные примеры // After - ВСЁ BREAKING message PaymentRequest { oneof payment_info { string credit_card = 1; // CreditCardInfo -> string PayPalInfo bank_account = 2; // BankAccountInfo -> PayPalInfo PayPalInfo paypal_email = 3; // string -> PayPalInfo string crypto = 4; // CryptoWalletInfo -> string } } ```"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::11","title":"ONEOF_FIELD_SAME_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо смены типа — добавьте новое поле в тот же oneof:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо смены типа — добавьте новое поле в тот же oneof:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::12","title":"ONEOF_FIELD_SAME_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::13","title":"ONEOF_FIELD_SAME_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message SearchRequest { string query = 1; oneof filter { string category = 2 [deprecated = true]; // Старый тип int32 user_id = 3 [deprecated = true]; bool is_premium = 4 [deprecated = true]; DateRan","content":"Хороший (Безопасный) message SearchRequest { string query = 1; oneof filter { string category = 2 [deprecated = true]; // Старый тип int32 user_id = 3 [deprecated = true]; bool is_premium = 4 [deprecated = true]; DateRange date_range = 5 [deprecated = true]; int32 category_id = 6; // Новая версия string user_identifier = 7; string premium_status = 8; string date_filter = 9; } } ```"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::14","title":"ONEOF_FIELD_SAME_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Или создайте новый oneof:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Или создайте новый oneof:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::15","title":"ONEOF_FIELD_SAME_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::16","title":"ONEOF_FIELD_SAME_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message SearchRequest { string query = 1; oneof filter { option deprecated = true; string category = 2 [deprecated = true]; int32 user_id = 3 [deprecated = true]; bool is_premium = 4 [deprecated = tr","content":"Хороший (Безопасный) message SearchRequest { string query = 1; oneof filter { option deprecated = true; string category = 2 [deprecated = true]; int32 user_id = 3 [deprecated = true]; bool is_premium = 4 [deprecated = true]; DateRange date_range = 5 [deprecated = true]; } oneof filter_v2 { int32 category_id = 6; string user_identifier = 7; PremiumFilter premium_filter = 8; TimeFilter time_filter = 9; } } ```"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::17","title":"ONEOF_FIELD_SAME_TYPE","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Влияние"],"excerpt":"Влияние **Wire Format:** Старые бинарные данные не читаются корректно **Generated Code:** Меняются типы-обёртки, код клиента не компилируется **Type Safety:** switch по варианту oneof ломается **Runtime Errors:** Ошибки ","content":"Влияние **Wire Format:** Старые бинарные данные не читаются корректно **Generated Code:** Меняются типы-обёртки, код клиента не компилируется **Type Safety:** switch по варианту oneof ломается **Runtime Errors:** Ошибки десериализации и логики при несовпадении типов"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::18","title":"ONEOF_FIELD_SAME_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Реальный пример"],"excerpt":"Реальный пример **Ломается клиентский код:** ```go // Before searchReq := &myapi.SearchRequest{ Query: \"golang jobs\", }","content":"Реальный пример **Ломается клиентский код:** ```go // Before searchReq := &myapi.SearchRequest{ Query: \"golang jobs\", }"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::19","title":"ONEOF_FIELD_SAME_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Реальный пример"],"excerpt":"Реальный пример // Устанавливаем вариант oneof searchReq.Filter = &myapi.SearchRequest_Category{ Category: \"engineering\", }","content":"Реальный пример // Устанавливаем вариант oneof searchReq.Filter = &myapi.SearchRequest_Category{ Category: \"engineering\", }"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::20","title":"ONEOF_FIELD_SAME_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Реальный пример"],"excerpt":"Реальный пример // Обработка вариантов switch filter := searchReq.Filter.(type) { case *myapi.SearchRequest_Category: return searchByCategory(filter.Category) case *myapi.SearchRequest_UserId: return searchByUserId(filte","content":"Реальный пример // Обработка вариантов switch filter := searchReq.Filter.(type) { case *myapi.SearchRequest_Category: return searchByCategory(filter.Category) case *myapi.SearchRequest_UserId: return searchByUserId(filter.UserId) default: return errors.New(\"unsupported filter\") }"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::21","title":"ONEOF_FIELD_SAME_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Реальный пример"],"excerpt":"Реальный пример // After — тип Category стал int32 searchReq.Filter = &myapi.SearchRequest_Category{ Category: \"engineering\", // ERROR }","content":"Реальный пример // After — тип Category стал int32 searchReq.Filter = &myapi.SearchRequest_Category{ Category: \"engineering\", // ERROR }"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::22","title":"ONEOF_FIELD_SAME_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Реальный пример"],"excerpt":"Реальный пример switch filter := searchReq.Filter.(type) { case *myapi.SearchRequest_Category: return searchByCategory(filter.Category) // ERROR case *myapi.SearchRequest_UserId: return searchByUserId(filter.UserId) // E","content":"Реальный пример switch filter := searchReq.Filter.(type) { case *myapi.SearchRequest_Category: return searchByCategory(filter.Category) // ERROR case *myapi.SearchRequest_UserId: return searchByUserId(filter.UserId) // ERROR: UserId теперь string } ```"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::23","title":"ONEOF_FIELD_SAME_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Реальный пример"],"excerpt":"Реальный пример **Ломается серверная логика:** ```go // Before func handleSearchFilter(req *SearchRequest) (*SearchResult, error) { switch filter := req.Filter.(type) { case *SearchRequest_Category: return searchDatabase","content":"Реальный пример **Ломается серверная логика:** ```go // Before func handleSearchFilter(req *SearchRequest) (*SearchResult, error) { switch filter := req.Filter.(type) { case *SearchRequest_Category: return searchDatabase(\"category\", filter.Category), nil case *SearchRequest_UserId: return searchDatabase(\"user_id\", strconv.Itoa(int(filter.UserId))), nil default: return nil, errors.New(\"no filter specified\") } }"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::24","title":"ONEOF_FIELD_SAME_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Реальный пример"],"excerpt":"Реальный пример // After — несовпадения типов func handleSearchFilter(req *SearchRequest) (*SearchResult, error) { switch filter := req.Filter.(type) { case *SearchRequest_Category: // filter.Category теперь int32, а код","content":"Реальный пример // After — несовпадения типов func handleSearchFilter(req *SearchRequest) (*SearchResult, error) { switch filter := req.Filter.(type) { case *SearchRequest_Category: // filter.Category теперь int32, а код ожидал string return searchDatabase(\"category\", filter.Category), nil // ERROR case *SearchRequest_UserId: userIdStr := filter.UserId // string вместо int32 userId, _ := strconv.Atoi(userIdStr) return searchDatabase(\"user_id\", strconv.Itoa(userId)), nil } } ```"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::25","title":"ONEOF_FIELD_SAME_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Реальный пример"],"excerpt":"Реальный пример **Порча данных:**","content":"Реальный пример **Порча данных:**"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::26","title":"ONEOF_FIELD_SAME_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции Добавьте новое поле: Сервер поддерживает оба: Клиенты переходят на category_id. Скрипты миграции преобразуют старые данные. В следующей major‑версии:","content":"Стратегия миграции Добавьте новое поле: Сервер поддерживает оба: Клиенты переходят на category_id. Скрипты миграции преобразуют старые данные. В следующей major‑версии:"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::27","title":"ONEOF_FIELD_SAME_TYPE","section":"Переход к структурированным типам","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Переход к структурированным типам"],"excerpt":"Переход к структурированным типам","content":"Переход к структурированным типам"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::28","title":"ONEOF_FIELD_SAME_TYPE","section":"Матрица совместимости","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Матрица совместимости"],"excerpt":"Матрица совместимости From Type To Type Результат ----------- --------- ----------- string int32/int64 ❌ BREAKING int32 string ❌ BREAKING bool string ❌ BREAKING message string ❌ BREAKING string message ❌ BREAKING enum in","content":"Матрица совместимости From Type To Type Результат ----------- --------- ----------- 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::top::29","title":"ONEOF_FIELD_SAME_TYPE","section":"Влияние на сгенерированный код","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Влияние на сгенерированный код"],"excerpt":"Влияние на сгенерированный код","content":"Влияние на сгенерированный код"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::30","title":"ONEOF_FIELD_SAME_TYPE","section":"Валидация","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Валидация"],"excerpt":"Валидация **После (сломано):**","content":"Валидация **После (сломано):**"},{"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":"Это правило проверяет, что ни один oneof блок не был удалён из сообщений. Удаление oneof ломает совместимость по wire‑формату и сгенерированный код: существующие данные могут содержать ранее выбранный вариант, а клиентск","content":"Это правило проверяет, что ни один oneof блок не был удалён из сообщений. Удаление oneof ломает совместимость по wire‑формату и сгенерированный код: существующие данные могут содержать ранее выбранный вариант, а клиентский код зависит от типов-обёрток и методов доступа, генерируемых для oneof."},{"id":"cli/breaking-changes/rules/oneof-no-delete::breaking::1","title":"ONEOF_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-no-delete::breaking::2","title":"ONEOF_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/oneof-no-delete::breaking::3","title":"ONEOF_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message LoginRequest { string username = 1; oneof credentials { string password = 2; string api_key = 3; string oauth_token = 4; } }","content":"Плохой (Breaking) 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::breaking::4","title":"ONEOF_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message PaymentMethod { // [!code --] oneof method { // [!code --] CreditCard credit_card = 1; // [!code --] BankAccount bank_account = 2; // [!code --] PayPal paypal = 3; // [!code --] } // [!code --] ","content":"Плохой (Breaking) 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::breaking::5","title":"ONEOF_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message Order { string id = 1; PaymentMethod payment = 2; } ```","content":"Плохой (Breaking) message Order { string id = 1; PaymentMethod payment = 2; } ```"},{"id":"cli/breaking-changes/rules/oneof-no-delete::breaking::6","title":"ONEOF_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-no-delete::breaking::7","title":"ONEOF_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/oneof-no-delete::breaking::8","title":"ONEOF_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message LoginRequest { string username = 1; // credentials oneof удалён — BREAKING CHANGE! string password = 2; // Теперь обычные поля string api_key = 3; // Потеряна взаимная исключаемость string oauth","content":"Плохой (Breaking) message LoginRequest { string username = 1; // credentials oneof удалён — BREAKING CHANGE! string password = 2; // Теперь обычные поля string api_key = 3; // Потеряна взаимная исключаемость string oauth_token = 4; }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::breaking::9","title":"ONEOF_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message PaymentMethod { // method oneof удалён — BREAKING CHANGE! CreditCard credit_card = 1; // Теперь можно установить все поля одновременно BankAccount bank_account = 2; PayPal paypal = 3; }","content":"Плохой (Breaking) message PaymentMethod { // method oneof удалён — BREAKING CHANGE! CreditCard credit_card = 1; // Теперь можно установить все поля одновременно BankAccount bank_account = 2; PayPal paypal = 3; }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::breaking::10","title":"ONEOF_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message Order { string id = 1; PaymentMethod payment = 2; } ```","content":"Плохой (Breaking) message Order { string id = 1; PaymentMethod payment = 2; } ```"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::11","title":"ONEOF_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры **Удаление вложенного oneof:** ```proto // Before message UserProfile { string name = 1; message ContactInfo { oneof contact_method { // [!code --] string email = 1; // [!code --] string phone = 2;","content":"Дополнительные примеры **Удаление вложенного oneof:** ```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::top::12","title":"ONEOF_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры // After - BREAKING CHANGE! message UserProfile { string name = 1; message ContactInfo { // contact_method oneof удалён string email = 1; // Больше не эксклюзивно string phone = 2; // Можно задать ","content":"Дополнительные примеры // After - BREAKING CHANGE! message UserProfile { string name = 1; message ContactInfo { // contact_method oneof удалён string email = 1; // Больше не эксклюзивно string phone = 2; // Можно задать всё сразу string slack_id = 3; } ContactInfo contact = 2; } ```"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::13","title":"ONEOF_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо удаления — депрецируйте oneof:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо удаления — депрецируйте oneof:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::14","title":"ONEOF_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::15","title":"ONEOF_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message LoginRequest { string username = 1; oneof credentials { option deprecated = true; // [!code focus] string password = 2 [deprecated = true]; // [!code focus] string api_key = 3 [deprecated = t","content":"Хороший (Безопасный) 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::top::16","title":"ONEOF_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message PaymentMethod { oneof method { option deprecated = true; // [!code focus] CreditCard credit_card = 1 [deprecated = true]; // [!code focus] BankAccount bank_account = 2 [deprecated = true]; //","content":"Хороший (Безопасный) 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::top::17","title":"ONEOF_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Или заменить новой структурой:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Или заменить новой структурой:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::18","title":"ONEOF_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::19","title":"ONEOF_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message LoginRequest { string username = 1; oneof credentials { option deprecated = true; // [!code focus] // Старый oneof string password = 2 [deprecated = true]; // [!code focus] string api_key = 3","content":"Хороший (Безопасный) message LoginRequest { string username = 1; oneof credentials { option deprecated = true; // [!code focus] // Старый 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] // Новый дизайн 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::top::20","title":"ONEOF_NO_DELETE","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Влияние"],"excerpt":"Влияние **Wire Format:** Теряются семантика взаимной исключаемости — больше одного поля может быть установлено **Generated Code:** Удаляются типы-обёртки и accessor методы — код клиента не компилируется **Business Logic:","content":"Влияние **Wire Format:** Теряются семантика взаимной исключаемости — больше одного поля может быть установлено **Generated Code:** Удаляются типы-обёртки и accessor методы — код клиента не компилируется **Business Logic:** Нарушаются инварианты «только один из» **Validation:** Логика проверок должна быть переписана вручную"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::21","title":"ONEOF_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Код клиента ломается:** ```go // Before - oneOf даёт взаимную исключаемость loginReq := &myapi.LoginRequest{ Username: \"user123\", }","content":"Реальный пример **Код клиента ломается:** ```go // Before - oneOf даёт взаимную исключаемость loginReq := &myapi.LoginRequest{ Username: \"user123\", }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::22","title":"ONEOF_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример loginReq.Credentials = &myapi.LoginRequest_Password{ Password: \"secret123\", }","content":"Реальный пример loginReq.Credentials = &myapi.LoginRequest_Password{ Password: \"secret123\", }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::23","title":"ONEOF_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример switch cred := loginReq.Credentials.(type) { case *myapi.LoginRequest_Password: // ERROR после удаления return authenticatePassword(cred.Password) case *myapi.LoginRequest_ApiKey: // ERROR после удаления ","content":"Реальный пример switch cred := loginReq.Credentials.(type) { case *myapi.LoginRequest_Password: // ERROR после удаления return authenticatePassword(cred.Password) case *myapi.LoginRequest_ApiKey: // ERROR после удаления return authenticateApiKey(cred.ApiKey) default: return errors.New(\"no credentials provided\") }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::24","title":"ONEOF_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример // Compilation errors: // undefined: myapi.LoginRequest_Password // undefined field: loginReq.Credentials ```","content":"Реальный пример // Compilation errors: // undefined: myapi.LoginRequest_Password // undefined field: loginReq.Credentials ```"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::25","title":"ONEOF_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Валидация на сервере ломается:** ```go // Before func validateLoginRequest(req *LoginRequest) error { if req.Credentials == nil { return errors.New(\"credentials required\") } switch req.Credentials.(type","content":"Реальный пример **Валидация на сервере ломается:** ```go // Before func validateLoginRequest(req *LoginRequest) error { if req.Credentials == nil { return errors.New(\"credentials required\") } 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::top::26","title":"ONEOF_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример // After func validateLoginRequest(req *LoginRequest) error { credCount := 0 if req.Password != \"\" { credCount++ } if req.ApiKey != \"\" { credCount++ } if req.OauthToken != \"\" { credCount++ }","content":"Реальный пример // After func validateLoginRequest(req *LoginRequest) error { credCount := 0 if req.Password != \"\" { credCount++ } if req.ApiKey != \"\" { credCount++ } if req.OauthToken != \"\" { credCount++ }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::27","title":"ONEOF_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример if credCount == 0 { return errors.New(\"no credentials provided\") } if credCount > 1 { return errors.New(\"multiple credentials provided\") }","content":"Реальный пример if credCount == 0 { return errors.New(\"no credentials provided\") } if credCount > 1 { return errors.New(\"multiple credentials provided\") }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::28","title":"ONEOF_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример if req.Password != \"\" { return validatePassword(req.Password) } // Дополнительные проверки вручную... return nil } ```","content":"Реальный пример if req.Password != \"\" { return validatePassword(req.Password) } // Дополнительные проверки вручную... return nil } ```"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::29","title":"ONEOF_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Проблемы бизнес‑логики:** ```go // Before payment := &PaymentMethod{ Method: &PaymentMethod_CreditCard{ CreditCard: &CreditCard{Number: \"1234\"}, }, }","content":"Реальный пример **Проблемы бизнес‑логики:** ```go // Before payment := &PaymentMethod{ Method: &PaymentMethod_CreditCard{ CreditCard: &CreditCard{Number: \"1234\"}, }, }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::30","title":"ONEOF_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример // After — можно задать несколько способов сразу payment := &PaymentMethod{ CreditCard: &CreditCard{Number: \"1234\"}, BankAccount: &BankAccount{Number: \"5678\"}, // Ломает бизнес-логику } ```","content":"Реальный пример // After — можно задать несколько способов сразу payment := &PaymentMethod{ CreditCard: &CreditCard{Number: \"1234\"}, BankAccount: &BankAccount{Number: \"5678\"}, // Ломает бизнес-логику } ```"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::31","title":"ONEOF_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Депрецируйте старый oneof и его поля:**","content":"Стратегия миграции **Депрецируйте старый oneof и его поля:**"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::32","title":"ONEOF_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Создайте новый блок при необходимости:**","content":"Стратегия миграции **Создайте новый блок при необходимости:**"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::33","title":"ONEOF_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Сервер: поддерживайте оба до миграции:**","content":"Стратегия миграции **Сервер: поддерживайте оба до миграции:**"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::34","title":"ONEOF_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Клиенты: переходите на новый oneof:**","content":"Стратегия миграции **Клиенты: переходите на новый oneof:**"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::35","title":"ONEOF_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Удалите старый oneof** в следующей major‑версии.","content":"Стратегия миграции **Удалите старый oneof** в следующей major‑версии."},{"id":"cli/breaking-changes/rules/oneof-no-delete::oneof::36","title":"ONEOF_NO_DELETE","section":"Замена oneof обычными полями","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#oneof","headings":["Замена oneof обычными полями"],"excerpt":"Замена oneof обычными полями ```proto message SearchRequest { // НЕЛЬЗЯ просто убрать oneof — ломает семантику string text_query = 1; // BREAKING int32 user_id = 2; // BREAKING string category = 3; // BREAKING }","content":"Замена oneof обычными полями ```proto message SearchRequest { // НЕЛЬЗЯ просто убрать oneof — ломает семантику string text_query = 1; // BREAKING int32 user_id = 2; // BREAKING string category = 3; // BREAKING }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::oneof::37","title":"ONEOF_NO_DELETE","section":"Замена oneof обычными полями","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#oneof","headings":["Замена oneof обычными полями"],"excerpt":"Замена oneof обычными полями message SearchRequest { oneof query { option deprecated = true; string text_query = 1 [deprecated = true]; int32 user_id = 2 [deprecated = true]; string category = 3 [deprecated = true]; } st","content":"Замена oneof обычными полями message SearchRequest { oneof query { option deprecated = true; string text_query = 1 [deprecated = true]; int32 user_id = 2 [deprecated = true]; string category = 3 [deprecated = true]; } string search_text = 4; repeated string filters = 5; } ```"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::38","title":"ONEOF_NO_DELETE","section":"Упрощение структуры сообщения","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Упрощение структуры сообщения"],"excerpt":"Упрощение структуры сообщения ```proto message NotificationSettings { string email = 1; // BREAKING: был в oneof string phone = 2; // BREAKING string webhook_url = 3; // BREAKING }","content":"Упрощение структуры сообщения ```proto message NotificationSettings { string email = 1; // BREAKING: был в oneof string phone = 2; // BREAKING string webhook_url = 3; // BREAKING }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::39","title":"ONEOF_NO_DELETE","section":"Упрощение структуры сообщения","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Упрощение структуры сообщения"],"excerpt":"Упрощение структуры сообщения message NotificationSettings { oneof delivery_method { EmailNotification email = 1; SmsNotification phone = 2; WebhookNotification webhook = 3; } } ```","content":"Упрощение структуры сообщения message NotificationSettings { oneof delivery_method { EmailNotification email = 1; SmsNotification phone = 2; WebhookNotification webhook = 3; } } ```"},{"id":"cli/breaking-changes/rules/oneof-no-delete::proto2-proto3::40","title":"ONEOF_NO_DELETE","section":"Миграция с proto2 на proto3","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#proto2-proto3","headings":["Миграция с proto2 на proto3"],"excerpt":"Миграция с proto2 на proto3 ```proto // proto2 message Request { optional string name = 1; oneof data { string text = 2; int32 number = 3; } }","content":"Миграция с proto2 на proto3 ```proto // proto2 message Request { optional string name = 1; oneof data { string text = 2; int32 number = 3; } }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::proto2-proto3::41","title":"ONEOF_NO_DELETE","section":"Миграция с proto2 на proto3","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#proto2-proto3","headings":["Миграция с proto2 на proto3"],"excerpt":"Миграция с proto2 на proto3 // proto3 — сохраняем oneof message Request { string name = 1; oneof data { string text = 2; int32 number = 3; } } ```","content":"Миграция с proto2 на proto3 // proto3 — сохраняем oneof message Request { string name = 1; oneof data { string text = 2; int32 number = 3; } } ```"},{"id":"cli/breaking-changes/rules/oneof-no-delete::oneof::42","title":"ONEOF_NO_DELETE","section":"Что даёт oneof","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#oneof","headings":["Что даёт oneof"],"excerpt":"Что даёт oneof Взаимная исключаемость Типобезопасность в коде Ясность намерения API («выбери один») Эффективная сериализация — кодируется только выбранный вариант","content":"Что даёт oneof Взаимная исключаемость Типобезопасность в коде Ясность намерения API («выбери один») Эффективная сериализация — кодируется только выбранный вариант"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::43","title":"ONEOF_NO_DELETE","section":"Что теряется при удалении","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Что теряется при удалении"],"excerpt":"Что теряется при удалении Инвариант «только один» Генерируемые wrapper-типы и методы Автоматическая валидация выбора Понятность контракта API","content":"Что теряется при удалении Инвариант «только один» Генерируемые wrapper-типы и методы Автоматическая валидация выбора Понятность контракта API"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::44","title":"ONEOF_NO_DELETE","section":"Влияние на код генерации","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Влияние на код генерации"],"excerpt":"Влияние на код генерации ```go // С oneof type LoginRequest struct { Username string Credentials isLoginRequest_Credentials }","content":"Влияние на код генерации ```go // С oneof type LoginRequest struct { Username string Credentials isLoginRequest_Credentials }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::45","title":"ONEOF_NO_DELETE","section":"Влияние на код генерации","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Влияние на код генерации"],"excerpt":"Влияние на код генерации // Без oneof type LoginRequest struct { Username string Password string ApiKey string OauthToken string // Возможны многозначные конфликтующие состояния } ```","content":"Влияние на код генерации // Без oneof type LoginRequest struct { Username string Password string ApiKey string 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":"Правило проверяет, что ни один RPC‑метод не был удалён из service. Удаление RPC ломает сгенерированный код и клиентские приложения, которые этот метод вызывают.","content":"Правило проверяет, что ни один RPC‑метод не был удалён из service. Удаление RPC ломает сгенерированный код и клиентские приложения, которые этот метод вызывают."},{"id":"cli/breaking-changes/rules/rpc-no-delete::breaking::1","title":"RPC_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/rpc-no-delete::breaking::2","title":"RPC_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/rpc-no-delete::breaking::3","title":"RPC_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); rpc DeleteUser(DeleteUserRequest) returns (DeleteUserResponse","content":"Плохой (Breaking) 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::breaking::4","title":"RPC_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/rpc-no-delete::breaking::5","title":"RPC_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/rpc-no-delete::breaking::6","title":"RPC_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); // DeleteUser RPC удалён — BREAKING CHANGE! } ```","content":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); // DeleteUser RPC удалён — BREAKING CHANGE! } ```"},{"id":"cli/breaking-changes/rules/rpc-no-delete::top::7","title":"RPC_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо удаления — пометить RPC deprecated:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо удаления — пометить RPC deprecated:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/rpc-no-delete::top::8","title":"RPC_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/rpc-no-delete::top::9","title":"RPC_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); rpc DeleteUser(DeleteUserRequest) returns (DeleteUserRespo","content":"Хороший (Безопасный) 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::top::10","title":"RPC_NO_DELETE","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete","headings":["Влияние"],"excerpt":"Влияние **Generated Code:** Stub/метод исчезает — клиенты не компилируются **Client Applications:** Существующие вызовы метода падают при сборке **Runtime:** gRPC клиенты теряют определение метода","content":"Влияние **Generated Code:** Stub/метод исчезает — клиенты не компилируются **Client Applications:** Существующие вызовы метода падают при сборке **Runtime:** gRPC клиенты теряют определение метода"},{"id":"cli/breaking-changes/rules/rpc-no-delete::top::11","title":"RPC_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Сначала деприкация:**","content":"Стратегия миграции **Сначала деприкация:**"},{"id":"cli/breaking-changes/rules/rpc-no-delete::top::12","title":"RPC_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Имплементация может возвращать ошибку**, указывая что метод устарел (например, INTERNAL / UNIMPLEMENTED)","content":"Стратегия миграции **Имплементация может возвращать ошибку**, указывая что метод устарел (например, INTERNAL / UNIMPLEMENTED)"},{"id":"cli/breaking-changes/rules/rpc-no-delete::top::13","title":"RPC_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Удалить в следующей major‑версии** после миграции всех клиентов","content":"Стратегия миграции **Удалить в следующей major‑версии** после миграции всех клиентов"},{"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":"Это правило проверяет, что RPC‑методы сохраняют прежний тип сообщения запроса (request message type). Изменение типа запроса RPC ломает совместимость по wire‑формату и сгенерированный код: клиенты ожидают конкретную стру","content":"Это правило проверяет, что RPC‑методы сохраняют прежний тип сообщения запроса (request message type). Изменение типа запроса RPC ломает совместимость по wire‑формату и сгенерированный код: клиенты ожидают конкретную структуру при вызове метода."},{"id":"cli/breaking-changes/rules/rpc-same-request-type::breaking::1","title":"RPC_SAME_REQUEST_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::breaking::2","title":"RPC_SAME_REQUEST_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::breaking::3","title":"RPC_SAME_REQUEST_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse); }","content":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse); }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::breaking::4","title":"RPC_SAME_REQUEST_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message GetUserRequest { string user_id = 1; }","content":"Плохой (Breaking) message GetUserRequest { string user_id = 1; }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::breaking::5","title":"RPC_SAME_REQUEST_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message UpdateUserRequest { string user_id = 1; string name = 2; string email = 3; } ```","content":"Плохой (Breaking) message UpdateUserRequest { string user_id = 1; string name = 2; string email = 3; } ```"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::breaking::6","title":"RPC_SAME_REQUEST_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::breaking::7","title":"RPC_SAME_REQUEST_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::breaking::8","title":"RPC_SAME_REQUEST_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequestV2) returns (GetUserResponse); // [!code --] Изменён тип запроса rpc UpdateUser(UserUpdateRequest) returns (UpdateUserResponse); // [!code --] Изменён тип","content":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequestV2) returns (GetUserResponse); // [!code --] Изменён тип запроса rpc UpdateUser(UserUpdateRequest) returns (UpdateUserResponse); // [!code --] Изменён тип запроса }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::breaking::9","title":"RPC_SAME_REQUEST_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message GetUserRequestV2 { // [!code --] Новый тип запроса string id = 1; bool include_profile = 2; }","content":"Плохой (Breaking) message GetUserRequestV2 { // [!code --] Новый тип запроса string id = 1; bool include_profile = 2; }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::breaking::10","title":"RPC_SAME_REQUEST_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message UserUpdateRequest { // [!code --] Новый тип запроса string id = 1; UserProfile profile = 2; } ```","content":"Плохой (Breaking) message UserUpdateRequest { // [!code --] Новый тип запроса string id = 1; UserProfile profile = 2; } ```"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::11","title":"RPC_SAME_REQUEST_TYPE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры **Смена типа из другого пакета:** ```proto // Before import \"common/user.proto\";","content":"Дополнительные примеры **Смена типа из другого пакета:** ```proto // Before import \"common/user.proto\";"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::12","title":"RPC_SAME_REQUEST_TYPE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры service UserService { rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); }","content":"Дополнительные примеры service UserService { rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::13","title":"RPC_SAME_REQUEST_TYPE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры // After - BREAKING CHANGE! import \"v2/user.proto\";","content":"Дополнительные примеры // After - BREAKING CHANGE! import \"v2/user.proto\";"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::14","title":"RPC_SAME_REQUEST_TYPE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры service UserService { rpc CreateUser(v2.CreateUserRequest) returns (CreateUserResponse); // Другой package } ```","content":"Дополнительные примеры service UserService { rpc CreateUser(v2.CreateUserRequest) returns (CreateUserResponse); // Другой package } ```"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::15","title":"RPC_SAME_REQUEST_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо изменения типа — версионируйте RPC:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо изменения типа — версионируйте RPC:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::16","title":"RPC_SAME_REQUEST_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::17","title":"RPC_SAME_REQUEST_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse) { option deprecated = true; // [!code focus] } rpc GetUserV2(GetUserRequestV2) returns (GetUserResponse); // [!code focus] ","content":"Хороший (Безопасный) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse) { option deprecated = true; // [!code focus] } rpc GetUserV2(GetUserRequestV2) returns (GetUserResponse); // [!code focus] // Новый метод rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse) { option deprecated = true; // [!code focus] } rpc UpdateUserV2(UserUpdateRequest) returns (UpdateUserResponse); // [!code focus] // Новый метод }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::18","title":"RPC_SAME_REQUEST_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) // Старые сообщения — для обратной совместимости message GetUserRequest { string user_id = 1; }","content":"Хороший (Безопасный) // Старые сообщения — для обратной совместимости message GetUserRequest { string user_id = 1; }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::19","title":"RPC_SAME_REQUEST_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) // Новая версия сообщения message GetUserRequestV2 { // [!code focus] string id = 1; // [!code focus] bool include_profile = 2; // [!code focus] } // [!code focus] ```","content":"Хороший (Безопасный) // Новая версия сообщения 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::top::20","title":"RPC_SAME_REQUEST_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Или создайте новую версию сервиса (package v2):** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Или создайте новую версию сервиса (package v2):** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::21","title":"RPC_SAME_REQUEST_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v2; // [!code focus]","content":"Хороший (Безопасный) package myapi.v2; // [!code focus]"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::22","title":"RPC_SAME_REQUEST_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); // [!code focus] rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse); // [!code focus] }","content":"Хороший (Безопасный) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); // [!code focus] rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse); // [!code focus] }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::23","title":"RPC_SAME_REQUEST_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message GetUserRequest { // [!code focus] string id = 1; // [!code focus] bool include_profile = 2; // [!code focus] } // [!code focus] ```","content":"Хороший (Безопасный) message GetUserRequest { // [!code focus] string id = 1; // [!code focus] bool include_profile = 2; // [!code focus] } // [!code focus] ```"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::24","title":"RPC_SAME_REQUEST_TYPE","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Влияние"],"excerpt":"Влияние **Wire Format:** Старые запросы клиентов не десериализуются новым сервером **Generated Code:** Сигнатуры методов в stubs меняются — компиляция клиентов падает **gRPC Calls:** Требуется использовать другую структу","content":"Влияние **Wire Format:** Старые запросы клиентов не десериализуются новым сервером **Generated Code:** Сигнатуры методов в stubs меняются — компиляция клиентов падает **gRPC Calls:** Требуется использовать другую структуру запроса **Runtime Errors:** Несоответствие типов вызывает ошибки выполнения"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::25","title":"RPC_SAME_REQUEST_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Реальный пример"],"excerpt":"Реальный пример **Код клиента ломается:** ```go // Before client := myapi.NewUserServiceClient(conn) resp, err := client.GetUser(ctx, &myapi.GetUserRequest{ UserId: \"user123\", })","content":"Реальный пример **Код клиента ломается:** ```go // Before client := myapi.NewUserServiceClient(conn) resp, err := client.GetUser(ctx, &myapi.GetUserRequest{ UserId: \"user123\", })"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::26","title":"RPC_SAME_REQUEST_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Реальный пример"],"excerpt":"Реальный пример // After (тип запроса изменён) client := myapi.NewUserServiceClient(conn) resp, err := client.GetUser(ctx, &myapi.GetUserRequest{ // ERROR: тип не найден UserId: \"user123\", // ERROR: поле не найдено })","content":"Реальный пример // After (тип запроса изменён) client := myapi.NewUserServiceClient(conn) resp, err := client.GetUser(ctx, &myapi.GetUserRequest{ // ERROR: тип не найден UserId: \"user123\", // ERROR: поле не найдено })"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::27","title":"RPC_SAME_REQUEST_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Реальный пример"],"excerpt":"Реальный пример // Новый корректный вызов: resp, err := client.GetUser(ctx, &myapi.GetUserRequestV2{ Id: \"user123\", IncludeProfile: true, }) ```","content":"Реальный пример // Новый корректный вызов: resp, err := client.GetUser(ctx, &myapi.GetUserRequestV2{ Id: \"user123\", IncludeProfile: true, }) ```"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::28","title":"RPC_SAME_REQUEST_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Реальный пример"],"excerpt":"Реальный пример **Серверная реализация ломается:** ```go // Before func (s *server) GetUser(ctx context.Context, req *GetUserRequest) (*GetUserResponse, error) { userID := req.UserId // ... }","content":"Реальный пример **Серверная реализация ломается:** ```go // Before func (s *server) GetUser(ctx context.Context, req *GetUserRequest) (*GetUserResponse, error) { userID := req.UserId // ... }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::29","title":"RPC_SAME_REQUEST_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Реальный пример"],"excerpt":"Реальный пример // After func (s *server) GetUser(ctx context.Context, req *GetUserRequestV2) (*GetUserResponse, error) { userID := req.Id include := req.IncludeProfile // ... новая логика } ```","content":"Реальный пример // After func (s *server) GetUser(ctx context.Context, req *GetUserRequestV2) (*GetUserResponse, error) { userID := req.Id include := req.IncludeProfile // ... новая логика } ```"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::30","title":"RPC_SAME_REQUEST_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Добавьте новый RPC с новым типом запроса:**","content":"Стратегия миграции **Добавьте новый RPC с новым типом запроса:**"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::31","title":"RPC_SAME_REQUEST_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Поддерживайте оба метода на сервере:** ```go func (s *server) GetUser(ctx context.Context, req *GetUserRequest) (*GetUserResponse, error) { return s.getUserInternal(req.UserId, false) }","content":"Стратегия миграции **Поддерживайте оба метода на сервере:** ```go func (s *server) GetUser(ctx context.Context, req *GetUserRequest) (*GetUserResponse, error) { return s.getUserInternal(req.UserId, false) }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::32","title":"RPC_SAME_REQUEST_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции func (s *server) GetUserV2(ctx context.Context, req *GetUserRequestV2) (*GetUserResponse, error) { return s.getUserInternal(req.Id, req.IncludeProfile) } ```","content":"Стратегия миграции func (s *server) GetUserV2(ctx context.Context, req *GetUserRequestV2) (*GetUserResponse, error) { return s.getUserInternal(req.Id, req.IncludeProfile) } ```"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::33","title":"RPC_SAME_REQUEST_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Мигрируйте клиентов на V2:**","content":"Стратегия миграции **Мигрируйте клиентов на V2:**"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::34","title":"RPC_SAME_REQUEST_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Удалите старый метод в следующей major‑версии:**","content":"Стратегия миграции **Удалите старый метод в следующей major‑версии:**"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::35","title":"RPC_SAME_REQUEST_TYPE","section":"Добавление обязательных полей","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Добавление обязательных полей"],"excerpt":"Добавление обязательных полей ```proto // ПЛОХО: меняем существующий запрос message GetUserRequest { string user_id = 1; bool include_deleted = 2; // BREAKING }","content":"Добавление обязательных полей ```proto // ПЛОХО: меняем существующий запрос message GetUserRequest { string user_id = 1; bool include_deleted = 2; // BREAKING }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::36","title":"RPC_SAME_REQUEST_TYPE","section":"Добавление обязательных полей","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Добавление обязательных полей"],"excerpt":"Добавление обязательных полей // Хорошо: новая версия message GetUserRequestV2 { string user_id = 1; bool include_deleted = 2; } ```","content":"Добавление обязательных полей // Хорошо: новая версия message GetUserRequestV2 { string user_id = 1; bool include_deleted = 2; } ```"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::37","title":"RPC_SAME_REQUEST_TYPE","section":"Реструктуризация данных запроса","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Реструктуризация данных запроса"],"excerpt":"Реструктуризация данных запроса ```proto // ПЛОХО: меняем структуру прямо message UpdateUserRequest { UserProfile profile = 1; // BREAKING }","content":"Реструктуризация данных запроса ```proto // ПЛОХО: меняем структуру прямо message UpdateUserRequest { UserProfile profile = 1; // BREAKING }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::38","title":"RPC_SAME_REQUEST_TYPE","section":"Реструктуризация данных запроса","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Реструктуризация данных запроса"],"excerpt":"Реструктуризация данных запроса // Хорошо: версионирование rpc UpdateUser(UpdateUserRequest) returns (...) { option deprecated = true; } rpc UpdateUserV2(UpdateUserRequestV2) returns (...); ```","content":"Реструктуризация данных запроса // Хорошо: версионирование rpc UpdateUser(UpdateUserRequest) returns (...) { option deprecated = true; } rpc UpdateUserV2(UpdateUserRequestV2) returns (...); ```"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::39","title":"RPC_SAME_REQUEST_TYPE","section":"Миграция пакета","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Миграция пакета"],"excerpt":"Миграция пакета ```proto // ПЛОХО: заменяем тип на пакет v2 прямо import \"v2/messages.proto\"; // BREAKING","content":"Миграция пакета ```proto // ПЛОХО: заменяем тип на пакет v2 прямо import \"v2/messages.proto\"; // BREAKING"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::40","title":"RPC_SAME_REQUEST_TYPE","section":"Миграция пакета","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Миграция пакета"],"excerpt":"Миграция пакета // Хорошо: добавляем новый RPC rpc OldMethod(v1.Request) returns (...) { option deprecated = true; } rpc NewMethod(v2.Request) returns (...); ```","content":"Миграция пакета // Хорошо: добавляем новый RPC 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":"Это правило проверяет, что RPC‑методы сохраняют тот же тип ответного сообщения (response message type). Изменение типа ответа RPC ломает совместимость по wire‑формату и сгенерированный код: клиенты ожидают конкретную стр","content":"Это правило проверяет, что RPC‑методы сохраняют тот же тип ответного сообщения (response message type). Изменение типа ответа RPC ломает совместимость по wire‑формату и сгенерированный код: клиенты ожидают конкретную структуру при получении ответа."},{"id":"cli/breaking-changes/rules/rpc-same-response-type::breaking::1","title":"RPC_SAME_RESPONSE_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::breaking::2","title":"RPC_SAME_RESPONSE_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::breaking::3","title":"RPC_SAME_RESPONSE_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse); }","content":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse); }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::breaking::4","title":"RPC_SAME_RESPONSE_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message GetUserResponse { string user_id = 1; string name = 2; string email = 3; }","content":"Плохой (Breaking) message GetUserResponse { string user_id = 1; string name = 2; string email = 3; }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::breaking::5","title":"RPC_SAME_RESPONSE_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message UpdateUserResponse { bool success = 1; string message = 2; } ```","content":"Плохой (Breaking) message UpdateUserResponse { bool success = 1; string message = 2; } ```"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::breaking::6","title":"RPC_SAME_RESPONSE_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::breaking::7","title":"RPC_SAME_RESPONSE_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::breaking::8","title":"RPC_SAME_RESPONSE_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponseV2); // [!code --] Изменён тип ответа rpc UpdateUser(UpdateUserRequest) returns (UserUpdateResponse); // [!code --] Изменён тип ","content":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponseV2); // [!code --] Изменён тип ответа rpc UpdateUser(UpdateUserRequest) returns (UserUpdateResponse); // [!code --] Изменён тип ответа }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::breaking::9","title":"RPC_SAME_RESPONSE_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message GetUserResponseV2 { // [!code --] Другой тип сообщения string id = 1; UserProfile profile = 2; repeated string permissions = 3; }","content":"Плохой (Breaking) message GetUserResponseV2 { // [!code --] Другой тип сообщения string id = 1; UserProfile profile = 2; repeated string permissions = 3; }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::breaking::10","title":"RPC_SAME_RESPONSE_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message UserUpdateResponse { // [!code --] Другой тип сообщения UpdateResult result = 1; UserProfile updated_profile = 2; } ```","content":"Плохой (Breaking) message UserUpdateResponse { // [!code --] Другой тип сообщения UpdateResult result = 1; UserProfile updated_profile = 2; } ```"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::11","title":"RPC_SAME_RESPONSE_TYPE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры **Смена типа из другого пакета:** ```proto // Before import \"common/responses.proto\";","content":"Дополнительные примеры **Смена типа из другого пакета:** ```proto // Before import \"common/responses.proto\";"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::12","title":"RPC_SAME_RESPONSE_TYPE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры service UserService { rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); }","content":"Дополнительные примеры service UserService { rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::13","title":"RPC_SAME_RESPONSE_TYPE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры // After - BREAKING CHANGE! import \"v2/responses.proto\";","content":"Дополнительные примеры // After - BREAKING CHANGE! import \"v2/responses.proto\";"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::14","title":"RPC_SAME_RESPONSE_TYPE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры service UserService { rpc CreateUser(CreateUserRequest) returns (v2.CreateUserResponse); // Другой package } ```","content":"Дополнительные примеры service UserService { rpc CreateUser(CreateUserRequest) returns (v2.CreateUserResponse); // Другой package } ```"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::15","title":"RPC_SAME_RESPONSE_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо изменения типа — версионируйте RPC:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо изменения типа — версионируйте RPC:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::16","title":"RPC_SAME_RESPONSE_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::17","title":"RPC_SAME_RESPONSE_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse) { option deprecated = true; // [!code focus] } rpc GetUserV2(GetUserRequest) returns (GetUserResponseV2); // [!code focus] ","content":"Хороший (Безопасный) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse) { option deprecated = true; // [!code focus] } rpc GetUserV2(GetUserRequest) returns (GetUserResponseV2); // [!code focus] // Новый метод rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse) { option deprecated = true; // [!code focus] } rpc UpdateUserV2(UpdateUserRequest) returns (UserUpdateResponse); // [!code focus] // Новый метод }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::18","title":"RPC_SAME_RESPONSE_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) // Старые сообщения сохраняем для обратной совместимости message GetUserResponse { string user_id = 1; string name = 2; string email = 3; }","content":"Хороший (Безопасный) // Старые сообщения сохраняем для обратной совместимости message GetUserResponse { string user_id = 1; string name = 2; string email = 3; }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::19","title":"RPC_SAME_RESPONSE_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) // Новая расширенная версия message GetUserResponseV2 { // [!code focus] string id = 1; // [!code focus] UserProfile profile = 2; // [!code focus] repeated string permissions = 3; // [!code focus] } ","content":"Хороший (Безопасный) // Новая расширенная версия 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::top::20","title":"RPC_SAME_RESPONSE_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Или создайте новую версию сервиса (package v2):** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Или создайте новую версию сервиса (package v2):** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::21","title":"RPC_SAME_RESPONSE_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v2; // [!code focus]","content":"Хороший (Безопасный) package myapi.v2; // [!code focus]"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::22","title":"RPC_SAME_RESPONSE_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); // [!code focus] rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse); // [!code focus] }","content":"Хороший (Безопасный) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); // [!code focus] rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse); // [!code focus] }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::23","title":"RPC_SAME_RESPONSE_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message GetUserResponse { // [!code focus] string id = 1; // [!code focus] UserProfile profile = 2; // [!code focus] repeated string permissions = 3; // [!code focus] } // [!code focus] ```","content":"Хороший (Безопасный) message GetUserResponse { // [!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::top::24","title":"RPC_SAME_RESPONSE_TYPE","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Влияние"],"excerpt":"Влияние **Wire Format:** Ответы сервера не десериализуются у старых клиентов **Generated Code:** Сигнатуры ожидают старый тип — компиляция падает **gRPC Calls:** Меняются типы в сгенерированных stub'ах **Runtime Errors:*","content":"Влияние **Wire Format:** Ответы сервера не десериализуются у старых клиентов **Generated Code:** Сигнатуры ожидают старый тип — компиляция падает **gRPC Calls:** Меняются типы в сгенерированных stub'ах **Runtime Errors:** Несоответствие типов ломает обработку ответа"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::25","title":"RPC_SAME_RESPONSE_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Реальный пример"],"excerpt":"Реальный пример **Код клиента ломается:** ```go // Before client := myapi.NewUserServiceClient(conn) resp, err := client.GetUser(ctx, &myapi.GetUserRequest{ UserId: \"user123\", }) if err != nil { return err }","content":"Реальный пример **Код клиента ломается:** ```go // Before 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::top::26","title":"RPC_SAME_RESPONSE_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Реальный пример"],"excerpt":"Реальный пример userID := resp.UserId name := resp.Name","content":"Реальный пример userID := resp.UserId name := resp.Name"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::27","title":"RPC_SAME_RESPONSE_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Реальный пример"],"excerpt":"Реальный пример // After (тип ответа изменён) client := myapi.NewUserServiceClient(conn) resp, err := client.GetUser(ctx, &myapi.GetUserRequest{ UserId: \"user123\", }) if err != nil { return err }","content":"Реальный пример // After (тип ответа изменён) 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::top::28","title":"RPC_SAME_RESPONSE_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Реальный пример"],"excerpt":"Реальный пример // Ошибки компиляции: userID := resp.UserId // ERROR name := resp.Name // ERROR","content":"Реальный пример // Ошибки компиляции: userID := resp.UserId // ERROR name := resp.Name // ERROR"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::29","title":"RPC_SAME_RESPONSE_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Реальный пример"],"excerpt":"Реальный пример // Новый способ: userID := resp.Id profile := resp.Profile permissions := resp.Permissions ```","content":"Реальный пример // Новый способ: userID := resp.Id profile := resp.Profile permissions := resp.Permissions ```"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::30","title":"RPC_SAME_RESPONSE_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Реальный пример"],"excerpt":"Реальный пример **Имплементация сервера также должна быть переписана:** ```go // Before func (s *server) GetUser(ctx context.Context, req *GetUserRequest) (*GetUserResponse, error) { return &GetUserResponse{ UserId: \"use","content":"Реальный пример **Имплементация сервера также должна быть переписана:** ```go // Before 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::top::31","title":"RPC_SAME_RESPONSE_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Реальный пример"],"excerpt":"Реальный пример // After func (s *server) GetUser(ctx context.Context, req *GetUserRequest) (*GetUserResponseV2, error) { return &GetUserResponseV2{ Id: \"user123\", Profile: &UserProfile{ Name: \"John Doe\", Email: \"john@ex","content":"Реальный пример // After func (s *server) GetUser(ctx context.Context, req *GetUserRequest) (*GetUserResponseV2, error) { return &GetUserResponseV2{ Id: \"user123\", Profile: &UserProfile{ Name: \"John Doe\", Email: \"john@example.com\", }, Permissions: []string{\"read\"}, }, nil } ```"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::32","title":"RPC_SAME_RESPONSE_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Добавьте новый RPC c новым типом ответа:**","content":"Стратегия миграции **Добавьте новый RPC c новым типом ответа:**"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::33","title":"RPC_SAME_RESPONSE_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Поддерживайте оба на сервере:** ```go func (s *server) GetUser(ctx context.Context, req *GetUserRequest) (*GetUserResponse, error) { user := s.getUserInternal(req.UserId) return &GetUserResponse{ Use","content":"Стратегия миграции **Поддерживайте оба на сервере:** ```go func (s *server) GetUser(ctx context.Context, req *GetUserRequest) (*GetUserResponse, error) { user := s.getUserInternal(req.UserId) return &GetUserResponse{ UserId: user.ID, Name: user.Name, Email: user.Email, }, nil }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::34","title":"RPC_SAME_RESPONSE_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции func (s *server) GetUserV2(ctx context.Context, req *GetUserRequest) (*GetUserResponseV2, error) { user := s.getUserInternal(req.UserId) return &GetUserResponseV2{ Id: user.ID, Profile: &UserProfile{ N","content":"Стратегия миграции func (s *server) GetUserV2(ctx context.Context, req *GetUserRequest) (*GetUserResponseV2, error) { user := s.getUserInternal(req.UserId) return &GetUserResponseV2{ Id: user.ID, Profile: &UserProfile{ Name: user.Name, Email: user.Email, }, Permissions: user.Permissions, }, nil } ```"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::35","title":"RPC_SAME_RESPONSE_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Мигрируйте клиентов на новый RPC:**","content":"Стратегия миграции **Мигрируйте клиентов на новый RPC:**"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::36","title":"RPC_SAME_RESPONSE_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Удалите старый RPC** в следующей major‑версии:","content":"Стратегия миграции **Удалите старый RPC** в следующей major‑версии:"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::37","title":"RPC_SAME_RESPONSE_TYPE","section":"Добавление новых обязательных полей","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Добавление новых обязательных полей"],"excerpt":"Добавление новых обязательных полей ```proto // ПЛОХО: меняем существующий тип message GetUserResponse { string user_id = 1; string name = 2; UserProfile profile = 3; // BREAKING }","content":"Добавление новых обязательных полей ```proto // ПЛОХО: меняем существующий тип message GetUserResponse { string user_id = 1; string name = 2; UserProfile profile = 3; // BREAKING }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::38","title":"RPC_SAME_RESPONSE_TYPE","section":"Добавление новых обязательных полей","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Добавление новых обязательных полей"],"excerpt":"Добавление новых обязательных полей // Хорошо: новая версия message GetUserResponseV2 { string user_id = 1; string name = 2; UserProfile profile = 3; } ```","content":"Добавление новых обязательных полей // Хорошо: новая версия message GetUserResponseV2 { string user_id = 1; string name = 2; UserProfile profile = 3; } ```"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::39","title":"RPC_SAME_RESPONSE_TYPE","section":"Реструктуризация ответа","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Реструктуризация ответа"],"excerpt":"Реструктуризация ответа ```proto // ПЛОХО: меняем структуру прямо message UpdateUserResponse { UserDetails details = 1; // BREAKING }","content":"Реструктуризация ответа ```proto // ПЛОХО: меняем структуру прямо message UpdateUserResponse { UserDetails details = 1; // BREAKING }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::40","title":"RPC_SAME_RESPONSE_TYPE","section":"Реструктуризация ответа","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Реструктуризация ответа"],"excerpt":"Реструктуризация ответа // Хорошо: версионирование rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse) { option deprecated = true; } rpc UpdateUserV2(UpdateUserRequest) returns (UpdateUserResponseV2); ```","content":"Реструктуризация ответа // Хорошо: версионирование rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse) { option deprecated = true; } rpc UpdateUserV2(UpdateUserRequest) returns (UpdateUserResponseV2); ```"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::41","title":"RPC_SAME_RESPONSE_TYPE","section":"Изменение формата ошибок","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Изменение формата ошибок"],"excerpt":"Изменение формата ошибок ```proto // ПЛОХО: меняем формат напрямую message CreateUserResponse { ErrorDetails error = 1; // BREAKING }","content":"Изменение формата ошибок ```proto // ПЛОХО: меняем формат напрямую message CreateUserResponse { ErrorDetails error = 1; // BREAKING }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::42","title":"RPC_SAME_RESPONSE_TYPE","section":"Изменение формата ошибок","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Изменение формата ошибок"],"excerpt":"Изменение формата ошибок // Хорошо: новая версия rpc CreateUser(CreateUserRequest) returns (CreateUserResponse) { option deprecated = true; } rpc CreateUserV2(CreateUserRequest) returns (CreateUserResponseV2); ```","content":"Изменение формата ошибок // Хорошо: новая версия rpc CreateUser(CreateUserRequest) returns (CreateUserResponse) { option deprecated = true; } rpc CreateUserV2(CreateUserRequest) returns (CreateUserResponseV2); ```"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::43","title":"RPC_SAME_RESPONSE_TYPE","section":"Миграция формата","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Миграция формата"],"excerpt":"Миграция формата ```proto // ПЛОХО: перевод простой структуры в сложную message GetUserResponse { UserData data = 1; // BREAKING }","content":"Миграция формата ```proto // ПЛОХО: перевод простой структуры в сложную message GetUserResponse { UserData data = 1; // BREAKING }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::44","title":"RPC_SAME_RESPONSE_TYPE","section":"Миграция формата","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Миграция формата"],"excerpt":"Миграция формата // Хорошо: предоставляем обе версии rpc GetUser(GetUserRequest) returns (GetUserResponse) { option deprecated = true; } rpc GetUserDetailed(GetUserRequest) returns (GetUserDetailedResponse); ```","content":"Миграция формата // Хорошо: предоставляем обе версии 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":"Данное правило проверяет, что ни один service не был удалён из proto‑файлов. Удаление service ломает сгенерированный код и клиентские приложения, которые на него опираются.","content":"Данное правило проверяет, что ни один service не был удалён из proto‑файлов. Удаление service ломает сгенерированный код и клиентские приложения, которые на него опираются."},{"id":"cli/breaking-changes/rules/service-no-delete::breaking::1","title":"SERVICE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/service-no-delete::breaking::2","title":"SERVICE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/service-no-delete::breaking::3","title":"SERVICE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); }","content":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); }"},{"id":"cli/breaking-changes/rules/service-no-delete::breaking::4","title":"SERVICE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) service OrderService { // [!code --] rpc GetOrder(GetOrderRequest) returns (GetOrderResponse); // [!code --] } // [!code --] ```","content":"Плохой (Breaking) service OrderService { // [!code --] rpc GetOrder(GetOrderRequest) returns (GetOrderResponse); // [!code --] } // [!code --] ```"},{"id":"cli/breaking-changes/rules/service-no-delete::breaking::5","title":"SERVICE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/service-no-delete::breaking::6","title":"SERVICE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/service-no-delete::breaking::7","title":"SERVICE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); }","content":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); }"},{"id":"cli/breaking-changes/rules/service-no-delete::breaking::8","title":"SERVICE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) // OrderService удалён — BREAKING CHANGE! ```","content":"Плохой (Breaking) // OrderService удалён — BREAKING CHANGE! ```"},{"id":"cli/breaking-changes/rules/service-no-delete::top::9","title":"SERVICE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо удаления — отметьте service как deprecated:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо удаления — отметьте service как deprecated:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/service-no-delete::top::10","title":"SERVICE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/service-no-delete::top::11","title":"SERVICE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); }","content":"Хороший (Безопасный) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); }"},{"id":"cli/breaking-changes/rules/service-no-delete::top::12","title":"SERVICE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) service OrderService { option deprecated = true; // [!code focus] rpc GetOrder(GetOrderRequest) returns (GetOrderResponse) { option deprecated = true; // [!code focus] } } ```","content":"Хороший (Безопасный) 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::top::13","title":"SERVICE_NO_DELETE","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete","headings":["Влияние"],"excerpt":"Влияние **Generated Code:** Классы / интерфейсы сервиса исчезают — клиенты не компилируются **Client Applications:** Существующие вызовы к удалённому сервису падают на этапе сборки **Runtime:** gRPC клиенты теряют опреде","content":"Влияние **Generated Code:** Классы / интерфейсы сервиса исчезают — клиенты не компилируются **Client Applications:** Существующие вызовы к удалённому сервису падают на этапе сборки **Runtime:** gRPC клиенты теряют определение метода/сервиса"},{"id":"cli/breaking-changes/rules/service-no-delete::top::14","title":"SERVICE_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Сначала деприкация:**","content":"Стратегия миграции **Сначала деприкация:**"},{"id":"cli/breaking-changes/rules/service-no-delete::top::15","title":"SERVICE_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Уведомите клиентов** о сроках вывода из эксплуатации","content":"Стратегия миграции **Уведомите клиентов** о сроках вывода из эксплуатации"},{"id":"cli/breaking-changes/rules/service-no-delete::top::16","title":"SERVICE_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Удалите после периода миграции** в следующей major‑версии","content":"Стратегия миграции **Удалите после периода миграции** в следующей major‑версии"},{"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 Формат вывода для команд с поддержкой нескольких форматов (text/json) значение по умолчанию зависит от команды"},{"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 Базовая директория для поиска файлов Текущая рабочая дир","content":"Command-Specific Flags Flag Short Environment Description Default ------ ------- ------------- ------------- --------- --path -p Directory path to lint . --root -r Базовая директория для поиска файлов Текущая рабочая директория --format -f EASYP_FORMAT Использует глобальный флаг формата (text/json) Использует глобальное значение по умолчанию"},{"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 из поддиректории с правильным разрешением импортов easyp lint --root src/IPC/Contracts --path .","content":"Command-Specific Flags Lint из поддиректории с правильным разрешением импортов 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 # глобальный флаг","content":"Command-Specific Flags JSON output format easyp --format json lint # глобальный флаг"},{"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 Путь к директории с proto файлами для генерации . --root -r Базова","content":"Command-Specific Flags Flag Short Environment Description Default ------ ------- ------------- ------------- --------- --path -p EASYP_ROOT_GENERATE_PATH Путь к директории с proto файлами для генерации . --root -r Базовая директория для поиска файлов Текущая рабочая директория"},{"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 из поддиректории с правильным разрешением импортов easyp generate --root src/IPC/Contracts --path .","content":"Command-Specific Flags Generate из поддиректории с правильным разрешением импортов 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 Использует глобальный флаг формата (text/json) Использует глобальное значение по умолчанию"},{"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 # глобальный флаг ```","content":"Command-Specific Flags JSON output easyp --format json breaking --against main # глобальный флаг ```"},{"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 работает интерактивно: Если в корне целевой директории есть buf.yml/buf.yaml, команда предложит миграцию из Buf. Если easyp.yaml уже существует, команда запросит подтверждение на перезап","content":"Command-Specific Flags easyp init работает интерактивно: Если в корне целевой директории есть buf.yml/buf.yaml, команда предложит миграцию из Buf. Если easyp.yaml уже существует, команда запросит подтверждение на перезапись."},{"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 Путь до файла конфигурации easyp.yaml --format (global) -f EASYP_FORMAT Глобаль","content":"Command-Specific Flags Flag Short Environment Description Default ------ ------- ------------- ------------- --------- --config -c EASYP_CFG Путь до файла конфигурации easyp.yaml --format (global) -f EASYP_FORMAT Глобальный формат вывода для команд с несколькими форматами (json или text) зависит от команды (json для 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 Проверить конфиг по умолчанию с JSON выводом (статус 0 если ошибок нет) easyp validate-config","content":"Command-Specific Flags **Examples:** ```bash Проверить конфиг по умолчанию с JSON выводом (статус 0 если ошибок нет) 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 Проверить другой файл и вывести в текстовом формате (глобальный --format) easyp --format text validate-config --config example.easyp.yaml ```","content":"Command-Specific Flags Проверить другой файл и вывести в текстовом формате (глобальный --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 Формат вывода для поддерживаемых команд (text/json). Если не указан, каждая команда использует своё значение по умолчанию. значение по умолчанию зависит от команды 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::top::45","title":"EasyP Configuration Reference","section":"Переменные окружения в конфигурации","path":"/docs/guide/cli/configuration/configuration","headings":["Переменные окружения в конфигурации"],"excerpt":"Переменные окружения в конфигурации EasyP поддерживает расширение переменных окружения непосредственно в файле конфигурации easyp.yaml. Это позволяет использовать переменные окружения для динамических значений конфигурац","content":"Переменные окружения в конфигурации EasyP поддерживает расширение переменных окружения непосредственно в файле конфигурации easyp.yaml. Это позволяет использовать переменные окружения для динамических значений конфигурации."},{"id":"cli/configuration/configuration::top::46","title":"EasyP Configuration Reference","section":"Переменные окружения в конфигурации","path":"/docs/guide/cli/configuration/configuration","headings":["Переменные окружения в конфигурации"],"excerpt":"Переменные окружения в конфигурации **Пример со всеми поддерживаемыми возможностями:** ```yaml deps: # Базовое расширение: ${VAR} - расширяется в значение переменной VAR - ${GOOGLEAPIS_REPO}@${GOOGLEAPIS_VERSION} # Значе","content":"Переменные окружения в конфигурации **Пример со всеми поддерживаемыми возможностями:** ```yaml deps: # Базовое расширение: ${VAR} - расширяется в значение переменной VAR - ${GOOGLEAPIS_REPO}@${GOOGLEAPIS_VERSION} # Значение по умолчанию: ${VAR:-default} - использует default, если VAR не установлена или пустая - ${GNOSTIC_REPO:-github.com/google/gnostic}@${GNOSTIC_VERSION:-v0.7.0}"},{"id":"cli/configuration/configuration::top::47","title":"EasyP Configuration Reference","section":"Переменные окружения в конфигурации","path":"/docs/guide/cli/configuration/configuration","headings":["Переменные окружения в конфигурации"],"excerpt":"Переменные окружения в конфигурации generate: inputs: # Значение по умолчанию, если INPUT_DIR не установлена - directory: ${INPUT_DIR:-proto} plugins: - name: go # Базовое расширение out: ${OUTPUT_DIR} opts: # Значение п","content":"Переменные окружения в конфигурации generate: inputs: # Значение по умолчанию, если INPUT_DIR не установлена - directory: ${INPUT_DIR:-proto} plugins: - name: go # Базовое расширение out: ${OUTPUT_DIR} opts: # Значение по умолчанию module: ${MODULE_NAME:-github.com/example/project} timeout: ${TIMEOUT:-30} # Экранирование: $$ становится буквальным $, $${VAR} становится буквальным ${VAR} path: \"${BASE_DIR}/$${TEMP}/file\" # Результат: \"/tmp/${TEMP}/file\" (если BASE_DIR=/tmp) literal: \"$$\" # Результат: \"$\" ```"},{"id":"cli/configuration/configuration::top::48","title":"EasyP Configuration Reference","section":"Переменные окружения в конфигурации","path":"/docs/guide/cli/configuration/configuration","headings":["Переменные окружения в конфигурации"],"excerpt":"Переменные окружения в конфигурации **Поддерживаемый синтаксис:** ${VAR} - расширяется в значение переменной VAR ${VAR:-default} - использует default, если VAR не установлена или пустая ${VAR:=default} - использует defau","content":"Переменные окружения в конфигурации **Поддерживаемый синтаксис:** ${VAR} - расширяется в значение переменной VAR ${VAR:-default} - использует default, если VAR не установлена или пустая ${VAR:=default} - использует default, если VAR не установлена или пустая ${VAR-default} - использует default, если VAR не установлена (пустая строка сохраняется) $${VAR} или $$VAR - экранирует в буквальную строку ${VAR} или $VAR $$ - экранирует в буквальный символ $"},{"id":"cli/configuration/configuration::top::49","title":"EasyP Configuration Reference","section":"Переменные окружения в конфигурации","path":"/docs/guide/cli/configuration/configuration","headings":["Переменные окружения в конфигурации"],"excerpt":"Переменные окружения в конфигурации **Примечание:** Переменные окружения расширяются до парсинга YAML, поэтому любой паттерн ${STRING} будет обработан. Используйте $$ для экранирования символов доллара, когда нужны буква","content":"Переменные окружения в конфигурации **Примечание:** Переменные окружения расширяются до парсинга YAML, поэтому любой паттерн ${STRING} будет обработан. Используйте $$ для экранирования символов доллара, когда нужны буквальные значения."},{"id":"cli/configuration/configuration::version::50","title":"EasyP Configuration Reference","section":"version","path":"/docs/guide/cli/configuration/configuration#version","headings":["version"],"excerpt":"version **Опционально (legacy-совместимость).** Поле поддерживается для обратной совместимости и может быть опущено в новых конфигурациях.","content":"version **Опционально (legacy-совместимость).** Поле поддерживается для обратной совместимости и может быть опущено в новых конфигурациях."},{"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:** не задано **Рекомендация:** если сохраняете поле, используйте v1alpha","content":"version **Type:** string **Default:** не задано **Рекомендация:** если сохраняете поле, используйте v1alpha"},{"id":"cli/configuration/configuration::version::52","title":"EasyP Configuration Reference","section":"version","path":"/docs/guide/cli/configuration/configuration#version","headings":["version"],"excerpt":"version На поведение рантайма это поле не влияет.","content":"version На поведение рантайма это поле не влияет."},{"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, required) - Output directory for generated files opts (mapstring, optional) - Plugin-specific options; each key can be a single value or an array of 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::top::0","title":"Go","section":"Установка плагинов","path":"/docs/guide/cli/generator/examples/go","headings":["Установка плагинов"],"excerpt":"Установка плагинов Сначала установите необходимые плагины для работы с gRPC:","content":"Установка плагинов Сначала установите необходимые плагины для работы с gRPC:"},{"id":"cli/generator/examples/go::top::1","title":"Go","section":"Установка плагинов","path":"/docs/guide/cli/generator/examples/go","headings":["Установка плагинов"],"excerpt":"Установка плагинов Эти команды установят плагины protoc-gen-go и protoc-gen-go-grpc для использования с EasyP.","content":"Установка плагинов Эти команды установят плагины protoc-gen-go и protoc-gen-go-grpc для использования с EasyP."},{"id":"cli/generator/examples/go::proto::2","title":"Go","section":"Пример proto‑сервиса","path":"/docs/guide/cli/generator/examples/go#proto","headings":["Пример proto‑сервиса"],"excerpt":"Пример proto‑сервиса Ниже пример proto-файла для сервиса Echo:","content":"Пример proto‑сервиса Ниже пример proto-файла для сервиса Echo:"},{"id":"cli/generator/examples/go::proto::3","title":"Go","section":"Пример proto‑сервиса","path":"/docs/guide/cli/generator/examples/go#proto","headings":["Пример proto‑сервиса"],"excerpt":"Пример proto‑сервиса ```proto syntax = \"proto3\";","content":"Пример proto‑сервиса ```proto syntax = \"proto3\";"},{"id":"cli/generator/examples/go::proto::4","title":"Go","section":"Пример proto‑сервиса","path":"/docs/guide/cli/generator/examples/go#proto","headings":["Пример proto‑сервиса"],"excerpt":"Пример proto‑сервиса package api.echo.v1;","content":"Пример proto‑сервиса package api.echo.v1;"},{"id":"cli/generator/examples/go::proto::5","title":"Go","section":"Пример proto‑сервиса","path":"/docs/guide/cli/generator/examples/go#proto","headings":["Пример proto‑сервиса"],"excerpt":"Пример proto‑сервиса option go_package = \"github.com/easyp-tech/example/api/echo/v1;pb\";","content":"Пример proto‑сервиса option go_package = \"github.com/easyp-tech/example/api/echo/v1;pb\";"},{"id":"cli/generator/examples/go::proto::6","title":"Go","section":"Пример proto‑сервиса","path":"/docs/guide/cli/generator/examples/go#proto","headings":["Пример proto‑сервиса"],"excerpt":"Пример proto‑сервиса service EchoAPI { rpc Echo(EchoRequest) returns (EchoResponse); rpc EchoStream(EchoStreamRequest) returns (EchoResponse); }","content":"Пример proto‑сервиса service EchoAPI { rpc Echo(EchoRequest) returns (EchoResponse); rpc EchoStream(EchoStreamRequest) returns (EchoResponse); }"},{"id":"cli/generator/examples/go::proto::7","title":"Go","section":"Пример proto‑сервиса","path":"/docs/guide/cli/generator/examples/go#proto","headings":["Пример proto‑сервиса"],"excerpt":"Пример proto‑сервиса message EchoRequest { string payload = 1; }","content":"Пример proto‑сервиса message EchoRequest { string payload = 1; }"},{"id":"cli/generator/examples/go::proto::8","title":"Go","section":"Пример proto‑сервиса","path":"/docs/guide/cli/generator/examples/go#proto","headings":["Пример proto‑сервиса"],"excerpt":"Пример proto‑сервиса message EchoResponse { string payload = 2; }","content":"Пример proto‑сервиса message EchoResponse { string payload = 2; }"},{"id":"cli/generator/examples/go::proto::9","title":"Go","section":"Пример proto‑сервиса","path":"/docs/guide/cli/generator/examples/go#proto","headings":["Пример proto‑сервиса"],"excerpt":"Пример proto‑сервиса message EchoStreamRequest { string payload = 1; }","content":"Пример proto‑сервиса message EchoStreamRequest { string payload = 1; }"},{"id":"cli/generator/examples/go::proto::10","title":"Go","section":"Пример proto‑сервиса","path":"/docs/guide/cli/generator/examples/go#proto","headings":["Пример proto‑сервиса"],"excerpt":"Пример proto‑сервиса message EchoStreamResponse { string payload = 2; } ```","content":"Пример proto‑сервиса message EchoStreamResponse { string payload = 2; } ```"},{"id":"cli/generator/examples/go::top::11","title":"Go","section":"Настройка конфигурации","path":"/docs/guide/cli/generator/examples/go","headings":["Настройка конфигурации"],"excerpt":"Настройка конфигурации Создайте и настройте файл конфигурации easyp.yaml:","content":"Настройка конфигурации Создайте и настройте файл конфигурации easyp.yaml:"},{"id":"cli/generator/examples/go::top::12","title":"Go","section":"Настройка конфигурации","path":"/docs/guide/cli/generator/examples/go","headings":["Настройка конфигурации"],"excerpt":"Настройка конфигурации Этот файл указывает использование двух плагинов: go для генерации Go-кода и go-grpc для генерации gRPC-кода, вместе с их опциями.","content":"Настройка конфигурации Этот файл указывает использование двух плагинов: go для генерации Go-кода и go-grpc для генерации gRPC-кода, вместе с их опциями."},{"id":"cli/generator/examples/go::top::13","title":"Go","section":"Генерация кода","path":"/docs/guide/cli/generator/examples/go","headings":["Генерация кода"],"excerpt":"Генерация кода Чтобы сгенерировать код, выполните команду:","content":"Генерация кода Чтобы сгенерировать код, выполните команду:"},{"id":"cli/generator/examples/go::top::14","title":"Go","section":"Генерация кода","path":"/docs/guide/cli/generator/examples/go","headings":["Генерация кода"],"excerpt":"Генерация кода Если флаг --cfg не указан, по умолчанию используется файл easyp.yaml в текущей директории:","content":"Генерация кода Если флаг --cfg не указан, по умолчанию используется файл easyp.yaml в текущей директории:"},{"id":"cli/generator/examples/go::top::15","title":"Go","section":"Генерация кода","path":"/docs/guide/cli/generator/examples/go","headings":["Генерация кода"],"excerpt":"Генерация кода Теперь у вас есть сгенерированный Go‑код, с которым можно напрямую работать.","content":"Генерация кода Теперь у вас есть сгенерированный Go‑код, с которым можно напрямую работать."},{"id":"cli/generator/examples/grpc-gateway::top::0","title":"gRPC-Gateway","section":"Установка плагинов","path":"/docs/guide/cli/generator/examples/grpc-gateway","headings":["Установка плагинов"],"excerpt":"Установка плагинов В дополнение к плагинам для работы с gRPC, необходимо установить следующие плагины для gRPC-Gateway:","content":"Установка плагинов В дополнение к плагинам для работы с gRPC, необходимо установить следующие плагины для gRPC-Gateway:"},{"id":"cli/generator/examples/grpc-gateway::top::1","title":"gRPC-Gateway","section":"Установка плагинов","path":"/docs/guide/cli/generator/examples/grpc-gateway","headings":["Установка плагинов"],"excerpt":"Установка плагинов go install google.golang.org/protobuf/cmd/protoc-gen-go@latest go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest go install github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2@","content":"Установка плагинов go install google.golang.org/protobuf/cmd/protoc-gen-go@latest go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest go install github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2@latest go install github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway@latest"},{"id":"cli/generator/examples/grpc-gateway::top::2","title":"gRPC-Gateway","section":"Установка плагинов","path":"/docs/guide/cli/generator/examples/grpc-gateway","headings":["Установка плагинов"],"excerpt":"Установка плагинов Эти команды установят плагины protoc-gen-go, protoc-gen-go-grpc, protoc-gen-openapiv2 и protoc-gen-grpc-gateway для использования с EasyP.","content":"Установка плагинов Эти команды установят плагины protoc-gen-go, protoc-gen-go-grpc, protoc-gen-openapiv2 и protoc-gen-grpc-gateway для использования с EasyP."},{"id":"cli/generator/examples/grpc-gateway::proto::3","title":"gRPC-Gateway","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/grpc-gateway#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса Ниже — исходный proto‑файл для сервиса Echo:","content":"Пример Proto сервиса Ниже — исходный proto‑файл для сервиса Echo:"},{"id":"cli/generator/examples/grpc-gateway::proto::4","title":"gRPC-Gateway","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/grpc-gateway#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса syntax = \"proto3\";","content":"Пример Proto сервиса syntax = \"proto3\";"},{"id":"cli/generator/examples/grpc-gateway::proto::5","title":"gRPC-Gateway","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/grpc-gateway#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса package api.echo.v1;","content":"Пример Proto сервиса package api.echo.v1;"},{"id":"cli/generator/examples/grpc-gateway::proto::6","title":"gRPC-Gateway","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/grpc-gateway#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса option go_package = \"github.com/easyp-tech/example/api/echo/v1;pb\";","content":"Пример Proto сервиса option go_package = \"github.com/easyp-tech/example/api/echo/v1;pb\";"},{"id":"cli/generator/examples/grpc-gateway::proto::7","title":"gRPC-Gateway","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/grpc-gateway#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса service EchoAPI { rpc Echo(EchoRequest) returns (EchoResponse); }","content":"Пример Proto сервиса service EchoAPI { rpc Echo(EchoRequest) returns (EchoResponse); }"},{"id":"cli/generator/examples/grpc-gateway::proto::8","title":"gRPC-Gateway","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/grpc-gateway#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса message EchoRequest { string payload = 1; }","content":"Пример Proto сервиса message EchoRequest { string payload = 1; }"},{"id":"cli/generator/examples/grpc-gateway::proto::9","title":"gRPC-Gateway","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/grpc-gateway#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса message EchoResponse { string payload = 2; }","content":"Пример Proto сервиса message EchoResponse { string payload = 2; }"},{"id":"cli/generator/examples/grpc-gateway::proto::10","title":"gRPC-Gateway","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/grpc-gateway#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса Чтобы использовать gRPC-Gateway, обновите proto‑файл, добавив HTTP‑опции:","content":"Пример Proto сервиса Чтобы использовать gRPC-Gateway, обновите proto‑файл, добавив HTTP‑опции:"},{"id":"cli/generator/examples/grpc-gateway::proto::11","title":"gRPC-Gateway","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/grpc-gateway#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса syntax = \"proto3\"; import \"google/api/annotations.proto\";","content":"Пример Proto сервиса syntax = \"proto3\"; import \"google/api/annotations.proto\";"},{"id":"cli/generator/examples/grpc-gateway::proto::12","title":"gRPC-Gateway","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/grpc-gateway#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса package api.echo.v1;","content":"Пример Proto сервиса package api.echo.v1;"},{"id":"cli/generator/examples/grpc-gateway::proto::13","title":"gRPC-Gateway","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/grpc-gateway#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса option go_package = \"github.com/easyp-tech/example/api/echo/v1;pb\";","content":"Пример Proto сервиса option go_package = \"github.com/easyp-tech/example/api/echo/v1;pb\";"},{"id":"cli/generator/examples/grpc-gateway::proto::14","title":"gRPC-Gateway","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/grpc-gateway#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса service EchoAPI { rpc Echo(EchoRequest) returns (EchoResponse) { option (google.api.http) = { // [!code ++] post: \"/api/v1/echo\" // [!code ++] body: \"*\" // [!code ++] }; // [!code ++] } }","content":"Пример Proto сервиса 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::proto::15","title":"gRPC-Gateway","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/grpc-gateway#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса message EchoRequest { string payload = 1; }","content":"Пример Proto сервиса message EchoRequest { string payload = 1; }"},{"id":"cli/generator/examples/grpc-gateway::proto::16","title":"gRPC-Gateway","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/grpc-gateway#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса message EchoResponse { string payload = 2; }","content":"Пример Proto сервиса message EchoResponse { string payload = 2; }"},{"id":"cli/generator/examples/grpc-gateway::top::17","title":"gRPC-Gateway","section":"Настройка конфигурации","path":"/docs/guide/cli/generator/examples/grpc-gateway","headings":["Настройка конфигурации"],"excerpt":"Настройка конфигурации Обновите файл easyp.yaml, добавив необходимые зависимости и плагины: deps: # [!code ++] - github.com/googleapis/googleapis # [!code ++]","content":"Настройка конфигурации Обновите файл easyp.yaml, добавив необходимые зависимости и плагины: deps: # [!code ++] - github.com/googleapis/googleapis # [!code ++]"},{"id":"cli/generator/examples/grpc-gateway::top::18","title":"gRPC-Gateway","section":"Настройка конфигурации","path":"/docs/guide/cli/generator/examples/grpc-gateway","headings":["Настройка конфигурации"],"excerpt":"Настройка конфигурации 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":"Настройка конфигурации 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::top::19","title":"gRPC-Gateway","section":"Настройка конфигурации","path":"/docs/guide/cli/generator/examples/grpc-gateway","headings":["Настройка конфигурации"],"excerpt":"Настройка конфигурации Секция deps перечисляет зависимости, необходимые для импортов proto‑файлов. В данном случае добавляем github.com/googleapis/googleapis, поскольку там находится файл annotations.proto, используемый ","content":"Настройка конфигурации Секция deps перечисляет зависимости, необходимые для импортов proto‑файлов. В данном случае добавляем github.com/googleapis/googleapis, поскольку там находится файл annotations.proto, используемый в определении сервиса."},{"id":"cli/generator/examples/grpc-gateway::top::20","title":"gRPC-Gateway","section":"Обновление зависимостей","path":"/docs/guide/cli/generator/examples/grpc-gateway","headings":["Обновление зависимостей"],"excerpt":"Обновление зависимостей После обновления конфигурации выполните команду для загрузки указанных зависимостей:","content":"Обновление зависимостей После обновления конфигурации выполните команду для загрузки указанных зависимостей:"},{"id":"cli/generator/examples/grpc-gateway::top::21","title":"gRPC-Gateway","section":"Обновление зависимостей","path":"/docs/guide/cli/generator/examples/grpc-gateway","headings":["Обновление зависимостей"],"excerpt":"Обновление зависимостей easyp mod update","content":"Обновление зависимостей easyp mod update"},{"id":"cli/generator/examples/grpc-gateway::top::22","title":"gRPC-Gateway","section":"Обновление зависимостей","path":"/docs/guide/cli/generator/examples/grpc-gateway","headings":["Обновление зависимостей"],"excerpt":"Обновление зависимостей Больше деталей по управлению зависимостями см. в разделе Package Manager.","content":"Обновление зависимостей Больше деталей по управлению зависимостями см. в разделе Package Manager."},{"id":"cli/generator/examples/grpc-gateway::top::23","title":"gRPC-Gateway","section":"Генерация кода","path":"/docs/guide/cli/generator/examples/grpc-gateway","headings":["Генерация кода"],"excerpt":"Генерация кода Для генерации кода используйте:","content":"Генерация кода Для генерации кода используйте:"},{"id":"cli/generator/examples/grpc-gateway::top::24","title":"gRPC-Gateway","section":"Генерация кода","path":"/docs/guide/cli/generator/examples/grpc-gateway","headings":["Генерация кода"],"excerpt":"Генерация кода easyp --cfg easyp.yaml generate","content":"Генерация кода easyp --cfg easyp.yaml generate"},{"id":"cli/generator/examples/grpc-gateway::top::25","title":"gRPC-Gateway","section":"Генерация кода","path":"/docs/guide/cli/generator/examples/grpc-gateway","headings":["Генерация кода"],"excerpt":"Генерация кода Если флаг --cfg не указан, по умолчанию используется файл easyp.yaml из текущей директории:","content":"Генерация кода Если флаг --cfg не указан, по умолчанию используется файл easyp.yaml из текущей директории:"},{"id":"cli/generator/examples/grpc-gateway::top::26","title":"gRPC-Gateway","section":"Генерация кода","path":"/docs/guide/cli/generator/examples/grpc-gateway","headings":["Генерация кода"],"excerpt":"Генерация кода Теперь у вас сгенерированы Go‑код и код gRPC-Gateway, с которыми можно работать напрямую.","content":"Генерация кода Теперь у вас сгенерированы Go‑код и код gRPC-Gateway, с которыми можно работать напрямую."},{"id":"cli/generator/examples/validate::top::0","title":"Validate","section":"Установка плагинов","path":"/docs/guide/cli/generator/examples/validate","headings":["Установка плагинов"],"excerpt":"Установка плагинов Сначала установите необходимые плагины для работы с gRPC и проверок (validate):","content":"Установка плагинов Сначала установите необходимые плагины для работы с gRPC и проверок (validate):"},{"id":"cli/generator/examples/validate::top::1","title":"Validate","section":"Установка плагинов","path":"/docs/guide/cli/generator/examples/validate","headings":["Установка плагинов"],"excerpt":"Установка плагинов Эти команды установят плагины protoc-gen-go, protoc-gen-go-grpc и protoc-gen-validate для использования вместе с EasyP.","content":"Установка плагинов Эти команды установят плагины protoc-gen-go, protoc-gen-go-grpc и protoc-gen-validate для использования вместе с EasyP."},{"id":"cli/generator/examples/validate::proto::2","title":"Validate","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/validate#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса Ниже пример proto‑файла для сервиса Echo:","content":"Пример Proto сервиса Ниже пример proto‑файла для сервиса Echo:"},{"id":"cli/generator/examples/validate::proto::3","title":"Validate","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/validate#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса ```proto syntax = \"proto3\";","content":"Пример Proto сервиса ```proto syntax = \"proto3\";"},{"id":"cli/generator/examples/validate::proto::4","title":"Validate","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/validate#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса package api.echo.v1;","content":"Пример Proto сервиса package api.echo.v1;"},{"id":"cli/generator/examples/validate::proto::5","title":"Validate","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/validate#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса import \"validate/validate.proto\";","content":"Пример Proto сервиса import \"validate/validate.proto\";"},{"id":"cli/generator/examples/validate::proto::6","title":"Validate","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/validate#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса option go_package = \"github.com/easyp-tech/example/api/echo/v1;pb\";","content":"Пример Proto сервиса option go_package = \"github.com/easyp-tech/example/api/echo/v1;pb\";"},{"id":"cli/generator/examples/validate::proto::7","title":"Validate","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/validate#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса service EchoAPI { rpc Echo(EchoRequest) returns (EchoResponse); rpc EchoStream(EchoStreamRequest) returns (EchoResponse); }","content":"Пример Proto сервиса service EchoAPI { rpc Echo(EchoRequest) returns (EchoResponse); rpc EchoStream(EchoStreamRequest) returns (EchoResponse); }"},{"id":"cli/generator/examples/validate::proto::8","title":"Validate","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/validate#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса message EchoRequest { string payload = 1 [(validate.rules).string = {max_len: 200}]; }","content":"Пример Proto сервиса message EchoRequest { string payload = 1 [(validate.rules).string = {max_len: 200}]; }"},{"id":"cli/generator/examples/validate::proto::9","title":"Validate","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/validate#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса message EchoResponse { string payload = 2; }","content":"Пример Proto сервиса message EchoResponse { string payload = 2; }"},{"id":"cli/generator/examples/validate::proto::10","title":"Validate","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/validate#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса message EchoStreamRequest { string payload = 1 [(validate.rules).string = {max_len: 200}]; }","content":"Пример Proto сервиса message EchoStreamRequest { string payload = 1 [(validate.rules).string = {max_len: 200}]; }"},{"id":"cli/generator/examples/validate::proto::11","title":"Validate","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/validate#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса message EchoStreamResponse { string payload = 2; } ```","content":"Пример Proto сервиса message EchoStreamResponse { string payload = 2; } ```"},{"id":"cli/generator/examples/validate::top::12","title":"Validate","section":"Настройка конфигурации","path":"/docs/guide/cli/generator/examples/validate","headings":["Настройка конфигурации"],"excerpt":"Настройка конфигурации Создайте и настройте файл конфигурации easyp.yaml:","content":"Настройка конфигурации Создайте и настройте файл конфигурации easyp.yaml:"},{"id":"cli/generator/examples/validate::top::13","title":"Validate","section":"Настройка конфигурации","path":"/docs/guide/cli/generator/examples/validate","headings":["Настройка конфигурации"],"excerpt":"Настройка конфигурации ```yaml deps: # [!code ++] - github.com/bufbuild/protoc-gen-validate # [!code ++]","content":"Настройка конфигурации ```yaml deps: # [!code ++] - github.com/bufbuild/protoc-gen-validate # [!code ++]"},{"id":"cli/generator/examples/validate::top::14","title":"Validate","section":"Настройка конфигурации","path":"/docs/guide/cli/generator/examples/validate","headings":["Настройка конфигурации"],"excerpt":"Настройка конфигурации 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: sourc","content":"Настройка конфигурации 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::top::15","title":"Validate","section":"Генерация кода","path":"/docs/guide/cli/generator/examples/validate","headings":["Генерация кода"],"excerpt":"Генерация кода Чтобы сгенерировать код, выполните команду:","content":"Генерация кода Чтобы сгенерировать код, выполните команду:"},{"id":"cli/generator/examples/validate::top::16","title":"Validate","section":"Генерация кода","path":"/docs/guide/cli/generator/examples/validate","headings":["Генерация кода"],"excerpt":"Генерация кода Если флаг --cfg не указан, по умолчанию используется файл easyp.yaml из текущего каталога:","content":"Генерация кода Если флаг --cfg не указан, по умолчанию используется файл easyp.yaml из текущего каталога:"},{"id":"cli/generator/examples/validate::top::17","title":"Validate","section":"Генерация кода","path":"/docs/guide/cli/generator/examples/validate","headings":["Генерация кода"],"excerpt":"Генерация кода Теперь у вас есть сгенерированный Go‑код с поддержкой валидации, и вы можете напрямую использовать его в проекте.","content":"Генерация кода Теперь у вас есть сгенерированный Go‑код с поддержкой валидации, и вы можете напрямую использовать его в проекте."},{"id":"cli/generator/generator::top::0","title":"Генератор","path":"/docs/guide/cli/generator/generator","headings":[],"excerpt":"EasyP включает мощный генератор, который упрощает процесс получения кода из proto‑файлов. Благодаря YAML‑конфигурациям работа становится гораздо более удобной и интуитивной по сравнению с прямым использованием команды pr","content":"EasyP включает мощный генератор, который упрощает процесс получения кода из proto‑файлов. Благодаря YAML‑конфигурациям работа становится гораздо более удобной и интуитивной по сравнению с прямым использованием команды protoc."},{"id":"cli/generator/generator::top::1","title":"Генератор","section":"Ключевые особенности генератора","path":"/docs/guide/cli/generator/generator","headings":["Ключевые особенности генератора"],"excerpt":"Ключевые особенности генератора **Упрощённая генерация кода**: - Генерация кода из proto через декларативную YAML‑конфигурацию. - Избавляет от необходимости писать длинные и сложные команды protoc.","content":"Ключевые особенности генератора **Упрощённая генерация кода**: - Генерация кода из proto через декларативную YAML‑конфигурацию. - Избавляет от необходимости писать длинные и сложные команды protoc."},{"id":"cli/generator/generator::top::2","title":"Генератор","section":"Ключевые особенности генератора","path":"/docs/guide/cli/generator/generator","headings":["Ключевые особенности генератора"],"excerpt":"Ключевые особенности генератора **Обёртка над protoc**: - EasyP выступает как удобный слой над protoc, предоставляя декларативный API. - Поддерживает все опции и плагины, доступные protoc.","content":"Ключевые особенности генератора **Обёртка над protoc**: - EasyP выступает как удобный слой над protoc, предоставляя декларативный API. - Поддерживает все опции и плагины, доступные protoc."},{"id":"cli/generator/generator::top::3","title":"Генератор","section":"Ключевые особенности генератора","path":"/docs/guide/cli/generator/generator","headings":["Ключевые особенности генератора"],"excerpt":"Ключевые особенности генератора **Гибкость и кастомизация**: - Используются те же параметры, что и у плагинов protoc, прямо в конфиге. - Поддерживается множество плагинов и их параметры в одной конфигурации.","content":"Ключевые особенности генератора **Гибкость и кастомизация**: - Используются те же параметры, что и у плагинов protoc, прямо в конфиге. - Поддерживается множество плагинов и их параметры в одной конфигурации."},{"id":"cli/generator/generator::top::4","title":"Генератор","section":"Ключевые особенности генератора","path":"/docs/guide/cli/generator/generator","headings":["Ключевые особенности генератора"],"excerpt":"Ключевые особенности генератора **Генерация из нескольких источников**: - Локальные директории и удалённые Git‑репозитории одновременно. - Лёгкая интеграция с существующими проектами и репозиториями.","content":"Ключевые особенности генератора **Генерация из нескольких источников**: - Локальные директории и удалённые Git‑репозитории одновременно. - Лёгкая интеграция с существующими проектами и репозиториями."},{"id":"cli/generator/generator::top::5","title":"Генератор","section":"Ключевые особенности генератора","path":"/docs/guide/cli/generator/generator","headings":["Ключевые особенности генератора"],"excerpt":"Ключевые особенности генератора **Удалённая генерация**: - Генерация из удалённых Git репозиториев без локального checkout.","content":"Ключевые особенности генератора **Удалённая генерация**: - Генерация из удалённых Git репозиториев без локального checkout."},{"id":"cli/generator/generator::top::6","title":"Генератор","section":"Ключевые особенности генератора","path":"/docs/guide/cli/generator/generator","headings":["Ключевые особенности генератора"],"excerpt":"Ключевые особенности генератора **Интеграция с менеджером пакетов**: - Прозрачная работа с зависимостями через пакетный менеджер EasyP. - Автоматическое разрешение и подключение proto‑зависимостей.","content":"Ключевые особенности генератора **Интеграция с менеджером пакетов**: - Прозрачная работа с зависимостями через пакетный менеджер EasyP. - Автоматическое разрешение и подключение proto‑зависимостей."},{"id":"cli/generator/generator::complete-configuration-example::7","title":"Генератор","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":"Генератор","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":"Генератор","section":"Complete Configuration Example","path":"/docs/guide/cli/generator/generator#complete-configuration-example","headings":["Complete Configuration Example"],"excerpt":"Complete Configuration Example Managed mode - автоматическая установка file и field опций managed: enabled: true disable: - module: github.com/googleapis/googleapis # Отключить для конкретного модуля override: - file_opt","content":"Complete Configuration Example Managed mode - автоматическая установка file и field опций managed: enabled: true disable: - module: github.com/googleapis/googleapis # Отключить для конкретного модуля 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/ # Применить к конкретному пути"},{"id":"cli/generator/generator::complete-configuration-example::10","title":"Генератор","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":"Генератор","section":"Локальный ввод (Local Directory Input)","path":"/docs/guide/cli/generator/generator#local-directory-input","headings":["Локальный ввод (Local Directory Input)"],"excerpt":"Локальный ввод (Local Directory Input) Локальная директория — самый распространённый и простой способ указать откуда брать proto для генерации. Используйте этот вариант, если файлы уже находятся в репозитории проекта.","content":"Локальный ввод (Local Directory Input) Локальная директория — самый распространённый и простой способ указать откуда брать proto для генерации. Используйте этот вариант, если файлы уже находятся в репозитории проекта."},{"id":"cli/generator/generator::local-directory-input::12","title":"Генератор","section":"Локальный ввод (Local Directory Input)","path":"/docs/guide/cli/generator/generator#local-directory-input","headings":["Локальный ввод (Local Directory Input)"],"excerpt":"Локальный ввод (Local Directory Input) **Когда применять:** Proto файлы находятся в кодовой базе проекта Нужен полный контроль над структурой каталогов Проект — один сервис или приложение Файлы меняются не слишком часто","content":"Локальный ввод (Local Directory Input) **Когда применять:** Proto файлы находятся в кодовой базе проекта Нужен полный контроль над структурой каталогов Проект — один сервис или приложение Файлы меняются не слишком часто"},{"id":"cli/generator/generator::local-directory-input::13","title":"Генератор","section":"Локальный ввод (Local Directory Input)","path":"/docs/guide/cli/generator/generator#local-directory-input","headings":["Локальный ввод (Local Directory Input)"],"excerpt":"Локальный ввод (Local Directory Input)","content":"Локальный ввод (Local Directory Input)"},{"id":"cli/generator/generator::local-directory-input::14","title":"Генератор","section":"Локальный ввод (Local Directory Input)","path":"/docs/guide/cli/generator/generator#local-directory-input","headings":["Локальный ввод (Local Directory Input)"],"excerpt":"Локальный ввод (Local Directory Input) Параметр root особенно полезен в монорепозиториях: он позволяет управлять тем, откуда будут резолвиться пути импортов. Если указать родительскую директорию, импорты будут оцениватьс","content":"Локальный ввод (Local Directory Input) Параметр root особенно полезен в монорепозиториях: он позволяет управлять тем, откуда будут резолвиться пути импортов. Если указать родительскую директорию, импорты будут оцениваться относительно неё, а не текущего рабочего каталога."},{"id":"cli/generator/generator::local-directory-input::15","title":"Генератор","section":"Локальный ввод (Local Directory Input)","path":"/docs/guide/cli/generator/generator#local-directory-input","headings":["Локальный ввод (Local Directory Input)"],"excerpt":"Локальный ввод (Local Directory Input) **Параметры:**","content":"Локальный ввод (Local Directory Input) **Параметры:**"},{"id":"cli/generator/generator::local-directory-input::16","title":"Генератор","section":"Локальный ввод (Local Directory Input)","path":"/docs/guide/cli/generator/generator#local-directory-input","headings":["Локальный ввод (Local Directory Input)"],"excerpt":"Локальный ввод (Local Directory Input) Параметр Тип Обязателен Значение по умолчанию Описание ---------- ----- ------------ ----------------------- ---------- path string ✅ - Каталог, содержащий proto файлы root string ❌","content":"Локальный ввод (Local Directory Input) Параметр Тип Обязателен Значение по умолчанию Описание ---------- ----- ------------ ----------------------- ---------- path string ✅ - Каталог, содержащий proto файлы root string ❌ \".\" Корневая директория для разрешения import путей"},{"id":"cli/generator/generator::local-directory-input::17","title":"Генератор","section":"Локальный ввод (Local Directory Input)","path":"/docs/guide/cli/generator/generator#local-directory-input","headings":["Локальный ввод (Local Directory Input)"],"excerpt":"Локальный ввод (Local Directory Input) **Примеры:**","content":"Локальный ввод (Local Directory Input) **Примеры:**"},{"id":"cli/generator/generator::local-directory-input::18","title":"Генератор","section":"Локальный ввод (Local Directory Input)","path":"/docs/guide/cli/generator/generator#local-directory-input","headings":["Локальный ввод (Local Directory Input)"],"excerpt":"Локальный ввод (Local Directory Input) Ниже показана разница между базовым указанием директории и расширенной конфигурацией с пользовательским корнем импортов:","content":"Локальный ввод (Local Directory Input) Ниже показана разница между базовым указанием директории и расширенной конфигурацией с пользовательским корнем импортов:"},{"id":"cli/generator/generator::local-directory-input::19","title":"Генератор","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::20","title":"Генератор","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::git-remote-git-repository-input::21","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) Этот тип входных данных позволяет генерировать код из proto‑файлов, находящихся в удалённых репозиториях, без локального checkout. Особенно полезно при использовани","content":"Удалённый Git репозиторий (Remote Git Repository Input) Этот тип входных данных позволяет генерировать код из proto‑файлов, находящихся в удалённых репозиториях, без локального checkout. Особенно полезно при использовании API других команд или внешних поставщиков."},{"id":"cli/generator/generator::git-remote-git-repository-input::22","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) **Когда использовать:** Потребление proto определений из других сервисов/команд Интеграция с внешними вендорскими API Работа с общими библиотеками proto в нескольки","content":"Удалённый Git репозиторий (Remote Git Repository Input) **Когда использовать:** Потребление proto определений из других сервисов/команд Интеграция с внешними вендорскими API Работа с общими библиотеками proto в нескольких проектах Необходимо гарантировать корректную (зафиксированную) версию внешних API"},{"id":"cli/generator/generator::git-remote-git-repository-input::23","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) **Рекомендации:** В продакшене всегда фиксируйте версии (@v1.0.0, а не latest) Используйте семантические версии при наличии — проще сопровождать Предпочитайте публи","content":"Удалённый Git репозиторий (Remote Git Repository Input) **Рекомендации:** В продакшене всегда фиксируйте версии (@v1.0.0, а не latest) Используйте семантические версии при наличии — проще сопровождать Предпочитайте публичные теги вместо хеша коммита (лучше отслеживаемость)"},{"id":"cli/generator/generator::git-remote-git-repository-input::24","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input)","content":"Удалённый Git репозиторий (Remote Git Repository Input)"},{"id":"cli/generator/generator::git-remote-git-repository-input::25","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) Параметр root задаёт корень для разрешения импортов файлов из этого репозитория.","content":"Удалённый Git репозиторий (Remote Git Repository Input) Параметр root задаёт корень для разрешения импортов файлов из этого репозитория."},{"id":"cli/generator/generator::git-remote-git-repository-input::26","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) **Параметры:**","content":"Удалённый Git репозиторий (Remote Git Repository Input) **Параметры:**"},{"id":"cli/generator/generator::git-remote-git-repository-input::27","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) Параметр Тип Обязателен По умолчанию Описание ---------- ----- ------------ -------------- ---------- url string ✅ - URL Git репозитория с необязательной версией / ","content":"Удалённый Git репозиторий (Remote Git Repository Input) Параметр Тип Обязателен По умолчанию Описание ---------- ----- ------------ -------------- ---------- url string ✅ - URL Git репозитория с необязательной версией / тегом / коммитом sub_directory string ❌ \"\" Поддиректория внутри репозитория, где лежат proto root string ❌ \"\" Корневой путь для разрешения импортов"},{"id":"cli/generator/generator::git-remote-git-repository-input::28","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) **Варианты формата URL:**","content":"Удалённый Git репозиторий (Remote Git Repository Input) **Варианты формата URL:**"},{"id":"cli/generator/generator::git-remote-git-repository-input::29","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) EasyP поддерживает несколько форматов для ссылки на удалённые репозитории. Каждый подходит под разные требования по стабильности:","content":"Удалённый Git репозиторий (Remote Git Repository Input) EasyP поддерживает несколько форматов для ссылки на удалённые репозитории. Каждый подходит под разные требования по стабильности:"},{"id":"cli/generator/generator::git-remote-git-repository-input::30","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) **Tagged versions** — для продакшена, стабильные неизменяемые ссылки **Semantic versions** — читаемость и управление зависимостями **Commit hashes** — доступ к конк","content":"Удалённый Git репозиторий (Remote Git Repository Input) **Tagged versions** — для продакшена, стабильные неизменяемые ссылки **Semantic versions** — читаемость и управление зависимостями **Commit hashes** — доступ к конкретному коммиту, если нет тега **Latest** — только для разработки, непредсказуемо **Full HTTPS URLs** — приватные репозитории или нестандартный хостинг"},{"id":"cli/generator/generator::git-remote-git-repository-input::31","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) ```yaml Тег — стабильно для продакшена url: \"github.com/googleapis/googleapis@common-protos-1_3_1\"","content":"Удалённый Git репозиторий (Remote Git Repository Input) ```yaml Тег — стабильно для продакшена url: \"github.com/googleapis/googleapis@common-protos-1_3_1\""},{"id":"cli/generator/generator::git-remote-git-repository-input::32","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) Семантическая версия url: \"github.com/grpc-ecosystem/grpc-gateway@v2.19.1\"","content":"Удалённый Git репозиторий (Remote Git Repository Input) Семантическая версия url: \"github.com/grpc-ecosystem/grpc-gateway@v2.19.1\""},{"id":"cli/generator/generator::git-remote-git-repository-input::33","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) Хеш коммита — точечный фикс url: \"github.com/company/protos@abc123def456\"","content":"Удалённый Git репозиторий (Remote Git Repository Input) Хеш коммита — точечный фикс url: \"github.com/company/protos@abc123def456\""},{"id":"cli/generator/generator::git-remote-git-repository-input::34","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) Latest — только dev, НЕ для продакшена url: \"github.com/company/protos\"","content":"Удалённый Git репозиторий (Remote Git Repository Input) Latest — только dev, НЕ для продакшена url: \"github.com/company/protos\""},{"id":"cli/generator/generator::git-remote-git-repository-input::35","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) Полный HTTPS URL — приватный или кастомный Git url: \"https://github.com/company/private-protos.git\" ```","content":"Удалённый Git репозиторий (Remote Git Repository Input) Полный HTTPS URL — приватный или кастомный Git url: \"https://github.com/company/private-protos.git\" ```"},{"id":"cli/generator/generator::git-remote-git-repository-input::36","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) **Примеры:**","content":"Удалённый Git репозиторий (Remote Git Repository Input) **Примеры:**"},{"id":"cli/generator/generator::git-remote-git-repository-input::37","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) Ниже паттерны использования удалённых источников в разных сценариях:","content":"Удалённый Git репозиторий (Remote Git Repository Input) Ниже паттерны использования удалённых источников в разных сценариях:"},{"id":"cli/generator/generator::git-remote-git-repository-input::38","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input)","content":"Удалённый Git репозиторий (Remote Git Repository Input)"},{"id":"cli/generator/generator::top::39","title":"Генератор","section":"Конфигурация плагинов","path":"/docs/guide/cli/generator/generator","headings":["Конфигурация плагинов"],"excerpt":"Конфигурация плагинов Конфигурация плагинов определяет какие генераторы кода будут запущены и как они себя ведут. EasyP поддерживает любой плагин protoc, что делает его крайне гибким для разных языковых экосистем и сцена","content":"Конфигурация плагинов Конфигурация плагинов определяет какие генераторы кода будут запущены и как они себя ведут. EasyP поддерживает любой плагин protoc, что делает его крайне гибким для разных языковых экосистем и сценариев."},{"id":"cli/generator/generator::top::40","title":"Генератор","section":"Конфигурация плагинов","path":"/docs/guide/cli/generator/generator","headings":["Конфигурация плагинов"],"excerpt":"Конфигурация плагинов На верхнем уровне есть **четыре способа указать, как именно запускать плагин**:","content":"Конфигурация плагинов На верхнем уровне есть **четыре способа указать, как именно запускать плагин**:"},{"id":"cli/generator/generator::top::41","title":"Генератор","section":"Конфигурация плагинов","path":"/docs/guide/cli/generator/generator","headings":["Конфигурация плагинов"],"excerpt":"Конфигурация плагинов **name** – запуск плагина по имени из PATH или использование встроенного плагина. **path** – запуск плагина по абсолютному/относительному пути к исполняемому файлу. **remote** – удалённый плагин по ","content":"Конфигурация плагинов **name** – запуск плагина по имени из PATH или использование встроенного плагина. **path** – запуск плагина по абсолютному/относительному пути к исполняемому файлу. **remote** – удалённый плагин по URL (через remote‑executor EasyP). **command** – запуск плагина через произвольную команду (например, go run ...)."},{"id":"cli/generator/generator::top::42","title":"Генератор","section":"Конфигурация плагинов","path":"/docs/guide/cli/generator/generator","headings":["Конфигурация плагинов"],"excerpt":"Конфигурация плагинов Для каждого плагина должен быть указан **ровно один** из параметров name, path, remote или command.","content":"Конфигурация плагинов Для каждого плагина должен быть указан **ровно один** из параметров name, path, remote или command."},{"id":"cli/generator/generator::name::43","title":"Генератор","section":"Плагин по имени (name)","path":"/docs/guide/cli/generator/generator#name","headings":["Плагин по имени (name)"],"excerpt":"Плагин по имени (name) Локальный режим по имени — стандартный: плагины установлены в системе и запускаются напрямую через EasyP.","content":"Плагин по имени (name) Локальный режим по имени — стандартный: плагины установлены в системе и запускаются напрямую через EasyP."},{"id":"cli/generator/generator::name::44","title":"Генератор","section":"Плагин по имени (name)","path":"/docs/guide/cli/generator/generator#name","headings":["Плагин по имени (name)"],"excerpt":"Плагин по имени (name) **Когда использовать name:** Стандартные языки (Go, Python, TypeScript и т.д.) Есть контроль над окружением сборки Критична производительность (нет сетевых задержек) Хочется опираться на PATH или в","content":"Плагин по имени (name) **Когда использовать name:** Стандартные языки (Go, Python, TypeScript и т.д.) Есть контроль над окружением сборки Критична производительность (нет сетевых задержек) Хочется опираться на PATH или встроенные плагины"},{"id":"cli/generator/generator::name::45","title":"Генератор","section":"Плагин по имени (name)","path":"/docs/guide/cli/generator/generator#name","headings":["Плагин по имени (name)"],"excerpt":"Плагин по имени (name) **Требования к установке:** Плагины установлены и доступны в PATH (если не используются встроенные). Имена следуют шаблону protoc-gen-{name}. Установка через менеджеры пакетов (go install, npm inst","content":"Плагин по имени (name) **Требования к установке:** Плагины установлены и доступны в PATH (если не используются встроенные). Имена следуют шаблону protoc-gen-{name}. Установка через менеджеры пакетов (go install, npm install, pip install и т.п.)."},{"id":"cli/generator/generator::name::46","title":"Генератор","section":"Плагин по имени (name)","path":"/docs/guide/cli/generator/generator#name","headings":["Плагин по имени (name)"],"excerpt":"Плагин по имени (name) Параметр with_imports критичен при использовании зависимостей из пакетного менеджера: установите true, чтобы прототипы из секции deps попали в генерацию.","content":"Плагин по имени (name) Параметр with_imports критичен при использовании зависимостей из пакетного менеджера: установите true, чтобы прототипы из секции deps попали в генерацию."},{"id":"cli/generator/generator::path::47","title":"Генератор","section":"Плагин по пути (path)","path":"/docs/guide/cli/generator/generator#path","headings":["Плагин по пути (path)"],"excerpt":"Плагин по пути (path) Иногда нужно запускать плагин из конкретного бинарника, не добавляя его в PATH (например, бинарь в репозитории или в build‑директории). В этом случае можно указать явный путь:","content":"Плагин по пути (path) Иногда нужно запускать плагин из конкретного бинарника, не добавляя его в PATH (например, бинарь в репозитории или в build‑директории). В этом случае можно указать явный путь:"},{"id":"cli/generator/generator::path::48","title":"Генератор","section":"Плагин по пути (path)","path":"/docs/guide/cli/generator/generator#path","headings":["Плагин по пути (path)"],"excerpt":"Плагин по пути (path) **Когда использовать path:** Бинарники плагинов хранятся в репозитории (для воспроизводимых сборок). Используются несколько версий одного и того же плагина параллельно. Не хочется «загрязнять» глоба","content":"Плагин по пути (path) **Когда использовать path:** Бинарники плагинов хранятся в репозитории (для воспроизводимых сборок). Используются несколько версий одного и того же плагина параллельно. Не хочется «загрязнять» глобальный PATH."},{"id":"cli/generator/generator::remote::49","title":"Генератор","section":"Удалённый плагин (remote)","path":"/docs/guide/cli/generator/generator#remote","headings":["Удалённый плагин (remote)"],"excerpt":"Удалённый плагин (remote) Удалённые плагины выполняются по URL. EasyP отправляет на удалённую сторону CodeGeneratorRequest и получает обратно CodeGeneratorResponse.","content":"Удалённый плагин (remote) Удалённые плагины выполняются по URL. EasyP отправляет на удалённую сторону CodeGeneratorRequest и получает обратно CodeGeneratorResponse."},{"id":"cli/generator/generator::remote::50","title":"Генератор","section":"Удалённый плагин (remote)","path":"/docs/guide/cli/generator/generator#remote","headings":["Удалённый плагин (remote)"],"excerpt":"Удалённый плагин (remote) Ниже приведён реальный пример использования EasyP API Service как удалённого исполнителя плагинов (тот же формат используется в разделе про API Service):","content":"Удалённый плагин (remote) Ниже приведён реальный пример использования EasyP API Service как удалённого исполнителя плагинов (тот же формат используется в разделе про API Service):"},{"id":"cli/generator/generator::remote::51","title":"Генератор","section":"Удалённый плагин (remote)","path":"/docs/guide/cli/generator/generator#remote","headings":["Удалённый плагин (remote)"],"excerpt":"Удалённый плагин (remote) ```yaml generate: plugins: # Удалённое выполнение плагинов через EasyP API Service - remote: api.easyp.tech/protobuf/go:v1.36.10 out: . opts: paths: source_relative","content":"Удалённый плагин (remote) ```yaml generate: plugins: # Удалённое выполнение плагинов через EasyP API Service - remote: api.easyp.tech/protobuf/go:v1.36.10 out: . opts: paths: source_relative"},{"id":"cli/generator/generator::remote::52","title":"Генератор","section":"Удалённый плагин (remote)","path":"/docs/guide/cli/generator/generator#remote","headings":["Удалённый плагин (remote)"],"excerpt":"Удалённый плагин (remote) remote: api.easyp.tech/grpc/go:v1.5.1 out: . opts: paths: source_relative ```","content":"Удалённый плагин (remote) remote: api.easyp.tech/grpc/go:v1.5.1 out: . opts: paths: source_relative ```"},{"id":"cli/generator/generator::remote::53","title":"Генератор","section":"Удалённый плагин (remote)","path":"/docs/guide/cli/generator/generator#remote","headings":["Удалённый плагин (remote)"],"excerpt":"Удалённый плагин (remote) **Типичные сценарии для remote:** Централизованный сервис плагинов внутри компании (например, EasyP API Service). Запуск тяжёлых плагинов на выделенных машинах вместо CI‑агентов. Совместное испо","content":"Удалённый плагин (remote) **Типичные сценарии для remote:** Централизованный сервис плагинов внутри компании (например, EasyP API Service). Запуск тяжёлых плагинов на выделенных машинах вместо CI‑агентов. Совместное использование одной реализации плагина разными командами."},{"id":"cli/generator/generator::command::54","title":"Генератор","section":"Выполнение плагина через команду (command)","path":"/docs/guide/cli/generator/generator#command","headings":["Выполнение плагина через команду (command)"],"excerpt":"Выполнение плагина через команду (command) Вы можете указать плагин как массив команд для выполнения. Это полезно для запуска плагинов через go run или любые другие инструменты без предварительной установки бинарника пла","content":"Выполнение плагина через команду (command) Вы можете указать плагин как массив команд для выполнения. Это полезно для запуска плагинов через go run или любые другие инструменты без предварительной установки бинарника плагина:"},{"id":"cli/generator/generator::command::55","title":"Генератор","section":"Выполнение плагина через команду (command)","path":"/docs/guide/cli/generator/generator#command","headings":["Выполнение плагина через команду (command)"],"excerpt":"Выполнение плагина через команду (command)","content":"Выполнение плагина через команду (command)"},{"id":"cli/generator/generator::command::56","title":"Генератор","section":"Выполнение плагина через команду (command)","path":"/docs/guide/cli/generator/generator#command","headings":["Выполнение плагина через команду (command)"],"excerpt":"Выполнение плагина через команду (command) В этом режиме EasyP: **запускает указанную команду** как дочерний процесс; **пишет CodeGeneratorRequest в stdin** процесса; **читает CodeGeneratorResponse из stdout**, как и для","content":"Выполнение плагина через команду (command) В этом режиме EasyP: **запускает указанную команду** как дочерний процесс; **пишет CodeGeneratorRequest в stdin** процесса; **читает CodeGeneratorResponse из stdout**, как и для обычных плагинов protoc."},{"id":"cli/generator/generator::command::57","title":"Генератор","section":"Выполнение плагина через команду (command)","path":"/docs/guide/cli/generator/generator#command","headings":["Выполнение плагина через команду (command)"],"excerpt":"Выполнение плагина через команду (command) **Приоритет источников плагина:** command — выполнение через указанную команду (наивысший приоритет) remote — удалённый плагин через URL name — локальный плагин из PATH или встр","content":"Выполнение плагина через команду (command) **Приоритет источников плагина:** command — выполнение через указанную команду (наивысший приоритет) remote — удалённый плагин через URL name — локальный плагин из PATH или встроенный плагин path — путь к исполняемому файлу плагина"},{"id":"cli/generator/generator::command::58","title":"Генератор","section":"Выполнение плагина через команду (command)","path":"/docs/guide/cli/generator/generator#command","headings":["Выполнение плагина через команду (command)"],"excerpt":"Выполнение плагина через команду (command) **Параметры (источники и общие опции плагина):**","content":"Выполнение плагина через команду (command) **Параметры (источники и общие опции плагина):**"},{"id":"cli/generator/generator::command::59","title":"Генератор","section":"Выполнение плагина через команду (command)","path":"/docs/guide/cli/generator/generator#command","headings":["Выполнение плагина через команду (command)"],"excerpt":"Выполнение плагина через команду (command) Параметр Тип Обязателен По умолчанию Описание ---------- ----- ------------ -------------- ---------- name string ❌ - Имя / идентификатор плагина (например, go, go-grpc, grpc-ga","content":"Выполнение плагина через команду (command) Параметр Тип Обязателен По умолчанию Описание ---------- ----- ------------ -------------- ---------- name string ❌ - Имя / идентификатор плагина (например, go, go-grpc, grpc-gateway) command []string ❌ - Команда для выполнения плагина (например, [\"go\", \"run\", \"package\"]) remote string ❌ - URL удалённого плагина path string ❌ - Путь к исполняемому файлу плагина out string ✅ - Директория для сгенерированных файлов opts mapstring ❌ {} Специфичные опции плагина; значения-списки передаются как повторяющиеся key=value with_imports bool ❌ false Включать proto из зависимостей"},{"id":"cli/generator/generator::command::60","title":"Генератор","section":"Выполнение плагина через команду (command)","path":"/docs/guide/cli/generator/generator#command","headings":["Выполнение плагина через команду (command)"],"excerpt":"Выполнение плагина через команду (command) **Примечание:** Для каждого плагина должен быть указан ровно один источник (name, command, remote или path). Если opts.outputServices задан как [\"grpc-js\", \"generic-definitions\"","content":"Выполнение плагина через команду (command) **Примечание:** Для каждого плагина должен быть указан ровно один источник (name, command, remote или path). Если opts.outputServices задан как [\"grpc-js\", \"generic-definitions\"], EasyP передаст outputServices=grpc-js,outputServices=generic-definitions."},{"id":"cli/generator/generator::command::61","title":"Генератор","section":"Выполнение плагина через команду (command)","path":"/docs/guide/cli/generator/generator#command","headings":["Выполнение плагина через команду (command)"],"excerpt":"Выполнение плагина через команду (command) **Примеры использования источника command:**","content":"Выполнение плагина через команду (command) **Примеры использования источника command:**"},{"id":"cli/generator/generator::command::62","title":"Генератор","section":"Выполнение плагина через команду (command)","path":"/docs/guide/cli/generator/generator#command","headings":["Выполнение плагина через команду (command)"],"excerpt":"Выполнение плагина через команду (command) ```yaml generate: inputs: - directory: \"proto\"","content":"Выполнение плагина через команду (command) ```yaml generate: inputs: - directory: \"proto\""},{"id":"cli/generator/generator::command::63","title":"Генератор","section":"Выполнение плагина через команду (command)","path":"/docs/guide/cli/generator/generator#command","headings":["Выполнение плагина через команду (command)"],"excerpt":"Выполнение плагина через команду (command) plugins: # 1) gRPC-Gateway через go run (без предварительной установки бинарника) - command: [\"go\", \"run\", \"github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway@v2.","content":"Выполнение плагина через команду (command) plugins: # 1) gRPC-Gateway через go run (без предварительной установки бинарника) - 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::command::64","title":"Генератор","section":"Выполнение плагина через команду (command)","path":"/docs/guide/cli/generator/generator#command","headings":["Выполнение плагина через команду (command)"],"excerpt":"Выполнение плагина через команду (command) 2) protoc-gen-validate через go run - command: [\"go\", \"run\", \"github.com/bufbuild/protoc-gen-validate@v0.10.1\"] out: ./gen/go opts: paths: source_relative lang: go","content":"Выполнение плагина через команду (command) 2) protoc-gen-validate через 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::command::65","title":"Генератор","section":"Выполнение плагина через команду (command)","path":"/docs/guide/cli/generator/generator#command","headings":["Выполнение плагина через команду (command)"],"excerpt":"Выполнение плагина через команду (command) 3) Произвольный кастомный скрипт-обёртка - command: [\"bash\", \"./scripts/custom-protoc-plugin.sh\"] out: ./gen/custom opts: foo: bar ```","content":"Выполнение плагина через команду (command) 3) Произвольный кастомный скрипт-обёртка - command: [\"bash\", \"./scripts/custom-protoc-plugin.sh\"] out: ./gen/custom opts: foo: bar ```"},{"id":"cli/generator/generator::builtin-plugins::66","title":"Генератор","section":"Встроенные плагины (Builtin Plugins)","path":"/docs/guide/cli/generator/generator#builtin-plugins","headings":["Встроенные плагины (Builtin Plugins)"],"excerpt":"Встроенные плагины (Builtin Plugins) EasyP поддерживает встроенные плагины для базовых языков protobuf и gRPC. Эти плагины встроены в бинарник как WASM-модули и не требуют установки внешних зависимостей.","content":"Встроенные плагины (Builtin Plugins) EasyP поддерживает встроенные плагины для базовых языков protobuf и gRPC. Эти плагины встроены в бинарник как WASM-модули и не требуют установки внешних зависимостей."},{"id":"cli/generator/generator::builtin-plugins::67","title":"Генератор","section":"Встроенные плагины (Builtin Plugins)","path":"/docs/guide/cli/generator/generator#builtin-plugins","headings":["Встроенные плагины (Builtin Plugins)"],"excerpt":"Встроенные плагины (Builtin Plugins) **Преимущества встроенных плагинов:** **Портативность**: Один бинарник со всеми необходимыми плагинами **Удобство**: Не требуется установка внешних зависимостей **Стабильность**: Верс","content":"Встроенные плагины (Builtin Plugins) **Преимущества встроенных плагинов:** **Портативность**: Один бинарник со всеми необходимыми плагинами **Удобство**: Не требуется установка внешних зависимостей **Стабильность**: Версии плагинов зафиксированы в бинарнике **Изоляция**: Не зависит от системных установок плагинов"},{"id":"cli/generator/generator::builtin-plugins::68","title":"Генератор","section":"Встроенные плагины (Builtin Plugins)","path":"/docs/guide/cli/generator/generator#builtin-plugins","headings":["Встроенные плагины (Builtin Plugins)"],"excerpt":"Встроенные плагины (Builtin Plugins) **Поддерживаемые встроенные плагины:**","content":"Встроенные плагины (Builtin Plugins) **Поддерживаемые встроенные плагины:**"},{"id":"cli/generator/generator::protobuf::69","title":"Генератор","section":"Protobuf базовые плагины","path":"/docs/guide/cli/generator/generator#protobuf","headings":["Protobuf базовые плагины"],"excerpt":"Protobuf базовые плагины Следующие плагины встроены для генерации базового protobuf кода:","content":"Protobuf базовые плагины Следующие плагины встроены для генерации базового protobuf кода:"},{"id":"cli/generator/generator::protobuf::70","title":"Генератор","section":"Protobuf базовые плагины","path":"/docs/guide/cli/generator/generator#protobuf","headings":["Protobuf базовые плагины"],"excerpt":"Protobuf базовые плагины Имя плагина Описание Соответствующий protoc плагин ------------- ---------- ------------------------------- cpp Генерация C++ кода из proto файлов protoc-gen-cpp csharp Генерация C# кода из proto","content":"Protobuf базовые плагины Имя плагина Описание Соответствующий protoc плагин ------------- ---------- ------------------------------- cpp Генерация C++ кода из proto файлов protoc-gen-cpp csharp Генерация C# кода из proto файлов protoc-gen-csharp java Генерация Java кода из proto файлов protoc-gen-java kotlin Генерация Kotlin кода из proto файлов protoc-gen-kotlin objc Генерация Objective-C кода из proto файлов protoc-gen-objc php Генерация PHP кода из proto файлов protoc-gen-php python Генерация Python кода из proto файлов protoc-gen-python ruby Генерация Ruby кода из proto файлов protoc-gen-ruby"},{"id":"cli/generator/generator::grpc::71","title":"Генератор","section":"gRPC плагины","path":"/docs/guide/cli/generator/generator#grpc","headings":["gRPC плагины"],"excerpt":"gRPC плагины Следующие плагины встроены для генерации gRPC кода:","content":"gRPC плагины Следующие плагины встроены для генерации gRPC кода:"},{"id":"cli/generator/generator::grpc::72","title":"Генератор","section":"gRPC плагины","path":"/docs/guide/cli/generator/generator#grpc","headings":["gRPC плагины"],"excerpt":"gRPC плагины Имя плагина Описание Соответствующий protoc плагин ------------- ---------- ------------------------------- grpc_cpp Генерация gRPC кода для C++ grpc_cpp_plugin grpc_csharp Генерация gRPC кода для C# grpc_cs","content":"gRPC плагины Имя плагина Описание Соответствующий protoc плагин ------------- ---------- ------------------------------- grpc_cpp Генерация gRPC кода для C++ grpc_cpp_plugin grpc_csharp Генерация gRPC кода для C# grpc_csharp_plugin grpc_java Генерация gRPC кода для Java grpc_java_plugin grpc_node Генерация gRPC кода для Node.js grpc_node_plugin grpc_objc Генерация gRPC кода для Objective-C grpc_objective_c_plugin grpc_php Генерация gRPC кода для PHP grpc_php_plugin grpc_python Генерация gRPC кода для Python grpc_python_plugin grpc_ruby Генерация gRPC кода для Ruby grpc_ruby_plugin"},{"id":"cli/generator/generator::grpc::73","title":"Генератор","section":"gRPC плагины","path":"/docs/guide/cli/generator/generator#grpc","headings":["gRPC плагины"],"excerpt":"gRPC плагины **Логика выбора плагина:**","content":"gRPC плагины **Логика выбора плагина:**"},{"id":"cli/generator/generator::grpc::74","title":"Генератор","section":"gRPC плагины","path":"/docs/guide/cli/generator/generator#grpc","headings":["gRPC плагины"],"excerpt":"gRPC плагины EasyP использует следующий приоритет при выборе executor'а для плагина:","content":"gRPC плагины EasyP использует следующий приоритет при выборе executor'а для плагина:"},{"id":"cli/generator/generator::grpc::75","title":"Генератор","section":"gRPC плагины","path":"/docs/guide/cli/generator/generator#grpc","headings":["gRPC плагины"],"excerpt":"gRPC плагины **Удалённый плагин** (если указан url) — всегда имеет наивысший приоритет **Встроенный плагин** (если плагин встроен и не найден в PATH) — используется автоматически **Локальный плагин** (из PATH) — использу","content":"gRPC плагины **Удалённый плагин** (если указан url) — всегда имеет наивысший приоритет **Встроенный плагин** (если плагин встроен и не найден в PATH) — используется автоматически **Локальный плагин** (из PATH) — используется по умолчанию для обратной совместимости"},{"id":"cli/generator/generator::grpc::76","title":"Генератор","section":"gRPC плагины","path":"/docs/guide/cli/generator/generator#grpc","headings":["gRPC плагины"],"excerpt":"gRPC плагины **Пример использования:**","content":"gRPC плагины **Пример использования:**"},{"id":"cli/generator/generator::grpc::77","title":"Генератор","section":"gRPC плагины","path":"/docs/guide/cli/generator/generator#grpc","headings":["gRPC плагины"],"excerpt":"gRPC плагины Встроенные плагины включены в бинарник EasyP:","content":"gRPC плагины Встроенные плагины включены в бинарник EasyP:"},{"id":"cli/generator/generator::grpc::78","title":"Генератор","section":"gRPC плагины","path":"/docs/guide/cli/generator/generator#grpc","headings":["gRPC плагины"],"excerpt":"gRPC плагины ```bash Сборка go build ./cmd/easyp","content":"gRPC плагины ```bash Сборка go build ./cmd/easyp"},{"id":"cli/generator/generator::grpc::79","title":"Генератор","section":"gRPC плагины","path":"/docs/guide/cli/generator/generator#grpc","headings":["gRPC плагины"],"excerpt":"gRPC плагины Установка go install github.com/easyp-tech/easyp/cmd/easyp@latest ```","content":"gRPC плагины Установка go install github.com/easyp-tech/easyp/cmd/easyp@latest ```"},{"id":"cli/generator/generator::grpc::80","title":"Генератор","section":"gRPC плагины","path":"/docs/guide/cli/generator/generator#grpc","headings":["gRPC плагины"],"excerpt":"gRPC плагины **Обратная совместимость:**","content":"gRPC плагины **Обратная совместимость:**"},{"id":"cli/generator/generator::grpc::81","title":"Генератор","section":"gRPC плагины","path":"/docs/guide/cli/generator/generator#grpc","headings":["gRPC плагины"],"excerpt":"gRPC плагины Встроенные плагины полностью совместимы с существующими конфигурациями. Если плагин найден в PATH, он будет использован вместо встроенного. Это гарантирует, что:","content":"gRPC плагины Встроенные плагины полностью совместимы с существующими конфигурациями. Если плагин найден в PATH, он будет использован вместо встроенного. Это гарантирует, что:"},{"id":"cli/generator/generator::grpc::82","title":"Генератор","section":"gRPC плагины","path":"/docs/guide/cli/generator/generator#grpc","headings":["gRPC плагины"],"excerpt":"gRPC плагины Существующие конфигурации продолжают работать без изменений Можно переопределить встроенный плагин, установив его в системе Приоритет отдаётся локальным установкам для гибкости","content":"gRPC плагины Существующие конфигурации продолжают работать без изменений Можно переопределить встроенный плагин, установив его в системе Приоритет отдаётся локальным установкам для гибкости"},{"id":"cli/generator/generator::top::83","title":"Генератор","section":"Справочник опций плагинов","path":"/docs/guide/cli/generator/generator","headings":["Справочник опций плагинов"],"excerpt":"Справочник опций плагинов Ниже перечислены наиболее часто используемые плагины и их настройки. Каждый плагин имеет параметры, влияющие на результат генерации — понимание этих опций важно для получения нужного вывода.","content":"Справочник опций плагинов Ниже перечислены наиболее часто используемые плагины и их настройки. Каждый плагин имеет параметры, влияющие на результат генерации — понимание этих опций важно для получения нужного вывода."},{"id":"cli/generator/generator::go-plugins::84","title":"Генератор","section":"Go Plugins","path":"/docs/guide/cli/generator/generator#go-plugins","headings":["Go Plugins"],"excerpt":"Go Plugins Плагины для Go — самые зрелые и распространённые. Опция paths управляет тем, как формируются пути импортов; остальные опции дают тонкую настройку вывода.","content":"Go Plugins Плагины для Go — самые зрелые и распространённые. Опция paths управляет тем, как формируются пути импортов; остальные опции дают тонкую настройку вывода."},{"id":"cli/generator/generator::grpc-gateway-plugins::85","title":"Генератор","section":"gRPC-Gateway Plugins","path":"/docs/guide/cli/generator/generator#grpc-gateway-plugins","headings":["gRPC-Gateway Plugins"],"excerpt":"gRPC-Gateway Plugins Позволяют экспонировать gRPC сервисы как REST API и генерировать OpenAPI. Критично для HTTP/JSON поверх gRPC.","content":"gRPC-Gateway Plugins Позволяют экспонировать gRPC сервисы как REST API и генерировать OpenAPI. Критично для HTTP/JSON поверх gRPC."},{"id":"cli/generator/generator::validation-plugins::86","title":"Генератор","section":"Validation Plugins","path":"/docs/guide/cli/generator/generator#validation-plugins","headings":["Validation Plugins"],"excerpt":"Validation Plugins Генерируют код валидации на основе правил в proto, устраняя ручную проверку.","content":"Validation Plugins Генерируют код валидации на основе правил в proto, устраняя ручную проверку."},{"id":"cli/generator/generator::typescriptjavascript-plugins::87","title":"Генератор","section":"TypeScript/JavaScript Plugins","path":"/docs/guide/cli/generator/generator#typescriptjavascript-plugins","headings":["TypeScript/JavaScript Plugins"],"excerpt":"TypeScript/JavaScript Plugins TypeScript плагины нужны фронтенду: типобезопасные интерфейсы и клиенты.","content":"TypeScript/JavaScript Plugins TypeScript плагины нужны фронтенду: типобезопасные интерфейсы и клиенты."},{"id":"cli/generator/generator::managed-mode::88","title":"Генератор","section":"Managed Mode","path":"/docs/guide/cli/generator/generator#managed-mode","headings":["Managed Mode"],"excerpt":"Managed Mode Managed mode автоматически устанавливает file и field опции в protobuf дескрипторах во время генерации кода без изменения исходных .proto файлов. Эта функция совместима с managed mode в buf и обеспечивает ед","content":"Managed Mode Managed mode автоматически устанавливает file и field опции в protobuf дескрипторах во время генерации кода без изменения исходных .proto файлов. Эта функция совместима с managed mode в buf и обеспечивает единообразный способ управления языково-специфичными опциями в вашей кодовой базе."},{"id":"cli/generator/generator::managed-mode::89","title":"Генератор","section":"Managed Mode","path":"/docs/guide/cli/generator/generator#managed-mode","headings":["Managed Mode"],"excerpt":"Managed Mode **Ключевые преимущества:** **Без изменений proto файлов**: Опции применяются во время генерации, proto файлы остаются чистыми **Согласованные значения по умолчанию**: Автоматическое применение языковых согла","content":"Managed Mode **Ключевые преимущества:** **Без изменений proto файлов**: Опции применяются во время генерации, proto файлы остаются чистыми **Согласованные значения по умолчанию**: Автоматическое применение языковых соглашений об именовании **Централизованная конфигурация**: Управление всеми опциями в одном месте (easyp.yaml) **Правила для модулей**: Применение разных опций к разным модулям или путям **Совместимость с buf**: Работает так же, как managed mode в buf"},{"id":"cli/generator/generator::top::90","title":"Генератор","section":"Как это работает","path":"/docs/guide/cli/generator/generator","headings":["Как это работает"],"excerpt":"Как это работает Когда managed mode включён, EasyP автоматически применяет file и field опции к protobuf дескрипторам перед генерацией кода. Это происходит в памяти, поэтому исходные .proto файлы остаются неизменными.","content":"Как это работает Когда managed mode включён, EasyP автоматически применяет file и field опции к protobuf дескрипторам перед генерацией кода. Это происходит в памяти, поэтому исходные .proto файлы остаются неизменными."},{"id":"cli/generator/generator::top::91","title":"Генератор","section":"Как это работает","path":"/docs/guide/cli/generator/generator","headings":["Как это работает"],"excerpt":"Как это работает **Значения по умолчанию** применяются для определённых опций на основе языковых соглашений: Java: java_package_prefix по умолчанию \"com\", java_multiple_files по умолчанию true C#: csharp_namespace по умо","content":"Как это работает **Значения по умолчанию** применяются для определённых опций на основе языковых соглашений: Java: java_package_prefix по умолчанию \"com\", java_multiple_files по умолчанию true C#: csharp_namespace по умолчанию PascalCase имени пакета Ruby: ruby_package по умолчанию PascalCase с разделителем :: PHP: php_namespace по умолчанию PascalCase с разделителем \\ Objective-C: objc_class_prefix по умолчанию первые буквы частей пакета C++: cc_enable_arenas по умолчанию true"},{"id":"cli/generator/generator::top::92","title":"Генератор","section":"Как это работает","path":"/docs/guide/cli/generator/generator","headings":["Как это работает"],"excerpt":"Как это работает **Overrides** позволяют установить конкретные значения для опций с поддержкой фильтрации по модулю, protobuf package, пути или полю. Если не указаны module, package и path, override применяется ко всем ф","content":"Как это работает **Overrides** позволяют установить конкретные значения для опций с поддержкой фильтрации по модулю, protobuf package, пути или полю. Если не указаны module, package и path, override применяется ко всем файлам в запросе генерации, включая зависимости и git_repo inputs."},{"id":"cli/generator/generator::top::93","title":"Генератор","section":"Как это работает","path":"/docs/guide/cli/generator/generator","headings":["Как это работает"],"excerpt":"Как это работает **Disables** позволяют предотвратить изменение managed mode определённых опций или файлов. Это рекомендуемый способ исключить внешние зависимости, у которых свои опции уже заданы.","content":"Как это работает **Disables** позволяют предотвратить изменение managed mode определённых опций или файлов. Это рекомендуемый способ исключить внешние зависимости, у которых свои опции уже заданы."},{"id":"cli/generator/generator::top::94","title":"Генератор","section":"Конфигурация","path":"/docs/guide/cli/generator/generator","headings":["Конфигурация"],"excerpt":"Конфигурация ```yaml generate: managed: enabled: true disable: # Отключить managed mode для конкретного модуля - module: github.com/googleapis/googleapis # Отключить конкретную опцию глобально - file_option: java_package","content":"Конфигурация ```yaml generate: managed: enabled: true disable: # Отключить managed mode для конкретного модуля - module: github.com/googleapis/googleapis # Отключить конкретную опцию глобально - file_option: java_package_prefix"},{"id":"cli/generator/generator::top::95","title":"Генератор","section":"Конфигурация","path":"/docs/guide/cli/generator/generator","headings":["Конфигурация"],"excerpt":"Конфигурация Отключить для конкретного protobuf package - package: acme.weather.v1 file_option: java_package # Отключить для конкретного пути - path: legacy/ file_option: go_package # Отключить field опцию для конкретног","content":"Конфигурация Отключить для конкретного protobuf package - package: acme.weather.v1 file_option: java_package # Отключить для конкретного пути - path: legacy/ file_option: go_package # Отключить field опцию для конкретного поля - field_option: jstype field: com.example.User.id override: # Переопределить go_package_prefix для всех файлов - file_option: go_package_prefix value: github.com/mycompany/myproject/gen/go # Переопределить для конкретного модуля - file_option: java_package_prefix value: com.mycompany module: github.com/mycompany/internal-protos"},{"id":"cli/generator/generator::top::96","title":"Генератор","section":"Конфигурация","path":"/docs/guide/cli/generator/generator","headings":["Конфигурация"],"excerpt":"Конфигурация Переопределить для конкретного protobuf package - file_option: go_package_prefix value: github.com/mycompany/myproject/gen/go package: acme.weather.v1 # Переопределить для конкретного пути - file_option: csh","content":"Конфигурация Переопределить для конкретного protobuf package - file_option: go_package_prefix value: github.com/mycompany/myproject/gen/go package: acme.weather.v1 # Переопределить для конкретного пути - file_option: csharp_namespace_prefix value: MyCompany path: api/v1/ # Переопределить для нескольких файлов с одинаковым значением используя префиксный путь # Это совпадет и с internal/cms/bmi.proto, и с internal/cms/bmi_service.proto - file_option: go_package value: spec/cms/bmi path: \"internal/cms/bmi\" # Переопределить field опцию для конкретного пути - field_option: jstype value: JS_STRING path: api/v1/ # Переопределить для конкретного поля - field_option: jstype value: JS_NUMBER field: com.example.User.big_id ```"},{"id":"cli/generator/generator::file-options::97","title":"Генератор","section":"Поддерживаемые File Options","path":"/docs/guide/cli/generator/generator#file-options","headings":["Поддерживаемые File Options"],"excerpt":"Поддерживаемые File Options Опция Описание Есть значение по умолчанию? ------- ---------- ---------------------------- go_package Go import path ❌ go_package_prefix Префикс для Go import paths ❌ java_package Имя Java пак","content":"Поддерживаемые File Options Опция Описание Есть значение по умолчанию? ------- ---------- ---------------------------- go_package Go import path ❌ go_package_prefix Префикс для Go import paths ❌ java_package Имя Java пакета ❌ java_package_prefix Префикс для Java пакетов ✅ (\"com\") java_package_suffix Суффикс для Java пакетов ❌ java_multiple_files Генерировать несколько Java файлов ✅ (true) java_outer_classname Имя внешнего класса ✅ (PascalCase + \"Proto\") java_string_check_utf8 UTF-8 валидация ❌ csharp_namespace C# namespace ✅ (PascalCase) csharp_namespace_prefix Префикс для C# namespaces ❌ ruby_package Имя Ruby модуля ✅ (PascalCase с ::) ruby_package_suffix Суффикс для Ruby пакетов ❌ php_namespace PHP namespace ✅ (PascalCase с \\) php_metadata_namespace PHP metadata namespace ❌ php_metadata_namespace_suffix Суффикс для PHP metadata ❌ objc_class_prefix Objective-C префикс класса ✅ (Первые буквы) swift_prefix Swift префикс ❌ optimize_for Оптимизация генерации кода ❌ cc_enable_arenas C++ arena аллокация ✅ (true)"},{"id":"cli/generator/generator::field-options::98","title":"Генератор","section":"Поддерживаемые Field Options","path":"/docs/guide/cli/generator/generator#field-options","headings":["Поддерживаемые Field Options"],"excerpt":"Поддерживаемые Field Options Опция Описание Применяется к ------- ---------- --------------- jstype JavaScript тип для 64-битных целых чисел int64, uint64, sint64, fixed64, sfixed64","content":"Поддерживаемые Field Options Опция Описание Применяется к ------- ---------- --------------- jstype JavaScript тип для 64-битных целых чисел int64, uint64, sint64, fixed64, sfixed64"},{"id":"cli/generator/generator::top::99","title":"Генератор","section":"Базовая настройка со значениями по умолчанию","path":"/docs/guide/cli/generator/generator","headings":["Базовая настройка со значениями по умолчанию"],"excerpt":"Базовая настройка со значениями по умолчанию Включите managed mode для получения автоматических значений по умолчанию для всех поддерживаемых языков:","content":"Базовая настройка со значениями по умолчанию Включите managed mode для получения автоматических значений по умолчанию для всех поддерживаемых языков:"},{"id":"cli/generator/generator::top::100","title":"Генератор","section":"Базовая настройка со значениями по умолчанию","path":"/docs/guide/cli/generator/generator","headings":["Базовая настройка со значениями по умолчанию"],"excerpt":"Базовая настройка со значениями по умолчанию","content":"Базовая настройка со значениями по умолчанию"},{"id":"cli/generator/generator::top::101","title":"Генератор","section":"Базовая настройка со значениями по умолчанию","path":"/docs/guide/cli/generator/generator","headings":["Базовая настройка со значениями по умолчанию"],"excerpt":"Базовая настройка со значениями по умолчанию Это автоматически установит: java_package в com. для всех файлов java_multiple_files в true csharp_namespace в PascalCase имени пакета ruby_package в PascalCase с разделителем","content":"Базовая настройка со значениями по умолчанию Это автоматически установит: java_package в com. для всех файлов java_multiple_files в true csharp_namespace в PascalCase имени пакета ruby_package в PascalCase с разделителем :: И многое другое..."},{"id":"cli/generator/generator::go::102","title":"Генератор","section":"Кастомный префикс Go пакета","path":"/docs/guide/cli/generator/generator#go","headings":["Кастомный префикс Go пакета"],"excerpt":"Кастомный префикс Go пакета Переопределите префикс Go пакета для вашего проекта:","content":"Кастомный префикс Go пакета Переопределите префикс Go пакета для вашего проекта:"},{"id":"cli/generator/generator::go::103","title":"Генератор","section":"Кастомный префикс Go пакета","path":"/docs/guide/cli/generator/generator#go","headings":["Кастомный префикс Go пакета"],"excerpt":"Кастомный префикс Go пакета Это установит go_package в github.com/mycompany/myproject/gen/go/ для всех файлов.","content":"Кастомный префикс Go пакета Это установит go_package в github.com/mycompany/myproject/gen/go/ для всех файлов."},{"id":"cli/generator/generator::go::104","title":"Генератор","section":"Динамические пути Go пакетов с маркерами","path":"/docs/guide/cli/generator/generator#go","headings":["Динамические пути Go пакетов с маркерами"],"excerpt":"Динамические пути Go пакетов с маркерами Для более сложной генерации путей можно использовать маркеры в значениях go_package_prefix или go_package:","content":"Динамические пути Go пакетов с маркерами Для более сложной генерации путей можно использовать маркеры в значениях go_package_prefix или go_package:"},{"id":"cli/generator/generator::go::105","title":"Генератор","section":"Динамические пути Go пакетов с маркерами","path":"/docs/guide/cli/generator/generator#go","headings":["Динамические пути Go пакетов с маркерами"],"excerpt":"Динамические пути Go пакетов с маркерами","content":"Динамические пути Go пакетов с маркерами"},{"id":"cli/generator/generator::go::106","title":"Генератор","section":"Динамические пути Go пакетов с маркерами","path":"/docs/guide/cli/generator/generator#go","headings":["Динамические пути Go пакетов с маркерами"],"excerpt":"Динамические пути Go пакетов с маркерами **Доступные маркеры:** {{file_path}} - Полный путь файла без расширения .proto - Пример: internal/cms/as.proto → internal/cms/as {{file_dir}} - Только путь директории, без имени ф","content":"Динамические пути Go пакетов с маркерами **Доступные маркеры:** {{file_path}} - Полный путь файла без расширения .proto - Пример: internal/cms/as.proto → internal/cms/as {{file_dir}} - Только путь директории, без имени файла - Пример: internal/cms/as.proto → internal/cms {{file_dir_without:prefix/}} - Путь директории с удалением префикса и базового имени файла без суффиксов _service/_grpc - Пример: {{file_dir_without:internal/}} для internal/cms/as_service.proto → cms/as {{file_path_without:prefix/}} - Полный путь файла с удалением префикса - Пример: {{file_path_without:internal/}} для internal/cms/as.proto → cms/as"},{"id":"cli/generator/generator::top::107","title":"Генератор","section":"Переопределения для конкретных модулей","path":"/docs/guide/cli/generator/generator","headings":["Переопределения для конкретных модулей"],"excerpt":"Переопределения для конкретных модулей Примените разные опции к разным модулям:","content":"Переопределения для конкретных модулей Примените разные опции к разным модулям:"},{"id":"cli/generator/generator::top::108","title":"Генератор","section":"Переопределения для конкретных модулей","path":"/docs/guide/cli/generator/generator","headings":["Переопределения для конкретных модулей"],"excerpt":"Переопределения для конкретных модулей","content":"Переопределения для конкретных модулей"},{"id":"cli/generator/generator::top::109","title":"Генератор","section":"Переопределения для конкретных модулей","path":"/docs/guide/cli/generator/generator","headings":["Переопределения для конкретных модулей"],"excerpt":"Переопределения для конкретных модулей module должен точно совпадать с источником модуля в EasyP: это значение из deps или git_repo.url до @version (например, github.com/mycompany/internal-protos или https://github.com/m","content":"Переопределения для конкретных модулей module должен точно совпадать с источником модуля в EasyP: это значение из deps или git_repo.url до @version (например, github.com/mycompany/internal-protos или https://github.com/mycompany/internal-protos). Это не Go module path из go.mod."},{"id":"cli/generator/generator::top::110","title":"Генератор","section":"Переопределения для конкретных модулей","path":"/docs/guide/cli/generator/generator","headings":["Переопределения для конкретных модулей"],"excerpt":"Переопределения для конкретных модулей package должен точно совпадать со значением package в .proto файле, например acme.weather.v1.","content":"Переопределения для конкретных модулей package должен точно совпадать со значением package в .proto файле, например acme.weather.v1."},{"id":"cli/generator/generator::protobuf-package::111","title":"Генератор","section":"Переопределения для конкретного protobuf package","path":"/docs/guide/cli/generator/generator#protobuf-package","headings":["Переопределения для конкретного protobuf package"],"excerpt":"Переопределения для конкретного protobuf package Примените отдельные опции к файлам из конкретного protobuf package:","content":"Переопределения для конкретного protobuf package Примените отдельные опции к файлам из конкретного protobuf package:"},{"id":"cli/generator/generator::protobuf-package::112","title":"Генератор","section":"Переопределения для конкретного protobuf package","path":"/docs/guide/cli/generator/generator#protobuf-package","headings":["Переопределения для конкретного protobuf package"],"excerpt":"Переопределения для конкретного protobuf package","content":"Переопределения для конкретного protobuf package"},{"id":"cli/generator/generator::top::113","title":"Генератор","section":"Отключение для внешних зависимостей","path":"/docs/guide/cli/generator/generator","headings":["Отключение для внешних зависимостей"],"excerpt":"Отключение для внешних зависимостей Отключите managed mode для внешних зависимостей, у которых уже установлены опции:","content":"Отключение для внешних зависимостей Отключите managed mode для внешних зависимостей, у которых уже установлены опции:"},{"id":"cli/generator/generator::top::114","title":"Генератор","section":"Отключение для внешних зависимостей","path":"/docs/guide/cli/generator/generator","headings":["Отключение для внешних зависимостей"],"excerpt":"Отключение для внешних зависимостей","content":"Отключение для внешних зависимостей"},{"id":"cli/generator/generator::javascript::115","title":"Генератор","section":"Типобезопасность JavaScript","path":"/docs/guide/cli/generator/generator#javascript","headings":["Типобезопасность JavaScript"],"excerpt":"Типобезопасность JavaScript Установите jstype в JS_STRING для всех 64-битных целочисленных полей, чтобы предотвратить потерю точности в JavaScript:","content":"Типобезопасность JavaScript Установите jstype в JS_STRING для всех 64-битных целочисленных полей, чтобы предотвратить потерю точности в JavaScript:"},{"id":"cli/generator/generator::top::116","title":"Генератор","section":"Совпадение путей","path":"/docs/guide/cli/generator/generator","headings":["Совпадение путей"],"excerpt":"Совпадение путей Совпадение путей в managed mode использует префиксное совпадение (как в buf):","content":"Совпадение путей Совпадение путей в managed mode использует префиксное совпадение (как в buf):"},{"id":"cli/generator/generator::top::117","title":"Генератор","section":"Совпадение путей","path":"/docs/guide/cli/generator/generator","headings":["Совпадение путей"],"excerpt":"Совпадение путей **Путь директории** (заканчивается на /): Совпадает со всеми файлами в этой директории и поддиректориях - Пример: path: \"internal/cms/\" совпадает с internal/cms/as.proto, internal/cms/node.proto, interna","content":"Совпадение путей **Путь директории** (заканчивается на /): Совпадает со всеми файлами в этой директории и поддиректориях - Пример: path: \"internal/cms/\" совпадает с internal/cms/as.proto, internal/cms/node.proto, internal/cms/v1/service.proto **Точный путь файла** (заканчивается на .proto): Совпадает только с этим конкретным файлом - Пример: path: \"internal/cms/as.proto\" совпадает только с internal/cms/as.proto **Префиксный путь** (без завершающего / или .proto): Использует префиксное совпадение (не директориально-осознанное) - Пример: path: \"internal/cms\" совпадает с internal/cms/as.proto, но также с internal/cmsv2/file.proto - **Совет**: Используйте префиксные пути для группировки нескольких файлов с одинаковым значением. Например, path: \"internal/cms/bmi\" совпадает и с internal/cms/bmi.proto, и с internal/cms/bmi_service.proto, что позволяет установить одно и то же значение go_package для обоих файлов одним правилом."},{"id":"cli/generator/generator::top::118","title":"Генератор","section":"Приоритет правил","path":"/docs/guide/cli/generator/generator","headings":["Приоритет правил"],"excerpt":"Приоритет правил Когда несколько правил соответствуют одному файлу или полю, применяется следующий приоритет:","content":"Приоритет правил Когда несколько правил соответствуют одному файлу или полю, применяется следующий приоритет:"},{"id":"cli/generator/generator::top::119","title":"Генератор","section":"Приоритет правил","path":"/docs/guide/cli/generator/generator","headings":["Приоритет правил"],"excerpt":"Приоритет правил **Disable правила** имеют приоритет — если опция отключена, она не будет применена **Override правила** применяются по порядку — последнее совпадающее правило побеждает **Значения по умолчанию** применяю","content":"Приоритет правил **Disable правила** имеют приоритет — если опция отключена, она не будет применена **Override правила** применяются по порядку — последнее совпадающее правило побеждает **Значения по умолчанию** применяются только если нет совпадающего override и опция не отключена"},{"id":"cli/generator/generator::buf::120","title":"Генератор","section":"Совместимость с buf","path":"/docs/guide/cli/generator/generator#buf","headings":["Совместимость с buf"],"excerpt":"Совместимость с buf Managed mode в EasyP совместим с managed mode в buf. Тот же формат конфигурации и поведение применяются, что упрощает миграцию между инструментами или использование обоих в одном workflow.","content":"Совместимость с buf Managed mode в EasyP совместим с managed mode в buf. Тот же формат конфигурации и поведение применяются, что упрощает миграцию между инструментами или использование обоих в одном workflow."},{"id":"cli/generator/generator::descriptor-set::121","title":"Генератор","section":"Генерация Descriptor Set","path":"/docs/guide/cli/generator/generator#descriptor-set","headings":["Генерация Descriptor Set"],"excerpt":"Генерация Descriptor Set **https://protobuf.dev/programming-guides/techniques/#self-description**","content":"Генерация Descriptor Set **https://protobuf.dev/programming-guides/techniques/#self-description**"},{"id":"cli/generator/generator::descriptor-set::122","title":"Генератор","section":"Генерация Descriptor Set","path":"/docs/guide/cli/generator/generator#descriptor-set","headings":["Генерация Descriptor Set"],"excerpt":"Генерация Descriptor Set EasyP поддерживает генерацию бинарных FileDescriptorSet файлов с помощью флага --descriptor_set_out. Это позволяет создавать самоописывающиеся protobuf сообщения, которые включают информацию о сх","content":"Генерация Descriptor Set EasyP поддерживает генерацию бинарных FileDescriptorSet файлов с помощью флага --descriptor_set_out. Это позволяет создавать самоописывающиеся protobuf сообщения, которые включают информацию о схеме вместе с данными."},{"id":"cli/generator/generator::descriptor-set::123","title":"Генератор","section":"Генерация Descriptor Set","path":"/docs/guide/cli/generator/generator#descriptor-set","headings":["Генерация Descriptor Set"],"excerpt":"Генерация Descriptor Set **Флаги CLI:**","content":"Генерация Descriptor Set **Флаги CLI:**"},{"id":"cli/generator/generator::descriptor-set::124","title":"Генератор","section":"Генерация Descriptor Set","path":"/docs/guide/cli/generator/generator#descriptor-set","headings":["Генерация Descriptor Set"],"excerpt":"Генерация Descriptor Set --descriptor_set_out - Путь для вывода бинарного FileDescriptorSet --include_imports - Включить все транзитивные зависимости в FileDescriptorSet","content":"Генерация Descriptor Set --descriptor_set_out - Путь для вывода бинарного FileDescriptorSet --include_imports - Включить все транзитивные зависимости в FileDescriptorSet"},{"id":"cli/generator/generator::descriptor-set::125","title":"Генератор","section":"Генерация Descriptor Set","path":"/docs/guide/cli/generator/generator#descriptor-set","headings":["Генерация Descriptor Set"],"excerpt":"Генерация Descriptor Set **Пример:**","content":"Генерация Descriptor Set **Пример:**"},{"id":"cli/generator/generator::descriptor-set::126","title":"Генератор","section":"Генерация Descriptor Set","path":"/docs/guide/cli/generator/generator#descriptor-set","headings":["Генерация Descriptor Set"],"excerpt":"Генерация Descriptor Set ```bash Генерация descriptor set только с целевыми файлами easyp generate --descriptor_set_out=./schema.pb","content":"Генерация Descriptor Set ```bash Генерация descriptor set только с целевыми файлами easyp generate --descriptor_set_out=./schema.pb"},{"id":"cli/generator/generator::descriptor-set::127","title":"Генератор","section":"Генерация Descriptor Set","path":"/docs/guide/cli/generator/generator#descriptor-set","headings":["Генерация Descriptor Set"],"excerpt":"Генерация Descriptor Set Генерация descriptor set со всеми зависимостями easyp generate --descriptor_set_out=./schema.pb --include_imports ```","content":"Генерация Descriptor Set Генерация descriptor set со всеми зависимостями easyp generate --descriptor_set_out=./schema.pb --include_imports ```"},{"id":"cli/generator/generator::descriptor-set::128","title":"Генератор","section":"Генерация Descriptor Set","path":"/docs/guide/cli/generator/generator#descriptor-set","headings":["Генерация Descriptor Set"],"excerpt":"Генерация Descriptor Set Самоописывающиеся сообщения полезны для динамического парсинга сообщений, валидации схемы во время выполнения, реестров схем и создания универсальных gRPC клиентов. Для получения дополнительной и","content":"Генерация Descriptor Set Самоописывающиеся сообщения полезны для динамического парсинга сообщений, валидации схемы во время выполнения, реестров схем и создания универсальных gRPC клиентов. Для получения дополнительной информации см. документацию Protocol Buffers о самоописании."},{"id":"cli/generator/generator::top::129","title":"Генератор","section":"Интеграция с менеджером пакетов","path":"/docs/guide/cli/generator/generator","headings":["Интеграция с менеджером пакетов"],"excerpt":"Интеграция с менеджером пакетов Одной из самых мощных возможностей EasyP является бесшовная интеграция генератора кода с менеджером пакетов. Это устраняет проблему ручного управления proto‑зависимостями и гарантирует, чт","content":"Интеграция с менеджером пакетов Одной из самых мощных возможностей EasyP является бесшовная интеграция генератора кода с менеджером пакетов. Это устраняет проблему ручного управления proto‑зависимостями и гарантирует, что при генерации используются корректные (зафиксированные) версии импортируемых файлов."},{"id":"cli/generator/generator::top::130","title":"Генератор","section":"Интеграция с менеджером пакетов","path":"/docs/guide/cli/generator/generator","headings":["Интеграция с менеджером пакетов"],"excerpt":"Интеграция с менеджером пакетов **Ключевые преимущества:** **Автоматическое разрешение зависимостей**: не нужно вручную прописывать пути импортов **Согласованность версий**: фиксация в easyp.lock гарантирует воспроизводи","content":"Интеграция с менеджером пакетов **Ключевые преимущества:** **Автоматическое разрешение зависимостей**: не нужно вручную прописывать пути импортов **Согласованность версий**: фиксация в easyp.lock гарантирует воспроизводимость **Транзитивные зависимости**: вложенные цепочки подтягиваются автоматически **Производительность**: локальный кеш — скачивание один раз и повторное использование"},{"id":"cli/generator/generator::top::131","title":"Генератор","section":"Автоматическое разрешение зависимостей","path":"/docs/guide/cli/generator/generator","headings":["Автоматическое разрешение зависимостей"],"excerpt":"Автоматическое разрешение зависимостей Когда вы указываете зависимости в секции deps, генератор автоматически добавляет их в путь импортов. Ваши proto‑файлы могут делать стандартные import из этих зависимостей без дополн","content":"Автоматическое разрешение зависимостей Когда вы указываете зависимости в секции deps, генератор автоматически добавляет их в путь импортов. Ваши proto‑файлы могут делать стандартные import из этих зависимостей без дополнительной настройки."},{"id":"cli/generator/generator::top::132","title":"Генератор","section":"Автоматическое разрешение зависимостей","path":"/docs/guide/cli/generator/generator","headings":["Автоматическое разрешение зависимостей"],"excerpt":"Автоматическое разрешение зависимостей **Как это работает:** EasyP скачивает и кеширует зависимости из deps Во время генерации кешированные файлы автоматически добавляются в import‑path protoc Ваши proto‑файлы используют","content":"Автоматическое разрешение зависимостей **Как это работает:** EasyP скачивает и кеширует зависимости из deps Во время генерации кешированные файлы автоматически добавляются в import‑path protoc Ваши proto‑файлы используют обычные import строки для обращения к зависимостям При with_imports: true в вывод попадают и локальные файлы, и файлы зависимостей"},{"id":"cli/generator/generator::top::133","title":"Генератор","section":"Автоматическое разрешение зависимостей","path":"/docs/guide/cli/generator/generator","headings":["Автоматическое разрешение зависимостей"],"excerpt":"Автоматическое разрешение зависимостей Ниже простой пример — зависимости указываются один раз в deps, далее они доступны при генерации автоматически:","content":"Автоматическое разрешение зависимостей Ниже простой пример — зависимости указываются один раз в deps, далее они доступны при генерации автоматически:"},{"id":"cli/generator/generator::top::134","title":"Генератор","section":"Автоматическое разрешение зависимостей","path":"/docs/guide/cli/generator/generator","headings":["Автоматическое разрешение зависимостей"],"excerpt":"Автоматическое разрешение зависимостей ```yaml deps: - github.com/googleapis/googleapis@common-protos-1_3_1 - github.com/grpc-ecosystem/grpc-gateway@v2.19.1","content":"Автоматическое разрешение зависимостей ```yaml deps: - github.com/googleapis/googleapis@common-protos-1_3_1 - github.com/grpc-ecosystem/grpc-gateway@v2.19.1"},{"id":"cli/generator/generator::top::135","title":"Генератор","section":"Автоматическое разрешение зависимостей","path":"/docs/guide/cli/generator/generator","headings":["Автоматическое разрешение зависимостей"],"excerpt":"Автоматическое разрешение зависимостей generate: inputs: - directory: \"proto\" plugins: - name: go out: ./gen/go opts: paths: source_relative with_imports: true # This automatically includes googleapis and grpc-gateway pr","content":"Автоматическое разрешение зависимостей 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::top::136","title":"Генератор","section":"Примеры использования зависимостей","path":"/docs/guide/cli/generator/generator","headings":["Примеры использования зависимостей"],"excerpt":"Примеры использования зависимостей Ниже показаны распространённые способы интеграции внешних proto‑зависимостей в процесс генерации.","content":"Примеры использования зависимостей Ниже показаны распространённые способы интеграции внешних proto‑зависимостей в процесс генерации."},{"id":"cli/generator/generator::google-apis::137","title":"Генератор","section":"Использование Google APIs","path":"/docs/guide/cli/generator/generator#google-apis","headings":["Использование Google APIs"],"excerpt":"Использование Google APIs Google APIs — одна из самых популярных коллекций зависимостей: стандартные типы, аннотации для REST, проверки и общие структуры данных.","content":"Использование Google APIs Google APIs — одна из самых популярных коллекций зависимостей: стандартные типы, аннотации для REST, проверки и общие структуры данных."},{"id":"cli/generator/generator::google-apis::138","title":"Генератор","section":"Использование Google APIs","path":"/docs/guide/cli/generator/generator#google-apis","headings":["Использование Google APIs"],"excerpt":"Использование Google APIs **Когда использовать Google APIs:** Построение REST поверх gRPC (gRPC-Gateway) Нужны стандартные типы (Timestamp, Duration, Any) Требуются аннотации поведения полей (field behavior) Интеграция с","content":"Использование Google APIs **Когда использовать Google APIs:** Построение REST поверх gRPC (gRPC-Gateway) Нужны стандартные типы (Timestamp, Duration, Any) Требуются аннотации поведения полей (field behavior) Интеграция с сервисами Google Cloud"},{"id":"cli/generator/generator::google-apis::139","title":"Генератор","section":"Использование Google APIs","path":"/docs/guide/cli/generator/generator#google-apis","headings":["Использование Google APIs"],"excerpt":"Использование Google APIs Минимальная конфигурация для подключения Google APIs:","content":"Использование Google APIs Минимальная конфигурация для подключения Google APIs:"},{"id":"cli/generator/generator::google-apis::140","title":"Генератор","section":"Использование Google APIs","path":"/docs/guide/cli/generator/generator#google-apis","headings":["Использование Google APIs"],"excerpt":"Использование Google APIs ```yaml deps: - github.com/googleapis/googleapis@common-protos-1_3_1","content":"Использование Google APIs ```yaml deps: - github.com/googleapis/googleapis@common-protos-1_3_1"},{"id":"cli/generator/generator::google-apis::141","title":"Генератор","section":"Использование Google APIs","path":"/docs/guide/cli/generator/generator#google-apis","headings":["Использование Google APIs"],"excerpt":"Использование Google APIs generate: inputs: - directory: \"api/proto\" plugins: - name: go out: ./gen/go opts: paths: source_relative with_imports: true ```","content":"Использование Google APIs generate: inputs: - directory: \"api/proto\" plugins: - name: go out: ./gen/go opts: paths: source_relative with_imports: true ```"},{"id":"cli/generator/generator::google-apis::142","title":"Генератор","section":"Использование Google APIs","path":"/docs/guide/cli/generator/generator#google-apis","headings":["Использование Google APIs"],"excerpt":"Использование Google APIs **Важно:** Всегда фиксируйте версию (например common-protos-1_3_1) — не используйте latest в продакшене.","content":"Использование Google APIs **Важно:** Всегда фиксируйте версию (например common-protos-1_3_1) — не используйте latest в продакшене."},{"id":"cli/generator/generator::google-apis::143","title":"Генератор","section":"Использование Google APIs","path":"/docs/guide/cli/generator/generator#google-apis","headings":["Использование Google APIs"],"excerpt":"Использование Google APIs После настройки ваши proto могут импортировать определения Google API. Ниже пример сервиса с HTTP аннотацией:","content":"Использование Google APIs После настройки ваши proto могут импортировать определения Google API. Ниже пример сервиса с HTTP аннотацией:"},{"id":"cli/generator/generator::google-apis::144","title":"Генератор","section":"Использование Google APIs","path":"/docs/guide/cli/generator/generator#google-apis","headings":["Использование Google APIs"],"excerpt":"Использование Google APIs ```proto // api/proto/service.proto syntax = \"proto3\";","content":"Использование Google APIs ```proto // api/proto/service.proto syntax = \"proto3\";"},{"id":"cli/generator/generator::google-apis::145","title":"Генератор","section":"Использование Google APIs","path":"/docs/guide/cli/generator/generator#google-apis","headings":["Использование Google APIs"],"excerpt":"Использование Google APIs import \"google/api/annotations.proto\"; import \"google/protobuf/timestamp.proto\";","content":"Использование Google APIs import \"google/api/annotations.proto\"; import \"google/protobuf/timestamp.proto\";"},{"id":"cli/generator/generator::google-apis::146","title":"Генератор","section":"Использование Google APIs","path":"/docs/guide/cli/generator/generator#google-apis","headings":["Использование Google APIs"],"excerpt":"Использование Google APIs service MyService { rpc GetData(GetDataRequest) returns (GetDataResponse) { option (google.api.http) = { get: \"/v1/data\" }; } } ```","content":"Использование Google APIs service MyService { rpc GetData(GetDataRequest) returns (GetDataResponse) { option (google.api.http) = { get: \"/v1/data\" }; } } ```"},{"id":"cli/generator/generator::top::147","title":"Генератор","section":"Использование правил валидации","path":"/docs/guide/cli/generator/generator","headings":["Использование правил валидации"],"excerpt":"Использование правил валидации protoc-gen-validate даёт мощную проверку полей прямо в определениях proto, устраняя необходимость писать отдельную логику валидации в приложении.","content":"Использование правил валидации protoc-gen-validate даёт мощную проверку полей прямо в определениях proto, устраняя необходимость писать отдельную логику валидации в приложении."},{"id":"cli/generator/generator::top::148","title":"Генератор","section":"Использование правил валидации","path":"/docs/guide/cli/generator/generator","headings":["Использование правил валидации"],"excerpt":"Использование правил валидации **Когда применять валидацию:** Проверка входных данных API Ограничения моделей БД Проверка конфигурационных файлов Любая ситуация, где критична целостность данных","content":"Использование правил валидации **Когда применять валидацию:** Проверка входных данных API Ограничения моделей БД Проверка конфигурационных файлов Любая ситуация, где критична целостность данных"},{"id":"cli/generator/generator::top::149","title":"Генератор","section":"Использование правил валидации","path":"/docs/guide/cli/generator/generator","headings":["Использование правил валидации"],"excerpt":"Использование правил валидации **Преимущества:** Правила валидации — часть proto (единый источник истины) Генерация создаёт функции проверки автоматически Единообразие проверок между языками Производительнее чем проверка","content":"Использование правил валидации **Преимущества:** Правила валидации — часть proto (единый источник истины) Генерация создаёт функции проверки автоматически Единообразие проверок между языками Производительнее чем проверка через runtime reflection"},{"id":"cli/generator/generator::top::150","title":"Генератор","section":"Использование правил валидации","path":"/docs/guide/cli/generator/generator","headings":["Использование правил валидации"],"excerpt":"Использование правил валидации ```yaml deps: - github.com/bufbuild/protoc-gen-validate@v0.10.1","content":"Использование правил валидации ```yaml deps: - github.com/bufbuild/protoc-gen-validate@v0.10.1"},{"id":"cli/generator/generator::top::151","title":"Генератор","section":"Использование правил валидации","path":"/docs/guide/cli/generator/generator","headings":["Использование правил валидации"],"excerpt":"Использование правил валидации 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":"Использование правил валидации 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::top::152","title":"Генератор","section":"Использование правил валидации","path":"/docs/guide/cli/generator/generator","headings":["Использование правил валидации"],"excerpt":"Использование правил валидации **Примечание:** Нужны одновременно зависимость (для импортов proto) и плагин (для генерации кода), чтобы получить полноценную поддержку валидации.","content":"Использование правил валидации **Примечание:** Нужны одновременно зависимость (для импортов proto) и плагин (для генерации кода), чтобы получить полноценную поддержку валидации."},{"id":"cli/generator/generator::top::153","title":"Генератор","section":"Использование правил валидации","path":"/docs/guide/cli/generator/generator","headings":["Использование правил валидации"],"excerpt":"Использование правил валидации Так выглядят правила валидации в proto — сгенерированный код будет автоматически их применять:","content":"Использование правил валидации Так выглядят правила валидации в proto — сгенерированный код будет автоматически их применять:"},{"id":"cli/generator/generator::top::154","title":"Генератор","section":"Использование правил валидации","path":"/docs/guide/cli/generator/generator","headings":["Использование правил валидации"],"excerpt":"Использование правил валидации ```proto // proto/user.proto syntax = \"proto3\";","content":"Использование правил валидации ```proto // proto/user.proto syntax = \"proto3\";"},{"id":"cli/generator/generator::top::155","title":"Генератор","section":"Использование правил валидации","path":"/docs/guide/cli/generator/generator","headings":["Использование правил валидации"],"excerpt":"Использование правил валидации import \"validate/validate.proto\";","content":"Использование правил валидации import \"validate/validate.proto\";"},{"id":"cli/generator/generator::top::156","title":"Генератор","section":"Использование правил валидации","path":"/docs/guide/cli/generator/generator","headings":["Использование правил валидации"],"excerpt":"Использование правил валидации message User { string email = 1 [(validate.rules).string.email = true]; int32 age = 2 [(validate.rules).int32.gte = 0]; } ```","content":"Использование правил валидации message User { string email = 1 [(validate.rules).string.email = true]; int32 age = 2 [(validate.rules).int32.gte = 0]; } ```"},{"id":"cli/generator/generator::top::157","title":"Генератор","section":"Комплексная конфигурация с несколькими зависимостями","path":"/docs/guide/cli/generator/generator","headings":["Комплексная конфигурация с несколькими зависимостями"],"excerpt":"Комплексная конфигурация с несколькими зависимостями Пример ниже показывает продакшен‑конфигурацию, объединяющую несколько зависимостей и плагины для полного цикла разработки API:","content":"Комплексная конфигурация с несколькими зависимостями Пример ниже показывает продакшен‑конфигурацию, объединяющую несколько зависимостей и плагины для полного цикла разработки API:"},{"id":"cli/generator/generator::top::158","title":"Генератор","section":"Комплексная конфигурация с несколькими зависимостями","path":"/docs/guide/cli/generator/generator","headings":["Комплексная конфигурация с несколькими зависимостями"],"excerpt":"Комплексная конфигурация с несколькими зависимостями ```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 HT","content":"Комплексная конфигурация с несколькими зависимостями ```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::top::159","title":"Генератор","section":"Комплексная конфигурация с несколькими зависимостями","path":"/docs/guide/cli/generator/generator","headings":["Комплексная конфигурация с несколькими зависимостями"],"excerpt":"Комплексная конфигурация с несколькими зависимостями generate: inputs: - directory: \"api/proto\" plugins: # Go code generation - Core protobuf structures - name: go out: ./gen/go opts: paths: source_relative module: githu","content":"Комплексная конфигурация с несколькими зависимостями 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::top::160","title":"Генератор","section":"Интеграция с кешем зависимостей","path":"/docs/guide/cli/generator/generator","headings":["Интеграция с кешем зависимостей"],"excerpt":"Интеграция с кешем зависимостей Генератор использует модульный кеш EasyP для ускорения сборок:","content":"Интеграция с кешем зависимостей Генератор использует модульный кеш EasyP для ускорения сборок:"},{"id":"cli/generator/generator::top::161","title":"Генератор","section":"Интеграция с кешем зависимостей","path":"/docs/guide/cli/generator/generator","headings":["Интеграция с кешем зависимостей"],"excerpt":"Интеграция с кешем зависимостей ```bash Download dependencies once easyp mod download","content":"Интеграция с кешем зависимостей ```bash Download dependencies once easyp mod download"},{"id":"cli/generator/generator::top::162","title":"Генератор","section":"Интеграция с кешем зависимостей","path":"/docs/guide/cli/generator/generator","headings":["Интеграция с кешем зависимостей"],"excerpt":"Интеграция с кешем зависимостей Generate code (uses cached dependencies) easyp generate","content":"Интеграция с кешем зависимостей Generate code (uses cached dependencies) easyp generate"},{"id":"cli/generator/generator::top::163","title":"Генератор","section":"Интеграция с кешем зависимостей","path":"/docs/guide/cli/generator/generator","headings":["Интеграция с кешем зависимостей"],"excerpt":"Интеграция с кешем зависимостей Dependencies are cached in ~/.easyp/mod/ ls ~/.easyp/mod/github.com/googleapis/googleapis/ ```","content":"Интеграция с кешем зависимостей Dependencies are cached in ~/.easyp/mod/ ls ~/.easyp/mod/github.com/googleapis/googleapis/ ```"},{"id":"cli/generator/generator::top::164","title":"Генератор","section":"Удалённая генерация","path":"/docs/guide/cli/generator/generator","headings":["Удалённая генерация"],"excerpt":"Удалённая генерация Удалённая генерация — мощная возможность, позволяющая генерировать код из proto‑файлов в удалённых Git‑репозиториях без локального checkout. Это поддерживает микросервисную архитектуру, где команды ис","content":"Удалённая генерация Удалённая генерация — мощная возможность, позволяющая генерировать код из proto‑файлов в удалённых Git‑репозиториях без локального checkout. Это поддерживает микросервисную архитектуру, где команды используют API друг друга без жёсткой связки."},{"id":"cli/generator/generator::top::165","title":"Генератор","section":"Удалённая генерация","path":"/docs/guide/cli/generator/generator","headings":["Удалённая генерация"],"excerpt":"Удалённая генерация **Преимущества:** **Развязка разработки**: Команды развиваются независимо, используя версии API друг друга **Контроль версий**: Фиксация внешних API гарантирует стабильность **Меньше размер репозитори","content":"Удалённая генерация **Преимущества:** **Развязка разработки**: Команды развиваются независимо, используя версии API друг друга **Контроль версий**: Фиксация внешних API гарантирует стабильность **Меньше размер репозитория**: Нет необходимости в vendoring/submodule внешних proto **Автоматические обновления**: Легко перейти на новую версию по готовности"},{"id":"cli/generator/generator::top::166","title":"Генератор","section":"Удалённая генерация","path":"/docs/guide/cli/generator/generator","headings":["Удалённая генерация"],"excerpt":"Удалённая генерация **Рекомендации:** В продакшене используйте только тегированные версии В разработке можно тестировать latest, но в проде фиксируйте При наличии используйте семантическое версионирование Учитывайте сете","content":"Удалённая генерация **Рекомендации:** В продакшене используйте только тегированные версии В разработке можно тестировать latest, но в проде фиксируйте При наличии используйте семантическое версионирование Учитывайте сетевые ограничения в CI/CD"},{"id":"cli/generator/generator::proto::167","title":"Генератор","section":"Источники удалённых proto","path":"/docs/guide/cli/generator/generator#proto","headings":["Источники удалённых proto"],"excerpt":"Источники удалённых proto Генерация напрямую из удалённых репозиториев — полезно в микросервисной архитектуре, где разные команды владеют разными proto.","content":"Источники удалённых proto Генерация напрямую из удалённых репозиториев — полезно в микросервисной архитектуре, где разные команды владеют разными proto."},{"id":"cli/generator/generator::proto::168","title":"Генератор","section":"Источники удалённых proto","path":"/docs/guide/cli/generator/generator#proto","headings":["Источники удалённых proto"],"excerpt":"Источники удалённых proto **Типовой workflow:** Команда A публикует proto с версиями в Git Команда B добавляет их в свой easyp.yaml При генерации EasyP скачивает и подключает удалённые proto Сгенерированный код содержит ","content":"Источники удалённых proto **Типовой workflow:** Команда A публикует proto с версиями в Git Команда B добавляет их в свой easyp.yaml При генерации EasyP скачивает и подключает удалённые proto Сгенерированный код содержит клиентские библиотеки сервисов команды A"},{"id":"cli/generator/generator::proto::169","title":"Генератор","section":"Источники удалённых proto","path":"/docs/guide/cli/generator/generator#proto","headings":["Источники удалённых proto"],"excerpt":"Источники удалённых proto Практический пример объединения локальных и удалённых источников в одной конфигурации генерации:","content":"Источники удалённых proto Практический пример объединения локальных и удалённых источников в одной конфигурации генерации:"},{"id":"cli/generator/generator::top::170","title":"Генератор","section":"Сценарии использования удалённой генерации","path":"/docs/guide/cli/generator/generator","headings":["Сценарии использования удалённой генерации"],"excerpt":"Сценарии использования удалённой генерации Примеры ниже показывают реальные ситуации, где удалённая генерация даёт ощутимую выгоду.","content":"Сценарии использования удалённой генерации Примеры ниже показывают реальные ситуации, где удалённая генерация даёт ощутимую выгоду."},{"id":"cli/generator/generator::multi-team-development::171","title":"Генератор","section":"Много команд (Multi-Team Development)","path":"/docs/guide/cli/generator/generator#multi-team-development","headings":["Много команд (Multi-Team Development)"],"excerpt":"Много команд (Multi-Team Development) Мультикомандная разработка особенно выигрывает: вместо координации общих репозиториев и сложного управления зависимостями — независимая эволюция API с контролируемыми обновлениями че","content":"Много команд (Multi-Team Development) Мультикомандная разработка особенно выигрывает: вместо координации общих репозиториев и сложного управления зависимостями — независимая эволюция API с контролируемыми обновлениями через версии."},{"id":"cli/generator/generator::multi-team-development::172","title":"Генератор","section":"Много команд (Multi-Team Development)","path":"/docs/guide/cli/generator/generator#multi-team-development","headings":["Много команд (Multi-Team Development)"],"excerpt":"Много команд (Multi-Team Development) Паттерн ценен в крупных организациях, где: Команды имеют разные циклы релизов и скорости разработки Владение API определено, потребление — массовое Нужно избежать overhead от координ","content":"Много команд (Multi-Team Development) Паттерн ценен в крупных организациях, где: Команды имеют разные циклы релизов и скорости разработки Владение API определено, потребление — массовое Нужно избежать overhead от координации общих proto репозиториев Команды используют разные стеки, но должны взаимодействовать"},{"id":"cli/generator/generator::multi-team-development::173","title":"Генератор","section":"Много команд (Multi-Team Development)","path":"/docs/guide/cli/generator/generator#multi-team-development","headings":["Много команд (Multi-Team Development)"],"excerpt":"Много команд (Multi-Team Development)","content":"Много команд (Multi-Team Development)"},{"id":"cli/generator/generator::api::174","title":"Генератор","section":"Интеграция с API вендоров","path":"/docs/guide/cli/generator/generator#api","headings":["Интеграция с API вендоров"],"excerpt":"Интеграция с API вендоров Многие вендоры публикуют proto для своих API, позволяя генерировать типобезопасных клиентов вместо ручных HTTP реализаций. Это повышает типовую строгость, автоматизирует сериализацию и часто уск","content":"Интеграция с API вендоров Многие вендоры публикуют proto для своих API, позволяя генерировать типобезопасных клиентов вместо ручных HTTP реализаций. Это повышает типовую строгость, автоматизирует сериализацию и часто ускоряет работу."},{"id":"cli/generator/generator::api::175","title":"Генератор","section":"Интеграция с API вендоров","path":"/docs/guide/cli/generator/generator#api","headings":["Интеграция с API вендоров"],"excerpt":"Интеграция с API вендоров Преимущества использования proto от вендоров: **Type safety**: Проверка типов на этапе компиляции **Automatic updates**: Новые возможности приходят с обновлением версии **Consistency**: Единые п","content":"Интеграция с API вендоров Преимущества использования proto от вендоров: **Type safety**: Проверка типов на этапе компиляции **Automatic updates**: Новые возможности приходят с обновлением версии **Consistency**: Единые паттерны интерфейсов между интеграциями **Performance**: Бинарная сериализация быстрее JSON **Documentation**: Proto выступают источником истины для API"},{"id":"cli/generator/generator::top::176","title":"Генератор","section":"Команды","path":"/docs/guide/cli/generator/generator","headings":["Команды"],"excerpt":"Команды CLI EasyP предоставляет гибкие варианты запуска генерации с разными конфигурациями и окружениями.","content":"Команды CLI EasyP предоставляет гибкие варианты запуска генерации с разными конфигурациями и окружениями."},{"id":"cli/generator/generator::top::177","title":"Генератор","section":"Базовая генерация","path":"/docs/guide/cli/generator/generator","headings":["Базовая генерация"],"excerpt":"Базовая генерация Ниже наиболее часто применяемые варианты команд для разработки и продакшена:","content":"Базовая генерация Ниже наиболее часто применяемые варианты команд для разработки и продакшена:"},{"id":"cli/generator/generator::top::178","title":"Генератор","section":"Базовая генерация","path":"/docs/guide/cli/generator/generator","headings":["Базовая генерация"],"excerpt":"Базовая генерация ```bash Use default easyp.yaml configuration - Most common for development easyp generate","content":"Базовая генерация ```bash Use default easyp.yaml configuration - Most common for development easyp generate"},{"id":"cli/generator/generator::top::179","title":"Генератор","section":"Базовая генерация","path":"/docs/guide/cli/generator/generator","headings":["Базовая генерация"],"excerpt":"Базовая генерация Use custom configuration file - Essential for multi-environment setups easyp --cfg production.easyp.yaml generate","content":"Базовая генерация Use custom configuration file - Essential for multi-environment setups easyp --cfg production.easyp.yaml generate"},{"id":"cli/generator/generator::top::180","title":"Генератор","section":"Базовая генерация","path":"/docs/guide/cli/generator/generator","headings":["Базовая генерация"],"excerpt":"Базовая генерация Generate with debug logs - Helpful for debugging and CI/CD easyp --debug generate","content":"Базовая генерация Generate with debug logs - Helpful for debugging and CI/CD easyp --debug generate"},{"id":"cli/generator/generator::top::181","title":"Генератор","section":"Базовая генерация","path":"/docs/guide/cli/generator/generator","headings":["Базовая генерация"],"excerpt":"Базовая генерация Generate with custom cache location - Useful for CI systems or shared environments EASYPPATH=/tmp/easyp-cache easyp generate ```","content":"Базовая генерация Generate with custom cache location - Useful for CI systems or shared environments EASYPPATH=/tmp/easyp-cache easyp generate ```"},{"id":"cli/generator/generator::top::182","title":"Генератор","section":"Интеграция с менеджером пакетов","path":"/docs/guide/cli/generator/generator","headings":["Интеграция с менеджером пакетов"],"excerpt":"Интеграция с менеджером пакетов Интеграция с менеджером пакетов позволяет либо явно управлять зависимостями, либо поручить это генератору. Явный путь даёт больше контроля, автоматический — больше удобства:","content":"Интеграция с менеджером пакетов Интеграция с менеджером пакетов позволяет либо явно управлять зависимостями, либо поручить это генератору. Явный путь даёт больше контроля, автоматический — больше удобства:"},{"id":"cli/generator/generator::top::183","title":"Генератор","section":"Интеграция с менеджером пакетов","path":"/docs/guide/cli/generator/generator","headings":["Интеграция с менеджером пакетов"],"excerpt":"Интеграция с менеджером пакетов ```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":"Интеграция с менеджером пакетов ```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::top::184","title":"Генератор","section":"Интеграция с менеджером пакетов","path":"/docs/guide/cli/generator/generator","headings":["Интеграция с менеджером пакетов"],"excerpt":"Интеграция с менеджером пакетов Automatic workflow - Convenient for development (generate downloads dependencies automatically) easyp generate ```","content":"Интеграция с менеджером пакетов Automatic workflow - Convenient for development (generate downloads dependencies automatically) easyp generate ```"},{"id":"cli/generator/generator::advanced-usage::185","title":"Генератор","section":"Расширенное использование (Advanced Usage)","path":"/docs/guide/cli/generator/generator#advanced-usage","headings":["Расширенное использование (Advanced Usage)"],"excerpt":"Расширенное использование (Advanced Usage) Эти варианты полезны для специфических сценариев деплоя, отладки или когда нужен более тонкий контроль процесса генерации:","content":"Расширенное использование (Advanced Usage) Эти варианты полезны для специфических сценариев деплоя, отладки или когда нужен более тонкий контроль процесса генерации:"},{"id":"cli/generator/generator::advanced-usage::186","title":"Генератор","section":"Расширенное использование (Advanced Usage)","path":"/docs/guide/cli/generator/generator#advanced-usage","headings":["Расширенное использование (Advanced Usage)"],"excerpt":"Расширенное использование (Advanced Usage) ```bash Генерация из конкретной директории (перекрывает настройку в файле конфигурации) easyp generate --path=./api/proto","content":"Расширенное использование (Advanced Usage) ```bash Генерация из конкретной директории (перекрывает настройку в файле конфигурации) easyp generate --path=./api/proto"},{"id":"cli/generator/generator::advanced-usage::187","title":"Генератор","section":"Расширенное использование (Advanced Usage)","path":"/docs/guide/cli/generator/generator#advanced-usage","headings":["Расширенное использование (Advanced Usage)"],"excerpt":"Расширенное использование (Advanced Usage) Генерация с vendored зависимостями (оффлайн / Docker контейнеры) easyp mod vendor easyp generate","content":"Расширенное использование (Advanced Usage) Генерация с vendored зависимостями (оффлайн / Docker контейнеры) easyp mod vendor easyp generate"},{"id":"cli/generator/generator::advanced-usage::188","title":"Генератор","section":"Расширенное использование (Advanced Usage)","path":"/docs/guide/cli/generator/generator#advanced-usage","headings":["Расширенное использование (Advanced Usage)"],"excerpt":"Расширенное использование (Advanced Usage) Генерация из кастомного project root (удобно для монореп и вложенных рабочих директорий) easyp generate --root=/usr/local/src/my-project --path=./api/proto ```","content":"Расширенное использование (Advanced Usage) Генерация из кастомного project root (удобно для монореп и вложенных рабочих директорий) easyp generate --root=/usr/local/src/my-project --path=./api/proto ```"},{"id":"cli/generator/generator::common-patterns::189","title":"Генератор","section":"Типовые паттерны (Common Patterns)","path":"/docs/guide/cli/generator/generator#common-patterns","headings":["Типовые паттерны (Common Patterns)"],"excerpt":"Типовые паттерны (Common Patterns) Эти схемы отражают реальные сценарии и лучшие практики организации генерации кода в разных структурах проектов.","content":"Типовые паттерны (Common Patterns) Эти схемы отражают реальные сценарии и лучшие практики организации генерации кода в разных структурах проектов."},{"id":"cli/generator/generator::multi-language-generation::190","title":"Генератор","section":"Мульти-языковая генерация (Multi-Language Generation)","path":"/docs/guide/cli/generator/generator#multi-language-generation","headings":["Мульти-языковая генерация (Multi-Language Generation)"],"excerpt":"Мульти-языковая генерация (Multi-Language Generation) Мульти-языковая генерация критична для компаний, использующих разные технологии в стеке. EasyP облегчает получение согласованных клиентских библиотек и типов для неск","content":"Мульти-языковая генерация (Multi-Language Generation) Мульти-языковая генерация критична для компаний, использующих разные технологии в стеке. EasyP облегчает получение согласованных клиентских библиотек и типов для нескольких языков из одного источника proto."},{"id":"cli/generator/generator::multi-language-generation::191","title":"Генератор","section":"Мульти-языковая генерация (Multi-Language Generation)","path":"/docs/guide/cli/generator/generator#multi-language-generation","headings":["Мульти-языковая генерация (Multi-Language Generation)"],"excerpt":"Мульти-языковая генерация (Multi-Language Generation) **Типовые сценарии:** **Full‑stack приложения**: backend на Go/Java + фронтенд на TypeScript **Платформы данных**: сервисы на Go + аналитика / ML на Python **Микросер","content":"Мульти-языковая генерация (Multi-Language Generation) **Типовые сценарии:** **Full‑stack приложения**: backend на Go/Java + фронтенд на TypeScript **Платформы данных**: сервисы на Go + аналитика / ML на Python **Микросервисы**: каждый сервис — оптимальный язык под задачу **Внешние SDK**: предоставление клиентских библиотек партнёрам **Интеграция с легаси**: современные gRPC сервисы + старые системы"},{"id":"cli/generator/generator::multi-language-generation::192","title":"Генератор","section":"Мульти-языковая генерация (Multi-Language Generation)","path":"/docs/guide/cli/generator/generator#multi-language-generation","headings":["Мульти-языковая генерация (Multi-Language Generation)"],"excerpt":"Мульти-языковая генерация (Multi-Language Generation) **Производительность:** Каждый плагин запускается отдельно — время растёт линейно от количества плагинов Для больших наборов используйте параллельный запуск (make -j4","content":"Мульти-языковая генерация (Multi-Language Generation) **Производительность:** Каждый плагин запускается отдельно — время растёт линейно от количества плагинов Для больших наборов используйте параллельный запуск (make -j4) Структурируйте выходные директории иерархически — меньше конфликтов Плагины имеют разную скорость — профилируйте сборку для поиска узких мест"},{"id":"cli/generator/generator::multi-language-generation::193","title":"Генератор","section":"Мульти-языковая генерация (Multi-Language Generation)","path":"/docs/guide/cli/generator/generator#multi-language-generation","headings":["Мульти-языковая генерация (Multi-Language Generation)"],"excerpt":"Мульти-языковая генерация (Multi-Language Generation) **Преимущества сопровождения:** Единый источник истины для API снижает риск расхождения схем Согласованные типы уменьшают интеграционные баги Автоматическая синхрониз","content":"Мульти-языковая генерация (Multi-Language Generation) **Преимущества сопровождения:** Единый источник истины для API снижает риск расхождения схем Согласованные типы уменьшают интеграционные баги Автоматическая синхронизация при изменении proto исключает ручные правки Меньше риска дрейфа API между реализациями на разных языках Рефакторинг упрощается — изменения транзитивно отражаются во всех артефактах"},{"id":"cli/generator/generator::multi-language-generation::194","title":"Генератор","section":"Мульти-языковая генерация (Multi-Language Generation)","path":"/docs/guide/cli/generator/generator#multi-language-generation","headings":["Мульти-языковая генерация (Multi-Language Generation)"],"excerpt":"Мульти-языковая генерация (Multi-Language Generation) Ниже пример типичной мульти-языковой конфигурации для full‑stack приложения: backend, веб‑клиент, аналитика и документация:","content":"Мульти-языковая генерация (Multi-Language Generation) Ниже пример типичной мульти-языковой конфигурации для full‑stack приложения: backend, веб‑клиент, аналитика и документация:"},{"id":"cli/generator/generator::multi-language-generation::195","title":"Генератор","section":"Мульти-языковая генерация (Multi-Language Generation)","path":"/docs/guide/cli/generator/generator#multi-language-generation","headings":["Мульти-языковая генерация (Multi-Language Generation)"],"excerpt":"Мульти-языковая генерация (Multi-Language Generation)","content":"Мульти-языковая генерация (Multi-Language Generation)"},{"id":"cli/generator/generator::multi-language-generation::196","title":"Генератор","section":"Мульти-языковая генерация (Multi-Language Generation)","path":"/docs/guide/cli/generator/generator#multi-language-generation","headings":["Мульти-языковая генерация (Multi-Language Generation)"],"excerpt":"Мульти-языковая генерация (Multi-Language Generation) **Совет по организации:** Используйте отдельные выходные директории для каждого языка, чтобы избежать конфликтов файлов и упростить интеграцию с языковыми сборочными ","content":"Мульти-языковая генерация (Multi-Language Generation) **Совет по организации:** Используйте отдельные выходные директории для каждого языка, чтобы избежать конфликтов файлов и упростить интеграцию с языковыми сборочными системами."},{"id":"cli/generator/generator::multi-language-generation::197","title":"Генератор","section":"Мульти-языковая генерация (Multi-Language Generation)","path":"/docs/guide/cli/generator/generator#multi-language-generation","headings":["Мульти-языковая генерация (Multi-Language Generation)"],"excerpt":"Мульти-языковая генерация (Multi-Language Generation) Генератор EasyP — комплексное решение для генерации кода из Protocol Buffers: от простой локальной разработки до сложных enterprise‑сценариев с удалёнными зависимостя","content":"Мульти-языковая генерация (Multi-Language Generation) Генератор EasyP — комплексное решение для генерации кода из Protocol Buffers: от простой локальной разработки до сложных enterprise‑сценариев с удалёнными зависимостями и мульти-языковым выводом."},{"id":"cli/linter/linter::proto::0","title":"Линтер","section":"Зачем нужен линтер для proto файлов?","path":"/docs/guide/cli/linter/linter#proto","headings":["Зачем нужен линтер для proto файлов?"],"excerpt":"Зачем нужен линтер для proto файлов? Линтеры играют ключевую роль в современной разработке, особенно когда речь о .proto файлах. Они обеспечивают единый стиль и структуру, помогают находить потенциальные ошибки на ранних","content":"Зачем нужен линтер для proto файлов? Линтеры играют ключевую роль в современной разработке, особенно когда речь о .proto файлах. Они обеспечивают единый стиль и структуру, помогают находить потенциальные ошибки на ранних этапах и поддерживают читаемость кода. Это даёт выгоды:"},{"id":"cli/linter/linter::proto::1","title":"Линтер","section":"Зачем нужен линтер для proto файлов?","path":"/docs/guide/cli/linter/linter#proto","headings":["Зачем нужен линтер для proto файлов?"],"excerpt":"Зачем нужен линтер для proto файлов? **Снижение затрат на разработку:** Ошибки ловятся раньше, меньше времени на отладку. **Улучшение командного взаимодействия:** Единообразный код легче понимать и сопровождать. **Бизнес","content":"Зачем нужен линтер для proto файлов? **Снижение затрат на разработку:** Ошибки ловятся раньше, меньше времени на отладку. **Улучшение командного взаимодействия:** Единообразный код легче понимать и сопровождать. **Бизнес-эффективность:** Более качественный код → меньше инцидентов в проде → ниже стоимость поддержки."},{"id":"cli/linter/linter::top::2","title":"Линтер","section":"Справочник по конфигурации","path":"/docs/guide/cli/linter/linter","headings":["Справочник по конфигурации"],"excerpt":"Справочник по конфигурации Конфигурация линтера настраивается в секции lint файла easyp.yaml.","content":"Справочник по конфигурации Конфигурация линтера настраивается в секции lint файла easyp.yaml."},{"id":"cli/linter/linter::use-string::3","title":"Линтер","section":"use ([]string)","path":"/docs/guide/cli/linter/linter#use-string","headings":["use ([]string)"],"excerpt":"use ([]string) Определяет набор правил или категорий для включения. Можно смешивать категории и конкретные правила.","content":"use ([]string) Определяет набор правил или категорий для включения. Можно смешивать категории и конкретные правила."},{"id":"cli/linter/linter::use-string::4","title":"Линтер","section":"use ([]string)","path":"/docs/guide/cli/linter/linter#use-string","headings":["use ([]string)"],"excerpt":"use ([]string) **Категории:** **MINIMAL**: Базовая согласованность пакетов **BASIC**: Соглашения по именованию и структуре **DEFAULT**: Рекомендованные правила для большинства проектов **COMMENTS**: Требования к коммента","content":"use ([]string) **Категории:** **MINIMAL**: Базовая согласованность пакетов **BASIC**: Соглашения по именованию и структуре **DEFAULT**: Рекомендованные правила для большинства проектов **COMMENTS**: Требования к комментариям **UNARY_RPC**: Ограничение на streaming RPC"},{"id":"cli/linter/linter::use-string::5","title":"Линтер","section":"use ([]string)","path":"/docs/guide/cli/linter/linter#use-string","headings":["use ([]string)"],"excerpt":"use ([]string) **Индивидуальные правила:** Любое имя правила (например ENUM_PASCAL_CASE, FIELD_LOWER_SNAKE_CASE)","content":"use ([]string) **Индивидуальные правила:** Любое имя правила (например ENUM_PASCAL_CASE, FIELD_LOWER_SNAKE_CASE)"},{"id":"cli/linter/linter::use-string::6","title":"Линтер","section":"use ([]string)","path":"/docs/guide/cli/linter/linter#use-string","headings":["use ([]string)"],"excerpt":"use ([]string) **Примеры:** ```yaml Только категории use: [MINIMAL, BASIC, DEFAULT]","content":"use ([]string) **Примеры:** ```yaml Только категории use: [MINIMAL, BASIC, DEFAULT]"},{"id":"cli/linter/linter::use-string::7","title":"Линтер","section":"use ([]string)","path":"/docs/guide/cli/linter/linter#use-string","headings":["use ([]string)"],"excerpt":"use ([]string) Смешивание use: - MINIMAL - COMMENT_SERVICE - COMMENT_RPC - ENUM_PASCAL_CASE","content":"use ([]string) Смешивание use: - MINIMAL - COMMENT_SERVICE - COMMENT_RPC - ENUM_PASCAL_CASE"},{"id":"cli/linter/linter::use-string::8","title":"Линтер","section":"use ([]string)","path":"/docs/guide/cli/linter/linter#use-string","headings":["use ([]string)"],"excerpt":"use ([]string) Точный набор use: - PACKAGE_DEFINED - SERVICE_PASCAL_CASE - FIELD_LOWER_SNAKE_CASE ```","content":"use ([]string) Точный набор use: - PACKAGE_DEFINED - SERVICE_PASCAL_CASE - FIELD_LOWER_SNAKE_CASE ```"},{"id":"cli/linter/linter::enum_zero_value_suffix-string::9","title":"Линтер","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) Обязывает нулевое значение enum иметь заданный суффикс.","content":"enum_zero_value_suffix (string) Обязывает нулевое значение enum иметь заданный суффикс."},{"id":"cli/linter/linter::enum_zero_value_suffix-string::10","title":"Линтер","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) **Обычно:** \"UNSPECIFIED\", \"UNKNOWN\", \"DEFAULT\"","content":"enum_zero_value_suffix (string) **Обычно:** \"UNSPECIFIED\", \"UNKNOWN\", \"DEFAULT\""},{"id":"cli/linter/linter::enum_zero_value_suffix-string::11","title":"Линтер","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)","content":"enum_zero_value_suffix (string)"},{"id":"cli/linter/linter::service_suffix-string::12","title":"Линтер","section":"service_suffix (string)","path":"/docs/guide/cli/linter/linter#service_suffix-string","headings":["service_suffix (string)"],"excerpt":"service_suffix (string) Требуемый суффикс для имён сервисов (унификация стиля).","content":"service_suffix (string) Требуемый суффикс для имён сервисов (унификация стиля)."},{"id":"cli/linter/linter::ignore-string::13","title":"Линтер","section":"ignore ([]string)","path":"/docs/guide/cli/linter/linter#ignore-string","headings":["ignore ([]string)"],"excerpt":"ignore ([]string) Полное исключение путей из линтинга.","content":"ignore ([]string) Полное исключение путей из линтинга."},{"id":"cli/linter/linter::ignore-string::14","title":"Линтер","section":"ignore ([]string)","path":"/docs/guide/cli/linter/linter#ignore-string","headings":["ignore ([]string)"],"excerpt":"ignore ([]string) **Use cases:** vendor / third_party сгенерированные файлы легаси подпакеты тестовые фикстуры","content":"ignore ([]string) **Use cases:** vendor / third_party сгенерированные файлы легаси подпакеты тестовые фикстуры"},{"id":"cli/linter/linter::except-string::15","title":"Линтер","section":"except ([]string)","path":"/docs/guide/cli/linter/linter#except-string","headings":["except ([]string)"],"excerpt":"except ([]string) Глобально отключает правила.","content":"except ([]string) Глобально отключает правила."},{"id":"cli/linter/linter::allow_comment_ignores-bool::16","title":"Линтер","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) Разрешает инлайн‑игнор правил комментариями.","content":"allow_comment_ignores (bool) Разрешает инлайн‑игнор правил комментариями."},{"id":"cli/linter/linter::ignore_only-mapstringstring::17","title":"Линтер","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) Таргетированное игнорирование конкретных правил для указанных путей.","content":"ignore_only (mapstringstring) Таргетированное игнорирование конкретных правил для указанных путей."},{"id":"cli/linter/linter::top::18","title":"Линтер","section":"Игнор правил комментариями","path":"/docs/guide/cli/linter/linter","headings":["Игнор правил комментариями"],"excerpt":"Игнор правил комментариями Если включён allow_comment_ignores, можно точечно отключать правила.","content":"Игнор правил комментариями Если включён allow_comment_ignores, можно точечно отключать правила."},{"id":"cli/linter/linter::top::19","title":"Линтер","section":"Несколько правил в одной строке","path":"/docs/guide/cli/linter/linter","headings":["Несколько правил в одной строке"],"excerpt":"Несколько правил в одной строке","content":"Несколько правил в одной строке"},{"id":"cli/linter/linter::top::20","title":"Линтер","section":"Используйте редко","path":"/docs/guide/cli/linter/linter","headings":["Используйте редко"],"excerpt":"Используйте редко Частое игнорирование = сигнал пересмотреть конфигурацию.","content":"Используйте редко Частое игнорирование = сигнал пересмотреть конфигурацию."},{"id":"cli/linter/linter::top::21","title":"Линтер","section":"Предпочитайте конфигурацию","path":"/docs/guide/cli/linter/linter","headings":["Предпочитайте конфигурацию"],"excerpt":"Предпочитайте конфигурацию Если нужно игнорировать правило в группе файлов — используйте ignore_only.","content":"Предпочитайте конфигурацию Если нужно игнорировать правило в группе файлов — используйте ignore_only."},{"id":"cli/linter/linter::top::22","title":"Линтер","section":"Категории линтера","path":"/docs/guide/cli/linter/linter","headings":["Категории линтера"],"excerpt":"Категории линтера Категории помогают быстро выбрать уровень строгости.","content":"Категории линтера Категории помогают быстро выбрать уровень строгости."},{"id":"cli/linter/linter::top::23","title":"Линтер","section":"Категории линтера","path":"/docs/guide/cli/linter/linter","headings":["Категории линтера"],"excerpt":"Категории линтера **Когда использовать:** **MINIMAL**: Минимальная базовая целостность **BASIC**: Частые соглашения имен **DEFAULT**: Дополнительные проверки качества **COMMENTS**: Обязательные комментарии (API, команды)","content":"Категории линтера **Когда использовать:** **MINIMAL**: Минимальная базовая целостность **BASIC**: Частые соглашения имен **DEFAULT**: Дополнительные проверки качества **COMMENTS**: Обязательные комментарии (API, команды) **UNARY_RPC**: Ограничить streaming RPC"},{"id":"cli/linter/linter::minimal::24","title":"Линтер","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::25","title":"Линтер","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::26","title":"Линтер","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::27","title":"Линтер","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::28","title":"Линтер","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::top::29","title":"Линтер","section":"Заключение","path":"/docs/guide/cli/linter/linter","headings":["Заключение"],"excerpt":"Заключение Внедрение EasyP линдера для ваших proto файлов заметно улучшит workflow, качество и поддерживаемость кода. Полная совместимость с Buf позволяет командам мигрировать без боли, используя гибкую конфигурацию и мо","content":"Заключение Внедрение EasyP линдера для ваших proto файлов заметно улучшит workflow, качество и поддерживаемость кода. Полная совместимость с Buf позволяет командам мигрировать без боли, используя гибкую конфигурацию и мощные возможности из коробки."},{"id":"cli/linter/rules/comment-enum-value::top::0","title":"COMMENT_ENUM_VALUE","path":"/docs/guide/cli/linter/rules/comment-enum-value","headings":[],"excerpt":"Это правило проверяет, что все значения enum имеют комментарий.","content":"Это правило проверяет, что все значения enum имеют комментарий."},{"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 ```proto syntax = \"proto3\";","content":"Good ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/comment-enum-value::good::4","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":"Это правило проверяет, что enum имеет комментарий.","content":"Это правило проверяет, что enum имеет комментарий."},{"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":"Это правило проверяет, что все поля сообщений имеют комментарий.","content":"Это правило проверяет, что все поля сообщений имеют комментарий."},{"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":"Это правило проверяет, что message имеет комментарий.","content":"Это правило проверяет, что message имеет комментарий."},{"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 ```proto syntax = \"proto3\";","content":"Bad ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/comment-message::bad::2","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::3","title":"COMMENT_MESSAGE","section":"Good","path":"/docs/guide/cli/linter/rules/comment-message#good","headings":["Good"],"excerpt":"Good ```proto syntax = \"proto3\";","content":"Good ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/comment-message::good::4","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":"Это правило проверяет, что oneof имеет комментарий.","content":"Это правило проверяет, что oneof имеет комментарий."},{"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":"Это правило проверяет, что сервис имеет комментарий.","content":"Это правило проверяет, что сервис имеет комментарий."},{"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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **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":"Это правило проверяет, что все файлы в заданной директории находятся в одном и том же package.","content":"Это правило проверяет, что все файлы в заданной директории находятся в одном и том же 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":"Это правило проверяет, что первое значение enum равно нулю.","content":"Это правило проверяет, что первое значение enum равно нулю."},{"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 ```proto syntax = \"proto3\";","content":"Bad ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/enum-first-value-zero::bad::3","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::4","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::5","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":"Это правило проверяет, что опция allow_alias не установлена в значение true внутри enum.","content":"Это правило проверяет, что опция allow_alias не установлена в значение true внутри 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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **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":"Это правило проверяет, что имена enum написаны в стиле PascalCase.","content":"Это правило проверяет, что имена enum написаны в стиле 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":"Это правило проверяет, что все значения enum имеют префикс, совпадающий с именем enum.","content":"Это правило проверяет, что все значения enum имеют префикс, совпадающий с именем enum."},{"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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **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":"Это правило проверяет, что значения enum записаны в стиле UPPER_SNAKE_CASE.","content":"Это правило проверяет, что значения enum записаны в стиле 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":"Это правило проверяет, что все нулевые значения enum имеют суффикс _NONE или ваш кастомный (пользовательский) суффикс.","content":"Это правило проверяет, что все нулевые значения enum имеют суффикс _NONE или ваш кастомный (пользовательский) суффикс."},{"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":"**MINIMAL** **BASIC** **DEFAULT**","content":"**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":"Это правило проверяет, что имена полей сообщений записаны в стиле lower_snake_case.","content":"Это правило проверяет, что имена полей сообщений записаны в стиле 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":"Это правило проверяет, что все файлы имеют имя в формате lower_snake_case (только строчные буквы, цифры и символ подчеркивания, без пробелов и заглавных букв).","content":"Это правило проверяет, что все файлы имеют имя в формате 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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **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":"Это правило проверяет, что в proto-файле не используются public импорты (оператор import public \"...\").","content":"Это правило проверяет, что в proto-файле не используются public импорты (оператор import public \"...\")."},{"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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **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":"Это правило проверяет, что в proto‑файле не используются weak‑импорты (import weak \"...\").","content":"Это правило проверяет, что в proto‑файле не используются weak‑импорты (import weak \"...\")."},{"id":"cli/linter/rules/import-no-weak::top::2","title":"IMPORT_NO_WEAK","path":"/docs/guide/cli/linter/rules/import-no-weak","headings":[],"excerpt":"Weak import (синтаксис import weak) допустим в proto2, но его использование усложняет анализ зависимостей и может приводить к неочевидным ошибкам при генерации кода. Рекомендуется всегда использовать обычный import.","content":"Weak import (синтаксис import weak) допустим в proto2, но его использование усложняет анализ зависимостей и может приводить к неочевидным ошибкам при генерации кода. Рекомендуется всегда использовать обычный import."},{"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 ```proto syntax = \"proto2\";","content":"Bad ```proto syntax = \"proto2\";"},{"id":"cli/linter/rules/import-no-weak::bad::4","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::5","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::6","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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **MINIMAL** **BASIC** **DEFAULT**"},{"id":"cli/linter/rules/import-used::top::1","title":"IMPORT_USED","path":"/docs/guide/cli/linter/rules/import-used","headings":[],"excerpt":"Это правило проверяет, что все импорты используются в proto-файле.","content":"Это правило проверяет, что все импорты используются в proto-файле."},{"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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **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":"Это правило проверяет, что имена сообщений (message) записаны в стиле PascalCase.","content":"Это правило проверяет, что имена сообщений (message) записаны в стиле 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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **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":"Это правило проверяет, что имена oneof записаны в стиле lower_snake_case.","content":"Это правило проверяет, что имена oneof записаны в стиле 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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **MINIMAL** **BASIC** **DEFAULT**"},{"id":"cli/linter/rules/package-defined::top::1","title":"PACKAGE_DEFINED","path":"/docs/guide/cli/linter/rules/package-defined","headings":[],"excerpt":"Это правило проверяет, что во всех файлах присутствует директива package.","content":"Это правило проверяет, что во всех файлах присутствует директива package."},{"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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **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":"Это правило проверяет, что все файлы находятся в директории, имя которой соответствует имени их пакета.","content":"Это правило проверяет, что все файлы находятся в директории, имя которой соответствует имени их пакета."},{"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":"Это правило проверяет, что имена package записаны в формате lower_snake_case (строчные буквы, при необходимости цифры и символ подчеркивания, без пробелов и заглавных букв).","content":"Это правило проверяет, что имена package записаны в формате 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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **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":"Это правило проверяет, что все файлы с заданным пакетом используют одно и то же пространство имён C# (csharp_namespace).","content":"Это правило проверяет, что все файлы с заданным пакетом используют одно и то же пространство имён C# (csharp_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\"; // [!code focus] ```","content":"Good option csharp_namespace = \"Foo.Bar\"; // [!code focus] ```"},{"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 ```proto // File: pkg/bar.proto","content":"Good ```proto // File: pkg/bar.proto"},{"id":"cli/linter/rules/package-same-csharp-namespace::good::9","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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **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":"Это правило проверяет, что все файлы с данным package находятся в одной директории.","content":"Это правило проверяет, что все файлы с данным package находятся в одной директории."},{"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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **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":"Это правило проверяет, что все файлы с одним и тем же package используют одно и то же значение опции go_package.","content":"Это правило проверяет, что все файлы с одним и тем же package используют одно и то же значение опции 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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **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":"Это правило проверяет, что все файлы с одним и тем же package используют одинаковое значение опции java_package.","content":"Это правило проверяет, что все файлы с одним и тем же package используют одинаковое значение опции 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 ```proto // File: pkg/bar.proto","content":"Bad ```proto // File: pkg/bar.proto"},{"id":"cli/linter/rules/package-same-java-multiple-files::bad::6","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::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 ```proto // File: pkg/foo.proto","content":"Good ```proto // File: pkg/foo.proto"},{"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 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::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 ```proto // File: pkg/bar.proto","content":"Good ```proto // File: pkg/bar.proto"},{"id":"cli/linter/rules/package-same-java-multiple-files::good::10","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":"Это правило проверяет, что все файлы с одним и тем же package используют одно и то же значение опции java_package.","content":"Это правило проверяет, что все файлы с одним и тем же package используют одно и то же значение опции 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":"Это правило проверяет, что все файлы с одним и тем же package используют одно и то же значение опции php_namespace.","content":"Это правило проверяет, что все файлы с одним и тем же package используют одно и то же значение опции 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":"Это правило проверяет, что все файлы с одним и тем же package используют один и тот же swift_prefix.","content":"Это правило проверяет, что все файлы с одним и тем же package используют один и тот же 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":"Это правило проверяет, что суффикс версии пакета имеет формат _vX, где X — числовая версия.","content":"Это правило проверяет, что суффикс версии пакета имеет формат _vX, где X — числовая версия."},{"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":"Это правило проверяет, что RPC не использует клиентский стриминг (запрос не является stream ...).","content":"Это правило проверяет, что RPC не использует клиентский стриминг (запрос не является stream ...)."},{"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":"Это правило проверяет, что RPC не использует серверный стриминг (ответ не является stream ...).","content":"Это правило проверяет, что RPC не использует серверный стриминг (ответ не является stream ...)."},{"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":"Это правило проверяет, что все имена RPC написаны в стиле PascalCase.","content":"Это правило проверяет, что все имена RPC написаны в стиле 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":"Это правило проверяет, что все сообщения запроса и ответа RPC уникальны: для каждого метода используются собственные (не переиспользуются одинаковые пары Request / Response у разных RPC).","content":"Это правило проверяет, что все сообщения запроса и ответа RPC уникальны: для каждого метода используются собственные (не переиспользуются одинаковые пары Request / Response у разных RPC)."},{"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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **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":"Это правило проверяет, что все сообщения запроса RPC названы в формате MethodRequest.","content":"Это правило проверяет, что все сообщения запроса RPC названы в формате 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":"Это правило проверяет, что все сообщения ответа RPC названы в формате MethodResponse.","content":"Это правило проверяет, что все сообщения ответа RPC названы в формате 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":"**MINIMAL** **BASIC** **DEFAULT**","content":"**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":"Это правило проверяет, что все имена сервисов написаны в стиле PascalCase.","content":"Это правило проверяет, что все имена сервисов написаны в стиле 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":"Это правило проверяет, что все сервисы имеют суффикс Service или ваш пользовательский суффикс.","content":"Это правило проверяет, что все сервисы имеют суффикс Service или ваш пользовательский суффикс."},{"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 против Buf: управление пакетами","path":"/docs/guide/cli/package-manager/easyp-vs-buf","headings":[],"excerpt":"EasyP против Buf: управление пакетами","content":"EasyP против Buf: управление пакетами"},{"id":"cli/package-manager/easyp-vs-buf::top::1","title":"EasyP против Buf: управление пакетами","path":"/docs/guide/cli/package-manager/easyp-vs-buf","headings":[],"excerpt":"Этот документ даёт подробное сравнение децентрализованного подхода EasyP к управлению пакетами и централизованной модели Buf через Buf Schema Registry (BSR), чтобы помочь понять ключевые различия и выбрать подходящее реш","content":"Этот документ даёт подробное сравнение децентрализованного подхода EasyP к управлению пакетами и централизованной модели Buf через Buf Schema Registry (BSR), чтобы помочь понять ключевые различия и выбрать подходящее решение для ваших задач."},{"id":"cli/package-manager/easyp-vs-buf::easyp-git::2","title":"EasyP против Buf: управление пакетами","section":"EasyP: децентрализованный подход на базе Git","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp-git","headings":["EasyP: децентрализованный подход на базе Git"],"excerpt":"EasyP: децентрализованный подход на базе Git","content":"EasyP: децентрализованный подход на базе Git"},{"id":"cli/package-manager/easyp-vs-buf::buf-bsr::3","title":"EasyP против Buf: управление пакетами","section":"Buf: централизованный реестр (BSR)","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf-bsr","headings":["Buf: централизованный реестр (BSR)"],"excerpt":"Buf: централизованный реестр (BSR)","content":"Buf: централизованный реестр (BSR)"},{"id":"cli/package-manager/easyp-vs-buf::top::4","title":"EasyP против Buf: управление пакетами","section":"Краткое резюме различий","path":"/docs/guide/cli/package-manager/easyp-vs-buf","headings":["Краткое резюме различий"],"excerpt":"Краткое резюме различий Аспект EasyP Buf -------- ------- ----- **Архитектура** Децентрализованная (Git) Централизованная (реестр BSR) **Источник зависимостей** Любой Git репозиторий Только модули BSR **Единая точка отка","content":"Краткое резюме различий Аспект EasyP Buf -------- ------- ----- **Архитектура** Децентрализованная (Git) Централизованная (реестр BSR) **Источник зависимостей** Любой Git репозиторий Только модули BSR **Единая точка отказа** Нет Да (buf.build) **Enterprise / air‑gapped** Полная поддержка Требует доступа к BSR или приватного BSR **Аутентификация** Git (SSH / HTTPS) Токены Buf + Git **Vendor lock‑in** Отсутствует Привязка к экосистеме Buf **Частные репозитории** Нативно через Git Нужно опубликовать в BSR **Оффлайн поддержка** Полная (через vendoring) Ограничена (кэшированные модули) **Стоимость** Бесплатно (использует существующий Git) Бесплатный тариф + платные планы **Сложность настройки** Минимальная Средняя (настройка BSR)"},{"id":"cli/package-manager/easyp-vs-buf::top::5","title":"EasyP против Buf: управление пакетами","section":"Подробное сравнение возможностей","path":"/docs/guide/cli/package-manager/easyp-vs-buf","headings":["Подробное сравнение возможностей"],"excerpt":"Подробное сравнение возможностей","content":"Подробное сравнение возможностей"},{"id":"cli/package-manager/easyp-vs-buf::1::6","title":"EasyP против Buf: управление пакетами","section":"1. Философия управления зависимостями","path":"/docs/guide/cli/package-manager/easyp-vs-buf#1","headings":["1. Философия управления зависимостями"],"excerpt":"Философия управления зависимостями","content":"Философия управления зависимостями"},{"id":"cli/package-manager/easyp-vs-buf::easyp-git::7","title":"EasyP против Buf: управление пакетами","section":"EasyP: «Любой Git репозиторий — это пакет»","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp-git","headings":["EasyP: «Любой Git репозиторий — это пакет»"],"excerpt":"EasyP: «Любой Git репозиторий — это пакет»","content":"EasyP: «Любой Git репозиторий — это пакет»"},{"id":"cli/package-manager/easyp-vs-buf::easyp-git::8","title":"EasyP против Buf: управление пакетами","section":"EasyP: «Любой Git репозиторий — это пакет»","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp-git","headings":["EasyP: «Любой Git репозиторий — это пакет»"],"excerpt":"EasyP: «Любой Git репозиторий — это пакет» **Преимущества:** ✅ Использование любого существующего репозитория сразу ✅ Не нужно «публиковать» в отдельный реестр ✅ Истинный источник версий — Git ✅ Работает с приватными сер","content":"EasyP: «Любой Git репозиторий — это пакет» **Преимущества:** ✅ Использование любого существующего репозитория сразу ✅ Не нужно «публиковать» в отдельный реестр ✅ Истинный источник версий — Git ✅ Работает с приватными серверами без доп. настроек"},{"id":"cli/package-manager/easyp-vs-buf::buf::9","title":"EasyP против Buf: управление пакетами","section":"Buf: «Сначала реестр»","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf","headings":["Buf: «Сначала реестр»"],"excerpt":"Buf: «Сначала реестр» **Преимущества:** ✅ Курируемые, проверенные модули ✅ Богатые метаданные и документация ✅ Визуализация графа зависимостей ✅ Принуждение семантического версионирования","content":"Buf: «Сначала реестр» **Преимущества:** ✅ Курируемые, проверенные модули ✅ Богатые метаданные и документация ✅ Визуализация графа зависимостей ✅ Принуждение семантического версионирования"},{"id":"cli/package-manager/easyp-vs-buf::buf::10","title":"EasyP против Buf: управление пакетами","section":"Buf: «Сначала реестр»","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf","headings":["Buf: «Сначала реестр»"],"excerpt":"Buf: «Сначала реестр» **Ограничения:** ❌ Нужно опубликовать в BSR перед использованием ❌ Требует аккаунт и аутентификацию ❌ Нельзя напрямую сослаться на произвольный Git репозиторий","content":"Buf: «Сначала реестр» **Ограничения:** ❌ Нужно опубликовать в BSR перед использованием ❌ Требует аккаунт и аутентификацию ❌ Нельзя напрямую сослаться на произвольный Git репозиторий"},{"id":"cli/package-manager/easyp-vs-buf::2-airgapped::11","title":"EasyP против Buf: управление пакетами","section":"2. Корпоративные и изолированные (air‑gapped) среды","path":"/docs/guide/cli/package-manager/easyp-vs-buf#2-airgapped","headings":["2. Корпоративные и изолированные (air‑gapped) среды"],"excerpt":"Корпоративные и изолированные (air‑gapped) среды","content":"Корпоративные и изолированные (air‑gapped) среды"},{"id":"cli/package-manager/easyp-vs-buf::easyp::12","title":"EasyP против Buf: управление пакетами","section":"EasyP: Полноценная оффлайн‑поддержка","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["EasyP: Полноценная оффлайн‑поддержка"],"excerpt":"EasyP: Полноценная оффлайн‑поддержка **Сценарий**: крупная компания со строгими сетевыми политиками","content":"EasyP: Полноценная оффлайн‑поддержка **Сценарий**: крупная компания со строгими сетевыми политиками"},{"id":"cli/package-manager/easyp-vs-buf::easyp::13","title":"EasyP против Buf: управление пакетами","section":"EasyP: Полноценная оффлайн‑поддержка","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["EasyP: Полноценная оффлайн‑поддержка"],"excerpt":"EasyP: Полноценная оффлайн‑поддержка ```bash Среда с доступом в интернет easyp mod download # Скачивает в ~/.easyp/ easyp mod vendor # Создает easyp_vendor/","content":"EasyP: Полноценная оффлайн‑поддержка ```bash Среда с доступом в интернет easyp mod download # Скачивает в ~/.easyp/ easyp mod vendor # Создает easyp_vendor/"},{"id":"cli/package-manager/easyp-vs-buf::easyp::14","title":"EasyP против Buf: управление пакетами","section":"EasyP: Полноценная оффлайн‑поддержка","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["EasyP: Полноценная оффлайн‑поддержка"],"excerpt":"EasyP: Полноценная оффлайн‑поддержка Перенос в изолированный сегмент tar -czf easyp-deps.tar.gz ~/.easyp easyp_vendor/ ... перенос архива ...","content":"EasyP: Полноценная оффлайн‑поддержка Перенос в изолированный сегмент tar -czf easyp-deps.tar.gz ~/.easyp easyp_vendor/ ... перенос архива ..."},{"id":"cli/package-manager/easyp-vs-buf::easyp::15","title":"EasyP против Buf: управление пакетами","section":"EasyP: Полноценная оффлайн‑поддержка","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["EasyP: Полноценная оффлайн‑поддержка"],"excerpt":"EasyP: Полноценная оффлайн‑поддержка В изолированной среде tar -xzf easyp-deps.tar.gz export EASYPPATH=$PWD/.easyp easyp generate # Работает оффлайн ```","content":"EasyP: Полноценная оффлайн‑поддержка В изолированной среде tar -xzf easyp-deps.tar.gz export EASYPPATH=$PWD/.easyp easyp generate # Работает оффлайн ```"},{"id":"cli/package-manager/easyp-vs-buf::easyp::16","title":"EasyP против Buf: управление пакетами","section":"EasyP: Полноценная оффлайн‑поддержка","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["EasyP: Полноценная оффлайн‑поддержка"],"excerpt":"EasyP: Полноценная оффлайн‑поддержка **Плюсы:** ✅ Не зависит от внешних сервисов ✅ Не нужен внутренний реестр ✅ Использует существующую Git инфраструктуру ✅ Простая файловая дистрибуция","content":"EasyP: Полноценная оффлайн‑поддержка **Плюсы:** ✅ Не зависит от внешних сервисов ✅ Не нужен внутренний реестр ✅ Использует существующую Git инфраструктуру ✅ Простая файловая дистрибуция"},{"id":"cli/package-manager/easyp-vs-buf::buf::17","title":"EasyP против Buf: управление пакетами","section":"Buf: Требует инфраструктуру реестра","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf","headings":["Buf: Требует инфраструктуру реестра"],"excerpt":"Buf: Требует инфраструктуру реестра ```bash Вариант 1: использовать buf.build (нужен интернет) buf mod download","content":"Buf: Требует инфраструктуру реестра ```bash Вариант 1: использовать buf.build (нужен интернет) buf mod download"},{"id":"cli/package-manager/easyp-vs-buf::buf::18","title":"EasyP против Buf: управление пакетами","section":"Buf: Требует инфраструктуру реестра","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf","headings":["Buf: Требует инфраструктуру реестра"],"excerpt":"Buf: Требует инфраструктуру реестра Вариант 2: поднимать приватный BSR (сложно) Развернуть сервер реестра Перепубликовать все модули внутрь Настроить доступы, аутентификацию Поддерживать работоспособность ```","content":"Buf: Требует инфраструктуру реестра Вариант 2: поднимать приватный BSR (сложно) Развернуть сервер реестра Перепубликовать все модули внутрь Настроить доступы, аутентификацию Поддерживать работоспособность ```"},{"id":"cli/package-manager/easyp-vs-buf::buf::19","title":"EasyP против Buf: управление пакетами","section":"Buf: Требует инфраструктуру реестра","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf","headings":["Buf: Требует инфраструктуру реестра"],"excerpt":"Buf: Требует инфраструктуру реестра **Минусы:** ❌ Постоянный интернет или дорогой приватный BSR ❌ Сложная инфраструктура для частных установок ❌ Все модули нужно републиковать ❌ Дополнительные операционные затраты","content":"Buf: Требует инфраструктуру реестра **Минусы:** ❌ Постоянный интернет или дорогой приватный BSR ❌ Сложная инфраструктура для частных установок ❌ Все модули нужно републиковать ❌ Дополнительные операционные затраты"},{"id":"cli/package-manager/easyp-vs-buf::easyp::20","title":"EasyP против Buf: управление пакетами","section":"EasyP: Прямой контроль","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["EasyP: Прямой контроль"],"excerpt":"EasyP: Прямой контроль ```yaml Полный контроль источников deps: # Публичный репозиторий — ваша конкретная версия - github.com/googleapis/googleapis@common-protos-1_3_1","content":"EasyP: Прямой контроль ```yaml Полный контроль источников deps: # Публичный репозиторий — ваша конкретная версия - github.com/googleapis/googleapis@common-protos-1_3_1"},{"id":"cli/package-manager/easyp-vs-buf::easyp::21","title":"EasyP против Buf: управление пакетами","section":"EasyP: Прямой контроль","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["EasyP: Прямой контроль"],"excerpt":"EasyP: Прямой контроль Внутренний репозиторий - gitlab.company.com/security/validated-protos@v1.0.0","content":"EasyP: Прямой контроль Внутренний репозиторий - gitlab.company.com/security/validated-protos@v1.0.0"},{"id":"cli/package-manager/easyp-vs-buf::easyp::22","title":"EasyP против Buf: управление пакетами","section":"EasyP: Прямой контроль","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["EasyP: Прямой контроль"],"excerpt":"EasyP: Прямой контроль Точный коммит (горячий фикс) - github.com/bufbuild/protoc-gen-validate@abc123def456 ```","content":"EasyP: Прямой контроль Точный коммит (горячий фикс) - github.com/bufbuild/protoc-gen-validate@abc123def456 ```"},{"id":"cli/package-manager/easyp-vs-buf::easyp::23","title":"EasyP против Buf: управление пакетами","section":"EasyP: Прямой контроль","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["EasyP: Прямой контроль"],"excerpt":"EasyP: Прямой контроль **Преимущества по безопасности:** ✅ Нет посредника — берём из исходного репозитория ✅ Аудит через историю Git ✅ Нельзя «забанить» доступ извне ✅ Свои процессы сканирования / валидации ✅ Можно форкн","content":"EasyP: Прямой контроль **Преимущества по безопасности:** ✅ Нет посредника — берём из исходного репозитория ✅ Аудит через историю Git ✅ Нельзя «забанить» доступ извне ✅ Свои процессы сканирования / валидации ✅ Можно форкнуть и удерживать критические версии"},{"id":"cli/package-manager/easyp-vs-buf::buf::24","title":"EasyP против Buf: управление пакетами","section":"Buf: Зависимость от реестра","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf","headings":["Buf: Зависимость от реестра"],"excerpt":"Buf: Зависимость от реестра **Риски:** ⚠️ Посредник контролирует доступность ⚠️ Возможны ограничения / санкции на аккаунт ⚠️ Модуль могут удалить или депрекейтнуть ⚠️ Политики обновлений диктуются стороной ⚠️ Нужно довер","content":"Buf: Зависимость от реестра **Риски:** ⚠️ Посредник контролирует доступность ⚠️ Возможны ограничения / санкции на аккаунт ⚠️ Модуль могут удалить или депрекейтнуть ⚠️ Политики обновлений диктуются стороной ⚠️ Нужно доверять внешней безопасности"},{"id":"cli/package-manager/easyp-vs-buf::1::25","title":"EasyP против Buf: управление пакетами","section":"Сценарий 1: Стартап с публичными зависимостями","path":"/docs/guide/cli/package-manager/easyp-vs-buf#1","headings":["Сценарий 1: Стартап с публичными зависимостями"],"excerpt":"Сценарий 1: Стартап с публичными зависимостями **EasyP:**","content":"Сценарий 1: Стартап с публичными зависимостями **EasyP:**"},{"id":"cli/package-manager/easyp-vs-buf::1::26","title":"EasyP против Buf: управление пакетами","section":"Сценарий 1: Стартап с публичными зависимостями","path":"/docs/guide/cli/package-manager/easyp-vs-buf#1","headings":["Сценарий 1: Стартап с публичными зависимостями"],"excerpt":"Сценарий 1: Стартап с публичными зависимостями **Buf:**","content":"Сценарий 1: Стартап с публичными зависимостями **Buf:**"},{"id":"cli/package-manager/easyp-vs-buf::1::27","title":"EasyP против Buf: управление пакетами","section":"Сценарий 1: Стартап с публичными зависимостями","path":"/docs/guide/cli/package-manager/easyp-vs-buf#1","headings":["Сценарий 1: Стартап с публичными зависимостями"],"excerpt":"Сценарий 1: Стартап с публичными зависимостями **Итог:** Паритет — оба хорошо подходят для публичных пакетов.","content":"Сценарий 1: Стартап с публичными зависимостями **Итог:** Паритет — оба хорошо подходят для публичных пакетов."},{"id":"cli/package-manager/easyp-vs-buf::2::28","title":"EasyP против Buf: управление пакетами","section":"Сценарий 2: Компания со смешанными публичными/приватными зависимостями","path":"/docs/guide/cli/package-manager/easyp-vs-buf#2","headings":["Сценарий 2: Компания со смешанными публичными/приватными зависимостями"],"excerpt":"Сценарий 2: Компания со смешанными публичными/приватными зависимостями **EasyP:**","content":"Сценарий 2: Компания со смешанными публичными/приватными зависимостями **EasyP:**"},{"id":"cli/package-manager/easyp-vs-buf::2::29","title":"EasyP против Buf: управление пакетами","section":"Сценарий 2: Компания со смешанными публичными/приватными зависимостями","path":"/docs/guide/cli/package-manager/easyp-vs-buf#2","headings":["Сценарий 2: Компания со смешанными публичными/приватными зависимостями"],"excerpt":"Сценарий 2: Компания со смешанными публичными/приватными зависимостями **Buf:**","content":"Сценарий 2: Компания со смешанными публичными/приватными зависимостями **Buf:**"},{"id":"cli/package-manager/easyp-vs-buf::2::30","title":"EasyP против Buf: управление пакетами","section":"Сценарий 2: Компания со смешанными публичными/приватными зависимостями","path":"/docs/guide/cli/package-manager/easyp-vs-buf#2","headings":["Сценарий 2: Компания со смешанными публичными/приватными зависимостями"],"excerpt":"Сценарий 2: Компания со смешанными публичными/приватными зависимостями **Итог:** **EasyP** — не требует публикации внутрь BSR.","content":"Сценарий 2: Компания со смешанными публичными/приватными зависимостями **Итог:** **EasyP** — не требует публикации внутрь BSR."},{"id":"cli/package-manager/easyp-vs-buf::3-airgap::31","title":"EasyP против Buf: управление пакетами","section":"Сценарий 3: Государственный / оборонный подрядчик (полный air‑gap)","path":"/docs/guide/cli/package-manager/easyp-vs-buf#3-airgap","headings":["Сценарий 3: Государственный / оборонный подрядчик (полный air‑gap)"],"excerpt":"Сценарий 3: Государственный / оборонный подрядчик (полный air‑gap) **EasyP:**","content":"Сценарий 3: Государственный / оборонный подрядчик (полный air‑gap) **EasyP:**"},{"id":"cli/package-manager/easyp-vs-buf::3-airgap::32","title":"EasyP против Buf: управление пакетами","section":"Сценарий 3: Государственный / оборонный подрядчик (полный air‑gap)","path":"/docs/guide/cli/package-manager/easyp-vs-buf#3-airgap","headings":["Сценарий 3: Государственный / оборонный подрядчик (полный air‑gap)"],"excerpt":"Сценарий 3: Государственный / оборонный подрядчик (полный air‑gap) **Buf:**","content":"Сценарий 3: Государственный / оборонный подрядчик (полный air‑gap) **Buf:**"},{"id":"cli/package-manager/easyp-vs-buf::3-airgap::33","title":"EasyP против Buf: управление пакетами","section":"Сценарий 3: Государственный / оборонный подрядчик (полный air‑gap)","path":"/docs/guide/cli/package-manager/easyp-vs-buf#3-airgap","headings":["Сценарий 3: Государственный / оборонный подрядчик (полный air‑gap)"],"excerpt":"Сценарий 3: Государственный / оборонный подрядчик (полный air‑gap) **Итог:** **EasyP** — значительно проще.","content":"Сценарий 3: Государственный / оборонный подрядчик (полный air‑gap) **Итог:** **EasyP** — значительно проще."},{"id":"cli/package-manager/easyp-vs-buf::4::34","title":"EasyP против Buf: управление пакетами","section":"Сценарий 4: Комплаенс и аудит","path":"/docs/guide/cli/package-manager/easyp-vs-buf#4","headings":["Сценарий 4: Комплаенс и аудит"],"excerpt":"Сценарий 4: Комплаенс и аудит **EasyP:** ✅ Прямой аудит изменений (коммиты) ✅ Нет внешних точек зависимости в проде ✅ Повторяемость через фиксированные коммиты / vendor ✅ Управление уязвимостями — в ваших руках","content":"Сценарий 4: Комплаенс и аудит **EasyP:** ✅ Прямой аудит изменений (коммиты) ✅ Нет внешних точек зависимости в проде ✅ Повторяемость через фиксированные коммиты / vendor ✅ Управление уязвимостями — в ваших руках"},{"id":"cli/package-manager/easyp-vs-buf::4::35","title":"EasyP против Buf: управление пакетами","section":"Сценарий 4: Комплаенс и аудит","path":"/docs/guide/cli/package-manager/easyp-vs-buf#4","headings":["Сценарий 4: Комплаенс и аудит"],"excerpt":"Сценарий 4: Комплаенс и аудит **Buf:** ⚠️ Нужно учитывать BSR в области аудита ⚠️ Дополнительный риск третьей стороны ⚠️ Модули — внешние контролируемые артефакты ⚠️ Сложнее трассировать от реестра к исходникам","content":"Сценарий 4: Комплаенс и аудит **Buf:** ⚠️ Нужно учитывать BSR в области аудита ⚠️ Дополнительный риск третьей стороны ⚠️ Модули — внешние контролируемые артефакты ⚠️ Сложнее трассировать от реестра к исходникам"},{"id":"cli/package-manager/easyp-vs-buf::4::36","title":"EasyP против Buf: управление пакетами","section":"Сценарий 4: Комплаенс и аудит","path":"/docs/guide/cli/package-manager/easyp-vs-buf#4","headings":["Сценарий 4: Комплаенс и аудит"],"excerpt":"Сценарий 4: Комплаенс и аудит **Итог:** **EasyP** — проще для комплаенса.","content":"Сценарий 4: Комплаенс и аудит **Итог:** **EasyP** — проще для комплаенса."},{"id":"cli/package-manager/easyp-vs-buf::easyp::37","title":"EasyP против Buf: управление пакетами","section":"EasyP: Нулевая дополнительная инфраструктура","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["EasyP: Нулевая дополнительная инфраструктура"],"excerpt":"EasyP: Нулевая дополнительная инфраструктура **Затраты:** ✅ $0 — используете существующий Git ✅ Нет дополнительных сервисов/серверов ✅ Нет лицензирования ✅ Масштабирование в рамках Git","content":"EasyP: Нулевая дополнительная инфраструктура **Затраты:** ✅ $0 — используете существующий Git ✅ Нет дополнительных сервисов/серверов ✅ Нет лицензирования ✅ Масштабирование в рамках Git"},{"id":"cli/package-manager/easyp-vs-buf::easyp::38","title":"EasyP против Buf: управление пакетами","section":"EasyP: Нулевая дополнительная инфраструктура","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["EasyP: Нулевая дополнительная инфраструктура"],"excerpt":"EasyP: Нулевая дополнительная инфраструктура **Инфраструктура:** Использует текущие репозитории (GitHub/GitLab/и т.д.) Аутентификация — штатная Резервирование/DR — как уже настроено для Git","content":"EasyP: Нулевая дополнительная инфраструктура **Инфраструктура:** Использует текущие репозитории (GitHub/GitLab/и т.д.) Аутентификация — штатная Резервирование/DR — как уже настроено для Git"},{"id":"cli/package-manager/easyp-vs-buf::buf::39","title":"EasyP против Buf: управление пакетами","section":"Buf: Затраты на реестр","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf","headings":["Buf: Затраты на реестр"],"excerpt":"Buf: Затраты на реестр **Hosted BSR (buf.build):** ✅ Бесплатный уровень ❌ Платные тарифы для приватного и расширенного использования ❌ Потенциальные изменения ценовой политики ❌ Вопросы локализации данных","content":"Buf: Затраты на реестр **Hosted BSR (buf.build):** ✅ Бесплатный уровень ❌ Платные тарифы для приватного и расширенного использования ❌ Потенциальные изменения ценовой политики ❌ Вопросы локализации данных"},{"id":"cli/package-manager/easyp-vs-buf::buf::40","title":"EasyP против Buf: управление пакетами","section":"Buf: Затраты на реестр","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf","headings":["Buf: Затраты на реестр"],"excerpt":"Buf: Затраты на реестр **Приватный BSR:** ❌ Серверы, БД, балансировка ❌ Мониторинг, обновления, бэкапы ❌ Лицензирование enterprise функционала ❌ Доп. планирование отказоустойчивости","content":"Buf: Затраты на реестр **Приватный BSR:** ❌ Серверы, БД, балансировка ❌ Мониторинг, обновления, бэкапы ❌ Лицензирование enterprise функционала ❌ Доп. планирование отказоустойчивости"},{"id":"cli/package-manager/easyp-vs-buf::easyp::41","title":"EasyP против Buf: управление пакетами","section":"EasyP: Нет привязки","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["EasyP: Нет привязки"],"excerpt":"EasyP: Нет привязки **Миграция ИЗ EasyP:** (Обычные Git ссылки — легко перенести в другой инструмент.)","content":"EasyP: Нет привязки **Миграция ИЗ EasyP:** (Обычные Git ссылки — легко перенести в другой инструмент.)"},{"id":"cli/package-manager/easyp-vs-buf::easyp::42","title":"EasyP против Buf: управление пакетами","section":"EasyP: Нет привязки","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["EasyP: Нет привязки"],"excerpt":"EasyP: Нет привязки **Миграция В EasyP:**","content":"EasyP: Нет привязки **Миграция В EasyP:**"},{"id":"cli/package-manager/easyp-vs-buf::buf-lockin::43","title":"EasyP против Buf: управление пакетами","section":"Buf: Потенциальный lock‑in","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf-lockin","headings":["Buf: Потенциальный lock‑in"],"excerpt":"Buf: Потенциальный lock‑in **Миграция ИЗ Buf:** ❌ Нужно сопоставить BSR модули с исходными Git репо ❌ Имена модулей BSR не совпадают с URL ❌ Возможна потеря удобных метаданных ❌ Сложно при глубокой интеграции с BSR","content":"Buf: Потенциальный lock‑in **Миграция ИЗ Buf:** ❌ Нужно сопоставить BSR модули с исходными Git репо ❌ Имена модулей BSR не совпадают с URL ❌ Возможна потеря удобных метаданных ❌ Сложно при глубокой интеграции с BSR"},{"id":"cli/package-manager/easyp-vs-buf::buf-lockin::44","title":"EasyP против Buf: управление пакетами","section":"Buf: Потенциальный lock‑in","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf-lockin","headings":["Buf: Потенциальный lock‑in"],"excerpt":"Buf: Потенциальный lock‑in **Миграция В Buf:** ❌ Нужно опубликовать всё в BSR ❌ Нельзя ссылаться напрямую на Git ❌ Принять workflow BSR (push/pull модулей)","content":"Buf: Потенциальный lock‑in **Миграция В Buf:** ❌ Нужно опубликовать всё в BSR ❌ Нельзя ссылаться напрямую на Git ❌ Принять workflow BSR (push/pull модулей)"},{"id":"cli/package-manager/easyp-vs-buf::easyp::45","title":"EasyP против Buf: управление пакетами","section":"Выберите EasyP, если:","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["Выберите EasyP, если:"],"excerpt":"Выберите EasyP, если: ✅ **Air‑gapped / закрытые среды** Нужна работа без внешних сервисов Строгий комплаенс / контроль цепочки поставок","content":"Выберите EasyP, если: ✅ **Air‑gapped / закрытые среды** Нужна работа без внешних сервисов Строгий комплаенс / контроль цепочки поставок"},{"id":"cli/package-manager/easyp-vs-buf::easyp::46","title":"EasyP против Buf: управление пакетами","section":"Выберите EasyP, если:","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["Выберите EasyP, если:"],"excerpt":"Выберите EasyP, если: ✅ **Фокус на безопасности** Контроль источников зависимостей Минимизация рисков третьих сторон","content":"Выберите EasyP, если: ✅ **Фокус на безопасности** Контроль источников зависимостей Минимизация рисков третьих сторон"},{"id":"cli/package-manager/easyp-vs-buf::easyp::47","title":"EasyP против Buf: управление пакетами","section":"Выберите EasyP, если:","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["Выберите EasyP, если:"],"excerpt":"Выберите EasyP, если: ✅ **Git‑центричная культура** Частные репозитории — норма Не хотите добавлять новый ключевой сервис","content":"Выберите EasyP, если: ✅ **Git‑центричная культура** Частные репозитории — норма Не хотите добавлять новый ключевой сервис"},{"id":"cli/package-manager/easyp-vs-buf::easyp::48","title":"EasyP против Buf: управление пакетами","section":"Выберите EasyP, если:","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["Выберите EasyP, если:"],"excerpt":"Выберите EasyP, если: ✅ **Ограниченный бюджет** Минимизация операционных расходов Предсказуемая стоимость = 0","content":"Выберите EasyP, если: ✅ **Ограниченный бюджет** Минимизация операционных расходов Предсказуемая стоимость = 0"},{"id":"cli/package-manager/easyp-vs-buf::easyp::49","title":"EasyP против Buf: управление пакетами","section":"Выберите EasyP, если:","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["Выберите EasyP, если:"],"excerpt":"Выберите EasyP, если: ✅ **Смешанные публичные/частные зависимости** Не хотите перекладывать всё в реестр Нужна гибкость форматов и размещения","content":"Выберите EasyP, если: ✅ **Смешанные публичные/частные зависимости** Не хотите перекладывать всё в реестр Нужна гибкость форматов и размещения"},{"id":"cli/package-manager/easyp-vs-buf::buf::50","title":"EasyP против Buf: управление пакетами","section":"Выберите Buf, если:","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf","headings":["Выберите Buf, если:"],"excerpt":"Выберите Buf, если: ✅ **Глубокая интеграция в экосистему BSR** Уже используете линтеры / генерацию Buf Нужны курируемые официальные модули Важны метаданные и граф зависимостей","content":"Выберите Buf, если: ✅ **Глубокая интеграция в экосистему BSR** Уже используете линтеры / генерацию Buf Нужны курируемые официальные модули Важны метаданные и граф зависимостей"},{"id":"cli/package-manager/easyp-vs-buf::buf::51","title":"EasyP против Buf: управление пакетами","section":"Выберите Buf, если:","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf","headings":["Выберите Buf, если:"],"excerpt":"Выберите Buf, если: ✅ **Сотрудничество и открытая разработка** Централизованное обнаружение модулей Совместная работа над общими пакетами","content":"Выберите Buf, если: ✅ **Сотрудничество и открытая разработка** Централизованное обнаружение модулей Совместная работа над общими пакетами"},{"id":"cli/package-manager/easyp-vs-buf::buf::52","title":"EasyP против Buf: управление пакетами","section":"Выберите Buf, если:","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf","headings":["Выберите Buf, если:"],"excerpt":"Выберите Buf, если: ✅ **Команда новичков в protobuf** Требуется «направляющая» структура Ценность документации внутри реестра","content":"Выберите Buf, если: ✅ **Команда новичков в protobuf** Требуется «направляющая» структура Ценность документации внутри реестра"},{"id":"cli/package-manager/easyp-vs-buf::buf::53","title":"EasyP против Buf: управление пакетами","section":"Выберите Buf, если:","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf","headings":["Выберите Buf, если:"],"excerpt":"Выберите Buf, если: ✅ **Небольшой набор публичных зависимостей** В основном используете популярные общие пакеты Вас устраивает зависимость от BSR","content":"Выберите Buf, если: ✅ **Небольшой набор публичных зависимостей** В основном используете популярные общие пакеты Вас устраивает зависимость от BSR"},{"id":"cli/package-manager/easyp-vs-buf::buf-easyp::54","title":"EasyP против Buf: управление пакетами","section":"Переход с Buf на EasyP","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf-easyp","headings":["Переход с Buf на EasyP"],"excerpt":"Переход с Buf на EasyP Найдите исходные Git репозитории для каждого модуля BSR Сопоставьте имена BSR → Git ссылки (с версиями/тегами) Обновите конфигурацию (easyp.yaml) Протестируйте генерацию и совместимость","content":"Переход с Buf на EasyP Найдите исходные Git репозитории для каждого модуля BSR Сопоставьте имена BSR → Git ссылки (с версиями/тегами) Обновите конфигурацию (easyp.yaml) Протестируйте генерацию и совместимость"},{"id":"cli/package-manager/easyp-vs-buf::buf-easyp::55","title":"EasyP против Buf: управление пакетами","section":"Переход с Buf на EasyP","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf-easyp","headings":["Переход с Buf на EasyP"],"excerpt":"Переход с Buf на EasyP ```yaml Было (buf.yaml) deps: - buf.build/googleapis/googleapis - buf.build/grpc/grpc","content":"Переход с Buf на EasyP ```yaml Было (buf.yaml) deps: - buf.build/googleapis/googleapis - buf.build/grpc/grpc"},{"id":"cli/package-manager/easyp-vs-buf::buf-easyp::56","title":"EasyP против Buf: управление пакетами","section":"Переход с Buf на EasyP","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf-easyp","headings":["Переход с Buf на EasyP"],"excerpt":"Переход с Buf на EasyP Стало (easyp.yaml) deps: - github.com/googleapis/googleapis@common-protos-1_3_1 - github.com/grpc/grpc@v1.50.0 ```","content":"Переход с Buf на EasyP Стало (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::easyp-buf::57","title":"EasyP против Buf: управление пакетами","section":"Переход с EasyP на Buf","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp-buf","headings":["Переход с EasyP на Buf"],"excerpt":"Переход с EasyP на Buf Опубликуйте используемые репозитории как модули BSR Настройте аутентификацию / организацию Buf Замените Git ссылки на BSR модули Перейдите к push/pull workflow Buf","content":"Переход с EasyP на Buf Опубликуйте используемые репозитории как модули BSR Настройте аутентификацию / организацию Buf Замените Git ссылки на BSR модули Перейдите к push/pull workflow Buf"},{"id":"cli/package-manager/easyp-vs-buf::top::58","title":"EasyP против Buf: управление пакетами","section":"Заключение","path":"/docs/guide/cli/package-manager/easyp-vs-buf","headings":["Заключение"],"excerpt":"Заключение Оба инструмента решают задачу управления зависимостями protobuf, но подходят под разные приоритеты:","content":"Заключение Оба инструмента решают задачу управления зависимостями protobuf, но подходят под разные приоритеты:"},{"id":"cli/package-manager/easyp-vs-buf::top::59","title":"EasyP против Buf: управление пакетами","section":"Заключение","path":"/docs/guide/cli/package-manager/easyp-vs-buf","headings":["Заключение"],"excerpt":"Заключение **Сильные стороны EasyP:** Корпоративные / изолированные среды Жёсткие требования безопасности и аудита Минимальные затраты и отсутствие доп. инфраструктуры Прямое использование Git (без промежуточного слоя) П","content":"Заключение **Сильные стороны EasyP:** Корпоративные / изолированные среды Жёсткие требования безопасности и аудита Минимальные затраты и отсутствие доп. инфраструктуры Прямое использование Git (без промежуточного слоя) Простота масштабирования"},{"id":"cli/package-manager/easyp-vs-buf::top::60","title":"EasyP против Buf: управление пакетами","section":"Заключение","path":"/docs/guide/cli/package-manager/easyp-vs-buf","headings":["Заключение"],"excerpt":"Заключение **Сильные стороны Buf:** Богатая экосистема вокруг реестра Курируемые и документированные модули Удобство для новых команд в protobuf Средства визуализации и централизованного обмена","content":"Заключение **Сильные стороны Buf:** Богатая экосистема вокруг реестра Курируемые и документированные модули Удобство для новых команд в protobuf Средства визуализации и централизованного обмена"},{"id":"cli/package-manager/easyp-vs-buf::top::61","title":"EasyP против Buf: управление пакетами","section":"Заключение","path":"/docs/guide/cli/package-manager/easyp-vs-buf","headings":["Заключение"],"excerpt":"Заключение Выбор часто сводится к балансу между **контролем vs. удобством**, **безопасностью vs. централизованными функциями**, и **стоимостью vs. managed‑сервисом**.","content":"Заключение Выбор часто сводится к балансу между **контролем vs. удобством**, **безопасностью vs. централизованными функциями**, и **стоимостью vs. managed‑сервисом**."},{"id":"cli/package-manager/easyp-vs-buf::top::62","title":"EasyP против Buf: управление пакетами","section":"Заключение","path":"/docs/guide/cli/package-manager/easyp-vs-buf","headings":["Заключение"],"excerpt":"Заключение Для большинства enterprise‑окружений децентрализованный Git‑подход EasyP обеспечивает нужные гибкость, безопасность и предсказуемость расходов, тогда как Buf отлично подходит командам, которым важна централизо","content":"Заключение Для большинства enterprise‑окружений децентрализованный Git‑подход EasyP обеспечивает нужные гибкость, безопасность и предсказуемость расходов, тогда как Buf отлично подходит командам, которым важна централизованная коллаборация и богатая экосистема вокруг реестра."},{"id":"cli/package-manager/package-manager::top::0","title":"Менеджер пакетов","path":"/docs/guide/cli/package-manager/package-manager","headings":[],"excerpt":"EasyP предоставляет мощный менеджер пакетов для protobuf‑зависимостей, упрощающий их управление за счёт децентрализованного подхода на базе Git. В отличие от централизованных решений, EasyP работает напрямую с Git‑репози","content":"EasyP предоставляет мощный менеджер пакетов для protobuf‑зависимостей, упрощающий их управление за счёт децентрализованного подхода на базе Git. В отличие от централизованных решений, EasyP работает напрямую с Git‑репозиториями, давая вам полный контроль."},{"id":"cli/package-manager/package-manager::top::1","title":"Менеджер пакетов","section":"Обзор","path":"/docs/guide/cli/package-manager/package-manager","headings":["Обзор"],"excerpt":"Обзор Менеджер пакетов EasyP следует философии **Go modules** — любой Git‑репозиторий может быть источником. Это даёт преимущества:","content":"Обзор Менеджер пакетов EasyP следует философии **Go modules** — любой Git‑репозиторий может быть источником. Это даёт преимущества:"},{"id":"cli/package-manager/package-manager::top::2","title":"Менеджер пакетов","section":"Обзор","path":"/docs/guide/cli/package-manager/package-manager","headings":["Обзор"],"excerpt":"Обзор **Децентрализация** — нет единой точки отказа или контроля **Безопасность** — прямой доступ к исходникам **Гибкость** — публичные, приватные и корпоративные репозитории **Воспроизводимость** — lock‑файлы обеспечива","content":"Обзор **Децентрализация** — нет единой точки отказа или контроля **Безопасность** — прямой доступ к исходникам **Гибкость** — публичные, приватные и корпоративные репозитории **Воспроизводимость** — lock‑файлы обеспечивают одинаковые сборки **Производительность** — локальный кеш сокращает сетевые запросы"},{"id":"cli/package-manager/package-manager::top::3","title":"Менеджер пакетов","section":"Основные возможности","path":"/docs/guide/cli/package-manager/package-manager","headings":["Основные возможности"],"excerpt":"Основные возможности Возможность Описание ------------- ---------- **Git-Native** Любой Git репозиторий, не нужен спец‑сервер **Множество форматов версий** Теги, коммиты, псевдо‑версии, latest **Lock Files** Воспроизводи","content":"Основные возможности Возможность Описание ------------- ---------- **Git-Native** Любой Git репозиторий, не нужен спец‑сервер **Множество форматов версий** Теги, коммиты, псевдо‑версии, latest **Lock Files** Воспроизводимые сборки через easyp.lock **Локальный кеш** Архитектура как у Go modules **Vendoring** Локальное копирование для оффлайн сборок **YAML конфигурация** Простые и читаемые декларации"},{"id":"cli/package-manager/package-manager::top::4","title":"Менеджер пакетов","section":"Архитектура","path":"/docs/guide/cli/package-manager/package-manager","headings":["Архитектура"],"excerpt":"Архитектура EasyP использует двухуровневый кеш, вдохновлённый Go modules:","content":"Архитектура EasyP использует двухуровневый кеш, вдохновлённый Go modules:"},{"id":"cli/package-manager/package-manager::top::5","title":"Менеджер пакетов","section":"Расположение кеша","path":"/docs/guide/cli/package-manager/package-manager","headings":["Расположение кеша"],"excerpt":"Расположение кеша Окружение Путь Как задать ----------- ------ ----------- **По умолчанию** $HOME/.easyp Автоматически **Свое** Любая директория Переменная EASYPPATH **CI/CD** В каталоге проекта export EASYPPATH=$CI_PROJ","content":"Расположение кеша Окружение Путь Как задать ----------- ------ ----------- **По умолчанию** $HOME/.easyp Автоматически **Свое** Любая директория Переменная EASYPPATH **CI/CD** В каталоге проекта export EASYPPATH=$CI_PROJECT_DIR/.easyp"},{"id":"cli/package-manager/package-manager::top::6","title":"Менеджер пакетов","section":"Базовая конфигурация","path":"/docs/guide/cli/package-manager/package-manager","headings":["Базовая конфигурация"],"excerpt":"Базовая конфигурация Зависимости описываются в easyp.yaml:","content":"Базовая конфигурация Зависимости описываются в easyp.yaml:"},{"id":"cli/package-manager/package-manager::multi-environment-setup::7","title":"Менеджер пакетов","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 # Последнее для разработки - github.com/mycompany/internal-protos # Внутренние изменения - github.com/bufbuild/protoc-gen-va","content":"Multi-Environment Setup ```yaml development.easyp.yaml deps: - github.com/googleapis/googleapis # Последнее для разработки - github.com/mycompany/internal-protos # Внутренние изменения - github.com/bufbuild/protoc-gen-validate # Новые фичи"},{"id":"cli/package-manager/package-manager::multi-environment-setup::8","title":"Менеджер пакетов","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 # Зафиксировано - github.com/mycompany/internal-protos@v2.1.0 # Стабильно - github.com/bufbuild/protoc-gen-valida","content":"Multi-Environment Setup production.easyp.yaml deps: - github.com/googleapis/googleapis@common-protos-1_3_1 # Зафиксировано - github.com/mycompany/internal-protos@v2.1.0 # Стабильно - github.com/bufbuild/protoc-gen-validate@v0.10.1 # Проверено ```"},{"id":"cli/package-manager/package-manager::top::9","title":"Менеджер пакетов","section":"Приватные репозитории","path":"/docs/guide/cli/package-manager/package-manager","headings":["Приватные репозитории"],"excerpt":"Приватные репозитории ```yaml deps: # Публичное - github.com/googleapis/googleapis@common-protos-1_3_1","content":"Приватные репозитории ```yaml deps: # Публичное - github.com/googleapis/googleapis@common-protos-1_3_1"},{"id":"cli/package-manager/package-manager::top::10","title":"Менеджер пакетов","section":"Приватные репозитории","path":"/docs/guide/cli/package-manager/package-manager","headings":["Приватные репозитории"],"excerpt":"Приватные репозитории Частные - github.com/mycompany/auth-protos@v1.5.0 - github.com/mycompany/common-types@v2.0.1","content":"Приватные репозитории Частные - github.com/mycompany/auth-protos@v1.5.0 - github.com/mycompany/common-types@v2.0.1"},{"id":"cli/package-manager/package-manager::top::11","title":"Менеджер пакетов","section":"Приватные репозитории","path":"/docs/guide/cli/package-manager/package-manager","headings":["Приватные репозитории"],"excerpt":"Приватные репозитории Внутренний GitLab - gitlab.company.com/platform/messaging-protos@v0.3.0 ```","content":"Приватные репозитории Внутренний GitLab - gitlab.company.com/platform/messaging-protos@v0.3.0 ```"},{"id":"cli/package-manager/package-manager::top::12","title":"Менеджер пакетов","section":"Стратегии версионирования","path":"/docs/guide/cli/package-manager/package-manager","headings":["Стратегии версионирования"],"excerpt":"Стратегии версионирования Поддерживаются разные способы фиксации версий:","content":"Стратегии версионирования Поддерживаются разные способы фиксации версий:"},{"id":"cli/package-manager/package-manager::1::13","title":"Менеджер пакетов","section":"1. Семантические теги (для продакшена)","path":"/docs/guide/cli/package-manager/package-manager#1","headings":["1. Семантические теги (для продакшена)"],"excerpt":"Семантические теги (для продакшена)","content":"Семантические теги (для продакшена)"},{"id":"cli/package-manager/package-manager::1::14","title":"Менеджер пакетов","section":"1. Семантические теги (для продакшена)","path":"/docs/guide/cli/package-manager/package-manager#1","headings":["1. Семантические теги (для продакшена)"],"excerpt":"Семантические теги (для продакшена) **Используйте когда:** Продакшен Стабильное потребление API Нужна воспроизводимость","content":"Семантические теги (для продакшена) **Используйте когда:** Продакшен Стабильное потребление API Нужна воспроизводимость"},{"id":"cli/package-manager/package-manager::2-development::15","title":"Менеджер пакетов","section":"2. Последний тег (development)","path":"/docs/guide/cli/package-manager/package-manager#2-development","headings":["2. Последний тег (development)"],"excerpt":"Последний тег (development) **Подходит для:** Активной разработки Получения свежих возможностей Тестирования совместимости","content":"Последний тег (development) **Подходит для:** Активной разработки Получения свежих возможностей Тестирования совместимости"},{"id":"cli/package-manager/package-manager::3-bleeding-edge::16","title":"Менеджер пакетов","section":"3. Хеш коммита (Bleeding Edge)","path":"/docs/guide/cli/package-manager/package-manager#3-bleeding-edge","headings":["3. Хеш коммита (Bleeding Edge)"],"excerpt":"Хеш коммита (Bleeding Edge) **Когда нужно:** Нерелизные фичи Тест конкретного фикса Вклад в upstream","content":"Хеш коммита (Bleeding Edge) **Когда нужно:** Нерелизные фичи Тест конкретного фикса Вклад в upstream"},{"id":"cli/package-manager/package-manager::4::17","title":"Менеджер пакетов","section":"4. Псевдо‑версии (автоматически)","path":"/docs/guide/cli/package-manager/package-manager#4","headings":["4. Псевдо‑версии (автоматически)"],"excerpt":"Псевдо‑версии (автоматически) Если нет подходящего тега — создаётся псевдо‑версия:","content":"Псевдо‑версии (автоматически) Если нет подходящего тега — создаётся псевдо‑версия:"},{"id":"cli/package-manager/package-manager::easyp-mod-download::18","title":"Менеджер пакетов","section":"easyp mod download","path":"/docs/guide/cli/package-manager/package-manager#easyp-mod-download","headings":["easyp mod download"],"excerpt":"easyp mod download Скачивает и устанавливает все объявленные зависимости.","content":"easyp mod download Скачивает и устанавливает все объявленные зависимости."},{"id":"cli/package-manager/package-manager::easyp-mod-download::19","title":"Менеджер пакетов","section":"easyp mod download","path":"/docs/guide/cli/package-manager/package-manager#easyp-mod-download","headings":["easyp mod download"],"excerpt":"easyp mod download **Что делает:** Разрешает версии (теги → коммиты) Скачивает архивы в cache/download Проверяет контрольные суммы Распаковывает в cache/mod Обновляет easyp.lock","content":"easyp mod download **Что делает:** Разрешает версии (теги → коммиты) Скачивает архивы в cache/download Проверяет контрольные суммы Распаковывает в cache/mod Обновляет easyp.lock"},{"id":"cli/package-manager/package-manager::easyp-mod-download::20","title":"Менеджер пакетов","section":"easyp mod download","path":"/docs/guide/cli/package-manager/package-manager#easyp-mod-download","headings":["easyp mod download"],"excerpt":"easyp mod download **Пример:**","content":"easyp mod download **Пример:**"},{"id":"cli/package-manager/package-manager::easyp-mod-vendor::21","title":"Менеджер пакетов","section":"easyp mod vendor","path":"/docs/guide/cli/package-manager/package-manager#easyp-mod-vendor","headings":["easyp mod vendor"],"excerpt":"easyp mod vendor Копирует все proto зависимости в локальный easyp_vendor/ для оффлайна.","content":"easyp mod vendor Копирует все proto зависимости в локальный easyp_vendor/ для оффлайна."},{"id":"cli/package-manager/package-manager::easyp-mod-vendor::22","title":"Менеджер пакетов","section":"easyp mod vendor","path":"/docs/guide/cli/package-manager/package-manager#easyp-mod-vendor","headings":["easyp mod vendor"],"excerpt":"easyp mod vendor **Сценарии:** Docker сборки Air-gapped окружения Воспроизводимость Ускорение","content":"easyp mod vendor **Сценарии:** Docker сборки Air-gapped окружения Воспроизводимость Ускорение"},{"id":"cli/package-manager/package-manager::easyp-mod-update::23","title":"Менеджер пакетов","section":"easyp mod update","path":"/docs/guide/cli/package-manager/package-manager#easyp-mod-update","headings":["easyp mod update"],"excerpt":"easyp mod update Обновляет версии согласно easyp.yaml, пересоздаёт lock.","content":"easyp mod update Обновляет версии согласно easyp.yaml, пересоздаёт lock."},{"id":"cli/package-manager/package-manager::lock::24","title":"Менеджер пакетов","section":"Lock файл","path":"/docs/guide/cli/package-manager/package-manager#lock","headings":["Lock файл"],"excerpt":"Lock файл easyp.lock фиксирует точные версии и хеш содержимого:","content":"Lock файл easyp.lock фиксирует точные версии и хеш содержимого:"},{"id":"cli/package-manager/package-manager::lock::25","title":"Менеджер пакетов","section":"Lock файл","path":"/docs/guide/cli/package-manager/package-manager#lock","headings":["Lock файл"],"excerpt":"Lock файл **Формат строки:** Путь модуля Версия (тег или псевдо) Хеш содержимого (h1:)","content":"Lock файл **Формат строки:** Путь модуля Версия (тег или псевдо) Хеш содержимого (h1:)"},{"id":"cli/package-manager/package-manager::lock::26","title":"Менеджер пакетов","section":"Lock файл","path":"/docs/guide/cli/package-manager/package-manager#lock","headings":["Lock файл"],"excerpt":"Lock файл **Практики:** ✅ Коммитить easyp.lock ✅ Осознанно обновлять mod update ✅ Ревью изменений версий ❌ Не редактировать вручную","content":"Lock файл **Практики:** ✅ Коммитить easyp.lock ✅ Осознанно обновлять mod update ✅ Ревью изменений версий ❌ Не редактировать вручную"},{"id":"cli/package-manager/package-manager::top::27","title":"Менеджер пакетов","section":"Публичные репозитории","path":"/docs/guide/cli/package-manager/package-manager","headings":["Публичные репозитории"],"excerpt":"Публичные репозитории Работают без настроек:","content":"Публичные репозитории Работают без настроек:"},{"id":"cli/package-manager/package-manager::ssh::28","title":"Менеджер пакетов","section":"SSH ключи (рекомендуется)","path":"/docs/guide/cli/package-manager/package-manager#ssh","headings":["SSH ключи (рекомендуется)"],"excerpt":"SSH ключи (рекомендуется) Конфиг остаётся с HTTPS URL:","content":"SSH ключи (рекомендуется) Конфиг остаётся с HTTPS URL:"},{"id":"cli/package-manager/package-manager::personal-access-tokens::29","title":"Менеджер пакетов","section":"Personal Access Tokens","path":"/docs/guide/cli/package-manager/package-manager#personal-access-tokens","headings":["Personal Access Tokens"],"excerpt":"Personal Access Tokens ```bash git config --global credential.helper store echo \"https://username:token@github.com\" >> ~/.git-credentials","content":"Personal Access Tokens ```bash git config --global credential.helper store echo \"https://username:token@github.com\" >> ~/.git-credentials"},{"id":"cli/package-manager/package-manager::personal-access-tokens::30","title":"Менеджер пакетов","section":"Personal Access Tokens","path":"/docs/guide/cli/package-manager/package-manager#personal-access-tokens","headings":["Personal Access Tokens"],"excerpt":"Personal Access Tokens git config --global url.\"https://username:token@github.com/mycompany\".insteadOf \"https://github.com/mycompany\" ```","content":"Personal Access Tokens git config --global url.\"https://username:token@github.com/mycompany\".insteadOf \"https://github.com/mycompany\" ```"},{"id":"cli/package-manager/package-manager::top::31","title":"Менеджер пакетов","section":"Инициализация проекта","path":"/docs/guide/cli/package-manager/package-manager","headings":["Инициализация проекта"],"excerpt":"Инициализация проекта ```bash cat > easyp.yaml << EOF deps: - github.com/googleapis/googleapis - github.com/grpc-ecosystem/grpc-gateway@v2.19.1 EOF","content":"Инициализация проекта ```bash 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::top::32","title":"Менеджер пакетов","section":"Инициализация проекта","path":"/docs/guide/cli/package-manager/package-manager","headings":["Инициализация проекта"],"excerpt":"Инициализация проекта easyp mod download ls ~/.easyp/mod/github.com/googleapis/googleapis/ ```","content":"Инициализация проекта easyp mod download ls ~/.easyp/mod/github.com/googleapis/googleapis/ ```"},{"id":"cli/package-manager/package-manager::repository-not-found-authentication-failed::33","title":"Менеджер пакетов","section":"\"Repository not found\" / \"Authentication failed\"","path":"/docs/guide/cli/package-manager/package-manager#repository-not-found-authentication-failed","headings":["\"Repository not found\" / \"Authentication failed\""],"excerpt":"\"Repository not found\" / \"Authentication failed\"","content":"\"Repository not found\" / \"Authentication failed\""},{"id":"cli/package-manager/package-manager::cache-corruption-checksum-mismatch::34","title":"Менеджер пакетов","section":"\"Cache corruption\" / \"Checksum mismatch\"","path":"/docs/guide/cli/package-manager/package-manager#cache-corruption-checksum-mismatch","headings":["\"Cache corruption\" / \"Checksum mismatch\""],"excerpt":"\"Cache corruption\" / \"Checksum mismatch\"","content":"\"Cache corruption\" / \"Checksum mismatch\""},{"id":"cli/package-manager/package-manager::docker-multi-stage::35","title":"Менеджер пакетов","section":"Docker multi-stage","path":"/docs/guide/cli/package-manager/package-manager#docker-multi-stage","headings":["Docker multi-stage"],"excerpt":"Docker multi-stage ```dockerfile FROM ghcr.io/easyp-tech/easyp:latest AS deps WORKDIR /workspace COPY easyp.yaml easyp.lock ./ RUN easyp mod vendor","content":"Docker multi-stage ```dockerfile 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::36","title":"Менеджер пакетов","section":"Docker multi-stage","path":"/docs/guide/cli/package-manager/package-manager#docker-multi-stage","headings":["Docker multi-stage"],"excerpt":"Docker multi-stage FROM alpine:latest AS build WORKDIR /app COPY --from=deps /workspace/easyp_vendor ./easyp_vendor COPY . . RUN easyp generate ```","content":"Docker multi-stage FROM alpine:latest AS build WORKDIR /app COPY --from=deps /workspace/easyp_vendor ./easyp_vendor COPY . . RUN easyp generate ```"},{"id":"cli/package-manager/package-manager::monorepo::37","title":"Менеджер пакетов","section":"Monorepo","path":"/docs/guide/cli/package-manager/package-manager#monorepo","headings":["Monorepo"],"excerpt":"Monorepo Каждый easyp.yaml может иметь свой набор зависимостей.","content":"Monorepo Каждый easyp.yaml может иметь свой набор зависимостей."},{"id":"cli/package-manager/package-manager::workflow::38","title":"Менеджер пакетов","section":"Workflow разработки","path":"/docs/guide/cli/package-manager/package-manager#workflow","headings":["Workflow разработки"],"excerpt":"Workflow разработки ✅ Latest теги в активной разработке ✅ Фиксация версий в продакшене ✅ Коммит lock файла ✅ Ревью обновлений ✅ Тест после обновления","content":"Workflow разработки ✅ Latest теги в активной разработке ✅ Фиксация версий в продакшене ✅ Коммит lock файла ✅ Ревью обновлений ✅ Тест после обновления"},{"id":"cli/package-manager/package-manager::top::39","title":"Менеджер пакетов","section":"Безопасность","path":"/docs/guide/cli/package-manager/package-manager","headings":["Безопасность"],"excerpt":"Безопасность ✅ Фиксируйте версии ✅ Используйте SSH ключи ✅ Оценивайте новые зависимости ✅ Следите за уязвимостями ❌ Не храните секреты в конфиге","content":"Безопасность ✅ Фиксируйте версии ✅ Используйте SSH ключи ✅ Оценивайте новые зависимости ✅ Следите за уязвимостями ❌ Не храните секреты в конфиге"},{"id":"cli/package-manager/package-manager::top::40","title":"Менеджер пакетов","section":"Производительность","path":"/docs/guide/cli/package-manager/package-manager","headings":["Производительность"],"excerpt":"Производительность ✅ Агрессивное кеширование в CI ✅ Vendoring для частых сборок ✅ Чистка старого кеша ✅ Общий кеш для команды","content":"Производительность ✅ Агрессивное кеширование в CI ✅ Vendoring для частых сборок ✅ Чистка старого кеша ✅ Общий кеш для команды"},{"id":"cli/package-manager/package-manager::top::41","title":"Менеджер пакетов","section":"Командная работа","path":"/docs/guide/cli/package-manager/package-manager","headings":["Командная работа"],"excerpt":"Командная работа ✅ Документация по аутентификации ✅ Единые инструменты ✅ Автоматизация обновлений с тестами ✅ Общий кеш при возможности","content":"Командная работа ✅ Документация по аутентификации ✅ Единые инструменты ✅ Автоматизация обновлений с тестами ✅ Общий кеш при возможности"},{"id":"cli/package-manager/package-manager::top::42","title":"Менеджер пакетов","section":"Командная работа","path":"/docs/guide/cli/package-manager/package-manager","headings":["Командная работа"],"excerpt":"Командная работа Менеджер пакетов EasyP — масштабируемое децентрализованное решение от одиночных проектов до enterprise, сохраняя простоту и надёжность.","content":"Командная работа Менеджер пакетов EasyP — масштабируемое децентрализованное решение от одиночных проектов до enterprise, сохраняя простоту и надёжность."},{"id":"introduction/install::top::0","title":"Установка EasyP CLI","section":"Установка через менеджер пакетов системы","path":"/docs/guide/introduction/install","headings":["Установка через менеджер пакетов системы"],"excerpt":"Установка через менеджер пакетов системы","content":"Установка через менеджер пакетов системы"},{"id":"introduction/install::top::1","title":"Установка EasyP CLI","section":"Рекомендуемый способ установки","path":"/docs/guide/introduction/install","headings":["Рекомендуемый способ установки"],"excerpt":"Рекомендуемый способ установки","content":"Рекомендуемый способ установки"},{"id":"introduction/install::homebrew::2","title":"Установка EasyP CLI","section":"Homebrew","path":"/docs/guide/introduction/install#homebrew","headings":["Homebrew"],"excerpt":"Homebrew Можно установить бинарный релиз в macOS через Homebrew:","content":"Homebrew Можно установить бинарный релиз в macOS через Homebrew:"},{"id":"introduction/install::homebrew::3","title":"Установка EasyP CLI","section":"Homebrew","path":"/docs/guide/introduction/install#homebrew","headings":["Homebrew"],"excerpt":"Homebrew Work in progress — поддержка других менеджеров (apt, yum, pacman и т.д.) в процессе.","content":"Homebrew Work in progress — поддержка других менеджеров (apt, yum, pacman и т.д.) в процессе."},{"id":"introduction/install::_-_::4","title":"Установка EasyP CLI","section":"_Не рекомендуется_","path":"/docs/guide/introduction/install#_-_","headings":["_Не рекомендуется_"],"excerpt":"_Не рекомендуется_ Локальная установка менее предпочтительна, потому что пакетные менеджеры обеспечивают: Автоматические обновления и патчи безопасности Лучшую интеграцию с системой Упрощённую установку и удаление Подпис","content":"_Не рекомендуется_ Локальная установка менее предпочтительна, потому что пакетные менеджеры обеспечивают: Автоматические обновления и патчи безопасности Лучшую интеграцию с системой Упрощённую установку и удаление Подписанные и проверенные бинарники"},{"id":"introduction/install::go-install::5","title":"Установка EasyP CLI","section":"Установка через go install","path":"/docs/guide/introduction/install#go-install","headings":["Установка через go install"],"excerpt":"Установка через go install Команда установит последнюю стабильную версию easyp:","content":"Установка через go install Команда установит последнюю стабильную версию easyp:"},{"id":"introduction/install::top::6","title":"Установка EasyP CLI","section":"Сборка из исходников","path":"/docs/guide/introduction/install","headings":["Сборка из исходников"],"excerpt":"Сборка из исходников Клонирование репозитория","content":"Сборка из исходников Клонирование репозитория"},{"id":"introduction/install::top::7","title":"Установка EasyP CLI","section":"Сборка из исходников","path":"/docs/guide/introduction/install","headings":["Сборка из исходников"],"excerpt":"Сборка из исходников Сборка с помощью Go","content":"Сборка из исходников Сборка с помощью Go"},{"id":"introduction/quickstart::top::0","title":"Быстрый старт (Quickstart)","path":"/docs/guide/introduction/quickstart","headings":[],"excerpt":"EasyP — современный toolkit для работы с файлами Protobuf. В этом кратком руководстве вы научитесь:","content":"EasyP — современный toolkit для работы с файлами Protobuf. В этом кратком руководстве вы научитесь:"},{"id":"introduction/quickstart::top::1","title":"Быстрый старт (Quickstart)","path":"/docs/guide/introduction/quickstart","headings":[],"excerpt":"**Инициализировать** проект с конфигурацией EasyP **Настраивать линтинг**, чтобы ловить ошибки и соблюдать лучшие практики **Управлять зависимостями** из Git‑репозиториев **Генерировать код** из ваших Protobuf файлов","content":"**Инициализировать** проект с конфигурацией EasyP **Настраивать линтинг**, чтобы ловить ошибки и соблюдать лучшие практики **Управлять зависимостями** из Git‑репозиториев **Генерировать код** из ваших Protobuf файлов"},{"id":"introduction/quickstart::top::2","title":"Быстрый старт (Quickstart)","section":"Предварительные требования","path":"/docs/guide/introduction/quickstart","headings":["Предварительные требования"],"excerpt":"Предварительные требования Перед началом убедитесь, что у вас установлены:","content":"Предварительные требования Перед началом убедитесь, что у вас установлены:"},{"id":"introduction/quickstart::top::3","title":"Быстрый старт (Quickstart)","section":"Предварительные требования","path":"/docs/guide/introduction/quickstart","headings":["Предварительные требования"],"excerpt":"Предварительные требования **EasyP CLI** — см. руководство по установке **Git** доступен в вашем $PATH **Файлы .proto** (или создайте их по ходу)","content":"Предварительные требования **EasyP CLI** — см. руководство по установке **Git** доступен в вашем $PATH **Файлы .proto** (или создайте их по ходу)"},{"id":"introduction/quickstart::top::4","title":"Быстрый старт (Quickstart)","section":"Предварительные требования","path":"/docs/guide/introduction/quickstart","headings":["Предварительные требования"],"excerpt":"Предварительные требования Проверить версию EasyP:","content":"Предварительные требования Проверить версию EasyP:"},{"id":"introduction/quickstart::top::5","title":"Быстрый старт (Quickstart)","section":"Инициализация проекта","path":"/docs/guide/introduction/quickstart","headings":["Инициализация проекта"],"excerpt":"Инициализация проекта Создайте базовый файл конфигурации easyp.yaml в корне проекта:","content":"Инициализация проекта Создайте базовый файл конфигурации easyp.yaml в корне проекта:"},{"id":"introduction/quickstart::top::6","title":"Быстрый старт (Quickstart)","section":"Инициализация проекта","path":"/docs/guide/introduction/quickstart","headings":["Инициализация проекта"],"excerpt":"Инициализация проекта Команда генерирует шаблон easyp.yaml с комментариями, дефолтными lint-правилами и настройками breaking-check. easyp init работает интерактивно: если в корне есть buf.yml/buf.yaml, EasyP предложит ми","content":"Инициализация проекта Команда генерирует шаблон easyp.yaml с комментариями, дефолтными lint-правилами и настройками breaking-check. easyp init работает интерактивно: если в корне есть buf.yml/buf.yaml, EasyP предложит миграцию; если easyp.yaml уже существует, попросит подтверждение перед перезаписью."},{"id":"introduction/quickstart::top::7","title":"Быстрый старт (Quickstart)","section":"Настройка линтинга","path":"/docs/guide/introduction/quickstart","headings":["Настройка линтинга"],"excerpt":"Настройка линтинга Линтинг помогает находить проблемы и поддерживать единый стиль. EasyP использует правила, совместимые с Buf.","content":"Настройка линтинга Линтинг помогает находить проблемы и поддерживать единый стиль. EasyP использует правила, совместимые с Buf."},{"id":"introduction/quickstart::top::8","title":"Быстрый старт (Quickstart)","section":"Настройка линтинга","path":"/docs/guide/introduction/quickstart","headings":["Настройка линтинга"],"excerpt":"Настройка линтинга Секция lint уже создаётся командой easyp init. При необходимости отредактируйте её, например так:","content":"Настройка линтинга Секция lint уже создаётся командой easyp init. При необходимости отредактируйте её, например так:"},{"id":"introduction/quickstart::top::9","title":"Быстрый старт (Quickstart)","section":"Настройка линтинга","path":"/docs/guide/introduction/quickstart","headings":["Настройка линтинга"],"excerpt":"Настройка линтинга Запустите линтер:","content":"Настройка линтинга Запустите линтер:"},{"id":"introduction/quickstart::top::10","title":"Быстрый старт (Quickstart)","section":"Настройка линтинга","path":"/docs/guide/introduction/quickstart","headings":["Настройка линтинга"],"excerpt":"Настройка линтинга Линтер проверит все .proto файлы и сообщит о найденных проблемах.","content":"Настройка линтинга Линтер проверит все .proto файлы и сообщит о найденных проблемах."},{"id":"introduction/quickstart::top::11","title":"Быстрый старт (Quickstart)","section":"Настройка линтинга","path":"/docs/guide/introduction/quickstart","headings":["Настройка линтинга"],"excerpt":"Настройка линтинга ::: tip Правила линтинга EasyP на 100% совместимы с Buf — мигрировать просто. :::","content":"Настройка линтинга ::: tip Правила линтинга EasyP на 100% совместимы с Buf — мигрировать просто. :::"},{"id":"introduction/quickstart::top::12","title":"Быстрый старт (Quickstart)","section":"Управление зависимостями","path":"/docs/guide/introduction/quickstart","headings":["Управление зависимостями"],"excerpt":"Управление зависимостями Если вы используете сторонние protobuf пакеты (например Google APIs или gRPC Gateway), EasyP упрощает их подключение.","content":"Управление зависимостями Если вы используете сторонние protobuf пакеты (например Google APIs или gRPC Gateway), EasyP упрощает их подключение."},{"id":"introduction/quickstart::top::13","title":"Быстрый старт (Quickstart)","section":"Формат зависимости","path":"/docs/guide/introduction/quickstart","headings":["Формат зависимости"],"excerpt":"Формат зависимости Запись: $GIT_LINK@$VERSION","content":"Формат зависимости Запись: $GIT_LINK@$VERSION"},{"id":"introduction/quickstart::top::14","title":"Быстрый старт (Quickstart)","section":"Формат зависимости","path":"/docs/guide/introduction/quickstart","headings":["Формат зависимости"],"excerpt":"Формат зависимости **$GIT_LINK** — URL любого Git‑репозитория (GitHub, GitLab и т.д.) **$VERSION** — тег или хеш коммита (опционально)","content":"Формат зависимости **$GIT_LINK** — URL любого Git‑репозитория (GitHub, GitLab и т.д.) **$VERSION** — тег или хеш коммита (опционально)"},{"id":"introduction/quickstart::top::15","title":"Быстрый старт (Quickstart)","section":"Формат зависимости","path":"/docs/guide/introduction/quickstart","headings":["Формат зависимости"],"excerpt":"Формат зависимости Если версия не указана — берётся последний коммит из основной ветки.","content":"Формат зависимости Если версия не указана — берётся последний коммит из основной ветки."},{"id":"introduction/quickstart::top::16","title":"Быстрый старт (Quickstart)","section":"Добавление зависимостей","path":"/docs/guide/introduction/quickstart","headings":["Добавление зависимостей"],"excerpt":"Добавление зависимостей Дополните easyp.yaml:","content":"Добавление зависимостей Дополните easyp.yaml:"},{"id":"introduction/quickstart::top::17","title":"Быстрый старт (Quickstart)","section":"Загрузка зависимостей","path":"/docs/guide/introduction/quickstart","headings":["Загрузка зависимостей"],"excerpt":"Загрузка зависимостей Команда: Скачивает версии из easyp.lock, если он существует Иначе — берёт из easyp.yaml и создаёт easyp.lock","content":"Загрузка зависимостей Команда: Скачивает версии из easyp.lock, если он существует Иначе — берёт из easyp.yaml и создаёт easyp.lock"},{"id":"introduction/quickstart::top::18","title":"Быстрый старт (Quickstart)","section":"Загрузка зависимостей","path":"/docs/guide/introduction/quickstart","headings":["Загрузка зависимостей"],"excerpt":"Загрузка зависимостей ::: info Совет: easyp mod update — игнорирует lock‑файл и подтягивает актуальные версии из easyp.yaml. :::","content":"Загрузка зависимостей ::: info Совет: easyp mod update — игнорирует lock‑файл и подтягивает актуальные версии из easyp.yaml. :::"},{"id":"introduction/quickstart::top::19","title":"Быстрый старт (Quickstart)","section":"Генерация кода","path":"/docs/guide/introduction/quickstart","headings":["Генерация кода"],"excerpt":"Генерация кода EasyP поддерживает все стандартные protoc‑плагины.","content":"Генерация кода EasyP поддерживает все стандартные protoc‑плагины."},{"id":"introduction/quickstart::top::20","title":"Быстрый старт (Quickstart)","section":"Конфигурация генерации","path":"/docs/guide/introduction/quickstart","headings":["Конфигурация генерации"],"excerpt":"Конфигурация генерации Добавьте плагины:","content":"Конфигурация генерации Добавьте плагины:"},{"id":"introduction/quickstart::top::21","title":"Быстрый старт (Quickstart)","section":"Запуск генерации","path":"/docs/guide/introduction/quickstart","headings":["Запуск генерации"],"excerpt":"Запуск генерации EasyP выполнит: Разрешение всех зависимостей Подключение к сервису EasyP (или локальный режим) Запуск указанных плагинов Вывод сгенерированного кода в нужные директории","content":"Запуск генерации EasyP выполнит: Разрешение всех зависимостей Подключение к сервису EasyP (или локальный режим) Запуск указанных плагинов Вывод сгенерированного кода в нужные директории"},{"id":"introduction/quickstart::top::22","title":"Быстрый старт (Quickstart)","section":"Запуск генерации","path":"/docs/guide/introduction/quickstart","headings":["Запуск генерации"],"excerpt":"Запуск генерации ::: tip Гибридный рантайм: WASM для скорости, Docker — для тяжёлых плагинов. :::","content":"Запуск генерации ::: tip Гибридный рантайм: WASM для скорости, Docker — для тяжёлых плагинов. :::"},{"id":"introduction/quickstart::top::23","title":"Быстрый старт (Quickstart)","section":"Следующие шаги","path":"/docs/guide/introduction/quickstart","headings":["Следующие шаги"],"excerpt":"Следующие шаги Поздравляем! 🎉 Вы успешно: ✅ Инициализировали проект EasyP ✅ Настроили линтинг ✅ Управляете внешними зависимостями ✅ Сгенерировали код из .proto","content":"Следующие шаги Поздравляем! 🎉 Вы успешно: ✅ Инициализировали проект EasyP ✅ Настроили линтинг ✅ Управляете внешними зависимостями ✅ Сгенерировали код из .proto"},{"id":"introduction/quickstart::top::24","title":"Быстрый старт (Quickstart)","section":"Узнать больше","path":"/docs/guide/introduction/quickstart","headings":["Узнать больше"],"excerpt":"Узнать больше **CLI Reference** — подробности по командам **API Service** — удалённая генерация **Configuration** — все опции конфигурации","content":"Узнать больше **CLI Reference** — подробности по командам **API Service** — удалённая генерация **Configuration** — все опции конфигурации"},{"id":"introduction/quickstart::top::25","title":"Быстрый старт (Quickstart)","section":"Узнать больше","path":"/docs/guide/introduction/quickstart","headings":["Узнать больше"],"excerpt":"Узнать больше *Приятной работы с Protobuf — без боли! 🚀*","content":"Узнать больше *Приятной работы с Protobuf — без боли! 🚀*"},{"id":"introduction/what-is::top::0","title":"Что такое EasyP?","path":"/docs/guide/introduction/what-is","headings":[],"excerpt":"EasyP — это современный инструментарий для работы с Protocol Buffers, который объединяет весь ваш protobuf‑workflow в один мощный CLI‑инструмент. Он совмещает линтинг, управление пакетами, генерацию кода и проверку совме","content":"EasyP — это современный инструментарий для работы с Protocol Buffers, который объединяет весь ваш protobuf‑workflow в один мощный CLI‑инструмент. Он совмещает линтинг, управление пакетами, генерацию кода и проверку совместимости в единой среде и устраняет сложность традиционной работы с protobuf."},{"id":"introduction/what-is::top::1","title":"Что такое EasyP?","path":"/docs/guide/introduction/what-is","headings":[],"excerpt":"Хотите просто попробовать? Перейдите сразу к разделу Quickstart.","content":"Хотите просто попробовать? Перейдите сразу к разделу Quickstart."},{"id":"introduction/what-is::protobuf::2","title":"Что такое EasyP?","section":"Проблема: фрагментированные protobuf‑процессы","path":"/docs/guide/introduction/what-is#protobuf","headings":["Проблема: фрагментированные protobuf‑процессы"],"excerpt":"Проблема: фрагментированные protobuf‑процессы Работа с Protocol Buffers в разных проектах часто создает лишнюю сложность и трение:","content":"Проблема: фрагментированные protobuf‑процессы Работа с Protocol Buffers в разных проектах часто создает лишнюю сложность и трение:"},{"id":"introduction/what-is::top::3","title":"Что такое EasyP?","section":"Хаос инструментов","path":"/docs/guide/introduction/what-is","headings":["Хаос инструментов"],"excerpt":"Хаос инструментов **Много отдельных утилит**: Отдельно для линтинга, генерации и управления зависимостями **Несогласованные конфигурации**: Разные форматы и правила в разных командах **Сложный онбординг**: Новым разработ","content":"Хаос инструментов **Много отдельных утилит**: Отдельно для линтинга, генерации и управления зависимостями **Несогласованные конфигурации**: Разные форматы и правила в разных командах **Сложный онбординг**: Новым разработчикам нужно долго вникать"},{"id":"introduction/what-is::top::4","title":"Что такое EasyP?","section":"Проблемы управления зависимостями","path":"/docs/guide/introduction/what-is","headings":["Проблемы управления зависимостями"],"excerpt":"Проблемы управления зависимостями **Нет стандартизированного подхода**: Каждый проект решает это по‑своему **Конфликты версий**: Трудно сводить разные версии одних и тех же proto‑библиотек **Неповторяемость сборок**: Сло","content":"Проблемы управления зависимостями **Нет стандартизированного подхода**: Каждый проект решает это по‑своему **Конфликты версий**: Трудно сводить разные версии одних и тех же proto‑библиотек **Неповторяемость сборок**: Сложно гарантировать одинаковый результат в разных окружениях"},{"id":"introduction/what-is::top::5","title":"Что такое EasyP?","section":"Трение в разработке","path":"/docs/guide/introduction/what-is","headings":["Трение в разработке"],"excerpt":"Трение в разработке **Ручные операции**: Много повторяющихся шагов **Разрастание конфигураций**: Множество файлов и форматов **Затратная проверка совместимости**: Часто вручную и постфактум","content":"Трение в разработке **Ручные операции**: Много повторяющихся шагов **Разрастание конфигураций**: Множество файлов и форматов **Затратная проверка совместимости**: Часто вручную и постфактум"},{"id":"introduction/what-is::protobuf::6","title":"Что такое EasyP?","section":"Решение: единый protobuf‑инструментарий","path":"/docs/guide/introduction/what-is#protobuf","headings":["Решение: единый protobuf‑инструментарий"],"excerpt":"Решение: единый protobuf‑инструментарий EasyP устраняет эти проблемы, предоставляя целостный opinionated‑подход и стандартизируя процессы:","content":"Решение: единый protobuf‑инструментарий EasyP устраняет эти проблемы, предоставляя целостный opinionated‑подход и стандартизируя процессы:"},{"id":"introduction/what-is::top::7","title":"Что такое EasyP?","section":"Один инструмент — все задачи","path":"/docs/guide/introduction/what-is","headings":["Один инструмент — все задачи"],"excerpt":"Один инструмент — все задачи Вместо жонглирования утилитами EasyP даёт: **Linting** с расширенными наборами правил **Package management** с Git‑нативными зависимостями **Code generation** локально и удалённо **Breaking c","content":"Один инструмент — все задачи Вместо жонглирования утилитами EasyP даёт: **Linting** с расширенными наборами правил **Package management** с Git‑нативными зависимостями **Code generation** локально и удалённо **Breaking change detection** для контроля совместимости API"},{"id":"introduction/what-is::top::8","title":"Что такое EasyP?","section":"Единая конфигурация","path":"/docs/guide/introduction/what-is","headings":["Единая конфигурация"],"excerpt":"Единая конфигурация Один файл easyp.yaml описывает весь workflow — меньше расхождений, проще сопровождать.","content":"Единая конфигурация Один файл easyp.yaml описывает весь workflow — меньше расхождений, проще сопровождать."},{"id":"introduction/what-is::gitnative::9","title":"Что такое EasyP?","section":"Git‑native зависимости","path":"/docs/guide/introduction/what-is#gitnative","headings":["Git‑native зависимости"],"excerpt":"Git‑native зависимости Прямое использование Git‑репозиториев вместо централизованных реестров: прозрачная история, контроль версий, воспроизводимые сборки.","content":"Git‑native зависимости Прямое использование Git‑репозиториев вместо централизованных реестров: прозрачная история, контроль версий, воспроизводимые сборки."},{"id":"introduction/what-is::top::10","title":"Что такое EasyP?","section":"Ключевые возможности","path":"/docs/guide/introduction/what-is","headings":["Ключевые возможности"],"excerpt":"Ключевые возможности Feature Description --------- ------------- 🔍 **Comprehensive Linting** Полная поддержка правил buf с настраиваемыми профилями для лучших практик API‑дизайна. 📦 **Smart Package Manager** Git‑ориент","content":"Ключевые возможности Feature Description --------- ------------- 🔍 **Comprehensive Linting** Полная поддержка правил buf с настраиваемыми профилями для лучших практик API‑дизайна. 📦 **Smart Package Manager** Git‑ориентированное управление зависимостями с lock‑файлом для воспроизводимости. ⚡ **Code Generation** Многозадачная генерация кода с поддержкой локальных и удалённых protoc‑плагинов. 🔄 **Breaking Change Detection** Автоматическая проверка совместимости API против веток Git. 🌐 **Remote Plugin Support** Выполнение плагинов через централизованный EasyP API сервис без локальных установок. 🎯 **Developer Experience** Автодополнение, понятные ошибки, единая структура и документация."},{"id":"introduction/what-is::top::11","title":"Что такое EasyP?","section":"Типы поддерживаемых плагинов","path":"/docs/guide/introduction/what-is","headings":["Типы поддерживаемых плагинов"],"excerpt":"Типы поддерживаемых плагинов EasyP гибко подходит к выполнению генерации:","content":"Типы поддерживаемых плагинов EasyP гибко подходит к выполнению генерации:"},{"id":"introduction/what-is::local-plugins::12","title":"Что такое EasyP?","section":"Local Plugins","path":"/docs/guide/introduction/what-is#local-plugins","headings":["Local Plugins"],"excerpt":"Local Plugins Стандартные установленные protoc‑плагины:","content":"Local Plugins Стандартные установленные protoc‑плагины:"},{"id":"introduction/what-is::remote-plugins::13","title":"Что такое EasyP?","section":"Remote Plugins","path":"/docs/guide/introduction/what-is#remote-plugins","headings":["Remote Plugins"],"excerpt":"Remote Plugins Плагины через EasyP API сервис для воспроизводимости:","content":"Remote Plugins Плагины через EasyP API сервис для воспроизводимости:"},{"id":"introduction/what-is::custom-plugins::14","title":"Что такое EasyP?","section":"Custom Plugins","path":"/docs/guide/introduction/what-is#custom-plugins","headings":["Custom Plugins"],"excerpt":"Custom Plugins Поддержка экосистемы пользовательских расширений.","content":"Custom Plugins Поддержка экосистемы пользовательских расширений."},{"id":"introduction/what-is::top::15","title":"Что такое EasyP?","section":"Децентрализованный менеджмент пакетов","path":"/docs/guide/introduction/what-is","headings":["Децентрализованный менеджмент пакетов"],"excerpt":"Децентрализованный менеджмент пакетов В отличие от других решений EasyP не требует централизованного реестра. Любой Git‑репозиторий может быть источником:","content":"Децентрализованный менеджмент пакетов В отличие от других решений EasyP не требует централизованного реестра. Любой Git‑репозиторий может быть источником:"},{"id":"introduction/what-is::top::16","title":"Что такое EasyP?","section":"Децентрализованный менеджмент пакетов","path":"/docs/guide/introduction/what-is","headings":["Децентрализованный менеджмент пакетов"],"excerpt":"Децентрализованный менеджмент пакетов **Гибкость**: Любой Git‑хостинг (GitHub, GitLab, self‑hosted) **Нет vendor lock‑in**: Зависимости не привязаны к одному провайдеру **Полная история**: Ветки, теги, ревью **Enterprise","content":"Децентрализованный менеджмент пакетов **Гибкость**: Любой Git‑хостинг (GitHub, GitLab, self‑hosted) **Нет vendor lock‑in**: Зависимости не привязаны к одному провайдеру **Полная история**: Ветки, теги, ревью **Enterprise‑совместимость**: Поддержка приватных репозиториев"},{"id":"introduction/what-is::buf::17","title":"Что такое EasyP?","section":"Бесшовная миграция с Buf","path":"/docs/guide/introduction/what-is#buf","headings":["Бесшовная миграция с Buf"],"excerpt":"Бесшовная миграция с Buf EasyP изначально совместим с экосистемой buf:","content":"Бесшовная миграция с Buf EasyP изначально совместим с экосистемой buf:"},{"id":"introduction/what-is::buf::18","title":"Что такое EasyP?","section":"Бесшовная миграция с Buf","path":"/docs/guide/introduction/what-is#buf","headings":["Бесшовная миграция с Buf"],"excerpt":"Бесшовная миграция с Buf **Совпадающие rule sets** **Похожая структура YAML** **Минимальные изменения для замены** **Постепенное внедрение** без ломки текущего пайплайна","content":"Бесшовная миграция с Buf **Совпадающие rule sets** **Похожая структура YAML** **Минимальные изменения для замены** **Постепенное внедрение** без ломки текущего пайплайна"},{"id":"introduction/what-is::easyp-vs-bufbuild::19","title":"Что такое EasyP?","section":"EasyP vs buf.build","path":"/docs/guide/introduction/what-is#easyp-vs-bufbuild","headings":["EasyP vs buf.build"],"excerpt":"EasyP vs buf.build Feature EasyP buf.build --------- -------- ----------- **Dependency Management** Git‑репозитории Buf Schema Registry (BSR) **Vendor Lock-in** Нет Привязка к BSR для полного функционала **Plugin Executi","content":"EasyP vs buf.build Feature EasyP buf.build --------- -------- ----------- **Dependency Management** Git‑репозитории Buf Schema Registry (BSR) **Vendor Lock-in** Нет Привязка к BSR для полного функционала **Plugin Execution** Local + Remote Local + BSR plugins **Private Dependencies** Любой Git провайдер BSR или ручное управление **Offline Development** Полная поддержка (mod vendor) Ограниченно без доступа к BSR **Enterprise Integration** Использует существующий Git Требует настройку BSR **Breaking Change Detection** Против любой Git ссылки Аналогично **Package Distribution** Любой Git Публикация через BSR **License** Apache 2.0 Apache 2.0 **Community** Growing Established"},{"id":"introduction/what-is::easyp-vs-bufbuild::20","title":"Что такое EasyP?","section":"EasyP vs buf.build","path":"/docs/guide/introduction/what-is#easyp-vs-bufbuild","headings":["EasyP vs buf.build"],"excerpt":"EasyP vs buf.build **Преимущества миграции:** Без изменения инфраструктуры Плавное принятие новых возможностей Гибрид локальных и удалённых плагинов Единая конфигурация вместо набора файлов","content":"EasyP vs buf.build **Преимущества миграции:** Без изменения инфраструктуры Плавное принятие новых возможностей Гибрид локальных и удалённых плагинов Единая конфигурация вместо набора файлов"},{"id":"introduction/what-is::protobuf::21","title":"Что такое EasyP?","section":"Наши цели для Protobuf","path":"/docs/guide/introduction/what-is#protobuf","headings":["Наши цели для Protobuf"],"excerpt":"Наши цели для Protobuf Миссия EasyP — ускорить принятие **schema‑driven API** через удобный, надёжный и прозрачный инструментарий.","content":"Наши цели для Protobuf Миссия EasyP — ускорить принятие **schema‑driven API** через удобный, надёжный и прозрачный инструментарий."},{"id":"introduction/what-is::top::22","title":"Что такое EasyP?","section":"Современная экосистема","path":"/docs/guide/introduction/what-is","headings":["Современная экосистема"],"excerpt":"Современная экосистема Повышаем DX вокруг protobuf, чтобы конкурентно выглядеть по простоте против REST/JSON, сохраняя типовую строгость и производительность.","content":"Современная экосистема Повышаем DX вокруг protobuf, чтобы конкурентно выглядеть по простоте против REST/JSON, сохраняя типовую строгость и производительность."},{"id":"introduction/what-is::developer-experience::23","title":"Что такое EasyP?","section":"Developer Experience прежде всего","path":"/docs/guide/introduction/what-is#developer-experience","headings":["Developer Experience прежде всего"],"excerpt":"Developer Experience прежде всего Интуитивный CLI, понятные ошибки, ясные сообщения, минимальная фрагментация.","content":"Developer Experience прежде всего Интуитивный CLI, понятные ошибки, ясные сообщения, минимальная фрагментация."},{"id":"introduction/what-is::enterprise::24","title":"Что такое EasyP?","section":"Готов к Enterprise","path":"/docs/guide/introduction/what-is#enterprise","headings":["Готов к Enterprise"],"excerpt":"Готов к Enterprise Воспроизводимые сборки, приватные репозитории, интеграция в CI/CD.","content":"Готов к Enterprise Воспроизводимые сборки, приватные репозитории, интеграция в CI/CD."},{"id":"introduction/what-is::top::25","title":"Что такое EasyP?","section":"Для индивидуальных разработчиков","path":"/docs/guide/introduction/what-is","headings":["Для индивидуальных разработчиков"],"excerpt":"Для индивидуальных разработчиков Быстрый старт за минуты Один инструмент — меньше когнитивной нагрузки Понятная документация","content":"Для индивидуальных разработчиков Быстрый старт за минуты Один инструмент — меньше когнитивной нагрузки Понятная документация"},{"id":"introduction/what-is::top::26","title":"Что такое EasyP?","section":"Для команд","path":"/docs/guide/introduction/what-is","headings":["Для команд"],"excerpt":"Для команд Единые стандарты Повторяемые сборки (lock‑файл) Ускоренный онбординг","content":"Для команд Единые стандарты Повторяемые сборки (lock‑файл) Ускоренный онбординг"},{"id":"introduction/what-is::top::27","title":"Что такое EasyP?","section":"Для организаций","path":"/docs/guide/introduction/what-is","headings":["Для организаций"],"excerpt":"Для организаций Нет vendor lock‑in Безопасность приватных репозиториев Лёгкая интеграция в существующие пайплайны","content":"Для организаций Нет vendor lock‑in Безопасность приватных репозиториев Лёгкая интеграция в существующие пайплайны"},{"id":"introduction/what-is::top::28","title":"Что такое EasyP?","section":"Что дальше?","path":"/docs/guide/introduction/what-is","headings":["Что дальше?"],"excerpt":"Что дальше? EasyP упрощает работу с protobuf — фокусируйтесь на API, а не на рутине. Хотите начать?","content":"Что дальше? EasyP упрощает работу с protobuf — фокусируйтесь на API, а не на рутине. Хотите начать?"},{"id":"introduction/what-is::top::29","title":"Что такое EasyP?","section":"Что дальше?","path":"/docs/guide/introduction/what-is","headings":["Что дальше?"],"excerpt":"Что дальше? Смотрите Installation Guide и Quickstart.","content":"Что дальше? Смотрите Installation Guide и Quickstart."},{"id":"introduction/what-is::stargazers-over-time::30","title":"Что такое 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 В работе","content":"Buf CLI В работе"},{"id":"migration/protoc::top::0","title":"Миграция с protoc на EasyP","path":"/docs/guide/migration/protoc","headings":[],"excerpt":"Исходная англоязычная версия файла содержала только заголовок и пометку “Work in progress”. Ниже — полноценный русскоязычный черновик раздела миграции. Уточни, если требуется сократить или изменить уровень детализации.","content":"Исходная англоязычная версия файла содержала только заголовок и пометку “Work in progress”. Ниже — полноценный русскоязычный черновик раздела миграции. Уточни, если требуется сократить или изменить уровень детализации."},{"id":"migration/protoc::1::1","title":"Миграция с protoc на EasyP","section":"1. Краткое сравнение","path":"/docs/guide/migration/protoc#1","headings":["1. Краткое сравнение"],"excerpt":"Краткое сравнение Аспект protoc EasyP -------- ---------- ------- Базовая роль Базовый компилятор .proto файлов Инструмент “всё в одном”: линтинг, проверка несовместимых изменений, менеджер пакетов, генерация Конфигураци","content":"Краткое сравнение Аспект protoc EasyP -------- ---------- ------- Базовая роль Базовый компилятор .proto файлов Инструмент “всё в одном”: линтинг, проверка несовместимых изменений, менеджер пакетов, генерация Конфигурация Чаще shell‑скрипты / Makefile / вручную передаваемые флаги Единый файл easyp.yaml (YAML или JSON) Управление зависимостями Ручной git clone, submodule, vendoring Секция deps с Git‑репозиториями Набор правил линтера Нет встроенного Встроенный линтер с правилами (можно включать/исключать) Проверка breaking changes Отсутствует из коробки Команда easyp breaking Расширенные плагины Установка и вызов через флаги --plugin Плагины через конфиг; поддержка удалённого выполнения (API Service) и стандартного локального Единообразие в CI Нужно собирать вручную Консистентные команды: lint, breaking, generate"},{"id":"migration/protoc::2::2","title":"Миграция с protoc на EasyP","section":"2. Когда имеет смысл мигрировать","path":"/docs/guide/migration/protoc#2","headings":["2. Когда имеет смысл мигрировать"],"excerpt":"Когда имеет смысл мигрировать Миграция на EasyP особенно полезна если: Есть потребность в автоматической проверке качества (стиль, именование) .proto файлов. Нужна защита от нелегитимных несовместимых изменений при эволю","content":"Когда имеет смысл мигрировать Миграция на EasyP особенно полезна если: Есть потребность в автоматической проверке качества (стиль, именование) .proto файлов. Нужна защита от нелегитимных несовместимых изменений при эволюции схем. В проекте используется несколько языков генерации и растёт число скриптов вокруг protoc. Вы хотите единый конфиг вместо множества shell/Makefile комбинаций. Планируется централизованное исполнение плагинов (через API Service) или унификация окружения в CI."},{"id":"migration/protoc::3-protoc::3","title":"Миграция с protoc на EasyP","section":"3. Типичный сценарий “до” (только protoc)","path":"/docs/guide/migration/protoc#3-protoc","headings":["3. Типичный сценарий “до” (только protoc)"],"excerpt":"Типичный сценарий “до” (только protoc) Пример: локальные скрипты / Makefile:","content":"Типичный сценарий “до” (только protoc) Пример: локальные скрипты / Makefile:"},{"id":"migration/protoc::3-protoc::4","title":"Миграция с protoc на EasyP","section":"3. Типичный сценарий “до” (только protoc)","path":"/docs/guide/migration/protoc#3-protoc","headings":["3. Типичный сценарий “до” (только protoc)"],"excerpt":"Типичный сценарий “до” (только protoc)","content":"Типичный сценарий “до” (только protoc)"},{"id":"migration/protoc::3-protoc::5","title":"Миграция с protoc на EasyP","section":"3. Типичный сценарий “до” (только protoc)","path":"/docs/guide/migration/protoc#3-protoc","headings":["3. Типичный сценарий “до” (только protoc)"],"excerpt":"Типичный сценарий “до” (только protoc) Дополнительные зависимости (googleapis, validate, grpc-gateway) скачиваются вручную или через submodules.","content":"Типичный сценарий “до” (только protoc) Дополнительные зависимости (googleapis, validate, grpc-gateway) скачиваются вручную или через submodules."},{"id":"migration/protoc::4-easyp::6","title":"Миграция с protoc на EasyP","section":"4. Типичный сценарий “после” (EasyP)","path":"/docs/guide/migration/protoc#4-easyp","headings":["4. Типичный сценарий “после” (EasyP)"],"excerpt":"Типичный сценарий “после” (EasyP) Единый файл easyp.yaml:","content":"Типичный сценарий “после” (EasyP) Единый файл easyp.yaml:"},{"id":"migration/protoc::4-easyp::7","title":"Миграция с protoc на EasyP","section":"4. Типичный сценарий “после” (EasyP)","path":"/docs/guide/migration/protoc#4-easyp","headings":["4. Типичный сценарий “после” (EasyP)"],"excerpt":"Типичный сценарий “после” (EasyP) ```yaml deps: - github.com/googleapis/googleapis - github.com/envoyproxy/protoc-gen-validate","content":"Типичный сценарий “после” (EasyP) ```yaml deps: - github.com/googleapis/googleapis - github.com/envoyproxy/protoc-gen-validate"},{"id":"migration/protoc::4-easyp::8","title":"Миграция с protoc на EasyP","section":"4. Типичный сценарий “после” (EasyP)","path":"/docs/guide/migration/protoc#4-easyp","headings":["4. Типичный сценарий “после” (EasyP)"],"excerpt":"Типичный сценарий “после” (EasyP) generate: plugins: - name: go out: gen/go opts: paths: source_relative - name: go-grpc out: gen/go opts: paths: source_relative require_unimplemented_servers: false - name: validate out:","content":"Типичный сценарий “после” (EasyP) generate: plugins: - name: go out: gen/go opts: paths: source_relative - name: go-grpc out: gen/go opts: paths: source_relative require_unimplemented_servers: false - name: validate out: gen/go opts: paths: source_relative lang: \"go\" ```"},{"id":"migration/protoc::4-easyp::9","title":"Миграция с protoc на EasyP","section":"4. Типичный сценарий “после” (EasyP)","path":"/docs/guide/migration/protoc#4-easyp","headings":["4. Типичный сценарий “после” (EasyP)"],"excerpt":"Типичный сценарий “после” (EasyP) Команды:","content":"Типичный сценарий “после” (EasyP) Команды:"},{"id":"migration/protoc::5::10","title":"Миграция с protoc на EasyP","section":"5. Пошаговая миграция","path":"/docs/guide/migration/protoc#5","headings":["5. Пошаговая миграция"],"excerpt":"Пошаговая миграция Инвентаризация: - Соберите список всех вызовов protoc (скрипты, Makefile, CI). - Зафиксируйте используемые плагины и их версии. Создание easyp.yaml: - Поле version не обязательно (можете оставить его т","content":"Пошаговая миграция Инвентаризация: - Соберите список всех вызовов protoc (скрипты, Makefile, CI). - Зафиксируйте используемые плагины и их версии. Создание easyp.yaml: - Поле version не обязательно (можете оставить его только для обратной совместимости). - Перенесите плагины в секцию generate.plugins. - Укажите опции, которые ранее передавались в командной строке. Зависимости: - Все внешние каталоги (googleapis, validate, grpc-gateway и т.п.) занесите в deps. - Удалите лишние submodules при необходимости. Линтер: - Запустите easyp lint и посмотрите на предупреждения. - При необходимости добавьте lint.use, lint.ignore, lint.except. Проверка breaking changes: - Выберите референс (обычно origin/main или предыдущий тег). - Запустите easyp breaking --against git-ref=origin/main. - Настройте игнорируемые изменения (breaking.ignore), если нужно. Обновление CI: - Замените прямые вызовы protoc на easyp generate. - Добавьте отдельные шаги lint и breaking. Очистка: - Удалите устаревшие генерационные скрипты, если они дублируют функционал EasyP. Документация: - Обновите README / CONTRIBUTING (новый способ генерации). Верификация: - Сравните результат генерации до и после (git diff). - Убедитесь, что имена файлов и пути совпадают или скорректируйте структуру."},{"id":"migration/protoc::6-ci-github-actions::11","title":"Миграция с protoc на EasyP","section":"6. Замена в CI (пример GitHub Actions)","path":"/docs/guide/migration/protoc#6-ci-github-actions","headings":["6. Замена в CI (пример GitHub Actions)"],"excerpt":"Замена в CI (пример GitHub Actions) ```yaml name: Install EasyP run: go install github.com/easyp-tech/easyp/cmd/easyp@latest","content":"Замена в CI (пример GitHub Actions) ```yaml name: Install EasyP run: go install github.com/easyp-tech/easyp/cmd/easyp@latest"},{"id":"migration/protoc::6-ci-github-actions::12","title":"Миграция с protoc на EasyP","section":"6. Замена в CI (пример GitHub Actions)","path":"/docs/guide/migration/protoc#6-ci-github-actions","headings":["6. Замена в CI (пример GitHub Actions)"],"excerpt":"Замена в CI (пример GitHub Actions) name: Lint run: easyp lint","content":"Замена в CI (пример GitHub Actions) name: Lint run: easyp lint"},{"id":"migration/protoc::6-ci-github-actions::13","title":"Миграция с protoc на EasyP","section":"6. Замена в CI (пример GitHub Actions)","path":"/docs/guide/migration/protoc#6-ci-github-actions","headings":["6. Замена в CI (пример GitHub Actions)"],"excerpt":"Замена в CI (пример GitHub Actions) name: Breaking run: easyp breaking --against git-ref=origin/main","content":"Замена в CI (пример GitHub Actions) name: Breaking run: easyp breaking --against git-ref=origin/main"},{"id":"migration/protoc::6-ci-github-actions::14","title":"Миграция с protoc на EasyP","section":"6. Замена в CI (пример GitHub Actions)","path":"/docs/guide/migration/protoc#6-ci-github-actions","headings":["6. Замена в CI (пример GitHub Actions)"],"excerpt":"Замена в CI (пример GitHub Actions) name: Generate run: easyp generate ```","content":"Замена в CI (пример GitHub Actions) name: Generate run: easyp generate ```"},{"id":"migration/protoc::7::15","title":"Миграция с protoc на EasyP","section":"7. Работа с плагинами","path":"/docs/guide/migration/protoc#7","headings":["7. Работа с плагинами"],"excerpt":"Работа с плагинами Тип В protoc В EasyP ----- ---------- --------- Стандартные (protoc-gen-go) Указание через --go_out plugins: - name: go ... gRPC --go-grpc_out Второй плагин go-grpc Validate Доп. установка + --validate","content":"Работа с плагинами Тип В protoc В EasyP ----- ---------- --------- Стандартные (protoc-gen-go) Указание через --go_out plugins: - name: go ... gRPC --go-grpc_out Второй плагин go-grpc Validate Доп. установка + --validate_out - name: validate с opts gRPC-Gateway / OpenAPI --grpc-gateway_out / --openapiv2_out Плагины grpc-gateway, openapiv2 Кастомные Путь к бинарю / --plugin=protoc-gen-xxx - name: xxx или удалённый remote: (если используется API Service)"},{"id":"migration/protoc::7::16","title":"Миграция с protoc на EasyP","section":"7. Работа с плагинами","path":"/docs/guide/migration/protoc#7","headings":["7. Работа с плагинами"],"excerpt":"Работа с плагинами Если вы переходите на удалённое выполнение (API Service), записи в конфиге могут выглядеть так:","content":"Работа с плагинами Если вы переходите на удалённое выполнение (API Service), записи в конфиге могут выглядеть так:"},{"id":"migration/protoc::8::17","title":"Миграция с protoc на EasyP","section":"8. Проверка корректности после миграции","path":"/docs/guide/migration/protoc#8","headings":["8. Проверка корректности после миграции"],"excerpt":"Проверка корректности после миграции git diff после easyp generate — не должно быть неожиданных изменений. Сравнить размер и содержимое каталога сгенерированных файлов. Запустить ваш потребляющий код (сборка, тесты). Про","content":"Проверка корректности после миграции git diff после easyp generate — не должно быть неожиданных изменений. Сравнить размер и содержимое каталога сгенерированных файлов. Запустить ваш потребляющий код (сборка, тесты). Проверить, что плагины (validate, grpc-gateway) продолжают вставлять необходимые аннотации / опции. Линт не должен выдавать критичных ошибок — скорректируйте стиль .proto, если требуется."},{"id":"migration/protoc::9::18","title":"Миграция с protoc на EasyP","section":"9. Частые проблемы","path":"/docs/guide/migration/protoc#9","headings":["9. Частые проблемы"],"excerpt":"Частые проблемы Проблема Причина Решение ---------- --------- --------- Плагин не найден Не установлен или не указан в PATH Выполнить go install ... или добавить в конфиг как remote Ошибка импорта .proto Отсутствует репо","content":"Частые проблемы Проблема Причина Решение ---------- --------- --------- Плагин не найден Не установлен или не указан в PATH Выполнить go install ... или добавить в конфиг как remote Ошибка импорта .proto Отсутствует репозиторий в deps Добавить адрес в секцию deps и easyp mod update Несовместимые изменения на каждом PR Отсутствует игнор/настройка сравнения Уточнить ветку/тег в --against или настроить breaking.ignore Локально работает, в CI падает В CI нет зависимостей (не вызван update) Добавить шаг easyp mod update перед generate Дубликаты сгенерированных файлов Изменена структура путей или out Синхронизировать out и paths: source_relative опции"},{"id":"migration/protoc::10-go::19","title":"Миграция с protoc на EasyP","section":"10. Минимальный пример конфигурации (только Go)","path":"/docs/guide/migration/protoc#10-go","headings":["10. Минимальный пример конфигурации (только Go)"],"excerpt":"Минимальный пример конфигурации (только Go)","content":"Минимальный пример конфигурации (только Go)"},{"id":"migration/protoc::10-go::20","title":"Миграция с protoc на EasyP","section":"10. Минимальный пример конфигурации (только Go)","path":"/docs/guide/migration/protoc#10-go","headings":["10. Минимальный пример конфигурации (только Go)"],"excerpt":"Минимальный пример конфигурации (только Go) Команды:","content":"Минимальный пример конфигурации (только Go) Команды:"},{"id":"migration/protoc::11-go-grpc-gateway-validate-breaking-lint::21","title":"Миграция с protoc на EasyP","section":"11. Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint)","path":"/docs/guide/migration/protoc#11-go-grpc-gateway-validate-breaking-lint","headings":["11. Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint)"],"excerpt":"Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint) ```yaml lint: use: - ENUM_FIRST_VALUE_ZERO - SERVICE_SUFFIX allow_comment_ignores: false enum_zero_value_suffix: _NONE service_suffix: Service","content":"Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint) ```yaml lint: use: - ENUM_FIRST_VALUE_ZERO - SERVICE_SUFFIX allow_comment_ignores: false enum_zero_value_suffix: _NONE service_suffix: Service"},{"id":"migration/protoc::11-go-grpc-gateway-validate-breaking-lint::22","title":"Миграция с protoc на EasyP","section":"11. Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint)","path":"/docs/guide/migration/protoc#11-go-grpc-gateway-validate-breaking-lint","headings":["11. Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint)"],"excerpt":"Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint) deps: - github.com/googleapis/googleapis - github.com/envoyproxy/protoc-gen-validate","content":"Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint) deps: - github.com/googleapis/googleapis - github.com/envoyproxy/protoc-gen-validate"},{"id":"migration/protoc::11-go-grpc-gateway-validate-breaking-lint::23","title":"Миграция с protoc на EasyP","section":"11. Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint)","path":"/docs/guide/migration/protoc#11-go-grpc-gateway-validate-breaking-lint","headings":["11. Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint)"],"excerpt":"Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint) generate: plugins: - name: go out: gen/go opts: paths: source_relative - name: go-grpc out: gen/go opts: paths: source_relative require_unimplemented_","content":"Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint) generate: plugins: - name: go out: gen/go opts: paths: source_relative - name: go-grpc out: gen/go opts: paths: source_relative require_unimplemented_servers: false - name: validate out: gen/go opts: paths: source_relative lang: \"go\" - name: grpc-gateway out: gen/go opts: paths: source_relative - name: openapiv2 out: gen/openapi opts: simple_operation_ids: true"},{"id":"migration/protoc::11-go-grpc-gateway-validate-breaking-lint::24","title":"Миграция с protoc на EasyP","section":"11. Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint)","path":"/docs/guide/migration/protoc#11-go-grpc-gateway-validate-breaking-lint","headings":["11. Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint)"],"excerpt":"Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint) breaking: against_git_ref: main ignore: - ENUM_VALUE_SAME_NAME ```","content":"Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint) breaking: against_git_ref: main ignore: - ENUM_VALUE_SAME_NAME ```"},{"id":"migration/protoc::12-checklist::25","title":"Миграция с protoc на EasyP","section":"12. Checklist миграции","path":"/docs/guide/migration/protoc#12-checklist","headings":["12. Checklist миграции"],"excerpt":"Checklist миграции [ ] Собраны все текущие вызовы protoc. [ ] Создан easyp.yaml с секциями generate и (опционально) lint, breaking. [ ] Добавлены все внешние зависимости в deps. [ ] Успешно выполнен easyp mod update. [ ]","content":"Checklist миграции [ ] Собраны все текущие вызовы protoc. [ ] Создан easyp.yaml с секциями generate и (опционально) lint, breaking. [ ] Добавлены все внешние зависимости в deps. [ ] Успешно выполнен easyp mod update. [ ] easyp generate даёт идентичный или ожидаемо обновлённый результат. [ ] easyp lint проходит без критичных ошибок (или ошибки обработаны). [ ] easyp breaking --against git-ref=origin/main не выдаёт неожиданных блокирующих нарушений. [ ] CI обновлён (заменены прямые вызовы protoc). [ ] Документация проекта обновлена (README: как генерировать)."},{"id":"migration/protoc::13::26","title":"Миграция с protoc на EasyP","section":"13. Дополнительные рекомендации","path":"/docs/guide/migration/protoc#13","headings":["13. Дополнительные рекомендации"],"excerpt":"Дополнительные рекомендации Сначала мигрируйте один сервис / пакет — снизит риск массовых конфликтов. Закоммитьте easyp.yaml отдельно, затем выполните генерацию и линт — проще ревью. Если нужны разные наборы плагинов для","content":"Дополнительные рекомендации Сначала мигрируйте один сервис / пакет — снизит риск массовых конфликтов. Закоммитьте easyp.yaml отдельно, затем выполните генерацию и линт — проще ревью. Если нужны разные наборы плагинов для разных микросервисов — используйте несколько конфигов (например: easyp.microservice-a.yaml + easyp.microservice-b.yaml). Внедрите проверку актуальности генерации: шаг CI, который валидирует отсутствие diff после easyp generate."},{"id":"migration/protoc::14::27","title":"Миграция с protoc на EasyP","section":"14. Статус","path":"/docs/guide/migration/protoc#14","headings":["14. Статус"],"excerpt":"Статус Этот файл — русская расширенная версия, заменяющая placeholder “Work in progress”. При появлении новых возможностей EasyP (дополнительные поля в конфиге, новые плагины, расширения breaking‑проверок) обновите соотв","content":"Статус Этот файл — русская расширенная версия, заменяющая placeholder “Work in progress”. При появлении новых возможностей EasyP (дополнительные поля в конфиге, новые плагины, расширения breaking‑проверок) обновите соответствующие разделы."},{"id":"migration/protoc::14::28","title":"Миграция с protoc на EasyP","section":"14. Статус","path":"/docs/guide/migration/protoc#14","headings":["14. Статус"],"excerpt":"Статус Если нужен упрощённый вариант (только перевод без расширения), сообщи — могу сократить до минимальных двух блоков.","content":"Статус Если нужен упрощённый вариант (только перевод без расширения), сообщи — могу сократить до минимальных двух блоков."},{"id":"migration/protolock::top::0","title":"Protolock","path":"/docs/guide/migration/protolock","headings":[],"excerpt":"Protolock В процессе разработки","content":"Protolock В процессе разработки"},{"id":"migration/prototool::top::0","title":"Prototool","section":"Состояние","path":"/docs/guide/migration/prototool","headings":["Состояние"],"excerpt":"Состояние Этот раздел был помечен как “Work in progress” в оригинальной английской версии. Ниже — переведённое и дополненное практическое руководство по миграции с Prototool на EasyP. Имя инструмента Prototool не перевод","content":"Состояние Этот раздел был помечен как “Work in progress” в оригинальной английской версии. Ниже — переведённое и дополненное практическое руководство по миграции с Prototool на EasyP. Имя инструмента Prototool не переводится."},{"id":"migration/prototool::top::1","title":"Prototool","section":"Цель миграции","path":"/docs/guide/migration/prototool","headings":["Цель миграции"],"excerpt":"Цель миграции Перейти от конфигурации и рабочих процессов Prototool к эквиваленту на EasyP с минимальными изменениями, сохранив: Линтинг .proto файлов. Генерацию кода через protoc-плагины. Управление зависимостями. Прове","content":"Цель миграции Перейти от конфигурации и рабочих процессов Prototool к эквиваленту на EasyP с минимальными изменениями, сохранив: Линтинг .proto файлов. Генерацию кода через protoc-плагины. Управление зависимостями. Проверку несовместимых изменений (в Prototool это приходилось реализовывать внешними инструментами; в EasyP встроено)."},{"id":"migration/prototool::top::2","title":"Prototool","section":"Кратко о различиях","path":"/docs/guide/migration/prototool","headings":["Кратко о различиях"],"excerpt":"Кратко о различиях Область Prototool EasyP Комментарий --------- ----------- ------- ------------- Конфигурация prototool.yaml easyp.yaml Форматы YAML/JSON поддерживаются; структура отличается. Линтинг Встроенные наборы ","content":"Кратко о различиях Область Prototool EasyP Комментарий --------- ----------- ------- ------------- Конфигурация prototool.yaml easyp.yaml Форматы YAML/JSON поддерживаются; структура отличается. Линтинг Встроенные наборы + кастомные правила Наборы через lint.use, тонкая настройка ignore/except EasyP даёт больше гибкости группировки. Генерация Раздел generate + плагины через Docker/локально generate.plugins (локальные/WASM/удалённые) EasyP может выполнять плагины удалённо (API Service). Зависимости Обычно через include-пути / внешние git clone вручную Секция deps (Git репозитории) + mod update Более декларативно. Breaking Changes Нет встроенного механизма Секция breaking + команда easyp breaking Из коробки. Lock-in Зависимость от модели Prototool Минималистичный формат, «любой Git — пакет» Облегчает выход / интеграцию с другими экосистемами."},{"id":"migration/prototool::prototool::3","title":"Prototool","section":"Типовая структура Prototool (упрощённо)","path":"/docs/guide/migration/prototool#prototool","headings":["Типовая структура Prototool (упрощённо)"],"excerpt":"Типовая структура Prototool (упрощённо)","content":"Типовая структура Prototool (упрощённо)"},{"id":"migration/prototool::prototool::4","title":"Prototool","section":"Типовая структура Prototool (упрощённо)","path":"/docs/guide/migration/prototool#prototool","headings":["Типовая структура Prototool (упрощённо)"],"excerpt":"Типовая структура Prototool (упрощённо) Особенности: include_paths задаёт пути поиска импортов. lint.group + rules.add/remove регулируют активные проверки. generate.plugins описывает плагины для protoc.","content":"Типовая структура Prototool (упрощённо) Особенности: include_paths задаёт пути поиска импортов. lint.group + rules.add/remove регулируют активные проверки. generate.plugins описывает плагины для protoc."},{"id":"migration/prototool::prototool::5","title":"Prototool","section":"Типовая структура Prototool (упрощённо)","path":"/docs/guide/migration/prototool#prototool","headings":["Типовая структура Prototool (упрощённо)"],"excerpt":"Типовая структура Prototool (упрощённо) ---","content":"Типовая структура Prototool (упрощённо) ---"},{"id":"migration/prototool::easyp::6","title":"Prototool","section":"Эквивалент на EasyP","path":"/docs/guide/migration/prototool#easyp","headings":["Эквивалент на EasyP"],"excerpt":"Эквивалент на EasyP ```yaml easyp.yaml (пример) deps: - github.com/org/common-protos # вместо manual include - github.com/org/third-party-protos","content":"Эквивалент на EasyP ```yaml easyp.yaml (пример) deps: - github.com/org/common-protos # вместо manual include - github.com/org/third-party-protos"},{"id":"migration/prototool::easyp::7","title":"Prototool","section":"Эквивалент на EasyP","path":"/docs/guide/migration/prototool#easyp","headings":["Эквивалент на EasyP"],"excerpt":"Эквивалент на EasyP lint: use: - MINIMAL - BASIC enum_zero_value_suffix: \"_NONE\" service_suffix: \"Service\" ignore: - COMMENT_FIELD except: - ENUM_VALUE_PREFIX allow_comment_ignores: true","content":"Эквивалент на EasyP lint: use: - MINIMAL - BASIC enum_zero_value_suffix: \"_NONE\" service_suffix: \"Service\" ignore: - COMMENT_FIELD except: - ENUM_VALUE_PREFIX allow_comment_ignores: true"},{"id":"migration/prototool::easyp::8","title":"Prototool","section":"Эквивалент на EasyP","path":"/docs/guide/migration/prototool#easyp","headings":["Эквивалент на EasyP"],"excerpt":"Эквивалент на EasyP generate: plugins: - name: go out: gen/go opts: paths: source_relative - name: go-grpc out: gen/go opts: paths: source_relative require_unimplemented_servers: false","content":"Эквивалент на EasyP generate: plugins: - name: go out: gen/go opts: paths: source_relative - name: go-grpc out: gen/go opts: paths: source_relative require_unimplemented_servers: false"},{"id":"migration/prototool::easyp::9","title":"Prototool","section":"Эквивалент на EasyP","path":"/docs/guide/migration/prototool#easyp","headings":["Эквивалент на EasyP"],"excerpt":"Эквивалент на EasyP breaking: against_git_ref: main ignore: - FIELD_SAME_TYPE ```","content":"Эквивалент на EasyP breaking: against_git_ref: main ignore: - FIELD_SAME_TYPE ```"},{"id":"migration/prototool::easyp::10","title":"Prototool","section":"Эквивалент на EasyP","path":"/docs/guide/migration/prototool#easyp","headings":["Эквивалент на EasyP"],"excerpt":"Эквивалент на EasyP Комментарии: deps заменяет необходимость вручную прописывать include paths: EasyP подтянет их через git. lint.use активирует наборы правил (MINIMAL/BASIC/DEFAULT и т.д.). Дополнительные настройки (enu","content":"Эквивалент на EasyP Комментарии: deps заменяет необходимость вручную прописывать include paths: EasyP подтянет их через git. lint.use активирует наборы правил (MINIMAL/BASIC/DEFAULT и т.д.). Дополнительные настройки (enum_zero_value_suffix, service_suffix) задают политики нейминга. breaking позволяет сразу контролировать несовместимые изменения."},{"id":"migration/prototool::top::11","title":"Prototool","section":"Шаги миграции","path":"/docs/guide/migration/prototool","headings":["Шаги миграции"],"excerpt":"Шаги миграции Инвентаризация: - Соберите текущий prototool.yaml, списки include paths и плагины. - Зафиксируйте используемые кастомные правила, если есть.","content":"Шаги миграции Инвентаризация: - Соберите текущий prototool.yaml, списки include paths и плагины. - Зафиксируйте используемые кастомные правила, если есть."},{"id":"migration/prototool::top::12","title":"Prototool","section":"Шаги миграции","path":"/docs/guide/migration/prototool","headings":["Шаги миграции"],"excerpt":"Шаги миграции Зависимости: - Любые каталоги, которые вы вручную добавляли в include_paths, преобразуйте в git-репозитории (если ещё нет). - Добавьте их в deps (формат: github.com/owner/repo или путь к вашей приватной сис","content":"Шаги миграции Зависимости: - Любые каталоги, которые вы вручную добавляли в include_paths, преобразуйте в git-репозитории (если ещё нет). - Добавьте их в deps (формат: github.com/owner/repo или путь к вашей приватной системе Git)."},{"id":"migration/prototool::top::13","title":"Prototool","section":"Шаги миграции","path":"/docs/guide/migration/prototool","headings":["Шаги миграции"],"excerpt":"Шаги миграции Линтинг: - Определите какой group использовался (basic, default, …) → сопоставьте с наборами EasyP (MINIMAL, BASIC, DEFAULT). - Индивидуальные добавления (rules.add) перенесите в lint.use или except/ignore:","content":"Шаги миграции Линтинг: - Определите какой group использовался (basic, default, …) → сопоставьте с наборами EasyP (MINIMAL, BASIC, DEFAULT). - Индивидуальные добавления (rules.add) перенесите в lint.use или except/ignore: - Если правило нужно активировать — включите через набор или явно. - Если нужно отключить — добавьте в ignore."},{"id":"migration/prototool::top::14","title":"Prototool","section":"Шаги миграции","path":"/docs/guide/migration/prototool","headings":["Шаги миграции"],"excerpt":"Шаги миграции Генерация: - Сохраните список плагинов. В большинстве случаев имена совпадут (go, go-grpc, др.). - Если раньше использовали Docker-окружение Prototool — проверьте поддержку удалённых плагинов через API Serv","content":"Шаги миграции Генерация: - Сохраните список плагинов. В большинстве случаев имена совпадут (go, go-grpc, др.). - Если раньше использовали Docker-окружение Prototool — проверьте поддержку удалённых плагинов через API Service EasyP (опционально). - Перепишите в секцию generate.plugins."},{"id":"migration/prototool::top::15","title":"Prototool","section":"Шаги миграции","path":"/docs/guide/migration/prototool","headings":["Шаги миграции"],"excerpt":"Шаги миграции Дополнительные опции: - Настройки нейминга enum/service перенести в enum_zero_value_suffix, service_suffix. - Если были внешние скрипты для проверки breaking changes — удалите их и включите breaking с again","content":"Шаги миграции Дополнительные опции: - Настройки нейминга enum/service перенести в enum_zero_value_suffix, service_suffix. - Если были внешние скрипты для проверки breaking changes — удалите их и включите breaking с against_git_ref."},{"id":"migration/prototool::top::16","title":"Prototool","section":"Шаги миграции","path":"/docs/guide/migration/prototool","headings":["Шаги миграции"],"excerpt":"Шаги миграции Верификация: - Запустите: easyp mod update (скачивание deps). - Затем: easyp lint. - Далее: easyp generate. - И, если нужно: easyp breaking --against git-ref=origin/main.","content":"Шаги миграции Верификация: - Запустите: easyp mod update (скачивание deps). - Затем: easyp lint. - Далее: easyp generate. - И, если нужно: easyp breaking --against git-ref=origin/main."},{"id":"migration/prototool::top::17","title":"Prototool","section":"Шаги миграции","path":"/docs/guide/migration/prototool","headings":["Шаги миграции"],"excerpt":"Шаги миграции CI/CD: - Обновите workflow (GitHub Actions / GitLab) — замените вызовы Prototool на EasyP команды. - Добавьте шаг проверки несовместимых изменений.","content":"Шаги миграции CI/CD: - Обновите workflow (GitHub Actions / GitLab) — замените вызовы Prototool на EasyP команды. - Добавьте шаг проверки несовместимых изменений."},{"id":"migration/prototool::top::18","title":"Prototool","section":"Сопоставление правил (общая идея)","path":"/docs/guide/migration/prototool","headings":["Сопоставление правил (общая идея)"],"excerpt":"Сопоставление правил (общая идея) Prototool концепт EasyP ------------------- ------ lint.group lint.use (наборы) rules.add/remove except / ignore include_paths deps (git источники) plugins generate.plugins (внешние скри","content":"Сопоставление правил (общая идея) Prototool концепт EasyP ------------------- ------ lint.group lint.use (наборы) rules.add/remove except / ignore include_paths deps (git источники) plugins generate.plugins (внешние скрипты для breaking) breaking секция + команда"},{"id":"migration/prototool::top::19","title":"Prototool","section":"Сопоставление правил (общая идея)","path":"/docs/guide/migration/prototool","headings":["Сопоставление правил (общая идея)"],"excerpt":"Сопоставление правил (общая идея) ---","content":"Сопоставление правил (общая идея) ---"},{"id":"migration/prototool::top::20","title":"Prototool","section":"Приватные репозитории","path":"/docs/guide/migration/prototool","headings":["Приватные репозитории"],"excerpt":"Приватные репозитории Если ранее Prototool просто видел локальные каталоги, теперь: Добавьте SSH ключи/токены в CI для доступа к приватным Git. Укажите их в deps как обычные git-URL (формат зависит от реализации EasyP; д","content":"Приватные репозитории Если ранее Prototool просто видел локальные каталоги, теперь: Добавьте SSH ключи/токены в CI для доступа к приватным Git. Укажите их в deps как обычные git-URL (формат зависит от реализации EasyP; для публичных — стандартный)."},{"id":"migration/prototool::top::21","title":"Prototool","section":"Типовые проблемы при миграции","path":"/docs/guide/migration/prototool","headings":["Типовые проблемы при миграции"],"excerpt":"Типовые проблемы при миграции Проблема Причина Решение ---------- --------- --------- Правила линтера не совпадают Неверное сопоставление групп Проверить документацию EasyP по наборам правил Импорты не находятся Забыли д","content":"Типовые проблемы при миграции Проблема Причина Решение ---------- --------- --------- Правила линтера не совпадают Неверное сопоставление групп Проверить документацию EasyP по наборам правил Импорты не находятся Забыли добавить репозиторий в deps Добавить в deps и выполнить easyp mod update Генерация падает на опциях Плагин требует другие flags Проверить opts и документацию плагина breaking сообщает слишком много Слишком строгий базовый набор Добавить конкретные правила в breaking.ignore Долгая генерация Нет кеша/много deps Включить кэширование в CI (vendor/.easyp/deps)"},{"id":"migration/prototool::top::22","title":"Prototool","section":"Типовые проблемы при миграции","path":"/docs/guide/migration/prototool","headings":["Типовые проблемы при миграции"],"excerpt":"Типовые проблемы при миграции ---","content":"Типовые проблемы при миграции ---"},{"id":"migration/prototool::top::23","title":"Prototool","section":"Минимальная конфигурация после миграции","path":"/docs/guide/migration/prototool","headings":["Минимальная конфигурация после миграции"],"excerpt":"Минимальная конфигурация после миграции","content":"Минимальная конфигурация после миграции"},{"id":"migration/prototool::top::24","title":"Prototool","section":"Минимальная конфигурация после миграции","path":"/docs/guide/migration/prototool","headings":["Минимальная конфигурация после миграции"],"excerpt":"Минимальная конфигурация после миграции ---","content":"Минимальная конфигурация после миграции ---"},{"id":"migration/prototool::top::25","title":"Prototool","section":"Рекомендации по упрощению","path":"/docs/guide/migration/prototool","headings":["Рекомендации по упрощению"],"excerpt":"Рекомендации по упрощению Начните с минимального lint.use (MINIMAL), затем постепенно включайте дополнительные наборы. Не переносите слепо все ignore — часть правил может уже быть улучшена в EasyP. Сначала настроить deps","content":"Рекомендации по упрощению Начните с минимального lint.use (MINIMAL), затем постепенно включайте дополнительные наборы. Не переносите слепо все ignore — часть правил может уже быть улучшена в EasyP. Сначала настроить deps и генерацию, затем усложнять линт/нейминг. Фиксируйте миграцию по шагам (коммиты: deps → lint → generate → breaking → CI)."},{"id":"migration/prototool::top::26","title":"Prototool","section":"Проверка результата","path":"/docs/guide/migration/prototool","headings":["Проверка результата"],"excerpt":"Проверка результата Скрипт локальной быстрой проверки (пример):","content":"Проверка результата Скрипт локальной быстрой проверки (пример):"},{"id":"migration/prototool::top::27","title":"Prototool","section":"Проверка результата","path":"/docs/guide/migration/prototool","headings":["Проверка результата"],"excerpt":"Проверка результата ```bash #!/usr/bin/env bash set -euo pipefail","content":"Проверка результата ```bash #!/usr/bin/env bash set -euo pipefail"},{"id":"migration/prototool::top::28","title":"Prototool","section":"Проверка результата","path":"/docs/guide/migration/prototool","headings":["Проверка результата"],"excerpt":"Проверка результата echo \"[1] deps update\" easyp mod update","content":"Проверка результата echo \"[1] deps update\" easyp mod update"},{"id":"migration/prototool::top::29","title":"Prototool","section":"Проверка результата","path":"/docs/guide/migration/prototool","headings":["Проверка результата"],"excerpt":"Проверка результата echo \"[2] lint\" easyp lint","content":"Проверка результата echo \"[2] lint\" easyp lint"},{"id":"migration/prototool::top::30","title":"Prototool","section":"Проверка результата","path":"/docs/guide/migration/prototool","headings":["Проверка результата"],"excerpt":"Проверка результата echo \"[3] breaking vs main\" easyp breaking --against git-ref=origin/main echo \"Breaking changes detected (review needed)\"","content":"Проверка результата echo \"[3] breaking vs main\" easyp breaking --against git-ref=origin/main echo \"Breaking changes detected (review needed)\""},{"id":"migration/prototool::top::31","title":"Prototool","section":"Проверка результата","path":"/docs/guide/migration/prototool","headings":["Проверка результата"],"excerpt":"Проверка результата echo \"[4] generate\" easyp generate","content":"Проверка результата echo \"[4] generate\" easyp generate"},{"id":"migration/prototool::top::32","title":"Prototool","section":"Проверка результата","path":"/docs/guide/migration/prototool","headings":["Проверка результата"],"excerpt":"Проверка результата echo \"Done.\" ```","content":"Проверка результата echo \"Done.\" ```"},{"id":"migration/prototool::top::33","title":"Prototool","section":"Заключение","path":"/docs/guide/migration/prototool","headings":["Заключение"],"excerpt":"Заключение Миграция с Prototool на EasyP сводится к: Переносу путей и внешних каталогов в декларативные deps. Переформатированию линта под lint.use + ignore/except. Переносу генерации в generate.plugins. Добавлению встро","content":"Заключение Миграция с Prototool на EasyP сводится к: Переносу путей и внешних каталогов в декларативные deps. Переформатированию линта под lint.use + ignore/except. Переносу генерации в generate.plugins. Добавлению встроенного механизма breaking. Адаптации CI."},{"id":"migration/prototool::top::34","title":"Prototool","section":"Заключение","path":"/docs/guide/migration/prototool","headings":["Заключение"],"excerpt":"Заключение После этого конфигурация становится более прозрачной, а проверка несовместимых изменений — из коробки.","content":"Заключение После этого конфигурация становится более прозрачной, а проверка несовместимых изменений — из коробки."},{"id":"migration/prototool::top::35","title":"Prototool","section":"Заключение","path":"/docs/guide/migration/prototool","headings":["Заключение"],"excerpt":"Заключение *Готово: базовый перевод и расширенное руководство по миграции с Prototool на EasyP.*","content":"Заключение *Готово: базовый перевод и расширенное руководство по миграции с Prototool на EasyP.*"},{"id":"TRANSLATION_STATUS::top::0","title":"Translation Status (ru-guide)","path":"/docs/guide/TRANSLATION_STATUS","headings":[],"excerpt":"Этот файл отслеживает прогресс перевода русской документации. Используемые статусы: TODO — требуется перевод IN_PROGRESS — перевод начат, требуется вычитка DONE — перевод завершён и вычитан SKIPPED — не требует перевода ","content":"Этот файл отслеживает прогресс перевода русской документации. Используемые статусы: TODO — требуется перевод IN_PROGRESS — перевод начат, требуется вычитка DONE — перевод завершён и вычитан SKIPPED — не требует перевода (намеренно оставлено на английском)"},{"id":"TRANSLATION_STATUS::top::1","title":"Translation Status (ru-guide)","path":"/docs/guide/TRANSLATION_STATUS","headings":[],"excerpt":"Правила: После полного перевода файла убрать исходный английский текст и маркер Термины протокола и ключевые идентификаторы (названия правил, CLI команды, YAML ключи) НЕ переводим. Если структура исходного файла изменила","content":"Правила: После полного перевода файла убрать исходный английский текст и маркер Термины протокола и ключевые идентификаторы (названия правил, CLI команды, YAML ключи) НЕ переводим. Если структура исходного файла изменилась — добавить в начало: Для больших изменений: сначала IN_PROGRESS, после вычитки менять на DONE."},{"id":"TRANSLATION_STATUS::summary::2","title":"Translation Status (ru-guide)","section":"Summary","path":"/docs/guide/TRANSLATION_STATUS#summary","headings":["Summary"],"excerpt":"Summary Итого файлов: 76 DONE: 76 IN_PROGRESS: 0 TODO: 0","content":"Summary Итого файлов: 76 DONE: 76 IN_PROGRESS: 0 TODO: 0"},{"id":"TRANSLATION_STATUS::priority-order::3","title":"Translation Status (ru-guide)","section":"Priority Order (рекомендованный)","path":"/docs/guide/TRANSLATION_STATUS#priority-order","headings":["Priority Order (рекомендованный)"],"excerpt":"Priority Order (рекомендованный) introduction/what-is.md introduction/quickstart.md introduction/install.md cli/linter/linter.md cli/generator/generator.md cli/package-manager/package-manager.md cli/breaking-changes/brea","content":"Priority Order (рекомендованный) introduction/what-is.md introduction/quickstart.md introduction/install.md cli/linter/linter.md cli/generator/generator.md cli/package-manager/package-manager.md cli/breaking-changes/breaking-changes.md api-service/overview.md migration/* (пакетом)"},{"id":"TRANSLATION_STATUS::priority-order::4","title":"Translation Status (ru-guide)","section":"Priority Order (рекомендованный)","path":"/docs/guide/TRANSLATION_STATUS#priority-order","headings":["Priority Order (рекомендованный)"],"excerpt":"Priority Order (рекомендованный) ---","content":"Priority Order (рекомендованный) ---"},{"id":"TRANSLATION_STATUS::file-status-table::5","title":"Translation Status (ru-guide)","section":"File Status Table","path":"/docs/guide/TRANSLATION_STATUS#file-status-table","headings":["File Status Table"],"excerpt":"File Status Table File Status Notes ------ -------- ------- introduction/what-is.md DONE Полный перевод выполнен introduction/quickstart.md DONE Структура сохранена, перевод вычитан introduction/install.md DONE Переведен","content":"File Status Table File Status Notes ------ -------- ------- introduction/what-is.md DONE Полный перевод выполнен introduction/quickstart.md DONE Структура сохранена, перевод вычитан introduction/install.md DONE Переведено, команды проверены api-service/overview.md DONE Переведено ci-cd/github-actions.md DONE Переведено ci-cd/gitlab.md DONE Переведено cli/auto-completion/auto-completion.md DONE Переведено cli/breaking-changes/breaking-changes.md DONE Переведено и вычитано cli/breaking-changes/rules/enum-no-delete.md DONE Переведено cli/breaking-changes/rules/enum-value-no-delete.md DONE Переведено cli/breaking-changes/rules/enum-value-same-name.md DONE Переведено cli/breaking-changes/rules/field-no-delete.md DONE Переведено cli/breaking-changes/rules/field-same-cardinality.md DONE Переведено cli/breaking-changes/rules/field-same-type.md DONE Переведено cli/breaking-changes/rules/import-no-delete.md DONE Переведено cli/breaking-changes/rules/message-no-delete.md DONE Переведено cli/breaking-changes/rules/oneof-field-no-delete.md DONE Переведено cli/breaking-changes/rules/oneof-field-same-type.md DONE Переведено cli/breaking-changes/rules/oneof-no-delete.md DONE Переведено cli/breaking-changes/rules/rpc-no-delete.md DONE Переведено cli/breaking-changes/rules/rpc-same-request-type.md DONE Переведено cli/breaking-changes/rules/rpc-same-response-type.md DONE Переведено cli/breaking-changes/rules/service-no-delete.md DONE Переведено cli/configuration/configuration.md DONE Переведено cli/generator/examples/go.md DONE Переведено cli/generator/examples/grpc-gateway.md DONE Переведено cli/generator/examples/validate.md DONE Переведено cli/generator/generator.md DONE Переведено и вычитано cli/linter/linter.md DONE Переведено и вычитано cli/linter/rules/comment-enum-value.md DONE Переведено cli/linter/rules/comment-enum.md DONE Переведено cli/linter/rules/comment-field.md DONE Переведено cli/linter/rules/comment-message.md DONE Переведено cli/linter/rules/comment-oneof.md DONE Переведено cli/linter/rules/comment-rpc.md DONE Переведено cli/linter/rules/comment-service.md DONE Переведено cli/linter/rules/directory-same-package.md DONE Переведено cli/linter/rules/enum-first-value-zero.md DONE Переведено cli/linter/rules/enum-no-allow-alias.md DONE Переведено cli/linter/rules/enum-pascal-case.md DONE Переведено cli/linter/rules/enum-value-prefix.md DONE Переведено cli/linter/rules/enum-value-upper-snake-case.md DONE Переведено cli/linter/rules/enum-zero-value-suffix.md DONE Переведено cli/linter/rules/field-lower-snake-case.md DONE Переведено cli/linter/rules/file-lower-snake-case.md DONE Переведено cli/linter/rules/import-no-public.md DONE Переведено cli/linter/rules/import-no-weak.md DONE Переведено cli/linter/rules/import-used.md DONE Переведено cli/linter/rules/message-pascal-case.md DONE Переведено cli/linter/rules/oneof-lower-snake-case.md DONE Переведено cli/linter/rules/package-defined.md DONE Переведено cli/linter/rules/package-directory-match.md DONE Переведено cli/linter/rules/package-lower-snake-case.md DONE Переведено cli/linter/rules/package-same-csharp-namespace.md DONE Переведено cli/linter/rules/package-same-directory.md DONE Переведено cli/linter/rules/package-same-go-package.md DONE Переведено cli/linter/rules/package-same-java-multiple-files.md DONE Переведено cli/linter/rules/package-same-java-package.md DONE Переведено cli/linter/rules/package-same-php-namespace.md DONE Переведено cli/linter/rules/package-same-ruby-package.md DONE Переведено cli/linter/rules/package-same-swift-prefix.md DONE Переведено cli/linter/rules/package-version-suffix.md DONE Переведено cli/linter/rules/rpc-no-client-streaming.md DONE Переведено cli/linter/rules/rpc-no-server-streaming.md DONE Переведено cli/linter/rules/rpc-pascal-case.md DONE Переведено cli/linter/rules/rpc-request-response-unique.md DONE Переведено cli/linter/rules/rpc-request-standard-name.md DONE Переведено cli/linter/rules/rpc-response-standard-name.md DONE Переведено cli/linter/rules/service-pascal-case.md DONE Переведено cli/linter/rules/service-suffix.md DONE Переведено cli/package-manager/easyp-vs-buf.md DONE Переведено cli/package-manager/package-manager.md DONE Переведено и вычитано migration/buf-cli.md DONE Переведено migration/protoc.md DONE Переведено migration/protolock.md DONE Переведено migration/prototool.md DONE Переведено"},{"id":"TRANSLATION_STATUS::workflow::6","title":"Translation Status (ru-guide)","section":"Workflow","path":"/docs/guide/TRANSLATION_STATUS#workflow","headings":["Workflow"],"excerpt":"Workflow Выбираем файл со статусом TODO. Меняем статус на IN_PROGRESS здесь. Переводим, проверяем терминологию (сверка с глоссарием — добавить позже). Меняем статус на DONE. Удаляем маркер внутри файла.","content":"Workflow Выбираем файл со статусом TODO. Меняем статус на IN_PROGRESS здесь. Переводим, проверяем терминологию (сверка с глоссарием — добавить позже). Меняем статус на DONE. Удаляем маркер внутри файла."},{"id":"TRANSLATION_STATUS::planned-terminology::7","title":"Translation Status (ru-guide)","section":"Planned Terminology (черновик)","path":"/docs/guide/TRANSLATION_STATUS#planned-terminology","headings":["Planned Terminology (черновик)"],"excerpt":"Planned Terminology (черновик) EN RU Notes ---- ---- ------- Linting Линтинг Транслитерация Breaking Changes Несовместимые изменения Название секции Dependency Зависимость Code Generation Генерация кода Lock file Lock-фа","content":"Planned Terminology (черновик) EN RU Notes ---- ---- ------- Linting Линтинг Транслитерация Breaking Changes Несовместимые изменения Название секции Dependency Зависимость Code Generation Генерация кода Lock file Lock-файл Remote Plugin Удалённый плагин Package Manager Менеджер пакетов"},{"id":"TRANSLATION_STATUS::planned-terminology::8","title":"Translation Status (ru-guide)","section":"Planned Terminology (черновик)","path":"/docs/guide/TRANSLATION_STATUS#planned-terminology","headings":["Planned Terminology (черновик)"],"excerpt":"Planned Terminology (черновик) (Будет дополнено.)","content":"Planned Terminology (черновик) (Будет дополнено.)"},{"id":"TRANSLATION_STATUS::planned-terminology::9","title":"Translation Status (ru-guide)","section":"Planned Terminology (черновик)","path":"/docs/guide/TRANSLATION_STATUS#planned-terminology","headings":["Planned Terminology (черновик)"],"excerpt":"Planned Terminology (черновик) ---","content":"Planned Terminology (черновик) ---"},{"id":"TRANSLATION_STATUS::top::10","title":"Translation Status (ru-guide)","section":"История обновлений","path":"/docs/guide/TRANSLATION_STATUS","headings":["История обновлений"],"excerpt":"История обновлений Initial file created: all statuses set (3 IN_PROGRESS, rest TODO). Marked breaking-changes page as DONE. Linter rules (41 файлов) переведены: статусы DONE. Breaking-changes rules (15 файлов) вычитаны и","content":"История обновлений Initial file created: all statuses set (3 IN_PROGRESS, rest TODO). Marked breaking-changes page as DONE. Linter rules (41 файлов) переведены: статусы DONE. Breaking-changes rules (15 файлов) вычитаны и помечены DONE. Все оставшиеся страницы переведены: итог DONE = 76."}] \ No newline at end of file diff --git a/docs/public/docs/guide/cli/generator/generator.md b/docs/public/docs/guide/cli/generator/generator.md index fa04560d..94b16fdd 100644 --- a/docs/public/docs/guide/cli/generator/generator.md +++ b/docs/public/docs/guide/cli/generator/generator.md @@ -574,7 +574,7 @@ When managed mode is enabled, EasyP automatically applies file and field options - Objective-C: `objc_class_prefix` defaults to first letters of package parts - C++: `cc_enable_arenas` defaults to `true` -**Overrides** allow you to set specific values for options, with support for filtering by module, path, or field. Without `module` or `path`, an override applies to all files in the generation request, including dependencies and `git_repo` inputs. +**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. **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. @@ -590,6 +590,10 @@ generate: # Disable specific option globally - file_option: java_package_prefix + + # Disable for specific protobuf package + - package: acme.weather.v1 + file_option: java_package # Disable for specific path - path: legacy/ @@ -608,6 +612,11 @@ generate: - file_option: java_package_prefix value: com.mycompany module: github.com/mycompany/internal-protos + + # 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 @@ -761,6 +770,24 @@ generate: `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`. +`package` matches the protobuf `package` declaration exactly, for example `acme.weather.v1`. + +#### Package-Specific Overrides + +Apply different options to files from a specific protobuf package: + +```yaml +generate: + managed: + enabled: true + override: + - file_option: go_package_prefix + value: github.com/mycompany/myproject/gen/go + - file_option: go_package + package: acme.weather.v1 + value: github.com/mycompany/myproject/gen/go/acme/weather/v1 +``` + #### Disabling for External Dependencies Disable managed mode for external dependencies that already have their options set: diff --git a/docs/public/docs/ru-guide/cli/generator/generator.md b/docs/public/docs/ru-guide/cli/generator/generator.md index 6b17395f..16afe1fd 100644 --- a/docs/public/docs/ru-guide/cli/generator/generator.md +++ b/docs/public/docs/ru-guide/cli/generator/generator.md @@ -574,7 +574,7 @@ Managed mode автоматически устанавливает file и field - Objective-C: `objc_class_prefix` по умолчанию первые буквы частей пакета - C++: `cc_enable_arenas` по умолчанию `true` -**Overrides** позволяют установить конкретные значения для опций с поддержкой фильтрации по модулю, пути или полю. Если не указаны `module` и `path`, override применяется ко всем файлам в запросе генерации, включая зависимости и `git_repo` inputs. +**Overrides** позволяют установить конкретные значения для опций с поддержкой фильтрации по модулю, protobuf package, пути или полю. Если не указаны `module`, `package` и `path`, override применяется ко всем файлам в запросе генерации, включая зависимости и `git_repo` inputs. **Disables** позволяют предотвратить изменение managed mode определённых опций или файлов. Это рекомендуемый способ исключить внешние зависимости, у которых свои опции уже заданы. @@ -590,6 +590,10 @@ generate: # Отключить конкретную опцию глобально - file_option: java_package_prefix + + # Отключить для конкретного protobuf package + - package: acme.weather.v1 + file_option: java_package # Отключить для конкретного пути - path: legacy/ @@ -608,6 +612,11 @@ generate: - file_option: java_package_prefix value: com.mycompany module: github.com/mycompany/internal-protos + + # Переопределить для конкретного protobuf package + - file_option: go_package_prefix + value: github.com/mycompany/myproject/gen/go + package: acme.weather.v1 # Переопределить для конкретного пути - file_option: csharp_namespace_prefix @@ -761,6 +770,24 @@ generate: `module` должен точно совпадать с источником модуля в EasyP: это значение из `deps` или `git_repo.url` до `@version` (например, `github.com/mycompany/internal-protos` или `https://github.com/mycompany/internal-protos`). Это не Go module path из `go.mod`. +`package` должен точно совпадать со значением `package` в `.proto` файле, например `acme.weather.v1`. + +#### Переопределения для конкретного protobuf package + +Примените отдельные опции к файлам из конкретного protobuf package: + +```yaml +generate: + managed: + enabled: true + override: + - file_option: go_package_prefix + value: github.com/mycompany/myproject/gen/go + - file_option: go_package + package: acme.weather.v1 + value: github.com/mycompany/myproject/gen/go/acme/weather/v1 +``` + #### Отключение для внешних зависимостей Отключите managed mode для внешних зависимостей, у которых уже установлены опции: diff --git a/docs/public/search/index.en.json b/docs/public/search/index.en.json index 853e288a..c3308632 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, required) - Output directory for generated files opts (mapstring, optional) - Plugin-specific options; each key can be a single value or an array of 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 ✅ - 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, path, or field. Without module or path, an override applies to all files in the generation request, including","content":"How It Works **Overrides** allow you to set specific values for options, with support for filtering by module, path, or field. Without module 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::supported-file-options::92","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::93","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::94","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::95","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::96","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::97","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::98","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::99","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::100","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::101","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::102","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::disabling-for-external-dependencies::103","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::104","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::105","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::106","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::107","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::108","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::109","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::110","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::111","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::112","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::113","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::114","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::115","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::116","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::117","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::118","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::119","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::120","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::121","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::122","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::123","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::124","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::125","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::126","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::127","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::128","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::129","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::130","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::131","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::132","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::133","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::134","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::135","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::136","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::137","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::138","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::139","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::140","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::141","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::142","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::143","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::144","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::145","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::146","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::147","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::148","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::149","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::150","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::151","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::152","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::153","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::154","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::155","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::156","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::157","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::158","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::159","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::160","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::161","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::162","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::163","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::164","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::165","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::166","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::167","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::168","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::169","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::170","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::171","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::172","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::173","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::174","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::175","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::176","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::177","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::178","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::179","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::180","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::181","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::182","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::183","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::184","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::185","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-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, required) - Output directory for generated files opts (mapstring, optional) - Plugin-specific options; each key can be a single value or an array of 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 ✅ - 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/docs/public/search/index.ru.json b/docs/public/search/index.ru.json index 6434c044..b7eac7ec 100644 --- a/docs/public/search/index.ru.json +++ b/docs/public/search/index.ru.json @@ -1 +1 @@ -[{"id":"api-service/overview::top::0","title":"Обзор API Service","path":"/docs/guide/api-service/overview","headings":[],"excerpt":"**Централизованный сервис выполнения protobuf‑плагинов для консистентной изолированной генерации кода**","content":"**Централизованный сервис выполнения protobuf‑плагинов для консистентной изолированной генерации кода**"},{"id":"api-service/overview::top::1","title":"Обзор API Service","path":"/docs/guide/api-service/overview","headings":[],"excerpt":"EasyP API Service устраняет хаос управления плагинами, предоставляя централизованный запуск protobuf/gRPC плагинов в изолированных Docker‑контейнерах. Он даёт единую платформу, позволяющую командам стандартизировать проц","content":"EasyP API Service устраняет хаос управления плагинами, предоставляя централизованный запуск protobuf/gRPC плагинов в изолированных Docker‑контейнерах. Он даёт единую платформу, позволяющую командам стандартизировать процесс генерации кода без операционных затрат на установку и поддержку плагинов на машинах разработчиков."},{"id":"api-service/overview::easyp-api-service::2","title":"Обзор API Service","section":"Зачем нужен EasyP API Service?","path":"/docs/guide/api-service/overview#easyp-api-service","headings":["Зачем нужен EasyP API Service?"],"excerpt":"Зачем нужен EasyP API Service?","content":"Зачем нужен EasyP API Service?"},{"id":"api-service/overview::top::3","title":"Обзор API Service","section":"Проблема","path":"/docs/guide/api-service/overview","headings":["Проблема"],"excerpt":"Проблема Управление генерацией protobuf/gRPC кода в командах порождает существенную операционную сложность:","content":"Проблема Управление генерацией protobuf/gRPC кода в командах порождает существенную операционную сложность:"},{"id":"api-service/overview::top::4","title":"Обзор API Service","section":"Несогласованность версий","path":"/docs/guide/api-service/overview","headings":["Несогласованность версий"],"excerpt":"Несогласованность версий Разработчики локально используют разные версии плагинов → расхождения в генерированном коде и падения сборки Синдром «у меня работает» при различиях окружений Требуется ручная координация, чтобы ","content":"Несогласованность версий Разработчики локально используют разные версии плагинов → расхождения в генерированном коде и падения сборки Синдром «у меня работает» при различиях окружений Требуется ручная координация, чтобы вся команда была синхронизирована по версиям"},{"id":"api-service/overview::top::5","title":"Обзор API Service","section":"Операционные накладные расходы","path":"/docs/guide/api-service/overview","headings":["Операционные накладные расходы"],"excerpt":"Операционные накладные расходы DevOps тратят время на установку и обновление плагинов на рабочих станциях Новый разработчик — ручная настройка правильных версий Обновление плагинов требует коммуникации с каждым отдельно ","content":"Операционные накладные расходы DevOps тратят время на установку и обновление плагинов на рабочих станциях Новый разработчик — ручная настройка правильных версий Обновление плагинов требует коммуникации с каждым отдельно Нет централизованного контроля утверждённых версий"},{"id":"api-service/overview::top::6","title":"Обзор API Service","section":"Риски безопасности и комплаенса","path":"/docs/guide/api-service/overview","headings":["Риски безопасности и комплаенса"],"excerpt":"Риски безопасности и комплаенса Плагины ставятся из разных источников без валидации Нет аудита: какой плагин для какого билда использовался Сложно применять политики безопасности к инструментам генерации","content":"Риски безопасности и комплаенса Плагины ставятся из разных источников без валидации Нет аудита: какой плагин для какого билда использовался Сложно применять политики безопасности к инструментам генерации"},{"id":"api-service/overview::top::7","title":"Обзор API Service","section":"Решение: централизованный запуск плагинов","path":"/docs/guide/api-service/overview","headings":["Решение: централизованный запуск плагинов"],"excerpt":"Решение: централизованный запуск плагинов EasyP API Service решает эти проблемы за счёт централизованного управления:","content":"Решение: централизованный запуск плагинов EasyP API Service решает эти проблемы за счёт централизованного управления:"},{"id":"api-service/overview::top::8","title":"Обзор API Service","section":"Решение: централизованный запуск плагинов","path":"/docs/guide/api-service/overview","headings":["Решение: централизованный запуск плагинов"],"excerpt":"Решение: централизованный запуск плагинов Проблема Решение ---------- --------- **Контроль версий** Мгновенное распространение новых версий через Docker‑образы **Операции** Команда эксплуатации управляет конфигурациями б","content":"Решение: централизованный запуск плагинов Проблема Решение ---------- --------- **Контроль версий** Мгновенное распространение новых версий через Docker‑образы **Операции** Команда эксплуатации управляет конфигурациями без доступа на машины разработчиков **Безопасность** Все плагины запускаются в изолированных контейнерах с ограничениями ресурсов **Консистентность** Единая среда выполнения вне зависимости от локальной установки **Опыт разработчика** Не нужно устанавливать и сопровождать плагины локально"},{"id":"api-service/overview::top::9","title":"Обзор API Service","section":"Архитектура","path":"/docs/guide/api-service/overview","headings":["Архитектура"],"excerpt":"Архитектура Архитектура сервиса упрощена и сфокусирована на надёжном выполнении плагинов:","content":"Архитектура Архитектура сервиса упрощена и сфокусирована на надёжном выполнении плагинов:"},{"id":"api-service/overview::api-layer::10","title":"Обзор API Service","section":"API Layer","path":"/docs/guide/api-service/overview#api-layer","headings":["API Layer"],"excerpt":"API Layer **gRPC Server** — основной API для запросов генерации Каждый запуск плагина — отдельный gRPC‑запрос Получает CodeGeneratorRequest от CLI","content":"API Layer **gRPC Server** — основной API для запросов генерации Каждый запуск плагина — отдельный gRPC‑запрос Получает CodeGeneratorRequest от CLI"},{"id":"api-service/overview::execution-engine::11","title":"Обзор API Service","section":"Execution Engine","path":"/docs/guide/api-service/overview#execution-engine","headings":["Execution Engine"],"excerpt":"Execution Engine **Docker Runtime** — изолированный запуск плагинов Подтягивает образы из публичных реестров (Docker Hub и т.п.) Применяет лимиты CPU/памяти на плагин","content":"Execution Engine **Docker Runtime** — изолированный запуск плагинов Подтягивает образы из публичных реестров (Docker Hub и т.п.) Применяет лимиты CPU/памяти на плагин"},{"id":"api-service/overview::storage-layer::12","title":"Обзор API Service","section":"Storage Layer","path":"/docs/guide/api-service/overview#storage-layer","headings":["Storage Layer"],"excerpt":"Storage Layer **PostgreSQL** хранит параметры выполнения: - Ограничения ресурсов (CPU, память) - Конфигурацию и метаданные плагинов - Логи выполнения (аудит) - _Примечание: функциональность хранения будет расширяться_","content":"Storage Layer **PostgreSQL** хранит параметры выполнения: - Ограничения ресурсов (CPU, память) - Конфигурацию и метаданные плагинов - Логи выполнения (аудит) - _Примечание: функциональность хранения будет расширяться_"},{"id":"api-service/overview::monitoring::13","title":"Обзор API Service","section":"Monitoring","path":"/docs/guide/api-service/overview#monitoring","headings":["Monitoring"],"excerpt":"Monitoring **Prometheus** — сбор метрик Отслеживает время выполнения, успешность, использование ресурсов","content":"Monitoring **Prometheus** — сбор метрик Отслеживает время выполнения, успешность, использование ресурсов"},{"id":"api-service/overview::easyp-cli::14","title":"Обзор API Service","section":"Локальное выполнение (EasyP CLI)","path":"/docs/guide/api-service/overview#easyp-cli","headings":["Локальное выполнение (EasyP CLI)"],"excerpt":"Локальное выполнение (EasyP CLI) При локальном запуске CLI поддерживает: **Installed plugins**: системно установленные protoc плагины **WASM plugins**: лёгкие WebAssembly плагины","content":"Локальное выполнение (EasyP CLI) При локальном запуске CLI поддерживает: **Installed plugins**: системно установленные protoc плагины **WASM plugins**: лёгкие WebAssembly плагины"},{"id":"api-service/overview::api-service::15","title":"Обзор API Service","section":"Удалённое выполнение (API Service)","path":"/docs/guide/api-service/overview#api-service","headings":["Удалённое выполнение (API Service)"],"excerpt":"Удалённое выполнение (API Service) При работе через сервис: **Только Docker**: плагины запускаются как контейнеры **Центральный контроль**: операционная команда управляет доступными версиями **Консистентная среда**: один","content":"Удалённое выполнение (API Service) При работе через сервис: **Только Docker**: плагины запускаются как контейнеры **Центральный контроль**: операционная команда управляет доступными версиями **Консистентная среда**: одинаковое окружение для всех разработчиков"},{"id":"api-service/overview::top::16","title":"Обзор API Service","section":"Шаги выполнения","path":"/docs/guide/api-service/overview","headings":["Шаги выполнения"],"excerpt":"Шаги выполнения **CLI Parsing**: CLI парсит локальные .proto файлы **Request Sending**: Отправляет CodeGeneratorRequest в API Service (по одному на плагин) **Parameter Lookup**: Сервис получает параметры запуска из Postg","content":"Шаги выполнения **CLI Parsing**: CLI парсит локальные .proto файлы **Request Sending**: Отправляет CodeGeneratorRequest в API Service (по одному на плагин) **Parameter Lookup**: Сервис получает параметры запуска из PostgreSQL **Docker Execution**: Запускает плагин в изолированном контейнере **Metrics Recording**: Записывает метрики после завершения **Response**: Возвращает сгенерированный код обратно в CLI"},{"id":"api-service/overview::top::17","title":"Обзор API Service","section":"Ключевые возможности","path":"/docs/guide/api-service/overview","headings":["Ключевые возможности"],"excerpt":"Ключевые возможности Возможность Описание ------------- ---------- **🐳 Изоляция плагинов** Каждый плагин в отдельном безопасном контейнере **⚙️ Контроль ресурсов** Лимиты CPU и памяти на уровне контейнера **📊 Метрики &","content":"Ключевые возможности Возможность Описание ------------- ---------- **🐳 Изоляция плагинов** Каждый плагин в отдельном безопасном контейнере **⚙️ Контроль ресурсов** Лимиты CPU и памяти на уровне контейнера **📊 Метрики & мониторинг** Полный набор Prometheus метрик **🔄 Управление версиями** Централизованно через Docker‑образы **⚡ Простой протокол** Стандарт CodeGeneratorRequest/Response **🔒 Безопасность прежде всего** Изоляция + ограниченные ресурсы"},{"id":"api-service/overview::top::18","title":"Обзор API Service","section":"Конфигурация","path":"/docs/guide/api-service/overview","headings":["Конфигурация"],"excerpt":"Конфигурация Сервис настраивается через переменные окружения.","content":"Конфигурация Сервис настраивается через переменные окружения."},{"id":"api-service/overview::top::19","title":"Обзор API Service","section":"Хранение параметров плагинов","path":"/docs/guide/api-service/overview","headings":["Хранение параметров плагинов"],"excerpt":"Хранение параметров плагинов PostgreSQL хранит параметры выполнения для каждого плагина:","content":"Хранение параметров плагинов PostgreSQL хранит параметры выполнения для каждого плагина:"},{"id":"api-service/overview::top::20","title":"Обзор API Service","section":"Хранение параметров плагинов","path":"/docs/guide/api-service/overview","headings":["Хранение параметров плагинов"],"excerpt":"Хранение параметров плагинов ::: tip Схема хранения будет расширена — аудит логов, аналитика использования, кеширование плагинов. :::","content":"Хранение параметров плагинов ::: tip Схема хранения будет расширена — аудит логов, аналитика использования, кеширование плагинов. :::"},{"id":"api-service/overview::easyp-cli::21","title":"Обзор API Service","section":"Интеграция с EasyP CLI","path":"/docs/guide/api-service/overview#easyp-cli","headings":["Интеграция с EasyP CLI"],"excerpt":"Интеграция с EasyP CLI Пример easyp.yaml для удалённого запуска:","content":"Интеграция с EasyP CLI Пример easyp.yaml для удалённого запуска:"},{"id":"api-service/overview::easyp-cli::22","title":"Обзор API Service","section":"Интеграция с EasyP CLI","path":"/docs/guide/api-service/overview#easyp-cli","headings":["Интеграция с EasyP CLI"],"excerpt":"Интеграция с EasyP CLI Запуск генерации:","content":"Интеграция с EasyP CLI Запуск генерации:"},{"id":"api-service/overview::easyp-cli::23","title":"Обзор API Service","section":"Интеграция с EasyP CLI","path":"/docs/guide/api-service/overview#easyp-cli","headings":["Интеграция с EasyP CLI"],"excerpt":"Интеграция с EasyP CLI CLI: Парсит protobuf‑файлы Отправляет отдельные запросы в сервис для каждого плагина Получает ответы с кодом Записывает файлы в указанные директории","content":"Интеграция с EasyP CLI CLI: Парсит protobuf‑файлы Отправляет отдельные запросы в сервис для каждого плагина Получает ответы с кодом Записывает файлы в указанные директории"},{"id":"api-service/overview::top::24","title":"Обзор API Service","section":"Доступные метрики","path":"/docs/guide/api-service/overview","headings":["Доступные метрики"],"excerpt":"Доступные метрики Метрики Prometheus:","content":"Доступные метрики Метрики Prometheus:"},{"id":"api-service/overview::top::25","title":"Обзор API Service","section":"Доступные метрики","path":"/docs/guide/api-service/overview","headings":["Доступные метрики"],"excerpt":"Доступные метрики Метрика Описание --------- ---------- easyp_api_service_api_grpc_server_handled_total Общее число gRPC запросов по статусам easyp_api_service_api_grpc_server_handling_seconds Гистограмма задержек gRPC e","content":"Доступные метрики Метрика Описание --------- ---------- easyp_api_service_api_grpc_server_handled_total Общее число gRPC запросов по статусам easyp_api_service_api_grpc_server_handling_seconds Гистограмма задержек gRPC easyp_api_service_generated_plugin_code_total Выполнения плагинов по имени easyp_api_service_repo_call_duration_seconds Латентность запросов к БД easyp_api_service_repo_errors_total Количество ошибок доступа к БД easyp_api_service_standard_panics_total Число восстановленных паник"},{"id":"api-service/overview::top::26","title":"Обзор API Service","section":"Характеристики производительности","path":"/docs/guide/api-service/overview","headings":["Характеристики производительности"],"excerpt":"Характеристики производительности Показатель Типичное значение Примечания ----------- ------------------- ----------- **Cold Start** 2–5 сек Первая загрузка образа **Warm Start** 100–500 мс Образ закеширован **Throughput","content":"Характеристики производительности Показатель Типичное значение Примечания ----------- ------------------- ----------- **Cold Start** 2–5 сек Первая загрузка образа **Warm Start** 100–500 мс Образ закеширован **Throughput** 20–50 одновременных Зависит от ресурсов **Memory Usage** 50–200 MB На выполнение одного плагина"},{"id":"api-service/overview::top::27","title":"Обзор API Service","section":"Изоляция контейнеров","path":"/docs/guide/api-service/overview","headings":["Изоляция контейнеров"],"excerpt":"Изоляция контейнеров Каждый плагин в отдельном эфемерном контейнере Нет сетевого доступа в процессе выполнения Лимиты CPU/памяти через Docker Контейнер удаляется после завершения","content":"Изоляция контейнеров Каждый плагин в отдельном эфемерном контейнере Нет сетевого доступа в процессе выполнения Лимиты CPU/памяти через Docker Контейнер удаляется после завершения"},{"id":"api-service/overview::api::28","title":"Обзор API Service","section":"Безопасность API","path":"/docs/guide/api-service/overview#api","headings":["Безопасность API"],"excerpt":"Безопасность API gRPC транспорт Поддержка токенов аутентификации (в продакшн окружениях) Валидация входных данных Аудитные логи в PostgreSQL","content":"Безопасность API gRPC транспорт Поддержка токенов аутентификации (в продакшн окружениях) Валидация входных данных Аудитные логи в PostgreSQL"},{"id":"api-service/overview::top::29","title":"Обзор API Service","section":"Масштабирование","path":"/docs/guide/api-service/overview","headings":["Масштабирование"],"excerpt":"Масштабирование **Горизонтальное**: несколько инстансов за балансировщиком **Ресурсы**: настройка лимитов для тяжёлых плагинов **База данных**: репликация PostgreSQL для отказоустойчивости","content":"Масштабирование **Горизонтальное**: несколько инстансов за балансировщиком **Ресурсы**: настройка лимитов для тяжёлых плагинов **База данных**: репликация PostgreSQL для отказоустойчивости"},{"id":"api-service/overview::top::30","title":"Обзор API Service","section":"Мониторинг","path":"/docs/guide/api-service/overview","headings":["Мониторинг"],"excerpt":"Мониторинг **Метрики**: Prometheus **Алертинг**: оповещения на высокие ошибки/латентность **Логи**: структурированные для аудита и отладки","content":"Мониторинг **Метрики**: Prometheus **Алертинг**: оповещения на высокие ошибки/латентность **Логи**: структурированные для аудита и отладки"},{"id":"api-service/overview::top::31","title":"Обзор API Service","section":"План развития","path":"/docs/guide/api-service/overview","headings":["План развития"],"excerpt":"План развития Запланировано: Кеширование результатов генерации Расширенный аудит и аналитика использования Поддержка приватных реестров плагинов Более умное распределение ресурсов","content":"План развития Запланировано: Кеширование результатов генерации Расширенный аудит и аналитика использования Поддержка приватных реестров плагинов Более умное распределение ресурсов"},{"id":"api-service/overview::top::32","title":"Обзор API Service","section":"Сообщество и поддержка","path":"/docs/guide/api-service/overview","headings":["Сообщество и поддержка"],"excerpt":"Сообщество и поддержка **💬 Telegram чат** — обсуждения **🐛 GitHub Issues** — баги и запросы фич **📖 Документация** — полный набор материалов","content":"Сообщество и поддержка **💬 Telegram чат** — обсуждения **🐛 GitHub Issues** — баги и запросы фич **📖 Документация** — полный набор материалов"},{"id":"api-service/overview::top::33","title":"Обзор API Service","section":"Сообщество и поддержка","path":"/docs/guide/api-service/overview","headings":["Сообщество и поддержка"],"excerpt":"Сообщество и поддержка *Упростите свои protobuf‑воркфлоу с централизованным управлением выполнением плагинов.*","content":"Сообщество и поддержка *Упростите свои protobuf‑воркфлоу с централизованным управлением выполнением плагинов.*"},{"id":"ci-cd/github-actions::top::0","title":"GitHub Actions","path":"/docs/guide/ci-cd/github-actions","headings":[],"excerpt":"Полное руководство по интеграции EasyP в конвейеры GitHub Actions для линтинга, проверки несовместимых изменений, генерации кода и автоматизации релизов.","content":"Полное руководство по интеграции EasyP в конвейеры GitHub Actions для линтинга, проверки несовместимых изменений, генерации кода и автоматизации релизов."},{"id":"ci-cd/github-actions::easyp-ci::1","title":"GitHub Actions","section":"Зачем использовать EasyP в CI","path":"/docs/guide/ci-cd/github-actions#easyp-ci","headings":["Зачем использовать EasyP в CI"],"excerpt":"Зачем использовать EasyP в CI Встраивание EasyP в GitHub Actions даёт: Единообразие правил линтинга и генерации между разработчиками. Автоматическое выявление несовместимых изменений (breaking changes) до мержа. Гарантию","content":"Зачем использовать EasyP в CI Встраивание EasyP в GitHub Actions даёт: Единообразие правил линтинга и генерации между разработчиками. Автоматическое выявление несовместимых изменений (breaking changes) до мержа. Гарантию, что сгенерированный код не «устарел» относительно .proto. Возможность централизованной проверки зависимостей и версии конфигурации."},{"id":"ci-cd/github-actions::top::2","title":"GitHub Actions","section":"Предварительные требования","path":"/docs/guide/ci-cd/github-actions","headings":["Предварительные требования"],"excerpt":"Предварительные требования Репозиторий содержит файл конфигурации easyp.yaml (или находится в корне, если запускается без --cfg). Установлены / определены зависимости в секции deps (если нужны внешние импорты). Для прива","content":"Предварительные требования Репозиторий содержит файл конфигурации easyp.yaml (или находится в корне, если запускается без --cfg). Установлены / определены зависимости в секции deps (если нужны внешние импорты). Для приватных Git-репозиториев настроен доступ (SSH key / deploy key / токен). В workflow есть шаги по установке Go (если EasyP поставляется через go install) или заранее подготовленный бинарь."},{"id":"ci-cd/github-actions::top::3","title":"GitHub Actions","section":"Базовый пример (быстрый старт)","path":"/docs/guide/ci-cd/github-actions","headings":["Базовый пример (быстрый старт)"],"excerpt":"Базовый пример (быстрый старт) Минимальный workflow для проверки линта и несовместимых изменений при открытия Pull Request:","content":"Базовый пример (быстрый старт) Минимальный workflow для проверки линта и несовместимых изменений при открытия Pull Request:"},{"id":"ci-cd/github-actions::top::4","title":"GitHub Actions","section":"Базовый пример (быстрый старт)","path":"/docs/guide/ci-cd/github-actions","headings":["Базовый пример (быстрый старт)"],"excerpt":"Базовый пример (быстрый старт) ```yaml name: easyp-ci","content":"Базовый пример (быстрый старт) ```yaml name: easyp-ci"},{"id":"ci-cd/github-actions::top::5","title":"GitHub Actions","section":"Базовый пример (быстрый старт)","path":"/docs/guide/ci-cd/github-actions","headings":["Базовый пример (быстрый старт)"],"excerpt":"Базовый пример (быстрый старт) on: pull_request: paths: - '**/*.proto' - 'easyp.yaml'","content":"Базовый пример (быстрый старт) on: pull_request: paths: - '**/*.proto' - 'easyp.yaml'"},{"id":"ci-cd/github-actions::top::6","title":"GitHub Actions","section":"Базовый пример (быстрый старт)","path":"/docs/guide/ci-cd/github-actions","headings":["Базовый пример (быстрый старт)"],"excerpt":"Базовый пример (быстрый старт) jobs: lint-and-breaking: runs-on: ubuntu-latest","content":"Базовый пример (быстрый старт) jobs: lint-and-breaking: runs-on: ubuntu-latest"},{"id":"ci-cd/github-actions::top::7","title":"GitHub Actions","section":"Базовый пример (быстрый старт)","path":"/docs/guide/ci-cd/github-actions","headings":["Базовый пример (быстрый старт)"],"excerpt":"Базовый пример (быстрый старт) steps: - name: Checkout uses: actions/checkout@v4","content":"Базовый пример (быстрый старт) steps: - name: Checkout uses: actions/checkout@v4"},{"id":"ci-cd/github-actions::top::8","title":"GitHub Actions","section":"Базовый пример (быстрый старт)","path":"/docs/guide/ci-cd/github-actions","headings":["Базовый пример (быстрый старт)"],"excerpt":"Базовый пример (быстрый старт) name: Setup Go uses: actions/setup-go@v5 with: go-version: '1.22'","content":"Базовый пример (быстрый старт) name: Setup Go uses: actions/setup-go@v5 with: go-version: '1.22'"},{"id":"ci-cd/github-actions::top::9","title":"GitHub Actions","section":"Базовый пример (быстрый старт)","path":"/docs/guide/ci-cd/github-actions","headings":["Базовый пример (быстрый старт)"],"excerpt":"Базовый пример (быстрый старт) name: Install EasyP run: go install github.com/easyp-tech/easyp/cmd/easyp@latest","content":"Базовый пример (быстрый старт) name: Install EasyP run: go install github.com/easyp-tech/easyp/cmd/easyp@latest"},{"id":"ci-cd/github-actions::top::10","title":"GitHub Actions","section":"Базовый пример (быстрый старт)","path":"/docs/guide/ci-cd/github-actions","headings":["Базовый пример (быстрый старт)"],"excerpt":"Базовый пример (быстрый старт) name: Verify EasyP version run: which easyp easyp version","content":"Базовый пример (быстрый старт) name: Verify EasyP version run: which easyp easyp version"},{"id":"ci-cd/github-actions::top::11","title":"GitHub Actions","section":"Базовый пример (быстрый старт)","path":"/docs/guide/ci-cd/github-actions","headings":["Базовый пример (быстрый старт)"],"excerpt":"Базовый пример (быстрый старт) name: Lint run: easyp lint","content":"Базовый пример (быстрый старт) name: Lint run: easyp lint"},{"id":"ci-cd/github-actions::top::12","title":"GitHub Actions","section":"Базовый пример (быстрый старт)","path":"/docs/guide/ci-cd/github-actions","headings":["Базовый пример (быстрый старт)"],"excerpt":"Базовый пример (быстрый старт) name: Breaking changes check (against main) run: easyp breaking --against git-ref=origin/main ```","content":"Базовый пример (быстрый старт) name: Breaking changes check (against main) run: easyp breaking --against git-ref=origin/main ```"},{"id":"ci-cd/github-actions::easyp::13","title":"GitHub Actions","section":"Установка EasyP","path":"/docs/guide/ci-cd/github-actions#easyp","headings":["Установка EasyP"],"excerpt":"Установка EasyP Варианты: Через go install (как в примере выше). Использование заранее собранного бинаря (артефакт релиза).","content":"Установка EasyP Варианты: Через go install (как в примере выше). Использование заранее собранного бинаря (артефакт релиза)."},{"id":"ci-cd/github-actions::top::14","title":"GitHub Actions","section":"Кэширование","path":"/docs/guide/ci-cd/github-actions","headings":["Кэширование"],"excerpt":"Кэширование Для ускорения повторных сборок можно кэшировать: Go модульный кеш (если используете генерацию с плагинами Go). Внешние зависимые Git-клонирования (папки vendor или содержимое deps при использовании easyp mod ","content":"Кэширование Для ускорения повторных сборок можно кэшировать: Go модульный кеш (если используете генерацию с плагинами Go). Внешние зависимые Git-клонирования (папки vendor или содержимое deps при использовании easyp mod download / easyp mod update). Сгенерированный код (если он тяжёлый, но чаще генерируется заново)."},{"id":"ci-cd/github-actions::top::15","title":"GitHub Actions","section":"Кэширование","path":"/docs/guide/ci-cd/github-actions","headings":["Кэширование"],"excerpt":"Кэширование Пример кэширования Go:","content":"Кэширование Пример кэширования Go:"},{"id":"ci-cd/github-actions::top::16","title":"GitHub Actions","section":"Кэширование","path":"/docs/guide/ci-cd/github-actions","headings":["Кэширование"],"excerpt":"Кэширование Пример кэширования каталога зависимостей EasyP (если вы используете локальный vendor-подход):","content":"Кэширование Пример кэширования каталога зависимостей EasyP (если вы используете локальный vendor-подход):"},{"id":"ci-cd/github-actions::top::17","title":"GitHub Actions","section":"Кэширование","path":"/docs/guide/ci-cd/github-actions","headings":["Кэширование"],"excerpt":"Кэширование (Создайте .easyp/deps как целевой каталог, если ваша стратегия скачивания такова.)","content":"Кэширование (Создайте .easyp/deps как целевой каталог, если ваша стратегия скачивания такова.)"},{"id":"ci-cd/github-actions::top::18","title":"GitHub Actions","section":"Линтинг","path":"/docs/guide/ci-cd/github-actions","headings":["Линтинг"],"excerpt":"Линтинг Рекомендуется: В PR: всегда запускать. На main: можно запускать для верификации перед релизом.","content":"Линтинг Рекомендуется: В PR: всегда запускать. На main: можно запускать для верификации перед релизом."},{"id":"ci-cd/github-actions::top::19","title":"GitHub Actions","section":"Линтинг","path":"/docs/guide/ci-cd/github-actions","headings":["Линтинг"],"excerpt":"Линтинг Расширенный пример с выводом подробностей и игнорированием комментариев (если включено в конфиг):","content":"Линтинг Расширенный пример с выводом подробностей и игнорированием комментариев (если включено в конфиг):"},{"id":"ci-cd/github-actions::breaking-changes::20","title":"GitHub Actions","section":"Проверка несовместимых изменений (Breaking Changes)","path":"/docs/guide/ci-cd/github-actions#breaking-changes","headings":["Проверка несовместимых изменений (Breaking Changes)"],"excerpt":"Проверка несовместимых изменений (Breaking Changes) EasyP может сравнивать текущее состояние против ветки / коммита / тега.","content":"Проверка несовместимых изменений (Breaking Changes) EasyP может сравнивать текущее состояние против ветки / коммита / тега."},{"id":"ci-cd/github-actions::breaking-changes::21","title":"GitHub Actions","section":"Проверка несовместимых изменений (Breaking Changes)","path":"/docs/guide/ci-cd/github-actions#breaking-changes","headings":["Проверка несовместимых изменений (Breaking Changes)"],"excerpt":"Проверка несовместимых изменений (Breaking Changes) Примеры: ```bash Сравнить против origin/main easyp breaking --against git-ref=origin/main","content":"Проверка несовместимых изменений (Breaking Changes) Примеры: ```bash Сравнить против origin/main easyp breaking --against git-ref=origin/main"},{"id":"ci-cd/github-actions::breaking-changes::22","title":"GitHub Actions","section":"Проверка несовместимых изменений (Breaking Changes)","path":"/docs/guide/ci-cd/github-actions#breaking-changes","headings":["Проверка несовместимых изменений (Breaking Changes)"],"excerpt":"Проверка несовместимых изменений (Breaking Changes) Сравнить против тега релиза easyp breaking --against git-ref=v1.5.2","content":"Проверка несовместимых изменений (Breaking Changes) Сравнить против тега релиза easyp breaking --against git-ref=v1.5.2"},{"id":"ci-cd/github-actions::breaking-changes::23","title":"GitHub Actions","section":"Проверка несовместимых изменений (Breaking Changes)","path":"/docs/guide/ci-cd/github-actions#breaking-changes","headings":["Проверка несовместимых изменений (Breaking Changes)"],"excerpt":"Проверка несовместимых изменений (Breaking Changes) Игнорировать определённые правила (если у вас настроено в easyp.yaml) easyp breaking ```","content":"Проверка несовместимых изменений (Breaking Changes) Игнорировать определённые правила (если у вас настроено в easyp.yaml) easyp breaking ```"},{"id":"ci-cd/github-actions::breaking-changes::24","title":"GitHub Actions","section":"Проверка несовместимых изменений (Breaking Changes)","path":"/docs/guide/ci-cd/github-actions#breaking-changes","headings":["Проверка несовместимых изменений (Breaking Changes)"],"excerpt":"Проверка несовместимых изменений (Breaking Changes) Workflow шаг:","content":"Проверка несовместимых изменений (Breaking Changes) Workflow шаг:"},{"id":"ci-cd/github-actions::breaking-changes::25","title":"GitHub Actions","section":"Проверка несовместимых изменений (Breaking Changes)","path":"/docs/guide/ci-cd/github-actions#breaking-changes","headings":["Проверка несовместимых изменений (Breaking Changes)"],"excerpt":"Проверка несовместимых изменений (Breaking Changes)","content":"Проверка несовместимых изменений (Breaking Changes)"},{"id":"ci-cd/github-actions::breaking-changes::26","title":"GitHub Actions","section":"Проверка несовместимых изменений (Breaking Changes)","path":"/docs/guide/ci-cd/github-actions#breaking-changes","headings":["Проверка несовместимых изменений (Breaking Changes)"],"excerpt":"Проверка несовместимых изменений (Breaking Changes) Если нужно «мягко» пропустить (например, выводить предупреждения, но не падать билд):","content":"Проверка несовместимых изменений (Breaking Changes) Если нужно «мягко» пропустить (например, выводить предупреждения, но не падать билд):"},{"id":"ci-cd/github-actions::breaking-changes::27","title":"GitHub Actions","section":"Проверка несовместимых изменений (Breaking Changes)","path":"/docs/guide/ci-cd/github-actions#breaking-changes","headings":["Проверка несовместимых изменений (Breaking Changes)"],"excerpt":"Проверка несовместимых изменений (Breaking Changes)","content":"Проверка несовместимых изменений (Breaking Changes)"},{"id":"ci-cd/github-actions::top::28","title":"GitHub Actions","section":"Генерация кода","path":"/docs/guide/ci-cd/github-actions","headings":["Генерация кода"],"excerpt":"Генерация кода Обычно для генерации:","content":"Генерация кода Обычно для генерации:"},{"id":"ci-cd/github-actions::top::29","title":"GitHub Actions","section":"Генерация кода","path":"/docs/guide/ci-cd/github-actions","headings":["Генерация кода"],"excerpt":"Генерация кода Если нужно явно указать конфиг:","content":"Генерация кода Если нужно явно указать конфиг:"},{"id":"ci-cd/github-actions::top::30","title":"GitHub Actions","section":"Генерация кода","path":"/docs/guide/ci-cd/github-actions","headings":["Генерация кода"],"excerpt":"Генерация кода Можно добавить проверку «не осталось ли не закоммиченных изменений» (гарантия, что сгенерированный код актуален):","content":"Генерация кода Можно добавить проверку «не осталось ли не закоммиченных изменений» (гарантия, что сгенерированный код актуален):"},{"id":"ci-cd/github-actions::matrix-strategy::31","title":"GitHub Actions","section":"Матрица (Matrix strategy)","path":"/docs/guide/ci-cd/github-actions#matrix-strategy","headings":["Матрица (Matrix strategy)"],"excerpt":"Матрица (Matrix strategy) Если у вас несколько вариантов конфигураций или разных языков генерации (через плагины), можно использовать matrix:","content":"Матрица (Matrix strategy) Если у вас несколько вариантов конфигураций или разных языков генерации (через плагины), можно использовать matrix:"},{"id":"ci-cd/github-actions::matrix-strategy::32","title":"GitHub Actions","section":"Матрица (Matrix strategy)","path":"/docs/guide/ci-cd/github-actions#matrix-strategy","headings":["Матрица (Matrix strategy)"],"excerpt":"Матрица (Matrix strategy) ```yaml jobs: generate: runs-on: ubuntu-latest strategy: fail-fast: false matrix: lang: [go, python] steps: - uses: actions/checkout@v4","content":"Матрица (Matrix strategy) ```yaml jobs: generate: runs-on: ubuntu-latest strategy: fail-fast: false matrix: lang: [go, python] steps: - uses: actions/checkout@v4"},{"id":"ci-cd/github-actions::matrix-strategy::33","title":"GitHub Actions","section":"Матрица (Matrix strategy)","path":"/docs/guide/ci-cd/github-actions#matrix-strategy","headings":["Матрица (Matrix strategy)"],"excerpt":"Матрица (Matrix strategy) name: Setup Go (only for go) if: matrix.lang == 'go' uses: actions/setup-go@v5 with: go-version: '1.22'","content":"Матрица (Matrix strategy) name: Setup Go (only for go) if: matrix.lang == 'go' uses: actions/setup-go@v5 with: go-version: '1.22'"},{"id":"ci-cd/github-actions::matrix-strategy::34","title":"GitHub Actions","section":"Матрица (Matrix strategy)","path":"/docs/guide/ci-cd/github-actions#matrix-strategy","headings":["Матрица (Matrix strategy)"],"excerpt":"Матрица (Matrix strategy) name: Install EasyP run: go install github.com/easyp-tech/easyp/cmd/easyp@latest","content":"Матрица (Matrix strategy) name: Install EasyP run: go install github.com/easyp-tech/easyp/cmd/easyp@latest"},{"id":"ci-cd/github-actions::matrix-strategy::35","title":"GitHub Actions","section":"Матрица (Matrix strategy)","path":"/docs/guide/ci-cd/github-actions#matrix-strategy","headings":["Матрица (Matrix strategy)"],"excerpt":"Матрица (Matrix strategy) name: Generate run: if [ \"${{ matrix.lang }}\" = \"go\" ]; then easyp generate elif [ \"${{ matrix.lang }}\" = \"python\" ]; then easyp generate --plugin python fi ```","content":"Матрица (Matrix strategy) name: Generate run: if [ \"${{ matrix.lang }}\" = \"go\" ]; then easyp generate elif [ \"${{ matrix.lang }}\" = \"python\" ]; then easyp generate --plugin python fi ```"},{"id":"ci-cd/github-actions::deps::36","title":"GitHub Actions","section":"Работа с приватными репозиториями (deps)","path":"/docs/guide/ci-cd/github-actions#deps","headings":["Работа с приватными репозиториями (deps)"],"excerpt":"Работа с приватными репозиториями (deps) Если вы указываете приватные Git-пакеты в секции deps:","content":"Работа с приватными репозиториями (deps) Если вы указываете приватные Git-пакеты в секции deps:"},{"id":"ci-cd/github-actions::deps::37","title":"GitHub Actions","section":"Работа с приватными репозиториями (deps)","path":"/docs/guide/ci-cd/github-actions#deps","headings":["Работа с приватными репозиториями (deps)"],"excerpt":"Работа с приватными репозиториями (deps) Настройте deploy key или используйте GIT_SSH_COMMAND с токеном. Добавьте known_hosts (либо установите StrictHostKeyChecking=no для внутренних систем, но осознанно).","content":"Работа с приватными репозиториями (deps) Настройте deploy key или используйте GIT_SSH_COMMAND с токеном. Добавьте known_hosts (либо установите StrictHostKeyChecking=no для внутренних систем, но осознанно)."},{"id":"ci-cd/github-actions::deps::38","title":"GitHub Actions","section":"Работа с приватными репозиториями (deps)","path":"/docs/guide/ci-cd/github-actions#deps","headings":["Работа с приватными репозиториями (deps)"],"excerpt":"Работа с приватными репозиториями (deps) Пример:","content":"Работа с приватными репозиториями (deps) Пример:"},{"id":"ci-cd/github-actions::deps::39","title":"GitHub Actions","section":"Работа с приватными репозиториями (deps)","path":"/docs/guide/ci-cd/github-actions#deps","headings":["Работа с приватными репозиториями (deps)"],"excerpt":"Работа с приватными репозиториями (deps) ```yaml name: Prepare SSH run: mkdir -p ~/.ssh echo \"${{ secrets.DEPLOY_KEY }}\" > ~/.ssh/id_rsa chmod 600 ~/.ssh/id_rsa ssh-keyscan github.com >> ~/.ssh/known_hosts","content":"Работа с приватными репозиториями (deps) ```yaml name: Prepare SSH run: mkdir -p ~/.ssh echo \"${{ secrets.DEPLOY_KEY }}\" > ~/.ssh/id_rsa chmod 600 ~/.ssh/id_rsa ssh-keyscan github.com >> ~/.ssh/known_hosts"},{"id":"ci-cd/github-actions::deps::40","title":"GitHub Actions","section":"Работа с приватными репозиториями (deps)","path":"/docs/guide/ci-cd/github-actions#deps","headings":["Работа с приватными репозиториями (deps)"],"excerpt":"Работа с приватными репозиториями (deps) name: Update deps run: easyp mod update ```","content":"Работа с приватными репозиториями (deps) name: Update deps run: easyp mod update ```"},{"id":"ci-cd/github-actions::top::41","title":"GitHub Actions","section":"Оптимизация времени сборки","path":"/docs/guide/ci-cd/github-actions","headings":["Оптимизация времени сборки"],"excerpt":"Оптимизация времени сборки Используйте кэш для Go / deps. Запускайте линт/брейкинг только если изменились .proto или easyp.yaml (paths фильтр). Разделяйте workflow: быстрый линт в PR, тяжелая генерация в push на main. Вы","content":"Оптимизация времени сборки Используйте кэш для Go / deps. Запускайте линт/брейкинг только если изменились .proto или easyp.yaml (paths фильтр). Разделяйте workflow: быстрый линт в PR, тяжелая генерация в push на main. Выносите генерацию OpenAPI / gRPC-Gateway в отдельный job (параллелизм)."},{"id":"ci-cd/github-actions::workflow::42","title":"GitHub Actions","section":"Продвинутый workflow (многостадийный)","path":"/docs/guide/ci-cd/github-actions#workflow","headings":["Продвинутый workflow (многостадийный)"],"excerpt":"Продвинутый workflow (многостадийный) ```yaml name: easyp-pipeline","content":"Продвинутый workflow (многостадийный) ```yaml name: easyp-pipeline"},{"id":"ci-cd/github-actions::workflow::43","title":"GitHub Actions","section":"Продвинутый workflow (многостадийный)","path":"/docs/guide/ci-cd/github-actions#workflow","headings":["Продвинутый workflow (многостадийный)"],"excerpt":"Продвинутый workflow (многостадийный) on: pull_request: paths: - '**/*.proto' - 'easyp.yaml' push: branches: - main","content":"Продвинутый workflow (многостадийный) on: pull_request: paths: - '**/*.proto' - 'easyp.yaml' push: branches: - main"},{"id":"ci-cd/github-actions::workflow::44","title":"GitHub Actions","section":"Продвинутый workflow (многостадийный)","path":"/docs/guide/ci-cd/github-actions#workflow","headings":["Продвинутый workflow (многостадийный)"],"excerpt":"Продвинутый workflow (многостадийный) jobs: validate: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4","content":"Продвинутый workflow (многостадийный) jobs: validate: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4"},{"id":"ci-cd/github-actions::workflow::45","title":"GitHub Actions","section":"Продвинутый workflow (многостадийный)","path":"/docs/guide/ci-cd/github-actions#workflow","headings":["Продвинутый workflow (многостадийный)"],"excerpt":"Продвинутый workflow (многостадийный) uses: actions/setup-go@v5 with: go-version: '1.22'","content":"Продвинутый workflow (многостадийный) uses: actions/setup-go@v5 with: go-version: '1.22'"},{"id":"ci-cd/github-actions::workflow::46","title":"GitHub Actions","section":"Продвинутый workflow (многостадийный)","path":"/docs/guide/ci-cd/github-actions#workflow","headings":["Продвинутый workflow (многостадийный)"],"excerpt":"Продвинутый workflow (многостадийный) name: Install EasyP run: go install github.com/easyp-tech/easyp/cmd/easyp@latest","content":"Продвинутый workflow (многостадийный) name: Install EasyP run: go install github.com/easyp-tech/easyp/cmd/easyp@latest"},{"id":"ci-cd/github-actions::workflow::47","title":"GitHub Actions","section":"Продвинутый workflow (многостадийный)","path":"/docs/guide/ci-cd/github-actions#workflow","headings":["Продвинутый workflow (многостадийный)"],"excerpt":"Продвинутый workflow (многостадийный) name: Lint run: easyp lint","content":"Продвинутый workflow (многостадийный) name: Lint run: easyp lint"},{"id":"ci-cd/github-actions::workflow::48","title":"GitHub Actions","section":"Продвинутый workflow (многостадийный)","path":"/docs/guide/ci-cd/github-actions#workflow","headings":["Продвинутый workflow (многостадийный)"],"excerpt":"Продвинутый workflow (многостадийный) name: Breaking check (against main) if: github.event_name == 'pull_request' run: easyp breaking --against git-ref=origin/main","content":"Продвинутый workflow (многостадийный) name: Breaking check (against main) if: github.event_name == 'pull_request' run: easyp breaking --against git-ref=origin/main"},{"id":"ci-cd/github-actions::workflow::49","title":"GitHub Actions","section":"Продвинутый workflow (многостадийный)","path":"/docs/guide/ci-cd/github-actions#workflow","headings":["Продвинутый workflow (многостадийный)"],"excerpt":"Продвинутый workflow (многостадийный) generate: needs: validate if: github.event_name == 'push' runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-go@v5 with: go-version: '1.22' - name: Insta","content":"Продвинутый workflow (многостадийный) generate: needs: validate if: github.event_name == 'push' runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-go@v5 with: go-version: '1.22' - name: Install EasyP run: go install github.com/easyp-tech/easyp/cmd/easyp@latest - name: Generate Code run: easyp generate - name: Check diffs run: if [ -n \"$(git status --porcelain)\" ]; then echo \"Generated files changed after generate step.\" git diff --name-only exit 1 fi ```"},{"id":"ci-cd/github-actions::top::50","title":"GitHub Actions","section":"Автоматизация релиза (пример)","path":"/docs/guide/ci-cd/github-actions","headings":["Автоматизация релиза (пример)"],"excerpt":"Автоматизация релиза (пример) Можно добавить workflow, который по тегу создаёт релиз и валидирует proto:","content":"Автоматизация релиза (пример) Можно добавить workflow, который по тегу создаёт релиз и валидирует proto:"},{"id":"ci-cd/github-actions::top::51","title":"GitHub Actions","section":"Автоматизация релиза (пример)","path":"/docs/guide/ci-cd/github-actions","headings":["Автоматизация релиза (пример)"],"excerpt":"Автоматизация релиза (пример) ```yaml name: release-verify","content":"Автоматизация релиза (пример) ```yaml name: release-verify"},{"id":"ci-cd/github-actions::top::52","title":"GitHub Actions","section":"Автоматизация релиза (пример)","path":"/docs/guide/ci-cd/github-actions","headings":["Автоматизация релиза (пример)"],"excerpt":"Автоматизация релиза (пример) on: push: tags: - 'v*.*.*'","content":"Автоматизация релиза (пример) on: push: tags: - 'v*.*.*'"},{"id":"ci-cd/github-actions::top::53","title":"GitHub Actions","section":"Автоматизация релиза (пример)","path":"/docs/guide/ci-cd/github-actions","headings":["Автоматизация релиза (пример)"],"excerpt":"Автоматизация релиза (пример) jobs: release-check: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4","content":"Автоматизация релиза (пример) jobs: release-check: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4"},{"id":"ci-cd/github-actions::top::54","title":"GitHub Actions","section":"Автоматизация релиза (пример)","path":"/docs/guide/ci-cd/github-actions","headings":["Автоматизация релиза (пример)"],"excerpt":"Автоматизация релиза (пример) uses: actions/setup-go@v5 with: go-version: '1.22'","content":"Автоматизация релиза (пример) uses: actions/setup-go@v5 with: go-version: '1.22'"},{"id":"ci-cd/github-actions::top::55","title":"GitHub Actions","section":"Автоматизация релиза (пример)","path":"/docs/guide/ci-cd/github-actions","headings":["Автоматизация релиза (пример)"],"excerpt":"Автоматизация релиза (пример) name: Install EasyP run: go install github.com/easyp-tech/easyp/cmd/easyp@latest","content":"Автоматизация релиза (пример) name: Install EasyP run: go install github.com/easyp-tech/easyp/cmd/easyp@latest"},{"id":"ci-cd/github-actions::top::56","title":"GitHub Actions","section":"Автоматизация релиза (пример)","path":"/docs/guide/ci-cd/github-actions","headings":["Автоматизация релиза (пример)"],"excerpt":"Автоматизация релиза (пример) name: Lint run: easyp lint","content":"Автоматизация релиза (пример) name: Lint run: easyp lint"},{"id":"ci-cd/github-actions::top::57","title":"GitHub Actions","section":"Автоматизация релиза (пример)","path":"/docs/guide/ci-cd/github-actions","headings":["Автоматизация релиза (пример)"],"excerpt":"Автоматизация релиза (пример) name: Breaking vs previous tag run: PREV_TAG=$(git tag --sort=-creatordate grep -v \"${GITHUB_REF_NAME}\" head -n1 true) if [ -n \"$PREV_TAG\" ]; then echo \"Comparing against $PREV_TAG\" easyp br","content":"Автоматизация релиза (пример) name: Breaking vs previous tag run: PREV_TAG=$(git tag --sort=-creatordate grep -v \"${GITHUB_REF_NAME}\" head -n1 true) if [ -n \"$PREV_TAG\" ]; then echo \"Comparing against $PREV_TAG\" easyp breaking --against git-ref=$PREV_TAG else echo \"No previous tag, skipping breaking check\" fi"},{"id":"ci-cd/github-actions::top::58","title":"GitHub Actions","section":"Автоматизация релиза (пример)","path":"/docs/guide/ci-cd/github-actions","headings":["Автоматизация релиза (пример)"],"excerpt":"Автоматизация релиза (пример) name: Generate to ensure consistency run: easyp generate ```","content":"Автоматизация релиза (пример) name: Generate to ensure consistency run: easyp generate ```"},{"id":"ci-cd/github-actions::top::59","title":"GitHub Actions","section":"Отладка","path":"/docs/guide/ci-cd/github-actions","headings":["Отладка"],"excerpt":"Отладка Если нужно больше логов:","content":"Отладка Если нужно больше логов:"},{"id":"ci-cd/github-actions::top::60","title":"GitHub Actions","section":"Отладка","path":"/docs/guide/ci-cd/github-actions","headings":["Отладка"],"excerpt":"Отладка Добавьте вывод окружения для диагностики:","content":"Отладка Добавьте вывод окружения для диагностики:"},{"id":"ci-cd/github-actions::top::61","title":"GitHub Actions","section":"Переменные окружения (примерно)","path":"/docs/guide/ci-cd/github-actions","headings":["Переменные окружения (примерно)"],"excerpt":"Переменные окружения (примерно) Переменная Назначение ------------ ----------- EASYP_SERVICE_HOST Хост удалённого API Service (если используете удалённые плагины) EASYP_SERVICE_GRPC_PORT Порт удалённого сервиса GIT_SSH_C","content":"Переменные окружения (примерно) Переменная Назначение ------------ ----------- EASYP_SERVICE_HOST Хост удалённого API Service (если используете удалённые плагины) EASYP_SERVICE_GRPC_PORT Порт удалённого сервиса GIT_SSH_COMMAND Кастомная команда SSH (частные репозитории) GOFLAGS Можно выставить -mod=readonly для Go генерации"},{"id":"ci-cd/github-actions::top::62","title":"GitHub Actions","section":"Переменные окружения (примерно)","path":"/docs/guide/ci-cd/github-actions","headings":["Переменные окружения (примерно)"],"excerpt":"Переменные окружения (примерно) (Используйте только те, что действительно нужны вашему проекту.)","content":"Переменные окружения (примерно) (Используйте только те, что действительно нужны вашему проекту.)"},{"id":"ci-cd/github-actions::top::63","title":"GitHub Actions","section":"Частые ошибки","path":"/docs/guide/ci-cd/github-actions","headings":["Частые ошибки"],"excerpt":"Частые ошибки Симптом Причина Решение --------- --------- --------- Линт падает на неизвестных правилах Правила указаны в easyp.yaml, но версия EasyP их не поддерживает Обновить EasyP (go install ...@latest) breaking сра","content":"Частые ошибки Симптом Причина Решение --------- --------- --------- Линт падает на неизвестных правилах Правила указаны в easyp.yaml, но версия EasyP их не поддерживает Обновить EasyP (go install ...@latest) breaking сравнение ничего не находит Неверный --against (нет fetch удалённой ветки) Добавить шаг git fetch --all --tags Сгенерированный код в PR отличается от main Отсутствует проверка генерации в CI Добавить шаг «Ensure generated code is up-to-date» Приватные deps не скачиваются Нет SSH ключа или токена Настроить secrets + шаг подготовки SSH Долгое выполнение Отсутствует кеш Добавить кэширование модулей и deps"},{"id":"ci-cd/github-actions::top::64","title":"GitHub Actions","section":"Рекомендации по поддержке","path":"/docs/guide/ci-cd/github-actions","headings":["Рекомендации по поддержке"],"excerpt":"Рекомендации по поддержке Заготовить шаблон workflow и копировать между сервисами (DRY). Включить paths фильтры, чтобы не тратить минуты на нерелевантные изменения. Проверять easyp.yaml при изменениях отдельно — можно за","content":"Рекомендации по поддержке Заготовить шаблон workflow и копировать между сервисами (DRY). Включить paths фильтры, чтобы не тратить минуты на нерелевантные изменения. Проверять easyp.yaml при изменениях отдельно — можно запускать «конфигурационный тест» (например, easyp lint без файлов, чтобы убедиться, что конфиг валиден). При появлении новых правил линтера обновляйте конфиг и фиксируйте ошибки сразу в одной ветке."},{"id":"ci-cd/github-actions::top::65","title":"GitHub Actions","section":"Рекомендации по поддержке","path":"/docs/guide/ci-cd/github-actions","headings":["Рекомендации по поддержке"],"excerpt":"Рекомендации по поддержке Готово: вы можете расширять разделы генерации, добавлять OpenAPI / grpc-gateway / validate плагины, матрицы по языкам и интегрировать тесты поверх сгенерированного кода, если требуется.","content":"Рекомендации по поддержке Готово: вы можете расширять разделы генерации, добавлять OpenAPI / grpc-gateway / validate плагины, матрицы по языкам и интегрировать тесты поверх сгенерированного кода, если требуется."},{"id":"ci-cd/gitlab::top::0","title":"GitLab CI","section":"В процессе разработки","path":"/docs/guide/ci-cd/gitlab","headings":["В процессе разработки"],"excerpt":"В процессе разработки Документация по интеграции EasyP с GitLab CI находится в процессе подготовки. Планируемые разделы: Быстрый старт (пример .gitlab-ci.yml для линтинга и проверки несовместимых изменений) Кэширование з","content":"В процессе разработки Документация по интеграции EasyP с GitLab CI находится в процессе подготовки. Планируемые разделы: Быстрый старт (пример .gitlab-ci.yml для линтинга и проверки несовместимых изменений) Кэширование зависимостей и ускорение сборок Генерация кода и проверка актуальности артефактов Работа с приватными Git-репозиториями в deps Матрицы (parallel jobs) для разных языков и плагинов Автоматизация релизов по тегам"},{"id":"ci-cd/gitlab::top::1","title":"GitLab CI","section":"В процессе разработки","path":"/docs/guide/ci-cd/gitlab","headings":["В процессе разработки"],"excerpt":"В процессе разработки Если вам нужен пример прямо сейчас, базовый минимальный вариант может выглядеть так:","content":"В процессе разработки Если вам нужен пример прямо сейчас, базовый минимальный вариант может выглядеть так:"},{"id":"ci-cd/gitlab::top::2","title":"GitLab CI","section":"В процессе разработки","path":"/docs/guide/ci-cd/gitlab","headings":["В процессе разработки"],"excerpt":"В процессе разработки ```yaml stages: - validate - generate","content":"В процессе разработки ```yaml stages: - validate - generate"},{"id":"ci-cd/gitlab::top::3","title":"GitLab CI","section":"В процессе разработки","path":"/docs/guide/ci-cd/gitlab","headings":["В процессе разработки"],"excerpt":"В процессе разработки variables: GO_VERSION: \"1.22\"","content":"В процессе разработки variables: GO_VERSION: \"1.22\""},{"id":"ci-cd/gitlab::top::4","title":"GitLab CI","section":"В процессе разработки","path":"/docs/guide/ci-cd/gitlab","headings":["В процессе разработки"],"excerpt":"В процессе разработки validate: stage: validate image: golang:${GO_VERSION} before_script: - go install github.com/easyp-tech/easyp/cmd/easyp@latest - echo \"EasyP version:\" - easyp version # При необходимости: git fetch ","content":"В процессе разработки validate: stage: validate image: golang:${GO_VERSION} before_script: - go install github.com/easyp-tech/easyp/cmd/easyp@latest - echo \"EasyP version:\" - easyp version # При необходимости: git fetch --all --tags script: - easyp lint - easyp breaking --against git-ref=origin/main only: changes: - \"**/*.proto\" - \"easyp.yaml\""},{"id":"ci-cd/gitlab::top::5","title":"GitLab CI","section":"В процессе разработки","path":"/docs/guide/ci-cd/gitlab","headings":["В процессе разработки"],"excerpt":"В процессе разработки generate: stage: generate image: golang:${GO_VERSION} before_script: - go install github.com/easyp-tech/easyp/cmd/easyp@latest script: - easyp generate - if [ -n \"$(git status --porcelain)\" ]; then ","content":"В процессе разработки generate: stage: generate image: golang:${GO_VERSION} before_script: - go install github.com/easyp-tech/easyp/cmd/easyp@latest script: - easyp generate - if [ -n \"$(git status --porcelain)\" ]; then echo \"Сгенерированный код не актуален. Закоммитьте изменения локально.\" git diff --name-only exit 1 fi only: - main"},{"id":"ci-cd/gitlab::top::6","title":"GitLab CI","section":"В процессе разработки","path":"/docs/guide/ci-cd/gitlab","headings":["В процессе разработки"],"excerpt":"В процессе разработки Дополнительные рекомендации будут добавлены позже.","content":"В процессе разработки Дополнительные рекомендации будут добавлены позже."},{"id":"cli/auto-completion/auto-completion::zsh::0","title":"Автодополнение","section":"Автодополнение для zsh","path":"/docs/guide/cli/auto-completion/auto-completion#zsh","headings":["Автодополнение для zsh"],"excerpt":"Автодополнение для zsh Добавьте следующую строку в ваш файл запуска ~/.zshrc:","content":"Автодополнение для zsh Добавьте следующую строку в ваш файл запуска ~/.zshrc:"},{"id":"cli/auto-completion/auto-completion::zsh::1","title":"Автодополнение","section":"Автодополнение для zsh","path":"/docs/guide/cli/auto-completion/auto-completion#zsh","headings":["Автодополнение для zsh"],"excerpt":"Автодополнение для zsh Перезапустите оболочку или выполните:","content":"Автодополнение для zsh Перезапустите оболочку или выполните:"},{"id":"cli/auto-completion/auto-completion::bash::2","title":"Автодополнение","section":"Автодополнение для Bash","path":"/docs/guide/cli/auto-completion/auto-completion#bash","headings":["Автодополнение для Bash"],"excerpt":"Автодополнение для Bash Установите bash-completion и подключите его в ~/.bashrc. Добавьте следующую строку в файл запуска ~/.bashrc:","content":"Автодополнение для Bash Установите bash-completion и подключите его в ~/.bashrc. Добавьте следующую строку в файл запуска ~/.bashrc:"},{"id":"cli/auto-completion/auto-completion::bash::3","title":"Автодополнение","section":"Автодополнение для Bash","path":"/docs/guide/cli/auto-completion/auto-completion#bash","headings":["Автодополнение для Bash"],"excerpt":"Автодополнение для Bash Перезапустите оболочку или выполните:","content":"Автодополнение для Bash Перезапустите оболочку или выполните:"},{"id":"cli/auto-completion/auto-completion::top::4","title":"Автодополнение","section":"Примечания","path":"/docs/guide/cli/auto-completion/auto-completion","headings":["Примечания"],"excerpt":"Примечания Команда easyp completion выводит скрипт автодополнения для соответствующей оболочки. Если используете другую оболочку (например, fish), можно сгенерировать вывод и сохранить вручную: При обновлении версии Easy","content":"Примечания Команда easyp completion выводит скрипт автодополнения для соответствующей оболочки. Если используете другую оболочку (например, fish), можно сгенерировать вывод и сохранить вручную: При обновлении версии EasyP рекомендуется заново перезагрузить оболочку, чтобы подтянуть возможные изменения в автодополнении."},{"id":"cli/breaking-changes/breaking-changes::top::0","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":[],"excerpt":"Обнаружение несовместимых изменений (Breaking Changes Detection)","content":"Обнаружение несовместимых изменений (Breaking Changes Detection)"},{"id":"cli/breaking-changes/breaking-changes::top::1","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":[],"excerpt":"Механизм EasyP для обнаружения несовместимых (breaking) изменений помогает поддерживать обратную совместимость ваших protobuf API, автоматически выявляя изменения, способные сломать существующих клиентов. Это критично дл","content":"Механизм EasyP для обнаружения несовместимых (breaking) изменений помогает поддерживать обратную совместимость ваших protobuf API, автоматически выявляя изменения, способные сломать существующих клиентов. Это критично для стабильных API в продакшене."},{"id":"cli/breaking-changes/breaking-changes::top::2","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Обзор","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Обзор"],"excerpt":"Обзор Проверка несовместимых изменений сравнивает текущий набор protobuf‑файлов с предыдущей версией (обычно из другой Git ветки) и фиксирует модификации, которые могут вызвать проблемы совместимости для уже работающих к","content":"Обзор Проверка несовместимых изменений сравнивает текущий набор protobuf‑файлов с предыдущей версией (обычно из другой Git ветки) и фиксирует модификации, которые могут вызвать проблемы совместимости для уже работающих клиентов."},{"id":"cli/breaking-changes/breaking-changes::top::3","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Ключевые возможности","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Ключевые возможности"],"excerpt":"Ключевые возможности **Сравнение через Git**: Сопоставление с любой Git‑ссылкой (ветка, тег, commit) **Комплексный анализ**: Проверка сервисов, сообщений, enum'ов, полей и import'ов **Выборочное игнорирование**: Пропуск ","content":"Ключевые возможности **Сравнение через Git**: Сопоставление с любой Git‑ссылкой (ветка, тег, commit) **Комплексный анализ**: Проверка сервисов, сообщений, enum'ов, полей и import'ов **Выборочное игнорирование**: Пропуск указанных директорий из анализа **Детализированные отчёты**: Понятные ошибки с именами файлов, строками и позициями"},{"id":"cli/breaking-changes/breaking-changes::top::4","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Как работает","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Как работает"],"excerpt":"Как работает Детектор breaking changes выполняет следующие шаги:","content":"Как работает Детектор breaking changes выполняет следующие шаги:"},{"id":"cli/breaking-changes/breaking-changes::top::5","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Как работает","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Как работает"],"excerpt":"Как работает **Получение ветки сравнения**: Забирает proto-файлы из указанной Git‑ссылки **Парсинг обеих версий**: Анализирует структуру текущих и предыдущих файлов **Сравнение сущностей**: Последовательно проверяет все ","content":"Как работает **Получение ветки сравнения**: Забирает proto-файлы из указанной Git‑ссылки **Парсинг обеих версий**: Анализирует структуру текущих и предыдущих файлов **Сравнение сущностей**: Последовательно проверяет все элементы protobuf на breaking изменения **Формирование отчёта**: Генерирует подробные записи об ошибках с локациями и описаниями"},{"id":"cli/breaking-changes/breaking-changes::top::6","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Уровень проверки","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Уровень проверки"],"excerpt":"Уровень проверки EasyP реализует уровень проверки **WIRE+**: ✅ **Полная совместимость по wire‑формату** — старые и новые версии могут обмениваться данными ✅ **Обнаружение удалений элементов** — сервисы, сообщения, поля и","content":"Уровень проверки EasyP реализует уровень проверки **WIRE+**: ✅ **Полная совместимость по wire‑формату** — старые и новые версии могут обмениваться данными ✅ **Обнаружение удалений элементов** — сервисы, сообщения, поля и т.п. ✅ **Безопасность типов** — выявляет несовместимые изменения типов ❌ **Переименования полей/методов** — пока не детектируются (в планах) ❌ **Изменения на уровне файлов** — переносы пакетов, file options ещё не проверяются"},{"id":"cli/breaking-changes/breaking-changes::top::7","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Уровень проверки","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Уровень проверки"],"excerpt":"Уровень проверки Это даёт сильные гарантии совместимости и меньше ограничений, чем инструменты, требующие совместимости сгенерированного кода.","content":"Уровень проверки Это даёт сильные гарантии совместимости и меньше ограничений, чем инструменты, требующие совместимости сгенерированного кода."},{"id":"cli/breaking-changes/breaking-changes::top::8","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Конфигурация","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Конфигурация"],"excerpt":"Конфигурация Настройка в easyp.yaml:","content":"Конфигурация Настройка в easyp.yaml:"},{"id":"cli/breaking-changes/breaking-changes::top::9","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Параметры конфигурации","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Параметры конфигурации"],"excerpt":"Параметры конфигурации Option Description Default Required -------- ------------- --------- ---------- against_git_ref Git‑ссылка для сравнения \"master\" No ignore Список директорий для исключения из анализа [] No","content":"Параметры конфигурации Option Description Default Required -------- ------------- --------- ---------- against_git_ref Git‑ссылка для сравнения \"master\" No ignore Список директорий для исключения из анализа [] No"},{"id":"cli/breaking-changes/breaking-changes::top::10","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Базовый пример","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Базовый пример"],"excerpt":"Базовый пример Сравнение текущих изменений с веткой main:","content":"Базовый пример Сравнение текущих изменений с веткой main:"},{"id":"cli/breaking-changes/breaking-changes::top::11","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Использование файла конфигурации","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Использование файла конфигурации"],"excerpt":"Использование файла конфигурации","content":"Использование файла конфигурации"},{"id":"cli/breaking-changes/breaking-changes::top::12","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Уровень проверки","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Уровень проверки"],"excerpt":"Уровень проверки EasyP сейчас работает на уровне **WIRE+**, обеспечивая совместимость wire‑формата плюс защиту от удалений и изменения критичных типов.","content":"Уровень проверки EasyP сейчас работает на уровне **WIRE+**, обеспечивая совместимость wire‑формата плюс защиту от удалений и изменения критичных типов."},{"id":"cli/breaking-changes/breaking-changes::buf::13","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Сравнение с категориями Buf","path":"/docs/guide/cli/breaking-changes/breaking-changes#buf","headings":["Сравнение с категориями Buf"],"excerpt":"Сравнение с категориями Buf Check Type Buf WIRE Buf WIRE_JSON Buf FILE EasyP Current ------------ ---------- --------------- ---------- --------------- **Element Deletions** Service deletion ❌ ❌ ✅ ✅ RPC method deletion ❌","content":"Сравнение с категориями Buf 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::top::14","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Что это означает","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Что это означает"],"excerpt":"Что это означает **✅ EasyP обнаружит:** Все breaking изменения wire‑формата Удаления сервисов, методов, сообщений, полей Изменения типов, ломающие сериализацию Переименования enum‑значений (при сохранении номера)","content":"Что это означает **✅ EasyP обнаружит:** Все breaking изменения wire‑формата Удаления сервисов, методов, сообщений, полей Изменения типов, ломающие сериализацию Переименования enum‑значений (при сохранении номера)"},{"id":"cli/breaking-changes/breaking-changes::top::15","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Что это означает","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Что это означает"],"excerpt":"Что это означает **❌ EasyP НЕ обнаружит:** Переименование полей (с тем же номером) Изменение package File options (go_package, java_package, и т.п.) Перемещение типов между файлами в одном package","content":"Что это означает **❌ EasyP НЕ обнаружит:** Переименование полей (с тем же номером) Изменение package File options (go_package, java_package, и т.п.) Перемещение типов между файлами в одном package"},{"id":"cli/breaking-changes/breaking-changes::breaking-changes::16","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Правила Breaking Changes","path":"/docs/guide/cli/breaking-changes/breaking-changes#breaking-changes","headings":["Правила Breaking Changes"],"excerpt":"Правила Breaking Changes EasyP обнаруживает следующие типы breaking изменений:","content":"Правила Breaking Changes EasyP обнаруживает следующие типы breaking изменений:"},{"id":"cli/breaking-changes/breaking-changes::top::17","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Сравнение уровней","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Сравнение уровней"],"excerpt":"Сравнение уровней Detection Level Description EasyP Support ---------------- ------------- --------------- **WIRE** Совместимость только по wire‑формату ✅ **Full support** **WIRE+** Wire + обнаружение удалений ✅ **Curren","content":"Сравнение уровней Detection Level Description EasyP Support ---------------- ------------- --------------- **WIRE** Совместимость только по wire‑формату ✅ **Full support** **WIRE+** Wire + обнаружение удалений ✅ **Current level** **FILE** Совместимость сгенерированного кода ❌ Partial (planned)"},{"id":"cli/breaking-changes/breaking-changes::top::18","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Категории правил","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Категории правил"],"excerpt":"Категории правил Каждая категория имеет свою документацию с примерами:","content":"Категории правил Каждая категория имеет свою документацию с примерами:"},{"id":"cli/breaking-changes/breaking-changes::service-rpc::19","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"🚨 Изменения Service и RPC","path":"/docs/guide/cli/breaking-changes/breaking-changes#service-rpc","headings":["🚨 Изменения Service и RPC"],"excerpt":"🚨 Изменения Service и RPC 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 и RPC 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-field::20","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"📦 Изменения Message и Field","path":"/docs/guide/cli/breaking-changes/breaking-changes#message-field","headings":["📦 Изменения Message и Field"],"excerpt":"📦 Изменения Message и Field 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 и Field 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::21","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"🔢 Изменения Enum","path":"/docs/guide/cli/breaking-changes/breaking-changes#enum","headings":["🔢 Изменения Enum"],"excerpt":"🔢 Изменения Enum 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 val","content":"🔢 Изменения Enum 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::22","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"🔗 Изменения OneOf","path":"/docs/guide/cli/breaking-changes/breaking-changes#oneof","headings":["🔗 Изменения OneOf"],"excerpt":"🔗 Изменения OneOf Rule Description Status ------ ------------- --------- ONEOF_NO_DELETE OneOf fields cannot be deleted ✅ Implemented ONEOF_FIELD_NO_DELETE Fields within oneofs cannot be deleted ✅ Implemented ONEOF_FIEL","content":"🔗 Изменения OneOf 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::23","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"📥 Изменения Import","path":"/docs/guide/cli/breaking-changes/breaking-changes#import","headings":["📥 Изменения Import"],"excerpt":"📥 Изменения Import Rule Description Status ------ ------------- --------- IMPORT_NO_DELETE Import statements cannot be removed ✅ Implemented","content":"📥 Изменения Import Rule Description Status ------ ------------- --------- IMPORT_NO_DELETE Import statements cannot be removed ✅ Implemented"},{"id":"cli/breaking-changes/breaking-changes::top::24","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Не обнаруживается сейчас","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Не обнаруживается сейчас"],"excerpt":"Не обнаруживается сейчас Изменения ниже **НЕ детектируются** EasyP (могут ломать сгенерированный код):","content":"Не обнаруживается сейчас Изменения ниже **НЕ детектируются** EasyP (могут ломать сгенерированный код):"},{"id":"cli/breaking-changes/breaking-changes::top::25","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Не обнаруживается сейчас","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Не обнаруживается сейчас"],"excerpt":"Не обнаруживается сейчас Change Type Example Impact ------------- --------- -------- Field renaming string name = 1 → string full_name = 1 Ломает код Package changes package v1 → package v2 Меняются пути импорта File opt","content":"Не обнаруживается сейчас Change Type Example Impact ------------- --------- -------- Field renaming string name = 1 → string full_name = 1 Ломает код Package changes package v1 → package v2 Меняются пути импорта File options option go_package = \"old\" → option go_package = \"new\" Меняется расположение кода Moving between files Message перемещено в другой .proto Зависимости import'ов"},{"id":"cli/breaking-changes/breaking-changes::top::26","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Документация правил","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Документация правил"],"excerpt":"Документация правил См. подробные файлы правил для примеров и стратегий миграции:","content":"Документация правил См. подробные файлы правил для примеров и стратегий миграции:"},{"id":"cli/breaking-changes/breaking-changes::top::27","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Документация правил","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Документация правил"],"excerpt":"Документация правил Service: SERVICE_NO_DELETE, RPC_NO_DELETE, RPC_SAME_REQUEST_TYPE, RPC_SAME_RESPONSE_TYPE Message: MESSAGE_NO_DELETE, FIELD_NO_DELETE, FIELD_SAME_TYPE, FIELD_SAME_CARDINALITY Enum: ENUM_NO_DELETE, ENUM","content":"Документация правил Service: SERVICE_NO_DELETE, RPC_NO_DELETE, RPC_SAME_REQUEST_TYPE, RPC_SAME_RESPONSE_TYPE Message: MESSAGE_NO_DELETE, FIELD_NO_DELETE, FIELD_SAME_TYPE, FIELD_SAME_CARDINALITY Enum: ENUM_NO_DELETE, ENUM_VALUE_NO_DELETE, ENUM_VALUE_SAME_NAME OneOf: ONEOF_NO_DELETE, ONEOF_FIELD_NO_DELETE, ONEOF_FIELD_SAME_TYPE Import: IMPORT_NO_DELETE"},{"id":"cli/breaking-changes/breaking-changes::top::28","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Документация правил","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Документация правил"],"excerpt":"Документация правил Каждое правило содержит: ❌ Плохие примеры (breaking) ✅ Безопасные альтернативы 🔧 Стратегии миграции 📋 Реальные сообщения ошибок из EasyP","content":"Документация правил Каждое правило содержит: ❌ Плохие примеры (breaking) ✅ Безопасные альтернативы 🔧 Стратегии миграции 📋 Реальные сообщения ошибок из EasyP"},{"id":"cli/breaking-changes/breaking-changes::top::29","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"✅ Безопасные изменения (разрешены всегда)","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["✅ Безопасные изменения (разрешены всегда)"],"excerpt":"✅ Безопасные изменения (разрешены всегда) ```proto // Добавление новых элементов — безопасно message User { string name = 1; string email = 2; string phone = 3; // ✅ Новое поле }","content":"✅ Безопасные изменения (разрешены всегда) ```proto // Добавление новых элементов — безопасно message User { string name = 1; string email = 2; string phone = 3; // ✅ Новое поле }"},{"id":"cli/breaking-changes/breaking-changes::top::30","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"✅ Безопасные изменения (разрешены всегда)","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["✅ Безопасные изменения (разрешены всегда)"],"excerpt":"✅ Безопасные изменения (разрешены всегда) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc GetUserProfile(GetUserRequest) returns (UserProfile); // ✅ Новый RPC }","content":"✅ Безопасные изменения (разрешены всегда) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc GetUserProfile(GetUserRequest) returns (UserProfile); // ✅ Новый RPC }"},{"id":"cli/breaking-changes/breaking-changes::top::31","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"✅ Безопасные изменения (разрешены всегда)","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["✅ Безопасные изменения (разрешены всегда)"],"excerpt":"✅ Безопасные изменения (разрешены всегда) enum Status { STATUS_UNSPECIFIED = 0; STATUS_ACTIVE = 1; STATUS_PENDING = 2; // ✅ Новое enum значение } ```","content":"✅ Безопасные изменения (разрешены всегда) enum Status { STATUS_UNSPECIFIED = 0; STATUS_ACTIVE = 1; STATUS_PENDING = 2; // ✅ Новое enum значение } ```"},{"id":"cli/breaking-changes/breaking-changes::top::32","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"❌ Несовместимые изменения (обнаруживаются всегда)","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["❌ Несовместимые изменения (обнаруживаются всегда)"],"excerpt":"❌ Несовместимые изменения (обнаруживаются всегда) ```proto // Удаления и смена типов ломают совместимость message User { string name = 1; // ❌ Удалённое поле }","content":"❌ Несовместимые изменения (обнаруживаются всегда) ```proto // Удаления и смена типов ломают совместимость message User { string name = 1; // ❌ Удалённое поле }"},{"id":"cli/breaking-changes/breaking-changes::top::33","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"❌ Несовместимые изменения (обнаруживаются всегда)","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["❌ Несовместимые изменения (обнаруживаются всегда)"],"excerpt":"❌ Несовместимые изменения (обнаруживаются всегда) service UserService { // ❌ Удалённый RPC метод rpc GetUser(GetUserRequestV2) returns (GetUserResponse); // ❌ Изменён тип запроса } ```","content":"❌ Несовместимые изменения (обнаруживаются всегда) service UserService { // ❌ Удалённый RPC метод rpc GetUser(GetUserRequestV2) returns (GetUserResponse); // ❌ Изменён тип запроса } ```"},{"id":"cli/breaking-changes/breaking-changes::top::34","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Сценарий: Изменения пока не детектируются","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Сценарий: Изменения пока не детектируются"],"excerpt":"Сценарий: Изменения пока не детектируются ```proto // 🟡 Ломает сгенерированный код, но проходит проверки EasyP message User { string user_name = 1; // Переименовано с \"name\" string user_email = 2; // Переименовано с \"em","content":"Сценарий: Изменения пока не детектируются ```proto // 🟡 Ломает сгенерированный код, но проходит проверки EasyP message User { string user_name = 1; // Переименовано с \"name\" string user_email = 2; // Переименовано с \"email\" }"},{"id":"cli/breaking-changes/breaking-changes::top::35","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Сценарий: Изменения пока не детектируются","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Сценарий: Изменения пока не детектируются"],"excerpt":"Сценарий: Изменения пока не детектируются service UserService { rpc GetUserProfile(GetUserRequest) returns (GetUserResponse); // Переименовано с GetUser } ```","content":"Сценарий: Изменения пока не детектируются service UserService { rpc GetUserProfile(GetUserRequest) returns (GetUserResponse); // Переименовано с GetUser } ```"},{"id":"cli/breaking-changes/breaking-changes::top::36","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Текстовый формат (по умолчанию)","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Текстовый формат (по умолчанию)"],"excerpt":"Текстовый формат (по умолчанию)","content":"Текстовый формат (по умолчанию)"},{"id":"cli/breaking-changes/breaking-changes::1::37","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"1. Регулярный запуск","path":"/docs/guide/cli/breaking-changes/breaking-changes#1","headings":["1. Регулярный запуск"],"excerpt":"Регулярный запуск Добавьте проверку несовместимых изменений в CI/CD:","content":"Регулярный запуск Добавьте проверку несовместимых изменений в CI/CD:"},{"id":"cli/breaking-changes/breaking-changes::2::38","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"2. Защита веток","path":"/docs/guide/cli/breaking-changes/breaking-changes#2","headings":["2. Защита веток"],"excerpt":"Защита веток Блокируйте слияния с breaking изменениями:","content":"Защита веток Блокируйте слияния с breaking изменениями:"},{"id":"cli/breaking-changes/breaking-changes::3::39","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"3. Стратегия версионирования","path":"/docs/guide/cli/breaking-changes/breaking-changes#3","headings":["3. Стратегия версионирования"],"excerpt":"Стратегия версионирования При необходимости breaking изменений: Создайте новую версию пакета (myservice.v2) Поддерживайте старую версию в период миграции Добавляйте уведомления о деприкации","content":"Стратегия версионирования При необходимости breaking изменений: Создайте новую версию пакета (myservice.v2) Поддерживайте старую версию в период миграции Добавляйте уведомления о деприкации"},{"id":"cli/breaking-changes/breaking-changes::4::40","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"4. Игнорирование путей","path":"/docs/guide/cli/breaking-changes/breaking-changes#4","headings":["4. Игнорирование путей"],"excerpt":"Игнорирование путей Используйте ignore осознанно:","content":"Игнорирование путей Используйте ignore осознанно:"},{"id":"cli/breaking-changes/breaking-changes::repository-does-not-exist::41","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Проблема: \"Repository does not exist\"","path":"/docs/guide/cli/breaking-changes/breaking-changes#repository-does-not-exist","headings":["Проблема: \"Repository does not exist\""],"excerpt":"Проблема: \"Repository does not exist\" Решение: Выполняйте команду внутри Git репозитория с нужной веткой.","content":"Проблема: \"Repository does not exist\" Решение: Выполняйте команду внутри Git репозитория с нужной веткой."},{"id":"cli/breaking-changes/breaking-changes::cannot-find-git-ref::42","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Проблема: \"Cannot find git ref\"","path":"/docs/guide/cli/breaking-changes/breaking-changes#cannot-find-git-ref","headings":["Проблема: \"Cannot find git ref\""],"excerpt":"Проблема: \"Cannot find git ref\" Решение: Проверьте наличие ссылки:","content":"Проблема: \"Cannot find git ref\" Решение: Проверьте наличие ссылки:"},{"id":"cli/breaking-changes/breaking-changes::top::43","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Проблема: Ложные срабатывания на сгенерированный код","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Проблема: Ложные срабатывания на сгенерированный код"],"excerpt":"Проблема: Ложные срабатывания на сгенерированный код Решение: Исключите директории генерации:","content":"Проблема: Ложные срабатывания на сгенерированный код Решение: Исключите директории генерации:"},{"id":"cli/breaking-changes/breaking-changes::top::44","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Проблема: Очень много изменений","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Проблема: Очень много изменений"],"excerpt":"Проблема: Очень много изменений Решение: Создайте новую версию API Вносите изменения постепенно Используйте feature flags","content":"Проблема: Очень много изменений Решение: Создайте новую версию API Вносите изменения постепенно Используйте feature flags"},{"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 - name: Install EasyP run: curl -sSfL https://raw.githubusercontent.com/easyp-tech/easyp/main/install.","content":"GitHub Actions jobs: breaking-changes: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 with: fetch-depth: 0 - 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-pre-push-hook::48","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Pre-commit / pre-push hook","path":"/docs/guide/cli/breaking-changes/breaking-changes#pre-commit-pre-push-hook","headings":["Pre-commit / pre-push hook"],"excerpt":"Pre-commit / pre-push hook ```bash #!/bin/sh .git/hooks/pre-push","content":"Pre-commit / pre-push hook ```bash #!/bin/sh .git/hooks/pre-push"},{"id":"cli/breaking-changes/breaking-changes::pre-commit-pre-push-hook::49","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Pre-commit / pre-push hook","path":"/docs/guide/cli/breaking-changes/breaking-changes#pre-commit-pre-push-hook","headings":["Pre-commit / pre-push hook"],"excerpt":"Pre-commit / pre-push hook protected_branch='main' current_branch=$(git symbolic-ref HEAD sed -e 's,.*/\\(.*\\),\\1,')","content":"Pre-commit / pre-push hook protected_branch='main' current_branch=$(git symbolic-ref HEAD sed -e 's,.*/\\(.*\\),\\1,')"},{"id":"cli/breaking-changes/breaking-changes::pre-commit-pre-push-hook::50","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Pre-commit / pre-push hook","path":"/docs/guide/cli/breaking-changes/breaking-changes#pre-commit-pre-push-hook","headings":["Pre-commit / pre-push hook"],"excerpt":"Pre-commit / pre-push 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.","content":"Pre-commit / pre-push 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::top::51","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Режим отладки","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Режим отладки"],"excerpt":"Режим отладки Включите debug‑логирование:","content":"Режим отладки Включите debug‑логирование:"},{"id":"cli/breaking-changes/breaking-changes::top::52","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Ручное сравнение","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Ручное сравнение"],"excerpt":"Ручное сравнение Для сложных случаев:","content":"Ручное сравнение Для сложных случаев:"},{"id":"cli/breaking-changes/breaking-changes::top::53","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Оптимизация производительности","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Оптимизация производительности"],"excerpt":"Оптимизация производительности Ограничьте область:","content":"Оптимизация производительности Ограничьте область:"},{"id":"cli/breaking-changes/breaking-changes::top::54","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Оптимизация производительности","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Оптимизация производительности"],"excerpt":"Оптимизация производительности","content":"Оптимизация производительности"},{"id":"cli/breaking-changes/breaking-changes::top::55","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Оптимизация производительности","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Оптимизация производительности"],"excerpt":"Оптимизация производительности Механизм обнаружения несовместимых изменений в EasyP обеспечивает надёжную основу для безопасной эволюции protobuf‑схем при сохранении совместимости API.","content":"Оптимизация производительности Механизм обнаружения несовместимых изменений в EasyP обеспечивает надёжную основу для безопасной эволюции protobuf‑схем при сохранении совместимости API."},{"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":"Это правило проверяет, что ни один enum не был удалён из proto‑файлов. Удаление enum ломает совместимость по wire‑формату и сгенерированный код: сохранённые данные могут содержать удалённые значения, а клиентский код опи","content":"Это правило проверяет, что ни один enum не был удалён из proto‑файлов. Удаление enum ломает совместимость по wire‑формату и сгенерированный код: сохранённые данные могут содержать удалённые значения, а клиентский код опирается на сгенерированные типы и константы enum."},{"id":"cli/breaking-changes/rules/enum-no-delete::breaking::1","title":"ENUM_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-no-delete::breaking::2","title":"ENUM_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/enum-no-delete::breaking::3","title":"ENUM_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_CONFIRMED = 2; ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_DELIVERED = 4; }","content":"Плохой (Breaking) 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::breaking::4","title":"ENUM_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) enum UserRole { // [!code --] USER_ROLE_UNSPECIFIED = 0; // [!code --] USER_ROLE_ADMIN = 1; // [!code --] USER_ROLE_USER = 2; // [!code --] } // [!code --]","content":"Плохой (Breaking) 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::breaking::5","title":"ENUM_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message Order { string id = 1; OrderStatus status = 2; UserRole created_by_role = 3; } ```","content":"Плохой (Breaking) message Order { string id = 1; OrderStatus status = 2; UserRole created_by_role = 3; } ```"},{"id":"cli/breaking-changes/rules/enum-no-delete::breaking::6","title":"ENUM_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-no-delete::breaking::7","title":"ENUM_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/enum-no-delete::breaking::8","title":"ENUM_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_CONFIRMED = 2; ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_DELIVERED = 4; }","content":"Плохой (Breaking) 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::breaking::9","title":"ENUM_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) // UserRole enum удалён — BREAKING CHANGE!","content":"Плохой (Breaking) // UserRole enum удалён — BREAKING CHANGE!"},{"id":"cli/breaking-changes/rules/enum-no-delete::breaking::10","title":"ENUM_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message Order { string id = 1; OrderStatus status = 2; UserRole created_by_role = 3; // ERROR: UserRole больше не существует } ```","content":"Плохой (Breaking) message Order { string id = 1; OrderStatus status = 2; UserRole created_by_role = 3; // ERROR: UserRole больше не существует } ```"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::11","title":"ENUM_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры **Удаление вложенного enum:** ```proto // Before message User { string name = 1; Status status = 2; enum Status { // [!code --] STATUS_UNSPECIFIED = 0; // [!code --] STATUS_ACTIVE = 1; // [!code --","content":"Дополнительные примеры **Удаление вложенного enum:** ```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::top::12","title":"ENUM_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры // After - BREAKING CHANGE! message User { string name = 1; Status status = 2; // ERROR: Status удалён // Вложенный enum Status удалён } ```","content":"Дополнительные примеры // After - BREAKING CHANGE! message User { string name = 1; Status status = 2; // ERROR: Status удалён // Вложенный enum Status удалён } ```"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::13","title":"ENUM_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо удаления — пометить enum deprecated:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо удаления — пометить enum deprecated:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::14","title":"ENUM_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::15","title":"ENUM_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_CONFIRMED = 2; ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_DELIVERED = 4; }","content":"Хороший (Безопасный) 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::top::16","title":"ENUM_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) enum UserRole { option deprecated = true; // [!code focus] USER_ROLE_UNSPECIFIED = 0; USER_ROLE_ADMIN = 1; USER_ROLE_USER = 2; }","content":"Хороший (Безопасный) 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::top::17","title":"ENUM_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message Order { string id = 1; OrderStatus status = 2; UserRole created_by_role = 3 [deprecated = true]; // [!code focus] } ```","content":"Хороший (Безопасный) 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::top::18","title":"ENUM_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Или заменить новым enum:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Или заменить новым enum:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::19","title":"ENUM_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::20","title":"ENUM_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_CONFIRMED = 2; ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_DELIVERED = 4; }","content":"Хороший (Безопасный) 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::top::21","title":"ENUM_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) enum UserRole { option deprecated = true; // [!code focus] // Старый enum USER_ROLE_UNSPECIFIED = 0; USER_ROLE_ADMIN = 1; USER_ROLE_USER = 2; }","content":"Хороший (Безопасный) enum UserRole { option deprecated = true; // [!code focus] // Старый enum USER_ROLE_UNSPECIFIED = 0; USER_ROLE_ADMIN = 1; USER_ROLE_USER = 2; }"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::22","title":"ENUM_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) enum UserPermission { // [!code focus] // Новый enum USER_PERMISSION_UNSPECIFIED = 0; // [!code focus] USER_PERMISSION_READ = 1; // [!code focus] USER_PERMISSION_WRITE = 2; // [!code focus] USER_PERM","content":"Хороший (Безопасный) enum UserPermission { // [!code focus] // Новый enum 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::top::23","title":"ENUM_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message Order { string id = 1; OrderStatus status = 2; UserRole created_by_role = 3 [deprecated = true]; // [!code focus] UserPermission created_by_permission = 4; // [!code focus] } ```","content":"Хороший (Безопасный) message Order { string id = 1; OrderStatus status = 2; UserRole created_by_role = 3 [deprecated = true]; // [!code focus] UserPermission created_by_permission = 4; // [!code focus] } ```"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::24","title":"ENUM_NO_DELETE","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Влияние"],"excerpt":"Влияние **Wire Format:** Данные с удалённым enum не десериализуются корректно **Generated Code:** Тип и константы удаляются — компиляция клиентов ломается **Field References:** Поля с типом удалённого enum становятся нев","content":"Влияние **Wire Format:** Данные с удалённым enum не десериализуются корректно **Generated Code:** Тип и константы удаляются — компиляция клиентов ломается **Field References:** Поля с типом удалённого enum становятся невалидны **Switch Statements:** switch по enum ломается (неизвестные кейсы)"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::25","title":"ENUM_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Код клиента ломается:** ```go // Before order := &myapi.Order{ Id: \"order123\", Status: myapi.OrderStatus_ORDER_STATUS_PENDING, CreatedByRole: myapi.UserRole_USER_ROLE_ADMIN, // ERROR после удаления }","content":"Реальный пример **Код клиента ломается:** ```go // Before order := &myapi.Order{ Id: \"order123\", Status: myapi.OrderStatus_ORDER_STATUS_PENDING, CreatedByRole: myapi.UserRole_USER_ROLE_ADMIN, // ERROR после удаления }"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::26","title":"ENUM_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример switch order.CreatedByRole { case myapi.UserRole_USER_ROLE_ADMIN: // ERROR // Admin logic case myapi.UserRole_USER_ROLE_USER: // ERROR // User logic }","content":"Реальный пример switch order.CreatedByRole { case myapi.UserRole_USER_ROLE_ADMIN: // ERROR // Admin logic case myapi.UserRole_USER_ROLE_USER: // ERROR // User logic }"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::27","title":"ENUM_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример // undefined: myapi.UserRole // undefined: myapi.UserRole_USER_ROLE_ADMIN ```","content":"Реальный пример // undefined: myapi.UserRole // undefined: myapi.UserRole_USER_ROLE_ADMIN ```"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::28","title":"ENUM_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Старые данные становятся нечитаемыми:**","content":"Реальный пример **Старые данные становятся нечитаемыми:**"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::29","title":"ENUM_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Серверная логика ломается:**","content":"Реальный пример **Серверная логика ломается:**"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::30","title":"ENUM_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Депрецируйте enum:** **Пометьте поля со старым enum deprecated:** **Создайте новый enum:** **Сервер обрабатывает оба:** **Удалите старый enum в следующей major‑версии.**","content":"Стратегия миграции **Депрецируйте enum:** **Пометьте поля со старым enum deprecated:** **Создайте новый enum:** **Сервер обрабатывает оба:** **Удалите старый enum в следующей major‑версии.**"},{"id":"cli/breaking-changes/rules/enum-no-delete::enum::31","title":"ENUM_NO_DELETE","section":"Редизайн enum","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#enum","headings":["Редизайн enum"],"excerpt":"Редизайн enum ```proto enum Priority { option deprecated = true; PRIORITY_UNSPECIFIED = 0; PRIORITY_LOW = 1; PRIORITY_HIGH = 2; }","content":"Редизайн enum ```proto enum Priority { option deprecated = true; PRIORITY_UNSPECIFIED = 0; PRIORITY_LOW = 1; PRIORITY_HIGH = 2; }"},{"id":"cli/breaking-changes/rules/enum-no-delete::enum::32","title":"ENUM_NO_DELETE","section":"Редизайн enum","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#enum","headings":["Редизайн enum"],"excerpt":"Редизайн enum enum TaskPriority { TASK_PRIORITY_UNSPECIFIED = 0; TASK_PRIORITY_LOW = 1; TASK_PRIORITY_MEDIUM = 2; TASK_PRIORITY_HIGH = 3; TASK_PRIORITY_URGENT = 4; } ```","content":"Редизайн enum enum TaskPriority { 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::enum::33","title":"ENUM_NO_DELETE","section":"Консолидация enum","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#enum","headings":["Консолидация enum"],"excerpt":"Консолидация enum ```proto enum Status { option deprecated = true; STATUS_UNSPECIFIED = 0; STATUS_ACTIVE = 1; }","content":"Консолидация enum ```proto enum Status { option deprecated = true; STATUS_UNSPECIFIED = 0; STATUS_ACTIVE = 1; }"},{"id":"cli/breaking-changes/rules/enum-no-delete::enum::34","title":"ENUM_NO_DELETE","section":"Консолидация enum","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#enum","headings":["Консолидация enum"],"excerpt":"Консолидация enum enum State { option deprecated = true; STATE_UNSPECIFIED = 0; STATE_ENABLED = 1; }","content":"Консолидация enum enum State { option deprecated = true; STATE_UNSPECIFIED = 0; STATE_ENABLED = 1; }"},{"id":"cli/breaking-changes/rules/enum-no-delete::enum::35","title":"ENUM_NO_DELETE","section":"Консолидация enum","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#enum","headings":["Консолидация enum"],"excerpt":"Консолидация enum enum EntityStatus { ENTITY_STATUS_UNSPECIFIED = 0; ENTITY_STATUS_ACTIVE = 1; ENTITY_STATUS_INACTIVE = 2; ENTITY_STATUS_ENABLED = 3; ENTITY_STATUS_DISABLED = 4; } ```","content":"Консолидация enum enum EntityStatus { 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::enum::36","title":"ENUM_NO_DELETE","section":"Перемещение enum в новый пакет","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#enum","headings":["Перемещение enum в новый пакет"],"excerpt":"Перемещение enum в новый пакет ```proto enum UserRole { option deprecated = true; USER_ROLE_UNSPECIFIED = 0; USER_ROLE_ADMIN = 1; }","content":"Перемещение enum в новый пакет ```proto enum UserRole { option deprecated = true; USER_ROLE_UNSPECIFIED = 0; USER_ROLE_ADMIN = 1; }"},{"id":"cli/breaking-changes/rules/enum-no-delete::enum::37","title":"ENUM_NO_DELETE","section":"Перемещение enum в новый пакет","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#enum","headings":["Перемещение enum в новый пакет"],"excerpt":"Перемещение enum в новый пакет import \"common/roles.proto\";","content":"Перемещение enum в новый пакет import \"common/roles.proto\";"},{"id":"cli/breaking-changes/rules/enum-no-delete::enum::38","title":"ENUM_NO_DELETE","section":"Перемещение enum в новый пакет","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#enum","headings":["Перемещение enum в новый пакет"],"excerpt":"Перемещение enum в новый пакет message Order { UserRole old_role = 3 [deprecated = true]; common.UserRole new_role = 4; } ```","content":"Перемещение enum в новый пакет message Order { UserRole old_role = 3 [deprecated = true]; common.UserRole new_role = 4; } ```"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::39","title":"ENUM_NO_DELETE","section":"Версионирование / новая версия пакета","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Версионирование / новая версия пакета"],"excerpt":"Версионирование / новая версия пакета ```proto package myapi.v2;","content":"Версионирование / новая версия пакета ```proto package myapi.v2;"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::40","title":"ENUM_NO_DELETE","section":"Версионирование / новая версия пакета","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Версионирование / новая версия пакета"],"excerpt":"Версионирование / новая версия пакета enum UserPermission { USER_PERMISSION_UNSPECIFIED = 0; USER_PERMISSION_READ = 1; USER_PERMISSION_WRITE = 2; USER_PERMISSION_ADMIN = 3; }","content":"Версионирование / новая версия пакета 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::top::41","title":"ENUM_NO_DELETE","section":"Версионирование / новая версия пакета","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Версионирование / новая версия пакета"],"excerpt":"Версионирование / новая версия пакета message Order { string id = 1; UserPermission created_by_permission = 2; } ```","content":"Версионирование / новая версия пакета message Order { string id = 1; UserPermission created_by_permission = 2; } ```"},{"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":"Правило проверяет, что ни одно значение enum (enum value) не было удалено. Удаление значения ломает совместимость по wire‑формату и сгенерированный код: в уже сохранённых данных могут присутствовать удалённые значения, а","content":"Правило проверяет, что ни одно значение enum (enum value) не было удалено. Удаление значения ломает совместимость по wire‑формату и сгенерированный код: в уже сохранённых данных могут присутствовать удалённые значения, а клиентский код может ссылаться на соответствующие константы."},{"id":"cli/breaking-changes/rules/enum-value-no-delete::breaking::1","title":"ENUM_VALUE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::breaking::2","title":"ENUM_VALUE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::breaking::3","title":"ENUM_VALUE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) 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":"Плохой (Breaking) 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::breaking::4","title":"ENUM_VALUE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) enum Priority { PRIORITY_UNSPECIFIED = 0; PRIORITY_LOW = 1; PRIORITY_MEDIUM = 2; PRIORITY_HIGH = 3; PRIORITY_URGENT = 4; } ```","content":"Плохой (Breaking) 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::breaking::5","title":"ENUM_VALUE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::breaking::6","title":"ENUM_VALUE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::breaking::7","title":"ENUM_VALUE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) 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 --] ","content":"Плохой (Breaking) 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 --] Удалено значение enum — BREAKING! }"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::breaking::8","title":"ENUM_VALUE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) enum Priority { PRIORITY_UNSPECIFIED = 0; PRIORITY_LOW = 1; PRIORITY_MEDIUM = 2; PRIORITY_HIGH = 3; // PRIORITY_URGENT = 4; // [!code --] Удалено значение enum — BREAKING! } ```","content":"Плохой (Breaking) enum Priority { PRIORITY_UNSPECIFIED = 0; PRIORITY_LOW = 1; PRIORITY_MEDIUM = 2; PRIORITY_HIGH = 3; // PRIORITY_URGENT = 4; // [!code --] Удалено значение enum — BREAKING! } ```"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::9","title":"ENUM_VALUE_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры **Множественное удаление значений:** ```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_S","content":"Дополнительные примеры **Множественное удаление значений:** ```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::top::10","title":"ENUM_VALUE_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры // 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","content":"Дополнительные примеры // 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::top::11","title":"ENUM_VALUE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо удаления — пометить значения deprecated:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо удаления — пометить значения deprecated:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::12","title":"ENUM_VALUE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::13","title":"ENUM_VALUE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) 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 = t","content":"Хороший (Безопасный) 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::top::14","title":"ENUM_VALUE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) enum Priority { PRIORITY_UNSPECIFIED = 0; PRIORITY_LOW = 1; PRIORITY_MEDIUM = 2; PRIORITY_HIGH = 3; PRIORITY_URGENT = 4 [deprecated = true]; // [!code focus] } ```","content":"Хороший (Безопасный) 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::top::15","title":"ENUM_VALUE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Или зарезервировать номер и имя после удаления:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Или зарезервировать номер и имя после удаления:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::16","title":"ENUM_VALUE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::17","title":"ENUM_VALUE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) enum OrderStatus { reserved 5; // [!code focus] reserved \"ORDER_STATUS_CANCELLED\"; // [!code focus]","content":"Хороший (Безопасный) enum OrderStatus { reserved 5; // [!code focus] reserved \"ORDER_STATUS_CANCELLED\"; // [!code focus]"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::18","title":"ENUM_VALUE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_CONFIRMED = 2; ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_DELIVERED = 4; }","content":"Хороший (Безопасный) 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::top::19","title":"ENUM_VALUE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) enum Priority { reserved 4; // [!code focus] reserved \"PRIORITY_URGENT\"; // [!code focus]","content":"Хороший (Безопасный) enum Priority { reserved 4; // [!code focus] reserved \"PRIORITY_URGENT\"; // [!code focus]"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::20","title":"ENUM_VALUE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) PRIORITY_UNSPECIFIED = 0; PRIORITY_LOW = 1; PRIORITY_MEDIUM = 2; PRIORITY_HIGH = 3; } ```","content":"Хороший (Безопасный) PRIORITY_UNSPECIFIED = 0; PRIORITY_LOW = 1; PRIORITY_MEDIUM = 2; PRIORITY_HIGH = 3; } ```"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::21","title":"ENUM_VALUE_NO_DELETE","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Влияние"],"excerpt":"Влияние **Wire Format:** Данные с удалёнными значениями не десериализуются корректно **Generated Code:** Константы исчезают — клиентский код не компилируется **Client Applications:** Ссылки на удалённые значения вызывают","content":"Влияние **Wire Format:** Данные с удалёнными значениями не десериализуются корректно **Generated Code:** Константы исчезают — клиентский код не компилируется **Client Applications:** Ссылки на удалённые значения вызывают ошибки компиляции **Switch Statements:** switch по enum ломается (неизвестные case) **Default Handling:** Поведение при неизвестных значениях меняется"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::22","title":"ENUM_VALUE_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Код клиента ломается:** ```go order := &myapi.Order{ Status: myapi.OrderStatus_ORDER_STATUS_CANCELLED, // ERROR после удаления }","content":"Реальный пример **Код клиента ломается:** ```go order := &myapi.Order{ Status: myapi.OrderStatus_ORDER_STATUS_CANCELLED, // ERROR после удаления }"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::23","title":"ENUM_VALUE_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример switch order.Status { case myapi.OrderStatus_ORDER_STATUS_PENDING: // Pending case myapi.OrderStatus_ORDER_STATUS_CANCELLED: // ERROR: undefined // Cancellation default: // Unknown } // undefined: myapi.O","content":"Реальный пример switch order.Status { case myapi.OrderStatus_ORDER_STATUS_PENDING: // Pending case myapi.OrderStatus_ORDER_STATUS_CANCELLED: // ERROR: undefined // Cancellation default: // Unknown } // undefined: myapi.OrderStatus_ORDER_STATUS_CANCELLED ```"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::24","title":"ENUM_VALUE_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Проблемы с уже сохранёнными данными:**","content":"Реальный пример **Проблемы с уже сохранёнными данными:**"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::25","title":"ENUM_VALUE_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Валидация на сервере:** ```go func validateOrderStatus(status OrderStatus) error { switch status { case OrderStatus_ORDER_STATUS_PENDING, OrderStatus_ORDER_STATUS_CONFIRMED, OrderStatus_ORDER_STATUS_SHI","content":"Реальный пример **Валидация на сервере:** ```go 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 после удаления return nil default: return errors.New(\"invalid order status\") } }"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::26","title":"ENUM_VALUE_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример func canModifyOrder(order *Order) bool { return order.Status != OrderStatus_ORDER_STATUS_CANCELLED // ERROR } ```","content":"Реальный пример func canModifyOrder(order *Order) bool { return order.Status != OrderStatus_ORDER_STATUS_CANCELLED // ERROR } ```"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::27","title":"ENUM_VALUE_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Сначала пометить deprecated:** **Перестать использовать deprecated значение в новом коде:** **Обработка legacy в клиенте:** **Резервирование после миграции:** **Никогда не переиспользовать номера** —","content":"Стратегия миграции **Сначала пометить deprecated:** **Перестать использовать deprecated значение в новом коде:** **Обработка legacy в клиенте:** **Резервирование после миграции:** **Никогда не переиспользовать номера** — зарезервированы навсегда."},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::28","title":"ENUM_VALUE_NO_DELETE","section":"Предотвращение переиспользования номера","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Предотвращение переиспользования номера"],"excerpt":"Предотвращение переиспользования номера ```proto enum Status { reserved 2; reserved \"STATUS_DELETED\";","content":"Предотвращение переиспользования номера ```proto enum Status { reserved 2; reserved \"STATUS_DELETED\";"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::29","title":"ENUM_VALUE_NO_DELETE","section":"Предотвращение переиспользования номера","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Предотвращение переиспользования номера"],"excerpt":"Предотвращение переиспользования номера STATUS_UNSPECIFIED = 0; STATUS_ACTIVE = 1; STATUS_INACTIVE = 3; // STATUS_DELETED = 2; // Не переиспользуем } ```","content":"Предотвращение переиспользования номера STATUS_UNSPECIFIED = 0; STATUS_ACTIVE = 1; STATUS_INACTIVE = 3; // STATUS_DELETED = 2; // Не переиспользуем } ```"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::json::30","title":"ENUM_VALUE_NO_DELETE","section":"JSON совместимость","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#json","headings":["JSON совместимость"],"excerpt":"JSON совместимость ```proto enum Color { reserved 2; reserved \"RED\";","content":"JSON совместимость ```proto enum Color { reserved 2; reserved \"RED\";"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::json::31","title":"ENUM_VALUE_NO_DELETE","section":"JSON совместимость","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#json","headings":["JSON совместимость"],"excerpt":"JSON совместимость COLOR_UNSPECIFIED = 0; COLOR_BLUE = 1; COLOR_GREEN = 3; // COLOR_RED = 2; // Был удалён } ```","content":"JSON совместимость COLOR_UNSPECIFIED = 0; COLOR_BLUE = 1; COLOR_GREEN = 3; // COLOR_RED = 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":"Это правило проверяет, что имя enum значения для каждого номера (number) не изменилось. Переименование enum значения при сохранении его номера ломает совместимость JSON и сгенерированный код: клиенты ожидают конкретные и","content":"Это правило проверяет, что имя enum значения для каждого номера (number) не изменилось. Переименование enum значения при сохранении его номера ломает совместимость JSON и сгенерированный код: клиенты ожидают конкретные имена констант."},{"id":"cli/breaking-changes/rules/enum-value-same-name::breaking::1","title":"ENUM_VALUE_SAME_NAME","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-value-same-name::breaking::2","title":"ENUM_VALUE_SAME_NAME","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/enum-value-same-name::breaking::3","title":"ENUM_VALUE_SAME_NAME","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_CONFIRMED = 2; ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_DELIVERED = 4; } ```","content":"Плохой (Breaking) 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::breaking::4","title":"ENUM_VALUE_SAME_NAME","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-value-same-name::breaking::5","title":"ENUM_VALUE_SAME_NAME","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/enum-value-same-name::breaking::6","title":"ENUM_VALUE_SAME_NAME","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_APPROVED = 2; // [!code --] Было ORDER_STATUS_CONFIRMED ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_COMPLETED = 4; // [","content":"Плохой (Breaking) enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_APPROVED = 2; // [!code --] Было ORDER_STATUS_CONFIRMED ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_COMPLETED = 4; // [!code --] Было ORDER_STATUS_DELIVERED } ```"},{"id":"cli/breaking-changes/rules/enum-value-same-name::top::7","title":"ENUM_VALUE_SAME_NAME","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры **Множественные переименования:** ```proto // Before enum UserRole { USER_ROLE_UNSPECIFIED = 0; USER_ROLE_ADMIN = 1; USER_ROLE_MODERATOR = 2; USER_ROLE_USER = 3; }","content":"Дополнительные примеры **Множественные переименования:** ```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::top::8","title":"ENUM_VALUE_SAME_NAME","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры // After - ВСЁ BREAKING enum UserRole { USER_ROLE_UNSPECIFIED = 0; USER_ROLE_ADMINISTRATOR = 1; // BREAKING: ADMIN -> ADMINISTRATOR USER_ROLE_MOD = 2; // BREAKING: MODERATOR -> MOD USER_ROLE_MEMBER","content":"Дополнительные примеры // After - ВСЁ BREAKING 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::top::9","title":"ENUM_VALUE_SAME_NAME","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо переименования — добавить новые значения и пометить старые deprecated:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо переименования — добавить новые значения и пометить старые deprecated:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-value-same-name::top::10","title":"ENUM_VALUE_SAME_NAME","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/enum-value-same-name::top::11","title":"ENUM_VALUE_SAME_NAME","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) 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 [depre","content":"Хороший (Безопасный) 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] // Новое значение вместо переименования ORDER_STATUS_COMPLETED = 6; // [!code focus] } ```"},{"id":"cli/breaking-changes/rules/enum-value-same-name::top::12","title":"ENUM_VALUE_SAME_NAME","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Или создать новую версию enum:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Или создать новую версию enum:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-value-same-name::top::13","title":"ENUM_VALUE_SAME_NAME","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v2; // [!code focus]","content":"Хороший (Безопасный) package myapi.v2; // [!code focus]"},{"id":"cli/breaking-changes/rules/enum-value-same-name::top::14","title":"ENUM_VALUE_SAME_NAME","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_APPROVED = 2; // [!code focus] // «Чистые» имена в v2 ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_COMPLETED = 4; // ","content":"Хороший (Безопасный) enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_APPROVED = 2; // [!code focus] // «Чистые» имена в v2 ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_COMPLETED = 4; // [!code focus] } ```"},{"id":"cli/breaking-changes/rules/enum-value-same-name::top::15","title":"ENUM_VALUE_SAME_NAME","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Влияние"],"excerpt":"Влияние **Generated Code:** Меняются имена констант — компиляция клиентов ломается **JSON Compatibility:** JSON использует имена enum — старые документы не парсятся **Client Applications:** Код со старым именем константы","content":"Влияние **Generated Code:** Меняются имена констант — компиляция клиентов ломается **JSON Compatibility:** JSON использует имена enum — старые документы не парсятся **Client Applications:** Код со старым именем константы не компилируется **Documentation:** Документация устаревает с неправильными именами"},{"id":"cli/breaking-changes/rules/enum-value-same-name::top::16","title":"ENUM_VALUE_SAME_NAME","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Реальный пример"],"excerpt":"Реальный пример **Ломается код клиента:** ```go // Before status := myapi.OrderStatus_ORDER_STATUS_CONFIRMED if order.Status == myapi.OrderStatus_ORDER_STATUS_DELIVERED { // handle delivery }","content":"Реальный пример **Ломается код клиента:** ```go // Before 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::top::17","title":"ENUM_VALUE_SAME_NAME","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Реальный пример"],"excerpt":"Реальный пример // After (переименовано) — ошибки компиляции status := myapi.OrderStatus_ORDER_STATUS_CONFIRMED // ERROR: undefined if order.Status == myapi.OrderStatus_ORDER_STATUS_DELIVERED { // ERROR: undefined // han","content":"Реальный пример // After (переименовано) — ошибки компиляции status := myapi.OrderStatus_ORDER_STATUS_CONFIRMED // ERROR: undefined if order.Status == myapi.OrderStatus_ORDER_STATUS_DELIVERED { // ERROR: undefined // handle delivery } ```"},{"id":"cli/breaking-changes/rules/enum-value-same-name::top::18","title":"ENUM_VALUE_SAME_NAME","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Реальный пример"],"excerpt":"Реальный пример **JSON совместимость ломается:** ```json // Раньше { \"status\": \"ORDER_STATUS_CONFIRMED\" }","content":"Реальный пример **JSON совместимость ломается:** ```json // Раньше { \"status\": \"ORDER_STATUS_CONFIRMED\" }"},{"id":"cli/breaking-changes/rules/enum-value-same-name::top::19","title":"ENUM_VALUE_SAME_NAME","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Реальный пример"],"excerpt":"Реальный пример // После { \"status\": \"ORDER_STATUS_APPROVED\" // Старые JSON больше не парсятся } ```","content":"Реальный пример // После { \"status\": \"ORDER_STATUS_APPROVED\" // Старые JSON больше не парсятся } ```"},{"id":"cli/breaking-changes/rules/enum-value-same-name::top::20","title":"ENUM_VALUE_SAME_NAME","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Добавьте новое значение вместо переименования:**","content":"Стратегия миграции **Добавьте новое значение вместо переименования:**"},{"id":"cli/breaking-changes/rules/enum-value-same-name::top::21","title":"ENUM_VALUE_SAME_NAME","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Сервер обрабатывает оба значения на переходном этапе** **Мигрируйте клиентов** на новые значения **Удалите (reserve) старое имя и номер** в следующей major‑версии:","content":"Стратегия миграции **Сервер обрабатывает оба значения на переходном этапе** **Мигрируйте клиентов** на новые значения **Удалите (reserve) старое имя и номер** в следующей major‑версии:"},{"id":"cli/breaking-changes/rules/enum-value-same-name::allow-alias::22","title":"ENUM_VALUE_SAME_NAME","section":"Allow Alias (исключение)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name#allow-alias","headings":["Allow Alias (исключение)"],"excerpt":"Allow Alias (исключение) С allow_alias = true можно временно иметь два имени для одного номера:","content":"Allow Alias (исключение) С allow_alias = true можно временно иметь два имени для одного номера:"},{"id":"cli/breaking-changes/rules/enum-value-same-name::allow-alias::23","title":"ENUM_VALUE_SAME_NAME","section":"Allow Alias (исключение)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name#allow-alias","headings":["Allow Alias (исключение)"],"excerpt":"Allow Alias (исключение) Примечание: Сейчас EasyP всё равно считает это breaking (может измениться в будущем).","content":"Allow Alias (исключение) Примечание: Сейчас EasyP всё равно считает это breaking (может измениться в будущем)."},{"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":"Это правило проверяет, что ни одно поле сообщения (message field) не было удалено. Удаление поля ломает совместимость по wire‑формату и сгенерированный код: в существующих данных может присутствовать удалённое поле, а кл","content":"Это правило проверяет, что ни одно поле сообщения (message field) не было удалено. Удаление поля ломает совместимость по wire‑формату и сгенерированный код: в существующих данных может присутствовать удалённое поле, а клиентский код может ссылаться на него."},{"id":"cli/breaking-changes/rules/field-no-delete::breaking::1","title":"FIELD_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-no-delete::breaking::2","title":"FIELD_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/field-no-delete::breaking::3","title":"FIELD_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message User { string name = 1; string email = 2; int32 age = 3; string phone = 4; // [!code --] } ```","content":"Плохой (Breaking) message User { string name = 1; string email = 2; int32 age = 3; string phone = 4; // [!code --] } ```"},{"id":"cli/breaking-changes/rules/field-no-delete::breaking::4","title":"FIELD_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-no-delete::breaking::5","title":"FIELD_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/field-no-delete::breaking::6","title":"FIELD_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message User { string name = 1; string email = 2; int32 age = 3; // phone поле удалено — BREAKING CHANGE! } ```","content":"Плохой (Breaking) message User { string name = 1; string email = 2; int32 age = 3; // phone поле удалено — BREAKING CHANGE! } ```"},{"id":"cli/breaking-changes/rules/field-no-delete::top::7","title":"FIELD_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо удаления — пометить поле deprecated:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо удаления — пометить поле deprecated:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-no-delete::top::8","title":"FIELD_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/field-no-delete::top::9","title":"FIELD_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message User { string name = 1; string email = 2; int32 age = 3; string phone = 4 [deprecated = true]; // [!code focus] } ```","content":"Хороший (Безопасный) 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::top::10","title":"FIELD_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Или зарезервировать номер и имя поля после удаления:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Или зарезервировать номер и имя поля после удаления:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-no-delete::top::11","title":"FIELD_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/field-no-delete::top::12","title":"FIELD_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message User { reserved 4; // [!code focus] reserved \"phone\"; // [!code focus] string name = 1; string email = 2; int32 age = 3; } ```","content":"Хороший (Безопасный) 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::top::13","title":"FIELD_NO_DELETE","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete","headings":["Влияние"],"excerpt":"Влияние **Wire Format:** Старые сообщения с удалённым полем некорректно десериализуются **Generated Code:** Удаляются аксессоры (get/set), компиляция клиента ломается **Data Loss:** Потеря сохранённых данных, связанных с","content":"Влияние **Wire Format:** Старые сообщения с удалённым полем некорректно десериализуются **Generated Code:** Удаляются аксессоры (get/set), компиляция клиента ломается **Data Loss:** Потеря сохранённых данных, связанных с полем **JSON Compatibility:** JSON парсеры ожидают наличие поля и могут выдавать ошибки"},{"id":"cli/breaking-changes/rules/field-no-delete::top::14","title":"FIELD_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Сначала пометить deprecated:**","content":"Стратегия миграции **Сначала пометить deprecated:**"},{"id":"cli/breaking-changes/rules/field-no-delete::top::15","title":"FIELD_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Прекратить запись в поле** в прикладном коде","content":"Стратегия миграции **Прекратить запись в поле** в прикладном коде"},{"id":"cli/breaking-changes/rules/field-no-delete::top::16","title":"FIELD_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Зарезервировать поле** в следующей версии, чтобы избежать повторного использования:","content":"Стратегия миграции **Зарезервировать поле** в следующей версии, чтобы избежать повторного использования:"},{"id":"cli/breaking-changes/rules/field-no-delete::top::17","title":"FIELD_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Никогда не переиспользовать номер поля** — должен оставаться в reserved навсегда","content":"Стратегия миграции **Никогда не переиспользовать номер поля** — должен оставаться в reserved навсегда"},{"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":"Правило проверяет, что поля сообщений сохраняют ту же кардинальность (обязательность / optional). Изменение кардинальности поля ломает совместимость по wire‑формату и сгенерированный код: семантика присутствия и ожидания","content":"Правило проверяет, что поля сообщений сохраняют ту же кардинальность (обязательность / optional). Изменение кардинальности поля ломает совместимость по wire‑формату и сгенерированный код: семантика присутствия и ожидания клиентского кода отличаются для optional и required (implicit) полей."},{"id":"cli/breaking-changes/rules/field-same-cardinality::breaking::1","title":"FIELD_SAME_CARDINALITY","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-same-cardinality::breaking::2","title":"FIELD_SAME_CARDINALITY","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/field-same-cardinality::breaking::3","title":"FIELD_SAME_CARDINALITY","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message User { string name = 1; string email = 2; int32 age = 3; }","content":"Плохой (Breaking) message User { string name = 1; string email = 2; int32 age = 3; }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::breaking::4","title":"FIELD_SAME_CARDINALITY","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message CreateUserRequest { string name = 1; optional string email = 2; string phone = 3; } ```","content":"Плохой (Breaking) message CreateUserRequest { string name = 1; optional string email = 2; string phone = 3; } ```"},{"id":"cli/breaking-changes/rules/field-same-cardinality::breaking::5","title":"FIELD_SAME_CARDINALITY","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-same-cardinality::breaking::6","title":"FIELD_SAME_CARDINALITY","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/field-same-cardinality::breaking::7","title":"FIELD_SAME_CARDINALITY","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message User { string name = 1; optional string email = 2; // [!code --] Было required (implicit), стало optional int32 age = 3; }","content":"Плохой (Breaking) message User { string name = 1; optional string email = 2; // [!code --] Было required (implicit), стало optional int32 age = 3; }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::breaking::8","title":"FIELD_SAME_CARDINALITY","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message CreateUserRequest { string name = 1; string email = 2; // [!code --] Было optional, стало требуемым (implicit required) string phone = 3; } ```","content":"Плохой (Breaking) message CreateUserRequest { string name = 1; string email = 2; // [!code --] Было optional, стало требуемым (implicit required) string phone = 3; } ```"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::9","title":"FIELD_SAME_CARDINALITY","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры **Проблемы миграции Proto2 → Proto3:**","content":"Дополнительные примеры **Проблемы миграции Proto2 → Proto3:**"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::10","title":"FIELD_SAME_CARDINALITY","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры ```proto // Before (proto2) syntax = \"proto2\";","content":"Дополнительные примеры ```proto // Before (proto2) syntax = \"proto2\";"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::11","title":"FIELD_SAME_CARDINALITY","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры message Order { required string id = 1; optional string notes = 2; repeated string tags = 3; }","content":"Дополнительные примеры message Order { required string id = 1; optional string notes = 2; repeated string tags = 3; }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::12","title":"FIELD_SAME_CARDINALITY","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры // After (proto3) - BREAKING CHANGES! syntax = \"proto3\";","content":"Дополнительные примеры // After (proto3) - BREAKING CHANGES! syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::13","title":"FIELD_SAME_CARDINALITY","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры message Order { string id = 1; // BREAKING: required -> implicit optional string notes = 2; // BREAKING: explicit optional -> implicit optional repeated string tags = 3; // OK } ```","content":"Дополнительные примеры message Order { string id = 1; // BREAKING: required -> implicit optional string notes = 2; // BREAKING: explicit optional -> implicit optional repeated string tags = 3; // OK } ```"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::14","title":"FIELD_SAME_CARDINALITY","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо изменения кардинальности — добавьте новое поле:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо изменения кардинальности — добавьте новое поле:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::15","title":"FIELD_SAME_CARDINALITY","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::16","title":"FIELD_SAME_CARDINALITY","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message User { string name = 1; string email = 2 [deprecated = true]; // [!code focus] Сохраняем старую кардинальность int32 age = 3; optional string email_optional = 4; // [!code focus] Новое option","content":"Хороший (Безопасный) message User { string name = 1; string email = 2 [deprecated = true]; // [!code focus] Сохраняем старую кардинальность int32 age = 3; optional string email_optional = 4; // [!code focus] Новое optional поле }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::17","title":"FIELD_SAME_CARDINALITY","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message CreateUserRequest { string name = 1; optional string email = 2 [deprecated = true]; // [!code focus] string phone = 3; string email_required = 4; // [!code focus] Новое требуемое поле } ```","content":"Хороший (Безопасный) message CreateUserRequest { string name = 1; optional string email = 2 [deprecated = true]; // [!code focus] string phone = 3; string email_required = 4; // [!code focus] Новое требуемое поле } ```"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::18","title":"FIELD_SAME_CARDINALITY","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Или создайте новую версию сообщения:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Или создайте новую версию сообщения:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::19","title":"FIELD_SAME_CARDINALITY","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v2; // [!code focus]","content":"Хороший (Безопасный) package myapi.v2; // [!code focus]"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::20","title":"FIELD_SAME_CARDINALITY","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message User { string name = 1; optional string email = 2; // [!code focus] Чистая модель в v2 int32 age = 3; }","content":"Хороший (Безопасный) message User { string name = 1; optional string email = 2; // [!code focus] Чистая модель в v2 int32 age = 3; }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::21","title":"FIELD_SAME_CARDINALITY","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message CreateUserRequest { string name = 1; string email = 2; // [!code focus] Требуемое в v2 string phone = 3; } ```","content":"Хороший (Безопасный) message CreateUserRequest { string name = 1; string email = 2; // [!code focus] Требуемое в v2 string phone = 3; } ```"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::22","title":"FIELD_SAME_CARDINALITY","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Влияние"],"excerpt":"Влияние **Wire Format:** Меняется семантика присутствия — клиенты неправильно ожидают поля **Generated Code:** Меняются методы доступа / проверки (has, clear) **Validation:** Правила проверки обязательности переписываютс","content":"Влияние **Wire Format:** Меняется семантика присутствия — клиенты неправильно ожидают поля **Generated Code:** Меняются методы доступа / проверки (has, clear) **Validation:** Правила проверки обязательности переписываются **Default Values:** Optional и required по‑разному обрабатывают отсутствие значения"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::23","title":"FIELD_SAME_CARDINALITY","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Реальный пример"],"excerpt":"Реальный пример **Код клиента ломается при смене кардинальности:** ```go // Before - поле фактически требуется (implicit) user := &myapi.User{ Name: \"John\", Email: \"john@example.com\", Age: 30, }","content":"Реальный пример **Код клиента ломается при смене кардинальности:** ```go // Before - поле фактически требуется (implicit) user := &myapi.User{ Name: \"John\", Email: \"john@example.com\", Age: 30, }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::24","title":"FIELD_SAME_CARDINALITY","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Реальный пример"],"excerpt":"Реальный пример if user.Email != \"\" { // Есть значение }","content":"Реальный пример if user.Email != \"\" { // Есть значение }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::25","title":"FIELD_SAME_CARDINALITY","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Реальный пример"],"excerpt":"Реальный пример // After - поле стало optional (pointer) user := &myapi.User{ Name: \"John\", Age: 30, // Email может отсутствовать }","content":"Реальный пример // After - поле стало optional (pointer) user := &myapi.User{ Name: \"John\", Age: 30, // Email может отсутствовать }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::26","title":"FIELD_SAME_CARDINALITY","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Реальный пример"],"excerpt":"Реальный пример if user.Email != nil && *user.Email != \"\" { // Есть значение (новый способ) }","content":"Реальный пример if user.Email != nil && *user.Email != \"\" { // Есть значение (новый способ) }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::27","title":"FIELD_SAME_CARDINALITY","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Реальный пример"],"excerpt":"Реальный пример user.Email = &emailValue // Присваивание указателя вместо строки ```","content":"Реальный пример user.Email = &emailValue // Присваивание указателя вместо строки ```"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::28","title":"FIELD_SAME_CARDINALITY","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Реальный пример"],"excerpt":"Реальный пример **Валидация на сервере:** ```go // Before func validateUser(user *User) error { if user.Email == \"\" { return errors.New(\"email is required\") } return nil }","content":"Реальный пример **Валидация на сервере:** ```go // Before func validateUser(user *User) error { if user.Email == \"\" { return errors.New(\"email is required\") } return nil }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::29","title":"FIELD_SAME_CARDINALITY","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Реальный пример"],"excerpt":"Реальный пример // After func validateUser(user *User) error { if user.Email == nil { return errors.New(\"email is required\") } if *user.Email == \"\" { return errors.New(\"email cannot be empty\") } return nil } ```","content":"Реальный пример // After func validateUser(user *User) error { if user.Email == nil { return errors.New(\"email is required\") } if *user.Email == \"\" { return errors.New(\"email cannot be empty\") } return nil } ```"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::30","title":"FIELD_SAME_CARDINALITY","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Добавьте новое поле** с нужной кардинальностью:","content":"Стратегия миграции **Добавьте новое поле** с нужной кардинальностью:"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::31","title":"FIELD_SAME_CARDINALITY","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Период двойной записи** — заполняйте оба поля:","content":"Стратегия миграции **Период двойной записи** — заполняйте оба поля:"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::32","title":"FIELD_SAME_CARDINALITY","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Клиенты постепенно переходят**:","content":"Стратегия миграции **Клиенты постепенно переходят**:"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::33","title":"FIELD_SAME_CARDINALITY","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Удаление старого поля** в следующей major‑версии:","content":"Стратегия миграции **Удаление старого поля** в следующей major‑версии:"},{"id":"cli/breaking-changes/rules/field-same-cardinality::proto2-proto3::34","title":"FIELD_SAME_CARDINALITY","section":"Миграция Proto2 → Proto3","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#proto2-proto3","headings":["Миграция Proto2 → Proto3"],"excerpt":"Миграция Proto2 → Proto3 ```proto syntax = \"proto3\"; message Order { string id = 1; // BREAKING если был required }","content":"Миграция Proto2 → Proto3 ```proto syntax = \"proto3\"; message Order { string id = 1; // BREAKING если был required }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::proto2-proto3::35","title":"FIELD_SAME_CARDINALITY","section":"Миграция Proto2 → Proto3","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#proto2-proto3","headings":["Миграция Proto2 → Proto3"],"excerpt":"Миграция Proto2 → Proto3 // Сохранить семантику: syntax = \"proto3\"; message Order { string id = 1; optional string notes = 2; } ```","content":"Миграция Proto2 → Proto3 // Сохранить семантику: syntax = \"proto3\"; message Order { string id = 1; optional string notes = 2; } ```"},{"id":"cli/breaking-changes/rules/field-same-cardinality::optional-required::36","title":"FIELD_SAME_CARDINALITY","section":"Делать optional поле required","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#optional-required","headings":["Делать optional поле required"],"excerpt":"Делать optional поле required ```proto message CreateUserRequest { string name = 1; string email = 2; // BREAKING (раньше optional) }","content":"Делать optional поле required ```proto message CreateUserRequest { string name = 1; string email = 2; // BREAKING (раньше optional) }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::optional-required::37","title":"FIELD_SAME_CARDINALITY","section":"Делать optional поле required","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#optional-required","headings":["Делать optional поле required"],"excerpt":"Делать optional поле required message CreateUserRequest { string name = 1; optional string email = 2 [deprecated = true]; string required_email = 3; } ```","content":"Делать optional поле required message CreateUserRequest { string name = 1; optional string email = 2 [deprecated = true]; string required_email = 3; } ```"},{"id":"cli/breaking-changes/rules/field-same-cardinality::required-optional::38","title":"FIELD_SAME_CARDINALITY","section":"Делать required поле optional","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#required-optional","headings":["Делать required поле optional"],"excerpt":"Делать required поле optional ```proto message User { optional string phone = 3; // BREAKING (было implicit required) }","content":"Делать required поле optional ```proto message User { optional string phone = 3; // BREAKING (было implicit required) }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::required-optional::39","title":"FIELD_SAME_CARDINALITY","section":"Делать required поле optional","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#required-optional","headings":["Делать required поле optional"],"excerpt":"Делать required поле optional message User { string phone = 3 [deprecated = true]; optional string phone_optional = 4; } ```","content":"Делать required поле optional message User { string phone = 3 [deprecated = true]; optional string phone_optional = 4; } ```"},{"id":"cli/breaking-changes/rules/field-same-cardinality::protobuf::40","title":"FIELD_SAME_CARDINALITY","section":"Типы кардинальности в Protobuf","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#protobuf","headings":["Типы кардинальности в Protobuf"],"excerpt":"Типы кардинальности в Protobuf","content":"Типы кардинальности в Protobuf"},{"id":"cli/breaking-changes/rules/field-same-cardinality::proto3::41","title":"FIELD_SAME_CARDINALITY","section":"Proto3","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#proto3","headings":["Proto3"],"excerpt":"Proto3 **Implicit optional**: string name = 1; **Explicit optional**: optional string email = 2; **Repeated**: repeated string tags = 3; **Map**: map metadata = 4;","content":"Proto3 **Implicit optional**: string name = 1; **Explicit optional**: optional string email = 2; **Repeated**: repeated string tags = 3; **Map**: map metadata = 4;"},{"id":"cli/breaking-changes/rules/field-same-cardinality::proto2::42","title":"FIELD_SAME_CARDINALITY","section":"Proto2","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#proto2","headings":["Proto2"],"excerpt":"Proto2 **Required**: required string id = 1; **Optional**: optional string email = 2; **Repeated**: repeated string tags = 3;","content":"Proto2 **Required**: required string id = 1; **Optional**: optional string email = 2; **Repeated**: repeated string tags = 3;"},{"id":"cli/breaking-changes/rules/field-same-cardinality::breaking::43","title":"FIELD_SAME_CARDINALITY","section":"Матрица Breaking изменений","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#breaking","headings":["Матрица Breaking изменений"],"excerpt":"Матрица Breaking изменений From To Result ------ ---- -------- Required Optional ❌ BREAKING Optional Required ❌ BREAKING Implicit Explicit ❌ BREAKING Explicit Implicit ❌ BREAKING Single Repeated ❌ BREAKING Repeated Singl","content":"Матрица Breaking изменений 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":"Правило проверяет, что типы полей сообщений (message fields) не изменяются. Смена типа поля ломает совместимость по wire‑формату и сгенерированный код: бинарное представление и ожидания клиентского кода различаются для р","content":"Правило проверяет, что типы полей сообщений (message fields) не изменяются. Смена типа поля ломает совместимость по wire‑формату и сгенерированный код: бинарное представление и ожидания клиентского кода различаются для разных типов."},{"id":"cli/breaking-changes/rules/field-same-type::breaking::1","title":"FIELD_SAME_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-same-type::breaking::2","title":"FIELD_SAME_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/field-same-type::breaking::3","title":"FIELD_SAME_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message Product { string name = 1; int32 price = 2; bool available = 3; } ```","content":"Плохой (Breaking) message Product { string name = 1; int32 price = 2; bool available = 3; } ```"},{"id":"cli/breaking-changes/rules/field-same-type::breaking::4","title":"FIELD_SAME_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-same-type::breaking::5","title":"FIELD_SAME_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/field-same-type::breaking::6","title":"FIELD_SAME_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message Product { string name = 1; string price = 2; // [!code --] Changed from int32 to string (изменён тип) bool available = 3; } ```","content":"Плохой (Breaking) 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::top::7","title":"FIELD_SAME_TYPE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/field-same-type","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры **Несовместимые изменения типов:** ```proto // Before message Order { string id = 1; int64 timestamp = 2; repeated string tags = 3; OrderStatus status = 4; }","content":"Дополнительные примеры **Несовместимые изменения типов:** ```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::top::8","title":"FIELD_SAME_TYPE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/field-same-type","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры // After - ВСЁ BREAKING message Order { int32 id = 1; // string -> int32: BREAKING string timestamp = 2; // int64 -> string: BREAKING string tags = 3; // repeated -> singular: BREAKING int32 status","content":"Дополнительные примеры // After - ВСЁ BREAKING 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::top::9","title":"FIELD_SAME_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо смены типа — добавьте новое поле:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо смены типа — добавьте новое поле:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-same-type::top::10","title":"FIELD_SAME_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/field-same-type::top::11","title":"FIELD_SAME_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message Product { string name = 1; int32 price = 2 [deprecated = true]; // [!code focus] // Старое поле помечено deprecated bool available = 3; string price_formatted = 4; // [!code focus] // Новое п","content":"Хороший (Безопасный) message Product { string name = 1; int32 price = 2 [deprecated = true]; // [!code focus] // Старое поле помечено deprecated bool available = 3; string price_formatted = 4; // [!code focus] // Новое поле со строковым представлением } ```"},{"id":"cli/breaking-changes/rules/field-same-type::top::12","title":"FIELD_SAME_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Или создайте новую версию сообщения:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Или создайте новую версию сообщения:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-same-type::top::13","title":"FIELD_SAME_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v2; // [!code focus] // Новая версия package","content":"Хороший (Безопасный) package myapi.v2; // [!code focus] // Новая версия package"},{"id":"cli/breaking-changes/rules/field-same-type::top::14","title":"FIELD_SAME_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message Product { string name = 1; string price = 2; // [!code focus] // В v2 уже string bool available = 3; } ```","content":"Хороший (Безопасный) message Product { string name = 1; string price = 2; // [!code focus] // В v2 уже string bool available = 3; } ```"},{"id":"cli/breaking-changes/rules/field-same-type::top::15","title":"FIELD_SAME_TYPE","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/field-same-type","headings":["Влияние"],"excerpt":"Влияние **Wire Format:** Старые бинарные данные не десериализуются корректно **Generated Code:** Меняются типы в сгенерированном коде — клиенты не компилируются **Runtime Errors:** Ошибки парсинга при несовпадении ожидае","content":"Влияние **Wire Format:** Старые бинарные данные не десериализуются корректно **Generated Code:** Меняются типы в сгенерированном коде — клиенты не компилируются **Runtime Errors:** Ошибки парсинга при несовпадении ожидаемого типа **Data Corruption:** Неверная интерпретация байтов данных"},{"id":"cli/breaking-changes/rules/field-same-type::top::16","title":"FIELD_SAME_TYPE","section":"Типовые проблемы изменений типов","path":"/docs/guide/cli/breaking-changes/rules/field-same-type","headings":["Типовые проблемы изменений типов"],"excerpt":"Типовые проблемы изменений типов","content":"Типовые проблемы изменений типов"},{"id":"cli/breaking-changes/rules/field-same-type::top::17","title":"FIELD_SAME_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/field-same-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Добавьте новое поле** с нужным типом:","content":"Стратегия миграции **Добавьте новое поле** с нужным типом:"},{"id":"cli/breaking-changes/rules/field-same-type::top::18","title":"FIELD_SAME_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/field-same-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Период двойной записи** — заполняйте оба поля для совместимости","content":"Стратегия миграции **Период двойной записи** — заполняйте оба поля для совместимости"},{"id":"cli/breaking-changes/rules/field-same-type::top::19","title":"FIELD_SAME_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/field-same-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Мигрируйте клиентов** на новое поле постепенно","content":"Стратегия миграции **Мигрируйте клиентов** на новое поле постепенно"},{"id":"cli/breaking-changes/rules/field-same-type::top::20","title":"FIELD_SAME_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/field-same-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Удалите старое поле** в следующей major‑версии:","content":"Стратегия миграции **Удалите старое поле** в следующей major‑версии:"},{"id":"cli/breaking-changes/rules/field-same-type::wire::21","title":"FIELD_SAME_TYPE","section":"Безопасные изменения (Теоретически wire‑совместимые)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type#wire","headings":["Безопасные изменения (Теоретически wire‑совместимые)"],"excerpt":"Безопасные изменения (Теоретически wire‑совместимые) Примечание: EasyP сейчас считает ЛЮБУЮ смену типа breaking. Однако технически некоторые случаи совместимы:","content":"Безопасные изменения (Теоретически wire‑совместимые) Примечание: EasyP сейчас считает ЛЮБУЮ смену типа breaking. Однако технически некоторые случаи совместимы:"},{"id":"cli/breaking-changes/rules/field-same-type::wire::22","title":"FIELD_SAME_TYPE","section":"Безопасные изменения (Теоретически wire‑совместимые)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type#wire","headings":["Безопасные изменения (Теоретически wire‑совместимые)"],"excerpt":"Безопасные изменения (Теоретически wire‑совместимые) int32 ↔ uint32 (одно кодирование) int64 ↔ uint64 (одно кодирование) string → bytes (если все строки валидный UTF‑8)","content":"Безопасные изменения (Теоретически wire‑совместимые) int32 ↔ uint32 (одно кодирование) int64 ↔ uint64 (одно кодирование) string → bytes (если все строки валидный UTF‑8)"},{"id":"cli/breaking-changes/rules/field-same-type::wire::23","title":"FIELD_SAME_TYPE","section":"Безопасные изменения (Теоретически wire‑совместимые)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type#wire","headings":["Безопасные изменения (Теоретически wire‑совместимые)"],"excerpt":"Безопасные изменения (Теоретически wire‑совместимые) Эти исключения могут получить отдельную обработку в будущих версиях EasyP с более гибкими уровнями строгости.","content":"Безопасные изменения (Теоретически wire‑совместимые) Эти исключения могут получить отдельную обработку в будущих версиях EasyP с более гибкими уровнями строгости."},{"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":"Это правило проверяет, что ни одна инструкция import не была удалена из proto‑файла. Удаление import ломает совместимость по wire‑формату и сгенерированный код: типы из импортируемых файлов могли использоваться в текущем","content":"Это правило проверяет, что ни одна инструкция import не была удалена из proto‑файла. Удаление import ломает совместимость по wire‑формату и сгенерированный код: типы из импортируемых файлов могли использоваться в текущем файле, и их удаление делает эти типы недоступными."},{"id":"cli/breaking-changes/rules/import-no-delete::breaking::1","title":"IMPORT_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/import-no-delete::breaking::2","title":"IMPORT_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/import-no-delete::breaking::3","title":"IMPORT_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) import \"google/protobuf/timestamp.proto\"; import \"google/protobuf/duration.proto\"; import \"common/user.proto\"; import \"common/address.proto\";","content":"Плохой (Breaking) 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::breaking::4","title":"IMPORT_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) 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":"Плохой (Breaking) 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::breaking::5","title":"IMPORT_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/import-no-delete::breaking::6","title":"IMPORT_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/import-no-delete::breaking::7","title":"IMPORT_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) import \"google/protobuf/timestamp.proto\"; // import \"google/protobuf/duration.proto\"; // [!code --] Удалён import — BREAKING // import \"common/user.proto\"; // [!code --] Удалён import — BREAKING // impo","content":"Плохой (Breaking) import \"google/protobuf/timestamp.proto\"; // import \"google/protobuf/duration.proto\"; // [!code --] Удалён import — BREAKING // import \"common/user.proto\"; // [!code --] Удалён import — BREAKING // import \"common/address.proto\"; // [!code --] Удалён import — BREAKING"},{"id":"cli/breaking-changes/rules/import-no-delete::breaking::8","title":"IMPORT_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message Order { string id = 1; google.protobuf.Timestamp created_at = 2; google.protobuf.Duration processing_time = 3; // ERROR: Duration недоступен common.User customer = 4; // ERROR: User недоступен c","content":"Плохой (Breaking) message Order { string id = 1; google.protobuf.Timestamp created_at = 2; google.protobuf.Duration processing_time = 3; // ERROR: Duration недоступен common.User customer = 4; // ERROR: User недоступен common.Address shipping_address = 5; // ERROR: Address недоступен } ```"},{"id":"cli/breaking-changes/rules/import-no-delete::top::9","title":"IMPORT_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры **Сервис ломается при удалённых import:** ```proto // Before import \"google/api/annotations.proto\"; import \"google/protobuf/empty.proto\"; import \"common/auth.proto\";","content":"Дополнительные примеры **Сервис ломается при удалённых import:** ```proto // Before import \"google/api/annotations.proto\"; import \"google/protobuf/empty.proto\"; import \"common/auth.proto\";"},{"id":"cli/breaking-changes/rules/import-no-delete::top::10","title":"IMPORT_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры service OrderService { rpc GetOrder(GetOrderRequest) returns (Order) { option (google.api.http) = { get: \"/v1/orders/{id}\" }; } rpc DeleteOrder(common.AuthRequest) returns (google.protobuf.Empty); ","content":"Дополнительные примеры 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::top::11","title":"IMPORT_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры // After - BREAKING CHANGES! // import \"google/api/annotations.proto\"; // BREAKING: deleted // import \"google/protobuf/empty.proto\"; // BREAKING: deleted // import \"common/auth.proto\"; // BREAKING:","content":"Дополнительные примеры // 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::top::12","title":"IMPORT_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры service OrderService { rpc GetOrder(GetOrderRequest) returns (Order) { option (google.api.http) = { // ERROR: annotations недоступен get: \"/v1/orders/{id}\" }; } rpc DeleteOrder(common.AuthRequest) ","content":"Дополнительные примеры service OrderService { rpc GetOrder(GetOrderRequest) returns (Order) { option (google.api.http) = { // ERROR: annotations недоступен get: \"/v1/orders/{id}\" }; } rpc DeleteOrder(common.AuthRequest) returns (google.protobuf.Empty); // ERROR: типы недоступны } ```"},{"id":"cli/breaking-changes/rules/import-no-delete::top::13","title":"IMPORT_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо удаления оставьте неиспользуемые import:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо удаления оставьте неиспользуемые import:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/import-no-delete::top::14","title":"IMPORT_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/import-no-delete::top::15","title":"IMPORT_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) import \"google/protobuf/timestamp.proto\"; import \"google/protobuf/duration.proto\"; // [!code focus] // Оставляем даже если не используется import \"common/user.proto\"; // [!code focus] import \"common/","content":"Хороший (Безопасный) import \"google/protobuf/timestamp.proto\"; import \"google/protobuf/duration.proto\"; // [!code focus] // Оставляем даже если не используется import \"common/user.proto\"; // [!code focus] import \"common/address.proto\"; // [!code focus]"},{"id":"cli/breaking-changes/rules/import-no-delete::top::16","title":"IMPORT_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message Order { string id = 1; google.protobuf.Timestamp created_at = 2; // Поля, использовавшие Duration/User/Address, удалены — import оставлены } ```","content":"Хороший (Безопасный) message Order { string id = 1; google.protobuf.Timestamp created_at = 2; // Поля, использовавшие Duration/User/Address, удалены — import оставлены } ```"},{"id":"cli/breaking-changes/rules/import-no-delete::top::17","title":"IMPORT_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Или добавьте новые типы, сохранив старые import:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Или добавьте новые типы, сохранив старые import:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/import-no-delete::top::18","title":"IMPORT_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/import-no-delete::top::19","title":"IMPORT_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) import \"google/protobuf/timestamp.proto\"; import \"google/protobuf/duration.proto\"; // [!code focus] import \"common/user.proto\"; // [!code focus] import \"common/address.proto\"; // [!code focus] import","content":"Хороший (Безопасный) import \"google/protobuf/timestamp.proto\"; import \"google/protobuf/duration.proto\"; // [!code focus] import \"common/user.proto\"; // [!code focus] import \"common/address.proto\"; // [!code focus] import \"common/v2/user.proto\"; // [!code focus] // Новый import"},{"id":"cli/breaking-changes/rules/import-no-delete::top::20","title":"IMPORT_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message Order { string id = 1; google.protobuf.Timestamp created_at = 2; google.protobuf.Duration processing_time = 3 [deprecated = true]; // [!code focus] common.User customer = 4 [deprecated = true","content":"Хороший (Безопасный) message Order { string id = 1; google.protobuf.Timestamp created_at = 2; google.protobuf.Duration processing_time = 3 [deprecated = true]; // [!code focus] common.User customer = 4 [deprecated = true]; // [!code focus] common.Address shipping_address = 5 [deprecated = true]; // [!code focus] int32 processing_seconds = 6; common.v2.UserProfile customer_v2 = 7; string shipping_address_text = 8; } ```"},{"id":"cli/breaking-changes/rules/import-no-delete::top::21","title":"IMPORT_NO_DELETE","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Влияние"],"excerpt":"Влияние **Generated Code:** Типы пропадают → ошибка компиляции **Wire Format:** Сообщения с удалёнными типами не десериализуются **Field References:** Поля с этими типами становятся невалидны **Service Definitions:** RPC","content":"Влияние **Generated Code:** Типы пропадают → ошибка компиляции **Wire Format:** Сообщения с удалёнными типами не десериализуются **Field References:** Поля с этими типами становятся невалидны **Service Definitions:** RPC с типами из удалённых файлов ломаются **Options Usage:** Пользовательские опции из импортов недоступны"},{"id":"cli/breaking-changes/rules/import-no-delete::top::22","title":"IMPORT_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Код клиента ломается:**","content":"Реальный пример **Код клиента ломается:**"},{"id":"cli/breaking-changes/rules/import-no-delete::top::23","title":"IMPORT_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Серверная логика ломается:**","content":"Реальный пример **Серверная логика ломается:**"},{"id":"cli/breaking-changes/rules/import-no-delete::top::24","title":"IMPORT_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Компиляция proto ломается:**","content":"Реальный пример **Компиляция proto ломается:**"},{"id":"cli/breaking-changes/rules/import-no-delete::top::25","title":"IMPORT_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции Сохраняйте import даже если типы более не используются: Добавляйте новые import рядом со старыми: Депрецируйте поля со старыми типами постепенно: Сервер: поддерживайте оба варианта: Удаляйте import тол","content":"Стратегия миграции Сохраняйте import даже если типы более не используются: Добавляйте новые import рядом со старыми: Депрецируйте поля со старыми типами постепенно: Сервер: поддерживайте оба варианта: Удаляйте import только в следующей major‑версии после полной миграции."},{"id":"cli/breaking-changes/rules/import-no-delete::top::26","title":"IMPORT_NO_DELETE","section":"Замена зависимости","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Замена зависимости"],"excerpt":"Замена зависимости ```proto import \"old/user.proto\"; // Старый import \"new/user.proto\"; // Новый","content":"Замена зависимости ```proto import \"old/user.proto\"; // Старый import \"new/user.proto\"; // Новый"},{"id":"cli/breaking-changes/rules/import-no-delete::top::27","title":"IMPORT_NO_DELETE","section":"Замена зависимости","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Замена зависимости"],"excerpt":"Замена зависимости message Order { old.User customer = 4 [deprecated = true]; new.UserProfile customer_v2 = 5; } ```","content":"Замена зависимости message Order { old.User customer = 4 [deprecated = true]; new.UserProfile customer_v2 = 5; } ```"},{"id":"cli/breaking-changes/rules/import-no-delete::top::28","title":"IMPORT_NO_DELETE","section":"Удаление функционала","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Удаление функционала"],"excerpt":"Удаление функционала ```proto import \"feature/analytics.proto\"; // Оставить даже если поле удалено","content":"Удаление функционала ```proto import \"feature/analytics.proto\"; // Оставить даже если поле удалено"},{"id":"cli/breaking-changes/rules/import-no-delete::top::29","title":"IMPORT_NO_DELETE","section":"Удаление функционала","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Удаление функционала"],"excerpt":"Удаление функционала message Order { string id = 1; // feature.AnalyticsData analytics = 2; // Поле удалено, import остаётся } ```","content":"Удаление функционала message Order { string id = 1; // feature.AnalyticsData analytics = 2; // Поле удалено, import остаётся } ```"},{"id":"cli/breaking-changes/rules/import-no-delete::protobuf::30","title":"IMPORT_NO_DELETE","section":"Миграция версии protobuf","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#protobuf","headings":["Миграция версии protobuf"],"excerpt":"Миграция версии protobuf ```proto import \"google/protobuf/timestamp.proto\"; import \"google/protobuf/duration.proto\";","content":"Миграция версии protobuf ```proto import \"google/protobuf/timestamp.proto\"; import \"google/protobuf/duration.proto\";"},{"id":"cli/breaking-changes/rules/import-no-delete::protobuf::31","title":"IMPORT_NO_DELETE","section":"Миграция версии protobuf","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#protobuf","headings":["Миграция версии protobuf"],"excerpt":"Миграция версии protobuf message Event { google.protobuf.Timestamp timestamp = 1; int64 timestamp_millis = 2; } ```","content":"Миграция версии protobuf message Event { google.protobuf.Timestamp timestamp = 1; int64 timestamp_millis = 2; } ```"},{"id":"cli/breaking-changes/rules/import-no-delete::top::32","title":"IMPORT_NO_DELETE","section":"Упрощение сложных зависимостей","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Упрощение сложных зависимостей"],"excerpt":"Упрощение сложных зависимостей ```proto import \"complex/config.proto\";","content":"Упрощение сложных зависимостей ```proto import \"complex/config.proto\";"},{"id":"cli/breaking-changes/rules/import-no-delete::top::33","title":"IMPORT_NO_DELETE","section":"Упрощение сложных зависимостей","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Упрощение сложных зависимостей"],"excerpt":"Упрощение сложных зависимостей message Settings { complex.ConfigData config = 1 [deprecated = true]; string config_json = 2; } ```","content":"Упрощение сложных зависимостей message Settings { complex.ConfigData config = 1 [deprecated = true]; string config_json = 2; } ```"},{"id":"cli/breaking-changes/rules/import-no-delete::import-vs::34","title":"IMPORT_NO_DELETE","section":"Удаление import vs использование поля","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#import-vs","headings":["Удаление import vs использование поля"],"excerpt":"Удаление import vs использование поля","content":"Удаление import vs использование поля"},{"id":"cli/breaking-changes/rules/import-no-delete::import::35","title":"IMPORT_NO_DELETE","section":"Аудит import","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#import","headings":["Аудит import"],"excerpt":"Аудит import (Даже если не найдено — не удаляем.)","content":"Аудит 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":"Это правило проверяет, что ни одно сообщение (message) не было удалено из proto‑файлов. Удаление message ломает совместимость по wire‑формату и сгенерированный код: в существующих данных могут присутствовать экземпляры у","content":"Это правило проверяет, что ни одно сообщение (message) не было удалено из proto‑файлов. Удаление message ломает совместимость по wire‑формату и сгенерированный код: в существующих данных могут присутствовать экземпляры удалённого типа, а клиентский код зависит от сгенерированных структур и классов."},{"id":"cli/breaking-changes/rules/message-no-delete::breaking::1","title":"MESSAGE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/message-no-delete::breaking::2","title":"MESSAGE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/message-no-delete::breaking::3","title":"MESSAGE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message User { string name = 1; string email = 2; Address address = 3; }","content":"Плохой (Breaking) message User { string name = 1; string email = 2; Address address = 3; }"},{"id":"cli/breaking-changes/rules/message-no-delete::breaking::4","title":"MESSAGE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message Address { // [!code --] string street = 1; // [!code --] string city = 2; // [!code --] string country = 3; // [!code --] } // [!code --]","content":"Плохой (Breaking) message Address { // [!code --] string street = 1; // [!code --] string city = 2; // [!code --] string country = 3; // [!code --] } // [!code --]"},{"id":"cli/breaking-changes/rules/message-no-delete::breaking::5","title":"MESSAGE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message Order { string id = 1; User user = 2; } ```","content":"Плохой (Breaking) message Order { string id = 1; User user = 2; } ```"},{"id":"cli/breaking-changes/rules/message-no-delete::breaking::6","title":"MESSAGE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/message-no-delete::breaking::7","title":"MESSAGE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/message-no-delete::breaking::8","title":"MESSAGE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message User { string name = 1; string email = 2; Address address = 3; // ERROR: Address больше не существует }","content":"Плохой (Breaking) message User { string name = 1; string email = 2; Address address = 3; // ERROR: Address больше не существует }"},{"id":"cli/breaking-changes/rules/message-no-delete::breaking::9","title":"MESSAGE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) // Address удалён — BREAKING CHANGE!","content":"Плохой (Breaking) // Address удалён — BREAKING CHANGE!"},{"id":"cli/breaking-changes/rules/message-no-delete::breaking::10","title":"MESSAGE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message Order { string id = 1; User user = 2; } ```","content":"Плохой (Breaking) message Order { string id = 1; User user = 2; } ```"},{"id":"cli/breaking-changes/rules/message-no-delete::top::11","title":"MESSAGE_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры **Удаление вложенного сообщения:**","content":"Дополнительные примеры **Удаление вложенного сообщения:**"},{"id":"cli/breaking-changes/rules/message-no-delete::top::12","title":"MESSAGE_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры ```proto // Before message User { string name = 1; Profile profile = 2; message Profile { // [!code --] string bio = 1; // [!code --] string avatar_url = 2; // [!code --] } // [!code --] }","content":"Дополнительные примеры ```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::top::13","title":"MESSAGE_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры // After - BREAKING CHANGE! message User { string name = 1; Profile profile = 2; // ERROR: Profile удалён // Вложенное сообщение Profile удалено } ```","content":"Дополнительные примеры // After - BREAKING CHANGE! message User { string name = 1; Profile profile = 2; // ERROR: Profile удалён // Вложенное сообщение Profile удалено } ```"},{"id":"cli/breaking-changes/rules/message-no-delete::top::14","title":"MESSAGE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо удаления — пометить как deprecated:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо удаления — пометить как deprecated:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/message-no-delete::top::15","title":"MESSAGE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/message-no-delete::top::16","title":"MESSAGE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message User { string name = 1; string email = 2; Address address = 3 [deprecated = true]; // [!code focus] }","content":"Хороший (Безопасный) message User { string name = 1; string email = 2; Address address = 3 [deprecated = true]; // [!code focus] }"},{"id":"cli/breaking-changes/rules/message-no-delete::top::17","title":"MESSAGE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message Address { option deprecated = true; // [!code focus] string street = 1; string city = 2; string country = 3; }","content":"Хороший (Безопасный) message Address { option deprecated = true; // [!code focus] string street = 1; string city = 2; string country = 3; }"},{"id":"cli/breaking-changes/rules/message-no-delete::top::18","title":"MESSAGE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message Order { string id = 1; User user = 2; } ```","content":"Хороший (Безопасный) message Order { string id = 1; User user = 2; } ```"},{"id":"cli/breaking-changes/rules/message-no-delete::top::19","title":"MESSAGE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Или заменить новой версией сообщения:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Или заменить новой версией сообщения:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/message-no-delete::top::20","title":"MESSAGE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/message-no-delete::top::21","title":"MESSAGE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message User { string name = 1; string email = 2; Address address = 3 [deprecated = true]; // [!code focus] // Старое поле AddressV2 address_v2 = 4; // [!code focus] // Новая улучшенная структура }","content":"Хороший (Безопасный) message User { string name = 1; string email = 2; Address address = 3 [deprecated = true]; // [!code focus] // Старое поле AddressV2 address_v2 = 4; // [!code focus] // Новая улучшенная структура }"},{"id":"cli/breaking-changes/rules/message-no-delete::top::22","title":"MESSAGE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message Address { option deprecated = true; // [!code focus] string street = 1; string city = 2; string country = 3; }","content":"Хороший (Безопасный) message Address { option deprecated = true; // [!code focus] string street = 1; string city = 2; string country = 3; }"},{"id":"cli/breaking-changes/rules/message-no-delete::top::23","title":"MESSAGE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) 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 c","content":"Хороший (Безопасный) 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::top::24","title":"MESSAGE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message Order { string id = 1; User user = 2; } ```","content":"Хороший (Безопасный) message Order { string id = 1; User user = 2; } ```"},{"id":"cli/breaking-changes/rules/message-no-delete::top::25","title":"MESSAGE_NO_DELETE","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Влияние"],"excerpt":"Влияние **Wire Format:** Старые данные с удалённым сообщением не десериализуются **Generated Code:** Классы/структуры удаляются — компиляция клиента ломается **Field References:** Поля, использующие удалённый тип, станов","content":"Влияние **Wire Format:** Старые данные с удалённым сообщением не десериализуются **Generated Code:** Классы/структуры удаляются — компиляция клиента ломается **Field References:** Поля, использующие удалённый тип, становятся невалидны **Nested Dependencies:** Все сообщения, ссылающиеся на удалённый тип, ломаются"},{"id":"cli/breaking-changes/rules/message-no-delete::top::26","title":"MESSAGE_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Код клиента ломается:** ```go // Before user := &myapi.User{ Name: \"John Doe\", Email: \"john@example.com\", Address: &myapi.Address{ // ERROR после удаления Street: \"123 Main St\", City: \"New York\", Countr","content":"Реальный пример **Код клиента ломается:** ```go // Before user := &myapi.User{ Name: \"John Doe\", Email: \"john@example.com\", Address: &myapi.Address{ // ERROR после удаления Street: \"123 Main St\", City: \"New York\", Country: \"USA\", }, }"},{"id":"cli/breaking-changes/rules/message-no-delete::top::27","title":"MESSAGE_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример // undefined: myapi.Address ```","content":"Реальный пример // undefined: myapi.Address ```"},{"id":"cli/breaking-changes/rules/message-no-delete::top::28","title":"MESSAGE_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Старые данные становятся нечитаемыми:**","content":"Реальный пример **Старые данные становятся нечитаемыми:**"},{"id":"cli/breaking-changes/rules/message-no-delete::top::29","title":"MESSAGE_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Пометить как deprecated:** **Пометить поля, использующие его:** **Добавить замену при необходимости:** **Удалить в следующей major‑версии после периода миграции**","content":"Стратегия миграции **Пометить как deprecated:** **Пометить поля, использующие его:** **Добавить замену при необходимости:** **Удалить в следующей major‑версии после периода миграции**"},{"id":"cli/breaking-changes/rules/message-no-delete::top::30","title":"MESSAGE_NO_DELETE","section":"Рефакторинг структуры","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Рефакторинг структуры"],"excerpt":"Рефакторинг структуры ```proto message UserInfo { option deprecated = true; string name = 1; string email = 2; }","content":"Рефакторинг структуры ```proto message UserInfo { option deprecated = true; string name = 1; string email = 2; }"},{"id":"cli/breaking-changes/rules/message-no-delete::top::31","title":"MESSAGE_NO_DELETE","section":"Рефакторинг структуры","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Рефакторинг структуры"],"excerpt":"Рефакторинг структуры message UserProfile { string full_name = 1; string email_address = 2; string phone = 3; } ```","content":"Рефакторинг структуры message UserProfile { string full_name = 1; string email_address = 2; string phone = 3; } ```"},{"id":"cli/breaking-changes/rules/message-no-delete::top::32","title":"MESSAGE_NO_DELETE","section":"Удаление «неиспользуемых» сообщений","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Удаление «неиспользуемых» сообщений"],"excerpt":"Удаление «неиспользуемых» сообщений","content":"Удаление «неиспользуемых» сообщений"},{"id":"cli/breaking-changes/rules/message-no-delete::top::33","title":"MESSAGE_NO_DELETE","section":"Миграция версии","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Миграция версии"],"excerpt":"Миграция версии ```proto package myapi.v2;","content":"Миграция версии ```proto package myapi.v2;"},{"id":"cli/breaking-changes/rules/message-no-delete::top::34","title":"MESSAGE_NO_DELETE","section":"Миграция версии","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Миграция версии"],"excerpt":"Миграция версии message User { // Новая структура без устаревших ссылок } ```","content":"Миграция версии message User { // Новая структура без устаревших ссылок } ```"},{"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":"Правило проверяет, что ни одно поле внутри oneof группы не было удалено. Удаление поля из oneof ломает совместимость по wire‑формату и сгенерированный код: в сохранённых данных может присутствовать выбранный вариант, а к","content":"Правило проверяет, что ни одно поле внутри oneof группы не было удалено. Удаление поля из oneof ломает совместимость по wire‑формату и сгенерированный код: в сохранённых данных может присутствовать выбранный вариант, а клиентский код опирается на сгенерированные типы‑обёртки и методы доступа."},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::breaking::1","title":"ONEOF_FIELD_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::breaking::2","title":"ONEOF_FIELD_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::breaking::3","title":"ONEOF_FIELD_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message LoginRequest { string username = 1; oneof credentials { string password = 2; string api_key = 3; string oauth_token = 4; string certificate = 5; } }","content":"Плохой (Breaking) 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::breaking::4","title":"ONEOF_FIELD_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message SearchQuery { oneof filter { string text = 1; int32 user_id = 2; string category = 3; DateRange date_range = 4; } } ```","content":"Плохой (Breaking) 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::breaking::5","title":"ONEOF_FIELD_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::breaking::6","title":"ONEOF_FIELD_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::breaking::7","title":"ONEOF_FIELD_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message LoginRequest { string username = 1; oneof credentials { string password = 2; string api_key = 3; // string oauth_token = 4; // [!code --] Удалено поле oneof — BREAKING! // string certificate = 5","content":"Плохой (Breaking) message LoginRequest { string username = 1; oneof credentials { string password = 2; string api_key = 3; // string oauth_token = 4; // [!code --] Удалено поле oneof — BREAKING! // string certificate = 5; // [!code --] Удалено поле oneof — BREAKING! } }"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::breaking::8","title":"ONEOF_FIELD_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message SearchQuery { oneof filter { string text = 1; int32 user_id = 2; // string category = 3; // [!code --] Удалено поле oneof — BREAKING! // DateRange date_range = 4; // [!code --] Удалено поле oneo","content":"Плохой (Breaking) message SearchQuery { oneof filter { string text = 1; int32 user_id = 2; // string category = 3; // [!code --] Удалено поле oneof — BREAKING! // DateRange date_range = 4; // [!code --] Удалено поле oneof — BREAKING! } } ```"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::9","title":"ONEOF_FIELD_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры **Удаление вложенных oneof полей:** ```proto // Before message PaymentRequest { string order_id = 1; oneof payment_method { CreditCardPayment credit_card = 2; BankTransferPayment bank_transfer = 3;","content":"Дополнительные примеры **Удаление вложенных oneof полей:** ```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::top::10","title":"ONEOF_FIELD_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры // After - BREAKING CHANGES! message PaymentRequest { string order_id = 1; oneof payment_method { CreditCardPayment credit_card = 2; BankTransferPayment bank_transfer = 3; // CryptoPayment crypto =","content":"Дополнительные примеры // 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::top::11","title":"ONEOF_FIELD_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо удаления — пометить поля deprecated:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо удаления — пометить поля deprecated:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::12","title":"ONEOF_FIELD_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::13","title":"ONEOF_FIELD_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) 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 [deprecate","content":"Хороший (Безопасный) 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::top::14","title":"ONEOF_FIELD_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) 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":"Хороший (Безопасный) 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::top::15","title":"ONEOF_FIELD_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Или добавить новые поля, оставив старые:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Или добавить новые поля, оставив старые:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::16","title":"ONEOF_FIELD_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::17","title":"ONEOF_FIELD_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message LoginRequest { string username = 1; oneof credentials { string password = 2; string api_key = 3; string oauth_token = 4 [deprecated = true]; // [!code focus] // Старое поле string certificate","content":"Хороший (Безопасный) 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] OAuthCredentials oauth_v2 = 6; // [!code focus] // Новый структурированный вариант CertificateCredentials cert_v2 = 7; // [!code focus] } } ```"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::18","title":"ONEOF_FIELD_NO_DELETE","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Влияние"],"excerpt":"Влияние **Wire Format:** Данные, содержащие удалённый вариант, не десериализуются корректно **Generated Code:** Удаляются типы‑обёртки и accessor методы — компиляция клиентов ломается **Type Safety:** Логика switch по ти","content":"Влияние **Wire Format:** Данные, содержащие удалённый вариант, не десериализуются корректно **Generated Code:** Удаляются типы‑обёртки и accessor методы — компиляция клиентов ломается **Type Safety:** Логика switch по типам oneof разваливается **Business Logic:** Код, ожидающий конкретный вариант, перестаёт работать"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::19","title":"ONEOF_FIELD_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Код клиента ломается:** ```go // Before loginReq := &myapi.LoginRequest{ Username: \"user123\", }","content":"Реальный пример **Код клиента ломается:** ```go // Before loginReq := &myapi.LoginRequest{ Username: \"user123\", }"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::20","title":"ONEOF_FIELD_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример loginReq.Credentials = &myapi.LoginRequest_OauthToken{ OauthToken: \"token123\", // ERROR после удаления поля }","content":"Реальный пример loginReq.Credentials = &myapi.LoginRequest_OauthToken{ OauthToken: \"token123\", // ERROR после удаления поля }"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::21","title":"ONEOF_FIELD_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример switch cred := loginReq.Credentials.(type) { case *myapi.LoginRequest_Password: return authenticatePassword(cred.Password) case *myapi.LoginRequest_OauthToken: // ERROR: тип удалён return authenticateOAut","content":"Реальный пример switch cred := loginReq.Credentials.(type) { case *myapi.LoginRequest_Password: return authenticatePassword(cred.Password) case *myapi.LoginRequest_OauthToken: // ERROR: тип удалён return authenticateOAuth(cred.OauthToken) case *myapi.LoginRequest_Certificate: // ERROR: тип удалён return authenticateCert(cred.Certificate) default: return errors.New(\"unsupported credential type\") } // undefined: myapi.LoginRequest_OauthToken // undefined: myapi.LoginRequest_Certificate ```"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::22","title":"ONEOF_FIELD_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Серверная логика ломается:**","content":"Реальный пример **Серверная логика ломается:**"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::23","title":"ONEOF_FIELD_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Старые данные становятся нечитаемыми:**","content":"Реальный пример **Старые данные становятся нечитаемыми:**"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::24","title":"ONEOF_FIELD_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Депрецируйте сначала:** **Добавьте новые структурированные поля:** **Сервер: поддерживайте оба варианта:** **Мигрируйте клиентов на новое поле:** **Зарезервируйте номера удалённых полей в следующей m","content":"Стратегия миграции **Депрецируйте сначала:** **Добавьте новые структурированные поля:** **Сервер: поддерживайте оба варианта:** **Мигрируйте клиентов на новое поле:** **Зарезервируйте номера удалённых полей в следующей major‑версии:**"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::25","title":"ONEOF_FIELD_NO_DELETE","section":"Удаление неподдерживаемых методов аутентификации","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Удаление неподдерживаемых методов аутентификации"],"excerpt":"Удаление неподдерживаемых методов аутентификации","content":"Удаление неподдерживаемых методов аутентификации"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::26","title":"ONEOF_FIELD_NO_DELETE","section":"Изменения бизнес‑логики платежей","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Изменения бизнес‑логики платежей"],"excerpt":"Изменения бизнес‑логики платежей","content":"Изменения бизнес‑логики платежей"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::oneof-field-deletion-vs::27","title":"ONEOF_FIELD_NO_DELETE","section":"OneOf Field Deletion vs обычное удаление","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#oneof-field-deletion-vs","headings":["OneOf Field Deletion vs обычное удаление"],"excerpt":"OneOf Field Deletion vs обычное удаление","content":"OneOf Field Deletion vs обычное удаление"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::28","title":"ONEOF_FIELD_NO_DELETE","section":"Отличия от удаления обычного поля","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Отличия от удаления обычного поля"],"excerpt":"Отличия от удаления обычного поля ```proto message User { string name = 1; // string email = 2; // BREAKING: обычное поле }","content":"Отличия от удаления обычного поля ```proto message User { string name = 1; // string email = 2; // BREAKING: обычное поле }"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::29","title":"ONEOF_FIELD_NO_DELETE","section":"Отличия от удаления обычного поля","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Отличия от удаления обычного поля"],"excerpt":"Отличия от удаления обычного поля message User { oneof contact { string email = 1; // string phone = 2; // BREAKING: поле в oneof } } ```","content":"Отличия от удаления обычного поля message User { oneof contact { string email = 1; // string phone = 2; // BREAKING: поле в oneof } } ```"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::30","title":"ONEOF_FIELD_NO_DELETE","section":"Влияние на сгенерированный код","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Влияние на сгенерированный код"],"excerpt":"Влияние на сгенерированный код ```go // Обычное поле: удаляется простой геттер // user.GetEmail()","content":"Влияние на сгенерированный код ```go // Обычное поле: удаляется простой геттер // user.GetEmail()"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::31","title":"ONEOF_FIELD_NO_DELETE","section":"Влияние на сгенерированный код","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Влияние на сгенерированный код"],"excerpt":"Влияние на сгенерированный код // Поле в oneof: пропадает тип-обёртка, кейсы switch ломаются // *LoginRequest_OauthToken ```","content":"Влияние на сгенерированный код // Поле в oneof: пропадает тип-обёртка, кейсы switch ломаются // *LoginRequest_OauthToken ```"},{"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":"Это правило проверяет, что тип поля внутри oneof НЕ меняется. Смена типа любого варианта oneof — несовместимое (breaking) изменение: существующие данные сериализованы с прежним типом, а клиентский код ожидает конкретные ","content":"Это правило проверяет, что тип поля внутри oneof НЕ меняется. Смена типа любого варианта oneof — несовместимое (breaking) изменение: существующие данные сериализованы с прежним типом, а клиентский код ожидает конкретные типы-обёртки и методы доступа, сгенерированные для каждого варианта."},{"id":"cli/breaking-changes/rules/oneof-field-same-type::breaking::1","title":"ONEOF_FIELD_SAME_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::breaking::2","title":"ONEOF_FIELD_SAME_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::breaking::3","title":"ONEOF_FIELD_SAME_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message SearchRequest { string query = 1; oneof filter { string category = 2; int32 user_id = 3; bool is_premium = 4; DateRange date_range = 5; } }","content":"Плохой (Breaking) 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::breaking::4","title":"ONEOF_FIELD_SAME_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message NotificationSettings { oneof delivery { string email = 1; int64 phone_number = 2; WebhookConfig webhook = 3; } } ```","content":"Плохой (Breaking) message NotificationSettings { oneof delivery { string email = 1; int64 phone_number = 2; WebhookConfig webhook = 3; } } ```"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::breaking::5","title":"ONEOF_FIELD_SAME_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::breaking::6","title":"ONEOF_FIELD_SAME_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::breaking::7","title":"ONEOF_FIELD_SAME_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message SearchRequest { string query = 1; oneof filter { int32 category = 2; // [!code --] Было string -> стало int32 (BREAKING) string user_id = 3; // [!code --] Было int32 -> стало string (BREAKING) s","content":"Плохой (Breaking) message SearchRequest { string query = 1; oneof filter { int32 category = 2; // [!code --] Было string -> стало int32 (BREAKING) string user_id = 3; // [!code --] Было int32 -> стало string (BREAKING) string is_premium = 4; // [!code --] Было bool -> стало string (BREAKING) string date_range = 5; // [!code --] Было DateRange -> стало string (BREAKING) } }"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::breaking::8","title":"ONEOF_FIELD_SAME_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message NotificationSettings { oneof delivery { EmailConfig email = 1; // [!code --] Было string -> стало EmailConfig (BREAKING) string phone_number = 2; // [!code --] Было int64 -> стало string (BREAKI","content":"Плохой (Breaking) message NotificationSettings { oneof delivery { EmailConfig email = 1; // [!code --] Было string -> стало EmailConfig (BREAKING) string phone_number = 2; // [!code --] Было int64 -> стало string (BREAKING) string webhook = 3; // [!code --] Было WebhookConfig -> стало string (BREAKING) } } ```"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::9","title":"ONEOF_FIELD_SAME_TYPE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры **Комплексные изменения типов:** ```proto // Before message PaymentRequest { oneof payment_info { CreditCardInfo credit_card = 1; BankAccountInfo bank_account = 2; string paypal_email = 3; CryptoWa","content":"Дополнительные примеры **Комплексные изменения типов:** ```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::top::10","title":"ONEOF_FIELD_SAME_TYPE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры // After - ВСЁ BREAKING message PaymentRequest { oneof payment_info { string credit_card = 1; // CreditCardInfo -> string PayPalInfo bank_account = 2; // BankAccountInfo -> PayPalInfo PayPalInfo pa","content":"Дополнительные примеры // After - ВСЁ BREAKING message PaymentRequest { oneof payment_info { string credit_card = 1; // CreditCardInfo -> string PayPalInfo bank_account = 2; // BankAccountInfo -> PayPalInfo PayPalInfo paypal_email = 3; // string -> PayPalInfo string crypto = 4; // CryptoWalletInfo -> string } } ```"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::11","title":"ONEOF_FIELD_SAME_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо смены типа — добавьте новое поле в тот же oneof:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо смены типа — добавьте новое поле в тот же oneof:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::12","title":"ONEOF_FIELD_SAME_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::13","title":"ONEOF_FIELD_SAME_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message SearchRequest { string query = 1; oneof filter { string category = 2 [deprecated = true]; // Старый тип int32 user_id = 3 [deprecated = true]; bool is_premium = 4 [deprecated = true]; DateRan","content":"Хороший (Безопасный) message SearchRequest { string query = 1; oneof filter { string category = 2 [deprecated = true]; // Старый тип int32 user_id = 3 [deprecated = true]; bool is_premium = 4 [deprecated = true]; DateRange date_range = 5 [deprecated = true]; int32 category_id = 6; // Новая версия string user_identifier = 7; string premium_status = 8; string date_filter = 9; } } ```"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::14","title":"ONEOF_FIELD_SAME_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Или создайте новый oneof:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Или создайте новый oneof:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::15","title":"ONEOF_FIELD_SAME_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::16","title":"ONEOF_FIELD_SAME_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message SearchRequest { string query = 1; oneof filter { option deprecated = true; string category = 2 [deprecated = true]; int32 user_id = 3 [deprecated = true]; bool is_premium = 4 [deprecated = tr","content":"Хороший (Безопасный) message SearchRequest { string query = 1; oneof filter { option deprecated = true; string category = 2 [deprecated = true]; int32 user_id = 3 [deprecated = true]; bool is_premium = 4 [deprecated = true]; DateRange date_range = 5 [deprecated = true]; } oneof filter_v2 { int32 category_id = 6; string user_identifier = 7; PremiumFilter premium_filter = 8; TimeFilter time_filter = 9; } } ```"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::17","title":"ONEOF_FIELD_SAME_TYPE","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Влияние"],"excerpt":"Влияние **Wire Format:** Старые бинарные данные не читаются корректно **Generated Code:** Меняются типы-обёртки, код клиента не компилируется **Type Safety:** switch по варианту oneof ломается **Runtime Errors:** Ошибки ","content":"Влияние **Wire Format:** Старые бинарные данные не читаются корректно **Generated Code:** Меняются типы-обёртки, код клиента не компилируется **Type Safety:** switch по варианту oneof ломается **Runtime Errors:** Ошибки десериализации и логики при несовпадении типов"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::18","title":"ONEOF_FIELD_SAME_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Реальный пример"],"excerpt":"Реальный пример **Ломается клиентский код:** ```go // Before searchReq := &myapi.SearchRequest{ Query: \"golang jobs\", }","content":"Реальный пример **Ломается клиентский код:** ```go // Before searchReq := &myapi.SearchRequest{ Query: \"golang jobs\", }"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::19","title":"ONEOF_FIELD_SAME_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Реальный пример"],"excerpt":"Реальный пример // Устанавливаем вариант oneof searchReq.Filter = &myapi.SearchRequest_Category{ Category: \"engineering\", }","content":"Реальный пример // Устанавливаем вариант oneof searchReq.Filter = &myapi.SearchRequest_Category{ Category: \"engineering\", }"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::20","title":"ONEOF_FIELD_SAME_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Реальный пример"],"excerpt":"Реальный пример // Обработка вариантов switch filter := searchReq.Filter.(type) { case *myapi.SearchRequest_Category: return searchByCategory(filter.Category) case *myapi.SearchRequest_UserId: return searchByUserId(filte","content":"Реальный пример // Обработка вариантов switch filter := searchReq.Filter.(type) { case *myapi.SearchRequest_Category: return searchByCategory(filter.Category) case *myapi.SearchRequest_UserId: return searchByUserId(filter.UserId) default: return errors.New(\"unsupported filter\") }"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::21","title":"ONEOF_FIELD_SAME_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Реальный пример"],"excerpt":"Реальный пример // After — тип Category стал int32 searchReq.Filter = &myapi.SearchRequest_Category{ Category: \"engineering\", // ERROR }","content":"Реальный пример // After — тип Category стал int32 searchReq.Filter = &myapi.SearchRequest_Category{ Category: \"engineering\", // ERROR }"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::22","title":"ONEOF_FIELD_SAME_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Реальный пример"],"excerpt":"Реальный пример switch filter := searchReq.Filter.(type) { case *myapi.SearchRequest_Category: return searchByCategory(filter.Category) // ERROR case *myapi.SearchRequest_UserId: return searchByUserId(filter.UserId) // E","content":"Реальный пример switch filter := searchReq.Filter.(type) { case *myapi.SearchRequest_Category: return searchByCategory(filter.Category) // ERROR case *myapi.SearchRequest_UserId: return searchByUserId(filter.UserId) // ERROR: UserId теперь string } ```"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::23","title":"ONEOF_FIELD_SAME_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Реальный пример"],"excerpt":"Реальный пример **Ломается серверная логика:** ```go // Before func handleSearchFilter(req *SearchRequest) (*SearchResult, error) { switch filter := req.Filter.(type) { case *SearchRequest_Category: return searchDatabase","content":"Реальный пример **Ломается серверная логика:** ```go // Before func handleSearchFilter(req *SearchRequest) (*SearchResult, error) { switch filter := req.Filter.(type) { case *SearchRequest_Category: return searchDatabase(\"category\", filter.Category), nil case *SearchRequest_UserId: return searchDatabase(\"user_id\", strconv.Itoa(int(filter.UserId))), nil default: return nil, errors.New(\"no filter specified\") } }"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::24","title":"ONEOF_FIELD_SAME_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Реальный пример"],"excerpt":"Реальный пример // After — несовпадения типов func handleSearchFilter(req *SearchRequest) (*SearchResult, error) { switch filter := req.Filter.(type) { case *SearchRequest_Category: // filter.Category теперь int32, а код","content":"Реальный пример // After — несовпадения типов func handleSearchFilter(req *SearchRequest) (*SearchResult, error) { switch filter := req.Filter.(type) { case *SearchRequest_Category: // filter.Category теперь int32, а код ожидал string return searchDatabase(\"category\", filter.Category), nil // ERROR case *SearchRequest_UserId: userIdStr := filter.UserId // string вместо int32 userId, _ := strconv.Atoi(userIdStr) return searchDatabase(\"user_id\", strconv.Itoa(userId)), nil } } ```"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::25","title":"ONEOF_FIELD_SAME_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Реальный пример"],"excerpt":"Реальный пример **Порча данных:**","content":"Реальный пример **Порча данных:**"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::26","title":"ONEOF_FIELD_SAME_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции Добавьте новое поле: Сервер поддерживает оба: Клиенты переходят на category_id. Скрипты миграции преобразуют старые данные. В следующей major‑версии:","content":"Стратегия миграции Добавьте новое поле: Сервер поддерживает оба: Клиенты переходят на category_id. Скрипты миграции преобразуют старые данные. В следующей major‑версии:"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::27","title":"ONEOF_FIELD_SAME_TYPE","section":"Переход к структурированным типам","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Переход к структурированным типам"],"excerpt":"Переход к структурированным типам","content":"Переход к структурированным типам"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::28","title":"ONEOF_FIELD_SAME_TYPE","section":"Матрица совместимости","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Матрица совместимости"],"excerpt":"Матрица совместимости From Type To Type Результат ----------- --------- ----------- string int32/int64 ❌ BREAKING int32 string ❌ BREAKING bool string ❌ BREAKING message string ❌ BREAKING string message ❌ BREAKING enum in","content":"Матрица совместимости From Type To Type Результат ----------- --------- ----------- 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::top::29","title":"ONEOF_FIELD_SAME_TYPE","section":"Влияние на сгенерированный код","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Влияние на сгенерированный код"],"excerpt":"Влияние на сгенерированный код","content":"Влияние на сгенерированный код"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::30","title":"ONEOF_FIELD_SAME_TYPE","section":"Валидация","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Валидация"],"excerpt":"Валидация **После (сломано):**","content":"Валидация **После (сломано):**"},{"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":"Это правило проверяет, что ни один oneof блок не был удалён из сообщений. Удаление oneof ломает совместимость по wire‑формату и сгенерированный код: существующие данные могут содержать ранее выбранный вариант, а клиентск","content":"Это правило проверяет, что ни один oneof блок не был удалён из сообщений. Удаление oneof ломает совместимость по wire‑формату и сгенерированный код: существующие данные могут содержать ранее выбранный вариант, а клиентский код зависит от типов-обёрток и методов доступа, генерируемых для oneof."},{"id":"cli/breaking-changes/rules/oneof-no-delete::breaking::1","title":"ONEOF_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-no-delete::breaking::2","title":"ONEOF_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/oneof-no-delete::breaking::3","title":"ONEOF_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message LoginRequest { string username = 1; oneof credentials { string password = 2; string api_key = 3; string oauth_token = 4; } }","content":"Плохой (Breaking) 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::breaking::4","title":"ONEOF_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message PaymentMethod { // [!code --] oneof method { // [!code --] CreditCard credit_card = 1; // [!code --] BankAccount bank_account = 2; // [!code --] PayPal paypal = 3; // [!code --] } // [!code --] ","content":"Плохой (Breaking) 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::breaking::5","title":"ONEOF_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message Order { string id = 1; PaymentMethod payment = 2; } ```","content":"Плохой (Breaking) message Order { string id = 1; PaymentMethod payment = 2; } ```"},{"id":"cli/breaking-changes/rules/oneof-no-delete::breaking::6","title":"ONEOF_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-no-delete::breaking::7","title":"ONEOF_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/oneof-no-delete::breaking::8","title":"ONEOF_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message LoginRequest { string username = 1; // credentials oneof удалён — BREAKING CHANGE! string password = 2; // Теперь обычные поля string api_key = 3; // Потеряна взаимная исключаемость string oauth","content":"Плохой (Breaking) message LoginRequest { string username = 1; // credentials oneof удалён — BREAKING CHANGE! string password = 2; // Теперь обычные поля string api_key = 3; // Потеряна взаимная исключаемость string oauth_token = 4; }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::breaking::9","title":"ONEOF_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message PaymentMethod { // method oneof удалён — BREAKING CHANGE! CreditCard credit_card = 1; // Теперь можно установить все поля одновременно BankAccount bank_account = 2; PayPal paypal = 3; }","content":"Плохой (Breaking) message PaymentMethod { // method oneof удалён — BREAKING CHANGE! CreditCard credit_card = 1; // Теперь можно установить все поля одновременно BankAccount bank_account = 2; PayPal paypal = 3; }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::breaking::10","title":"ONEOF_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message Order { string id = 1; PaymentMethod payment = 2; } ```","content":"Плохой (Breaking) message Order { string id = 1; PaymentMethod payment = 2; } ```"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::11","title":"ONEOF_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры **Удаление вложенного oneof:** ```proto // Before message UserProfile { string name = 1; message ContactInfo { oneof contact_method { // [!code --] string email = 1; // [!code --] string phone = 2;","content":"Дополнительные примеры **Удаление вложенного oneof:** ```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::top::12","title":"ONEOF_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры // After - BREAKING CHANGE! message UserProfile { string name = 1; message ContactInfo { // contact_method oneof удалён string email = 1; // Больше не эксклюзивно string phone = 2; // Можно задать ","content":"Дополнительные примеры // After - BREAKING CHANGE! message UserProfile { string name = 1; message ContactInfo { // contact_method oneof удалён string email = 1; // Больше не эксклюзивно string phone = 2; // Можно задать всё сразу string slack_id = 3; } ContactInfo contact = 2; } ```"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::13","title":"ONEOF_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо удаления — депрецируйте oneof:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо удаления — депрецируйте oneof:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::14","title":"ONEOF_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::15","title":"ONEOF_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message LoginRequest { string username = 1; oneof credentials { option deprecated = true; // [!code focus] string password = 2 [deprecated = true]; // [!code focus] string api_key = 3 [deprecated = t","content":"Хороший (Безопасный) 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::top::16","title":"ONEOF_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message PaymentMethod { oneof method { option deprecated = true; // [!code focus] CreditCard credit_card = 1 [deprecated = true]; // [!code focus] BankAccount bank_account = 2 [deprecated = true]; //","content":"Хороший (Безопасный) 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::top::17","title":"ONEOF_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Или заменить новой структурой:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Или заменить новой структурой:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::18","title":"ONEOF_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::19","title":"ONEOF_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message LoginRequest { string username = 1; oneof credentials { option deprecated = true; // [!code focus] // Старый oneof string password = 2 [deprecated = true]; // [!code focus] string api_key = 3","content":"Хороший (Безопасный) message LoginRequest { string username = 1; oneof credentials { option deprecated = true; // [!code focus] // Старый 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] // Новый дизайн 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::top::20","title":"ONEOF_NO_DELETE","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Влияние"],"excerpt":"Влияние **Wire Format:** Теряются семантика взаимной исключаемости — больше одного поля может быть установлено **Generated Code:** Удаляются типы-обёртки и accessor методы — код клиента не компилируется **Business Logic:","content":"Влияние **Wire Format:** Теряются семантика взаимной исключаемости — больше одного поля может быть установлено **Generated Code:** Удаляются типы-обёртки и accessor методы — код клиента не компилируется **Business Logic:** Нарушаются инварианты «только один из» **Validation:** Логика проверок должна быть переписана вручную"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::21","title":"ONEOF_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Код клиента ломается:** ```go // Before - oneOf даёт взаимную исключаемость loginReq := &myapi.LoginRequest{ Username: \"user123\", }","content":"Реальный пример **Код клиента ломается:** ```go // Before - oneOf даёт взаимную исключаемость loginReq := &myapi.LoginRequest{ Username: \"user123\", }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::22","title":"ONEOF_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример loginReq.Credentials = &myapi.LoginRequest_Password{ Password: \"secret123\", }","content":"Реальный пример loginReq.Credentials = &myapi.LoginRequest_Password{ Password: \"secret123\", }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::23","title":"ONEOF_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример switch cred := loginReq.Credentials.(type) { case *myapi.LoginRequest_Password: // ERROR после удаления return authenticatePassword(cred.Password) case *myapi.LoginRequest_ApiKey: // ERROR после удаления ","content":"Реальный пример switch cred := loginReq.Credentials.(type) { case *myapi.LoginRequest_Password: // ERROR после удаления return authenticatePassword(cred.Password) case *myapi.LoginRequest_ApiKey: // ERROR после удаления return authenticateApiKey(cred.ApiKey) default: return errors.New(\"no credentials provided\") }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::24","title":"ONEOF_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример // Compilation errors: // undefined: myapi.LoginRequest_Password // undefined field: loginReq.Credentials ```","content":"Реальный пример // Compilation errors: // undefined: myapi.LoginRequest_Password // undefined field: loginReq.Credentials ```"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::25","title":"ONEOF_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Валидация на сервере ломается:** ```go // Before func validateLoginRequest(req *LoginRequest) error { if req.Credentials == nil { return errors.New(\"credentials required\") } switch req.Credentials.(type","content":"Реальный пример **Валидация на сервере ломается:** ```go // Before func validateLoginRequest(req *LoginRequest) error { if req.Credentials == nil { return errors.New(\"credentials required\") } 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::top::26","title":"ONEOF_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример // After func validateLoginRequest(req *LoginRequest) error { credCount := 0 if req.Password != \"\" { credCount++ } if req.ApiKey != \"\" { credCount++ } if req.OauthToken != \"\" { credCount++ }","content":"Реальный пример // After func validateLoginRequest(req *LoginRequest) error { credCount := 0 if req.Password != \"\" { credCount++ } if req.ApiKey != \"\" { credCount++ } if req.OauthToken != \"\" { credCount++ }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::27","title":"ONEOF_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример if credCount == 0 { return errors.New(\"no credentials provided\") } if credCount > 1 { return errors.New(\"multiple credentials provided\") }","content":"Реальный пример if credCount == 0 { return errors.New(\"no credentials provided\") } if credCount > 1 { return errors.New(\"multiple credentials provided\") }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::28","title":"ONEOF_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример if req.Password != \"\" { return validatePassword(req.Password) } // Дополнительные проверки вручную... return nil } ```","content":"Реальный пример if req.Password != \"\" { return validatePassword(req.Password) } // Дополнительные проверки вручную... return nil } ```"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::29","title":"ONEOF_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Проблемы бизнес‑логики:** ```go // Before payment := &PaymentMethod{ Method: &PaymentMethod_CreditCard{ CreditCard: &CreditCard{Number: \"1234\"}, }, }","content":"Реальный пример **Проблемы бизнес‑логики:** ```go // Before payment := &PaymentMethod{ Method: &PaymentMethod_CreditCard{ CreditCard: &CreditCard{Number: \"1234\"}, }, }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::30","title":"ONEOF_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример // After — можно задать несколько способов сразу payment := &PaymentMethod{ CreditCard: &CreditCard{Number: \"1234\"}, BankAccount: &BankAccount{Number: \"5678\"}, // Ломает бизнес-логику } ```","content":"Реальный пример // After — можно задать несколько способов сразу payment := &PaymentMethod{ CreditCard: &CreditCard{Number: \"1234\"}, BankAccount: &BankAccount{Number: \"5678\"}, // Ломает бизнес-логику } ```"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::31","title":"ONEOF_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Депрецируйте старый oneof и его поля:**","content":"Стратегия миграции **Депрецируйте старый oneof и его поля:**"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::32","title":"ONEOF_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Создайте новый блок при необходимости:**","content":"Стратегия миграции **Создайте новый блок при необходимости:**"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::33","title":"ONEOF_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Сервер: поддерживайте оба до миграции:**","content":"Стратегия миграции **Сервер: поддерживайте оба до миграции:**"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::34","title":"ONEOF_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Клиенты: переходите на новый oneof:**","content":"Стратегия миграции **Клиенты: переходите на новый oneof:**"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::35","title":"ONEOF_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Удалите старый oneof** в следующей major‑версии.","content":"Стратегия миграции **Удалите старый oneof** в следующей major‑версии."},{"id":"cli/breaking-changes/rules/oneof-no-delete::oneof::36","title":"ONEOF_NO_DELETE","section":"Замена oneof обычными полями","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#oneof","headings":["Замена oneof обычными полями"],"excerpt":"Замена oneof обычными полями ```proto message SearchRequest { // НЕЛЬЗЯ просто убрать oneof — ломает семантику string text_query = 1; // BREAKING int32 user_id = 2; // BREAKING string category = 3; // BREAKING }","content":"Замена oneof обычными полями ```proto message SearchRequest { // НЕЛЬЗЯ просто убрать oneof — ломает семантику string text_query = 1; // BREAKING int32 user_id = 2; // BREAKING string category = 3; // BREAKING }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::oneof::37","title":"ONEOF_NO_DELETE","section":"Замена oneof обычными полями","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#oneof","headings":["Замена oneof обычными полями"],"excerpt":"Замена oneof обычными полями message SearchRequest { oneof query { option deprecated = true; string text_query = 1 [deprecated = true]; int32 user_id = 2 [deprecated = true]; string category = 3 [deprecated = true]; } st","content":"Замена oneof обычными полями message SearchRequest { oneof query { option deprecated = true; string text_query = 1 [deprecated = true]; int32 user_id = 2 [deprecated = true]; string category = 3 [deprecated = true]; } string search_text = 4; repeated string filters = 5; } ```"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::38","title":"ONEOF_NO_DELETE","section":"Упрощение структуры сообщения","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Упрощение структуры сообщения"],"excerpt":"Упрощение структуры сообщения ```proto message NotificationSettings { string email = 1; // BREAKING: был в oneof string phone = 2; // BREAKING string webhook_url = 3; // BREAKING }","content":"Упрощение структуры сообщения ```proto message NotificationSettings { string email = 1; // BREAKING: был в oneof string phone = 2; // BREAKING string webhook_url = 3; // BREAKING }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::39","title":"ONEOF_NO_DELETE","section":"Упрощение структуры сообщения","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Упрощение структуры сообщения"],"excerpt":"Упрощение структуры сообщения message NotificationSettings { oneof delivery_method { EmailNotification email = 1; SmsNotification phone = 2; WebhookNotification webhook = 3; } } ```","content":"Упрощение структуры сообщения message NotificationSettings { oneof delivery_method { EmailNotification email = 1; SmsNotification phone = 2; WebhookNotification webhook = 3; } } ```"},{"id":"cli/breaking-changes/rules/oneof-no-delete::proto2-proto3::40","title":"ONEOF_NO_DELETE","section":"Миграция с proto2 на proto3","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#proto2-proto3","headings":["Миграция с proto2 на proto3"],"excerpt":"Миграция с proto2 на proto3 ```proto // proto2 message Request { optional string name = 1; oneof data { string text = 2; int32 number = 3; } }","content":"Миграция с proto2 на proto3 ```proto // proto2 message Request { optional string name = 1; oneof data { string text = 2; int32 number = 3; } }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::proto2-proto3::41","title":"ONEOF_NO_DELETE","section":"Миграция с proto2 на proto3","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#proto2-proto3","headings":["Миграция с proto2 на proto3"],"excerpt":"Миграция с proto2 на proto3 // proto3 — сохраняем oneof message Request { string name = 1; oneof data { string text = 2; int32 number = 3; } } ```","content":"Миграция с proto2 на proto3 // proto3 — сохраняем oneof message Request { string name = 1; oneof data { string text = 2; int32 number = 3; } } ```"},{"id":"cli/breaking-changes/rules/oneof-no-delete::oneof::42","title":"ONEOF_NO_DELETE","section":"Что даёт oneof","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#oneof","headings":["Что даёт oneof"],"excerpt":"Что даёт oneof Взаимная исключаемость Типобезопасность в коде Ясность намерения API («выбери один») Эффективная сериализация — кодируется только выбранный вариант","content":"Что даёт oneof Взаимная исключаемость Типобезопасность в коде Ясность намерения API («выбери один») Эффективная сериализация — кодируется только выбранный вариант"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::43","title":"ONEOF_NO_DELETE","section":"Что теряется при удалении","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Что теряется при удалении"],"excerpt":"Что теряется при удалении Инвариант «только один» Генерируемые wrapper-типы и методы Автоматическая валидация выбора Понятность контракта API","content":"Что теряется при удалении Инвариант «только один» Генерируемые wrapper-типы и методы Автоматическая валидация выбора Понятность контракта API"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::44","title":"ONEOF_NO_DELETE","section":"Влияние на код генерации","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Влияние на код генерации"],"excerpt":"Влияние на код генерации ```go // С oneof type LoginRequest struct { Username string Credentials isLoginRequest_Credentials }","content":"Влияние на код генерации ```go // С oneof type LoginRequest struct { Username string Credentials isLoginRequest_Credentials }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::45","title":"ONEOF_NO_DELETE","section":"Влияние на код генерации","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Влияние на код генерации"],"excerpt":"Влияние на код генерации // Без oneof type LoginRequest struct { Username string Password string ApiKey string OauthToken string // Возможны многозначные конфликтующие состояния } ```","content":"Влияние на код генерации // Без oneof type LoginRequest struct { Username string Password string ApiKey string 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":"Правило проверяет, что ни один RPC‑метод не был удалён из service. Удаление RPC ломает сгенерированный код и клиентские приложения, которые этот метод вызывают.","content":"Правило проверяет, что ни один RPC‑метод не был удалён из service. Удаление RPC ломает сгенерированный код и клиентские приложения, которые этот метод вызывают."},{"id":"cli/breaking-changes/rules/rpc-no-delete::breaking::1","title":"RPC_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/rpc-no-delete::breaking::2","title":"RPC_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/rpc-no-delete::breaking::3","title":"RPC_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); rpc DeleteUser(DeleteUserRequest) returns (DeleteUserResponse","content":"Плохой (Breaking) 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::breaking::4","title":"RPC_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/rpc-no-delete::breaking::5","title":"RPC_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/rpc-no-delete::breaking::6","title":"RPC_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); // DeleteUser RPC удалён — BREAKING CHANGE! } ```","content":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); // DeleteUser RPC удалён — BREAKING CHANGE! } ```"},{"id":"cli/breaking-changes/rules/rpc-no-delete::top::7","title":"RPC_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо удаления — пометить RPC deprecated:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо удаления — пометить RPC deprecated:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/rpc-no-delete::top::8","title":"RPC_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/rpc-no-delete::top::9","title":"RPC_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); rpc DeleteUser(DeleteUserRequest) returns (DeleteUserRespo","content":"Хороший (Безопасный) 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::top::10","title":"RPC_NO_DELETE","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete","headings":["Влияние"],"excerpt":"Влияние **Generated Code:** Stub/метод исчезает — клиенты не компилируются **Client Applications:** Существующие вызовы метода падают при сборке **Runtime:** gRPC клиенты теряют определение метода","content":"Влияние **Generated Code:** Stub/метод исчезает — клиенты не компилируются **Client Applications:** Существующие вызовы метода падают при сборке **Runtime:** gRPC клиенты теряют определение метода"},{"id":"cli/breaking-changes/rules/rpc-no-delete::top::11","title":"RPC_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Сначала деприкация:**","content":"Стратегия миграции **Сначала деприкация:**"},{"id":"cli/breaking-changes/rules/rpc-no-delete::top::12","title":"RPC_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Имплементация может возвращать ошибку**, указывая что метод устарел (например, INTERNAL / UNIMPLEMENTED)","content":"Стратегия миграции **Имплементация может возвращать ошибку**, указывая что метод устарел (например, INTERNAL / UNIMPLEMENTED)"},{"id":"cli/breaking-changes/rules/rpc-no-delete::top::13","title":"RPC_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Удалить в следующей major‑версии** после миграции всех клиентов","content":"Стратегия миграции **Удалить в следующей major‑версии** после миграции всех клиентов"},{"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":"Это правило проверяет, что RPC‑методы сохраняют прежний тип сообщения запроса (request message type). Изменение типа запроса RPC ломает совместимость по wire‑формату и сгенерированный код: клиенты ожидают конкретную стру","content":"Это правило проверяет, что RPC‑методы сохраняют прежний тип сообщения запроса (request message type). Изменение типа запроса RPC ломает совместимость по wire‑формату и сгенерированный код: клиенты ожидают конкретную структуру при вызове метода."},{"id":"cli/breaking-changes/rules/rpc-same-request-type::breaking::1","title":"RPC_SAME_REQUEST_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::breaking::2","title":"RPC_SAME_REQUEST_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::breaking::3","title":"RPC_SAME_REQUEST_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse); }","content":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse); }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::breaking::4","title":"RPC_SAME_REQUEST_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message GetUserRequest { string user_id = 1; }","content":"Плохой (Breaking) message GetUserRequest { string user_id = 1; }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::breaking::5","title":"RPC_SAME_REQUEST_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message UpdateUserRequest { string user_id = 1; string name = 2; string email = 3; } ```","content":"Плохой (Breaking) message UpdateUserRequest { string user_id = 1; string name = 2; string email = 3; } ```"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::breaking::6","title":"RPC_SAME_REQUEST_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::breaking::7","title":"RPC_SAME_REQUEST_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::breaking::8","title":"RPC_SAME_REQUEST_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequestV2) returns (GetUserResponse); // [!code --] Изменён тип запроса rpc UpdateUser(UserUpdateRequest) returns (UpdateUserResponse); // [!code --] Изменён тип","content":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequestV2) returns (GetUserResponse); // [!code --] Изменён тип запроса rpc UpdateUser(UserUpdateRequest) returns (UpdateUserResponse); // [!code --] Изменён тип запроса }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::breaking::9","title":"RPC_SAME_REQUEST_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message GetUserRequestV2 { // [!code --] Новый тип запроса string id = 1; bool include_profile = 2; }","content":"Плохой (Breaking) message GetUserRequestV2 { // [!code --] Новый тип запроса string id = 1; bool include_profile = 2; }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::breaking::10","title":"RPC_SAME_REQUEST_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message UserUpdateRequest { // [!code --] Новый тип запроса string id = 1; UserProfile profile = 2; } ```","content":"Плохой (Breaking) message UserUpdateRequest { // [!code --] Новый тип запроса string id = 1; UserProfile profile = 2; } ```"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::11","title":"RPC_SAME_REQUEST_TYPE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры **Смена типа из другого пакета:** ```proto // Before import \"common/user.proto\";","content":"Дополнительные примеры **Смена типа из другого пакета:** ```proto // Before import \"common/user.proto\";"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::12","title":"RPC_SAME_REQUEST_TYPE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры service UserService { rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); }","content":"Дополнительные примеры service UserService { rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::13","title":"RPC_SAME_REQUEST_TYPE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры // After - BREAKING CHANGE! import \"v2/user.proto\";","content":"Дополнительные примеры // After - BREAKING CHANGE! import \"v2/user.proto\";"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::14","title":"RPC_SAME_REQUEST_TYPE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры service UserService { rpc CreateUser(v2.CreateUserRequest) returns (CreateUserResponse); // Другой package } ```","content":"Дополнительные примеры service UserService { rpc CreateUser(v2.CreateUserRequest) returns (CreateUserResponse); // Другой package } ```"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::15","title":"RPC_SAME_REQUEST_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо изменения типа — версионируйте RPC:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо изменения типа — версионируйте RPC:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::16","title":"RPC_SAME_REQUEST_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::17","title":"RPC_SAME_REQUEST_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse) { option deprecated = true; // [!code focus] } rpc GetUserV2(GetUserRequestV2) returns (GetUserResponse); // [!code focus] ","content":"Хороший (Безопасный) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse) { option deprecated = true; // [!code focus] } rpc GetUserV2(GetUserRequestV2) returns (GetUserResponse); // [!code focus] // Новый метод rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse) { option deprecated = true; // [!code focus] } rpc UpdateUserV2(UserUpdateRequest) returns (UpdateUserResponse); // [!code focus] // Новый метод }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::18","title":"RPC_SAME_REQUEST_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) // Старые сообщения — для обратной совместимости message GetUserRequest { string user_id = 1; }","content":"Хороший (Безопасный) // Старые сообщения — для обратной совместимости message GetUserRequest { string user_id = 1; }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::19","title":"RPC_SAME_REQUEST_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) // Новая версия сообщения message GetUserRequestV2 { // [!code focus] string id = 1; // [!code focus] bool include_profile = 2; // [!code focus] } // [!code focus] ```","content":"Хороший (Безопасный) // Новая версия сообщения 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::top::20","title":"RPC_SAME_REQUEST_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Или создайте новую версию сервиса (package v2):** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Или создайте новую версию сервиса (package v2):** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::21","title":"RPC_SAME_REQUEST_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v2; // [!code focus]","content":"Хороший (Безопасный) package myapi.v2; // [!code focus]"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::22","title":"RPC_SAME_REQUEST_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); // [!code focus] rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse); // [!code focus] }","content":"Хороший (Безопасный) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); // [!code focus] rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse); // [!code focus] }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::23","title":"RPC_SAME_REQUEST_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message GetUserRequest { // [!code focus] string id = 1; // [!code focus] bool include_profile = 2; // [!code focus] } // [!code focus] ```","content":"Хороший (Безопасный) message GetUserRequest { // [!code focus] string id = 1; // [!code focus] bool include_profile = 2; // [!code focus] } // [!code focus] ```"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::24","title":"RPC_SAME_REQUEST_TYPE","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Влияние"],"excerpt":"Влияние **Wire Format:** Старые запросы клиентов не десериализуются новым сервером **Generated Code:** Сигнатуры методов в stubs меняются — компиляция клиентов падает **gRPC Calls:** Требуется использовать другую структу","content":"Влияние **Wire Format:** Старые запросы клиентов не десериализуются новым сервером **Generated Code:** Сигнатуры методов в stubs меняются — компиляция клиентов падает **gRPC Calls:** Требуется использовать другую структуру запроса **Runtime Errors:** Несоответствие типов вызывает ошибки выполнения"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::25","title":"RPC_SAME_REQUEST_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Реальный пример"],"excerpt":"Реальный пример **Код клиента ломается:** ```go // Before client := myapi.NewUserServiceClient(conn) resp, err := client.GetUser(ctx, &myapi.GetUserRequest{ UserId: \"user123\", })","content":"Реальный пример **Код клиента ломается:** ```go // Before client := myapi.NewUserServiceClient(conn) resp, err := client.GetUser(ctx, &myapi.GetUserRequest{ UserId: \"user123\", })"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::26","title":"RPC_SAME_REQUEST_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Реальный пример"],"excerpt":"Реальный пример // After (тип запроса изменён) client := myapi.NewUserServiceClient(conn) resp, err := client.GetUser(ctx, &myapi.GetUserRequest{ // ERROR: тип не найден UserId: \"user123\", // ERROR: поле не найдено })","content":"Реальный пример // After (тип запроса изменён) client := myapi.NewUserServiceClient(conn) resp, err := client.GetUser(ctx, &myapi.GetUserRequest{ // ERROR: тип не найден UserId: \"user123\", // ERROR: поле не найдено })"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::27","title":"RPC_SAME_REQUEST_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Реальный пример"],"excerpt":"Реальный пример // Новый корректный вызов: resp, err := client.GetUser(ctx, &myapi.GetUserRequestV2{ Id: \"user123\", IncludeProfile: true, }) ```","content":"Реальный пример // Новый корректный вызов: resp, err := client.GetUser(ctx, &myapi.GetUserRequestV2{ Id: \"user123\", IncludeProfile: true, }) ```"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::28","title":"RPC_SAME_REQUEST_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Реальный пример"],"excerpt":"Реальный пример **Серверная реализация ломается:** ```go // Before func (s *server) GetUser(ctx context.Context, req *GetUserRequest) (*GetUserResponse, error) { userID := req.UserId // ... }","content":"Реальный пример **Серверная реализация ломается:** ```go // Before func (s *server) GetUser(ctx context.Context, req *GetUserRequest) (*GetUserResponse, error) { userID := req.UserId // ... }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::29","title":"RPC_SAME_REQUEST_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Реальный пример"],"excerpt":"Реальный пример // After func (s *server) GetUser(ctx context.Context, req *GetUserRequestV2) (*GetUserResponse, error) { userID := req.Id include := req.IncludeProfile // ... новая логика } ```","content":"Реальный пример // After func (s *server) GetUser(ctx context.Context, req *GetUserRequestV2) (*GetUserResponse, error) { userID := req.Id include := req.IncludeProfile // ... новая логика } ```"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::30","title":"RPC_SAME_REQUEST_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Добавьте новый RPC с новым типом запроса:**","content":"Стратегия миграции **Добавьте новый RPC с новым типом запроса:**"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::31","title":"RPC_SAME_REQUEST_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Поддерживайте оба метода на сервере:** ```go func (s *server) GetUser(ctx context.Context, req *GetUserRequest) (*GetUserResponse, error) { return s.getUserInternal(req.UserId, false) }","content":"Стратегия миграции **Поддерживайте оба метода на сервере:** ```go func (s *server) GetUser(ctx context.Context, req *GetUserRequest) (*GetUserResponse, error) { return s.getUserInternal(req.UserId, false) }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::32","title":"RPC_SAME_REQUEST_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции func (s *server) GetUserV2(ctx context.Context, req *GetUserRequestV2) (*GetUserResponse, error) { return s.getUserInternal(req.Id, req.IncludeProfile) } ```","content":"Стратегия миграции func (s *server) GetUserV2(ctx context.Context, req *GetUserRequestV2) (*GetUserResponse, error) { return s.getUserInternal(req.Id, req.IncludeProfile) } ```"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::33","title":"RPC_SAME_REQUEST_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Мигрируйте клиентов на V2:**","content":"Стратегия миграции **Мигрируйте клиентов на V2:**"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::34","title":"RPC_SAME_REQUEST_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Удалите старый метод в следующей major‑версии:**","content":"Стратегия миграции **Удалите старый метод в следующей major‑версии:**"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::35","title":"RPC_SAME_REQUEST_TYPE","section":"Добавление обязательных полей","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Добавление обязательных полей"],"excerpt":"Добавление обязательных полей ```proto // ПЛОХО: меняем существующий запрос message GetUserRequest { string user_id = 1; bool include_deleted = 2; // BREAKING }","content":"Добавление обязательных полей ```proto // ПЛОХО: меняем существующий запрос message GetUserRequest { string user_id = 1; bool include_deleted = 2; // BREAKING }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::36","title":"RPC_SAME_REQUEST_TYPE","section":"Добавление обязательных полей","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Добавление обязательных полей"],"excerpt":"Добавление обязательных полей // Хорошо: новая версия message GetUserRequestV2 { string user_id = 1; bool include_deleted = 2; } ```","content":"Добавление обязательных полей // Хорошо: новая версия message GetUserRequestV2 { string user_id = 1; bool include_deleted = 2; } ```"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::37","title":"RPC_SAME_REQUEST_TYPE","section":"Реструктуризация данных запроса","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Реструктуризация данных запроса"],"excerpt":"Реструктуризация данных запроса ```proto // ПЛОХО: меняем структуру прямо message UpdateUserRequest { UserProfile profile = 1; // BREAKING }","content":"Реструктуризация данных запроса ```proto // ПЛОХО: меняем структуру прямо message UpdateUserRequest { UserProfile profile = 1; // BREAKING }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::38","title":"RPC_SAME_REQUEST_TYPE","section":"Реструктуризация данных запроса","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Реструктуризация данных запроса"],"excerpt":"Реструктуризация данных запроса // Хорошо: версионирование rpc UpdateUser(UpdateUserRequest) returns (...) { option deprecated = true; } rpc UpdateUserV2(UpdateUserRequestV2) returns (...); ```","content":"Реструктуризация данных запроса // Хорошо: версионирование rpc UpdateUser(UpdateUserRequest) returns (...) { option deprecated = true; } rpc UpdateUserV2(UpdateUserRequestV2) returns (...); ```"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::39","title":"RPC_SAME_REQUEST_TYPE","section":"Миграция пакета","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Миграция пакета"],"excerpt":"Миграция пакета ```proto // ПЛОХО: заменяем тип на пакет v2 прямо import \"v2/messages.proto\"; // BREAKING","content":"Миграция пакета ```proto // ПЛОХО: заменяем тип на пакет v2 прямо import \"v2/messages.proto\"; // BREAKING"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::40","title":"RPC_SAME_REQUEST_TYPE","section":"Миграция пакета","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Миграция пакета"],"excerpt":"Миграция пакета // Хорошо: добавляем новый RPC rpc OldMethod(v1.Request) returns (...) { option deprecated = true; } rpc NewMethod(v2.Request) returns (...); ```","content":"Миграция пакета // Хорошо: добавляем новый RPC 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":"Это правило проверяет, что RPC‑методы сохраняют тот же тип ответного сообщения (response message type). Изменение типа ответа RPC ломает совместимость по wire‑формату и сгенерированный код: клиенты ожидают конкретную стр","content":"Это правило проверяет, что RPC‑методы сохраняют тот же тип ответного сообщения (response message type). Изменение типа ответа RPC ломает совместимость по wire‑формату и сгенерированный код: клиенты ожидают конкретную структуру при получении ответа."},{"id":"cli/breaking-changes/rules/rpc-same-response-type::breaking::1","title":"RPC_SAME_RESPONSE_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::breaking::2","title":"RPC_SAME_RESPONSE_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::breaking::3","title":"RPC_SAME_RESPONSE_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse); }","content":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse); }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::breaking::4","title":"RPC_SAME_RESPONSE_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message GetUserResponse { string user_id = 1; string name = 2; string email = 3; }","content":"Плохой (Breaking) message GetUserResponse { string user_id = 1; string name = 2; string email = 3; }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::breaking::5","title":"RPC_SAME_RESPONSE_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message UpdateUserResponse { bool success = 1; string message = 2; } ```","content":"Плохой (Breaking) message UpdateUserResponse { bool success = 1; string message = 2; } ```"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::breaking::6","title":"RPC_SAME_RESPONSE_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::breaking::7","title":"RPC_SAME_RESPONSE_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::breaking::8","title":"RPC_SAME_RESPONSE_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponseV2); // [!code --] Изменён тип ответа rpc UpdateUser(UpdateUserRequest) returns (UserUpdateResponse); // [!code --] Изменён тип ","content":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponseV2); // [!code --] Изменён тип ответа rpc UpdateUser(UpdateUserRequest) returns (UserUpdateResponse); // [!code --] Изменён тип ответа }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::breaking::9","title":"RPC_SAME_RESPONSE_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message GetUserResponseV2 { // [!code --] Другой тип сообщения string id = 1; UserProfile profile = 2; repeated string permissions = 3; }","content":"Плохой (Breaking) message GetUserResponseV2 { // [!code --] Другой тип сообщения string id = 1; UserProfile profile = 2; repeated string permissions = 3; }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::breaking::10","title":"RPC_SAME_RESPONSE_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message UserUpdateResponse { // [!code --] Другой тип сообщения UpdateResult result = 1; UserProfile updated_profile = 2; } ```","content":"Плохой (Breaking) message UserUpdateResponse { // [!code --] Другой тип сообщения UpdateResult result = 1; UserProfile updated_profile = 2; } ```"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::11","title":"RPC_SAME_RESPONSE_TYPE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры **Смена типа из другого пакета:** ```proto // Before import \"common/responses.proto\";","content":"Дополнительные примеры **Смена типа из другого пакета:** ```proto // Before import \"common/responses.proto\";"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::12","title":"RPC_SAME_RESPONSE_TYPE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры service UserService { rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); }","content":"Дополнительные примеры service UserService { rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::13","title":"RPC_SAME_RESPONSE_TYPE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры // After - BREAKING CHANGE! import \"v2/responses.proto\";","content":"Дополнительные примеры // After - BREAKING CHANGE! import \"v2/responses.proto\";"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::14","title":"RPC_SAME_RESPONSE_TYPE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры service UserService { rpc CreateUser(CreateUserRequest) returns (v2.CreateUserResponse); // Другой package } ```","content":"Дополнительные примеры service UserService { rpc CreateUser(CreateUserRequest) returns (v2.CreateUserResponse); // Другой package } ```"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::15","title":"RPC_SAME_RESPONSE_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо изменения типа — версионируйте RPC:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо изменения типа — версионируйте RPC:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::16","title":"RPC_SAME_RESPONSE_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::17","title":"RPC_SAME_RESPONSE_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse) { option deprecated = true; // [!code focus] } rpc GetUserV2(GetUserRequest) returns (GetUserResponseV2); // [!code focus] ","content":"Хороший (Безопасный) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse) { option deprecated = true; // [!code focus] } rpc GetUserV2(GetUserRequest) returns (GetUserResponseV2); // [!code focus] // Новый метод rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse) { option deprecated = true; // [!code focus] } rpc UpdateUserV2(UpdateUserRequest) returns (UserUpdateResponse); // [!code focus] // Новый метод }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::18","title":"RPC_SAME_RESPONSE_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) // Старые сообщения сохраняем для обратной совместимости message GetUserResponse { string user_id = 1; string name = 2; string email = 3; }","content":"Хороший (Безопасный) // Старые сообщения сохраняем для обратной совместимости message GetUserResponse { string user_id = 1; string name = 2; string email = 3; }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::19","title":"RPC_SAME_RESPONSE_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) // Новая расширенная версия message GetUserResponseV2 { // [!code focus] string id = 1; // [!code focus] UserProfile profile = 2; // [!code focus] repeated string permissions = 3; // [!code focus] } ","content":"Хороший (Безопасный) // Новая расширенная версия 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::top::20","title":"RPC_SAME_RESPONSE_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Или создайте новую версию сервиса (package v2):** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Или создайте новую версию сервиса (package v2):** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::21","title":"RPC_SAME_RESPONSE_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v2; // [!code focus]","content":"Хороший (Безопасный) package myapi.v2; // [!code focus]"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::22","title":"RPC_SAME_RESPONSE_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); // [!code focus] rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse); // [!code focus] }","content":"Хороший (Безопасный) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); // [!code focus] rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse); // [!code focus] }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::23","title":"RPC_SAME_RESPONSE_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message GetUserResponse { // [!code focus] string id = 1; // [!code focus] UserProfile profile = 2; // [!code focus] repeated string permissions = 3; // [!code focus] } // [!code focus] ```","content":"Хороший (Безопасный) message GetUserResponse { // [!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::top::24","title":"RPC_SAME_RESPONSE_TYPE","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Влияние"],"excerpt":"Влияние **Wire Format:** Ответы сервера не десериализуются у старых клиентов **Generated Code:** Сигнатуры ожидают старый тип — компиляция падает **gRPC Calls:** Меняются типы в сгенерированных stub'ах **Runtime Errors:*","content":"Влияние **Wire Format:** Ответы сервера не десериализуются у старых клиентов **Generated Code:** Сигнатуры ожидают старый тип — компиляция падает **gRPC Calls:** Меняются типы в сгенерированных stub'ах **Runtime Errors:** Несоответствие типов ломает обработку ответа"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::25","title":"RPC_SAME_RESPONSE_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Реальный пример"],"excerpt":"Реальный пример **Код клиента ломается:** ```go // Before client := myapi.NewUserServiceClient(conn) resp, err := client.GetUser(ctx, &myapi.GetUserRequest{ UserId: \"user123\", }) if err != nil { return err }","content":"Реальный пример **Код клиента ломается:** ```go // Before 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::top::26","title":"RPC_SAME_RESPONSE_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Реальный пример"],"excerpt":"Реальный пример userID := resp.UserId name := resp.Name","content":"Реальный пример userID := resp.UserId name := resp.Name"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::27","title":"RPC_SAME_RESPONSE_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Реальный пример"],"excerpt":"Реальный пример // After (тип ответа изменён) client := myapi.NewUserServiceClient(conn) resp, err := client.GetUser(ctx, &myapi.GetUserRequest{ UserId: \"user123\", }) if err != nil { return err }","content":"Реальный пример // After (тип ответа изменён) 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::top::28","title":"RPC_SAME_RESPONSE_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Реальный пример"],"excerpt":"Реальный пример // Ошибки компиляции: userID := resp.UserId // ERROR name := resp.Name // ERROR","content":"Реальный пример // Ошибки компиляции: userID := resp.UserId // ERROR name := resp.Name // ERROR"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::29","title":"RPC_SAME_RESPONSE_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Реальный пример"],"excerpt":"Реальный пример // Новый способ: userID := resp.Id profile := resp.Profile permissions := resp.Permissions ```","content":"Реальный пример // Новый способ: userID := resp.Id profile := resp.Profile permissions := resp.Permissions ```"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::30","title":"RPC_SAME_RESPONSE_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Реальный пример"],"excerpt":"Реальный пример **Имплементация сервера также должна быть переписана:** ```go // Before func (s *server) GetUser(ctx context.Context, req *GetUserRequest) (*GetUserResponse, error) { return &GetUserResponse{ UserId: \"use","content":"Реальный пример **Имплементация сервера также должна быть переписана:** ```go // Before 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::top::31","title":"RPC_SAME_RESPONSE_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Реальный пример"],"excerpt":"Реальный пример // After func (s *server) GetUser(ctx context.Context, req *GetUserRequest) (*GetUserResponseV2, error) { return &GetUserResponseV2{ Id: \"user123\", Profile: &UserProfile{ Name: \"John Doe\", Email: \"john@ex","content":"Реальный пример // After func (s *server) GetUser(ctx context.Context, req *GetUserRequest) (*GetUserResponseV2, error) { return &GetUserResponseV2{ Id: \"user123\", Profile: &UserProfile{ Name: \"John Doe\", Email: \"john@example.com\", }, Permissions: []string{\"read\"}, }, nil } ```"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::32","title":"RPC_SAME_RESPONSE_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Добавьте новый RPC c новым типом ответа:**","content":"Стратегия миграции **Добавьте новый RPC c новым типом ответа:**"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::33","title":"RPC_SAME_RESPONSE_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Поддерживайте оба на сервере:** ```go func (s *server) GetUser(ctx context.Context, req *GetUserRequest) (*GetUserResponse, error) { user := s.getUserInternal(req.UserId) return &GetUserResponse{ Use","content":"Стратегия миграции **Поддерживайте оба на сервере:** ```go func (s *server) GetUser(ctx context.Context, req *GetUserRequest) (*GetUserResponse, error) { user := s.getUserInternal(req.UserId) return &GetUserResponse{ UserId: user.ID, Name: user.Name, Email: user.Email, }, nil }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::34","title":"RPC_SAME_RESPONSE_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции func (s *server) GetUserV2(ctx context.Context, req *GetUserRequest) (*GetUserResponseV2, error) { user := s.getUserInternal(req.UserId) return &GetUserResponseV2{ Id: user.ID, Profile: &UserProfile{ N","content":"Стратегия миграции func (s *server) GetUserV2(ctx context.Context, req *GetUserRequest) (*GetUserResponseV2, error) { user := s.getUserInternal(req.UserId) return &GetUserResponseV2{ Id: user.ID, Profile: &UserProfile{ Name: user.Name, Email: user.Email, }, Permissions: user.Permissions, }, nil } ```"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::35","title":"RPC_SAME_RESPONSE_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Мигрируйте клиентов на новый RPC:**","content":"Стратегия миграции **Мигрируйте клиентов на новый RPC:**"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::36","title":"RPC_SAME_RESPONSE_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Удалите старый RPC** в следующей major‑версии:","content":"Стратегия миграции **Удалите старый RPC** в следующей major‑версии:"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::37","title":"RPC_SAME_RESPONSE_TYPE","section":"Добавление новых обязательных полей","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Добавление новых обязательных полей"],"excerpt":"Добавление новых обязательных полей ```proto // ПЛОХО: меняем существующий тип message GetUserResponse { string user_id = 1; string name = 2; UserProfile profile = 3; // BREAKING }","content":"Добавление новых обязательных полей ```proto // ПЛОХО: меняем существующий тип message GetUserResponse { string user_id = 1; string name = 2; UserProfile profile = 3; // BREAKING }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::38","title":"RPC_SAME_RESPONSE_TYPE","section":"Добавление новых обязательных полей","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Добавление новых обязательных полей"],"excerpt":"Добавление новых обязательных полей // Хорошо: новая версия message GetUserResponseV2 { string user_id = 1; string name = 2; UserProfile profile = 3; } ```","content":"Добавление новых обязательных полей // Хорошо: новая версия message GetUserResponseV2 { string user_id = 1; string name = 2; UserProfile profile = 3; } ```"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::39","title":"RPC_SAME_RESPONSE_TYPE","section":"Реструктуризация ответа","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Реструктуризация ответа"],"excerpt":"Реструктуризация ответа ```proto // ПЛОХО: меняем структуру прямо message UpdateUserResponse { UserDetails details = 1; // BREAKING }","content":"Реструктуризация ответа ```proto // ПЛОХО: меняем структуру прямо message UpdateUserResponse { UserDetails details = 1; // BREAKING }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::40","title":"RPC_SAME_RESPONSE_TYPE","section":"Реструктуризация ответа","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Реструктуризация ответа"],"excerpt":"Реструктуризация ответа // Хорошо: версионирование rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse) { option deprecated = true; } rpc UpdateUserV2(UpdateUserRequest) returns (UpdateUserResponseV2); ```","content":"Реструктуризация ответа // Хорошо: версионирование rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse) { option deprecated = true; } rpc UpdateUserV2(UpdateUserRequest) returns (UpdateUserResponseV2); ```"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::41","title":"RPC_SAME_RESPONSE_TYPE","section":"Изменение формата ошибок","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Изменение формата ошибок"],"excerpt":"Изменение формата ошибок ```proto // ПЛОХО: меняем формат напрямую message CreateUserResponse { ErrorDetails error = 1; // BREAKING }","content":"Изменение формата ошибок ```proto // ПЛОХО: меняем формат напрямую message CreateUserResponse { ErrorDetails error = 1; // BREAKING }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::42","title":"RPC_SAME_RESPONSE_TYPE","section":"Изменение формата ошибок","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Изменение формата ошибок"],"excerpt":"Изменение формата ошибок // Хорошо: новая версия rpc CreateUser(CreateUserRequest) returns (CreateUserResponse) { option deprecated = true; } rpc CreateUserV2(CreateUserRequest) returns (CreateUserResponseV2); ```","content":"Изменение формата ошибок // Хорошо: новая версия rpc CreateUser(CreateUserRequest) returns (CreateUserResponse) { option deprecated = true; } rpc CreateUserV2(CreateUserRequest) returns (CreateUserResponseV2); ```"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::43","title":"RPC_SAME_RESPONSE_TYPE","section":"Миграция формата","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Миграция формата"],"excerpt":"Миграция формата ```proto // ПЛОХО: перевод простой структуры в сложную message GetUserResponse { UserData data = 1; // BREAKING }","content":"Миграция формата ```proto // ПЛОХО: перевод простой структуры в сложную message GetUserResponse { UserData data = 1; // BREAKING }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::44","title":"RPC_SAME_RESPONSE_TYPE","section":"Миграция формата","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Миграция формата"],"excerpt":"Миграция формата // Хорошо: предоставляем обе версии rpc GetUser(GetUserRequest) returns (GetUserResponse) { option deprecated = true; } rpc GetUserDetailed(GetUserRequest) returns (GetUserDetailedResponse); ```","content":"Миграция формата // Хорошо: предоставляем обе версии 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":"Данное правило проверяет, что ни один service не был удалён из proto‑файлов. Удаление service ломает сгенерированный код и клиентские приложения, которые на него опираются.","content":"Данное правило проверяет, что ни один service не был удалён из proto‑файлов. Удаление service ломает сгенерированный код и клиентские приложения, которые на него опираются."},{"id":"cli/breaking-changes/rules/service-no-delete::breaking::1","title":"SERVICE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/service-no-delete::breaking::2","title":"SERVICE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/service-no-delete::breaking::3","title":"SERVICE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); }","content":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); }"},{"id":"cli/breaking-changes/rules/service-no-delete::breaking::4","title":"SERVICE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) service OrderService { // [!code --] rpc GetOrder(GetOrderRequest) returns (GetOrderResponse); // [!code --] } // [!code --] ```","content":"Плохой (Breaking) service OrderService { // [!code --] rpc GetOrder(GetOrderRequest) returns (GetOrderResponse); // [!code --] } // [!code --] ```"},{"id":"cli/breaking-changes/rules/service-no-delete::breaking::5","title":"SERVICE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/service-no-delete::breaking::6","title":"SERVICE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/service-no-delete::breaking::7","title":"SERVICE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); }","content":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); }"},{"id":"cli/breaking-changes/rules/service-no-delete::breaking::8","title":"SERVICE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) // OrderService удалён — BREAKING CHANGE! ```","content":"Плохой (Breaking) // OrderService удалён — BREAKING CHANGE! ```"},{"id":"cli/breaking-changes/rules/service-no-delete::top::9","title":"SERVICE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо удаления — отметьте service как deprecated:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо удаления — отметьте service как deprecated:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/service-no-delete::top::10","title":"SERVICE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/service-no-delete::top::11","title":"SERVICE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); }","content":"Хороший (Безопасный) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); }"},{"id":"cli/breaking-changes/rules/service-no-delete::top::12","title":"SERVICE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) service OrderService { option deprecated = true; // [!code focus] rpc GetOrder(GetOrderRequest) returns (GetOrderResponse) { option deprecated = true; // [!code focus] } } ```","content":"Хороший (Безопасный) 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::top::13","title":"SERVICE_NO_DELETE","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete","headings":["Влияние"],"excerpt":"Влияние **Generated Code:** Классы / интерфейсы сервиса исчезают — клиенты не компилируются **Client Applications:** Существующие вызовы к удалённому сервису падают на этапе сборки **Runtime:** gRPC клиенты теряют опреде","content":"Влияние **Generated Code:** Классы / интерфейсы сервиса исчезают — клиенты не компилируются **Client Applications:** Существующие вызовы к удалённому сервису падают на этапе сборки **Runtime:** gRPC клиенты теряют определение метода/сервиса"},{"id":"cli/breaking-changes/rules/service-no-delete::top::14","title":"SERVICE_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Сначала деприкация:**","content":"Стратегия миграции **Сначала деприкация:**"},{"id":"cli/breaking-changes/rules/service-no-delete::top::15","title":"SERVICE_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Уведомите клиентов** о сроках вывода из эксплуатации","content":"Стратегия миграции **Уведомите клиентов** о сроках вывода из эксплуатации"},{"id":"cli/breaking-changes/rules/service-no-delete::top::16","title":"SERVICE_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Удалите после периода миграции** в следующей major‑версии","content":"Стратегия миграции **Удалите после периода миграции** в следующей major‑версии"},{"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 Формат вывода для команд с поддержкой нескольких форматов (text/json) значение по умолчанию зависит от команды"},{"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 Базовая директория для поиска файлов Текущая рабочая дир","content":"Command-Specific Flags Flag Short Environment Description Default ------ ------- ------------- ------------- --------- --path -p Directory path to lint . --root -r Базовая директория для поиска файлов Текущая рабочая директория --format -f EASYP_FORMAT Использует глобальный флаг формата (text/json) Использует глобальное значение по умолчанию"},{"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 из поддиректории с правильным разрешением импортов easyp lint --root src/IPC/Contracts --path .","content":"Command-Specific Flags Lint из поддиректории с правильным разрешением импортов 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 # глобальный флаг","content":"Command-Specific Flags JSON output format easyp --format json lint # глобальный флаг"},{"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 Путь к директории с proto файлами для генерации . --root -r Базова","content":"Command-Specific Flags Flag Short Environment Description Default ------ ------- ------------- ------------- --------- --path -p EASYP_ROOT_GENERATE_PATH Путь к директории с proto файлами для генерации . --root -r Базовая директория для поиска файлов Текущая рабочая директория"},{"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 из поддиректории с правильным разрешением импортов easyp generate --root src/IPC/Contracts --path .","content":"Command-Specific Flags Generate из поддиректории с правильным разрешением импортов 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 Использует глобальный флаг формата (text/json) Использует глобальное значение по умолчанию"},{"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 # глобальный флаг ```","content":"Command-Specific Flags JSON output easyp --format json breaking --against main # глобальный флаг ```"},{"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 работает интерактивно: Если в корне целевой директории есть buf.yml/buf.yaml, команда предложит миграцию из Buf. Если easyp.yaml уже существует, команда запросит подтверждение на перезап","content":"Command-Specific Flags easyp init работает интерактивно: Если в корне целевой директории есть buf.yml/buf.yaml, команда предложит миграцию из Buf. Если easyp.yaml уже существует, команда запросит подтверждение на перезапись."},{"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 Путь до файла конфигурации easyp.yaml --format (global) -f EASYP_FORMAT Глобаль","content":"Command-Specific Flags Flag Short Environment Description Default ------ ------- ------------- ------------- --------- --config -c EASYP_CFG Путь до файла конфигурации easyp.yaml --format (global) -f EASYP_FORMAT Глобальный формат вывода для команд с несколькими форматами (json или text) зависит от команды (json для 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 Проверить конфиг по умолчанию с JSON выводом (статус 0 если ошибок нет) easyp validate-config","content":"Command-Specific Flags **Examples:** ```bash Проверить конфиг по умолчанию с JSON выводом (статус 0 если ошибок нет) 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 Проверить другой файл и вывести в текстовом формате (глобальный --format) easyp --format text validate-config --config example.easyp.yaml ```","content":"Command-Specific Flags Проверить другой файл и вывести в текстовом формате (глобальный --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 Формат вывода для поддерживаемых команд (text/json). Если не указан, каждая команда использует своё значение по умолчанию. значение по умолчанию зависит от команды 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::top::45","title":"EasyP Configuration Reference","section":"Переменные окружения в конфигурации","path":"/docs/guide/cli/configuration/configuration","headings":["Переменные окружения в конфигурации"],"excerpt":"Переменные окружения в конфигурации EasyP поддерживает расширение переменных окружения непосредственно в файле конфигурации easyp.yaml. Это позволяет использовать переменные окружения для динамических значений конфигурац","content":"Переменные окружения в конфигурации EasyP поддерживает расширение переменных окружения непосредственно в файле конфигурации easyp.yaml. Это позволяет использовать переменные окружения для динамических значений конфигурации."},{"id":"cli/configuration/configuration::top::46","title":"EasyP Configuration Reference","section":"Переменные окружения в конфигурации","path":"/docs/guide/cli/configuration/configuration","headings":["Переменные окружения в конфигурации"],"excerpt":"Переменные окружения в конфигурации **Пример со всеми поддерживаемыми возможностями:** ```yaml deps: # Базовое расширение: ${VAR} - расширяется в значение переменной VAR - ${GOOGLEAPIS_REPO}@${GOOGLEAPIS_VERSION} # Значе","content":"Переменные окружения в конфигурации **Пример со всеми поддерживаемыми возможностями:** ```yaml deps: # Базовое расширение: ${VAR} - расширяется в значение переменной VAR - ${GOOGLEAPIS_REPO}@${GOOGLEAPIS_VERSION} # Значение по умолчанию: ${VAR:-default} - использует default, если VAR не установлена или пустая - ${GNOSTIC_REPO:-github.com/google/gnostic}@${GNOSTIC_VERSION:-v0.7.0}"},{"id":"cli/configuration/configuration::top::47","title":"EasyP Configuration Reference","section":"Переменные окружения в конфигурации","path":"/docs/guide/cli/configuration/configuration","headings":["Переменные окружения в конфигурации"],"excerpt":"Переменные окружения в конфигурации generate: inputs: # Значение по умолчанию, если INPUT_DIR не установлена - directory: ${INPUT_DIR:-proto} plugins: - name: go # Базовое расширение out: ${OUTPUT_DIR} opts: # Значение п","content":"Переменные окружения в конфигурации generate: inputs: # Значение по умолчанию, если INPUT_DIR не установлена - directory: ${INPUT_DIR:-proto} plugins: - name: go # Базовое расширение out: ${OUTPUT_DIR} opts: # Значение по умолчанию module: ${MODULE_NAME:-github.com/example/project} timeout: ${TIMEOUT:-30} # Экранирование: $$ становится буквальным $, $${VAR} становится буквальным ${VAR} path: \"${BASE_DIR}/$${TEMP}/file\" # Результат: \"/tmp/${TEMP}/file\" (если BASE_DIR=/tmp) literal: \"$$\" # Результат: \"$\" ```"},{"id":"cli/configuration/configuration::top::48","title":"EasyP Configuration Reference","section":"Переменные окружения в конфигурации","path":"/docs/guide/cli/configuration/configuration","headings":["Переменные окружения в конфигурации"],"excerpt":"Переменные окружения в конфигурации **Поддерживаемый синтаксис:** ${VAR} - расширяется в значение переменной VAR ${VAR:-default} - использует default, если VAR не установлена или пустая ${VAR:=default} - использует defau","content":"Переменные окружения в конфигурации **Поддерживаемый синтаксис:** ${VAR} - расширяется в значение переменной VAR ${VAR:-default} - использует default, если VAR не установлена или пустая ${VAR:=default} - использует default, если VAR не установлена или пустая ${VAR-default} - использует default, если VAR не установлена (пустая строка сохраняется) $${VAR} или $$VAR - экранирует в буквальную строку ${VAR} или $VAR $$ - экранирует в буквальный символ $"},{"id":"cli/configuration/configuration::top::49","title":"EasyP Configuration Reference","section":"Переменные окружения в конфигурации","path":"/docs/guide/cli/configuration/configuration","headings":["Переменные окружения в конфигурации"],"excerpt":"Переменные окружения в конфигурации **Примечание:** Переменные окружения расширяются до парсинга YAML, поэтому любой паттерн ${STRING} будет обработан. Используйте $$ для экранирования символов доллара, когда нужны буква","content":"Переменные окружения в конфигурации **Примечание:** Переменные окружения расширяются до парсинга YAML, поэтому любой паттерн ${STRING} будет обработан. Используйте $$ для экранирования символов доллара, когда нужны буквальные значения."},{"id":"cli/configuration/configuration::version::50","title":"EasyP Configuration Reference","section":"version","path":"/docs/guide/cli/configuration/configuration#version","headings":["version"],"excerpt":"version **Опционально (legacy-совместимость).** Поле поддерживается для обратной совместимости и может быть опущено в новых конфигурациях.","content":"version **Опционально (legacy-совместимость).** Поле поддерживается для обратной совместимости и может быть опущено в новых конфигурациях."},{"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:** не задано **Рекомендация:** если сохраняете поле, используйте v1alpha","content":"version **Type:** string **Default:** не задано **Рекомендация:** если сохраняете поле, используйте v1alpha"},{"id":"cli/configuration/configuration::version::52","title":"EasyP Configuration Reference","section":"version","path":"/docs/guide/cli/configuration/configuration#version","headings":["version"],"excerpt":"version На поведение рантайма это поле не влияет.","content":"version На поведение рантайма это поле не влияет."},{"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, required) - Output directory for generated files opts (mapstring, optional) - Plugin-specific options; each key can be a single value or an array of 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::top::0","title":"Go","section":"Установка плагинов","path":"/docs/guide/cli/generator/examples/go","headings":["Установка плагинов"],"excerpt":"Установка плагинов Сначала установите необходимые плагины для работы с gRPC:","content":"Установка плагинов Сначала установите необходимые плагины для работы с gRPC:"},{"id":"cli/generator/examples/go::top::1","title":"Go","section":"Установка плагинов","path":"/docs/guide/cli/generator/examples/go","headings":["Установка плагинов"],"excerpt":"Установка плагинов Эти команды установят плагины protoc-gen-go и protoc-gen-go-grpc для использования с EasyP.","content":"Установка плагинов Эти команды установят плагины protoc-gen-go и protoc-gen-go-grpc для использования с EasyP."},{"id":"cli/generator/examples/go::proto::2","title":"Go","section":"Пример proto‑сервиса","path":"/docs/guide/cli/generator/examples/go#proto","headings":["Пример proto‑сервиса"],"excerpt":"Пример proto‑сервиса Ниже пример proto-файла для сервиса Echo:","content":"Пример proto‑сервиса Ниже пример proto-файла для сервиса Echo:"},{"id":"cli/generator/examples/go::proto::3","title":"Go","section":"Пример proto‑сервиса","path":"/docs/guide/cli/generator/examples/go#proto","headings":["Пример proto‑сервиса"],"excerpt":"Пример proto‑сервиса ```proto syntax = \"proto3\";","content":"Пример proto‑сервиса ```proto syntax = \"proto3\";"},{"id":"cli/generator/examples/go::proto::4","title":"Go","section":"Пример proto‑сервиса","path":"/docs/guide/cli/generator/examples/go#proto","headings":["Пример proto‑сервиса"],"excerpt":"Пример proto‑сервиса package api.echo.v1;","content":"Пример proto‑сервиса package api.echo.v1;"},{"id":"cli/generator/examples/go::proto::5","title":"Go","section":"Пример proto‑сервиса","path":"/docs/guide/cli/generator/examples/go#proto","headings":["Пример proto‑сервиса"],"excerpt":"Пример proto‑сервиса option go_package = \"github.com/easyp-tech/example/api/echo/v1;pb\";","content":"Пример proto‑сервиса option go_package = \"github.com/easyp-tech/example/api/echo/v1;pb\";"},{"id":"cli/generator/examples/go::proto::6","title":"Go","section":"Пример proto‑сервиса","path":"/docs/guide/cli/generator/examples/go#proto","headings":["Пример proto‑сервиса"],"excerpt":"Пример proto‑сервиса service EchoAPI { rpc Echo(EchoRequest) returns (EchoResponse); rpc EchoStream(EchoStreamRequest) returns (EchoResponse); }","content":"Пример proto‑сервиса service EchoAPI { rpc Echo(EchoRequest) returns (EchoResponse); rpc EchoStream(EchoStreamRequest) returns (EchoResponse); }"},{"id":"cli/generator/examples/go::proto::7","title":"Go","section":"Пример proto‑сервиса","path":"/docs/guide/cli/generator/examples/go#proto","headings":["Пример proto‑сервиса"],"excerpt":"Пример proto‑сервиса message EchoRequest { string payload = 1; }","content":"Пример proto‑сервиса message EchoRequest { string payload = 1; }"},{"id":"cli/generator/examples/go::proto::8","title":"Go","section":"Пример proto‑сервиса","path":"/docs/guide/cli/generator/examples/go#proto","headings":["Пример proto‑сервиса"],"excerpt":"Пример proto‑сервиса message EchoResponse { string payload = 2; }","content":"Пример proto‑сервиса message EchoResponse { string payload = 2; }"},{"id":"cli/generator/examples/go::proto::9","title":"Go","section":"Пример proto‑сервиса","path":"/docs/guide/cli/generator/examples/go#proto","headings":["Пример proto‑сервиса"],"excerpt":"Пример proto‑сервиса message EchoStreamRequest { string payload = 1; }","content":"Пример proto‑сервиса message EchoStreamRequest { string payload = 1; }"},{"id":"cli/generator/examples/go::proto::10","title":"Go","section":"Пример proto‑сервиса","path":"/docs/guide/cli/generator/examples/go#proto","headings":["Пример proto‑сервиса"],"excerpt":"Пример proto‑сервиса message EchoStreamResponse { string payload = 2; } ```","content":"Пример proto‑сервиса message EchoStreamResponse { string payload = 2; } ```"},{"id":"cli/generator/examples/go::top::11","title":"Go","section":"Настройка конфигурации","path":"/docs/guide/cli/generator/examples/go","headings":["Настройка конфигурации"],"excerpt":"Настройка конфигурации Создайте и настройте файл конфигурации easyp.yaml:","content":"Настройка конфигурации Создайте и настройте файл конфигурации easyp.yaml:"},{"id":"cli/generator/examples/go::top::12","title":"Go","section":"Настройка конфигурации","path":"/docs/guide/cli/generator/examples/go","headings":["Настройка конфигурации"],"excerpt":"Настройка конфигурации Этот файл указывает использование двух плагинов: go для генерации Go-кода и go-grpc для генерации gRPC-кода, вместе с их опциями.","content":"Настройка конфигурации Этот файл указывает использование двух плагинов: go для генерации Go-кода и go-grpc для генерации gRPC-кода, вместе с их опциями."},{"id":"cli/generator/examples/go::top::13","title":"Go","section":"Генерация кода","path":"/docs/guide/cli/generator/examples/go","headings":["Генерация кода"],"excerpt":"Генерация кода Чтобы сгенерировать код, выполните команду:","content":"Генерация кода Чтобы сгенерировать код, выполните команду:"},{"id":"cli/generator/examples/go::top::14","title":"Go","section":"Генерация кода","path":"/docs/guide/cli/generator/examples/go","headings":["Генерация кода"],"excerpt":"Генерация кода Если флаг --cfg не указан, по умолчанию используется файл easyp.yaml в текущей директории:","content":"Генерация кода Если флаг --cfg не указан, по умолчанию используется файл easyp.yaml в текущей директории:"},{"id":"cli/generator/examples/go::top::15","title":"Go","section":"Генерация кода","path":"/docs/guide/cli/generator/examples/go","headings":["Генерация кода"],"excerpt":"Генерация кода Теперь у вас есть сгенерированный Go‑код, с которым можно напрямую работать.","content":"Генерация кода Теперь у вас есть сгенерированный Go‑код, с которым можно напрямую работать."},{"id":"cli/generator/examples/grpc-gateway::top::0","title":"gRPC-Gateway","section":"Установка плагинов","path":"/docs/guide/cli/generator/examples/grpc-gateway","headings":["Установка плагинов"],"excerpt":"Установка плагинов В дополнение к плагинам для работы с gRPC, необходимо установить следующие плагины для gRPC-Gateway:","content":"Установка плагинов В дополнение к плагинам для работы с gRPC, необходимо установить следующие плагины для gRPC-Gateway:"},{"id":"cli/generator/examples/grpc-gateway::top::1","title":"gRPC-Gateway","section":"Установка плагинов","path":"/docs/guide/cli/generator/examples/grpc-gateway","headings":["Установка плагинов"],"excerpt":"Установка плагинов go install google.golang.org/protobuf/cmd/protoc-gen-go@latest go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest go install github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2@","content":"Установка плагинов go install google.golang.org/protobuf/cmd/protoc-gen-go@latest go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest go install github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2@latest go install github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway@latest"},{"id":"cli/generator/examples/grpc-gateway::top::2","title":"gRPC-Gateway","section":"Установка плагинов","path":"/docs/guide/cli/generator/examples/grpc-gateway","headings":["Установка плагинов"],"excerpt":"Установка плагинов Эти команды установят плагины protoc-gen-go, protoc-gen-go-grpc, protoc-gen-openapiv2 и protoc-gen-grpc-gateway для использования с EasyP.","content":"Установка плагинов Эти команды установят плагины protoc-gen-go, protoc-gen-go-grpc, protoc-gen-openapiv2 и protoc-gen-grpc-gateway для использования с EasyP."},{"id":"cli/generator/examples/grpc-gateway::proto::3","title":"gRPC-Gateway","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/grpc-gateway#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса Ниже — исходный proto‑файл для сервиса Echo:","content":"Пример Proto сервиса Ниже — исходный proto‑файл для сервиса Echo:"},{"id":"cli/generator/examples/grpc-gateway::proto::4","title":"gRPC-Gateway","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/grpc-gateway#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса syntax = \"proto3\";","content":"Пример Proto сервиса syntax = \"proto3\";"},{"id":"cli/generator/examples/grpc-gateway::proto::5","title":"gRPC-Gateway","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/grpc-gateway#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса package api.echo.v1;","content":"Пример Proto сервиса package api.echo.v1;"},{"id":"cli/generator/examples/grpc-gateway::proto::6","title":"gRPC-Gateway","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/grpc-gateway#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса option go_package = \"github.com/easyp-tech/example/api/echo/v1;pb\";","content":"Пример Proto сервиса option go_package = \"github.com/easyp-tech/example/api/echo/v1;pb\";"},{"id":"cli/generator/examples/grpc-gateway::proto::7","title":"gRPC-Gateway","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/grpc-gateway#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса service EchoAPI { rpc Echo(EchoRequest) returns (EchoResponse); }","content":"Пример Proto сервиса service EchoAPI { rpc Echo(EchoRequest) returns (EchoResponse); }"},{"id":"cli/generator/examples/grpc-gateway::proto::8","title":"gRPC-Gateway","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/grpc-gateway#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса message EchoRequest { string payload = 1; }","content":"Пример Proto сервиса message EchoRequest { string payload = 1; }"},{"id":"cli/generator/examples/grpc-gateway::proto::9","title":"gRPC-Gateway","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/grpc-gateway#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса message EchoResponse { string payload = 2; }","content":"Пример Proto сервиса message EchoResponse { string payload = 2; }"},{"id":"cli/generator/examples/grpc-gateway::proto::10","title":"gRPC-Gateway","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/grpc-gateway#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса Чтобы использовать gRPC-Gateway, обновите proto‑файл, добавив HTTP‑опции:","content":"Пример Proto сервиса Чтобы использовать gRPC-Gateway, обновите proto‑файл, добавив HTTP‑опции:"},{"id":"cli/generator/examples/grpc-gateway::proto::11","title":"gRPC-Gateway","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/grpc-gateway#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса syntax = \"proto3\"; import \"google/api/annotations.proto\";","content":"Пример Proto сервиса syntax = \"proto3\"; import \"google/api/annotations.proto\";"},{"id":"cli/generator/examples/grpc-gateway::proto::12","title":"gRPC-Gateway","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/grpc-gateway#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса package api.echo.v1;","content":"Пример Proto сервиса package api.echo.v1;"},{"id":"cli/generator/examples/grpc-gateway::proto::13","title":"gRPC-Gateway","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/grpc-gateway#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса option go_package = \"github.com/easyp-tech/example/api/echo/v1;pb\";","content":"Пример Proto сервиса option go_package = \"github.com/easyp-tech/example/api/echo/v1;pb\";"},{"id":"cli/generator/examples/grpc-gateway::proto::14","title":"gRPC-Gateway","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/grpc-gateway#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса service EchoAPI { rpc Echo(EchoRequest) returns (EchoResponse) { option (google.api.http) = { // [!code ++] post: \"/api/v1/echo\" // [!code ++] body: \"*\" // [!code ++] }; // [!code ++] } }","content":"Пример Proto сервиса 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::proto::15","title":"gRPC-Gateway","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/grpc-gateway#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса message EchoRequest { string payload = 1; }","content":"Пример Proto сервиса message EchoRequest { string payload = 1; }"},{"id":"cli/generator/examples/grpc-gateway::proto::16","title":"gRPC-Gateway","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/grpc-gateway#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса message EchoResponse { string payload = 2; }","content":"Пример Proto сервиса message EchoResponse { string payload = 2; }"},{"id":"cli/generator/examples/grpc-gateway::top::17","title":"gRPC-Gateway","section":"Настройка конфигурации","path":"/docs/guide/cli/generator/examples/grpc-gateway","headings":["Настройка конфигурации"],"excerpt":"Настройка конфигурации Обновите файл easyp.yaml, добавив необходимые зависимости и плагины: deps: # [!code ++] - github.com/googleapis/googleapis # [!code ++]","content":"Настройка конфигурации Обновите файл easyp.yaml, добавив необходимые зависимости и плагины: deps: # [!code ++] - github.com/googleapis/googleapis # [!code ++]"},{"id":"cli/generator/examples/grpc-gateway::top::18","title":"gRPC-Gateway","section":"Настройка конфигурации","path":"/docs/guide/cli/generator/examples/grpc-gateway","headings":["Настройка конфигурации"],"excerpt":"Настройка конфигурации 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":"Настройка конфигурации 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::top::19","title":"gRPC-Gateway","section":"Настройка конфигурации","path":"/docs/guide/cli/generator/examples/grpc-gateway","headings":["Настройка конфигурации"],"excerpt":"Настройка конфигурации Секция deps перечисляет зависимости, необходимые для импортов proto‑файлов. В данном случае добавляем github.com/googleapis/googleapis, поскольку там находится файл annotations.proto, используемый ","content":"Настройка конфигурации Секция deps перечисляет зависимости, необходимые для импортов proto‑файлов. В данном случае добавляем github.com/googleapis/googleapis, поскольку там находится файл annotations.proto, используемый в определении сервиса."},{"id":"cli/generator/examples/grpc-gateway::top::20","title":"gRPC-Gateway","section":"Обновление зависимостей","path":"/docs/guide/cli/generator/examples/grpc-gateway","headings":["Обновление зависимостей"],"excerpt":"Обновление зависимостей После обновления конфигурации выполните команду для загрузки указанных зависимостей:","content":"Обновление зависимостей После обновления конфигурации выполните команду для загрузки указанных зависимостей:"},{"id":"cli/generator/examples/grpc-gateway::top::21","title":"gRPC-Gateway","section":"Обновление зависимостей","path":"/docs/guide/cli/generator/examples/grpc-gateway","headings":["Обновление зависимостей"],"excerpt":"Обновление зависимостей easyp mod update","content":"Обновление зависимостей easyp mod update"},{"id":"cli/generator/examples/grpc-gateway::top::22","title":"gRPC-Gateway","section":"Обновление зависимостей","path":"/docs/guide/cli/generator/examples/grpc-gateway","headings":["Обновление зависимостей"],"excerpt":"Обновление зависимостей Больше деталей по управлению зависимостями см. в разделе Package Manager.","content":"Обновление зависимостей Больше деталей по управлению зависимостями см. в разделе Package Manager."},{"id":"cli/generator/examples/grpc-gateway::top::23","title":"gRPC-Gateway","section":"Генерация кода","path":"/docs/guide/cli/generator/examples/grpc-gateway","headings":["Генерация кода"],"excerpt":"Генерация кода Для генерации кода используйте:","content":"Генерация кода Для генерации кода используйте:"},{"id":"cli/generator/examples/grpc-gateway::top::24","title":"gRPC-Gateway","section":"Генерация кода","path":"/docs/guide/cli/generator/examples/grpc-gateway","headings":["Генерация кода"],"excerpt":"Генерация кода easyp --cfg easyp.yaml generate","content":"Генерация кода easyp --cfg easyp.yaml generate"},{"id":"cli/generator/examples/grpc-gateway::top::25","title":"gRPC-Gateway","section":"Генерация кода","path":"/docs/guide/cli/generator/examples/grpc-gateway","headings":["Генерация кода"],"excerpt":"Генерация кода Если флаг --cfg не указан, по умолчанию используется файл easyp.yaml из текущей директории:","content":"Генерация кода Если флаг --cfg не указан, по умолчанию используется файл easyp.yaml из текущей директории:"},{"id":"cli/generator/examples/grpc-gateway::top::26","title":"gRPC-Gateway","section":"Генерация кода","path":"/docs/guide/cli/generator/examples/grpc-gateway","headings":["Генерация кода"],"excerpt":"Генерация кода Теперь у вас сгенерированы Go‑код и код gRPC-Gateway, с которыми можно работать напрямую.","content":"Генерация кода Теперь у вас сгенерированы Go‑код и код gRPC-Gateway, с которыми можно работать напрямую."},{"id":"cli/generator/examples/validate::top::0","title":"Validate","section":"Установка плагинов","path":"/docs/guide/cli/generator/examples/validate","headings":["Установка плагинов"],"excerpt":"Установка плагинов Сначала установите необходимые плагины для работы с gRPC и проверок (validate):","content":"Установка плагинов Сначала установите необходимые плагины для работы с gRPC и проверок (validate):"},{"id":"cli/generator/examples/validate::top::1","title":"Validate","section":"Установка плагинов","path":"/docs/guide/cli/generator/examples/validate","headings":["Установка плагинов"],"excerpt":"Установка плагинов Эти команды установят плагины protoc-gen-go, protoc-gen-go-grpc и protoc-gen-validate для использования вместе с EasyP.","content":"Установка плагинов Эти команды установят плагины protoc-gen-go, protoc-gen-go-grpc и protoc-gen-validate для использования вместе с EasyP."},{"id":"cli/generator/examples/validate::proto::2","title":"Validate","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/validate#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса Ниже пример proto‑файла для сервиса Echo:","content":"Пример Proto сервиса Ниже пример proto‑файла для сервиса Echo:"},{"id":"cli/generator/examples/validate::proto::3","title":"Validate","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/validate#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса ```proto syntax = \"proto3\";","content":"Пример Proto сервиса ```proto syntax = \"proto3\";"},{"id":"cli/generator/examples/validate::proto::4","title":"Validate","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/validate#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса package api.echo.v1;","content":"Пример Proto сервиса package api.echo.v1;"},{"id":"cli/generator/examples/validate::proto::5","title":"Validate","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/validate#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса import \"validate/validate.proto\";","content":"Пример Proto сервиса import \"validate/validate.proto\";"},{"id":"cli/generator/examples/validate::proto::6","title":"Validate","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/validate#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса option go_package = \"github.com/easyp-tech/example/api/echo/v1;pb\";","content":"Пример Proto сервиса option go_package = \"github.com/easyp-tech/example/api/echo/v1;pb\";"},{"id":"cli/generator/examples/validate::proto::7","title":"Validate","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/validate#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса service EchoAPI { rpc Echo(EchoRequest) returns (EchoResponse); rpc EchoStream(EchoStreamRequest) returns (EchoResponse); }","content":"Пример Proto сервиса service EchoAPI { rpc Echo(EchoRequest) returns (EchoResponse); rpc EchoStream(EchoStreamRequest) returns (EchoResponse); }"},{"id":"cli/generator/examples/validate::proto::8","title":"Validate","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/validate#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса message EchoRequest { string payload = 1 [(validate.rules).string = {max_len: 200}]; }","content":"Пример Proto сервиса message EchoRequest { string payload = 1 [(validate.rules).string = {max_len: 200}]; }"},{"id":"cli/generator/examples/validate::proto::9","title":"Validate","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/validate#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса message EchoResponse { string payload = 2; }","content":"Пример Proto сервиса message EchoResponse { string payload = 2; }"},{"id":"cli/generator/examples/validate::proto::10","title":"Validate","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/validate#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса message EchoStreamRequest { string payload = 1 [(validate.rules).string = {max_len: 200}]; }","content":"Пример Proto сервиса message EchoStreamRequest { string payload = 1 [(validate.rules).string = {max_len: 200}]; }"},{"id":"cli/generator/examples/validate::proto::11","title":"Validate","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/validate#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса message EchoStreamResponse { string payload = 2; } ```","content":"Пример Proto сервиса message EchoStreamResponse { string payload = 2; } ```"},{"id":"cli/generator/examples/validate::top::12","title":"Validate","section":"Настройка конфигурации","path":"/docs/guide/cli/generator/examples/validate","headings":["Настройка конфигурации"],"excerpt":"Настройка конфигурации Создайте и настройте файл конфигурации easyp.yaml:","content":"Настройка конфигурации Создайте и настройте файл конфигурации easyp.yaml:"},{"id":"cli/generator/examples/validate::top::13","title":"Validate","section":"Настройка конфигурации","path":"/docs/guide/cli/generator/examples/validate","headings":["Настройка конфигурации"],"excerpt":"Настройка конфигурации ```yaml deps: # [!code ++] - github.com/bufbuild/protoc-gen-validate # [!code ++]","content":"Настройка конфигурации ```yaml deps: # [!code ++] - github.com/bufbuild/protoc-gen-validate # [!code ++]"},{"id":"cli/generator/examples/validate::top::14","title":"Validate","section":"Настройка конфигурации","path":"/docs/guide/cli/generator/examples/validate","headings":["Настройка конфигурации"],"excerpt":"Настройка конфигурации 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: sourc","content":"Настройка конфигурации 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::top::15","title":"Validate","section":"Генерация кода","path":"/docs/guide/cli/generator/examples/validate","headings":["Генерация кода"],"excerpt":"Генерация кода Чтобы сгенерировать код, выполните команду:","content":"Генерация кода Чтобы сгенерировать код, выполните команду:"},{"id":"cli/generator/examples/validate::top::16","title":"Validate","section":"Генерация кода","path":"/docs/guide/cli/generator/examples/validate","headings":["Генерация кода"],"excerpt":"Генерация кода Если флаг --cfg не указан, по умолчанию используется файл easyp.yaml из текущего каталога:","content":"Генерация кода Если флаг --cfg не указан, по умолчанию используется файл easyp.yaml из текущего каталога:"},{"id":"cli/generator/examples/validate::top::17","title":"Validate","section":"Генерация кода","path":"/docs/guide/cli/generator/examples/validate","headings":["Генерация кода"],"excerpt":"Генерация кода Теперь у вас есть сгенерированный Go‑код с поддержкой валидации, и вы можете напрямую использовать его в проекте.","content":"Генерация кода Теперь у вас есть сгенерированный Go‑код с поддержкой валидации, и вы можете напрямую использовать его в проекте."},{"id":"cli/generator/generator::top::0","title":"Генератор","path":"/docs/guide/cli/generator/generator","headings":[],"excerpt":"EasyP включает мощный генератор, который упрощает процесс получения кода из proto‑файлов. Благодаря YAML‑конфигурациям работа становится гораздо более удобной и интуитивной по сравнению с прямым использованием команды pr","content":"EasyP включает мощный генератор, который упрощает процесс получения кода из proto‑файлов. Благодаря YAML‑конфигурациям работа становится гораздо более удобной и интуитивной по сравнению с прямым использованием команды protoc."},{"id":"cli/generator/generator::top::1","title":"Генератор","section":"Ключевые особенности генератора","path":"/docs/guide/cli/generator/generator","headings":["Ключевые особенности генератора"],"excerpt":"Ключевые особенности генератора **Упрощённая генерация кода**: - Генерация кода из proto через декларативную YAML‑конфигурацию. - Избавляет от необходимости писать длинные и сложные команды protoc.","content":"Ключевые особенности генератора **Упрощённая генерация кода**: - Генерация кода из proto через декларативную YAML‑конфигурацию. - Избавляет от необходимости писать длинные и сложные команды protoc."},{"id":"cli/generator/generator::top::2","title":"Генератор","section":"Ключевые особенности генератора","path":"/docs/guide/cli/generator/generator","headings":["Ключевые особенности генератора"],"excerpt":"Ключевые особенности генератора **Обёртка над protoc**: - EasyP выступает как удобный слой над protoc, предоставляя декларативный API. - Поддерживает все опции и плагины, доступные protoc.","content":"Ключевые особенности генератора **Обёртка над protoc**: - EasyP выступает как удобный слой над protoc, предоставляя декларативный API. - Поддерживает все опции и плагины, доступные protoc."},{"id":"cli/generator/generator::top::3","title":"Генератор","section":"Ключевые особенности генератора","path":"/docs/guide/cli/generator/generator","headings":["Ключевые особенности генератора"],"excerpt":"Ключевые особенности генератора **Гибкость и кастомизация**: - Используются те же параметры, что и у плагинов protoc, прямо в конфиге. - Поддерживается множество плагинов и их параметры в одной конфигурации.","content":"Ключевые особенности генератора **Гибкость и кастомизация**: - Используются те же параметры, что и у плагинов protoc, прямо в конфиге. - Поддерживается множество плагинов и их параметры в одной конфигурации."},{"id":"cli/generator/generator::top::4","title":"Генератор","section":"Ключевые особенности генератора","path":"/docs/guide/cli/generator/generator","headings":["Ключевые особенности генератора"],"excerpt":"Ключевые особенности генератора **Генерация из нескольких источников**: - Локальные директории и удалённые Git‑репозитории одновременно. - Лёгкая интеграция с существующими проектами и репозиториями.","content":"Ключевые особенности генератора **Генерация из нескольких источников**: - Локальные директории и удалённые Git‑репозитории одновременно. - Лёгкая интеграция с существующими проектами и репозиториями."},{"id":"cli/generator/generator::top::5","title":"Генератор","section":"Ключевые особенности генератора","path":"/docs/guide/cli/generator/generator","headings":["Ключевые особенности генератора"],"excerpt":"Ключевые особенности генератора **Удалённая генерация**: - Генерация из удалённых Git репозиториев без локального checkout.","content":"Ключевые особенности генератора **Удалённая генерация**: - Генерация из удалённых Git репозиториев без локального checkout."},{"id":"cli/generator/generator::top::6","title":"Генератор","section":"Ключевые особенности генератора","path":"/docs/guide/cli/generator/generator","headings":["Ключевые особенности генератора"],"excerpt":"Ключевые особенности генератора **Интеграция с менеджером пакетов**: - Прозрачная работа с зависимостями через пакетный менеджер EasyP. - Автоматическое разрешение и подключение proto‑зависимостей.","content":"Ключевые особенности генератора **Интеграция с менеджером пакетов**: - Прозрачная работа с зависимостями через пакетный менеджер EasyP. - Автоматическое разрешение и подключение proto‑зависимостей."},{"id":"cli/generator/generator::complete-configuration-example::7","title":"Генератор","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":"Генератор","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":"Генератор","section":"Complete Configuration Example","path":"/docs/guide/cli/generator/generator#complete-configuration-example","headings":["Complete Configuration Example"],"excerpt":"Complete Configuration Example Managed mode - автоматическая установка file и field опций managed: enabled: true disable: - module: github.com/googleapis/googleapis # Отключить для конкретного модуля override: - file_opt","content":"Complete Configuration Example Managed mode - автоматическая установка file и field опций managed: enabled: true disable: - module: github.com/googleapis/googleapis # Отключить для конкретного модуля 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/ # Применить к конкретному пути"},{"id":"cli/generator/generator::complete-configuration-example::10","title":"Генератор","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":"Генератор","section":"Локальный ввод (Local Directory Input)","path":"/docs/guide/cli/generator/generator#local-directory-input","headings":["Локальный ввод (Local Directory Input)"],"excerpt":"Локальный ввод (Local Directory Input) Локальная директория — самый распространённый и простой способ указать откуда брать proto для генерации. Используйте этот вариант, если файлы уже находятся в репозитории проекта.","content":"Локальный ввод (Local Directory Input) Локальная директория — самый распространённый и простой способ указать откуда брать proto для генерации. Используйте этот вариант, если файлы уже находятся в репозитории проекта."},{"id":"cli/generator/generator::local-directory-input::12","title":"Генератор","section":"Локальный ввод (Local Directory Input)","path":"/docs/guide/cli/generator/generator#local-directory-input","headings":["Локальный ввод (Local Directory Input)"],"excerpt":"Локальный ввод (Local Directory Input) **Когда применять:** Proto файлы находятся в кодовой базе проекта Нужен полный контроль над структурой каталогов Проект — один сервис или приложение Файлы меняются не слишком часто","content":"Локальный ввод (Local Directory Input) **Когда применять:** Proto файлы находятся в кодовой базе проекта Нужен полный контроль над структурой каталогов Проект — один сервис или приложение Файлы меняются не слишком часто"},{"id":"cli/generator/generator::local-directory-input::13","title":"Генератор","section":"Локальный ввод (Local Directory Input)","path":"/docs/guide/cli/generator/generator#local-directory-input","headings":["Локальный ввод (Local Directory Input)"],"excerpt":"Локальный ввод (Local Directory Input)","content":"Локальный ввод (Local Directory Input)"},{"id":"cli/generator/generator::local-directory-input::14","title":"Генератор","section":"Локальный ввод (Local Directory Input)","path":"/docs/guide/cli/generator/generator#local-directory-input","headings":["Локальный ввод (Local Directory Input)"],"excerpt":"Локальный ввод (Local Directory Input) Параметр root особенно полезен в монорепозиториях: он позволяет управлять тем, откуда будут резолвиться пути импортов. Если указать родительскую директорию, импорты будут оцениватьс","content":"Локальный ввод (Local Directory Input) Параметр root особенно полезен в монорепозиториях: он позволяет управлять тем, откуда будут резолвиться пути импортов. Если указать родительскую директорию, импорты будут оцениваться относительно неё, а не текущего рабочего каталога."},{"id":"cli/generator/generator::local-directory-input::15","title":"Генератор","section":"Локальный ввод (Local Directory Input)","path":"/docs/guide/cli/generator/generator#local-directory-input","headings":["Локальный ввод (Local Directory Input)"],"excerpt":"Локальный ввод (Local Directory Input) **Параметры:**","content":"Локальный ввод (Local Directory Input) **Параметры:**"},{"id":"cli/generator/generator::local-directory-input::16","title":"Генератор","section":"Локальный ввод (Local Directory Input)","path":"/docs/guide/cli/generator/generator#local-directory-input","headings":["Локальный ввод (Local Directory Input)"],"excerpt":"Локальный ввод (Local Directory Input) Параметр Тип Обязателен Значение по умолчанию Описание ---------- ----- ------------ ----------------------- ---------- path string ✅ - Каталог, содержащий proto файлы root string ❌","content":"Локальный ввод (Local Directory Input) Параметр Тип Обязателен Значение по умолчанию Описание ---------- ----- ------------ ----------------------- ---------- path string ✅ - Каталог, содержащий proto файлы root string ❌ \".\" Корневая директория для разрешения import путей"},{"id":"cli/generator/generator::local-directory-input::17","title":"Генератор","section":"Локальный ввод (Local Directory Input)","path":"/docs/guide/cli/generator/generator#local-directory-input","headings":["Локальный ввод (Local Directory Input)"],"excerpt":"Локальный ввод (Local Directory Input) **Примеры:**","content":"Локальный ввод (Local Directory Input) **Примеры:**"},{"id":"cli/generator/generator::local-directory-input::18","title":"Генератор","section":"Локальный ввод (Local Directory Input)","path":"/docs/guide/cli/generator/generator#local-directory-input","headings":["Локальный ввод (Local Directory Input)"],"excerpt":"Локальный ввод (Local Directory Input) Ниже показана разница между базовым указанием директории и расширенной конфигурацией с пользовательским корнем импортов:","content":"Локальный ввод (Local Directory Input) Ниже показана разница между базовым указанием директории и расширенной конфигурацией с пользовательским корнем импортов:"},{"id":"cli/generator/generator::local-directory-input::19","title":"Генератор","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::20","title":"Генератор","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::git-remote-git-repository-input::21","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) Этот тип входных данных позволяет генерировать код из proto‑файлов, находящихся в удалённых репозиториях, без локального checkout. Особенно полезно при использовани","content":"Удалённый Git репозиторий (Remote Git Repository Input) Этот тип входных данных позволяет генерировать код из proto‑файлов, находящихся в удалённых репозиториях, без локального checkout. Особенно полезно при использовании API других команд или внешних поставщиков."},{"id":"cli/generator/generator::git-remote-git-repository-input::22","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) **Когда использовать:** Потребление proto определений из других сервисов/команд Интеграция с внешними вендорскими API Работа с общими библиотеками proto в нескольки","content":"Удалённый Git репозиторий (Remote Git Repository Input) **Когда использовать:** Потребление proto определений из других сервисов/команд Интеграция с внешними вендорскими API Работа с общими библиотеками proto в нескольких проектах Необходимо гарантировать корректную (зафиксированную) версию внешних API"},{"id":"cli/generator/generator::git-remote-git-repository-input::23","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) **Рекомендации:** В продакшене всегда фиксируйте версии (@v1.0.0, а не latest) Используйте семантические версии при наличии — проще сопровождать Предпочитайте публи","content":"Удалённый Git репозиторий (Remote Git Repository Input) **Рекомендации:** В продакшене всегда фиксируйте версии (@v1.0.0, а не latest) Используйте семантические версии при наличии — проще сопровождать Предпочитайте публичные теги вместо хеша коммита (лучше отслеживаемость)"},{"id":"cli/generator/generator::git-remote-git-repository-input::24","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input)","content":"Удалённый Git репозиторий (Remote Git Repository Input)"},{"id":"cli/generator/generator::git-remote-git-repository-input::25","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) Параметр root задаёт корень для разрешения импортов файлов из этого репозитория.","content":"Удалённый Git репозиторий (Remote Git Repository Input) Параметр root задаёт корень для разрешения импортов файлов из этого репозитория."},{"id":"cli/generator/generator::git-remote-git-repository-input::26","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) **Параметры:**","content":"Удалённый Git репозиторий (Remote Git Repository Input) **Параметры:**"},{"id":"cli/generator/generator::git-remote-git-repository-input::27","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) Параметр Тип Обязателен По умолчанию Описание ---------- ----- ------------ -------------- ---------- url string ✅ - URL Git репозитория с необязательной версией / ","content":"Удалённый Git репозиторий (Remote Git Repository Input) Параметр Тип Обязателен По умолчанию Описание ---------- ----- ------------ -------------- ---------- url string ✅ - URL Git репозитория с необязательной версией / тегом / коммитом sub_directory string ❌ \"\" Поддиректория внутри репозитория, где лежат proto root string ❌ \"\" Корневой путь для разрешения импортов"},{"id":"cli/generator/generator::git-remote-git-repository-input::28","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) **Варианты формата URL:**","content":"Удалённый Git репозиторий (Remote Git Repository Input) **Варианты формата URL:**"},{"id":"cli/generator/generator::git-remote-git-repository-input::29","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) EasyP поддерживает несколько форматов для ссылки на удалённые репозитории. Каждый подходит под разные требования по стабильности:","content":"Удалённый Git репозиторий (Remote Git Repository Input) EasyP поддерживает несколько форматов для ссылки на удалённые репозитории. Каждый подходит под разные требования по стабильности:"},{"id":"cli/generator/generator::git-remote-git-repository-input::30","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) **Tagged versions** — для продакшена, стабильные неизменяемые ссылки **Semantic versions** — читаемость и управление зависимостями **Commit hashes** — доступ к конк","content":"Удалённый Git репозиторий (Remote Git Repository Input) **Tagged versions** — для продакшена, стабильные неизменяемые ссылки **Semantic versions** — читаемость и управление зависимостями **Commit hashes** — доступ к конкретному коммиту, если нет тега **Latest** — только для разработки, непредсказуемо **Full HTTPS URLs** — приватные репозитории или нестандартный хостинг"},{"id":"cli/generator/generator::git-remote-git-repository-input::31","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) ```yaml Тег — стабильно для продакшена url: \"github.com/googleapis/googleapis@common-protos-1_3_1\"","content":"Удалённый Git репозиторий (Remote Git Repository Input) ```yaml Тег — стабильно для продакшена url: \"github.com/googleapis/googleapis@common-protos-1_3_1\""},{"id":"cli/generator/generator::git-remote-git-repository-input::32","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) Семантическая версия url: \"github.com/grpc-ecosystem/grpc-gateway@v2.19.1\"","content":"Удалённый Git репозиторий (Remote Git Repository Input) Семантическая версия url: \"github.com/grpc-ecosystem/grpc-gateway@v2.19.1\""},{"id":"cli/generator/generator::git-remote-git-repository-input::33","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) Хеш коммита — точечный фикс url: \"github.com/company/protos@abc123def456\"","content":"Удалённый Git репозиторий (Remote Git Repository Input) Хеш коммита — точечный фикс url: \"github.com/company/protos@abc123def456\""},{"id":"cli/generator/generator::git-remote-git-repository-input::34","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) Latest — только dev, НЕ для продакшена url: \"github.com/company/protos\"","content":"Удалённый Git репозиторий (Remote Git Repository Input) Latest — только dev, НЕ для продакшена url: \"github.com/company/protos\""},{"id":"cli/generator/generator::git-remote-git-repository-input::35","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) Полный HTTPS URL — приватный или кастомный Git url: \"https://github.com/company/private-protos.git\" ```","content":"Удалённый Git репозиторий (Remote Git Repository Input) Полный HTTPS URL — приватный или кастомный Git url: \"https://github.com/company/private-protos.git\" ```"},{"id":"cli/generator/generator::git-remote-git-repository-input::36","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) **Примеры:**","content":"Удалённый Git репозиторий (Remote Git Repository Input) **Примеры:**"},{"id":"cli/generator/generator::git-remote-git-repository-input::37","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) Ниже паттерны использования удалённых источников в разных сценариях:","content":"Удалённый Git репозиторий (Remote Git Repository Input) Ниже паттерны использования удалённых источников в разных сценариях:"},{"id":"cli/generator/generator::git-remote-git-repository-input::38","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input)","content":"Удалённый Git репозиторий (Remote Git Repository Input)"},{"id":"cli/generator/generator::top::39","title":"Генератор","section":"Конфигурация плагинов","path":"/docs/guide/cli/generator/generator","headings":["Конфигурация плагинов"],"excerpt":"Конфигурация плагинов Конфигурация плагинов определяет какие генераторы кода будут запущены и как они себя ведут. EasyP поддерживает любой плагин protoc, что делает его крайне гибким для разных языковых экосистем и сцена","content":"Конфигурация плагинов Конфигурация плагинов определяет какие генераторы кода будут запущены и как они себя ведут. EasyP поддерживает любой плагин protoc, что делает его крайне гибким для разных языковых экосистем и сценариев."},{"id":"cli/generator/generator::top::40","title":"Генератор","section":"Конфигурация плагинов","path":"/docs/guide/cli/generator/generator","headings":["Конфигурация плагинов"],"excerpt":"Конфигурация плагинов На верхнем уровне есть **четыре способа указать, как именно запускать плагин**:","content":"Конфигурация плагинов На верхнем уровне есть **четыре способа указать, как именно запускать плагин**:"},{"id":"cli/generator/generator::top::41","title":"Генератор","section":"Конфигурация плагинов","path":"/docs/guide/cli/generator/generator","headings":["Конфигурация плагинов"],"excerpt":"Конфигурация плагинов **name** – запуск плагина по имени из PATH или использование встроенного плагина. **path** – запуск плагина по абсолютному/относительному пути к исполняемому файлу. **remote** – удалённый плагин по ","content":"Конфигурация плагинов **name** – запуск плагина по имени из PATH или использование встроенного плагина. **path** – запуск плагина по абсолютному/относительному пути к исполняемому файлу. **remote** – удалённый плагин по URL (через remote‑executor EasyP). **command** – запуск плагина через произвольную команду (например, go run ...)."},{"id":"cli/generator/generator::top::42","title":"Генератор","section":"Конфигурация плагинов","path":"/docs/guide/cli/generator/generator","headings":["Конфигурация плагинов"],"excerpt":"Конфигурация плагинов Для каждого плагина должен быть указан **ровно один** из параметров name, path, remote или command.","content":"Конфигурация плагинов Для каждого плагина должен быть указан **ровно один** из параметров name, path, remote или command."},{"id":"cli/generator/generator::name::43","title":"Генератор","section":"Плагин по имени (name)","path":"/docs/guide/cli/generator/generator#name","headings":["Плагин по имени (name)"],"excerpt":"Плагин по имени (name) Локальный режим по имени — стандартный: плагины установлены в системе и запускаются напрямую через EasyP.","content":"Плагин по имени (name) Локальный режим по имени — стандартный: плагины установлены в системе и запускаются напрямую через EasyP."},{"id":"cli/generator/generator::name::44","title":"Генератор","section":"Плагин по имени (name)","path":"/docs/guide/cli/generator/generator#name","headings":["Плагин по имени (name)"],"excerpt":"Плагин по имени (name) **Когда использовать name:** Стандартные языки (Go, Python, TypeScript и т.д.) Есть контроль над окружением сборки Критична производительность (нет сетевых задержек) Хочется опираться на PATH или в","content":"Плагин по имени (name) **Когда использовать name:** Стандартные языки (Go, Python, TypeScript и т.д.) Есть контроль над окружением сборки Критична производительность (нет сетевых задержек) Хочется опираться на PATH или встроенные плагины"},{"id":"cli/generator/generator::name::45","title":"Генератор","section":"Плагин по имени (name)","path":"/docs/guide/cli/generator/generator#name","headings":["Плагин по имени (name)"],"excerpt":"Плагин по имени (name) **Требования к установке:** Плагины установлены и доступны в PATH (если не используются встроенные). Имена следуют шаблону protoc-gen-{name}. Установка через менеджеры пакетов (go install, npm inst","content":"Плагин по имени (name) **Требования к установке:** Плагины установлены и доступны в PATH (если не используются встроенные). Имена следуют шаблону protoc-gen-{name}. Установка через менеджеры пакетов (go install, npm install, pip install и т.п.)."},{"id":"cli/generator/generator::name::46","title":"Генератор","section":"Плагин по имени (name)","path":"/docs/guide/cli/generator/generator#name","headings":["Плагин по имени (name)"],"excerpt":"Плагин по имени (name) Параметр with_imports критичен при использовании зависимостей из пакетного менеджера: установите true, чтобы прототипы из секции deps попали в генерацию.","content":"Плагин по имени (name) Параметр with_imports критичен при использовании зависимостей из пакетного менеджера: установите true, чтобы прототипы из секции deps попали в генерацию."},{"id":"cli/generator/generator::path::47","title":"Генератор","section":"Плагин по пути (path)","path":"/docs/guide/cli/generator/generator#path","headings":["Плагин по пути (path)"],"excerpt":"Плагин по пути (path) Иногда нужно запускать плагин из конкретного бинарника, не добавляя его в PATH (например, бинарь в репозитории или в build‑директории). В этом случае можно указать явный путь:","content":"Плагин по пути (path) Иногда нужно запускать плагин из конкретного бинарника, не добавляя его в PATH (например, бинарь в репозитории или в build‑директории). В этом случае можно указать явный путь:"},{"id":"cli/generator/generator::path::48","title":"Генератор","section":"Плагин по пути (path)","path":"/docs/guide/cli/generator/generator#path","headings":["Плагин по пути (path)"],"excerpt":"Плагин по пути (path) **Когда использовать path:** Бинарники плагинов хранятся в репозитории (для воспроизводимых сборок). Используются несколько версий одного и того же плагина параллельно. Не хочется «загрязнять» глоба","content":"Плагин по пути (path) **Когда использовать path:** Бинарники плагинов хранятся в репозитории (для воспроизводимых сборок). Используются несколько версий одного и того же плагина параллельно. Не хочется «загрязнять» глобальный PATH."},{"id":"cli/generator/generator::remote::49","title":"Генератор","section":"Удалённый плагин (remote)","path":"/docs/guide/cli/generator/generator#remote","headings":["Удалённый плагин (remote)"],"excerpt":"Удалённый плагин (remote) Удалённые плагины выполняются по URL. EasyP отправляет на удалённую сторону CodeGeneratorRequest и получает обратно CodeGeneratorResponse.","content":"Удалённый плагин (remote) Удалённые плагины выполняются по URL. EasyP отправляет на удалённую сторону CodeGeneratorRequest и получает обратно CodeGeneratorResponse."},{"id":"cli/generator/generator::remote::50","title":"Генератор","section":"Удалённый плагин (remote)","path":"/docs/guide/cli/generator/generator#remote","headings":["Удалённый плагин (remote)"],"excerpt":"Удалённый плагин (remote) Ниже приведён реальный пример использования EasyP API Service как удалённого исполнителя плагинов (тот же формат используется в разделе про API Service):","content":"Удалённый плагин (remote) Ниже приведён реальный пример использования EasyP API Service как удалённого исполнителя плагинов (тот же формат используется в разделе про API Service):"},{"id":"cli/generator/generator::remote::51","title":"Генератор","section":"Удалённый плагин (remote)","path":"/docs/guide/cli/generator/generator#remote","headings":["Удалённый плагин (remote)"],"excerpt":"Удалённый плагин (remote) ```yaml generate: plugins: # Удалённое выполнение плагинов через EasyP API Service - remote: api.easyp.tech/protobuf/go:v1.36.10 out: . opts: paths: source_relative","content":"Удалённый плагин (remote) ```yaml generate: plugins: # Удалённое выполнение плагинов через EasyP API Service - remote: api.easyp.tech/protobuf/go:v1.36.10 out: . opts: paths: source_relative"},{"id":"cli/generator/generator::remote::52","title":"Генератор","section":"Удалённый плагин (remote)","path":"/docs/guide/cli/generator/generator#remote","headings":["Удалённый плагин (remote)"],"excerpt":"Удалённый плагин (remote) remote: api.easyp.tech/grpc/go:v1.5.1 out: . opts: paths: source_relative ```","content":"Удалённый плагин (remote) remote: api.easyp.tech/grpc/go:v1.5.1 out: . opts: paths: source_relative ```"},{"id":"cli/generator/generator::remote::53","title":"Генератор","section":"Удалённый плагин (remote)","path":"/docs/guide/cli/generator/generator#remote","headings":["Удалённый плагин (remote)"],"excerpt":"Удалённый плагин (remote) **Типичные сценарии для remote:** Централизованный сервис плагинов внутри компании (например, EasyP API Service). Запуск тяжёлых плагинов на выделенных машинах вместо CI‑агентов. Совместное испо","content":"Удалённый плагин (remote) **Типичные сценарии для remote:** Централизованный сервис плагинов внутри компании (например, EasyP API Service). Запуск тяжёлых плагинов на выделенных машинах вместо CI‑агентов. Совместное использование одной реализации плагина разными командами."},{"id":"cli/generator/generator::command::54","title":"Генератор","section":"Выполнение плагина через команду (command)","path":"/docs/guide/cli/generator/generator#command","headings":["Выполнение плагина через команду (command)"],"excerpt":"Выполнение плагина через команду (command) Вы можете указать плагин как массив команд для выполнения. Это полезно для запуска плагинов через go run или любые другие инструменты без предварительной установки бинарника пла","content":"Выполнение плагина через команду (command) Вы можете указать плагин как массив команд для выполнения. Это полезно для запуска плагинов через go run или любые другие инструменты без предварительной установки бинарника плагина:"},{"id":"cli/generator/generator::command::55","title":"Генератор","section":"Выполнение плагина через команду (command)","path":"/docs/guide/cli/generator/generator#command","headings":["Выполнение плагина через команду (command)"],"excerpt":"Выполнение плагина через команду (command)","content":"Выполнение плагина через команду (command)"},{"id":"cli/generator/generator::command::56","title":"Генератор","section":"Выполнение плагина через команду (command)","path":"/docs/guide/cli/generator/generator#command","headings":["Выполнение плагина через команду (command)"],"excerpt":"Выполнение плагина через команду (command) В этом режиме EasyP: **запускает указанную команду** как дочерний процесс; **пишет CodeGeneratorRequest в stdin** процесса; **читает CodeGeneratorResponse из stdout**, как и для","content":"Выполнение плагина через команду (command) В этом режиме EasyP: **запускает указанную команду** как дочерний процесс; **пишет CodeGeneratorRequest в stdin** процесса; **читает CodeGeneratorResponse из stdout**, как и для обычных плагинов protoc."},{"id":"cli/generator/generator::command::57","title":"Генератор","section":"Выполнение плагина через команду (command)","path":"/docs/guide/cli/generator/generator#command","headings":["Выполнение плагина через команду (command)"],"excerpt":"Выполнение плагина через команду (command) **Приоритет источников плагина:** command — выполнение через указанную команду (наивысший приоритет) remote — удалённый плагин через URL name — локальный плагин из PATH или встр","content":"Выполнение плагина через команду (command) **Приоритет источников плагина:** command — выполнение через указанную команду (наивысший приоритет) remote — удалённый плагин через URL name — локальный плагин из PATH или встроенный плагин path — путь к исполняемому файлу плагина"},{"id":"cli/generator/generator::command::58","title":"Генератор","section":"Выполнение плагина через команду (command)","path":"/docs/guide/cli/generator/generator#command","headings":["Выполнение плагина через команду (command)"],"excerpt":"Выполнение плагина через команду (command) **Параметры (источники и общие опции плагина):**","content":"Выполнение плагина через команду (command) **Параметры (источники и общие опции плагина):**"},{"id":"cli/generator/generator::command::59","title":"Генератор","section":"Выполнение плагина через команду (command)","path":"/docs/guide/cli/generator/generator#command","headings":["Выполнение плагина через команду (command)"],"excerpt":"Выполнение плагина через команду (command) Параметр Тип Обязателен По умолчанию Описание ---------- ----- ------------ -------------- ---------- name string ❌ - Имя / идентификатор плагина (например, go, go-grpc, grpc-ga","content":"Выполнение плагина через команду (command) Параметр Тип Обязателен По умолчанию Описание ---------- ----- ------------ -------------- ---------- name string ❌ - Имя / идентификатор плагина (например, go, go-grpc, grpc-gateway) command []string ❌ - Команда для выполнения плагина (например, [\"go\", \"run\", \"package\"]) remote string ❌ - URL удалённого плагина path string ❌ - Путь к исполняемому файлу плагина out string ✅ - Директория для сгенерированных файлов opts mapstring ❌ {} Специфичные опции плагина; значения-списки передаются как повторяющиеся key=value with_imports bool ❌ false Включать proto из зависимостей"},{"id":"cli/generator/generator::command::60","title":"Генератор","section":"Выполнение плагина через команду (command)","path":"/docs/guide/cli/generator/generator#command","headings":["Выполнение плагина через команду (command)"],"excerpt":"Выполнение плагина через команду (command) **Примечание:** Для каждого плагина должен быть указан ровно один источник (name, command, remote или path). Если opts.outputServices задан как [\"grpc-js\", \"generic-definitions\"","content":"Выполнение плагина через команду (command) **Примечание:** Для каждого плагина должен быть указан ровно один источник (name, command, remote или path). Если opts.outputServices задан как [\"grpc-js\", \"generic-definitions\"], EasyP передаст outputServices=grpc-js,outputServices=generic-definitions."},{"id":"cli/generator/generator::command::61","title":"Генератор","section":"Выполнение плагина через команду (command)","path":"/docs/guide/cli/generator/generator#command","headings":["Выполнение плагина через команду (command)"],"excerpt":"Выполнение плагина через команду (command) **Примеры использования источника command:**","content":"Выполнение плагина через команду (command) **Примеры использования источника command:**"},{"id":"cli/generator/generator::command::62","title":"Генератор","section":"Выполнение плагина через команду (command)","path":"/docs/guide/cli/generator/generator#command","headings":["Выполнение плагина через команду (command)"],"excerpt":"Выполнение плагина через команду (command) ```yaml generate: inputs: - directory: \"proto\"","content":"Выполнение плагина через команду (command) ```yaml generate: inputs: - directory: \"proto\""},{"id":"cli/generator/generator::command::63","title":"Генератор","section":"Выполнение плагина через команду (command)","path":"/docs/guide/cli/generator/generator#command","headings":["Выполнение плагина через команду (command)"],"excerpt":"Выполнение плагина через команду (command) plugins: # 1) gRPC-Gateway через go run (без предварительной установки бинарника) - command: [\"go\", \"run\", \"github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway@v2.","content":"Выполнение плагина через команду (command) plugins: # 1) gRPC-Gateway через go run (без предварительной установки бинарника) - 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::command::64","title":"Генератор","section":"Выполнение плагина через команду (command)","path":"/docs/guide/cli/generator/generator#command","headings":["Выполнение плагина через команду (command)"],"excerpt":"Выполнение плагина через команду (command) 2) protoc-gen-validate через go run - command: [\"go\", \"run\", \"github.com/bufbuild/protoc-gen-validate@v0.10.1\"] out: ./gen/go opts: paths: source_relative lang: go","content":"Выполнение плагина через команду (command) 2) protoc-gen-validate через 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::command::65","title":"Генератор","section":"Выполнение плагина через команду (command)","path":"/docs/guide/cli/generator/generator#command","headings":["Выполнение плагина через команду (command)"],"excerpt":"Выполнение плагина через команду (command) 3) Произвольный кастомный скрипт-обёртка - command: [\"bash\", \"./scripts/custom-protoc-plugin.sh\"] out: ./gen/custom opts: foo: bar ```","content":"Выполнение плагина через команду (command) 3) Произвольный кастомный скрипт-обёртка - command: [\"bash\", \"./scripts/custom-protoc-plugin.sh\"] out: ./gen/custom opts: foo: bar ```"},{"id":"cli/generator/generator::builtin-plugins::66","title":"Генератор","section":"Встроенные плагины (Builtin Plugins)","path":"/docs/guide/cli/generator/generator#builtin-plugins","headings":["Встроенные плагины (Builtin Plugins)"],"excerpt":"Встроенные плагины (Builtin Plugins) EasyP поддерживает встроенные плагины для базовых языков protobuf и gRPC. Эти плагины встроены в бинарник как WASM-модули и не требуют установки внешних зависимостей.","content":"Встроенные плагины (Builtin Plugins) EasyP поддерживает встроенные плагины для базовых языков protobuf и gRPC. Эти плагины встроены в бинарник как WASM-модули и не требуют установки внешних зависимостей."},{"id":"cli/generator/generator::builtin-plugins::67","title":"Генератор","section":"Встроенные плагины (Builtin Plugins)","path":"/docs/guide/cli/generator/generator#builtin-plugins","headings":["Встроенные плагины (Builtin Plugins)"],"excerpt":"Встроенные плагины (Builtin Plugins) **Преимущества встроенных плагинов:** **Портативность**: Один бинарник со всеми необходимыми плагинами **Удобство**: Не требуется установка внешних зависимостей **Стабильность**: Верс","content":"Встроенные плагины (Builtin Plugins) **Преимущества встроенных плагинов:** **Портативность**: Один бинарник со всеми необходимыми плагинами **Удобство**: Не требуется установка внешних зависимостей **Стабильность**: Версии плагинов зафиксированы в бинарнике **Изоляция**: Не зависит от системных установок плагинов"},{"id":"cli/generator/generator::builtin-plugins::68","title":"Генератор","section":"Встроенные плагины (Builtin Plugins)","path":"/docs/guide/cli/generator/generator#builtin-plugins","headings":["Встроенные плагины (Builtin Plugins)"],"excerpt":"Встроенные плагины (Builtin Plugins) **Поддерживаемые встроенные плагины:**","content":"Встроенные плагины (Builtin Plugins) **Поддерживаемые встроенные плагины:**"},{"id":"cli/generator/generator::protobuf::69","title":"Генератор","section":"Protobuf базовые плагины","path":"/docs/guide/cli/generator/generator#protobuf","headings":["Protobuf базовые плагины"],"excerpt":"Protobuf базовые плагины Следующие плагины встроены для генерации базового protobuf кода:","content":"Protobuf базовые плагины Следующие плагины встроены для генерации базового protobuf кода:"},{"id":"cli/generator/generator::protobuf::70","title":"Генератор","section":"Protobuf базовые плагины","path":"/docs/guide/cli/generator/generator#protobuf","headings":["Protobuf базовые плагины"],"excerpt":"Protobuf базовые плагины Имя плагина Описание Соответствующий protoc плагин ------------- ---------- ------------------------------- cpp Генерация C++ кода из proto файлов protoc-gen-cpp csharp Генерация C# кода из proto","content":"Protobuf базовые плагины Имя плагина Описание Соответствующий protoc плагин ------------- ---------- ------------------------------- cpp Генерация C++ кода из proto файлов protoc-gen-cpp csharp Генерация C# кода из proto файлов protoc-gen-csharp java Генерация Java кода из proto файлов protoc-gen-java kotlin Генерация Kotlin кода из proto файлов protoc-gen-kotlin objc Генерация Objective-C кода из proto файлов protoc-gen-objc php Генерация PHP кода из proto файлов protoc-gen-php python Генерация Python кода из proto файлов protoc-gen-python ruby Генерация Ruby кода из proto файлов protoc-gen-ruby"},{"id":"cli/generator/generator::grpc::71","title":"Генератор","section":"gRPC плагины","path":"/docs/guide/cli/generator/generator#grpc","headings":["gRPC плагины"],"excerpt":"gRPC плагины Следующие плагины встроены для генерации gRPC кода:","content":"gRPC плагины Следующие плагины встроены для генерации gRPC кода:"},{"id":"cli/generator/generator::grpc::72","title":"Генератор","section":"gRPC плагины","path":"/docs/guide/cli/generator/generator#grpc","headings":["gRPC плагины"],"excerpt":"gRPC плагины Имя плагина Описание Соответствующий protoc плагин ------------- ---------- ------------------------------- grpc_cpp Генерация gRPC кода для C++ grpc_cpp_plugin grpc_csharp Генерация gRPC кода для C# grpc_cs","content":"gRPC плагины Имя плагина Описание Соответствующий protoc плагин ------------- ---------- ------------------------------- grpc_cpp Генерация gRPC кода для C++ grpc_cpp_plugin grpc_csharp Генерация gRPC кода для C# grpc_csharp_plugin grpc_java Генерация gRPC кода для Java grpc_java_plugin grpc_node Генерация gRPC кода для Node.js grpc_node_plugin grpc_objc Генерация gRPC кода для Objective-C grpc_objective_c_plugin grpc_php Генерация gRPC кода для PHP grpc_php_plugin grpc_python Генерация gRPC кода для Python grpc_python_plugin grpc_ruby Генерация gRPC кода для Ruby grpc_ruby_plugin"},{"id":"cli/generator/generator::grpc::73","title":"Генератор","section":"gRPC плагины","path":"/docs/guide/cli/generator/generator#grpc","headings":["gRPC плагины"],"excerpt":"gRPC плагины **Логика выбора плагина:**","content":"gRPC плагины **Логика выбора плагина:**"},{"id":"cli/generator/generator::grpc::74","title":"Генератор","section":"gRPC плагины","path":"/docs/guide/cli/generator/generator#grpc","headings":["gRPC плагины"],"excerpt":"gRPC плагины EasyP использует следующий приоритет при выборе executor'а для плагина:","content":"gRPC плагины EasyP использует следующий приоритет при выборе executor'а для плагина:"},{"id":"cli/generator/generator::grpc::75","title":"Генератор","section":"gRPC плагины","path":"/docs/guide/cli/generator/generator#grpc","headings":["gRPC плагины"],"excerpt":"gRPC плагины **Удалённый плагин** (если указан url) — всегда имеет наивысший приоритет **Встроенный плагин** (если плагин встроен и не найден в PATH) — используется автоматически **Локальный плагин** (из PATH) — использу","content":"gRPC плагины **Удалённый плагин** (если указан url) — всегда имеет наивысший приоритет **Встроенный плагин** (если плагин встроен и не найден в PATH) — используется автоматически **Локальный плагин** (из PATH) — используется по умолчанию для обратной совместимости"},{"id":"cli/generator/generator::grpc::76","title":"Генератор","section":"gRPC плагины","path":"/docs/guide/cli/generator/generator#grpc","headings":["gRPC плагины"],"excerpt":"gRPC плагины **Пример использования:**","content":"gRPC плагины **Пример использования:**"},{"id":"cli/generator/generator::grpc::77","title":"Генератор","section":"gRPC плагины","path":"/docs/guide/cli/generator/generator#grpc","headings":["gRPC плагины"],"excerpt":"gRPC плагины Встроенные плагины включены в бинарник EasyP:","content":"gRPC плагины Встроенные плагины включены в бинарник EasyP:"},{"id":"cli/generator/generator::grpc::78","title":"Генератор","section":"gRPC плагины","path":"/docs/guide/cli/generator/generator#grpc","headings":["gRPC плагины"],"excerpt":"gRPC плагины ```bash Сборка go build ./cmd/easyp","content":"gRPC плагины ```bash Сборка go build ./cmd/easyp"},{"id":"cli/generator/generator::grpc::79","title":"Генератор","section":"gRPC плагины","path":"/docs/guide/cli/generator/generator#grpc","headings":["gRPC плагины"],"excerpt":"gRPC плагины Установка go install github.com/easyp-tech/easyp/cmd/easyp@latest ```","content":"gRPC плагины Установка go install github.com/easyp-tech/easyp/cmd/easyp@latest ```"},{"id":"cli/generator/generator::grpc::80","title":"Генератор","section":"gRPC плагины","path":"/docs/guide/cli/generator/generator#grpc","headings":["gRPC плагины"],"excerpt":"gRPC плагины **Обратная совместимость:**","content":"gRPC плагины **Обратная совместимость:**"},{"id":"cli/generator/generator::grpc::81","title":"Генератор","section":"gRPC плагины","path":"/docs/guide/cli/generator/generator#grpc","headings":["gRPC плагины"],"excerpt":"gRPC плагины Встроенные плагины полностью совместимы с существующими конфигурациями. Если плагин найден в PATH, он будет использован вместо встроенного. Это гарантирует, что:","content":"gRPC плагины Встроенные плагины полностью совместимы с существующими конфигурациями. Если плагин найден в PATH, он будет использован вместо встроенного. Это гарантирует, что:"},{"id":"cli/generator/generator::grpc::82","title":"Генератор","section":"gRPC плагины","path":"/docs/guide/cli/generator/generator#grpc","headings":["gRPC плагины"],"excerpt":"gRPC плагины Существующие конфигурации продолжают работать без изменений Можно переопределить встроенный плагин, установив его в системе Приоритет отдаётся локальным установкам для гибкости","content":"gRPC плагины Существующие конфигурации продолжают работать без изменений Можно переопределить встроенный плагин, установив его в системе Приоритет отдаётся локальным установкам для гибкости"},{"id":"cli/generator/generator::top::83","title":"Генератор","section":"Справочник опций плагинов","path":"/docs/guide/cli/generator/generator","headings":["Справочник опций плагинов"],"excerpt":"Справочник опций плагинов Ниже перечислены наиболее часто используемые плагины и их настройки. Каждый плагин имеет параметры, влияющие на результат генерации — понимание этих опций важно для получения нужного вывода.","content":"Справочник опций плагинов Ниже перечислены наиболее часто используемые плагины и их настройки. Каждый плагин имеет параметры, влияющие на результат генерации — понимание этих опций важно для получения нужного вывода."},{"id":"cli/generator/generator::go-plugins::84","title":"Генератор","section":"Go Plugins","path":"/docs/guide/cli/generator/generator#go-plugins","headings":["Go Plugins"],"excerpt":"Go Plugins Плагины для Go — самые зрелые и распространённые. Опция paths управляет тем, как формируются пути импортов; остальные опции дают тонкую настройку вывода.","content":"Go Plugins Плагины для Go — самые зрелые и распространённые. Опция paths управляет тем, как формируются пути импортов; остальные опции дают тонкую настройку вывода."},{"id":"cli/generator/generator::grpc-gateway-plugins::85","title":"Генератор","section":"gRPC-Gateway Plugins","path":"/docs/guide/cli/generator/generator#grpc-gateway-plugins","headings":["gRPC-Gateway Plugins"],"excerpt":"gRPC-Gateway Plugins Позволяют экспонировать gRPC сервисы как REST API и генерировать OpenAPI. Критично для HTTP/JSON поверх gRPC.","content":"gRPC-Gateway Plugins Позволяют экспонировать gRPC сервисы как REST API и генерировать OpenAPI. Критично для HTTP/JSON поверх gRPC."},{"id":"cli/generator/generator::validation-plugins::86","title":"Генератор","section":"Validation Plugins","path":"/docs/guide/cli/generator/generator#validation-plugins","headings":["Validation Plugins"],"excerpt":"Validation Plugins Генерируют код валидации на основе правил в proto, устраняя ручную проверку.","content":"Validation Plugins Генерируют код валидации на основе правил в proto, устраняя ручную проверку."},{"id":"cli/generator/generator::typescriptjavascript-plugins::87","title":"Генератор","section":"TypeScript/JavaScript Plugins","path":"/docs/guide/cli/generator/generator#typescriptjavascript-plugins","headings":["TypeScript/JavaScript Plugins"],"excerpt":"TypeScript/JavaScript Plugins TypeScript плагины нужны фронтенду: типобезопасные интерфейсы и клиенты.","content":"TypeScript/JavaScript Plugins TypeScript плагины нужны фронтенду: типобезопасные интерфейсы и клиенты."},{"id":"cli/generator/generator::managed-mode::88","title":"Генератор","section":"Managed Mode","path":"/docs/guide/cli/generator/generator#managed-mode","headings":["Managed Mode"],"excerpt":"Managed Mode Managed mode автоматически устанавливает file и field опции в protobuf дескрипторах во время генерации кода без изменения исходных .proto файлов. Эта функция совместима с managed mode в buf и обеспечивает ед","content":"Managed Mode Managed mode автоматически устанавливает file и field опции в protobuf дескрипторах во время генерации кода без изменения исходных .proto файлов. Эта функция совместима с managed mode в buf и обеспечивает единообразный способ управления языково-специфичными опциями в вашей кодовой базе."},{"id":"cli/generator/generator::managed-mode::89","title":"Генератор","section":"Managed Mode","path":"/docs/guide/cli/generator/generator#managed-mode","headings":["Managed Mode"],"excerpt":"Managed Mode **Ключевые преимущества:** **Без изменений proto файлов**: Опции применяются во время генерации, proto файлы остаются чистыми **Согласованные значения по умолчанию**: Автоматическое применение языковых согла","content":"Managed Mode **Ключевые преимущества:** **Без изменений proto файлов**: Опции применяются во время генерации, proto файлы остаются чистыми **Согласованные значения по умолчанию**: Автоматическое применение языковых соглашений об именовании **Централизованная конфигурация**: Управление всеми опциями в одном месте (easyp.yaml) **Правила для модулей**: Применение разных опций к разным модулям или путям **Совместимость с buf**: Работает так же, как managed mode в buf"},{"id":"cli/generator/generator::top::90","title":"Генератор","section":"Как это работает","path":"/docs/guide/cli/generator/generator","headings":["Как это работает"],"excerpt":"Как это работает Когда managed mode включён, EasyP автоматически применяет file и field опции к protobuf дескрипторам перед генерацией кода. Это происходит в памяти, поэтому исходные .proto файлы остаются неизменными.","content":"Как это работает Когда managed mode включён, EasyP автоматически применяет file и field опции к protobuf дескрипторам перед генерацией кода. Это происходит в памяти, поэтому исходные .proto файлы остаются неизменными."},{"id":"cli/generator/generator::top::91","title":"Генератор","section":"Как это работает","path":"/docs/guide/cli/generator/generator","headings":["Как это работает"],"excerpt":"Как это работает **Значения по умолчанию** применяются для определённых опций на основе языковых соглашений: Java: java_package_prefix по умолчанию \"com\", java_multiple_files по умолчанию true C#: csharp_namespace по умо","content":"Как это работает **Значения по умолчанию** применяются для определённых опций на основе языковых соглашений: Java: java_package_prefix по умолчанию \"com\", java_multiple_files по умолчанию true C#: csharp_namespace по умолчанию PascalCase имени пакета Ruby: ruby_package по умолчанию PascalCase с разделителем :: PHP: php_namespace по умолчанию PascalCase с разделителем \\ Objective-C: objc_class_prefix по умолчанию первые буквы частей пакета C++: cc_enable_arenas по умолчанию true"},{"id":"cli/generator/generator::top::92","title":"Генератор","section":"Как это работает","path":"/docs/guide/cli/generator/generator","headings":["Как это работает"],"excerpt":"Как это работает **Overrides** позволяют установить конкретные значения для опций с поддержкой фильтрации по модулю, пути или полю. Если не указаны module и path, override применяется ко всем файлам в запросе генерации, ","content":"Как это работает **Overrides** позволяют установить конкретные значения для опций с поддержкой фильтрации по модулю, пути или полю. Если не указаны module и path, override применяется ко всем файлам в запросе генерации, включая зависимости и git_repo inputs."},{"id":"cli/generator/generator::top::93","title":"Генератор","section":"Как это работает","path":"/docs/guide/cli/generator/generator","headings":["Как это работает"],"excerpt":"Как это работает **Disables** позволяют предотвратить изменение managed mode определённых опций или файлов. Это рекомендуемый способ исключить внешние зависимости, у которых свои опции уже заданы.","content":"Как это работает **Disables** позволяют предотвратить изменение managed mode определённых опций или файлов. Это рекомендуемый способ исключить внешние зависимости, у которых свои опции уже заданы."},{"id":"cli/generator/generator::file-options::94","title":"Генератор","section":"Поддерживаемые File Options","path":"/docs/guide/cli/generator/generator#file-options","headings":["Поддерживаемые File Options"],"excerpt":"Поддерживаемые File Options Опция Описание Есть значение по умолчанию? ------- ---------- ---------------------------- go_package Go import path ❌ go_package_prefix Префикс для Go import paths ❌ java_package Имя Java пак","content":"Поддерживаемые File Options Опция Описание Есть значение по умолчанию? ------- ---------- ---------------------------- go_package Go import path ❌ go_package_prefix Префикс для Go import paths ❌ java_package Имя Java пакета ❌ java_package_prefix Префикс для Java пакетов ✅ (\"com\") java_package_suffix Суффикс для Java пакетов ❌ java_multiple_files Генерировать несколько Java файлов ✅ (true) java_outer_classname Имя внешнего класса ✅ (PascalCase + \"Proto\") java_string_check_utf8 UTF-8 валидация ❌ csharp_namespace C# namespace ✅ (PascalCase) csharp_namespace_prefix Префикс для C# namespaces ❌ ruby_package Имя Ruby модуля ✅ (PascalCase с ::) ruby_package_suffix Суффикс для Ruby пакетов ❌ php_namespace PHP namespace ✅ (PascalCase с \\) php_metadata_namespace PHP metadata namespace ❌ php_metadata_namespace_suffix Суффикс для PHP metadata ❌ objc_class_prefix Objective-C префикс класса ✅ (Первые буквы) swift_prefix Swift префикс ❌ optimize_for Оптимизация генерации кода ❌ cc_enable_arenas C++ arena аллокация ✅ (true)"},{"id":"cli/generator/generator::field-options::95","title":"Генератор","section":"Поддерживаемые Field Options","path":"/docs/guide/cli/generator/generator#field-options","headings":["Поддерживаемые Field Options"],"excerpt":"Поддерживаемые Field Options Опция Описание Применяется к ------- ---------- --------------- jstype JavaScript тип для 64-битных целых чисел int64, uint64, sint64, fixed64, sfixed64","content":"Поддерживаемые Field Options Опция Описание Применяется к ------- ---------- --------------- jstype JavaScript тип для 64-битных целых чисел int64, uint64, sint64, fixed64, sfixed64"},{"id":"cli/generator/generator::top::96","title":"Генератор","section":"Базовая настройка со значениями по умолчанию","path":"/docs/guide/cli/generator/generator","headings":["Базовая настройка со значениями по умолчанию"],"excerpt":"Базовая настройка со значениями по умолчанию Включите managed mode для получения автоматических значений по умолчанию для всех поддерживаемых языков:","content":"Базовая настройка со значениями по умолчанию Включите managed mode для получения автоматических значений по умолчанию для всех поддерживаемых языков:"},{"id":"cli/generator/generator::top::97","title":"Генератор","section":"Базовая настройка со значениями по умолчанию","path":"/docs/guide/cli/generator/generator","headings":["Базовая настройка со значениями по умолчанию"],"excerpt":"Базовая настройка со значениями по умолчанию","content":"Базовая настройка со значениями по умолчанию"},{"id":"cli/generator/generator::top::98","title":"Генератор","section":"Базовая настройка со значениями по умолчанию","path":"/docs/guide/cli/generator/generator","headings":["Базовая настройка со значениями по умолчанию"],"excerpt":"Базовая настройка со значениями по умолчанию Это автоматически установит: java_package в com. для всех файлов java_multiple_files в true csharp_namespace в PascalCase имени пакета ruby_package в PascalCase с разделителем","content":"Базовая настройка со значениями по умолчанию Это автоматически установит: java_package в com. для всех файлов java_multiple_files в true csharp_namespace в PascalCase имени пакета ruby_package в PascalCase с разделителем :: И многое другое..."},{"id":"cli/generator/generator::go::99","title":"Генератор","section":"Кастомный префикс Go пакета","path":"/docs/guide/cli/generator/generator#go","headings":["Кастомный префикс Go пакета"],"excerpt":"Кастомный префикс Go пакета Переопределите префикс Go пакета для вашего проекта:","content":"Кастомный префикс Go пакета Переопределите префикс Go пакета для вашего проекта:"},{"id":"cli/generator/generator::go::100","title":"Генератор","section":"Кастомный префикс Go пакета","path":"/docs/guide/cli/generator/generator#go","headings":["Кастомный префикс Go пакета"],"excerpt":"Кастомный префикс Go пакета Это установит go_package в github.com/mycompany/myproject/gen/go/ для всех файлов.","content":"Кастомный префикс Go пакета Это установит go_package в github.com/mycompany/myproject/gen/go/ для всех файлов."},{"id":"cli/generator/generator::go::101","title":"Генератор","section":"Динамические пути Go пакетов с маркерами","path":"/docs/guide/cli/generator/generator#go","headings":["Динамические пути Go пакетов с маркерами"],"excerpt":"Динамические пути Go пакетов с маркерами Для более сложной генерации путей можно использовать маркеры в значениях go_package_prefix или go_package:","content":"Динамические пути Go пакетов с маркерами Для более сложной генерации путей можно использовать маркеры в значениях go_package_prefix или go_package:"},{"id":"cli/generator/generator::go::102","title":"Генератор","section":"Динамические пути Go пакетов с маркерами","path":"/docs/guide/cli/generator/generator#go","headings":["Динамические пути Go пакетов с маркерами"],"excerpt":"Динамические пути Go пакетов с маркерами","content":"Динамические пути Go пакетов с маркерами"},{"id":"cli/generator/generator::go::103","title":"Генератор","section":"Динамические пути Go пакетов с маркерами","path":"/docs/guide/cli/generator/generator#go","headings":["Динамические пути Go пакетов с маркерами"],"excerpt":"Динамические пути Go пакетов с маркерами **Доступные маркеры:** {{file_path}} - Полный путь файла без расширения .proto - Пример: internal/cms/as.proto → internal/cms/as {{file_dir}} - Только путь директории, без имени ф","content":"Динамические пути Go пакетов с маркерами **Доступные маркеры:** {{file_path}} - Полный путь файла без расширения .proto - Пример: internal/cms/as.proto → internal/cms/as {{file_dir}} - Только путь директории, без имени файла - Пример: internal/cms/as.proto → internal/cms {{file_dir_without:prefix/}} - Путь директории с удалением префикса и базового имени файла без суффиксов _service/_grpc - Пример: {{file_dir_without:internal/}} для internal/cms/as_service.proto → cms/as {{file_path_without:prefix/}} - Полный путь файла с удалением префикса - Пример: {{file_path_without:internal/}} для internal/cms/as.proto → cms/as"},{"id":"cli/generator/generator::top::104","title":"Генератор","section":"Переопределения для конкретных модулей","path":"/docs/guide/cli/generator/generator","headings":["Переопределения для конкретных модулей"],"excerpt":"Переопределения для конкретных модулей Примените разные опции к разным модулям:","content":"Переопределения для конкретных модулей Примените разные опции к разным модулям:"},{"id":"cli/generator/generator::top::105","title":"Генератор","section":"Переопределения для конкретных модулей","path":"/docs/guide/cli/generator/generator","headings":["Переопределения для конкретных модулей"],"excerpt":"Переопределения для конкретных модулей","content":"Переопределения для конкретных модулей"},{"id":"cli/generator/generator::top::106","title":"Генератор","section":"Переопределения для конкретных модулей","path":"/docs/guide/cli/generator/generator","headings":["Переопределения для конкретных модулей"],"excerpt":"Переопределения для конкретных модулей module должен точно совпадать с источником модуля в EasyP: это значение из deps или git_repo.url до @version (например, github.com/mycompany/internal-protos или https://github.com/m","content":"Переопределения для конкретных модулей module должен точно совпадать с источником модуля в EasyP: это значение из deps или git_repo.url до @version (например, github.com/mycompany/internal-protos или https://github.com/mycompany/internal-protos). Это не Go module path из go.mod."},{"id":"cli/generator/generator::top::107","title":"Генератор","section":"Отключение для внешних зависимостей","path":"/docs/guide/cli/generator/generator","headings":["Отключение для внешних зависимостей"],"excerpt":"Отключение для внешних зависимостей Отключите managed mode для внешних зависимостей, у которых уже установлены опции:","content":"Отключение для внешних зависимостей Отключите managed mode для внешних зависимостей, у которых уже установлены опции:"},{"id":"cli/generator/generator::top::108","title":"Генератор","section":"Отключение для внешних зависимостей","path":"/docs/guide/cli/generator/generator","headings":["Отключение для внешних зависимостей"],"excerpt":"Отключение для внешних зависимостей","content":"Отключение для внешних зависимостей"},{"id":"cli/generator/generator::javascript::109","title":"Генератор","section":"Типобезопасность JavaScript","path":"/docs/guide/cli/generator/generator#javascript","headings":["Типобезопасность JavaScript"],"excerpt":"Типобезопасность JavaScript Установите jstype в JS_STRING для всех 64-битных целочисленных полей, чтобы предотвратить потерю точности в JavaScript:","content":"Типобезопасность JavaScript Установите jstype в JS_STRING для всех 64-битных целочисленных полей, чтобы предотвратить потерю точности в JavaScript:"},{"id":"cli/generator/generator::top::110","title":"Генератор","section":"Совпадение путей","path":"/docs/guide/cli/generator/generator","headings":["Совпадение путей"],"excerpt":"Совпадение путей Совпадение путей в managed mode использует префиксное совпадение (как в buf):","content":"Совпадение путей Совпадение путей в managed mode использует префиксное совпадение (как в buf):"},{"id":"cli/generator/generator::top::111","title":"Генератор","section":"Совпадение путей","path":"/docs/guide/cli/generator/generator","headings":["Совпадение путей"],"excerpt":"Совпадение путей **Путь директории** (заканчивается на /): Совпадает со всеми файлами в этой директории и поддиректориях - Пример: path: \"internal/cms/\" совпадает с internal/cms/as.proto, internal/cms/node.proto, interna","content":"Совпадение путей **Путь директории** (заканчивается на /): Совпадает со всеми файлами в этой директории и поддиректориях - Пример: path: \"internal/cms/\" совпадает с internal/cms/as.proto, internal/cms/node.proto, internal/cms/v1/service.proto **Точный путь файла** (заканчивается на .proto): Совпадает только с этим конкретным файлом - Пример: path: \"internal/cms/as.proto\" совпадает только с internal/cms/as.proto **Префиксный путь** (без завершающего / или .proto): Использует префиксное совпадение (не директориально-осознанное) - Пример: path: \"internal/cms\" совпадает с internal/cms/as.proto, но также с internal/cmsv2/file.proto - **Совет**: Используйте префиксные пути для группировки нескольких файлов с одинаковым значением. Например, path: \"internal/cms/bmi\" совпадает и с internal/cms/bmi.proto, и с internal/cms/bmi_service.proto, что позволяет установить одно и то же значение go_package для обоих файлов одним правилом."},{"id":"cli/generator/generator::top::112","title":"Генератор","section":"Приоритет правил","path":"/docs/guide/cli/generator/generator","headings":["Приоритет правил"],"excerpt":"Приоритет правил Когда несколько правил соответствуют одному файлу или полю, применяется следующий приоритет:","content":"Приоритет правил Когда несколько правил соответствуют одному файлу или полю, применяется следующий приоритет:"},{"id":"cli/generator/generator::top::113","title":"Генератор","section":"Приоритет правил","path":"/docs/guide/cli/generator/generator","headings":["Приоритет правил"],"excerpt":"Приоритет правил **Disable правила** имеют приоритет — если опция отключена, она не будет применена **Override правила** применяются по порядку — последнее совпадающее правило побеждает **Значения по умолчанию** применяю","content":"Приоритет правил **Disable правила** имеют приоритет — если опция отключена, она не будет применена **Override правила** применяются по порядку — последнее совпадающее правило побеждает **Значения по умолчанию** применяются только если нет совпадающего override и опция не отключена"},{"id":"cli/generator/generator::buf::114","title":"Генератор","section":"Совместимость с buf","path":"/docs/guide/cli/generator/generator#buf","headings":["Совместимость с buf"],"excerpt":"Совместимость с buf Managed mode в EasyP совместим с managed mode в buf. Тот же формат конфигурации и поведение применяются, что упрощает миграцию между инструментами или использование обоих в одном workflow.","content":"Совместимость с buf Managed mode в EasyP совместим с managed mode в buf. Тот же формат конфигурации и поведение применяются, что упрощает миграцию между инструментами или использование обоих в одном workflow."},{"id":"cli/generator/generator::descriptor-set::115","title":"Генератор","section":"Генерация Descriptor Set","path":"/docs/guide/cli/generator/generator#descriptor-set","headings":["Генерация Descriptor Set"],"excerpt":"Генерация Descriptor Set **https://protobuf.dev/programming-guides/techniques/#self-description**","content":"Генерация Descriptor Set **https://protobuf.dev/programming-guides/techniques/#self-description**"},{"id":"cli/generator/generator::descriptor-set::116","title":"Генератор","section":"Генерация Descriptor Set","path":"/docs/guide/cli/generator/generator#descriptor-set","headings":["Генерация Descriptor Set"],"excerpt":"Генерация Descriptor Set EasyP поддерживает генерацию бинарных FileDescriptorSet файлов с помощью флага --descriptor_set_out. Это позволяет создавать самоописывающиеся protobuf сообщения, которые включают информацию о сх","content":"Генерация Descriptor Set EasyP поддерживает генерацию бинарных FileDescriptorSet файлов с помощью флага --descriptor_set_out. Это позволяет создавать самоописывающиеся protobuf сообщения, которые включают информацию о схеме вместе с данными."},{"id":"cli/generator/generator::descriptor-set::117","title":"Генератор","section":"Генерация Descriptor Set","path":"/docs/guide/cli/generator/generator#descriptor-set","headings":["Генерация Descriptor Set"],"excerpt":"Генерация Descriptor Set **Флаги CLI:**","content":"Генерация Descriptor Set **Флаги CLI:**"},{"id":"cli/generator/generator::descriptor-set::118","title":"Генератор","section":"Генерация Descriptor Set","path":"/docs/guide/cli/generator/generator#descriptor-set","headings":["Генерация Descriptor Set"],"excerpt":"Генерация Descriptor Set --descriptor_set_out - Путь для вывода бинарного FileDescriptorSet --include_imports - Включить все транзитивные зависимости в FileDescriptorSet","content":"Генерация Descriptor Set --descriptor_set_out - Путь для вывода бинарного FileDescriptorSet --include_imports - Включить все транзитивные зависимости в FileDescriptorSet"},{"id":"cli/generator/generator::descriptor-set::119","title":"Генератор","section":"Генерация Descriptor Set","path":"/docs/guide/cli/generator/generator#descriptor-set","headings":["Генерация Descriptor Set"],"excerpt":"Генерация Descriptor Set **Пример:**","content":"Генерация Descriptor Set **Пример:**"},{"id":"cli/generator/generator::descriptor-set::120","title":"Генератор","section":"Генерация Descriptor Set","path":"/docs/guide/cli/generator/generator#descriptor-set","headings":["Генерация Descriptor Set"],"excerpt":"Генерация Descriptor Set ```bash Генерация descriptor set только с целевыми файлами easyp generate --descriptor_set_out=./schema.pb","content":"Генерация Descriptor Set ```bash Генерация descriptor set только с целевыми файлами easyp generate --descriptor_set_out=./schema.pb"},{"id":"cli/generator/generator::descriptor-set::121","title":"Генератор","section":"Генерация Descriptor Set","path":"/docs/guide/cli/generator/generator#descriptor-set","headings":["Генерация Descriptor Set"],"excerpt":"Генерация Descriptor Set Генерация descriptor set со всеми зависимостями easyp generate --descriptor_set_out=./schema.pb --include_imports ```","content":"Генерация Descriptor Set Генерация descriptor set со всеми зависимостями easyp generate --descriptor_set_out=./schema.pb --include_imports ```"},{"id":"cli/generator/generator::descriptor-set::122","title":"Генератор","section":"Генерация Descriptor Set","path":"/docs/guide/cli/generator/generator#descriptor-set","headings":["Генерация Descriptor Set"],"excerpt":"Генерация Descriptor Set Самоописывающиеся сообщения полезны для динамического парсинга сообщений, валидации схемы во время выполнения, реестров схем и создания универсальных gRPC клиентов. Для получения дополнительной и","content":"Генерация Descriptor Set Самоописывающиеся сообщения полезны для динамического парсинга сообщений, валидации схемы во время выполнения, реестров схем и создания универсальных gRPC клиентов. Для получения дополнительной информации см. документацию Protocol Buffers о самоописании."},{"id":"cli/generator/generator::top::123","title":"Генератор","section":"Интеграция с менеджером пакетов","path":"/docs/guide/cli/generator/generator","headings":["Интеграция с менеджером пакетов"],"excerpt":"Интеграция с менеджером пакетов Одной из самых мощных возможностей EasyP является бесшовная интеграция генератора кода с менеджером пакетов. Это устраняет проблему ручного управления proto‑зависимостями и гарантирует, чт","content":"Интеграция с менеджером пакетов Одной из самых мощных возможностей EasyP является бесшовная интеграция генератора кода с менеджером пакетов. Это устраняет проблему ручного управления proto‑зависимостями и гарантирует, что при генерации используются корректные (зафиксированные) версии импортируемых файлов."},{"id":"cli/generator/generator::top::124","title":"Генератор","section":"Интеграция с менеджером пакетов","path":"/docs/guide/cli/generator/generator","headings":["Интеграция с менеджером пакетов"],"excerpt":"Интеграция с менеджером пакетов **Ключевые преимущества:** **Автоматическое разрешение зависимостей**: не нужно вручную прописывать пути импортов **Согласованность версий**: фиксация в easyp.lock гарантирует воспроизводи","content":"Интеграция с менеджером пакетов **Ключевые преимущества:** **Автоматическое разрешение зависимостей**: не нужно вручную прописывать пути импортов **Согласованность версий**: фиксация в easyp.lock гарантирует воспроизводимость **Транзитивные зависимости**: вложенные цепочки подтягиваются автоматически **Производительность**: локальный кеш — скачивание один раз и повторное использование"},{"id":"cli/generator/generator::top::125","title":"Генератор","section":"Автоматическое разрешение зависимостей","path":"/docs/guide/cli/generator/generator","headings":["Автоматическое разрешение зависимостей"],"excerpt":"Автоматическое разрешение зависимостей Когда вы указываете зависимости в секции deps, генератор автоматически добавляет их в путь импортов. Ваши proto‑файлы могут делать стандартные import из этих зависимостей без дополн","content":"Автоматическое разрешение зависимостей Когда вы указываете зависимости в секции deps, генератор автоматически добавляет их в путь импортов. Ваши proto‑файлы могут делать стандартные import из этих зависимостей без дополнительной настройки."},{"id":"cli/generator/generator::top::126","title":"Генератор","section":"Автоматическое разрешение зависимостей","path":"/docs/guide/cli/generator/generator","headings":["Автоматическое разрешение зависимостей"],"excerpt":"Автоматическое разрешение зависимостей **Как это работает:** EasyP скачивает и кеширует зависимости из deps Во время генерации кешированные файлы автоматически добавляются в import‑path protoc Ваши proto‑файлы используют","content":"Автоматическое разрешение зависимостей **Как это работает:** EasyP скачивает и кеширует зависимости из deps Во время генерации кешированные файлы автоматически добавляются в import‑path protoc Ваши proto‑файлы используют обычные import строки для обращения к зависимостям При with_imports: true в вывод попадают и локальные файлы, и файлы зависимостей"},{"id":"cli/generator/generator::top::127","title":"Генератор","section":"Автоматическое разрешение зависимостей","path":"/docs/guide/cli/generator/generator","headings":["Автоматическое разрешение зависимостей"],"excerpt":"Автоматическое разрешение зависимостей Ниже простой пример — зависимости указываются один раз в deps, далее они доступны при генерации автоматически:","content":"Автоматическое разрешение зависимостей Ниже простой пример — зависимости указываются один раз в deps, далее они доступны при генерации автоматически:"},{"id":"cli/generator/generator::top::128","title":"Генератор","section":"Автоматическое разрешение зависимостей","path":"/docs/guide/cli/generator/generator","headings":["Автоматическое разрешение зависимостей"],"excerpt":"Автоматическое разрешение зависимостей ```yaml deps: - github.com/googleapis/googleapis@common-protos-1_3_1 - github.com/grpc-ecosystem/grpc-gateway@v2.19.1","content":"Автоматическое разрешение зависимостей ```yaml deps: - github.com/googleapis/googleapis@common-protos-1_3_1 - github.com/grpc-ecosystem/grpc-gateway@v2.19.1"},{"id":"cli/generator/generator::top::129","title":"Генератор","section":"Автоматическое разрешение зависимостей","path":"/docs/guide/cli/generator/generator","headings":["Автоматическое разрешение зависимостей"],"excerpt":"Автоматическое разрешение зависимостей generate: inputs: - directory: \"proto\" plugins: - name: go out: ./gen/go opts: paths: source_relative with_imports: true # This automatically includes googleapis and grpc-gateway pr","content":"Автоматическое разрешение зависимостей 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::top::130","title":"Генератор","section":"Примеры использования зависимостей","path":"/docs/guide/cli/generator/generator","headings":["Примеры использования зависимостей"],"excerpt":"Примеры использования зависимостей Ниже показаны распространённые способы интеграции внешних proto‑зависимостей в процесс генерации.","content":"Примеры использования зависимостей Ниже показаны распространённые способы интеграции внешних proto‑зависимостей в процесс генерации."},{"id":"cli/generator/generator::google-apis::131","title":"Генератор","section":"Использование Google APIs","path":"/docs/guide/cli/generator/generator#google-apis","headings":["Использование Google APIs"],"excerpt":"Использование Google APIs Google APIs — одна из самых популярных коллекций зависимостей: стандартные типы, аннотации для REST, проверки и общие структуры данных.","content":"Использование Google APIs Google APIs — одна из самых популярных коллекций зависимостей: стандартные типы, аннотации для REST, проверки и общие структуры данных."},{"id":"cli/generator/generator::google-apis::132","title":"Генератор","section":"Использование Google APIs","path":"/docs/guide/cli/generator/generator#google-apis","headings":["Использование Google APIs"],"excerpt":"Использование Google APIs **Когда использовать Google APIs:** Построение REST поверх gRPC (gRPC-Gateway) Нужны стандартные типы (Timestamp, Duration, Any) Требуются аннотации поведения полей (field behavior) Интеграция с","content":"Использование Google APIs **Когда использовать Google APIs:** Построение REST поверх gRPC (gRPC-Gateway) Нужны стандартные типы (Timestamp, Duration, Any) Требуются аннотации поведения полей (field behavior) Интеграция с сервисами Google Cloud"},{"id":"cli/generator/generator::google-apis::133","title":"Генератор","section":"Использование Google APIs","path":"/docs/guide/cli/generator/generator#google-apis","headings":["Использование Google APIs"],"excerpt":"Использование Google APIs Минимальная конфигурация для подключения Google APIs:","content":"Использование Google APIs Минимальная конфигурация для подключения Google APIs:"},{"id":"cli/generator/generator::google-apis::134","title":"Генератор","section":"Использование Google APIs","path":"/docs/guide/cli/generator/generator#google-apis","headings":["Использование Google APIs"],"excerpt":"Использование Google APIs ```yaml deps: - github.com/googleapis/googleapis@common-protos-1_3_1","content":"Использование Google APIs ```yaml deps: - github.com/googleapis/googleapis@common-protos-1_3_1"},{"id":"cli/generator/generator::google-apis::135","title":"Генератор","section":"Использование Google APIs","path":"/docs/guide/cli/generator/generator#google-apis","headings":["Использование Google APIs"],"excerpt":"Использование Google APIs generate: inputs: - directory: \"api/proto\" plugins: - name: go out: ./gen/go opts: paths: source_relative with_imports: true ```","content":"Использование Google APIs generate: inputs: - directory: \"api/proto\" plugins: - name: go out: ./gen/go opts: paths: source_relative with_imports: true ```"},{"id":"cli/generator/generator::google-apis::136","title":"Генератор","section":"Использование Google APIs","path":"/docs/guide/cli/generator/generator#google-apis","headings":["Использование Google APIs"],"excerpt":"Использование Google APIs **Важно:** Всегда фиксируйте версию (например common-protos-1_3_1) — не используйте latest в продакшене.","content":"Использование Google APIs **Важно:** Всегда фиксируйте версию (например common-protos-1_3_1) — не используйте latest в продакшене."},{"id":"cli/generator/generator::google-apis::137","title":"Генератор","section":"Использование Google APIs","path":"/docs/guide/cli/generator/generator#google-apis","headings":["Использование Google APIs"],"excerpt":"Использование Google APIs После настройки ваши proto могут импортировать определения Google API. Ниже пример сервиса с HTTP аннотацией:","content":"Использование Google APIs После настройки ваши proto могут импортировать определения Google API. Ниже пример сервиса с HTTP аннотацией:"},{"id":"cli/generator/generator::google-apis::138","title":"Генератор","section":"Использование Google APIs","path":"/docs/guide/cli/generator/generator#google-apis","headings":["Использование Google APIs"],"excerpt":"Использование Google APIs ```proto // api/proto/service.proto syntax = \"proto3\";","content":"Использование Google APIs ```proto // api/proto/service.proto syntax = \"proto3\";"},{"id":"cli/generator/generator::google-apis::139","title":"Генератор","section":"Использование Google APIs","path":"/docs/guide/cli/generator/generator#google-apis","headings":["Использование Google APIs"],"excerpt":"Использование Google APIs import \"google/api/annotations.proto\"; import \"google/protobuf/timestamp.proto\";","content":"Использование Google APIs import \"google/api/annotations.proto\"; import \"google/protobuf/timestamp.proto\";"},{"id":"cli/generator/generator::google-apis::140","title":"Генератор","section":"Использование Google APIs","path":"/docs/guide/cli/generator/generator#google-apis","headings":["Использование Google APIs"],"excerpt":"Использование Google APIs service MyService { rpc GetData(GetDataRequest) returns (GetDataResponse) { option (google.api.http) = { get: \"/v1/data\" }; } } ```","content":"Использование Google APIs service MyService { rpc GetData(GetDataRequest) returns (GetDataResponse) { option (google.api.http) = { get: \"/v1/data\" }; } } ```"},{"id":"cli/generator/generator::top::141","title":"Генератор","section":"Использование правил валидации","path":"/docs/guide/cli/generator/generator","headings":["Использование правил валидации"],"excerpt":"Использование правил валидации protoc-gen-validate даёт мощную проверку полей прямо в определениях proto, устраняя необходимость писать отдельную логику валидации в приложении.","content":"Использование правил валидации protoc-gen-validate даёт мощную проверку полей прямо в определениях proto, устраняя необходимость писать отдельную логику валидации в приложении."},{"id":"cli/generator/generator::top::142","title":"Генератор","section":"Использование правил валидации","path":"/docs/guide/cli/generator/generator","headings":["Использование правил валидации"],"excerpt":"Использование правил валидации **Когда применять валидацию:** Проверка входных данных API Ограничения моделей БД Проверка конфигурационных файлов Любая ситуация, где критична целостность данных","content":"Использование правил валидации **Когда применять валидацию:** Проверка входных данных API Ограничения моделей БД Проверка конфигурационных файлов Любая ситуация, где критична целостность данных"},{"id":"cli/generator/generator::top::143","title":"Генератор","section":"Использование правил валидации","path":"/docs/guide/cli/generator/generator","headings":["Использование правил валидации"],"excerpt":"Использование правил валидации **Преимущества:** Правила валидации — часть proto (единый источник истины) Генерация создаёт функции проверки автоматически Единообразие проверок между языками Производительнее чем проверка","content":"Использование правил валидации **Преимущества:** Правила валидации — часть proto (единый источник истины) Генерация создаёт функции проверки автоматически Единообразие проверок между языками Производительнее чем проверка через runtime reflection"},{"id":"cli/generator/generator::top::144","title":"Генератор","section":"Использование правил валидации","path":"/docs/guide/cli/generator/generator","headings":["Использование правил валидации"],"excerpt":"Использование правил валидации ```yaml deps: - github.com/bufbuild/protoc-gen-validate@v0.10.1","content":"Использование правил валидации ```yaml deps: - github.com/bufbuild/protoc-gen-validate@v0.10.1"},{"id":"cli/generator/generator::top::145","title":"Генератор","section":"Использование правил валидации","path":"/docs/guide/cli/generator/generator","headings":["Использование правил валидации"],"excerpt":"Использование правил валидации 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":"Использование правил валидации 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::top::146","title":"Генератор","section":"Использование правил валидации","path":"/docs/guide/cli/generator/generator","headings":["Использование правил валидации"],"excerpt":"Использование правил валидации **Примечание:** Нужны одновременно зависимость (для импортов proto) и плагин (для генерации кода), чтобы получить полноценную поддержку валидации.","content":"Использование правил валидации **Примечание:** Нужны одновременно зависимость (для импортов proto) и плагин (для генерации кода), чтобы получить полноценную поддержку валидации."},{"id":"cli/generator/generator::top::147","title":"Генератор","section":"Использование правил валидации","path":"/docs/guide/cli/generator/generator","headings":["Использование правил валидации"],"excerpt":"Использование правил валидации Так выглядят правила валидации в proto — сгенерированный код будет автоматически их применять:","content":"Использование правил валидации Так выглядят правила валидации в proto — сгенерированный код будет автоматически их применять:"},{"id":"cli/generator/generator::top::148","title":"Генератор","section":"Использование правил валидации","path":"/docs/guide/cli/generator/generator","headings":["Использование правил валидации"],"excerpt":"Использование правил валидации ```proto // proto/user.proto syntax = \"proto3\";","content":"Использование правил валидации ```proto // proto/user.proto syntax = \"proto3\";"},{"id":"cli/generator/generator::top::149","title":"Генератор","section":"Использование правил валидации","path":"/docs/guide/cli/generator/generator","headings":["Использование правил валидации"],"excerpt":"Использование правил валидации import \"validate/validate.proto\";","content":"Использование правил валидации import \"validate/validate.proto\";"},{"id":"cli/generator/generator::top::150","title":"Генератор","section":"Использование правил валидации","path":"/docs/guide/cli/generator/generator","headings":["Использование правил валидации"],"excerpt":"Использование правил валидации message User { string email = 1 [(validate.rules).string.email = true]; int32 age = 2 [(validate.rules).int32.gte = 0]; } ```","content":"Использование правил валидации message User { string email = 1 [(validate.rules).string.email = true]; int32 age = 2 [(validate.rules).int32.gte = 0]; } ```"},{"id":"cli/generator/generator::top::151","title":"Генератор","section":"Комплексная конфигурация с несколькими зависимостями","path":"/docs/guide/cli/generator/generator","headings":["Комплексная конфигурация с несколькими зависимостями"],"excerpt":"Комплексная конфигурация с несколькими зависимостями Пример ниже показывает продакшен‑конфигурацию, объединяющую несколько зависимостей и плагины для полного цикла разработки API:","content":"Комплексная конфигурация с несколькими зависимостями Пример ниже показывает продакшен‑конфигурацию, объединяющую несколько зависимостей и плагины для полного цикла разработки API:"},{"id":"cli/generator/generator::top::152","title":"Генератор","section":"Комплексная конфигурация с несколькими зависимостями","path":"/docs/guide/cli/generator/generator","headings":["Комплексная конфигурация с несколькими зависимостями"],"excerpt":"Комплексная конфигурация с несколькими зависимостями ```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 HT","content":"Комплексная конфигурация с несколькими зависимостями ```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::top::153","title":"Генератор","section":"Комплексная конфигурация с несколькими зависимостями","path":"/docs/guide/cli/generator/generator","headings":["Комплексная конфигурация с несколькими зависимостями"],"excerpt":"Комплексная конфигурация с несколькими зависимостями generate: inputs: - directory: \"api/proto\" plugins: # Go code generation - Core protobuf structures - name: go out: ./gen/go opts: paths: source_relative module: githu","content":"Комплексная конфигурация с несколькими зависимостями 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::top::154","title":"Генератор","section":"Интеграция с кешем зависимостей","path":"/docs/guide/cli/generator/generator","headings":["Интеграция с кешем зависимостей"],"excerpt":"Интеграция с кешем зависимостей Генератор использует модульный кеш EasyP для ускорения сборок:","content":"Интеграция с кешем зависимостей Генератор использует модульный кеш EasyP для ускорения сборок:"},{"id":"cli/generator/generator::top::155","title":"Генератор","section":"Интеграция с кешем зависимостей","path":"/docs/guide/cli/generator/generator","headings":["Интеграция с кешем зависимостей"],"excerpt":"Интеграция с кешем зависимостей ```bash Download dependencies once easyp mod download","content":"Интеграция с кешем зависимостей ```bash Download dependencies once easyp mod download"},{"id":"cli/generator/generator::top::156","title":"Генератор","section":"Интеграция с кешем зависимостей","path":"/docs/guide/cli/generator/generator","headings":["Интеграция с кешем зависимостей"],"excerpt":"Интеграция с кешем зависимостей Generate code (uses cached dependencies) easyp generate","content":"Интеграция с кешем зависимостей Generate code (uses cached dependencies) easyp generate"},{"id":"cli/generator/generator::top::157","title":"Генератор","section":"Интеграция с кешем зависимостей","path":"/docs/guide/cli/generator/generator","headings":["Интеграция с кешем зависимостей"],"excerpt":"Интеграция с кешем зависимостей Dependencies are cached in ~/.easyp/mod/ ls ~/.easyp/mod/github.com/googleapis/googleapis/ ```","content":"Интеграция с кешем зависимостей Dependencies are cached in ~/.easyp/mod/ ls ~/.easyp/mod/github.com/googleapis/googleapis/ ```"},{"id":"cli/generator/generator::top::158","title":"Генератор","section":"Удалённая генерация","path":"/docs/guide/cli/generator/generator","headings":["Удалённая генерация"],"excerpt":"Удалённая генерация Удалённая генерация — мощная возможность, позволяющая генерировать код из proto‑файлов в удалённых Git‑репозиториях без локального checkout. Это поддерживает микросервисную архитектуру, где команды ис","content":"Удалённая генерация Удалённая генерация — мощная возможность, позволяющая генерировать код из proto‑файлов в удалённых Git‑репозиториях без локального checkout. Это поддерживает микросервисную архитектуру, где команды используют API друг друга без жёсткой связки."},{"id":"cli/generator/generator::top::159","title":"Генератор","section":"Удалённая генерация","path":"/docs/guide/cli/generator/generator","headings":["Удалённая генерация"],"excerpt":"Удалённая генерация **Преимущества:** **Развязка разработки**: Команды развиваются независимо, используя версии API друг друга **Контроль версий**: Фиксация внешних API гарантирует стабильность **Меньше размер репозитори","content":"Удалённая генерация **Преимущества:** **Развязка разработки**: Команды развиваются независимо, используя версии API друг друга **Контроль версий**: Фиксация внешних API гарантирует стабильность **Меньше размер репозитория**: Нет необходимости в vendoring/submodule внешних proto **Автоматические обновления**: Легко перейти на новую версию по готовности"},{"id":"cli/generator/generator::top::160","title":"Генератор","section":"Удалённая генерация","path":"/docs/guide/cli/generator/generator","headings":["Удалённая генерация"],"excerpt":"Удалённая генерация **Рекомендации:** В продакшене используйте только тегированные версии В разработке можно тестировать latest, но в проде фиксируйте При наличии используйте семантическое версионирование Учитывайте сете","content":"Удалённая генерация **Рекомендации:** В продакшене используйте только тегированные версии В разработке можно тестировать latest, но в проде фиксируйте При наличии используйте семантическое версионирование Учитывайте сетевые ограничения в CI/CD"},{"id":"cli/generator/generator::proto::161","title":"Генератор","section":"Источники удалённых proto","path":"/docs/guide/cli/generator/generator#proto","headings":["Источники удалённых proto"],"excerpt":"Источники удалённых proto Генерация напрямую из удалённых репозиториев — полезно в микросервисной архитектуре, где разные команды владеют разными proto.","content":"Источники удалённых proto Генерация напрямую из удалённых репозиториев — полезно в микросервисной архитектуре, где разные команды владеют разными proto."},{"id":"cli/generator/generator::proto::162","title":"Генератор","section":"Источники удалённых proto","path":"/docs/guide/cli/generator/generator#proto","headings":["Источники удалённых proto"],"excerpt":"Источники удалённых proto **Типовой workflow:** Команда A публикует proto с версиями в Git Команда B добавляет их в свой easyp.yaml При генерации EasyP скачивает и подключает удалённые proto Сгенерированный код содержит ","content":"Источники удалённых proto **Типовой workflow:** Команда A публикует proto с версиями в Git Команда B добавляет их в свой easyp.yaml При генерации EasyP скачивает и подключает удалённые proto Сгенерированный код содержит клиентские библиотеки сервисов команды A"},{"id":"cli/generator/generator::proto::163","title":"Генератор","section":"Источники удалённых proto","path":"/docs/guide/cli/generator/generator#proto","headings":["Источники удалённых proto"],"excerpt":"Источники удалённых proto Практический пример объединения локальных и удалённых источников в одной конфигурации генерации:","content":"Источники удалённых proto Практический пример объединения локальных и удалённых источников в одной конфигурации генерации:"},{"id":"cli/generator/generator::top::164","title":"Генератор","section":"Сценарии использования удалённой генерации","path":"/docs/guide/cli/generator/generator","headings":["Сценарии использования удалённой генерации"],"excerpt":"Сценарии использования удалённой генерации Примеры ниже показывают реальные ситуации, где удалённая генерация даёт ощутимую выгоду.","content":"Сценарии использования удалённой генерации Примеры ниже показывают реальные ситуации, где удалённая генерация даёт ощутимую выгоду."},{"id":"cli/generator/generator::multi-team-development::165","title":"Генератор","section":"Много команд (Multi-Team Development)","path":"/docs/guide/cli/generator/generator#multi-team-development","headings":["Много команд (Multi-Team Development)"],"excerpt":"Много команд (Multi-Team Development) Мультикомандная разработка особенно выигрывает: вместо координации общих репозиториев и сложного управления зависимостями — независимая эволюция API с контролируемыми обновлениями че","content":"Много команд (Multi-Team Development) Мультикомандная разработка особенно выигрывает: вместо координации общих репозиториев и сложного управления зависимостями — независимая эволюция API с контролируемыми обновлениями через версии."},{"id":"cli/generator/generator::multi-team-development::166","title":"Генератор","section":"Много команд (Multi-Team Development)","path":"/docs/guide/cli/generator/generator#multi-team-development","headings":["Много команд (Multi-Team Development)"],"excerpt":"Много команд (Multi-Team Development) Паттерн ценен в крупных организациях, где: Команды имеют разные циклы релизов и скорости разработки Владение API определено, потребление — массовое Нужно избежать overhead от координ","content":"Много команд (Multi-Team Development) Паттерн ценен в крупных организациях, где: Команды имеют разные циклы релизов и скорости разработки Владение API определено, потребление — массовое Нужно избежать overhead от координации общих proto репозиториев Команды используют разные стеки, но должны взаимодействовать"},{"id":"cli/generator/generator::multi-team-development::167","title":"Генератор","section":"Много команд (Multi-Team Development)","path":"/docs/guide/cli/generator/generator#multi-team-development","headings":["Много команд (Multi-Team Development)"],"excerpt":"Много команд (Multi-Team Development)","content":"Много команд (Multi-Team Development)"},{"id":"cli/generator/generator::api::168","title":"Генератор","section":"Интеграция с API вендоров","path":"/docs/guide/cli/generator/generator#api","headings":["Интеграция с API вендоров"],"excerpt":"Интеграция с API вендоров Многие вендоры публикуют proto для своих API, позволяя генерировать типобезопасных клиентов вместо ручных HTTP реализаций. Это повышает типовую строгость, автоматизирует сериализацию и часто уск","content":"Интеграция с API вендоров Многие вендоры публикуют proto для своих API, позволяя генерировать типобезопасных клиентов вместо ручных HTTP реализаций. Это повышает типовую строгость, автоматизирует сериализацию и часто ускоряет работу."},{"id":"cli/generator/generator::api::169","title":"Генератор","section":"Интеграция с API вендоров","path":"/docs/guide/cli/generator/generator#api","headings":["Интеграция с API вендоров"],"excerpt":"Интеграция с API вендоров Преимущества использования proto от вендоров: **Type safety**: Проверка типов на этапе компиляции **Automatic updates**: Новые возможности приходят с обновлением версии **Consistency**: Единые п","content":"Интеграция с API вендоров Преимущества использования proto от вендоров: **Type safety**: Проверка типов на этапе компиляции **Automatic updates**: Новые возможности приходят с обновлением версии **Consistency**: Единые паттерны интерфейсов между интеграциями **Performance**: Бинарная сериализация быстрее JSON **Documentation**: Proto выступают источником истины для API"},{"id":"cli/generator/generator::top::170","title":"Генератор","section":"Команды","path":"/docs/guide/cli/generator/generator","headings":["Команды"],"excerpt":"Команды CLI EasyP предоставляет гибкие варианты запуска генерации с разными конфигурациями и окружениями.","content":"Команды CLI EasyP предоставляет гибкие варианты запуска генерации с разными конфигурациями и окружениями."},{"id":"cli/generator/generator::top::171","title":"Генератор","section":"Базовая генерация","path":"/docs/guide/cli/generator/generator","headings":["Базовая генерация"],"excerpt":"Базовая генерация Ниже наиболее часто применяемые варианты команд для разработки и продакшена:","content":"Базовая генерация Ниже наиболее часто применяемые варианты команд для разработки и продакшена:"},{"id":"cli/generator/generator::top::172","title":"Генератор","section":"Базовая генерация","path":"/docs/guide/cli/generator/generator","headings":["Базовая генерация"],"excerpt":"Базовая генерация ```bash Use default easyp.yaml configuration - Most common for development easyp generate","content":"Базовая генерация ```bash Use default easyp.yaml configuration - Most common for development easyp generate"},{"id":"cli/generator/generator::top::173","title":"Генератор","section":"Базовая генерация","path":"/docs/guide/cli/generator/generator","headings":["Базовая генерация"],"excerpt":"Базовая генерация Use custom configuration file - Essential for multi-environment setups easyp --cfg production.easyp.yaml generate","content":"Базовая генерация Use custom configuration file - Essential for multi-environment setups easyp --cfg production.easyp.yaml generate"},{"id":"cli/generator/generator::top::174","title":"Генератор","section":"Базовая генерация","path":"/docs/guide/cli/generator/generator","headings":["Базовая генерация"],"excerpt":"Базовая генерация Generate with debug logs - Helpful for debugging and CI/CD easyp --debug generate","content":"Базовая генерация Generate with debug logs - Helpful for debugging and CI/CD easyp --debug generate"},{"id":"cli/generator/generator::top::175","title":"Генератор","section":"Базовая генерация","path":"/docs/guide/cli/generator/generator","headings":["Базовая генерация"],"excerpt":"Базовая генерация Generate with custom cache location - Useful for CI systems or shared environments EASYPPATH=/tmp/easyp-cache easyp generate ```","content":"Базовая генерация Generate with custom cache location - Useful for CI systems or shared environments EASYPPATH=/tmp/easyp-cache easyp generate ```"},{"id":"cli/generator/generator::top::176","title":"Генератор","section":"Интеграция с менеджером пакетов","path":"/docs/guide/cli/generator/generator","headings":["Интеграция с менеджером пакетов"],"excerpt":"Интеграция с менеджером пакетов Интеграция с менеджером пакетов позволяет либо явно управлять зависимостями, либо поручить это генератору. Явный путь даёт больше контроля, автоматический — больше удобства:","content":"Интеграция с менеджером пакетов Интеграция с менеджером пакетов позволяет либо явно управлять зависимостями, либо поручить это генератору. Явный путь даёт больше контроля, автоматический — больше удобства:"},{"id":"cli/generator/generator::top::177","title":"Генератор","section":"Интеграция с менеджером пакетов","path":"/docs/guide/cli/generator/generator","headings":["Интеграция с менеджером пакетов"],"excerpt":"Интеграция с менеджером пакетов ```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":"Интеграция с менеджером пакетов ```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::top::178","title":"Генератор","section":"Интеграция с менеджером пакетов","path":"/docs/guide/cli/generator/generator","headings":["Интеграция с менеджером пакетов"],"excerpt":"Интеграция с менеджером пакетов Automatic workflow - Convenient for development (generate downloads dependencies automatically) easyp generate ```","content":"Интеграция с менеджером пакетов Automatic workflow - Convenient for development (generate downloads dependencies automatically) easyp generate ```"},{"id":"cli/generator/generator::advanced-usage::179","title":"Генератор","section":"Расширенное использование (Advanced Usage)","path":"/docs/guide/cli/generator/generator#advanced-usage","headings":["Расширенное использование (Advanced Usage)"],"excerpt":"Расширенное использование (Advanced Usage) Эти варианты полезны для специфических сценариев деплоя, отладки или когда нужен более тонкий контроль процесса генерации:","content":"Расширенное использование (Advanced Usage) Эти варианты полезны для специфических сценариев деплоя, отладки или когда нужен более тонкий контроль процесса генерации:"},{"id":"cli/generator/generator::advanced-usage::180","title":"Генератор","section":"Расширенное использование (Advanced Usage)","path":"/docs/guide/cli/generator/generator#advanced-usage","headings":["Расширенное использование (Advanced Usage)"],"excerpt":"Расширенное использование (Advanced Usage) ```bash Генерация из конкретной директории (перекрывает настройку в файле конфигурации) easyp generate --path=./api/proto","content":"Расширенное использование (Advanced Usage) ```bash Генерация из конкретной директории (перекрывает настройку в файле конфигурации) easyp generate --path=./api/proto"},{"id":"cli/generator/generator::advanced-usage::181","title":"Генератор","section":"Расширенное использование (Advanced Usage)","path":"/docs/guide/cli/generator/generator#advanced-usage","headings":["Расширенное использование (Advanced Usage)"],"excerpt":"Расширенное использование (Advanced Usage) Генерация с vendored зависимостями (оффлайн / Docker контейнеры) easyp mod vendor easyp generate","content":"Расширенное использование (Advanced Usage) Генерация с vendored зависимостями (оффлайн / Docker контейнеры) easyp mod vendor easyp generate"},{"id":"cli/generator/generator::advanced-usage::182","title":"Генератор","section":"Расширенное использование (Advanced Usage)","path":"/docs/guide/cli/generator/generator#advanced-usage","headings":["Расширенное использование (Advanced Usage)"],"excerpt":"Расширенное использование (Advanced Usage) Генерация из кастомного project root (удобно для монореп и вложенных рабочих директорий) easyp generate --root=/usr/local/src/my-project --path=./api/proto ```","content":"Расширенное использование (Advanced Usage) Генерация из кастомного project root (удобно для монореп и вложенных рабочих директорий) easyp generate --root=/usr/local/src/my-project --path=./api/proto ```"},{"id":"cli/generator/generator::common-patterns::183","title":"Генератор","section":"Типовые паттерны (Common Patterns)","path":"/docs/guide/cli/generator/generator#common-patterns","headings":["Типовые паттерны (Common Patterns)"],"excerpt":"Типовые паттерны (Common Patterns) Эти схемы отражают реальные сценарии и лучшие практики организации генерации кода в разных структурах проектов.","content":"Типовые паттерны (Common Patterns) Эти схемы отражают реальные сценарии и лучшие практики организации генерации кода в разных структурах проектов."},{"id":"cli/generator/generator::multi-language-generation::184","title":"Генератор","section":"Мульти-языковая генерация (Multi-Language Generation)","path":"/docs/guide/cli/generator/generator#multi-language-generation","headings":["Мульти-языковая генерация (Multi-Language Generation)"],"excerpt":"Мульти-языковая генерация (Multi-Language Generation) Мульти-языковая генерация критична для компаний, использующих разные технологии в стеке. EasyP облегчает получение согласованных клиентских библиотек и типов для неск","content":"Мульти-языковая генерация (Multi-Language Generation) Мульти-языковая генерация критична для компаний, использующих разные технологии в стеке. EasyP облегчает получение согласованных клиентских библиотек и типов для нескольких языков из одного источника proto."},{"id":"cli/generator/generator::multi-language-generation::185","title":"Генератор","section":"Мульти-языковая генерация (Multi-Language Generation)","path":"/docs/guide/cli/generator/generator#multi-language-generation","headings":["Мульти-языковая генерация (Multi-Language Generation)"],"excerpt":"Мульти-языковая генерация (Multi-Language Generation) **Типовые сценарии:** **Full‑stack приложения**: backend на Go/Java + фронтенд на TypeScript **Платформы данных**: сервисы на Go + аналитика / ML на Python **Микросер","content":"Мульти-языковая генерация (Multi-Language Generation) **Типовые сценарии:** **Full‑stack приложения**: backend на Go/Java + фронтенд на TypeScript **Платформы данных**: сервисы на Go + аналитика / ML на Python **Микросервисы**: каждый сервис — оптимальный язык под задачу **Внешние SDK**: предоставление клиентских библиотек партнёрам **Интеграция с легаси**: современные gRPC сервисы + старые системы"},{"id":"cli/generator/generator::multi-language-generation::186","title":"Генератор","section":"Мульти-языковая генерация (Multi-Language Generation)","path":"/docs/guide/cli/generator/generator#multi-language-generation","headings":["Мульти-языковая генерация (Multi-Language Generation)"],"excerpt":"Мульти-языковая генерация (Multi-Language Generation) **Производительность:** Каждый плагин запускается отдельно — время растёт линейно от количества плагинов Для больших наборов используйте параллельный запуск (make -j4","content":"Мульти-языковая генерация (Multi-Language Generation) **Производительность:** Каждый плагин запускается отдельно — время растёт линейно от количества плагинов Для больших наборов используйте параллельный запуск (make -j4) Структурируйте выходные директории иерархически — меньше конфликтов Плагины имеют разную скорость — профилируйте сборку для поиска узких мест"},{"id":"cli/generator/generator::multi-language-generation::187","title":"Генератор","section":"Мульти-языковая генерация (Multi-Language Generation)","path":"/docs/guide/cli/generator/generator#multi-language-generation","headings":["Мульти-языковая генерация (Multi-Language Generation)"],"excerpt":"Мульти-языковая генерация (Multi-Language Generation) **Преимущества сопровождения:** Единый источник истины для API снижает риск расхождения схем Согласованные типы уменьшают интеграционные баги Автоматическая синхрониз","content":"Мульти-языковая генерация (Multi-Language Generation) **Преимущества сопровождения:** Единый источник истины для API снижает риск расхождения схем Согласованные типы уменьшают интеграционные баги Автоматическая синхронизация при изменении proto исключает ручные правки Меньше риска дрейфа API между реализациями на разных языках Рефакторинг упрощается — изменения транзитивно отражаются во всех артефактах"},{"id":"cli/generator/generator::multi-language-generation::188","title":"Генератор","section":"Мульти-языковая генерация (Multi-Language Generation)","path":"/docs/guide/cli/generator/generator#multi-language-generation","headings":["Мульти-языковая генерация (Multi-Language Generation)"],"excerpt":"Мульти-языковая генерация (Multi-Language Generation) Ниже пример типичной мульти-языковой конфигурации для full‑stack приложения: backend, веб‑клиент, аналитика и документация:","content":"Мульти-языковая генерация (Multi-Language Generation) Ниже пример типичной мульти-языковой конфигурации для full‑stack приложения: backend, веб‑клиент, аналитика и документация:"},{"id":"cli/generator/generator::multi-language-generation::189","title":"Генератор","section":"Мульти-языковая генерация (Multi-Language Generation)","path":"/docs/guide/cli/generator/generator#multi-language-generation","headings":["Мульти-языковая генерация (Multi-Language Generation)"],"excerpt":"Мульти-языковая генерация (Multi-Language Generation)","content":"Мульти-языковая генерация (Multi-Language Generation)"},{"id":"cli/generator/generator::multi-language-generation::190","title":"Генератор","section":"Мульти-языковая генерация (Multi-Language Generation)","path":"/docs/guide/cli/generator/generator#multi-language-generation","headings":["Мульти-языковая генерация (Multi-Language Generation)"],"excerpt":"Мульти-языковая генерация (Multi-Language Generation) **Совет по организации:** Используйте отдельные выходные директории для каждого языка, чтобы избежать конфликтов файлов и упростить интеграцию с языковыми сборочными ","content":"Мульти-языковая генерация (Multi-Language Generation) **Совет по организации:** Используйте отдельные выходные директории для каждого языка, чтобы избежать конфликтов файлов и упростить интеграцию с языковыми сборочными системами."},{"id":"cli/generator/generator::multi-language-generation::191","title":"Генератор","section":"Мульти-языковая генерация (Multi-Language Generation)","path":"/docs/guide/cli/generator/generator#multi-language-generation","headings":["Мульти-языковая генерация (Multi-Language Generation)"],"excerpt":"Мульти-языковая генерация (Multi-Language Generation) Генератор EasyP — комплексное решение для генерации кода из Protocol Buffers: от простой локальной разработки до сложных enterprise‑сценариев с удалёнными зависимостя","content":"Мульти-языковая генерация (Multi-Language Generation) Генератор EasyP — комплексное решение для генерации кода из Protocol Buffers: от простой локальной разработки до сложных enterprise‑сценариев с удалёнными зависимостями и мульти-языковым выводом."},{"id":"cli/linter/linter::proto::0","title":"Линтер","section":"Зачем нужен линтер для proto файлов?","path":"/docs/guide/cli/linter/linter#proto","headings":["Зачем нужен линтер для proto файлов?"],"excerpt":"Зачем нужен линтер для proto файлов? Линтеры играют ключевую роль в современной разработке, особенно когда речь о .proto файлах. Они обеспечивают единый стиль и структуру, помогают находить потенциальные ошибки на ранних","content":"Зачем нужен линтер для proto файлов? Линтеры играют ключевую роль в современной разработке, особенно когда речь о .proto файлах. Они обеспечивают единый стиль и структуру, помогают находить потенциальные ошибки на ранних этапах и поддерживают читаемость кода. Это даёт выгоды:"},{"id":"cli/linter/linter::proto::1","title":"Линтер","section":"Зачем нужен линтер для proto файлов?","path":"/docs/guide/cli/linter/linter#proto","headings":["Зачем нужен линтер для proto файлов?"],"excerpt":"Зачем нужен линтер для proto файлов? **Снижение затрат на разработку:** Ошибки ловятся раньше, меньше времени на отладку. **Улучшение командного взаимодействия:** Единообразный код легче понимать и сопровождать. **Бизнес","content":"Зачем нужен линтер для proto файлов? **Снижение затрат на разработку:** Ошибки ловятся раньше, меньше времени на отладку. **Улучшение командного взаимодействия:** Единообразный код легче понимать и сопровождать. **Бизнес-эффективность:** Более качественный код → меньше инцидентов в проде → ниже стоимость поддержки."},{"id":"cli/linter/linter::top::2","title":"Линтер","section":"Справочник по конфигурации","path":"/docs/guide/cli/linter/linter","headings":["Справочник по конфигурации"],"excerpt":"Справочник по конфигурации Конфигурация линтера настраивается в секции lint файла easyp.yaml.","content":"Справочник по конфигурации Конфигурация линтера настраивается в секции lint файла easyp.yaml."},{"id":"cli/linter/linter::use-string::3","title":"Линтер","section":"use ([]string)","path":"/docs/guide/cli/linter/linter#use-string","headings":["use ([]string)"],"excerpt":"use ([]string) Определяет набор правил или категорий для включения. Можно смешивать категории и конкретные правила.","content":"use ([]string) Определяет набор правил или категорий для включения. Можно смешивать категории и конкретные правила."},{"id":"cli/linter/linter::use-string::4","title":"Линтер","section":"use ([]string)","path":"/docs/guide/cli/linter/linter#use-string","headings":["use ([]string)"],"excerpt":"use ([]string) **Категории:** **MINIMAL**: Базовая согласованность пакетов **BASIC**: Соглашения по именованию и структуре **DEFAULT**: Рекомендованные правила для большинства проектов **COMMENTS**: Требования к коммента","content":"use ([]string) **Категории:** **MINIMAL**: Базовая согласованность пакетов **BASIC**: Соглашения по именованию и структуре **DEFAULT**: Рекомендованные правила для большинства проектов **COMMENTS**: Требования к комментариям **UNARY_RPC**: Ограничение на streaming RPC"},{"id":"cli/linter/linter::use-string::5","title":"Линтер","section":"use ([]string)","path":"/docs/guide/cli/linter/linter#use-string","headings":["use ([]string)"],"excerpt":"use ([]string) **Индивидуальные правила:** Любое имя правила (например ENUM_PASCAL_CASE, FIELD_LOWER_SNAKE_CASE)","content":"use ([]string) **Индивидуальные правила:** Любое имя правила (например ENUM_PASCAL_CASE, FIELD_LOWER_SNAKE_CASE)"},{"id":"cli/linter/linter::use-string::6","title":"Линтер","section":"use ([]string)","path":"/docs/guide/cli/linter/linter#use-string","headings":["use ([]string)"],"excerpt":"use ([]string) **Примеры:** ```yaml Только категории use: [MINIMAL, BASIC, DEFAULT]","content":"use ([]string) **Примеры:** ```yaml Только категории use: [MINIMAL, BASIC, DEFAULT]"},{"id":"cli/linter/linter::use-string::7","title":"Линтер","section":"use ([]string)","path":"/docs/guide/cli/linter/linter#use-string","headings":["use ([]string)"],"excerpt":"use ([]string) Смешивание use: - MINIMAL - COMMENT_SERVICE - COMMENT_RPC - ENUM_PASCAL_CASE","content":"use ([]string) Смешивание use: - MINIMAL - COMMENT_SERVICE - COMMENT_RPC - ENUM_PASCAL_CASE"},{"id":"cli/linter/linter::use-string::8","title":"Линтер","section":"use ([]string)","path":"/docs/guide/cli/linter/linter#use-string","headings":["use ([]string)"],"excerpt":"use ([]string) Точный набор use: - PACKAGE_DEFINED - SERVICE_PASCAL_CASE - FIELD_LOWER_SNAKE_CASE ```","content":"use ([]string) Точный набор use: - PACKAGE_DEFINED - SERVICE_PASCAL_CASE - FIELD_LOWER_SNAKE_CASE ```"},{"id":"cli/linter/linter::enum_zero_value_suffix-string::9","title":"Линтер","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) Обязывает нулевое значение enum иметь заданный суффикс.","content":"enum_zero_value_suffix (string) Обязывает нулевое значение enum иметь заданный суффикс."},{"id":"cli/linter/linter::enum_zero_value_suffix-string::10","title":"Линтер","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) **Обычно:** \"UNSPECIFIED\", \"UNKNOWN\", \"DEFAULT\"","content":"enum_zero_value_suffix (string) **Обычно:** \"UNSPECIFIED\", \"UNKNOWN\", \"DEFAULT\""},{"id":"cli/linter/linter::enum_zero_value_suffix-string::11","title":"Линтер","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)","content":"enum_zero_value_suffix (string)"},{"id":"cli/linter/linter::service_suffix-string::12","title":"Линтер","section":"service_suffix (string)","path":"/docs/guide/cli/linter/linter#service_suffix-string","headings":["service_suffix (string)"],"excerpt":"service_suffix (string) Требуемый суффикс для имён сервисов (унификация стиля).","content":"service_suffix (string) Требуемый суффикс для имён сервисов (унификация стиля)."},{"id":"cli/linter/linter::ignore-string::13","title":"Линтер","section":"ignore ([]string)","path":"/docs/guide/cli/linter/linter#ignore-string","headings":["ignore ([]string)"],"excerpt":"ignore ([]string) Полное исключение путей из линтинга.","content":"ignore ([]string) Полное исключение путей из линтинга."},{"id":"cli/linter/linter::ignore-string::14","title":"Линтер","section":"ignore ([]string)","path":"/docs/guide/cli/linter/linter#ignore-string","headings":["ignore ([]string)"],"excerpt":"ignore ([]string) **Use cases:** vendor / third_party сгенерированные файлы легаси подпакеты тестовые фикстуры","content":"ignore ([]string) **Use cases:** vendor / third_party сгенерированные файлы легаси подпакеты тестовые фикстуры"},{"id":"cli/linter/linter::except-string::15","title":"Линтер","section":"except ([]string)","path":"/docs/guide/cli/linter/linter#except-string","headings":["except ([]string)"],"excerpt":"except ([]string) Глобально отключает правила.","content":"except ([]string) Глобально отключает правила."},{"id":"cli/linter/linter::allow_comment_ignores-bool::16","title":"Линтер","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) Разрешает инлайн‑игнор правил комментариями.","content":"allow_comment_ignores (bool) Разрешает инлайн‑игнор правил комментариями."},{"id":"cli/linter/linter::ignore_only-mapstringstring::17","title":"Линтер","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) Таргетированное игнорирование конкретных правил для указанных путей.","content":"ignore_only (mapstringstring) Таргетированное игнорирование конкретных правил для указанных путей."},{"id":"cli/linter/linter::top::18","title":"Линтер","section":"Игнор правил комментариями","path":"/docs/guide/cli/linter/linter","headings":["Игнор правил комментариями"],"excerpt":"Игнор правил комментариями Если включён allow_comment_ignores, можно точечно отключать правила.","content":"Игнор правил комментариями Если включён allow_comment_ignores, можно точечно отключать правила."},{"id":"cli/linter/linter::top::19","title":"Линтер","section":"Несколько правил в одной строке","path":"/docs/guide/cli/linter/linter","headings":["Несколько правил в одной строке"],"excerpt":"Несколько правил в одной строке","content":"Несколько правил в одной строке"},{"id":"cli/linter/linter::top::20","title":"Линтер","section":"Используйте редко","path":"/docs/guide/cli/linter/linter","headings":["Используйте редко"],"excerpt":"Используйте редко Частое игнорирование = сигнал пересмотреть конфигурацию.","content":"Используйте редко Частое игнорирование = сигнал пересмотреть конфигурацию."},{"id":"cli/linter/linter::top::21","title":"Линтер","section":"Предпочитайте конфигурацию","path":"/docs/guide/cli/linter/linter","headings":["Предпочитайте конфигурацию"],"excerpt":"Предпочитайте конфигурацию Если нужно игнорировать правило в группе файлов — используйте ignore_only.","content":"Предпочитайте конфигурацию Если нужно игнорировать правило в группе файлов — используйте ignore_only."},{"id":"cli/linter/linter::top::22","title":"Линтер","section":"Категории линтера","path":"/docs/guide/cli/linter/linter","headings":["Категории линтера"],"excerpt":"Категории линтера Категории помогают быстро выбрать уровень строгости.","content":"Категории линтера Категории помогают быстро выбрать уровень строгости."},{"id":"cli/linter/linter::top::23","title":"Линтер","section":"Категории линтера","path":"/docs/guide/cli/linter/linter","headings":["Категории линтера"],"excerpt":"Категории линтера **Когда использовать:** **MINIMAL**: Минимальная базовая целостность **BASIC**: Частые соглашения имен **DEFAULT**: Дополнительные проверки качества **COMMENTS**: Обязательные комментарии (API, команды)","content":"Категории линтера **Когда использовать:** **MINIMAL**: Минимальная базовая целостность **BASIC**: Частые соглашения имен **DEFAULT**: Дополнительные проверки качества **COMMENTS**: Обязательные комментарии (API, команды) **UNARY_RPC**: Ограничить streaming RPC"},{"id":"cli/linter/linter::minimal::24","title":"Линтер","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::25","title":"Линтер","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::26","title":"Линтер","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::27","title":"Линтер","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::28","title":"Линтер","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::top::29","title":"Линтер","section":"Заключение","path":"/docs/guide/cli/linter/linter","headings":["Заключение"],"excerpt":"Заключение Внедрение EasyP линдера для ваших proto файлов заметно улучшит workflow, качество и поддерживаемость кода. Полная совместимость с Buf позволяет командам мигрировать без боли, используя гибкую конфигурацию и мо","content":"Заключение Внедрение EasyP линдера для ваших proto файлов заметно улучшит workflow, качество и поддерживаемость кода. Полная совместимость с Buf позволяет командам мигрировать без боли, используя гибкую конфигурацию и мощные возможности из коробки."},{"id":"cli/linter/rules/comment-enum-value::top::0","title":"COMMENT_ENUM_VALUE","path":"/docs/guide/cli/linter/rules/comment-enum-value","headings":[],"excerpt":"Это правило проверяет, что все значения enum имеют комментарий.","content":"Это правило проверяет, что все значения enum имеют комментарий."},{"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 ```proto syntax = \"proto3\";","content":"Good ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/comment-enum-value::good::4","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":"Это правило проверяет, что enum имеет комментарий.","content":"Это правило проверяет, что enum имеет комментарий."},{"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":"Это правило проверяет, что все поля сообщений имеют комментарий.","content":"Это правило проверяет, что все поля сообщений имеют комментарий."},{"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":"Это правило проверяет, что message имеет комментарий.","content":"Это правило проверяет, что message имеет комментарий."},{"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 ```proto syntax = \"proto3\";","content":"Bad ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/comment-message::bad::2","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::3","title":"COMMENT_MESSAGE","section":"Good","path":"/docs/guide/cli/linter/rules/comment-message#good","headings":["Good"],"excerpt":"Good ```proto syntax = \"proto3\";","content":"Good ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/comment-message::good::4","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":"Это правило проверяет, что oneof имеет комментарий.","content":"Это правило проверяет, что oneof имеет комментарий."},{"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":"Это правило проверяет, что сервис имеет комментарий.","content":"Это правило проверяет, что сервис имеет комментарий."},{"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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **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":"Это правило проверяет, что все файлы в заданной директории находятся в одном и том же package.","content":"Это правило проверяет, что все файлы в заданной директории находятся в одном и том же 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":"Это правило проверяет, что первое значение enum равно нулю.","content":"Это правило проверяет, что первое значение enum равно нулю."},{"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 ```proto syntax = \"proto3\";","content":"Bad ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/enum-first-value-zero::bad::3","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::4","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::5","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":"Это правило проверяет, что опция allow_alias не установлена в значение true внутри enum.","content":"Это правило проверяет, что опция allow_alias не установлена в значение true внутри 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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **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":"Это правило проверяет, что имена enum написаны в стиле PascalCase.","content":"Это правило проверяет, что имена enum написаны в стиле 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":"Это правило проверяет, что все значения enum имеют префикс, совпадающий с именем enum.","content":"Это правило проверяет, что все значения enum имеют префикс, совпадающий с именем enum."},{"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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **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":"Это правило проверяет, что значения enum записаны в стиле UPPER_SNAKE_CASE.","content":"Это правило проверяет, что значения enum записаны в стиле 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":"Это правило проверяет, что все нулевые значения enum имеют суффикс _NONE или ваш кастомный (пользовательский) суффикс.","content":"Это правило проверяет, что все нулевые значения enum имеют суффикс _NONE или ваш кастомный (пользовательский) суффикс."},{"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":"**MINIMAL** **BASIC** **DEFAULT**","content":"**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":"Это правило проверяет, что имена полей сообщений записаны в стиле lower_snake_case.","content":"Это правило проверяет, что имена полей сообщений записаны в стиле 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":"Это правило проверяет, что все файлы имеют имя в формате lower_snake_case (только строчные буквы, цифры и символ подчеркивания, без пробелов и заглавных букв).","content":"Это правило проверяет, что все файлы имеют имя в формате 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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **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":"Это правило проверяет, что в proto-файле не используются public импорты (оператор import public \"...\").","content":"Это правило проверяет, что в proto-файле не используются public импорты (оператор import public \"...\")."},{"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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **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":"Это правило проверяет, что в proto‑файле не используются weak‑импорты (import weak \"...\").","content":"Это правило проверяет, что в proto‑файле не используются weak‑импорты (import weak \"...\")."},{"id":"cli/linter/rules/import-no-weak::top::2","title":"IMPORT_NO_WEAK","path":"/docs/guide/cli/linter/rules/import-no-weak","headings":[],"excerpt":"Weak import (синтаксис import weak) допустим в proto2, но его использование усложняет анализ зависимостей и может приводить к неочевидным ошибкам при генерации кода. Рекомендуется всегда использовать обычный import.","content":"Weak import (синтаксис import weak) допустим в proto2, но его использование усложняет анализ зависимостей и может приводить к неочевидным ошибкам при генерации кода. Рекомендуется всегда использовать обычный import."},{"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 ```proto syntax = \"proto2\";","content":"Bad ```proto syntax = \"proto2\";"},{"id":"cli/linter/rules/import-no-weak::bad::4","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::5","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::6","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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **MINIMAL** **BASIC** **DEFAULT**"},{"id":"cli/linter/rules/import-used::top::1","title":"IMPORT_USED","path":"/docs/guide/cli/linter/rules/import-used","headings":[],"excerpt":"Это правило проверяет, что все импорты используются в proto-файле.","content":"Это правило проверяет, что все импорты используются в proto-файле."},{"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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **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":"Это правило проверяет, что имена сообщений (message) записаны в стиле PascalCase.","content":"Это правило проверяет, что имена сообщений (message) записаны в стиле 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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **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":"Это правило проверяет, что имена oneof записаны в стиле lower_snake_case.","content":"Это правило проверяет, что имена oneof записаны в стиле 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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **MINIMAL** **BASIC** **DEFAULT**"},{"id":"cli/linter/rules/package-defined::top::1","title":"PACKAGE_DEFINED","path":"/docs/guide/cli/linter/rules/package-defined","headings":[],"excerpt":"Это правило проверяет, что во всех файлах присутствует директива package.","content":"Это правило проверяет, что во всех файлах присутствует директива package."},{"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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **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":"Это правило проверяет, что все файлы находятся в директории, имя которой соответствует имени их пакета.","content":"Это правило проверяет, что все файлы находятся в директории, имя которой соответствует имени их пакета."},{"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":"Это правило проверяет, что имена package записаны в формате lower_snake_case (строчные буквы, при необходимости цифры и символ подчеркивания, без пробелов и заглавных букв).","content":"Это правило проверяет, что имена package записаны в формате 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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **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":"Это правило проверяет, что все файлы с заданным пакетом используют одно и то же пространство имён C# (csharp_namespace).","content":"Это правило проверяет, что все файлы с заданным пакетом используют одно и то же пространство имён C# (csharp_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\"; // [!code focus] ```","content":"Good option csharp_namespace = \"Foo.Bar\"; // [!code focus] ```"},{"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 ```proto // File: pkg/bar.proto","content":"Good ```proto // File: pkg/bar.proto"},{"id":"cli/linter/rules/package-same-csharp-namespace::good::9","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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **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":"Это правило проверяет, что все файлы с данным package находятся в одной директории.","content":"Это правило проверяет, что все файлы с данным package находятся в одной директории."},{"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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **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":"Это правило проверяет, что все файлы с одним и тем же package используют одно и то же значение опции go_package.","content":"Это правило проверяет, что все файлы с одним и тем же package используют одно и то же значение опции 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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **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":"Это правило проверяет, что все файлы с одним и тем же package используют одинаковое значение опции java_package.","content":"Это правило проверяет, что все файлы с одним и тем же package используют одинаковое значение опции 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 ```proto // File: pkg/bar.proto","content":"Bad ```proto // File: pkg/bar.proto"},{"id":"cli/linter/rules/package-same-java-multiple-files::bad::6","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::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 ```proto // File: pkg/foo.proto","content":"Good ```proto // File: pkg/foo.proto"},{"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 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::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 ```proto // File: pkg/bar.proto","content":"Good ```proto // File: pkg/bar.proto"},{"id":"cli/linter/rules/package-same-java-multiple-files::good::10","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":"Это правило проверяет, что все файлы с одним и тем же package используют одно и то же значение опции java_package.","content":"Это правило проверяет, что все файлы с одним и тем же package используют одно и то же значение опции 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":"Это правило проверяет, что все файлы с одним и тем же package используют одно и то же значение опции php_namespace.","content":"Это правило проверяет, что все файлы с одним и тем же package используют одно и то же значение опции 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":"Это правило проверяет, что все файлы с одним и тем же package используют один и тот же swift_prefix.","content":"Это правило проверяет, что все файлы с одним и тем же package используют один и тот же 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":"Это правило проверяет, что суффикс версии пакета имеет формат _vX, где X — числовая версия.","content":"Это правило проверяет, что суффикс версии пакета имеет формат _vX, где X — числовая версия."},{"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":"Это правило проверяет, что RPC не использует клиентский стриминг (запрос не является stream ...).","content":"Это правило проверяет, что RPC не использует клиентский стриминг (запрос не является stream ...)."},{"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":"Это правило проверяет, что RPC не использует серверный стриминг (ответ не является stream ...).","content":"Это правило проверяет, что RPC не использует серверный стриминг (ответ не является stream ...)."},{"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":"Это правило проверяет, что все имена RPC написаны в стиле PascalCase.","content":"Это правило проверяет, что все имена RPC написаны в стиле 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":"Это правило проверяет, что все сообщения запроса и ответа RPC уникальны: для каждого метода используются собственные (не переиспользуются одинаковые пары Request / Response у разных RPC).","content":"Это правило проверяет, что все сообщения запроса и ответа RPC уникальны: для каждого метода используются собственные (не переиспользуются одинаковые пары Request / Response у разных RPC)."},{"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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **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":"Это правило проверяет, что все сообщения запроса RPC названы в формате MethodRequest.","content":"Это правило проверяет, что все сообщения запроса RPC названы в формате 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":"Это правило проверяет, что все сообщения ответа RPC названы в формате MethodResponse.","content":"Это правило проверяет, что все сообщения ответа RPC названы в формате 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":"**MINIMAL** **BASIC** **DEFAULT**","content":"**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":"Это правило проверяет, что все имена сервисов написаны в стиле PascalCase.","content":"Это правило проверяет, что все имена сервисов написаны в стиле 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":"Это правило проверяет, что все сервисы имеют суффикс Service или ваш пользовательский суффикс.","content":"Это правило проверяет, что все сервисы имеют суффикс Service или ваш пользовательский суффикс."},{"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 против Buf: управление пакетами","path":"/docs/guide/cli/package-manager/easyp-vs-buf","headings":[],"excerpt":"EasyP против Buf: управление пакетами","content":"EasyP против Buf: управление пакетами"},{"id":"cli/package-manager/easyp-vs-buf::top::1","title":"EasyP против Buf: управление пакетами","path":"/docs/guide/cli/package-manager/easyp-vs-buf","headings":[],"excerpt":"Этот документ даёт подробное сравнение децентрализованного подхода EasyP к управлению пакетами и централизованной модели Buf через Buf Schema Registry (BSR), чтобы помочь понять ключевые различия и выбрать подходящее реш","content":"Этот документ даёт подробное сравнение децентрализованного подхода EasyP к управлению пакетами и централизованной модели Buf через Buf Schema Registry (BSR), чтобы помочь понять ключевые различия и выбрать подходящее решение для ваших задач."},{"id":"cli/package-manager/easyp-vs-buf::easyp-git::2","title":"EasyP против Buf: управление пакетами","section":"EasyP: децентрализованный подход на базе Git","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp-git","headings":["EasyP: децентрализованный подход на базе Git"],"excerpt":"EasyP: децентрализованный подход на базе Git","content":"EasyP: децентрализованный подход на базе Git"},{"id":"cli/package-manager/easyp-vs-buf::buf-bsr::3","title":"EasyP против Buf: управление пакетами","section":"Buf: централизованный реестр (BSR)","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf-bsr","headings":["Buf: централизованный реестр (BSR)"],"excerpt":"Buf: централизованный реестр (BSR)","content":"Buf: централизованный реестр (BSR)"},{"id":"cli/package-manager/easyp-vs-buf::top::4","title":"EasyP против Buf: управление пакетами","section":"Краткое резюме различий","path":"/docs/guide/cli/package-manager/easyp-vs-buf","headings":["Краткое резюме различий"],"excerpt":"Краткое резюме различий Аспект EasyP Buf -------- ------- ----- **Архитектура** Децентрализованная (Git) Централизованная (реестр BSR) **Источник зависимостей** Любой Git репозиторий Только модули BSR **Единая точка отка","content":"Краткое резюме различий Аспект EasyP Buf -------- ------- ----- **Архитектура** Децентрализованная (Git) Централизованная (реестр BSR) **Источник зависимостей** Любой Git репозиторий Только модули BSR **Единая точка отказа** Нет Да (buf.build) **Enterprise / air‑gapped** Полная поддержка Требует доступа к BSR или приватного BSR **Аутентификация** Git (SSH / HTTPS) Токены Buf + Git **Vendor lock‑in** Отсутствует Привязка к экосистеме Buf **Частные репозитории** Нативно через Git Нужно опубликовать в BSR **Оффлайн поддержка** Полная (через vendoring) Ограничена (кэшированные модули) **Стоимость** Бесплатно (использует существующий Git) Бесплатный тариф + платные планы **Сложность настройки** Минимальная Средняя (настройка BSR)"},{"id":"cli/package-manager/easyp-vs-buf::top::5","title":"EasyP против Buf: управление пакетами","section":"Подробное сравнение возможностей","path":"/docs/guide/cli/package-manager/easyp-vs-buf","headings":["Подробное сравнение возможностей"],"excerpt":"Подробное сравнение возможностей","content":"Подробное сравнение возможностей"},{"id":"cli/package-manager/easyp-vs-buf::1::6","title":"EasyP против Buf: управление пакетами","section":"1. Философия управления зависимостями","path":"/docs/guide/cli/package-manager/easyp-vs-buf#1","headings":["1. Философия управления зависимостями"],"excerpt":"Философия управления зависимостями","content":"Философия управления зависимостями"},{"id":"cli/package-manager/easyp-vs-buf::easyp-git::7","title":"EasyP против Buf: управление пакетами","section":"EasyP: «Любой Git репозиторий — это пакет»","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp-git","headings":["EasyP: «Любой Git репозиторий — это пакет»"],"excerpt":"EasyP: «Любой Git репозиторий — это пакет»","content":"EasyP: «Любой Git репозиторий — это пакет»"},{"id":"cli/package-manager/easyp-vs-buf::easyp-git::8","title":"EasyP против Buf: управление пакетами","section":"EasyP: «Любой Git репозиторий — это пакет»","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp-git","headings":["EasyP: «Любой Git репозиторий — это пакет»"],"excerpt":"EasyP: «Любой Git репозиторий — это пакет» **Преимущества:** ✅ Использование любого существующего репозитория сразу ✅ Не нужно «публиковать» в отдельный реестр ✅ Истинный источник версий — Git ✅ Работает с приватными сер","content":"EasyP: «Любой Git репозиторий — это пакет» **Преимущества:** ✅ Использование любого существующего репозитория сразу ✅ Не нужно «публиковать» в отдельный реестр ✅ Истинный источник версий — Git ✅ Работает с приватными серверами без доп. настроек"},{"id":"cli/package-manager/easyp-vs-buf::buf::9","title":"EasyP против Buf: управление пакетами","section":"Buf: «Сначала реестр»","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf","headings":["Buf: «Сначала реестр»"],"excerpt":"Buf: «Сначала реестр» **Преимущества:** ✅ Курируемые, проверенные модули ✅ Богатые метаданные и документация ✅ Визуализация графа зависимостей ✅ Принуждение семантического версионирования","content":"Buf: «Сначала реестр» **Преимущества:** ✅ Курируемые, проверенные модули ✅ Богатые метаданные и документация ✅ Визуализация графа зависимостей ✅ Принуждение семантического версионирования"},{"id":"cli/package-manager/easyp-vs-buf::buf::10","title":"EasyP против Buf: управление пакетами","section":"Buf: «Сначала реестр»","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf","headings":["Buf: «Сначала реестр»"],"excerpt":"Buf: «Сначала реестр» **Ограничения:** ❌ Нужно опубликовать в BSR перед использованием ❌ Требует аккаунт и аутентификацию ❌ Нельзя напрямую сослаться на произвольный Git репозиторий","content":"Buf: «Сначала реестр» **Ограничения:** ❌ Нужно опубликовать в BSR перед использованием ❌ Требует аккаунт и аутентификацию ❌ Нельзя напрямую сослаться на произвольный Git репозиторий"},{"id":"cli/package-manager/easyp-vs-buf::2-airgapped::11","title":"EasyP против Buf: управление пакетами","section":"2. Корпоративные и изолированные (air‑gapped) среды","path":"/docs/guide/cli/package-manager/easyp-vs-buf#2-airgapped","headings":["2. Корпоративные и изолированные (air‑gapped) среды"],"excerpt":"Корпоративные и изолированные (air‑gapped) среды","content":"Корпоративные и изолированные (air‑gapped) среды"},{"id":"cli/package-manager/easyp-vs-buf::easyp::12","title":"EasyP против Buf: управление пакетами","section":"EasyP: Полноценная оффлайн‑поддержка","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["EasyP: Полноценная оффлайн‑поддержка"],"excerpt":"EasyP: Полноценная оффлайн‑поддержка **Сценарий**: крупная компания со строгими сетевыми политиками","content":"EasyP: Полноценная оффлайн‑поддержка **Сценарий**: крупная компания со строгими сетевыми политиками"},{"id":"cli/package-manager/easyp-vs-buf::easyp::13","title":"EasyP против Buf: управление пакетами","section":"EasyP: Полноценная оффлайн‑поддержка","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["EasyP: Полноценная оффлайн‑поддержка"],"excerpt":"EasyP: Полноценная оффлайн‑поддержка ```bash Среда с доступом в интернет easyp mod download # Скачивает в ~/.easyp/ easyp mod vendor # Создает easyp_vendor/","content":"EasyP: Полноценная оффлайн‑поддержка ```bash Среда с доступом в интернет easyp mod download # Скачивает в ~/.easyp/ easyp mod vendor # Создает easyp_vendor/"},{"id":"cli/package-manager/easyp-vs-buf::easyp::14","title":"EasyP против Buf: управление пакетами","section":"EasyP: Полноценная оффлайн‑поддержка","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["EasyP: Полноценная оффлайн‑поддержка"],"excerpt":"EasyP: Полноценная оффлайн‑поддержка Перенос в изолированный сегмент tar -czf easyp-deps.tar.gz ~/.easyp easyp_vendor/ ... перенос архива ...","content":"EasyP: Полноценная оффлайн‑поддержка Перенос в изолированный сегмент tar -czf easyp-deps.tar.gz ~/.easyp easyp_vendor/ ... перенос архива ..."},{"id":"cli/package-manager/easyp-vs-buf::easyp::15","title":"EasyP против Buf: управление пакетами","section":"EasyP: Полноценная оффлайн‑поддержка","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["EasyP: Полноценная оффлайн‑поддержка"],"excerpt":"EasyP: Полноценная оффлайн‑поддержка В изолированной среде tar -xzf easyp-deps.tar.gz export EASYPPATH=$PWD/.easyp easyp generate # Работает оффлайн ```","content":"EasyP: Полноценная оффлайн‑поддержка В изолированной среде tar -xzf easyp-deps.tar.gz export EASYPPATH=$PWD/.easyp easyp generate # Работает оффлайн ```"},{"id":"cli/package-manager/easyp-vs-buf::easyp::16","title":"EasyP против Buf: управление пакетами","section":"EasyP: Полноценная оффлайн‑поддержка","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["EasyP: Полноценная оффлайн‑поддержка"],"excerpt":"EasyP: Полноценная оффлайн‑поддержка **Плюсы:** ✅ Не зависит от внешних сервисов ✅ Не нужен внутренний реестр ✅ Использует существующую Git инфраструктуру ✅ Простая файловая дистрибуция","content":"EasyP: Полноценная оффлайн‑поддержка **Плюсы:** ✅ Не зависит от внешних сервисов ✅ Не нужен внутренний реестр ✅ Использует существующую Git инфраструктуру ✅ Простая файловая дистрибуция"},{"id":"cli/package-manager/easyp-vs-buf::buf::17","title":"EasyP против Buf: управление пакетами","section":"Buf: Требует инфраструктуру реестра","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf","headings":["Buf: Требует инфраструктуру реестра"],"excerpt":"Buf: Требует инфраструктуру реестра ```bash Вариант 1: использовать buf.build (нужен интернет) buf mod download","content":"Buf: Требует инфраструктуру реестра ```bash Вариант 1: использовать buf.build (нужен интернет) buf mod download"},{"id":"cli/package-manager/easyp-vs-buf::buf::18","title":"EasyP против Buf: управление пакетами","section":"Buf: Требует инфраструктуру реестра","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf","headings":["Buf: Требует инфраструктуру реестра"],"excerpt":"Buf: Требует инфраструктуру реестра Вариант 2: поднимать приватный BSR (сложно) Развернуть сервер реестра Перепубликовать все модули внутрь Настроить доступы, аутентификацию Поддерживать работоспособность ```","content":"Buf: Требует инфраструктуру реестра Вариант 2: поднимать приватный BSR (сложно) Развернуть сервер реестра Перепубликовать все модули внутрь Настроить доступы, аутентификацию Поддерживать работоспособность ```"},{"id":"cli/package-manager/easyp-vs-buf::buf::19","title":"EasyP против Buf: управление пакетами","section":"Buf: Требует инфраструктуру реестра","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf","headings":["Buf: Требует инфраструктуру реестра"],"excerpt":"Buf: Требует инфраструктуру реестра **Минусы:** ❌ Постоянный интернет или дорогой приватный BSR ❌ Сложная инфраструктура для частных установок ❌ Все модули нужно републиковать ❌ Дополнительные операционные затраты","content":"Buf: Требует инфраструктуру реестра **Минусы:** ❌ Постоянный интернет или дорогой приватный BSR ❌ Сложная инфраструктура для частных установок ❌ Все модули нужно републиковать ❌ Дополнительные операционные затраты"},{"id":"cli/package-manager/easyp-vs-buf::easyp::20","title":"EasyP против Buf: управление пакетами","section":"EasyP: Прямой контроль","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["EasyP: Прямой контроль"],"excerpt":"EasyP: Прямой контроль ```yaml Полный контроль источников deps: # Публичный репозиторий — ваша конкретная версия - github.com/googleapis/googleapis@common-protos-1_3_1","content":"EasyP: Прямой контроль ```yaml Полный контроль источников deps: # Публичный репозиторий — ваша конкретная версия - github.com/googleapis/googleapis@common-protos-1_3_1"},{"id":"cli/package-manager/easyp-vs-buf::easyp::21","title":"EasyP против Buf: управление пакетами","section":"EasyP: Прямой контроль","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["EasyP: Прямой контроль"],"excerpt":"EasyP: Прямой контроль Внутренний репозиторий - gitlab.company.com/security/validated-protos@v1.0.0","content":"EasyP: Прямой контроль Внутренний репозиторий - gitlab.company.com/security/validated-protos@v1.0.0"},{"id":"cli/package-manager/easyp-vs-buf::easyp::22","title":"EasyP против Buf: управление пакетами","section":"EasyP: Прямой контроль","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["EasyP: Прямой контроль"],"excerpt":"EasyP: Прямой контроль Точный коммит (горячий фикс) - github.com/bufbuild/protoc-gen-validate@abc123def456 ```","content":"EasyP: Прямой контроль Точный коммит (горячий фикс) - github.com/bufbuild/protoc-gen-validate@abc123def456 ```"},{"id":"cli/package-manager/easyp-vs-buf::easyp::23","title":"EasyP против Buf: управление пакетами","section":"EasyP: Прямой контроль","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["EasyP: Прямой контроль"],"excerpt":"EasyP: Прямой контроль **Преимущества по безопасности:** ✅ Нет посредника — берём из исходного репозитория ✅ Аудит через историю Git ✅ Нельзя «забанить» доступ извне ✅ Свои процессы сканирования / валидации ✅ Можно форкн","content":"EasyP: Прямой контроль **Преимущества по безопасности:** ✅ Нет посредника — берём из исходного репозитория ✅ Аудит через историю Git ✅ Нельзя «забанить» доступ извне ✅ Свои процессы сканирования / валидации ✅ Можно форкнуть и удерживать критические версии"},{"id":"cli/package-manager/easyp-vs-buf::buf::24","title":"EasyP против Buf: управление пакетами","section":"Buf: Зависимость от реестра","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf","headings":["Buf: Зависимость от реестра"],"excerpt":"Buf: Зависимость от реестра **Риски:** ⚠️ Посредник контролирует доступность ⚠️ Возможны ограничения / санкции на аккаунт ⚠️ Модуль могут удалить или депрекейтнуть ⚠️ Политики обновлений диктуются стороной ⚠️ Нужно довер","content":"Buf: Зависимость от реестра **Риски:** ⚠️ Посредник контролирует доступность ⚠️ Возможны ограничения / санкции на аккаунт ⚠️ Модуль могут удалить или депрекейтнуть ⚠️ Политики обновлений диктуются стороной ⚠️ Нужно доверять внешней безопасности"},{"id":"cli/package-manager/easyp-vs-buf::1::25","title":"EasyP против Buf: управление пакетами","section":"Сценарий 1: Стартап с публичными зависимостями","path":"/docs/guide/cli/package-manager/easyp-vs-buf#1","headings":["Сценарий 1: Стартап с публичными зависимостями"],"excerpt":"Сценарий 1: Стартап с публичными зависимостями **EasyP:**","content":"Сценарий 1: Стартап с публичными зависимостями **EasyP:**"},{"id":"cli/package-manager/easyp-vs-buf::1::26","title":"EasyP против Buf: управление пакетами","section":"Сценарий 1: Стартап с публичными зависимостями","path":"/docs/guide/cli/package-manager/easyp-vs-buf#1","headings":["Сценарий 1: Стартап с публичными зависимостями"],"excerpt":"Сценарий 1: Стартап с публичными зависимостями **Buf:**","content":"Сценарий 1: Стартап с публичными зависимостями **Buf:**"},{"id":"cli/package-manager/easyp-vs-buf::1::27","title":"EasyP против Buf: управление пакетами","section":"Сценарий 1: Стартап с публичными зависимостями","path":"/docs/guide/cli/package-manager/easyp-vs-buf#1","headings":["Сценарий 1: Стартап с публичными зависимостями"],"excerpt":"Сценарий 1: Стартап с публичными зависимостями **Итог:** Паритет — оба хорошо подходят для публичных пакетов.","content":"Сценарий 1: Стартап с публичными зависимостями **Итог:** Паритет — оба хорошо подходят для публичных пакетов."},{"id":"cli/package-manager/easyp-vs-buf::2::28","title":"EasyP против Buf: управление пакетами","section":"Сценарий 2: Компания со смешанными публичными/приватными зависимостями","path":"/docs/guide/cli/package-manager/easyp-vs-buf#2","headings":["Сценарий 2: Компания со смешанными публичными/приватными зависимостями"],"excerpt":"Сценарий 2: Компания со смешанными публичными/приватными зависимостями **EasyP:**","content":"Сценарий 2: Компания со смешанными публичными/приватными зависимостями **EasyP:**"},{"id":"cli/package-manager/easyp-vs-buf::2::29","title":"EasyP против Buf: управление пакетами","section":"Сценарий 2: Компания со смешанными публичными/приватными зависимостями","path":"/docs/guide/cli/package-manager/easyp-vs-buf#2","headings":["Сценарий 2: Компания со смешанными публичными/приватными зависимостями"],"excerpt":"Сценарий 2: Компания со смешанными публичными/приватными зависимостями **Buf:**","content":"Сценарий 2: Компания со смешанными публичными/приватными зависимостями **Buf:**"},{"id":"cli/package-manager/easyp-vs-buf::2::30","title":"EasyP против Buf: управление пакетами","section":"Сценарий 2: Компания со смешанными публичными/приватными зависимостями","path":"/docs/guide/cli/package-manager/easyp-vs-buf#2","headings":["Сценарий 2: Компания со смешанными публичными/приватными зависимостями"],"excerpt":"Сценарий 2: Компания со смешанными публичными/приватными зависимостями **Итог:** **EasyP** — не требует публикации внутрь BSR.","content":"Сценарий 2: Компания со смешанными публичными/приватными зависимостями **Итог:** **EasyP** — не требует публикации внутрь BSR."},{"id":"cli/package-manager/easyp-vs-buf::3-airgap::31","title":"EasyP против Buf: управление пакетами","section":"Сценарий 3: Государственный / оборонный подрядчик (полный air‑gap)","path":"/docs/guide/cli/package-manager/easyp-vs-buf#3-airgap","headings":["Сценарий 3: Государственный / оборонный подрядчик (полный air‑gap)"],"excerpt":"Сценарий 3: Государственный / оборонный подрядчик (полный air‑gap) **EasyP:**","content":"Сценарий 3: Государственный / оборонный подрядчик (полный air‑gap) **EasyP:**"},{"id":"cli/package-manager/easyp-vs-buf::3-airgap::32","title":"EasyP против Buf: управление пакетами","section":"Сценарий 3: Государственный / оборонный подрядчик (полный air‑gap)","path":"/docs/guide/cli/package-manager/easyp-vs-buf#3-airgap","headings":["Сценарий 3: Государственный / оборонный подрядчик (полный air‑gap)"],"excerpt":"Сценарий 3: Государственный / оборонный подрядчик (полный air‑gap) **Buf:**","content":"Сценарий 3: Государственный / оборонный подрядчик (полный air‑gap) **Buf:**"},{"id":"cli/package-manager/easyp-vs-buf::3-airgap::33","title":"EasyP против Buf: управление пакетами","section":"Сценарий 3: Государственный / оборонный подрядчик (полный air‑gap)","path":"/docs/guide/cli/package-manager/easyp-vs-buf#3-airgap","headings":["Сценарий 3: Государственный / оборонный подрядчик (полный air‑gap)"],"excerpt":"Сценарий 3: Государственный / оборонный подрядчик (полный air‑gap) **Итог:** **EasyP** — значительно проще.","content":"Сценарий 3: Государственный / оборонный подрядчик (полный air‑gap) **Итог:** **EasyP** — значительно проще."},{"id":"cli/package-manager/easyp-vs-buf::4::34","title":"EasyP против Buf: управление пакетами","section":"Сценарий 4: Комплаенс и аудит","path":"/docs/guide/cli/package-manager/easyp-vs-buf#4","headings":["Сценарий 4: Комплаенс и аудит"],"excerpt":"Сценарий 4: Комплаенс и аудит **EasyP:** ✅ Прямой аудит изменений (коммиты) ✅ Нет внешних точек зависимости в проде ✅ Повторяемость через фиксированные коммиты / vendor ✅ Управление уязвимостями — в ваших руках","content":"Сценарий 4: Комплаенс и аудит **EasyP:** ✅ Прямой аудит изменений (коммиты) ✅ Нет внешних точек зависимости в проде ✅ Повторяемость через фиксированные коммиты / vendor ✅ Управление уязвимостями — в ваших руках"},{"id":"cli/package-manager/easyp-vs-buf::4::35","title":"EasyP против Buf: управление пакетами","section":"Сценарий 4: Комплаенс и аудит","path":"/docs/guide/cli/package-manager/easyp-vs-buf#4","headings":["Сценарий 4: Комплаенс и аудит"],"excerpt":"Сценарий 4: Комплаенс и аудит **Buf:** ⚠️ Нужно учитывать BSR в области аудита ⚠️ Дополнительный риск третьей стороны ⚠️ Модули — внешние контролируемые артефакты ⚠️ Сложнее трассировать от реестра к исходникам","content":"Сценарий 4: Комплаенс и аудит **Buf:** ⚠️ Нужно учитывать BSR в области аудита ⚠️ Дополнительный риск третьей стороны ⚠️ Модули — внешние контролируемые артефакты ⚠️ Сложнее трассировать от реестра к исходникам"},{"id":"cli/package-manager/easyp-vs-buf::4::36","title":"EasyP против Buf: управление пакетами","section":"Сценарий 4: Комплаенс и аудит","path":"/docs/guide/cli/package-manager/easyp-vs-buf#4","headings":["Сценарий 4: Комплаенс и аудит"],"excerpt":"Сценарий 4: Комплаенс и аудит **Итог:** **EasyP** — проще для комплаенса.","content":"Сценарий 4: Комплаенс и аудит **Итог:** **EasyP** — проще для комплаенса."},{"id":"cli/package-manager/easyp-vs-buf::easyp::37","title":"EasyP против Buf: управление пакетами","section":"EasyP: Нулевая дополнительная инфраструктура","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["EasyP: Нулевая дополнительная инфраструктура"],"excerpt":"EasyP: Нулевая дополнительная инфраструктура **Затраты:** ✅ $0 — используете существующий Git ✅ Нет дополнительных сервисов/серверов ✅ Нет лицензирования ✅ Масштабирование в рамках Git","content":"EasyP: Нулевая дополнительная инфраструктура **Затраты:** ✅ $0 — используете существующий Git ✅ Нет дополнительных сервисов/серверов ✅ Нет лицензирования ✅ Масштабирование в рамках Git"},{"id":"cli/package-manager/easyp-vs-buf::easyp::38","title":"EasyP против Buf: управление пакетами","section":"EasyP: Нулевая дополнительная инфраструктура","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["EasyP: Нулевая дополнительная инфраструктура"],"excerpt":"EasyP: Нулевая дополнительная инфраструктура **Инфраструктура:** Использует текущие репозитории (GitHub/GitLab/и т.д.) Аутентификация — штатная Резервирование/DR — как уже настроено для Git","content":"EasyP: Нулевая дополнительная инфраструктура **Инфраструктура:** Использует текущие репозитории (GitHub/GitLab/и т.д.) Аутентификация — штатная Резервирование/DR — как уже настроено для Git"},{"id":"cli/package-manager/easyp-vs-buf::buf::39","title":"EasyP против Buf: управление пакетами","section":"Buf: Затраты на реестр","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf","headings":["Buf: Затраты на реестр"],"excerpt":"Buf: Затраты на реестр **Hosted BSR (buf.build):** ✅ Бесплатный уровень ❌ Платные тарифы для приватного и расширенного использования ❌ Потенциальные изменения ценовой политики ❌ Вопросы локализации данных","content":"Buf: Затраты на реестр **Hosted BSR (buf.build):** ✅ Бесплатный уровень ❌ Платные тарифы для приватного и расширенного использования ❌ Потенциальные изменения ценовой политики ❌ Вопросы локализации данных"},{"id":"cli/package-manager/easyp-vs-buf::buf::40","title":"EasyP против Buf: управление пакетами","section":"Buf: Затраты на реестр","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf","headings":["Buf: Затраты на реестр"],"excerpt":"Buf: Затраты на реестр **Приватный BSR:** ❌ Серверы, БД, балансировка ❌ Мониторинг, обновления, бэкапы ❌ Лицензирование enterprise функционала ❌ Доп. планирование отказоустойчивости","content":"Buf: Затраты на реестр **Приватный BSR:** ❌ Серверы, БД, балансировка ❌ Мониторинг, обновления, бэкапы ❌ Лицензирование enterprise функционала ❌ Доп. планирование отказоустойчивости"},{"id":"cli/package-manager/easyp-vs-buf::easyp::41","title":"EasyP против Buf: управление пакетами","section":"EasyP: Нет привязки","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["EasyP: Нет привязки"],"excerpt":"EasyP: Нет привязки **Миграция ИЗ EasyP:** (Обычные Git ссылки — легко перенести в другой инструмент.)","content":"EasyP: Нет привязки **Миграция ИЗ EasyP:** (Обычные Git ссылки — легко перенести в другой инструмент.)"},{"id":"cli/package-manager/easyp-vs-buf::easyp::42","title":"EasyP против Buf: управление пакетами","section":"EasyP: Нет привязки","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["EasyP: Нет привязки"],"excerpt":"EasyP: Нет привязки **Миграция В EasyP:**","content":"EasyP: Нет привязки **Миграция В EasyP:**"},{"id":"cli/package-manager/easyp-vs-buf::buf-lockin::43","title":"EasyP против Buf: управление пакетами","section":"Buf: Потенциальный lock‑in","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf-lockin","headings":["Buf: Потенциальный lock‑in"],"excerpt":"Buf: Потенциальный lock‑in **Миграция ИЗ Buf:** ❌ Нужно сопоставить BSR модули с исходными Git репо ❌ Имена модулей BSR не совпадают с URL ❌ Возможна потеря удобных метаданных ❌ Сложно при глубокой интеграции с BSR","content":"Buf: Потенциальный lock‑in **Миграция ИЗ Buf:** ❌ Нужно сопоставить BSR модули с исходными Git репо ❌ Имена модулей BSR не совпадают с URL ❌ Возможна потеря удобных метаданных ❌ Сложно при глубокой интеграции с BSR"},{"id":"cli/package-manager/easyp-vs-buf::buf-lockin::44","title":"EasyP против Buf: управление пакетами","section":"Buf: Потенциальный lock‑in","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf-lockin","headings":["Buf: Потенциальный lock‑in"],"excerpt":"Buf: Потенциальный lock‑in **Миграция В Buf:** ❌ Нужно опубликовать всё в BSR ❌ Нельзя ссылаться напрямую на Git ❌ Принять workflow BSR (push/pull модулей)","content":"Buf: Потенциальный lock‑in **Миграция В Buf:** ❌ Нужно опубликовать всё в BSR ❌ Нельзя ссылаться напрямую на Git ❌ Принять workflow BSR (push/pull модулей)"},{"id":"cli/package-manager/easyp-vs-buf::easyp::45","title":"EasyP против Buf: управление пакетами","section":"Выберите EasyP, если:","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["Выберите EasyP, если:"],"excerpt":"Выберите EasyP, если: ✅ **Air‑gapped / закрытые среды** Нужна работа без внешних сервисов Строгий комплаенс / контроль цепочки поставок","content":"Выберите EasyP, если: ✅ **Air‑gapped / закрытые среды** Нужна работа без внешних сервисов Строгий комплаенс / контроль цепочки поставок"},{"id":"cli/package-manager/easyp-vs-buf::easyp::46","title":"EasyP против Buf: управление пакетами","section":"Выберите EasyP, если:","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["Выберите EasyP, если:"],"excerpt":"Выберите EasyP, если: ✅ **Фокус на безопасности** Контроль источников зависимостей Минимизация рисков третьих сторон","content":"Выберите EasyP, если: ✅ **Фокус на безопасности** Контроль источников зависимостей Минимизация рисков третьих сторон"},{"id":"cli/package-manager/easyp-vs-buf::easyp::47","title":"EasyP против Buf: управление пакетами","section":"Выберите EasyP, если:","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["Выберите EasyP, если:"],"excerpt":"Выберите EasyP, если: ✅ **Git‑центричная культура** Частные репозитории — норма Не хотите добавлять новый ключевой сервис","content":"Выберите EasyP, если: ✅ **Git‑центричная культура** Частные репозитории — норма Не хотите добавлять новый ключевой сервис"},{"id":"cli/package-manager/easyp-vs-buf::easyp::48","title":"EasyP против Buf: управление пакетами","section":"Выберите EasyP, если:","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["Выберите EasyP, если:"],"excerpt":"Выберите EasyP, если: ✅ **Ограниченный бюджет** Минимизация операционных расходов Предсказуемая стоимость = 0","content":"Выберите EasyP, если: ✅ **Ограниченный бюджет** Минимизация операционных расходов Предсказуемая стоимость = 0"},{"id":"cli/package-manager/easyp-vs-buf::easyp::49","title":"EasyP против Buf: управление пакетами","section":"Выберите EasyP, если:","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["Выберите EasyP, если:"],"excerpt":"Выберите EasyP, если: ✅ **Смешанные публичные/частные зависимости** Не хотите перекладывать всё в реестр Нужна гибкость форматов и размещения","content":"Выберите EasyP, если: ✅ **Смешанные публичные/частные зависимости** Не хотите перекладывать всё в реестр Нужна гибкость форматов и размещения"},{"id":"cli/package-manager/easyp-vs-buf::buf::50","title":"EasyP против Buf: управление пакетами","section":"Выберите Buf, если:","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf","headings":["Выберите Buf, если:"],"excerpt":"Выберите Buf, если: ✅ **Глубокая интеграция в экосистему BSR** Уже используете линтеры / генерацию Buf Нужны курируемые официальные модули Важны метаданные и граф зависимостей","content":"Выберите Buf, если: ✅ **Глубокая интеграция в экосистему BSR** Уже используете линтеры / генерацию Buf Нужны курируемые официальные модули Важны метаданные и граф зависимостей"},{"id":"cli/package-manager/easyp-vs-buf::buf::51","title":"EasyP против Buf: управление пакетами","section":"Выберите Buf, если:","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf","headings":["Выберите Buf, если:"],"excerpt":"Выберите Buf, если: ✅ **Сотрудничество и открытая разработка** Централизованное обнаружение модулей Совместная работа над общими пакетами","content":"Выберите Buf, если: ✅ **Сотрудничество и открытая разработка** Централизованное обнаружение модулей Совместная работа над общими пакетами"},{"id":"cli/package-manager/easyp-vs-buf::buf::52","title":"EasyP против Buf: управление пакетами","section":"Выберите Buf, если:","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf","headings":["Выберите Buf, если:"],"excerpt":"Выберите Buf, если: ✅ **Команда новичков в protobuf** Требуется «направляющая» структура Ценность документации внутри реестра","content":"Выберите Buf, если: ✅ **Команда новичков в protobuf** Требуется «направляющая» структура Ценность документации внутри реестра"},{"id":"cli/package-manager/easyp-vs-buf::buf::53","title":"EasyP против Buf: управление пакетами","section":"Выберите Buf, если:","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf","headings":["Выберите Buf, если:"],"excerpt":"Выберите Buf, если: ✅ **Небольшой набор публичных зависимостей** В основном используете популярные общие пакеты Вас устраивает зависимость от BSR","content":"Выберите Buf, если: ✅ **Небольшой набор публичных зависимостей** В основном используете популярные общие пакеты Вас устраивает зависимость от BSR"},{"id":"cli/package-manager/easyp-vs-buf::buf-easyp::54","title":"EasyP против Buf: управление пакетами","section":"Переход с Buf на EasyP","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf-easyp","headings":["Переход с Buf на EasyP"],"excerpt":"Переход с Buf на EasyP Найдите исходные Git репозитории для каждого модуля BSR Сопоставьте имена BSR → Git ссылки (с версиями/тегами) Обновите конфигурацию (easyp.yaml) Протестируйте генерацию и совместимость","content":"Переход с Buf на EasyP Найдите исходные Git репозитории для каждого модуля BSR Сопоставьте имена BSR → Git ссылки (с версиями/тегами) Обновите конфигурацию (easyp.yaml) Протестируйте генерацию и совместимость"},{"id":"cli/package-manager/easyp-vs-buf::buf-easyp::55","title":"EasyP против Buf: управление пакетами","section":"Переход с Buf на EasyP","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf-easyp","headings":["Переход с Buf на EasyP"],"excerpt":"Переход с Buf на EasyP ```yaml Было (buf.yaml) deps: - buf.build/googleapis/googleapis - buf.build/grpc/grpc","content":"Переход с Buf на EasyP ```yaml Было (buf.yaml) deps: - buf.build/googleapis/googleapis - buf.build/grpc/grpc"},{"id":"cli/package-manager/easyp-vs-buf::buf-easyp::56","title":"EasyP против Buf: управление пакетами","section":"Переход с Buf на EasyP","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf-easyp","headings":["Переход с Buf на EasyP"],"excerpt":"Переход с Buf на EasyP Стало (easyp.yaml) deps: - github.com/googleapis/googleapis@common-protos-1_3_1 - github.com/grpc/grpc@v1.50.0 ```","content":"Переход с Buf на EasyP Стало (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::easyp-buf::57","title":"EasyP против Buf: управление пакетами","section":"Переход с EasyP на Buf","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp-buf","headings":["Переход с EasyP на Buf"],"excerpt":"Переход с EasyP на Buf Опубликуйте используемые репозитории как модули BSR Настройте аутентификацию / организацию Buf Замените Git ссылки на BSR модули Перейдите к push/pull workflow Buf","content":"Переход с EasyP на Buf Опубликуйте используемые репозитории как модули BSR Настройте аутентификацию / организацию Buf Замените Git ссылки на BSR модули Перейдите к push/pull workflow Buf"},{"id":"cli/package-manager/easyp-vs-buf::top::58","title":"EasyP против Buf: управление пакетами","section":"Заключение","path":"/docs/guide/cli/package-manager/easyp-vs-buf","headings":["Заключение"],"excerpt":"Заключение Оба инструмента решают задачу управления зависимостями protobuf, но подходят под разные приоритеты:","content":"Заключение Оба инструмента решают задачу управления зависимостями protobuf, но подходят под разные приоритеты:"},{"id":"cli/package-manager/easyp-vs-buf::top::59","title":"EasyP против Buf: управление пакетами","section":"Заключение","path":"/docs/guide/cli/package-manager/easyp-vs-buf","headings":["Заключение"],"excerpt":"Заключение **Сильные стороны EasyP:** Корпоративные / изолированные среды Жёсткие требования безопасности и аудита Минимальные затраты и отсутствие доп. инфраструктуры Прямое использование Git (без промежуточного слоя) П","content":"Заключение **Сильные стороны EasyP:** Корпоративные / изолированные среды Жёсткие требования безопасности и аудита Минимальные затраты и отсутствие доп. инфраструктуры Прямое использование Git (без промежуточного слоя) Простота масштабирования"},{"id":"cli/package-manager/easyp-vs-buf::top::60","title":"EasyP против Buf: управление пакетами","section":"Заключение","path":"/docs/guide/cli/package-manager/easyp-vs-buf","headings":["Заключение"],"excerpt":"Заключение **Сильные стороны Buf:** Богатая экосистема вокруг реестра Курируемые и документированные модули Удобство для новых команд в protobuf Средства визуализации и централизованного обмена","content":"Заключение **Сильные стороны Buf:** Богатая экосистема вокруг реестра Курируемые и документированные модули Удобство для новых команд в protobuf Средства визуализации и централизованного обмена"},{"id":"cli/package-manager/easyp-vs-buf::top::61","title":"EasyP против Buf: управление пакетами","section":"Заключение","path":"/docs/guide/cli/package-manager/easyp-vs-buf","headings":["Заключение"],"excerpt":"Заключение Выбор часто сводится к балансу между **контролем vs. удобством**, **безопасностью vs. централизованными функциями**, и **стоимостью vs. managed‑сервисом**.","content":"Заключение Выбор часто сводится к балансу между **контролем vs. удобством**, **безопасностью vs. централизованными функциями**, и **стоимостью vs. managed‑сервисом**."},{"id":"cli/package-manager/easyp-vs-buf::top::62","title":"EasyP против Buf: управление пакетами","section":"Заключение","path":"/docs/guide/cli/package-manager/easyp-vs-buf","headings":["Заключение"],"excerpt":"Заключение Для большинства enterprise‑окружений децентрализованный Git‑подход EasyP обеспечивает нужные гибкость, безопасность и предсказуемость расходов, тогда как Buf отлично подходит командам, которым важна централизо","content":"Заключение Для большинства enterprise‑окружений децентрализованный Git‑подход EasyP обеспечивает нужные гибкость, безопасность и предсказуемость расходов, тогда как Buf отлично подходит командам, которым важна централизованная коллаборация и богатая экосистема вокруг реестра."},{"id":"cli/package-manager/package-manager::top::0","title":"Менеджер пакетов","path":"/docs/guide/cli/package-manager/package-manager","headings":[],"excerpt":"EasyP предоставляет мощный менеджер пакетов для protobuf‑зависимостей, упрощающий их управление за счёт децентрализованного подхода на базе Git. В отличие от централизованных решений, EasyP работает напрямую с Git‑репози","content":"EasyP предоставляет мощный менеджер пакетов для protobuf‑зависимостей, упрощающий их управление за счёт децентрализованного подхода на базе Git. В отличие от централизованных решений, EasyP работает напрямую с Git‑репозиториями, давая вам полный контроль."},{"id":"cli/package-manager/package-manager::top::1","title":"Менеджер пакетов","section":"Обзор","path":"/docs/guide/cli/package-manager/package-manager","headings":["Обзор"],"excerpt":"Обзор Менеджер пакетов EasyP следует философии **Go modules** — любой Git‑репозиторий может быть источником. Это даёт преимущества:","content":"Обзор Менеджер пакетов EasyP следует философии **Go modules** — любой Git‑репозиторий может быть источником. Это даёт преимущества:"},{"id":"cli/package-manager/package-manager::top::2","title":"Менеджер пакетов","section":"Обзор","path":"/docs/guide/cli/package-manager/package-manager","headings":["Обзор"],"excerpt":"Обзор **Децентрализация** — нет единой точки отказа или контроля **Безопасность** — прямой доступ к исходникам **Гибкость** — публичные, приватные и корпоративные репозитории **Воспроизводимость** — lock‑файлы обеспечива","content":"Обзор **Децентрализация** — нет единой точки отказа или контроля **Безопасность** — прямой доступ к исходникам **Гибкость** — публичные, приватные и корпоративные репозитории **Воспроизводимость** — lock‑файлы обеспечивают одинаковые сборки **Производительность** — локальный кеш сокращает сетевые запросы"},{"id":"cli/package-manager/package-manager::top::3","title":"Менеджер пакетов","section":"Основные возможности","path":"/docs/guide/cli/package-manager/package-manager","headings":["Основные возможности"],"excerpt":"Основные возможности Возможность Описание ------------- ---------- **Git-Native** Любой Git репозиторий, не нужен спец‑сервер **Множество форматов версий** Теги, коммиты, псевдо‑версии, latest **Lock Files** Воспроизводи","content":"Основные возможности Возможность Описание ------------- ---------- **Git-Native** Любой Git репозиторий, не нужен спец‑сервер **Множество форматов версий** Теги, коммиты, псевдо‑версии, latest **Lock Files** Воспроизводимые сборки через easyp.lock **Локальный кеш** Архитектура как у Go modules **Vendoring** Локальное копирование для оффлайн сборок **YAML конфигурация** Простые и читаемые декларации"},{"id":"cli/package-manager/package-manager::top::4","title":"Менеджер пакетов","section":"Архитектура","path":"/docs/guide/cli/package-manager/package-manager","headings":["Архитектура"],"excerpt":"Архитектура EasyP использует двухуровневый кеш, вдохновлённый Go modules:","content":"Архитектура EasyP использует двухуровневый кеш, вдохновлённый Go modules:"},{"id":"cli/package-manager/package-manager::top::5","title":"Менеджер пакетов","section":"Расположение кеша","path":"/docs/guide/cli/package-manager/package-manager","headings":["Расположение кеша"],"excerpt":"Расположение кеша Окружение Путь Как задать ----------- ------ ----------- **По умолчанию** $HOME/.easyp Автоматически **Свое** Любая директория Переменная EASYPPATH **CI/CD** В каталоге проекта export EASYPPATH=$CI_PROJ","content":"Расположение кеша Окружение Путь Как задать ----------- ------ ----------- **По умолчанию** $HOME/.easyp Автоматически **Свое** Любая директория Переменная EASYPPATH **CI/CD** В каталоге проекта export EASYPPATH=$CI_PROJECT_DIR/.easyp"},{"id":"cli/package-manager/package-manager::top::6","title":"Менеджер пакетов","section":"Базовая конфигурация","path":"/docs/guide/cli/package-manager/package-manager","headings":["Базовая конфигурация"],"excerpt":"Базовая конфигурация Зависимости описываются в easyp.yaml:","content":"Базовая конфигурация Зависимости описываются в easyp.yaml:"},{"id":"cli/package-manager/package-manager::multi-environment-setup::7","title":"Менеджер пакетов","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 # Последнее для разработки - github.com/mycompany/internal-protos # Внутренние изменения - github.com/bufbuild/protoc-gen-va","content":"Multi-Environment Setup ```yaml development.easyp.yaml deps: - github.com/googleapis/googleapis # Последнее для разработки - github.com/mycompany/internal-protos # Внутренние изменения - github.com/bufbuild/protoc-gen-validate # Новые фичи"},{"id":"cli/package-manager/package-manager::multi-environment-setup::8","title":"Менеджер пакетов","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 # Зафиксировано - github.com/mycompany/internal-protos@v2.1.0 # Стабильно - github.com/bufbuild/protoc-gen-valida","content":"Multi-Environment Setup production.easyp.yaml deps: - github.com/googleapis/googleapis@common-protos-1_3_1 # Зафиксировано - github.com/mycompany/internal-protos@v2.1.0 # Стабильно - github.com/bufbuild/protoc-gen-validate@v0.10.1 # Проверено ```"},{"id":"cli/package-manager/package-manager::top::9","title":"Менеджер пакетов","section":"Приватные репозитории","path":"/docs/guide/cli/package-manager/package-manager","headings":["Приватные репозитории"],"excerpt":"Приватные репозитории ```yaml deps: # Публичное - github.com/googleapis/googleapis@common-protos-1_3_1","content":"Приватные репозитории ```yaml deps: # Публичное - github.com/googleapis/googleapis@common-protos-1_3_1"},{"id":"cli/package-manager/package-manager::top::10","title":"Менеджер пакетов","section":"Приватные репозитории","path":"/docs/guide/cli/package-manager/package-manager","headings":["Приватные репозитории"],"excerpt":"Приватные репозитории Частные - github.com/mycompany/auth-protos@v1.5.0 - github.com/mycompany/common-types@v2.0.1","content":"Приватные репозитории Частные - github.com/mycompany/auth-protos@v1.5.0 - github.com/mycompany/common-types@v2.0.1"},{"id":"cli/package-manager/package-manager::top::11","title":"Менеджер пакетов","section":"Приватные репозитории","path":"/docs/guide/cli/package-manager/package-manager","headings":["Приватные репозитории"],"excerpt":"Приватные репозитории Внутренний GitLab - gitlab.company.com/platform/messaging-protos@v0.3.0 ```","content":"Приватные репозитории Внутренний GitLab - gitlab.company.com/platform/messaging-protos@v0.3.0 ```"},{"id":"cli/package-manager/package-manager::top::12","title":"Менеджер пакетов","section":"Стратегии версионирования","path":"/docs/guide/cli/package-manager/package-manager","headings":["Стратегии версионирования"],"excerpt":"Стратегии версионирования Поддерживаются разные способы фиксации версий:","content":"Стратегии версионирования Поддерживаются разные способы фиксации версий:"},{"id":"cli/package-manager/package-manager::1::13","title":"Менеджер пакетов","section":"1. Семантические теги (для продакшена)","path":"/docs/guide/cli/package-manager/package-manager#1","headings":["1. Семантические теги (для продакшена)"],"excerpt":"Семантические теги (для продакшена)","content":"Семантические теги (для продакшена)"},{"id":"cli/package-manager/package-manager::1::14","title":"Менеджер пакетов","section":"1. Семантические теги (для продакшена)","path":"/docs/guide/cli/package-manager/package-manager#1","headings":["1. Семантические теги (для продакшена)"],"excerpt":"Семантические теги (для продакшена) **Используйте когда:** Продакшен Стабильное потребление API Нужна воспроизводимость","content":"Семантические теги (для продакшена) **Используйте когда:** Продакшен Стабильное потребление API Нужна воспроизводимость"},{"id":"cli/package-manager/package-manager::2-development::15","title":"Менеджер пакетов","section":"2. Последний тег (development)","path":"/docs/guide/cli/package-manager/package-manager#2-development","headings":["2. Последний тег (development)"],"excerpt":"Последний тег (development) **Подходит для:** Активной разработки Получения свежих возможностей Тестирования совместимости","content":"Последний тег (development) **Подходит для:** Активной разработки Получения свежих возможностей Тестирования совместимости"},{"id":"cli/package-manager/package-manager::3-bleeding-edge::16","title":"Менеджер пакетов","section":"3. Хеш коммита (Bleeding Edge)","path":"/docs/guide/cli/package-manager/package-manager#3-bleeding-edge","headings":["3. Хеш коммита (Bleeding Edge)"],"excerpt":"Хеш коммита (Bleeding Edge) **Когда нужно:** Нерелизные фичи Тест конкретного фикса Вклад в upstream","content":"Хеш коммита (Bleeding Edge) **Когда нужно:** Нерелизные фичи Тест конкретного фикса Вклад в upstream"},{"id":"cli/package-manager/package-manager::4::17","title":"Менеджер пакетов","section":"4. Псевдо‑версии (автоматически)","path":"/docs/guide/cli/package-manager/package-manager#4","headings":["4. Псевдо‑версии (автоматически)"],"excerpt":"Псевдо‑версии (автоматически) Если нет подходящего тега — создаётся псевдо‑версия:","content":"Псевдо‑версии (автоматически) Если нет подходящего тега — создаётся псевдо‑версия:"},{"id":"cli/package-manager/package-manager::easyp-mod-download::18","title":"Менеджер пакетов","section":"easyp mod download","path":"/docs/guide/cli/package-manager/package-manager#easyp-mod-download","headings":["easyp mod download"],"excerpt":"easyp mod download Скачивает и устанавливает все объявленные зависимости.","content":"easyp mod download Скачивает и устанавливает все объявленные зависимости."},{"id":"cli/package-manager/package-manager::easyp-mod-download::19","title":"Менеджер пакетов","section":"easyp mod download","path":"/docs/guide/cli/package-manager/package-manager#easyp-mod-download","headings":["easyp mod download"],"excerpt":"easyp mod download **Что делает:** Разрешает версии (теги → коммиты) Скачивает архивы в cache/download Проверяет контрольные суммы Распаковывает в cache/mod Обновляет easyp.lock","content":"easyp mod download **Что делает:** Разрешает версии (теги → коммиты) Скачивает архивы в cache/download Проверяет контрольные суммы Распаковывает в cache/mod Обновляет easyp.lock"},{"id":"cli/package-manager/package-manager::easyp-mod-download::20","title":"Менеджер пакетов","section":"easyp mod download","path":"/docs/guide/cli/package-manager/package-manager#easyp-mod-download","headings":["easyp mod download"],"excerpt":"easyp mod download **Пример:**","content":"easyp mod download **Пример:**"},{"id":"cli/package-manager/package-manager::easyp-mod-vendor::21","title":"Менеджер пакетов","section":"easyp mod vendor","path":"/docs/guide/cli/package-manager/package-manager#easyp-mod-vendor","headings":["easyp mod vendor"],"excerpt":"easyp mod vendor Копирует все proto зависимости в локальный easyp_vendor/ для оффлайна.","content":"easyp mod vendor Копирует все proto зависимости в локальный easyp_vendor/ для оффлайна."},{"id":"cli/package-manager/package-manager::easyp-mod-vendor::22","title":"Менеджер пакетов","section":"easyp mod vendor","path":"/docs/guide/cli/package-manager/package-manager#easyp-mod-vendor","headings":["easyp mod vendor"],"excerpt":"easyp mod vendor **Сценарии:** Docker сборки Air-gapped окружения Воспроизводимость Ускорение","content":"easyp mod vendor **Сценарии:** Docker сборки Air-gapped окружения Воспроизводимость Ускорение"},{"id":"cli/package-manager/package-manager::easyp-mod-update::23","title":"Менеджер пакетов","section":"easyp mod update","path":"/docs/guide/cli/package-manager/package-manager#easyp-mod-update","headings":["easyp mod update"],"excerpt":"easyp mod update Обновляет версии согласно easyp.yaml, пересоздаёт lock.","content":"easyp mod update Обновляет версии согласно easyp.yaml, пересоздаёт lock."},{"id":"cli/package-manager/package-manager::lock::24","title":"Менеджер пакетов","section":"Lock файл","path":"/docs/guide/cli/package-manager/package-manager#lock","headings":["Lock файл"],"excerpt":"Lock файл easyp.lock фиксирует точные версии и хеш содержимого:","content":"Lock файл easyp.lock фиксирует точные версии и хеш содержимого:"},{"id":"cli/package-manager/package-manager::lock::25","title":"Менеджер пакетов","section":"Lock файл","path":"/docs/guide/cli/package-manager/package-manager#lock","headings":["Lock файл"],"excerpt":"Lock файл **Формат строки:** Путь модуля Версия (тег или псевдо) Хеш содержимого (h1:)","content":"Lock файл **Формат строки:** Путь модуля Версия (тег или псевдо) Хеш содержимого (h1:)"},{"id":"cli/package-manager/package-manager::lock::26","title":"Менеджер пакетов","section":"Lock файл","path":"/docs/guide/cli/package-manager/package-manager#lock","headings":["Lock файл"],"excerpt":"Lock файл **Практики:** ✅ Коммитить easyp.lock ✅ Осознанно обновлять mod update ✅ Ревью изменений версий ❌ Не редактировать вручную","content":"Lock файл **Практики:** ✅ Коммитить easyp.lock ✅ Осознанно обновлять mod update ✅ Ревью изменений версий ❌ Не редактировать вручную"},{"id":"cli/package-manager/package-manager::top::27","title":"Менеджер пакетов","section":"Публичные репозитории","path":"/docs/guide/cli/package-manager/package-manager","headings":["Публичные репозитории"],"excerpt":"Публичные репозитории Работают без настроек:","content":"Публичные репозитории Работают без настроек:"},{"id":"cli/package-manager/package-manager::ssh::28","title":"Менеджер пакетов","section":"SSH ключи (рекомендуется)","path":"/docs/guide/cli/package-manager/package-manager#ssh","headings":["SSH ключи (рекомендуется)"],"excerpt":"SSH ключи (рекомендуется) Конфиг остаётся с HTTPS URL:","content":"SSH ключи (рекомендуется) Конфиг остаётся с HTTPS URL:"},{"id":"cli/package-manager/package-manager::personal-access-tokens::29","title":"Менеджер пакетов","section":"Personal Access Tokens","path":"/docs/guide/cli/package-manager/package-manager#personal-access-tokens","headings":["Personal Access Tokens"],"excerpt":"Personal Access Tokens ```bash git config --global credential.helper store echo \"https://username:token@github.com\" >> ~/.git-credentials","content":"Personal Access Tokens ```bash git config --global credential.helper store echo \"https://username:token@github.com\" >> ~/.git-credentials"},{"id":"cli/package-manager/package-manager::personal-access-tokens::30","title":"Менеджер пакетов","section":"Personal Access Tokens","path":"/docs/guide/cli/package-manager/package-manager#personal-access-tokens","headings":["Personal Access Tokens"],"excerpt":"Personal Access Tokens git config --global url.\"https://username:token@github.com/mycompany\".insteadOf \"https://github.com/mycompany\" ```","content":"Personal Access Tokens git config --global url.\"https://username:token@github.com/mycompany\".insteadOf \"https://github.com/mycompany\" ```"},{"id":"cli/package-manager/package-manager::top::31","title":"Менеджер пакетов","section":"Инициализация проекта","path":"/docs/guide/cli/package-manager/package-manager","headings":["Инициализация проекта"],"excerpt":"Инициализация проекта ```bash cat > easyp.yaml << EOF deps: - github.com/googleapis/googleapis - github.com/grpc-ecosystem/grpc-gateway@v2.19.1 EOF","content":"Инициализация проекта ```bash 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::top::32","title":"Менеджер пакетов","section":"Инициализация проекта","path":"/docs/guide/cli/package-manager/package-manager","headings":["Инициализация проекта"],"excerpt":"Инициализация проекта easyp mod download ls ~/.easyp/mod/github.com/googleapis/googleapis/ ```","content":"Инициализация проекта easyp mod download ls ~/.easyp/mod/github.com/googleapis/googleapis/ ```"},{"id":"cli/package-manager/package-manager::repository-not-found-authentication-failed::33","title":"Менеджер пакетов","section":"\"Repository not found\" / \"Authentication failed\"","path":"/docs/guide/cli/package-manager/package-manager#repository-not-found-authentication-failed","headings":["\"Repository not found\" / \"Authentication failed\""],"excerpt":"\"Repository not found\" / \"Authentication failed\"","content":"\"Repository not found\" / \"Authentication failed\""},{"id":"cli/package-manager/package-manager::cache-corruption-checksum-mismatch::34","title":"Менеджер пакетов","section":"\"Cache corruption\" / \"Checksum mismatch\"","path":"/docs/guide/cli/package-manager/package-manager#cache-corruption-checksum-mismatch","headings":["\"Cache corruption\" / \"Checksum mismatch\""],"excerpt":"\"Cache corruption\" / \"Checksum mismatch\"","content":"\"Cache corruption\" / \"Checksum mismatch\""},{"id":"cli/package-manager/package-manager::docker-multi-stage::35","title":"Менеджер пакетов","section":"Docker multi-stage","path":"/docs/guide/cli/package-manager/package-manager#docker-multi-stage","headings":["Docker multi-stage"],"excerpt":"Docker multi-stage ```dockerfile FROM ghcr.io/easyp-tech/easyp:latest AS deps WORKDIR /workspace COPY easyp.yaml easyp.lock ./ RUN easyp mod vendor","content":"Docker multi-stage ```dockerfile 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::36","title":"Менеджер пакетов","section":"Docker multi-stage","path":"/docs/guide/cli/package-manager/package-manager#docker-multi-stage","headings":["Docker multi-stage"],"excerpt":"Docker multi-stage FROM alpine:latest AS build WORKDIR /app COPY --from=deps /workspace/easyp_vendor ./easyp_vendor COPY . . RUN easyp generate ```","content":"Docker multi-stage FROM alpine:latest AS build WORKDIR /app COPY --from=deps /workspace/easyp_vendor ./easyp_vendor COPY . . RUN easyp generate ```"},{"id":"cli/package-manager/package-manager::monorepo::37","title":"Менеджер пакетов","section":"Monorepo","path":"/docs/guide/cli/package-manager/package-manager#monorepo","headings":["Monorepo"],"excerpt":"Monorepo Каждый easyp.yaml может иметь свой набор зависимостей.","content":"Monorepo Каждый easyp.yaml может иметь свой набор зависимостей."},{"id":"cli/package-manager/package-manager::workflow::38","title":"Менеджер пакетов","section":"Workflow разработки","path":"/docs/guide/cli/package-manager/package-manager#workflow","headings":["Workflow разработки"],"excerpt":"Workflow разработки ✅ Latest теги в активной разработке ✅ Фиксация версий в продакшене ✅ Коммит lock файла ✅ Ревью обновлений ✅ Тест после обновления","content":"Workflow разработки ✅ Latest теги в активной разработке ✅ Фиксация версий в продакшене ✅ Коммит lock файла ✅ Ревью обновлений ✅ Тест после обновления"},{"id":"cli/package-manager/package-manager::top::39","title":"Менеджер пакетов","section":"Безопасность","path":"/docs/guide/cli/package-manager/package-manager","headings":["Безопасность"],"excerpt":"Безопасность ✅ Фиксируйте версии ✅ Используйте SSH ключи ✅ Оценивайте новые зависимости ✅ Следите за уязвимостями ❌ Не храните секреты в конфиге","content":"Безопасность ✅ Фиксируйте версии ✅ Используйте SSH ключи ✅ Оценивайте новые зависимости ✅ Следите за уязвимостями ❌ Не храните секреты в конфиге"},{"id":"cli/package-manager/package-manager::top::40","title":"Менеджер пакетов","section":"Производительность","path":"/docs/guide/cli/package-manager/package-manager","headings":["Производительность"],"excerpt":"Производительность ✅ Агрессивное кеширование в CI ✅ Vendoring для частых сборок ✅ Чистка старого кеша ✅ Общий кеш для команды","content":"Производительность ✅ Агрессивное кеширование в CI ✅ Vendoring для частых сборок ✅ Чистка старого кеша ✅ Общий кеш для команды"},{"id":"cli/package-manager/package-manager::top::41","title":"Менеджер пакетов","section":"Командная работа","path":"/docs/guide/cli/package-manager/package-manager","headings":["Командная работа"],"excerpt":"Командная работа ✅ Документация по аутентификации ✅ Единые инструменты ✅ Автоматизация обновлений с тестами ✅ Общий кеш при возможности","content":"Командная работа ✅ Документация по аутентификации ✅ Единые инструменты ✅ Автоматизация обновлений с тестами ✅ Общий кеш при возможности"},{"id":"cli/package-manager/package-manager::top::42","title":"Менеджер пакетов","section":"Командная работа","path":"/docs/guide/cli/package-manager/package-manager","headings":["Командная работа"],"excerpt":"Командная работа Менеджер пакетов EasyP — масштабируемое децентрализованное решение от одиночных проектов до enterprise, сохраняя простоту и надёжность.","content":"Командная работа Менеджер пакетов EasyP — масштабируемое децентрализованное решение от одиночных проектов до enterprise, сохраняя простоту и надёжность."},{"id":"introduction/install::top::0","title":"Установка EasyP CLI","section":"Установка через менеджер пакетов системы","path":"/docs/guide/introduction/install","headings":["Установка через менеджер пакетов системы"],"excerpt":"Установка через менеджер пакетов системы","content":"Установка через менеджер пакетов системы"},{"id":"introduction/install::top::1","title":"Установка EasyP CLI","section":"Рекомендуемый способ установки","path":"/docs/guide/introduction/install","headings":["Рекомендуемый способ установки"],"excerpt":"Рекомендуемый способ установки","content":"Рекомендуемый способ установки"},{"id":"introduction/install::homebrew::2","title":"Установка EasyP CLI","section":"Homebrew","path":"/docs/guide/introduction/install#homebrew","headings":["Homebrew"],"excerpt":"Homebrew Можно установить бинарный релиз в macOS через Homebrew:","content":"Homebrew Можно установить бинарный релиз в macOS через Homebrew:"},{"id":"introduction/install::homebrew::3","title":"Установка EasyP CLI","section":"Homebrew","path":"/docs/guide/introduction/install#homebrew","headings":["Homebrew"],"excerpt":"Homebrew Work in progress — поддержка других менеджеров (apt, yum, pacman и т.д.) в процессе.","content":"Homebrew Work in progress — поддержка других менеджеров (apt, yum, pacman и т.д.) в процессе."},{"id":"introduction/install::_-_::4","title":"Установка EasyP CLI","section":"_Не рекомендуется_","path":"/docs/guide/introduction/install#_-_","headings":["_Не рекомендуется_"],"excerpt":"_Не рекомендуется_ Локальная установка менее предпочтительна, потому что пакетные менеджеры обеспечивают: Автоматические обновления и патчи безопасности Лучшую интеграцию с системой Упрощённую установку и удаление Подпис","content":"_Не рекомендуется_ Локальная установка менее предпочтительна, потому что пакетные менеджеры обеспечивают: Автоматические обновления и патчи безопасности Лучшую интеграцию с системой Упрощённую установку и удаление Подписанные и проверенные бинарники"},{"id":"introduction/install::go-install::5","title":"Установка EasyP CLI","section":"Установка через go install","path":"/docs/guide/introduction/install#go-install","headings":["Установка через go install"],"excerpt":"Установка через go install Команда установит последнюю стабильную версию easyp:","content":"Установка через go install Команда установит последнюю стабильную версию easyp:"},{"id":"introduction/install::top::6","title":"Установка EasyP CLI","section":"Сборка из исходников","path":"/docs/guide/introduction/install","headings":["Сборка из исходников"],"excerpt":"Сборка из исходников Клонирование репозитория","content":"Сборка из исходников Клонирование репозитория"},{"id":"introduction/install::top::7","title":"Установка EasyP CLI","section":"Сборка из исходников","path":"/docs/guide/introduction/install","headings":["Сборка из исходников"],"excerpt":"Сборка из исходников Сборка с помощью Go","content":"Сборка из исходников Сборка с помощью Go"},{"id":"introduction/quickstart::top::0","title":"Быстрый старт (Quickstart)","path":"/docs/guide/introduction/quickstart","headings":[],"excerpt":"EasyP — современный toolkit для работы с файлами Protobuf. В этом кратком руководстве вы научитесь:","content":"EasyP — современный toolkit для работы с файлами Protobuf. В этом кратком руководстве вы научитесь:"},{"id":"introduction/quickstart::top::1","title":"Быстрый старт (Quickstart)","path":"/docs/guide/introduction/quickstart","headings":[],"excerpt":"**Инициализировать** проект с конфигурацией EasyP **Настраивать линтинг**, чтобы ловить ошибки и соблюдать лучшие практики **Управлять зависимостями** из Git‑репозиториев **Генерировать код** из ваших Protobuf файлов","content":"**Инициализировать** проект с конфигурацией EasyP **Настраивать линтинг**, чтобы ловить ошибки и соблюдать лучшие практики **Управлять зависимостями** из Git‑репозиториев **Генерировать код** из ваших Protobuf файлов"},{"id":"introduction/quickstart::top::2","title":"Быстрый старт (Quickstart)","section":"Предварительные требования","path":"/docs/guide/introduction/quickstart","headings":["Предварительные требования"],"excerpt":"Предварительные требования Перед началом убедитесь, что у вас установлены:","content":"Предварительные требования Перед началом убедитесь, что у вас установлены:"},{"id":"introduction/quickstart::top::3","title":"Быстрый старт (Quickstart)","section":"Предварительные требования","path":"/docs/guide/introduction/quickstart","headings":["Предварительные требования"],"excerpt":"Предварительные требования **EasyP CLI** — см. руководство по установке **Git** доступен в вашем $PATH **Файлы .proto** (или создайте их по ходу)","content":"Предварительные требования **EasyP CLI** — см. руководство по установке **Git** доступен в вашем $PATH **Файлы .proto** (или создайте их по ходу)"},{"id":"introduction/quickstart::top::4","title":"Быстрый старт (Quickstart)","section":"Предварительные требования","path":"/docs/guide/introduction/quickstart","headings":["Предварительные требования"],"excerpt":"Предварительные требования Проверить версию EasyP:","content":"Предварительные требования Проверить версию EasyP:"},{"id":"introduction/quickstart::top::5","title":"Быстрый старт (Quickstart)","section":"Инициализация проекта","path":"/docs/guide/introduction/quickstart","headings":["Инициализация проекта"],"excerpt":"Инициализация проекта Создайте базовый файл конфигурации easyp.yaml в корне проекта:","content":"Инициализация проекта Создайте базовый файл конфигурации easyp.yaml в корне проекта:"},{"id":"introduction/quickstart::top::6","title":"Быстрый старт (Quickstart)","section":"Инициализация проекта","path":"/docs/guide/introduction/quickstart","headings":["Инициализация проекта"],"excerpt":"Инициализация проекта Команда генерирует шаблон easyp.yaml с комментариями, дефолтными lint-правилами и настройками breaking-check. easyp init работает интерактивно: если в корне есть buf.yml/buf.yaml, EasyP предложит ми","content":"Инициализация проекта Команда генерирует шаблон easyp.yaml с комментариями, дефолтными lint-правилами и настройками breaking-check. easyp init работает интерактивно: если в корне есть buf.yml/buf.yaml, EasyP предложит миграцию; если easyp.yaml уже существует, попросит подтверждение перед перезаписью."},{"id":"introduction/quickstart::top::7","title":"Быстрый старт (Quickstart)","section":"Настройка линтинга","path":"/docs/guide/introduction/quickstart","headings":["Настройка линтинга"],"excerpt":"Настройка линтинга Линтинг помогает находить проблемы и поддерживать единый стиль. EasyP использует правила, совместимые с Buf.","content":"Настройка линтинга Линтинг помогает находить проблемы и поддерживать единый стиль. EasyP использует правила, совместимые с Buf."},{"id":"introduction/quickstart::top::8","title":"Быстрый старт (Quickstart)","section":"Настройка линтинга","path":"/docs/guide/introduction/quickstart","headings":["Настройка линтинга"],"excerpt":"Настройка линтинга Секция lint уже создаётся командой easyp init. При необходимости отредактируйте её, например так:","content":"Настройка линтинга Секция lint уже создаётся командой easyp init. При необходимости отредактируйте её, например так:"},{"id":"introduction/quickstart::top::9","title":"Быстрый старт (Quickstart)","section":"Настройка линтинга","path":"/docs/guide/introduction/quickstart","headings":["Настройка линтинга"],"excerpt":"Настройка линтинга Запустите линтер:","content":"Настройка линтинга Запустите линтер:"},{"id":"introduction/quickstart::top::10","title":"Быстрый старт (Quickstart)","section":"Настройка линтинга","path":"/docs/guide/introduction/quickstart","headings":["Настройка линтинга"],"excerpt":"Настройка линтинга Линтер проверит все .proto файлы и сообщит о найденных проблемах.","content":"Настройка линтинга Линтер проверит все .proto файлы и сообщит о найденных проблемах."},{"id":"introduction/quickstart::top::11","title":"Быстрый старт (Quickstart)","section":"Настройка линтинга","path":"/docs/guide/introduction/quickstart","headings":["Настройка линтинга"],"excerpt":"Настройка линтинга ::: tip Правила линтинга EasyP на 100% совместимы с Buf — мигрировать просто. :::","content":"Настройка линтинга ::: tip Правила линтинга EasyP на 100% совместимы с Buf — мигрировать просто. :::"},{"id":"introduction/quickstart::top::12","title":"Быстрый старт (Quickstart)","section":"Управление зависимостями","path":"/docs/guide/introduction/quickstart","headings":["Управление зависимостями"],"excerpt":"Управление зависимостями Если вы используете сторонние protobuf пакеты (например Google APIs или gRPC Gateway), EasyP упрощает их подключение.","content":"Управление зависимостями Если вы используете сторонние protobuf пакеты (например Google APIs или gRPC Gateway), EasyP упрощает их подключение."},{"id":"introduction/quickstart::top::13","title":"Быстрый старт (Quickstart)","section":"Формат зависимости","path":"/docs/guide/introduction/quickstart","headings":["Формат зависимости"],"excerpt":"Формат зависимости Запись: $GIT_LINK@$VERSION","content":"Формат зависимости Запись: $GIT_LINK@$VERSION"},{"id":"introduction/quickstart::top::14","title":"Быстрый старт (Quickstart)","section":"Формат зависимости","path":"/docs/guide/introduction/quickstart","headings":["Формат зависимости"],"excerpt":"Формат зависимости **$GIT_LINK** — URL любого Git‑репозитория (GitHub, GitLab и т.д.) **$VERSION** — тег или хеш коммита (опционально)","content":"Формат зависимости **$GIT_LINK** — URL любого Git‑репозитория (GitHub, GitLab и т.д.) **$VERSION** — тег или хеш коммита (опционально)"},{"id":"introduction/quickstart::top::15","title":"Быстрый старт (Quickstart)","section":"Формат зависимости","path":"/docs/guide/introduction/quickstart","headings":["Формат зависимости"],"excerpt":"Формат зависимости Если версия не указана — берётся последний коммит из основной ветки.","content":"Формат зависимости Если версия не указана — берётся последний коммит из основной ветки."},{"id":"introduction/quickstart::top::16","title":"Быстрый старт (Quickstart)","section":"Добавление зависимостей","path":"/docs/guide/introduction/quickstart","headings":["Добавление зависимостей"],"excerpt":"Добавление зависимостей Дополните easyp.yaml:","content":"Добавление зависимостей Дополните easyp.yaml:"},{"id":"introduction/quickstart::top::17","title":"Быстрый старт (Quickstart)","section":"Загрузка зависимостей","path":"/docs/guide/introduction/quickstart","headings":["Загрузка зависимостей"],"excerpt":"Загрузка зависимостей Команда: Скачивает версии из easyp.lock, если он существует Иначе — берёт из easyp.yaml и создаёт easyp.lock","content":"Загрузка зависимостей Команда: Скачивает версии из easyp.lock, если он существует Иначе — берёт из easyp.yaml и создаёт easyp.lock"},{"id":"introduction/quickstart::top::18","title":"Быстрый старт (Quickstart)","section":"Загрузка зависимостей","path":"/docs/guide/introduction/quickstart","headings":["Загрузка зависимостей"],"excerpt":"Загрузка зависимостей ::: info Совет: easyp mod update — игнорирует lock‑файл и подтягивает актуальные версии из easyp.yaml. :::","content":"Загрузка зависимостей ::: info Совет: easyp mod update — игнорирует lock‑файл и подтягивает актуальные версии из easyp.yaml. :::"},{"id":"introduction/quickstart::top::19","title":"Быстрый старт (Quickstart)","section":"Генерация кода","path":"/docs/guide/introduction/quickstart","headings":["Генерация кода"],"excerpt":"Генерация кода EasyP поддерживает все стандартные protoc‑плагины.","content":"Генерация кода EasyP поддерживает все стандартные protoc‑плагины."},{"id":"introduction/quickstart::top::20","title":"Быстрый старт (Quickstart)","section":"Конфигурация генерации","path":"/docs/guide/introduction/quickstart","headings":["Конфигурация генерации"],"excerpt":"Конфигурация генерации Добавьте плагины:","content":"Конфигурация генерации Добавьте плагины:"},{"id":"introduction/quickstart::top::21","title":"Быстрый старт (Quickstart)","section":"Запуск генерации","path":"/docs/guide/introduction/quickstart","headings":["Запуск генерации"],"excerpt":"Запуск генерации EasyP выполнит: Разрешение всех зависимостей Подключение к сервису EasyP (или локальный режим) Запуск указанных плагинов Вывод сгенерированного кода в нужные директории","content":"Запуск генерации EasyP выполнит: Разрешение всех зависимостей Подключение к сервису EasyP (или локальный режим) Запуск указанных плагинов Вывод сгенерированного кода в нужные директории"},{"id":"introduction/quickstart::top::22","title":"Быстрый старт (Quickstart)","section":"Запуск генерации","path":"/docs/guide/introduction/quickstart","headings":["Запуск генерации"],"excerpt":"Запуск генерации ::: tip Гибридный рантайм: WASM для скорости, Docker — для тяжёлых плагинов. :::","content":"Запуск генерации ::: tip Гибридный рантайм: WASM для скорости, Docker — для тяжёлых плагинов. :::"},{"id":"introduction/quickstart::top::23","title":"Быстрый старт (Quickstart)","section":"Следующие шаги","path":"/docs/guide/introduction/quickstart","headings":["Следующие шаги"],"excerpt":"Следующие шаги Поздравляем! 🎉 Вы успешно: ✅ Инициализировали проект EasyP ✅ Настроили линтинг ✅ Управляете внешними зависимостями ✅ Сгенерировали код из .proto","content":"Следующие шаги Поздравляем! 🎉 Вы успешно: ✅ Инициализировали проект EasyP ✅ Настроили линтинг ✅ Управляете внешними зависимостями ✅ Сгенерировали код из .proto"},{"id":"introduction/quickstart::top::24","title":"Быстрый старт (Quickstart)","section":"Узнать больше","path":"/docs/guide/introduction/quickstart","headings":["Узнать больше"],"excerpt":"Узнать больше **CLI Reference** — подробности по командам **API Service** — удалённая генерация **Configuration** — все опции конфигурации","content":"Узнать больше **CLI Reference** — подробности по командам **API Service** — удалённая генерация **Configuration** — все опции конфигурации"},{"id":"introduction/quickstart::top::25","title":"Быстрый старт (Quickstart)","section":"Узнать больше","path":"/docs/guide/introduction/quickstart","headings":["Узнать больше"],"excerpt":"Узнать больше *Приятной работы с Protobuf — без боли! 🚀*","content":"Узнать больше *Приятной работы с Protobuf — без боли! 🚀*"},{"id":"introduction/what-is::top::0","title":"Что такое EasyP?","path":"/docs/guide/introduction/what-is","headings":[],"excerpt":"EasyP — это современный инструментарий для работы с Protocol Buffers, который объединяет весь ваш protobuf‑workflow в один мощный CLI‑инструмент. Он совмещает линтинг, управление пакетами, генерацию кода и проверку совме","content":"EasyP — это современный инструментарий для работы с Protocol Buffers, который объединяет весь ваш protobuf‑workflow в один мощный CLI‑инструмент. Он совмещает линтинг, управление пакетами, генерацию кода и проверку совместимости в единой среде и устраняет сложность традиционной работы с protobuf."},{"id":"introduction/what-is::top::1","title":"Что такое EasyP?","path":"/docs/guide/introduction/what-is","headings":[],"excerpt":"Хотите просто попробовать? Перейдите сразу к разделу Quickstart.","content":"Хотите просто попробовать? Перейдите сразу к разделу Quickstart."},{"id":"introduction/what-is::protobuf::2","title":"Что такое EasyP?","section":"Проблема: фрагментированные protobuf‑процессы","path":"/docs/guide/introduction/what-is#protobuf","headings":["Проблема: фрагментированные protobuf‑процессы"],"excerpt":"Проблема: фрагментированные protobuf‑процессы Работа с Protocol Buffers в разных проектах часто создает лишнюю сложность и трение:","content":"Проблема: фрагментированные protobuf‑процессы Работа с Protocol Buffers в разных проектах часто создает лишнюю сложность и трение:"},{"id":"introduction/what-is::top::3","title":"Что такое EasyP?","section":"Хаос инструментов","path":"/docs/guide/introduction/what-is","headings":["Хаос инструментов"],"excerpt":"Хаос инструментов **Много отдельных утилит**: Отдельно для линтинга, генерации и управления зависимостями **Несогласованные конфигурации**: Разные форматы и правила в разных командах **Сложный онбординг**: Новым разработ","content":"Хаос инструментов **Много отдельных утилит**: Отдельно для линтинга, генерации и управления зависимостями **Несогласованные конфигурации**: Разные форматы и правила в разных командах **Сложный онбординг**: Новым разработчикам нужно долго вникать"},{"id":"introduction/what-is::top::4","title":"Что такое EasyP?","section":"Проблемы управления зависимостями","path":"/docs/guide/introduction/what-is","headings":["Проблемы управления зависимостями"],"excerpt":"Проблемы управления зависимостями **Нет стандартизированного подхода**: Каждый проект решает это по‑своему **Конфликты версий**: Трудно сводить разные версии одних и тех же proto‑библиотек **Неповторяемость сборок**: Сло","content":"Проблемы управления зависимостями **Нет стандартизированного подхода**: Каждый проект решает это по‑своему **Конфликты версий**: Трудно сводить разные версии одних и тех же proto‑библиотек **Неповторяемость сборок**: Сложно гарантировать одинаковый результат в разных окружениях"},{"id":"introduction/what-is::top::5","title":"Что такое EasyP?","section":"Трение в разработке","path":"/docs/guide/introduction/what-is","headings":["Трение в разработке"],"excerpt":"Трение в разработке **Ручные операции**: Много повторяющихся шагов **Разрастание конфигураций**: Множество файлов и форматов **Затратная проверка совместимости**: Часто вручную и постфактум","content":"Трение в разработке **Ручные операции**: Много повторяющихся шагов **Разрастание конфигураций**: Множество файлов и форматов **Затратная проверка совместимости**: Часто вручную и постфактум"},{"id":"introduction/what-is::protobuf::6","title":"Что такое EasyP?","section":"Решение: единый protobuf‑инструментарий","path":"/docs/guide/introduction/what-is#protobuf","headings":["Решение: единый protobuf‑инструментарий"],"excerpt":"Решение: единый protobuf‑инструментарий EasyP устраняет эти проблемы, предоставляя целостный opinionated‑подход и стандартизируя процессы:","content":"Решение: единый protobuf‑инструментарий EasyP устраняет эти проблемы, предоставляя целостный opinionated‑подход и стандартизируя процессы:"},{"id":"introduction/what-is::top::7","title":"Что такое EasyP?","section":"Один инструмент — все задачи","path":"/docs/guide/introduction/what-is","headings":["Один инструмент — все задачи"],"excerpt":"Один инструмент — все задачи Вместо жонглирования утилитами EasyP даёт: **Linting** с расширенными наборами правил **Package management** с Git‑нативными зависимостями **Code generation** локально и удалённо **Breaking c","content":"Один инструмент — все задачи Вместо жонглирования утилитами EasyP даёт: **Linting** с расширенными наборами правил **Package management** с Git‑нативными зависимостями **Code generation** локально и удалённо **Breaking change detection** для контроля совместимости API"},{"id":"introduction/what-is::top::8","title":"Что такое EasyP?","section":"Единая конфигурация","path":"/docs/guide/introduction/what-is","headings":["Единая конфигурация"],"excerpt":"Единая конфигурация Один файл easyp.yaml описывает весь workflow — меньше расхождений, проще сопровождать.","content":"Единая конфигурация Один файл easyp.yaml описывает весь workflow — меньше расхождений, проще сопровождать."},{"id":"introduction/what-is::gitnative::9","title":"Что такое EasyP?","section":"Git‑native зависимости","path":"/docs/guide/introduction/what-is#gitnative","headings":["Git‑native зависимости"],"excerpt":"Git‑native зависимости Прямое использование Git‑репозиториев вместо централизованных реестров: прозрачная история, контроль версий, воспроизводимые сборки.","content":"Git‑native зависимости Прямое использование Git‑репозиториев вместо централизованных реестров: прозрачная история, контроль версий, воспроизводимые сборки."},{"id":"introduction/what-is::top::10","title":"Что такое EasyP?","section":"Ключевые возможности","path":"/docs/guide/introduction/what-is","headings":["Ключевые возможности"],"excerpt":"Ключевые возможности Feature Description --------- ------------- 🔍 **Comprehensive Linting** Полная поддержка правил buf с настраиваемыми профилями для лучших практик API‑дизайна. 📦 **Smart Package Manager** Git‑ориент","content":"Ключевые возможности Feature Description --------- ------------- 🔍 **Comprehensive Linting** Полная поддержка правил buf с настраиваемыми профилями для лучших практик API‑дизайна. 📦 **Smart Package Manager** Git‑ориентированное управление зависимостями с lock‑файлом для воспроизводимости. ⚡ **Code Generation** Многозадачная генерация кода с поддержкой локальных и удалённых protoc‑плагинов. 🔄 **Breaking Change Detection** Автоматическая проверка совместимости API против веток Git. 🌐 **Remote Plugin Support** Выполнение плагинов через централизованный EasyP API сервис без локальных установок. 🎯 **Developer Experience** Автодополнение, понятные ошибки, единая структура и документация."},{"id":"introduction/what-is::top::11","title":"Что такое EasyP?","section":"Типы поддерживаемых плагинов","path":"/docs/guide/introduction/what-is","headings":["Типы поддерживаемых плагинов"],"excerpt":"Типы поддерживаемых плагинов EasyP гибко подходит к выполнению генерации:","content":"Типы поддерживаемых плагинов EasyP гибко подходит к выполнению генерации:"},{"id":"introduction/what-is::local-plugins::12","title":"Что такое EasyP?","section":"Local Plugins","path":"/docs/guide/introduction/what-is#local-plugins","headings":["Local Plugins"],"excerpt":"Local Plugins Стандартные установленные protoc‑плагины:","content":"Local Plugins Стандартные установленные protoc‑плагины:"},{"id":"introduction/what-is::remote-plugins::13","title":"Что такое EasyP?","section":"Remote Plugins","path":"/docs/guide/introduction/what-is#remote-plugins","headings":["Remote Plugins"],"excerpt":"Remote Plugins Плагины через EasyP API сервис для воспроизводимости:","content":"Remote Plugins Плагины через EasyP API сервис для воспроизводимости:"},{"id":"introduction/what-is::custom-plugins::14","title":"Что такое EasyP?","section":"Custom Plugins","path":"/docs/guide/introduction/what-is#custom-plugins","headings":["Custom Plugins"],"excerpt":"Custom Plugins Поддержка экосистемы пользовательских расширений.","content":"Custom Plugins Поддержка экосистемы пользовательских расширений."},{"id":"introduction/what-is::top::15","title":"Что такое EasyP?","section":"Децентрализованный менеджмент пакетов","path":"/docs/guide/introduction/what-is","headings":["Децентрализованный менеджмент пакетов"],"excerpt":"Децентрализованный менеджмент пакетов В отличие от других решений EasyP не требует централизованного реестра. Любой Git‑репозиторий может быть источником:","content":"Децентрализованный менеджмент пакетов В отличие от других решений EasyP не требует централизованного реестра. Любой Git‑репозиторий может быть источником:"},{"id":"introduction/what-is::top::16","title":"Что такое EasyP?","section":"Децентрализованный менеджмент пакетов","path":"/docs/guide/introduction/what-is","headings":["Децентрализованный менеджмент пакетов"],"excerpt":"Децентрализованный менеджмент пакетов **Гибкость**: Любой Git‑хостинг (GitHub, GitLab, self‑hosted) **Нет vendor lock‑in**: Зависимости не привязаны к одному провайдеру **Полная история**: Ветки, теги, ревью **Enterprise","content":"Децентрализованный менеджмент пакетов **Гибкость**: Любой Git‑хостинг (GitHub, GitLab, self‑hosted) **Нет vendor lock‑in**: Зависимости не привязаны к одному провайдеру **Полная история**: Ветки, теги, ревью **Enterprise‑совместимость**: Поддержка приватных репозиториев"},{"id":"introduction/what-is::buf::17","title":"Что такое EasyP?","section":"Бесшовная миграция с Buf","path":"/docs/guide/introduction/what-is#buf","headings":["Бесшовная миграция с Buf"],"excerpt":"Бесшовная миграция с Buf EasyP изначально совместим с экосистемой buf:","content":"Бесшовная миграция с Buf EasyP изначально совместим с экосистемой buf:"},{"id":"introduction/what-is::buf::18","title":"Что такое EasyP?","section":"Бесшовная миграция с Buf","path":"/docs/guide/introduction/what-is#buf","headings":["Бесшовная миграция с Buf"],"excerpt":"Бесшовная миграция с Buf **Совпадающие rule sets** **Похожая структура YAML** **Минимальные изменения для замены** **Постепенное внедрение** без ломки текущего пайплайна","content":"Бесшовная миграция с Buf **Совпадающие rule sets** **Похожая структура YAML** **Минимальные изменения для замены** **Постепенное внедрение** без ломки текущего пайплайна"},{"id":"introduction/what-is::easyp-vs-bufbuild::19","title":"Что такое EasyP?","section":"EasyP vs buf.build","path":"/docs/guide/introduction/what-is#easyp-vs-bufbuild","headings":["EasyP vs buf.build"],"excerpt":"EasyP vs buf.build Feature EasyP buf.build --------- -------- ----------- **Dependency Management** Git‑репозитории Buf Schema Registry (BSR) **Vendor Lock-in** Нет Привязка к BSR для полного функционала **Plugin Executi","content":"EasyP vs buf.build Feature EasyP buf.build --------- -------- ----------- **Dependency Management** Git‑репозитории Buf Schema Registry (BSR) **Vendor Lock-in** Нет Привязка к BSR для полного функционала **Plugin Execution** Local + Remote Local + BSR plugins **Private Dependencies** Любой Git провайдер BSR или ручное управление **Offline Development** Полная поддержка (mod vendor) Ограниченно без доступа к BSR **Enterprise Integration** Использует существующий Git Требует настройку BSR **Breaking Change Detection** Против любой Git ссылки Аналогично **Package Distribution** Любой Git Публикация через BSR **License** Apache 2.0 Apache 2.0 **Community** Growing Established"},{"id":"introduction/what-is::easyp-vs-bufbuild::20","title":"Что такое EasyP?","section":"EasyP vs buf.build","path":"/docs/guide/introduction/what-is#easyp-vs-bufbuild","headings":["EasyP vs buf.build"],"excerpt":"EasyP vs buf.build **Преимущества миграции:** Без изменения инфраструктуры Плавное принятие новых возможностей Гибрид локальных и удалённых плагинов Единая конфигурация вместо набора файлов","content":"EasyP vs buf.build **Преимущества миграции:** Без изменения инфраструктуры Плавное принятие новых возможностей Гибрид локальных и удалённых плагинов Единая конфигурация вместо набора файлов"},{"id":"introduction/what-is::protobuf::21","title":"Что такое EasyP?","section":"Наши цели для Protobuf","path":"/docs/guide/introduction/what-is#protobuf","headings":["Наши цели для Protobuf"],"excerpt":"Наши цели для Protobuf Миссия EasyP — ускорить принятие **schema‑driven API** через удобный, надёжный и прозрачный инструментарий.","content":"Наши цели для Protobuf Миссия EasyP — ускорить принятие **schema‑driven API** через удобный, надёжный и прозрачный инструментарий."},{"id":"introduction/what-is::top::22","title":"Что такое EasyP?","section":"Современная экосистема","path":"/docs/guide/introduction/what-is","headings":["Современная экосистема"],"excerpt":"Современная экосистема Повышаем DX вокруг protobuf, чтобы конкурентно выглядеть по простоте против REST/JSON, сохраняя типовую строгость и производительность.","content":"Современная экосистема Повышаем DX вокруг protobuf, чтобы конкурентно выглядеть по простоте против REST/JSON, сохраняя типовую строгость и производительность."},{"id":"introduction/what-is::developer-experience::23","title":"Что такое EasyP?","section":"Developer Experience прежде всего","path":"/docs/guide/introduction/what-is#developer-experience","headings":["Developer Experience прежде всего"],"excerpt":"Developer Experience прежде всего Интуитивный CLI, понятные ошибки, ясные сообщения, минимальная фрагментация.","content":"Developer Experience прежде всего Интуитивный CLI, понятные ошибки, ясные сообщения, минимальная фрагментация."},{"id":"introduction/what-is::enterprise::24","title":"Что такое EasyP?","section":"Готов к Enterprise","path":"/docs/guide/introduction/what-is#enterprise","headings":["Готов к Enterprise"],"excerpt":"Готов к Enterprise Воспроизводимые сборки, приватные репозитории, интеграция в CI/CD.","content":"Готов к Enterprise Воспроизводимые сборки, приватные репозитории, интеграция в CI/CD."},{"id":"introduction/what-is::top::25","title":"Что такое EasyP?","section":"Для индивидуальных разработчиков","path":"/docs/guide/introduction/what-is","headings":["Для индивидуальных разработчиков"],"excerpt":"Для индивидуальных разработчиков Быстрый старт за минуты Один инструмент — меньше когнитивной нагрузки Понятная документация","content":"Для индивидуальных разработчиков Быстрый старт за минуты Один инструмент — меньше когнитивной нагрузки Понятная документация"},{"id":"introduction/what-is::top::26","title":"Что такое EasyP?","section":"Для команд","path":"/docs/guide/introduction/what-is","headings":["Для команд"],"excerpt":"Для команд Единые стандарты Повторяемые сборки (lock‑файл) Ускоренный онбординг","content":"Для команд Единые стандарты Повторяемые сборки (lock‑файл) Ускоренный онбординг"},{"id":"introduction/what-is::top::27","title":"Что такое EasyP?","section":"Для организаций","path":"/docs/guide/introduction/what-is","headings":["Для организаций"],"excerpt":"Для организаций Нет vendor lock‑in Безопасность приватных репозиториев Лёгкая интеграция в существующие пайплайны","content":"Для организаций Нет vendor lock‑in Безопасность приватных репозиториев Лёгкая интеграция в существующие пайплайны"},{"id":"introduction/what-is::top::28","title":"Что такое EasyP?","section":"Что дальше?","path":"/docs/guide/introduction/what-is","headings":["Что дальше?"],"excerpt":"Что дальше? EasyP упрощает работу с protobuf — фокусируйтесь на API, а не на рутине. Хотите начать?","content":"Что дальше? EasyP упрощает работу с protobuf — фокусируйтесь на API, а не на рутине. Хотите начать?"},{"id":"introduction/what-is::top::29","title":"Что такое EasyP?","section":"Что дальше?","path":"/docs/guide/introduction/what-is","headings":["Что дальше?"],"excerpt":"Что дальше? Смотрите Installation Guide и Quickstart.","content":"Что дальше? Смотрите Installation Guide и Quickstart."},{"id":"introduction/what-is::stargazers-over-time::30","title":"Что такое 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 В работе","content":"Buf CLI В работе"},{"id":"migration/protoc::top::0","title":"Миграция с protoc на EasyP","path":"/docs/guide/migration/protoc","headings":[],"excerpt":"Исходная англоязычная версия файла содержала только заголовок и пометку “Work in progress”. Ниже — полноценный русскоязычный черновик раздела миграции. Уточни, если требуется сократить или изменить уровень детализации.","content":"Исходная англоязычная версия файла содержала только заголовок и пометку “Work in progress”. Ниже — полноценный русскоязычный черновик раздела миграции. Уточни, если требуется сократить или изменить уровень детализации."},{"id":"migration/protoc::1::1","title":"Миграция с protoc на EasyP","section":"1. Краткое сравнение","path":"/docs/guide/migration/protoc#1","headings":["1. Краткое сравнение"],"excerpt":"Краткое сравнение Аспект protoc EasyP -------- ---------- ------- Базовая роль Базовый компилятор .proto файлов Инструмент “всё в одном”: линтинг, проверка несовместимых изменений, менеджер пакетов, генерация Конфигураци","content":"Краткое сравнение Аспект protoc EasyP -------- ---------- ------- Базовая роль Базовый компилятор .proto файлов Инструмент “всё в одном”: линтинг, проверка несовместимых изменений, менеджер пакетов, генерация Конфигурация Чаще shell‑скрипты / Makefile / вручную передаваемые флаги Единый файл easyp.yaml (YAML или JSON) Управление зависимостями Ручной git clone, submodule, vendoring Секция deps с Git‑репозиториями Набор правил линтера Нет встроенного Встроенный линтер с правилами (можно включать/исключать) Проверка breaking changes Отсутствует из коробки Команда easyp breaking Расширенные плагины Установка и вызов через флаги --plugin Плагины через конфиг; поддержка удалённого выполнения (API Service) и стандартного локального Единообразие в CI Нужно собирать вручную Консистентные команды: lint, breaking, generate"},{"id":"migration/protoc::2::2","title":"Миграция с protoc на EasyP","section":"2. Когда имеет смысл мигрировать","path":"/docs/guide/migration/protoc#2","headings":["2. Когда имеет смысл мигрировать"],"excerpt":"Когда имеет смысл мигрировать Миграция на EasyP особенно полезна если: Есть потребность в автоматической проверке качества (стиль, именование) .proto файлов. Нужна защита от нелегитимных несовместимых изменений при эволю","content":"Когда имеет смысл мигрировать Миграция на EasyP особенно полезна если: Есть потребность в автоматической проверке качества (стиль, именование) .proto файлов. Нужна защита от нелегитимных несовместимых изменений при эволюции схем. В проекте используется несколько языков генерации и растёт число скриптов вокруг protoc. Вы хотите единый конфиг вместо множества shell/Makefile комбинаций. Планируется централизованное исполнение плагинов (через API Service) или унификация окружения в CI."},{"id":"migration/protoc::3-protoc::3","title":"Миграция с protoc на EasyP","section":"3. Типичный сценарий “до” (только protoc)","path":"/docs/guide/migration/protoc#3-protoc","headings":["3. Типичный сценарий “до” (только protoc)"],"excerpt":"Типичный сценарий “до” (только protoc) Пример: локальные скрипты / Makefile:","content":"Типичный сценарий “до” (только protoc) Пример: локальные скрипты / Makefile:"},{"id":"migration/protoc::3-protoc::4","title":"Миграция с protoc на EasyP","section":"3. Типичный сценарий “до” (только protoc)","path":"/docs/guide/migration/protoc#3-protoc","headings":["3. Типичный сценарий “до” (только protoc)"],"excerpt":"Типичный сценарий “до” (только protoc)","content":"Типичный сценарий “до” (только protoc)"},{"id":"migration/protoc::3-protoc::5","title":"Миграция с protoc на EasyP","section":"3. Типичный сценарий “до” (только protoc)","path":"/docs/guide/migration/protoc#3-protoc","headings":["3. Типичный сценарий “до” (только protoc)"],"excerpt":"Типичный сценарий “до” (только protoc) Дополнительные зависимости (googleapis, validate, grpc-gateway) скачиваются вручную или через submodules.","content":"Типичный сценарий “до” (только protoc) Дополнительные зависимости (googleapis, validate, grpc-gateway) скачиваются вручную или через submodules."},{"id":"migration/protoc::4-easyp::6","title":"Миграция с protoc на EasyP","section":"4. Типичный сценарий “после” (EasyP)","path":"/docs/guide/migration/protoc#4-easyp","headings":["4. Типичный сценарий “после” (EasyP)"],"excerpt":"Типичный сценарий “после” (EasyP) Единый файл easyp.yaml:","content":"Типичный сценарий “после” (EasyP) Единый файл easyp.yaml:"},{"id":"migration/protoc::4-easyp::7","title":"Миграция с protoc на EasyP","section":"4. Типичный сценарий “после” (EasyP)","path":"/docs/guide/migration/protoc#4-easyp","headings":["4. Типичный сценарий “после” (EasyP)"],"excerpt":"Типичный сценарий “после” (EasyP) ```yaml deps: - github.com/googleapis/googleapis - github.com/envoyproxy/protoc-gen-validate","content":"Типичный сценарий “после” (EasyP) ```yaml deps: - github.com/googleapis/googleapis - github.com/envoyproxy/protoc-gen-validate"},{"id":"migration/protoc::4-easyp::8","title":"Миграция с protoc на EasyP","section":"4. Типичный сценарий “после” (EasyP)","path":"/docs/guide/migration/protoc#4-easyp","headings":["4. Типичный сценарий “после” (EasyP)"],"excerpt":"Типичный сценарий “после” (EasyP) generate: plugins: - name: go out: gen/go opts: paths: source_relative - name: go-grpc out: gen/go opts: paths: source_relative require_unimplemented_servers: false - name: validate out:","content":"Типичный сценарий “после” (EasyP) generate: plugins: - name: go out: gen/go opts: paths: source_relative - name: go-grpc out: gen/go opts: paths: source_relative require_unimplemented_servers: false - name: validate out: gen/go opts: paths: source_relative lang: \"go\" ```"},{"id":"migration/protoc::4-easyp::9","title":"Миграция с protoc на EasyP","section":"4. Типичный сценарий “после” (EasyP)","path":"/docs/guide/migration/protoc#4-easyp","headings":["4. Типичный сценарий “после” (EasyP)"],"excerpt":"Типичный сценарий “после” (EasyP) Команды:","content":"Типичный сценарий “после” (EasyP) Команды:"},{"id":"migration/protoc::5::10","title":"Миграция с protoc на EasyP","section":"5. Пошаговая миграция","path":"/docs/guide/migration/protoc#5","headings":["5. Пошаговая миграция"],"excerpt":"Пошаговая миграция Инвентаризация: - Соберите список всех вызовов protoc (скрипты, Makefile, CI). - Зафиксируйте используемые плагины и их версии. Создание easyp.yaml: - Поле version не обязательно (можете оставить его т","content":"Пошаговая миграция Инвентаризация: - Соберите список всех вызовов protoc (скрипты, Makefile, CI). - Зафиксируйте используемые плагины и их версии. Создание easyp.yaml: - Поле version не обязательно (можете оставить его только для обратной совместимости). - Перенесите плагины в секцию generate.plugins. - Укажите опции, которые ранее передавались в командной строке. Зависимости: - Все внешние каталоги (googleapis, validate, grpc-gateway и т.п.) занесите в deps. - Удалите лишние submodules при необходимости. Линтер: - Запустите easyp lint и посмотрите на предупреждения. - При необходимости добавьте lint.use, lint.ignore, lint.except. Проверка breaking changes: - Выберите референс (обычно origin/main или предыдущий тег). - Запустите easyp breaking --against git-ref=origin/main. - Настройте игнорируемые изменения (breaking.ignore), если нужно. Обновление CI: - Замените прямые вызовы protoc на easyp generate. - Добавьте отдельные шаги lint и breaking. Очистка: - Удалите устаревшие генерационные скрипты, если они дублируют функционал EasyP. Документация: - Обновите README / CONTRIBUTING (новый способ генерации). Верификация: - Сравните результат генерации до и после (git diff). - Убедитесь, что имена файлов и пути совпадают или скорректируйте структуру."},{"id":"migration/protoc::6-ci-github-actions::11","title":"Миграция с protoc на EasyP","section":"6. Замена в CI (пример GitHub Actions)","path":"/docs/guide/migration/protoc#6-ci-github-actions","headings":["6. Замена в CI (пример GitHub Actions)"],"excerpt":"Замена в CI (пример GitHub Actions) ```yaml name: Install EasyP run: go install github.com/easyp-tech/easyp/cmd/easyp@latest","content":"Замена в CI (пример GitHub Actions) ```yaml name: Install EasyP run: go install github.com/easyp-tech/easyp/cmd/easyp@latest"},{"id":"migration/protoc::6-ci-github-actions::12","title":"Миграция с protoc на EasyP","section":"6. Замена в CI (пример GitHub Actions)","path":"/docs/guide/migration/protoc#6-ci-github-actions","headings":["6. Замена в CI (пример GitHub Actions)"],"excerpt":"Замена в CI (пример GitHub Actions) name: Lint run: easyp lint","content":"Замена в CI (пример GitHub Actions) name: Lint run: easyp lint"},{"id":"migration/protoc::6-ci-github-actions::13","title":"Миграция с protoc на EasyP","section":"6. Замена в CI (пример GitHub Actions)","path":"/docs/guide/migration/protoc#6-ci-github-actions","headings":["6. Замена в CI (пример GitHub Actions)"],"excerpt":"Замена в CI (пример GitHub Actions) name: Breaking run: easyp breaking --against git-ref=origin/main","content":"Замена в CI (пример GitHub Actions) name: Breaking run: easyp breaking --against git-ref=origin/main"},{"id":"migration/protoc::6-ci-github-actions::14","title":"Миграция с protoc на EasyP","section":"6. Замена в CI (пример GitHub Actions)","path":"/docs/guide/migration/protoc#6-ci-github-actions","headings":["6. Замена в CI (пример GitHub Actions)"],"excerpt":"Замена в CI (пример GitHub Actions) name: Generate run: easyp generate ```","content":"Замена в CI (пример GitHub Actions) name: Generate run: easyp generate ```"},{"id":"migration/protoc::7::15","title":"Миграция с protoc на EasyP","section":"7. Работа с плагинами","path":"/docs/guide/migration/protoc#7","headings":["7. Работа с плагинами"],"excerpt":"Работа с плагинами Тип В protoc В EasyP ----- ---------- --------- Стандартные (protoc-gen-go) Указание через --go_out plugins: - name: go ... gRPC --go-grpc_out Второй плагин go-grpc Validate Доп. установка + --validate","content":"Работа с плагинами Тип В protoc В EasyP ----- ---------- --------- Стандартные (protoc-gen-go) Указание через --go_out plugins: - name: go ... gRPC --go-grpc_out Второй плагин go-grpc Validate Доп. установка + --validate_out - name: validate с opts gRPC-Gateway / OpenAPI --grpc-gateway_out / --openapiv2_out Плагины grpc-gateway, openapiv2 Кастомные Путь к бинарю / --plugin=protoc-gen-xxx - name: xxx или удалённый remote: (если используется API Service)"},{"id":"migration/protoc::7::16","title":"Миграция с protoc на EasyP","section":"7. Работа с плагинами","path":"/docs/guide/migration/protoc#7","headings":["7. Работа с плагинами"],"excerpt":"Работа с плагинами Если вы переходите на удалённое выполнение (API Service), записи в конфиге могут выглядеть так:","content":"Работа с плагинами Если вы переходите на удалённое выполнение (API Service), записи в конфиге могут выглядеть так:"},{"id":"migration/protoc::8::17","title":"Миграция с protoc на EasyP","section":"8. Проверка корректности после миграции","path":"/docs/guide/migration/protoc#8","headings":["8. Проверка корректности после миграции"],"excerpt":"Проверка корректности после миграции git diff после easyp generate — не должно быть неожиданных изменений. Сравнить размер и содержимое каталога сгенерированных файлов. Запустить ваш потребляющий код (сборка, тесты). Про","content":"Проверка корректности после миграции git diff после easyp generate — не должно быть неожиданных изменений. Сравнить размер и содержимое каталога сгенерированных файлов. Запустить ваш потребляющий код (сборка, тесты). Проверить, что плагины (validate, grpc-gateway) продолжают вставлять необходимые аннотации / опции. Линт не должен выдавать критичных ошибок — скорректируйте стиль .proto, если требуется."},{"id":"migration/protoc::9::18","title":"Миграция с protoc на EasyP","section":"9. Частые проблемы","path":"/docs/guide/migration/protoc#9","headings":["9. Частые проблемы"],"excerpt":"Частые проблемы Проблема Причина Решение ---------- --------- --------- Плагин не найден Не установлен или не указан в PATH Выполнить go install ... или добавить в конфиг как remote Ошибка импорта .proto Отсутствует репо","content":"Частые проблемы Проблема Причина Решение ---------- --------- --------- Плагин не найден Не установлен или не указан в PATH Выполнить go install ... или добавить в конфиг как remote Ошибка импорта .proto Отсутствует репозиторий в deps Добавить адрес в секцию deps и easyp mod update Несовместимые изменения на каждом PR Отсутствует игнор/настройка сравнения Уточнить ветку/тег в --against или настроить breaking.ignore Локально работает, в CI падает В CI нет зависимостей (не вызван update) Добавить шаг easyp mod update перед generate Дубликаты сгенерированных файлов Изменена структура путей или out Синхронизировать out и paths: source_relative опции"},{"id":"migration/protoc::10-go::19","title":"Миграция с protoc на EasyP","section":"10. Минимальный пример конфигурации (только Go)","path":"/docs/guide/migration/protoc#10-go","headings":["10. Минимальный пример конфигурации (только Go)"],"excerpt":"Минимальный пример конфигурации (только Go)","content":"Минимальный пример конфигурации (только Go)"},{"id":"migration/protoc::10-go::20","title":"Миграция с protoc на EasyP","section":"10. Минимальный пример конфигурации (только Go)","path":"/docs/guide/migration/protoc#10-go","headings":["10. Минимальный пример конфигурации (только Go)"],"excerpt":"Минимальный пример конфигурации (только Go) Команды:","content":"Минимальный пример конфигурации (только Go) Команды:"},{"id":"migration/protoc::11-go-grpc-gateway-validate-breaking-lint::21","title":"Миграция с protoc на EasyP","section":"11. Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint)","path":"/docs/guide/migration/protoc#11-go-grpc-gateway-validate-breaking-lint","headings":["11. Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint)"],"excerpt":"Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint) ```yaml lint: use: - ENUM_FIRST_VALUE_ZERO - SERVICE_SUFFIX allow_comment_ignores: false enum_zero_value_suffix: _NONE service_suffix: Service","content":"Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint) ```yaml lint: use: - ENUM_FIRST_VALUE_ZERO - SERVICE_SUFFIX allow_comment_ignores: false enum_zero_value_suffix: _NONE service_suffix: Service"},{"id":"migration/protoc::11-go-grpc-gateway-validate-breaking-lint::22","title":"Миграция с protoc на EasyP","section":"11. Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint)","path":"/docs/guide/migration/protoc#11-go-grpc-gateway-validate-breaking-lint","headings":["11. Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint)"],"excerpt":"Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint) deps: - github.com/googleapis/googleapis - github.com/envoyproxy/protoc-gen-validate","content":"Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint) deps: - github.com/googleapis/googleapis - github.com/envoyproxy/protoc-gen-validate"},{"id":"migration/protoc::11-go-grpc-gateway-validate-breaking-lint::23","title":"Миграция с protoc на EasyP","section":"11. Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint)","path":"/docs/guide/migration/protoc#11-go-grpc-gateway-validate-breaking-lint","headings":["11. Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint)"],"excerpt":"Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint) generate: plugins: - name: go out: gen/go opts: paths: source_relative - name: go-grpc out: gen/go opts: paths: source_relative require_unimplemented_","content":"Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint) generate: plugins: - name: go out: gen/go opts: paths: source_relative - name: go-grpc out: gen/go opts: paths: source_relative require_unimplemented_servers: false - name: validate out: gen/go opts: paths: source_relative lang: \"go\" - name: grpc-gateway out: gen/go opts: paths: source_relative - name: openapiv2 out: gen/openapi opts: simple_operation_ids: true"},{"id":"migration/protoc::11-go-grpc-gateway-validate-breaking-lint::24","title":"Миграция с protoc на EasyP","section":"11. Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint)","path":"/docs/guide/migration/protoc#11-go-grpc-gateway-validate-breaking-lint","headings":["11. Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint)"],"excerpt":"Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint) breaking: against_git_ref: main ignore: - ENUM_VALUE_SAME_NAME ```","content":"Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint) breaking: against_git_ref: main ignore: - ENUM_VALUE_SAME_NAME ```"},{"id":"migration/protoc::12-checklist::25","title":"Миграция с protoc на EasyP","section":"12. Checklist миграции","path":"/docs/guide/migration/protoc#12-checklist","headings":["12. Checklist миграции"],"excerpt":"Checklist миграции [ ] Собраны все текущие вызовы protoc. [ ] Создан easyp.yaml с секциями generate и (опционально) lint, breaking. [ ] Добавлены все внешние зависимости в deps. [ ] Успешно выполнен easyp mod update. [ ]","content":"Checklist миграции [ ] Собраны все текущие вызовы protoc. [ ] Создан easyp.yaml с секциями generate и (опционально) lint, breaking. [ ] Добавлены все внешние зависимости в deps. [ ] Успешно выполнен easyp mod update. [ ] easyp generate даёт идентичный или ожидаемо обновлённый результат. [ ] easyp lint проходит без критичных ошибок (или ошибки обработаны). [ ] easyp breaking --against git-ref=origin/main не выдаёт неожиданных блокирующих нарушений. [ ] CI обновлён (заменены прямые вызовы protoc). [ ] Документация проекта обновлена (README: как генерировать)."},{"id":"migration/protoc::13::26","title":"Миграция с protoc на EasyP","section":"13. Дополнительные рекомендации","path":"/docs/guide/migration/protoc#13","headings":["13. Дополнительные рекомендации"],"excerpt":"Дополнительные рекомендации Сначала мигрируйте один сервис / пакет — снизит риск массовых конфликтов. Закоммитьте easyp.yaml отдельно, затем выполните генерацию и линт — проще ревью. Если нужны разные наборы плагинов для","content":"Дополнительные рекомендации Сначала мигрируйте один сервис / пакет — снизит риск массовых конфликтов. Закоммитьте easyp.yaml отдельно, затем выполните генерацию и линт — проще ревью. Если нужны разные наборы плагинов для разных микросервисов — используйте несколько конфигов (например: easyp.microservice-a.yaml + easyp.microservice-b.yaml). Внедрите проверку актуальности генерации: шаг CI, который валидирует отсутствие diff после easyp generate."},{"id":"migration/protoc::14::27","title":"Миграция с protoc на EasyP","section":"14. Статус","path":"/docs/guide/migration/protoc#14","headings":["14. Статус"],"excerpt":"Статус Этот файл — русская расширенная версия, заменяющая placeholder “Work in progress”. При появлении новых возможностей EasyP (дополнительные поля в конфиге, новые плагины, расширения breaking‑проверок) обновите соотв","content":"Статус Этот файл — русская расширенная версия, заменяющая placeholder “Work in progress”. При появлении новых возможностей EasyP (дополнительные поля в конфиге, новые плагины, расширения breaking‑проверок) обновите соответствующие разделы."},{"id":"migration/protoc::14::28","title":"Миграция с protoc на EasyP","section":"14. Статус","path":"/docs/guide/migration/protoc#14","headings":["14. Статус"],"excerpt":"Статус Если нужен упрощённый вариант (только перевод без расширения), сообщи — могу сократить до минимальных двух блоков.","content":"Статус Если нужен упрощённый вариант (только перевод без расширения), сообщи — могу сократить до минимальных двух блоков."},{"id":"migration/protolock::top::0","title":"Protolock","path":"/docs/guide/migration/protolock","headings":[],"excerpt":"Protolock В процессе разработки","content":"Protolock В процессе разработки"},{"id":"migration/prototool::top::0","title":"Prototool","section":"Состояние","path":"/docs/guide/migration/prototool","headings":["Состояние"],"excerpt":"Состояние Этот раздел был помечен как “Work in progress” в оригинальной английской версии. Ниже — переведённое и дополненное практическое руководство по миграции с Prototool на EasyP. Имя инструмента Prototool не перевод","content":"Состояние Этот раздел был помечен как “Work in progress” в оригинальной английской версии. Ниже — переведённое и дополненное практическое руководство по миграции с Prototool на EasyP. Имя инструмента Prototool не переводится."},{"id":"migration/prototool::top::1","title":"Prototool","section":"Цель миграции","path":"/docs/guide/migration/prototool","headings":["Цель миграции"],"excerpt":"Цель миграции Перейти от конфигурации и рабочих процессов Prototool к эквиваленту на EasyP с минимальными изменениями, сохранив: Линтинг .proto файлов. Генерацию кода через protoc-плагины. Управление зависимостями. Прове","content":"Цель миграции Перейти от конфигурации и рабочих процессов Prototool к эквиваленту на EasyP с минимальными изменениями, сохранив: Линтинг .proto файлов. Генерацию кода через protoc-плагины. Управление зависимостями. Проверку несовместимых изменений (в Prototool это приходилось реализовывать внешними инструментами; в EasyP встроено)."},{"id":"migration/prototool::top::2","title":"Prototool","section":"Кратко о различиях","path":"/docs/guide/migration/prototool","headings":["Кратко о различиях"],"excerpt":"Кратко о различиях Область Prototool EasyP Комментарий --------- ----------- ------- ------------- Конфигурация prototool.yaml easyp.yaml Форматы YAML/JSON поддерживаются; структура отличается. Линтинг Встроенные наборы ","content":"Кратко о различиях Область Prototool EasyP Комментарий --------- ----------- ------- ------------- Конфигурация prototool.yaml easyp.yaml Форматы YAML/JSON поддерживаются; структура отличается. Линтинг Встроенные наборы + кастомные правила Наборы через lint.use, тонкая настройка ignore/except EasyP даёт больше гибкости группировки. Генерация Раздел generate + плагины через Docker/локально generate.plugins (локальные/WASM/удалённые) EasyP может выполнять плагины удалённо (API Service). Зависимости Обычно через include-пути / внешние git clone вручную Секция deps (Git репозитории) + mod update Более декларативно. Breaking Changes Нет встроенного механизма Секция breaking + команда easyp breaking Из коробки. Lock-in Зависимость от модели Prototool Минималистичный формат, «любой Git — пакет» Облегчает выход / интеграцию с другими экосистемами."},{"id":"migration/prototool::prototool::3","title":"Prototool","section":"Типовая структура Prototool (упрощённо)","path":"/docs/guide/migration/prototool#prototool","headings":["Типовая структура Prototool (упрощённо)"],"excerpt":"Типовая структура Prototool (упрощённо)","content":"Типовая структура Prototool (упрощённо)"},{"id":"migration/prototool::prototool::4","title":"Prototool","section":"Типовая структура Prototool (упрощённо)","path":"/docs/guide/migration/prototool#prototool","headings":["Типовая структура Prototool (упрощённо)"],"excerpt":"Типовая структура Prototool (упрощённо) Особенности: include_paths задаёт пути поиска импортов. lint.group + rules.add/remove регулируют активные проверки. generate.plugins описывает плагины для protoc.","content":"Типовая структура Prototool (упрощённо) Особенности: include_paths задаёт пути поиска импортов. lint.group + rules.add/remove регулируют активные проверки. generate.plugins описывает плагины для protoc."},{"id":"migration/prototool::prototool::5","title":"Prototool","section":"Типовая структура Prototool (упрощённо)","path":"/docs/guide/migration/prototool#prototool","headings":["Типовая структура Prototool (упрощённо)"],"excerpt":"Типовая структура Prototool (упрощённо) ---","content":"Типовая структура Prototool (упрощённо) ---"},{"id":"migration/prototool::easyp::6","title":"Prototool","section":"Эквивалент на EasyP","path":"/docs/guide/migration/prototool#easyp","headings":["Эквивалент на EasyP"],"excerpt":"Эквивалент на EasyP ```yaml easyp.yaml (пример) deps: - github.com/org/common-protos # вместо manual include - github.com/org/third-party-protos","content":"Эквивалент на EasyP ```yaml easyp.yaml (пример) deps: - github.com/org/common-protos # вместо manual include - github.com/org/third-party-protos"},{"id":"migration/prototool::easyp::7","title":"Prototool","section":"Эквивалент на EasyP","path":"/docs/guide/migration/prototool#easyp","headings":["Эквивалент на EasyP"],"excerpt":"Эквивалент на EasyP lint: use: - MINIMAL - BASIC enum_zero_value_suffix: \"_NONE\" service_suffix: \"Service\" ignore: - COMMENT_FIELD except: - ENUM_VALUE_PREFIX allow_comment_ignores: true","content":"Эквивалент на EasyP lint: use: - MINIMAL - BASIC enum_zero_value_suffix: \"_NONE\" service_suffix: \"Service\" ignore: - COMMENT_FIELD except: - ENUM_VALUE_PREFIX allow_comment_ignores: true"},{"id":"migration/prototool::easyp::8","title":"Prototool","section":"Эквивалент на EasyP","path":"/docs/guide/migration/prototool#easyp","headings":["Эквивалент на EasyP"],"excerpt":"Эквивалент на EasyP generate: plugins: - name: go out: gen/go opts: paths: source_relative - name: go-grpc out: gen/go opts: paths: source_relative require_unimplemented_servers: false","content":"Эквивалент на EasyP generate: plugins: - name: go out: gen/go opts: paths: source_relative - name: go-grpc out: gen/go opts: paths: source_relative require_unimplemented_servers: false"},{"id":"migration/prototool::easyp::9","title":"Prototool","section":"Эквивалент на EasyP","path":"/docs/guide/migration/prototool#easyp","headings":["Эквивалент на EasyP"],"excerpt":"Эквивалент на EasyP breaking: against_git_ref: main ignore: - FIELD_SAME_TYPE ```","content":"Эквивалент на EasyP breaking: against_git_ref: main ignore: - FIELD_SAME_TYPE ```"},{"id":"migration/prototool::easyp::10","title":"Prototool","section":"Эквивалент на EasyP","path":"/docs/guide/migration/prototool#easyp","headings":["Эквивалент на EasyP"],"excerpt":"Эквивалент на EasyP Комментарии: deps заменяет необходимость вручную прописывать include paths: EasyP подтянет их через git. lint.use активирует наборы правил (MINIMAL/BASIC/DEFAULT и т.д.). Дополнительные настройки (enu","content":"Эквивалент на EasyP Комментарии: deps заменяет необходимость вручную прописывать include paths: EasyP подтянет их через git. lint.use активирует наборы правил (MINIMAL/BASIC/DEFAULT и т.д.). Дополнительные настройки (enum_zero_value_suffix, service_suffix) задают политики нейминга. breaking позволяет сразу контролировать несовместимые изменения."},{"id":"migration/prototool::top::11","title":"Prototool","section":"Шаги миграции","path":"/docs/guide/migration/prototool","headings":["Шаги миграции"],"excerpt":"Шаги миграции Инвентаризация: - Соберите текущий prototool.yaml, списки include paths и плагины. - Зафиксируйте используемые кастомные правила, если есть.","content":"Шаги миграции Инвентаризация: - Соберите текущий prototool.yaml, списки include paths и плагины. - Зафиксируйте используемые кастомные правила, если есть."},{"id":"migration/prototool::top::12","title":"Prototool","section":"Шаги миграции","path":"/docs/guide/migration/prototool","headings":["Шаги миграции"],"excerpt":"Шаги миграции Зависимости: - Любые каталоги, которые вы вручную добавляли в include_paths, преобразуйте в git-репозитории (если ещё нет). - Добавьте их в deps (формат: github.com/owner/repo или путь к вашей приватной сис","content":"Шаги миграции Зависимости: - Любые каталоги, которые вы вручную добавляли в include_paths, преобразуйте в git-репозитории (если ещё нет). - Добавьте их в deps (формат: github.com/owner/repo или путь к вашей приватной системе Git)."},{"id":"migration/prototool::top::13","title":"Prototool","section":"Шаги миграции","path":"/docs/guide/migration/prototool","headings":["Шаги миграции"],"excerpt":"Шаги миграции Линтинг: - Определите какой group использовался (basic, default, …) → сопоставьте с наборами EasyP (MINIMAL, BASIC, DEFAULT). - Индивидуальные добавления (rules.add) перенесите в lint.use или except/ignore:","content":"Шаги миграции Линтинг: - Определите какой group использовался (basic, default, …) → сопоставьте с наборами EasyP (MINIMAL, BASIC, DEFAULT). - Индивидуальные добавления (rules.add) перенесите в lint.use или except/ignore: - Если правило нужно активировать — включите через набор или явно. - Если нужно отключить — добавьте в ignore."},{"id":"migration/prototool::top::14","title":"Prototool","section":"Шаги миграции","path":"/docs/guide/migration/prototool","headings":["Шаги миграции"],"excerpt":"Шаги миграции Генерация: - Сохраните список плагинов. В большинстве случаев имена совпадут (go, go-grpc, др.). - Если раньше использовали Docker-окружение Prototool — проверьте поддержку удалённых плагинов через API Serv","content":"Шаги миграции Генерация: - Сохраните список плагинов. В большинстве случаев имена совпадут (go, go-grpc, др.). - Если раньше использовали Docker-окружение Prototool — проверьте поддержку удалённых плагинов через API Service EasyP (опционально). - Перепишите в секцию generate.plugins."},{"id":"migration/prototool::top::15","title":"Prototool","section":"Шаги миграции","path":"/docs/guide/migration/prototool","headings":["Шаги миграции"],"excerpt":"Шаги миграции Дополнительные опции: - Настройки нейминга enum/service перенести в enum_zero_value_suffix, service_suffix. - Если были внешние скрипты для проверки breaking changes — удалите их и включите breaking с again","content":"Шаги миграции Дополнительные опции: - Настройки нейминга enum/service перенести в enum_zero_value_suffix, service_suffix. - Если были внешние скрипты для проверки breaking changes — удалите их и включите breaking с against_git_ref."},{"id":"migration/prototool::top::16","title":"Prototool","section":"Шаги миграции","path":"/docs/guide/migration/prototool","headings":["Шаги миграции"],"excerpt":"Шаги миграции Верификация: - Запустите: easyp mod update (скачивание deps). - Затем: easyp lint. - Далее: easyp generate. - И, если нужно: easyp breaking --against git-ref=origin/main.","content":"Шаги миграции Верификация: - Запустите: easyp mod update (скачивание deps). - Затем: easyp lint. - Далее: easyp generate. - И, если нужно: easyp breaking --against git-ref=origin/main."},{"id":"migration/prototool::top::17","title":"Prototool","section":"Шаги миграции","path":"/docs/guide/migration/prototool","headings":["Шаги миграции"],"excerpt":"Шаги миграции CI/CD: - Обновите workflow (GitHub Actions / GitLab) — замените вызовы Prototool на EasyP команды. - Добавьте шаг проверки несовместимых изменений.","content":"Шаги миграции CI/CD: - Обновите workflow (GitHub Actions / GitLab) — замените вызовы Prototool на EasyP команды. - Добавьте шаг проверки несовместимых изменений."},{"id":"migration/prototool::top::18","title":"Prototool","section":"Сопоставление правил (общая идея)","path":"/docs/guide/migration/prototool","headings":["Сопоставление правил (общая идея)"],"excerpt":"Сопоставление правил (общая идея) Prototool концепт EasyP ------------------- ------ lint.group lint.use (наборы) rules.add/remove except / ignore include_paths deps (git источники) plugins generate.plugins (внешние скри","content":"Сопоставление правил (общая идея) Prototool концепт EasyP ------------------- ------ lint.group lint.use (наборы) rules.add/remove except / ignore include_paths deps (git источники) plugins generate.plugins (внешние скрипты для breaking) breaking секция + команда"},{"id":"migration/prototool::top::19","title":"Prototool","section":"Сопоставление правил (общая идея)","path":"/docs/guide/migration/prototool","headings":["Сопоставление правил (общая идея)"],"excerpt":"Сопоставление правил (общая идея) ---","content":"Сопоставление правил (общая идея) ---"},{"id":"migration/prototool::top::20","title":"Prototool","section":"Приватные репозитории","path":"/docs/guide/migration/prototool","headings":["Приватные репозитории"],"excerpt":"Приватные репозитории Если ранее Prototool просто видел локальные каталоги, теперь: Добавьте SSH ключи/токены в CI для доступа к приватным Git. Укажите их в deps как обычные git-URL (формат зависит от реализации EasyP; д","content":"Приватные репозитории Если ранее Prototool просто видел локальные каталоги, теперь: Добавьте SSH ключи/токены в CI для доступа к приватным Git. Укажите их в deps как обычные git-URL (формат зависит от реализации EasyP; для публичных — стандартный)."},{"id":"migration/prototool::top::21","title":"Prototool","section":"Типовые проблемы при миграции","path":"/docs/guide/migration/prototool","headings":["Типовые проблемы при миграции"],"excerpt":"Типовые проблемы при миграции Проблема Причина Решение ---------- --------- --------- Правила линтера не совпадают Неверное сопоставление групп Проверить документацию EasyP по наборам правил Импорты не находятся Забыли д","content":"Типовые проблемы при миграции Проблема Причина Решение ---------- --------- --------- Правила линтера не совпадают Неверное сопоставление групп Проверить документацию EasyP по наборам правил Импорты не находятся Забыли добавить репозиторий в deps Добавить в deps и выполнить easyp mod update Генерация падает на опциях Плагин требует другие flags Проверить opts и документацию плагина breaking сообщает слишком много Слишком строгий базовый набор Добавить конкретные правила в breaking.ignore Долгая генерация Нет кеша/много deps Включить кэширование в CI (vendor/.easyp/deps)"},{"id":"migration/prototool::top::22","title":"Prototool","section":"Типовые проблемы при миграции","path":"/docs/guide/migration/prototool","headings":["Типовые проблемы при миграции"],"excerpt":"Типовые проблемы при миграции ---","content":"Типовые проблемы при миграции ---"},{"id":"migration/prototool::top::23","title":"Prototool","section":"Минимальная конфигурация после миграции","path":"/docs/guide/migration/prototool","headings":["Минимальная конфигурация после миграции"],"excerpt":"Минимальная конфигурация после миграции","content":"Минимальная конфигурация после миграции"},{"id":"migration/prototool::top::24","title":"Prototool","section":"Минимальная конфигурация после миграции","path":"/docs/guide/migration/prototool","headings":["Минимальная конфигурация после миграции"],"excerpt":"Минимальная конфигурация после миграции ---","content":"Минимальная конфигурация после миграции ---"},{"id":"migration/prototool::top::25","title":"Prototool","section":"Рекомендации по упрощению","path":"/docs/guide/migration/prototool","headings":["Рекомендации по упрощению"],"excerpt":"Рекомендации по упрощению Начните с минимального lint.use (MINIMAL), затем постепенно включайте дополнительные наборы. Не переносите слепо все ignore — часть правил может уже быть улучшена в EasyP. Сначала настроить deps","content":"Рекомендации по упрощению Начните с минимального lint.use (MINIMAL), затем постепенно включайте дополнительные наборы. Не переносите слепо все ignore — часть правил может уже быть улучшена в EasyP. Сначала настроить deps и генерацию, затем усложнять линт/нейминг. Фиксируйте миграцию по шагам (коммиты: deps → lint → generate → breaking → CI)."},{"id":"migration/prototool::top::26","title":"Prototool","section":"Проверка результата","path":"/docs/guide/migration/prototool","headings":["Проверка результата"],"excerpt":"Проверка результата Скрипт локальной быстрой проверки (пример):","content":"Проверка результата Скрипт локальной быстрой проверки (пример):"},{"id":"migration/prototool::top::27","title":"Prototool","section":"Проверка результата","path":"/docs/guide/migration/prototool","headings":["Проверка результата"],"excerpt":"Проверка результата ```bash #!/usr/bin/env bash set -euo pipefail","content":"Проверка результата ```bash #!/usr/bin/env bash set -euo pipefail"},{"id":"migration/prototool::top::28","title":"Prototool","section":"Проверка результата","path":"/docs/guide/migration/prototool","headings":["Проверка результата"],"excerpt":"Проверка результата echo \"[1] deps update\" easyp mod update","content":"Проверка результата echo \"[1] deps update\" easyp mod update"},{"id":"migration/prototool::top::29","title":"Prototool","section":"Проверка результата","path":"/docs/guide/migration/prototool","headings":["Проверка результата"],"excerpt":"Проверка результата echo \"[2] lint\" easyp lint","content":"Проверка результата echo \"[2] lint\" easyp lint"},{"id":"migration/prototool::top::30","title":"Prototool","section":"Проверка результата","path":"/docs/guide/migration/prototool","headings":["Проверка результата"],"excerpt":"Проверка результата echo \"[3] breaking vs main\" easyp breaking --against git-ref=origin/main echo \"Breaking changes detected (review needed)\"","content":"Проверка результата echo \"[3] breaking vs main\" easyp breaking --against git-ref=origin/main echo \"Breaking changes detected (review needed)\""},{"id":"migration/prototool::top::31","title":"Prototool","section":"Проверка результата","path":"/docs/guide/migration/prototool","headings":["Проверка результата"],"excerpt":"Проверка результата echo \"[4] generate\" easyp generate","content":"Проверка результата echo \"[4] generate\" easyp generate"},{"id":"migration/prototool::top::32","title":"Prototool","section":"Проверка результата","path":"/docs/guide/migration/prototool","headings":["Проверка результата"],"excerpt":"Проверка результата echo \"Done.\" ```","content":"Проверка результата echo \"Done.\" ```"},{"id":"migration/prototool::top::33","title":"Prototool","section":"Заключение","path":"/docs/guide/migration/prototool","headings":["Заключение"],"excerpt":"Заключение Миграция с Prototool на EasyP сводится к: Переносу путей и внешних каталогов в декларативные deps. Переформатированию линта под lint.use + ignore/except. Переносу генерации в generate.plugins. Добавлению встро","content":"Заключение Миграция с Prototool на EasyP сводится к: Переносу путей и внешних каталогов в декларативные deps. Переформатированию линта под lint.use + ignore/except. Переносу генерации в generate.plugins. Добавлению встроенного механизма breaking. Адаптации CI."},{"id":"migration/prototool::top::34","title":"Prototool","section":"Заключение","path":"/docs/guide/migration/prototool","headings":["Заключение"],"excerpt":"Заключение После этого конфигурация становится более прозрачной, а проверка несовместимых изменений — из коробки.","content":"Заключение После этого конфигурация становится более прозрачной, а проверка несовместимых изменений — из коробки."},{"id":"migration/prototool::top::35","title":"Prototool","section":"Заключение","path":"/docs/guide/migration/prototool","headings":["Заключение"],"excerpt":"Заключение *Готово: базовый перевод и расширенное руководство по миграции с Prototool на EasyP.*","content":"Заключение *Готово: базовый перевод и расширенное руководство по миграции с Prototool на EasyP.*"},{"id":"TRANSLATION_STATUS::top::0","title":"Translation Status (ru-guide)","path":"/docs/guide/TRANSLATION_STATUS","headings":[],"excerpt":"Этот файл отслеживает прогресс перевода русской документации. Используемые статусы: TODO — требуется перевод IN_PROGRESS — перевод начат, требуется вычитка DONE — перевод завершён и вычитан SKIPPED — не требует перевода ","content":"Этот файл отслеживает прогресс перевода русской документации. Используемые статусы: TODO — требуется перевод IN_PROGRESS — перевод начат, требуется вычитка DONE — перевод завершён и вычитан SKIPPED — не требует перевода (намеренно оставлено на английском)"},{"id":"TRANSLATION_STATUS::top::1","title":"Translation Status (ru-guide)","path":"/docs/guide/TRANSLATION_STATUS","headings":[],"excerpt":"Правила: После полного перевода файла убрать исходный английский текст и маркер Термины протокола и ключевые идентификаторы (названия правил, CLI команды, YAML ключи) НЕ переводим. Если структура исходного файла изменила","content":"Правила: После полного перевода файла убрать исходный английский текст и маркер Термины протокола и ключевые идентификаторы (названия правил, CLI команды, YAML ключи) НЕ переводим. Если структура исходного файла изменилась — добавить в начало: Для больших изменений: сначала IN_PROGRESS, после вычитки менять на DONE."},{"id":"TRANSLATION_STATUS::summary::2","title":"Translation Status (ru-guide)","section":"Summary","path":"/docs/guide/TRANSLATION_STATUS#summary","headings":["Summary"],"excerpt":"Summary Итого файлов: 76 DONE: 76 IN_PROGRESS: 0 TODO: 0","content":"Summary Итого файлов: 76 DONE: 76 IN_PROGRESS: 0 TODO: 0"},{"id":"TRANSLATION_STATUS::priority-order::3","title":"Translation Status (ru-guide)","section":"Priority Order (рекомендованный)","path":"/docs/guide/TRANSLATION_STATUS#priority-order","headings":["Priority Order (рекомендованный)"],"excerpt":"Priority Order (рекомендованный) introduction/what-is.md introduction/quickstart.md introduction/install.md cli/linter/linter.md cli/generator/generator.md cli/package-manager/package-manager.md cli/breaking-changes/brea","content":"Priority Order (рекомендованный) introduction/what-is.md introduction/quickstart.md introduction/install.md cli/linter/linter.md cli/generator/generator.md cli/package-manager/package-manager.md cli/breaking-changes/breaking-changes.md api-service/overview.md migration/* (пакетом)"},{"id":"TRANSLATION_STATUS::priority-order::4","title":"Translation Status (ru-guide)","section":"Priority Order (рекомендованный)","path":"/docs/guide/TRANSLATION_STATUS#priority-order","headings":["Priority Order (рекомендованный)"],"excerpt":"Priority Order (рекомендованный) ---","content":"Priority Order (рекомендованный) ---"},{"id":"TRANSLATION_STATUS::file-status-table::5","title":"Translation Status (ru-guide)","section":"File Status Table","path":"/docs/guide/TRANSLATION_STATUS#file-status-table","headings":["File Status Table"],"excerpt":"File Status Table File Status Notes ------ -------- ------- introduction/what-is.md DONE Полный перевод выполнен introduction/quickstart.md DONE Структура сохранена, перевод вычитан introduction/install.md DONE Переведен","content":"File Status Table File Status Notes ------ -------- ------- introduction/what-is.md DONE Полный перевод выполнен introduction/quickstart.md DONE Структура сохранена, перевод вычитан introduction/install.md DONE Переведено, команды проверены api-service/overview.md DONE Переведено ci-cd/github-actions.md DONE Переведено ci-cd/gitlab.md DONE Переведено cli/auto-completion/auto-completion.md DONE Переведено cli/breaking-changes/breaking-changes.md DONE Переведено и вычитано cli/breaking-changes/rules/enum-no-delete.md DONE Переведено cli/breaking-changes/rules/enum-value-no-delete.md DONE Переведено cli/breaking-changes/rules/enum-value-same-name.md DONE Переведено cli/breaking-changes/rules/field-no-delete.md DONE Переведено cli/breaking-changes/rules/field-same-cardinality.md DONE Переведено cli/breaking-changes/rules/field-same-type.md DONE Переведено cli/breaking-changes/rules/import-no-delete.md DONE Переведено cli/breaking-changes/rules/message-no-delete.md DONE Переведено cli/breaking-changes/rules/oneof-field-no-delete.md DONE Переведено cli/breaking-changes/rules/oneof-field-same-type.md DONE Переведено cli/breaking-changes/rules/oneof-no-delete.md DONE Переведено cli/breaking-changes/rules/rpc-no-delete.md DONE Переведено cli/breaking-changes/rules/rpc-same-request-type.md DONE Переведено cli/breaking-changes/rules/rpc-same-response-type.md DONE Переведено cli/breaking-changes/rules/service-no-delete.md DONE Переведено cli/configuration/configuration.md DONE Переведено cli/generator/examples/go.md DONE Переведено cli/generator/examples/grpc-gateway.md DONE Переведено cli/generator/examples/validate.md DONE Переведено cli/generator/generator.md DONE Переведено и вычитано cli/linter/linter.md DONE Переведено и вычитано cli/linter/rules/comment-enum-value.md DONE Переведено cli/linter/rules/comment-enum.md DONE Переведено cli/linter/rules/comment-field.md DONE Переведено cli/linter/rules/comment-message.md DONE Переведено cli/linter/rules/comment-oneof.md DONE Переведено cli/linter/rules/comment-rpc.md DONE Переведено cli/linter/rules/comment-service.md DONE Переведено cli/linter/rules/directory-same-package.md DONE Переведено cli/linter/rules/enum-first-value-zero.md DONE Переведено cli/linter/rules/enum-no-allow-alias.md DONE Переведено cli/linter/rules/enum-pascal-case.md DONE Переведено cli/linter/rules/enum-value-prefix.md DONE Переведено cli/linter/rules/enum-value-upper-snake-case.md DONE Переведено cli/linter/rules/enum-zero-value-suffix.md DONE Переведено cli/linter/rules/field-lower-snake-case.md DONE Переведено cli/linter/rules/file-lower-snake-case.md DONE Переведено cli/linter/rules/import-no-public.md DONE Переведено cli/linter/rules/import-no-weak.md DONE Переведено cli/linter/rules/import-used.md DONE Переведено cli/linter/rules/message-pascal-case.md DONE Переведено cli/linter/rules/oneof-lower-snake-case.md DONE Переведено cli/linter/rules/package-defined.md DONE Переведено cli/linter/rules/package-directory-match.md DONE Переведено cli/linter/rules/package-lower-snake-case.md DONE Переведено cli/linter/rules/package-same-csharp-namespace.md DONE Переведено cli/linter/rules/package-same-directory.md DONE Переведено cli/linter/rules/package-same-go-package.md DONE Переведено cli/linter/rules/package-same-java-multiple-files.md DONE Переведено cli/linter/rules/package-same-java-package.md DONE Переведено cli/linter/rules/package-same-php-namespace.md DONE Переведено cli/linter/rules/package-same-ruby-package.md DONE Переведено cli/linter/rules/package-same-swift-prefix.md DONE Переведено cli/linter/rules/package-version-suffix.md DONE Переведено cli/linter/rules/rpc-no-client-streaming.md DONE Переведено cli/linter/rules/rpc-no-server-streaming.md DONE Переведено cli/linter/rules/rpc-pascal-case.md DONE Переведено cli/linter/rules/rpc-request-response-unique.md DONE Переведено cli/linter/rules/rpc-request-standard-name.md DONE Переведено cli/linter/rules/rpc-response-standard-name.md DONE Переведено cli/linter/rules/service-pascal-case.md DONE Переведено cli/linter/rules/service-suffix.md DONE Переведено cli/package-manager/easyp-vs-buf.md DONE Переведено cli/package-manager/package-manager.md DONE Переведено и вычитано migration/buf-cli.md DONE Переведено migration/protoc.md DONE Переведено migration/protolock.md DONE Переведено migration/prototool.md DONE Переведено"},{"id":"TRANSLATION_STATUS::workflow::6","title":"Translation Status (ru-guide)","section":"Workflow","path":"/docs/guide/TRANSLATION_STATUS#workflow","headings":["Workflow"],"excerpt":"Workflow Выбираем файл со статусом TODO. Меняем статус на IN_PROGRESS здесь. Переводим, проверяем терминологию (сверка с глоссарием — добавить позже). Меняем статус на DONE. Удаляем маркер внутри файла.","content":"Workflow Выбираем файл со статусом TODO. Меняем статус на IN_PROGRESS здесь. Переводим, проверяем терминологию (сверка с глоссарием — добавить позже). Меняем статус на DONE. Удаляем маркер внутри файла."},{"id":"TRANSLATION_STATUS::planned-terminology::7","title":"Translation Status (ru-guide)","section":"Planned Terminology (черновик)","path":"/docs/guide/TRANSLATION_STATUS#planned-terminology","headings":["Planned Terminology (черновик)"],"excerpt":"Planned Terminology (черновик) EN RU Notes ---- ---- ------- Linting Линтинг Транслитерация Breaking Changes Несовместимые изменения Название секции Dependency Зависимость Code Generation Генерация кода Lock file Lock-фа","content":"Planned Terminology (черновик) EN RU Notes ---- ---- ------- Linting Линтинг Транслитерация Breaking Changes Несовместимые изменения Название секции Dependency Зависимость Code Generation Генерация кода Lock file Lock-файл Remote Plugin Удалённый плагин Package Manager Менеджер пакетов"},{"id":"TRANSLATION_STATUS::planned-terminology::8","title":"Translation Status (ru-guide)","section":"Planned Terminology (черновик)","path":"/docs/guide/TRANSLATION_STATUS#planned-terminology","headings":["Planned Terminology (черновик)"],"excerpt":"Planned Terminology (черновик) (Будет дополнено.)","content":"Planned Terminology (черновик) (Будет дополнено.)"},{"id":"TRANSLATION_STATUS::planned-terminology::9","title":"Translation Status (ru-guide)","section":"Planned Terminology (черновик)","path":"/docs/guide/TRANSLATION_STATUS#planned-terminology","headings":["Planned Terminology (черновик)"],"excerpt":"Planned Terminology (черновик) ---","content":"Planned Terminology (черновик) ---"},{"id":"TRANSLATION_STATUS::top::10","title":"Translation Status (ru-guide)","section":"История обновлений","path":"/docs/guide/TRANSLATION_STATUS","headings":["История обновлений"],"excerpt":"История обновлений Initial file created: all statuses set (3 IN_PROGRESS, rest TODO). Marked breaking-changes page as DONE. Linter rules (41 файлов) переведены: статусы DONE. Breaking-changes rules (15 файлов) вычитаны и","content":"История обновлений Initial file created: all statuses set (3 IN_PROGRESS, rest TODO). Marked breaking-changes page as DONE. Linter rules (41 файлов) переведены: статусы DONE. Breaking-changes rules (15 файлов) вычитаны и помечены DONE. Все оставшиеся страницы переведены: итог DONE = 76."}] \ No newline at end of file +[{"id":"api-service/overview::top::0","title":"Обзор API Service","path":"/docs/guide/api-service/overview","headings":[],"excerpt":"**Централизованный сервис выполнения protobuf‑плагинов для консистентной изолированной генерации кода**","content":"**Централизованный сервис выполнения protobuf‑плагинов для консистентной изолированной генерации кода**"},{"id":"api-service/overview::top::1","title":"Обзор API Service","path":"/docs/guide/api-service/overview","headings":[],"excerpt":"EasyP API Service устраняет хаос управления плагинами, предоставляя централизованный запуск protobuf/gRPC плагинов в изолированных Docker‑контейнерах. Он даёт единую платформу, позволяющую командам стандартизировать проц","content":"EasyP API Service устраняет хаос управления плагинами, предоставляя централизованный запуск protobuf/gRPC плагинов в изолированных Docker‑контейнерах. Он даёт единую платформу, позволяющую командам стандартизировать процесс генерации кода без операционных затрат на установку и поддержку плагинов на машинах разработчиков."},{"id":"api-service/overview::easyp-api-service::2","title":"Обзор API Service","section":"Зачем нужен EasyP API Service?","path":"/docs/guide/api-service/overview#easyp-api-service","headings":["Зачем нужен EasyP API Service?"],"excerpt":"Зачем нужен EasyP API Service?","content":"Зачем нужен EasyP API Service?"},{"id":"api-service/overview::top::3","title":"Обзор API Service","section":"Проблема","path":"/docs/guide/api-service/overview","headings":["Проблема"],"excerpt":"Проблема Управление генерацией protobuf/gRPC кода в командах порождает существенную операционную сложность:","content":"Проблема Управление генерацией protobuf/gRPC кода в командах порождает существенную операционную сложность:"},{"id":"api-service/overview::top::4","title":"Обзор API Service","section":"Несогласованность версий","path":"/docs/guide/api-service/overview","headings":["Несогласованность версий"],"excerpt":"Несогласованность версий Разработчики локально используют разные версии плагинов → расхождения в генерированном коде и падения сборки Синдром «у меня работает» при различиях окружений Требуется ручная координация, чтобы ","content":"Несогласованность версий Разработчики локально используют разные версии плагинов → расхождения в генерированном коде и падения сборки Синдром «у меня работает» при различиях окружений Требуется ручная координация, чтобы вся команда была синхронизирована по версиям"},{"id":"api-service/overview::top::5","title":"Обзор API Service","section":"Операционные накладные расходы","path":"/docs/guide/api-service/overview","headings":["Операционные накладные расходы"],"excerpt":"Операционные накладные расходы DevOps тратят время на установку и обновление плагинов на рабочих станциях Новый разработчик — ручная настройка правильных версий Обновление плагинов требует коммуникации с каждым отдельно ","content":"Операционные накладные расходы DevOps тратят время на установку и обновление плагинов на рабочих станциях Новый разработчик — ручная настройка правильных версий Обновление плагинов требует коммуникации с каждым отдельно Нет централизованного контроля утверждённых версий"},{"id":"api-service/overview::top::6","title":"Обзор API Service","section":"Риски безопасности и комплаенса","path":"/docs/guide/api-service/overview","headings":["Риски безопасности и комплаенса"],"excerpt":"Риски безопасности и комплаенса Плагины ставятся из разных источников без валидации Нет аудита: какой плагин для какого билда использовался Сложно применять политики безопасности к инструментам генерации","content":"Риски безопасности и комплаенса Плагины ставятся из разных источников без валидации Нет аудита: какой плагин для какого билда использовался Сложно применять политики безопасности к инструментам генерации"},{"id":"api-service/overview::top::7","title":"Обзор API Service","section":"Решение: централизованный запуск плагинов","path":"/docs/guide/api-service/overview","headings":["Решение: централизованный запуск плагинов"],"excerpt":"Решение: централизованный запуск плагинов EasyP API Service решает эти проблемы за счёт централизованного управления:","content":"Решение: централизованный запуск плагинов EasyP API Service решает эти проблемы за счёт централизованного управления:"},{"id":"api-service/overview::top::8","title":"Обзор API Service","section":"Решение: централизованный запуск плагинов","path":"/docs/guide/api-service/overview","headings":["Решение: централизованный запуск плагинов"],"excerpt":"Решение: централизованный запуск плагинов Проблема Решение ---------- --------- **Контроль версий** Мгновенное распространение новых версий через Docker‑образы **Операции** Команда эксплуатации управляет конфигурациями б","content":"Решение: централизованный запуск плагинов Проблема Решение ---------- --------- **Контроль версий** Мгновенное распространение новых версий через Docker‑образы **Операции** Команда эксплуатации управляет конфигурациями без доступа на машины разработчиков **Безопасность** Все плагины запускаются в изолированных контейнерах с ограничениями ресурсов **Консистентность** Единая среда выполнения вне зависимости от локальной установки **Опыт разработчика** Не нужно устанавливать и сопровождать плагины локально"},{"id":"api-service/overview::top::9","title":"Обзор API Service","section":"Архитектура","path":"/docs/guide/api-service/overview","headings":["Архитектура"],"excerpt":"Архитектура Архитектура сервиса упрощена и сфокусирована на надёжном выполнении плагинов:","content":"Архитектура Архитектура сервиса упрощена и сфокусирована на надёжном выполнении плагинов:"},{"id":"api-service/overview::api-layer::10","title":"Обзор API Service","section":"API Layer","path":"/docs/guide/api-service/overview#api-layer","headings":["API Layer"],"excerpt":"API Layer **gRPC Server** — основной API для запросов генерации Каждый запуск плагина — отдельный gRPC‑запрос Получает CodeGeneratorRequest от CLI","content":"API Layer **gRPC Server** — основной API для запросов генерации Каждый запуск плагина — отдельный gRPC‑запрос Получает CodeGeneratorRequest от CLI"},{"id":"api-service/overview::execution-engine::11","title":"Обзор API Service","section":"Execution Engine","path":"/docs/guide/api-service/overview#execution-engine","headings":["Execution Engine"],"excerpt":"Execution Engine **Docker Runtime** — изолированный запуск плагинов Подтягивает образы из публичных реестров (Docker Hub и т.п.) Применяет лимиты CPU/памяти на плагин","content":"Execution Engine **Docker Runtime** — изолированный запуск плагинов Подтягивает образы из публичных реестров (Docker Hub и т.п.) Применяет лимиты CPU/памяти на плагин"},{"id":"api-service/overview::storage-layer::12","title":"Обзор API Service","section":"Storage Layer","path":"/docs/guide/api-service/overview#storage-layer","headings":["Storage Layer"],"excerpt":"Storage Layer **PostgreSQL** хранит параметры выполнения: - Ограничения ресурсов (CPU, память) - Конфигурацию и метаданные плагинов - Логи выполнения (аудит) - _Примечание: функциональность хранения будет расширяться_","content":"Storage Layer **PostgreSQL** хранит параметры выполнения: - Ограничения ресурсов (CPU, память) - Конфигурацию и метаданные плагинов - Логи выполнения (аудит) - _Примечание: функциональность хранения будет расширяться_"},{"id":"api-service/overview::monitoring::13","title":"Обзор API Service","section":"Monitoring","path":"/docs/guide/api-service/overview#monitoring","headings":["Monitoring"],"excerpt":"Monitoring **Prometheus** — сбор метрик Отслеживает время выполнения, успешность, использование ресурсов","content":"Monitoring **Prometheus** — сбор метрик Отслеживает время выполнения, успешность, использование ресурсов"},{"id":"api-service/overview::easyp-cli::14","title":"Обзор API Service","section":"Локальное выполнение (EasyP CLI)","path":"/docs/guide/api-service/overview#easyp-cli","headings":["Локальное выполнение (EasyP CLI)"],"excerpt":"Локальное выполнение (EasyP CLI) При локальном запуске CLI поддерживает: **Installed plugins**: системно установленные protoc плагины **WASM plugins**: лёгкие WebAssembly плагины","content":"Локальное выполнение (EasyP CLI) При локальном запуске CLI поддерживает: **Installed plugins**: системно установленные protoc плагины **WASM plugins**: лёгкие WebAssembly плагины"},{"id":"api-service/overview::api-service::15","title":"Обзор API Service","section":"Удалённое выполнение (API Service)","path":"/docs/guide/api-service/overview#api-service","headings":["Удалённое выполнение (API Service)"],"excerpt":"Удалённое выполнение (API Service) При работе через сервис: **Только Docker**: плагины запускаются как контейнеры **Центральный контроль**: операционная команда управляет доступными версиями **Консистентная среда**: один","content":"Удалённое выполнение (API Service) При работе через сервис: **Только Docker**: плагины запускаются как контейнеры **Центральный контроль**: операционная команда управляет доступными версиями **Консистентная среда**: одинаковое окружение для всех разработчиков"},{"id":"api-service/overview::top::16","title":"Обзор API Service","section":"Шаги выполнения","path":"/docs/guide/api-service/overview","headings":["Шаги выполнения"],"excerpt":"Шаги выполнения **CLI Parsing**: CLI парсит локальные .proto файлы **Request Sending**: Отправляет CodeGeneratorRequest в API Service (по одному на плагин) **Parameter Lookup**: Сервис получает параметры запуска из Postg","content":"Шаги выполнения **CLI Parsing**: CLI парсит локальные .proto файлы **Request Sending**: Отправляет CodeGeneratorRequest в API Service (по одному на плагин) **Parameter Lookup**: Сервис получает параметры запуска из PostgreSQL **Docker Execution**: Запускает плагин в изолированном контейнере **Metrics Recording**: Записывает метрики после завершения **Response**: Возвращает сгенерированный код обратно в CLI"},{"id":"api-service/overview::top::17","title":"Обзор API Service","section":"Ключевые возможности","path":"/docs/guide/api-service/overview","headings":["Ключевые возможности"],"excerpt":"Ключевые возможности Возможность Описание ------------- ---------- **🐳 Изоляция плагинов** Каждый плагин в отдельном безопасном контейнере **⚙️ Контроль ресурсов** Лимиты CPU и памяти на уровне контейнера **📊 Метрики &","content":"Ключевые возможности Возможность Описание ------------- ---------- **🐳 Изоляция плагинов** Каждый плагин в отдельном безопасном контейнере **⚙️ Контроль ресурсов** Лимиты CPU и памяти на уровне контейнера **📊 Метрики & мониторинг** Полный набор Prometheus метрик **🔄 Управление версиями** Централизованно через Docker‑образы **⚡ Простой протокол** Стандарт CodeGeneratorRequest/Response **🔒 Безопасность прежде всего** Изоляция + ограниченные ресурсы"},{"id":"api-service/overview::top::18","title":"Обзор API Service","section":"Конфигурация","path":"/docs/guide/api-service/overview","headings":["Конфигурация"],"excerpt":"Конфигурация Сервис настраивается через переменные окружения.","content":"Конфигурация Сервис настраивается через переменные окружения."},{"id":"api-service/overview::top::19","title":"Обзор API Service","section":"Хранение параметров плагинов","path":"/docs/guide/api-service/overview","headings":["Хранение параметров плагинов"],"excerpt":"Хранение параметров плагинов PostgreSQL хранит параметры выполнения для каждого плагина:","content":"Хранение параметров плагинов PostgreSQL хранит параметры выполнения для каждого плагина:"},{"id":"api-service/overview::top::20","title":"Обзор API Service","section":"Хранение параметров плагинов","path":"/docs/guide/api-service/overview","headings":["Хранение параметров плагинов"],"excerpt":"Хранение параметров плагинов ::: tip Схема хранения будет расширена — аудит логов, аналитика использования, кеширование плагинов. :::","content":"Хранение параметров плагинов ::: tip Схема хранения будет расширена — аудит логов, аналитика использования, кеширование плагинов. :::"},{"id":"api-service/overview::easyp-cli::21","title":"Обзор API Service","section":"Интеграция с EasyP CLI","path":"/docs/guide/api-service/overview#easyp-cli","headings":["Интеграция с EasyP CLI"],"excerpt":"Интеграция с EasyP CLI Пример easyp.yaml для удалённого запуска:","content":"Интеграция с EasyP CLI Пример easyp.yaml для удалённого запуска:"},{"id":"api-service/overview::easyp-cli::22","title":"Обзор API Service","section":"Интеграция с EasyP CLI","path":"/docs/guide/api-service/overview#easyp-cli","headings":["Интеграция с EasyP CLI"],"excerpt":"Интеграция с EasyP CLI Запуск генерации:","content":"Интеграция с EasyP CLI Запуск генерации:"},{"id":"api-service/overview::easyp-cli::23","title":"Обзор API Service","section":"Интеграция с EasyP CLI","path":"/docs/guide/api-service/overview#easyp-cli","headings":["Интеграция с EasyP CLI"],"excerpt":"Интеграция с EasyP CLI CLI: Парсит protobuf‑файлы Отправляет отдельные запросы в сервис для каждого плагина Получает ответы с кодом Записывает файлы в указанные директории","content":"Интеграция с EasyP CLI CLI: Парсит protobuf‑файлы Отправляет отдельные запросы в сервис для каждого плагина Получает ответы с кодом Записывает файлы в указанные директории"},{"id":"api-service/overview::top::24","title":"Обзор API Service","section":"Доступные метрики","path":"/docs/guide/api-service/overview","headings":["Доступные метрики"],"excerpt":"Доступные метрики Метрики Prometheus:","content":"Доступные метрики Метрики Prometheus:"},{"id":"api-service/overview::top::25","title":"Обзор API Service","section":"Доступные метрики","path":"/docs/guide/api-service/overview","headings":["Доступные метрики"],"excerpt":"Доступные метрики Метрика Описание --------- ---------- easyp_api_service_api_grpc_server_handled_total Общее число gRPC запросов по статусам easyp_api_service_api_grpc_server_handling_seconds Гистограмма задержек gRPC e","content":"Доступные метрики Метрика Описание --------- ---------- easyp_api_service_api_grpc_server_handled_total Общее число gRPC запросов по статусам easyp_api_service_api_grpc_server_handling_seconds Гистограмма задержек gRPC easyp_api_service_generated_plugin_code_total Выполнения плагинов по имени easyp_api_service_repo_call_duration_seconds Латентность запросов к БД easyp_api_service_repo_errors_total Количество ошибок доступа к БД easyp_api_service_standard_panics_total Число восстановленных паник"},{"id":"api-service/overview::top::26","title":"Обзор API Service","section":"Характеристики производительности","path":"/docs/guide/api-service/overview","headings":["Характеристики производительности"],"excerpt":"Характеристики производительности Показатель Типичное значение Примечания ----------- ------------------- ----------- **Cold Start** 2–5 сек Первая загрузка образа **Warm Start** 100–500 мс Образ закеширован **Throughput","content":"Характеристики производительности Показатель Типичное значение Примечания ----------- ------------------- ----------- **Cold Start** 2–5 сек Первая загрузка образа **Warm Start** 100–500 мс Образ закеширован **Throughput** 20–50 одновременных Зависит от ресурсов **Memory Usage** 50–200 MB На выполнение одного плагина"},{"id":"api-service/overview::top::27","title":"Обзор API Service","section":"Изоляция контейнеров","path":"/docs/guide/api-service/overview","headings":["Изоляция контейнеров"],"excerpt":"Изоляция контейнеров Каждый плагин в отдельном эфемерном контейнере Нет сетевого доступа в процессе выполнения Лимиты CPU/памяти через Docker Контейнер удаляется после завершения","content":"Изоляция контейнеров Каждый плагин в отдельном эфемерном контейнере Нет сетевого доступа в процессе выполнения Лимиты CPU/памяти через Docker Контейнер удаляется после завершения"},{"id":"api-service/overview::api::28","title":"Обзор API Service","section":"Безопасность API","path":"/docs/guide/api-service/overview#api","headings":["Безопасность API"],"excerpt":"Безопасность API gRPC транспорт Поддержка токенов аутентификации (в продакшн окружениях) Валидация входных данных Аудитные логи в PostgreSQL","content":"Безопасность API gRPC транспорт Поддержка токенов аутентификации (в продакшн окружениях) Валидация входных данных Аудитные логи в PostgreSQL"},{"id":"api-service/overview::top::29","title":"Обзор API Service","section":"Масштабирование","path":"/docs/guide/api-service/overview","headings":["Масштабирование"],"excerpt":"Масштабирование **Горизонтальное**: несколько инстансов за балансировщиком **Ресурсы**: настройка лимитов для тяжёлых плагинов **База данных**: репликация PostgreSQL для отказоустойчивости","content":"Масштабирование **Горизонтальное**: несколько инстансов за балансировщиком **Ресурсы**: настройка лимитов для тяжёлых плагинов **База данных**: репликация PostgreSQL для отказоустойчивости"},{"id":"api-service/overview::top::30","title":"Обзор API Service","section":"Мониторинг","path":"/docs/guide/api-service/overview","headings":["Мониторинг"],"excerpt":"Мониторинг **Метрики**: Prometheus **Алертинг**: оповещения на высокие ошибки/латентность **Логи**: структурированные для аудита и отладки","content":"Мониторинг **Метрики**: Prometheus **Алертинг**: оповещения на высокие ошибки/латентность **Логи**: структурированные для аудита и отладки"},{"id":"api-service/overview::top::31","title":"Обзор API Service","section":"План развития","path":"/docs/guide/api-service/overview","headings":["План развития"],"excerpt":"План развития Запланировано: Кеширование результатов генерации Расширенный аудит и аналитика использования Поддержка приватных реестров плагинов Более умное распределение ресурсов","content":"План развития Запланировано: Кеширование результатов генерации Расширенный аудит и аналитика использования Поддержка приватных реестров плагинов Более умное распределение ресурсов"},{"id":"api-service/overview::top::32","title":"Обзор API Service","section":"Сообщество и поддержка","path":"/docs/guide/api-service/overview","headings":["Сообщество и поддержка"],"excerpt":"Сообщество и поддержка **💬 Telegram чат** — обсуждения **🐛 GitHub Issues** — баги и запросы фич **📖 Документация** — полный набор материалов","content":"Сообщество и поддержка **💬 Telegram чат** — обсуждения **🐛 GitHub Issues** — баги и запросы фич **📖 Документация** — полный набор материалов"},{"id":"api-service/overview::top::33","title":"Обзор API Service","section":"Сообщество и поддержка","path":"/docs/guide/api-service/overview","headings":["Сообщество и поддержка"],"excerpt":"Сообщество и поддержка *Упростите свои protobuf‑воркфлоу с централизованным управлением выполнением плагинов.*","content":"Сообщество и поддержка *Упростите свои protobuf‑воркфлоу с централизованным управлением выполнением плагинов.*"},{"id":"ci-cd/github-actions::top::0","title":"GitHub Actions","path":"/docs/guide/ci-cd/github-actions","headings":[],"excerpt":"Полное руководство по интеграции EasyP в конвейеры GitHub Actions для линтинга, проверки несовместимых изменений, генерации кода и автоматизации релизов.","content":"Полное руководство по интеграции EasyP в конвейеры GitHub Actions для линтинга, проверки несовместимых изменений, генерации кода и автоматизации релизов."},{"id":"ci-cd/github-actions::easyp-ci::1","title":"GitHub Actions","section":"Зачем использовать EasyP в CI","path":"/docs/guide/ci-cd/github-actions#easyp-ci","headings":["Зачем использовать EasyP в CI"],"excerpt":"Зачем использовать EasyP в CI Встраивание EasyP в GitHub Actions даёт: Единообразие правил линтинга и генерации между разработчиками. Автоматическое выявление несовместимых изменений (breaking changes) до мержа. Гарантию","content":"Зачем использовать EasyP в CI Встраивание EasyP в GitHub Actions даёт: Единообразие правил линтинга и генерации между разработчиками. Автоматическое выявление несовместимых изменений (breaking changes) до мержа. Гарантию, что сгенерированный код не «устарел» относительно .proto. Возможность централизованной проверки зависимостей и версии конфигурации."},{"id":"ci-cd/github-actions::top::2","title":"GitHub Actions","section":"Предварительные требования","path":"/docs/guide/ci-cd/github-actions","headings":["Предварительные требования"],"excerpt":"Предварительные требования Репозиторий содержит файл конфигурации easyp.yaml (или находится в корне, если запускается без --cfg). Установлены / определены зависимости в секции deps (если нужны внешние импорты). Для прива","content":"Предварительные требования Репозиторий содержит файл конфигурации easyp.yaml (или находится в корне, если запускается без --cfg). Установлены / определены зависимости в секции deps (если нужны внешние импорты). Для приватных Git-репозиториев настроен доступ (SSH key / deploy key / токен). В workflow есть шаги по установке Go (если EasyP поставляется через go install) или заранее подготовленный бинарь."},{"id":"ci-cd/github-actions::top::3","title":"GitHub Actions","section":"Базовый пример (быстрый старт)","path":"/docs/guide/ci-cd/github-actions","headings":["Базовый пример (быстрый старт)"],"excerpt":"Базовый пример (быстрый старт) Минимальный workflow для проверки линта и несовместимых изменений при открытия Pull Request:","content":"Базовый пример (быстрый старт) Минимальный workflow для проверки линта и несовместимых изменений при открытия Pull Request:"},{"id":"ci-cd/github-actions::top::4","title":"GitHub Actions","section":"Базовый пример (быстрый старт)","path":"/docs/guide/ci-cd/github-actions","headings":["Базовый пример (быстрый старт)"],"excerpt":"Базовый пример (быстрый старт) ```yaml name: easyp-ci","content":"Базовый пример (быстрый старт) ```yaml name: easyp-ci"},{"id":"ci-cd/github-actions::top::5","title":"GitHub Actions","section":"Базовый пример (быстрый старт)","path":"/docs/guide/ci-cd/github-actions","headings":["Базовый пример (быстрый старт)"],"excerpt":"Базовый пример (быстрый старт) on: pull_request: paths: - '**/*.proto' - 'easyp.yaml'","content":"Базовый пример (быстрый старт) on: pull_request: paths: - '**/*.proto' - 'easyp.yaml'"},{"id":"ci-cd/github-actions::top::6","title":"GitHub Actions","section":"Базовый пример (быстрый старт)","path":"/docs/guide/ci-cd/github-actions","headings":["Базовый пример (быстрый старт)"],"excerpt":"Базовый пример (быстрый старт) jobs: lint-and-breaking: runs-on: ubuntu-latest","content":"Базовый пример (быстрый старт) jobs: lint-and-breaking: runs-on: ubuntu-latest"},{"id":"ci-cd/github-actions::top::7","title":"GitHub Actions","section":"Базовый пример (быстрый старт)","path":"/docs/guide/ci-cd/github-actions","headings":["Базовый пример (быстрый старт)"],"excerpt":"Базовый пример (быстрый старт) steps: - name: Checkout uses: actions/checkout@v4","content":"Базовый пример (быстрый старт) steps: - name: Checkout uses: actions/checkout@v4"},{"id":"ci-cd/github-actions::top::8","title":"GitHub Actions","section":"Базовый пример (быстрый старт)","path":"/docs/guide/ci-cd/github-actions","headings":["Базовый пример (быстрый старт)"],"excerpt":"Базовый пример (быстрый старт) name: Setup Go uses: actions/setup-go@v5 with: go-version: '1.22'","content":"Базовый пример (быстрый старт) name: Setup Go uses: actions/setup-go@v5 with: go-version: '1.22'"},{"id":"ci-cd/github-actions::top::9","title":"GitHub Actions","section":"Базовый пример (быстрый старт)","path":"/docs/guide/ci-cd/github-actions","headings":["Базовый пример (быстрый старт)"],"excerpt":"Базовый пример (быстрый старт) name: Install EasyP run: go install github.com/easyp-tech/easyp/cmd/easyp@latest","content":"Базовый пример (быстрый старт) name: Install EasyP run: go install github.com/easyp-tech/easyp/cmd/easyp@latest"},{"id":"ci-cd/github-actions::top::10","title":"GitHub Actions","section":"Базовый пример (быстрый старт)","path":"/docs/guide/ci-cd/github-actions","headings":["Базовый пример (быстрый старт)"],"excerpt":"Базовый пример (быстрый старт) name: Verify EasyP version run: which easyp easyp version","content":"Базовый пример (быстрый старт) name: Verify EasyP version run: which easyp easyp version"},{"id":"ci-cd/github-actions::top::11","title":"GitHub Actions","section":"Базовый пример (быстрый старт)","path":"/docs/guide/ci-cd/github-actions","headings":["Базовый пример (быстрый старт)"],"excerpt":"Базовый пример (быстрый старт) name: Lint run: easyp lint","content":"Базовый пример (быстрый старт) name: Lint run: easyp lint"},{"id":"ci-cd/github-actions::top::12","title":"GitHub Actions","section":"Базовый пример (быстрый старт)","path":"/docs/guide/ci-cd/github-actions","headings":["Базовый пример (быстрый старт)"],"excerpt":"Базовый пример (быстрый старт) name: Breaking changes check (against main) run: easyp breaking --against git-ref=origin/main ```","content":"Базовый пример (быстрый старт) name: Breaking changes check (against main) run: easyp breaking --against git-ref=origin/main ```"},{"id":"ci-cd/github-actions::easyp::13","title":"GitHub Actions","section":"Установка EasyP","path":"/docs/guide/ci-cd/github-actions#easyp","headings":["Установка EasyP"],"excerpt":"Установка EasyP Варианты: Через go install (как в примере выше). Использование заранее собранного бинаря (артефакт релиза).","content":"Установка EasyP Варианты: Через go install (как в примере выше). Использование заранее собранного бинаря (артефакт релиза)."},{"id":"ci-cd/github-actions::top::14","title":"GitHub Actions","section":"Кэширование","path":"/docs/guide/ci-cd/github-actions","headings":["Кэширование"],"excerpt":"Кэширование Для ускорения повторных сборок можно кэшировать: Go модульный кеш (если используете генерацию с плагинами Go). Внешние зависимые Git-клонирования (папки vendor или содержимое deps при использовании easyp mod ","content":"Кэширование Для ускорения повторных сборок можно кэшировать: Go модульный кеш (если используете генерацию с плагинами Go). Внешние зависимые Git-клонирования (папки vendor или содержимое deps при использовании easyp mod download / easyp mod update). Сгенерированный код (если он тяжёлый, но чаще генерируется заново)."},{"id":"ci-cd/github-actions::top::15","title":"GitHub Actions","section":"Кэширование","path":"/docs/guide/ci-cd/github-actions","headings":["Кэширование"],"excerpt":"Кэширование Пример кэширования Go:","content":"Кэширование Пример кэширования Go:"},{"id":"ci-cd/github-actions::top::16","title":"GitHub Actions","section":"Кэширование","path":"/docs/guide/ci-cd/github-actions","headings":["Кэширование"],"excerpt":"Кэширование Пример кэширования каталога зависимостей EasyP (если вы используете локальный vendor-подход):","content":"Кэширование Пример кэширования каталога зависимостей EasyP (если вы используете локальный vendor-подход):"},{"id":"ci-cd/github-actions::top::17","title":"GitHub Actions","section":"Кэширование","path":"/docs/guide/ci-cd/github-actions","headings":["Кэширование"],"excerpt":"Кэширование (Создайте .easyp/deps как целевой каталог, если ваша стратегия скачивания такова.)","content":"Кэширование (Создайте .easyp/deps как целевой каталог, если ваша стратегия скачивания такова.)"},{"id":"ci-cd/github-actions::top::18","title":"GitHub Actions","section":"Линтинг","path":"/docs/guide/ci-cd/github-actions","headings":["Линтинг"],"excerpt":"Линтинг Рекомендуется: В PR: всегда запускать. На main: можно запускать для верификации перед релизом.","content":"Линтинг Рекомендуется: В PR: всегда запускать. На main: можно запускать для верификации перед релизом."},{"id":"ci-cd/github-actions::top::19","title":"GitHub Actions","section":"Линтинг","path":"/docs/guide/ci-cd/github-actions","headings":["Линтинг"],"excerpt":"Линтинг Расширенный пример с выводом подробностей и игнорированием комментариев (если включено в конфиг):","content":"Линтинг Расширенный пример с выводом подробностей и игнорированием комментариев (если включено в конфиг):"},{"id":"ci-cd/github-actions::breaking-changes::20","title":"GitHub Actions","section":"Проверка несовместимых изменений (Breaking Changes)","path":"/docs/guide/ci-cd/github-actions#breaking-changes","headings":["Проверка несовместимых изменений (Breaking Changes)"],"excerpt":"Проверка несовместимых изменений (Breaking Changes) EasyP может сравнивать текущее состояние против ветки / коммита / тега.","content":"Проверка несовместимых изменений (Breaking Changes) EasyP может сравнивать текущее состояние против ветки / коммита / тега."},{"id":"ci-cd/github-actions::breaking-changes::21","title":"GitHub Actions","section":"Проверка несовместимых изменений (Breaking Changes)","path":"/docs/guide/ci-cd/github-actions#breaking-changes","headings":["Проверка несовместимых изменений (Breaking Changes)"],"excerpt":"Проверка несовместимых изменений (Breaking Changes) Примеры: ```bash Сравнить против origin/main easyp breaking --against git-ref=origin/main","content":"Проверка несовместимых изменений (Breaking Changes) Примеры: ```bash Сравнить против origin/main easyp breaking --against git-ref=origin/main"},{"id":"ci-cd/github-actions::breaking-changes::22","title":"GitHub Actions","section":"Проверка несовместимых изменений (Breaking Changes)","path":"/docs/guide/ci-cd/github-actions#breaking-changes","headings":["Проверка несовместимых изменений (Breaking Changes)"],"excerpt":"Проверка несовместимых изменений (Breaking Changes) Сравнить против тега релиза easyp breaking --against git-ref=v1.5.2","content":"Проверка несовместимых изменений (Breaking Changes) Сравнить против тега релиза easyp breaking --against git-ref=v1.5.2"},{"id":"ci-cd/github-actions::breaking-changes::23","title":"GitHub Actions","section":"Проверка несовместимых изменений (Breaking Changes)","path":"/docs/guide/ci-cd/github-actions#breaking-changes","headings":["Проверка несовместимых изменений (Breaking Changes)"],"excerpt":"Проверка несовместимых изменений (Breaking Changes) Игнорировать определённые правила (если у вас настроено в easyp.yaml) easyp breaking ```","content":"Проверка несовместимых изменений (Breaking Changes) Игнорировать определённые правила (если у вас настроено в easyp.yaml) easyp breaking ```"},{"id":"ci-cd/github-actions::breaking-changes::24","title":"GitHub Actions","section":"Проверка несовместимых изменений (Breaking Changes)","path":"/docs/guide/ci-cd/github-actions#breaking-changes","headings":["Проверка несовместимых изменений (Breaking Changes)"],"excerpt":"Проверка несовместимых изменений (Breaking Changes) Workflow шаг:","content":"Проверка несовместимых изменений (Breaking Changes) Workflow шаг:"},{"id":"ci-cd/github-actions::breaking-changes::25","title":"GitHub Actions","section":"Проверка несовместимых изменений (Breaking Changes)","path":"/docs/guide/ci-cd/github-actions#breaking-changes","headings":["Проверка несовместимых изменений (Breaking Changes)"],"excerpt":"Проверка несовместимых изменений (Breaking Changes)","content":"Проверка несовместимых изменений (Breaking Changes)"},{"id":"ci-cd/github-actions::breaking-changes::26","title":"GitHub Actions","section":"Проверка несовместимых изменений (Breaking Changes)","path":"/docs/guide/ci-cd/github-actions#breaking-changes","headings":["Проверка несовместимых изменений (Breaking Changes)"],"excerpt":"Проверка несовместимых изменений (Breaking Changes) Если нужно «мягко» пропустить (например, выводить предупреждения, но не падать билд):","content":"Проверка несовместимых изменений (Breaking Changes) Если нужно «мягко» пропустить (например, выводить предупреждения, но не падать билд):"},{"id":"ci-cd/github-actions::breaking-changes::27","title":"GitHub Actions","section":"Проверка несовместимых изменений (Breaking Changes)","path":"/docs/guide/ci-cd/github-actions#breaking-changes","headings":["Проверка несовместимых изменений (Breaking Changes)"],"excerpt":"Проверка несовместимых изменений (Breaking Changes)","content":"Проверка несовместимых изменений (Breaking Changes)"},{"id":"ci-cd/github-actions::top::28","title":"GitHub Actions","section":"Генерация кода","path":"/docs/guide/ci-cd/github-actions","headings":["Генерация кода"],"excerpt":"Генерация кода Обычно для генерации:","content":"Генерация кода Обычно для генерации:"},{"id":"ci-cd/github-actions::top::29","title":"GitHub Actions","section":"Генерация кода","path":"/docs/guide/ci-cd/github-actions","headings":["Генерация кода"],"excerpt":"Генерация кода Если нужно явно указать конфиг:","content":"Генерация кода Если нужно явно указать конфиг:"},{"id":"ci-cd/github-actions::top::30","title":"GitHub Actions","section":"Генерация кода","path":"/docs/guide/ci-cd/github-actions","headings":["Генерация кода"],"excerpt":"Генерация кода Можно добавить проверку «не осталось ли не закоммиченных изменений» (гарантия, что сгенерированный код актуален):","content":"Генерация кода Можно добавить проверку «не осталось ли не закоммиченных изменений» (гарантия, что сгенерированный код актуален):"},{"id":"ci-cd/github-actions::matrix-strategy::31","title":"GitHub Actions","section":"Матрица (Matrix strategy)","path":"/docs/guide/ci-cd/github-actions#matrix-strategy","headings":["Матрица (Matrix strategy)"],"excerpt":"Матрица (Matrix strategy) Если у вас несколько вариантов конфигураций или разных языков генерации (через плагины), можно использовать matrix:","content":"Матрица (Matrix strategy) Если у вас несколько вариантов конфигураций или разных языков генерации (через плагины), можно использовать matrix:"},{"id":"ci-cd/github-actions::matrix-strategy::32","title":"GitHub Actions","section":"Матрица (Matrix strategy)","path":"/docs/guide/ci-cd/github-actions#matrix-strategy","headings":["Матрица (Matrix strategy)"],"excerpt":"Матрица (Matrix strategy) ```yaml jobs: generate: runs-on: ubuntu-latest strategy: fail-fast: false matrix: lang: [go, python] steps: - uses: actions/checkout@v4","content":"Матрица (Matrix strategy) ```yaml jobs: generate: runs-on: ubuntu-latest strategy: fail-fast: false matrix: lang: [go, python] steps: - uses: actions/checkout@v4"},{"id":"ci-cd/github-actions::matrix-strategy::33","title":"GitHub Actions","section":"Матрица (Matrix strategy)","path":"/docs/guide/ci-cd/github-actions#matrix-strategy","headings":["Матрица (Matrix strategy)"],"excerpt":"Матрица (Matrix strategy) name: Setup Go (only for go) if: matrix.lang == 'go' uses: actions/setup-go@v5 with: go-version: '1.22'","content":"Матрица (Matrix strategy) name: Setup Go (only for go) if: matrix.lang == 'go' uses: actions/setup-go@v5 with: go-version: '1.22'"},{"id":"ci-cd/github-actions::matrix-strategy::34","title":"GitHub Actions","section":"Матрица (Matrix strategy)","path":"/docs/guide/ci-cd/github-actions#matrix-strategy","headings":["Матрица (Matrix strategy)"],"excerpt":"Матрица (Matrix strategy) name: Install EasyP run: go install github.com/easyp-tech/easyp/cmd/easyp@latest","content":"Матрица (Matrix strategy) name: Install EasyP run: go install github.com/easyp-tech/easyp/cmd/easyp@latest"},{"id":"ci-cd/github-actions::matrix-strategy::35","title":"GitHub Actions","section":"Матрица (Matrix strategy)","path":"/docs/guide/ci-cd/github-actions#matrix-strategy","headings":["Матрица (Matrix strategy)"],"excerpt":"Матрица (Matrix strategy) name: Generate run: if [ \"${{ matrix.lang }}\" = \"go\" ]; then easyp generate elif [ \"${{ matrix.lang }}\" = \"python\" ]; then easyp generate --plugin python fi ```","content":"Матрица (Matrix strategy) name: Generate run: if [ \"${{ matrix.lang }}\" = \"go\" ]; then easyp generate elif [ \"${{ matrix.lang }}\" = \"python\" ]; then easyp generate --plugin python fi ```"},{"id":"ci-cd/github-actions::deps::36","title":"GitHub Actions","section":"Работа с приватными репозиториями (deps)","path":"/docs/guide/ci-cd/github-actions#deps","headings":["Работа с приватными репозиториями (deps)"],"excerpt":"Работа с приватными репозиториями (deps) Если вы указываете приватные Git-пакеты в секции deps:","content":"Работа с приватными репозиториями (deps) Если вы указываете приватные Git-пакеты в секции deps:"},{"id":"ci-cd/github-actions::deps::37","title":"GitHub Actions","section":"Работа с приватными репозиториями (deps)","path":"/docs/guide/ci-cd/github-actions#deps","headings":["Работа с приватными репозиториями (deps)"],"excerpt":"Работа с приватными репозиториями (deps) Настройте deploy key или используйте GIT_SSH_COMMAND с токеном. Добавьте known_hosts (либо установите StrictHostKeyChecking=no для внутренних систем, но осознанно).","content":"Работа с приватными репозиториями (deps) Настройте deploy key или используйте GIT_SSH_COMMAND с токеном. Добавьте known_hosts (либо установите StrictHostKeyChecking=no для внутренних систем, но осознанно)."},{"id":"ci-cd/github-actions::deps::38","title":"GitHub Actions","section":"Работа с приватными репозиториями (deps)","path":"/docs/guide/ci-cd/github-actions#deps","headings":["Работа с приватными репозиториями (deps)"],"excerpt":"Работа с приватными репозиториями (deps) Пример:","content":"Работа с приватными репозиториями (deps) Пример:"},{"id":"ci-cd/github-actions::deps::39","title":"GitHub Actions","section":"Работа с приватными репозиториями (deps)","path":"/docs/guide/ci-cd/github-actions#deps","headings":["Работа с приватными репозиториями (deps)"],"excerpt":"Работа с приватными репозиториями (deps) ```yaml name: Prepare SSH run: mkdir -p ~/.ssh echo \"${{ secrets.DEPLOY_KEY }}\" > ~/.ssh/id_rsa chmod 600 ~/.ssh/id_rsa ssh-keyscan github.com >> ~/.ssh/known_hosts","content":"Работа с приватными репозиториями (deps) ```yaml name: Prepare SSH run: mkdir -p ~/.ssh echo \"${{ secrets.DEPLOY_KEY }}\" > ~/.ssh/id_rsa chmod 600 ~/.ssh/id_rsa ssh-keyscan github.com >> ~/.ssh/known_hosts"},{"id":"ci-cd/github-actions::deps::40","title":"GitHub Actions","section":"Работа с приватными репозиториями (deps)","path":"/docs/guide/ci-cd/github-actions#deps","headings":["Работа с приватными репозиториями (deps)"],"excerpt":"Работа с приватными репозиториями (deps) name: Update deps run: easyp mod update ```","content":"Работа с приватными репозиториями (deps) name: Update deps run: easyp mod update ```"},{"id":"ci-cd/github-actions::top::41","title":"GitHub Actions","section":"Оптимизация времени сборки","path":"/docs/guide/ci-cd/github-actions","headings":["Оптимизация времени сборки"],"excerpt":"Оптимизация времени сборки Используйте кэш для Go / deps. Запускайте линт/брейкинг только если изменились .proto или easyp.yaml (paths фильтр). Разделяйте workflow: быстрый линт в PR, тяжелая генерация в push на main. Вы","content":"Оптимизация времени сборки Используйте кэш для Go / deps. Запускайте линт/брейкинг только если изменились .proto или easyp.yaml (paths фильтр). Разделяйте workflow: быстрый линт в PR, тяжелая генерация в push на main. Выносите генерацию OpenAPI / gRPC-Gateway в отдельный job (параллелизм)."},{"id":"ci-cd/github-actions::workflow::42","title":"GitHub Actions","section":"Продвинутый workflow (многостадийный)","path":"/docs/guide/ci-cd/github-actions#workflow","headings":["Продвинутый workflow (многостадийный)"],"excerpt":"Продвинутый workflow (многостадийный) ```yaml name: easyp-pipeline","content":"Продвинутый workflow (многостадийный) ```yaml name: easyp-pipeline"},{"id":"ci-cd/github-actions::workflow::43","title":"GitHub Actions","section":"Продвинутый workflow (многостадийный)","path":"/docs/guide/ci-cd/github-actions#workflow","headings":["Продвинутый workflow (многостадийный)"],"excerpt":"Продвинутый workflow (многостадийный) on: pull_request: paths: - '**/*.proto' - 'easyp.yaml' push: branches: - main","content":"Продвинутый workflow (многостадийный) on: pull_request: paths: - '**/*.proto' - 'easyp.yaml' push: branches: - main"},{"id":"ci-cd/github-actions::workflow::44","title":"GitHub Actions","section":"Продвинутый workflow (многостадийный)","path":"/docs/guide/ci-cd/github-actions#workflow","headings":["Продвинутый workflow (многостадийный)"],"excerpt":"Продвинутый workflow (многостадийный) jobs: validate: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4","content":"Продвинутый workflow (многостадийный) jobs: validate: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4"},{"id":"ci-cd/github-actions::workflow::45","title":"GitHub Actions","section":"Продвинутый workflow (многостадийный)","path":"/docs/guide/ci-cd/github-actions#workflow","headings":["Продвинутый workflow (многостадийный)"],"excerpt":"Продвинутый workflow (многостадийный) uses: actions/setup-go@v5 with: go-version: '1.22'","content":"Продвинутый workflow (многостадийный) uses: actions/setup-go@v5 with: go-version: '1.22'"},{"id":"ci-cd/github-actions::workflow::46","title":"GitHub Actions","section":"Продвинутый workflow (многостадийный)","path":"/docs/guide/ci-cd/github-actions#workflow","headings":["Продвинутый workflow (многостадийный)"],"excerpt":"Продвинутый workflow (многостадийный) name: Install EasyP run: go install github.com/easyp-tech/easyp/cmd/easyp@latest","content":"Продвинутый workflow (многостадийный) name: Install EasyP run: go install github.com/easyp-tech/easyp/cmd/easyp@latest"},{"id":"ci-cd/github-actions::workflow::47","title":"GitHub Actions","section":"Продвинутый workflow (многостадийный)","path":"/docs/guide/ci-cd/github-actions#workflow","headings":["Продвинутый workflow (многостадийный)"],"excerpt":"Продвинутый workflow (многостадийный) name: Lint run: easyp lint","content":"Продвинутый workflow (многостадийный) name: Lint run: easyp lint"},{"id":"ci-cd/github-actions::workflow::48","title":"GitHub Actions","section":"Продвинутый workflow (многостадийный)","path":"/docs/guide/ci-cd/github-actions#workflow","headings":["Продвинутый workflow (многостадийный)"],"excerpt":"Продвинутый workflow (многостадийный) name: Breaking check (against main) if: github.event_name == 'pull_request' run: easyp breaking --against git-ref=origin/main","content":"Продвинутый workflow (многостадийный) name: Breaking check (against main) if: github.event_name == 'pull_request' run: easyp breaking --against git-ref=origin/main"},{"id":"ci-cd/github-actions::workflow::49","title":"GitHub Actions","section":"Продвинутый workflow (многостадийный)","path":"/docs/guide/ci-cd/github-actions#workflow","headings":["Продвинутый workflow (многостадийный)"],"excerpt":"Продвинутый workflow (многостадийный) generate: needs: validate if: github.event_name == 'push' runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-go@v5 with: go-version: '1.22' - name: Insta","content":"Продвинутый workflow (многостадийный) generate: needs: validate if: github.event_name == 'push' runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-go@v5 with: go-version: '1.22' - name: Install EasyP run: go install github.com/easyp-tech/easyp/cmd/easyp@latest - name: Generate Code run: easyp generate - name: Check diffs run: if [ -n \"$(git status --porcelain)\" ]; then echo \"Generated files changed after generate step.\" git diff --name-only exit 1 fi ```"},{"id":"ci-cd/github-actions::top::50","title":"GitHub Actions","section":"Автоматизация релиза (пример)","path":"/docs/guide/ci-cd/github-actions","headings":["Автоматизация релиза (пример)"],"excerpt":"Автоматизация релиза (пример) Можно добавить workflow, который по тегу создаёт релиз и валидирует proto:","content":"Автоматизация релиза (пример) Можно добавить workflow, который по тегу создаёт релиз и валидирует proto:"},{"id":"ci-cd/github-actions::top::51","title":"GitHub Actions","section":"Автоматизация релиза (пример)","path":"/docs/guide/ci-cd/github-actions","headings":["Автоматизация релиза (пример)"],"excerpt":"Автоматизация релиза (пример) ```yaml name: release-verify","content":"Автоматизация релиза (пример) ```yaml name: release-verify"},{"id":"ci-cd/github-actions::top::52","title":"GitHub Actions","section":"Автоматизация релиза (пример)","path":"/docs/guide/ci-cd/github-actions","headings":["Автоматизация релиза (пример)"],"excerpt":"Автоматизация релиза (пример) on: push: tags: - 'v*.*.*'","content":"Автоматизация релиза (пример) on: push: tags: - 'v*.*.*'"},{"id":"ci-cd/github-actions::top::53","title":"GitHub Actions","section":"Автоматизация релиза (пример)","path":"/docs/guide/ci-cd/github-actions","headings":["Автоматизация релиза (пример)"],"excerpt":"Автоматизация релиза (пример) jobs: release-check: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4","content":"Автоматизация релиза (пример) jobs: release-check: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4"},{"id":"ci-cd/github-actions::top::54","title":"GitHub Actions","section":"Автоматизация релиза (пример)","path":"/docs/guide/ci-cd/github-actions","headings":["Автоматизация релиза (пример)"],"excerpt":"Автоматизация релиза (пример) uses: actions/setup-go@v5 with: go-version: '1.22'","content":"Автоматизация релиза (пример) uses: actions/setup-go@v5 with: go-version: '1.22'"},{"id":"ci-cd/github-actions::top::55","title":"GitHub Actions","section":"Автоматизация релиза (пример)","path":"/docs/guide/ci-cd/github-actions","headings":["Автоматизация релиза (пример)"],"excerpt":"Автоматизация релиза (пример) name: Install EasyP run: go install github.com/easyp-tech/easyp/cmd/easyp@latest","content":"Автоматизация релиза (пример) name: Install EasyP run: go install github.com/easyp-tech/easyp/cmd/easyp@latest"},{"id":"ci-cd/github-actions::top::56","title":"GitHub Actions","section":"Автоматизация релиза (пример)","path":"/docs/guide/ci-cd/github-actions","headings":["Автоматизация релиза (пример)"],"excerpt":"Автоматизация релиза (пример) name: Lint run: easyp lint","content":"Автоматизация релиза (пример) name: Lint run: easyp lint"},{"id":"ci-cd/github-actions::top::57","title":"GitHub Actions","section":"Автоматизация релиза (пример)","path":"/docs/guide/ci-cd/github-actions","headings":["Автоматизация релиза (пример)"],"excerpt":"Автоматизация релиза (пример) name: Breaking vs previous tag run: PREV_TAG=$(git tag --sort=-creatordate grep -v \"${GITHUB_REF_NAME}\" head -n1 true) if [ -n \"$PREV_TAG\" ]; then echo \"Comparing against $PREV_TAG\" easyp br","content":"Автоматизация релиза (пример) name: Breaking vs previous tag run: PREV_TAG=$(git tag --sort=-creatordate grep -v \"${GITHUB_REF_NAME}\" head -n1 true) if [ -n \"$PREV_TAG\" ]; then echo \"Comparing against $PREV_TAG\" easyp breaking --against git-ref=$PREV_TAG else echo \"No previous tag, skipping breaking check\" fi"},{"id":"ci-cd/github-actions::top::58","title":"GitHub Actions","section":"Автоматизация релиза (пример)","path":"/docs/guide/ci-cd/github-actions","headings":["Автоматизация релиза (пример)"],"excerpt":"Автоматизация релиза (пример) name: Generate to ensure consistency run: easyp generate ```","content":"Автоматизация релиза (пример) name: Generate to ensure consistency run: easyp generate ```"},{"id":"ci-cd/github-actions::top::59","title":"GitHub Actions","section":"Отладка","path":"/docs/guide/ci-cd/github-actions","headings":["Отладка"],"excerpt":"Отладка Если нужно больше логов:","content":"Отладка Если нужно больше логов:"},{"id":"ci-cd/github-actions::top::60","title":"GitHub Actions","section":"Отладка","path":"/docs/guide/ci-cd/github-actions","headings":["Отладка"],"excerpt":"Отладка Добавьте вывод окружения для диагностики:","content":"Отладка Добавьте вывод окружения для диагностики:"},{"id":"ci-cd/github-actions::top::61","title":"GitHub Actions","section":"Переменные окружения (примерно)","path":"/docs/guide/ci-cd/github-actions","headings":["Переменные окружения (примерно)"],"excerpt":"Переменные окружения (примерно) Переменная Назначение ------------ ----------- EASYP_SERVICE_HOST Хост удалённого API Service (если используете удалённые плагины) EASYP_SERVICE_GRPC_PORT Порт удалённого сервиса GIT_SSH_C","content":"Переменные окружения (примерно) Переменная Назначение ------------ ----------- EASYP_SERVICE_HOST Хост удалённого API Service (если используете удалённые плагины) EASYP_SERVICE_GRPC_PORT Порт удалённого сервиса GIT_SSH_COMMAND Кастомная команда SSH (частные репозитории) GOFLAGS Можно выставить -mod=readonly для Go генерации"},{"id":"ci-cd/github-actions::top::62","title":"GitHub Actions","section":"Переменные окружения (примерно)","path":"/docs/guide/ci-cd/github-actions","headings":["Переменные окружения (примерно)"],"excerpt":"Переменные окружения (примерно) (Используйте только те, что действительно нужны вашему проекту.)","content":"Переменные окружения (примерно) (Используйте только те, что действительно нужны вашему проекту.)"},{"id":"ci-cd/github-actions::top::63","title":"GitHub Actions","section":"Частые ошибки","path":"/docs/guide/ci-cd/github-actions","headings":["Частые ошибки"],"excerpt":"Частые ошибки Симптом Причина Решение --------- --------- --------- Линт падает на неизвестных правилах Правила указаны в easyp.yaml, но версия EasyP их не поддерживает Обновить EasyP (go install ...@latest) breaking сра","content":"Частые ошибки Симптом Причина Решение --------- --------- --------- Линт падает на неизвестных правилах Правила указаны в easyp.yaml, но версия EasyP их не поддерживает Обновить EasyP (go install ...@latest) breaking сравнение ничего не находит Неверный --against (нет fetch удалённой ветки) Добавить шаг git fetch --all --tags Сгенерированный код в PR отличается от main Отсутствует проверка генерации в CI Добавить шаг «Ensure generated code is up-to-date» Приватные deps не скачиваются Нет SSH ключа или токена Настроить secrets + шаг подготовки SSH Долгое выполнение Отсутствует кеш Добавить кэширование модулей и deps"},{"id":"ci-cd/github-actions::top::64","title":"GitHub Actions","section":"Рекомендации по поддержке","path":"/docs/guide/ci-cd/github-actions","headings":["Рекомендации по поддержке"],"excerpt":"Рекомендации по поддержке Заготовить шаблон workflow и копировать между сервисами (DRY). Включить paths фильтры, чтобы не тратить минуты на нерелевантные изменения. Проверять easyp.yaml при изменениях отдельно — можно за","content":"Рекомендации по поддержке Заготовить шаблон workflow и копировать между сервисами (DRY). Включить paths фильтры, чтобы не тратить минуты на нерелевантные изменения. Проверять easyp.yaml при изменениях отдельно — можно запускать «конфигурационный тест» (например, easyp lint без файлов, чтобы убедиться, что конфиг валиден). При появлении новых правил линтера обновляйте конфиг и фиксируйте ошибки сразу в одной ветке."},{"id":"ci-cd/github-actions::top::65","title":"GitHub Actions","section":"Рекомендации по поддержке","path":"/docs/guide/ci-cd/github-actions","headings":["Рекомендации по поддержке"],"excerpt":"Рекомендации по поддержке Готово: вы можете расширять разделы генерации, добавлять OpenAPI / grpc-gateway / validate плагины, матрицы по языкам и интегрировать тесты поверх сгенерированного кода, если требуется.","content":"Рекомендации по поддержке Готово: вы можете расширять разделы генерации, добавлять OpenAPI / grpc-gateway / validate плагины, матрицы по языкам и интегрировать тесты поверх сгенерированного кода, если требуется."},{"id":"ci-cd/gitlab::top::0","title":"GitLab CI","section":"В процессе разработки","path":"/docs/guide/ci-cd/gitlab","headings":["В процессе разработки"],"excerpt":"В процессе разработки Документация по интеграции EasyP с GitLab CI находится в процессе подготовки. Планируемые разделы: Быстрый старт (пример .gitlab-ci.yml для линтинга и проверки несовместимых изменений) Кэширование з","content":"В процессе разработки Документация по интеграции EasyP с GitLab CI находится в процессе подготовки. Планируемые разделы: Быстрый старт (пример .gitlab-ci.yml для линтинга и проверки несовместимых изменений) Кэширование зависимостей и ускорение сборок Генерация кода и проверка актуальности артефактов Работа с приватными Git-репозиториями в deps Матрицы (parallel jobs) для разных языков и плагинов Автоматизация релизов по тегам"},{"id":"ci-cd/gitlab::top::1","title":"GitLab CI","section":"В процессе разработки","path":"/docs/guide/ci-cd/gitlab","headings":["В процессе разработки"],"excerpt":"В процессе разработки Если вам нужен пример прямо сейчас, базовый минимальный вариант может выглядеть так:","content":"В процессе разработки Если вам нужен пример прямо сейчас, базовый минимальный вариант может выглядеть так:"},{"id":"ci-cd/gitlab::top::2","title":"GitLab CI","section":"В процессе разработки","path":"/docs/guide/ci-cd/gitlab","headings":["В процессе разработки"],"excerpt":"В процессе разработки ```yaml stages: - validate - generate","content":"В процессе разработки ```yaml stages: - validate - generate"},{"id":"ci-cd/gitlab::top::3","title":"GitLab CI","section":"В процессе разработки","path":"/docs/guide/ci-cd/gitlab","headings":["В процессе разработки"],"excerpt":"В процессе разработки variables: GO_VERSION: \"1.22\"","content":"В процессе разработки variables: GO_VERSION: \"1.22\""},{"id":"ci-cd/gitlab::top::4","title":"GitLab CI","section":"В процессе разработки","path":"/docs/guide/ci-cd/gitlab","headings":["В процессе разработки"],"excerpt":"В процессе разработки validate: stage: validate image: golang:${GO_VERSION} before_script: - go install github.com/easyp-tech/easyp/cmd/easyp@latest - echo \"EasyP version:\" - easyp version # При необходимости: git fetch ","content":"В процессе разработки validate: stage: validate image: golang:${GO_VERSION} before_script: - go install github.com/easyp-tech/easyp/cmd/easyp@latest - echo \"EasyP version:\" - easyp version # При необходимости: git fetch --all --tags script: - easyp lint - easyp breaking --against git-ref=origin/main only: changes: - \"**/*.proto\" - \"easyp.yaml\""},{"id":"ci-cd/gitlab::top::5","title":"GitLab CI","section":"В процессе разработки","path":"/docs/guide/ci-cd/gitlab","headings":["В процессе разработки"],"excerpt":"В процессе разработки generate: stage: generate image: golang:${GO_VERSION} before_script: - go install github.com/easyp-tech/easyp/cmd/easyp@latest script: - easyp generate - if [ -n \"$(git status --porcelain)\" ]; then ","content":"В процессе разработки generate: stage: generate image: golang:${GO_VERSION} before_script: - go install github.com/easyp-tech/easyp/cmd/easyp@latest script: - easyp generate - if [ -n \"$(git status --porcelain)\" ]; then echo \"Сгенерированный код не актуален. Закоммитьте изменения локально.\" git diff --name-only exit 1 fi only: - main"},{"id":"ci-cd/gitlab::top::6","title":"GitLab CI","section":"В процессе разработки","path":"/docs/guide/ci-cd/gitlab","headings":["В процессе разработки"],"excerpt":"В процессе разработки Дополнительные рекомендации будут добавлены позже.","content":"В процессе разработки Дополнительные рекомендации будут добавлены позже."},{"id":"cli/auto-completion/auto-completion::zsh::0","title":"Автодополнение","section":"Автодополнение для zsh","path":"/docs/guide/cli/auto-completion/auto-completion#zsh","headings":["Автодополнение для zsh"],"excerpt":"Автодополнение для zsh Добавьте следующую строку в ваш файл запуска ~/.zshrc:","content":"Автодополнение для zsh Добавьте следующую строку в ваш файл запуска ~/.zshrc:"},{"id":"cli/auto-completion/auto-completion::zsh::1","title":"Автодополнение","section":"Автодополнение для zsh","path":"/docs/guide/cli/auto-completion/auto-completion#zsh","headings":["Автодополнение для zsh"],"excerpt":"Автодополнение для zsh Перезапустите оболочку или выполните:","content":"Автодополнение для zsh Перезапустите оболочку или выполните:"},{"id":"cli/auto-completion/auto-completion::bash::2","title":"Автодополнение","section":"Автодополнение для Bash","path":"/docs/guide/cli/auto-completion/auto-completion#bash","headings":["Автодополнение для Bash"],"excerpt":"Автодополнение для Bash Установите bash-completion и подключите его в ~/.bashrc. Добавьте следующую строку в файл запуска ~/.bashrc:","content":"Автодополнение для Bash Установите bash-completion и подключите его в ~/.bashrc. Добавьте следующую строку в файл запуска ~/.bashrc:"},{"id":"cli/auto-completion/auto-completion::bash::3","title":"Автодополнение","section":"Автодополнение для Bash","path":"/docs/guide/cli/auto-completion/auto-completion#bash","headings":["Автодополнение для Bash"],"excerpt":"Автодополнение для Bash Перезапустите оболочку или выполните:","content":"Автодополнение для Bash Перезапустите оболочку или выполните:"},{"id":"cli/auto-completion/auto-completion::top::4","title":"Автодополнение","section":"Примечания","path":"/docs/guide/cli/auto-completion/auto-completion","headings":["Примечания"],"excerpt":"Примечания Команда easyp completion выводит скрипт автодополнения для соответствующей оболочки. Если используете другую оболочку (например, fish), можно сгенерировать вывод и сохранить вручную: При обновлении версии Easy","content":"Примечания Команда easyp completion выводит скрипт автодополнения для соответствующей оболочки. Если используете другую оболочку (например, fish), можно сгенерировать вывод и сохранить вручную: При обновлении версии EasyP рекомендуется заново перезагрузить оболочку, чтобы подтянуть возможные изменения в автодополнении."},{"id":"cli/breaking-changes/breaking-changes::top::0","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":[],"excerpt":"Обнаружение несовместимых изменений (Breaking Changes Detection)","content":"Обнаружение несовместимых изменений (Breaking Changes Detection)"},{"id":"cli/breaking-changes/breaking-changes::top::1","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":[],"excerpt":"Механизм EasyP для обнаружения несовместимых (breaking) изменений помогает поддерживать обратную совместимость ваших protobuf API, автоматически выявляя изменения, способные сломать существующих клиентов. Это критично дл","content":"Механизм EasyP для обнаружения несовместимых (breaking) изменений помогает поддерживать обратную совместимость ваших protobuf API, автоматически выявляя изменения, способные сломать существующих клиентов. Это критично для стабильных API в продакшене."},{"id":"cli/breaking-changes/breaking-changes::top::2","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Обзор","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Обзор"],"excerpt":"Обзор Проверка несовместимых изменений сравнивает текущий набор protobuf‑файлов с предыдущей версией (обычно из другой Git ветки) и фиксирует модификации, которые могут вызвать проблемы совместимости для уже работающих к","content":"Обзор Проверка несовместимых изменений сравнивает текущий набор protobuf‑файлов с предыдущей версией (обычно из другой Git ветки) и фиксирует модификации, которые могут вызвать проблемы совместимости для уже работающих клиентов."},{"id":"cli/breaking-changes/breaking-changes::top::3","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Ключевые возможности","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Ключевые возможности"],"excerpt":"Ключевые возможности **Сравнение через Git**: Сопоставление с любой Git‑ссылкой (ветка, тег, commit) **Комплексный анализ**: Проверка сервисов, сообщений, enum'ов, полей и import'ов **Выборочное игнорирование**: Пропуск ","content":"Ключевые возможности **Сравнение через Git**: Сопоставление с любой Git‑ссылкой (ветка, тег, commit) **Комплексный анализ**: Проверка сервисов, сообщений, enum'ов, полей и import'ов **Выборочное игнорирование**: Пропуск указанных директорий из анализа **Детализированные отчёты**: Понятные ошибки с именами файлов, строками и позициями"},{"id":"cli/breaking-changes/breaking-changes::top::4","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Как работает","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Как работает"],"excerpt":"Как работает Детектор breaking changes выполняет следующие шаги:","content":"Как работает Детектор breaking changes выполняет следующие шаги:"},{"id":"cli/breaking-changes/breaking-changes::top::5","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Как работает","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Как работает"],"excerpt":"Как работает **Получение ветки сравнения**: Забирает proto-файлы из указанной Git‑ссылки **Парсинг обеих версий**: Анализирует структуру текущих и предыдущих файлов **Сравнение сущностей**: Последовательно проверяет все ","content":"Как работает **Получение ветки сравнения**: Забирает proto-файлы из указанной Git‑ссылки **Парсинг обеих версий**: Анализирует структуру текущих и предыдущих файлов **Сравнение сущностей**: Последовательно проверяет все элементы protobuf на breaking изменения **Формирование отчёта**: Генерирует подробные записи об ошибках с локациями и описаниями"},{"id":"cli/breaking-changes/breaking-changes::top::6","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Уровень проверки","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Уровень проверки"],"excerpt":"Уровень проверки EasyP реализует уровень проверки **WIRE+**: ✅ **Полная совместимость по wire‑формату** — старые и новые версии могут обмениваться данными ✅ **Обнаружение удалений элементов** — сервисы, сообщения, поля и","content":"Уровень проверки EasyP реализует уровень проверки **WIRE+**: ✅ **Полная совместимость по wire‑формату** — старые и новые версии могут обмениваться данными ✅ **Обнаружение удалений элементов** — сервисы, сообщения, поля и т.п. ✅ **Безопасность типов** — выявляет несовместимые изменения типов ❌ **Переименования полей/методов** — пока не детектируются (в планах) ❌ **Изменения на уровне файлов** — переносы пакетов, file options ещё не проверяются"},{"id":"cli/breaking-changes/breaking-changes::top::7","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Уровень проверки","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Уровень проверки"],"excerpt":"Уровень проверки Это даёт сильные гарантии совместимости и меньше ограничений, чем инструменты, требующие совместимости сгенерированного кода.","content":"Уровень проверки Это даёт сильные гарантии совместимости и меньше ограничений, чем инструменты, требующие совместимости сгенерированного кода."},{"id":"cli/breaking-changes/breaking-changes::top::8","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Конфигурация","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Конфигурация"],"excerpt":"Конфигурация Настройка в easyp.yaml:","content":"Конфигурация Настройка в easyp.yaml:"},{"id":"cli/breaking-changes/breaking-changes::top::9","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Параметры конфигурации","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Параметры конфигурации"],"excerpt":"Параметры конфигурации Option Description Default Required -------- ------------- --------- ---------- against_git_ref Git‑ссылка для сравнения \"master\" No ignore Список директорий для исключения из анализа [] No","content":"Параметры конфигурации Option Description Default Required -------- ------------- --------- ---------- against_git_ref Git‑ссылка для сравнения \"master\" No ignore Список директорий для исключения из анализа [] No"},{"id":"cli/breaking-changes/breaking-changes::top::10","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Базовый пример","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Базовый пример"],"excerpt":"Базовый пример Сравнение текущих изменений с веткой main:","content":"Базовый пример Сравнение текущих изменений с веткой main:"},{"id":"cli/breaking-changes/breaking-changes::top::11","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Использование файла конфигурации","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Использование файла конфигурации"],"excerpt":"Использование файла конфигурации","content":"Использование файла конфигурации"},{"id":"cli/breaking-changes/breaking-changes::top::12","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Уровень проверки","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Уровень проверки"],"excerpt":"Уровень проверки EasyP сейчас работает на уровне **WIRE+**, обеспечивая совместимость wire‑формата плюс защиту от удалений и изменения критичных типов.","content":"Уровень проверки EasyP сейчас работает на уровне **WIRE+**, обеспечивая совместимость wire‑формата плюс защиту от удалений и изменения критичных типов."},{"id":"cli/breaking-changes/breaking-changes::buf::13","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Сравнение с категориями Buf","path":"/docs/guide/cli/breaking-changes/breaking-changes#buf","headings":["Сравнение с категориями Buf"],"excerpt":"Сравнение с категориями Buf Check Type Buf WIRE Buf WIRE_JSON Buf FILE EasyP Current ------------ ---------- --------------- ---------- --------------- **Element Deletions** Service deletion ❌ ❌ ✅ ✅ RPC method deletion ❌","content":"Сравнение с категориями Buf 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::top::14","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Что это означает","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Что это означает"],"excerpt":"Что это означает **✅ EasyP обнаружит:** Все breaking изменения wire‑формата Удаления сервисов, методов, сообщений, полей Изменения типов, ломающие сериализацию Переименования enum‑значений (при сохранении номера)","content":"Что это означает **✅ EasyP обнаружит:** Все breaking изменения wire‑формата Удаления сервисов, методов, сообщений, полей Изменения типов, ломающие сериализацию Переименования enum‑значений (при сохранении номера)"},{"id":"cli/breaking-changes/breaking-changes::top::15","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Что это означает","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Что это означает"],"excerpt":"Что это означает **❌ EasyP НЕ обнаружит:** Переименование полей (с тем же номером) Изменение package File options (go_package, java_package, и т.п.) Перемещение типов между файлами в одном package","content":"Что это означает **❌ EasyP НЕ обнаружит:** Переименование полей (с тем же номером) Изменение package File options (go_package, java_package, и т.п.) Перемещение типов между файлами в одном package"},{"id":"cli/breaking-changes/breaking-changes::breaking-changes::16","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Правила Breaking Changes","path":"/docs/guide/cli/breaking-changes/breaking-changes#breaking-changes","headings":["Правила Breaking Changes"],"excerpt":"Правила Breaking Changes EasyP обнаруживает следующие типы breaking изменений:","content":"Правила Breaking Changes EasyP обнаруживает следующие типы breaking изменений:"},{"id":"cli/breaking-changes/breaking-changes::top::17","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Сравнение уровней","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Сравнение уровней"],"excerpt":"Сравнение уровней Detection Level Description EasyP Support ---------------- ------------- --------------- **WIRE** Совместимость только по wire‑формату ✅ **Full support** **WIRE+** Wire + обнаружение удалений ✅ **Curren","content":"Сравнение уровней Detection Level Description EasyP Support ---------------- ------------- --------------- **WIRE** Совместимость только по wire‑формату ✅ **Full support** **WIRE+** Wire + обнаружение удалений ✅ **Current level** **FILE** Совместимость сгенерированного кода ❌ Partial (planned)"},{"id":"cli/breaking-changes/breaking-changes::top::18","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Категории правил","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Категории правил"],"excerpt":"Категории правил Каждая категория имеет свою документацию с примерами:","content":"Категории правил Каждая категория имеет свою документацию с примерами:"},{"id":"cli/breaking-changes/breaking-changes::service-rpc::19","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"🚨 Изменения Service и RPC","path":"/docs/guide/cli/breaking-changes/breaking-changes#service-rpc","headings":["🚨 Изменения Service и RPC"],"excerpt":"🚨 Изменения Service и RPC 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 и RPC 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-field::20","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"📦 Изменения Message и Field","path":"/docs/guide/cli/breaking-changes/breaking-changes#message-field","headings":["📦 Изменения Message и Field"],"excerpt":"📦 Изменения Message и Field 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 и Field 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::21","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"🔢 Изменения Enum","path":"/docs/guide/cli/breaking-changes/breaking-changes#enum","headings":["🔢 Изменения Enum"],"excerpt":"🔢 Изменения Enum 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 val","content":"🔢 Изменения Enum 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::22","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"🔗 Изменения OneOf","path":"/docs/guide/cli/breaking-changes/breaking-changes#oneof","headings":["🔗 Изменения OneOf"],"excerpt":"🔗 Изменения OneOf Rule Description Status ------ ------------- --------- ONEOF_NO_DELETE OneOf fields cannot be deleted ✅ Implemented ONEOF_FIELD_NO_DELETE Fields within oneofs cannot be deleted ✅ Implemented ONEOF_FIEL","content":"🔗 Изменения OneOf 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::23","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"📥 Изменения Import","path":"/docs/guide/cli/breaking-changes/breaking-changes#import","headings":["📥 Изменения Import"],"excerpt":"📥 Изменения Import Rule Description Status ------ ------------- --------- IMPORT_NO_DELETE Import statements cannot be removed ✅ Implemented","content":"📥 Изменения Import Rule Description Status ------ ------------- --------- IMPORT_NO_DELETE Import statements cannot be removed ✅ Implemented"},{"id":"cli/breaking-changes/breaking-changes::top::24","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Не обнаруживается сейчас","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Не обнаруживается сейчас"],"excerpt":"Не обнаруживается сейчас Изменения ниже **НЕ детектируются** EasyP (могут ломать сгенерированный код):","content":"Не обнаруживается сейчас Изменения ниже **НЕ детектируются** EasyP (могут ломать сгенерированный код):"},{"id":"cli/breaking-changes/breaking-changes::top::25","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Не обнаруживается сейчас","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Не обнаруживается сейчас"],"excerpt":"Не обнаруживается сейчас Change Type Example Impact ------------- --------- -------- Field renaming string name = 1 → string full_name = 1 Ломает код Package changes package v1 → package v2 Меняются пути импорта File opt","content":"Не обнаруживается сейчас Change Type Example Impact ------------- --------- -------- Field renaming string name = 1 → string full_name = 1 Ломает код Package changes package v1 → package v2 Меняются пути импорта File options option go_package = \"old\" → option go_package = \"new\" Меняется расположение кода Moving between files Message перемещено в другой .proto Зависимости import'ов"},{"id":"cli/breaking-changes/breaking-changes::top::26","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Документация правил","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Документация правил"],"excerpt":"Документация правил См. подробные файлы правил для примеров и стратегий миграции:","content":"Документация правил См. подробные файлы правил для примеров и стратегий миграции:"},{"id":"cli/breaking-changes/breaking-changes::top::27","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Документация правил","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Документация правил"],"excerpt":"Документация правил Service: SERVICE_NO_DELETE, RPC_NO_DELETE, RPC_SAME_REQUEST_TYPE, RPC_SAME_RESPONSE_TYPE Message: MESSAGE_NO_DELETE, FIELD_NO_DELETE, FIELD_SAME_TYPE, FIELD_SAME_CARDINALITY Enum: ENUM_NO_DELETE, ENUM","content":"Документация правил Service: SERVICE_NO_DELETE, RPC_NO_DELETE, RPC_SAME_REQUEST_TYPE, RPC_SAME_RESPONSE_TYPE Message: MESSAGE_NO_DELETE, FIELD_NO_DELETE, FIELD_SAME_TYPE, FIELD_SAME_CARDINALITY Enum: ENUM_NO_DELETE, ENUM_VALUE_NO_DELETE, ENUM_VALUE_SAME_NAME OneOf: ONEOF_NO_DELETE, ONEOF_FIELD_NO_DELETE, ONEOF_FIELD_SAME_TYPE Import: IMPORT_NO_DELETE"},{"id":"cli/breaking-changes/breaking-changes::top::28","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Документация правил","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Документация правил"],"excerpt":"Документация правил Каждое правило содержит: ❌ Плохие примеры (breaking) ✅ Безопасные альтернативы 🔧 Стратегии миграции 📋 Реальные сообщения ошибок из EasyP","content":"Документация правил Каждое правило содержит: ❌ Плохие примеры (breaking) ✅ Безопасные альтернативы 🔧 Стратегии миграции 📋 Реальные сообщения ошибок из EasyP"},{"id":"cli/breaking-changes/breaking-changes::top::29","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"✅ Безопасные изменения (разрешены всегда)","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["✅ Безопасные изменения (разрешены всегда)"],"excerpt":"✅ Безопасные изменения (разрешены всегда) ```proto // Добавление новых элементов — безопасно message User { string name = 1; string email = 2; string phone = 3; // ✅ Новое поле }","content":"✅ Безопасные изменения (разрешены всегда) ```proto // Добавление новых элементов — безопасно message User { string name = 1; string email = 2; string phone = 3; // ✅ Новое поле }"},{"id":"cli/breaking-changes/breaking-changes::top::30","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"✅ Безопасные изменения (разрешены всегда)","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["✅ Безопасные изменения (разрешены всегда)"],"excerpt":"✅ Безопасные изменения (разрешены всегда) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc GetUserProfile(GetUserRequest) returns (UserProfile); // ✅ Новый RPC }","content":"✅ Безопасные изменения (разрешены всегда) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc GetUserProfile(GetUserRequest) returns (UserProfile); // ✅ Новый RPC }"},{"id":"cli/breaking-changes/breaking-changes::top::31","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"✅ Безопасные изменения (разрешены всегда)","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["✅ Безопасные изменения (разрешены всегда)"],"excerpt":"✅ Безопасные изменения (разрешены всегда) enum Status { STATUS_UNSPECIFIED = 0; STATUS_ACTIVE = 1; STATUS_PENDING = 2; // ✅ Новое enum значение } ```","content":"✅ Безопасные изменения (разрешены всегда) enum Status { STATUS_UNSPECIFIED = 0; STATUS_ACTIVE = 1; STATUS_PENDING = 2; // ✅ Новое enum значение } ```"},{"id":"cli/breaking-changes/breaking-changes::top::32","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"❌ Несовместимые изменения (обнаруживаются всегда)","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["❌ Несовместимые изменения (обнаруживаются всегда)"],"excerpt":"❌ Несовместимые изменения (обнаруживаются всегда) ```proto // Удаления и смена типов ломают совместимость message User { string name = 1; // ❌ Удалённое поле }","content":"❌ Несовместимые изменения (обнаруживаются всегда) ```proto // Удаления и смена типов ломают совместимость message User { string name = 1; // ❌ Удалённое поле }"},{"id":"cli/breaking-changes/breaking-changes::top::33","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"❌ Несовместимые изменения (обнаруживаются всегда)","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["❌ Несовместимые изменения (обнаруживаются всегда)"],"excerpt":"❌ Несовместимые изменения (обнаруживаются всегда) service UserService { // ❌ Удалённый RPC метод rpc GetUser(GetUserRequestV2) returns (GetUserResponse); // ❌ Изменён тип запроса } ```","content":"❌ Несовместимые изменения (обнаруживаются всегда) service UserService { // ❌ Удалённый RPC метод rpc GetUser(GetUserRequestV2) returns (GetUserResponse); // ❌ Изменён тип запроса } ```"},{"id":"cli/breaking-changes/breaking-changes::top::34","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Сценарий: Изменения пока не детектируются","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Сценарий: Изменения пока не детектируются"],"excerpt":"Сценарий: Изменения пока не детектируются ```proto // 🟡 Ломает сгенерированный код, но проходит проверки EasyP message User { string user_name = 1; // Переименовано с \"name\" string user_email = 2; // Переименовано с \"em","content":"Сценарий: Изменения пока не детектируются ```proto // 🟡 Ломает сгенерированный код, но проходит проверки EasyP message User { string user_name = 1; // Переименовано с \"name\" string user_email = 2; // Переименовано с \"email\" }"},{"id":"cli/breaking-changes/breaking-changes::top::35","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Сценарий: Изменения пока не детектируются","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Сценарий: Изменения пока не детектируются"],"excerpt":"Сценарий: Изменения пока не детектируются service UserService { rpc GetUserProfile(GetUserRequest) returns (GetUserResponse); // Переименовано с GetUser } ```","content":"Сценарий: Изменения пока не детектируются service UserService { rpc GetUserProfile(GetUserRequest) returns (GetUserResponse); // Переименовано с GetUser } ```"},{"id":"cli/breaking-changes/breaking-changes::top::36","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Текстовый формат (по умолчанию)","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Текстовый формат (по умолчанию)"],"excerpt":"Текстовый формат (по умолчанию)","content":"Текстовый формат (по умолчанию)"},{"id":"cli/breaking-changes/breaking-changes::1::37","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"1. Регулярный запуск","path":"/docs/guide/cli/breaking-changes/breaking-changes#1","headings":["1. Регулярный запуск"],"excerpt":"Регулярный запуск Добавьте проверку несовместимых изменений в CI/CD:","content":"Регулярный запуск Добавьте проверку несовместимых изменений в CI/CD:"},{"id":"cli/breaking-changes/breaking-changes::2::38","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"2. Защита веток","path":"/docs/guide/cli/breaking-changes/breaking-changes#2","headings":["2. Защита веток"],"excerpt":"Защита веток Блокируйте слияния с breaking изменениями:","content":"Защита веток Блокируйте слияния с breaking изменениями:"},{"id":"cli/breaking-changes/breaking-changes::3::39","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"3. Стратегия версионирования","path":"/docs/guide/cli/breaking-changes/breaking-changes#3","headings":["3. Стратегия версионирования"],"excerpt":"Стратегия версионирования При необходимости breaking изменений: Создайте новую версию пакета (myservice.v2) Поддерживайте старую версию в период миграции Добавляйте уведомления о деприкации","content":"Стратегия версионирования При необходимости breaking изменений: Создайте новую версию пакета (myservice.v2) Поддерживайте старую версию в период миграции Добавляйте уведомления о деприкации"},{"id":"cli/breaking-changes/breaking-changes::4::40","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"4. Игнорирование путей","path":"/docs/guide/cli/breaking-changes/breaking-changes#4","headings":["4. Игнорирование путей"],"excerpt":"Игнорирование путей Используйте ignore осознанно:","content":"Игнорирование путей Используйте ignore осознанно:"},{"id":"cli/breaking-changes/breaking-changes::repository-does-not-exist::41","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Проблема: \"Repository does not exist\"","path":"/docs/guide/cli/breaking-changes/breaking-changes#repository-does-not-exist","headings":["Проблема: \"Repository does not exist\""],"excerpt":"Проблема: \"Repository does not exist\" Решение: Выполняйте команду внутри Git репозитория с нужной веткой.","content":"Проблема: \"Repository does not exist\" Решение: Выполняйте команду внутри Git репозитория с нужной веткой."},{"id":"cli/breaking-changes/breaking-changes::cannot-find-git-ref::42","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Проблема: \"Cannot find git ref\"","path":"/docs/guide/cli/breaking-changes/breaking-changes#cannot-find-git-ref","headings":["Проблема: \"Cannot find git ref\""],"excerpt":"Проблема: \"Cannot find git ref\" Решение: Проверьте наличие ссылки:","content":"Проблема: \"Cannot find git ref\" Решение: Проверьте наличие ссылки:"},{"id":"cli/breaking-changes/breaking-changes::top::43","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Проблема: Ложные срабатывания на сгенерированный код","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Проблема: Ложные срабатывания на сгенерированный код"],"excerpt":"Проблема: Ложные срабатывания на сгенерированный код Решение: Исключите директории генерации:","content":"Проблема: Ложные срабатывания на сгенерированный код Решение: Исключите директории генерации:"},{"id":"cli/breaking-changes/breaking-changes::top::44","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Проблема: Очень много изменений","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Проблема: Очень много изменений"],"excerpt":"Проблема: Очень много изменений Решение: Создайте новую версию API Вносите изменения постепенно Используйте feature flags","content":"Проблема: Очень много изменений Решение: Создайте новую версию API Вносите изменения постепенно Используйте feature flags"},{"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 - name: Install EasyP run: curl -sSfL https://raw.githubusercontent.com/easyp-tech/easyp/main/install.","content":"GitHub Actions jobs: breaking-changes: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 with: fetch-depth: 0 - 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-pre-push-hook::48","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Pre-commit / pre-push hook","path":"/docs/guide/cli/breaking-changes/breaking-changes#pre-commit-pre-push-hook","headings":["Pre-commit / pre-push hook"],"excerpt":"Pre-commit / pre-push hook ```bash #!/bin/sh .git/hooks/pre-push","content":"Pre-commit / pre-push hook ```bash #!/bin/sh .git/hooks/pre-push"},{"id":"cli/breaking-changes/breaking-changes::pre-commit-pre-push-hook::49","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Pre-commit / pre-push hook","path":"/docs/guide/cli/breaking-changes/breaking-changes#pre-commit-pre-push-hook","headings":["Pre-commit / pre-push hook"],"excerpt":"Pre-commit / pre-push hook protected_branch='main' current_branch=$(git symbolic-ref HEAD sed -e 's,.*/\\(.*\\),\\1,')","content":"Pre-commit / pre-push hook protected_branch='main' current_branch=$(git symbolic-ref HEAD sed -e 's,.*/\\(.*\\),\\1,')"},{"id":"cli/breaking-changes/breaking-changes::pre-commit-pre-push-hook::50","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Pre-commit / pre-push hook","path":"/docs/guide/cli/breaking-changes/breaking-changes#pre-commit-pre-push-hook","headings":["Pre-commit / pre-push hook"],"excerpt":"Pre-commit / pre-push 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.","content":"Pre-commit / pre-push 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::top::51","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Режим отладки","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Режим отладки"],"excerpt":"Режим отладки Включите debug‑логирование:","content":"Режим отладки Включите debug‑логирование:"},{"id":"cli/breaking-changes/breaking-changes::top::52","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Ручное сравнение","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Ручное сравнение"],"excerpt":"Ручное сравнение Для сложных случаев:","content":"Ручное сравнение Для сложных случаев:"},{"id":"cli/breaking-changes/breaking-changes::top::53","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Оптимизация производительности","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Оптимизация производительности"],"excerpt":"Оптимизация производительности Ограничьте область:","content":"Оптимизация производительности Ограничьте область:"},{"id":"cli/breaking-changes/breaking-changes::top::54","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Оптимизация производительности","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Оптимизация производительности"],"excerpt":"Оптимизация производительности","content":"Оптимизация производительности"},{"id":"cli/breaking-changes/breaking-changes::top::55","title":"Обнаружение несовместимых изменений (Breaking Changes Detection)","section":"Оптимизация производительности","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":["Оптимизация производительности"],"excerpt":"Оптимизация производительности Механизм обнаружения несовместимых изменений в EasyP обеспечивает надёжную основу для безопасной эволюции protobuf‑схем при сохранении совместимости API.","content":"Оптимизация производительности Механизм обнаружения несовместимых изменений в EasyP обеспечивает надёжную основу для безопасной эволюции protobuf‑схем при сохранении совместимости API."},{"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":"Это правило проверяет, что ни один enum не был удалён из proto‑файлов. Удаление enum ломает совместимость по wire‑формату и сгенерированный код: сохранённые данные могут содержать удалённые значения, а клиентский код опи","content":"Это правило проверяет, что ни один enum не был удалён из proto‑файлов. Удаление enum ломает совместимость по wire‑формату и сгенерированный код: сохранённые данные могут содержать удалённые значения, а клиентский код опирается на сгенерированные типы и константы enum."},{"id":"cli/breaking-changes/rules/enum-no-delete::breaking::1","title":"ENUM_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-no-delete::breaking::2","title":"ENUM_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/enum-no-delete::breaking::3","title":"ENUM_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_CONFIRMED = 2; ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_DELIVERED = 4; }","content":"Плохой (Breaking) 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::breaking::4","title":"ENUM_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) enum UserRole { // [!code --] USER_ROLE_UNSPECIFIED = 0; // [!code --] USER_ROLE_ADMIN = 1; // [!code --] USER_ROLE_USER = 2; // [!code --] } // [!code --]","content":"Плохой (Breaking) 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::breaking::5","title":"ENUM_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message Order { string id = 1; OrderStatus status = 2; UserRole created_by_role = 3; } ```","content":"Плохой (Breaking) message Order { string id = 1; OrderStatus status = 2; UserRole created_by_role = 3; } ```"},{"id":"cli/breaking-changes/rules/enum-no-delete::breaking::6","title":"ENUM_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-no-delete::breaking::7","title":"ENUM_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/enum-no-delete::breaking::8","title":"ENUM_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_CONFIRMED = 2; ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_DELIVERED = 4; }","content":"Плохой (Breaking) 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::breaking::9","title":"ENUM_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) // UserRole enum удалён — BREAKING CHANGE!","content":"Плохой (Breaking) // UserRole enum удалён — BREAKING CHANGE!"},{"id":"cli/breaking-changes/rules/enum-no-delete::breaking::10","title":"ENUM_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message Order { string id = 1; OrderStatus status = 2; UserRole created_by_role = 3; // ERROR: UserRole больше не существует } ```","content":"Плохой (Breaking) message Order { string id = 1; OrderStatus status = 2; UserRole created_by_role = 3; // ERROR: UserRole больше не существует } ```"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::11","title":"ENUM_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры **Удаление вложенного enum:** ```proto // Before message User { string name = 1; Status status = 2; enum Status { // [!code --] STATUS_UNSPECIFIED = 0; // [!code --] STATUS_ACTIVE = 1; // [!code --","content":"Дополнительные примеры **Удаление вложенного enum:** ```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::top::12","title":"ENUM_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры // After - BREAKING CHANGE! message User { string name = 1; Status status = 2; // ERROR: Status удалён // Вложенный enum Status удалён } ```","content":"Дополнительные примеры // After - BREAKING CHANGE! message User { string name = 1; Status status = 2; // ERROR: Status удалён // Вложенный enum Status удалён } ```"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::13","title":"ENUM_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо удаления — пометить enum deprecated:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо удаления — пометить enum deprecated:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::14","title":"ENUM_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::15","title":"ENUM_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_CONFIRMED = 2; ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_DELIVERED = 4; }","content":"Хороший (Безопасный) 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::top::16","title":"ENUM_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) enum UserRole { option deprecated = true; // [!code focus] USER_ROLE_UNSPECIFIED = 0; USER_ROLE_ADMIN = 1; USER_ROLE_USER = 2; }","content":"Хороший (Безопасный) 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::top::17","title":"ENUM_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message Order { string id = 1; OrderStatus status = 2; UserRole created_by_role = 3 [deprecated = true]; // [!code focus] } ```","content":"Хороший (Безопасный) 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::top::18","title":"ENUM_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Или заменить новым enum:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Или заменить новым enum:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::19","title":"ENUM_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::20","title":"ENUM_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_CONFIRMED = 2; ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_DELIVERED = 4; }","content":"Хороший (Безопасный) 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::top::21","title":"ENUM_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) enum UserRole { option deprecated = true; // [!code focus] // Старый enum USER_ROLE_UNSPECIFIED = 0; USER_ROLE_ADMIN = 1; USER_ROLE_USER = 2; }","content":"Хороший (Безопасный) enum UserRole { option deprecated = true; // [!code focus] // Старый enum USER_ROLE_UNSPECIFIED = 0; USER_ROLE_ADMIN = 1; USER_ROLE_USER = 2; }"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::22","title":"ENUM_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) enum UserPermission { // [!code focus] // Новый enum USER_PERMISSION_UNSPECIFIED = 0; // [!code focus] USER_PERMISSION_READ = 1; // [!code focus] USER_PERMISSION_WRITE = 2; // [!code focus] USER_PERM","content":"Хороший (Безопасный) enum UserPermission { // [!code focus] // Новый enum 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::top::23","title":"ENUM_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message Order { string id = 1; OrderStatus status = 2; UserRole created_by_role = 3 [deprecated = true]; // [!code focus] UserPermission created_by_permission = 4; // [!code focus] } ```","content":"Хороший (Безопасный) message Order { string id = 1; OrderStatus status = 2; UserRole created_by_role = 3 [deprecated = true]; // [!code focus] UserPermission created_by_permission = 4; // [!code focus] } ```"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::24","title":"ENUM_NO_DELETE","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Влияние"],"excerpt":"Влияние **Wire Format:** Данные с удалённым enum не десериализуются корректно **Generated Code:** Тип и константы удаляются — компиляция клиентов ломается **Field References:** Поля с типом удалённого enum становятся нев","content":"Влияние **Wire Format:** Данные с удалённым enum не десериализуются корректно **Generated Code:** Тип и константы удаляются — компиляция клиентов ломается **Field References:** Поля с типом удалённого enum становятся невалидны **Switch Statements:** switch по enum ломается (неизвестные кейсы)"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::25","title":"ENUM_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Код клиента ломается:** ```go // Before order := &myapi.Order{ Id: \"order123\", Status: myapi.OrderStatus_ORDER_STATUS_PENDING, CreatedByRole: myapi.UserRole_USER_ROLE_ADMIN, // ERROR после удаления }","content":"Реальный пример **Код клиента ломается:** ```go // Before order := &myapi.Order{ Id: \"order123\", Status: myapi.OrderStatus_ORDER_STATUS_PENDING, CreatedByRole: myapi.UserRole_USER_ROLE_ADMIN, // ERROR после удаления }"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::26","title":"ENUM_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример switch order.CreatedByRole { case myapi.UserRole_USER_ROLE_ADMIN: // ERROR // Admin logic case myapi.UserRole_USER_ROLE_USER: // ERROR // User logic }","content":"Реальный пример switch order.CreatedByRole { case myapi.UserRole_USER_ROLE_ADMIN: // ERROR // Admin logic case myapi.UserRole_USER_ROLE_USER: // ERROR // User logic }"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::27","title":"ENUM_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример // undefined: myapi.UserRole // undefined: myapi.UserRole_USER_ROLE_ADMIN ```","content":"Реальный пример // undefined: myapi.UserRole // undefined: myapi.UserRole_USER_ROLE_ADMIN ```"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::28","title":"ENUM_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Старые данные становятся нечитаемыми:**","content":"Реальный пример **Старые данные становятся нечитаемыми:**"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::29","title":"ENUM_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Серверная логика ломается:**","content":"Реальный пример **Серверная логика ломается:**"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::30","title":"ENUM_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Депрецируйте enum:** **Пометьте поля со старым enum deprecated:** **Создайте новый enum:** **Сервер обрабатывает оба:** **Удалите старый enum в следующей major‑версии.**","content":"Стратегия миграции **Депрецируйте enum:** **Пометьте поля со старым enum deprecated:** **Создайте новый enum:** **Сервер обрабатывает оба:** **Удалите старый enum в следующей major‑версии.**"},{"id":"cli/breaking-changes/rules/enum-no-delete::enum::31","title":"ENUM_NO_DELETE","section":"Редизайн enum","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#enum","headings":["Редизайн enum"],"excerpt":"Редизайн enum ```proto enum Priority { option deprecated = true; PRIORITY_UNSPECIFIED = 0; PRIORITY_LOW = 1; PRIORITY_HIGH = 2; }","content":"Редизайн enum ```proto enum Priority { option deprecated = true; PRIORITY_UNSPECIFIED = 0; PRIORITY_LOW = 1; PRIORITY_HIGH = 2; }"},{"id":"cli/breaking-changes/rules/enum-no-delete::enum::32","title":"ENUM_NO_DELETE","section":"Редизайн enum","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#enum","headings":["Редизайн enum"],"excerpt":"Редизайн enum enum TaskPriority { TASK_PRIORITY_UNSPECIFIED = 0; TASK_PRIORITY_LOW = 1; TASK_PRIORITY_MEDIUM = 2; TASK_PRIORITY_HIGH = 3; TASK_PRIORITY_URGENT = 4; } ```","content":"Редизайн enum enum TaskPriority { 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::enum::33","title":"ENUM_NO_DELETE","section":"Консолидация enum","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#enum","headings":["Консолидация enum"],"excerpt":"Консолидация enum ```proto enum Status { option deprecated = true; STATUS_UNSPECIFIED = 0; STATUS_ACTIVE = 1; }","content":"Консолидация enum ```proto enum Status { option deprecated = true; STATUS_UNSPECIFIED = 0; STATUS_ACTIVE = 1; }"},{"id":"cli/breaking-changes/rules/enum-no-delete::enum::34","title":"ENUM_NO_DELETE","section":"Консолидация enum","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#enum","headings":["Консолидация enum"],"excerpt":"Консолидация enum enum State { option deprecated = true; STATE_UNSPECIFIED = 0; STATE_ENABLED = 1; }","content":"Консолидация enum enum State { option deprecated = true; STATE_UNSPECIFIED = 0; STATE_ENABLED = 1; }"},{"id":"cli/breaking-changes/rules/enum-no-delete::enum::35","title":"ENUM_NO_DELETE","section":"Консолидация enum","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#enum","headings":["Консолидация enum"],"excerpt":"Консолидация enum enum EntityStatus { ENTITY_STATUS_UNSPECIFIED = 0; ENTITY_STATUS_ACTIVE = 1; ENTITY_STATUS_INACTIVE = 2; ENTITY_STATUS_ENABLED = 3; ENTITY_STATUS_DISABLED = 4; } ```","content":"Консолидация enum enum EntityStatus { 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::enum::36","title":"ENUM_NO_DELETE","section":"Перемещение enum в новый пакет","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#enum","headings":["Перемещение enum в новый пакет"],"excerpt":"Перемещение enum в новый пакет ```proto enum UserRole { option deprecated = true; USER_ROLE_UNSPECIFIED = 0; USER_ROLE_ADMIN = 1; }","content":"Перемещение enum в новый пакет ```proto enum UserRole { option deprecated = true; USER_ROLE_UNSPECIFIED = 0; USER_ROLE_ADMIN = 1; }"},{"id":"cli/breaking-changes/rules/enum-no-delete::enum::37","title":"ENUM_NO_DELETE","section":"Перемещение enum в новый пакет","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#enum","headings":["Перемещение enum в новый пакет"],"excerpt":"Перемещение enum в новый пакет import \"common/roles.proto\";","content":"Перемещение enum в новый пакет import \"common/roles.proto\";"},{"id":"cli/breaking-changes/rules/enum-no-delete::enum::38","title":"ENUM_NO_DELETE","section":"Перемещение enum в новый пакет","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#enum","headings":["Перемещение enum в новый пакет"],"excerpt":"Перемещение enum в новый пакет message Order { UserRole old_role = 3 [deprecated = true]; common.UserRole new_role = 4; } ```","content":"Перемещение enum в новый пакет message Order { UserRole old_role = 3 [deprecated = true]; common.UserRole new_role = 4; } ```"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::39","title":"ENUM_NO_DELETE","section":"Версионирование / новая версия пакета","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Версионирование / новая версия пакета"],"excerpt":"Версионирование / новая версия пакета ```proto package myapi.v2;","content":"Версионирование / новая версия пакета ```proto package myapi.v2;"},{"id":"cli/breaking-changes/rules/enum-no-delete::top::40","title":"ENUM_NO_DELETE","section":"Версионирование / новая версия пакета","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Версионирование / новая версия пакета"],"excerpt":"Версионирование / новая версия пакета enum UserPermission { USER_PERMISSION_UNSPECIFIED = 0; USER_PERMISSION_READ = 1; USER_PERMISSION_WRITE = 2; USER_PERMISSION_ADMIN = 3; }","content":"Версионирование / новая версия пакета 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::top::41","title":"ENUM_NO_DELETE","section":"Версионирование / новая версия пакета","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":["Версионирование / новая версия пакета"],"excerpt":"Версионирование / новая версия пакета message Order { string id = 1; UserPermission created_by_permission = 2; } ```","content":"Версионирование / новая версия пакета message Order { string id = 1; UserPermission created_by_permission = 2; } ```"},{"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":"Правило проверяет, что ни одно значение enum (enum value) не было удалено. Удаление значения ломает совместимость по wire‑формату и сгенерированный код: в уже сохранённых данных могут присутствовать удалённые значения, а","content":"Правило проверяет, что ни одно значение enum (enum value) не было удалено. Удаление значения ломает совместимость по wire‑формату и сгенерированный код: в уже сохранённых данных могут присутствовать удалённые значения, а клиентский код может ссылаться на соответствующие константы."},{"id":"cli/breaking-changes/rules/enum-value-no-delete::breaking::1","title":"ENUM_VALUE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::breaking::2","title":"ENUM_VALUE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::breaking::3","title":"ENUM_VALUE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) 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":"Плохой (Breaking) 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::breaking::4","title":"ENUM_VALUE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) enum Priority { PRIORITY_UNSPECIFIED = 0; PRIORITY_LOW = 1; PRIORITY_MEDIUM = 2; PRIORITY_HIGH = 3; PRIORITY_URGENT = 4; } ```","content":"Плохой (Breaking) 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::breaking::5","title":"ENUM_VALUE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::breaking::6","title":"ENUM_VALUE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::breaking::7","title":"ENUM_VALUE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) 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 --] ","content":"Плохой (Breaking) 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 --] Удалено значение enum — BREAKING! }"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::breaking::8","title":"ENUM_VALUE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) enum Priority { PRIORITY_UNSPECIFIED = 0; PRIORITY_LOW = 1; PRIORITY_MEDIUM = 2; PRIORITY_HIGH = 3; // PRIORITY_URGENT = 4; // [!code --] Удалено значение enum — BREAKING! } ```","content":"Плохой (Breaking) enum Priority { PRIORITY_UNSPECIFIED = 0; PRIORITY_LOW = 1; PRIORITY_MEDIUM = 2; PRIORITY_HIGH = 3; // PRIORITY_URGENT = 4; // [!code --] Удалено значение enum — BREAKING! } ```"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::9","title":"ENUM_VALUE_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры **Множественное удаление значений:** ```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_S","content":"Дополнительные примеры **Множественное удаление значений:** ```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::top::10","title":"ENUM_VALUE_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры // 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","content":"Дополнительные примеры // 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::top::11","title":"ENUM_VALUE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо удаления — пометить значения deprecated:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо удаления — пометить значения deprecated:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::12","title":"ENUM_VALUE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::13","title":"ENUM_VALUE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) 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 = t","content":"Хороший (Безопасный) 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::top::14","title":"ENUM_VALUE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) enum Priority { PRIORITY_UNSPECIFIED = 0; PRIORITY_LOW = 1; PRIORITY_MEDIUM = 2; PRIORITY_HIGH = 3; PRIORITY_URGENT = 4 [deprecated = true]; // [!code focus] } ```","content":"Хороший (Безопасный) 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::top::15","title":"ENUM_VALUE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Или зарезервировать номер и имя после удаления:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Или зарезервировать номер и имя после удаления:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::16","title":"ENUM_VALUE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::17","title":"ENUM_VALUE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) enum OrderStatus { reserved 5; // [!code focus] reserved \"ORDER_STATUS_CANCELLED\"; // [!code focus]","content":"Хороший (Безопасный) enum OrderStatus { reserved 5; // [!code focus] reserved \"ORDER_STATUS_CANCELLED\"; // [!code focus]"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::18","title":"ENUM_VALUE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_CONFIRMED = 2; ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_DELIVERED = 4; }","content":"Хороший (Безопасный) 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::top::19","title":"ENUM_VALUE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) enum Priority { reserved 4; // [!code focus] reserved \"PRIORITY_URGENT\"; // [!code focus]","content":"Хороший (Безопасный) enum Priority { reserved 4; // [!code focus] reserved \"PRIORITY_URGENT\"; // [!code focus]"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::20","title":"ENUM_VALUE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) PRIORITY_UNSPECIFIED = 0; PRIORITY_LOW = 1; PRIORITY_MEDIUM = 2; PRIORITY_HIGH = 3; } ```","content":"Хороший (Безопасный) PRIORITY_UNSPECIFIED = 0; PRIORITY_LOW = 1; PRIORITY_MEDIUM = 2; PRIORITY_HIGH = 3; } ```"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::21","title":"ENUM_VALUE_NO_DELETE","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Влияние"],"excerpt":"Влияние **Wire Format:** Данные с удалёнными значениями не десериализуются корректно **Generated Code:** Константы исчезают — клиентский код не компилируется **Client Applications:** Ссылки на удалённые значения вызывают","content":"Влияние **Wire Format:** Данные с удалёнными значениями не десериализуются корректно **Generated Code:** Константы исчезают — клиентский код не компилируется **Client Applications:** Ссылки на удалённые значения вызывают ошибки компиляции **Switch Statements:** switch по enum ломается (неизвестные case) **Default Handling:** Поведение при неизвестных значениях меняется"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::22","title":"ENUM_VALUE_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Код клиента ломается:** ```go order := &myapi.Order{ Status: myapi.OrderStatus_ORDER_STATUS_CANCELLED, // ERROR после удаления }","content":"Реальный пример **Код клиента ломается:** ```go order := &myapi.Order{ Status: myapi.OrderStatus_ORDER_STATUS_CANCELLED, // ERROR после удаления }"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::23","title":"ENUM_VALUE_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример switch order.Status { case myapi.OrderStatus_ORDER_STATUS_PENDING: // Pending case myapi.OrderStatus_ORDER_STATUS_CANCELLED: // ERROR: undefined // Cancellation default: // Unknown } // undefined: myapi.O","content":"Реальный пример switch order.Status { case myapi.OrderStatus_ORDER_STATUS_PENDING: // Pending case myapi.OrderStatus_ORDER_STATUS_CANCELLED: // ERROR: undefined // Cancellation default: // Unknown } // undefined: myapi.OrderStatus_ORDER_STATUS_CANCELLED ```"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::24","title":"ENUM_VALUE_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Проблемы с уже сохранёнными данными:**","content":"Реальный пример **Проблемы с уже сохранёнными данными:**"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::25","title":"ENUM_VALUE_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Валидация на сервере:** ```go func validateOrderStatus(status OrderStatus) error { switch status { case OrderStatus_ORDER_STATUS_PENDING, OrderStatus_ORDER_STATUS_CONFIRMED, OrderStatus_ORDER_STATUS_SHI","content":"Реальный пример **Валидация на сервере:** ```go 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 после удаления return nil default: return errors.New(\"invalid order status\") } }"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::26","title":"ENUM_VALUE_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример func canModifyOrder(order *Order) bool { return order.Status != OrderStatus_ORDER_STATUS_CANCELLED // ERROR } ```","content":"Реальный пример func canModifyOrder(order *Order) bool { return order.Status != OrderStatus_ORDER_STATUS_CANCELLED // ERROR } ```"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::27","title":"ENUM_VALUE_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Сначала пометить deprecated:** **Перестать использовать deprecated значение в новом коде:** **Обработка legacy в клиенте:** **Резервирование после миграции:** **Никогда не переиспользовать номера** —","content":"Стратегия миграции **Сначала пометить deprecated:** **Перестать использовать deprecated значение в новом коде:** **Обработка legacy в клиенте:** **Резервирование после миграции:** **Никогда не переиспользовать номера** — зарезервированы навсегда."},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::28","title":"ENUM_VALUE_NO_DELETE","section":"Предотвращение переиспользования номера","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Предотвращение переиспользования номера"],"excerpt":"Предотвращение переиспользования номера ```proto enum Status { reserved 2; reserved \"STATUS_DELETED\";","content":"Предотвращение переиспользования номера ```proto enum Status { reserved 2; reserved \"STATUS_DELETED\";"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::29","title":"ENUM_VALUE_NO_DELETE","section":"Предотвращение переиспользования номера","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":["Предотвращение переиспользования номера"],"excerpt":"Предотвращение переиспользования номера STATUS_UNSPECIFIED = 0; STATUS_ACTIVE = 1; STATUS_INACTIVE = 3; // STATUS_DELETED = 2; // Не переиспользуем } ```","content":"Предотвращение переиспользования номера STATUS_UNSPECIFIED = 0; STATUS_ACTIVE = 1; STATUS_INACTIVE = 3; // STATUS_DELETED = 2; // Не переиспользуем } ```"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::json::30","title":"ENUM_VALUE_NO_DELETE","section":"JSON совместимость","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#json","headings":["JSON совместимость"],"excerpt":"JSON совместимость ```proto enum Color { reserved 2; reserved \"RED\";","content":"JSON совместимость ```proto enum Color { reserved 2; reserved \"RED\";"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::json::31","title":"ENUM_VALUE_NO_DELETE","section":"JSON совместимость","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#json","headings":["JSON совместимость"],"excerpt":"JSON совместимость COLOR_UNSPECIFIED = 0; COLOR_BLUE = 1; COLOR_GREEN = 3; // COLOR_RED = 2; // Был удалён } ```","content":"JSON совместимость COLOR_UNSPECIFIED = 0; COLOR_BLUE = 1; COLOR_GREEN = 3; // COLOR_RED = 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":"Это правило проверяет, что имя enum значения для каждого номера (number) не изменилось. Переименование enum значения при сохранении его номера ломает совместимость JSON и сгенерированный код: клиенты ожидают конкретные и","content":"Это правило проверяет, что имя enum значения для каждого номера (number) не изменилось. Переименование enum значения при сохранении его номера ломает совместимость JSON и сгенерированный код: клиенты ожидают конкретные имена констант."},{"id":"cli/breaking-changes/rules/enum-value-same-name::breaking::1","title":"ENUM_VALUE_SAME_NAME","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-value-same-name::breaking::2","title":"ENUM_VALUE_SAME_NAME","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/enum-value-same-name::breaking::3","title":"ENUM_VALUE_SAME_NAME","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_CONFIRMED = 2; ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_DELIVERED = 4; } ```","content":"Плохой (Breaking) 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::breaking::4","title":"ENUM_VALUE_SAME_NAME","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-value-same-name::breaking::5","title":"ENUM_VALUE_SAME_NAME","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/enum-value-same-name::breaking::6","title":"ENUM_VALUE_SAME_NAME","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_APPROVED = 2; // [!code --] Было ORDER_STATUS_CONFIRMED ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_COMPLETED = 4; // [","content":"Плохой (Breaking) enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_APPROVED = 2; // [!code --] Было ORDER_STATUS_CONFIRMED ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_COMPLETED = 4; // [!code --] Было ORDER_STATUS_DELIVERED } ```"},{"id":"cli/breaking-changes/rules/enum-value-same-name::top::7","title":"ENUM_VALUE_SAME_NAME","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры **Множественные переименования:** ```proto // Before enum UserRole { USER_ROLE_UNSPECIFIED = 0; USER_ROLE_ADMIN = 1; USER_ROLE_MODERATOR = 2; USER_ROLE_USER = 3; }","content":"Дополнительные примеры **Множественные переименования:** ```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::top::8","title":"ENUM_VALUE_SAME_NAME","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры // After - ВСЁ BREAKING enum UserRole { USER_ROLE_UNSPECIFIED = 0; USER_ROLE_ADMINISTRATOR = 1; // BREAKING: ADMIN -> ADMINISTRATOR USER_ROLE_MOD = 2; // BREAKING: MODERATOR -> MOD USER_ROLE_MEMBER","content":"Дополнительные примеры // After - ВСЁ BREAKING 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::top::9","title":"ENUM_VALUE_SAME_NAME","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо переименования — добавить новые значения и пометить старые deprecated:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо переименования — добавить новые значения и пометить старые deprecated:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-value-same-name::top::10","title":"ENUM_VALUE_SAME_NAME","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/enum-value-same-name::top::11","title":"ENUM_VALUE_SAME_NAME","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) 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 [depre","content":"Хороший (Безопасный) 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] // Новое значение вместо переименования ORDER_STATUS_COMPLETED = 6; // [!code focus] } ```"},{"id":"cli/breaking-changes/rules/enum-value-same-name::top::12","title":"ENUM_VALUE_SAME_NAME","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Или создать новую версию enum:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Или создать новую версию enum:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-value-same-name::top::13","title":"ENUM_VALUE_SAME_NAME","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v2; // [!code focus]","content":"Хороший (Безопасный) package myapi.v2; // [!code focus]"},{"id":"cli/breaking-changes/rules/enum-value-same-name::top::14","title":"ENUM_VALUE_SAME_NAME","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_APPROVED = 2; // [!code focus] // «Чистые» имена в v2 ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_COMPLETED = 4; // ","content":"Хороший (Безопасный) enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_APPROVED = 2; // [!code focus] // «Чистые» имена в v2 ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_COMPLETED = 4; // [!code focus] } ```"},{"id":"cli/breaking-changes/rules/enum-value-same-name::top::15","title":"ENUM_VALUE_SAME_NAME","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Влияние"],"excerpt":"Влияние **Generated Code:** Меняются имена констант — компиляция клиентов ломается **JSON Compatibility:** JSON использует имена enum — старые документы не парсятся **Client Applications:** Код со старым именем константы","content":"Влияние **Generated Code:** Меняются имена констант — компиляция клиентов ломается **JSON Compatibility:** JSON использует имена enum — старые документы не парсятся **Client Applications:** Код со старым именем константы не компилируется **Documentation:** Документация устаревает с неправильными именами"},{"id":"cli/breaking-changes/rules/enum-value-same-name::top::16","title":"ENUM_VALUE_SAME_NAME","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Реальный пример"],"excerpt":"Реальный пример **Ломается код клиента:** ```go // Before status := myapi.OrderStatus_ORDER_STATUS_CONFIRMED if order.Status == myapi.OrderStatus_ORDER_STATUS_DELIVERED { // handle delivery }","content":"Реальный пример **Ломается код клиента:** ```go // Before 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::top::17","title":"ENUM_VALUE_SAME_NAME","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Реальный пример"],"excerpt":"Реальный пример // After (переименовано) — ошибки компиляции status := myapi.OrderStatus_ORDER_STATUS_CONFIRMED // ERROR: undefined if order.Status == myapi.OrderStatus_ORDER_STATUS_DELIVERED { // ERROR: undefined // han","content":"Реальный пример // After (переименовано) — ошибки компиляции status := myapi.OrderStatus_ORDER_STATUS_CONFIRMED // ERROR: undefined if order.Status == myapi.OrderStatus_ORDER_STATUS_DELIVERED { // ERROR: undefined // handle delivery } ```"},{"id":"cli/breaking-changes/rules/enum-value-same-name::top::18","title":"ENUM_VALUE_SAME_NAME","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Реальный пример"],"excerpt":"Реальный пример **JSON совместимость ломается:** ```json // Раньше { \"status\": \"ORDER_STATUS_CONFIRMED\" }","content":"Реальный пример **JSON совместимость ломается:** ```json // Раньше { \"status\": \"ORDER_STATUS_CONFIRMED\" }"},{"id":"cli/breaking-changes/rules/enum-value-same-name::top::19","title":"ENUM_VALUE_SAME_NAME","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Реальный пример"],"excerpt":"Реальный пример // После { \"status\": \"ORDER_STATUS_APPROVED\" // Старые JSON больше не парсятся } ```","content":"Реальный пример // После { \"status\": \"ORDER_STATUS_APPROVED\" // Старые JSON больше не парсятся } ```"},{"id":"cli/breaking-changes/rules/enum-value-same-name::top::20","title":"ENUM_VALUE_SAME_NAME","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Добавьте новое значение вместо переименования:**","content":"Стратегия миграции **Добавьте новое значение вместо переименования:**"},{"id":"cli/breaking-changes/rules/enum-value-same-name::top::21","title":"ENUM_VALUE_SAME_NAME","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Сервер обрабатывает оба значения на переходном этапе** **Мигрируйте клиентов** на новые значения **Удалите (reserve) старое имя и номер** в следующей major‑версии:","content":"Стратегия миграции **Сервер обрабатывает оба значения на переходном этапе** **Мигрируйте клиентов** на новые значения **Удалите (reserve) старое имя и номер** в следующей major‑версии:"},{"id":"cli/breaking-changes/rules/enum-value-same-name::allow-alias::22","title":"ENUM_VALUE_SAME_NAME","section":"Allow Alias (исключение)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name#allow-alias","headings":["Allow Alias (исключение)"],"excerpt":"Allow Alias (исключение) С allow_alias = true можно временно иметь два имени для одного номера:","content":"Allow Alias (исключение) С allow_alias = true можно временно иметь два имени для одного номера:"},{"id":"cli/breaking-changes/rules/enum-value-same-name::allow-alias::23","title":"ENUM_VALUE_SAME_NAME","section":"Allow Alias (исключение)","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name#allow-alias","headings":["Allow Alias (исключение)"],"excerpt":"Allow Alias (исключение) Примечание: Сейчас EasyP всё равно считает это breaking (может измениться в будущем).","content":"Allow Alias (исключение) Примечание: Сейчас EasyP всё равно считает это breaking (может измениться в будущем)."},{"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":"Это правило проверяет, что ни одно поле сообщения (message field) не было удалено. Удаление поля ломает совместимость по wire‑формату и сгенерированный код: в существующих данных может присутствовать удалённое поле, а кл","content":"Это правило проверяет, что ни одно поле сообщения (message field) не было удалено. Удаление поля ломает совместимость по wire‑формату и сгенерированный код: в существующих данных может присутствовать удалённое поле, а клиентский код может ссылаться на него."},{"id":"cli/breaking-changes/rules/field-no-delete::breaking::1","title":"FIELD_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-no-delete::breaking::2","title":"FIELD_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/field-no-delete::breaking::3","title":"FIELD_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message User { string name = 1; string email = 2; int32 age = 3; string phone = 4; // [!code --] } ```","content":"Плохой (Breaking) message User { string name = 1; string email = 2; int32 age = 3; string phone = 4; // [!code --] } ```"},{"id":"cli/breaking-changes/rules/field-no-delete::breaking::4","title":"FIELD_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-no-delete::breaking::5","title":"FIELD_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/field-no-delete::breaking::6","title":"FIELD_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message User { string name = 1; string email = 2; int32 age = 3; // phone поле удалено — BREAKING CHANGE! } ```","content":"Плохой (Breaking) message User { string name = 1; string email = 2; int32 age = 3; // phone поле удалено — BREAKING CHANGE! } ```"},{"id":"cli/breaking-changes/rules/field-no-delete::top::7","title":"FIELD_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо удаления — пометить поле deprecated:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо удаления — пометить поле deprecated:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-no-delete::top::8","title":"FIELD_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/field-no-delete::top::9","title":"FIELD_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message User { string name = 1; string email = 2; int32 age = 3; string phone = 4 [deprecated = true]; // [!code focus] } ```","content":"Хороший (Безопасный) 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::top::10","title":"FIELD_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Или зарезервировать номер и имя поля после удаления:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Или зарезервировать номер и имя поля после удаления:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-no-delete::top::11","title":"FIELD_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/field-no-delete::top::12","title":"FIELD_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message User { reserved 4; // [!code focus] reserved \"phone\"; // [!code focus] string name = 1; string email = 2; int32 age = 3; } ```","content":"Хороший (Безопасный) 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::top::13","title":"FIELD_NO_DELETE","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete","headings":["Влияние"],"excerpt":"Влияние **Wire Format:** Старые сообщения с удалённым полем некорректно десериализуются **Generated Code:** Удаляются аксессоры (get/set), компиляция клиента ломается **Data Loss:** Потеря сохранённых данных, связанных с","content":"Влияние **Wire Format:** Старые сообщения с удалённым полем некорректно десериализуются **Generated Code:** Удаляются аксессоры (get/set), компиляция клиента ломается **Data Loss:** Потеря сохранённых данных, связанных с полем **JSON Compatibility:** JSON парсеры ожидают наличие поля и могут выдавать ошибки"},{"id":"cli/breaking-changes/rules/field-no-delete::top::14","title":"FIELD_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Сначала пометить deprecated:**","content":"Стратегия миграции **Сначала пометить deprecated:**"},{"id":"cli/breaking-changes/rules/field-no-delete::top::15","title":"FIELD_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Прекратить запись в поле** в прикладном коде","content":"Стратегия миграции **Прекратить запись в поле** в прикладном коде"},{"id":"cli/breaking-changes/rules/field-no-delete::top::16","title":"FIELD_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Зарезервировать поле** в следующей версии, чтобы избежать повторного использования:","content":"Стратегия миграции **Зарезервировать поле** в следующей версии, чтобы избежать повторного использования:"},{"id":"cli/breaking-changes/rules/field-no-delete::top::17","title":"FIELD_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Никогда не переиспользовать номер поля** — должен оставаться в reserved навсегда","content":"Стратегия миграции **Никогда не переиспользовать номер поля** — должен оставаться в reserved навсегда"},{"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":"Правило проверяет, что поля сообщений сохраняют ту же кардинальность (обязательность / optional). Изменение кардинальности поля ломает совместимость по wire‑формату и сгенерированный код: семантика присутствия и ожидания","content":"Правило проверяет, что поля сообщений сохраняют ту же кардинальность (обязательность / optional). Изменение кардинальности поля ломает совместимость по wire‑формату и сгенерированный код: семантика присутствия и ожидания клиентского кода отличаются для optional и required (implicit) полей."},{"id":"cli/breaking-changes/rules/field-same-cardinality::breaking::1","title":"FIELD_SAME_CARDINALITY","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-same-cardinality::breaking::2","title":"FIELD_SAME_CARDINALITY","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/field-same-cardinality::breaking::3","title":"FIELD_SAME_CARDINALITY","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message User { string name = 1; string email = 2; int32 age = 3; }","content":"Плохой (Breaking) message User { string name = 1; string email = 2; int32 age = 3; }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::breaking::4","title":"FIELD_SAME_CARDINALITY","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message CreateUserRequest { string name = 1; optional string email = 2; string phone = 3; } ```","content":"Плохой (Breaking) message CreateUserRequest { string name = 1; optional string email = 2; string phone = 3; } ```"},{"id":"cli/breaking-changes/rules/field-same-cardinality::breaking::5","title":"FIELD_SAME_CARDINALITY","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-same-cardinality::breaking::6","title":"FIELD_SAME_CARDINALITY","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/field-same-cardinality::breaking::7","title":"FIELD_SAME_CARDINALITY","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message User { string name = 1; optional string email = 2; // [!code --] Было required (implicit), стало optional int32 age = 3; }","content":"Плохой (Breaking) message User { string name = 1; optional string email = 2; // [!code --] Было required (implicit), стало optional int32 age = 3; }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::breaking::8","title":"FIELD_SAME_CARDINALITY","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message CreateUserRequest { string name = 1; string email = 2; // [!code --] Было optional, стало требуемым (implicit required) string phone = 3; } ```","content":"Плохой (Breaking) message CreateUserRequest { string name = 1; string email = 2; // [!code --] Было optional, стало требуемым (implicit required) string phone = 3; } ```"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::9","title":"FIELD_SAME_CARDINALITY","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры **Проблемы миграции Proto2 → Proto3:**","content":"Дополнительные примеры **Проблемы миграции Proto2 → Proto3:**"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::10","title":"FIELD_SAME_CARDINALITY","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры ```proto // Before (proto2) syntax = \"proto2\";","content":"Дополнительные примеры ```proto // Before (proto2) syntax = \"proto2\";"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::11","title":"FIELD_SAME_CARDINALITY","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры message Order { required string id = 1; optional string notes = 2; repeated string tags = 3; }","content":"Дополнительные примеры message Order { required string id = 1; optional string notes = 2; repeated string tags = 3; }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::12","title":"FIELD_SAME_CARDINALITY","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры // After (proto3) - BREAKING CHANGES! syntax = \"proto3\";","content":"Дополнительные примеры // After (proto3) - BREAKING CHANGES! syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::13","title":"FIELD_SAME_CARDINALITY","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры message Order { string id = 1; // BREAKING: required -> implicit optional string notes = 2; // BREAKING: explicit optional -> implicit optional repeated string tags = 3; // OK } ```","content":"Дополнительные примеры message Order { string id = 1; // BREAKING: required -> implicit optional string notes = 2; // BREAKING: explicit optional -> implicit optional repeated string tags = 3; // OK } ```"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::14","title":"FIELD_SAME_CARDINALITY","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо изменения кардинальности — добавьте новое поле:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо изменения кардинальности — добавьте новое поле:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::15","title":"FIELD_SAME_CARDINALITY","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::16","title":"FIELD_SAME_CARDINALITY","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message User { string name = 1; string email = 2 [deprecated = true]; // [!code focus] Сохраняем старую кардинальность int32 age = 3; optional string email_optional = 4; // [!code focus] Новое option","content":"Хороший (Безопасный) message User { string name = 1; string email = 2 [deprecated = true]; // [!code focus] Сохраняем старую кардинальность int32 age = 3; optional string email_optional = 4; // [!code focus] Новое optional поле }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::17","title":"FIELD_SAME_CARDINALITY","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message CreateUserRequest { string name = 1; optional string email = 2 [deprecated = true]; // [!code focus] string phone = 3; string email_required = 4; // [!code focus] Новое требуемое поле } ```","content":"Хороший (Безопасный) message CreateUserRequest { string name = 1; optional string email = 2 [deprecated = true]; // [!code focus] string phone = 3; string email_required = 4; // [!code focus] Новое требуемое поле } ```"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::18","title":"FIELD_SAME_CARDINALITY","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Или создайте новую версию сообщения:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Или создайте новую версию сообщения:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::19","title":"FIELD_SAME_CARDINALITY","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v2; // [!code focus]","content":"Хороший (Безопасный) package myapi.v2; // [!code focus]"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::20","title":"FIELD_SAME_CARDINALITY","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message User { string name = 1; optional string email = 2; // [!code focus] Чистая модель в v2 int32 age = 3; }","content":"Хороший (Безопасный) message User { string name = 1; optional string email = 2; // [!code focus] Чистая модель в v2 int32 age = 3; }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::21","title":"FIELD_SAME_CARDINALITY","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message CreateUserRequest { string name = 1; string email = 2; // [!code focus] Требуемое в v2 string phone = 3; } ```","content":"Хороший (Безопасный) message CreateUserRequest { string name = 1; string email = 2; // [!code focus] Требуемое в v2 string phone = 3; } ```"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::22","title":"FIELD_SAME_CARDINALITY","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Влияние"],"excerpt":"Влияние **Wire Format:** Меняется семантика присутствия — клиенты неправильно ожидают поля **Generated Code:** Меняются методы доступа / проверки (has, clear) **Validation:** Правила проверки обязательности переписываютс","content":"Влияние **Wire Format:** Меняется семантика присутствия — клиенты неправильно ожидают поля **Generated Code:** Меняются методы доступа / проверки (has, clear) **Validation:** Правила проверки обязательности переписываются **Default Values:** Optional и required по‑разному обрабатывают отсутствие значения"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::23","title":"FIELD_SAME_CARDINALITY","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Реальный пример"],"excerpt":"Реальный пример **Код клиента ломается при смене кардинальности:** ```go // Before - поле фактически требуется (implicit) user := &myapi.User{ Name: \"John\", Email: \"john@example.com\", Age: 30, }","content":"Реальный пример **Код клиента ломается при смене кардинальности:** ```go // Before - поле фактически требуется (implicit) user := &myapi.User{ Name: \"John\", Email: \"john@example.com\", Age: 30, }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::24","title":"FIELD_SAME_CARDINALITY","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Реальный пример"],"excerpt":"Реальный пример if user.Email != \"\" { // Есть значение }","content":"Реальный пример if user.Email != \"\" { // Есть значение }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::25","title":"FIELD_SAME_CARDINALITY","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Реальный пример"],"excerpt":"Реальный пример // After - поле стало optional (pointer) user := &myapi.User{ Name: \"John\", Age: 30, // Email может отсутствовать }","content":"Реальный пример // After - поле стало optional (pointer) user := &myapi.User{ Name: \"John\", Age: 30, // Email может отсутствовать }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::26","title":"FIELD_SAME_CARDINALITY","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Реальный пример"],"excerpt":"Реальный пример if user.Email != nil && *user.Email != \"\" { // Есть значение (новый способ) }","content":"Реальный пример if user.Email != nil && *user.Email != \"\" { // Есть значение (новый способ) }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::27","title":"FIELD_SAME_CARDINALITY","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Реальный пример"],"excerpt":"Реальный пример user.Email = &emailValue // Присваивание указателя вместо строки ```","content":"Реальный пример user.Email = &emailValue // Присваивание указателя вместо строки ```"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::28","title":"FIELD_SAME_CARDINALITY","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Реальный пример"],"excerpt":"Реальный пример **Валидация на сервере:** ```go // Before func validateUser(user *User) error { if user.Email == \"\" { return errors.New(\"email is required\") } return nil }","content":"Реальный пример **Валидация на сервере:** ```go // Before func validateUser(user *User) error { if user.Email == \"\" { return errors.New(\"email is required\") } return nil }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::29","title":"FIELD_SAME_CARDINALITY","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Реальный пример"],"excerpt":"Реальный пример // After func validateUser(user *User) error { if user.Email == nil { return errors.New(\"email is required\") } if *user.Email == \"\" { return errors.New(\"email cannot be empty\") } return nil } ```","content":"Реальный пример // After func validateUser(user *User) error { if user.Email == nil { return errors.New(\"email is required\") } if *user.Email == \"\" { return errors.New(\"email cannot be empty\") } return nil } ```"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::30","title":"FIELD_SAME_CARDINALITY","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Добавьте новое поле** с нужной кардинальностью:","content":"Стратегия миграции **Добавьте новое поле** с нужной кардинальностью:"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::31","title":"FIELD_SAME_CARDINALITY","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Период двойной записи** — заполняйте оба поля:","content":"Стратегия миграции **Период двойной записи** — заполняйте оба поля:"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::32","title":"FIELD_SAME_CARDINALITY","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Клиенты постепенно переходят**:","content":"Стратегия миграции **Клиенты постепенно переходят**:"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::33","title":"FIELD_SAME_CARDINALITY","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Удаление старого поля** в следующей major‑версии:","content":"Стратегия миграции **Удаление старого поля** в следующей major‑версии:"},{"id":"cli/breaking-changes/rules/field-same-cardinality::proto2-proto3::34","title":"FIELD_SAME_CARDINALITY","section":"Миграция Proto2 → Proto3","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#proto2-proto3","headings":["Миграция Proto2 → Proto3"],"excerpt":"Миграция Proto2 → Proto3 ```proto syntax = \"proto3\"; message Order { string id = 1; // BREAKING если был required }","content":"Миграция Proto2 → Proto3 ```proto syntax = \"proto3\"; message Order { string id = 1; // BREAKING если был required }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::proto2-proto3::35","title":"FIELD_SAME_CARDINALITY","section":"Миграция Proto2 → Proto3","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#proto2-proto3","headings":["Миграция Proto2 → Proto3"],"excerpt":"Миграция Proto2 → Proto3 // Сохранить семантику: syntax = \"proto3\"; message Order { string id = 1; optional string notes = 2; } ```","content":"Миграция Proto2 → Proto3 // Сохранить семантику: syntax = \"proto3\"; message Order { string id = 1; optional string notes = 2; } ```"},{"id":"cli/breaking-changes/rules/field-same-cardinality::optional-required::36","title":"FIELD_SAME_CARDINALITY","section":"Делать optional поле required","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#optional-required","headings":["Делать optional поле required"],"excerpt":"Делать optional поле required ```proto message CreateUserRequest { string name = 1; string email = 2; // BREAKING (раньше optional) }","content":"Делать optional поле required ```proto message CreateUserRequest { string name = 1; string email = 2; // BREAKING (раньше optional) }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::optional-required::37","title":"FIELD_SAME_CARDINALITY","section":"Делать optional поле required","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#optional-required","headings":["Делать optional поле required"],"excerpt":"Делать optional поле required message CreateUserRequest { string name = 1; optional string email = 2 [deprecated = true]; string required_email = 3; } ```","content":"Делать optional поле required message CreateUserRequest { string name = 1; optional string email = 2 [deprecated = true]; string required_email = 3; } ```"},{"id":"cli/breaking-changes/rules/field-same-cardinality::required-optional::38","title":"FIELD_SAME_CARDINALITY","section":"Делать required поле optional","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#required-optional","headings":["Делать required поле optional"],"excerpt":"Делать required поле optional ```proto message User { optional string phone = 3; // BREAKING (было implicit required) }","content":"Делать required поле optional ```proto message User { optional string phone = 3; // BREAKING (было implicit required) }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::required-optional::39","title":"FIELD_SAME_CARDINALITY","section":"Делать required поле optional","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#required-optional","headings":["Делать required поле optional"],"excerpt":"Делать required поле optional message User { string phone = 3 [deprecated = true]; optional string phone_optional = 4; } ```","content":"Делать required поле optional message User { string phone = 3 [deprecated = true]; optional string phone_optional = 4; } ```"},{"id":"cli/breaking-changes/rules/field-same-cardinality::protobuf::40","title":"FIELD_SAME_CARDINALITY","section":"Типы кардинальности в Protobuf","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#protobuf","headings":["Типы кардинальности в Protobuf"],"excerpt":"Типы кардинальности в Protobuf","content":"Типы кардинальности в Protobuf"},{"id":"cli/breaking-changes/rules/field-same-cardinality::proto3::41","title":"FIELD_SAME_CARDINALITY","section":"Proto3","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#proto3","headings":["Proto3"],"excerpt":"Proto3 **Implicit optional**: string name = 1; **Explicit optional**: optional string email = 2; **Repeated**: repeated string tags = 3; **Map**: map metadata = 4;","content":"Proto3 **Implicit optional**: string name = 1; **Explicit optional**: optional string email = 2; **Repeated**: repeated string tags = 3; **Map**: map metadata = 4;"},{"id":"cli/breaking-changes/rules/field-same-cardinality::proto2::42","title":"FIELD_SAME_CARDINALITY","section":"Proto2","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#proto2","headings":["Proto2"],"excerpt":"Proto2 **Required**: required string id = 1; **Optional**: optional string email = 2; **Repeated**: repeated string tags = 3;","content":"Proto2 **Required**: required string id = 1; **Optional**: optional string email = 2; **Repeated**: repeated string tags = 3;"},{"id":"cli/breaking-changes/rules/field-same-cardinality::breaking::43","title":"FIELD_SAME_CARDINALITY","section":"Матрица Breaking изменений","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#breaking","headings":["Матрица Breaking изменений"],"excerpt":"Матрица Breaking изменений From To Result ------ ---- -------- Required Optional ❌ BREAKING Optional Required ❌ BREAKING Implicit Explicit ❌ BREAKING Explicit Implicit ❌ BREAKING Single Repeated ❌ BREAKING Repeated Singl","content":"Матрица Breaking изменений 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":"Правило проверяет, что типы полей сообщений (message fields) не изменяются. Смена типа поля ломает совместимость по wire‑формату и сгенерированный код: бинарное представление и ожидания клиентского кода различаются для р","content":"Правило проверяет, что типы полей сообщений (message fields) не изменяются. Смена типа поля ломает совместимость по wire‑формату и сгенерированный код: бинарное представление и ожидания клиентского кода различаются для разных типов."},{"id":"cli/breaking-changes/rules/field-same-type::breaking::1","title":"FIELD_SAME_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-same-type::breaking::2","title":"FIELD_SAME_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/field-same-type::breaking::3","title":"FIELD_SAME_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message Product { string name = 1; int32 price = 2; bool available = 3; } ```","content":"Плохой (Breaking) message Product { string name = 1; int32 price = 2; bool available = 3; } ```"},{"id":"cli/breaking-changes/rules/field-same-type::breaking::4","title":"FIELD_SAME_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-same-type::breaking::5","title":"FIELD_SAME_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/field-same-type::breaking::6","title":"FIELD_SAME_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message Product { string name = 1; string price = 2; // [!code --] Changed from int32 to string (изменён тип) bool available = 3; } ```","content":"Плохой (Breaking) 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::top::7","title":"FIELD_SAME_TYPE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/field-same-type","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры **Несовместимые изменения типов:** ```proto // Before message Order { string id = 1; int64 timestamp = 2; repeated string tags = 3; OrderStatus status = 4; }","content":"Дополнительные примеры **Несовместимые изменения типов:** ```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::top::8","title":"FIELD_SAME_TYPE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/field-same-type","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры // After - ВСЁ BREAKING message Order { int32 id = 1; // string -> int32: BREAKING string timestamp = 2; // int64 -> string: BREAKING string tags = 3; // repeated -> singular: BREAKING int32 status","content":"Дополнительные примеры // After - ВСЁ BREAKING 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::top::9","title":"FIELD_SAME_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо смены типа — добавьте новое поле:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо смены типа — добавьте новое поле:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-same-type::top::10","title":"FIELD_SAME_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/field-same-type::top::11","title":"FIELD_SAME_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message Product { string name = 1; int32 price = 2 [deprecated = true]; // [!code focus] // Старое поле помечено deprecated bool available = 3; string price_formatted = 4; // [!code focus] // Новое п","content":"Хороший (Безопасный) message Product { string name = 1; int32 price = 2 [deprecated = true]; // [!code focus] // Старое поле помечено deprecated bool available = 3; string price_formatted = 4; // [!code focus] // Новое поле со строковым представлением } ```"},{"id":"cli/breaking-changes/rules/field-same-type::top::12","title":"FIELD_SAME_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Или создайте новую версию сообщения:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Или создайте новую версию сообщения:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-same-type::top::13","title":"FIELD_SAME_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v2; // [!code focus] // Новая версия package","content":"Хороший (Безопасный) package myapi.v2; // [!code focus] // Новая версия package"},{"id":"cli/breaking-changes/rules/field-same-type::top::14","title":"FIELD_SAME_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message Product { string name = 1; string price = 2; // [!code focus] // В v2 уже string bool available = 3; } ```","content":"Хороший (Безопасный) message Product { string name = 1; string price = 2; // [!code focus] // В v2 уже string bool available = 3; } ```"},{"id":"cli/breaking-changes/rules/field-same-type::top::15","title":"FIELD_SAME_TYPE","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/field-same-type","headings":["Влияние"],"excerpt":"Влияние **Wire Format:** Старые бинарные данные не десериализуются корректно **Generated Code:** Меняются типы в сгенерированном коде — клиенты не компилируются **Runtime Errors:** Ошибки парсинга при несовпадении ожидае","content":"Влияние **Wire Format:** Старые бинарные данные не десериализуются корректно **Generated Code:** Меняются типы в сгенерированном коде — клиенты не компилируются **Runtime Errors:** Ошибки парсинга при несовпадении ожидаемого типа **Data Corruption:** Неверная интерпретация байтов данных"},{"id":"cli/breaking-changes/rules/field-same-type::top::16","title":"FIELD_SAME_TYPE","section":"Типовые проблемы изменений типов","path":"/docs/guide/cli/breaking-changes/rules/field-same-type","headings":["Типовые проблемы изменений типов"],"excerpt":"Типовые проблемы изменений типов","content":"Типовые проблемы изменений типов"},{"id":"cli/breaking-changes/rules/field-same-type::top::17","title":"FIELD_SAME_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/field-same-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Добавьте новое поле** с нужным типом:","content":"Стратегия миграции **Добавьте новое поле** с нужным типом:"},{"id":"cli/breaking-changes/rules/field-same-type::top::18","title":"FIELD_SAME_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/field-same-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Период двойной записи** — заполняйте оба поля для совместимости","content":"Стратегия миграции **Период двойной записи** — заполняйте оба поля для совместимости"},{"id":"cli/breaking-changes/rules/field-same-type::top::19","title":"FIELD_SAME_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/field-same-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Мигрируйте клиентов** на новое поле постепенно","content":"Стратегия миграции **Мигрируйте клиентов** на новое поле постепенно"},{"id":"cli/breaking-changes/rules/field-same-type::top::20","title":"FIELD_SAME_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/field-same-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Удалите старое поле** в следующей major‑версии:","content":"Стратегия миграции **Удалите старое поле** в следующей major‑версии:"},{"id":"cli/breaking-changes/rules/field-same-type::wire::21","title":"FIELD_SAME_TYPE","section":"Безопасные изменения (Теоретически wire‑совместимые)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type#wire","headings":["Безопасные изменения (Теоретически wire‑совместимые)"],"excerpt":"Безопасные изменения (Теоретически wire‑совместимые) Примечание: EasyP сейчас считает ЛЮБУЮ смену типа breaking. Однако технически некоторые случаи совместимы:","content":"Безопасные изменения (Теоретически wire‑совместимые) Примечание: EasyP сейчас считает ЛЮБУЮ смену типа breaking. Однако технически некоторые случаи совместимы:"},{"id":"cli/breaking-changes/rules/field-same-type::wire::22","title":"FIELD_SAME_TYPE","section":"Безопасные изменения (Теоретически wire‑совместимые)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type#wire","headings":["Безопасные изменения (Теоретически wire‑совместимые)"],"excerpt":"Безопасные изменения (Теоретически wire‑совместимые) int32 ↔ uint32 (одно кодирование) int64 ↔ uint64 (одно кодирование) string → bytes (если все строки валидный UTF‑8)","content":"Безопасные изменения (Теоретически wire‑совместимые) int32 ↔ uint32 (одно кодирование) int64 ↔ uint64 (одно кодирование) string → bytes (если все строки валидный UTF‑8)"},{"id":"cli/breaking-changes/rules/field-same-type::wire::23","title":"FIELD_SAME_TYPE","section":"Безопасные изменения (Теоретически wire‑совместимые)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type#wire","headings":["Безопасные изменения (Теоретически wire‑совместимые)"],"excerpt":"Безопасные изменения (Теоретически wire‑совместимые) Эти исключения могут получить отдельную обработку в будущих версиях EasyP с более гибкими уровнями строгости.","content":"Безопасные изменения (Теоретически wire‑совместимые) Эти исключения могут получить отдельную обработку в будущих версиях EasyP с более гибкими уровнями строгости."},{"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":"Это правило проверяет, что ни одна инструкция import не была удалена из proto‑файла. Удаление import ломает совместимость по wire‑формату и сгенерированный код: типы из импортируемых файлов могли использоваться в текущем","content":"Это правило проверяет, что ни одна инструкция import не была удалена из proto‑файла. Удаление import ломает совместимость по wire‑формату и сгенерированный код: типы из импортируемых файлов могли использоваться в текущем файле, и их удаление делает эти типы недоступными."},{"id":"cli/breaking-changes/rules/import-no-delete::breaking::1","title":"IMPORT_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/import-no-delete::breaking::2","title":"IMPORT_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/import-no-delete::breaking::3","title":"IMPORT_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) import \"google/protobuf/timestamp.proto\"; import \"google/protobuf/duration.proto\"; import \"common/user.proto\"; import \"common/address.proto\";","content":"Плохой (Breaking) 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::breaking::4","title":"IMPORT_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) 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":"Плохой (Breaking) 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::breaking::5","title":"IMPORT_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/import-no-delete::breaking::6","title":"IMPORT_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/import-no-delete::breaking::7","title":"IMPORT_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) import \"google/protobuf/timestamp.proto\"; // import \"google/protobuf/duration.proto\"; // [!code --] Удалён import — BREAKING // import \"common/user.proto\"; // [!code --] Удалён import — BREAKING // impo","content":"Плохой (Breaking) import \"google/protobuf/timestamp.proto\"; // import \"google/protobuf/duration.proto\"; // [!code --] Удалён import — BREAKING // import \"common/user.proto\"; // [!code --] Удалён import — BREAKING // import \"common/address.proto\"; // [!code --] Удалён import — BREAKING"},{"id":"cli/breaking-changes/rules/import-no-delete::breaking::8","title":"IMPORT_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message Order { string id = 1; google.protobuf.Timestamp created_at = 2; google.protobuf.Duration processing_time = 3; // ERROR: Duration недоступен common.User customer = 4; // ERROR: User недоступен c","content":"Плохой (Breaking) message Order { string id = 1; google.protobuf.Timestamp created_at = 2; google.protobuf.Duration processing_time = 3; // ERROR: Duration недоступен common.User customer = 4; // ERROR: User недоступен common.Address shipping_address = 5; // ERROR: Address недоступен } ```"},{"id":"cli/breaking-changes/rules/import-no-delete::top::9","title":"IMPORT_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры **Сервис ломается при удалённых import:** ```proto // Before import \"google/api/annotations.proto\"; import \"google/protobuf/empty.proto\"; import \"common/auth.proto\";","content":"Дополнительные примеры **Сервис ломается при удалённых import:** ```proto // Before import \"google/api/annotations.proto\"; import \"google/protobuf/empty.proto\"; import \"common/auth.proto\";"},{"id":"cli/breaking-changes/rules/import-no-delete::top::10","title":"IMPORT_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры service OrderService { rpc GetOrder(GetOrderRequest) returns (Order) { option (google.api.http) = { get: \"/v1/orders/{id}\" }; } rpc DeleteOrder(common.AuthRequest) returns (google.protobuf.Empty); ","content":"Дополнительные примеры 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::top::11","title":"IMPORT_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры // After - BREAKING CHANGES! // import \"google/api/annotations.proto\"; // BREAKING: deleted // import \"google/protobuf/empty.proto\"; // BREAKING: deleted // import \"common/auth.proto\"; // BREAKING:","content":"Дополнительные примеры // 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::top::12","title":"IMPORT_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры service OrderService { rpc GetOrder(GetOrderRequest) returns (Order) { option (google.api.http) = { // ERROR: annotations недоступен get: \"/v1/orders/{id}\" }; } rpc DeleteOrder(common.AuthRequest) ","content":"Дополнительные примеры service OrderService { rpc GetOrder(GetOrderRequest) returns (Order) { option (google.api.http) = { // ERROR: annotations недоступен get: \"/v1/orders/{id}\" }; } rpc DeleteOrder(common.AuthRequest) returns (google.protobuf.Empty); // ERROR: типы недоступны } ```"},{"id":"cli/breaking-changes/rules/import-no-delete::top::13","title":"IMPORT_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо удаления оставьте неиспользуемые import:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо удаления оставьте неиспользуемые import:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/import-no-delete::top::14","title":"IMPORT_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/import-no-delete::top::15","title":"IMPORT_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) import \"google/protobuf/timestamp.proto\"; import \"google/protobuf/duration.proto\"; // [!code focus] // Оставляем даже если не используется import \"common/user.proto\"; // [!code focus] import \"common/","content":"Хороший (Безопасный) import \"google/protobuf/timestamp.proto\"; import \"google/protobuf/duration.proto\"; // [!code focus] // Оставляем даже если не используется import \"common/user.proto\"; // [!code focus] import \"common/address.proto\"; // [!code focus]"},{"id":"cli/breaking-changes/rules/import-no-delete::top::16","title":"IMPORT_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message Order { string id = 1; google.protobuf.Timestamp created_at = 2; // Поля, использовавшие Duration/User/Address, удалены — import оставлены } ```","content":"Хороший (Безопасный) message Order { string id = 1; google.protobuf.Timestamp created_at = 2; // Поля, использовавшие Duration/User/Address, удалены — import оставлены } ```"},{"id":"cli/breaking-changes/rules/import-no-delete::top::17","title":"IMPORT_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Или добавьте новые типы, сохранив старые import:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Или добавьте новые типы, сохранив старые import:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/import-no-delete::top::18","title":"IMPORT_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/import-no-delete::top::19","title":"IMPORT_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) import \"google/protobuf/timestamp.proto\"; import \"google/protobuf/duration.proto\"; // [!code focus] import \"common/user.proto\"; // [!code focus] import \"common/address.proto\"; // [!code focus] import","content":"Хороший (Безопасный) import \"google/protobuf/timestamp.proto\"; import \"google/protobuf/duration.proto\"; // [!code focus] import \"common/user.proto\"; // [!code focus] import \"common/address.proto\"; // [!code focus] import \"common/v2/user.proto\"; // [!code focus] // Новый import"},{"id":"cli/breaking-changes/rules/import-no-delete::top::20","title":"IMPORT_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message Order { string id = 1; google.protobuf.Timestamp created_at = 2; google.protobuf.Duration processing_time = 3 [deprecated = true]; // [!code focus] common.User customer = 4 [deprecated = true","content":"Хороший (Безопасный) message Order { string id = 1; google.protobuf.Timestamp created_at = 2; google.protobuf.Duration processing_time = 3 [deprecated = true]; // [!code focus] common.User customer = 4 [deprecated = true]; // [!code focus] common.Address shipping_address = 5 [deprecated = true]; // [!code focus] int32 processing_seconds = 6; common.v2.UserProfile customer_v2 = 7; string shipping_address_text = 8; } ```"},{"id":"cli/breaking-changes/rules/import-no-delete::top::21","title":"IMPORT_NO_DELETE","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Влияние"],"excerpt":"Влияние **Generated Code:** Типы пропадают → ошибка компиляции **Wire Format:** Сообщения с удалёнными типами не десериализуются **Field References:** Поля с этими типами становятся невалидны **Service Definitions:** RPC","content":"Влияние **Generated Code:** Типы пропадают → ошибка компиляции **Wire Format:** Сообщения с удалёнными типами не десериализуются **Field References:** Поля с этими типами становятся невалидны **Service Definitions:** RPC с типами из удалённых файлов ломаются **Options Usage:** Пользовательские опции из импортов недоступны"},{"id":"cli/breaking-changes/rules/import-no-delete::top::22","title":"IMPORT_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Код клиента ломается:**","content":"Реальный пример **Код клиента ломается:**"},{"id":"cli/breaking-changes/rules/import-no-delete::top::23","title":"IMPORT_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Серверная логика ломается:**","content":"Реальный пример **Серверная логика ломается:**"},{"id":"cli/breaking-changes/rules/import-no-delete::top::24","title":"IMPORT_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Компиляция proto ломается:**","content":"Реальный пример **Компиляция proto ломается:**"},{"id":"cli/breaking-changes/rules/import-no-delete::top::25","title":"IMPORT_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции Сохраняйте import даже если типы более не используются: Добавляйте новые import рядом со старыми: Депрецируйте поля со старыми типами постепенно: Сервер: поддерживайте оба варианта: Удаляйте import тол","content":"Стратегия миграции Сохраняйте import даже если типы более не используются: Добавляйте новые import рядом со старыми: Депрецируйте поля со старыми типами постепенно: Сервер: поддерживайте оба варианта: Удаляйте import только в следующей major‑версии после полной миграции."},{"id":"cli/breaking-changes/rules/import-no-delete::top::26","title":"IMPORT_NO_DELETE","section":"Замена зависимости","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Замена зависимости"],"excerpt":"Замена зависимости ```proto import \"old/user.proto\"; // Старый import \"new/user.proto\"; // Новый","content":"Замена зависимости ```proto import \"old/user.proto\"; // Старый import \"new/user.proto\"; // Новый"},{"id":"cli/breaking-changes/rules/import-no-delete::top::27","title":"IMPORT_NO_DELETE","section":"Замена зависимости","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Замена зависимости"],"excerpt":"Замена зависимости message Order { old.User customer = 4 [deprecated = true]; new.UserProfile customer_v2 = 5; } ```","content":"Замена зависимости message Order { old.User customer = 4 [deprecated = true]; new.UserProfile customer_v2 = 5; } ```"},{"id":"cli/breaking-changes/rules/import-no-delete::top::28","title":"IMPORT_NO_DELETE","section":"Удаление функционала","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Удаление функционала"],"excerpt":"Удаление функционала ```proto import \"feature/analytics.proto\"; // Оставить даже если поле удалено","content":"Удаление функционала ```proto import \"feature/analytics.proto\"; // Оставить даже если поле удалено"},{"id":"cli/breaking-changes/rules/import-no-delete::top::29","title":"IMPORT_NO_DELETE","section":"Удаление функционала","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Удаление функционала"],"excerpt":"Удаление функционала message Order { string id = 1; // feature.AnalyticsData analytics = 2; // Поле удалено, import остаётся } ```","content":"Удаление функционала message Order { string id = 1; // feature.AnalyticsData analytics = 2; // Поле удалено, import остаётся } ```"},{"id":"cli/breaking-changes/rules/import-no-delete::protobuf::30","title":"IMPORT_NO_DELETE","section":"Миграция версии protobuf","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#protobuf","headings":["Миграция версии protobuf"],"excerpt":"Миграция версии protobuf ```proto import \"google/protobuf/timestamp.proto\"; import \"google/protobuf/duration.proto\";","content":"Миграция версии protobuf ```proto import \"google/protobuf/timestamp.proto\"; import \"google/protobuf/duration.proto\";"},{"id":"cli/breaking-changes/rules/import-no-delete::protobuf::31","title":"IMPORT_NO_DELETE","section":"Миграция версии protobuf","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#protobuf","headings":["Миграция версии protobuf"],"excerpt":"Миграция версии protobuf message Event { google.protobuf.Timestamp timestamp = 1; int64 timestamp_millis = 2; } ```","content":"Миграция версии protobuf message Event { google.protobuf.Timestamp timestamp = 1; int64 timestamp_millis = 2; } ```"},{"id":"cli/breaking-changes/rules/import-no-delete::top::32","title":"IMPORT_NO_DELETE","section":"Упрощение сложных зависимостей","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Упрощение сложных зависимостей"],"excerpt":"Упрощение сложных зависимостей ```proto import \"complex/config.proto\";","content":"Упрощение сложных зависимостей ```proto import \"complex/config.proto\";"},{"id":"cli/breaking-changes/rules/import-no-delete::top::33","title":"IMPORT_NO_DELETE","section":"Упрощение сложных зависимостей","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":["Упрощение сложных зависимостей"],"excerpt":"Упрощение сложных зависимостей message Settings { complex.ConfigData config = 1 [deprecated = true]; string config_json = 2; } ```","content":"Упрощение сложных зависимостей message Settings { complex.ConfigData config = 1 [deprecated = true]; string config_json = 2; } ```"},{"id":"cli/breaking-changes/rules/import-no-delete::import-vs::34","title":"IMPORT_NO_DELETE","section":"Удаление import vs использование поля","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#import-vs","headings":["Удаление import vs использование поля"],"excerpt":"Удаление import vs использование поля","content":"Удаление import vs использование поля"},{"id":"cli/breaking-changes/rules/import-no-delete::import::35","title":"IMPORT_NO_DELETE","section":"Аудит import","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#import","headings":["Аудит import"],"excerpt":"Аудит import (Даже если не найдено — не удаляем.)","content":"Аудит 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":"Это правило проверяет, что ни одно сообщение (message) не было удалено из proto‑файлов. Удаление message ломает совместимость по wire‑формату и сгенерированный код: в существующих данных могут присутствовать экземпляры у","content":"Это правило проверяет, что ни одно сообщение (message) не было удалено из proto‑файлов. Удаление message ломает совместимость по wire‑формату и сгенерированный код: в существующих данных могут присутствовать экземпляры удалённого типа, а клиентский код зависит от сгенерированных структур и классов."},{"id":"cli/breaking-changes/rules/message-no-delete::breaking::1","title":"MESSAGE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/message-no-delete::breaking::2","title":"MESSAGE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/message-no-delete::breaking::3","title":"MESSAGE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message User { string name = 1; string email = 2; Address address = 3; }","content":"Плохой (Breaking) message User { string name = 1; string email = 2; Address address = 3; }"},{"id":"cli/breaking-changes/rules/message-no-delete::breaking::4","title":"MESSAGE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message Address { // [!code --] string street = 1; // [!code --] string city = 2; // [!code --] string country = 3; // [!code --] } // [!code --]","content":"Плохой (Breaking) message Address { // [!code --] string street = 1; // [!code --] string city = 2; // [!code --] string country = 3; // [!code --] } // [!code --]"},{"id":"cli/breaking-changes/rules/message-no-delete::breaking::5","title":"MESSAGE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message Order { string id = 1; User user = 2; } ```","content":"Плохой (Breaking) message Order { string id = 1; User user = 2; } ```"},{"id":"cli/breaking-changes/rules/message-no-delete::breaking::6","title":"MESSAGE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/message-no-delete::breaking::7","title":"MESSAGE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/message-no-delete::breaking::8","title":"MESSAGE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message User { string name = 1; string email = 2; Address address = 3; // ERROR: Address больше не существует }","content":"Плохой (Breaking) message User { string name = 1; string email = 2; Address address = 3; // ERROR: Address больше не существует }"},{"id":"cli/breaking-changes/rules/message-no-delete::breaking::9","title":"MESSAGE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) // Address удалён — BREAKING CHANGE!","content":"Плохой (Breaking) // Address удалён — BREAKING CHANGE!"},{"id":"cli/breaking-changes/rules/message-no-delete::breaking::10","title":"MESSAGE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message Order { string id = 1; User user = 2; } ```","content":"Плохой (Breaking) message Order { string id = 1; User user = 2; } ```"},{"id":"cli/breaking-changes/rules/message-no-delete::top::11","title":"MESSAGE_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры **Удаление вложенного сообщения:**","content":"Дополнительные примеры **Удаление вложенного сообщения:**"},{"id":"cli/breaking-changes/rules/message-no-delete::top::12","title":"MESSAGE_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры ```proto // Before message User { string name = 1; Profile profile = 2; message Profile { // [!code --] string bio = 1; // [!code --] string avatar_url = 2; // [!code --] } // [!code --] }","content":"Дополнительные примеры ```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::top::13","title":"MESSAGE_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры // After - BREAKING CHANGE! message User { string name = 1; Profile profile = 2; // ERROR: Profile удалён // Вложенное сообщение Profile удалено } ```","content":"Дополнительные примеры // After - BREAKING CHANGE! message User { string name = 1; Profile profile = 2; // ERROR: Profile удалён // Вложенное сообщение Profile удалено } ```"},{"id":"cli/breaking-changes/rules/message-no-delete::top::14","title":"MESSAGE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо удаления — пометить как deprecated:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо удаления — пометить как deprecated:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/message-no-delete::top::15","title":"MESSAGE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/message-no-delete::top::16","title":"MESSAGE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message User { string name = 1; string email = 2; Address address = 3 [deprecated = true]; // [!code focus] }","content":"Хороший (Безопасный) message User { string name = 1; string email = 2; Address address = 3 [deprecated = true]; // [!code focus] }"},{"id":"cli/breaking-changes/rules/message-no-delete::top::17","title":"MESSAGE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message Address { option deprecated = true; // [!code focus] string street = 1; string city = 2; string country = 3; }","content":"Хороший (Безопасный) message Address { option deprecated = true; // [!code focus] string street = 1; string city = 2; string country = 3; }"},{"id":"cli/breaking-changes/rules/message-no-delete::top::18","title":"MESSAGE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message Order { string id = 1; User user = 2; } ```","content":"Хороший (Безопасный) message Order { string id = 1; User user = 2; } ```"},{"id":"cli/breaking-changes/rules/message-no-delete::top::19","title":"MESSAGE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Или заменить новой версией сообщения:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Или заменить новой версией сообщения:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/message-no-delete::top::20","title":"MESSAGE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/message-no-delete::top::21","title":"MESSAGE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message User { string name = 1; string email = 2; Address address = 3 [deprecated = true]; // [!code focus] // Старое поле AddressV2 address_v2 = 4; // [!code focus] // Новая улучшенная структура }","content":"Хороший (Безопасный) message User { string name = 1; string email = 2; Address address = 3 [deprecated = true]; // [!code focus] // Старое поле AddressV2 address_v2 = 4; // [!code focus] // Новая улучшенная структура }"},{"id":"cli/breaking-changes/rules/message-no-delete::top::22","title":"MESSAGE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message Address { option deprecated = true; // [!code focus] string street = 1; string city = 2; string country = 3; }","content":"Хороший (Безопасный) message Address { option deprecated = true; // [!code focus] string street = 1; string city = 2; string country = 3; }"},{"id":"cli/breaking-changes/rules/message-no-delete::top::23","title":"MESSAGE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) 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 c","content":"Хороший (Безопасный) 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::top::24","title":"MESSAGE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message Order { string id = 1; User user = 2; } ```","content":"Хороший (Безопасный) message Order { string id = 1; User user = 2; } ```"},{"id":"cli/breaking-changes/rules/message-no-delete::top::25","title":"MESSAGE_NO_DELETE","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Влияние"],"excerpt":"Влияние **Wire Format:** Старые данные с удалённым сообщением не десериализуются **Generated Code:** Классы/структуры удаляются — компиляция клиента ломается **Field References:** Поля, использующие удалённый тип, станов","content":"Влияние **Wire Format:** Старые данные с удалённым сообщением не десериализуются **Generated Code:** Классы/структуры удаляются — компиляция клиента ломается **Field References:** Поля, использующие удалённый тип, становятся невалидны **Nested Dependencies:** Все сообщения, ссылающиеся на удалённый тип, ломаются"},{"id":"cli/breaking-changes/rules/message-no-delete::top::26","title":"MESSAGE_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Код клиента ломается:** ```go // Before user := &myapi.User{ Name: \"John Doe\", Email: \"john@example.com\", Address: &myapi.Address{ // ERROR после удаления Street: \"123 Main St\", City: \"New York\", Countr","content":"Реальный пример **Код клиента ломается:** ```go // Before user := &myapi.User{ Name: \"John Doe\", Email: \"john@example.com\", Address: &myapi.Address{ // ERROR после удаления Street: \"123 Main St\", City: \"New York\", Country: \"USA\", }, }"},{"id":"cli/breaking-changes/rules/message-no-delete::top::27","title":"MESSAGE_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример // undefined: myapi.Address ```","content":"Реальный пример // undefined: myapi.Address ```"},{"id":"cli/breaking-changes/rules/message-no-delete::top::28","title":"MESSAGE_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Старые данные становятся нечитаемыми:**","content":"Реальный пример **Старые данные становятся нечитаемыми:**"},{"id":"cli/breaking-changes/rules/message-no-delete::top::29","title":"MESSAGE_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Пометить как deprecated:** **Пометить поля, использующие его:** **Добавить замену при необходимости:** **Удалить в следующей major‑версии после периода миграции**","content":"Стратегия миграции **Пометить как deprecated:** **Пометить поля, использующие его:** **Добавить замену при необходимости:** **Удалить в следующей major‑версии после периода миграции**"},{"id":"cli/breaking-changes/rules/message-no-delete::top::30","title":"MESSAGE_NO_DELETE","section":"Рефакторинг структуры","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Рефакторинг структуры"],"excerpt":"Рефакторинг структуры ```proto message UserInfo { option deprecated = true; string name = 1; string email = 2; }","content":"Рефакторинг структуры ```proto message UserInfo { option deprecated = true; string name = 1; string email = 2; }"},{"id":"cli/breaking-changes/rules/message-no-delete::top::31","title":"MESSAGE_NO_DELETE","section":"Рефакторинг структуры","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Рефакторинг структуры"],"excerpt":"Рефакторинг структуры message UserProfile { string full_name = 1; string email_address = 2; string phone = 3; } ```","content":"Рефакторинг структуры message UserProfile { string full_name = 1; string email_address = 2; string phone = 3; } ```"},{"id":"cli/breaking-changes/rules/message-no-delete::top::32","title":"MESSAGE_NO_DELETE","section":"Удаление «неиспользуемых» сообщений","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Удаление «неиспользуемых» сообщений"],"excerpt":"Удаление «неиспользуемых» сообщений","content":"Удаление «неиспользуемых» сообщений"},{"id":"cli/breaking-changes/rules/message-no-delete::top::33","title":"MESSAGE_NO_DELETE","section":"Миграция версии","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Миграция версии"],"excerpt":"Миграция версии ```proto package myapi.v2;","content":"Миграция версии ```proto package myapi.v2;"},{"id":"cli/breaking-changes/rules/message-no-delete::top::34","title":"MESSAGE_NO_DELETE","section":"Миграция версии","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":["Миграция версии"],"excerpt":"Миграция версии message User { // Новая структура без устаревших ссылок } ```","content":"Миграция версии message User { // Новая структура без устаревших ссылок } ```"},{"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":"Правило проверяет, что ни одно поле внутри oneof группы не было удалено. Удаление поля из oneof ломает совместимость по wire‑формату и сгенерированный код: в сохранённых данных может присутствовать выбранный вариант, а к","content":"Правило проверяет, что ни одно поле внутри oneof группы не было удалено. Удаление поля из oneof ломает совместимость по wire‑формату и сгенерированный код: в сохранённых данных может присутствовать выбранный вариант, а клиентский код опирается на сгенерированные типы‑обёртки и методы доступа."},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::breaking::1","title":"ONEOF_FIELD_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::breaking::2","title":"ONEOF_FIELD_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::breaking::3","title":"ONEOF_FIELD_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message LoginRequest { string username = 1; oneof credentials { string password = 2; string api_key = 3; string oauth_token = 4; string certificate = 5; } }","content":"Плохой (Breaking) 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::breaking::4","title":"ONEOF_FIELD_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message SearchQuery { oneof filter { string text = 1; int32 user_id = 2; string category = 3; DateRange date_range = 4; } } ```","content":"Плохой (Breaking) 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::breaking::5","title":"ONEOF_FIELD_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::breaking::6","title":"ONEOF_FIELD_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::breaking::7","title":"ONEOF_FIELD_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message LoginRequest { string username = 1; oneof credentials { string password = 2; string api_key = 3; // string oauth_token = 4; // [!code --] Удалено поле oneof — BREAKING! // string certificate = 5","content":"Плохой (Breaking) message LoginRequest { string username = 1; oneof credentials { string password = 2; string api_key = 3; // string oauth_token = 4; // [!code --] Удалено поле oneof — BREAKING! // string certificate = 5; // [!code --] Удалено поле oneof — BREAKING! } }"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::breaking::8","title":"ONEOF_FIELD_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message SearchQuery { oneof filter { string text = 1; int32 user_id = 2; // string category = 3; // [!code --] Удалено поле oneof — BREAKING! // DateRange date_range = 4; // [!code --] Удалено поле oneo","content":"Плохой (Breaking) message SearchQuery { oneof filter { string text = 1; int32 user_id = 2; // string category = 3; // [!code --] Удалено поле oneof — BREAKING! // DateRange date_range = 4; // [!code --] Удалено поле oneof — BREAKING! } } ```"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::9","title":"ONEOF_FIELD_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры **Удаление вложенных oneof полей:** ```proto // Before message PaymentRequest { string order_id = 1; oneof payment_method { CreditCardPayment credit_card = 2; BankTransferPayment bank_transfer = 3;","content":"Дополнительные примеры **Удаление вложенных oneof полей:** ```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::top::10","title":"ONEOF_FIELD_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры // After - BREAKING CHANGES! message PaymentRequest { string order_id = 1; oneof payment_method { CreditCardPayment credit_card = 2; BankTransferPayment bank_transfer = 3; // CryptoPayment crypto =","content":"Дополнительные примеры // 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::top::11","title":"ONEOF_FIELD_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо удаления — пометить поля deprecated:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо удаления — пометить поля deprecated:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::12","title":"ONEOF_FIELD_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::13","title":"ONEOF_FIELD_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) 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 [deprecate","content":"Хороший (Безопасный) 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::top::14","title":"ONEOF_FIELD_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) 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":"Хороший (Безопасный) 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::top::15","title":"ONEOF_FIELD_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Или добавить новые поля, оставив старые:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Или добавить новые поля, оставив старые:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::16","title":"ONEOF_FIELD_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::17","title":"ONEOF_FIELD_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message LoginRequest { string username = 1; oneof credentials { string password = 2; string api_key = 3; string oauth_token = 4 [deprecated = true]; // [!code focus] // Старое поле string certificate","content":"Хороший (Безопасный) 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] OAuthCredentials oauth_v2 = 6; // [!code focus] // Новый структурированный вариант CertificateCredentials cert_v2 = 7; // [!code focus] } } ```"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::18","title":"ONEOF_FIELD_NO_DELETE","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Влияние"],"excerpt":"Влияние **Wire Format:** Данные, содержащие удалённый вариант, не десериализуются корректно **Generated Code:** Удаляются типы‑обёртки и accessor методы — компиляция клиентов ломается **Type Safety:** Логика switch по ти","content":"Влияние **Wire Format:** Данные, содержащие удалённый вариант, не десериализуются корректно **Generated Code:** Удаляются типы‑обёртки и accessor методы — компиляция клиентов ломается **Type Safety:** Логика switch по типам oneof разваливается **Business Logic:** Код, ожидающий конкретный вариант, перестаёт работать"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::19","title":"ONEOF_FIELD_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Код клиента ломается:** ```go // Before loginReq := &myapi.LoginRequest{ Username: \"user123\", }","content":"Реальный пример **Код клиента ломается:** ```go // Before loginReq := &myapi.LoginRequest{ Username: \"user123\", }"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::20","title":"ONEOF_FIELD_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример loginReq.Credentials = &myapi.LoginRequest_OauthToken{ OauthToken: \"token123\", // ERROR после удаления поля }","content":"Реальный пример loginReq.Credentials = &myapi.LoginRequest_OauthToken{ OauthToken: \"token123\", // ERROR после удаления поля }"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::21","title":"ONEOF_FIELD_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример switch cred := loginReq.Credentials.(type) { case *myapi.LoginRequest_Password: return authenticatePassword(cred.Password) case *myapi.LoginRequest_OauthToken: // ERROR: тип удалён return authenticateOAut","content":"Реальный пример switch cred := loginReq.Credentials.(type) { case *myapi.LoginRequest_Password: return authenticatePassword(cred.Password) case *myapi.LoginRequest_OauthToken: // ERROR: тип удалён return authenticateOAuth(cred.OauthToken) case *myapi.LoginRequest_Certificate: // ERROR: тип удалён return authenticateCert(cred.Certificate) default: return errors.New(\"unsupported credential type\") } // undefined: myapi.LoginRequest_OauthToken // undefined: myapi.LoginRequest_Certificate ```"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::22","title":"ONEOF_FIELD_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Серверная логика ломается:**","content":"Реальный пример **Серверная логика ломается:**"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::23","title":"ONEOF_FIELD_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Старые данные становятся нечитаемыми:**","content":"Реальный пример **Старые данные становятся нечитаемыми:**"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::24","title":"ONEOF_FIELD_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Депрецируйте сначала:** **Добавьте новые структурированные поля:** **Сервер: поддерживайте оба варианта:** **Мигрируйте клиентов на новое поле:** **Зарезервируйте номера удалённых полей в следующей m","content":"Стратегия миграции **Депрецируйте сначала:** **Добавьте новые структурированные поля:** **Сервер: поддерживайте оба варианта:** **Мигрируйте клиентов на новое поле:** **Зарезервируйте номера удалённых полей в следующей major‑версии:**"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::25","title":"ONEOF_FIELD_NO_DELETE","section":"Удаление неподдерживаемых методов аутентификации","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Удаление неподдерживаемых методов аутентификации"],"excerpt":"Удаление неподдерживаемых методов аутентификации","content":"Удаление неподдерживаемых методов аутентификации"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::26","title":"ONEOF_FIELD_NO_DELETE","section":"Изменения бизнес‑логики платежей","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Изменения бизнес‑логики платежей"],"excerpt":"Изменения бизнес‑логики платежей","content":"Изменения бизнес‑логики платежей"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::oneof-field-deletion-vs::27","title":"ONEOF_FIELD_NO_DELETE","section":"OneOf Field Deletion vs обычное удаление","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#oneof-field-deletion-vs","headings":["OneOf Field Deletion vs обычное удаление"],"excerpt":"OneOf Field Deletion vs обычное удаление","content":"OneOf Field Deletion vs обычное удаление"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::28","title":"ONEOF_FIELD_NO_DELETE","section":"Отличия от удаления обычного поля","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Отличия от удаления обычного поля"],"excerpt":"Отличия от удаления обычного поля ```proto message User { string name = 1; // string email = 2; // BREAKING: обычное поле }","content":"Отличия от удаления обычного поля ```proto message User { string name = 1; // string email = 2; // BREAKING: обычное поле }"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::29","title":"ONEOF_FIELD_NO_DELETE","section":"Отличия от удаления обычного поля","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Отличия от удаления обычного поля"],"excerpt":"Отличия от удаления обычного поля message User { oneof contact { string email = 1; // string phone = 2; // BREAKING: поле в oneof } } ```","content":"Отличия от удаления обычного поля message User { oneof contact { string email = 1; // string phone = 2; // BREAKING: поле в oneof } } ```"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::30","title":"ONEOF_FIELD_NO_DELETE","section":"Влияние на сгенерированный код","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Влияние на сгенерированный код"],"excerpt":"Влияние на сгенерированный код ```go // Обычное поле: удаляется простой геттер // user.GetEmail()","content":"Влияние на сгенерированный код ```go // Обычное поле: удаляется простой геттер // user.GetEmail()"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::31","title":"ONEOF_FIELD_NO_DELETE","section":"Влияние на сгенерированный код","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":["Влияние на сгенерированный код"],"excerpt":"Влияние на сгенерированный код // Поле в oneof: пропадает тип-обёртка, кейсы switch ломаются // *LoginRequest_OauthToken ```","content":"Влияние на сгенерированный код // Поле в oneof: пропадает тип-обёртка, кейсы switch ломаются // *LoginRequest_OauthToken ```"},{"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":"Это правило проверяет, что тип поля внутри oneof НЕ меняется. Смена типа любого варианта oneof — несовместимое (breaking) изменение: существующие данные сериализованы с прежним типом, а клиентский код ожидает конкретные ","content":"Это правило проверяет, что тип поля внутри oneof НЕ меняется. Смена типа любого варианта oneof — несовместимое (breaking) изменение: существующие данные сериализованы с прежним типом, а клиентский код ожидает конкретные типы-обёртки и методы доступа, сгенерированные для каждого варианта."},{"id":"cli/breaking-changes/rules/oneof-field-same-type::breaking::1","title":"ONEOF_FIELD_SAME_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::breaking::2","title":"ONEOF_FIELD_SAME_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::breaking::3","title":"ONEOF_FIELD_SAME_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message SearchRequest { string query = 1; oneof filter { string category = 2; int32 user_id = 3; bool is_premium = 4; DateRange date_range = 5; } }","content":"Плохой (Breaking) 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::breaking::4","title":"ONEOF_FIELD_SAME_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message NotificationSettings { oneof delivery { string email = 1; int64 phone_number = 2; WebhookConfig webhook = 3; } } ```","content":"Плохой (Breaking) message NotificationSettings { oneof delivery { string email = 1; int64 phone_number = 2; WebhookConfig webhook = 3; } } ```"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::breaking::5","title":"ONEOF_FIELD_SAME_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::breaking::6","title":"ONEOF_FIELD_SAME_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::breaking::7","title":"ONEOF_FIELD_SAME_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message SearchRequest { string query = 1; oneof filter { int32 category = 2; // [!code --] Было string -> стало int32 (BREAKING) string user_id = 3; // [!code --] Было int32 -> стало string (BREAKING) s","content":"Плохой (Breaking) message SearchRequest { string query = 1; oneof filter { int32 category = 2; // [!code --] Было string -> стало int32 (BREAKING) string user_id = 3; // [!code --] Было int32 -> стало string (BREAKING) string is_premium = 4; // [!code --] Было bool -> стало string (BREAKING) string date_range = 5; // [!code --] Было DateRange -> стало string (BREAKING) } }"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::breaking::8","title":"ONEOF_FIELD_SAME_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message NotificationSettings { oneof delivery { EmailConfig email = 1; // [!code --] Было string -> стало EmailConfig (BREAKING) string phone_number = 2; // [!code --] Было int64 -> стало string (BREAKI","content":"Плохой (Breaking) message NotificationSettings { oneof delivery { EmailConfig email = 1; // [!code --] Было string -> стало EmailConfig (BREAKING) string phone_number = 2; // [!code --] Было int64 -> стало string (BREAKING) string webhook = 3; // [!code --] Было WebhookConfig -> стало string (BREAKING) } } ```"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::9","title":"ONEOF_FIELD_SAME_TYPE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры **Комплексные изменения типов:** ```proto // Before message PaymentRequest { oneof payment_info { CreditCardInfo credit_card = 1; BankAccountInfo bank_account = 2; string paypal_email = 3; CryptoWa","content":"Дополнительные примеры **Комплексные изменения типов:** ```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::top::10","title":"ONEOF_FIELD_SAME_TYPE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры // After - ВСЁ BREAKING message PaymentRequest { oneof payment_info { string credit_card = 1; // CreditCardInfo -> string PayPalInfo bank_account = 2; // BankAccountInfo -> PayPalInfo PayPalInfo pa","content":"Дополнительные примеры // After - ВСЁ BREAKING message PaymentRequest { oneof payment_info { string credit_card = 1; // CreditCardInfo -> string PayPalInfo bank_account = 2; // BankAccountInfo -> PayPalInfo PayPalInfo paypal_email = 3; // string -> PayPalInfo string crypto = 4; // CryptoWalletInfo -> string } } ```"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::11","title":"ONEOF_FIELD_SAME_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо смены типа — добавьте новое поле в тот же oneof:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо смены типа — добавьте новое поле в тот же oneof:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::12","title":"ONEOF_FIELD_SAME_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::13","title":"ONEOF_FIELD_SAME_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message SearchRequest { string query = 1; oneof filter { string category = 2 [deprecated = true]; // Старый тип int32 user_id = 3 [deprecated = true]; bool is_premium = 4 [deprecated = true]; DateRan","content":"Хороший (Безопасный) message SearchRequest { string query = 1; oneof filter { string category = 2 [deprecated = true]; // Старый тип int32 user_id = 3 [deprecated = true]; bool is_premium = 4 [deprecated = true]; DateRange date_range = 5 [deprecated = true]; int32 category_id = 6; // Новая версия string user_identifier = 7; string premium_status = 8; string date_filter = 9; } } ```"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::14","title":"ONEOF_FIELD_SAME_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Или создайте новый oneof:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Или создайте новый oneof:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::15","title":"ONEOF_FIELD_SAME_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::16","title":"ONEOF_FIELD_SAME_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message SearchRequest { string query = 1; oneof filter { option deprecated = true; string category = 2 [deprecated = true]; int32 user_id = 3 [deprecated = true]; bool is_premium = 4 [deprecated = tr","content":"Хороший (Безопасный) message SearchRequest { string query = 1; oneof filter { option deprecated = true; string category = 2 [deprecated = true]; int32 user_id = 3 [deprecated = true]; bool is_premium = 4 [deprecated = true]; DateRange date_range = 5 [deprecated = true]; } oneof filter_v2 { int32 category_id = 6; string user_identifier = 7; PremiumFilter premium_filter = 8; TimeFilter time_filter = 9; } } ```"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::17","title":"ONEOF_FIELD_SAME_TYPE","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Влияние"],"excerpt":"Влияние **Wire Format:** Старые бинарные данные не читаются корректно **Generated Code:** Меняются типы-обёртки, код клиента не компилируется **Type Safety:** switch по варианту oneof ломается **Runtime Errors:** Ошибки ","content":"Влияние **Wire Format:** Старые бинарные данные не читаются корректно **Generated Code:** Меняются типы-обёртки, код клиента не компилируется **Type Safety:** switch по варианту oneof ломается **Runtime Errors:** Ошибки десериализации и логики при несовпадении типов"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::18","title":"ONEOF_FIELD_SAME_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Реальный пример"],"excerpt":"Реальный пример **Ломается клиентский код:** ```go // Before searchReq := &myapi.SearchRequest{ Query: \"golang jobs\", }","content":"Реальный пример **Ломается клиентский код:** ```go // Before searchReq := &myapi.SearchRequest{ Query: \"golang jobs\", }"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::19","title":"ONEOF_FIELD_SAME_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Реальный пример"],"excerpt":"Реальный пример // Устанавливаем вариант oneof searchReq.Filter = &myapi.SearchRequest_Category{ Category: \"engineering\", }","content":"Реальный пример // Устанавливаем вариант oneof searchReq.Filter = &myapi.SearchRequest_Category{ Category: \"engineering\", }"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::20","title":"ONEOF_FIELD_SAME_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Реальный пример"],"excerpt":"Реальный пример // Обработка вариантов switch filter := searchReq.Filter.(type) { case *myapi.SearchRequest_Category: return searchByCategory(filter.Category) case *myapi.SearchRequest_UserId: return searchByUserId(filte","content":"Реальный пример // Обработка вариантов switch filter := searchReq.Filter.(type) { case *myapi.SearchRequest_Category: return searchByCategory(filter.Category) case *myapi.SearchRequest_UserId: return searchByUserId(filter.UserId) default: return errors.New(\"unsupported filter\") }"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::21","title":"ONEOF_FIELD_SAME_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Реальный пример"],"excerpt":"Реальный пример // After — тип Category стал int32 searchReq.Filter = &myapi.SearchRequest_Category{ Category: \"engineering\", // ERROR }","content":"Реальный пример // After — тип Category стал int32 searchReq.Filter = &myapi.SearchRequest_Category{ Category: \"engineering\", // ERROR }"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::22","title":"ONEOF_FIELD_SAME_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Реальный пример"],"excerpt":"Реальный пример switch filter := searchReq.Filter.(type) { case *myapi.SearchRequest_Category: return searchByCategory(filter.Category) // ERROR case *myapi.SearchRequest_UserId: return searchByUserId(filter.UserId) // E","content":"Реальный пример switch filter := searchReq.Filter.(type) { case *myapi.SearchRequest_Category: return searchByCategory(filter.Category) // ERROR case *myapi.SearchRequest_UserId: return searchByUserId(filter.UserId) // ERROR: UserId теперь string } ```"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::23","title":"ONEOF_FIELD_SAME_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Реальный пример"],"excerpt":"Реальный пример **Ломается серверная логика:** ```go // Before func handleSearchFilter(req *SearchRequest) (*SearchResult, error) { switch filter := req.Filter.(type) { case *SearchRequest_Category: return searchDatabase","content":"Реальный пример **Ломается серверная логика:** ```go // Before func handleSearchFilter(req *SearchRequest) (*SearchResult, error) { switch filter := req.Filter.(type) { case *SearchRequest_Category: return searchDatabase(\"category\", filter.Category), nil case *SearchRequest_UserId: return searchDatabase(\"user_id\", strconv.Itoa(int(filter.UserId))), nil default: return nil, errors.New(\"no filter specified\") } }"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::24","title":"ONEOF_FIELD_SAME_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Реальный пример"],"excerpt":"Реальный пример // After — несовпадения типов func handleSearchFilter(req *SearchRequest) (*SearchResult, error) { switch filter := req.Filter.(type) { case *SearchRequest_Category: // filter.Category теперь int32, а код","content":"Реальный пример // After — несовпадения типов func handleSearchFilter(req *SearchRequest) (*SearchResult, error) { switch filter := req.Filter.(type) { case *SearchRequest_Category: // filter.Category теперь int32, а код ожидал string return searchDatabase(\"category\", filter.Category), nil // ERROR case *SearchRequest_UserId: userIdStr := filter.UserId // string вместо int32 userId, _ := strconv.Atoi(userIdStr) return searchDatabase(\"user_id\", strconv.Itoa(userId)), nil } } ```"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::25","title":"ONEOF_FIELD_SAME_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Реальный пример"],"excerpt":"Реальный пример **Порча данных:**","content":"Реальный пример **Порча данных:**"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::26","title":"ONEOF_FIELD_SAME_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции Добавьте новое поле: Сервер поддерживает оба: Клиенты переходят на category_id. Скрипты миграции преобразуют старые данные. В следующей major‑версии:","content":"Стратегия миграции Добавьте новое поле: Сервер поддерживает оба: Клиенты переходят на category_id. Скрипты миграции преобразуют старые данные. В следующей major‑версии:"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::27","title":"ONEOF_FIELD_SAME_TYPE","section":"Переход к структурированным типам","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Переход к структурированным типам"],"excerpt":"Переход к структурированным типам","content":"Переход к структурированным типам"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::28","title":"ONEOF_FIELD_SAME_TYPE","section":"Матрица совместимости","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Матрица совместимости"],"excerpt":"Матрица совместимости From Type To Type Результат ----------- --------- ----------- string int32/int64 ❌ BREAKING int32 string ❌ BREAKING bool string ❌ BREAKING message string ❌ BREAKING string message ❌ BREAKING enum in","content":"Матрица совместимости From Type To Type Результат ----------- --------- ----------- 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::top::29","title":"ONEOF_FIELD_SAME_TYPE","section":"Влияние на сгенерированный код","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Влияние на сгенерированный код"],"excerpt":"Влияние на сгенерированный код","content":"Влияние на сгенерированный код"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::30","title":"ONEOF_FIELD_SAME_TYPE","section":"Валидация","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":["Валидация"],"excerpt":"Валидация **После (сломано):**","content":"Валидация **После (сломано):**"},{"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":"Это правило проверяет, что ни один oneof блок не был удалён из сообщений. Удаление oneof ломает совместимость по wire‑формату и сгенерированный код: существующие данные могут содержать ранее выбранный вариант, а клиентск","content":"Это правило проверяет, что ни один oneof блок не был удалён из сообщений. Удаление oneof ломает совместимость по wire‑формату и сгенерированный код: существующие данные могут содержать ранее выбранный вариант, а клиентский код зависит от типов-обёрток и методов доступа, генерируемых для oneof."},{"id":"cli/breaking-changes/rules/oneof-no-delete::breaking::1","title":"ONEOF_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-no-delete::breaking::2","title":"ONEOF_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/oneof-no-delete::breaking::3","title":"ONEOF_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message LoginRequest { string username = 1; oneof credentials { string password = 2; string api_key = 3; string oauth_token = 4; } }","content":"Плохой (Breaking) 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::breaking::4","title":"ONEOF_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message PaymentMethod { // [!code --] oneof method { // [!code --] CreditCard credit_card = 1; // [!code --] BankAccount bank_account = 2; // [!code --] PayPal paypal = 3; // [!code --] } // [!code --] ","content":"Плохой (Breaking) 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::breaking::5","title":"ONEOF_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message Order { string id = 1; PaymentMethod payment = 2; } ```","content":"Плохой (Breaking) message Order { string id = 1; PaymentMethod payment = 2; } ```"},{"id":"cli/breaking-changes/rules/oneof-no-delete::breaking::6","title":"ONEOF_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-no-delete::breaking::7","title":"ONEOF_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/oneof-no-delete::breaking::8","title":"ONEOF_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message LoginRequest { string username = 1; // credentials oneof удалён — BREAKING CHANGE! string password = 2; // Теперь обычные поля string api_key = 3; // Потеряна взаимная исключаемость string oauth","content":"Плохой (Breaking) message LoginRequest { string username = 1; // credentials oneof удалён — BREAKING CHANGE! string password = 2; // Теперь обычные поля string api_key = 3; // Потеряна взаимная исключаемость string oauth_token = 4; }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::breaking::9","title":"ONEOF_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message PaymentMethod { // method oneof удалён — BREAKING CHANGE! CreditCard credit_card = 1; // Теперь можно установить все поля одновременно BankAccount bank_account = 2; PayPal paypal = 3; }","content":"Плохой (Breaking) message PaymentMethod { // method oneof удалён — BREAKING CHANGE! CreditCard credit_card = 1; // Теперь можно установить все поля одновременно BankAccount bank_account = 2; PayPal paypal = 3; }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::breaking::10","title":"ONEOF_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message Order { string id = 1; PaymentMethod payment = 2; } ```","content":"Плохой (Breaking) message Order { string id = 1; PaymentMethod payment = 2; } ```"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::11","title":"ONEOF_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры **Удаление вложенного oneof:** ```proto // Before message UserProfile { string name = 1; message ContactInfo { oneof contact_method { // [!code --] string email = 1; // [!code --] string phone = 2;","content":"Дополнительные примеры **Удаление вложенного oneof:** ```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::top::12","title":"ONEOF_NO_DELETE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры // After - BREAKING CHANGE! message UserProfile { string name = 1; message ContactInfo { // contact_method oneof удалён string email = 1; // Больше не эксклюзивно string phone = 2; // Можно задать ","content":"Дополнительные примеры // After - BREAKING CHANGE! message UserProfile { string name = 1; message ContactInfo { // contact_method oneof удалён string email = 1; // Больше не эксклюзивно string phone = 2; // Можно задать всё сразу string slack_id = 3; } ContactInfo contact = 2; } ```"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::13","title":"ONEOF_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо удаления — депрецируйте oneof:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо удаления — депрецируйте oneof:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::14","title":"ONEOF_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::15","title":"ONEOF_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message LoginRequest { string username = 1; oneof credentials { option deprecated = true; // [!code focus] string password = 2 [deprecated = true]; // [!code focus] string api_key = 3 [deprecated = t","content":"Хороший (Безопасный) 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::top::16","title":"ONEOF_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message PaymentMethod { oneof method { option deprecated = true; // [!code focus] CreditCard credit_card = 1 [deprecated = true]; // [!code focus] BankAccount bank_account = 2 [deprecated = true]; //","content":"Хороший (Безопасный) 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::top::17","title":"ONEOF_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Или заменить новой структурой:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Или заменить новой структурой:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::18","title":"ONEOF_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::19","title":"ONEOF_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message LoginRequest { string username = 1; oneof credentials { option deprecated = true; // [!code focus] // Старый oneof string password = 2 [deprecated = true]; // [!code focus] string api_key = 3","content":"Хороший (Безопасный) message LoginRequest { string username = 1; oneof credentials { option deprecated = true; // [!code focus] // Старый 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] // Новый дизайн 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::top::20","title":"ONEOF_NO_DELETE","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Влияние"],"excerpt":"Влияние **Wire Format:** Теряются семантика взаимной исключаемости — больше одного поля может быть установлено **Generated Code:** Удаляются типы-обёртки и accessor методы — код клиента не компилируется **Business Logic:","content":"Влияние **Wire Format:** Теряются семантика взаимной исключаемости — больше одного поля может быть установлено **Generated Code:** Удаляются типы-обёртки и accessor методы — код клиента не компилируется **Business Logic:** Нарушаются инварианты «только один из» **Validation:** Логика проверок должна быть переписана вручную"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::21","title":"ONEOF_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Код клиента ломается:** ```go // Before - oneOf даёт взаимную исключаемость loginReq := &myapi.LoginRequest{ Username: \"user123\", }","content":"Реальный пример **Код клиента ломается:** ```go // Before - oneOf даёт взаимную исключаемость loginReq := &myapi.LoginRequest{ Username: \"user123\", }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::22","title":"ONEOF_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример loginReq.Credentials = &myapi.LoginRequest_Password{ Password: \"secret123\", }","content":"Реальный пример loginReq.Credentials = &myapi.LoginRequest_Password{ Password: \"secret123\", }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::23","title":"ONEOF_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример switch cred := loginReq.Credentials.(type) { case *myapi.LoginRequest_Password: // ERROR после удаления return authenticatePassword(cred.Password) case *myapi.LoginRequest_ApiKey: // ERROR после удаления ","content":"Реальный пример switch cred := loginReq.Credentials.(type) { case *myapi.LoginRequest_Password: // ERROR после удаления return authenticatePassword(cred.Password) case *myapi.LoginRequest_ApiKey: // ERROR после удаления return authenticateApiKey(cred.ApiKey) default: return errors.New(\"no credentials provided\") }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::24","title":"ONEOF_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример // Compilation errors: // undefined: myapi.LoginRequest_Password // undefined field: loginReq.Credentials ```","content":"Реальный пример // Compilation errors: // undefined: myapi.LoginRequest_Password // undefined field: loginReq.Credentials ```"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::25","title":"ONEOF_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Валидация на сервере ломается:** ```go // Before func validateLoginRequest(req *LoginRequest) error { if req.Credentials == nil { return errors.New(\"credentials required\") } switch req.Credentials.(type","content":"Реальный пример **Валидация на сервере ломается:** ```go // Before func validateLoginRequest(req *LoginRequest) error { if req.Credentials == nil { return errors.New(\"credentials required\") } 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::top::26","title":"ONEOF_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример // After func validateLoginRequest(req *LoginRequest) error { credCount := 0 if req.Password != \"\" { credCount++ } if req.ApiKey != \"\" { credCount++ } if req.OauthToken != \"\" { credCount++ }","content":"Реальный пример // After func validateLoginRequest(req *LoginRequest) error { credCount := 0 if req.Password != \"\" { credCount++ } if req.ApiKey != \"\" { credCount++ } if req.OauthToken != \"\" { credCount++ }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::27","title":"ONEOF_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример if credCount == 0 { return errors.New(\"no credentials provided\") } if credCount > 1 { return errors.New(\"multiple credentials provided\") }","content":"Реальный пример if credCount == 0 { return errors.New(\"no credentials provided\") } if credCount > 1 { return errors.New(\"multiple credentials provided\") }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::28","title":"ONEOF_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример if req.Password != \"\" { return validatePassword(req.Password) } // Дополнительные проверки вручную... return nil } ```","content":"Реальный пример if req.Password != \"\" { return validatePassword(req.Password) } // Дополнительные проверки вручную... return nil } ```"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::29","title":"ONEOF_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример **Проблемы бизнес‑логики:** ```go // Before payment := &PaymentMethod{ Method: &PaymentMethod_CreditCard{ CreditCard: &CreditCard{Number: \"1234\"}, }, }","content":"Реальный пример **Проблемы бизнес‑логики:** ```go // Before payment := &PaymentMethod{ Method: &PaymentMethod_CreditCard{ CreditCard: &CreditCard{Number: \"1234\"}, }, }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::30","title":"ONEOF_NO_DELETE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Реальный пример"],"excerpt":"Реальный пример // After — можно задать несколько способов сразу payment := &PaymentMethod{ CreditCard: &CreditCard{Number: \"1234\"}, BankAccount: &BankAccount{Number: \"5678\"}, // Ломает бизнес-логику } ```","content":"Реальный пример // After — можно задать несколько способов сразу payment := &PaymentMethod{ CreditCard: &CreditCard{Number: \"1234\"}, BankAccount: &BankAccount{Number: \"5678\"}, // Ломает бизнес-логику } ```"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::31","title":"ONEOF_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Депрецируйте старый oneof и его поля:**","content":"Стратегия миграции **Депрецируйте старый oneof и его поля:**"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::32","title":"ONEOF_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Создайте новый блок при необходимости:**","content":"Стратегия миграции **Создайте новый блок при необходимости:**"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::33","title":"ONEOF_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Сервер: поддерживайте оба до миграции:**","content":"Стратегия миграции **Сервер: поддерживайте оба до миграции:**"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::34","title":"ONEOF_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Клиенты: переходите на новый oneof:**","content":"Стратегия миграции **Клиенты: переходите на новый oneof:**"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::35","title":"ONEOF_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Удалите старый oneof** в следующей major‑версии.","content":"Стратегия миграции **Удалите старый oneof** в следующей major‑версии."},{"id":"cli/breaking-changes/rules/oneof-no-delete::oneof::36","title":"ONEOF_NO_DELETE","section":"Замена oneof обычными полями","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#oneof","headings":["Замена oneof обычными полями"],"excerpt":"Замена oneof обычными полями ```proto message SearchRequest { // НЕЛЬЗЯ просто убрать oneof — ломает семантику string text_query = 1; // BREAKING int32 user_id = 2; // BREAKING string category = 3; // BREAKING }","content":"Замена oneof обычными полями ```proto message SearchRequest { // НЕЛЬЗЯ просто убрать oneof — ломает семантику string text_query = 1; // BREAKING int32 user_id = 2; // BREAKING string category = 3; // BREAKING }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::oneof::37","title":"ONEOF_NO_DELETE","section":"Замена oneof обычными полями","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#oneof","headings":["Замена oneof обычными полями"],"excerpt":"Замена oneof обычными полями message SearchRequest { oneof query { option deprecated = true; string text_query = 1 [deprecated = true]; int32 user_id = 2 [deprecated = true]; string category = 3 [deprecated = true]; } st","content":"Замена oneof обычными полями message SearchRequest { oneof query { option deprecated = true; string text_query = 1 [deprecated = true]; int32 user_id = 2 [deprecated = true]; string category = 3 [deprecated = true]; } string search_text = 4; repeated string filters = 5; } ```"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::38","title":"ONEOF_NO_DELETE","section":"Упрощение структуры сообщения","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Упрощение структуры сообщения"],"excerpt":"Упрощение структуры сообщения ```proto message NotificationSettings { string email = 1; // BREAKING: был в oneof string phone = 2; // BREAKING string webhook_url = 3; // BREAKING }","content":"Упрощение структуры сообщения ```proto message NotificationSettings { string email = 1; // BREAKING: был в oneof string phone = 2; // BREAKING string webhook_url = 3; // BREAKING }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::39","title":"ONEOF_NO_DELETE","section":"Упрощение структуры сообщения","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Упрощение структуры сообщения"],"excerpt":"Упрощение структуры сообщения message NotificationSettings { oneof delivery_method { EmailNotification email = 1; SmsNotification phone = 2; WebhookNotification webhook = 3; } } ```","content":"Упрощение структуры сообщения message NotificationSettings { oneof delivery_method { EmailNotification email = 1; SmsNotification phone = 2; WebhookNotification webhook = 3; } } ```"},{"id":"cli/breaking-changes/rules/oneof-no-delete::proto2-proto3::40","title":"ONEOF_NO_DELETE","section":"Миграция с proto2 на proto3","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#proto2-proto3","headings":["Миграция с proto2 на proto3"],"excerpt":"Миграция с proto2 на proto3 ```proto // proto2 message Request { optional string name = 1; oneof data { string text = 2; int32 number = 3; } }","content":"Миграция с proto2 на proto3 ```proto // proto2 message Request { optional string name = 1; oneof data { string text = 2; int32 number = 3; } }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::proto2-proto3::41","title":"ONEOF_NO_DELETE","section":"Миграция с proto2 на proto3","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#proto2-proto3","headings":["Миграция с proto2 на proto3"],"excerpt":"Миграция с proto2 на proto3 // proto3 — сохраняем oneof message Request { string name = 1; oneof data { string text = 2; int32 number = 3; } } ```","content":"Миграция с proto2 на proto3 // proto3 — сохраняем oneof message Request { string name = 1; oneof data { string text = 2; int32 number = 3; } } ```"},{"id":"cli/breaking-changes/rules/oneof-no-delete::oneof::42","title":"ONEOF_NO_DELETE","section":"Что даёт oneof","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#oneof","headings":["Что даёт oneof"],"excerpt":"Что даёт oneof Взаимная исключаемость Типобезопасность в коде Ясность намерения API («выбери один») Эффективная сериализация — кодируется только выбранный вариант","content":"Что даёт oneof Взаимная исключаемость Типобезопасность в коде Ясность намерения API («выбери один») Эффективная сериализация — кодируется только выбранный вариант"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::43","title":"ONEOF_NO_DELETE","section":"Что теряется при удалении","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Что теряется при удалении"],"excerpt":"Что теряется при удалении Инвариант «только один» Генерируемые wrapper-типы и методы Автоматическая валидация выбора Понятность контракта API","content":"Что теряется при удалении Инвариант «только один» Генерируемые wrapper-типы и методы Автоматическая валидация выбора Понятность контракта API"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::44","title":"ONEOF_NO_DELETE","section":"Влияние на код генерации","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Влияние на код генерации"],"excerpt":"Влияние на код генерации ```go // С oneof type LoginRequest struct { Username string Credentials isLoginRequest_Credentials }","content":"Влияние на код генерации ```go // С oneof type LoginRequest struct { Username string Credentials isLoginRequest_Credentials }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::45","title":"ONEOF_NO_DELETE","section":"Влияние на код генерации","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":["Влияние на код генерации"],"excerpt":"Влияние на код генерации // Без oneof type LoginRequest struct { Username string Password string ApiKey string OauthToken string // Возможны многозначные конфликтующие состояния } ```","content":"Влияние на код генерации // Без oneof type LoginRequest struct { Username string Password string ApiKey string 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":"Правило проверяет, что ни один RPC‑метод не был удалён из service. Удаление RPC ломает сгенерированный код и клиентские приложения, которые этот метод вызывают.","content":"Правило проверяет, что ни один RPC‑метод не был удалён из service. Удаление RPC ломает сгенерированный код и клиентские приложения, которые этот метод вызывают."},{"id":"cli/breaking-changes/rules/rpc-no-delete::breaking::1","title":"RPC_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/rpc-no-delete::breaking::2","title":"RPC_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/rpc-no-delete::breaking::3","title":"RPC_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); rpc DeleteUser(DeleteUserRequest) returns (DeleteUserResponse","content":"Плохой (Breaking) 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::breaking::4","title":"RPC_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/rpc-no-delete::breaking::5","title":"RPC_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/rpc-no-delete::breaking::6","title":"RPC_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); // DeleteUser RPC удалён — BREAKING CHANGE! } ```","content":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); // DeleteUser RPC удалён — BREAKING CHANGE! } ```"},{"id":"cli/breaking-changes/rules/rpc-no-delete::top::7","title":"RPC_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо удаления — пометить RPC deprecated:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо удаления — пометить RPC deprecated:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/rpc-no-delete::top::8","title":"RPC_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/rpc-no-delete::top::9","title":"RPC_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); rpc DeleteUser(DeleteUserRequest) returns (DeleteUserRespo","content":"Хороший (Безопасный) 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::top::10","title":"RPC_NO_DELETE","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete","headings":["Влияние"],"excerpt":"Влияние **Generated Code:** Stub/метод исчезает — клиенты не компилируются **Client Applications:** Существующие вызовы метода падают при сборке **Runtime:** gRPC клиенты теряют определение метода","content":"Влияние **Generated Code:** Stub/метод исчезает — клиенты не компилируются **Client Applications:** Существующие вызовы метода падают при сборке **Runtime:** gRPC клиенты теряют определение метода"},{"id":"cli/breaking-changes/rules/rpc-no-delete::top::11","title":"RPC_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Сначала деприкация:**","content":"Стратегия миграции **Сначала деприкация:**"},{"id":"cli/breaking-changes/rules/rpc-no-delete::top::12","title":"RPC_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Имплементация может возвращать ошибку**, указывая что метод устарел (например, INTERNAL / UNIMPLEMENTED)","content":"Стратегия миграции **Имплементация может возвращать ошибку**, указывая что метод устарел (например, INTERNAL / UNIMPLEMENTED)"},{"id":"cli/breaking-changes/rules/rpc-no-delete::top::13","title":"RPC_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Удалить в следующей major‑версии** после миграции всех клиентов","content":"Стратегия миграции **Удалить в следующей major‑версии** после миграции всех клиентов"},{"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":"Это правило проверяет, что RPC‑методы сохраняют прежний тип сообщения запроса (request message type). Изменение типа запроса RPC ломает совместимость по wire‑формату и сгенерированный код: клиенты ожидают конкретную стру","content":"Это правило проверяет, что RPC‑методы сохраняют прежний тип сообщения запроса (request message type). Изменение типа запроса RPC ломает совместимость по wire‑формату и сгенерированный код: клиенты ожидают конкретную структуру при вызове метода."},{"id":"cli/breaking-changes/rules/rpc-same-request-type::breaking::1","title":"RPC_SAME_REQUEST_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::breaking::2","title":"RPC_SAME_REQUEST_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::breaking::3","title":"RPC_SAME_REQUEST_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse); }","content":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse); }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::breaking::4","title":"RPC_SAME_REQUEST_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message GetUserRequest { string user_id = 1; }","content":"Плохой (Breaking) message GetUserRequest { string user_id = 1; }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::breaking::5","title":"RPC_SAME_REQUEST_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message UpdateUserRequest { string user_id = 1; string name = 2; string email = 3; } ```","content":"Плохой (Breaking) message UpdateUserRequest { string user_id = 1; string name = 2; string email = 3; } ```"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::breaking::6","title":"RPC_SAME_REQUEST_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::breaking::7","title":"RPC_SAME_REQUEST_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::breaking::8","title":"RPC_SAME_REQUEST_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequestV2) returns (GetUserResponse); // [!code --] Изменён тип запроса rpc UpdateUser(UserUpdateRequest) returns (UpdateUserResponse); // [!code --] Изменён тип","content":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequestV2) returns (GetUserResponse); // [!code --] Изменён тип запроса rpc UpdateUser(UserUpdateRequest) returns (UpdateUserResponse); // [!code --] Изменён тип запроса }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::breaking::9","title":"RPC_SAME_REQUEST_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message GetUserRequestV2 { // [!code --] Новый тип запроса string id = 1; bool include_profile = 2; }","content":"Плохой (Breaking) message GetUserRequestV2 { // [!code --] Новый тип запроса string id = 1; bool include_profile = 2; }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::breaking::10","title":"RPC_SAME_REQUEST_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message UserUpdateRequest { // [!code --] Новый тип запроса string id = 1; UserProfile profile = 2; } ```","content":"Плохой (Breaking) message UserUpdateRequest { // [!code --] Новый тип запроса string id = 1; UserProfile profile = 2; } ```"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::11","title":"RPC_SAME_REQUEST_TYPE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры **Смена типа из другого пакета:** ```proto // Before import \"common/user.proto\";","content":"Дополнительные примеры **Смена типа из другого пакета:** ```proto // Before import \"common/user.proto\";"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::12","title":"RPC_SAME_REQUEST_TYPE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры service UserService { rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); }","content":"Дополнительные примеры service UserService { rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::13","title":"RPC_SAME_REQUEST_TYPE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры // After - BREAKING CHANGE! import \"v2/user.proto\";","content":"Дополнительные примеры // After - BREAKING CHANGE! import \"v2/user.proto\";"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::14","title":"RPC_SAME_REQUEST_TYPE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры service UserService { rpc CreateUser(v2.CreateUserRequest) returns (CreateUserResponse); // Другой package } ```","content":"Дополнительные примеры service UserService { rpc CreateUser(v2.CreateUserRequest) returns (CreateUserResponse); // Другой package } ```"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::15","title":"RPC_SAME_REQUEST_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо изменения типа — версионируйте RPC:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо изменения типа — версионируйте RPC:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::16","title":"RPC_SAME_REQUEST_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::17","title":"RPC_SAME_REQUEST_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse) { option deprecated = true; // [!code focus] } rpc GetUserV2(GetUserRequestV2) returns (GetUserResponse); // [!code focus] ","content":"Хороший (Безопасный) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse) { option deprecated = true; // [!code focus] } rpc GetUserV2(GetUserRequestV2) returns (GetUserResponse); // [!code focus] // Новый метод rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse) { option deprecated = true; // [!code focus] } rpc UpdateUserV2(UserUpdateRequest) returns (UpdateUserResponse); // [!code focus] // Новый метод }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::18","title":"RPC_SAME_REQUEST_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) // Старые сообщения — для обратной совместимости message GetUserRequest { string user_id = 1; }","content":"Хороший (Безопасный) // Старые сообщения — для обратной совместимости message GetUserRequest { string user_id = 1; }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::19","title":"RPC_SAME_REQUEST_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) // Новая версия сообщения message GetUserRequestV2 { // [!code focus] string id = 1; // [!code focus] bool include_profile = 2; // [!code focus] } // [!code focus] ```","content":"Хороший (Безопасный) // Новая версия сообщения 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::top::20","title":"RPC_SAME_REQUEST_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Или создайте новую версию сервиса (package v2):** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Или создайте новую версию сервиса (package v2):** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::21","title":"RPC_SAME_REQUEST_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v2; // [!code focus]","content":"Хороший (Безопасный) package myapi.v2; // [!code focus]"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::22","title":"RPC_SAME_REQUEST_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); // [!code focus] rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse); // [!code focus] }","content":"Хороший (Безопасный) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); // [!code focus] rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse); // [!code focus] }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::23","title":"RPC_SAME_REQUEST_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message GetUserRequest { // [!code focus] string id = 1; // [!code focus] bool include_profile = 2; // [!code focus] } // [!code focus] ```","content":"Хороший (Безопасный) message GetUserRequest { // [!code focus] string id = 1; // [!code focus] bool include_profile = 2; // [!code focus] } // [!code focus] ```"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::24","title":"RPC_SAME_REQUEST_TYPE","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Влияние"],"excerpt":"Влияние **Wire Format:** Старые запросы клиентов не десериализуются новым сервером **Generated Code:** Сигнатуры методов в stubs меняются — компиляция клиентов падает **gRPC Calls:** Требуется использовать другую структу","content":"Влияние **Wire Format:** Старые запросы клиентов не десериализуются новым сервером **Generated Code:** Сигнатуры методов в stubs меняются — компиляция клиентов падает **gRPC Calls:** Требуется использовать другую структуру запроса **Runtime Errors:** Несоответствие типов вызывает ошибки выполнения"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::25","title":"RPC_SAME_REQUEST_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Реальный пример"],"excerpt":"Реальный пример **Код клиента ломается:** ```go // Before client := myapi.NewUserServiceClient(conn) resp, err := client.GetUser(ctx, &myapi.GetUserRequest{ UserId: \"user123\", })","content":"Реальный пример **Код клиента ломается:** ```go // Before client := myapi.NewUserServiceClient(conn) resp, err := client.GetUser(ctx, &myapi.GetUserRequest{ UserId: \"user123\", })"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::26","title":"RPC_SAME_REQUEST_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Реальный пример"],"excerpt":"Реальный пример // After (тип запроса изменён) client := myapi.NewUserServiceClient(conn) resp, err := client.GetUser(ctx, &myapi.GetUserRequest{ // ERROR: тип не найден UserId: \"user123\", // ERROR: поле не найдено })","content":"Реальный пример // After (тип запроса изменён) client := myapi.NewUserServiceClient(conn) resp, err := client.GetUser(ctx, &myapi.GetUserRequest{ // ERROR: тип не найден UserId: \"user123\", // ERROR: поле не найдено })"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::27","title":"RPC_SAME_REQUEST_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Реальный пример"],"excerpt":"Реальный пример // Новый корректный вызов: resp, err := client.GetUser(ctx, &myapi.GetUserRequestV2{ Id: \"user123\", IncludeProfile: true, }) ```","content":"Реальный пример // Новый корректный вызов: resp, err := client.GetUser(ctx, &myapi.GetUserRequestV2{ Id: \"user123\", IncludeProfile: true, }) ```"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::28","title":"RPC_SAME_REQUEST_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Реальный пример"],"excerpt":"Реальный пример **Серверная реализация ломается:** ```go // Before func (s *server) GetUser(ctx context.Context, req *GetUserRequest) (*GetUserResponse, error) { userID := req.UserId // ... }","content":"Реальный пример **Серверная реализация ломается:** ```go // Before func (s *server) GetUser(ctx context.Context, req *GetUserRequest) (*GetUserResponse, error) { userID := req.UserId // ... }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::29","title":"RPC_SAME_REQUEST_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Реальный пример"],"excerpt":"Реальный пример // After func (s *server) GetUser(ctx context.Context, req *GetUserRequestV2) (*GetUserResponse, error) { userID := req.Id include := req.IncludeProfile // ... новая логика } ```","content":"Реальный пример // After func (s *server) GetUser(ctx context.Context, req *GetUserRequestV2) (*GetUserResponse, error) { userID := req.Id include := req.IncludeProfile // ... новая логика } ```"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::30","title":"RPC_SAME_REQUEST_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Добавьте новый RPC с новым типом запроса:**","content":"Стратегия миграции **Добавьте новый RPC с новым типом запроса:**"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::31","title":"RPC_SAME_REQUEST_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Поддерживайте оба метода на сервере:** ```go func (s *server) GetUser(ctx context.Context, req *GetUserRequest) (*GetUserResponse, error) { return s.getUserInternal(req.UserId, false) }","content":"Стратегия миграции **Поддерживайте оба метода на сервере:** ```go func (s *server) GetUser(ctx context.Context, req *GetUserRequest) (*GetUserResponse, error) { return s.getUserInternal(req.UserId, false) }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::32","title":"RPC_SAME_REQUEST_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции func (s *server) GetUserV2(ctx context.Context, req *GetUserRequestV2) (*GetUserResponse, error) { return s.getUserInternal(req.Id, req.IncludeProfile) } ```","content":"Стратегия миграции func (s *server) GetUserV2(ctx context.Context, req *GetUserRequestV2) (*GetUserResponse, error) { return s.getUserInternal(req.Id, req.IncludeProfile) } ```"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::33","title":"RPC_SAME_REQUEST_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Мигрируйте клиентов на V2:**","content":"Стратегия миграции **Мигрируйте клиентов на V2:**"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::34","title":"RPC_SAME_REQUEST_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Удалите старый метод в следующей major‑версии:**","content":"Стратегия миграции **Удалите старый метод в следующей major‑версии:**"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::35","title":"RPC_SAME_REQUEST_TYPE","section":"Добавление обязательных полей","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Добавление обязательных полей"],"excerpt":"Добавление обязательных полей ```proto // ПЛОХО: меняем существующий запрос message GetUserRequest { string user_id = 1; bool include_deleted = 2; // BREAKING }","content":"Добавление обязательных полей ```proto // ПЛОХО: меняем существующий запрос message GetUserRequest { string user_id = 1; bool include_deleted = 2; // BREAKING }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::36","title":"RPC_SAME_REQUEST_TYPE","section":"Добавление обязательных полей","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Добавление обязательных полей"],"excerpt":"Добавление обязательных полей // Хорошо: новая версия message GetUserRequestV2 { string user_id = 1; bool include_deleted = 2; } ```","content":"Добавление обязательных полей // Хорошо: новая версия message GetUserRequestV2 { string user_id = 1; bool include_deleted = 2; } ```"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::37","title":"RPC_SAME_REQUEST_TYPE","section":"Реструктуризация данных запроса","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Реструктуризация данных запроса"],"excerpt":"Реструктуризация данных запроса ```proto // ПЛОХО: меняем структуру прямо message UpdateUserRequest { UserProfile profile = 1; // BREAKING }","content":"Реструктуризация данных запроса ```proto // ПЛОХО: меняем структуру прямо message UpdateUserRequest { UserProfile profile = 1; // BREAKING }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::38","title":"RPC_SAME_REQUEST_TYPE","section":"Реструктуризация данных запроса","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Реструктуризация данных запроса"],"excerpt":"Реструктуризация данных запроса // Хорошо: версионирование rpc UpdateUser(UpdateUserRequest) returns (...) { option deprecated = true; } rpc UpdateUserV2(UpdateUserRequestV2) returns (...); ```","content":"Реструктуризация данных запроса // Хорошо: версионирование rpc UpdateUser(UpdateUserRequest) returns (...) { option deprecated = true; } rpc UpdateUserV2(UpdateUserRequestV2) returns (...); ```"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::39","title":"RPC_SAME_REQUEST_TYPE","section":"Миграция пакета","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Миграция пакета"],"excerpt":"Миграция пакета ```proto // ПЛОХО: заменяем тип на пакет v2 прямо import \"v2/messages.proto\"; // BREAKING","content":"Миграция пакета ```proto // ПЛОХО: заменяем тип на пакет v2 прямо import \"v2/messages.proto\"; // BREAKING"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::40","title":"RPC_SAME_REQUEST_TYPE","section":"Миграция пакета","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":["Миграция пакета"],"excerpt":"Миграция пакета // Хорошо: добавляем новый RPC rpc OldMethod(v1.Request) returns (...) { option deprecated = true; } rpc NewMethod(v2.Request) returns (...); ```","content":"Миграция пакета // Хорошо: добавляем новый RPC 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":"Это правило проверяет, что RPC‑методы сохраняют тот же тип ответного сообщения (response message type). Изменение типа ответа RPC ломает совместимость по wire‑формату и сгенерированный код: клиенты ожидают конкретную стр","content":"Это правило проверяет, что RPC‑методы сохраняют тот же тип ответного сообщения (response message type). Изменение типа ответа RPC ломает совместимость по wire‑формату и сгенерированный код: клиенты ожидают конкретную структуру при получении ответа."},{"id":"cli/breaking-changes/rules/rpc-same-response-type::breaking::1","title":"RPC_SAME_RESPONSE_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::breaking::2","title":"RPC_SAME_RESPONSE_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::breaking::3","title":"RPC_SAME_RESPONSE_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse); }","content":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse); }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::breaking::4","title":"RPC_SAME_RESPONSE_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message GetUserResponse { string user_id = 1; string name = 2; string email = 3; }","content":"Плохой (Breaking) message GetUserResponse { string user_id = 1; string name = 2; string email = 3; }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::breaking::5","title":"RPC_SAME_RESPONSE_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message UpdateUserResponse { bool success = 1; string message = 2; } ```","content":"Плохой (Breaking) message UpdateUserResponse { bool success = 1; string message = 2; } ```"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::breaking::6","title":"RPC_SAME_RESPONSE_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::breaking::7","title":"RPC_SAME_RESPONSE_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::breaking::8","title":"RPC_SAME_RESPONSE_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponseV2); // [!code --] Изменён тип ответа rpc UpdateUser(UpdateUserRequest) returns (UserUpdateResponse); // [!code --] Изменён тип ","content":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponseV2); // [!code --] Изменён тип ответа rpc UpdateUser(UpdateUserRequest) returns (UserUpdateResponse); // [!code --] Изменён тип ответа }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::breaking::9","title":"RPC_SAME_RESPONSE_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message GetUserResponseV2 { // [!code --] Другой тип сообщения string id = 1; UserProfile profile = 2; repeated string permissions = 3; }","content":"Плохой (Breaking) message GetUserResponseV2 { // [!code --] Другой тип сообщения string id = 1; UserProfile profile = 2; repeated string permissions = 3; }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::breaking::10","title":"RPC_SAME_RESPONSE_TYPE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) message UserUpdateResponse { // [!code --] Другой тип сообщения UpdateResult result = 1; UserProfile updated_profile = 2; } ```","content":"Плохой (Breaking) message UserUpdateResponse { // [!code --] Другой тип сообщения UpdateResult result = 1; UserProfile updated_profile = 2; } ```"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::11","title":"RPC_SAME_RESPONSE_TYPE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры **Смена типа из другого пакета:** ```proto // Before import \"common/responses.proto\";","content":"Дополнительные примеры **Смена типа из другого пакета:** ```proto // Before import \"common/responses.proto\";"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::12","title":"RPC_SAME_RESPONSE_TYPE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры service UserService { rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); }","content":"Дополнительные примеры service UserService { rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::13","title":"RPC_SAME_RESPONSE_TYPE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры // After - BREAKING CHANGE! import \"v2/responses.proto\";","content":"Дополнительные примеры // After - BREAKING CHANGE! import \"v2/responses.proto\";"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::14","title":"RPC_SAME_RESPONSE_TYPE","section":"Дополнительные примеры","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Дополнительные примеры"],"excerpt":"Дополнительные примеры service UserService { rpc CreateUser(CreateUserRequest) returns (v2.CreateUserResponse); // Другой package } ```","content":"Дополнительные примеры service UserService { rpc CreateUser(CreateUserRequest) returns (v2.CreateUserResponse); // Другой package } ```"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::15","title":"RPC_SAME_RESPONSE_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо изменения типа — версионируйте RPC:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо изменения типа — версионируйте RPC:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::16","title":"RPC_SAME_RESPONSE_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::17","title":"RPC_SAME_RESPONSE_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse) { option deprecated = true; // [!code focus] } rpc GetUserV2(GetUserRequest) returns (GetUserResponseV2); // [!code focus] ","content":"Хороший (Безопасный) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse) { option deprecated = true; // [!code focus] } rpc GetUserV2(GetUserRequest) returns (GetUserResponseV2); // [!code focus] // Новый метод rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse) { option deprecated = true; // [!code focus] } rpc UpdateUserV2(UpdateUserRequest) returns (UserUpdateResponse); // [!code focus] // Новый метод }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::18","title":"RPC_SAME_RESPONSE_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) // Старые сообщения сохраняем для обратной совместимости message GetUserResponse { string user_id = 1; string name = 2; string email = 3; }","content":"Хороший (Безопасный) // Старые сообщения сохраняем для обратной совместимости message GetUserResponse { string user_id = 1; string name = 2; string email = 3; }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::19","title":"RPC_SAME_RESPONSE_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) // Новая расширенная версия message GetUserResponseV2 { // [!code focus] string id = 1; // [!code focus] UserProfile profile = 2; // [!code focus] repeated string permissions = 3; // [!code focus] } ","content":"Хороший (Безопасный) // Новая расширенная версия 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::top::20","title":"RPC_SAME_RESPONSE_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Или создайте новую версию сервиса (package v2):** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Или создайте новую версию сервиса (package v2):** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::21","title":"RPC_SAME_RESPONSE_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v2; // [!code focus]","content":"Хороший (Безопасный) package myapi.v2; // [!code focus]"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::22","title":"RPC_SAME_RESPONSE_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); // [!code focus] rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse); // [!code focus] }","content":"Хороший (Безопасный) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); // [!code focus] rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse); // [!code focus] }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::23","title":"RPC_SAME_RESPONSE_TYPE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) message GetUserResponse { // [!code focus] string id = 1; // [!code focus] UserProfile profile = 2; // [!code focus] repeated string permissions = 3; // [!code focus] } // [!code focus] ```","content":"Хороший (Безопасный) message GetUserResponse { // [!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::top::24","title":"RPC_SAME_RESPONSE_TYPE","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Влияние"],"excerpt":"Влияние **Wire Format:** Ответы сервера не десериализуются у старых клиентов **Generated Code:** Сигнатуры ожидают старый тип — компиляция падает **gRPC Calls:** Меняются типы в сгенерированных stub'ах **Runtime Errors:*","content":"Влияние **Wire Format:** Ответы сервера не десериализуются у старых клиентов **Generated Code:** Сигнатуры ожидают старый тип — компиляция падает **gRPC Calls:** Меняются типы в сгенерированных stub'ах **Runtime Errors:** Несоответствие типов ломает обработку ответа"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::25","title":"RPC_SAME_RESPONSE_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Реальный пример"],"excerpt":"Реальный пример **Код клиента ломается:** ```go // Before client := myapi.NewUserServiceClient(conn) resp, err := client.GetUser(ctx, &myapi.GetUserRequest{ UserId: \"user123\", }) if err != nil { return err }","content":"Реальный пример **Код клиента ломается:** ```go // Before 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::top::26","title":"RPC_SAME_RESPONSE_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Реальный пример"],"excerpt":"Реальный пример userID := resp.UserId name := resp.Name","content":"Реальный пример userID := resp.UserId name := resp.Name"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::27","title":"RPC_SAME_RESPONSE_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Реальный пример"],"excerpt":"Реальный пример // After (тип ответа изменён) client := myapi.NewUserServiceClient(conn) resp, err := client.GetUser(ctx, &myapi.GetUserRequest{ UserId: \"user123\", }) if err != nil { return err }","content":"Реальный пример // After (тип ответа изменён) 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::top::28","title":"RPC_SAME_RESPONSE_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Реальный пример"],"excerpt":"Реальный пример // Ошибки компиляции: userID := resp.UserId // ERROR name := resp.Name // ERROR","content":"Реальный пример // Ошибки компиляции: userID := resp.UserId // ERROR name := resp.Name // ERROR"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::29","title":"RPC_SAME_RESPONSE_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Реальный пример"],"excerpt":"Реальный пример // Новый способ: userID := resp.Id profile := resp.Profile permissions := resp.Permissions ```","content":"Реальный пример // Новый способ: userID := resp.Id profile := resp.Profile permissions := resp.Permissions ```"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::30","title":"RPC_SAME_RESPONSE_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Реальный пример"],"excerpt":"Реальный пример **Имплементация сервера также должна быть переписана:** ```go // Before func (s *server) GetUser(ctx context.Context, req *GetUserRequest) (*GetUserResponse, error) { return &GetUserResponse{ UserId: \"use","content":"Реальный пример **Имплементация сервера также должна быть переписана:** ```go // Before 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::top::31","title":"RPC_SAME_RESPONSE_TYPE","section":"Реальный пример","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Реальный пример"],"excerpt":"Реальный пример // After func (s *server) GetUser(ctx context.Context, req *GetUserRequest) (*GetUserResponseV2, error) { return &GetUserResponseV2{ Id: \"user123\", Profile: &UserProfile{ Name: \"John Doe\", Email: \"john@ex","content":"Реальный пример // After func (s *server) GetUser(ctx context.Context, req *GetUserRequest) (*GetUserResponseV2, error) { return &GetUserResponseV2{ Id: \"user123\", Profile: &UserProfile{ Name: \"John Doe\", Email: \"john@example.com\", }, Permissions: []string{\"read\"}, }, nil } ```"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::32","title":"RPC_SAME_RESPONSE_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Добавьте новый RPC c новым типом ответа:**","content":"Стратегия миграции **Добавьте новый RPC c новым типом ответа:**"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::33","title":"RPC_SAME_RESPONSE_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Поддерживайте оба на сервере:** ```go func (s *server) GetUser(ctx context.Context, req *GetUserRequest) (*GetUserResponse, error) { user := s.getUserInternal(req.UserId) return &GetUserResponse{ Use","content":"Стратегия миграции **Поддерживайте оба на сервере:** ```go func (s *server) GetUser(ctx context.Context, req *GetUserRequest) (*GetUserResponse, error) { user := s.getUserInternal(req.UserId) return &GetUserResponse{ UserId: user.ID, Name: user.Name, Email: user.Email, }, nil }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::34","title":"RPC_SAME_RESPONSE_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции func (s *server) GetUserV2(ctx context.Context, req *GetUserRequest) (*GetUserResponseV2, error) { user := s.getUserInternal(req.UserId) return &GetUserResponseV2{ Id: user.ID, Profile: &UserProfile{ N","content":"Стратегия миграции func (s *server) GetUserV2(ctx context.Context, req *GetUserRequest) (*GetUserResponseV2, error) { user := s.getUserInternal(req.UserId) return &GetUserResponseV2{ Id: user.ID, Profile: &UserProfile{ Name: user.Name, Email: user.Email, }, Permissions: user.Permissions, }, nil } ```"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::35","title":"RPC_SAME_RESPONSE_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Мигрируйте клиентов на новый RPC:**","content":"Стратегия миграции **Мигрируйте клиентов на новый RPC:**"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::36","title":"RPC_SAME_RESPONSE_TYPE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Удалите старый RPC** в следующей major‑версии:","content":"Стратегия миграции **Удалите старый RPC** в следующей major‑версии:"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::37","title":"RPC_SAME_RESPONSE_TYPE","section":"Добавление новых обязательных полей","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Добавление новых обязательных полей"],"excerpt":"Добавление новых обязательных полей ```proto // ПЛОХО: меняем существующий тип message GetUserResponse { string user_id = 1; string name = 2; UserProfile profile = 3; // BREAKING }","content":"Добавление новых обязательных полей ```proto // ПЛОХО: меняем существующий тип message GetUserResponse { string user_id = 1; string name = 2; UserProfile profile = 3; // BREAKING }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::38","title":"RPC_SAME_RESPONSE_TYPE","section":"Добавление новых обязательных полей","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Добавление новых обязательных полей"],"excerpt":"Добавление новых обязательных полей // Хорошо: новая версия message GetUserResponseV2 { string user_id = 1; string name = 2; UserProfile profile = 3; } ```","content":"Добавление новых обязательных полей // Хорошо: новая версия message GetUserResponseV2 { string user_id = 1; string name = 2; UserProfile profile = 3; } ```"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::39","title":"RPC_SAME_RESPONSE_TYPE","section":"Реструктуризация ответа","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Реструктуризация ответа"],"excerpt":"Реструктуризация ответа ```proto // ПЛОХО: меняем структуру прямо message UpdateUserResponse { UserDetails details = 1; // BREAKING }","content":"Реструктуризация ответа ```proto // ПЛОХО: меняем структуру прямо message UpdateUserResponse { UserDetails details = 1; // BREAKING }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::40","title":"RPC_SAME_RESPONSE_TYPE","section":"Реструктуризация ответа","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Реструктуризация ответа"],"excerpt":"Реструктуризация ответа // Хорошо: версионирование rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse) { option deprecated = true; } rpc UpdateUserV2(UpdateUserRequest) returns (UpdateUserResponseV2); ```","content":"Реструктуризация ответа // Хорошо: версионирование rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse) { option deprecated = true; } rpc UpdateUserV2(UpdateUserRequest) returns (UpdateUserResponseV2); ```"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::41","title":"RPC_SAME_RESPONSE_TYPE","section":"Изменение формата ошибок","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Изменение формата ошибок"],"excerpt":"Изменение формата ошибок ```proto // ПЛОХО: меняем формат напрямую message CreateUserResponse { ErrorDetails error = 1; // BREAKING }","content":"Изменение формата ошибок ```proto // ПЛОХО: меняем формат напрямую message CreateUserResponse { ErrorDetails error = 1; // BREAKING }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::42","title":"RPC_SAME_RESPONSE_TYPE","section":"Изменение формата ошибок","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Изменение формата ошибок"],"excerpt":"Изменение формата ошибок // Хорошо: новая версия rpc CreateUser(CreateUserRequest) returns (CreateUserResponse) { option deprecated = true; } rpc CreateUserV2(CreateUserRequest) returns (CreateUserResponseV2); ```","content":"Изменение формата ошибок // Хорошо: новая версия rpc CreateUser(CreateUserRequest) returns (CreateUserResponse) { option deprecated = true; } rpc CreateUserV2(CreateUserRequest) returns (CreateUserResponseV2); ```"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::43","title":"RPC_SAME_RESPONSE_TYPE","section":"Миграция формата","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Миграция формата"],"excerpt":"Миграция формата ```proto // ПЛОХО: перевод простой структуры в сложную message GetUserResponse { UserData data = 1; // BREAKING }","content":"Миграция формата ```proto // ПЛОХО: перевод простой структуры в сложную message GetUserResponse { UserData data = 1; // BREAKING }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::44","title":"RPC_SAME_RESPONSE_TYPE","section":"Миграция формата","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":["Миграция формата"],"excerpt":"Миграция формата // Хорошо: предоставляем обе версии rpc GetUser(GetUserRequest) returns (GetUserResponse) { option deprecated = true; } rpc GetUserDetailed(GetUserRequest) returns (GetUserDetailedResponse); ```","content":"Миграция формата // Хорошо: предоставляем обе версии 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":"Данное правило проверяет, что ни один service не был удалён из proto‑файлов. Удаление service ломает сгенерированный код и клиентские приложения, которые на него опираются.","content":"Данное правило проверяет, что ни один service не был удалён из proto‑файлов. Удаление service ломает сгенерированный код и клиентские приложения, которые на него опираются."},{"id":"cli/breaking-changes/rules/service-no-delete::breaking::1","title":"SERVICE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **До:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/service-no-delete::breaking::2","title":"SERVICE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/service-no-delete::breaking::3","title":"SERVICE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); }","content":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); }"},{"id":"cli/breaking-changes/rules/service-no-delete::breaking::4","title":"SERVICE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) service OrderService { // [!code --] rpc GetOrder(GetOrderRequest) returns (GetOrderResponse); // [!code --] } // [!code --] ```","content":"Плохой (Breaking) service OrderService { // [!code --] rpc GetOrder(GetOrderRequest) returns (GetOrderResponse); // [!code --] } // [!code --] ```"},{"id":"cli/breaking-changes/rules/service-no-delete::breaking::5","title":"SERVICE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";","content":"Плохой (Breaking) **После:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/service-no-delete::breaking::6","title":"SERVICE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) package myapi.v1;","content":"Плохой (Breaking) package myapi.v1;"},{"id":"cli/breaking-changes/rules/service-no-delete::breaking::7","title":"SERVICE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); }","content":"Плохой (Breaking) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); }"},{"id":"cli/breaking-changes/rules/service-no-delete::breaking::8","title":"SERVICE_NO_DELETE","section":"Плохой (Breaking)","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete#breaking","headings":["Плохой (Breaking)"],"excerpt":"Плохой (Breaking) // OrderService удалён — BREAKING CHANGE! ```","content":"Плохой (Breaking) // OrderService удалён — BREAKING CHANGE! ```"},{"id":"cli/breaking-changes/rules/service-no-delete::top::9","title":"SERVICE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) **Вместо удаления — отметьте service как deprecated:** ```proto syntax = \"proto3\";","content":"Хороший (Безопасный) **Вместо удаления — отметьте service как deprecated:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/service-no-delete::top::10","title":"SERVICE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) package myapi.v1;","content":"Хороший (Безопасный) package myapi.v1;"},{"id":"cli/breaking-changes/rules/service-no-delete::top::11","title":"SERVICE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); }","content":"Хороший (Безопасный) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); }"},{"id":"cli/breaking-changes/rules/service-no-delete::top::12","title":"SERVICE_NO_DELETE","section":"Хороший (Безопасный)","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete","headings":["Хороший (Безопасный)"],"excerpt":"Хороший (Безопасный) service OrderService { option deprecated = true; // [!code focus] rpc GetOrder(GetOrderRequest) returns (GetOrderResponse) { option deprecated = true; // [!code focus] } } ```","content":"Хороший (Безопасный) 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::top::13","title":"SERVICE_NO_DELETE","section":"Влияние","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete","headings":["Влияние"],"excerpt":"Влияние **Generated Code:** Классы / интерфейсы сервиса исчезают — клиенты не компилируются **Client Applications:** Существующие вызовы к удалённому сервису падают на этапе сборки **Runtime:** gRPC клиенты теряют опреде","content":"Влияние **Generated Code:** Классы / интерфейсы сервиса исчезают — клиенты не компилируются **Client Applications:** Существующие вызовы к удалённому сервису падают на этапе сборки **Runtime:** gRPC клиенты теряют определение метода/сервиса"},{"id":"cli/breaking-changes/rules/service-no-delete::top::14","title":"SERVICE_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Сначала деприкация:**","content":"Стратегия миграции **Сначала деприкация:**"},{"id":"cli/breaking-changes/rules/service-no-delete::top::15","title":"SERVICE_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Уведомите клиентов** о сроках вывода из эксплуатации","content":"Стратегия миграции **Уведомите клиентов** о сроках вывода из эксплуатации"},{"id":"cli/breaking-changes/rules/service-no-delete::top::16","title":"SERVICE_NO_DELETE","section":"Стратегия миграции","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete","headings":["Стратегия миграции"],"excerpt":"Стратегия миграции **Удалите после периода миграции** в следующей major‑версии","content":"Стратегия миграции **Удалите после периода миграции** в следующей major‑версии"},{"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 Формат вывода для команд с поддержкой нескольких форматов (text/json) значение по умолчанию зависит от команды"},{"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 Базовая директория для поиска файлов Текущая рабочая дир","content":"Command-Specific Flags Flag Short Environment Description Default ------ ------- ------------- ------------- --------- --path -p Directory path to lint . --root -r Базовая директория для поиска файлов Текущая рабочая директория --format -f EASYP_FORMAT Использует глобальный флаг формата (text/json) Использует глобальное значение по умолчанию"},{"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 из поддиректории с правильным разрешением импортов easyp lint --root src/IPC/Contracts --path .","content":"Command-Specific Flags Lint из поддиректории с правильным разрешением импортов 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 # глобальный флаг","content":"Command-Specific Flags JSON output format easyp --format json lint # глобальный флаг"},{"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 Путь к директории с proto файлами для генерации . --root -r Базова","content":"Command-Specific Flags Flag Short Environment Description Default ------ ------- ------------- ------------- --------- --path -p EASYP_ROOT_GENERATE_PATH Путь к директории с proto файлами для генерации . --root -r Базовая директория для поиска файлов Текущая рабочая директория"},{"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 из поддиректории с правильным разрешением импортов easyp generate --root src/IPC/Contracts --path .","content":"Command-Specific Flags Generate из поддиректории с правильным разрешением импортов 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 Использует глобальный флаг формата (text/json) Использует глобальное значение по умолчанию"},{"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 # глобальный флаг ```","content":"Command-Specific Flags JSON output easyp --format json breaking --against main # глобальный флаг ```"},{"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 работает интерактивно: Если в корне целевой директории есть buf.yml/buf.yaml, команда предложит миграцию из Buf. Если easyp.yaml уже существует, команда запросит подтверждение на перезап","content":"Command-Specific Flags easyp init работает интерактивно: Если в корне целевой директории есть buf.yml/buf.yaml, команда предложит миграцию из Buf. Если easyp.yaml уже существует, команда запросит подтверждение на перезапись."},{"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 Путь до файла конфигурации easyp.yaml --format (global) -f EASYP_FORMAT Глобаль","content":"Command-Specific Flags Flag Short Environment Description Default ------ ------- ------------- ------------- --------- --config -c EASYP_CFG Путь до файла конфигурации easyp.yaml --format (global) -f EASYP_FORMAT Глобальный формат вывода для команд с несколькими форматами (json или text) зависит от команды (json для 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 Проверить конфиг по умолчанию с JSON выводом (статус 0 если ошибок нет) easyp validate-config","content":"Command-Specific Flags **Examples:** ```bash Проверить конфиг по умолчанию с JSON выводом (статус 0 если ошибок нет) 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 Проверить другой файл и вывести в текстовом формате (глобальный --format) easyp --format text validate-config --config example.easyp.yaml ```","content":"Command-Specific Flags Проверить другой файл и вывести в текстовом формате (глобальный --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 Формат вывода для поддерживаемых команд (text/json). Если не указан, каждая команда использует своё значение по умолчанию. значение по умолчанию зависит от команды 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::top::45","title":"EasyP Configuration Reference","section":"Переменные окружения в конфигурации","path":"/docs/guide/cli/configuration/configuration","headings":["Переменные окружения в конфигурации"],"excerpt":"Переменные окружения в конфигурации EasyP поддерживает расширение переменных окружения непосредственно в файле конфигурации easyp.yaml. Это позволяет использовать переменные окружения для динамических значений конфигурац","content":"Переменные окружения в конфигурации EasyP поддерживает расширение переменных окружения непосредственно в файле конфигурации easyp.yaml. Это позволяет использовать переменные окружения для динамических значений конфигурации."},{"id":"cli/configuration/configuration::top::46","title":"EasyP Configuration Reference","section":"Переменные окружения в конфигурации","path":"/docs/guide/cli/configuration/configuration","headings":["Переменные окружения в конфигурации"],"excerpt":"Переменные окружения в конфигурации **Пример со всеми поддерживаемыми возможностями:** ```yaml deps: # Базовое расширение: ${VAR} - расширяется в значение переменной VAR - ${GOOGLEAPIS_REPO}@${GOOGLEAPIS_VERSION} # Значе","content":"Переменные окружения в конфигурации **Пример со всеми поддерживаемыми возможностями:** ```yaml deps: # Базовое расширение: ${VAR} - расширяется в значение переменной VAR - ${GOOGLEAPIS_REPO}@${GOOGLEAPIS_VERSION} # Значение по умолчанию: ${VAR:-default} - использует default, если VAR не установлена или пустая - ${GNOSTIC_REPO:-github.com/google/gnostic}@${GNOSTIC_VERSION:-v0.7.0}"},{"id":"cli/configuration/configuration::top::47","title":"EasyP Configuration Reference","section":"Переменные окружения в конфигурации","path":"/docs/guide/cli/configuration/configuration","headings":["Переменные окружения в конфигурации"],"excerpt":"Переменные окружения в конфигурации generate: inputs: # Значение по умолчанию, если INPUT_DIR не установлена - directory: ${INPUT_DIR:-proto} plugins: - name: go # Базовое расширение out: ${OUTPUT_DIR} opts: # Значение п","content":"Переменные окружения в конфигурации generate: inputs: # Значение по умолчанию, если INPUT_DIR не установлена - directory: ${INPUT_DIR:-proto} plugins: - name: go # Базовое расширение out: ${OUTPUT_DIR} opts: # Значение по умолчанию module: ${MODULE_NAME:-github.com/example/project} timeout: ${TIMEOUT:-30} # Экранирование: $$ становится буквальным $, $${VAR} становится буквальным ${VAR} path: \"${BASE_DIR}/$${TEMP}/file\" # Результат: \"/tmp/${TEMP}/file\" (если BASE_DIR=/tmp) literal: \"$$\" # Результат: \"$\" ```"},{"id":"cli/configuration/configuration::top::48","title":"EasyP Configuration Reference","section":"Переменные окружения в конфигурации","path":"/docs/guide/cli/configuration/configuration","headings":["Переменные окружения в конфигурации"],"excerpt":"Переменные окружения в конфигурации **Поддерживаемый синтаксис:** ${VAR} - расширяется в значение переменной VAR ${VAR:-default} - использует default, если VAR не установлена или пустая ${VAR:=default} - использует defau","content":"Переменные окружения в конфигурации **Поддерживаемый синтаксис:** ${VAR} - расширяется в значение переменной VAR ${VAR:-default} - использует default, если VAR не установлена или пустая ${VAR:=default} - использует default, если VAR не установлена или пустая ${VAR-default} - использует default, если VAR не установлена (пустая строка сохраняется) $${VAR} или $$VAR - экранирует в буквальную строку ${VAR} или $VAR $$ - экранирует в буквальный символ $"},{"id":"cli/configuration/configuration::top::49","title":"EasyP Configuration Reference","section":"Переменные окружения в конфигурации","path":"/docs/guide/cli/configuration/configuration","headings":["Переменные окружения в конфигурации"],"excerpt":"Переменные окружения в конфигурации **Примечание:** Переменные окружения расширяются до парсинга YAML, поэтому любой паттерн ${STRING} будет обработан. Используйте $$ для экранирования символов доллара, когда нужны буква","content":"Переменные окружения в конфигурации **Примечание:** Переменные окружения расширяются до парсинга YAML, поэтому любой паттерн ${STRING} будет обработан. Используйте $$ для экранирования символов доллара, когда нужны буквальные значения."},{"id":"cli/configuration/configuration::version::50","title":"EasyP Configuration Reference","section":"version","path":"/docs/guide/cli/configuration/configuration#version","headings":["version"],"excerpt":"version **Опционально (legacy-совместимость).** Поле поддерживается для обратной совместимости и может быть опущено в новых конфигурациях.","content":"version **Опционально (legacy-совместимость).** Поле поддерживается для обратной совместимости и может быть опущено в новых конфигурациях."},{"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:** не задано **Рекомендация:** если сохраняете поле, используйте v1alpha","content":"version **Type:** string **Default:** не задано **Рекомендация:** если сохраняете поле, используйте v1alpha"},{"id":"cli/configuration/configuration::version::52","title":"EasyP Configuration Reference","section":"version","path":"/docs/guide/cli/configuration/configuration#version","headings":["version"],"excerpt":"version На поведение рантайма это поле не влияет.","content":"version На поведение рантайма это поле не влияет."},{"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, required) - Output directory for generated files opts (mapstring, optional) - Plugin-specific options; each key can be a single value or an array of 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::top::0","title":"Go","section":"Установка плагинов","path":"/docs/guide/cli/generator/examples/go","headings":["Установка плагинов"],"excerpt":"Установка плагинов Сначала установите необходимые плагины для работы с gRPC:","content":"Установка плагинов Сначала установите необходимые плагины для работы с gRPC:"},{"id":"cli/generator/examples/go::top::1","title":"Go","section":"Установка плагинов","path":"/docs/guide/cli/generator/examples/go","headings":["Установка плагинов"],"excerpt":"Установка плагинов Эти команды установят плагины protoc-gen-go и protoc-gen-go-grpc для использования с EasyP.","content":"Установка плагинов Эти команды установят плагины protoc-gen-go и protoc-gen-go-grpc для использования с EasyP."},{"id":"cli/generator/examples/go::proto::2","title":"Go","section":"Пример proto‑сервиса","path":"/docs/guide/cli/generator/examples/go#proto","headings":["Пример proto‑сервиса"],"excerpt":"Пример proto‑сервиса Ниже пример proto-файла для сервиса Echo:","content":"Пример proto‑сервиса Ниже пример proto-файла для сервиса Echo:"},{"id":"cli/generator/examples/go::proto::3","title":"Go","section":"Пример proto‑сервиса","path":"/docs/guide/cli/generator/examples/go#proto","headings":["Пример proto‑сервиса"],"excerpt":"Пример proto‑сервиса ```proto syntax = \"proto3\";","content":"Пример proto‑сервиса ```proto syntax = \"proto3\";"},{"id":"cli/generator/examples/go::proto::4","title":"Go","section":"Пример proto‑сервиса","path":"/docs/guide/cli/generator/examples/go#proto","headings":["Пример proto‑сервиса"],"excerpt":"Пример proto‑сервиса package api.echo.v1;","content":"Пример proto‑сервиса package api.echo.v1;"},{"id":"cli/generator/examples/go::proto::5","title":"Go","section":"Пример proto‑сервиса","path":"/docs/guide/cli/generator/examples/go#proto","headings":["Пример proto‑сервиса"],"excerpt":"Пример proto‑сервиса option go_package = \"github.com/easyp-tech/example/api/echo/v1;pb\";","content":"Пример proto‑сервиса option go_package = \"github.com/easyp-tech/example/api/echo/v1;pb\";"},{"id":"cli/generator/examples/go::proto::6","title":"Go","section":"Пример proto‑сервиса","path":"/docs/guide/cli/generator/examples/go#proto","headings":["Пример proto‑сервиса"],"excerpt":"Пример proto‑сервиса service EchoAPI { rpc Echo(EchoRequest) returns (EchoResponse); rpc EchoStream(EchoStreamRequest) returns (EchoResponse); }","content":"Пример proto‑сервиса service EchoAPI { rpc Echo(EchoRequest) returns (EchoResponse); rpc EchoStream(EchoStreamRequest) returns (EchoResponse); }"},{"id":"cli/generator/examples/go::proto::7","title":"Go","section":"Пример proto‑сервиса","path":"/docs/guide/cli/generator/examples/go#proto","headings":["Пример proto‑сервиса"],"excerpt":"Пример proto‑сервиса message EchoRequest { string payload = 1; }","content":"Пример proto‑сервиса message EchoRequest { string payload = 1; }"},{"id":"cli/generator/examples/go::proto::8","title":"Go","section":"Пример proto‑сервиса","path":"/docs/guide/cli/generator/examples/go#proto","headings":["Пример proto‑сервиса"],"excerpt":"Пример proto‑сервиса message EchoResponse { string payload = 2; }","content":"Пример proto‑сервиса message EchoResponse { string payload = 2; }"},{"id":"cli/generator/examples/go::proto::9","title":"Go","section":"Пример proto‑сервиса","path":"/docs/guide/cli/generator/examples/go#proto","headings":["Пример proto‑сервиса"],"excerpt":"Пример proto‑сервиса message EchoStreamRequest { string payload = 1; }","content":"Пример proto‑сервиса message EchoStreamRequest { string payload = 1; }"},{"id":"cli/generator/examples/go::proto::10","title":"Go","section":"Пример proto‑сервиса","path":"/docs/guide/cli/generator/examples/go#proto","headings":["Пример proto‑сервиса"],"excerpt":"Пример proto‑сервиса message EchoStreamResponse { string payload = 2; } ```","content":"Пример proto‑сервиса message EchoStreamResponse { string payload = 2; } ```"},{"id":"cli/generator/examples/go::top::11","title":"Go","section":"Настройка конфигурации","path":"/docs/guide/cli/generator/examples/go","headings":["Настройка конфигурации"],"excerpt":"Настройка конфигурации Создайте и настройте файл конфигурации easyp.yaml:","content":"Настройка конфигурации Создайте и настройте файл конфигурации easyp.yaml:"},{"id":"cli/generator/examples/go::top::12","title":"Go","section":"Настройка конфигурации","path":"/docs/guide/cli/generator/examples/go","headings":["Настройка конфигурации"],"excerpt":"Настройка конфигурации Этот файл указывает использование двух плагинов: go для генерации Go-кода и go-grpc для генерации gRPC-кода, вместе с их опциями.","content":"Настройка конфигурации Этот файл указывает использование двух плагинов: go для генерации Go-кода и go-grpc для генерации gRPC-кода, вместе с их опциями."},{"id":"cli/generator/examples/go::top::13","title":"Go","section":"Генерация кода","path":"/docs/guide/cli/generator/examples/go","headings":["Генерация кода"],"excerpt":"Генерация кода Чтобы сгенерировать код, выполните команду:","content":"Генерация кода Чтобы сгенерировать код, выполните команду:"},{"id":"cli/generator/examples/go::top::14","title":"Go","section":"Генерация кода","path":"/docs/guide/cli/generator/examples/go","headings":["Генерация кода"],"excerpt":"Генерация кода Если флаг --cfg не указан, по умолчанию используется файл easyp.yaml в текущей директории:","content":"Генерация кода Если флаг --cfg не указан, по умолчанию используется файл easyp.yaml в текущей директории:"},{"id":"cli/generator/examples/go::top::15","title":"Go","section":"Генерация кода","path":"/docs/guide/cli/generator/examples/go","headings":["Генерация кода"],"excerpt":"Генерация кода Теперь у вас есть сгенерированный Go‑код, с которым можно напрямую работать.","content":"Генерация кода Теперь у вас есть сгенерированный Go‑код, с которым можно напрямую работать."},{"id":"cli/generator/examples/grpc-gateway::top::0","title":"gRPC-Gateway","section":"Установка плагинов","path":"/docs/guide/cli/generator/examples/grpc-gateway","headings":["Установка плагинов"],"excerpt":"Установка плагинов В дополнение к плагинам для работы с gRPC, необходимо установить следующие плагины для gRPC-Gateway:","content":"Установка плагинов В дополнение к плагинам для работы с gRPC, необходимо установить следующие плагины для gRPC-Gateway:"},{"id":"cli/generator/examples/grpc-gateway::top::1","title":"gRPC-Gateway","section":"Установка плагинов","path":"/docs/guide/cli/generator/examples/grpc-gateway","headings":["Установка плагинов"],"excerpt":"Установка плагинов go install google.golang.org/protobuf/cmd/protoc-gen-go@latest go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest go install github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2@","content":"Установка плагинов go install google.golang.org/protobuf/cmd/protoc-gen-go@latest go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest go install github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2@latest go install github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway@latest"},{"id":"cli/generator/examples/grpc-gateway::top::2","title":"gRPC-Gateway","section":"Установка плагинов","path":"/docs/guide/cli/generator/examples/grpc-gateway","headings":["Установка плагинов"],"excerpt":"Установка плагинов Эти команды установят плагины protoc-gen-go, protoc-gen-go-grpc, protoc-gen-openapiv2 и protoc-gen-grpc-gateway для использования с EasyP.","content":"Установка плагинов Эти команды установят плагины protoc-gen-go, protoc-gen-go-grpc, protoc-gen-openapiv2 и protoc-gen-grpc-gateway для использования с EasyP."},{"id":"cli/generator/examples/grpc-gateway::proto::3","title":"gRPC-Gateway","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/grpc-gateway#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса Ниже — исходный proto‑файл для сервиса Echo:","content":"Пример Proto сервиса Ниже — исходный proto‑файл для сервиса Echo:"},{"id":"cli/generator/examples/grpc-gateway::proto::4","title":"gRPC-Gateway","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/grpc-gateway#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса syntax = \"proto3\";","content":"Пример Proto сервиса syntax = \"proto3\";"},{"id":"cli/generator/examples/grpc-gateway::proto::5","title":"gRPC-Gateway","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/grpc-gateway#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса package api.echo.v1;","content":"Пример Proto сервиса package api.echo.v1;"},{"id":"cli/generator/examples/grpc-gateway::proto::6","title":"gRPC-Gateway","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/grpc-gateway#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса option go_package = \"github.com/easyp-tech/example/api/echo/v1;pb\";","content":"Пример Proto сервиса option go_package = \"github.com/easyp-tech/example/api/echo/v1;pb\";"},{"id":"cli/generator/examples/grpc-gateway::proto::7","title":"gRPC-Gateway","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/grpc-gateway#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса service EchoAPI { rpc Echo(EchoRequest) returns (EchoResponse); }","content":"Пример Proto сервиса service EchoAPI { rpc Echo(EchoRequest) returns (EchoResponse); }"},{"id":"cli/generator/examples/grpc-gateway::proto::8","title":"gRPC-Gateway","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/grpc-gateway#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса message EchoRequest { string payload = 1; }","content":"Пример Proto сервиса message EchoRequest { string payload = 1; }"},{"id":"cli/generator/examples/grpc-gateway::proto::9","title":"gRPC-Gateway","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/grpc-gateway#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса message EchoResponse { string payload = 2; }","content":"Пример Proto сервиса message EchoResponse { string payload = 2; }"},{"id":"cli/generator/examples/grpc-gateway::proto::10","title":"gRPC-Gateway","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/grpc-gateway#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса Чтобы использовать gRPC-Gateway, обновите proto‑файл, добавив HTTP‑опции:","content":"Пример Proto сервиса Чтобы использовать gRPC-Gateway, обновите proto‑файл, добавив HTTP‑опции:"},{"id":"cli/generator/examples/grpc-gateway::proto::11","title":"gRPC-Gateway","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/grpc-gateway#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса syntax = \"proto3\"; import \"google/api/annotations.proto\";","content":"Пример Proto сервиса syntax = \"proto3\"; import \"google/api/annotations.proto\";"},{"id":"cli/generator/examples/grpc-gateway::proto::12","title":"gRPC-Gateway","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/grpc-gateway#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса package api.echo.v1;","content":"Пример Proto сервиса package api.echo.v1;"},{"id":"cli/generator/examples/grpc-gateway::proto::13","title":"gRPC-Gateway","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/grpc-gateway#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса option go_package = \"github.com/easyp-tech/example/api/echo/v1;pb\";","content":"Пример Proto сервиса option go_package = \"github.com/easyp-tech/example/api/echo/v1;pb\";"},{"id":"cli/generator/examples/grpc-gateway::proto::14","title":"gRPC-Gateway","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/grpc-gateway#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса service EchoAPI { rpc Echo(EchoRequest) returns (EchoResponse) { option (google.api.http) = { // [!code ++] post: \"/api/v1/echo\" // [!code ++] body: \"*\" // [!code ++] }; // [!code ++] } }","content":"Пример Proto сервиса 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::proto::15","title":"gRPC-Gateway","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/grpc-gateway#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса message EchoRequest { string payload = 1; }","content":"Пример Proto сервиса message EchoRequest { string payload = 1; }"},{"id":"cli/generator/examples/grpc-gateway::proto::16","title":"gRPC-Gateway","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/grpc-gateway#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса message EchoResponse { string payload = 2; }","content":"Пример Proto сервиса message EchoResponse { string payload = 2; }"},{"id":"cli/generator/examples/grpc-gateway::top::17","title":"gRPC-Gateway","section":"Настройка конфигурации","path":"/docs/guide/cli/generator/examples/grpc-gateway","headings":["Настройка конфигурации"],"excerpt":"Настройка конфигурации Обновите файл easyp.yaml, добавив необходимые зависимости и плагины: deps: # [!code ++] - github.com/googleapis/googleapis # [!code ++]","content":"Настройка конфигурации Обновите файл easyp.yaml, добавив необходимые зависимости и плагины: deps: # [!code ++] - github.com/googleapis/googleapis # [!code ++]"},{"id":"cli/generator/examples/grpc-gateway::top::18","title":"gRPC-Gateway","section":"Настройка конфигурации","path":"/docs/guide/cli/generator/examples/grpc-gateway","headings":["Настройка конфигурации"],"excerpt":"Настройка конфигурации 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":"Настройка конфигурации 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::top::19","title":"gRPC-Gateway","section":"Настройка конфигурации","path":"/docs/guide/cli/generator/examples/grpc-gateway","headings":["Настройка конфигурации"],"excerpt":"Настройка конфигурации Секция deps перечисляет зависимости, необходимые для импортов proto‑файлов. В данном случае добавляем github.com/googleapis/googleapis, поскольку там находится файл annotations.proto, используемый ","content":"Настройка конфигурации Секция deps перечисляет зависимости, необходимые для импортов proto‑файлов. В данном случае добавляем github.com/googleapis/googleapis, поскольку там находится файл annotations.proto, используемый в определении сервиса."},{"id":"cli/generator/examples/grpc-gateway::top::20","title":"gRPC-Gateway","section":"Обновление зависимостей","path":"/docs/guide/cli/generator/examples/grpc-gateway","headings":["Обновление зависимостей"],"excerpt":"Обновление зависимостей После обновления конфигурации выполните команду для загрузки указанных зависимостей:","content":"Обновление зависимостей После обновления конфигурации выполните команду для загрузки указанных зависимостей:"},{"id":"cli/generator/examples/grpc-gateway::top::21","title":"gRPC-Gateway","section":"Обновление зависимостей","path":"/docs/guide/cli/generator/examples/grpc-gateway","headings":["Обновление зависимостей"],"excerpt":"Обновление зависимостей easyp mod update","content":"Обновление зависимостей easyp mod update"},{"id":"cli/generator/examples/grpc-gateway::top::22","title":"gRPC-Gateway","section":"Обновление зависимостей","path":"/docs/guide/cli/generator/examples/grpc-gateway","headings":["Обновление зависимостей"],"excerpt":"Обновление зависимостей Больше деталей по управлению зависимостями см. в разделе Package Manager.","content":"Обновление зависимостей Больше деталей по управлению зависимостями см. в разделе Package Manager."},{"id":"cli/generator/examples/grpc-gateway::top::23","title":"gRPC-Gateway","section":"Генерация кода","path":"/docs/guide/cli/generator/examples/grpc-gateway","headings":["Генерация кода"],"excerpt":"Генерация кода Для генерации кода используйте:","content":"Генерация кода Для генерации кода используйте:"},{"id":"cli/generator/examples/grpc-gateway::top::24","title":"gRPC-Gateway","section":"Генерация кода","path":"/docs/guide/cli/generator/examples/grpc-gateway","headings":["Генерация кода"],"excerpt":"Генерация кода easyp --cfg easyp.yaml generate","content":"Генерация кода easyp --cfg easyp.yaml generate"},{"id":"cli/generator/examples/grpc-gateway::top::25","title":"gRPC-Gateway","section":"Генерация кода","path":"/docs/guide/cli/generator/examples/grpc-gateway","headings":["Генерация кода"],"excerpt":"Генерация кода Если флаг --cfg не указан, по умолчанию используется файл easyp.yaml из текущей директории:","content":"Генерация кода Если флаг --cfg не указан, по умолчанию используется файл easyp.yaml из текущей директории:"},{"id":"cli/generator/examples/grpc-gateway::top::26","title":"gRPC-Gateway","section":"Генерация кода","path":"/docs/guide/cli/generator/examples/grpc-gateway","headings":["Генерация кода"],"excerpt":"Генерация кода Теперь у вас сгенерированы Go‑код и код gRPC-Gateway, с которыми можно работать напрямую.","content":"Генерация кода Теперь у вас сгенерированы Go‑код и код gRPC-Gateway, с которыми можно работать напрямую."},{"id":"cli/generator/examples/validate::top::0","title":"Validate","section":"Установка плагинов","path":"/docs/guide/cli/generator/examples/validate","headings":["Установка плагинов"],"excerpt":"Установка плагинов Сначала установите необходимые плагины для работы с gRPC и проверок (validate):","content":"Установка плагинов Сначала установите необходимые плагины для работы с gRPC и проверок (validate):"},{"id":"cli/generator/examples/validate::top::1","title":"Validate","section":"Установка плагинов","path":"/docs/guide/cli/generator/examples/validate","headings":["Установка плагинов"],"excerpt":"Установка плагинов Эти команды установят плагины protoc-gen-go, protoc-gen-go-grpc и protoc-gen-validate для использования вместе с EasyP.","content":"Установка плагинов Эти команды установят плагины protoc-gen-go, protoc-gen-go-grpc и protoc-gen-validate для использования вместе с EasyP."},{"id":"cli/generator/examples/validate::proto::2","title":"Validate","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/validate#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса Ниже пример proto‑файла для сервиса Echo:","content":"Пример Proto сервиса Ниже пример proto‑файла для сервиса Echo:"},{"id":"cli/generator/examples/validate::proto::3","title":"Validate","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/validate#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса ```proto syntax = \"proto3\";","content":"Пример Proto сервиса ```proto syntax = \"proto3\";"},{"id":"cli/generator/examples/validate::proto::4","title":"Validate","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/validate#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса package api.echo.v1;","content":"Пример Proto сервиса package api.echo.v1;"},{"id":"cli/generator/examples/validate::proto::5","title":"Validate","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/validate#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса import \"validate/validate.proto\";","content":"Пример Proto сервиса import \"validate/validate.proto\";"},{"id":"cli/generator/examples/validate::proto::6","title":"Validate","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/validate#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса option go_package = \"github.com/easyp-tech/example/api/echo/v1;pb\";","content":"Пример Proto сервиса option go_package = \"github.com/easyp-tech/example/api/echo/v1;pb\";"},{"id":"cli/generator/examples/validate::proto::7","title":"Validate","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/validate#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса service EchoAPI { rpc Echo(EchoRequest) returns (EchoResponse); rpc EchoStream(EchoStreamRequest) returns (EchoResponse); }","content":"Пример Proto сервиса service EchoAPI { rpc Echo(EchoRequest) returns (EchoResponse); rpc EchoStream(EchoStreamRequest) returns (EchoResponse); }"},{"id":"cli/generator/examples/validate::proto::8","title":"Validate","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/validate#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса message EchoRequest { string payload = 1 [(validate.rules).string = {max_len: 200}]; }","content":"Пример Proto сервиса message EchoRequest { string payload = 1 [(validate.rules).string = {max_len: 200}]; }"},{"id":"cli/generator/examples/validate::proto::9","title":"Validate","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/validate#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса message EchoResponse { string payload = 2; }","content":"Пример Proto сервиса message EchoResponse { string payload = 2; }"},{"id":"cli/generator/examples/validate::proto::10","title":"Validate","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/validate#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса message EchoStreamRequest { string payload = 1 [(validate.rules).string = {max_len: 200}]; }","content":"Пример Proto сервиса message EchoStreamRequest { string payload = 1 [(validate.rules).string = {max_len: 200}]; }"},{"id":"cli/generator/examples/validate::proto::11","title":"Validate","section":"Пример Proto сервиса","path":"/docs/guide/cli/generator/examples/validate#proto","headings":["Пример Proto сервиса"],"excerpt":"Пример Proto сервиса message EchoStreamResponse { string payload = 2; } ```","content":"Пример Proto сервиса message EchoStreamResponse { string payload = 2; } ```"},{"id":"cli/generator/examples/validate::top::12","title":"Validate","section":"Настройка конфигурации","path":"/docs/guide/cli/generator/examples/validate","headings":["Настройка конфигурации"],"excerpt":"Настройка конфигурации Создайте и настройте файл конфигурации easyp.yaml:","content":"Настройка конфигурации Создайте и настройте файл конфигурации easyp.yaml:"},{"id":"cli/generator/examples/validate::top::13","title":"Validate","section":"Настройка конфигурации","path":"/docs/guide/cli/generator/examples/validate","headings":["Настройка конфигурации"],"excerpt":"Настройка конфигурации ```yaml deps: # [!code ++] - github.com/bufbuild/protoc-gen-validate # [!code ++]","content":"Настройка конфигурации ```yaml deps: # [!code ++] - github.com/bufbuild/protoc-gen-validate # [!code ++]"},{"id":"cli/generator/examples/validate::top::14","title":"Validate","section":"Настройка конфигурации","path":"/docs/guide/cli/generator/examples/validate","headings":["Настройка конфигурации"],"excerpt":"Настройка конфигурации 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: sourc","content":"Настройка конфигурации 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::top::15","title":"Validate","section":"Генерация кода","path":"/docs/guide/cli/generator/examples/validate","headings":["Генерация кода"],"excerpt":"Генерация кода Чтобы сгенерировать код, выполните команду:","content":"Генерация кода Чтобы сгенерировать код, выполните команду:"},{"id":"cli/generator/examples/validate::top::16","title":"Validate","section":"Генерация кода","path":"/docs/guide/cli/generator/examples/validate","headings":["Генерация кода"],"excerpt":"Генерация кода Если флаг --cfg не указан, по умолчанию используется файл easyp.yaml из текущего каталога:","content":"Генерация кода Если флаг --cfg не указан, по умолчанию используется файл easyp.yaml из текущего каталога:"},{"id":"cli/generator/examples/validate::top::17","title":"Validate","section":"Генерация кода","path":"/docs/guide/cli/generator/examples/validate","headings":["Генерация кода"],"excerpt":"Генерация кода Теперь у вас есть сгенерированный Go‑код с поддержкой валидации, и вы можете напрямую использовать его в проекте.","content":"Генерация кода Теперь у вас есть сгенерированный Go‑код с поддержкой валидации, и вы можете напрямую использовать его в проекте."},{"id":"cli/generator/generator::top::0","title":"Генератор","path":"/docs/guide/cli/generator/generator","headings":[],"excerpt":"EasyP включает мощный генератор, который упрощает процесс получения кода из proto‑файлов. Благодаря YAML‑конфигурациям работа становится гораздо более удобной и интуитивной по сравнению с прямым использованием команды pr","content":"EasyP включает мощный генератор, который упрощает процесс получения кода из proto‑файлов. Благодаря YAML‑конфигурациям работа становится гораздо более удобной и интуитивной по сравнению с прямым использованием команды protoc."},{"id":"cli/generator/generator::top::1","title":"Генератор","section":"Ключевые особенности генератора","path":"/docs/guide/cli/generator/generator","headings":["Ключевые особенности генератора"],"excerpt":"Ключевые особенности генератора **Упрощённая генерация кода**: - Генерация кода из proto через декларативную YAML‑конфигурацию. - Избавляет от необходимости писать длинные и сложные команды protoc.","content":"Ключевые особенности генератора **Упрощённая генерация кода**: - Генерация кода из proto через декларативную YAML‑конфигурацию. - Избавляет от необходимости писать длинные и сложные команды protoc."},{"id":"cli/generator/generator::top::2","title":"Генератор","section":"Ключевые особенности генератора","path":"/docs/guide/cli/generator/generator","headings":["Ключевые особенности генератора"],"excerpt":"Ключевые особенности генератора **Обёртка над protoc**: - EasyP выступает как удобный слой над protoc, предоставляя декларативный API. - Поддерживает все опции и плагины, доступные protoc.","content":"Ключевые особенности генератора **Обёртка над protoc**: - EasyP выступает как удобный слой над protoc, предоставляя декларативный API. - Поддерживает все опции и плагины, доступные protoc."},{"id":"cli/generator/generator::top::3","title":"Генератор","section":"Ключевые особенности генератора","path":"/docs/guide/cli/generator/generator","headings":["Ключевые особенности генератора"],"excerpt":"Ключевые особенности генератора **Гибкость и кастомизация**: - Используются те же параметры, что и у плагинов protoc, прямо в конфиге. - Поддерживается множество плагинов и их параметры в одной конфигурации.","content":"Ключевые особенности генератора **Гибкость и кастомизация**: - Используются те же параметры, что и у плагинов protoc, прямо в конфиге. - Поддерживается множество плагинов и их параметры в одной конфигурации."},{"id":"cli/generator/generator::top::4","title":"Генератор","section":"Ключевые особенности генератора","path":"/docs/guide/cli/generator/generator","headings":["Ключевые особенности генератора"],"excerpt":"Ключевые особенности генератора **Генерация из нескольких источников**: - Локальные директории и удалённые Git‑репозитории одновременно. - Лёгкая интеграция с существующими проектами и репозиториями.","content":"Ключевые особенности генератора **Генерация из нескольких источников**: - Локальные директории и удалённые Git‑репозитории одновременно. - Лёгкая интеграция с существующими проектами и репозиториями."},{"id":"cli/generator/generator::top::5","title":"Генератор","section":"Ключевые особенности генератора","path":"/docs/guide/cli/generator/generator","headings":["Ключевые особенности генератора"],"excerpt":"Ключевые особенности генератора **Удалённая генерация**: - Генерация из удалённых Git репозиториев без локального checkout.","content":"Ключевые особенности генератора **Удалённая генерация**: - Генерация из удалённых Git репозиториев без локального checkout."},{"id":"cli/generator/generator::top::6","title":"Генератор","section":"Ключевые особенности генератора","path":"/docs/guide/cli/generator/generator","headings":["Ключевые особенности генератора"],"excerpt":"Ключевые особенности генератора **Интеграция с менеджером пакетов**: - Прозрачная работа с зависимостями через пакетный менеджер EasyP. - Автоматическое разрешение и подключение proto‑зависимостей.","content":"Ключевые особенности генератора **Интеграция с менеджером пакетов**: - Прозрачная работа с зависимостями через пакетный менеджер EasyP. - Автоматическое разрешение и подключение proto‑зависимостей."},{"id":"cli/generator/generator::complete-configuration-example::7","title":"Генератор","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":"Генератор","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":"Генератор","section":"Complete Configuration Example","path":"/docs/guide/cli/generator/generator#complete-configuration-example","headings":["Complete Configuration Example"],"excerpt":"Complete Configuration Example Managed mode - автоматическая установка file и field опций managed: enabled: true disable: - module: github.com/googleapis/googleapis # Отключить для конкретного модуля override: - file_opt","content":"Complete Configuration Example Managed mode - автоматическая установка file и field опций managed: enabled: true disable: - module: github.com/googleapis/googleapis # Отключить для конкретного модуля 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/ # Применить к конкретному пути"},{"id":"cli/generator/generator::complete-configuration-example::10","title":"Генератор","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":"Генератор","section":"Локальный ввод (Local Directory Input)","path":"/docs/guide/cli/generator/generator#local-directory-input","headings":["Локальный ввод (Local Directory Input)"],"excerpt":"Локальный ввод (Local Directory Input) Локальная директория — самый распространённый и простой способ указать откуда брать proto для генерации. Используйте этот вариант, если файлы уже находятся в репозитории проекта.","content":"Локальный ввод (Local Directory Input) Локальная директория — самый распространённый и простой способ указать откуда брать proto для генерации. Используйте этот вариант, если файлы уже находятся в репозитории проекта."},{"id":"cli/generator/generator::local-directory-input::12","title":"Генератор","section":"Локальный ввод (Local Directory Input)","path":"/docs/guide/cli/generator/generator#local-directory-input","headings":["Локальный ввод (Local Directory Input)"],"excerpt":"Локальный ввод (Local Directory Input) **Когда применять:** Proto файлы находятся в кодовой базе проекта Нужен полный контроль над структурой каталогов Проект — один сервис или приложение Файлы меняются не слишком часто","content":"Локальный ввод (Local Directory Input) **Когда применять:** Proto файлы находятся в кодовой базе проекта Нужен полный контроль над структурой каталогов Проект — один сервис или приложение Файлы меняются не слишком часто"},{"id":"cli/generator/generator::local-directory-input::13","title":"Генератор","section":"Локальный ввод (Local Directory Input)","path":"/docs/guide/cli/generator/generator#local-directory-input","headings":["Локальный ввод (Local Directory Input)"],"excerpt":"Локальный ввод (Local Directory Input)","content":"Локальный ввод (Local Directory Input)"},{"id":"cli/generator/generator::local-directory-input::14","title":"Генератор","section":"Локальный ввод (Local Directory Input)","path":"/docs/guide/cli/generator/generator#local-directory-input","headings":["Локальный ввод (Local Directory Input)"],"excerpt":"Локальный ввод (Local Directory Input) Параметр root особенно полезен в монорепозиториях: он позволяет управлять тем, откуда будут резолвиться пути импортов. Если указать родительскую директорию, импорты будут оцениватьс","content":"Локальный ввод (Local Directory Input) Параметр root особенно полезен в монорепозиториях: он позволяет управлять тем, откуда будут резолвиться пути импортов. Если указать родительскую директорию, импорты будут оцениваться относительно неё, а не текущего рабочего каталога."},{"id":"cli/generator/generator::local-directory-input::15","title":"Генератор","section":"Локальный ввод (Local Directory Input)","path":"/docs/guide/cli/generator/generator#local-directory-input","headings":["Локальный ввод (Local Directory Input)"],"excerpt":"Локальный ввод (Local Directory Input) **Параметры:**","content":"Локальный ввод (Local Directory Input) **Параметры:**"},{"id":"cli/generator/generator::local-directory-input::16","title":"Генератор","section":"Локальный ввод (Local Directory Input)","path":"/docs/guide/cli/generator/generator#local-directory-input","headings":["Локальный ввод (Local Directory Input)"],"excerpt":"Локальный ввод (Local Directory Input) Параметр Тип Обязателен Значение по умолчанию Описание ---------- ----- ------------ ----------------------- ---------- path string ✅ - Каталог, содержащий proto файлы root string ❌","content":"Локальный ввод (Local Directory Input) Параметр Тип Обязателен Значение по умолчанию Описание ---------- ----- ------------ ----------------------- ---------- path string ✅ - Каталог, содержащий proto файлы root string ❌ \".\" Корневая директория для разрешения import путей"},{"id":"cli/generator/generator::local-directory-input::17","title":"Генератор","section":"Локальный ввод (Local Directory Input)","path":"/docs/guide/cli/generator/generator#local-directory-input","headings":["Локальный ввод (Local Directory Input)"],"excerpt":"Локальный ввод (Local Directory Input) **Примеры:**","content":"Локальный ввод (Local Directory Input) **Примеры:**"},{"id":"cli/generator/generator::local-directory-input::18","title":"Генератор","section":"Локальный ввод (Local Directory Input)","path":"/docs/guide/cli/generator/generator#local-directory-input","headings":["Локальный ввод (Local Directory Input)"],"excerpt":"Локальный ввод (Local Directory Input) Ниже показана разница между базовым указанием директории и расширенной конфигурацией с пользовательским корнем импортов:","content":"Локальный ввод (Local Directory Input) Ниже показана разница между базовым указанием директории и расширенной конфигурацией с пользовательским корнем импортов:"},{"id":"cli/generator/generator::local-directory-input::19","title":"Генератор","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::20","title":"Генератор","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::git-remote-git-repository-input::21","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) Этот тип входных данных позволяет генерировать код из proto‑файлов, находящихся в удалённых репозиториях, без локального checkout. Особенно полезно при использовани","content":"Удалённый Git репозиторий (Remote Git Repository Input) Этот тип входных данных позволяет генерировать код из proto‑файлов, находящихся в удалённых репозиториях, без локального checkout. Особенно полезно при использовании API других команд или внешних поставщиков."},{"id":"cli/generator/generator::git-remote-git-repository-input::22","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) **Когда использовать:** Потребление proto определений из других сервисов/команд Интеграция с внешними вендорскими API Работа с общими библиотеками proto в нескольки","content":"Удалённый Git репозиторий (Remote Git Repository Input) **Когда использовать:** Потребление proto определений из других сервисов/команд Интеграция с внешними вендорскими API Работа с общими библиотеками proto в нескольких проектах Необходимо гарантировать корректную (зафиксированную) версию внешних API"},{"id":"cli/generator/generator::git-remote-git-repository-input::23","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) **Рекомендации:** В продакшене всегда фиксируйте версии (@v1.0.0, а не latest) Используйте семантические версии при наличии — проще сопровождать Предпочитайте публи","content":"Удалённый Git репозиторий (Remote Git Repository Input) **Рекомендации:** В продакшене всегда фиксируйте версии (@v1.0.0, а не latest) Используйте семантические версии при наличии — проще сопровождать Предпочитайте публичные теги вместо хеша коммита (лучше отслеживаемость)"},{"id":"cli/generator/generator::git-remote-git-repository-input::24","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input)","content":"Удалённый Git репозиторий (Remote Git Repository Input)"},{"id":"cli/generator/generator::git-remote-git-repository-input::25","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) Параметр root задаёт корень для разрешения импортов файлов из этого репозитория.","content":"Удалённый Git репозиторий (Remote Git Repository Input) Параметр root задаёт корень для разрешения импортов файлов из этого репозитория."},{"id":"cli/generator/generator::git-remote-git-repository-input::26","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) **Параметры:**","content":"Удалённый Git репозиторий (Remote Git Repository Input) **Параметры:**"},{"id":"cli/generator/generator::git-remote-git-repository-input::27","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) Параметр Тип Обязателен По умолчанию Описание ---------- ----- ------------ -------------- ---------- url string ✅ - URL Git репозитория с необязательной версией / ","content":"Удалённый Git репозиторий (Remote Git Repository Input) Параметр Тип Обязателен По умолчанию Описание ---------- ----- ------------ -------------- ---------- url string ✅ - URL Git репозитория с необязательной версией / тегом / коммитом sub_directory string ❌ \"\" Поддиректория внутри репозитория, где лежат proto root string ❌ \"\" Корневой путь для разрешения импортов"},{"id":"cli/generator/generator::git-remote-git-repository-input::28","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) **Варианты формата URL:**","content":"Удалённый Git репозиторий (Remote Git Repository Input) **Варианты формата URL:**"},{"id":"cli/generator/generator::git-remote-git-repository-input::29","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) EasyP поддерживает несколько форматов для ссылки на удалённые репозитории. Каждый подходит под разные требования по стабильности:","content":"Удалённый Git репозиторий (Remote Git Repository Input) EasyP поддерживает несколько форматов для ссылки на удалённые репозитории. Каждый подходит под разные требования по стабильности:"},{"id":"cli/generator/generator::git-remote-git-repository-input::30","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) **Tagged versions** — для продакшена, стабильные неизменяемые ссылки **Semantic versions** — читаемость и управление зависимостями **Commit hashes** — доступ к конк","content":"Удалённый Git репозиторий (Remote Git Repository Input) **Tagged versions** — для продакшена, стабильные неизменяемые ссылки **Semantic versions** — читаемость и управление зависимостями **Commit hashes** — доступ к конкретному коммиту, если нет тега **Latest** — только для разработки, непредсказуемо **Full HTTPS URLs** — приватные репозитории или нестандартный хостинг"},{"id":"cli/generator/generator::git-remote-git-repository-input::31","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) ```yaml Тег — стабильно для продакшена url: \"github.com/googleapis/googleapis@common-protos-1_3_1\"","content":"Удалённый Git репозиторий (Remote Git Repository Input) ```yaml Тег — стабильно для продакшена url: \"github.com/googleapis/googleapis@common-protos-1_3_1\""},{"id":"cli/generator/generator::git-remote-git-repository-input::32","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) Семантическая версия url: \"github.com/grpc-ecosystem/grpc-gateway@v2.19.1\"","content":"Удалённый Git репозиторий (Remote Git Repository Input) Семантическая версия url: \"github.com/grpc-ecosystem/grpc-gateway@v2.19.1\""},{"id":"cli/generator/generator::git-remote-git-repository-input::33","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) Хеш коммита — точечный фикс url: \"github.com/company/protos@abc123def456\"","content":"Удалённый Git репозиторий (Remote Git Repository Input) Хеш коммита — точечный фикс url: \"github.com/company/protos@abc123def456\""},{"id":"cli/generator/generator::git-remote-git-repository-input::34","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) Latest — только dev, НЕ для продакшена url: \"github.com/company/protos\"","content":"Удалённый Git репозиторий (Remote Git Repository Input) Latest — только dev, НЕ для продакшена url: \"github.com/company/protos\""},{"id":"cli/generator/generator::git-remote-git-repository-input::35","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) Полный HTTPS URL — приватный или кастомный Git url: \"https://github.com/company/private-protos.git\" ```","content":"Удалённый Git репозиторий (Remote Git Repository Input) Полный HTTPS URL — приватный или кастомный Git url: \"https://github.com/company/private-protos.git\" ```"},{"id":"cli/generator/generator::git-remote-git-repository-input::36","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) **Примеры:**","content":"Удалённый Git репозиторий (Remote Git Repository Input) **Примеры:**"},{"id":"cli/generator/generator::git-remote-git-repository-input::37","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input) Ниже паттерны использования удалённых источников в разных сценариях:","content":"Удалённый Git репозиторий (Remote Git Repository Input) Ниже паттерны использования удалённых источников в разных сценариях:"},{"id":"cli/generator/generator::git-remote-git-repository-input::38","title":"Генератор","section":"Удалённый Git репозиторий (Remote Git Repository Input)","path":"/docs/guide/cli/generator/generator#git-remote-git-repository-input","headings":["Удалённый Git репозиторий (Remote Git Repository Input)"],"excerpt":"Удалённый Git репозиторий (Remote Git Repository Input)","content":"Удалённый Git репозиторий (Remote Git Repository Input)"},{"id":"cli/generator/generator::top::39","title":"Генератор","section":"Конфигурация плагинов","path":"/docs/guide/cli/generator/generator","headings":["Конфигурация плагинов"],"excerpt":"Конфигурация плагинов Конфигурация плагинов определяет какие генераторы кода будут запущены и как они себя ведут. EasyP поддерживает любой плагин protoc, что делает его крайне гибким для разных языковых экосистем и сцена","content":"Конфигурация плагинов Конфигурация плагинов определяет какие генераторы кода будут запущены и как они себя ведут. EasyP поддерживает любой плагин protoc, что делает его крайне гибким для разных языковых экосистем и сценариев."},{"id":"cli/generator/generator::top::40","title":"Генератор","section":"Конфигурация плагинов","path":"/docs/guide/cli/generator/generator","headings":["Конфигурация плагинов"],"excerpt":"Конфигурация плагинов На верхнем уровне есть **четыре способа указать, как именно запускать плагин**:","content":"Конфигурация плагинов На верхнем уровне есть **четыре способа указать, как именно запускать плагин**:"},{"id":"cli/generator/generator::top::41","title":"Генератор","section":"Конфигурация плагинов","path":"/docs/guide/cli/generator/generator","headings":["Конфигурация плагинов"],"excerpt":"Конфигурация плагинов **name** – запуск плагина по имени из PATH или использование встроенного плагина. **path** – запуск плагина по абсолютному/относительному пути к исполняемому файлу. **remote** – удалённый плагин по ","content":"Конфигурация плагинов **name** – запуск плагина по имени из PATH или использование встроенного плагина. **path** – запуск плагина по абсолютному/относительному пути к исполняемому файлу. **remote** – удалённый плагин по URL (через remote‑executor EasyP). **command** – запуск плагина через произвольную команду (например, go run ...)."},{"id":"cli/generator/generator::top::42","title":"Генератор","section":"Конфигурация плагинов","path":"/docs/guide/cli/generator/generator","headings":["Конфигурация плагинов"],"excerpt":"Конфигурация плагинов Для каждого плагина должен быть указан **ровно один** из параметров name, path, remote или command.","content":"Конфигурация плагинов Для каждого плагина должен быть указан **ровно один** из параметров name, path, remote или command."},{"id":"cli/generator/generator::name::43","title":"Генератор","section":"Плагин по имени (name)","path":"/docs/guide/cli/generator/generator#name","headings":["Плагин по имени (name)"],"excerpt":"Плагин по имени (name) Локальный режим по имени — стандартный: плагины установлены в системе и запускаются напрямую через EasyP.","content":"Плагин по имени (name) Локальный режим по имени — стандартный: плагины установлены в системе и запускаются напрямую через EasyP."},{"id":"cli/generator/generator::name::44","title":"Генератор","section":"Плагин по имени (name)","path":"/docs/guide/cli/generator/generator#name","headings":["Плагин по имени (name)"],"excerpt":"Плагин по имени (name) **Когда использовать name:** Стандартные языки (Go, Python, TypeScript и т.д.) Есть контроль над окружением сборки Критична производительность (нет сетевых задержек) Хочется опираться на PATH или в","content":"Плагин по имени (name) **Когда использовать name:** Стандартные языки (Go, Python, TypeScript и т.д.) Есть контроль над окружением сборки Критична производительность (нет сетевых задержек) Хочется опираться на PATH или встроенные плагины"},{"id":"cli/generator/generator::name::45","title":"Генератор","section":"Плагин по имени (name)","path":"/docs/guide/cli/generator/generator#name","headings":["Плагин по имени (name)"],"excerpt":"Плагин по имени (name) **Требования к установке:** Плагины установлены и доступны в PATH (если не используются встроенные). Имена следуют шаблону protoc-gen-{name}. Установка через менеджеры пакетов (go install, npm inst","content":"Плагин по имени (name) **Требования к установке:** Плагины установлены и доступны в PATH (если не используются встроенные). Имена следуют шаблону protoc-gen-{name}. Установка через менеджеры пакетов (go install, npm install, pip install и т.п.)."},{"id":"cli/generator/generator::name::46","title":"Генератор","section":"Плагин по имени (name)","path":"/docs/guide/cli/generator/generator#name","headings":["Плагин по имени (name)"],"excerpt":"Плагин по имени (name) Параметр with_imports критичен при использовании зависимостей из пакетного менеджера: установите true, чтобы прототипы из секции deps попали в генерацию.","content":"Плагин по имени (name) Параметр with_imports критичен при использовании зависимостей из пакетного менеджера: установите true, чтобы прототипы из секции deps попали в генерацию."},{"id":"cli/generator/generator::path::47","title":"Генератор","section":"Плагин по пути (path)","path":"/docs/guide/cli/generator/generator#path","headings":["Плагин по пути (path)"],"excerpt":"Плагин по пути (path) Иногда нужно запускать плагин из конкретного бинарника, не добавляя его в PATH (например, бинарь в репозитории или в build‑директории). В этом случае можно указать явный путь:","content":"Плагин по пути (path) Иногда нужно запускать плагин из конкретного бинарника, не добавляя его в PATH (например, бинарь в репозитории или в build‑директории). В этом случае можно указать явный путь:"},{"id":"cli/generator/generator::path::48","title":"Генератор","section":"Плагин по пути (path)","path":"/docs/guide/cli/generator/generator#path","headings":["Плагин по пути (path)"],"excerpt":"Плагин по пути (path) **Когда использовать path:** Бинарники плагинов хранятся в репозитории (для воспроизводимых сборок). Используются несколько версий одного и того же плагина параллельно. Не хочется «загрязнять» глоба","content":"Плагин по пути (path) **Когда использовать path:** Бинарники плагинов хранятся в репозитории (для воспроизводимых сборок). Используются несколько версий одного и того же плагина параллельно. Не хочется «загрязнять» глобальный PATH."},{"id":"cli/generator/generator::remote::49","title":"Генератор","section":"Удалённый плагин (remote)","path":"/docs/guide/cli/generator/generator#remote","headings":["Удалённый плагин (remote)"],"excerpt":"Удалённый плагин (remote) Удалённые плагины выполняются по URL. EasyP отправляет на удалённую сторону CodeGeneratorRequest и получает обратно CodeGeneratorResponse.","content":"Удалённый плагин (remote) Удалённые плагины выполняются по URL. EasyP отправляет на удалённую сторону CodeGeneratorRequest и получает обратно CodeGeneratorResponse."},{"id":"cli/generator/generator::remote::50","title":"Генератор","section":"Удалённый плагин (remote)","path":"/docs/guide/cli/generator/generator#remote","headings":["Удалённый плагин (remote)"],"excerpt":"Удалённый плагин (remote) Ниже приведён реальный пример использования EasyP API Service как удалённого исполнителя плагинов (тот же формат используется в разделе про API Service):","content":"Удалённый плагин (remote) Ниже приведён реальный пример использования EasyP API Service как удалённого исполнителя плагинов (тот же формат используется в разделе про API Service):"},{"id":"cli/generator/generator::remote::51","title":"Генератор","section":"Удалённый плагин (remote)","path":"/docs/guide/cli/generator/generator#remote","headings":["Удалённый плагин (remote)"],"excerpt":"Удалённый плагин (remote) ```yaml generate: plugins: # Удалённое выполнение плагинов через EasyP API Service - remote: api.easyp.tech/protobuf/go:v1.36.10 out: . opts: paths: source_relative","content":"Удалённый плагин (remote) ```yaml generate: plugins: # Удалённое выполнение плагинов через EasyP API Service - remote: api.easyp.tech/protobuf/go:v1.36.10 out: . opts: paths: source_relative"},{"id":"cli/generator/generator::remote::52","title":"Генератор","section":"Удалённый плагин (remote)","path":"/docs/guide/cli/generator/generator#remote","headings":["Удалённый плагин (remote)"],"excerpt":"Удалённый плагин (remote) remote: api.easyp.tech/grpc/go:v1.5.1 out: . opts: paths: source_relative ```","content":"Удалённый плагин (remote) remote: api.easyp.tech/grpc/go:v1.5.1 out: . opts: paths: source_relative ```"},{"id":"cli/generator/generator::remote::53","title":"Генератор","section":"Удалённый плагин (remote)","path":"/docs/guide/cli/generator/generator#remote","headings":["Удалённый плагин (remote)"],"excerpt":"Удалённый плагин (remote) **Типичные сценарии для remote:** Централизованный сервис плагинов внутри компании (например, EasyP API Service). Запуск тяжёлых плагинов на выделенных машинах вместо CI‑агентов. Совместное испо","content":"Удалённый плагин (remote) **Типичные сценарии для remote:** Централизованный сервис плагинов внутри компании (например, EasyP API Service). Запуск тяжёлых плагинов на выделенных машинах вместо CI‑агентов. Совместное использование одной реализации плагина разными командами."},{"id":"cli/generator/generator::command::54","title":"Генератор","section":"Выполнение плагина через команду (command)","path":"/docs/guide/cli/generator/generator#command","headings":["Выполнение плагина через команду (command)"],"excerpt":"Выполнение плагина через команду (command) Вы можете указать плагин как массив команд для выполнения. Это полезно для запуска плагинов через go run или любые другие инструменты без предварительной установки бинарника пла","content":"Выполнение плагина через команду (command) Вы можете указать плагин как массив команд для выполнения. Это полезно для запуска плагинов через go run или любые другие инструменты без предварительной установки бинарника плагина:"},{"id":"cli/generator/generator::command::55","title":"Генератор","section":"Выполнение плагина через команду (command)","path":"/docs/guide/cli/generator/generator#command","headings":["Выполнение плагина через команду (command)"],"excerpt":"Выполнение плагина через команду (command)","content":"Выполнение плагина через команду (command)"},{"id":"cli/generator/generator::command::56","title":"Генератор","section":"Выполнение плагина через команду (command)","path":"/docs/guide/cli/generator/generator#command","headings":["Выполнение плагина через команду (command)"],"excerpt":"Выполнение плагина через команду (command) В этом режиме EasyP: **запускает указанную команду** как дочерний процесс; **пишет CodeGeneratorRequest в stdin** процесса; **читает CodeGeneratorResponse из stdout**, как и для","content":"Выполнение плагина через команду (command) В этом режиме EasyP: **запускает указанную команду** как дочерний процесс; **пишет CodeGeneratorRequest в stdin** процесса; **читает CodeGeneratorResponse из stdout**, как и для обычных плагинов protoc."},{"id":"cli/generator/generator::command::57","title":"Генератор","section":"Выполнение плагина через команду (command)","path":"/docs/guide/cli/generator/generator#command","headings":["Выполнение плагина через команду (command)"],"excerpt":"Выполнение плагина через команду (command) **Приоритет источников плагина:** command — выполнение через указанную команду (наивысший приоритет) remote — удалённый плагин через URL name — локальный плагин из PATH или встр","content":"Выполнение плагина через команду (command) **Приоритет источников плагина:** command — выполнение через указанную команду (наивысший приоритет) remote — удалённый плагин через URL name — локальный плагин из PATH или встроенный плагин path — путь к исполняемому файлу плагина"},{"id":"cli/generator/generator::command::58","title":"Генератор","section":"Выполнение плагина через команду (command)","path":"/docs/guide/cli/generator/generator#command","headings":["Выполнение плагина через команду (command)"],"excerpt":"Выполнение плагина через команду (command) **Параметры (источники и общие опции плагина):**","content":"Выполнение плагина через команду (command) **Параметры (источники и общие опции плагина):**"},{"id":"cli/generator/generator::command::59","title":"Генератор","section":"Выполнение плагина через команду (command)","path":"/docs/guide/cli/generator/generator#command","headings":["Выполнение плагина через команду (command)"],"excerpt":"Выполнение плагина через команду (command) Параметр Тип Обязателен По умолчанию Описание ---------- ----- ------------ -------------- ---------- name string ❌ - Имя / идентификатор плагина (например, go, go-grpc, grpc-ga","content":"Выполнение плагина через команду (command) Параметр Тип Обязателен По умолчанию Описание ---------- ----- ------------ -------------- ---------- name string ❌ - Имя / идентификатор плагина (например, go, go-grpc, grpc-gateway) command []string ❌ - Команда для выполнения плагина (например, [\"go\", \"run\", \"package\"]) remote string ❌ - URL удалённого плагина path string ❌ - Путь к исполняемому файлу плагина out string ✅ - Директория для сгенерированных файлов opts mapstring ❌ {} Специфичные опции плагина; значения-списки передаются как повторяющиеся key=value with_imports bool ❌ false Включать proto из зависимостей"},{"id":"cli/generator/generator::command::60","title":"Генератор","section":"Выполнение плагина через команду (command)","path":"/docs/guide/cli/generator/generator#command","headings":["Выполнение плагина через команду (command)"],"excerpt":"Выполнение плагина через команду (command) **Примечание:** Для каждого плагина должен быть указан ровно один источник (name, command, remote или path). Если opts.outputServices задан как [\"grpc-js\", \"generic-definitions\"","content":"Выполнение плагина через команду (command) **Примечание:** Для каждого плагина должен быть указан ровно один источник (name, command, remote или path). Если opts.outputServices задан как [\"grpc-js\", \"generic-definitions\"], EasyP передаст outputServices=grpc-js,outputServices=generic-definitions."},{"id":"cli/generator/generator::command::61","title":"Генератор","section":"Выполнение плагина через команду (command)","path":"/docs/guide/cli/generator/generator#command","headings":["Выполнение плагина через команду (command)"],"excerpt":"Выполнение плагина через команду (command) **Примеры использования источника command:**","content":"Выполнение плагина через команду (command) **Примеры использования источника command:**"},{"id":"cli/generator/generator::command::62","title":"Генератор","section":"Выполнение плагина через команду (command)","path":"/docs/guide/cli/generator/generator#command","headings":["Выполнение плагина через команду (command)"],"excerpt":"Выполнение плагина через команду (command) ```yaml generate: inputs: - directory: \"proto\"","content":"Выполнение плагина через команду (command) ```yaml generate: inputs: - directory: \"proto\""},{"id":"cli/generator/generator::command::63","title":"Генератор","section":"Выполнение плагина через команду (command)","path":"/docs/guide/cli/generator/generator#command","headings":["Выполнение плагина через команду (command)"],"excerpt":"Выполнение плагина через команду (command) plugins: # 1) gRPC-Gateway через go run (без предварительной установки бинарника) - command: [\"go\", \"run\", \"github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway@v2.","content":"Выполнение плагина через команду (command) plugins: # 1) gRPC-Gateway через go run (без предварительной установки бинарника) - 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::command::64","title":"Генератор","section":"Выполнение плагина через команду (command)","path":"/docs/guide/cli/generator/generator#command","headings":["Выполнение плагина через команду (command)"],"excerpt":"Выполнение плагина через команду (command) 2) protoc-gen-validate через go run - command: [\"go\", \"run\", \"github.com/bufbuild/protoc-gen-validate@v0.10.1\"] out: ./gen/go opts: paths: source_relative lang: go","content":"Выполнение плагина через команду (command) 2) protoc-gen-validate через 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::command::65","title":"Генератор","section":"Выполнение плагина через команду (command)","path":"/docs/guide/cli/generator/generator#command","headings":["Выполнение плагина через команду (command)"],"excerpt":"Выполнение плагина через команду (command) 3) Произвольный кастомный скрипт-обёртка - command: [\"bash\", \"./scripts/custom-protoc-plugin.sh\"] out: ./gen/custom opts: foo: bar ```","content":"Выполнение плагина через команду (command) 3) Произвольный кастомный скрипт-обёртка - command: [\"bash\", \"./scripts/custom-protoc-plugin.sh\"] out: ./gen/custom opts: foo: bar ```"},{"id":"cli/generator/generator::builtin-plugins::66","title":"Генератор","section":"Встроенные плагины (Builtin Plugins)","path":"/docs/guide/cli/generator/generator#builtin-plugins","headings":["Встроенные плагины (Builtin Plugins)"],"excerpt":"Встроенные плагины (Builtin Plugins) EasyP поддерживает встроенные плагины для базовых языков protobuf и gRPC. Эти плагины встроены в бинарник как WASM-модули и не требуют установки внешних зависимостей.","content":"Встроенные плагины (Builtin Plugins) EasyP поддерживает встроенные плагины для базовых языков protobuf и gRPC. Эти плагины встроены в бинарник как WASM-модули и не требуют установки внешних зависимостей."},{"id":"cli/generator/generator::builtin-plugins::67","title":"Генератор","section":"Встроенные плагины (Builtin Plugins)","path":"/docs/guide/cli/generator/generator#builtin-plugins","headings":["Встроенные плагины (Builtin Plugins)"],"excerpt":"Встроенные плагины (Builtin Plugins) **Преимущества встроенных плагинов:** **Портативность**: Один бинарник со всеми необходимыми плагинами **Удобство**: Не требуется установка внешних зависимостей **Стабильность**: Верс","content":"Встроенные плагины (Builtin Plugins) **Преимущества встроенных плагинов:** **Портативность**: Один бинарник со всеми необходимыми плагинами **Удобство**: Не требуется установка внешних зависимостей **Стабильность**: Версии плагинов зафиксированы в бинарнике **Изоляция**: Не зависит от системных установок плагинов"},{"id":"cli/generator/generator::builtin-plugins::68","title":"Генератор","section":"Встроенные плагины (Builtin Plugins)","path":"/docs/guide/cli/generator/generator#builtin-plugins","headings":["Встроенные плагины (Builtin Plugins)"],"excerpt":"Встроенные плагины (Builtin Plugins) **Поддерживаемые встроенные плагины:**","content":"Встроенные плагины (Builtin Plugins) **Поддерживаемые встроенные плагины:**"},{"id":"cli/generator/generator::protobuf::69","title":"Генератор","section":"Protobuf базовые плагины","path":"/docs/guide/cli/generator/generator#protobuf","headings":["Protobuf базовые плагины"],"excerpt":"Protobuf базовые плагины Следующие плагины встроены для генерации базового protobuf кода:","content":"Protobuf базовые плагины Следующие плагины встроены для генерации базового protobuf кода:"},{"id":"cli/generator/generator::protobuf::70","title":"Генератор","section":"Protobuf базовые плагины","path":"/docs/guide/cli/generator/generator#protobuf","headings":["Protobuf базовые плагины"],"excerpt":"Protobuf базовые плагины Имя плагина Описание Соответствующий protoc плагин ------------- ---------- ------------------------------- cpp Генерация C++ кода из proto файлов protoc-gen-cpp csharp Генерация C# кода из proto","content":"Protobuf базовые плагины Имя плагина Описание Соответствующий protoc плагин ------------- ---------- ------------------------------- cpp Генерация C++ кода из proto файлов protoc-gen-cpp csharp Генерация C# кода из proto файлов protoc-gen-csharp java Генерация Java кода из proto файлов protoc-gen-java kotlin Генерация Kotlin кода из proto файлов protoc-gen-kotlin objc Генерация Objective-C кода из proto файлов protoc-gen-objc php Генерация PHP кода из proto файлов protoc-gen-php python Генерация Python кода из proto файлов protoc-gen-python ruby Генерация Ruby кода из proto файлов protoc-gen-ruby"},{"id":"cli/generator/generator::grpc::71","title":"Генератор","section":"gRPC плагины","path":"/docs/guide/cli/generator/generator#grpc","headings":["gRPC плагины"],"excerpt":"gRPC плагины Следующие плагины встроены для генерации gRPC кода:","content":"gRPC плагины Следующие плагины встроены для генерации gRPC кода:"},{"id":"cli/generator/generator::grpc::72","title":"Генератор","section":"gRPC плагины","path":"/docs/guide/cli/generator/generator#grpc","headings":["gRPC плагины"],"excerpt":"gRPC плагины Имя плагина Описание Соответствующий protoc плагин ------------- ---------- ------------------------------- grpc_cpp Генерация gRPC кода для C++ grpc_cpp_plugin grpc_csharp Генерация gRPC кода для C# grpc_cs","content":"gRPC плагины Имя плагина Описание Соответствующий protoc плагин ------------- ---------- ------------------------------- grpc_cpp Генерация gRPC кода для C++ grpc_cpp_plugin grpc_csharp Генерация gRPC кода для C# grpc_csharp_plugin grpc_java Генерация gRPC кода для Java grpc_java_plugin grpc_node Генерация gRPC кода для Node.js grpc_node_plugin grpc_objc Генерация gRPC кода для Objective-C grpc_objective_c_plugin grpc_php Генерация gRPC кода для PHP grpc_php_plugin grpc_python Генерация gRPC кода для Python grpc_python_plugin grpc_ruby Генерация gRPC кода для Ruby grpc_ruby_plugin"},{"id":"cli/generator/generator::grpc::73","title":"Генератор","section":"gRPC плагины","path":"/docs/guide/cli/generator/generator#grpc","headings":["gRPC плагины"],"excerpt":"gRPC плагины **Логика выбора плагина:**","content":"gRPC плагины **Логика выбора плагина:**"},{"id":"cli/generator/generator::grpc::74","title":"Генератор","section":"gRPC плагины","path":"/docs/guide/cli/generator/generator#grpc","headings":["gRPC плагины"],"excerpt":"gRPC плагины EasyP использует следующий приоритет при выборе executor'а для плагина:","content":"gRPC плагины EasyP использует следующий приоритет при выборе executor'а для плагина:"},{"id":"cli/generator/generator::grpc::75","title":"Генератор","section":"gRPC плагины","path":"/docs/guide/cli/generator/generator#grpc","headings":["gRPC плагины"],"excerpt":"gRPC плагины **Удалённый плагин** (если указан url) — всегда имеет наивысший приоритет **Встроенный плагин** (если плагин встроен и не найден в PATH) — используется автоматически **Локальный плагин** (из PATH) — использу","content":"gRPC плагины **Удалённый плагин** (если указан url) — всегда имеет наивысший приоритет **Встроенный плагин** (если плагин встроен и не найден в PATH) — используется автоматически **Локальный плагин** (из PATH) — используется по умолчанию для обратной совместимости"},{"id":"cli/generator/generator::grpc::76","title":"Генератор","section":"gRPC плагины","path":"/docs/guide/cli/generator/generator#grpc","headings":["gRPC плагины"],"excerpt":"gRPC плагины **Пример использования:**","content":"gRPC плагины **Пример использования:**"},{"id":"cli/generator/generator::grpc::77","title":"Генератор","section":"gRPC плагины","path":"/docs/guide/cli/generator/generator#grpc","headings":["gRPC плагины"],"excerpt":"gRPC плагины Встроенные плагины включены в бинарник EasyP:","content":"gRPC плагины Встроенные плагины включены в бинарник EasyP:"},{"id":"cli/generator/generator::grpc::78","title":"Генератор","section":"gRPC плагины","path":"/docs/guide/cli/generator/generator#grpc","headings":["gRPC плагины"],"excerpt":"gRPC плагины ```bash Сборка go build ./cmd/easyp","content":"gRPC плагины ```bash Сборка go build ./cmd/easyp"},{"id":"cli/generator/generator::grpc::79","title":"Генератор","section":"gRPC плагины","path":"/docs/guide/cli/generator/generator#grpc","headings":["gRPC плагины"],"excerpt":"gRPC плагины Установка go install github.com/easyp-tech/easyp/cmd/easyp@latest ```","content":"gRPC плагины Установка go install github.com/easyp-tech/easyp/cmd/easyp@latest ```"},{"id":"cli/generator/generator::grpc::80","title":"Генератор","section":"gRPC плагины","path":"/docs/guide/cli/generator/generator#grpc","headings":["gRPC плагины"],"excerpt":"gRPC плагины **Обратная совместимость:**","content":"gRPC плагины **Обратная совместимость:**"},{"id":"cli/generator/generator::grpc::81","title":"Генератор","section":"gRPC плагины","path":"/docs/guide/cli/generator/generator#grpc","headings":["gRPC плагины"],"excerpt":"gRPC плагины Встроенные плагины полностью совместимы с существующими конфигурациями. Если плагин найден в PATH, он будет использован вместо встроенного. Это гарантирует, что:","content":"gRPC плагины Встроенные плагины полностью совместимы с существующими конфигурациями. Если плагин найден в PATH, он будет использован вместо встроенного. Это гарантирует, что:"},{"id":"cli/generator/generator::grpc::82","title":"Генератор","section":"gRPC плагины","path":"/docs/guide/cli/generator/generator#grpc","headings":["gRPC плагины"],"excerpt":"gRPC плагины Существующие конфигурации продолжают работать без изменений Можно переопределить встроенный плагин, установив его в системе Приоритет отдаётся локальным установкам для гибкости","content":"gRPC плагины Существующие конфигурации продолжают работать без изменений Можно переопределить встроенный плагин, установив его в системе Приоритет отдаётся локальным установкам для гибкости"},{"id":"cli/generator/generator::top::83","title":"Генератор","section":"Справочник опций плагинов","path":"/docs/guide/cli/generator/generator","headings":["Справочник опций плагинов"],"excerpt":"Справочник опций плагинов Ниже перечислены наиболее часто используемые плагины и их настройки. Каждый плагин имеет параметры, влияющие на результат генерации — понимание этих опций важно для получения нужного вывода.","content":"Справочник опций плагинов Ниже перечислены наиболее часто используемые плагины и их настройки. Каждый плагин имеет параметры, влияющие на результат генерации — понимание этих опций важно для получения нужного вывода."},{"id":"cli/generator/generator::go-plugins::84","title":"Генератор","section":"Go Plugins","path":"/docs/guide/cli/generator/generator#go-plugins","headings":["Go Plugins"],"excerpt":"Go Plugins Плагины для Go — самые зрелые и распространённые. Опция paths управляет тем, как формируются пути импортов; остальные опции дают тонкую настройку вывода.","content":"Go Plugins Плагины для Go — самые зрелые и распространённые. Опция paths управляет тем, как формируются пути импортов; остальные опции дают тонкую настройку вывода."},{"id":"cli/generator/generator::grpc-gateway-plugins::85","title":"Генератор","section":"gRPC-Gateway Plugins","path":"/docs/guide/cli/generator/generator#grpc-gateway-plugins","headings":["gRPC-Gateway Plugins"],"excerpt":"gRPC-Gateway Plugins Позволяют экспонировать gRPC сервисы как REST API и генерировать OpenAPI. Критично для HTTP/JSON поверх gRPC.","content":"gRPC-Gateway Plugins Позволяют экспонировать gRPC сервисы как REST API и генерировать OpenAPI. Критично для HTTP/JSON поверх gRPC."},{"id":"cli/generator/generator::validation-plugins::86","title":"Генератор","section":"Validation Plugins","path":"/docs/guide/cli/generator/generator#validation-plugins","headings":["Validation Plugins"],"excerpt":"Validation Plugins Генерируют код валидации на основе правил в proto, устраняя ручную проверку.","content":"Validation Plugins Генерируют код валидации на основе правил в proto, устраняя ручную проверку."},{"id":"cli/generator/generator::typescriptjavascript-plugins::87","title":"Генератор","section":"TypeScript/JavaScript Plugins","path":"/docs/guide/cli/generator/generator#typescriptjavascript-plugins","headings":["TypeScript/JavaScript Plugins"],"excerpt":"TypeScript/JavaScript Plugins TypeScript плагины нужны фронтенду: типобезопасные интерфейсы и клиенты.","content":"TypeScript/JavaScript Plugins TypeScript плагины нужны фронтенду: типобезопасные интерфейсы и клиенты."},{"id":"cli/generator/generator::managed-mode::88","title":"Генератор","section":"Managed Mode","path":"/docs/guide/cli/generator/generator#managed-mode","headings":["Managed Mode"],"excerpt":"Managed Mode Managed mode автоматически устанавливает file и field опции в protobuf дескрипторах во время генерации кода без изменения исходных .proto файлов. Эта функция совместима с managed mode в buf и обеспечивает ед","content":"Managed Mode Managed mode автоматически устанавливает file и field опции в protobuf дескрипторах во время генерации кода без изменения исходных .proto файлов. Эта функция совместима с managed mode в buf и обеспечивает единообразный способ управления языково-специфичными опциями в вашей кодовой базе."},{"id":"cli/generator/generator::managed-mode::89","title":"Генератор","section":"Managed Mode","path":"/docs/guide/cli/generator/generator#managed-mode","headings":["Managed Mode"],"excerpt":"Managed Mode **Ключевые преимущества:** **Без изменений proto файлов**: Опции применяются во время генерации, proto файлы остаются чистыми **Согласованные значения по умолчанию**: Автоматическое применение языковых согла","content":"Managed Mode **Ключевые преимущества:** **Без изменений proto файлов**: Опции применяются во время генерации, proto файлы остаются чистыми **Согласованные значения по умолчанию**: Автоматическое применение языковых соглашений об именовании **Централизованная конфигурация**: Управление всеми опциями в одном месте (easyp.yaml) **Правила для модулей**: Применение разных опций к разным модулям или путям **Совместимость с buf**: Работает так же, как managed mode в buf"},{"id":"cli/generator/generator::top::90","title":"Генератор","section":"Как это работает","path":"/docs/guide/cli/generator/generator","headings":["Как это работает"],"excerpt":"Как это работает Когда managed mode включён, EasyP автоматически применяет file и field опции к protobuf дескрипторам перед генерацией кода. Это происходит в памяти, поэтому исходные .proto файлы остаются неизменными.","content":"Как это работает Когда managed mode включён, EasyP автоматически применяет file и field опции к protobuf дескрипторам перед генерацией кода. Это происходит в памяти, поэтому исходные .proto файлы остаются неизменными."},{"id":"cli/generator/generator::top::91","title":"Генератор","section":"Как это работает","path":"/docs/guide/cli/generator/generator","headings":["Как это работает"],"excerpt":"Как это работает **Значения по умолчанию** применяются для определённых опций на основе языковых соглашений: Java: java_package_prefix по умолчанию \"com\", java_multiple_files по умолчанию true C#: csharp_namespace по умо","content":"Как это работает **Значения по умолчанию** применяются для определённых опций на основе языковых соглашений: Java: java_package_prefix по умолчанию \"com\", java_multiple_files по умолчанию true C#: csharp_namespace по умолчанию PascalCase имени пакета Ruby: ruby_package по умолчанию PascalCase с разделителем :: PHP: php_namespace по умолчанию PascalCase с разделителем \\ Objective-C: objc_class_prefix по умолчанию первые буквы частей пакета C++: cc_enable_arenas по умолчанию true"},{"id":"cli/generator/generator::top::92","title":"Генератор","section":"Как это работает","path":"/docs/guide/cli/generator/generator","headings":["Как это работает"],"excerpt":"Как это работает **Overrides** позволяют установить конкретные значения для опций с поддержкой фильтрации по модулю, protobuf package, пути или полю. Если не указаны module, package и path, override применяется ко всем ф","content":"Как это работает **Overrides** позволяют установить конкретные значения для опций с поддержкой фильтрации по модулю, protobuf package, пути или полю. Если не указаны module, package и path, override применяется ко всем файлам в запросе генерации, включая зависимости и git_repo inputs."},{"id":"cli/generator/generator::top::93","title":"Генератор","section":"Как это работает","path":"/docs/guide/cli/generator/generator","headings":["Как это работает"],"excerpt":"Как это работает **Disables** позволяют предотвратить изменение managed mode определённых опций или файлов. Это рекомендуемый способ исключить внешние зависимости, у которых свои опции уже заданы.","content":"Как это работает **Disables** позволяют предотвратить изменение managed mode определённых опций или файлов. Это рекомендуемый способ исключить внешние зависимости, у которых свои опции уже заданы."},{"id":"cli/generator/generator::top::94","title":"Генератор","section":"Конфигурация","path":"/docs/guide/cli/generator/generator","headings":["Конфигурация"],"excerpt":"Конфигурация ```yaml generate: managed: enabled: true disable: # Отключить managed mode для конкретного модуля - module: github.com/googleapis/googleapis # Отключить конкретную опцию глобально - file_option: java_package","content":"Конфигурация ```yaml generate: managed: enabled: true disable: # Отключить managed mode для конкретного модуля - module: github.com/googleapis/googleapis # Отключить конкретную опцию глобально - file_option: java_package_prefix"},{"id":"cli/generator/generator::top::95","title":"Генератор","section":"Конфигурация","path":"/docs/guide/cli/generator/generator","headings":["Конфигурация"],"excerpt":"Конфигурация Отключить для конкретного protobuf package - package: acme.weather.v1 file_option: java_package # Отключить для конкретного пути - path: legacy/ file_option: go_package # Отключить field опцию для конкретног","content":"Конфигурация Отключить для конкретного protobuf package - package: acme.weather.v1 file_option: java_package # Отключить для конкретного пути - path: legacy/ file_option: go_package # Отключить field опцию для конкретного поля - field_option: jstype field: com.example.User.id override: # Переопределить go_package_prefix для всех файлов - file_option: go_package_prefix value: github.com/mycompany/myproject/gen/go # Переопределить для конкретного модуля - file_option: java_package_prefix value: com.mycompany module: github.com/mycompany/internal-protos"},{"id":"cli/generator/generator::top::96","title":"Генератор","section":"Конфигурация","path":"/docs/guide/cli/generator/generator","headings":["Конфигурация"],"excerpt":"Конфигурация Переопределить для конкретного protobuf package - file_option: go_package_prefix value: github.com/mycompany/myproject/gen/go package: acme.weather.v1 # Переопределить для конкретного пути - file_option: csh","content":"Конфигурация Переопределить для конкретного protobuf package - file_option: go_package_prefix value: github.com/mycompany/myproject/gen/go package: acme.weather.v1 # Переопределить для конкретного пути - file_option: csharp_namespace_prefix value: MyCompany path: api/v1/ # Переопределить для нескольких файлов с одинаковым значением используя префиксный путь # Это совпадет и с internal/cms/bmi.proto, и с internal/cms/bmi_service.proto - file_option: go_package value: spec/cms/bmi path: \"internal/cms/bmi\" # Переопределить field опцию для конкретного пути - field_option: jstype value: JS_STRING path: api/v1/ # Переопределить для конкретного поля - field_option: jstype value: JS_NUMBER field: com.example.User.big_id ```"},{"id":"cli/generator/generator::file-options::97","title":"Генератор","section":"Поддерживаемые File Options","path":"/docs/guide/cli/generator/generator#file-options","headings":["Поддерживаемые File Options"],"excerpt":"Поддерживаемые File Options Опция Описание Есть значение по умолчанию? ------- ---------- ---------------------------- go_package Go import path ❌ go_package_prefix Префикс для Go import paths ❌ java_package Имя Java пак","content":"Поддерживаемые File Options Опция Описание Есть значение по умолчанию? ------- ---------- ---------------------------- go_package Go import path ❌ go_package_prefix Префикс для Go import paths ❌ java_package Имя Java пакета ❌ java_package_prefix Префикс для Java пакетов ✅ (\"com\") java_package_suffix Суффикс для Java пакетов ❌ java_multiple_files Генерировать несколько Java файлов ✅ (true) java_outer_classname Имя внешнего класса ✅ (PascalCase + \"Proto\") java_string_check_utf8 UTF-8 валидация ❌ csharp_namespace C# namespace ✅ (PascalCase) csharp_namespace_prefix Префикс для C# namespaces ❌ ruby_package Имя Ruby модуля ✅ (PascalCase с ::) ruby_package_suffix Суффикс для Ruby пакетов ❌ php_namespace PHP namespace ✅ (PascalCase с \\) php_metadata_namespace PHP metadata namespace ❌ php_metadata_namespace_suffix Суффикс для PHP metadata ❌ objc_class_prefix Objective-C префикс класса ✅ (Первые буквы) swift_prefix Swift префикс ❌ optimize_for Оптимизация генерации кода ❌ cc_enable_arenas C++ arena аллокация ✅ (true)"},{"id":"cli/generator/generator::field-options::98","title":"Генератор","section":"Поддерживаемые Field Options","path":"/docs/guide/cli/generator/generator#field-options","headings":["Поддерживаемые Field Options"],"excerpt":"Поддерживаемые Field Options Опция Описание Применяется к ------- ---------- --------------- jstype JavaScript тип для 64-битных целых чисел int64, uint64, sint64, fixed64, sfixed64","content":"Поддерживаемые Field Options Опция Описание Применяется к ------- ---------- --------------- jstype JavaScript тип для 64-битных целых чисел int64, uint64, sint64, fixed64, sfixed64"},{"id":"cli/generator/generator::top::99","title":"Генератор","section":"Базовая настройка со значениями по умолчанию","path":"/docs/guide/cli/generator/generator","headings":["Базовая настройка со значениями по умолчанию"],"excerpt":"Базовая настройка со значениями по умолчанию Включите managed mode для получения автоматических значений по умолчанию для всех поддерживаемых языков:","content":"Базовая настройка со значениями по умолчанию Включите managed mode для получения автоматических значений по умолчанию для всех поддерживаемых языков:"},{"id":"cli/generator/generator::top::100","title":"Генератор","section":"Базовая настройка со значениями по умолчанию","path":"/docs/guide/cli/generator/generator","headings":["Базовая настройка со значениями по умолчанию"],"excerpt":"Базовая настройка со значениями по умолчанию","content":"Базовая настройка со значениями по умолчанию"},{"id":"cli/generator/generator::top::101","title":"Генератор","section":"Базовая настройка со значениями по умолчанию","path":"/docs/guide/cli/generator/generator","headings":["Базовая настройка со значениями по умолчанию"],"excerpt":"Базовая настройка со значениями по умолчанию Это автоматически установит: java_package в com. для всех файлов java_multiple_files в true csharp_namespace в PascalCase имени пакета ruby_package в PascalCase с разделителем","content":"Базовая настройка со значениями по умолчанию Это автоматически установит: java_package в com. для всех файлов java_multiple_files в true csharp_namespace в PascalCase имени пакета ruby_package в PascalCase с разделителем :: И многое другое..."},{"id":"cli/generator/generator::go::102","title":"Генератор","section":"Кастомный префикс Go пакета","path":"/docs/guide/cli/generator/generator#go","headings":["Кастомный префикс Go пакета"],"excerpt":"Кастомный префикс Go пакета Переопределите префикс Go пакета для вашего проекта:","content":"Кастомный префикс Go пакета Переопределите префикс Go пакета для вашего проекта:"},{"id":"cli/generator/generator::go::103","title":"Генератор","section":"Кастомный префикс Go пакета","path":"/docs/guide/cli/generator/generator#go","headings":["Кастомный префикс Go пакета"],"excerpt":"Кастомный префикс Go пакета Это установит go_package в github.com/mycompany/myproject/gen/go/ для всех файлов.","content":"Кастомный префикс Go пакета Это установит go_package в github.com/mycompany/myproject/gen/go/ для всех файлов."},{"id":"cli/generator/generator::go::104","title":"Генератор","section":"Динамические пути Go пакетов с маркерами","path":"/docs/guide/cli/generator/generator#go","headings":["Динамические пути Go пакетов с маркерами"],"excerpt":"Динамические пути Go пакетов с маркерами Для более сложной генерации путей можно использовать маркеры в значениях go_package_prefix или go_package:","content":"Динамические пути Go пакетов с маркерами Для более сложной генерации путей можно использовать маркеры в значениях go_package_prefix или go_package:"},{"id":"cli/generator/generator::go::105","title":"Генератор","section":"Динамические пути Go пакетов с маркерами","path":"/docs/guide/cli/generator/generator#go","headings":["Динамические пути Go пакетов с маркерами"],"excerpt":"Динамические пути Go пакетов с маркерами","content":"Динамические пути Go пакетов с маркерами"},{"id":"cli/generator/generator::go::106","title":"Генератор","section":"Динамические пути Go пакетов с маркерами","path":"/docs/guide/cli/generator/generator#go","headings":["Динамические пути Go пакетов с маркерами"],"excerpt":"Динамические пути Go пакетов с маркерами **Доступные маркеры:** {{file_path}} - Полный путь файла без расширения .proto - Пример: internal/cms/as.proto → internal/cms/as {{file_dir}} - Только путь директории, без имени ф","content":"Динамические пути Go пакетов с маркерами **Доступные маркеры:** {{file_path}} - Полный путь файла без расширения .proto - Пример: internal/cms/as.proto → internal/cms/as {{file_dir}} - Только путь директории, без имени файла - Пример: internal/cms/as.proto → internal/cms {{file_dir_without:prefix/}} - Путь директории с удалением префикса и базового имени файла без суффиксов _service/_grpc - Пример: {{file_dir_without:internal/}} для internal/cms/as_service.proto → cms/as {{file_path_without:prefix/}} - Полный путь файла с удалением префикса - Пример: {{file_path_without:internal/}} для internal/cms/as.proto → cms/as"},{"id":"cli/generator/generator::top::107","title":"Генератор","section":"Переопределения для конкретных модулей","path":"/docs/guide/cli/generator/generator","headings":["Переопределения для конкретных модулей"],"excerpt":"Переопределения для конкретных модулей Примените разные опции к разным модулям:","content":"Переопределения для конкретных модулей Примените разные опции к разным модулям:"},{"id":"cli/generator/generator::top::108","title":"Генератор","section":"Переопределения для конкретных модулей","path":"/docs/guide/cli/generator/generator","headings":["Переопределения для конкретных модулей"],"excerpt":"Переопределения для конкретных модулей","content":"Переопределения для конкретных модулей"},{"id":"cli/generator/generator::top::109","title":"Генератор","section":"Переопределения для конкретных модулей","path":"/docs/guide/cli/generator/generator","headings":["Переопределения для конкретных модулей"],"excerpt":"Переопределения для конкретных модулей module должен точно совпадать с источником модуля в EasyP: это значение из deps или git_repo.url до @version (например, github.com/mycompany/internal-protos или https://github.com/m","content":"Переопределения для конкретных модулей module должен точно совпадать с источником модуля в EasyP: это значение из deps или git_repo.url до @version (например, github.com/mycompany/internal-protos или https://github.com/mycompany/internal-protos). Это не Go module path из go.mod."},{"id":"cli/generator/generator::top::110","title":"Генератор","section":"Переопределения для конкретных модулей","path":"/docs/guide/cli/generator/generator","headings":["Переопределения для конкретных модулей"],"excerpt":"Переопределения для конкретных модулей package должен точно совпадать со значением package в .proto файле, например acme.weather.v1.","content":"Переопределения для конкретных модулей package должен точно совпадать со значением package в .proto файле, например acme.weather.v1."},{"id":"cli/generator/generator::protobuf-package::111","title":"Генератор","section":"Переопределения для конкретного protobuf package","path":"/docs/guide/cli/generator/generator#protobuf-package","headings":["Переопределения для конкретного protobuf package"],"excerpt":"Переопределения для конкретного protobuf package Примените отдельные опции к файлам из конкретного protobuf package:","content":"Переопределения для конкретного protobuf package Примените отдельные опции к файлам из конкретного protobuf package:"},{"id":"cli/generator/generator::protobuf-package::112","title":"Генератор","section":"Переопределения для конкретного protobuf package","path":"/docs/guide/cli/generator/generator#protobuf-package","headings":["Переопределения для конкретного protobuf package"],"excerpt":"Переопределения для конкретного protobuf package","content":"Переопределения для конкретного protobuf package"},{"id":"cli/generator/generator::top::113","title":"Генератор","section":"Отключение для внешних зависимостей","path":"/docs/guide/cli/generator/generator","headings":["Отключение для внешних зависимостей"],"excerpt":"Отключение для внешних зависимостей Отключите managed mode для внешних зависимостей, у которых уже установлены опции:","content":"Отключение для внешних зависимостей Отключите managed mode для внешних зависимостей, у которых уже установлены опции:"},{"id":"cli/generator/generator::top::114","title":"Генератор","section":"Отключение для внешних зависимостей","path":"/docs/guide/cli/generator/generator","headings":["Отключение для внешних зависимостей"],"excerpt":"Отключение для внешних зависимостей","content":"Отключение для внешних зависимостей"},{"id":"cli/generator/generator::javascript::115","title":"Генератор","section":"Типобезопасность JavaScript","path":"/docs/guide/cli/generator/generator#javascript","headings":["Типобезопасность JavaScript"],"excerpt":"Типобезопасность JavaScript Установите jstype в JS_STRING для всех 64-битных целочисленных полей, чтобы предотвратить потерю точности в JavaScript:","content":"Типобезопасность JavaScript Установите jstype в JS_STRING для всех 64-битных целочисленных полей, чтобы предотвратить потерю точности в JavaScript:"},{"id":"cli/generator/generator::top::116","title":"Генератор","section":"Совпадение путей","path":"/docs/guide/cli/generator/generator","headings":["Совпадение путей"],"excerpt":"Совпадение путей Совпадение путей в managed mode использует префиксное совпадение (как в buf):","content":"Совпадение путей Совпадение путей в managed mode использует префиксное совпадение (как в buf):"},{"id":"cli/generator/generator::top::117","title":"Генератор","section":"Совпадение путей","path":"/docs/guide/cli/generator/generator","headings":["Совпадение путей"],"excerpt":"Совпадение путей **Путь директории** (заканчивается на /): Совпадает со всеми файлами в этой директории и поддиректориях - Пример: path: \"internal/cms/\" совпадает с internal/cms/as.proto, internal/cms/node.proto, interna","content":"Совпадение путей **Путь директории** (заканчивается на /): Совпадает со всеми файлами в этой директории и поддиректориях - Пример: path: \"internal/cms/\" совпадает с internal/cms/as.proto, internal/cms/node.proto, internal/cms/v1/service.proto **Точный путь файла** (заканчивается на .proto): Совпадает только с этим конкретным файлом - Пример: path: \"internal/cms/as.proto\" совпадает только с internal/cms/as.proto **Префиксный путь** (без завершающего / или .proto): Использует префиксное совпадение (не директориально-осознанное) - Пример: path: \"internal/cms\" совпадает с internal/cms/as.proto, но также с internal/cmsv2/file.proto - **Совет**: Используйте префиксные пути для группировки нескольких файлов с одинаковым значением. Например, path: \"internal/cms/bmi\" совпадает и с internal/cms/bmi.proto, и с internal/cms/bmi_service.proto, что позволяет установить одно и то же значение go_package для обоих файлов одним правилом."},{"id":"cli/generator/generator::top::118","title":"Генератор","section":"Приоритет правил","path":"/docs/guide/cli/generator/generator","headings":["Приоритет правил"],"excerpt":"Приоритет правил Когда несколько правил соответствуют одному файлу или полю, применяется следующий приоритет:","content":"Приоритет правил Когда несколько правил соответствуют одному файлу или полю, применяется следующий приоритет:"},{"id":"cli/generator/generator::top::119","title":"Генератор","section":"Приоритет правил","path":"/docs/guide/cli/generator/generator","headings":["Приоритет правил"],"excerpt":"Приоритет правил **Disable правила** имеют приоритет — если опция отключена, она не будет применена **Override правила** применяются по порядку — последнее совпадающее правило побеждает **Значения по умолчанию** применяю","content":"Приоритет правил **Disable правила** имеют приоритет — если опция отключена, она не будет применена **Override правила** применяются по порядку — последнее совпадающее правило побеждает **Значения по умолчанию** применяются только если нет совпадающего override и опция не отключена"},{"id":"cli/generator/generator::buf::120","title":"Генератор","section":"Совместимость с buf","path":"/docs/guide/cli/generator/generator#buf","headings":["Совместимость с buf"],"excerpt":"Совместимость с buf Managed mode в EasyP совместим с managed mode в buf. Тот же формат конфигурации и поведение применяются, что упрощает миграцию между инструментами или использование обоих в одном workflow.","content":"Совместимость с buf Managed mode в EasyP совместим с managed mode в buf. Тот же формат конфигурации и поведение применяются, что упрощает миграцию между инструментами или использование обоих в одном workflow."},{"id":"cli/generator/generator::descriptor-set::121","title":"Генератор","section":"Генерация Descriptor Set","path":"/docs/guide/cli/generator/generator#descriptor-set","headings":["Генерация Descriptor Set"],"excerpt":"Генерация Descriptor Set **https://protobuf.dev/programming-guides/techniques/#self-description**","content":"Генерация Descriptor Set **https://protobuf.dev/programming-guides/techniques/#self-description**"},{"id":"cli/generator/generator::descriptor-set::122","title":"Генератор","section":"Генерация Descriptor Set","path":"/docs/guide/cli/generator/generator#descriptor-set","headings":["Генерация Descriptor Set"],"excerpt":"Генерация Descriptor Set EasyP поддерживает генерацию бинарных FileDescriptorSet файлов с помощью флага --descriptor_set_out. Это позволяет создавать самоописывающиеся protobuf сообщения, которые включают информацию о сх","content":"Генерация Descriptor Set EasyP поддерживает генерацию бинарных FileDescriptorSet файлов с помощью флага --descriptor_set_out. Это позволяет создавать самоописывающиеся protobuf сообщения, которые включают информацию о схеме вместе с данными."},{"id":"cli/generator/generator::descriptor-set::123","title":"Генератор","section":"Генерация Descriptor Set","path":"/docs/guide/cli/generator/generator#descriptor-set","headings":["Генерация Descriptor Set"],"excerpt":"Генерация Descriptor Set **Флаги CLI:**","content":"Генерация Descriptor Set **Флаги CLI:**"},{"id":"cli/generator/generator::descriptor-set::124","title":"Генератор","section":"Генерация Descriptor Set","path":"/docs/guide/cli/generator/generator#descriptor-set","headings":["Генерация Descriptor Set"],"excerpt":"Генерация Descriptor Set --descriptor_set_out - Путь для вывода бинарного FileDescriptorSet --include_imports - Включить все транзитивные зависимости в FileDescriptorSet","content":"Генерация Descriptor Set --descriptor_set_out - Путь для вывода бинарного FileDescriptorSet --include_imports - Включить все транзитивные зависимости в FileDescriptorSet"},{"id":"cli/generator/generator::descriptor-set::125","title":"Генератор","section":"Генерация Descriptor Set","path":"/docs/guide/cli/generator/generator#descriptor-set","headings":["Генерация Descriptor Set"],"excerpt":"Генерация Descriptor Set **Пример:**","content":"Генерация Descriptor Set **Пример:**"},{"id":"cli/generator/generator::descriptor-set::126","title":"Генератор","section":"Генерация Descriptor Set","path":"/docs/guide/cli/generator/generator#descriptor-set","headings":["Генерация Descriptor Set"],"excerpt":"Генерация Descriptor Set ```bash Генерация descriptor set только с целевыми файлами easyp generate --descriptor_set_out=./schema.pb","content":"Генерация Descriptor Set ```bash Генерация descriptor set только с целевыми файлами easyp generate --descriptor_set_out=./schema.pb"},{"id":"cli/generator/generator::descriptor-set::127","title":"Генератор","section":"Генерация Descriptor Set","path":"/docs/guide/cli/generator/generator#descriptor-set","headings":["Генерация Descriptor Set"],"excerpt":"Генерация Descriptor Set Генерация descriptor set со всеми зависимостями easyp generate --descriptor_set_out=./schema.pb --include_imports ```","content":"Генерация Descriptor Set Генерация descriptor set со всеми зависимостями easyp generate --descriptor_set_out=./schema.pb --include_imports ```"},{"id":"cli/generator/generator::descriptor-set::128","title":"Генератор","section":"Генерация Descriptor Set","path":"/docs/guide/cli/generator/generator#descriptor-set","headings":["Генерация Descriptor Set"],"excerpt":"Генерация Descriptor Set Самоописывающиеся сообщения полезны для динамического парсинга сообщений, валидации схемы во время выполнения, реестров схем и создания универсальных gRPC клиентов. Для получения дополнительной и","content":"Генерация Descriptor Set Самоописывающиеся сообщения полезны для динамического парсинга сообщений, валидации схемы во время выполнения, реестров схем и создания универсальных gRPC клиентов. Для получения дополнительной информации см. документацию Protocol Buffers о самоописании."},{"id":"cli/generator/generator::top::129","title":"Генератор","section":"Интеграция с менеджером пакетов","path":"/docs/guide/cli/generator/generator","headings":["Интеграция с менеджером пакетов"],"excerpt":"Интеграция с менеджером пакетов Одной из самых мощных возможностей EasyP является бесшовная интеграция генератора кода с менеджером пакетов. Это устраняет проблему ручного управления proto‑зависимостями и гарантирует, чт","content":"Интеграция с менеджером пакетов Одной из самых мощных возможностей EasyP является бесшовная интеграция генератора кода с менеджером пакетов. Это устраняет проблему ручного управления proto‑зависимостями и гарантирует, что при генерации используются корректные (зафиксированные) версии импортируемых файлов."},{"id":"cli/generator/generator::top::130","title":"Генератор","section":"Интеграция с менеджером пакетов","path":"/docs/guide/cli/generator/generator","headings":["Интеграция с менеджером пакетов"],"excerpt":"Интеграция с менеджером пакетов **Ключевые преимущества:** **Автоматическое разрешение зависимостей**: не нужно вручную прописывать пути импортов **Согласованность версий**: фиксация в easyp.lock гарантирует воспроизводи","content":"Интеграция с менеджером пакетов **Ключевые преимущества:** **Автоматическое разрешение зависимостей**: не нужно вручную прописывать пути импортов **Согласованность версий**: фиксация в easyp.lock гарантирует воспроизводимость **Транзитивные зависимости**: вложенные цепочки подтягиваются автоматически **Производительность**: локальный кеш — скачивание один раз и повторное использование"},{"id":"cli/generator/generator::top::131","title":"Генератор","section":"Автоматическое разрешение зависимостей","path":"/docs/guide/cli/generator/generator","headings":["Автоматическое разрешение зависимостей"],"excerpt":"Автоматическое разрешение зависимостей Когда вы указываете зависимости в секции deps, генератор автоматически добавляет их в путь импортов. Ваши proto‑файлы могут делать стандартные import из этих зависимостей без дополн","content":"Автоматическое разрешение зависимостей Когда вы указываете зависимости в секции deps, генератор автоматически добавляет их в путь импортов. Ваши proto‑файлы могут делать стандартные import из этих зависимостей без дополнительной настройки."},{"id":"cli/generator/generator::top::132","title":"Генератор","section":"Автоматическое разрешение зависимостей","path":"/docs/guide/cli/generator/generator","headings":["Автоматическое разрешение зависимостей"],"excerpt":"Автоматическое разрешение зависимостей **Как это работает:** EasyP скачивает и кеширует зависимости из deps Во время генерации кешированные файлы автоматически добавляются в import‑path protoc Ваши proto‑файлы используют","content":"Автоматическое разрешение зависимостей **Как это работает:** EasyP скачивает и кеширует зависимости из deps Во время генерации кешированные файлы автоматически добавляются в import‑path protoc Ваши proto‑файлы используют обычные import строки для обращения к зависимостям При with_imports: true в вывод попадают и локальные файлы, и файлы зависимостей"},{"id":"cli/generator/generator::top::133","title":"Генератор","section":"Автоматическое разрешение зависимостей","path":"/docs/guide/cli/generator/generator","headings":["Автоматическое разрешение зависимостей"],"excerpt":"Автоматическое разрешение зависимостей Ниже простой пример — зависимости указываются один раз в deps, далее они доступны при генерации автоматически:","content":"Автоматическое разрешение зависимостей Ниже простой пример — зависимости указываются один раз в deps, далее они доступны при генерации автоматически:"},{"id":"cli/generator/generator::top::134","title":"Генератор","section":"Автоматическое разрешение зависимостей","path":"/docs/guide/cli/generator/generator","headings":["Автоматическое разрешение зависимостей"],"excerpt":"Автоматическое разрешение зависимостей ```yaml deps: - github.com/googleapis/googleapis@common-protos-1_3_1 - github.com/grpc-ecosystem/grpc-gateway@v2.19.1","content":"Автоматическое разрешение зависимостей ```yaml deps: - github.com/googleapis/googleapis@common-protos-1_3_1 - github.com/grpc-ecosystem/grpc-gateway@v2.19.1"},{"id":"cli/generator/generator::top::135","title":"Генератор","section":"Автоматическое разрешение зависимостей","path":"/docs/guide/cli/generator/generator","headings":["Автоматическое разрешение зависимостей"],"excerpt":"Автоматическое разрешение зависимостей generate: inputs: - directory: \"proto\" plugins: - name: go out: ./gen/go opts: paths: source_relative with_imports: true # This automatically includes googleapis and grpc-gateway pr","content":"Автоматическое разрешение зависимостей 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::top::136","title":"Генератор","section":"Примеры использования зависимостей","path":"/docs/guide/cli/generator/generator","headings":["Примеры использования зависимостей"],"excerpt":"Примеры использования зависимостей Ниже показаны распространённые способы интеграции внешних proto‑зависимостей в процесс генерации.","content":"Примеры использования зависимостей Ниже показаны распространённые способы интеграции внешних proto‑зависимостей в процесс генерации."},{"id":"cli/generator/generator::google-apis::137","title":"Генератор","section":"Использование Google APIs","path":"/docs/guide/cli/generator/generator#google-apis","headings":["Использование Google APIs"],"excerpt":"Использование Google APIs Google APIs — одна из самых популярных коллекций зависимостей: стандартные типы, аннотации для REST, проверки и общие структуры данных.","content":"Использование Google APIs Google APIs — одна из самых популярных коллекций зависимостей: стандартные типы, аннотации для REST, проверки и общие структуры данных."},{"id":"cli/generator/generator::google-apis::138","title":"Генератор","section":"Использование Google APIs","path":"/docs/guide/cli/generator/generator#google-apis","headings":["Использование Google APIs"],"excerpt":"Использование Google APIs **Когда использовать Google APIs:** Построение REST поверх gRPC (gRPC-Gateway) Нужны стандартные типы (Timestamp, Duration, Any) Требуются аннотации поведения полей (field behavior) Интеграция с","content":"Использование Google APIs **Когда использовать Google APIs:** Построение REST поверх gRPC (gRPC-Gateway) Нужны стандартные типы (Timestamp, Duration, Any) Требуются аннотации поведения полей (field behavior) Интеграция с сервисами Google Cloud"},{"id":"cli/generator/generator::google-apis::139","title":"Генератор","section":"Использование Google APIs","path":"/docs/guide/cli/generator/generator#google-apis","headings":["Использование Google APIs"],"excerpt":"Использование Google APIs Минимальная конфигурация для подключения Google APIs:","content":"Использование Google APIs Минимальная конфигурация для подключения Google APIs:"},{"id":"cli/generator/generator::google-apis::140","title":"Генератор","section":"Использование Google APIs","path":"/docs/guide/cli/generator/generator#google-apis","headings":["Использование Google APIs"],"excerpt":"Использование Google APIs ```yaml deps: - github.com/googleapis/googleapis@common-protos-1_3_1","content":"Использование Google APIs ```yaml deps: - github.com/googleapis/googleapis@common-protos-1_3_1"},{"id":"cli/generator/generator::google-apis::141","title":"Генератор","section":"Использование Google APIs","path":"/docs/guide/cli/generator/generator#google-apis","headings":["Использование Google APIs"],"excerpt":"Использование Google APIs generate: inputs: - directory: \"api/proto\" plugins: - name: go out: ./gen/go opts: paths: source_relative with_imports: true ```","content":"Использование Google APIs generate: inputs: - directory: \"api/proto\" plugins: - name: go out: ./gen/go opts: paths: source_relative with_imports: true ```"},{"id":"cli/generator/generator::google-apis::142","title":"Генератор","section":"Использование Google APIs","path":"/docs/guide/cli/generator/generator#google-apis","headings":["Использование Google APIs"],"excerpt":"Использование Google APIs **Важно:** Всегда фиксируйте версию (например common-protos-1_3_1) — не используйте latest в продакшене.","content":"Использование Google APIs **Важно:** Всегда фиксируйте версию (например common-protos-1_3_1) — не используйте latest в продакшене."},{"id":"cli/generator/generator::google-apis::143","title":"Генератор","section":"Использование Google APIs","path":"/docs/guide/cli/generator/generator#google-apis","headings":["Использование Google APIs"],"excerpt":"Использование Google APIs После настройки ваши proto могут импортировать определения Google API. Ниже пример сервиса с HTTP аннотацией:","content":"Использование Google APIs После настройки ваши proto могут импортировать определения Google API. Ниже пример сервиса с HTTP аннотацией:"},{"id":"cli/generator/generator::google-apis::144","title":"Генератор","section":"Использование Google APIs","path":"/docs/guide/cli/generator/generator#google-apis","headings":["Использование Google APIs"],"excerpt":"Использование Google APIs ```proto // api/proto/service.proto syntax = \"proto3\";","content":"Использование Google APIs ```proto // api/proto/service.proto syntax = \"proto3\";"},{"id":"cli/generator/generator::google-apis::145","title":"Генератор","section":"Использование Google APIs","path":"/docs/guide/cli/generator/generator#google-apis","headings":["Использование Google APIs"],"excerpt":"Использование Google APIs import \"google/api/annotations.proto\"; import \"google/protobuf/timestamp.proto\";","content":"Использование Google APIs import \"google/api/annotations.proto\"; import \"google/protobuf/timestamp.proto\";"},{"id":"cli/generator/generator::google-apis::146","title":"Генератор","section":"Использование Google APIs","path":"/docs/guide/cli/generator/generator#google-apis","headings":["Использование Google APIs"],"excerpt":"Использование Google APIs service MyService { rpc GetData(GetDataRequest) returns (GetDataResponse) { option (google.api.http) = { get: \"/v1/data\" }; } } ```","content":"Использование Google APIs service MyService { rpc GetData(GetDataRequest) returns (GetDataResponse) { option (google.api.http) = { get: \"/v1/data\" }; } } ```"},{"id":"cli/generator/generator::top::147","title":"Генератор","section":"Использование правил валидации","path":"/docs/guide/cli/generator/generator","headings":["Использование правил валидации"],"excerpt":"Использование правил валидации protoc-gen-validate даёт мощную проверку полей прямо в определениях proto, устраняя необходимость писать отдельную логику валидации в приложении.","content":"Использование правил валидации protoc-gen-validate даёт мощную проверку полей прямо в определениях proto, устраняя необходимость писать отдельную логику валидации в приложении."},{"id":"cli/generator/generator::top::148","title":"Генератор","section":"Использование правил валидации","path":"/docs/guide/cli/generator/generator","headings":["Использование правил валидации"],"excerpt":"Использование правил валидации **Когда применять валидацию:** Проверка входных данных API Ограничения моделей БД Проверка конфигурационных файлов Любая ситуация, где критична целостность данных","content":"Использование правил валидации **Когда применять валидацию:** Проверка входных данных API Ограничения моделей БД Проверка конфигурационных файлов Любая ситуация, где критична целостность данных"},{"id":"cli/generator/generator::top::149","title":"Генератор","section":"Использование правил валидации","path":"/docs/guide/cli/generator/generator","headings":["Использование правил валидации"],"excerpt":"Использование правил валидации **Преимущества:** Правила валидации — часть proto (единый источник истины) Генерация создаёт функции проверки автоматически Единообразие проверок между языками Производительнее чем проверка","content":"Использование правил валидации **Преимущества:** Правила валидации — часть proto (единый источник истины) Генерация создаёт функции проверки автоматически Единообразие проверок между языками Производительнее чем проверка через runtime reflection"},{"id":"cli/generator/generator::top::150","title":"Генератор","section":"Использование правил валидации","path":"/docs/guide/cli/generator/generator","headings":["Использование правил валидации"],"excerpt":"Использование правил валидации ```yaml deps: - github.com/bufbuild/protoc-gen-validate@v0.10.1","content":"Использование правил валидации ```yaml deps: - github.com/bufbuild/protoc-gen-validate@v0.10.1"},{"id":"cli/generator/generator::top::151","title":"Генератор","section":"Использование правил валидации","path":"/docs/guide/cli/generator/generator","headings":["Использование правил валидации"],"excerpt":"Использование правил валидации 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":"Использование правил валидации 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::top::152","title":"Генератор","section":"Использование правил валидации","path":"/docs/guide/cli/generator/generator","headings":["Использование правил валидации"],"excerpt":"Использование правил валидации **Примечание:** Нужны одновременно зависимость (для импортов proto) и плагин (для генерации кода), чтобы получить полноценную поддержку валидации.","content":"Использование правил валидации **Примечание:** Нужны одновременно зависимость (для импортов proto) и плагин (для генерации кода), чтобы получить полноценную поддержку валидации."},{"id":"cli/generator/generator::top::153","title":"Генератор","section":"Использование правил валидации","path":"/docs/guide/cli/generator/generator","headings":["Использование правил валидации"],"excerpt":"Использование правил валидации Так выглядят правила валидации в proto — сгенерированный код будет автоматически их применять:","content":"Использование правил валидации Так выглядят правила валидации в proto — сгенерированный код будет автоматически их применять:"},{"id":"cli/generator/generator::top::154","title":"Генератор","section":"Использование правил валидации","path":"/docs/guide/cli/generator/generator","headings":["Использование правил валидации"],"excerpt":"Использование правил валидации ```proto // proto/user.proto syntax = \"proto3\";","content":"Использование правил валидации ```proto // proto/user.proto syntax = \"proto3\";"},{"id":"cli/generator/generator::top::155","title":"Генератор","section":"Использование правил валидации","path":"/docs/guide/cli/generator/generator","headings":["Использование правил валидации"],"excerpt":"Использование правил валидации import \"validate/validate.proto\";","content":"Использование правил валидации import \"validate/validate.proto\";"},{"id":"cli/generator/generator::top::156","title":"Генератор","section":"Использование правил валидации","path":"/docs/guide/cli/generator/generator","headings":["Использование правил валидации"],"excerpt":"Использование правил валидации message User { string email = 1 [(validate.rules).string.email = true]; int32 age = 2 [(validate.rules).int32.gte = 0]; } ```","content":"Использование правил валидации message User { string email = 1 [(validate.rules).string.email = true]; int32 age = 2 [(validate.rules).int32.gte = 0]; } ```"},{"id":"cli/generator/generator::top::157","title":"Генератор","section":"Комплексная конфигурация с несколькими зависимостями","path":"/docs/guide/cli/generator/generator","headings":["Комплексная конфигурация с несколькими зависимостями"],"excerpt":"Комплексная конфигурация с несколькими зависимостями Пример ниже показывает продакшен‑конфигурацию, объединяющую несколько зависимостей и плагины для полного цикла разработки API:","content":"Комплексная конфигурация с несколькими зависимостями Пример ниже показывает продакшен‑конфигурацию, объединяющую несколько зависимостей и плагины для полного цикла разработки API:"},{"id":"cli/generator/generator::top::158","title":"Генератор","section":"Комплексная конфигурация с несколькими зависимостями","path":"/docs/guide/cli/generator/generator","headings":["Комплексная конфигурация с несколькими зависимостями"],"excerpt":"Комплексная конфигурация с несколькими зависимостями ```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 HT","content":"Комплексная конфигурация с несколькими зависимостями ```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::top::159","title":"Генератор","section":"Комплексная конфигурация с несколькими зависимостями","path":"/docs/guide/cli/generator/generator","headings":["Комплексная конфигурация с несколькими зависимостями"],"excerpt":"Комплексная конфигурация с несколькими зависимостями generate: inputs: - directory: \"api/proto\" plugins: # Go code generation - Core protobuf structures - name: go out: ./gen/go opts: paths: source_relative module: githu","content":"Комплексная конфигурация с несколькими зависимостями 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::top::160","title":"Генератор","section":"Интеграция с кешем зависимостей","path":"/docs/guide/cli/generator/generator","headings":["Интеграция с кешем зависимостей"],"excerpt":"Интеграция с кешем зависимостей Генератор использует модульный кеш EasyP для ускорения сборок:","content":"Интеграция с кешем зависимостей Генератор использует модульный кеш EasyP для ускорения сборок:"},{"id":"cli/generator/generator::top::161","title":"Генератор","section":"Интеграция с кешем зависимостей","path":"/docs/guide/cli/generator/generator","headings":["Интеграция с кешем зависимостей"],"excerpt":"Интеграция с кешем зависимостей ```bash Download dependencies once easyp mod download","content":"Интеграция с кешем зависимостей ```bash Download dependencies once easyp mod download"},{"id":"cli/generator/generator::top::162","title":"Генератор","section":"Интеграция с кешем зависимостей","path":"/docs/guide/cli/generator/generator","headings":["Интеграция с кешем зависимостей"],"excerpt":"Интеграция с кешем зависимостей Generate code (uses cached dependencies) easyp generate","content":"Интеграция с кешем зависимостей Generate code (uses cached dependencies) easyp generate"},{"id":"cli/generator/generator::top::163","title":"Генератор","section":"Интеграция с кешем зависимостей","path":"/docs/guide/cli/generator/generator","headings":["Интеграция с кешем зависимостей"],"excerpt":"Интеграция с кешем зависимостей Dependencies are cached in ~/.easyp/mod/ ls ~/.easyp/mod/github.com/googleapis/googleapis/ ```","content":"Интеграция с кешем зависимостей Dependencies are cached in ~/.easyp/mod/ ls ~/.easyp/mod/github.com/googleapis/googleapis/ ```"},{"id":"cli/generator/generator::top::164","title":"Генератор","section":"Удалённая генерация","path":"/docs/guide/cli/generator/generator","headings":["Удалённая генерация"],"excerpt":"Удалённая генерация Удалённая генерация — мощная возможность, позволяющая генерировать код из proto‑файлов в удалённых Git‑репозиториях без локального checkout. Это поддерживает микросервисную архитектуру, где команды ис","content":"Удалённая генерация Удалённая генерация — мощная возможность, позволяющая генерировать код из proto‑файлов в удалённых Git‑репозиториях без локального checkout. Это поддерживает микросервисную архитектуру, где команды используют API друг друга без жёсткой связки."},{"id":"cli/generator/generator::top::165","title":"Генератор","section":"Удалённая генерация","path":"/docs/guide/cli/generator/generator","headings":["Удалённая генерация"],"excerpt":"Удалённая генерация **Преимущества:** **Развязка разработки**: Команды развиваются независимо, используя версии API друг друга **Контроль версий**: Фиксация внешних API гарантирует стабильность **Меньше размер репозитори","content":"Удалённая генерация **Преимущества:** **Развязка разработки**: Команды развиваются независимо, используя версии API друг друга **Контроль версий**: Фиксация внешних API гарантирует стабильность **Меньше размер репозитория**: Нет необходимости в vendoring/submodule внешних proto **Автоматические обновления**: Легко перейти на новую версию по готовности"},{"id":"cli/generator/generator::top::166","title":"Генератор","section":"Удалённая генерация","path":"/docs/guide/cli/generator/generator","headings":["Удалённая генерация"],"excerpt":"Удалённая генерация **Рекомендации:** В продакшене используйте только тегированные версии В разработке можно тестировать latest, но в проде фиксируйте При наличии используйте семантическое версионирование Учитывайте сете","content":"Удалённая генерация **Рекомендации:** В продакшене используйте только тегированные версии В разработке можно тестировать latest, но в проде фиксируйте При наличии используйте семантическое версионирование Учитывайте сетевые ограничения в CI/CD"},{"id":"cli/generator/generator::proto::167","title":"Генератор","section":"Источники удалённых proto","path":"/docs/guide/cli/generator/generator#proto","headings":["Источники удалённых proto"],"excerpt":"Источники удалённых proto Генерация напрямую из удалённых репозиториев — полезно в микросервисной архитектуре, где разные команды владеют разными proto.","content":"Источники удалённых proto Генерация напрямую из удалённых репозиториев — полезно в микросервисной архитектуре, где разные команды владеют разными proto."},{"id":"cli/generator/generator::proto::168","title":"Генератор","section":"Источники удалённых proto","path":"/docs/guide/cli/generator/generator#proto","headings":["Источники удалённых proto"],"excerpt":"Источники удалённых proto **Типовой workflow:** Команда A публикует proto с версиями в Git Команда B добавляет их в свой easyp.yaml При генерации EasyP скачивает и подключает удалённые proto Сгенерированный код содержит ","content":"Источники удалённых proto **Типовой workflow:** Команда A публикует proto с версиями в Git Команда B добавляет их в свой easyp.yaml При генерации EasyP скачивает и подключает удалённые proto Сгенерированный код содержит клиентские библиотеки сервисов команды A"},{"id":"cli/generator/generator::proto::169","title":"Генератор","section":"Источники удалённых proto","path":"/docs/guide/cli/generator/generator#proto","headings":["Источники удалённых proto"],"excerpt":"Источники удалённых proto Практический пример объединения локальных и удалённых источников в одной конфигурации генерации:","content":"Источники удалённых proto Практический пример объединения локальных и удалённых источников в одной конфигурации генерации:"},{"id":"cli/generator/generator::top::170","title":"Генератор","section":"Сценарии использования удалённой генерации","path":"/docs/guide/cli/generator/generator","headings":["Сценарии использования удалённой генерации"],"excerpt":"Сценарии использования удалённой генерации Примеры ниже показывают реальные ситуации, где удалённая генерация даёт ощутимую выгоду.","content":"Сценарии использования удалённой генерации Примеры ниже показывают реальные ситуации, где удалённая генерация даёт ощутимую выгоду."},{"id":"cli/generator/generator::multi-team-development::171","title":"Генератор","section":"Много команд (Multi-Team Development)","path":"/docs/guide/cli/generator/generator#multi-team-development","headings":["Много команд (Multi-Team Development)"],"excerpt":"Много команд (Multi-Team Development) Мультикомандная разработка особенно выигрывает: вместо координации общих репозиториев и сложного управления зависимостями — независимая эволюция API с контролируемыми обновлениями че","content":"Много команд (Multi-Team Development) Мультикомандная разработка особенно выигрывает: вместо координации общих репозиториев и сложного управления зависимостями — независимая эволюция API с контролируемыми обновлениями через версии."},{"id":"cli/generator/generator::multi-team-development::172","title":"Генератор","section":"Много команд (Multi-Team Development)","path":"/docs/guide/cli/generator/generator#multi-team-development","headings":["Много команд (Multi-Team Development)"],"excerpt":"Много команд (Multi-Team Development) Паттерн ценен в крупных организациях, где: Команды имеют разные циклы релизов и скорости разработки Владение API определено, потребление — массовое Нужно избежать overhead от координ","content":"Много команд (Multi-Team Development) Паттерн ценен в крупных организациях, где: Команды имеют разные циклы релизов и скорости разработки Владение API определено, потребление — массовое Нужно избежать overhead от координации общих proto репозиториев Команды используют разные стеки, но должны взаимодействовать"},{"id":"cli/generator/generator::multi-team-development::173","title":"Генератор","section":"Много команд (Multi-Team Development)","path":"/docs/guide/cli/generator/generator#multi-team-development","headings":["Много команд (Multi-Team Development)"],"excerpt":"Много команд (Multi-Team Development)","content":"Много команд (Multi-Team Development)"},{"id":"cli/generator/generator::api::174","title":"Генератор","section":"Интеграция с API вендоров","path":"/docs/guide/cli/generator/generator#api","headings":["Интеграция с API вендоров"],"excerpt":"Интеграция с API вендоров Многие вендоры публикуют proto для своих API, позволяя генерировать типобезопасных клиентов вместо ручных HTTP реализаций. Это повышает типовую строгость, автоматизирует сериализацию и часто уск","content":"Интеграция с API вендоров Многие вендоры публикуют proto для своих API, позволяя генерировать типобезопасных клиентов вместо ручных HTTP реализаций. Это повышает типовую строгость, автоматизирует сериализацию и часто ускоряет работу."},{"id":"cli/generator/generator::api::175","title":"Генератор","section":"Интеграция с API вендоров","path":"/docs/guide/cli/generator/generator#api","headings":["Интеграция с API вендоров"],"excerpt":"Интеграция с API вендоров Преимущества использования proto от вендоров: **Type safety**: Проверка типов на этапе компиляции **Automatic updates**: Новые возможности приходят с обновлением версии **Consistency**: Единые п","content":"Интеграция с API вендоров Преимущества использования proto от вендоров: **Type safety**: Проверка типов на этапе компиляции **Automatic updates**: Новые возможности приходят с обновлением версии **Consistency**: Единые паттерны интерфейсов между интеграциями **Performance**: Бинарная сериализация быстрее JSON **Documentation**: Proto выступают источником истины для API"},{"id":"cli/generator/generator::top::176","title":"Генератор","section":"Команды","path":"/docs/guide/cli/generator/generator","headings":["Команды"],"excerpt":"Команды CLI EasyP предоставляет гибкие варианты запуска генерации с разными конфигурациями и окружениями.","content":"Команды CLI EasyP предоставляет гибкие варианты запуска генерации с разными конфигурациями и окружениями."},{"id":"cli/generator/generator::top::177","title":"Генератор","section":"Базовая генерация","path":"/docs/guide/cli/generator/generator","headings":["Базовая генерация"],"excerpt":"Базовая генерация Ниже наиболее часто применяемые варианты команд для разработки и продакшена:","content":"Базовая генерация Ниже наиболее часто применяемые варианты команд для разработки и продакшена:"},{"id":"cli/generator/generator::top::178","title":"Генератор","section":"Базовая генерация","path":"/docs/guide/cli/generator/generator","headings":["Базовая генерация"],"excerpt":"Базовая генерация ```bash Use default easyp.yaml configuration - Most common for development easyp generate","content":"Базовая генерация ```bash Use default easyp.yaml configuration - Most common for development easyp generate"},{"id":"cli/generator/generator::top::179","title":"Генератор","section":"Базовая генерация","path":"/docs/guide/cli/generator/generator","headings":["Базовая генерация"],"excerpt":"Базовая генерация Use custom configuration file - Essential for multi-environment setups easyp --cfg production.easyp.yaml generate","content":"Базовая генерация Use custom configuration file - Essential for multi-environment setups easyp --cfg production.easyp.yaml generate"},{"id":"cli/generator/generator::top::180","title":"Генератор","section":"Базовая генерация","path":"/docs/guide/cli/generator/generator","headings":["Базовая генерация"],"excerpt":"Базовая генерация Generate with debug logs - Helpful for debugging and CI/CD easyp --debug generate","content":"Базовая генерация Generate with debug logs - Helpful for debugging and CI/CD easyp --debug generate"},{"id":"cli/generator/generator::top::181","title":"Генератор","section":"Базовая генерация","path":"/docs/guide/cli/generator/generator","headings":["Базовая генерация"],"excerpt":"Базовая генерация Generate with custom cache location - Useful for CI systems or shared environments EASYPPATH=/tmp/easyp-cache easyp generate ```","content":"Базовая генерация Generate with custom cache location - Useful for CI systems or shared environments EASYPPATH=/tmp/easyp-cache easyp generate ```"},{"id":"cli/generator/generator::top::182","title":"Генератор","section":"Интеграция с менеджером пакетов","path":"/docs/guide/cli/generator/generator","headings":["Интеграция с менеджером пакетов"],"excerpt":"Интеграция с менеджером пакетов Интеграция с менеджером пакетов позволяет либо явно управлять зависимостями, либо поручить это генератору. Явный путь даёт больше контроля, автоматический — больше удобства:","content":"Интеграция с менеджером пакетов Интеграция с менеджером пакетов позволяет либо явно управлять зависимостями, либо поручить это генератору. Явный путь даёт больше контроля, автоматический — больше удобства:"},{"id":"cli/generator/generator::top::183","title":"Генератор","section":"Интеграция с менеджером пакетов","path":"/docs/guide/cli/generator/generator","headings":["Интеграция с менеджером пакетов"],"excerpt":"Интеграция с менеджером пакетов ```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":"Интеграция с менеджером пакетов ```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::top::184","title":"Генератор","section":"Интеграция с менеджером пакетов","path":"/docs/guide/cli/generator/generator","headings":["Интеграция с менеджером пакетов"],"excerpt":"Интеграция с менеджером пакетов Automatic workflow - Convenient for development (generate downloads dependencies automatically) easyp generate ```","content":"Интеграция с менеджером пакетов Automatic workflow - Convenient for development (generate downloads dependencies automatically) easyp generate ```"},{"id":"cli/generator/generator::advanced-usage::185","title":"Генератор","section":"Расширенное использование (Advanced Usage)","path":"/docs/guide/cli/generator/generator#advanced-usage","headings":["Расширенное использование (Advanced Usage)"],"excerpt":"Расширенное использование (Advanced Usage) Эти варианты полезны для специфических сценариев деплоя, отладки или когда нужен более тонкий контроль процесса генерации:","content":"Расширенное использование (Advanced Usage) Эти варианты полезны для специфических сценариев деплоя, отладки или когда нужен более тонкий контроль процесса генерации:"},{"id":"cli/generator/generator::advanced-usage::186","title":"Генератор","section":"Расширенное использование (Advanced Usage)","path":"/docs/guide/cli/generator/generator#advanced-usage","headings":["Расширенное использование (Advanced Usage)"],"excerpt":"Расширенное использование (Advanced Usage) ```bash Генерация из конкретной директории (перекрывает настройку в файле конфигурации) easyp generate --path=./api/proto","content":"Расширенное использование (Advanced Usage) ```bash Генерация из конкретной директории (перекрывает настройку в файле конфигурации) easyp generate --path=./api/proto"},{"id":"cli/generator/generator::advanced-usage::187","title":"Генератор","section":"Расширенное использование (Advanced Usage)","path":"/docs/guide/cli/generator/generator#advanced-usage","headings":["Расширенное использование (Advanced Usage)"],"excerpt":"Расширенное использование (Advanced Usage) Генерация с vendored зависимостями (оффлайн / Docker контейнеры) easyp mod vendor easyp generate","content":"Расширенное использование (Advanced Usage) Генерация с vendored зависимостями (оффлайн / Docker контейнеры) easyp mod vendor easyp generate"},{"id":"cli/generator/generator::advanced-usage::188","title":"Генератор","section":"Расширенное использование (Advanced Usage)","path":"/docs/guide/cli/generator/generator#advanced-usage","headings":["Расширенное использование (Advanced Usage)"],"excerpt":"Расширенное использование (Advanced Usage) Генерация из кастомного project root (удобно для монореп и вложенных рабочих директорий) easyp generate --root=/usr/local/src/my-project --path=./api/proto ```","content":"Расширенное использование (Advanced Usage) Генерация из кастомного project root (удобно для монореп и вложенных рабочих директорий) easyp generate --root=/usr/local/src/my-project --path=./api/proto ```"},{"id":"cli/generator/generator::common-patterns::189","title":"Генератор","section":"Типовые паттерны (Common Patterns)","path":"/docs/guide/cli/generator/generator#common-patterns","headings":["Типовые паттерны (Common Patterns)"],"excerpt":"Типовые паттерны (Common Patterns) Эти схемы отражают реальные сценарии и лучшие практики организации генерации кода в разных структурах проектов.","content":"Типовые паттерны (Common Patterns) Эти схемы отражают реальные сценарии и лучшие практики организации генерации кода в разных структурах проектов."},{"id":"cli/generator/generator::multi-language-generation::190","title":"Генератор","section":"Мульти-языковая генерация (Multi-Language Generation)","path":"/docs/guide/cli/generator/generator#multi-language-generation","headings":["Мульти-языковая генерация (Multi-Language Generation)"],"excerpt":"Мульти-языковая генерация (Multi-Language Generation) Мульти-языковая генерация критична для компаний, использующих разные технологии в стеке. EasyP облегчает получение согласованных клиентских библиотек и типов для неск","content":"Мульти-языковая генерация (Multi-Language Generation) Мульти-языковая генерация критична для компаний, использующих разные технологии в стеке. EasyP облегчает получение согласованных клиентских библиотек и типов для нескольких языков из одного источника proto."},{"id":"cli/generator/generator::multi-language-generation::191","title":"Генератор","section":"Мульти-языковая генерация (Multi-Language Generation)","path":"/docs/guide/cli/generator/generator#multi-language-generation","headings":["Мульти-языковая генерация (Multi-Language Generation)"],"excerpt":"Мульти-языковая генерация (Multi-Language Generation) **Типовые сценарии:** **Full‑stack приложения**: backend на Go/Java + фронтенд на TypeScript **Платформы данных**: сервисы на Go + аналитика / ML на Python **Микросер","content":"Мульти-языковая генерация (Multi-Language Generation) **Типовые сценарии:** **Full‑stack приложения**: backend на Go/Java + фронтенд на TypeScript **Платформы данных**: сервисы на Go + аналитика / ML на Python **Микросервисы**: каждый сервис — оптимальный язык под задачу **Внешние SDK**: предоставление клиентских библиотек партнёрам **Интеграция с легаси**: современные gRPC сервисы + старые системы"},{"id":"cli/generator/generator::multi-language-generation::192","title":"Генератор","section":"Мульти-языковая генерация (Multi-Language Generation)","path":"/docs/guide/cli/generator/generator#multi-language-generation","headings":["Мульти-языковая генерация (Multi-Language Generation)"],"excerpt":"Мульти-языковая генерация (Multi-Language Generation) **Производительность:** Каждый плагин запускается отдельно — время растёт линейно от количества плагинов Для больших наборов используйте параллельный запуск (make -j4","content":"Мульти-языковая генерация (Multi-Language Generation) **Производительность:** Каждый плагин запускается отдельно — время растёт линейно от количества плагинов Для больших наборов используйте параллельный запуск (make -j4) Структурируйте выходные директории иерархически — меньше конфликтов Плагины имеют разную скорость — профилируйте сборку для поиска узких мест"},{"id":"cli/generator/generator::multi-language-generation::193","title":"Генератор","section":"Мульти-языковая генерация (Multi-Language Generation)","path":"/docs/guide/cli/generator/generator#multi-language-generation","headings":["Мульти-языковая генерация (Multi-Language Generation)"],"excerpt":"Мульти-языковая генерация (Multi-Language Generation) **Преимущества сопровождения:** Единый источник истины для API снижает риск расхождения схем Согласованные типы уменьшают интеграционные баги Автоматическая синхрониз","content":"Мульти-языковая генерация (Multi-Language Generation) **Преимущества сопровождения:** Единый источник истины для API снижает риск расхождения схем Согласованные типы уменьшают интеграционные баги Автоматическая синхронизация при изменении proto исключает ручные правки Меньше риска дрейфа API между реализациями на разных языках Рефакторинг упрощается — изменения транзитивно отражаются во всех артефактах"},{"id":"cli/generator/generator::multi-language-generation::194","title":"Генератор","section":"Мульти-языковая генерация (Multi-Language Generation)","path":"/docs/guide/cli/generator/generator#multi-language-generation","headings":["Мульти-языковая генерация (Multi-Language Generation)"],"excerpt":"Мульти-языковая генерация (Multi-Language Generation) Ниже пример типичной мульти-языковой конфигурации для full‑stack приложения: backend, веб‑клиент, аналитика и документация:","content":"Мульти-языковая генерация (Multi-Language Generation) Ниже пример типичной мульти-языковой конфигурации для full‑stack приложения: backend, веб‑клиент, аналитика и документация:"},{"id":"cli/generator/generator::multi-language-generation::195","title":"Генератор","section":"Мульти-языковая генерация (Multi-Language Generation)","path":"/docs/guide/cli/generator/generator#multi-language-generation","headings":["Мульти-языковая генерация (Multi-Language Generation)"],"excerpt":"Мульти-языковая генерация (Multi-Language Generation)","content":"Мульти-языковая генерация (Multi-Language Generation)"},{"id":"cli/generator/generator::multi-language-generation::196","title":"Генератор","section":"Мульти-языковая генерация (Multi-Language Generation)","path":"/docs/guide/cli/generator/generator#multi-language-generation","headings":["Мульти-языковая генерация (Multi-Language Generation)"],"excerpt":"Мульти-языковая генерация (Multi-Language Generation) **Совет по организации:** Используйте отдельные выходные директории для каждого языка, чтобы избежать конфликтов файлов и упростить интеграцию с языковыми сборочными ","content":"Мульти-языковая генерация (Multi-Language Generation) **Совет по организации:** Используйте отдельные выходные директории для каждого языка, чтобы избежать конфликтов файлов и упростить интеграцию с языковыми сборочными системами."},{"id":"cli/generator/generator::multi-language-generation::197","title":"Генератор","section":"Мульти-языковая генерация (Multi-Language Generation)","path":"/docs/guide/cli/generator/generator#multi-language-generation","headings":["Мульти-языковая генерация (Multi-Language Generation)"],"excerpt":"Мульти-языковая генерация (Multi-Language Generation) Генератор EasyP — комплексное решение для генерации кода из Protocol Buffers: от простой локальной разработки до сложных enterprise‑сценариев с удалёнными зависимостя","content":"Мульти-языковая генерация (Multi-Language Generation) Генератор EasyP — комплексное решение для генерации кода из Protocol Buffers: от простой локальной разработки до сложных enterprise‑сценариев с удалёнными зависимостями и мульти-языковым выводом."},{"id":"cli/linter/linter::proto::0","title":"Линтер","section":"Зачем нужен линтер для proto файлов?","path":"/docs/guide/cli/linter/linter#proto","headings":["Зачем нужен линтер для proto файлов?"],"excerpt":"Зачем нужен линтер для proto файлов? Линтеры играют ключевую роль в современной разработке, особенно когда речь о .proto файлах. Они обеспечивают единый стиль и структуру, помогают находить потенциальные ошибки на ранних","content":"Зачем нужен линтер для proto файлов? Линтеры играют ключевую роль в современной разработке, особенно когда речь о .proto файлах. Они обеспечивают единый стиль и структуру, помогают находить потенциальные ошибки на ранних этапах и поддерживают читаемость кода. Это даёт выгоды:"},{"id":"cli/linter/linter::proto::1","title":"Линтер","section":"Зачем нужен линтер для proto файлов?","path":"/docs/guide/cli/linter/linter#proto","headings":["Зачем нужен линтер для proto файлов?"],"excerpt":"Зачем нужен линтер для proto файлов? **Снижение затрат на разработку:** Ошибки ловятся раньше, меньше времени на отладку. **Улучшение командного взаимодействия:** Единообразный код легче понимать и сопровождать. **Бизнес","content":"Зачем нужен линтер для proto файлов? **Снижение затрат на разработку:** Ошибки ловятся раньше, меньше времени на отладку. **Улучшение командного взаимодействия:** Единообразный код легче понимать и сопровождать. **Бизнес-эффективность:** Более качественный код → меньше инцидентов в проде → ниже стоимость поддержки."},{"id":"cli/linter/linter::top::2","title":"Линтер","section":"Справочник по конфигурации","path":"/docs/guide/cli/linter/linter","headings":["Справочник по конфигурации"],"excerpt":"Справочник по конфигурации Конфигурация линтера настраивается в секции lint файла easyp.yaml.","content":"Справочник по конфигурации Конфигурация линтера настраивается в секции lint файла easyp.yaml."},{"id":"cli/linter/linter::use-string::3","title":"Линтер","section":"use ([]string)","path":"/docs/guide/cli/linter/linter#use-string","headings":["use ([]string)"],"excerpt":"use ([]string) Определяет набор правил или категорий для включения. Можно смешивать категории и конкретные правила.","content":"use ([]string) Определяет набор правил или категорий для включения. Можно смешивать категории и конкретные правила."},{"id":"cli/linter/linter::use-string::4","title":"Линтер","section":"use ([]string)","path":"/docs/guide/cli/linter/linter#use-string","headings":["use ([]string)"],"excerpt":"use ([]string) **Категории:** **MINIMAL**: Базовая согласованность пакетов **BASIC**: Соглашения по именованию и структуре **DEFAULT**: Рекомендованные правила для большинства проектов **COMMENTS**: Требования к коммента","content":"use ([]string) **Категории:** **MINIMAL**: Базовая согласованность пакетов **BASIC**: Соглашения по именованию и структуре **DEFAULT**: Рекомендованные правила для большинства проектов **COMMENTS**: Требования к комментариям **UNARY_RPC**: Ограничение на streaming RPC"},{"id":"cli/linter/linter::use-string::5","title":"Линтер","section":"use ([]string)","path":"/docs/guide/cli/linter/linter#use-string","headings":["use ([]string)"],"excerpt":"use ([]string) **Индивидуальные правила:** Любое имя правила (например ENUM_PASCAL_CASE, FIELD_LOWER_SNAKE_CASE)","content":"use ([]string) **Индивидуальные правила:** Любое имя правила (например ENUM_PASCAL_CASE, FIELD_LOWER_SNAKE_CASE)"},{"id":"cli/linter/linter::use-string::6","title":"Линтер","section":"use ([]string)","path":"/docs/guide/cli/linter/linter#use-string","headings":["use ([]string)"],"excerpt":"use ([]string) **Примеры:** ```yaml Только категории use: [MINIMAL, BASIC, DEFAULT]","content":"use ([]string) **Примеры:** ```yaml Только категории use: [MINIMAL, BASIC, DEFAULT]"},{"id":"cli/linter/linter::use-string::7","title":"Линтер","section":"use ([]string)","path":"/docs/guide/cli/linter/linter#use-string","headings":["use ([]string)"],"excerpt":"use ([]string) Смешивание use: - MINIMAL - COMMENT_SERVICE - COMMENT_RPC - ENUM_PASCAL_CASE","content":"use ([]string) Смешивание use: - MINIMAL - COMMENT_SERVICE - COMMENT_RPC - ENUM_PASCAL_CASE"},{"id":"cli/linter/linter::use-string::8","title":"Линтер","section":"use ([]string)","path":"/docs/guide/cli/linter/linter#use-string","headings":["use ([]string)"],"excerpt":"use ([]string) Точный набор use: - PACKAGE_DEFINED - SERVICE_PASCAL_CASE - FIELD_LOWER_SNAKE_CASE ```","content":"use ([]string) Точный набор use: - PACKAGE_DEFINED - SERVICE_PASCAL_CASE - FIELD_LOWER_SNAKE_CASE ```"},{"id":"cli/linter/linter::enum_zero_value_suffix-string::9","title":"Линтер","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) Обязывает нулевое значение enum иметь заданный суффикс.","content":"enum_zero_value_suffix (string) Обязывает нулевое значение enum иметь заданный суффикс."},{"id":"cli/linter/linter::enum_zero_value_suffix-string::10","title":"Линтер","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) **Обычно:** \"UNSPECIFIED\", \"UNKNOWN\", \"DEFAULT\"","content":"enum_zero_value_suffix (string) **Обычно:** \"UNSPECIFIED\", \"UNKNOWN\", \"DEFAULT\""},{"id":"cli/linter/linter::enum_zero_value_suffix-string::11","title":"Линтер","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)","content":"enum_zero_value_suffix (string)"},{"id":"cli/linter/linter::service_suffix-string::12","title":"Линтер","section":"service_suffix (string)","path":"/docs/guide/cli/linter/linter#service_suffix-string","headings":["service_suffix (string)"],"excerpt":"service_suffix (string) Требуемый суффикс для имён сервисов (унификация стиля).","content":"service_suffix (string) Требуемый суффикс для имён сервисов (унификация стиля)."},{"id":"cli/linter/linter::ignore-string::13","title":"Линтер","section":"ignore ([]string)","path":"/docs/guide/cli/linter/linter#ignore-string","headings":["ignore ([]string)"],"excerpt":"ignore ([]string) Полное исключение путей из линтинга.","content":"ignore ([]string) Полное исключение путей из линтинга."},{"id":"cli/linter/linter::ignore-string::14","title":"Линтер","section":"ignore ([]string)","path":"/docs/guide/cli/linter/linter#ignore-string","headings":["ignore ([]string)"],"excerpt":"ignore ([]string) **Use cases:** vendor / third_party сгенерированные файлы легаси подпакеты тестовые фикстуры","content":"ignore ([]string) **Use cases:** vendor / third_party сгенерированные файлы легаси подпакеты тестовые фикстуры"},{"id":"cli/linter/linter::except-string::15","title":"Линтер","section":"except ([]string)","path":"/docs/guide/cli/linter/linter#except-string","headings":["except ([]string)"],"excerpt":"except ([]string) Глобально отключает правила.","content":"except ([]string) Глобально отключает правила."},{"id":"cli/linter/linter::allow_comment_ignores-bool::16","title":"Линтер","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) Разрешает инлайн‑игнор правил комментариями.","content":"allow_comment_ignores (bool) Разрешает инлайн‑игнор правил комментариями."},{"id":"cli/linter/linter::ignore_only-mapstringstring::17","title":"Линтер","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) Таргетированное игнорирование конкретных правил для указанных путей.","content":"ignore_only (mapstringstring) Таргетированное игнорирование конкретных правил для указанных путей."},{"id":"cli/linter/linter::top::18","title":"Линтер","section":"Игнор правил комментариями","path":"/docs/guide/cli/linter/linter","headings":["Игнор правил комментариями"],"excerpt":"Игнор правил комментариями Если включён allow_comment_ignores, можно точечно отключать правила.","content":"Игнор правил комментариями Если включён allow_comment_ignores, можно точечно отключать правила."},{"id":"cli/linter/linter::top::19","title":"Линтер","section":"Несколько правил в одной строке","path":"/docs/guide/cli/linter/linter","headings":["Несколько правил в одной строке"],"excerpt":"Несколько правил в одной строке","content":"Несколько правил в одной строке"},{"id":"cli/linter/linter::top::20","title":"Линтер","section":"Используйте редко","path":"/docs/guide/cli/linter/linter","headings":["Используйте редко"],"excerpt":"Используйте редко Частое игнорирование = сигнал пересмотреть конфигурацию.","content":"Используйте редко Частое игнорирование = сигнал пересмотреть конфигурацию."},{"id":"cli/linter/linter::top::21","title":"Линтер","section":"Предпочитайте конфигурацию","path":"/docs/guide/cli/linter/linter","headings":["Предпочитайте конфигурацию"],"excerpt":"Предпочитайте конфигурацию Если нужно игнорировать правило в группе файлов — используйте ignore_only.","content":"Предпочитайте конфигурацию Если нужно игнорировать правило в группе файлов — используйте ignore_only."},{"id":"cli/linter/linter::top::22","title":"Линтер","section":"Категории линтера","path":"/docs/guide/cli/linter/linter","headings":["Категории линтера"],"excerpt":"Категории линтера Категории помогают быстро выбрать уровень строгости.","content":"Категории линтера Категории помогают быстро выбрать уровень строгости."},{"id":"cli/linter/linter::top::23","title":"Линтер","section":"Категории линтера","path":"/docs/guide/cli/linter/linter","headings":["Категории линтера"],"excerpt":"Категории линтера **Когда использовать:** **MINIMAL**: Минимальная базовая целостность **BASIC**: Частые соглашения имен **DEFAULT**: Дополнительные проверки качества **COMMENTS**: Обязательные комментарии (API, команды)","content":"Категории линтера **Когда использовать:** **MINIMAL**: Минимальная базовая целостность **BASIC**: Частые соглашения имен **DEFAULT**: Дополнительные проверки качества **COMMENTS**: Обязательные комментарии (API, команды) **UNARY_RPC**: Ограничить streaming RPC"},{"id":"cli/linter/linter::minimal::24","title":"Линтер","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::25","title":"Линтер","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::26","title":"Линтер","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::27","title":"Линтер","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::28","title":"Линтер","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::top::29","title":"Линтер","section":"Заключение","path":"/docs/guide/cli/linter/linter","headings":["Заключение"],"excerpt":"Заключение Внедрение EasyP линдера для ваших proto файлов заметно улучшит workflow, качество и поддерживаемость кода. Полная совместимость с Buf позволяет командам мигрировать без боли, используя гибкую конфигурацию и мо","content":"Заключение Внедрение EasyP линдера для ваших proto файлов заметно улучшит workflow, качество и поддерживаемость кода. Полная совместимость с Buf позволяет командам мигрировать без боли, используя гибкую конфигурацию и мощные возможности из коробки."},{"id":"cli/linter/rules/comment-enum-value::top::0","title":"COMMENT_ENUM_VALUE","path":"/docs/guide/cli/linter/rules/comment-enum-value","headings":[],"excerpt":"Это правило проверяет, что все значения enum имеют комментарий.","content":"Это правило проверяет, что все значения enum имеют комментарий."},{"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 ```proto syntax = \"proto3\";","content":"Good ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/comment-enum-value::good::4","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":"Это правило проверяет, что enum имеет комментарий.","content":"Это правило проверяет, что enum имеет комментарий."},{"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":"Это правило проверяет, что все поля сообщений имеют комментарий.","content":"Это правило проверяет, что все поля сообщений имеют комментарий."},{"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":"Это правило проверяет, что message имеет комментарий.","content":"Это правило проверяет, что message имеет комментарий."},{"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 ```proto syntax = \"proto3\";","content":"Bad ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/comment-message::bad::2","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::3","title":"COMMENT_MESSAGE","section":"Good","path":"/docs/guide/cli/linter/rules/comment-message#good","headings":["Good"],"excerpt":"Good ```proto syntax = \"proto3\";","content":"Good ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/comment-message::good::4","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":"Это правило проверяет, что oneof имеет комментарий.","content":"Это правило проверяет, что oneof имеет комментарий."},{"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":"Это правило проверяет, что сервис имеет комментарий.","content":"Это правило проверяет, что сервис имеет комментарий."},{"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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **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":"Это правило проверяет, что все файлы в заданной директории находятся в одном и том же package.","content":"Это правило проверяет, что все файлы в заданной директории находятся в одном и том же 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":"Это правило проверяет, что первое значение enum равно нулю.","content":"Это правило проверяет, что первое значение enum равно нулю."},{"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 ```proto syntax = \"proto3\";","content":"Bad ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/enum-first-value-zero::bad::3","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::4","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::5","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":"Это правило проверяет, что опция allow_alias не установлена в значение true внутри enum.","content":"Это правило проверяет, что опция allow_alias не установлена в значение true внутри 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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **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":"Это правило проверяет, что имена enum написаны в стиле PascalCase.","content":"Это правило проверяет, что имена enum написаны в стиле 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":"Это правило проверяет, что все значения enum имеют префикс, совпадающий с именем enum.","content":"Это правило проверяет, что все значения enum имеют префикс, совпадающий с именем enum."},{"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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **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":"Это правило проверяет, что значения enum записаны в стиле UPPER_SNAKE_CASE.","content":"Это правило проверяет, что значения enum записаны в стиле 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":"Это правило проверяет, что все нулевые значения enum имеют суффикс _NONE или ваш кастомный (пользовательский) суффикс.","content":"Это правило проверяет, что все нулевые значения enum имеют суффикс _NONE или ваш кастомный (пользовательский) суффикс."},{"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":"**MINIMAL** **BASIC** **DEFAULT**","content":"**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":"Это правило проверяет, что имена полей сообщений записаны в стиле lower_snake_case.","content":"Это правило проверяет, что имена полей сообщений записаны в стиле 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":"Это правило проверяет, что все файлы имеют имя в формате lower_snake_case (только строчные буквы, цифры и символ подчеркивания, без пробелов и заглавных букв).","content":"Это правило проверяет, что все файлы имеют имя в формате 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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **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":"Это правило проверяет, что в proto-файле не используются public импорты (оператор import public \"...\").","content":"Это правило проверяет, что в proto-файле не используются public импорты (оператор import public \"...\")."},{"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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **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":"Это правило проверяет, что в proto‑файле не используются weak‑импорты (import weak \"...\").","content":"Это правило проверяет, что в proto‑файле не используются weak‑импорты (import weak \"...\")."},{"id":"cli/linter/rules/import-no-weak::top::2","title":"IMPORT_NO_WEAK","path":"/docs/guide/cli/linter/rules/import-no-weak","headings":[],"excerpt":"Weak import (синтаксис import weak) допустим в proto2, но его использование усложняет анализ зависимостей и может приводить к неочевидным ошибкам при генерации кода. Рекомендуется всегда использовать обычный import.","content":"Weak import (синтаксис import weak) допустим в proto2, но его использование усложняет анализ зависимостей и может приводить к неочевидным ошибкам при генерации кода. Рекомендуется всегда использовать обычный import."},{"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 ```proto syntax = \"proto2\";","content":"Bad ```proto syntax = \"proto2\";"},{"id":"cli/linter/rules/import-no-weak::bad::4","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::5","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::6","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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **MINIMAL** **BASIC** **DEFAULT**"},{"id":"cli/linter/rules/import-used::top::1","title":"IMPORT_USED","path":"/docs/guide/cli/linter/rules/import-used","headings":[],"excerpt":"Это правило проверяет, что все импорты используются в proto-файле.","content":"Это правило проверяет, что все импорты используются в proto-файле."},{"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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **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":"Это правило проверяет, что имена сообщений (message) записаны в стиле PascalCase.","content":"Это правило проверяет, что имена сообщений (message) записаны в стиле 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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **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":"Это правило проверяет, что имена oneof записаны в стиле lower_snake_case.","content":"Это правило проверяет, что имена oneof записаны в стиле 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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **MINIMAL** **BASIC** **DEFAULT**"},{"id":"cli/linter/rules/package-defined::top::1","title":"PACKAGE_DEFINED","path":"/docs/guide/cli/linter/rules/package-defined","headings":[],"excerpt":"Это правило проверяет, что во всех файлах присутствует директива package.","content":"Это правило проверяет, что во всех файлах присутствует директива package."},{"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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **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":"Это правило проверяет, что все файлы находятся в директории, имя которой соответствует имени их пакета.","content":"Это правило проверяет, что все файлы находятся в директории, имя которой соответствует имени их пакета."},{"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":"Это правило проверяет, что имена package записаны в формате lower_snake_case (строчные буквы, при необходимости цифры и символ подчеркивания, без пробелов и заглавных букв).","content":"Это правило проверяет, что имена package записаны в формате 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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **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":"Это правило проверяет, что все файлы с заданным пакетом используют одно и то же пространство имён C# (csharp_namespace).","content":"Это правило проверяет, что все файлы с заданным пакетом используют одно и то же пространство имён C# (csharp_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\"; // [!code focus] ```","content":"Good option csharp_namespace = \"Foo.Bar\"; // [!code focus] ```"},{"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 ```proto // File: pkg/bar.proto","content":"Good ```proto // File: pkg/bar.proto"},{"id":"cli/linter/rules/package-same-csharp-namespace::good::9","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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **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":"Это правило проверяет, что все файлы с данным package находятся в одной директории.","content":"Это правило проверяет, что все файлы с данным package находятся в одной директории."},{"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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **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":"Это правило проверяет, что все файлы с одним и тем же package используют одно и то же значение опции go_package.","content":"Это правило проверяет, что все файлы с одним и тем же package используют одно и то же значение опции 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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **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":"Это правило проверяет, что все файлы с одним и тем же package используют одинаковое значение опции java_package.","content":"Это правило проверяет, что все файлы с одним и тем же package используют одинаковое значение опции 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 ```proto // File: pkg/bar.proto","content":"Bad ```proto // File: pkg/bar.proto"},{"id":"cli/linter/rules/package-same-java-multiple-files::bad::6","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::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 ```proto // File: pkg/foo.proto","content":"Good ```proto // File: pkg/foo.proto"},{"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 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::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 ```proto // File: pkg/bar.proto","content":"Good ```proto // File: pkg/bar.proto"},{"id":"cli/linter/rules/package-same-java-multiple-files::good::10","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":"Это правило проверяет, что все файлы с одним и тем же package используют одно и то же значение опции java_package.","content":"Это правило проверяет, что все файлы с одним и тем же package используют одно и то же значение опции 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":"Это правило проверяет, что все файлы с одним и тем же package используют одно и то же значение опции php_namespace.","content":"Это правило проверяет, что все файлы с одним и тем же package используют одно и то же значение опции 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":"Это правило проверяет, что все файлы с одним и тем же package используют один и тот же swift_prefix.","content":"Это правило проверяет, что все файлы с одним и тем же package используют один и тот же 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":"Это правило проверяет, что суффикс версии пакета имеет формат _vX, где X — числовая версия.","content":"Это правило проверяет, что суффикс версии пакета имеет формат _vX, где X — числовая версия."},{"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":"Это правило проверяет, что RPC не использует клиентский стриминг (запрос не является stream ...).","content":"Это правило проверяет, что RPC не использует клиентский стриминг (запрос не является stream ...)."},{"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":"Это правило проверяет, что RPC не использует серверный стриминг (ответ не является stream ...).","content":"Это правило проверяет, что RPC не использует серверный стриминг (ответ не является stream ...)."},{"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":"Это правило проверяет, что все имена RPC написаны в стиле PascalCase.","content":"Это правило проверяет, что все имена RPC написаны в стиле 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":"Это правило проверяет, что все сообщения запроса и ответа RPC уникальны: для каждого метода используются собственные (не переиспользуются одинаковые пары Request / Response у разных RPC).","content":"Это правило проверяет, что все сообщения запроса и ответа RPC уникальны: для каждого метода используются собственные (не переиспользуются одинаковые пары Request / Response у разных RPC)."},{"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":"Категории: **MINIMAL** **BASIC** **DEFAULT**","content":"Категории: **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":"Это правило проверяет, что все сообщения запроса RPC названы в формате MethodRequest.","content":"Это правило проверяет, что все сообщения запроса RPC названы в формате 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":"Это правило проверяет, что все сообщения ответа RPC названы в формате MethodResponse.","content":"Это правило проверяет, что все сообщения ответа RPC названы в формате 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":"**MINIMAL** **BASIC** **DEFAULT**","content":"**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":"Это правило проверяет, что все имена сервисов написаны в стиле PascalCase.","content":"Это правило проверяет, что все имена сервисов написаны в стиле 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":"Это правило проверяет, что все сервисы имеют суффикс Service или ваш пользовательский суффикс.","content":"Это правило проверяет, что все сервисы имеют суффикс Service или ваш пользовательский суффикс."},{"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 против Buf: управление пакетами","path":"/docs/guide/cli/package-manager/easyp-vs-buf","headings":[],"excerpt":"EasyP против Buf: управление пакетами","content":"EasyP против Buf: управление пакетами"},{"id":"cli/package-manager/easyp-vs-buf::top::1","title":"EasyP против Buf: управление пакетами","path":"/docs/guide/cli/package-manager/easyp-vs-buf","headings":[],"excerpt":"Этот документ даёт подробное сравнение децентрализованного подхода EasyP к управлению пакетами и централизованной модели Buf через Buf Schema Registry (BSR), чтобы помочь понять ключевые различия и выбрать подходящее реш","content":"Этот документ даёт подробное сравнение децентрализованного подхода EasyP к управлению пакетами и централизованной модели Buf через Buf Schema Registry (BSR), чтобы помочь понять ключевые различия и выбрать подходящее решение для ваших задач."},{"id":"cli/package-manager/easyp-vs-buf::easyp-git::2","title":"EasyP против Buf: управление пакетами","section":"EasyP: децентрализованный подход на базе Git","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp-git","headings":["EasyP: децентрализованный подход на базе Git"],"excerpt":"EasyP: децентрализованный подход на базе Git","content":"EasyP: децентрализованный подход на базе Git"},{"id":"cli/package-manager/easyp-vs-buf::buf-bsr::3","title":"EasyP против Buf: управление пакетами","section":"Buf: централизованный реестр (BSR)","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf-bsr","headings":["Buf: централизованный реестр (BSR)"],"excerpt":"Buf: централизованный реестр (BSR)","content":"Buf: централизованный реестр (BSR)"},{"id":"cli/package-manager/easyp-vs-buf::top::4","title":"EasyP против Buf: управление пакетами","section":"Краткое резюме различий","path":"/docs/guide/cli/package-manager/easyp-vs-buf","headings":["Краткое резюме различий"],"excerpt":"Краткое резюме различий Аспект EasyP Buf -------- ------- ----- **Архитектура** Децентрализованная (Git) Централизованная (реестр BSR) **Источник зависимостей** Любой Git репозиторий Только модули BSR **Единая точка отка","content":"Краткое резюме различий Аспект EasyP Buf -------- ------- ----- **Архитектура** Децентрализованная (Git) Централизованная (реестр BSR) **Источник зависимостей** Любой Git репозиторий Только модули BSR **Единая точка отказа** Нет Да (buf.build) **Enterprise / air‑gapped** Полная поддержка Требует доступа к BSR или приватного BSR **Аутентификация** Git (SSH / HTTPS) Токены Buf + Git **Vendor lock‑in** Отсутствует Привязка к экосистеме Buf **Частные репозитории** Нативно через Git Нужно опубликовать в BSR **Оффлайн поддержка** Полная (через vendoring) Ограничена (кэшированные модули) **Стоимость** Бесплатно (использует существующий Git) Бесплатный тариф + платные планы **Сложность настройки** Минимальная Средняя (настройка BSR)"},{"id":"cli/package-manager/easyp-vs-buf::top::5","title":"EasyP против Buf: управление пакетами","section":"Подробное сравнение возможностей","path":"/docs/guide/cli/package-manager/easyp-vs-buf","headings":["Подробное сравнение возможностей"],"excerpt":"Подробное сравнение возможностей","content":"Подробное сравнение возможностей"},{"id":"cli/package-manager/easyp-vs-buf::1::6","title":"EasyP против Buf: управление пакетами","section":"1. Философия управления зависимостями","path":"/docs/guide/cli/package-manager/easyp-vs-buf#1","headings":["1. Философия управления зависимостями"],"excerpt":"Философия управления зависимостями","content":"Философия управления зависимостями"},{"id":"cli/package-manager/easyp-vs-buf::easyp-git::7","title":"EasyP против Buf: управление пакетами","section":"EasyP: «Любой Git репозиторий — это пакет»","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp-git","headings":["EasyP: «Любой Git репозиторий — это пакет»"],"excerpt":"EasyP: «Любой Git репозиторий — это пакет»","content":"EasyP: «Любой Git репозиторий — это пакет»"},{"id":"cli/package-manager/easyp-vs-buf::easyp-git::8","title":"EasyP против Buf: управление пакетами","section":"EasyP: «Любой Git репозиторий — это пакет»","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp-git","headings":["EasyP: «Любой Git репозиторий — это пакет»"],"excerpt":"EasyP: «Любой Git репозиторий — это пакет» **Преимущества:** ✅ Использование любого существующего репозитория сразу ✅ Не нужно «публиковать» в отдельный реестр ✅ Истинный источник версий — Git ✅ Работает с приватными сер","content":"EasyP: «Любой Git репозиторий — это пакет» **Преимущества:** ✅ Использование любого существующего репозитория сразу ✅ Не нужно «публиковать» в отдельный реестр ✅ Истинный источник версий — Git ✅ Работает с приватными серверами без доп. настроек"},{"id":"cli/package-manager/easyp-vs-buf::buf::9","title":"EasyP против Buf: управление пакетами","section":"Buf: «Сначала реестр»","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf","headings":["Buf: «Сначала реестр»"],"excerpt":"Buf: «Сначала реестр» **Преимущества:** ✅ Курируемые, проверенные модули ✅ Богатые метаданные и документация ✅ Визуализация графа зависимостей ✅ Принуждение семантического версионирования","content":"Buf: «Сначала реестр» **Преимущества:** ✅ Курируемые, проверенные модули ✅ Богатые метаданные и документация ✅ Визуализация графа зависимостей ✅ Принуждение семантического версионирования"},{"id":"cli/package-manager/easyp-vs-buf::buf::10","title":"EasyP против Buf: управление пакетами","section":"Buf: «Сначала реестр»","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf","headings":["Buf: «Сначала реестр»"],"excerpt":"Buf: «Сначала реестр» **Ограничения:** ❌ Нужно опубликовать в BSR перед использованием ❌ Требует аккаунт и аутентификацию ❌ Нельзя напрямую сослаться на произвольный Git репозиторий","content":"Buf: «Сначала реестр» **Ограничения:** ❌ Нужно опубликовать в BSR перед использованием ❌ Требует аккаунт и аутентификацию ❌ Нельзя напрямую сослаться на произвольный Git репозиторий"},{"id":"cli/package-manager/easyp-vs-buf::2-airgapped::11","title":"EasyP против Buf: управление пакетами","section":"2. Корпоративные и изолированные (air‑gapped) среды","path":"/docs/guide/cli/package-manager/easyp-vs-buf#2-airgapped","headings":["2. Корпоративные и изолированные (air‑gapped) среды"],"excerpt":"Корпоративные и изолированные (air‑gapped) среды","content":"Корпоративные и изолированные (air‑gapped) среды"},{"id":"cli/package-manager/easyp-vs-buf::easyp::12","title":"EasyP против Buf: управление пакетами","section":"EasyP: Полноценная оффлайн‑поддержка","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["EasyP: Полноценная оффлайн‑поддержка"],"excerpt":"EasyP: Полноценная оффлайн‑поддержка **Сценарий**: крупная компания со строгими сетевыми политиками","content":"EasyP: Полноценная оффлайн‑поддержка **Сценарий**: крупная компания со строгими сетевыми политиками"},{"id":"cli/package-manager/easyp-vs-buf::easyp::13","title":"EasyP против Buf: управление пакетами","section":"EasyP: Полноценная оффлайн‑поддержка","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["EasyP: Полноценная оффлайн‑поддержка"],"excerpt":"EasyP: Полноценная оффлайн‑поддержка ```bash Среда с доступом в интернет easyp mod download # Скачивает в ~/.easyp/ easyp mod vendor # Создает easyp_vendor/","content":"EasyP: Полноценная оффлайн‑поддержка ```bash Среда с доступом в интернет easyp mod download # Скачивает в ~/.easyp/ easyp mod vendor # Создает easyp_vendor/"},{"id":"cli/package-manager/easyp-vs-buf::easyp::14","title":"EasyP против Buf: управление пакетами","section":"EasyP: Полноценная оффлайн‑поддержка","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["EasyP: Полноценная оффлайн‑поддержка"],"excerpt":"EasyP: Полноценная оффлайн‑поддержка Перенос в изолированный сегмент tar -czf easyp-deps.tar.gz ~/.easyp easyp_vendor/ ... перенос архива ...","content":"EasyP: Полноценная оффлайн‑поддержка Перенос в изолированный сегмент tar -czf easyp-deps.tar.gz ~/.easyp easyp_vendor/ ... перенос архива ..."},{"id":"cli/package-manager/easyp-vs-buf::easyp::15","title":"EasyP против Buf: управление пакетами","section":"EasyP: Полноценная оффлайн‑поддержка","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["EasyP: Полноценная оффлайн‑поддержка"],"excerpt":"EasyP: Полноценная оффлайн‑поддержка В изолированной среде tar -xzf easyp-deps.tar.gz export EASYPPATH=$PWD/.easyp easyp generate # Работает оффлайн ```","content":"EasyP: Полноценная оффлайн‑поддержка В изолированной среде tar -xzf easyp-deps.tar.gz export EASYPPATH=$PWD/.easyp easyp generate # Работает оффлайн ```"},{"id":"cli/package-manager/easyp-vs-buf::easyp::16","title":"EasyP против Buf: управление пакетами","section":"EasyP: Полноценная оффлайн‑поддержка","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["EasyP: Полноценная оффлайн‑поддержка"],"excerpt":"EasyP: Полноценная оффлайн‑поддержка **Плюсы:** ✅ Не зависит от внешних сервисов ✅ Не нужен внутренний реестр ✅ Использует существующую Git инфраструктуру ✅ Простая файловая дистрибуция","content":"EasyP: Полноценная оффлайн‑поддержка **Плюсы:** ✅ Не зависит от внешних сервисов ✅ Не нужен внутренний реестр ✅ Использует существующую Git инфраструктуру ✅ Простая файловая дистрибуция"},{"id":"cli/package-manager/easyp-vs-buf::buf::17","title":"EasyP против Buf: управление пакетами","section":"Buf: Требует инфраструктуру реестра","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf","headings":["Buf: Требует инфраструктуру реестра"],"excerpt":"Buf: Требует инфраструктуру реестра ```bash Вариант 1: использовать buf.build (нужен интернет) buf mod download","content":"Buf: Требует инфраструктуру реестра ```bash Вариант 1: использовать buf.build (нужен интернет) buf mod download"},{"id":"cli/package-manager/easyp-vs-buf::buf::18","title":"EasyP против Buf: управление пакетами","section":"Buf: Требует инфраструктуру реестра","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf","headings":["Buf: Требует инфраструктуру реестра"],"excerpt":"Buf: Требует инфраструктуру реестра Вариант 2: поднимать приватный BSR (сложно) Развернуть сервер реестра Перепубликовать все модули внутрь Настроить доступы, аутентификацию Поддерживать работоспособность ```","content":"Buf: Требует инфраструктуру реестра Вариант 2: поднимать приватный BSR (сложно) Развернуть сервер реестра Перепубликовать все модули внутрь Настроить доступы, аутентификацию Поддерживать работоспособность ```"},{"id":"cli/package-manager/easyp-vs-buf::buf::19","title":"EasyP против Buf: управление пакетами","section":"Buf: Требует инфраструктуру реестра","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf","headings":["Buf: Требует инфраструктуру реестра"],"excerpt":"Buf: Требует инфраструктуру реестра **Минусы:** ❌ Постоянный интернет или дорогой приватный BSR ❌ Сложная инфраструктура для частных установок ❌ Все модули нужно републиковать ❌ Дополнительные операционные затраты","content":"Buf: Требует инфраструктуру реестра **Минусы:** ❌ Постоянный интернет или дорогой приватный BSR ❌ Сложная инфраструктура для частных установок ❌ Все модули нужно републиковать ❌ Дополнительные операционные затраты"},{"id":"cli/package-manager/easyp-vs-buf::easyp::20","title":"EasyP против Buf: управление пакетами","section":"EasyP: Прямой контроль","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["EasyP: Прямой контроль"],"excerpt":"EasyP: Прямой контроль ```yaml Полный контроль источников deps: # Публичный репозиторий — ваша конкретная версия - github.com/googleapis/googleapis@common-protos-1_3_1","content":"EasyP: Прямой контроль ```yaml Полный контроль источников deps: # Публичный репозиторий — ваша конкретная версия - github.com/googleapis/googleapis@common-protos-1_3_1"},{"id":"cli/package-manager/easyp-vs-buf::easyp::21","title":"EasyP против Buf: управление пакетами","section":"EasyP: Прямой контроль","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["EasyP: Прямой контроль"],"excerpt":"EasyP: Прямой контроль Внутренний репозиторий - gitlab.company.com/security/validated-protos@v1.0.0","content":"EasyP: Прямой контроль Внутренний репозиторий - gitlab.company.com/security/validated-protos@v1.0.0"},{"id":"cli/package-manager/easyp-vs-buf::easyp::22","title":"EasyP против Buf: управление пакетами","section":"EasyP: Прямой контроль","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["EasyP: Прямой контроль"],"excerpt":"EasyP: Прямой контроль Точный коммит (горячий фикс) - github.com/bufbuild/protoc-gen-validate@abc123def456 ```","content":"EasyP: Прямой контроль Точный коммит (горячий фикс) - github.com/bufbuild/protoc-gen-validate@abc123def456 ```"},{"id":"cli/package-manager/easyp-vs-buf::easyp::23","title":"EasyP против Buf: управление пакетами","section":"EasyP: Прямой контроль","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["EasyP: Прямой контроль"],"excerpt":"EasyP: Прямой контроль **Преимущества по безопасности:** ✅ Нет посредника — берём из исходного репозитория ✅ Аудит через историю Git ✅ Нельзя «забанить» доступ извне ✅ Свои процессы сканирования / валидации ✅ Можно форкн","content":"EasyP: Прямой контроль **Преимущества по безопасности:** ✅ Нет посредника — берём из исходного репозитория ✅ Аудит через историю Git ✅ Нельзя «забанить» доступ извне ✅ Свои процессы сканирования / валидации ✅ Можно форкнуть и удерживать критические версии"},{"id":"cli/package-manager/easyp-vs-buf::buf::24","title":"EasyP против Buf: управление пакетами","section":"Buf: Зависимость от реестра","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf","headings":["Buf: Зависимость от реестра"],"excerpt":"Buf: Зависимость от реестра **Риски:** ⚠️ Посредник контролирует доступность ⚠️ Возможны ограничения / санкции на аккаунт ⚠️ Модуль могут удалить или депрекейтнуть ⚠️ Политики обновлений диктуются стороной ⚠️ Нужно довер","content":"Buf: Зависимость от реестра **Риски:** ⚠️ Посредник контролирует доступность ⚠️ Возможны ограничения / санкции на аккаунт ⚠️ Модуль могут удалить или депрекейтнуть ⚠️ Политики обновлений диктуются стороной ⚠️ Нужно доверять внешней безопасности"},{"id":"cli/package-manager/easyp-vs-buf::1::25","title":"EasyP против Buf: управление пакетами","section":"Сценарий 1: Стартап с публичными зависимостями","path":"/docs/guide/cli/package-manager/easyp-vs-buf#1","headings":["Сценарий 1: Стартап с публичными зависимостями"],"excerpt":"Сценарий 1: Стартап с публичными зависимостями **EasyP:**","content":"Сценарий 1: Стартап с публичными зависимостями **EasyP:**"},{"id":"cli/package-manager/easyp-vs-buf::1::26","title":"EasyP против Buf: управление пакетами","section":"Сценарий 1: Стартап с публичными зависимостями","path":"/docs/guide/cli/package-manager/easyp-vs-buf#1","headings":["Сценарий 1: Стартап с публичными зависимостями"],"excerpt":"Сценарий 1: Стартап с публичными зависимостями **Buf:**","content":"Сценарий 1: Стартап с публичными зависимостями **Buf:**"},{"id":"cli/package-manager/easyp-vs-buf::1::27","title":"EasyP против Buf: управление пакетами","section":"Сценарий 1: Стартап с публичными зависимостями","path":"/docs/guide/cli/package-manager/easyp-vs-buf#1","headings":["Сценарий 1: Стартап с публичными зависимостями"],"excerpt":"Сценарий 1: Стартап с публичными зависимостями **Итог:** Паритет — оба хорошо подходят для публичных пакетов.","content":"Сценарий 1: Стартап с публичными зависимостями **Итог:** Паритет — оба хорошо подходят для публичных пакетов."},{"id":"cli/package-manager/easyp-vs-buf::2::28","title":"EasyP против Buf: управление пакетами","section":"Сценарий 2: Компания со смешанными публичными/приватными зависимостями","path":"/docs/guide/cli/package-manager/easyp-vs-buf#2","headings":["Сценарий 2: Компания со смешанными публичными/приватными зависимостями"],"excerpt":"Сценарий 2: Компания со смешанными публичными/приватными зависимостями **EasyP:**","content":"Сценарий 2: Компания со смешанными публичными/приватными зависимостями **EasyP:**"},{"id":"cli/package-manager/easyp-vs-buf::2::29","title":"EasyP против Buf: управление пакетами","section":"Сценарий 2: Компания со смешанными публичными/приватными зависимостями","path":"/docs/guide/cli/package-manager/easyp-vs-buf#2","headings":["Сценарий 2: Компания со смешанными публичными/приватными зависимостями"],"excerpt":"Сценарий 2: Компания со смешанными публичными/приватными зависимостями **Buf:**","content":"Сценарий 2: Компания со смешанными публичными/приватными зависимостями **Buf:**"},{"id":"cli/package-manager/easyp-vs-buf::2::30","title":"EasyP против Buf: управление пакетами","section":"Сценарий 2: Компания со смешанными публичными/приватными зависимостями","path":"/docs/guide/cli/package-manager/easyp-vs-buf#2","headings":["Сценарий 2: Компания со смешанными публичными/приватными зависимостями"],"excerpt":"Сценарий 2: Компания со смешанными публичными/приватными зависимостями **Итог:** **EasyP** — не требует публикации внутрь BSR.","content":"Сценарий 2: Компания со смешанными публичными/приватными зависимостями **Итог:** **EasyP** — не требует публикации внутрь BSR."},{"id":"cli/package-manager/easyp-vs-buf::3-airgap::31","title":"EasyP против Buf: управление пакетами","section":"Сценарий 3: Государственный / оборонный подрядчик (полный air‑gap)","path":"/docs/guide/cli/package-manager/easyp-vs-buf#3-airgap","headings":["Сценарий 3: Государственный / оборонный подрядчик (полный air‑gap)"],"excerpt":"Сценарий 3: Государственный / оборонный подрядчик (полный air‑gap) **EasyP:**","content":"Сценарий 3: Государственный / оборонный подрядчик (полный air‑gap) **EasyP:**"},{"id":"cli/package-manager/easyp-vs-buf::3-airgap::32","title":"EasyP против Buf: управление пакетами","section":"Сценарий 3: Государственный / оборонный подрядчик (полный air‑gap)","path":"/docs/guide/cli/package-manager/easyp-vs-buf#3-airgap","headings":["Сценарий 3: Государственный / оборонный подрядчик (полный air‑gap)"],"excerpt":"Сценарий 3: Государственный / оборонный подрядчик (полный air‑gap) **Buf:**","content":"Сценарий 3: Государственный / оборонный подрядчик (полный air‑gap) **Buf:**"},{"id":"cli/package-manager/easyp-vs-buf::3-airgap::33","title":"EasyP против Buf: управление пакетами","section":"Сценарий 3: Государственный / оборонный подрядчик (полный air‑gap)","path":"/docs/guide/cli/package-manager/easyp-vs-buf#3-airgap","headings":["Сценарий 3: Государственный / оборонный подрядчик (полный air‑gap)"],"excerpt":"Сценарий 3: Государственный / оборонный подрядчик (полный air‑gap) **Итог:** **EasyP** — значительно проще.","content":"Сценарий 3: Государственный / оборонный подрядчик (полный air‑gap) **Итог:** **EasyP** — значительно проще."},{"id":"cli/package-manager/easyp-vs-buf::4::34","title":"EasyP против Buf: управление пакетами","section":"Сценарий 4: Комплаенс и аудит","path":"/docs/guide/cli/package-manager/easyp-vs-buf#4","headings":["Сценарий 4: Комплаенс и аудит"],"excerpt":"Сценарий 4: Комплаенс и аудит **EasyP:** ✅ Прямой аудит изменений (коммиты) ✅ Нет внешних точек зависимости в проде ✅ Повторяемость через фиксированные коммиты / vendor ✅ Управление уязвимостями — в ваших руках","content":"Сценарий 4: Комплаенс и аудит **EasyP:** ✅ Прямой аудит изменений (коммиты) ✅ Нет внешних точек зависимости в проде ✅ Повторяемость через фиксированные коммиты / vendor ✅ Управление уязвимостями — в ваших руках"},{"id":"cli/package-manager/easyp-vs-buf::4::35","title":"EasyP против Buf: управление пакетами","section":"Сценарий 4: Комплаенс и аудит","path":"/docs/guide/cli/package-manager/easyp-vs-buf#4","headings":["Сценарий 4: Комплаенс и аудит"],"excerpt":"Сценарий 4: Комплаенс и аудит **Buf:** ⚠️ Нужно учитывать BSR в области аудита ⚠️ Дополнительный риск третьей стороны ⚠️ Модули — внешние контролируемые артефакты ⚠️ Сложнее трассировать от реестра к исходникам","content":"Сценарий 4: Комплаенс и аудит **Buf:** ⚠️ Нужно учитывать BSR в области аудита ⚠️ Дополнительный риск третьей стороны ⚠️ Модули — внешние контролируемые артефакты ⚠️ Сложнее трассировать от реестра к исходникам"},{"id":"cli/package-manager/easyp-vs-buf::4::36","title":"EasyP против Buf: управление пакетами","section":"Сценарий 4: Комплаенс и аудит","path":"/docs/guide/cli/package-manager/easyp-vs-buf#4","headings":["Сценарий 4: Комплаенс и аудит"],"excerpt":"Сценарий 4: Комплаенс и аудит **Итог:** **EasyP** — проще для комплаенса.","content":"Сценарий 4: Комплаенс и аудит **Итог:** **EasyP** — проще для комплаенса."},{"id":"cli/package-manager/easyp-vs-buf::easyp::37","title":"EasyP против Buf: управление пакетами","section":"EasyP: Нулевая дополнительная инфраструктура","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["EasyP: Нулевая дополнительная инфраструктура"],"excerpt":"EasyP: Нулевая дополнительная инфраструктура **Затраты:** ✅ $0 — используете существующий Git ✅ Нет дополнительных сервисов/серверов ✅ Нет лицензирования ✅ Масштабирование в рамках Git","content":"EasyP: Нулевая дополнительная инфраструктура **Затраты:** ✅ $0 — используете существующий Git ✅ Нет дополнительных сервисов/серверов ✅ Нет лицензирования ✅ Масштабирование в рамках Git"},{"id":"cli/package-manager/easyp-vs-buf::easyp::38","title":"EasyP против Buf: управление пакетами","section":"EasyP: Нулевая дополнительная инфраструктура","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["EasyP: Нулевая дополнительная инфраструктура"],"excerpt":"EasyP: Нулевая дополнительная инфраструктура **Инфраструктура:** Использует текущие репозитории (GitHub/GitLab/и т.д.) Аутентификация — штатная Резервирование/DR — как уже настроено для Git","content":"EasyP: Нулевая дополнительная инфраструктура **Инфраструктура:** Использует текущие репозитории (GitHub/GitLab/и т.д.) Аутентификация — штатная Резервирование/DR — как уже настроено для Git"},{"id":"cli/package-manager/easyp-vs-buf::buf::39","title":"EasyP против Buf: управление пакетами","section":"Buf: Затраты на реестр","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf","headings":["Buf: Затраты на реестр"],"excerpt":"Buf: Затраты на реестр **Hosted BSR (buf.build):** ✅ Бесплатный уровень ❌ Платные тарифы для приватного и расширенного использования ❌ Потенциальные изменения ценовой политики ❌ Вопросы локализации данных","content":"Buf: Затраты на реестр **Hosted BSR (buf.build):** ✅ Бесплатный уровень ❌ Платные тарифы для приватного и расширенного использования ❌ Потенциальные изменения ценовой политики ❌ Вопросы локализации данных"},{"id":"cli/package-manager/easyp-vs-buf::buf::40","title":"EasyP против Buf: управление пакетами","section":"Buf: Затраты на реестр","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf","headings":["Buf: Затраты на реестр"],"excerpt":"Buf: Затраты на реестр **Приватный BSR:** ❌ Серверы, БД, балансировка ❌ Мониторинг, обновления, бэкапы ❌ Лицензирование enterprise функционала ❌ Доп. планирование отказоустойчивости","content":"Buf: Затраты на реестр **Приватный BSR:** ❌ Серверы, БД, балансировка ❌ Мониторинг, обновления, бэкапы ❌ Лицензирование enterprise функционала ❌ Доп. планирование отказоустойчивости"},{"id":"cli/package-manager/easyp-vs-buf::easyp::41","title":"EasyP против Buf: управление пакетами","section":"EasyP: Нет привязки","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["EasyP: Нет привязки"],"excerpt":"EasyP: Нет привязки **Миграция ИЗ EasyP:** (Обычные Git ссылки — легко перенести в другой инструмент.)","content":"EasyP: Нет привязки **Миграция ИЗ EasyP:** (Обычные Git ссылки — легко перенести в другой инструмент.)"},{"id":"cli/package-manager/easyp-vs-buf::easyp::42","title":"EasyP против Buf: управление пакетами","section":"EasyP: Нет привязки","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["EasyP: Нет привязки"],"excerpt":"EasyP: Нет привязки **Миграция В EasyP:**","content":"EasyP: Нет привязки **Миграция В EasyP:**"},{"id":"cli/package-manager/easyp-vs-buf::buf-lockin::43","title":"EasyP против Buf: управление пакетами","section":"Buf: Потенциальный lock‑in","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf-lockin","headings":["Buf: Потенциальный lock‑in"],"excerpt":"Buf: Потенциальный lock‑in **Миграция ИЗ Buf:** ❌ Нужно сопоставить BSR модули с исходными Git репо ❌ Имена модулей BSR не совпадают с URL ❌ Возможна потеря удобных метаданных ❌ Сложно при глубокой интеграции с BSR","content":"Buf: Потенциальный lock‑in **Миграция ИЗ Buf:** ❌ Нужно сопоставить BSR модули с исходными Git репо ❌ Имена модулей BSR не совпадают с URL ❌ Возможна потеря удобных метаданных ❌ Сложно при глубокой интеграции с BSR"},{"id":"cli/package-manager/easyp-vs-buf::buf-lockin::44","title":"EasyP против Buf: управление пакетами","section":"Buf: Потенциальный lock‑in","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf-lockin","headings":["Buf: Потенциальный lock‑in"],"excerpt":"Buf: Потенциальный lock‑in **Миграция В Buf:** ❌ Нужно опубликовать всё в BSR ❌ Нельзя ссылаться напрямую на Git ❌ Принять workflow BSR (push/pull модулей)","content":"Buf: Потенциальный lock‑in **Миграция В Buf:** ❌ Нужно опубликовать всё в BSR ❌ Нельзя ссылаться напрямую на Git ❌ Принять workflow BSR (push/pull модулей)"},{"id":"cli/package-manager/easyp-vs-buf::easyp::45","title":"EasyP против Buf: управление пакетами","section":"Выберите EasyP, если:","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["Выберите EasyP, если:"],"excerpt":"Выберите EasyP, если: ✅ **Air‑gapped / закрытые среды** Нужна работа без внешних сервисов Строгий комплаенс / контроль цепочки поставок","content":"Выберите EasyP, если: ✅ **Air‑gapped / закрытые среды** Нужна работа без внешних сервисов Строгий комплаенс / контроль цепочки поставок"},{"id":"cli/package-manager/easyp-vs-buf::easyp::46","title":"EasyP против Buf: управление пакетами","section":"Выберите EasyP, если:","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["Выберите EasyP, если:"],"excerpt":"Выберите EasyP, если: ✅ **Фокус на безопасности** Контроль источников зависимостей Минимизация рисков третьих сторон","content":"Выберите EasyP, если: ✅ **Фокус на безопасности** Контроль источников зависимостей Минимизация рисков третьих сторон"},{"id":"cli/package-manager/easyp-vs-buf::easyp::47","title":"EasyP против Buf: управление пакетами","section":"Выберите EasyP, если:","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["Выберите EasyP, если:"],"excerpt":"Выберите EasyP, если: ✅ **Git‑центричная культура** Частные репозитории — норма Не хотите добавлять новый ключевой сервис","content":"Выберите EasyP, если: ✅ **Git‑центричная культура** Частные репозитории — норма Не хотите добавлять новый ключевой сервис"},{"id":"cli/package-manager/easyp-vs-buf::easyp::48","title":"EasyP против Buf: управление пакетами","section":"Выберите EasyP, если:","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["Выберите EasyP, если:"],"excerpt":"Выберите EasyP, если: ✅ **Ограниченный бюджет** Минимизация операционных расходов Предсказуемая стоимость = 0","content":"Выберите EasyP, если: ✅ **Ограниченный бюджет** Минимизация операционных расходов Предсказуемая стоимость = 0"},{"id":"cli/package-manager/easyp-vs-buf::easyp::49","title":"EasyP против Buf: управление пакетами","section":"Выберите EasyP, если:","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp","headings":["Выберите EasyP, если:"],"excerpt":"Выберите EasyP, если: ✅ **Смешанные публичные/частные зависимости** Не хотите перекладывать всё в реестр Нужна гибкость форматов и размещения","content":"Выберите EasyP, если: ✅ **Смешанные публичные/частные зависимости** Не хотите перекладывать всё в реестр Нужна гибкость форматов и размещения"},{"id":"cli/package-manager/easyp-vs-buf::buf::50","title":"EasyP против Buf: управление пакетами","section":"Выберите Buf, если:","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf","headings":["Выберите Buf, если:"],"excerpt":"Выберите Buf, если: ✅ **Глубокая интеграция в экосистему BSR** Уже используете линтеры / генерацию Buf Нужны курируемые официальные модули Важны метаданные и граф зависимостей","content":"Выберите Buf, если: ✅ **Глубокая интеграция в экосистему BSR** Уже используете линтеры / генерацию Buf Нужны курируемые официальные модули Важны метаданные и граф зависимостей"},{"id":"cli/package-manager/easyp-vs-buf::buf::51","title":"EasyP против Buf: управление пакетами","section":"Выберите Buf, если:","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf","headings":["Выберите Buf, если:"],"excerpt":"Выберите Buf, если: ✅ **Сотрудничество и открытая разработка** Централизованное обнаружение модулей Совместная работа над общими пакетами","content":"Выберите Buf, если: ✅ **Сотрудничество и открытая разработка** Централизованное обнаружение модулей Совместная работа над общими пакетами"},{"id":"cli/package-manager/easyp-vs-buf::buf::52","title":"EasyP против Buf: управление пакетами","section":"Выберите Buf, если:","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf","headings":["Выберите Buf, если:"],"excerpt":"Выберите Buf, если: ✅ **Команда новичков в protobuf** Требуется «направляющая» структура Ценность документации внутри реестра","content":"Выберите Buf, если: ✅ **Команда новичков в protobuf** Требуется «направляющая» структура Ценность документации внутри реестра"},{"id":"cli/package-manager/easyp-vs-buf::buf::53","title":"EasyP против Buf: управление пакетами","section":"Выберите Buf, если:","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf","headings":["Выберите Buf, если:"],"excerpt":"Выберите Buf, если: ✅ **Небольшой набор публичных зависимостей** В основном используете популярные общие пакеты Вас устраивает зависимость от BSR","content":"Выберите Buf, если: ✅ **Небольшой набор публичных зависимостей** В основном используете популярные общие пакеты Вас устраивает зависимость от BSR"},{"id":"cli/package-manager/easyp-vs-buf::buf-easyp::54","title":"EasyP против Buf: управление пакетами","section":"Переход с Buf на EasyP","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf-easyp","headings":["Переход с Buf на EasyP"],"excerpt":"Переход с Buf на EasyP Найдите исходные Git репозитории для каждого модуля BSR Сопоставьте имена BSR → Git ссылки (с версиями/тегами) Обновите конфигурацию (easyp.yaml) Протестируйте генерацию и совместимость","content":"Переход с Buf на EasyP Найдите исходные Git репозитории для каждого модуля BSR Сопоставьте имена BSR → Git ссылки (с версиями/тегами) Обновите конфигурацию (easyp.yaml) Протестируйте генерацию и совместимость"},{"id":"cli/package-manager/easyp-vs-buf::buf-easyp::55","title":"EasyP против Buf: управление пакетами","section":"Переход с Buf на EasyP","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf-easyp","headings":["Переход с Buf на EasyP"],"excerpt":"Переход с Buf на EasyP ```yaml Было (buf.yaml) deps: - buf.build/googleapis/googleapis - buf.build/grpc/grpc","content":"Переход с Buf на EasyP ```yaml Было (buf.yaml) deps: - buf.build/googleapis/googleapis - buf.build/grpc/grpc"},{"id":"cli/package-manager/easyp-vs-buf::buf-easyp::56","title":"EasyP против Buf: управление пакетами","section":"Переход с Buf на EasyP","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf-easyp","headings":["Переход с Buf на EasyP"],"excerpt":"Переход с Buf на EasyP Стало (easyp.yaml) deps: - github.com/googleapis/googleapis@common-protos-1_3_1 - github.com/grpc/grpc@v1.50.0 ```","content":"Переход с Buf на EasyP Стало (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::easyp-buf::57","title":"EasyP против Buf: управление пакетами","section":"Переход с EasyP на Buf","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp-buf","headings":["Переход с EasyP на Buf"],"excerpt":"Переход с EasyP на Buf Опубликуйте используемые репозитории как модули BSR Настройте аутентификацию / организацию Buf Замените Git ссылки на BSR модули Перейдите к push/pull workflow Buf","content":"Переход с EasyP на Buf Опубликуйте используемые репозитории как модули BSR Настройте аутентификацию / организацию Buf Замените Git ссылки на BSR модули Перейдите к push/pull workflow Buf"},{"id":"cli/package-manager/easyp-vs-buf::top::58","title":"EasyP против Buf: управление пакетами","section":"Заключение","path":"/docs/guide/cli/package-manager/easyp-vs-buf","headings":["Заключение"],"excerpt":"Заключение Оба инструмента решают задачу управления зависимостями protobuf, но подходят под разные приоритеты:","content":"Заключение Оба инструмента решают задачу управления зависимостями protobuf, но подходят под разные приоритеты:"},{"id":"cli/package-manager/easyp-vs-buf::top::59","title":"EasyP против Buf: управление пакетами","section":"Заключение","path":"/docs/guide/cli/package-manager/easyp-vs-buf","headings":["Заключение"],"excerpt":"Заключение **Сильные стороны EasyP:** Корпоративные / изолированные среды Жёсткие требования безопасности и аудита Минимальные затраты и отсутствие доп. инфраструктуры Прямое использование Git (без промежуточного слоя) П","content":"Заключение **Сильные стороны EasyP:** Корпоративные / изолированные среды Жёсткие требования безопасности и аудита Минимальные затраты и отсутствие доп. инфраструктуры Прямое использование Git (без промежуточного слоя) Простота масштабирования"},{"id":"cli/package-manager/easyp-vs-buf::top::60","title":"EasyP против Buf: управление пакетами","section":"Заключение","path":"/docs/guide/cli/package-manager/easyp-vs-buf","headings":["Заключение"],"excerpt":"Заключение **Сильные стороны Buf:** Богатая экосистема вокруг реестра Курируемые и документированные модули Удобство для новых команд в protobuf Средства визуализации и централизованного обмена","content":"Заключение **Сильные стороны Buf:** Богатая экосистема вокруг реестра Курируемые и документированные модули Удобство для новых команд в protobuf Средства визуализации и централизованного обмена"},{"id":"cli/package-manager/easyp-vs-buf::top::61","title":"EasyP против Buf: управление пакетами","section":"Заключение","path":"/docs/guide/cli/package-manager/easyp-vs-buf","headings":["Заключение"],"excerpt":"Заключение Выбор часто сводится к балансу между **контролем vs. удобством**, **безопасностью vs. централизованными функциями**, и **стоимостью vs. managed‑сервисом**.","content":"Заключение Выбор часто сводится к балансу между **контролем vs. удобством**, **безопасностью vs. централизованными функциями**, и **стоимостью vs. managed‑сервисом**."},{"id":"cli/package-manager/easyp-vs-buf::top::62","title":"EasyP против Buf: управление пакетами","section":"Заключение","path":"/docs/guide/cli/package-manager/easyp-vs-buf","headings":["Заключение"],"excerpt":"Заключение Для большинства enterprise‑окружений децентрализованный Git‑подход EasyP обеспечивает нужные гибкость, безопасность и предсказуемость расходов, тогда как Buf отлично подходит командам, которым важна централизо","content":"Заключение Для большинства enterprise‑окружений децентрализованный Git‑подход EasyP обеспечивает нужные гибкость, безопасность и предсказуемость расходов, тогда как Buf отлично подходит командам, которым важна централизованная коллаборация и богатая экосистема вокруг реестра."},{"id":"cli/package-manager/package-manager::top::0","title":"Менеджер пакетов","path":"/docs/guide/cli/package-manager/package-manager","headings":[],"excerpt":"EasyP предоставляет мощный менеджер пакетов для protobuf‑зависимостей, упрощающий их управление за счёт децентрализованного подхода на базе Git. В отличие от централизованных решений, EasyP работает напрямую с Git‑репози","content":"EasyP предоставляет мощный менеджер пакетов для protobuf‑зависимостей, упрощающий их управление за счёт децентрализованного подхода на базе Git. В отличие от централизованных решений, EasyP работает напрямую с Git‑репозиториями, давая вам полный контроль."},{"id":"cli/package-manager/package-manager::top::1","title":"Менеджер пакетов","section":"Обзор","path":"/docs/guide/cli/package-manager/package-manager","headings":["Обзор"],"excerpt":"Обзор Менеджер пакетов EasyP следует философии **Go modules** — любой Git‑репозиторий может быть источником. Это даёт преимущества:","content":"Обзор Менеджер пакетов EasyP следует философии **Go modules** — любой Git‑репозиторий может быть источником. Это даёт преимущества:"},{"id":"cli/package-manager/package-manager::top::2","title":"Менеджер пакетов","section":"Обзор","path":"/docs/guide/cli/package-manager/package-manager","headings":["Обзор"],"excerpt":"Обзор **Децентрализация** — нет единой точки отказа или контроля **Безопасность** — прямой доступ к исходникам **Гибкость** — публичные, приватные и корпоративные репозитории **Воспроизводимость** — lock‑файлы обеспечива","content":"Обзор **Децентрализация** — нет единой точки отказа или контроля **Безопасность** — прямой доступ к исходникам **Гибкость** — публичные, приватные и корпоративные репозитории **Воспроизводимость** — lock‑файлы обеспечивают одинаковые сборки **Производительность** — локальный кеш сокращает сетевые запросы"},{"id":"cli/package-manager/package-manager::top::3","title":"Менеджер пакетов","section":"Основные возможности","path":"/docs/guide/cli/package-manager/package-manager","headings":["Основные возможности"],"excerpt":"Основные возможности Возможность Описание ------------- ---------- **Git-Native** Любой Git репозиторий, не нужен спец‑сервер **Множество форматов версий** Теги, коммиты, псевдо‑версии, latest **Lock Files** Воспроизводи","content":"Основные возможности Возможность Описание ------------- ---------- **Git-Native** Любой Git репозиторий, не нужен спец‑сервер **Множество форматов версий** Теги, коммиты, псевдо‑версии, latest **Lock Files** Воспроизводимые сборки через easyp.lock **Локальный кеш** Архитектура как у Go modules **Vendoring** Локальное копирование для оффлайн сборок **YAML конфигурация** Простые и читаемые декларации"},{"id":"cli/package-manager/package-manager::top::4","title":"Менеджер пакетов","section":"Архитектура","path":"/docs/guide/cli/package-manager/package-manager","headings":["Архитектура"],"excerpt":"Архитектура EasyP использует двухуровневый кеш, вдохновлённый Go modules:","content":"Архитектура EasyP использует двухуровневый кеш, вдохновлённый Go modules:"},{"id":"cli/package-manager/package-manager::top::5","title":"Менеджер пакетов","section":"Расположение кеша","path":"/docs/guide/cli/package-manager/package-manager","headings":["Расположение кеша"],"excerpt":"Расположение кеша Окружение Путь Как задать ----------- ------ ----------- **По умолчанию** $HOME/.easyp Автоматически **Свое** Любая директория Переменная EASYPPATH **CI/CD** В каталоге проекта export EASYPPATH=$CI_PROJ","content":"Расположение кеша Окружение Путь Как задать ----------- ------ ----------- **По умолчанию** $HOME/.easyp Автоматически **Свое** Любая директория Переменная EASYPPATH **CI/CD** В каталоге проекта export EASYPPATH=$CI_PROJECT_DIR/.easyp"},{"id":"cli/package-manager/package-manager::top::6","title":"Менеджер пакетов","section":"Базовая конфигурация","path":"/docs/guide/cli/package-manager/package-manager","headings":["Базовая конфигурация"],"excerpt":"Базовая конфигурация Зависимости описываются в easyp.yaml:","content":"Базовая конфигурация Зависимости описываются в easyp.yaml:"},{"id":"cli/package-manager/package-manager::multi-environment-setup::7","title":"Менеджер пакетов","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 # Последнее для разработки - github.com/mycompany/internal-protos # Внутренние изменения - github.com/bufbuild/protoc-gen-va","content":"Multi-Environment Setup ```yaml development.easyp.yaml deps: - github.com/googleapis/googleapis # Последнее для разработки - github.com/mycompany/internal-protos # Внутренние изменения - github.com/bufbuild/protoc-gen-validate # Новые фичи"},{"id":"cli/package-manager/package-manager::multi-environment-setup::8","title":"Менеджер пакетов","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 # Зафиксировано - github.com/mycompany/internal-protos@v2.1.0 # Стабильно - github.com/bufbuild/protoc-gen-valida","content":"Multi-Environment Setup production.easyp.yaml deps: - github.com/googleapis/googleapis@common-protos-1_3_1 # Зафиксировано - github.com/mycompany/internal-protos@v2.1.0 # Стабильно - github.com/bufbuild/protoc-gen-validate@v0.10.1 # Проверено ```"},{"id":"cli/package-manager/package-manager::top::9","title":"Менеджер пакетов","section":"Приватные репозитории","path":"/docs/guide/cli/package-manager/package-manager","headings":["Приватные репозитории"],"excerpt":"Приватные репозитории ```yaml deps: # Публичное - github.com/googleapis/googleapis@common-protos-1_3_1","content":"Приватные репозитории ```yaml deps: # Публичное - github.com/googleapis/googleapis@common-protos-1_3_1"},{"id":"cli/package-manager/package-manager::top::10","title":"Менеджер пакетов","section":"Приватные репозитории","path":"/docs/guide/cli/package-manager/package-manager","headings":["Приватные репозитории"],"excerpt":"Приватные репозитории Частные - github.com/mycompany/auth-protos@v1.5.0 - github.com/mycompany/common-types@v2.0.1","content":"Приватные репозитории Частные - github.com/mycompany/auth-protos@v1.5.0 - github.com/mycompany/common-types@v2.0.1"},{"id":"cli/package-manager/package-manager::top::11","title":"Менеджер пакетов","section":"Приватные репозитории","path":"/docs/guide/cli/package-manager/package-manager","headings":["Приватные репозитории"],"excerpt":"Приватные репозитории Внутренний GitLab - gitlab.company.com/platform/messaging-protos@v0.3.0 ```","content":"Приватные репозитории Внутренний GitLab - gitlab.company.com/platform/messaging-protos@v0.3.0 ```"},{"id":"cli/package-manager/package-manager::top::12","title":"Менеджер пакетов","section":"Стратегии версионирования","path":"/docs/guide/cli/package-manager/package-manager","headings":["Стратегии версионирования"],"excerpt":"Стратегии версионирования Поддерживаются разные способы фиксации версий:","content":"Стратегии версионирования Поддерживаются разные способы фиксации версий:"},{"id":"cli/package-manager/package-manager::1::13","title":"Менеджер пакетов","section":"1. Семантические теги (для продакшена)","path":"/docs/guide/cli/package-manager/package-manager#1","headings":["1. Семантические теги (для продакшена)"],"excerpt":"Семантические теги (для продакшена)","content":"Семантические теги (для продакшена)"},{"id":"cli/package-manager/package-manager::1::14","title":"Менеджер пакетов","section":"1. Семантические теги (для продакшена)","path":"/docs/guide/cli/package-manager/package-manager#1","headings":["1. Семантические теги (для продакшена)"],"excerpt":"Семантические теги (для продакшена) **Используйте когда:** Продакшен Стабильное потребление API Нужна воспроизводимость","content":"Семантические теги (для продакшена) **Используйте когда:** Продакшен Стабильное потребление API Нужна воспроизводимость"},{"id":"cli/package-manager/package-manager::2-development::15","title":"Менеджер пакетов","section":"2. Последний тег (development)","path":"/docs/guide/cli/package-manager/package-manager#2-development","headings":["2. Последний тег (development)"],"excerpt":"Последний тег (development) **Подходит для:** Активной разработки Получения свежих возможностей Тестирования совместимости","content":"Последний тег (development) **Подходит для:** Активной разработки Получения свежих возможностей Тестирования совместимости"},{"id":"cli/package-manager/package-manager::3-bleeding-edge::16","title":"Менеджер пакетов","section":"3. Хеш коммита (Bleeding Edge)","path":"/docs/guide/cli/package-manager/package-manager#3-bleeding-edge","headings":["3. Хеш коммита (Bleeding Edge)"],"excerpt":"Хеш коммита (Bleeding Edge) **Когда нужно:** Нерелизные фичи Тест конкретного фикса Вклад в upstream","content":"Хеш коммита (Bleeding Edge) **Когда нужно:** Нерелизные фичи Тест конкретного фикса Вклад в upstream"},{"id":"cli/package-manager/package-manager::4::17","title":"Менеджер пакетов","section":"4. Псевдо‑версии (автоматически)","path":"/docs/guide/cli/package-manager/package-manager#4","headings":["4. Псевдо‑версии (автоматически)"],"excerpt":"Псевдо‑версии (автоматически) Если нет подходящего тега — создаётся псевдо‑версия:","content":"Псевдо‑версии (автоматически) Если нет подходящего тега — создаётся псевдо‑версия:"},{"id":"cli/package-manager/package-manager::easyp-mod-download::18","title":"Менеджер пакетов","section":"easyp mod download","path":"/docs/guide/cli/package-manager/package-manager#easyp-mod-download","headings":["easyp mod download"],"excerpt":"easyp mod download Скачивает и устанавливает все объявленные зависимости.","content":"easyp mod download Скачивает и устанавливает все объявленные зависимости."},{"id":"cli/package-manager/package-manager::easyp-mod-download::19","title":"Менеджер пакетов","section":"easyp mod download","path":"/docs/guide/cli/package-manager/package-manager#easyp-mod-download","headings":["easyp mod download"],"excerpt":"easyp mod download **Что делает:** Разрешает версии (теги → коммиты) Скачивает архивы в cache/download Проверяет контрольные суммы Распаковывает в cache/mod Обновляет easyp.lock","content":"easyp mod download **Что делает:** Разрешает версии (теги → коммиты) Скачивает архивы в cache/download Проверяет контрольные суммы Распаковывает в cache/mod Обновляет easyp.lock"},{"id":"cli/package-manager/package-manager::easyp-mod-download::20","title":"Менеджер пакетов","section":"easyp mod download","path":"/docs/guide/cli/package-manager/package-manager#easyp-mod-download","headings":["easyp mod download"],"excerpt":"easyp mod download **Пример:**","content":"easyp mod download **Пример:**"},{"id":"cli/package-manager/package-manager::easyp-mod-vendor::21","title":"Менеджер пакетов","section":"easyp mod vendor","path":"/docs/guide/cli/package-manager/package-manager#easyp-mod-vendor","headings":["easyp mod vendor"],"excerpt":"easyp mod vendor Копирует все proto зависимости в локальный easyp_vendor/ для оффлайна.","content":"easyp mod vendor Копирует все proto зависимости в локальный easyp_vendor/ для оффлайна."},{"id":"cli/package-manager/package-manager::easyp-mod-vendor::22","title":"Менеджер пакетов","section":"easyp mod vendor","path":"/docs/guide/cli/package-manager/package-manager#easyp-mod-vendor","headings":["easyp mod vendor"],"excerpt":"easyp mod vendor **Сценарии:** Docker сборки Air-gapped окружения Воспроизводимость Ускорение","content":"easyp mod vendor **Сценарии:** Docker сборки Air-gapped окружения Воспроизводимость Ускорение"},{"id":"cli/package-manager/package-manager::easyp-mod-update::23","title":"Менеджер пакетов","section":"easyp mod update","path":"/docs/guide/cli/package-manager/package-manager#easyp-mod-update","headings":["easyp mod update"],"excerpt":"easyp mod update Обновляет версии согласно easyp.yaml, пересоздаёт lock.","content":"easyp mod update Обновляет версии согласно easyp.yaml, пересоздаёт lock."},{"id":"cli/package-manager/package-manager::lock::24","title":"Менеджер пакетов","section":"Lock файл","path":"/docs/guide/cli/package-manager/package-manager#lock","headings":["Lock файл"],"excerpt":"Lock файл easyp.lock фиксирует точные версии и хеш содержимого:","content":"Lock файл easyp.lock фиксирует точные версии и хеш содержимого:"},{"id":"cli/package-manager/package-manager::lock::25","title":"Менеджер пакетов","section":"Lock файл","path":"/docs/guide/cli/package-manager/package-manager#lock","headings":["Lock файл"],"excerpt":"Lock файл **Формат строки:** Путь модуля Версия (тег или псевдо) Хеш содержимого (h1:)","content":"Lock файл **Формат строки:** Путь модуля Версия (тег или псевдо) Хеш содержимого (h1:)"},{"id":"cli/package-manager/package-manager::lock::26","title":"Менеджер пакетов","section":"Lock файл","path":"/docs/guide/cli/package-manager/package-manager#lock","headings":["Lock файл"],"excerpt":"Lock файл **Практики:** ✅ Коммитить easyp.lock ✅ Осознанно обновлять mod update ✅ Ревью изменений версий ❌ Не редактировать вручную","content":"Lock файл **Практики:** ✅ Коммитить easyp.lock ✅ Осознанно обновлять mod update ✅ Ревью изменений версий ❌ Не редактировать вручную"},{"id":"cli/package-manager/package-manager::top::27","title":"Менеджер пакетов","section":"Публичные репозитории","path":"/docs/guide/cli/package-manager/package-manager","headings":["Публичные репозитории"],"excerpt":"Публичные репозитории Работают без настроек:","content":"Публичные репозитории Работают без настроек:"},{"id":"cli/package-manager/package-manager::ssh::28","title":"Менеджер пакетов","section":"SSH ключи (рекомендуется)","path":"/docs/guide/cli/package-manager/package-manager#ssh","headings":["SSH ключи (рекомендуется)"],"excerpt":"SSH ключи (рекомендуется) Конфиг остаётся с HTTPS URL:","content":"SSH ключи (рекомендуется) Конфиг остаётся с HTTPS URL:"},{"id":"cli/package-manager/package-manager::personal-access-tokens::29","title":"Менеджер пакетов","section":"Personal Access Tokens","path":"/docs/guide/cli/package-manager/package-manager#personal-access-tokens","headings":["Personal Access Tokens"],"excerpt":"Personal Access Tokens ```bash git config --global credential.helper store echo \"https://username:token@github.com\" >> ~/.git-credentials","content":"Personal Access Tokens ```bash git config --global credential.helper store echo \"https://username:token@github.com\" >> ~/.git-credentials"},{"id":"cli/package-manager/package-manager::personal-access-tokens::30","title":"Менеджер пакетов","section":"Personal Access Tokens","path":"/docs/guide/cli/package-manager/package-manager#personal-access-tokens","headings":["Personal Access Tokens"],"excerpt":"Personal Access Tokens git config --global url.\"https://username:token@github.com/mycompany\".insteadOf \"https://github.com/mycompany\" ```","content":"Personal Access Tokens git config --global url.\"https://username:token@github.com/mycompany\".insteadOf \"https://github.com/mycompany\" ```"},{"id":"cli/package-manager/package-manager::top::31","title":"Менеджер пакетов","section":"Инициализация проекта","path":"/docs/guide/cli/package-manager/package-manager","headings":["Инициализация проекта"],"excerpt":"Инициализация проекта ```bash cat > easyp.yaml << EOF deps: - github.com/googleapis/googleapis - github.com/grpc-ecosystem/grpc-gateway@v2.19.1 EOF","content":"Инициализация проекта ```bash 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::top::32","title":"Менеджер пакетов","section":"Инициализация проекта","path":"/docs/guide/cli/package-manager/package-manager","headings":["Инициализация проекта"],"excerpt":"Инициализация проекта easyp mod download ls ~/.easyp/mod/github.com/googleapis/googleapis/ ```","content":"Инициализация проекта easyp mod download ls ~/.easyp/mod/github.com/googleapis/googleapis/ ```"},{"id":"cli/package-manager/package-manager::repository-not-found-authentication-failed::33","title":"Менеджер пакетов","section":"\"Repository not found\" / \"Authentication failed\"","path":"/docs/guide/cli/package-manager/package-manager#repository-not-found-authentication-failed","headings":["\"Repository not found\" / \"Authentication failed\""],"excerpt":"\"Repository not found\" / \"Authentication failed\"","content":"\"Repository not found\" / \"Authentication failed\""},{"id":"cli/package-manager/package-manager::cache-corruption-checksum-mismatch::34","title":"Менеджер пакетов","section":"\"Cache corruption\" / \"Checksum mismatch\"","path":"/docs/guide/cli/package-manager/package-manager#cache-corruption-checksum-mismatch","headings":["\"Cache corruption\" / \"Checksum mismatch\""],"excerpt":"\"Cache corruption\" / \"Checksum mismatch\"","content":"\"Cache corruption\" / \"Checksum mismatch\""},{"id":"cli/package-manager/package-manager::docker-multi-stage::35","title":"Менеджер пакетов","section":"Docker multi-stage","path":"/docs/guide/cli/package-manager/package-manager#docker-multi-stage","headings":["Docker multi-stage"],"excerpt":"Docker multi-stage ```dockerfile FROM ghcr.io/easyp-tech/easyp:latest AS deps WORKDIR /workspace COPY easyp.yaml easyp.lock ./ RUN easyp mod vendor","content":"Docker multi-stage ```dockerfile 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::36","title":"Менеджер пакетов","section":"Docker multi-stage","path":"/docs/guide/cli/package-manager/package-manager#docker-multi-stage","headings":["Docker multi-stage"],"excerpt":"Docker multi-stage FROM alpine:latest AS build WORKDIR /app COPY --from=deps /workspace/easyp_vendor ./easyp_vendor COPY . . RUN easyp generate ```","content":"Docker multi-stage FROM alpine:latest AS build WORKDIR /app COPY --from=deps /workspace/easyp_vendor ./easyp_vendor COPY . . RUN easyp generate ```"},{"id":"cli/package-manager/package-manager::monorepo::37","title":"Менеджер пакетов","section":"Monorepo","path":"/docs/guide/cli/package-manager/package-manager#monorepo","headings":["Monorepo"],"excerpt":"Monorepo Каждый easyp.yaml может иметь свой набор зависимостей.","content":"Monorepo Каждый easyp.yaml может иметь свой набор зависимостей."},{"id":"cli/package-manager/package-manager::workflow::38","title":"Менеджер пакетов","section":"Workflow разработки","path":"/docs/guide/cli/package-manager/package-manager#workflow","headings":["Workflow разработки"],"excerpt":"Workflow разработки ✅ Latest теги в активной разработке ✅ Фиксация версий в продакшене ✅ Коммит lock файла ✅ Ревью обновлений ✅ Тест после обновления","content":"Workflow разработки ✅ Latest теги в активной разработке ✅ Фиксация версий в продакшене ✅ Коммит lock файла ✅ Ревью обновлений ✅ Тест после обновления"},{"id":"cli/package-manager/package-manager::top::39","title":"Менеджер пакетов","section":"Безопасность","path":"/docs/guide/cli/package-manager/package-manager","headings":["Безопасность"],"excerpt":"Безопасность ✅ Фиксируйте версии ✅ Используйте SSH ключи ✅ Оценивайте новые зависимости ✅ Следите за уязвимостями ❌ Не храните секреты в конфиге","content":"Безопасность ✅ Фиксируйте версии ✅ Используйте SSH ключи ✅ Оценивайте новые зависимости ✅ Следите за уязвимостями ❌ Не храните секреты в конфиге"},{"id":"cli/package-manager/package-manager::top::40","title":"Менеджер пакетов","section":"Производительность","path":"/docs/guide/cli/package-manager/package-manager","headings":["Производительность"],"excerpt":"Производительность ✅ Агрессивное кеширование в CI ✅ Vendoring для частых сборок ✅ Чистка старого кеша ✅ Общий кеш для команды","content":"Производительность ✅ Агрессивное кеширование в CI ✅ Vendoring для частых сборок ✅ Чистка старого кеша ✅ Общий кеш для команды"},{"id":"cli/package-manager/package-manager::top::41","title":"Менеджер пакетов","section":"Командная работа","path":"/docs/guide/cli/package-manager/package-manager","headings":["Командная работа"],"excerpt":"Командная работа ✅ Документация по аутентификации ✅ Единые инструменты ✅ Автоматизация обновлений с тестами ✅ Общий кеш при возможности","content":"Командная работа ✅ Документация по аутентификации ✅ Единые инструменты ✅ Автоматизация обновлений с тестами ✅ Общий кеш при возможности"},{"id":"cli/package-manager/package-manager::top::42","title":"Менеджер пакетов","section":"Командная работа","path":"/docs/guide/cli/package-manager/package-manager","headings":["Командная работа"],"excerpt":"Командная работа Менеджер пакетов EasyP — масштабируемое децентрализованное решение от одиночных проектов до enterprise, сохраняя простоту и надёжность.","content":"Командная работа Менеджер пакетов EasyP — масштабируемое децентрализованное решение от одиночных проектов до enterprise, сохраняя простоту и надёжность."},{"id":"introduction/install::top::0","title":"Установка EasyP CLI","section":"Установка через менеджер пакетов системы","path":"/docs/guide/introduction/install","headings":["Установка через менеджер пакетов системы"],"excerpt":"Установка через менеджер пакетов системы","content":"Установка через менеджер пакетов системы"},{"id":"introduction/install::top::1","title":"Установка EasyP CLI","section":"Рекомендуемый способ установки","path":"/docs/guide/introduction/install","headings":["Рекомендуемый способ установки"],"excerpt":"Рекомендуемый способ установки","content":"Рекомендуемый способ установки"},{"id":"introduction/install::homebrew::2","title":"Установка EasyP CLI","section":"Homebrew","path":"/docs/guide/introduction/install#homebrew","headings":["Homebrew"],"excerpt":"Homebrew Можно установить бинарный релиз в macOS через Homebrew:","content":"Homebrew Можно установить бинарный релиз в macOS через Homebrew:"},{"id":"introduction/install::homebrew::3","title":"Установка EasyP CLI","section":"Homebrew","path":"/docs/guide/introduction/install#homebrew","headings":["Homebrew"],"excerpt":"Homebrew Work in progress — поддержка других менеджеров (apt, yum, pacman и т.д.) в процессе.","content":"Homebrew Work in progress — поддержка других менеджеров (apt, yum, pacman и т.д.) в процессе."},{"id":"introduction/install::_-_::4","title":"Установка EasyP CLI","section":"_Не рекомендуется_","path":"/docs/guide/introduction/install#_-_","headings":["_Не рекомендуется_"],"excerpt":"_Не рекомендуется_ Локальная установка менее предпочтительна, потому что пакетные менеджеры обеспечивают: Автоматические обновления и патчи безопасности Лучшую интеграцию с системой Упрощённую установку и удаление Подпис","content":"_Не рекомендуется_ Локальная установка менее предпочтительна, потому что пакетные менеджеры обеспечивают: Автоматические обновления и патчи безопасности Лучшую интеграцию с системой Упрощённую установку и удаление Подписанные и проверенные бинарники"},{"id":"introduction/install::go-install::5","title":"Установка EasyP CLI","section":"Установка через go install","path":"/docs/guide/introduction/install#go-install","headings":["Установка через go install"],"excerpt":"Установка через go install Команда установит последнюю стабильную версию easyp:","content":"Установка через go install Команда установит последнюю стабильную версию easyp:"},{"id":"introduction/install::top::6","title":"Установка EasyP CLI","section":"Сборка из исходников","path":"/docs/guide/introduction/install","headings":["Сборка из исходников"],"excerpt":"Сборка из исходников Клонирование репозитория","content":"Сборка из исходников Клонирование репозитория"},{"id":"introduction/install::top::7","title":"Установка EasyP CLI","section":"Сборка из исходников","path":"/docs/guide/introduction/install","headings":["Сборка из исходников"],"excerpt":"Сборка из исходников Сборка с помощью Go","content":"Сборка из исходников Сборка с помощью Go"},{"id":"introduction/quickstart::top::0","title":"Быстрый старт (Quickstart)","path":"/docs/guide/introduction/quickstart","headings":[],"excerpt":"EasyP — современный toolkit для работы с файлами Protobuf. В этом кратком руководстве вы научитесь:","content":"EasyP — современный toolkit для работы с файлами Protobuf. В этом кратком руководстве вы научитесь:"},{"id":"introduction/quickstart::top::1","title":"Быстрый старт (Quickstart)","path":"/docs/guide/introduction/quickstart","headings":[],"excerpt":"**Инициализировать** проект с конфигурацией EasyP **Настраивать линтинг**, чтобы ловить ошибки и соблюдать лучшие практики **Управлять зависимостями** из Git‑репозиториев **Генерировать код** из ваших Protobuf файлов","content":"**Инициализировать** проект с конфигурацией EasyP **Настраивать линтинг**, чтобы ловить ошибки и соблюдать лучшие практики **Управлять зависимостями** из Git‑репозиториев **Генерировать код** из ваших Protobuf файлов"},{"id":"introduction/quickstart::top::2","title":"Быстрый старт (Quickstart)","section":"Предварительные требования","path":"/docs/guide/introduction/quickstart","headings":["Предварительные требования"],"excerpt":"Предварительные требования Перед началом убедитесь, что у вас установлены:","content":"Предварительные требования Перед началом убедитесь, что у вас установлены:"},{"id":"introduction/quickstart::top::3","title":"Быстрый старт (Quickstart)","section":"Предварительные требования","path":"/docs/guide/introduction/quickstart","headings":["Предварительные требования"],"excerpt":"Предварительные требования **EasyP CLI** — см. руководство по установке **Git** доступен в вашем $PATH **Файлы .proto** (или создайте их по ходу)","content":"Предварительные требования **EasyP CLI** — см. руководство по установке **Git** доступен в вашем $PATH **Файлы .proto** (или создайте их по ходу)"},{"id":"introduction/quickstart::top::4","title":"Быстрый старт (Quickstart)","section":"Предварительные требования","path":"/docs/guide/introduction/quickstart","headings":["Предварительные требования"],"excerpt":"Предварительные требования Проверить версию EasyP:","content":"Предварительные требования Проверить версию EasyP:"},{"id":"introduction/quickstart::top::5","title":"Быстрый старт (Quickstart)","section":"Инициализация проекта","path":"/docs/guide/introduction/quickstart","headings":["Инициализация проекта"],"excerpt":"Инициализация проекта Создайте базовый файл конфигурации easyp.yaml в корне проекта:","content":"Инициализация проекта Создайте базовый файл конфигурации easyp.yaml в корне проекта:"},{"id":"introduction/quickstart::top::6","title":"Быстрый старт (Quickstart)","section":"Инициализация проекта","path":"/docs/guide/introduction/quickstart","headings":["Инициализация проекта"],"excerpt":"Инициализация проекта Команда генерирует шаблон easyp.yaml с комментариями, дефолтными lint-правилами и настройками breaking-check. easyp init работает интерактивно: если в корне есть buf.yml/buf.yaml, EasyP предложит ми","content":"Инициализация проекта Команда генерирует шаблон easyp.yaml с комментариями, дефолтными lint-правилами и настройками breaking-check. easyp init работает интерактивно: если в корне есть buf.yml/buf.yaml, EasyP предложит миграцию; если easyp.yaml уже существует, попросит подтверждение перед перезаписью."},{"id":"introduction/quickstart::top::7","title":"Быстрый старт (Quickstart)","section":"Настройка линтинга","path":"/docs/guide/introduction/quickstart","headings":["Настройка линтинга"],"excerpt":"Настройка линтинга Линтинг помогает находить проблемы и поддерживать единый стиль. EasyP использует правила, совместимые с Buf.","content":"Настройка линтинга Линтинг помогает находить проблемы и поддерживать единый стиль. EasyP использует правила, совместимые с Buf."},{"id":"introduction/quickstart::top::8","title":"Быстрый старт (Quickstart)","section":"Настройка линтинга","path":"/docs/guide/introduction/quickstart","headings":["Настройка линтинга"],"excerpt":"Настройка линтинга Секция lint уже создаётся командой easyp init. При необходимости отредактируйте её, например так:","content":"Настройка линтинга Секция lint уже создаётся командой easyp init. При необходимости отредактируйте её, например так:"},{"id":"introduction/quickstart::top::9","title":"Быстрый старт (Quickstart)","section":"Настройка линтинга","path":"/docs/guide/introduction/quickstart","headings":["Настройка линтинга"],"excerpt":"Настройка линтинга Запустите линтер:","content":"Настройка линтинга Запустите линтер:"},{"id":"introduction/quickstart::top::10","title":"Быстрый старт (Quickstart)","section":"Настройка линтинга","path":"/docs/guide/introduction/quickstart","headings":["Настройка линтинга"],"excerpt":"Настройка линтинга Линтер проверит все .proto файлы и сообщит о найденных проблемах.","content":"Настройка линтинга Линтер проверит все .proto файлы и сообщит о найденных проблемах."},{"id":"introduction/quickstart::top::11","title":"Быстрый старт (Quickstart)","section":"Настройка линтинга","path":"/docs/guide/introduction/quickstart","headings":["Настройка линтинга"],"excerpt":"Настройка линтинга ::: tip Правила линтинга EasyP на 100% совместимы с Buf — мигрировать просто. :::","content":"Настройка линтинга ::: tip Правила линтинга EasyP на 100% совместимы с Buf — мигрировать просто. :::"},{"id":"introduction/quickstart::top::12","title":"Быстрый старт (Quickstart)","section":"Управление зависимостями","path":"/docs/guide/introduction/quickstart","headings":["Управление зависимостями"],"excerpt":"Управление зависимостями Если вы используете сторонние protobuf пакеты (например Google APIs или gRPC Gateway), EasyP упрощает их подключение.","content":"Управление зависимостями Если вы используете сторонние protobuf пакеты (например Google APIs или gRPC Gateway), EasyP упрощает их подключение."},{"id":"introduction/quickstart::top::13","title":"Быстрый старт (Quickstart)","section":"Формат зависимости","path":"/docs/guide/introduction/quickstart","headings":["Формат зависимости"],"excerpt":"Формат зависимости Запись: $GIT_LINK@$VERSION","content":"Формат зависимости Запись: $GIT_LINK@$VERSION"},{"id":"introduction/quickstart::top::14","title":"Быстрый старт (Quickstart)","section":"Формат зависимости","path":"/docs/guide/introduction/quickstart","headings":["Формат зависимости"],"excerpt":"Формат зависимости **$GIT_LINK** — URL любого Git‑репозитория (GitHub, GitLab и т.д.) **$VERSION** — тег или хеш коммита (опционально)","content":"Формат зависимости **$GIT_LINK** — URL любого Git‑репозитория (GitHub, GitLab и т.д.) **$VERSION** — тег или хеш коммита (опционально)"},{"id":"introduction/quickstart::top::15","title":"Быстрый старт (Quickstart)","section":"Формат зависимости","path":"/docs/guide/introduction/quickstart","headings":["Формат зависимости"],"excerpt":"Формат зависимости Если версия не указана — берётся последний коммит из основной ветки.","content":"Формат зависимости Если версия не указана — берётся последний коммит из основной ветки."},{"id":"introduction/quickstart::top::16","title":"Быстрый старт (Quickstart)","section":"Добавление зависимостей","path":"/docs/guide/introduction/quickstart","headings":["Добавление зависимостей"],"excerpt":"Добавление зависимостей Дополните easyp.yaml:","content":"Добавление зависимостей Дополните easyp.yaml:"},{"id":"introduction/quickstart::top::17","title":"Быстрый старт (Quickstart)","section":"Загрузка зависимостей","path":"/docs/guide/introduction/quickstart","headings":["Загрузка зависимостей"],"excerpt":"Загрузка зависимостей Команда: Скачивает версии из easyp.lock, если он существует Иначе — берёт из easyp.yaml и создаёт easyp.lock","content":"Загрузка зависимостей Команда: Скачивает версии из easyp.lock, если он существует Иначе — берёт из easyp.yaml и создаёт easyp.lock"},{"id":"introduction/quickstart::top::18","title":"Быстрый старт (Quickstart)","section":"Загрузка зависимостей","path":"/docs/guide/introduction/quickstart","headings":["Загрузка зависимостей"],"excerpt":"Загрузка зависимостей ::: info Совет: easyp mod update — игнорирует lock‑файл и подтягивает актуальные версии из easyp.yaml. :::","content":"Загрузка зависимостей ::: info Совет: easyp mod update — игнорирует lock‑файл и подтягивает актуальные версии из easyp.yaml. :::"},{"id":"introduction/quickstart::top::19","title":"Быстрый старт (Quickstart)","section":"Генерация кода","path":"/docs/guide/introduction/quickstart","headings":["Генерация кода"],"excerpt":"Генерация кода EasyP поддерживает все стандартные protoc‑плагины.","content":"Генерация кода EasyP поддерживает все стандартные protoc‑плагины."},{"id":"introduction/quickstart::top::20","title":"Быстрый старт (Quickstart)","section":"Конфигурация генерации","path":"/docs/guide/introduction/quickstart","headings":["Конфигурация генерации"],"excerpt":"Конфигурация генерации Добавьте плагины:","content":"Конфигурация генерации Добавьте плагины:"},{"id":"introduction/quickstart::top::21","title":"Быстрый старт (Quickstart)","section":"Запуск генерации","path":"/docs/guide/introduction/quickstart","headings":["Запуск генерации"],"excerpt":"Запуск генерации EasyP выполнит: Разрешение всех зависимостей Подключение к сервису EasyP (или локальный режим) Запуск указанных плагинов Вывод сгенерированного кода в нужные директории","content":"Запуск генерации EasyP выполнит: Разрешение всех зависимостей Подключение к сервису EasyP (или локальный режим) Запуск указанных плагинов Вывод сгенерированного кода в нужные директории"},{"id":"introduction/quickstart::top::22","title":"Быстрый старт (Quickstart)","section":"Запуск генерации","path":"/docs/guide/introduction/quickstart","headings":["Запуск генерации"],"excerpt":"Запуск генерации ::: tip Гибридный рантайм: WASM для скорости, Docker — для тяжёлых плагинов. :::","content":"Запуск генерации ::: tip Гибридный рантайм: WASM для скорости, Docker — для тяжёлых плагинов. :::"},{"id":"introduction/quickstart::top::23","title":"Быстрый старт (Quickstart)","section":"Следующие шаги","path":"/docs/guide/introduction/quickstart","headings":["Следующие шаги"],"excerpt":"Следующие шаги Поздравляем! 🎉 Вы успешно: ✅ Инициализировали проект EasyP ✅ Настроили линтинг ✅ Управляете внешними зависимостями ✅ Сгенерировали код из .proto","content":"Следующие шаги Поздравляем! 🎉 Вы успешно: ✅ Инициализировали проект EasyP ✅ Настроили линтинг ✅ Управляете внешними зависимостями ✅ Сгенерировали код из .proto"},{"id":"introduction/quickstart::top::24","title":"Быстрый старт (Quickstart)","section":"Узнать больше","path":"/docs/guide/introduction/quickstart","headings":["Узнать больше"],"excerpt":"Узнать больше **CLI Reference** — подробности по командам **API Service** — удалённая генерация **Configuration** — все опции конфигурации","content":"Узнать больше **CLI Reference** — подробности по командам **API Service** — удалённая генерация **Configuration** — все опции конфигурации"},{"id":"introduction/quickstart::top::25","title":"Быстрый старт (Quickstart)","section":"Узнать больше","path":"/docs/guide/introduction/quickstart","headings":["Узнать больше"],"excerpt":"Узнать больше *Приятной работы с Protobuf — без боли! 🚀*","content":"Узнать больше *Приятной работы с Protobuf — без боли! 🚀*"},{"id":"introduction/what-is::top::0","title":"Что такое EasyP?","path":"/docs/guide/introduction/what-is","headings":[],"excerpt":"EasyP — это современный инструментарий для работы с Protocol Buffers, который объединяет весь ваш protobuf‑workflow в один мощный CLI‑инструмент. Он совмещает линтинг, управление пакетами, генерацию кода и проверку совме","content":"EasyP — это современный инструментарий для работы с Protocol Buffers, который объединяет весь ваш protobuf‑workflow в один мощный CLI‑инструмент. Он совмещает линтинг, управление пакетами, генерацию кода и проверку совместимости в единой среде и устраняет сложность традиционной работы с protobuf."},{"id":"introduction/what-is::top::1","title":"Что такое EasyP?","path":"/docs/guide/introduction/what-is","headings":[],"excerpt":"Хотите просто попробовать? Перейдите сразу к разделу Quickstart.","content":"Хотите просто попробовать? Перейдите сразу к разделу Quickstart."},{"id":"introduction/what-is::protobuf::2","title":"Что такое EasyP?","section":"Проблема: фрагментированные protobuf‑процессы","path":"/docs/guide/introduction/what-is#protobuf","headings":["Проблема: фрагментированные protobuf‑процессы"],"excerpt":"Проблема: фрагментированные protobuf‑процессы Работа с Protocol Buffers в разных проектах часто создает лишнюю сложность и трение:","content":"Проблема: фрагментированные protobuf‑процессы Работа с Protocol Buffers в разных проектах часто создает лишнюю сложность и трение:"},{"id":"introduction/what-is::top::3","title":"Что такое EasyP?","section":"Хаос инструментов","path":"/docs/guide/introduction/what-is","headings":["Хаос инструментов"],"excerpt":"Хаос инструментов **Много отдельных утилит**: Отдельно для линтинга, генерации и управления зависимостями **Несогласованные конфигурации**: Разные форматы и правила в разных командах **Сложный онбординг**: Новым разработ","content":"Хаос инструментов **Много отдельных утилит**: Отдельно для линтинга, генерации и управления зависимостями **Несогласованные конфигурации**: Разные форматы и правила в разных командах **Сложный онбординг**: Новым разработчикам нужно долго вникать"},{"id":"introduction/what-is::top::4","title":"Что такое EasyP?","section":"Проблемы управления зависимостями","path":"/docs/guide/introduction/what-is","headings":["Проблемы управления зависимостями"],"excerpt":"Проблемы управления зависимостями **Нет стандартизированного подхода**: Каждый проект решает это по‑своему **Конфликты версий**: Трудно сводить разные версии одних и тех же proto‑библиотек **Неповторяемость сборок**: Сло","content":"Проблемы управления зависимостями **Нет стандартизированного подхода**: Каждый проект решает это по‑своему **Конфликты версий**: Трудно сводить разные версии одних и тех же proto‑библиотек **Неповторяемость сборок**: Сложно гарантировать одинаковый результат в разных окружениях"},{"id":"introduction/what-is::top::5","title":"Что такое EasyP?","section":"Трение в разработке","path":"/docs/guide/introduction/what-is","headings":["Трение в разработке"],"excerpt":"Трение в разработке **Ручные операции**: Много повторяющихся шагов **Разрастание конфигураций**: Множество файлов и форматов **Затратная проверка совместимости**: Часто вручную и постфактум","content":"Трение в разработке **Ручные операции**: Много повторяющихся шагов **Разрастание конфигураций**: Множество файлов и форматов **Затратная проверка совместимости**: Часто вручную и постфактум"},{"id":"introduction/what-is::protobuf::6","title":"Что такое EasyP?","section":"Решение: единый protobuf‑инструментарий","path":"/docs/guide/introduction/what-is#protobuf","headings":["Решение: единый protobuf‑инструментарий"],"excerpt":"Решение: единый protobuf‑инструментарий EasyP устраняет эти проблемы, предоставляя целостный opinionated‑подход и стандартизируя процессы:","content":"Решение: единый protobuf‑инструментарий EasyP устраняет эти проблемы, предоставляя целостный opinionated‑подход и стандартизируя процессы:"},{"id":"introduction/what-is::top::7","title":"Что такое EasyP?","section":"Один инструмент — все задачи","path":"/docs/guide/introduction/what-is","headings":["Один инструмент — все задачи"],"excerpt":"Один инструмент — все задачи Вместо жонглирования утилитами EasyP даёт: **Linting** с расширенными наборами правил **Package management** с Git‑нативными зависимостями **Code generation** локально и удалённо **Breaking c","content":"Один инструмент — все задачи Вместо жонглирования утилитами EasyP даёт: **Linting** с расширенными наборами правил **Package management** с Git‑нативными зависимостями **Code generation** локально и удалённо **Breaking change detection** для контроля совместимости API"},{"id":"introduction/what-is::top::8","title":"Что такое EasyP?","section":"Единая конфигурация","path":"/docs/guide/introduction/what-is","headings":["Единая конфигурация"],"excerpt":"Единая конфигурация Один файл easyp.yaml описывает весь workflow — меньше расхождений, проще сопровождать.","content":"Единая конфигурация Один файл easyp.yaml описывает весь workflow — меньше расхождений, проще сопровождать."},{"id":"introduction/what-is::gitnative::9","title":"Что такое EasyP?","section":"Git‑native зависимости","path":"/docs/guide/introduction/what-is#gitnative","headings":["Git‑native зависимости"],"excerpt":"Git‑native зависимости Прямое использование Git‑репозиториев вместо централизованных реестров: прозрачная история, контроль версий, воспроизводимые сборки.","content":"Git‑native зависимости Прямое использование Git‑репозиториев вместо централизованных реестров: прозрачная история, контроль версий, воспроизводимые сборки."},{"id":"introduction/what-is::top::10","title":"Что такое EasyP?","section":"Ключевые возможности","path":"/docs/guide/introduction/what-is","headings":["Ключевые возможности"],"excerpt":"Ключевые возможности Feature Description --------- ------------- 🔍 **Comprehensive Linting** Полная поддержка правил buf с настраиваемыми профилями для лучших практик API‑дизайна. 📦 **Smart Package Manager** Git‑ориент","content":"Ключевые возможности Feature Description --------- ------------- 🔍 **Comprehensive Linting** Полная поддержка правил buf с настраиваемыми профилями для лучших практик API‑дизайна. 📦 **Smart Package Manager** Git‑ориентированное управление зависимостями с lock‑файлом для воспроизводимости. ⚡ **Code Generation** Многозадачная генерация кода с поддержкой локальных и удалённых protoc‑плагинов. 🔄 **Breaking Change Detection** Автоматическая проверка совместимости API против веток Git. 🌐 **Remote Plugin Support** Выполнение плагинов через централизованный EasyP API сервис без локальных установок. 🎯 **Developer Experience** Автодополнение, понятные ошибки, единая структура и документация."},{"id":"introduction/what-is::top::11","title":"Что такое EasyP?","section":"Типы поддерживаемых плагинов","path":"/docs/guide/introduction/what-is","headings":["Типы поддерживаемых плагинов"],"excerpt":"Типы поддерживаемых плагинов EasyP гибко подходит к выполнению генерации:","content":"Типы поддерживаемых плагинов EasyP гибко подходит к выполнению генерации:"},{"id":"introduction/what-is::local-plugins::12","title":"Что такое EasyP?","section":"Local Plugins","path":"/docs/guide/introduction/what-is#local-plugins","headings":["Local Plugins"],"excerpt":"Local Plugins Стандартные установленные protoc‑плагины:","content":"Local Plugins Стандартные установленные protoc‑плагины:"},{"id":"introduction/what-is::remote-plugins::13","title":"Что такое EasyP?","section":"Remote Plugins","path":"/docs/guide/introduction/what-is#remote-plugins","headings":["Remote Plugins"],"excerpt":"Remote Plugins Плагины через EasyP API сервис для воспроизводимости:","content":"Remote Plugins Плагины через EasyP API сервис для воспроизводимости:"},{"id":"introduction/what-is::custom-plugins::14","title":"Что такое EasyP?","section":"Custom Plugins","path":"/docs/guide/introduction/what-is#custom-plugins","headings":["Custom Plugins"],"excerpt":"Custom Plugins Поддержка экосистемы пользовательских расширений.","content":"Custom Plugins Поддержка экосистемы пользовательских расширений."},{"id":"introduction/what-is::top::15","title":"Что такое EasyP?","section":"Децентрализованный менеджмент пакетов","path":"/docs/guide/introduction/what-is","headings":["Децентрализованный менеджмент пакетов"],"excerpt":"Децентрализованный менеджмент пакетов В отличие от других решений EasyP не требует централизованного реестра. Любой Git‑репозиторий может быть источником:","content":"Децентрализованный менеджмент пакетов В отличие от других решений EasyP не требует централизованного реестра. Любой Git‑репозиторий может быть источником:"},{"id":"introduction/what-is::top::16","title":"Что такое EasyP?","section":"Децентрализованный менеджмент пакетов","path":"/docs/guide/introduction/what-is","headings":["Децентрализованный менеджмент пакетов"],"excerpt":"Децентрализованный менеджмент пакетов **Гибкость**: Любой Git‑хостинг (GitHub, GitLab, self‑hosted) **Нет vendor lock‑in**: Зависимости не привязаны к одному провайдеру **Полная история**: Ветки, теги, ревью **Enterprise","content":"Децентрализованный менеджмент пакетов **Гибкость**: Любой Git‑хостинг (GitHub, GitLab, self‑hosted) **Нет vendor lock‑in**: Зависимости не привязаны к одному провайдеру **Полная история**: Ветки, теги, ревью **Enterprise‑совместимость**: Поддержка приватных репозиториев"},{"id":"introduction/what-is::buf::17","title":"Что такое EasyP?","section":"Бесшовная миграция с Buf","path":"/docs/guide/introduction/what-is#buf","headings":["Бесшовная миграция с Buf"],"excerpt":"Бесшовная миграция с Buf EasyP изначально совместим с экосистемой buf:","content":"Бесшовная миграция с Buf EasyP изначально совместим с экосистемой buf:"},{"id":"introduction/what-is::buf::18","title":"Что такое EasyP?","section":"Бесшовная миграция с Buf","path":"/docs/guide/introduction/what-is#buf","headings":["Бесшовная миграция с Buf"],"excerpt":"Бесшовная миграция с Buf **Совпадающие rule sets** **Похожая структура YAML** **Минимальные изменения для замены** **Постепенное внедрение** без ломки текущего пайплайна","content":"Бесшовная миграция с Buf **Совпадающие rule sets** **Похожая структура YAML** **Минимальные изменения для замены** **Постепенное внедрение** без ломки текущего пайплайна"},{"id":"introduction/what-is::easyp-vs-bufbuild::19","title":"Что такое EasyP?","section":"EasyP vs buf.build","path":"/docs/guide/introduction/what-is#easyp-vs-bufbuild","headings":["EasyP vs buf.build"],"excerpt":"EasyP vs buf.build Feature EasyP buf.build --------- -------- ----------- **Dependency Management** Git‑репозитории Buf Schema Registry (BSR) **Vendor Lock-in** Нет Привязка к BSR для полного функционала **Plugin Executi","content":"EasyP vs buf.build Feature EasyP buf.build --------- -------- ----------- **Dependency Management** Git‑репозитории Buf Schema Registry (BSR) **Vendor Lock-in** Нет Привязка к BSR для полного функционала **Plugin Execution** Local + Remote Local + BSR plugins **Private Dependencies** Любой Git провайдер BSR или ручное управление **Offline Development** Полная поддержка (mod vendor) Ограниченно без доступа к BSR **Enterprise Integration** Использует существующий Git Требует настройку BSR **Breaking Change Detection** Против любой Git ссылки Аналогично **Package Distribution** Любой Git Публикация через BSR **License** Apache 2.0 Apache 2.0 **Community** Growing Established"},{"id":"introduction/what-is::easyp-vs-bufbuild::20","title":"Что такое EasyP?","section":"EasyP vs buf.build","path":"/docs/guide/introduction/what-is#easyp-vs-bufbuild","headings":["EasyP vs buf.build"],"excerpt":"EasyP vs buf.build **Преимущества миграции:** Без изменения инфраструктуры Плавное принятие новых возможностей Гибрид локальных и удалённых плагинов Единая конфигурация вместо набора файлов","content":"EasyP vs buf.build **Преимущества миграции:** Без изменения инфраструктуры Плавное принятие новых возможностей Гибрид локальных и удалённых плагинов Единая конфигурация вместо набора файлов"},{"id":"introduction/what-is::protobuf::21","title":"Что такое EasyP?","section":"Наши цели для Protobuf","path":"/docs/guide/introduction/what-is#protobuf","headings":["Наши цели для Protobuf"],"excerpt":"Наши цели для Protobuf Миссия EasyP — ускорить принятие **schema‑driven API** через удобный, надёжный и прозрачный инструментарий.","content":"Наши цели для Protobuf Миссия EasyP — ускорить принятие **schema‑driven API** через удобный, надёжный и прозрачный инструментарий."},{"id":"introduction/what-is::top::22","title":"Что такое EasyP?","section":"Современная экосистема","path":"/docs/guide/introduction/what-is","headings":["Современная экосистема"],"excerpt":"Современная экосистема Повышаем DX вокруг protobuf, чтобы конкурентно выглядеть по простоте против REST/JSON, сохраняя типовую строгость и производительность.","content":"Современная экосистема Повышаем DX вокруг protobuf, чтобы конкурентно выглядеть по простоте против REST/JSON, сохраняя типовую строгость и производительность."},{"id":"introduction/what-is::developer-experience::23","title":"Что такое EasyP?","section":"Developer Experience прежде всего","path":"/docs/guide/introduction/what-is#developer-experience","headings":["Developer Experience прежде всего"],"excerpt":"Developer Experience прежде всего Интуитивный CLI, понятные ошибки, ясные сообщения, минимальная фрагментация.","content":"Developer Experience прежде всего Интуитивный CLI, понятные ошибки, ясные сообщения, минимальная фрагментация."},{"id":"introduction/what-is::enterprise::24","title":"Что такое EasyP?","section":"Готов к Enterprise","path":"/docs/guide/introduction/what-is#enterprise","headings":["Готов к Enterprise"],"excerpt":"Готов к Enterprise Воспроизводимые сборки, приватные репозитории, интеграция в CI/CD.","content":"Готов к Enterprise Воспроизводимые сборки, приватные репозитории, интеграция в CI/CD."},{"id":"introduction/what-is::top::25","title":"Что такое EasyP?","section":"Для индивидуальных разработчиков","path":"/docs/guide/introduction/what-is","headings":["Для индивидуальных разработчиков"],"excerpt":"Для индивидуальных разработчиков Быстрый старт за минуты Один инструмент — меньше когнитивной нагрузки Понятная документация","content":"Для индивидуальных разработчиков Быстрый старт за минуты Один инструмент — меньше когнитивной нагрузки Понятная документация"},{"id":"introduction/what-is::top::26","title":"Что такое EasyP?","section":"Для команд","path":"/docs/guide/introduction/what-is","headings":["Для команд"],"excerpt":"Для команд Единые стандарты Повторяемые сборки (lock‑файл) Ускоренный онбординг","content":"Для команд Единые стандарты Повторяемые сборки (lock‑файл) Ускоренный онбординг"},{"id":"introduction/what-is::top::27","title":"Что такое EasyP?","section":"Для организаций","path":"/docs/guide/introduction/what-is","headings":["Для организаций"],"excerpt":"Для организаций Нет vendor lock‑in Безопасность приватных репозиториев Лёгкая интеграция в существующие пайплайны","content":"Для организаций Нет vendor lock‑in Безопасность приватных репозиториев Лёгкая интеграция в существующие пайплайны"},{"id":"introduction/what-is::top::28","title":"Что такое EasyP?","section":"Что дальше?","path":"/docs/guide/introduction/what-is","headings":["Что дальше?"],"excerpt":"Что дальше? EasyP упрощает работу с protobuf — фокусируйтесь на API, а не на рутине. Хотите начать?","content":"Что дальше? EasyP упрощает работу с protobuf — фокусируйтесь на API, а не на рутине. Хотите начать?"},{"id":"introduction/what-is::top::29","title":"Что такое EasyP?","section":"Что дальше?","path":"/docs/guide/introduction/what-is","headings":["Что дальше?"],"excerpt":"Что дальше? Смотрите Installation Guide и Quickstart.","content":"Что дальше? Смотрите Installation Guide и Quickstart."},{"id":"introduction/what-is::stargazers-over-time::30","title":"Что такое 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 В работе","content":"Buf CLI В работе"},{"id":"migration/protoc::top::0","title":"Миграция с protoc на EasyP","path":"/docs/guide/migration/protoc","headings":[],"excerpt":"Исходная англоязычная версия файла содержала только заголовок и пометку “Work in progress”. Ниже — полноценный русскоязычный черновик раздела миграции. Уточни, если требуется сократить или изменить уровень детализации.","content":"Исходная англоязычная версия файла содержала только заголовок и пометку “Work in progress”. Ниже — полноценный русскоязычный черновик раздела миграции. Уточни, если требуется сократить или изменить уровень детализации."},{"id":"migration/protoc::1::1","title":"Миграция с protoc на EasyP","section":"1. Краткое сравнение","path":"/docs/guide/migration/protoc#1","headings":["1. Краткое сравнение"],"excerpt":"Краткое сравнение Аспект protoc EasyP -------- ---------- ------- Базовая роль Базовый компилятор .proto файлов Инструмент “всё в одном”: линтинг, проверка несовместимых изменений, менеджер пакетов, генерация Конфигураци","content":"Краткое сравнение Аспект protoc EasyP -------- ---------- ------- Базовая роль Базовый компилятор .proto файлов Инструмент “всё в одном”: линтинг, проверка несовместимых изменений, менеджер пакетов, генерация Конфигурация Чаще shell‑скрипты / Makefile / вручную передаваемые флаги Единый файл easyp.yaml (YAML или JSON) Управление зависимостями Ручной git clone, submodule, vendoring Секция deps с Git‑репозиториями Набор правил линтера Нет встроенного Встроенный линтер с правилами (можно включать/исключать) Проверка breaking changes Отсутствует из коробки Команда easyp breaking Расширенные плагины Установка и вызов через флаги --plugin Плагины через конфиг; поддержка удалённого выполнения (API Service) и стандартного локального Единообразие в CI Нужно собирать вручную Консистентные команды: lint, breaking, generate"},{"id":"migration/protoc::2::2","title":"Миграция с protoc на EasyP","section":"2. Когда имеет смысл мигрировать","path":"/docs/guide/migration/protoc#2","headings":["2. Когда имеет смысл мигрировать"],"excerpt":"Когда имеет смысл мигрировать Миграция на EasyP особенно полезна если: Есть потребность в автоматической проверке качества (стиль, именование) .proto файлов. Нужна защита от нелегитимных несовместимых изменений при эволю","content":"Когда имеет смысл мигрировать Миграция на EasyP особенно полезна если: Есть потребность в автоматической проверке качества (стиль, именование) .proto файлов. Нужна защита от нелегитимных несовместимых изменений при эволюции схем. В проекте используется несколько языков генерации и растёт число скриптов вокруг protoc. Вы хотите единый конфиг вместо множества shell/Makefile комбинаций. Планируется централизованное исполнение плагинов (через API Service) или унификация окружения в CI."},{"id":"migration/protoc::3-protoc::3","title":"Миграция с protoc на EasyP","section":"3. Типичный сценарий “до” (только protoc)","path":"/docs/guide/migration/protoc#3-protoc","headings":["3. Типичный сценарий “до” (только protoc)"],"excerpt":"Типичный сценарий “до” (только protoc) Пример: локальные скрипты / Makefile:","content":"Типичный сценарий “до” (только protoc) Пример: локальные скрипты / Makefile:"},{"id":"migration/protoc::3-protoc::4","title":"Миграция с protoc на EasyP","section":"3. Типичный сценарий “до” (только protoc)","path":"/docs/guide/migration/protoc#3-protoc","headings":["3. Типичный сценарий “до” (только protoc)"],"excerpt":"Типичный сценарий “до” (только protoc)","content":"Типичный сценарий “до” (только protoc)"},{"id":"migration/protoc::3-protoc::5","title":"Миграция с protoc на EasyP","section":"3. Типичный сценарий “до” (только protoc)","path":"/docs/guide/migration/protoc#3-protoc","headings":["3. Типичный сценарий “до” (только protoc)"],"excerpt":"Типичный сценарий “до” (только protoc) Дополнительные зависимости (googleapis, validate, grpc-gateway) скачиваются вручную или через submodules.","content":"Типичный сценарий “до” (только protoc) Дополнительные зависимости (googleapis, validate, grpc-gateway) скачиваются вручную или через submodules."},{"id":"migration/protoc::4-easyp::6","title":"Миграция с protoc на EasyP","section":"4. Типичный сценарий “после” (EasyP)","path":"/docs/guide/migration/protoc#4-easyp","headings":["4. Типичный сценарий “после” (EasyP)"],"excerpt":"Типичный сценарий “после” (EasyP) Единый файл easyp.yaml:","content":"Типичный сценарий “после” (EasyP) Единый файл easyp.yaml:"},{"id":"migration/protoc::4-easyp::7","title":"Миграция с protoc на EasyP","section":"4. Типичный сценарий “после” (EasyP)","path":"/docs/guide/migration/protoc#4-easyp","headings":["4. Типичный сценарий “после” (EasyP)"],"excerpt":"Типичный сценарий “после” (EasyP) ```yaml deps: - github.com/googleapis/googleapis - github.com/envoyproxy/protoc-gen-validate","content":"Типичный сценарий “после” (EasyP) ```yaml deps: - github.com/googleapis/googleapis - github.com/envoyproxy/protoc-gen-validate"},{"id":"migration/protoc::4-easyp::8","title":"Миграция с protoc на EasyP","section":"4. Типичный сценарий “после” (EasyP)","path":"/docs/guide/migration/protoc#4-easyp","headings":["4. Типичный сценарий “после” (EasyP)"],"excerpt":"Типичный сценарий “после” (EasyP) generate: plugins: - name: go out: gen/go opts: paths: source_relative - name: go-grpc out: gen/go opts: paths: source_relative require_unimplemented_servers: false - name: validate out:","content":"Типичный сценарий “после” (EasyP) generate: plugins: - name: go out: gen/go opts: paths: source_relative - name: go-grpc out: gen/go opts: paths: source_relative require_unimplemented_servers: false - name: validate out: gen/go opts: paths: source_relative lang: \"go\" ```"},{"id":"migration/protoc::4-easyp::9","title":"Миграция с protoc на EasyP","section":"4. Типичный сценарий “после” (EasyP)","path":"/docs/guide/migration/protoc#4-easyp","headings":["4. Типичный сценарий “после” (EasyP)"],"excerpt":"Типичный сценарий “после” (EasyP) Команды:","content":"Типичный сценарий “после” (EasyP) Команды:"},{"id":"migration/protoc::5::10","title":"Миграция с protoc на EasyP","section":"5. Пошаговая миграция","path":"/docs/guide/migration/protoc#5","headings":["5. Пошаговая миграция"],"excerpt":"Пошаговая миграция Инвентаризация: - Соберите список всех вызовов protoc (скрипты, Makefile, CI). - Зафиксируйте используемые плагины и их версии. Создание easyp.yaml: - Поле version не обязательно (можете оставить его т","content":"Пошаговая миграция Инвентаризация: - Соберите список всех вызовов protoc (скрипты, Makefile, CI). - Зафиксируйте используемые плагины и их версии. Создание easyp.yaml: - Поле version не обязательно (можете оставить его только для обратной совместимости). - Перенесите плагины в секцию generate.plugins. - Укажите опции, которые ранее передавались в командной строке. Зависимости: - Все внешние каталоги (googleapis, validate, grpc-gateway и т.п.) занесите в deps. - Удалите лишние submodules при необходимости. Линтер: - Запустите easyp lint и посмотрите на предупреждения. - При необходимости добавьте lint.use, lint.ignore, lint.except. Проверка breaking changes: - Выберите референс (обычно origin/main или предыдущий тег). - Запустите easyp breaking --against git-ref=origin/main. - Настройте игнорируемые изменения (breaking.ignore), если нужно. Обновление CI: - Замените прямые вызовы protoc на easyp generate. - Добавьте отдельные шаги lint и breaking. Очистка: - Удалите устаревшие генерационные скрипты, если они дублируют функционал EasyP. Документация: - Обновите README / CONTRIBUTING (новый способ генерации). Верификация: - Сравните результат генерации до и после (git diff). - Убедитесь, что имена файлов и пути совпадают или скорректируйте структуру."},{"id":"migration/protoc::6-ci-github-actions::11","title":"Миграция с protoc на EasyP","section":"6. Замена в CI (пример GitHub Actions)","path":"/docs/guide/migration/protoc#6-ci-github-actions","headings":["6. Замена в CI (пример GitHub Actions)"],"excerpt":"Замена в CI (пример GitHub Actions) ```yaml name: Install EasyP run: go install github.com/easyp-tech/easyp/cmd/easyp@latest","content":"Замена в CI (пример GitHub Actions) ```yaml name: Install EasyP run: go install github.com/easyp-tech/easyp/cmd/easyp@latest"},{"id":"migration/protoc::6-ci-github-actions::12","title":"Миграция с protoc на EasyP","section":"6. Замена в CI (пример GitHub Actions)","path":"/docs/guide/migration/protoc#6-ci-github-actions","headings":["6. Замена в CI (пример GitHub Actions)"],"excerpt":"Замена в CI (пример GitHub Actions) name: Lint run: easyp lint","content":"Замена в CI (пример GitHub Actions) name: Lint run: easyp lint"},{"id":"migration/protoc::6-ci-github-actions::13","title":"Миграция с protoc на EasyP","section":"6. Замена в CI (пример GitHub Actions)","path":"/docs/guide/migration/protoc#6-ci-github-actions","headings":["6. Замена в CI (пример GitHub Actions)"],"excerpt":"Замена в CI (пример GitHub Actions) name: Breaking run: easyp breaking --against git-ref=origin/main","content":"Замена в CI (пример GitHub Actions) name: Breaking run: easyp breaking --against git-ref=origin/main"},{"id":"migration/protoc::6-ci-github-actions::14","title":"Миграция с protoc на EasyP","section":"6. Замена в CI (пример GitHub Actions)","path":"/docs/guide/migration/protoc#6-ci-github-actions","headings":["6. Замена в CI (пример GitHub Actions)"],"excerpt":"Замена в CI (пример GitHub Actions) name: Generate run: easyp generate ```","content":"Замена в CI (пример GitHub Actions) name: Generate run: easyp generate ```"},{"id":"migration/protoc::7::15","title":"Миграция с protoc на EasyP","section":"7. Работа с плагинами","path":"/docs/guide/migration/protoc#7","headings":["7. Работа с плагинами"],"excerpt":"Работа с плагинами Тип В protoc В EasyP ----- ---------- --------- Стандартные (protoc-gen-go) Указание через --go_out plugins: - name: go ... gRPC --go-grpc_out Второй плагин go-grpc Validate Доп. установка + --validate","content":"Работа с плагинами Тип В protoc В EasyP ----- ---------- --------- Стандартные (protoc-gen-go) Указание через --go_out plugins: - name: go ... gRPC --go-grpc_out Второй плагин go-grpc Validate Доп. установка + --validate_out - name: validate с opts gRPC-Gateway / OpenAPI --grpc-gateway_out / --openapiv2_out Плагины grpc-gateway, openapiv2 Кастомные Путь к бинарю / --plugin=protoc-gen-xxx - name: xxx или удалённый remote: (если используется API Service)"},{"id":"migration/protoc::7::16","title":"Миграция с protoc на EasyP","section":"7. Работа с плагинами","path":"/docs/guide/migration/protoc#7","headings":["7. Работа с плагинами"],"excerpt":"Работа с плагинами Если вы переходите на удалённое выполнение (API Service), записи в конфиге могут выглядеть так:","content":"Работа с плагинами Если вы переходите на удалённое выполнение (API Service), записи в конфиге могут выглядеть так:"},{"id":"migration/protoc::8::17","title":"Миграция с protoc на EasyP","section":"8. Проверка корректности после миграции","path":"/docs/guide/migration/protoc#8","headings":["8. Проверка корректности после миграции"],"excerpt":"Проверка корректности после миграции git diff после easyp generate — не должно быть неожиданных изменений. Сравнить размер и содержимое каталога сгенерированных файлов. Запустить ваш потребляющий код (сборка, тесты). Про","content":"Проверка корректности после миграции git diff после easyp generate — не должно быть неожиданных изменений. Сравнить размер и содержимое каталога сгенерированных файлов. Запустить ваш потребляющий код (сборка, тесты). Проверить, что плагины (validate, grpc-gateway) продолжают вставлять необходимые аннотации / опции. Линт не должен выдавать критичных ошибок — скорректируйте стиль .proto, если требуется."},{"id":"migration/protoc::9::18","title":"Миграция с protoc на EasyP","section":"9. Частые проблемы","path":"/docs/guide/migration/protoc#9","headings":["9. Частые проблемы"],"excerpt":"Частые проблемы Проблема Причина Решение ---------- --------- --------- Плагин не найден Не установлен или не указан в PATH Выполнить go install ... или добавить в конфиг как remote Ошибка импорта .proto Отсутствует репо","content":"Частые проблемы Проблема Причина Решение ---------- --------- --------- Плагин не найден Не установлен или не указан в PATH Выполнить go install ... или добавить в конфиг как remote Ошибка импорта .proto Отсутствует репозиторий в deps Добавить адрес в секцию deps и easyp mod update Несовместимые изменения на каждом PR Отсутствует игнор/настройка сравнения Уточнить ветку/тег в --against или настроить breaking.ignore Локально работает, в CI падает В CI нет зависимостей (не вызван update) Добавить шаг easyp mod update перед generate Дубликаты сгенерированных файлов Изменена структура путей или out Синхронизировать out и paths: source_relative опции"},{"id":"migration/protoc::10-go::19","title":"Миграция с protoc на EasyP","section":"10. Минимальный пример конфигурации (только Go)","path":"/docs/guide/migration/protoc#10-go","headings":["10. Минимальный пример конфигурации (только Go)"],"excerpt":"Минимальный пример конфигурации (только Go)","content":"Минимальный пример конфигурации (только Go)"},{"id":"migration/protoc::10-go::20","title":"Миграция с protoc на EasyP","section":"10. Минимальный пример конфигурации (только Go)","path":"/docs/guide/migration/protoc#10-go","headings":["10. Минимальный пример конфигурации (только Go)"],"excerpt":"Минимальный пример конфигурации (только Go) Команды:","content":"Минимальный пример конфигурации (только Go) Команды:"},{"id":"migration/protoc::11-go-grpc-gateway-validate-breaking-lint::21","title":"Миграция с protoc на EasyP","section":"11. Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint)","path":"/docs/guide/migration/protoc#11-go-grpc-gateway-validate-breaking-lint","headings":["11. Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint)"],"excerpt":"Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint) ```yaml lint: use: - ENUM_FIRST_VALUE_ZERO - SERVICE_SUFFIX allow_comment_ignores: false enum_zero_value_suffix: _NONE service_suffix: Service","content":"Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint) ```yaml lint: use: - ENUM_FIRST_VALUE_ZERO - SERVICE_SUFFIX allow_comment_ignores: false enum_zero_value_suffix: _NONE service_suffix: Service"},{"id":"migration/protoc::11-go-grpc-gateway-validate-breaking-lint::22","title":"Миграция с protoc на EasyP","section":"11. Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint)","path":"/docs/guide/migration/protoc#11-go-grpc-gateway-validate-breaking-lint","headings":["11. Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint)"],"excerpt":"Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint) deps: - github.com/googleapis/googleapis - github.com/envoyproxy/protoc-gen-validate","content":"Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint) deps: - github.com/googleapis/googleapis - github.com/envoyproxy/protoc-gen-validate"},{"id":"migration/protoc::11-go-grpc-gateway-validate-breaking-lint::23","title":"Миграция с protoc на EasyP","section":"11. Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint)","path":"/docs/guide/migration/protoc#11-go-grpc-gateway-validate-breaking-lint","headings":["11. Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint)"],"excerpt":"Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint) generate: plugins: - name: go out: gen/go opts: paths: source_relative - name: go-grpc out: gen/go opts: paths: source_relative require_unimplemented_","content":"Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint) generate: plugins: - name: go out: gen/go opts: paths: source_relative - name: go-grpc out: gen/go opts: paths: source_relative require_unimplemented_servers: false - name: validate out: gen/go opts: paths: source_relative lang: \"go\" - name: grpc-gateway out: gen/go opts: paths: source_relative - name: openapiv2 out: gen/openapi opts: simple_operation_ids: true"},{"id":"migration/protoc::11-go-grpc-gateway-validate-breaking-lint::24","title":"Миграция с protoc на EasyP","section":"11. Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint)","path":"/docs/guide/migration/protoc#11-go-grpc-gateway-validate-breaking-lint","headings":["11. Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint)"],"excerpt":"Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint) breaking: against_git_ref: main ignore: - ENUM_VALUE_SAME_NAME ```","content":"Расширенный пример (Go + gRPC + Gateway + Validate + Breaking и Lint) breaking: against_git_ref: main ignore: - ENUM_VALUE_SAME_NAME ```"},{"id":"migration/protoc::12-checklist::25","title":"Миграция с protoc на EasyP","section":"12. Checklist миграции","path":"/docs/guide/migration/protoc#12-checklist","headings":["12. Checklist миграции"],"excerpt":"Checklist миграции [ ] Собраны все текущие вызовы protoc. [ ] Создан easyp.yaml с секциями generate и (опционально) lint, breaking. [ ] Добавлены все внешние зависимости в deps. [ ] Успешно выполнен easyp mod update. [ ]","content":"Checklist миграции [ ] Собраны все текущие вызовы protoc. [ ] Создан easyp.yaml с секциями generate и (опционально) lint, breaking. [ ] Добавлены все внешние зависимости в deps. [ ] Успешно выполнен easyp mod update. [ ] easyp generate даёт идентичный или ожидаемо обновлённый результат. [ ] easyp lint проходит без критичных ошибок (или ошибки обработаны). [ ] easyp breaking --against git-ref=origin/main не выдаёт неожиданных блокирующих нарушений. [ ] CI обновлён (заменены прямые вызовы protoc). [ ] Документация проекта обновлена (README: как генерировать)."},{"id":"migration/protoc::13::26","title":"Миграция с protoc на EasyP","section":"13. Дополнительные рекомендации","path":"/docs/guide/migration/protoc#13","headings":["13. Дополнительные рекомендации"],"excerpt":"Дополнительные рекомендации Сначала мигрируйте один сервис / пакет — снизит риск массовых конфликтов. Закоммитьте easyp.yaml отдельно, затем выполните генерацию и линт — проще ревью. Если нужны разные наборы плагинов для","content":"Дополнительные рекомендации Сначала мигрируйте один сервис / пакет — снизит риск массовых конфликтов. Закоммитьте easyp.yaml отдельно, затем выполните генерацию и линт — проще ревью. Если нужны разные наборы плагинов для разных микросервисов — используйте несколько конфигов (например: easyp.microservice-a.yaml + easyp.microservice-b.yaml). Внедрите проверку актуальности генерации: шаг CI, который валидирует отсутствие diff после easyp generate."},{"id":"migration/protoc::14::27","title":"Миграция с protoc на EasyP","section":"14. Статус","path":"/docs/guide/migration/protoc#14","headings":["14. Статус"],"excerpt":"Статус Этот файл — русская расширенная версия, заменяющая placeholder “Work in progress”. При появлении новых возможностей EasyP (дополнительные поля в конфиге, новые плагины, расширения breaking‑проверок) обновите соотв","content":"Статус Этот файл — русская расширенная версия, заменяющая placeholder “Work in progress”. При появлении новых возможностей EasyP (дополнительные поля в конфиге, новые плагины, расширения breaking‑проверок) обновите соответствующие разделы."},{"id":"migration/protoc::14::28","title":"Миграция с protoc на EasyP","section":"14. Статус","path":"/docs/guide/migration/protoc#14","headings":["14. Статус"],"excerpt":"Статус Если нужен упрощённый вариант (только перевод без расширения), сообщи — могу сократить до минимальных двух блоков.","content":"Статус Если нужен упрощённый вариант (только перевод без расширения), сообщи — могу сократить до минимальных двух блоков."},{"id":"migration/protolock::top::0","title":"Protolock","path":"/docs/guide/migration/protolock","headings":[],"excerpt":"Protolock В процессе разработки","content":"Protolock В процессе разработки"},{"id":"migration/prototool::top::0","title":"Prototool","section":"Состояние","path":"/docs/guide/migration/prototool","headings":["Состояние"],"excerpt":"Состояние Этот раздел был помечен как “Work in progress” в оригинальной английской версии. Ниже — переведённое и дополненное практическое руководство по миграции с Prototool на EasyP. Имя инструмента Prototool не перевод","content":"Состояние Этот раздел был помечен как “Work in progress” в оригинальной английской версии. Ниже — переведённое и дополненное практическое руководство по миграции с Prototool на EasyP. Имя инструмента Prototool не переводится."},{"id":"migration/prototool::top::1","title":"Prototool","section":"Цель миграции","path":"/docs/guide/migration/prototool","headings":["Цель миграции"],"excerpt":"Цель миграции Перейти от конфигурации и рабочих процессов Prototool к эквиваленту на EasyP с минимальными изменениями, сохранив: Линтинг .proto файлов. Генерацию кода через protoc-плагины. Управление зависимостями. Прове","content":"Цель миграции Перейти от конфигурации и рабочих процессов Prototool к эквиваленту на EasyP с минимальными изменениями, сохранив: Линтинг .proto файлов. Генерацию кода через protoc-плагины. Управление зависимостями. Проверку несовместимых изменений (в Prototool это приходилось реализовывать внешними инструментами; в EasyP встроено)."},{"id":"migration/prototool::top::2","title":"Prototool","section":"Кратко о различиях","path":"/docs/guide/migration/prototool","headings":["Кратко о различиях"],"excerpt":"Кратко о различиях Область Prototool EasyP Комментарий --------- ----------- ------- ------------- Конфигурация prototool.yaml easyp.yaml Форматы YAML/JSON поддерживаются; структура отличается. Линтинг Встроенные наборы ","content":"Кратко о различиях Область Prototool EasyP Комментарий --------- ----------- ------- ------------- Конфигурация prototool.yaml easyp.yaml Форматы YAML/JSON поддерживаются; структура отличается. Линтинг Встроенные наборы + кастомные правила Наборы через lint.use, тонкая настройка ignore/except EasyP даёт больше гибкости группировки. Генерация Раздел generate + плагины через Docker/локально generate.plugins (локальные/WASM/удалённые) EasyP может выполнять плагины удалённо (API Service). Зависимости Обычно через include-пути / внешние git clone вручную Секция deps (Git репозитории) + mod update Более декларативно. Breaking Changes Нет встроенного механизма Секция breaking + команда easyp breaking Из коробки. Lock-in Зависимость от модели Prototool Минималистичный формат, «любой Git — пакет» Облегчает выход / интеграцию с другими экосистемами."},{"id":"migration/prototool::prototool::3","title":"Prototool","section":"Типовая структура Prototool (упрощённо)","path":"/docs/guide/migration/prototool#prototool","headings":["Типовая структура Prototool (упрощённо)"],"excerpt":"Типовая структура Prototool (упрощённо)","content":"Типовая структура Prototool (упрощённо)"},{"id":"migration/prototool::prototool::4","title":"Prototool","section":"Типовая структура Prototool (упрощённо)","path":"/docs/guide/migration/prototool#prototool","headings":["Типовая структура Prototool (упрощённо)"],"excerpt":"Типовая структура Prototool (упрощённо) Особенности: include_paths задаёт пути поиска импортов. lint.group + rules.add/remove регулируют активные проверки. generate.plugins описывает плагины для protoc.","content":"Типовая структура Prototool (упрощённо) Особенности: include_paths задаёт пути поиска импортов. lint.group + rules.add/remove регулируют активные проверки. generate.plugins описывает плагины для protoc."},{"id":"migration/prototool::prototool::5","title":"Prototool","section":"Типовая структура Prototool (упрощённо)","path":"/docs/guide/migration/prototool#prototool","headings":["Типовая структура Prototool (упрощённо)"],"excerpt":"Типовая структура Prototool (упрощённо) ---","content":"Типовая структура Prototool (упрощённо) ---"},{"id":"migration/prototool::easyp::6","title":"Prototool","section":"Эквивалент на EasyP","path":"/docs/guide/migration/prototool#easyp","headings":["Эквивалент на EasyP"],"excerpt":"Эквивалент на EasyP ```yaml easyp.yaml (пример) deps: - github.com/org/common-protos # вместо manual include - github.com/org/third-party-protos","content":"Эквивалент на EasyP ```yaml easyp.yaml (пример) deps: - github.com/org/common-protos # вместо manual include - github.com/org/third-party-protos"},{"id":"migration/prototool::easyp::7","title":"Prototool","section":"Эквивалент на EasyP","path":"/docs/guide/migration/prototool#easyp","headings":["Эквивалент на EasyP"],"excerpt":"Эквивалент на EasyP lint: use: - MINIMAL - BASIC enum_zero_value_suffix: \"_NONE\" service_suffix: \"Service\" ignore: - COMMENT_FIELD except: - ENUM_VALUE_PREFIX allow_comment_ignores: true","content":"Эквивалент на EasyP lint: use: - MINIMAL - BASIC enum_zero_value_suffix: \"_NONE\" service_suffix: \"Service\" ignore: - COMMENT_FIELD except: - ENUM_VALUE_PREFIX allow_comment_ignores: true"},{"id":"migration/prototool::easyp::8","title":"Prototool","section":"Эквивалент на EasyP","path":"/docs/guide/migration/prototool#easyp","headings":["Эквивалент на EasyP"],"excerpt":"Эквивалент на EasyP generate: plugins: - name: go out: gen/go opts: paths: source_relative - name: go-grpc out: gen/go opts: paths: source_relative require_unimplemented_servers: false","content":"Эквивалент на EasyP generate: plugins: - name: go out: gen/go opts: paths: source_relative - name: go-grpc out: gen/go opts: paths: source_relative require_unimplemented_servers: false"},{"id":"migration/prototool::easyp::9","title":"Prototool","section":"Эквивалент на EasyP","path":"/docs/guide/migration/prototool#easyp","headings":["Эквивалент на EasyP"],"excerpt":"Эквивалент на EasyP breaking: against_git_ref: main ignore: - FIELD_SAME_TYPE ```","content":"Эквивалент на EasyP breaking: against_git_ref: main ignore: - FIELD_SAME_TYPE ```"},{"id":"migration/prototool::easyp::10","title":"Prototool","section":"Эквивалент на EasyP","path":"/docs/guide/migration/prototool#easyp","headings":["Эквивалент на EasyP"],"excerpt":"Эквивалент на EasyP Комментарии: deps заменяет необходимость вручную прописывать include paths: EasyP подтянет их через git. lint.use активирует наборы правил (MINIMAL/BASIC/DEFAULT и т.д.). Дополнительные настройки (enu","content":"Эквивалент на EasyP Комментарии: deps заменяет необходимость вручную прописывать include paths: EasyP подтянет их через git. lint.use активирует наборы правил (MINIMAL/BASIC/DEFAULT и т.д.). Дополнительные настройки (enum_zero_value_suffix, service_suffix) задают политики нейминга. breaking позволяет сразу контролировать несовместимые изменения."},{"id":"migration/prototool::top::11","title":"Prototool","section":"Шаги миграции","path":"/docs/guide/migration/prototool","headings":["Шаги миграции"],"excerpt":"Шаги миграции Инвентаризация: - Соберите текущий prototool.yaml, списки include paths и плагины. - Зафиксируйте используемые кастомные правила, если есть.","content":"Шаги миграции Инвентаризация: - Соберите текущий prototool.yaml, списки include paths и плагины. - Зафиксируйте используемые кастомные правила, если есть."},{"id":"migration/prototool::top::12","title":"Prototool","section":"Шаги миграции","path":"/docs/guide/migration/prototool","headings":["Шаги миграции"],"excerpt":"Шаги миграции Зависимости: - Любые каталоги, которые вы вручную добавляли в include_paths, преобразуйте в git-репозитории (если ещё нет). - Добавьте их в deps (формат: github.com/owner/repo или путь к вашей приватной сис","content":"Шаги миграции Зависимости: - Любые каталоги, которые вы вручную добавляли в include_paths, преобразуйте в git-репозитории (если ещё нет). - Добавьте их в deps (формат: github.com/owner/repo или путь к вашей приватной системе Git)."},{"id":"migration/prototool::top::13","title":"Prototool","section":"Шаги миграции","path":"/docs/guide/migration/prototool","headings":["Шаги миграции"],"excerpt":"Шаги миграции Линтинг: - Определите какой group использовался (basic, default, …) → сопоставьте с наборами EasyP (MINIMAL, BASIC, DEFAULT). - Индивидуальные добавления (rules.add) перенесите в lint.use или except/ignore:","content":"Шаги миграции Линтинг: - Определите какой group использовался (basic, default, …) → сопоставьте с наборами EasyP (MINIMAL, BASIC, DEFAULT). - Индивидуальные добавления (rules.add) перенесите в lint.use или except/ignore: - Если правило нужно активировать — включите через набор или явно. - Если нужно отключить — добавьте в ignore."},{"id":"migration/prototool::top::14","title":"Prototool","section":"Шаги миграции","path":"/docs/guide/migration/prototool","headings":["Шаги миграции"],"excerpt":"Шаги миграции Генерация: - Сохраните список плагинов. В большинстве случаев имена совпадут (go, go-grpc, др.). - Если раньше использовали Docker-окружение Prototool — проверьте поддержку удалённых плагинов через API Serv","content":"Шаги миграции Генерация: - Сохраните список плагинов. В большинстве случаев имена совпадут (go, go-grpc, др.). - Если раньше использовали Docker-окружение Prototool — проверьте поддержку удалённых плагинов через API Service EasyP (опционально). - Перепишите в секцию generate.plugins."},{"id":"migration/prototool::top::15","title":"Prototool","section":"Шаги миграции","path":"/docs/guide/migration/prototool","headings":["Шаги миграции"],"excerpt":"Шаги миграции Дополнительные опции: - Настройки нейминга enum/service перенести в enum_zero_value_suffix, service_suffix. - Если были внешние скрипты для проверки breaking changes — удалите их и включите breaking с again","content":"Шаги миграции Дополнительные опции: - Настройки нейминга enum/service перенести в enum_zero_value_suffix, service_suffix. - Если были внешние скрипты для проверки breaking changes — удалите их и включите breaking с against_git_ref."},{"id":"migration/prototool::top::16","title":"Prototool","section":"Шаги миграции","path":"/docs/guide/migration/prototool","headings":["Шаги миграции"],"excerpt":"Шаги миграции Верификация: - Запустите: easyp mod update (скачивание deps). - Затем: easyp lint. - Далее: easyp generate. - И, если нужно: easyp breaking --against git-ref=origin/main.","content":"Шаги миграции Верификация: - Запустите: easyp mod update (скачивание deps). - Затем: easyp lint. - Далее: easyp generate. - И, если нужно: easyp breaking --against git-ref=origin/main."},{"id":"migration/prototool::top::17","title":"Prototool","section":"Шаги миграции","path":"/docs/guide/migration/prototool","headings":["Шаги миграции"],"excerpt":"Шаги миграции CI/CD: - Обновите workflow (GitHub Actions / GitLab) — замените вызовы Prototool на EasyP команды. - Добавьте шаг проверки несовместимых изменений.","content":"Шаги миграции CI/CD: - Обновите workflow (GitHub Actions / GitLab) — замените вызовы Prototool на EasyP команды. - Добавьте шаг проверки несовместимых изменений."},{"id":"migration/prototool::top::18","title":"Prototool","section":"Сопоставление правил (общая идея)","path":"/docs/guide/migration/prototool","headings":["Сопоставление правил (общая идея)"],"excerpt":"Сопоставление правил (общая идея) Prototool концепт EasyP ------------------- ------ lint.group lint.use (наборы) rules.add/remove except / ignore include_paths deps (git источники) plugins generate.plugins (внешние скри","content":"Сопоставление правил (общая идея) Prototool концепт EasyP ------------------- ------ lint.group lint.use (наборы) rules.add/remove except / ignore include_paths deps (git источники) plugins generate.plugins (внешние скрипты для breaking) breaking секция + команда"},{"id":"migration/prototool::top::19","title":"Prototool","section":"Сопоставление правил (общая идея)","path":"/docs/guide/migration/prototool","headings":["Сопоставление правил (общая идея)"],"excerpt":"Сопоставление правил (общая идея) ---","content":"Сопоставление правил (общая идея) ---"},{"id":"migration/prototool::top::20","title":"Prototool","section":"Приватные репозитории","path":"/docs/guide/migration/prototool","headings":["Приватные репозитории"],"excerpt":"Приватные репозитории Если ранее Prototool просто видел локальные каталоги, теперь: Добавьте SSH ключи/токены в CI для доступа к приватным Git. Укажите их в deps как обычные git-URL (формат зависит от реализации EasyP; д","content":"Приватные репозитории Если ранее Prototool просто видел локальные каталоги, теперь: Добавьте SSH ключи/токены в CI для доступа к приватным Git. Укажите их в deps как обычные git-URL (формат зависит от реализации EasyP; для публичных — стандартный)."},{"id":"migration/prototool::top::21","title":"Prototool","section":"Типовые проблемы при миграции","path":"/docs/guide/migration/prototool","headings":["Типовые проблемы при миграции"],"excerpt":"Типовые проблемы при миграции Проблема Причина Решение ---------- --------- --------- Правила линтера не совпадают Неверное сопоставление групп Проверить документацию EasyP по наборам правил Импорты не находятся Забыли д","content":"Типовые проблемы при миграции Проблема Причина Решение ---------- --------- --------- Правила линтера не совпадают Неверное сопоставление групп Проверить документацию EasyP по наборам правил Импорты не находятся Забыли добавить репозиторий в deps Добавить в deps и выполнить easyp mod update Генерация падает на опциях Плагин требует другие flags Проверить opts и документацию плагина breaking сообщает слишком много Слишком строгий базовый набор Добавить конкретные правила в breaking.ignore Долгая генерация Нет кеша/много deps Включить кэширование в CI (vendor/.easyp/deps)"},{"id":"migration/prototool::top::22","title":"Prototool","section":"Типовые проблемы при миграции","path":"/docs/guide/migration/prototool","headings":["Типовые проблемы при миграции"],"excerpt":"Типовые проблемы при миграции ---","content":"Типовые проблемы при миграции ---"},{"id":"migration/prototool::top::23","title":"Prototool","section":"Минимальная конфигурация после миграции","path":"/docs/guide/migration/prototool","headings":["Минимальная конфигурация после миграции"],"excerpt":"Минимальная конфигурация после миграции","content":"Минимальная конфигурация после миграции"},{"id":"migration/prototool::top::24","title":"Prototool","section":"Минимальная конфигурация после миграции","path":"/docs/guide/migration/prototool","headings":["Минимальная конфигурация после миграции"],"excerpt":"Минимальная конфигурация после миграции ---","content":"Минимальная конфигурация после миграции ---"},{"id":"migration/prototool::top::25","title":"Prototool","section":"Рекомендации по упрощению","path":"/docs/guide/migration/prototool","headings":["Рекомендации по упрощению"],"excerpt":"Рекомендации по упрощению Начните с минимального lint.use (MINIMAL), затем постепенно включайте дополнительные наборы. Не переносите слепо все ignore — часть правил может уже быть улучшена в EasyP. Сначала настроить deps","content":"Рекомендации по упрощению Начните с минимального lint.use (MINIMAL), затем постепенно включайте дополнительные наборы. Не переносите слепо все ignore — часть правил может уже быть улучшена в EasyP. Сначала настроить deps и генерацию, затем усложнять линт/нейминг. Фиксируйте миграцию по шагам (коммиты: deps → lint → generate → breaking → CI)."},{"id":"migration/prototool::top::26","title":"Prototool","section":"Проверка результата","path":"/docs/guide/migration/prototool","headings":["Проверка результата"],"excerpt":"Проверка результата Скрипт локальной быстрой проверки (пример):","content":"Проверка результата Скрипт локальной быстрой проверки (пример):"},{"id":"migration/prototool::top::27","title":"Prototool","section":"Проверка результата","path":"/docs/guide/migration/prototool","headings":["Проверка результата"],"excerpt":"Проверка результата ```bash #!/usr/bin/env bash set -euo pipefail","content":"Проверка результата ```bash #!/usr/bin/env bash set -euo pipefail"},{"id":"migration/prototool::top::28","title":"Prototool","section":"Проверка результата","path":"/docs/guide/migration/prototool","headings":["Проверка результата"],"excerpt":"Проверка результата echo \"[1] deps update\" easyp mod update","content":"Проверка результата echo \"[1] deps update\" easyp mod update"},{"id":"migration/prototool::top::29","title":"Prototool","section":"Проверка результата","path":"/docs/guide/migration/prototool","headings":["Проверка результата"],"excerpt":"Проверка результата echo \"[2] lint\" easyp lint","content":"Проверка результата echo \"[2] lint\" easyp lint"},{"id":"migration/prototool::top::30","title":"Prototool","section":"Проверка результата","path":"/docs/guide/migration/prototool","headings":["Проверка результата"],"excerpt":"Проверка результата echo \"[3] breaking vs main\" easyp breaking --against git-ref=origin/main echo \"Breaking changes detected (review needed)\"","content":"Проверка результата echo \"[3] breaking vs main\" easyp breaking --against git-ref=origin/main echo \"Breaking changes detected (review needed)\""},{"id":"migration/prototool::top::31","title":"Prototool","section":"Проверка результата","path":"/docs/guide/migration/prototool","headings":["Проверка результата"],"excerpt":"Проверка результата echo \"[4] generate\" easyp generate","content":"Проверка результата echo \"[4] generate\" easyp generate"},{"id":"migration/prototool::top::32","title":"Prototool","section":"Проверка результата","path":"/docs/guide/migration/prototool","headings":["Проверка результата"],"excerpt":"Проверка результата echo \"Done.\" ```","content":"Проверка результата echo \"Done.\" ```"},{"id":"migration/prototool::top::33","title":"Prototool","section":"Заключение","path":"/docs/guide/migration/prototool","headings":["Заключение"],"excerpt":"Заключение Миграция с Prototool на EasyP сводится к: Переносу путей и внешних каталогов в декларативные deps. Переформатированию линта под lint.use + ignore/except. Переносу генерации в generate.plugins. Добавлению встро","content":"Заключение Миграция с Prototool на EasyP сводится к: Переносу путей и внешних каталогов в декларативные deps. Переформатированию линта под lint.use + ignore/except. Переносу генерации в generate.plugins. Добавлению встроенного механизма breaking. Адаптации CI."},{"id":"migration/prototool::top::34","title":"Prototool","section":"Заключение","path":"/docs/guide/migration/prototool","headings":["Заключение"],"excerpt":"Заключение После этого конфигурация становится более прозрачной, а проверка несовместимых изменений — из коробки.","content":"Заключение После этого конфигурация становится более прозрачной, а проверка несовместимых изменений — из коробки."},{"id":"migration/prototool::top::35","title":"Prototool","section":"Заключение","path":"/docs/guide/migration/prototool","headings":["Заключение"],"excerpt":"Заключение *Готово: базовый перевод и расширенное руководство по миграции с Prototool на EasyP.*","content":"Заключение *Готово: базовый перевод и расширенное руководство по миграции с Prototool на EasyP.*"},{"id":"TRANSLATION_STATUS::top::0","title":"Translation Status (ru-guide)","path":"/docs/guide/TRANSLATION_STATUS","headings":[],"excerpt":"Этот файл отслеживает прогресс перевода русской документации. Используемые статусы: TODO — требуется перевод IN_PROGRESS — перевод начат, требуется вычитка DONE — перевод завершён и вычитан SKIPPED — не требует перевода ","content":"Этот файл отслеживает прогресс перевода русской документации. Используемые статусы: TODO — требуется перевод IN_PROGRESS — перевод начат, требуется вычитка DONE — перевод завершён и вычитан SKIPPED — не требует перевода (намеренно оставлено на английском)"},{"id":"TRANSLATION_STATUS::top::1","title":"Translation Status (ru-guide)","path":"/docs/guide/TRANSLATION_STATUS","headings":[],"excerpt":"Правила: После полного перевода файла убрать исходный английский текст и маркер Термины протокола и ключевые идентификаторы (названия правил, CLI команды, YAML ключи) НЕ переводим. Если структура исходного файла изменила","content":"Правила: После полного перевода файла убрать исходный английский текст и маркер Термины протокола и ключевые идентификаторы (названия правил, CLI команды, YAML ключи) НЕ переводим. Если структура исходного файла изменилась — добавить в начало: Для больших изменений: сначала IN_PROGRESS, после вычитки менять на DONE."},{"id":"TRANSLATION_STATUS::summary::2","title":"Translation Status (ru-guide)","section":"Summary","path":"/docs/guide/TRANSLATION_STATUS#summary","headings":["Summary"],"excerpt":"Summary Итого файлов: 76 DONE: 76 IN_PROGRESS: 0 TODO: 0","content":"Summary Итого файлов: 76 DONE: 76 IN_PROGRESS: 0 TODO: 0"},{"id":"TRANSLATION_STATUS::priority-order::3","title":"Translation Status (ru-guide)","section":"Priority Order (рекомендованный)","path":"/docs/guide/TRANSLATION_STATUS#priority-order","headings":["Priority Order (рекомендованный)"],"excerpt":"Priority Order (рекомендованный) introduction/what-is.md introduction/quickstart.md introduction/install.md cli/linter/linter.md cli/generator/generator.md cli/package-manager/package-manager.md cli/breaking-changes/brea","content":"Priority Order (рекомендованный) introduction/what-is.md introduction/quickstart.md introduction/install.md cli/linter/linter.md cli/generator/generator.md cli/package-manager/package-manager.md cli/breaking-changes/breaking-changes.md api-service/overview.md migration/* (пакетом)"},{"id":"TRANSLATION_STATUS::priority-order::4","title":"Translation Status (ru-guide)","section":"Priority Order (рекомендованный)","path":"/docs/guide/TRANSLATION_STATUS#priority-order","headings":["Priority Order (рекомендованный)"],"excerpt":"Priority Order (рекомендованный) ---","content":"Priority Order (рекомендованный) ---"},{"id":"TRANSLATION_STATUS::file-status-table::5","title":"Translation Status (ru-guide)","section":"File Status Table","path":"/docs/guide/TRANSLATION_STATUS#file-status-table","headings":["File Status Table"],"excerpt":"File Status Table File Status Notes ------ -------- ------- introduction/what-is.md DONE Полный перевод выполнен introduction/quickstart.md DONE Структура сохранена, перевод вычитан introduction/install.md DONE Переведен","content":"File Status Table File Status Notes ------ -------- ------- introduction/what-is.md DONE Полный перевод выполнен introduction/quickstart.md DONE Структура сохранена, перевод вычитан introduction/install.md DONE Переведено, команды проверены api-service/overview.md DONE Переведено ci-cd/github-actions.md DONE Переведено ci-cd/gitlab.md DONE Переведено cli/auto-completion/auto-completion.md DONE Переведено cli/breaking-changes/breaking-changes.md DONE Переведено и вычитано cli/breaking-changes/rules/enum-no-delete.md DONE Переведено cli/breaking-changes/rules/enum-value-no-delete.md DONE Переведено cli/breaking-changes/rules/enum-value-same-name.md DONE Переведено cli/breaking-changes/rules/field-no-delete.md DONE Переведено cli/breaking-changes/rules/field-same-cardinality.md DONE Переведено cli/breaking-changes/rules/field-same-type.md DONE Переведено cli/breaking-changes/rules/import-no-delete.md DONE Переведено cli/breaking-changes/rules/message-no-delete.md DONE Переведено cli/breaking-changes/rules/oneof-field-no-delete.md DONE Переведено cli/breaking-changes/rules/oneof-field-same-type.md DONE Переведено cli/breaking-changes/rules/oneof-no-delete.md DONE Переведено cli/breaking-changes/rules/rpc-no-delete.md DONE Переведено cli/breaking-changes/rules/rpc-same-request-type.md DONE Переведено cli/breaking-changes/rules/rpc-same-response-type.md DONE Переведено cli/breaking-changes/rules/service-no-delete.md DONE Переведено cli/configuration/configuration.md DONE Переведено cli/generator/examples/go.md DONE Переведено cli/generator/examples/grpc-gateway.md DONE Переведено cli/generator/examples/validate.md DONE Переведено cli/generator/generator.md DONE Переведено и вычитано cli/linter/linter.md DONE Переведено и вычитано cli/linter/rules/comment-enum-value.md DONE Переведено cli/linter/rules/comment-enum.md DONE Переведено cli/linter/rules/comment-field.md DONE Переведено cli/linter/rules/comment-message.md DONE Переведено cli/linter/rules/comment-oneof.md DONE Переведено cli/linter/rules/comment-rpc.md DONE Переведено cli/linter/rules/comment-service.md DONE Переведено cli/linter/rules/directory-same-package.md DONE Переведено cli/linter/rules/enum-first-value-zero.md DONE Переведено cli/linter/rules/enum-no-allow-alias.md DONE Переведено cli/linter/rules/enum-pascal-case.md DONE Переведено cli/linter/rules/enum-value-prefix.md DONE Переведено cli/linter/rules/enum-value-upper-snake-case.md DONE Переведено cli/linter/rules/enum-zero-value-suffix.md DONE Переведено cli/linter/rules/field-lower-snake-case.md DONE Переведено cli/linter/rules/file-lower-snake-case.md DONE Переведено cli/linter/rules/import-no-public.md DONE Переведено cli/linter/rules/import-no-weak.md DONE Переведено cli/linter/rules/import-used.md DONE Переведено cli/linter/rules/message-pascal-case.md DONE Переведено cli/linter/rules/oneof-lower-snake-case.md DONE Переведено cli/linter/rules/package-defined.md DONE Переведено cli/linter/rules/package-directory-match.md DONE Переведено cli/linter/rules/package-lower-snake-case.md DONE Переведено cli/linter/rules/package-same-csharp-namespace.md DONE Переведено cli/linter/rules/package-same-directory.md DONE Переведено cli/linter/rules/package-same-go-package.md DONE Переведено cli/linter/rules/package-same-java-multiple-files.md DONE Переведено cli/linter/rules/package-same-java-package.md DONE Переведено cli/linter/rules/package-same-php-namespace.md DONE Переведено cli/linter/rules/package-same-ruby-package.md DONE Переведено cli/linter/rules/package-same-swift-prefix.md DONE Переведено cli/linter/rules/package-version-suffix.md DONE Переведено cli/linter/rules/rpc-no-client-streaming.md DONE Переведено cli/linter/rules/rpc-no-server-streaming.md DONE Переведено cli/linter/rules/rpc-pascal-case.md DONE Переведено cli/linter/rules/rpc-request-response-unique.md DONE Переведено cli/linter/rules/rpc-request-standard-name.md DONE Переведено cli/linter/rules/rpc-response-standard-name.md DONE Переведено cli/linter/rules/service-pascal-case.md DONE Переведено cli/linter/rules/service-suffix.md DONE Переведено cli/package-manager/easyp-vs-buf.md DONE Переведено cli/package-manager/package-manager.md DONE Переведено и вычитано migration/buf-cli.md DONE Переведено migration/protoc.md DONE Переведено migration/protolock.md DONE Переведено migration/prototool.md DONE Переведено"},{"id":"TRANSLATION_STATUS::workflow::6","title":"Translation Status (ru-guide)","section":"Workflow","path":"/docs/guide/TRANSLATION_STATUS#workflow","headings":["Workflow"],"excerpt":"Workflow Выбираем файл со статусом TODO. Меняем статус на IN_PROGRESS здесь. Переводим, проверяем терминологию (сверка с глоссарием — добавить позже). Меняем статус на DONE. Удаляем маркер внутри файла.","content":"Workflow Выбираем файл со статусом TODO. Меняем статус на IN_PROGRESS здесь. Переводим, проверяем терминологию (сверка с глоссарием — добавить позже). Меняем статус на DONE. Удаляем маркер внутри файла."},{"id":"TRANSLATION_STATUS::planned-terminology::7","title":"Translation Status (ru-guide)","section":"Planned Terminology (черновик)","path":"/docs/guide/TRANSLATION_STATUS#planned-terminology","headings":["Planned Terminology (черновик)"],"excerpt":"Planned Terminology (черновик) EN RU Notes ---- ---- ------- Linting Линтинг Транслитерация Breaking Changes Несовместимые изменения Название секции Dependency Зависимость Code Generation Генерация кода Lock file Lock-фа","content":"Planned Terminology (черновик) EN RU Notes ---- ---- ------- Linting Линтинг Транслитерация Breaking Changes Несовместимые изменения Название секции Dependency Зависимость Code Generation Генерация кода Lock file Lock-файл Remote Plugin Удалённый плагин Package Manager Менеджер пакетов"},{"id":"TRANSLATION_STATUS::planned-terminology::8","title":"Translation Status (ru-guide)","section":"Planned Terminology (черновик)","path":"/docs/guide/TRANSLATION_STATUS#planned-terminology","headings":["Planned Terminology (черновик)"],"excerpt":"Planned Terminology (черновик) (Будет дополнено.)","content":"Planned Terminology (черновик) (Будет дополнено.)"},{"id":"TRANSLATION_STATUS::planned-terminology::9","title":"Translation Status (ru-guide)","section":"Planned Terminology (черновик)","path":"/docs/guide/TRANSLATION_STATUS#planned-terminology","headings":["Planned Terminology (черновик)"],"excerpt":"Planned Terminology (черновик) ---","content":"Planned Terminology (черновик) ---"},{"id":"TRANSLATION_STATUS::top::10","title":"Translation Status (ru-guide)","section":"История обновлений","path":"/docs/guide/TRANSLATION_STATUS","headings":["История обновлений"],"excerpt":"История обновлений Initial file created: all statuses set (3 IN_PROGRESS, rest TODO). Marked breaking-changes page as DONE. Linter rules (41 файлов) переведены: статусы DONE. Breaking-changes rules (15 файлов) вычитаны и","content":"История обновлений Initial file created: all statuses set (3 IN_PROGRESS, rest TODO). Marked breaking-changes page as DONE. Linter rules (41 файлов) переведены: статусы DONE. Breaking-changes rules (15 файлов) вычитаны и помечены DONE. Все оставшиеся страницы переведены: итог DONE = 76."}] \ No newline at end of file diff --git a/internal/api/temporaly_helper.go b/internal/api/temporaly_helper.go index bf992d53..1c20cadd 100644 --- a/internal/api/temporaly_helper.go +++ b/internal/api/temporaly_helper.go @@ -161,6 +161,7 @@ func convertManagedModeConfig(cfg config.ManagedMode) core.ManagedModeConfig { Disable: lo.Map(cfg.Disable, func(r config.ManagedDisableRule, _ int) core.ManagedDisableRule { return core.ManagedDisableRule{ Module: r.Module, + Package: r.Package, Path: r.Path, FileOption: core.FileOptionType(r.FileOption), FieldOption: core.FieldOptionType(r.FieldOption), @@ -173,6 +174,7 @@ func convertManagedModeConfig(cfg config.ManagedMode) core.ManagedModeConfig { FieldOption: core.FieldOptionType(r.FieldOption), Value: r.Value, Module: r.Module, + Package: r.Package, Path: r.Path, Field: r.Field, } diff --git a/internal/config/config.go b/internal/config/config.go index 7154d3dd..cd983510 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -92,6 +92,8 @@ func yamlNodeKind(kind yaml.Kind) string { type ManagedDisableRule struct { // Module disables managed mode for all files in the specified module. Module string `json:"module,omitempty" yaml:"module,omitempty"` + // Package disables managed mode for all files in the specified protobuf package. + Package string `json:"package,omitempty" yaml:"package,omitempty"` // Path disables managed mode for files matching the specified path (directory or file). Path string `json:"path,omitempty" yaml:"path,omitempty"` // FileOption disables a specific file option from being modified. @@ -112,6 +114,8 @@ type ManagedOverrideRule struct { Value any `json:"value,omitempty" yaml:"value,omitempty"` // Module applies this override only to files in the specified module. Module string `json:"module,omitempty" yaml:"module,omitempty"` + // Package applies this override only to files in the specified protobuf package. + Package string `json:"package,omitempty" yaml:"package,omitempty"` // Path applies this override only to files matching the specified path. Path string `json:"path,omitempty" yaml:"path,omitempty"` // Field applies this override only to the specified field (fully qualified name). @@ -314,7 +318,7 @@ func (m *ManagedMode) Validate() error { // Validate validates a disable rule. func (r *ManagedDisableRule) Validate() error { // At least one field must be set - if r.Module == "" && r.Path == "" && r.FileOption == "" && r.FieldOption == "" && r.Field == "" { + if r.Module == "" && r.Package == "" && r.Path == "" && r.FileOption == "" && r.FieldOption == "" && r.Field == "" { return errors.New("disable rule must have at least one field set") } diff --git a/internal/config/managed_mode_test.go b/internal/config/managed_mode_test.go new file mode 100644 index 00000000..87d042d5 --- /dev/null +++ b/internal/config/managed_mode_test.go @@ -0,0 +1,41 @@ +package config + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestParseConfig_ManagedModePackageSelectors(t *testing.T) { + content := `lint: + use: + - DIRECTORY_SAME_PACKAGE +generate: + inputs: + - directory: proto + plugins: + - name: go + out: . + managed: + enabled: true + disable: + - package: acme.weather.v1 + file_option: java_package_prefix + override: + - file_option: go_package_prefix + package: acme.weather.v1 + value: github.com/acme/gen/go +` + + cfg, err := ParseConfig([]byte(content)) + require.NoError(t, err) + + require.Len(t, cfg.Generate.Managed.Disable, 1) + require.Equal(t, "acme.weather.v1", cfg.Generate.Managed.Disable[0].Package) + require.Equal(t, "java_package_prefix", cfg.Generate.Managed.Disable[0].FileOption) + + require.Len(t, cfg.Generate.Managed.Override, 1) + require.Equal(t, "acme.weather.v1", cfg.Generate.Managed.Override[0].Package) + require.Equal(t, "go_package_prefix", cfg.Generate.Managed.Override[0].FileOption) + require.Equal(t, "github.com/acme/gen/go", cfg.Generate.Managed.Override[0].Value) +} diff --git a/internal/config/validate_raw.go b/internal/config/validate_raw.go index 085f995b..f18e2e63 100644 --- a/internal/config/validate_raw.go +++ b/internal/config/validate_raw.go @@ -161,12 +161,13 @@ func buildSchema() *v.FieldSchema { Type: v.TypeMap, AllowedKeys: map[string]*v.FieldSchema{ "module": {Type: v.TypeString}, + "package": {Type: v.TypeString}, "path": {Type: v.TypeString}, "file_option": {Type: v.TypeString}, "field_option": {Type: v.TypeString}, "field": {Type: v.TypeString}, }, - AnyOf: [][]string{{"module"}, {"path"}, {"file_option"}, {"field_option"}, {"field"}}, + AnyOf: [][]string{{"module"}, {"package"}, {"path"}, {"file_option"}, {"field_option"}, {"field"}}, MutuallyExclusive: []string{"file_option", "field_option"}, UnknownKeyPolicy: v.UnknownKeyWarn, Validators: []v.ValueValidator{managedDisableValidator{}}, @@ -179,6 +180,7 @@ func buildSchema() *v.FieldSchema { "field_option": {Type: v.TypeString}, "value": {Type: v.TypeAny, Required: true}, "module": {Type: v.TypeString}, + "package": {Type: v.TypeString}, "path": {Type: v.TypeString}, "field": {Type: v.TypeString}, }, diff --git a/internal/config/validate_raw_test.go b/internal/config/validate_raw_test.go index 534af0e7..d2c5ed59 100644 --- a/internal/config/validate_raw_test.go +++ b/internal/config/validate_raw_test.go @@ -179,6 +179,32 @@ breaking: require.True(t, hasWarning, "expected warning for unknown key 'unknown_field' in breaking section, got: %v", issues) } +func TestValidateRaw_ManagedModePackageSelectors(t *testing.T) { + content := `lint: + use: + - DIRECTORY_SAME_PACKAGE +generate: + inputs: + - directory: proto + plugins: + - name: go + out: . + managed: + enabled: true + disable: + - package: acme.weather.v1 + file_option: java_package_prefix + override: + - file_option: go_package_prefix + package: acme.weather.v1 + value: github.com/acme/gen/go +` + + issues, err := ValidateRaw([]byte(content)) + require.NoError(t, err) + require.False(t, HasErrors(issues), "package selector in managed mode should be valid, got: %v", issues) +} + func TestValidateRaw_DirectoryUnknownKey_NoDuplicate(t *testing.T) { content := `version: v1alpha lint: diff --git a/internal/config/yaml_validators.go b/internal/config/yaml_validators.go index 44655720..ad7f3243 100644 --- a/internal/config/yaml_validators.go +++ b/internal/config/yaml_validators.go @@ -168,11 +168,11 @@ func (pluginOptsValidator) Validate(node *yaml.Node, path string, ctx *v.Validat } default: ctx.AddError(v.ValidationError{ - Level: v.LevelError, - Path: optsPath, - Line: valNode.Line, - Column: valNode.Column, - Message: "opts value must be a scalar or sequence of scalars", + Level: v.LevelError, + Path: optsPath, + Line: valNode.Line, + Column: valNode.Column, + Message: "opts value must be a scalar or sequence of scalars", Expected: "scalar or sequence of scalars", Got: yamlKindName(valNode.Kind), }) @@ -195,13 +195,13 @@ func (managedDisableValidator) Validate(node *yaml.Node, path string, ctx *v.Val } return false } - if !(has("module") || has("path") || has("file_option") || has("field_option") || has("field")) { + if !(has("module") || has("package") || has("path") || has("file_option") || has("field_option") || has("field")) { ctx.AddError(v.ValidationError{ Level: v.LevelError, Path: path, Line: node.Line, Column: node.Column, - Message: "managed.disable entry must set at least one of module/path/file_option/field_option/field", + Message: "managed.disable entry must set at least one of module/package/path/file_option/field_option/field", }) } if has("file_option") && has("field_option") { diff --git a/internal/core/managed_mode.go b/internal/core/managed_mode.go index fbbf4eed..c89c1ddf 100644 --- a/internal/core/managed_mode.go +++ b/internal/core/managed_mode.go @@ -85,6 +85,8 @@ const ( type ManagedDisableRule struct { // Module disables managed mode for all files in the specified module. Module string + // Package disables managed mode for all files in the specified protobuf package. + Package string // Path disables managed mode for files matching the specified path (directory or file). Path string // FileOption disables a specific file option from being modified. @@ -105,6 +107,8 @@ type ManagedOverrideRule struct { Value any // Module applies this override only to files in the specified module. Module string + // Package applies this override only to files in the specified protobuf package. + Package string // Path applies this override only to files matching the specified path. Path string // Field applies this override only to the specified field (fully qualified name). @@ -126,9 +130,9 @@ type ManagedModeConfig struct { // ============================================================================ // IsFileOptionDisabled checks if a file option is disabled for the given file. -func (c *ManagedModeConfig) IsFileOptionDisabled(filePath, module string, option FileOptionType) bool { +func (c *ManagedModeConfig) IsFileOptionDisabled(filePath, module, protoPackage string, option FileOptionType) bool { for _, rule := range c.Disable { - if rule.matchesFileOption(filePath, module, option) { + if rule.matchesFileOption(filePath, module, protoPackage, option) { return true } } @@ -136,9 +140,9 @@ func (c *ManagedModeConfig) IsFileOptionDisabled(filePath, module string, option } // IsFieldOptionDisabled checks if a field option is disabled for the given field. -func (c *ManagedModeConfig) IsFieldOptionDisabled(filePath, module string, option FieldOptionType, fieldName string) bool { +func (c *ManagedModeConfig) IsFieldOptionDisabled(filePath, module, protoPackage string, option FieldOptionType, fieldName string) bool { for _, rule := range c.Disable { - if rule.matchesFieldOption(filePath, module, option, fieldName) { + if rule.matchesFieldOption(filePath, module, protoPackage, option, fieldName) { return true } } @@ -147,10 +151,10 @@ func (c *ManagedModeConfig) IsFieldOptionDisabled(filePath, module string, optio // GetFileOptionOverride returns the override value for a file option, or nil if not overridden. // If multiple overrides match, the last matching rule wins (buf behavior). -func (c *ManagedModeConfig) GetFileOptionOverride(filePath, module string, option FileOptionType) any { +func (c *ManagedModeConfig) GetFileOptionOverride(filePath, module, protoPackage string, option FileOptionType) any { var result any for _, rule := range c.Override { - if rule.FileOption == option && rule.matchesFileContext(filePath, module) { + if rule.FileOption == option && rule.matchesFileContext(filePath, module, protoPackage) { result = rule.Value } } @@ -159,10 +163,10 @@ func (c *ManagedModeConfig) GetFileOptionOverride(filePath, module string, optio // GetFieldOptionOverride returns the override value for a field option, or nil if not overridden. // If multiple overrides match, the last matching rule wins (buf behavior). -func (c *ManagedModeConfig) GetFieldOptionOverride(filePath, module string, option FieldOptionType, fieldName string) any { +func (c *ManagedModeConfig) GetFieldOptionOverride(filePath, module, protoPackage string, option FieldOptionType, fieldName string) any { var result any for _, rule := range c.Override { - if rule.FieldOption == option && rule.matchesFieldContext(filePath, module, fieldName) { + if rule.FieldOption == option && rule.matchesFieldContext(filePath, module, protoPackage, fieldName) { result = rule.Value } } @@ -174,7 +178,7 @@ func (c *ManagedModeConfig) GetFieldOptionOverride(filePath, module string, opti // ============================================================================ // matchesFileOption checks if a disable rule matches the given file option context. -func (r *ManagedDisableRule) matchesFileOption(filePath, module string, fileOption FileOptionType) bool { +func (r *ManagedDisableRule) matchesFileOption(filePath, module, protoPackage string, fileOption FileOptionType) bool { // If file option is specified, it must match if r.FileOption != "" && r.FileOption != fileOption { return false @@ -185,11 +189,11 @@ func (r *ManagedDisableRule) matchesFileOption(filePath, module string, fileOpti return false } - return r.matchesContext(filePath, module) + return r.matchesContext(filePath, module, protoPackage) } // matchesFieldOption checks if a disable rule matches the given field option context. -func (r *ManagedDisableRule) matchesFieldOption(filePath, module string, fieldOption FieldOptionType, fieldName string) bool { +func (r *ManagedDisableRule) matchesFieldOption(filePath, module, protoPackage string, fieldOption FieldOptionType, fieldName string) bool { // If field option is specified, it must match if r.FieldOption != "" && r.FieldOption != fieldOption { return false @@ -205,18 +209,22 @@ func (r *ManagedDisableRule) matchesFieldOption(filePath, module string, fieldOp return false } - return r.matchesContext(filePath, module) + return r.matchesContext(filePath, module, protoPackage) } -// matchesContext checks if module and path filters match. -// Uses exact module comparison to avoid false positives. -func (r *ManagedDisableRule) matchesContext(filePath, module string) bool { +// matchesContext checks if module, protobuf package, and path filters match. +// Uses exact comparison to avoid false positives. +func (r *ManagedDisableRule) matchesContext(filePath, module, protoPackage string) bool { // Check module match - use exact comparison to avoid false positives // e.g., "googleapis" should NOT match "github.com/mycompany/super-googleapis-tools" if r.Module != "" && r.Module != module { return false } + if r.Package != "" && r.Package != protoPackage { + return false + } + // Check path match - uses buf's path matching behavior if r.Path != "" { if !matchesPath(filePath, r.Path) { @@ -228,13 +236,17 @@ func (r *ManagedDisableRule) matchesContext(filePath, module string) bool { } // matchesFileContext checks if an override rule matches the given file context. -// Uses exact module comparison to avoid false positives. -func (r *ManagedOverrideRule) matchesFileContext(filePath, module string) bool { +// Uses exact comparison to avoid false positives. +func (r *ManagedOverrideRule) matchesFileContext(filePath, module, protoPackage string) bool { // Check module match - use exact comparison to avoid false positives if r.Module != "" && r.Module != module { return false } + if r.Package != "" && r.Package != protoPackage { + return false + } + // Check path match - uses buf's path matching behavior if r.Path != "" { if !matchesPath(filePath, r.Path) { @@ -246,13 +258,13 @@ func (r *ManagedOverrideRule) matchesFileContext(filePath, module string) bool { } // matchesFieldContext checks if an override rule matches the given field context. -func (r *ManagedOverrideRule) matchesFieldContext(filePath, module, fieldName string) bool { +func (r *ManagedOverrideRule) matchesFieldContext(filePath, module, protoPackage, fieldName string) bool { // Check field match if r.Field != "" && r.Field != fieldName { return false } - return r.matchesFileContext(filePath, module) + return r.matchesFileContext(filePath, module, protoPackage) } // ============================================================================ @@ -688,7 +700,7 @@ func ApplyManagedMode( applyFileOptions(fd, config, filePath, module, pkg) // Apply field options to all messages - applyFieldOptionsToMessages(fd.GetMessageType(), config, filePath, module, pkg) + applyFieldOptionsToMessages(fd.GetMessageType(), config, filePath, module, pkg, pkg) } return nil @@ -730,12 +742,12 @@ func applyFileOptions( } // Check if this override matches the current file context - if !override.matchesFileContext(filePath, module) { + if !override.matchesFileContext(filePath, module, pkg) { continue } // Check if this option is disabled - if config.IsFileOptionDisabled(filePath, module, override.FileOption) { + if config.IsFileOptionDisabled(filePath, module, pkg, override.FileOption) { continue } @@ -772,7 +784,7 @@ func applyFileOptions( } // Check if this option is disabled - if config.IsFileOptionDisabled(filePath, module, handler.Option) { + if config.IsFileOptionDisabled(filePath, module, pkg, handler.Option) { continue } @@ -792,7 +804,7 @@ func applyFileOptions( func applyFieldOptionsToMessages( messages []*descriptorpb.DescriptorProto, config ManagedModeConfig, - filePath, module, parentPath string, + filePath, module, protoPackage, parentPath string, ) { for _, msg := range messages { messagePath := parentPath + "." + msg.GetName() @@ -800,11 +812,11 @@ func applyFieldOptionsToMessages( // Apply options to each field for _, field := range msg.GetField() { fieldPath := messagePath + "." + field.GetName() - applyFieldOptions(field, config, filePath, module, fieldPath) + applyFieldOptions(field, config, filePath, module, protoPackage, fieldPath) } // Recursively process nested messages - applyFieldOptionsToMessages(msg.GetNestedType(), config, filePath, module, messagePath) + applyFieldOptionsToMessages(msg.GetNestedType(), config, filePath, module, protoPackage, messagePath) } } @@ -814,7 +826,7 @@ func applyFieldOptionsToMessages( func applyFieldOptions( field *descriptorpb.FieldDescriptorProto, config ManagedModeConfig, - filePath, module, fieldPath string, + filePath, module, protoPackage, fieldPath string, ) { for i := range fieldOptionHandlers { handler := &fieldOptionHandlers[i] @@ -825,12 +837,12 @@ func applyFieldOptions( } // Check if this option is disabled - if config.IsFieldOptionDisabled(filePath, module, handler.Option, fieldPath) { + if config.IsFieldOptionDisabled(filePath, module, protoPackage, handler.Option, fieldPath) { continue } // Get override value - field options only apply when explicitly overridden - override := config.GetFieldOptionOverride(filePath, module, handler.Option, fieldPath) + override := config.GetFieldOptionOverride(filePath, module, protoPackage, handler.Option, fieldPath) if override != nil { handler.Apply(field, override) continue diff --git a/internal/core/managed_mode_test.go b/internal/core/managed_mode_test.go index d6e921a3..4250bb6d 100644 --- a/internal/core/managed_mode_test.go +++ b/internal/core/managed_mode_test.go @@ -235,6 +235,46 @@ func TestApplyManagedMode_OverrideForModule(t *testing.T) { assert.Equal(t, expected2, fd2.Options.GetGoPackage()) } +func TestApplyManagedMode_OverrideForProtoPackage(t *testing.T) { + fd1 := &descriptorpb.FileDescriptorProto{ + Name: strPtr("acme/weather/v1/weather.proto"), + Package: strPtr("acme.weather.v1"), + Options: &descriptorpb.FileOptions{}, + } + + fd2 := &descriptorpb.FileDescriptorProto{ + Name: strPtr("acme/weather/v2/weather.proto"), + Package: strPtr("acme.weather.v2"), + Options: &descriptorpb.FileOptions{}, + } + + config := ManagedModeConfig{ + Enabled: true, + Override: []ManagedOverrideRule{ + { + FileOption: FileOptionGoPackagePrefix, + Value: "github.com/acme/default/gen/go", + }, + { + FileOption: FileOptionGoPackagePrefix, + Package: "acme.weather.v1", + Value: "github.com/acme/weather/v1/gen/go", + }, + }, + } + + fileToModule := map[string]string{ + "acme/weather/v1/weather.proto": "", + "acme/weather/v2/weather.proto": "", + } + + err := ApplyManagedMode([]*descriptorpb.FileDescriptorProto{fd1, fd2}, config, fileToModule) + require.NoError(t, err) + + assert.Equal(t, "github.com/acme/weather/v1/gen/go/acme/weather/v1;weatherv1", fd1.Options.GetGoPackage()) + assert.Equal(t, "github.com/acme/default/gen/go/acme/weather/v2;weatherv2", fd2.Options.GetGoPackage()) +} + func TestApplyManagedMode_LastRuleWins(t *testing.T) { fd := &descriptorpb.FileDescriptorProto{ Name: strPtr("acme/weather/v1/weather.proto"), @@ -589,6 +629,41 @@ func TestApplyManagedMode_DisableExternalModule(t *testing.T) { assert.Equal(t, "google.golang.org/genproto/googleapis/api/annotations", externalFile.Options.GetGoPackage()) } +func TestApplyManagedMode_DisableForProtoPackage(t *testing.T) { + fd1 := &descriptorpb.FileDescriptorProto{ + Name: strPtr("acme/weather/v1/weather.proto"), + Package: strPtr("acme.weather.v1"), + Options: &descriptorpb.FileOptions{}, + } + + fd2 := &descriptorpb.FileDescriptorProto{ + Name: strPtr("acme/weather/v2/weather.proto"), + Package: strPtr("acme.weather.v2"), + Options: &descriptorpb.FileOptions{}, + } + + config := ManagedModeConfig{ + Enabled: true, + Disable: []ManagedDisableRule{ + { + Package: "acme.weather.v1", + FileOption: FileOptionJavaPackagePrefix, + }, + }, + } + + fileToModule := map[string]string{ + "acme/weather/v1/weather.proto": "", + "acme/weather/v2/weather.proto": "", + } + + err := ApplyManagedMode([]*descriptorpb.FileDescriptorProto{fd1, fd2}, config, fileToModule) + require.NoError(t, err) + + assert.Nil(t, fd1.Options.JavaPackage) + assert.Equal(t, "com.acme.weather.v2", fd2.Options.GetJavaPackage()) +} + // Test cleanPackageName function func TestCleanPackageName(t *testing.T) { tests := []struct { @@ -705,7 +780,7 @@ func TestMatchesPath(t *testing.T) { rule := ManagedOverrideRule{ Path: tt.rulePath, } - result := rule.matchesFileContext(tt.filePath, "") + result := rule.matchesFileContext(tt.filePath, "", "") assert.Equal(t, tt.expected, result, "filePath: %s, rulePath: %s", tt.filePath, tt.rulePath) }) } diff --git a/mcp/easypconfig/easypconfig_test.go b/mcp/easypconfig/easypconfig_test.go index 688b6f91..3d74eaa5 100644 --- a/mcp/easypconfig/easypconfig_test.go +++ b/mcp/easypconfig/easypconfig_test.go @@ -206,6 +206,18 @@ func TestSchemaByPath_GitRepoOutAbsent(t *testing.T) { require.False(t, hasOut) } +func TestDescribe_ManagedRulePackageFieldPresent(t *testing.T) { + t.Parallel() + + out, err := Describe(DescribeInput{Path: "generate.managed.override"}) + require.NoError(t, err) + require.Contains(t, fieldPaths(out.Fields), "generate.managed.override[].package") + + out, err = Describe(DescribeInput{Path: "generate.managed.disable"}) + require.NoError(t, err) + require.Contains(t, fieldPaths(out.Fields), "generate.managed.disable[].package") +} + func TestMarshalConfigJSONSchema_Golden(t *testing.T) { t.Parallel() diff --git a/mcp/easypconfig/schema_model.go b/mcp/easypconfig/schema_model.go index bbb86725..a18b2d56 100644 --- a/mcp/easypconfig/schema_model.go +++ b/mcp/easypconfig/schema_model.go @@ -119,6 +119,7 @@ type configSchemaManaged struct { type configSchemaManagedDisableRule struct { Module string `json:"module,omitempty"` + Package string `json:"package,omitempty"` Path string `json:"path,omitempty"` FileOption string `json:"file_option,omitempty"` FieldOption string `json:"field_option,omitempty"` @@ -128,6 +129,7 @@ type configSchemaManagedDisableRule struct { func (configSchemaManagedDisableRule) JSONSchemaExtend(schema *invjsonschema.Schema) { schema.AnyOf = []*invjsonschema.Schema{ {Required: []string{"module"}}, + {Required: []string{"package"}}, {Required: []string{"path"}}, {Required: []string{"file_option"}}, {Required: []string{"field_option"}}, @@ -144,6 +146,7 @@ type configSchemaManagedOverrideRule struct { FieldOption string `json:"field_option,omitempty"` Value any `json:"value"` Module string `json:"module,omitempty"` + Package string `json:"package,omitempty"` Path string `json:"path,omitempty"` Field string `json:"field,omitempty"` } diff --git a/mcp/easypconfig/spec_docs.go b/mcp/easypconfig/spec_docs.go index 6bef9660..35cb7444 100644 --- a/mcp/easypconfig/spec_docs.go +++ b/mcp/easypconfig/spec_docs.go @@ -201,14 +201,14 @@ func docsByPath() map[string]nodeDoc { "generate.managed": { Fields: []FieldDoc{ {Path: "generate.managed.enabled", Type: "boolean", Required: false, Description: "Enable managed mode option rewriting.", DefaultValue: "false"}, - {Path: "generate.managed.disable", Type: "array", Required: false, Description: "Disable managed mode for matching modules, paths, or options."}, - {Path: "generate.managed.override", Type: "array", Required: false, Description: "Override file/field options with values. Without module/path, applies to all files."}, + {Path: "generate.managed.disable", Type: "array", Required: false, Description: "Disable managed mode for matching modules, protobuf packages, paths, or options."}, + {Path: "generate.managed.override", Type: "array", Required: false, Description: "Override file/field options with values. Without module/package/path, applies to all files."}, }, Examples: []Example{ { Title: "managed_mode_full", Description: "Managed mode with both disable and override rules.", - YAML: "generate:\n managed:\n enabled: true\n disable:\n - module: github.com/googleapis/googleapis\n - field_option: jstype\n field: acme.v1.Message.count\n override:\n - file_option: go_package_prefix\n value: github.com/acme/contracts/gen/go\n - field_option: jstype\n field: acme.v1.Message.count\n value: JS_STRING\n", + YAML: "generate:\n managed:\n enabled: true\n disable:\n - module: github.com/googleapis/googleapis\n - package: acme.v1\n file_option: java_package_prefix\n - field_option: jstype\n field: acme.v1.Message.count\n override:\n - file_option: go_package_prefix\n value: github.com/acme/contracts/gen/go\n - file_option: go_package\n package: acme.v1\n value: github.com/acme/contracts/gen/go/acme/v1\n - field_option: jstype\n field: acme.v1.Message.count\n value: JS_STRING\n", Paths: []string{"generate.managed"}, }, }, @@ -216,6 +216,7 @@ func docsByPath() map[string]nodeDoc { "generate.managed.disable": { Fields: []FieldDoc{ {Path: "generate.managed.disable[].module", Type: "string", Required: false, Description: "Apply disable to an exact EasyP module source (dependency/git_repo URL without @version)."}, + {Path: "generate.managed.disable[].package", Type: "string", Required: false, Description: "Apply disable to an exact protobuf package from the .proto file package declaration."}, {Path: "generate.managed.disable[].path", Type: "string", Required: false, Description: "Apply disable to path."}, {Path: "generate.managed.disable[].file_option", Type: "string", Required: false, Description: "Disable this file option."}, {Path: "generate.managed.disable[].field_option", Type: "string", Required: false, Description: "Disable this field option."}, @@ -225,7 +226,7 @@ func docsByPath() map[string]nodeDoc { { Title: "managed_disable_variants", Description: "Disable rules by path, file option, and field option.", - YAML: "generate:\n managed:\n disable:\n - path: proto/third_party\n - file_option: java_package\n - field_option: jstype\n field: acme.v1.Message.count\n", + YAML: "generate:\n managed:\n disable:\n - path: proto/third_party\n - package: acme.v1\n file_option: java_package\n - field_option: jstype\n field: acme.v1.Message.count\n", Paths: []string{"generate.managed.disable"}, }, }, @@ -233,6 +234,7 @@ func docsByPath() map[string]nodeDoc { "At least one key in each disable item is required.", "`file_option` and `field_option` cannot be used together.", "`field` requires `field_option`.", + "`package` matches the protobuf file package exactly.", }, }, "generate.managed.override": { @@ -241,6 +243,7 @@ func docsByPath() map[string]nodeDoc { {Path: "generate.managed.override[].field_option", Type: "string", Required: false, Description: "Target field option to override."}, {Path: "generate.managed.override[].value", Type: "any", Required: true, Description: "Override value."}, {Path: "generate.managed.override[].module", Type: "string", Required: false, Description: "Optional exact EasyP module selector (dependency/git_repo URL without @version)."}, + {Path: "generate.managed.override[].package", Type: "string", Required: false, Description: "Optional exact protobuf package selector from the .proto file package declaration."}, {Path: "generate.managed.override[].path", Type: "string", Required: false, Description: "Optional path selector."}, {Path: "generate.managed.override[].field", Type: "string", Required: false, Description: "Optional field selector (for field_option)."}, }, @@ -248,7 +251,7 @@ func docsByPath() map[string]nodeDoc { { Title: "managed_override_file_option", Description: "Override a file option with a custom value.", - YAML: "generate:\n managed:\n override:\n - file_option: java_package_prefix\n value: com.acme.generated\n", + YAML: "generate:\n managed:\n override:\n - file_option: java_package_prefix\n value: com.acme.generated\n - file_option: go_package_prefix\n package: acme.v1\n value: github.com/acme/generated/go\n", Paths: []string{"generate.managed.override"}, }, { @@ -261,6 +264,7 @@ func docsByPath() map[string]nodeDoc { Notes: []string{ "Each override item requires exactly one of file_option or field_option.", "`field` can only be used with `field_option`.", + "`package` matches the protobuf file package exactly.", }, }, "breaking": { diff --git a/schemas/easyp-config-v1.schema.json b/schemas/easyp-config-v1.schema.json index 64f7b5a9..d7404305 100644 --- a/schemas/easyp-config-v1.schema.json +++ b/schemas/easyp-config-v1.schema.json @@ -201,6 +201,11 @@ "module" ] }, + { + "required": [ + "package" + ] + }, { "required": [ "path" @@ -232,6 +237,9 @@ "module": { "type": "string" }, + "package": { + "type": "string" + }, "path": { "type": "string" }, @@ -286,6 +294,9 @@ "module": { "type": "string" }, + "package": { + "type": "string" + }, "path": { "type": "string" }, diff --git a/schemas/easyp-config.schema.json b/schemas/easyp-config.schema.json index 64f7b5a9..d7404305 100644 --- a/schemas/easyp-config.schema.json +++ b/schemas/easyp-config.schema.json @@ -201,6 +201,11 @@ "module" ] }, + { + "required": [ + "package" + ] + }, { "required": [ "path" @@ -232,6 +237,9 @@ "module": { "type": "string" }, + "package": { + "type": "string" + }, "path": { "type": "string" }, @@ -286,6 +294,9 @@ "module": { "type": "string" }, + "package": { + "type": "string" + }, "path": { "type": "string" },