CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-google-protobuf

Protocol Buffers JavaScript runtime library for serializing structured data

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

map-operations.mddocs/

Map Operations

The jspb.Map class provides an ES6 Map-like container specifically designed for Protocol Buffer map fields. It handles key-value pairs with automatic synchronization between JavaScript Map operations and the underlying Protocol Buffer array representation.

Core Map Class { .api }

const { Map } = require('google-protobuf');

// Create empty map
const map = new Map();

// Create map from existing array data
const existingData = [["key1", "value1"], ["key2", "value2"]];
const mapFromArray = new Map(existingData);

// Create map with value constructor (for message values)
const messageMap = new Map([], MessageConstructor);

// Basic properties
const isClean = map.arrClean; // Whether underlying array is synchronized

Type Definitions:

/**
 * @constructor
 * @param {Array=} arr Optional initial array of [key, value] pairs
 * @param {Function=} opt_valueCtor Optional constructor for map values
 */

/**
 * ES6 Map-like container for Protocol Buffer map fields
 */

Basic Map Operations { .api }

const { Map } = require('google-protobuf');

const map = new Map();

// Set key-value pairs
map.set("name", "John Doe");
map.set("age", "25");
map.set("active", "true");

// Get values by key
const name = map.get("name");        // "John Doe"
const age = map.get("age");          // "25" 
const missing = map.get("missing");  // undefined

// Check if key exists
const hasName = map.has("name");     // true
const hasEmail = map.has("email");   // false

// Delete entries
const wasDeleted = map.del("age");   // true (returns boolean)
const notDeleted = map.del("missing"); // false

// Get map size
const size = map.getLength();        // 2 (name and active remain)

// Clear all entries
map.clear();
console.log(map.getLength());       // 0

Type Definitions:

/**
 * @param {string} key Map key
 * @param {*} value Map value
 * @return {!Map} This map instance for chaining
 */

/**
 * @param {string} key Map key
 * @return {*} Value for key or undefined
 */

Iteration Methods { .api }

const { Map } = require('google-protobuf');

const userMap = new Map();
userMap.set("john", "John Doe");
userMap.set("jane", "Jane Smith");  
userMap.set("bob", "Bob Johnson");

// Iterate over entries (key-value pairs)
for (const [key, value] of map.entries()) {
  console.log(`${key}: ${value}`);
}

// Iterate over keys only
for (const key of map.keys()) {
  console.log(`Key: ${key}`);
}

// Iterate over values only
for (const value of map.values()) {
  console.log(`Value: ${value}`);
}

// forEach method with callback
map.forEach((value, key, map) => {
  console.log(`${key} => ${value}`);
});

// forEach with custom this context
const context = { prefix: "User: " };
map.forEach(function(value, key) {
  console.log(this.prefix + value);
}, context);

Type Definitions:

/**
 * @return {!Iterator<!Array<*>>} Iterator of [key, value] pairs
 */

/**
 * @param {function(*, string, !Map)} callback Function to execute for each entry
 * @param {*=} opt_thisArg Value to use as 'this' when executing callback
 */

Conversion Methods { .api }

Array Conversion

const { Map } = require('google-protobuf');

const map = new Map();
map.set("id", "123");
map.set("name", "Product");
map.set("price", "99.99");

// Convert to array representation
const arrayForm = map.toArray();
// Result: [["id", "123"], ["name", "Product"], ["price", "99.99"]]

// Get entry list (for binary serialization)
const entryList = map.getEntryList();
// Returns internal array structure used for Protocol Buffer serialization

// Example: Round-trip conversion
const originalData = [["key1", "value1"], ["key2", "value2"]];
const map = new Map(originalData);
const restored = map.toArray();
console.log(JSON.stringify(originalData) === JSON.stringify(restored)); // true

Object Conversion

const { Map } = require('google-protobuf');

const map = new Map();
map.set("user_id", "12345");
map.set("user_name", "Alice");
map.set("user_active", "true");

