Protobuf-ES

repository·main·Indexed 23 days ago

https://github.com/bufbuild/protobuf-es

A modern implementation of Protocol Buffers for JavaScript and TypeScript. It provides an ESM-first runtime (@bufbuild/protobuf) and a code generator (protoc-gen-es) that supports Node.js, Deno, Bun, and web browsers. Key features include strict adherence to the Protobuf specification, support for proto2 and proto3, and significantly smaller bundle sizes compared to google-protobuf.

Tokens
41.8K
Snippets
100
Records
269
Agent score
82%

What's inside protobuf-es

  1. Overview of @bufbuild/protobuf

    main

    Protobuf-ES is a complete implementation of Protocol Buffers in TypeScript designed for modern JavaScript environments including web browsers, Node.js, Deno, and Bun. It serves as the runtime library for the protoc-gen-es code generator.

    Key features include:

    • Modern Ecosystem Support: Full ECMAScript module (ESM) support and first-class TypeScript support.
    • Idiomatic Code: Generates idiomatic JavaScript and TypeScript code with much smaller bundle sizes compared to other implementations.
    • Feature Completeness: Implements all proto3 features (including canonical JSON format) and all proto2 features (including extensions and text format).
    • Standard APIs: Uses standard JavaScript APIs instead of the Closure Library.
    • Advanced Capabilities: Provides descriptor and reflection support and is verified by Protocol Buffers conformance tests.
  2. Write Protobuf plugins in TypeScript with @bufbuild/protoplugin

    main

    Protobuf-ES allows you to write standard Protobuf plugins using TypeScript. The @bufbuild/protoplugin package manages the plugin protocol (reading schema data from stdin and writing to stdout) and provides helpers for generating JavaScript and TypeScript code from schemas.

    Plugins follow the protoc-gen-x naming convention and are implemented as executables.

  3. Compare code size between Protobuf-ES and google-protobuf

    main

    Protobuf-ES provides a code size comparison against google-protobuf (via protoc-gen-js). The comparison is performed by generating code for a specific module, bundling it with esbuild, minifying the bundle, and compressing it.

    As the number of generated files increases, Protobuf-ES demonstrates significantly smaller bundle sizes (both minified and compressed) compared to protobuf-javascript.

  4. Understand the Protobuf-ES reference structure

    main

    The Protobuf-ES reference documentation is organized into several key areas to help you use the library effectively:

    • Code generation: Details on the shape of generated code (messages, enums, services), field type mappings, and available plugin options.
    • Runtime: Guidance on working with messages (creation, cloning, equality), serialization (binary and JSON), extensions, reflection, descriptors, registries, and well-known types.
    • Plugin authors: Instructions for writing, generating files for, and releasing custom plugins.
    • Type helpers: Information on specialized JSON types and experimental 'Valid' types for field guarantees.
    • Migration and troubleshooting: Resources for migrating from v1 and an FAQ for common issues like 64-bit integers and resolver problems.

    For end-to-end workflows, it is recommended to start with the Getting started guide.

  5. Create custom code generator plugins with @bufbuild/protoplugin

    main

    The @bufbuild/protoplugin package provides a framework for writing custom code generator plugins that are compatible with the Protobuf-ES ecosystem. These plugins can be used with both buf and protoc compilers to generate tailored TypeScript or JavaScript code from Protobuf schemas.

    When building a plugin, you have three primary strategies for handling output files:

    1. Full Control: Write your own generators for TypeScript, JavaScript, and declaration files.
    2. Automatic JS/DTS Generation: Generate only TypeScript files and let the framework automatically produce JavaScript and declaration files using its internal TypeScript compiler.
    3. Custom TypeScript Compiler: Generate only TypeScript files but provide your own TypeScript compiler to handle the generation of JavaScript and declaration files, allowing you to use specific TypeScript versions or compiler options.
  6. Explore Protobuf-ES usage patterns and examples

    main

    Protobuf-ES supports advanced use cases beyond simple message handling. You can explore the following patterns and runnable examples to understand how to implement complex logic:

    Advanced Patterns

    • Any with registries: Learn how to pack messages into google.protobuf.Any and unpack them using a registry when the specific type information is not directly available.
    • Custom option redaction: Learn how to define field options and use reflection to identify and clear annotated fields.

    Runnable Examples

    • Node message store: A Node.js application demonstrating how to write multiple Protobuf messages to a binary file and read them back as a stream (based on packages/protobuf-example).
    • Twirp plugin: A custom plugin implementation that generates TypeScript clients from Protobuf service definitions (based on packages/protoplugin-example).

    If you have not yet generated code, start with the Getting started guide.

  7. Naming conventions for generated fields and types

    main

    Protobuf-ES follows specific naming conventions to ensure compatibility with TypeScript and ECMAScript:

    • Field Names: Uses standard lower-camel case JSON conversion (e.g., snake_case becomes snakeCase). If a name conflicts with a reserved ECMAScript keyword or a built-in property, a $ is appended to the name.
    • Nested Types: Nested message and enum names are joined with underscores (e.g., User.Type becomes User_Type).
    • Packages: Package declarations are mostly ignored in generated identifiers to accommodate ECMAScript's lack of Protobuf-style namespaces, though they remain visible in descriptors and fully qualified names.
  8. Understand Protobuf-ES Descriptors

    main

    Descriptors are the schema model for Protobuf. While the Protobuf compiler parses .proto files into google.protobuf.*DescriptorProto messages, Protobuf-ES wraps these in more ergonomic types. Descriptors form a hierarchy rooted at a file descriptor (DescFile).

    Descriptor Hierarchy:

    • DescFile (Root)
      • messages: DescMessage[]
        • fields: DescField[]
        • oneofs: DescOneof[]
        • nestedMessages: DescMessage[]
        • nestedExtensions: DescExtension[]
        • nestedEnums: DescEnum[]
      • enums: DescEnum[]
      • extensions: DescExtension[]
      • services: DescService[]
  9. Core pieces of Protobuf-ES Reflection

    main

    The Reflection API is composed of several key abstractions:

    • Descriptors: Schema objects representing the structure of your Protobuf definitions, such as DescFile, DescMessage, DescField, DescEnum, and DescService.
    • Registries: Collections of descriptors that are keyed by their fully qualified names.
    • Custom options: Annotations on schema elements that are backed by extensions.
    • Dynamic messages: Tools for interacting with messages at runtime, including reflect(), ReflectMessage, ReflectList, and ReflectMap.