npm package: @protobuf-x/runtime
Description: High-performance Protocol Buffers runtime for TypeScript & JavaScript. Zero dependencies, native bigint, faster and smaller than protobufjs.
Author: vinikjkkj
Latest version: 0.1.1

# @protobuf-x/runtime

> High-performance Protocol Buffers runtime for TypeScript & JavaScript. Zero dependencies.

The runtime library that powers code generated by [`@protobuf-x/codegen`](https://www.npmjs.com/package/@protobuf-x/codegen).

- 🚀 **Faster** than `protobufjs` on encode, decode, create, JSON, clone, and equals
- 📦 **Smallest** runtime — minimal entry point is **3.4 KB brotli** (vs 6.2 KB for protobufjs minimal)
- ✅ **Zero dependencies** — pure TypeScript, runs anywhere
- 🌐 **Universal** — Node.js, Deno, Bun, browsers, Cloudflare Workers, etc.
- 🔒 **Type-safe** — full TypeScript types with native `bigint` (no `Long` wrapper)

## Installation

```bash
npm install @protobuf-x/runtime
npm install -D @protobuf-x/codegen
```

You'll typically use this together with [`@protobuf-x/codegen`](https://www.npmjs.com/package/@protobuf-x/codegen) which generates code that imports from this package.

## Quick start

```ts
// schema_pb.ts is generated from schema.proto by @protobuf-x/codegen
import { User } from './gen/schema_pb.js'

// Construct
const alice = new User({ name: 'Alice', age: 30 })

// Encode
const bytes: Uint8Array = alice.toBinary()

// Decode
const decoded = User.decode(bytes)
console.log(decoded.name) // 'Alice'

// JSON
const json = User.toJSON(alice)
const back = User.fromJSON(json)
```

## Two entry points

### Full (`@protobuf-x/runtime`) — 7.4 KB brotli

Includes everything: encode/decode, JSON, clone, equals, merge, streaming,
services, extensions, well-known types, validation, freeze, patch, diff.

```ts
import {
    Message,
    BinaryReader,
    BinaryWriter,
    encodeDelimited,
    decodeStream,
    ServiceClient,
    wellKnownToJSON
} from '@protobuf-x/runtime'
```

### Minimal (`@protobuf-x/runtime/minimal`) — 3.4 KB brotli

Encode/decode only. Use this for apps that just need binary serialization
(RPC, message queues, storage, edge workers).

```ts
import { Message, BinaryReader, BinaryWriter } from '@protobuf-x/runtime/minimal'
```

When you generate code with `protobuf-x --runtime-package @protobuf-x/runtime/minimal`,
the codegen automatically skips generating `toJSON`/`fromJSON` methods + JSON
interfaces (they're not needed at runtime), shrinking your bundle even further.

## Performance

Benchmarks on `bench.proto` with 4 messages (Small/Address/Medium/Large), Node.js 25:

| Operation     |      protobuf-x | protobufjs | Ratio |
| ------------- | --------------: | ---------: | ----: |
| Encode small  |  **9.0M ops/s** |       5.3M | 1.71x |
| Encode medium |  **1.7M ops/s** |       1.2M | 1.43x |
| Decode small  | **10.6M ops/s** |       8.8M | 1.21x |
| Decode medium |  **1.7M ops/s** |       1.6M | 1.04x |
| Create small  |   **27M ops/s** |        12M | 2.16x |
| toJSON small  |  **150M ops/s** |        41M | 3.68x |
| Clone medium  |  **833K ops/s** |       500K | 1.65x |

See the [main repo](https://github.com/vinikjkkj/protobuf-x) for full benchmark results.

## Bundle size

| Library                         | Brotli (min) |
| ------------------------------- | -----------: |
| **@protobuf-x/runtime/minimal** |   **3.4 KB** |
| protobufjs minimal              |       6.2 KB |
| **@protobuf-x/runtime**         |   **7.4 KB** |
| protobufjs full                 |      21.6 KB |

## Architecture highlights

### Two-pass encode

The two-pass approach (`sizeOf` + `encodeTo`) lets us allocate an exact-size
buffer up front and write sequentially with **zero grow checks** — much faster
than the growable-buffer approach used by `protobufjs` and `@bufbuild/protobuf`.

### Inlined varint codec

Both encode and decode varints are fully inlined — no function calls per byte,
no tuple allocations. The generated code uses these primitives directly.

### Native Buffer fast paths on Node.js

When running on Node.js, strings use `Buffer.utf8Slice` / `Buffer.utf8Write`
which are 3-5x faster than `TextEncoder` / `TextDecoder`. The reader lazily
wraps `Uint8Array` inputs as `Buffer` on the first string read, so payloads
without strings pay nothing for the wrapping.

### Native bigint

64-bit integers use the native `bigint` type — no `Long` polyfill, no
precision loss for large values, smaller bundle.

## API surface (full runtime)

```ts
// Binary
import { BinaryReader, BinaryWriter, WireType } from '@protobuf-x/runtime'

// Encode helpers (used by generated code)
import {
    varint32Size,
    varint64Size,
    int32Size,
    strByteLen,
    writeVarint,
    writeVarint64,
    writeInt32,
    writeSint32,
    writeFixed32,
    writeFixed64,
    writeBool,
    writeBytes,
    writeDouble,
    writeFloat,
    allocBuf,
    finalizeBuf
} from '@protobuf-x/runtime'

// Message base
import { Message, type MessageType } from '@protobuf-x/runtime'

// Type system
import {
    ScalarType,
    FieldRule,
    type FieldDescriptor,
    type MessageDescriptor,
    type EnumDescriptor
} from '@protobuf-x/runtime'

// Streaming
import { encodeDelimited, decodeStream, frame, Deframer } from '@protobuf-x/runtime'

// JSON
import { toJSON, fromJSON, wellKnownToJSON, wellKnownFromJSON } from '@protobuf-x/runtime'

// Utilities
import { equals, clone, merge, diff, patch, freeze, validate } from '@protobuf-x/runtime'

// Services
import { ServiceClient, type Transport } from '@protobuf-x/runtime'

// Pools
import { BufferPool, ObjectPool } from '@protobuf-x/runtime'
```

## Compatibility

- **Wire format**: 100% compatible with `protoc`, `protobufjs`, `@bufbuild/protobuf`,
  Google's reference implementations, and any other compliant protobuf library.
- **Node.js**: 18+
- **Browsers**: ES2022+ (Chrome 94+, Firefox 93+, Safari 16.4+)
- **Runtimes**: Deno, Bun, Cloudflare Workers, Vercel Edge, Netlify Edge

## License

MIT