CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-pbf

A low-level, lightweight protocol buffers implementation for JavaScript with high-performance binary serialization and deserialization capabilities.

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

schema-compilation.mddocs/

Schema Compilation

Compile protocol buffer schema files (.proto) into optimized JavaScript read/write functions. The compilation system generates highly optimized code for encoding and decoding specific protobuf schemas.

Compilation Functions

Runtime Compilation

Compile a parsed protocol buffer schema into executable functions:

/**
 * Compile a protobuf schema into read/write functions
 * @param proto - Parsed protobuf schema object
 * @returns Object containing generated read and write functions
 */
function compile(proto: object): Record<string, Function>;

Code Generation

Generate raw JavaScript/TypeScript code from a protobuf schema:

interface CompileOptions {
    dev?: boolean;        // Include development features and comments
    legacy?: boolean;     // Generate CommonJS instead of ESM
    noRead?: boolean;     // Skip generating read functions
    noWrite?: boolean;    // Skip generating write functions
}

/**
 * Compile a protobuf schema into raw JavaScript code
 * @param proto - Parsed protobuf schema object
 * @param options - Compilation options
 * @returns Generated JavaScript code as string
 */
function compileRaw(proto: object, options?: CompileOptions): string;

Schema Input Format

The compilation functions expect a parsed protobuf schema object (typically from resolve-protobuf-schema):

interface ProtoSchema {
    name?: string;
    syntax?: number;       // Protocol buffer version (2 or 3)
    fields?: ProtoField[];
    messages?: ProtoSchema[];
    enums?: ProtoEnum[];
    extensions?: any;
}

interface ProtoField {
    name: string;
    type: string;
    tag: number;
    repeated?: boolean;
    required?: boolean;
    optional?: boolean;
    oneof?: string;
    map?: {
        from: string;      // Key type
        to: string;        // Value type
    };
    options?: {
        packed?: string;   // "true" or "false"
        default?: string;
        jstype?: string;   // "JS_STRING" for string representation
    };
}

interface ProtoEnum {
    name: string;
    values: Record<string, { value: number }>;
}

Generated Function Pattern

For each message type in the schema, the compiler generates corresponding read and write functions:

// Generated read function signature
type ReadFunction<T> = (pbf: Pbf, end?: number) => T;

// Generated write function signature  
type WriteFunction<T> = (obj: T, pbf: Pbf) => void;

// Example generated functions for a "Person" message
interface GeneratedFunctions {
    readPerson: ReadFunction<Person>;
    writePerson: WriteFunction<Person>;
}

Usage Examples

Basic Schema Compilation

import { compile } from "pbf/compile";
import schema from "protocol-buffers-schema";
import fs from "fs";

// Parse .proto file
const proto = schema.parse(fs.readFileSync("person.proto"));

// Compile to functions
const { readPerson, writePerson } = compile(proto);

// Use generated functions
const person = readPerson(new Pbf(buffer));
const pbf = new Pbf();
writePerson(person, pbf);
const encoded = pbf.finish();

Code Generation

import { compileRaw } from "pbf/compile";
import schema from "protocol-buffers-schema";
import fs from "fs";

// Parse .proto file
const proto = schema.parse(fs.readFileSync("person.proto"));

// Generate JavaScript code
const jsCode = compileRaw(proto);

// Write to file
fs.writeFileSync("person.js", jsCode);

Compilation Options

import { compileRaw } from "pbf/compile";

// Generate CommonJS module with only write functions
const code = compileRaw(proto, {
    legacy: true,      // Use CommonJS exports
    noRead: true,      // Skip read functions
    dev: false         // Production mode
});

// Generate ESM module with development features
const devCode = compileRaw(proto, {
    legacy: false,     // Use ESM exports
    dev: true          // Include comments and debug info
});

Working with Complex Types

// Schema with nested messages and enums
const proto = {
    name: "AddressBook",
    fields: [
        { name: "people", type: "Person", tag: 1, repeated: true }
    ],
    messages: [
        {
            name: "Person",
            fields: [
                { name: "name", type: "string", tag: 1 },
                { name: "id", type: "int32", tag: 2 },
                { name: "email", type: "string", tag: 3 },
                { name: "phones", type: "PhoneNumber", tag: 4, repeated: true },
                { name: "type", type: "PhoneType", tag: 5 }
            ]
        },
        {
            name: "PhoneNumber", 
            fields: [
                { name: "number", type: "string", tag: 1 },
                { name: "type", type: "PhoneType", tag: 2 }
            ]
        }
    ],
    enums: [
        {
            name: "PhoneType",
            values: {
                MOBILE: { value: 0 },
                HOME: { value: 1 },
                WORK: { value: 2 }
            }
        }
    ]
};

const { readAddressBook, writeAddressBook, readPerson, writePerson, PhoneType } = compile(proto);

Map Field Support

// Schema with map fields
const proto = {
    name: "MapExample",
    fields: [
        { 
            name: "attributes", 
            type: "map",
            tag: 1,
            map: { from: "string", to: "string" }
        },
        {
            name: "counters",
            type: "map", 
            tag: 2,
            map: { from: "string", to: "int32" }
        }
    ]
};

const { readMapExample, writeMapExample } = compile(proto);

// Usage
const data = {
    attributes: { "color": "red", "size": "large" },
    counters: { "views": 100, "likes": 25 }
};

Packed Fields and Proto3

// Proto3 schema with packed repeated fields
const proto = {
    name: "PackedExample",
    syntax: 3,  // Proto3
    fields: [
        { 
            name: "numbers", 
            type: "int32", 
            tag: 1, 
            repeated: true,
            options: { packed: "true" }
        },
        {
            name: "flags",
            type: "bool",
            tag: 2,
            repeated: true,
            options: { packed: "true" }
        }
    ]
};

const { readPackedExample, writePackedExample } = compile(proto);

OneOf Fields

// Schema with oneof fields
const proto = {
    name: "OneOfExample",
    fields: [
        { name: "name", type: "string", tag: 1 },
        { name: "email", type: "string", tag: 2, oneof: "contact" },
        { name: "phone", type: "string", tag: 3, oneof: "contact" }
    ]
};

const { readOneOfExample, writeOneOfExample } = compile(proto);

// Usage - only one field in the oneof group will be set
const data1 = { name: "John", email: "john@example.com", contact: "email" };
const data2 = { name: "Jane", phone: "555-1234", contact: "phone" };

Error Handling

The compilation functions may throw errors for invalid schemas:

try {
    const functions = compile(proto);
} catch (error) {
    // Handle compilation errors:
    // - "Unexpected type: [type]" for unsupported types
    // - Schema validation errors
    // - Missing field type definitions
    console.error("Compilation failed:", error.message);
}

Install with Tessl CLI

npx tessl i tessl/npm-pbf

docs

buffer-operations.md

cli-tool.md

index.md

schema-compilation.md

tile.json