CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-cbor

Encode and parse data in the Concise Binary Object Representation (CBOR) data format (RFC8949).

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

integration-utilities.mddocs/

Integration and Utilities

Integration support for databases and frameworks, plus utility functions for package management and system reset capabilities.

Capabilities

LevelDB Integration

Codec for leveldb integration providing seamless CBOR encoding/decoding for keys and values in LevelDB databases.

/**
 * Codec for leveldb integration
 */
const leveldb = {
  /**
   * Decoder function for leveldb (decodeFirstSync)
   * @param {BufferLike} input - CBOR data to decode
   * @param {DecoderOptions} [options] - Decoding options
   * @returns {any} Decoded value
   */
  decode: function(input, options),
  
  /**
   * Encoder function for leveldb (encode)
   * @param {...any} objs - Objects to encode
   * @returns {Buffer} CBOR encoded data
   */
  encode: function(...objs),
  
  /**
   * Buffer support flag
   * @type {boolean}
   */
  buffer: true,
  
  /**
   * Codec name identifier
   * @type {string}
   */
  name: "cbor"
};

Usage Examples:

const cbor = require("cbor");
const level = require("level");

// Use CBOR codec with LevelDB
const db = level('./my-database', {
  keyEncoding: cbor.leveldb,
  valueEncoding: cbor.leveldb
});

// Store complex data types as keys and values
async function storeCBORData() {
  // Complex keys - objects, arrays, dates, etc.
  const complexKey = { type: "user", id: 12345, timestamp: new Date() };
  const complexValue = {
    name: "Alice Johnson",
    profile: {
      age: 30,
      skills: ["JavaScript", "Python", "CBOR"],
      active: true,
      lastLogin: new Date(),
      preferences: new Map([
        ["theme", "dark"],
        ["notifications", true]
      ])
    },
    bigNumber: 123456789012345678901234567890n
  };
  
  // Store with complex key/value
  await db.put(complexKey, complexValue);
  
  // Retrieve using the same complex key structure
  const retrieved = await db.get(complexKey);
  console.log('Retrieved user:', retrieved);
  
  // BigInt and other complex types are preserved
  console.log('BigInt value:', typeof retrieved.bigNumber); // 'bigint'
  console.log('Map preferences:', retrieved.profile.preferences instanceof Map); // true
}

// Numeric keys work seamlessly
async function useNumericKeys() {
  await db.put(42, "The answer to everything");
  await db.put(3.14159, "Pi value");
  
  const answer = await db.get(42);
  const pi = await db.get(3.14159);
  
  console.log(answer); // "The answer to everything"
  console.log(pi); // "Pi value"
}

// Array and object keys
async function useComplexKeys() {
  const arrayKey = [1, 2, "three", true];
  const objectKey = { x: 10, y: 20, z: 30 };
  
  await db.put(arrayKey, "Array key data");
  await db.put(objectKey, "Object key data");
  
  // Keys are compared by value, not reference
  const sameArrayKey = [1, 2, "three", true];
  const sameObjectKey = { x: 10, y: 20, z: 30 };
  
  const arrayData = await db.get(sameArrayKey);
  const objectData = await db.get(sameObjectKey);
  
  console.log(arrayData); // "Array key data"
  console.log(objectData); // "Object key data"
}

// Batch operations with CBOR
async function batchOperations() {
  const operations = [
    { type: 'put', key: { type: 'batch', id: 1 }, value: 'First batch item' },
    { type: 'put', key: { type: 'batch', id: 2 }, value: 'Second batch item' },
    { type: 'put', key: { type: 'batch', id: 3 }, value: 'Third batch item' }
  ];
  
  await db.batch(operations);
  
  // Read back batch items
  for (let i = 1; i <= 3; i++) {
    const key = { type: 'batch', id: i };
    const value = await db.get(key);
    console.log(`Batch ${i}:`, value);
  }
}

// Error handling with complex keys
async function handleErrors() {
  try {
    const nonExistentKey = { type: 'missing', id: 999 };
    const value = await db.get(nonExistentKey);
  } catch (error) {
    if (error.code === 'LEVEL_NOT_FOUND') {
      console.log('Key not found in database');
    }
  }
}

