### Install Dependencies Source: https://github.com/bufbuild/protovalidate-es/blob/main/packages/example/README.md Installs the necessary Node.js dependencies for the example project. Ensure Node.js version 20 or later is installed. ```shell curl -L https://github.com/bufbuild/protovalidate-es/archive/refs/heads/main.zip > protovalidate-es-main.zip unzip protovalidate-es-main.zip 'protovalidate-es-main/packages/example/*' cd protovalidate-es-main/packages/example npm install ``` -------------------------------- ### Install Protovalidate ES Source: https://github.com/bufbuild/protovalidate-es/blob/main/_autodocs/README.md Install the necessary packages using npm. ```bash npm install @bufbuild/protovalidate @bufbuild/protobuf ``` -------------------------------- ### Run Basic Validation Example Source: https://github.com/bufbuild/protovalidate-es/blob/main/packages/example/README.md Executes the basic example to validate a money transfer Protobuf message. Modify src/basic.ts to test different scenarios. ```shell npm start ``` -------------------------------- ### Unit Test Example Source: https://github.com/bufbuild/protovalidate-es/blob/main/_autodocs/MANIFEST.txt Illustrates how to write unit tests for Protovalidate ES configurations and validation logic. This example focuses on testing a specific validation rule. ```typescript import { createValidator } from '@buf/protovalidate-es.bufbuild_es/validator'; describe('MyProtoMessage validation', () => { it('should fail if field1 is negative', async () => { const validator = createValidator(); const message = new MyProtoMessage({ field1: -5 }); const result = await validator.validate(message); expect(result.ok).toBe(false); expect(result.violations).toHaveLength(1); expect(result.violations[0].path).toBe('field1'); }); }); ``` -------------------------------- ### Example: Inferring User Output Type Source: https://github.com/bufbuild/protovalidate-es/blob/main/_autodocs/types.md Demonstrates how to infer the output type for a UserSchema using the InferOutput utility. ```typescript const userSchema = createStandardSchema(UserSchema); type UserOutput = StandardSchemaV1.InferOutput; ``` -------------------------------- ### Create Validator with Default Configuration Source: https://github.com/bufbuild/protovalidate-es/blob/main/_autodocs/configuration.md Use the `createValidator` function without any arguments to initialize a validator with all default settings. This is the simplest way to get started. ```typescript import { createValidator } from "@bufbuild/protovalidate"; // Use all defaults const validator = createValidator(); ``` -------------------------------- ### Complete Protobuf Validation Example Source: https://github.com/bufbuild/protovalidate-es/blob/main/_autodocs/usage-examples.md Defines a User message with various validation rules including UUID, email format, string length and pattern, uint32 range, repeated field constraints, and a custom CEL expression. This example shows a comprehensive set of validation options. ```protobuf syntax = "proto3"; package example.v1; import "buf/validate/validate.proto"; message User { string id = 1 [(buf.validate.field).string.uuid = true]; string email = 2 [(buf.validate.field).string.email = true]; string username = 3 [ (buf.validate.field).string.min_len = 3, (buf.validate.field).string.max_len = 20, (buf.validate.field).string.pattern = "^[a-zA-Z0-9_]+$" ]; uint32 age = 4 [(buf.validate.field).uint32.gte = 0, (buf.validate.field).uint32.lte = 150]; repeated string tags = 5 [ (buf.validate.field).repeated.min_items = 0, (buf.validate.field).repeated.max_items = 10, (buf.validate.field).repeated.unique = true ]; option (buf.validate.message).cel = { id: "user.username_not_email" message: "username cannot equal email" expression: "this.username != this.email" }; } ``` -------------------------------- ### Example: Inferring User Input Type Source: https://github.com/bufbuild/protovalidate-es/blob/main/_autodocs/types.md Demonstrates how to infer the input type for a UserSchema using the InferInput utility. ```typescript const userSchema = createStandardSchema(UserSchema); type UserInput = StandardSchemaV1.InferInput; ``` -------------------------------- ### Complete Protobuf Definition Example Source: https://github.com/bufbuild/protovalidate-es/blob/main/_autodocs/MANIFEST.txt This section implies a full `.proto` file definition would be shown, which is not directly present in the provided text. It serves as a placeholder for where such a definition would be relevant. ```protobuf // Example Protobuf definition would be shown here. // syntax = "proto3"; // // message MyProtoMessage { // string name = 1; // int32 age = 2; // } ``` -------------------------------- ### Custom Registry Setup in Protovalidate ES Source: https://github.com/bufbuild/protovalidate-es/blob/main/_autodocs/README.md Illustrates how to create and use a custom registry with Protovalidate ES, allowing for custom extensions. ```typescript import { createRegistry } from "@bufbuild/protobuf"; const registry = createRegistry(CustomExtension); const validator = createValidator({ registry }); ``` -------------------------------- ### API Handler Integration: Express.js Example Source: https://github.com/bufbuild/protovalidate-es/blob/main/_autodocs/MANIFEST.txt Provides an example of integrating Protovalidate ES with an Express.js API handler to validate incoming request bodies. ```typescript import express from 'express'; import { createValidator } from '@buf/protovalidate-es.bufbuild_es/validator'; const app = express(); const validator = createValidator(); app.post('/validate', express.json(), async (req, res) => { const message = MyProtoMessage.fromObject(req.body); const result = await validator.validate(message); if (result.ok) { res.status(200).send('Validation successful'); } else { res.status(400).json(result.violations); } }); ``` -------------------------------- ### Custom RegexMatcher Implementation Example Source: https://github.com/bufbuild/protovalidate-es/blob/main/_autodocs/types.md Provides an example of implementing a custom RegexMatcher using the RE2 library. This custom matcher can be passed to `createValidator` to override the default regex behavior. ```typescript import { createValidator } from "@bufbuild/protovalidate"; const regexMatcher = (pattern: string, against: string): boolean => { try { return new RE2(pattern).test(against); } catch { return false; } }; const validator = createValidator({ regexMatch: regexMatcher }); ``` -------------------------------- ### Example Usage of Validator.validate() Source: https://github.com/bufbuild/protovalidate-es/blob/main/_autodocs/api-reference-validator.md Demonstrates how to create a validator, create a message instance, and validate it. Handles valid, invalid, and error states. ```typescript import { create } from "@bufbuild/protobuf"; import { createValidator } from "@bufbuild/protovalidate"; import { UserSchema } from "./gen/user_pb"; const validator = createValidator(); const user = create(UserSchema, { id: "550e8400-e29b-41d4-a716-446655440000", email: "user@example.com", firstName: "John", lastName: "Doe", }); const result = validator.validate(UserSchema, user); if (result.kind === "valid") { console.log("User is valid:", result.message); } else if (result.kind === "invalid") { console.log("Validation errors:"); for (const violation of result.violations) { console.log(` ${violation.toString()}`); } } else { // result.kind === "error" console.error("Compilation/runtime error:", result.error.message); } ``` -------------------------------- ### Protobuf string.prefix Validation Source: https://github.com/bufbuild/protovalidate-es/blob/main/_autodocs/validation-rules-reference.md Ensures a string field starts with a specific prefix. Default is an empty string (no prefix required). ```protobuf string resource = 1 [(buf.validate.field).string.prefix = "user-"]; ``` -------------------------------- ### Violation Path Example Source: https://github.com/bufbuild/protovalidate-es/blob/main/_autodocs/core-concepts.md Illustrates a typical violation message format showing the field path and rule path. ```plaintext user.addresses[0].zip_code: value does not match pattern [string.pattern] ``` -------------------------------- ### Generate Protobuf Code with Buf CLI Source: https://github.com/bufbuild/protovalidate-es/blob/main/packages/example/README.md Re-generates Protobuf code after modifying validation rules. Requires the Buf CLI to be installed. ```shell npx buf generate ``` -------------------------------- ### Standard Schema Integration: Basic Usage Source: https://github.com/bufbuild/protovalidate-es/blob/main/_autodocs/MANIFEST.txt Integrates Protovalidate ES with a standard schema definition. This example shows basic usage without type safety. ```typescript import { createStandardSchema } from '@buf/protovalidate-es.bufbuild_es/validator'; const schema = createStandardSchema(MyProtoMessage); const validator = createValidator({ standardSchema: schema, }); ``` -------------------------------- ### Complete Error Handling Source: https://github.com/bufbuild/protovalidate-es/blob/main/_autodocs/usage-examples.md This example demonstrates comprehensive error handling for validation results, distinguishing between valid messages, validation rule violations, and compilation or runtime errors. ```typescript import { createValidator, ValidationError, CompilationError, RuntimeError, } from "@bufbuild/protovalidate"; const validator = createValidator(); const result = validator.validate(UserSchema, user); switch (result.kind) { case "valid": console.log("Message is valid"); break; case "invalid": // Validation rule violations console.error("Validation violations:"); for (const violation of result.violations) { console.error( ` ${violation.toString()} [for_key: ${violation.forKey}]` ); } break; case "error": // Compilation or runtime error if (result.error instanceof CompilationError) { console.error("Failed to compile rules:", result.error.message); } else if (result.error instanceof RuntimeError) { console.error("Runtime error:", result.error.message); } else { console.error("Unknown error:", result.error); } break; } ``` -------------------------------- ### Create Standard Schema with Options Source: https://github.com/bufbuild/protovalidate-es/blob/main/_autodocs/configuration.md Use `createStandardSchema` to generate a validator schema with custom options. This example shows how to disable failFast and enable legacyRequired. ```typescript import { createStandardSchema } from "@bufbuild/protovalidate"; const userSchema = createStandardSchema(UserSchema, { failFast: false, legacyRequired: false, }); const result = userSchema["~standard"].validate(userData); ``` -------------------------------- ### Format Violation as String Source: https://github.com/bufbuild/protovalidate-es/blob/main/_autodocs/api-reference-errors.md Demonstrates how to use the `toString()` method to get a human-readable string representation of a `Violation`. ```typescript violation.toString(); // "email: value must be a valid email [email.format]" ``` -------------------------------- ### API Reference: Validator Source: https://github.com/bufbuild/protovalidate-es/blob/main/_autodocs/MANIFEST.txt Documentation for the `createValidator()` function, `ValidatorOptions` type, and the `Validator.validate()` method. Explains the return type `ValidationResult` and provides usage examples. ```APIDOC ## API Reference: Validator ### Description This section details the `createValidator()` function, its parameters, the `ValidatorOptions` type for configuration, and the `Validator.validate()` method. It also explains the `ValidationResult` return type and provides usage examples. ### Functions #### createValidator(options?: ValidatorOptions) - **Description**: Creates a validator instance. - **Parameters**: - `options` (ValidatorOptions) - Optional configuration for the validator. ### Types #### ValidatorOptions - **Description**: Configuration options for the validator. - **Fields**: - `rules` (object) - Custom validation rules. - `messages` (object) - Custom error messages. - `config` (object) - General configuration settings. #### Validator - **Description**: Represents a validator instance. - **Methods**: - `validate(data: any): ValidationResult` - Performs validation on the provided data. #### ValidationResult - **Description**: The result of a validation operation. - **Properties**: - `valid` (boolean) - True if the data is valid, false otherwise. - `errors` (ValidationError[]) - An array of validation errors if `valid` is false. ### Request Example ```typescript import { createValidator, ValidatorOptions } from "@bufbuild/protovalidate-es"; const options: ValidatorOptions = { // ... configuration ... }; const validator = createValidator(options); const result = validator.validate({ /* data to validate */ }); if (result.valid) { console.log("Validation successful!"); } else { console.error("Validation failed:", result.errors); } ``` ### Response #### Success Response (ValidationResult) - **valid** (boolean) - Indicates if the validation passed. - **errors** (ValidationError[]) - An array of errors if validation failed. #### Response Example ```json { "valid": false, "errors": [ { "message": "Value must be a string.", "path": "field.name" } ] } ``` ``` -------------------------------- ### Field-Level CEL Rule for Password Strength Source: https://github.com/bufbuild/protovalidate-es/blob/main/_autodocs/usage-examples.md Demonstrates how to apply a custom validation rule directly to a field using CEL. This example enforces password complexity by requiring uppercase, lowercase letters, and digits. ```typescript // Proto: // message User { // string password = 1 [(buf.validate.field).cel = [{ // id: "password_strength" // message: "password must contain uppercase, lowercase, and digit" // expression: "this.password.matches('[A-Z]') && this.password.matches('[a-z]') && this.password.matches('[0-9]')" // }]]; // } const user = create(UserSchema, { password: "abc", // Doesn't meet complexity rules }); const result = validator.validate(UserSchema, user); if (result.kind === "invalid") { const complexityError = result.violations.find( (v) => v.ruleId === "password_strength" ); if (complexityError) { console.log(complexityError.toString()); } } ``` -------------------------------- ### Create Validator Instance Source: https://github.com/bufbuild/protovalidate-es/blob/main/_autodocs/api-reference-validator.md Use `createValidator` to get a validator instance. It accepts optional `ValidatorOptions` to customize its behavior. ```typescript import { createValidator } from "@bufbuild/protovalidate"; import { createRegistry } from "@bufbuild/protobuf"; // Basic validator with default settings const validator = createValidator(); // Validator with custom registry const registry = createRegistry(); const validator = createValidator({ registry }); // Validator that stops on first error const validator = createValidator({ failFast: true }); // Validator with custom regex engine const validator = createValidator({ regexMatch: (pattern: string, against: string): boolean => { // Custom RE2 implementation return new RE2(pattern).test(against); }, }); ``` -------------------------------- ### Message-Level CEL Rule for Different Accounts Source: https://github.com/bufbuild/protovalidate-es/blob/main/_autodocs/usage-examples.md Illustrates how to define a custom validation rule at the message level using CEL. This example enforces that 'from_account' and 'to_account' fields must be different in a money transfer. ```typescript // Proto: // message MoneyTransfer { // string from_account = 1 [(buf.validate.field).string.uuid = true]; // string to_account = 2 [(buf.validate.field).string.uuid = true]; // double amount = 3 [(buf.validate.field).double.gt = 0]; // // option (buf.validate.message).cel = { // id: "different_accounts" // message: "from and to accounts must be different" // expression: "this.from_account != this.to_account" // }; // } const transfer = create(MoneyTransferSchema, { fromAccount: "550e8400-e29b-41d4-a716-446655440000", toAccount: "550e8400-e29b-41d4-a716-446655440000", // Same account amount: 100, }); const result = validator.validate(MoneyTransferSchema, transfer); if (result.kind === "invalid") { // Custom rule violation const customViolation = result.violations.find( (v) => v.ruleId === "different_accounts" ); if (customViolation) { console.log(customViolation.toString()); // "from and to accounts must be different [different_accounts]" } } ``` -------------------------------- ### Bytes Prefix Validation Source: https://github.com/bufbuild/protovalidate-es/blob/main/_autodocs/validation-rules-reference.md Enforces a specific byte prefix for a bytes field. Use when data must start with a known sequence. ```protobuf bytes data = 1 [(buf.validate.field).bytes.prefix = "\x00\x01"]; ``` -------------------------------- ### Run Benchmarks with npm Source: https://github.com/bufbuild/protovalidate-es/blob/main/packages/protovalidate-bench/README.md Execute benchmarks using npm. Ensure proto files are generated and dependencies are built before running. ```shell npm run bench ``` -------------------------------- ### Standard String and Numeric Rules Source: https://github.com/bufbuild/protovalidate-es/blob/main/_autodocs/core-concepts.md Demonstrates applying standard string and numeric validation rules using Protobuf field options. ```protobuf string email = 1 [(buf.validate.field).string.email = true]; uint32 age = 2 [(buf.validate.field).uint32.lte = 150]; ``` -------------------------------- ### Basic Validation with Default Configuration Source: https://github.com/bufbuild/protovalidate-es/blob/main/_autodocs/MANIFEST.txt Demonstrates the simplest way to validate a message using the default configuration. No specific imports are shown, implying they are handled elsewhere. ```typescript const validator = createValidator(); const result = await validator.validate(message); if (!result.ok) { // Handle validation errors } ``` -------------------------------- ### createStandardSchema with Custom Registry Source: https://github.com/bufbuild/protovalidate-es/blob/main/_autodocs/api-reference-standard-schema.md Shows how to initialize a Standard Schema validator with a custom Protobuf registry by passing it in the options object to `createStandardSchema`. ```typescript import { createStandardSchema } from "@bufbuild/protovalidate"; import { createRegistry } from "@bufbuild/protobuf"; import { UserSchema } from "./gen/user_pb"; const registry = createRegistry(); const userSchema = createStandardSchema(UserSchema, { registry }); const result = userSchema["~standard"].validate(userData); ``` -------------------------------- ### Basic Usage of Protovalidate ES Source: https://github.com/bufbuild/protovalidate-es/blob/main/_autodocs/README.md Demonstrates how to create a validator instance, create a message, and validate it. Handles valid, invalid, and error cases. ```typescript import { create } from "@bufbuild/protobuf"; import { createValidator } from "@bufbuild/protovalidate"; import { UserSchema } from "./gen/user_pb"; // Create validator const validator = createValidator(); // Create and validate message const user = create(UserSchema, { id: "550e8400-e29b-41d4-a716-446655440000", email: "user@example.com", }); const result = validator.validate(UserSchema, user); switch (result.kind) { case "valid": console.log("✓ Valid"); break; case "invalid": console.log("✗ Violations:", result.violations); break; case "error": console.error("✗ Error:", result.error.message); break; } ``` -------------------------------- ### Run Benchmarks with Turborepo Source: https://github.com/bufbuild/protovalidate-es/blob/main/packages/protovalidate-bench/README.md Use this command to run benchmarks with Turborepo. You can optionally specify a regex to filter tasks and a directory for outputting JSON results. ```shell npx turbo run bench -- [regex] --dir ``` -------------------------------- ### Create and Validate Standard Schema Source: https://github.com/bufbuild/protovalidate-es/blob/main/_autodocs/usage-examples.md Demonstrates creating a standard schema from a UserSchema and validating a user object. Use this when you need to validate data against a predefined schema. ```typescript import { createStandardSchema } from "@bufbuild/protovalidate"; const userSchema = createStandardSchema(UserSchema); const user = { id: "...", email: "user@example.com" }; const result = userSchema["~standard"].validate(user); if ("value" in result) { console.log("Valid:", result.value); } else { console.log("Issues:", result.issues); } ``` -------------------------------- ### Create and Use Validator Source: https://github.com/bufbuild/protovalidate-es/blob/main/_autodocs/INDEX.md Instantiate the validator and perform basic validation. Ensure you have the necessary imports. ```typescript import { createValidator, Validator } from "@bufbuild/protovalidate"; const validator = createValidator(); const result = validator.validate(schema, message); ``` -------------------------------- ### Get Rule Descriptor Source: https://github.com/bufbuild/protovalidate-es/blob/main/_autodocs/internal-architecture.md Retrieves the FieldRules descriptor for a given message. This is used for understanding the schema of validation rules, particularly for CEL compilation. ```typescript getRuleDescriptor() // Get FieldRules descriptor for a message ``` -------------------------------- ### Basic Usage of createStandardSchema Source: https://github.com/bufbuild/protovalidate-es/blob/main/_autodocs/api-reference-standard-schema.md Demonstrates how to create a Standard Schema validator for a `UserSchema` and use its `validate` method to check user data. It shows how to handle both valid and invalid results. ```typescript import { createStandardSchema } from "@bufbuild/protovalidate"; import { UserSchema } from "./gen/user_pb"; // Create a Standard Schema validator const userSchema = createStandardSchema(UserSchema); // Use with the Standard Schema validate function const user = { id: "123e4567-e89b-12d3-a456-426614174000", email: "user@example.com" }; const result = userSchema["~standard"].validate(user); if ("value" in result) { console.log("Valid user:", result.value); } else { console.log("Validation issues:", result.issues); } ``` -------------------------------- ### Simple Validation with Default Config Source: https://github.com/bufbuild/protovalidate-es/blob/main/_autodocs/usage-examples.md Use this snippet for basic validation of a Protocol Buffer message with the default configuration. It shows how to create a validator, instantiate a message, and check the validation result. ```typescript import { create } from "@bufbuild/protobuf"; import { createValidator } from "@bufbuild/protovalidate"; import { UserSchema } from "./gen/user_pb"; // Create a validator const validator = createValidator(); // Create a message const user = create(UserSchema, { id: "550e8400-e29b-41d4-a716-446655440000", email: "user@example.com", firstName: "John", lastName: "Doe", age: 30, }); // Validate const result = validator.validate(UserSchema, user); if (result.kind === "valid") { console.log("✓ User is valid"); console.log(result.message); } else if (result.kind === "invalid") { console.log("✗ Validation failed:"); result.violations.forEach((v) => { console.log(` - ${v.toString()}`); }); } else { // result.kind === "error" console.error("✗ Error:", result.error.message); } ``` -------------------------------- ### Validate Nested Message Fields Source: https://github.com/bufbuild/protovalidate-es/blob/main/_autodocs/usage-examples.md Illustrates how Protovalidate-ES automatically handles validation of nested message fields. This example shows a violation path that includes a nested field. ```typescript // Proto: // message User { // string id = 1 [(buf.validate.field).string.uuid = true]; // Address address = 2; // } // message Address { // string zip = 1 [(buf.validate.field).string.min_len = 5]; // } const user = create(UserSchema, { id: "550e8400-e29b-41d4-a716-446655440000", address: { zip: "123", // Too short; will fail validation }, }); const result = validator.validate(UserSchema, user); if (result.kind === "invalid") { // Violation path includes the nested field console.log(result.violations[0].toString()); // "address.zip: value length must be at least 5 characters [string.min_len]" } ``` -------------------------------- ### Multiple Validators: Different Configurations Source: https://github.com/bufbuild/protovalidate-es/blob/main/_autodocs/MANIFEST.txt Shows how to create and use multiple validator instances, each with different configurations, to suit various validation needs within an application. ```typescript const strictValidator = createValidator({ failFast: true }); const lenientValidator = createValidator({ failFast: false }); const resultStrict = await strictValidator.validate(messageA); const resultLenient = await lenientValidator.validate(messageB); ``` -------------------------------- ### Using Type Utilities for Schema Inference Source: https://github.com/bufbuild/protovalidate-es/blob/main/_autodocs/api-reference-standard-schema.md Shows how to use StandardSchemaV1 type utilities to infer the input and output types for schema validation and processing. ```typescript import { createStandardSchema } from "@bufbuild/protovalidate"; import { UserSchema } from "./gen/user_pb"; const userSchema = createStandardSchema(UserSchema); // Infer the expected input type type ValidateInput = StandardSchemaV1.InferInput; // Infer the validated output type type ValidateOutput = StandardSchemaV1.InferOutput; function processUser(input: ValidateInput): ValidateOutput { const result = userSchema["~standard"].validate(input); if ("value" in result) { return result.value; } throw new Error("Invalid user data"); } ``` -------------------------------- ### Create Validator with All Configuration Options Source: https://github.com/bufbuild/protovalidate-es/blob/main/_autodocs/configuration.md Combine multiple configuration options, including a custom registry, fail-fast behavior, legacy required field handling, disabling native rules, and a custom regex engine, in a single `createValidator` call. ```typescript import { createValidator } from "@bufbuild/protovalidate"; import { createRegistry } from "@bufbuild/protobuf"; const myRegistry = createRegistry(); const validator = createValidator({ registry: myRegistry, failFast: false, legacyRequired: true, disableNativeRules: false, regexMatch: (pattern: string, against: string) => { try { return new RegExp(pattern).test(against); } catch { return false; } }, }); ``` -------------------------------- ### Create and Inspect a Violation Source: https://github.com/bufbuild/protovalidate-es/blob/main/_autodocs/api-reference-errors.md Shows how to instantiate a `Violation` object and access its properties. ```typescript import { Violation } from "@bufbuild/protovalidate"; const violation = new Violation( "value must be a valid UUID", "string.uuid", [{ kind: "field", name: "id", number: 1 }], [{ kind: "field", name: "string" }, { kind: "field", name: "uuid" }], false, ); console.log(violation.toString()); // "id: value must be a valid UUID [string.uuid]" console.log(violation.message); // "value must be a valid UUID" console.log(violation.ruleId); // "string.uuid" console.log(violation.forKey); // false ``` -------------------------------- ### Any In Rule Source: https://github.com/bufbuild/protovalidate-es/blob/main/_autodocs/validation-rules-reference.md Ensures that the type URL of a google.protobuf.Any field is present in a specified list of allowed type URLs. Use when only specific Any types are permitted. ```protobuf google.protobuf.Any payload = 1 [(buf.validate.field).any.in = "type.googleapis.com/MyType"]; ``` -------------------------------- ### Create Protovalidate Validator Source: https://github.com/bufbuild/protovalidate-es/blob/main/_autodocs/core-concepts.md Initialize a validator instance. Options can include custom types to be added to the message registry and CEL environment. ```typescript const validator = createValidator(options?); ``` -------------------------------- ### Validate String as URI Reference Source: https://github.com/bufbuild/protovalidate-es/blob/main/_autodocs/validation-rules-reference.md Use this rule to ensure a string is a valid URI reference. Applied to string fields. ```protobuf string location = 1 [(buf.validate.field).string.uri_ref = true]; ``` -------------------------------- ### Standard Schema Integration: Type-Safe Usage Source: https://github.com/bufbuild/protovalidate-es/blob/main/_autodocs/MANIFEST.txt Demonstrates type-safe integration with a standard schema, ensuring that the schema definition aligns with the message types used. ```typescript import { createStandardSchema, StandardSchemaV1 } from '@buf/protovalidate-es.bufbuild_es/validator'; // Assuming MyProtoMessage is a typed message const schema = createStandardSchema(MyProtoMessage); const validator = createValidator({ standardSchema: schema, }); ``` -------------------------------- ### Protovalidate ES Package Exports Source: https://github.com/bufbuild/protovalidate-es/blob/main/_autodocs/README.md Main entry points for importing Protovalidate ES functionality. Use these to import specific types or the main validator. ```typescript // Main entry point export * from "./validator.js"; // Validator, ValidatorOptions, ValidationResult, createValidator export * from "./error.js"; // Errors, Violation export { createStandardSchema } from "./standard-schema.js"; ``` -------------------------------- ### Any Required Rule Source: https://github.com/bufbuild/protovalidate-es/blob/main/_autodocs/validation-rules-reference.md Validates that a google.protobuf.Any field is set. Use when the Any field must contain a value. ```protobuf google.protobuf.Any payload = 1 [(buf.validate.field).any.required = true]; ``` -------------------------------- ### Type Inference with createStandardSchema Source: https://github.com/bufbuild/protovalidate-es/blob/main/_autodocs/api-reference-standard-schema.md Illustrates how TypeScript can automatically infer the input and output types for a validator created with `createStandardSchema` using `StandardSchemaV1.InferInput` and `StandardSchemaV1.InferOutput`. ```typescript import { createStandardSchema } from "@bufbuild/protovalidate"; import { UserSchema } from "./gen/user_pb"; const userSchema = createStandardSchema(UserSchema); // TypeScript automatically infers input and output types type UserInput = StandardSchemaV1.InferInput; type UserOutput = StandardSchemaV1.InferOutput; ``` -------------------------------- ### Custom CEL Rule for Message Validation Source: https://github.com/bufbuild/protovalidate-es/blob/main/_autodocs/core-concepts.md Shows how to apply a custom validation rule using CEL expressions for a message field. ```protobuf message MoneyTransfer { string from_account = 1; string to_account = 2; option (buf.validate.message).cel = { id: "transfer.different_accounts" message: "from and to accounts must be different" expression: "this.from_account != this.to_account" }; } ``` -------------------------------- ### Create Validator with ReDoS Protection Source: https://github.com/bufbuild/protovalidate-es/blob/main/_autodocs/configuration.md Implement ReDoS (Regular Expression Denial of Service) protection by providing a custom `regexMatch` function that includes a timeout. This prevents malicious regex patterns from consuming excessive resources. ```typescript import { createValidator } from "@bufbuild/protovalidate"; // Custom regex with timeout protection const validator = createValidator({ regexMatch: (pattern: string, against: string): boolean => { try { // Set up a timeout to prevent ReDoS const timeoutPromise = new Promise((resolve) => { const timeout = setTimeout(() => { resolve(false); }, 100); // 100ms timeout try { const result = new RegExp(pattern).test(against); clearTimeout(timeout); resolve(result); } catch { clearTimeout(timeout); resolve(false); } }); return timeoutPromise as unknown as boolean; // Not truly async yet } catch { return false; } }, }); ``` -------------------------------- ### Complete Error Handling with All Result Kinds Source: https://github.com/bufbuild/protovalidate-es/blob/main/_autodocs/MANIFEST.txt Illustrates how to handle all possible validation result kinds: OK, CompilationError, and RuntimeError. This provides robust error management. ```typescript const result = await validator.validate(message); if (result.ok) { console.log('Validation successful!'); } else if (result.type === 'CompilationError') { console.error('Compilation error:', result.error); } else if (result.type === 'RuntimeError') { console.error('Runtime error:', result.error); } else { // Handle ValidationError console.error('Validation errors:'); for (const violation of result.violations) { console.error(`- ${violation.message} at ${violation.path}`); } } ``` -------------------------------- ### Standard Schema Validation in Protovalidate ES Source: https://github.com/bufbuild/protovalidate-es/blob/main/_autodocs/README.md Shows how to create and use a standard schema for validation, including checking for valid results or accessing issues on invalid results. ```typescript const schema = createStandardSchema(UserSchema); const result = schema["~standard"].validate(user); if ("value" in result) { // Valid } else { // Invalid - result.issues contains errors } ``` -------------------------------- ### Create Message Registry Source: https://github.com/bufbuild/protovalidate-es/blob/main/_autodocs/core-concepts.md Create a message registry to resolve custom Protobuf extensions used in validation rules. This is necessary when using custom extensions in your validation configurations. ```typescript const registry = createRegistry(customExtension); const validator = createValidator({ registry }); ``` -------------------------------- ### API Reference: Standard Schema Source: https://github.com/bufbuild/protovalidate-es/blob/main/_autodocs/MANIFEST.txt Details on the `createStandardSchema()` function and the `StandardSchemaV1` interface, including its nested types and type utilities for integration. ```APIDOC ## API Reference: Standard Schema ### Description This section covers the `createStandardSchema()` function and the `StandardSchemaV1` interface, which defines a standard structure for validation schemas. It also explains nested types like `Props`, `Result`, `Issue`, and type utilities such as `InferInput` and `InferOutput`. ### Functions #### createStandardSchema(schema: StandardSchemaV1) - **Description**: Creates a validator from a standard schema definition. - **Parameters**: - `schema` (StandardSchemaV1) - The validation schema object. ### Types #### StandardSchemaV1 - **Description**: Defines the structure for a version 1 standard validation schema. - **Properties**: - `type` (string) - The schema type (e.g., 'object', 'string', 'number'). - `properties` (StandardSchemaV1.Props) - Properties for object types. - `required` (string[]) - List of required properties. - `rules` (object) - Validation rules applicable to the schema type. - `issues` (StandardSchemaV1.Issue[]) - Defined issues for the schema. #### StandardSchemaV1.Props - **Description**: Defines the properties of an object schema. - **Type**: A record where keys are property names and values are `StandardSchemaV1` definitions. #### StandardSchemaV1.Result - **Description**: Represents the result of applying a schema. - **Properties**: - `value` (any) - The validated value. - `errors` (StandardSchemaV1.Issue[]) - Any validation issues found. #### StandardSchemaV1.Issue - **Description**: Represents a single validation issue. - **Properties**: - `message` (string) - The error message. - `path` (string) - The path to the field with the issue. - `ruleId` (string) - The ID of the rule that failed. #### Type Utilities - **InferInput** (type alias): Infers the input type for a given schema `T`. - **InferOutput** (type alias): Infers the output type for a given schema `T`. ### Integration Examples ```typescript import { createStandardSchema } from "@bufbuild/protovalidate-es"; interface UserSchema extends StandardSchemaV1 { type: 'object'; properties: { name: { type: 'string', rules: { min_len: 1 } }; age: { type: 'number', rules: { gt: 0 } }; }; required: ['name', 'age']; } const userSchema: UserSchema = { type: 'object', properties: { name: { type: 'string', rules: { min_len: 1 } }, age: { type: 'number', rules: { gt: 0 } }, }, required: ['name', 'age'], }; const validator = createStandardSchema(userSchema); const result = validator.validate({ name: 'Alice', age: 30 }); console.log(result); ``` ``` -------------------------------- ### Hostname and URI Validation Source: https://github.com/bufbuild/protovalidate-es/blob/main/_autodocs/internal-architecture.md Includes functions for validating hostnames, host:port combinations, email addresses, URIs, and URI references. Useful for string format validation. ```typescript isHostname(): boolean; // Validate hostname ``` ```typescript isHostAndPort(strict?): boolean; // Validate host:port ``` ```typescript isEmail(): boolean; // Validate email ``` ```typescript isUri(): boolean; // Validate URI ``` ```typescript isUriRef(): boolean; // Validate URI reference ``` -------------------------------- ### Create Validators with Different Configurations Source: https://github.com/bufbuild/protovalidate-es/blob/main/_autodocs/usage-examples.md Instantiate validators with specific configurations like `failFast` or `disableNativeRules` to control validation behavior. Choose the appropriate validator based on the use case, such as production, fast checks, or debugging. ```typescript // For production: accumulate all violations const prodValidator = createValidator({ failFast: false }); // For fast checks: stop on first error const gateValidator = createValidator({ failFast: true }); // For debugging: force CEL path const debugValidator = createValidator({ disableNativeRules: true }); // Apply appropriate validator if (isGatingCheck) { return gateValidator.validate(schema, msg); } else { return prodValidator.validate(schema, msg); } ``` -------------------------------- ### CelManager Initialization Source: https://github.com/bufbuild/protovalidate-es/blob/main/_autodocs/internal-architecture.md The CelManager manages the CEL environment, including compilation and evaluation. It registers Protovalidate-specific functions and caches compiled expressions. ```typescript export class CelManager { constructor(registry: Registry, regexMatcher?: RegexMatcher) { // ... implementation } updateCelNow(): void { // ... implementation } // ... other methods } ``` -------------------------------- ### Protobuf string.ipv6_prefix Validation Source: https://github.com/bufbuild/protovalidate-es/blob/main/_autodocs/validation-rules-reference.md Validates if a string field conforms to IPv6 CIDR notation. Default is false (no validation). ```protobuf string subnet = 1 [(buf.validate.field).string.ipv6_prefix = true]; ``` -------------------------------- ### Configuration: Custom Regex Matcher Source: https://github.com/bufbuild/protovalidate-es/blob/main/_autodocs/MANIFEST.txt Allows specifying a custom function for regex matching, providing flexibility beyond standard regex engines. ```typescript const validator = createValidator({ regexMatcher: (pattern, value) => { // Custom regex matching logic return customRegexMatch(pattern, value); }, }); ``` -------------------------------- ### Configure Registry for Custom Extensions Source: https://github.com/bufbuild/protovalidate-es/blob/main/_autodocs/configuration.md Pass a registry containing custom Protobuf extensions when creating a validator to enable custom validation rules. Without this, messages with custom extensions will cause a `RuntimeError`. ```typescript import { createValidator } from "@bufbuild/protovalidate"; import { createRegistry } from "@bufbuild/protobuf"; import { YourCustomExtensionSchema } from "./gen/your_extension_pb"; // Create a registry and add custom types const registry = createRegistry(YourCustomExtensionSchema); // Must pass the registry to access custom rules const validator = createValidator({ registry }); ``` -------------------------------- ### Protobuf string.hostname Validation Source: https://github.com/bufbuild/protovalidate-es/blob/main/_autodocs/validation-rules-reference.md Validates if a string field represents a valid hostname. Default is false (no validation). ```protobuf string host = 1 [(buf.validate.field).string.hostname = true]; ``` -------------------------------- ### Error Handling with Protovalidate ES Source: https://github.com/bufbuild/protovalidate-es/blob/main/_autodocs/README.md Demonstrates how to handle validation results, distinguishing between valid messages, invalid messages with violations, and compilation/runtime errors. ```typescript const result = validator.validate(schema, message); if (result.kind === "valid") { // Process valid message } else if (result.kind === "invalid") { // Handle violations for (const violation of result.violations) { console.log(violation.toString()); } } else { // Handle compilation/runtime error throw result.error; } ``` -------------------------------- ### Use Custom Registry for Extensions Source: https://github.com/bufbuild/protovalidate-es/blob/main/_autodocs/usage-examples.md Validate messages that include custom Protobuf extensions by providing a custom registry during validator creation. Ensure the extension schema is correctly imported. ```typescript import { createRegistry } from "@bufbuild/protobuf"; // Assume MyCustomExtensionSchema is generated from a custom .proto import { MyCustomExtensionSchema } from "./gen/my_custom_pb"; const registry = createRegistry(MyCustomExtensionSchema); const validator = createValidator({ registry }); const result = validator.validate(CustomMessageSchema, message); ``` -------------------------------- ### Define Protobuf Message with Validation Rules Source: https://github.com/bufbuild/protovalidate-es/blob/main/README.md Define a Protobuf message with standard validation rules for fields like UUID, age limits, email format, and maximum string length. Also includes a custom CEL expression for conditional validation. ```protobuf syntax = "proto3"; package acme.user.v1; import "buf/validate/validate.proto"; message User { string id = 1 [(buf.validate.field).string.uuid = true]; uint32 age = 2 [(buf.validate.field).uint32.lte = 150]; // We can only hope. string email = 3 [(buf.validate.field).string.email = true]; string first_name = 4 [(buf.validate.field).string.max_len = 64]; string last_name = 5 [(buf.validate.field).string.max_len = 64]; option (buf.validate.message).cel = { id: "first_name_requires_last_name" message: "last_name must be present if first_name is present" expression: "!has(this.first_name) || has(this.last_name)" }; } ``` -------------------------------- ### Protobuf string.ipv4_prefix Validation Source: https://github.com/bufbuild/protovalidate-es/blob/main/_autodocs/validation-rules-reference.md Validates if a string field conforms to IPv4 CIDR notation. Default is false (no validation). ```protobuf string subnet = 1 [(buf.validate.field).string.ipv4_prefix = true]; ``` -------------------------------- ### Cursor Creation Source: https://github.com/bufbuild/protovalidate-es/blob/main/_autodocs/internal-architecture.md Creates a new Cursor instance to track the field path during validation and accumulate violations. The root message and failFast behavior are configured at creation. ```typescript static create(root: DescMessage, failFast: boolean): Cursor; ``` -------------------------------- ### StandardSchemaV1 Type Utilities Source: https://github.com/bufbuild/protovalidate-es/blob/main/_autodocs/api-reference-standard-schema.md Utility types for inferring schema input and output types within the StandardSchemaV1 namespace. These utilities help in determining the expected data types for schema validation. ```APIDOC ## StandardSchemaV1 Type Utilities Utility types for inferring schema input and output types. ```typescript namespace StandardSchemaV1 { type InferInput = NonNullable["input"]; type InferOutput = NonNullable["output"]; } ``` ### Example: Using Type Utilities ```typescript import { createStandardSchema } from "@bufbuild/protovalidate"; import { UserSchema } from "./gen/user_pb"; const userSchema = createStandardSchema(UserSchema); // Infer the expected input type type ValidateInput = StandardSchemaV1.InferInput; // Infer the validated output type type ValidateOutput = StandardSchemaV1.InferOutput; function processUser(input: ValidateInput): ValidateOutput { const result = userSchema["~standard"].validate(input); if ("value" in result) { return result.value; } throw new Error("Invalid user data"); } ``` ``` -------------------------------- ### Handling Validation Issues Source: https://github.com/bufbuild/protovalidate-es/blob/main/_autodocs/api-reference-standard-schema.md Demonstrates how to iterate through validation issues returned by the validate method and log their path and message. ```typescript const result = userSchema["~standard"].validate(user); if ("issues" in result) { for (const issue of result.issues) { const pathStr = issue.path ? issue.path.join(".") : "(root)"; console.log(`${pathStr}: ${issue.message}`); // Output: "email: value must be a valid email" } } ``` -------------------------------- ### Protobuf Duration Validation Rules Source: https://github.com/bufbuild/protovalidate-es/blob/main/_autodocs/validation-rules-reference.md Demonstrates the use of duration validation rules like const, lt, lte, gt, and gte for google.protobuf.Duration fields. ```protobuf google.protobuf.Duration timeout = 1 [ (buf.validate.field).duration.const = {seconds: 30}, (buf.validate.field).duration.lt = {seconds: 300}, (buf.validate.field).duration.lte = {seconds: 300}, (buf.validate.field).duration.gt = {seconds: 0}, (buf.validate.field).duration.gte = {seconds: 1} ]; ``` -------------------------------- ### Define Protobuf Message with Validation Rules Source: https://github.com/bufbuild/protovalidate-es/blob/main/packages/protovalidate/README.md Annotate Protobuf messages with standard validation rules like UUID checks and custom CEL expressions for complex logic. ```protobuf syntax = "proto3"; package banking.v1; import "buf/validate/validate.proto"; message MoneyTransfer { string to_account_id = 1 [ // Standard rule: `to_account_id` must be a UUID. (buf.validate.field).string.uuid = true ]; string from_account_id = 2 [ // Standard rule: `from_account_id` must be a UUID. (buf.validate.field).string.uuid = true ]; // Custom rule: `to_account_id` and `from_account_id` can't be the same. option (buf.validate.message).cel = { id: "to_account_id.not.from_account_id" message: "to_account_id and from_account_id should not be the same value" expression: "this.to_account_id != this.from_account_id" }; } ``` -------------------------------- ### Protobuf Timestamp Validation Rules Source: https://github.com/bufbuild/protovalidate-es/blob/main/_autodocs/validation-rules-reference.md Illustrates timestamp validation rules including const, lt, lte, gt, and gte for google.protobuf.Timestamp fields. ```protobuf google.protobuf.Timestamp created_at = 1 [ (buf.validate.field).timestamp.const = {seconds: 1234567890}, (buf.validate.field).timestamp.lt = {seconds: 1609459200}, (buf.validate.field).timestamp.lte = {seconds: 1609459200}, (buf.validate.field).timestamp.gt = {seconds: 0}, (buf.validate.field).timestamp.gte = {seconds: 1000000000} ]; ``` -------------------------------- ### Planner Interface Source: https://github.com/bufbuild/protovalidate-es/blob/main/_autodocs/internal-architecture.md The Planner is responsible for compiling validation rules into executable evaluation plans. It memoizes plans by message descriptor to avoid recompilation. ```typescript export class Planner { // ... plan(message: DescMessage): Eval { // ... implementation } // ... } ``` -------------------------------- ### Configuration: Legacy Required Behavior Source: https://github.com/bufbuild/protovalidate-es/blob/main/_autodocs/MANIFEST.txt Enables legacy behavior for the 'required' rule, which might be necessary for maintaining compatibility with older versions or specific requirements. ```typescript const validator = createValidator({ legacyRequired: true, }); ``` -------------------------------- ### Configuration: Registry Source: https://github.com/bufbuild/protovalidate-es/blob/main/_autodocs/MANIFEST.txt Enables the use of custom functions and types within validation rules by providing a registry. This is essential for extending validation logic. ```typescript const validator = createValidator({ registry: { // Register custom functions or types here }, }); ``` -------------------------------- ### StandardSchemaV1 Type Utilities Source: https://github.com/bufbuild/protovalidate-es/blob/main/_autodocs/api-reference-standard-schema.md Provides utility types for inferring the input and output types of a schema. ```typescript namespace StandardSchemaV1 { type InferInput = NonNullable["input"]; type InferOutput = NonNullable["output"]; } ``` -------------------------------- ### createStandardSchema() Source: https://github.com/bufbuild/protovalidate-es/blob/main/_autodocs/MANIFEST.txt Creates a standard schema object that can be used for validation, providing a type-safe way to define validation rules. ```APIDOC ## createStandardSchema() ### Description Creates a standard schema object for validation. ### Signature createStandardSchema(props: StandardSchemaV1.Props) ### Parameters #### Props - **props** (StandardSchemaV1.Props) - Required - An object defining the schema properties and their validation rules. - **properties** (Record) - Optional - Nested schema properties. - **items** (StandardSchemaV1) - Optional - Schema for items in a collection. - **type** (string) - Optional - The data type of the property (e.g., 'string', 'number', 'boolean'). - **format** (string) - Optional - Specific format for the type (e.g., 'email', 'uuid'). - **rules** (Array) - Optional - An array of validation rules to apply. - **required** (boolean) - Optional - Indicates if the field is required. - **cel** (string) - Optional - A CEL expression for custom validation. ### Returns - **StandardSchemaV1** - A standard schema object. ``` -------------------------------- ### createValidator() Source: https://github.com/bufbuild/protovalidate-es/blob/main/_autodocs/api-reference-validator.md Creates a new validator instance with optional configuration. The validator object has a `validate()` method for checking messages. ```APIDOC ## createValidator() ### Description Create a new validator instance with optional configuration. ### Signature ```typescript function createValidator(opt?: ValidatorOptions): Validator ``` ### Parameters #### opt - **opt** (`ValidatorOptions`) - Optional - Configuration options for the validator. ### Returns A `Validator` object with a `validate()` method. ### ValidatorOptions Configuration #### registry - **registry** (`Registry`) - Optional - A Protobuf message registry for custom extensions and types. Used to unpack `google.protobuf.Any` messages in CEL expressions. #### failFast - **failFast** (`boolean`) - Optional - When true, validation stops at the first rule violation. When false, all violations are accumulated and returned together. #### regexMatch - **regexMatch** (`RegexMatcher`) - Optional - Custom regex engine implementation. Use for full RE2 compliance or to guard against ReDoS attacks. Function signature: `(pattern: string, against: string) => boolean` #### legacyRequired - **legacyRequired** (`boolean`) - Optional - When true, proto2 fields with the `required` label and fields with the edition feature `field_presence=LEGACY_REQUIRED` are validated to be set. #### disableNativeRules - **disableNativeRules** (`boolean`) - Optional - When true, forces all standard buf.validate.field rules through the CEL evaluator instead of using optimized native implementations. ### Example ```typescript import { createValidator } from "@bufbuild/protovalidate"; import { createRegistry } from "@bufbuild/protobuf"; // Basic validator with default settings const validator = createValidator(); // Validator with custom registry const registry = createRegistry(); const validator = createValidator({ registry }); // Validator that stops on first error const validator = createValidator({ failFast: true }); // Validator with custom regex engine const validator = createValidator({ regexMatch: (pattern: string, against: string): boolean => { // Custom RE2 implementation return new RE2(pattern).test(against); }, }); ``` ```