Protocol Buffers for JavaScript with TypeScript support, providing pure JavaScript implementation for serializing and deserializing structured data using Google's Protocol Buffer format.
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
High-performance binary serialization and deserialization with full type safety, validation, and conversion capabilities for protobuf messages.
Base message class providing static methods for all serialization operations and instance methods for message manipulation.
class Message<T extends object = object> {
/**
* Message type reference
*/
$type: Type;
/**
* Creates message instance from properties
* @param properties - Message properties
* @returns Message instance
*/
static create<T extends Message<T>>(this: Constructor<T>, properties?: { [k: string]: any }): T;
/**
* Encodes message to writer
* @param message - Message instance or plain object
* @param writer - Writer to encode to, creates new if omitted
* @returns Writer with encoded data
*/
static encode<T extends Message<T>>(this: Constructor<T>, message: T | { [k: string]: any }, writer?: Writer): Writer;
/**
* Encodes message with length delimiter
* @param message - Message instance or plain object
* @param writer - Writer to encode to, creates new if omitted
* @returns Writer with encoded data
*/
static encodeDelimited<T extends Message<T>>(this: Constructor<T>, message: T | { [k: string]: any }, writer?: Writer): Writer;
/**
* Decodes message from reader or buffer
* @param reader - Reader or buffer to decode from
* @param length - Message length if known
* @returns Decoded message instance
*/
static decode<T extends Message<T>>(this: Constructor<T>, reader: Reader | Uint8Array, length?: number): T;
/**
* Decodes length-delimited message
* @param reader - Reader or buffer to decode from
* @returns Decoded message instance
*/
static decodeDelimited<T extends Message<T>>(this: Constructor<T>, reader: Reader | Uint8Array): T;
/**
* Verifies message properties
* @param message - Message properties to verify
* @returns Error message or null if valid
*/
static verify(message: { [k: string]: any }): string | null;
/**
* Creates message from plain object
* @param object - Plain object to convert
* @returns Message instance
*/
static fromObject<T extends Message<T>>(this: Constructor<T>, object: { [k: string]: any }): T;
/**
* Converts message to plain object
* @param message - Message instance to convert
* @param options - Conversion options
* @returns Plain object representation
*/
static toObject<T extends Message<T>>(message: T, options?: IConversionOptions): { [k: string]: any };
/**
* Converts message to JSON representation
* @returns JSON object
*/
toJSON(): { [k: string]: any };
/**
* Checks if message equals another message
* @param message - Message to compare with
* @returns True if messages are equal
*/
equals(message: Message): boolean;
}Usage Examples:
const protobuf = require("protobufjs");
// Load schema and get message type
protobuf.load("schema.proto", function(err, root) {
const User = root.lookupType("User");
// Create message
const user = User.create({
id: 123,
name: "John Doe",
email: "john@example.com"
});
// Encode to binary
const buffer = User.encode(user).finish();
console.log("Encoded size:", buffer.length);
// Decode from binary
const decoded = User.decode(buffer);
console.log("Decoded:", decoded);
// Verify message structure
const errorMsg = User.verify({
id: "invalid", // Should be number
name: "Valid Name"
});
if (errorMsg) console.log("Validation error:", errorMsg);
});Operations available on Type instances for message manipulation.
class Type extends Namespace {
/**
* Creates message instance with type validation
* @param properties - Message properties
* @returns Message instance
*/
create(properties?: { [k: string]: any }): Message;
/**
* Encodes message with type information
* @param message - Message to encode
* @param writer - Optional writer
* @returns Writer with encoded data
*/
encode(message: Message | { [k: string]: any }, writer?: Writer): Writer;
/**
* Encodes message with length delimiter
* @param message - Message to encode
* @param writer - Optional writer
* @returns Writer with encoded data
*/
encodeDelimited(message: Message | { [k: string]: any }, writer?: Writer): Writer;
/**
* Decodes message using type schema
* @param reader - Reader or buffer
* @param length - Optional message length
* @returns Decoded message
*/
decode(reader: Reader | Uint8Array, length?: number): Message;
/**
* Decodes length-delimited message
* @param reader - Reader or buffer
* @returns Decoded message
*/
decodeDelimited(reader: Reader | Uint8Array): Message;
/**
* Verifies message against type schema
* @param message - Message to verify
* @returns Error message or null
*/
verify(message: { [k: string]: any }): string | null;
/**
* Creates message from plain object with type conversion
* @param object - Plain object
* @returns Message instance
*/
fromObject(object: { [k: string]: any }): Message;
/**
* Converts message to plain object with type information
* @param message - Message to convert
* @param options - Conversion options
* @returns Plain object
*/
toObject(message: Message, options?: IConversionOptions): { [k: string]: any };
}Usage Examples:
// Using Type methods directly
const MessageType = root.lookupType("package.Message");
// Create and encode
const message = MessageType.create({ field1: "value", field2: 42 });
const encoded = MessageType.encode(message).finish();
// Decode and verify
const decoded = MessageType.decode(encoded);
const valid = MessageType.verify(decoded);
if (valid === null) {
console.log("Message is valid");
}
// Object conversion
const plainObject = MessageType.toObject(message, {
longs: String,
enums: String,
bytes: String
});Configuration options for controlling serialization behavior and data type representation.
interface IConversionOptions {
/**
* Long number representation
* - String: Convert to string representation
* - Number: Convert to JavaScript number (may lose precision)
* - Long: Keep as Long object
*/
longs?: typeof String | typeof Number | typeof Long;
/**
* Enum value representation
* - String: Use enum names
* - Number: Use enum numeric values
*/
enums?: typeof String | typeof Number;
/**
* Byte array representation
* - Array: Convert to number array
* - String: Convert to base64 string
* - Uint8Array: Keep as Uint8Array
*/
bytes?: typeof Array | typeof String | typeof Uint8Array;
/**
* Whether to include default values
*/
defaults?: boolean;
/**
* Whether to include empty arrays
*/
arrays?: boolean;
/**
* Whether to include empty objects
*/
objects?: boolean;
/**
* Whether to include oneof properties that aren't set
*/
oneofs?: boolean;
}Usage Examples:
const message = MessageType.create({
id: Long.fromNumber(123456789012345),
status: StatusEnum.values.ACTIVE,
data: new Uint8Array([1, 2, 3, 4])
});
// Convert with different options
const jsonFriendly = MessageType.toObject(message, {
longs: String, // "123456789012345"
enums: String, // "ACTIVE"
bytes: String, // base64 encoded
defaults: true // include default values
});
const numeric = MessageType.toObject(message, {
longs: Number, // 123456789012345 (may lose precision)
enums: Number, // 1
bytes: Array // [1, 2, 3, 4]
});Message validation capabilities for ensuring data integrity and type safety.
/**
* Validates message properties against schema
* @param message - Message properties to validate
* @returns Error message string or null if valid
*/
function verify(message: { [k: string]: any }): string | null;
// Validation error types
interface ValidationErrors {
missingField: string; // "missing required field"
invalidType: string; // "invalid type for field"
outOfRange: string; // "value out of range"
invalidEnum: string; // "invalid enum value"
invalidOneOf: string; // "multiple oneof fields set"
}Usage Examples:
// Validate before encoding
const messageData = {
id: "not-a-number", // Invalid type
name: "", // Empty string
age: -5 // Invalid value
};
const error = MessageType.verify(messageData);
if (error) {
console.log("Validation failed:", error);
// Handle validation error
} else {
// Safe to create and encode
const message = MessageType.create(messageData);
const encoded = MessageType.encode(message).finish();
}
// Validate after decoding
const decoded = MessageType.decode(someBuffer);
const valid = MessageType.verify(decoded);
if (valid !== null) {
console.warn("Decoded message validation warning:", valid);
}Low-level binary format operations for custom serialization needs.
/**
* Finishes writer operations and returns encoded buffer
* @returns Encoded binary data
*/
Writer.prototype.finish(): Uint8Array;
/**
* Gets current writer length
* @returns Number of bytes written
*/
Writer.prototype.len: number;
/**
* Creates reader from binary data
* @param buffer - Binary data to read
* @returns Reader instance
*/
Reader.create(buffer: Uint8Array): Reader;
/**
* Current reader position
*/
Reader.prototype.pos: number;
/**
* Total buffer length
*/
Reader.prototype.len: number;Usage Examples:
// Custom encoding with length tracking
const writer = protobuf.Writer.create();
const message1 = Type1.encode(data1, writer);
const pos1 = writer.len;
const message2 = Type2.encode(data2, writer);
const pos2 = writer.len;
const buffer = writer.finish();
console.log(`Total size: ${buffer.length}, Message1: ${pos1}, Message2: ${pos2 - pos1}`);
// Custom decoding with position tracking
const reader = protobuf.Reader.create(buffer);
const decoded1 = Type1.decode(reader, pos1);
const decoded2 = Type2.decode(reader);
console.log(`Reader position: ${reader.pos}/${reader.len}`);Common error conditions and handling patterns in serialization operations.
interface SerializationError extends Error {
name: string; // Error type
message: string; // Error description
path?: string; // Field path that caused error
instance?: any; // Problematic value
}
// Common error types
interface ErrorTypes {
TypeError: "invalid type";
RangeError: "value out of range";
Error: "general serialization error";
}Usage Examples:
try {
// Encoding errors
const message = MessageType.create({
requiredField: null, // Missing required field
enumField: 999 // Invalid enum value
});
const encoded = MessageType.encode(message).finish();
} catch (err) {
console.error("Encoding error:", err.message);
if (err.path) console.error("Field path:", err.path);
}
try {
// Decoding errors
const corrupted = new Uint8Array([0xFF, 0xFF, 0xFF]);
const decoded = MessageType.decode(corrupted);
} catch (err) {
console.error("Decoding error:", err.message);
}interface Constructor<T> extends Function {
new (...args: any[]): T;
}
interface IConversionOptions {
longs?: typeof String | typeof Number | typeof Long;
enums?: typeof String | typeof Number;
bytes?: typeof Array | typeof String | typeof Uint8Array;
defaults?: boolean;
arrays?: boolean;
objects?: boolean;
oneofs?: boolean;
}
interface Long {
low: number;
high: number;
unsigned: boolean;
toNumber(): number;
toString(): string;
equals(other: Long): boolean;
static fromNumber(value: number): Long;
static fromString(value: string): Long;
}Install with Tessl CLI
npx tessl i tessl/npm-protobufjs