Package Reset Functionality

Reset encoder/decoder semantic types and configurations to their original defaults.

/**
 * Reset encoder/decoder semantic types to defaults
 * Resets both Encoder and Tagged semantic type mappings
 */
function reset();

Usage Examples:

const cbor = require("cbor");

// Add custom semantic types
cbor.Encoder.SEMANTIC_TYPES.MyClass = (encoder, obj) => {
  encoder.pushAny({ customEncoding: obj.serialize() });
  return true;
};

cbor.Tagged.TAGS[9999] = (value) => new MyClass(value.data);

// Custom encoding/decoding works
const customObj = new MyClass("test data");
const encoded = cbor.encode(customObj);
const decoded = cbor.decode(encoded);

// Reset everything to defaults
cbor.reset();

// Custom types are no longer available
console.log(cbor.Encoder.SEMANTIC_TYPES.MyClass); // undefined
console.log(cbor.Tagged.TAGS[9999]); // undefined

// Built-in types still work normally
const normalData = { name: "Alice", date: new Date() };
const normalEncoded = cbor.encode(normalData);
const normalDecoded = cbor.decode(normalEncoded);
console.log(normalDecoded); // Works as expected

Constants and Internal Types

Access to CBOR constants and internal type definitions for advanced usage.

/**
 * CBOR Major Types
 */
const MT = {
  POS_INT: 0,        // Positive integer
  NEG_INT: 1,        // Negative integer
  BYTE_STRING: 2,    // Byte string
  UTF8_STRING: 3,    // UTF-8 string
  ARRAY: 4,          // Array
  MAP: 5,            // Map
  TAG: 6,            // Tag
  SIMPLE_FLOAT: 7    // Simple/Float
};

/**
 * CBOR Tag Numbers
 */
const TAG = {
  DATE_STRING: 0,        // Date string (ISO 8601)
  DATE_EPOCH: 1,         // Epoch timestamp
  POS_BIGINT: 2,         // Positive bigint
  NEG_BIGINT: 3,         // Negative bigint
  DECIMAL_FRAC: 4,       // Decimal fraction
  BIGFLOAT: 5,           // Big float
  BASE64URL_EXPECTED: 21, // Base64url encoding expected
  BASE64_EXPECTED: 22,    // Base64 encoding expected
  BASE16_EXPECTED: 23,    // Base16 encoding expected
  CBOR: 24,              // Embedded CBOR
  URI: 32,               // URI
  BASE64URL: 33,         // Base64url
  BASE64: 34,            // Base64
  REGEXP: 35,            // Regular expression
  MIME: 36,              // MIME message
  SET: 258               // Set
};

/**
 * CBOR Simple Values
 */
const SIMPLE = {
  FALSE: 20,       // False
  TRUE: 21,        // True
  NULL: 22,        // Null
  UNDEFINED: 23    // Undefined
};

Usage Examples:

const cbor = require("cbor");

// Access constants for custom implementations
console.log(cbor.MT?.POS_INT); // 0 (if available)

// Create custom tagged values using standard tag numbers
const dateTagged = new cbor.Tagged(cbor.TAG?.DATE_STRING || 0, "2023-12-25T10:30:00Z");
const regexTagged = new cbor.Tagged(cbor.TAG?.REGEXP || 35, "pattern");

// Custom simple values
const customSimple = new cbor.Simple(cbor.SIMPLE?.TRUE || 21);

Utility Functions

Various utility functions for CBOR data manipulation and analysis.

/**
 * Convert CBOR null/undefined symbols to actual values
 * @param {any} val - Value to check and convert
 * @returns {any} Converted value
 */
function nullcheck(val);

Usage Examples:

const cbor = require("cbor");

// Null check utility
const data = cbor.decode(someEncodedData);
const checkedData = cbor.Decoder.nullcheck(data);

// Useful when working with streaming data where nulls might be symbols
function processStreamData(streamValue) {
  const actualValue = cbor.Decoder.nullcheck(streamValue);
  
  if (actualValue === null) {
    console.log('Received null value');
  } else if (actualValue === undefined) {
    console.log('Received undefined value');
  } else {
    console.log('Received value:', actualValue);
  }
}