// Convert to plain JavaScript object
const plainObject = map.toObject();
// Result: { user_id: "12345", user_name: "Alice", user_active: "true" }

// Convert with includeInstance flag and value transformation
const objectWithTransform = map.toObject(
  true,  // includeInstance - include the map instance
  (value) => value.toUpperCase() // valueToObject transformation function
);
// Result: { user_id: "12345", user_name: "ALICE", user_active: "TRUE" }

// Example: Converting message value maps
const messageMap = new Map([], AddressMessage);
const homeAddress = new AddressMessage();
homeAddress.setStreet("123 Main St");
messageMap.set("home", homeAddress);

const addressObject = messageMap.toObject(false, (addr) => addr.toObject());
// Result: { home: { street: "123 Main St", ... } }

Type Definitions:

/**
 * @param {boolean=} includeInstance Whether to include the map instance
 * @param {function(*): *=} valueToObject Function to convert values to objects  
 * @return {!Object} Plain JavaScript object
 */

Message Value Maps { .api }

Maps with message values require special handling through value constructors:

const { Map } = require('google-protobuf');

// Define message constructor for map values
class ContactInfo extends Message {
  getEmail() { return this.email_; }
  setEmail(value) { this.email_ = value; }
  
  getPhone() { return this.phone_; }
  setPhone(value) { this.phone_ = value; }
}

// Create map with message value constructor
const contactMap = new Map([], ContactInfo);

// Add message entries
const johnContact = new ContactInfo();
johnContact.setEmail("john@example.com");
johnContact.setPhone("555-0123");
contactMap.set("john", johnContact);

const janeContact = new ContactInfo();  
janeContact.setEmail("jane@example.com");
janeContact.setPhone("555-0456");
contactMap.set("jane", janeContact);

// Access message values
const johnInfo = contactMap.get("john");
console.log(johnInfo.getEmail()); // "john@example.com"

// Iterate over message values
contactMap.forEach((contact, name) => {
  console.log(`${name}: ${contact.getEmail()}`);
});

// Convert to object form
const contactObjects = contactMap.toObject(false, (contact) => ({
  email: contact.getEmail(),
  phone: contact.getPhone()
}));

Internal Synchronization { .api }

The map maintains synchronization between its internal structure and the underlying array:

const { Map } = require('google-protobuf');

const map = new Map();

// Check synchronization status
console.log(map.arrClean); // true - initially clean

// Modify map
map.set("key1", "value1");
console.log(map.arrClean); // false - now dirty

// Array conversion triggers synchronization  
const array = map.toArray();
console.log(map.arrClean); // true - clean after conversion

// Manual synchronization check
map.set("key2", "value2");
const entryList = map.getEntryList(); // Forces synchronization
console.log(map.arrClean); // true

// Example: Batch operations
const pairs = [
  ["name", "Alice"],
  ["age", "30"], 
  ["city", "New York"]
];

// Efficient batch loading
const batchMap = new Map(pairs); // Loads directly from array
console.log(batchMap.arrClean); // true - no sync needed

// Individual additions
pairs.forEach(([key, value]) => {
  batchMap.set(key, value);
});
// arrClean becomes false after modifications

Advanced Usage Patterns { .api }

Map Transformation

const { Map } = require('google-protobuf');

// Transform map keys and values
function transformMap(sourceMap, keyTransform, valueTransform) {
  const targetMap = new Map();
  
  sourceMap.forEach((value, key) => {
    const newKey = keyTransform ? keyTransform(key) : key;
    const newValue = valueTransform ? valueTransform(value) : value;
    targetMap.set(newKey, newValue);
  });
  
  return targetMap;
}

// Example usage
const originalMap = new Map();
originalMap.set("user_name", "alice");
originalMap.set("user_age", "25");

const transformedMap = transformMap(
  originalMap,
  key => key.replace("user_", ""),  // Remove prefix from keys
  value => value.toString().toUpperCase() // Uppercase values
);

// Result: { name: "ALICE", age: "25" }

Map Filtering

const { Map } = require('google-protobuf');

function filterMap(sourceMap, predicate) {
  const filteredMap = new Map();
  
  sourceMap.forEach((value, key) => {
    if (predicate(value, key)) {
      filteredMap.set(key, value);
    }
  });
  
  return filteredMap;
}

// Example: Filter out inactive users
const userMap = new Map();
userMap.set("alice", "active");
userMap.set("bob", "inactive");
userMap.set("charlie", "active");

const activeUsers = filterMap(userMap, (status) => status === "active");
// Result contains only alice and charlie

Map Merging

const { Map } = require('google-protobuf');

function mergeMaps(map1, map2, conflictResolver) {
  const mergedMap = new Map();
  
  // Copy all entries from first map
  map1.forEach((value, key) => {
    mergedMap.set(key, value);
  });
  
  // Merge entries from second map, resolving conflicts
  map2.forEach((value, key) => {
    if (mergedMap.has(key) && conflictResolver) {
      const existing = mergedMap.get(key);
      const resolved = conflictResolver(existing, value, key);
      mergedMap.set(key, resolved);
    } else {
      mergedMap.set(key, value);
    }
  });
  
  return mergedMap;
}

// Example: Merge user preferences
const defaultPrefs = new Map();
defaultPrefs.set("theme", "light");
defaultPrefs.set("notifications", "enabled");

const userPrefs = new Map();
userPrefs.set("theme", "dark");
userPrefs.set("language", "en");

const finalPrefs = mergeMaps(
  defaultPrefs, 
  userPrefs, 
  (defaultVal, userVal) => userVal // User preference wins
);
// Result: { theme: "dark", notifications: "enabled", language: "en" }

Serialization Integration { .api }

Maps integrate with Protocol Buffer serialization through the Message system:

const { Map, Message } = require('google-protobuf');

// Maps are typically accessed through message fields
class UserMessage extends Message {
  getAttributesMap() {
    return Message.getMapField(this, 1, false, null); // String map
  }
  
  getContactsMap() {
    return Message.getMapField(this, 2, false, ContactMessage); // Message map
  }
}

// Usage with message serialization
const user = new UserMessage();
const attrs = user.getAttributesMap();
attrs.set("role", "admin");
attrs.set("department", "engineering");

// Map is automatically serialized with the message
const serialized = user.serializeBinary();
const deserialized = UserMessage.deserializeBinary(serialized);

// Maps are preserved through serialization
const restoredAttrs = deserialized.getAttributesMap();
console.log(restoredAttrs.get("role")); // "admin"

Performance Considerations

Efficient Operations

const { Map } = require('google-protobuf');

// Batch operations are more efficient than individual ones
const entries = [
  ["key1", "value1"],
  ["key2", "value2"], 
  ["key3", "value3"]
];

// Efficient: Create map with initial data
const efficientMap = new Map(entries);

// Less efficient: Individual sets
const inefficientMap = new Map();
entries.forEach(([key, value]) => {
  inefficientMap.set(key, value);
});

// Check size without triggering synchronization
if (map.getLength() > 0) {
  // Process non-empty map
}

// Minimize conversions
const arrayOnce = map.toArray(); // Cache if needed multiple times

Memory Management

// Clear large maps when done
largeMap.clear();

// Avoid holding references to cleared maps
largeMap = null;

// Reuse maps for similar data structures
function processUserBatch(users) {
  const tempMap = new Map();
  
  users.forEach(user => {
    tempMap.clear(); // Reuse same map instance
    
    // Populate with user data
    tempMap.set("id", user.id);
    tempMap.set("name", user.name);
    
    // Process map
    processUserMap(tempMap);
  });
}

docs

binary-io.md

bytestring-utilities.md

debug-utilities.md

extension-fields.md

index.md

map-operations.md

message-operations.md

tile.json