Framework Integration Patterns

Common patterns for integrating CBOR with various frameworks and libraries.

Usage Examples:

const cbor = require("cbor");

// Express.js integration
const express = require("express");
const app = express();

// CBOR middleware
app.use('/api/cbor', (req, res, next) => {
  if (req.headers['content-type'] === 'application/cbor') {
    let buffer = Buffer.alloc(0);
    
    req.on('data', chunk => {
      buffer = Buffer.concat([buffer, chunk]);
    });
    
    req.on('end', () => {
      try {
        req.body = cbor.decode(buffer);
        next();
      } catch (error) {
        res.status(400).json({ error: 'Invalid CBOR data' });
      }
    });
  } else {
    next();
  }
});

// CBOR response helper
app.use((req, res, next) => {
  res.cbor = (data) => {
    res.setHeader('Content-Type', 'application/cbor');
    res.send(cbor.encode(data));
  };
  next();
});

// Redis integration with CBOR
const redis = require("redis");
const client = redis.createClient();

// CBOR-enabled Redis operations
const redisCBOR = {
  async set(key, value, options = {}) {
    const encoded = cbor.encode(value);
    return await client.set(key, encoded, options);
  },
  
  async get(key) {
    const encoded = await client.get(key);
    return encoded ? cbor.decode(encoded) : null;
  },
  
  async mset(keyValuePairs) {
    const encoded = keyValuePairs.map(([key, value]) => [key, cbor.encode(value)]);
    return await client.mset(encoded.flat());
  },
  
  async mget(keys) {
    const encoded = await client.mget(keys);
    return encoded.map(data => data ? cbor.decode(data) : null);
  }
};

// Socket.io integration
const { Server } = require("socket.io");
const io = new Server();

// CBOR packet handling
io.on('connection', (socket) => {
  socket.on('cbor-message', (encodedData) => {
    try {
      const message = cbor.decode(Buffer.from(encodedData));
      console.log('Received CBOR message:', message);
      
      // Process and respond with CBOR
      const response = { status: 'received', echo: message };
      socket.emit('cbor-response', cbor.encode(response));
    } catch (error) {
      socket.emit('cbor-error', { error: 'Invalid CBOR data' });
    }
  });
});

// Configuration management with CBOR
class CBORConfig {
  constructor(filePath) {
    this.filePath = filePath;
  }
  
  async load() {
    try {
      const fs = require('fs').promises;
      const data = await fs.readFile(this.filePath);
      return cbor.decode(data);
    } catch (error) {
      return {}; // Return empty config if file doesn't exist
    }
  }
  
  async save(config) {
    const fs = require('fs').promises;
    const encoded = cbor.encode(config);
    await fs.writeFile(this.filePath, encoded);
  }
  
  async update(updates) {
    const current = await this.load();
    const updated = { ...current, ...updates };
    await this.save(updated);
    return updated;
  }
}

// Usage
const config = new CBORConfig('./app-config.cbor');
await config.save({
  database: { host: 'localhost', port: 5432 },
  features: { enableLogging: true, maxUsers: 1000 },
  version: '1.2.0'
});

Error Handling

Integration utilities handle various error conditions:

  • LevelDB encoding/decoding errors
  • Invalid configuration during reset
  • Framework integration errors
  • File system errors in configuration management
const cbor = require("cbor");

// Robust error handling for integrations
async function safeIntegration() {
  try {
    // LevelDB operations
    const db = level('./db', { valueEncoding: cbor.leveldb });
    await db.put(complexKey, complexValue);
  } catch (error) {
    if (error.code === 'LEVEL_DATABASE_NOT_OPEN') {
      console.error('Database not open');
    } else if (error.message.includes('CBOR')) {
      console.error('CBOR encoding/decoding error:', error);
    } else {
      console.error('Unexpected error:', error);
    }
  }
  
  // Reset with error handling
  try {
    cbor.reset();
  } catch (error) {
    console.error('Reset failed:', error);
  }
}

Install with Tessl CLI

npx tessl i tessl/npm-cbor

docs

advanced-decoding.md

cbor-types.md

diagnostic-tools.md

encoding-decoding.md

index.md

integration-utilities.md

stream-processing.md

tile.json