Cross-platform utilities for byte manipulation, number handling, and comprehensive error handling with specific error types for different failure scenarios.
Comprehensive error handling with specific error types for different BSON operation failures.
/**
* Base error class for all BSON-related errors
*/
class BSONError extends Error {
/** Create BSON error with message and optional cause */
constructor(message: string, options?: { cause?: unknown });
/** Check if value is a BSON error */
static isBSONError(value: unknown): value is BSONError;
/** Error name identifier */
get name(): string; // "BSONError"
}
/**
* Version compatibility error
*/
class BSONVersionError extends BSONError {
constructor();
get name(): 'BSONVersionError';
}
/**
* Runtime/input validation error
*/
class BSONRuntimeError extends BSONError {
constructor(message: string);
get name(): 'BSONRuntimeError';
}
/**
* Parsing offset error (experimental)
*/
class BSONOffsetError extends BSONError {
constructor(message: string, offset: number, options?: { cause?: unknown });
get name(): 'BSONOffsetError';
/** Byte offset where error occurred */
readonly offset: number;
}Usage Examples:
import { serialize, BSONError } from "bson";
try {
// Attempt potentially problematic operation
const result = serialize(problematicData);
} catch (error) {
// Use type-safe error checking
if (BSONError.isBSONError(error)) {
console.log(`BSON operation failed: ${error.message}`);
// Handle specific error types
if (error.name === 'BSONRuntimeError') {
console.log('Runtime validation failed');
} else if (error.name === 'BSONVersionError') {
console.log('Version compatibility issue');
} else if (error.name === 'BSONOffsetError') {
console.log(`Parsing failed at byte offset: ${error.offset}`);
}
} else {
// Re-throw non-BSON errors
throw error;
}
}Cross-platform byte array utilities for handling binary data operations.
/**
* Cross-platform byte array utilities
*/
class ByteUtils {
/** Allocate zeroed byte array */
static allocate(size: number): Uint8Array;
/** Allocate uninitialized byte array (faster) */
static allocateUnsafe(size: number): Uint8Array;
/** Convert buffer to local platform format */
static toLocalBufferType(buffer: Uint8Array | ArrayBuffer): Uint8Array;
/** Compare two byte arrays for equality */
static equals(a: Uint8Array, b: Uint8Array): boolean;
/** Create Uint8Array from number array */
static fromNumberArray(array: number[]): Uint8Array;
/** Convert bytes to base64 string */
static toBase64(buffer: Uint8Array): string;
/** Create bytes from base64 string */
static fromBase64(base64: string): Uint8Array;
/** Convert bytes to hex string */
static toHex(buffer: Uint8Array): string;
/** Create bytes from hex string */
static fromHex(hex: string): Uint8Array;
/** Convert bytes to UTF-8 string */
static toUTF8(
buffer: Uint8Array,
start?: number,
end?: number,
fatal?: boolean
): string;
/** Convert UTF-8 string to bytes */
static fromUTF8(text: string): Uint8Array;
}Usage Examples:
import { ByteUtils } from "bson";
// Allocate and manipulate byte arrays
const buffer = ByteUtils.allocate(1024);
const unsafeBuffer = ByteUtils.allocateUnsafe(512); // Faster, uninitialized
// Encoding/decoding operations
const text = "Hello, BSON!";
const utf8Bytes = ByteUtils.fromUTF8(text);
const restored = ByteUtils.toUTF8(utf8Bytes);
console.log(restored); // "Hello, BSON!"
// Base64 operations
const data = new Uint8Array([72, 101, 108, 108, 111]); // "Hello"
const base64 = ByteUtils.toBase64(data);
console.log(base64); // "SGVsbG8="
const fromBase64 = ByteUtils.fromBase64(base64);
console.log(ByteUtils.equals(data, fromBase64)); // true
// Hex operations
const hexString = ByteUtils.toHex(data);
console.log(hexString); // "48656c6c6f"
const fromHex = ByteUtils.fromHex(hexString);
console.log(ByteUtils.equals(data, fromHex)); // true
// Array conversion
const numbers = [72, 101, 108, 108, 111];
const fromNumbers = ByteUtils.fromNumberArray(numbers);
console.log(ByteUtils.equals(data, fromNumbers)); // true
// Platform compatibility
const arrayBuffer = new ArrayBuffer(16);
const uint8Array = ByteUtils.toLocalBufferType(arrayBuffer);
console.log(uint8Array instanceof Uint8Array); // trueCross-platform number utilities for handling different numeric formats and endianness.
/**
* Cross-platform number utilities for binary data
*/
class NumberUtils {
/** Read 32-bit signed integer (little-endian) */
static getInt32LE(source: Uint8Array, offset: number): number;
/** Read 32-bit unsigned integer (little-endian) */
static getUint32LE(source: Uint8Array, offset: number): number;
/** Read 64-bit signed integer as BigInt (little-endian) */
static getBigInt64LE(source: Uint8Array, offset: number): bigint;
/** Read 64-bit unsigned integer as BigInt (little-endian) */
static getBigUint64LE(source: Uint8Array, offset: number): bigint;
/** Read 64-bit double precision float (little-endian) */
static getFloat64LE(source: Uint8Array, offset: number): number;
/** Write 32-bit signed integer (little-endian) */
static setInt32LE(destination: Uint8Array, offset: number, value: number): 4;
/** Write 32-bit unsigned integer (little-endian) */
static setUint32LE(destination: Uint8Array, offset: number, value: number): 4;
/** Write 64-bit signed integer from BigInt (little-endian) */
static setBigInt64LE(destination: Uint8Array, offset: number, value: bigint): 8;
/** Write 64-bit unsigned integer from BigInt (little-endian) */
static setBigUint64LE(destination: Uint8Array, offset: number, value: bigint): 8;
/** Write 64-bit double precision float (little-endian) */
static setFloat64LE(destination: Uint8Array, offset: number, value: number): 8;
}Usage Examples:
import { NumberUtils } from "bson";
// Create buffer for numeric operations
const buffer = new Uint8Array(16);
// Write different numeric types
let offset = 0;
offset += NumberUtils.setInt32LE(buffer, offset, -42); // 4 bytes
offset += NumberUtils.setUint32LE(buffer, offset, 3000000000); // 4 bytes
offset += NumberUtils.setBigInt64LE(buffer, offset, 9223372036854775807n); // 8 bytes
// Read them back
let readOffset = 0;
const int32 = NumberUtils.getInt32LE(buffer, readOffset);
readOffset += 4;
const uint32 = NumberUtils.getUint32LE(buffer, readOffset);
readOffset += 4;
const bigInt64 = NumberUtils.getBigInt64LE(buffer, readOffset);
console.log(int32); // -42
console.log(uint32); // 3000000000
console.log(bigInt64); // 9223372036854775807n
// Floating point operations
const floatBuffer = new Uint8Array(8);
NumberUtils.setFloat64LE(floatBuffer, 0, Math.PI);
const pi = NumberUtils.getFloat64LE(floatBuffer, 0);
console.log(pi); // 3.141592653589793
// Working with large numbers safely
const maxSafeInt = Number.MAX_SAFE_INTEGER;
const bigValue = BigInt(maxSafeInt) + 1n;
const bigBuffer = new Uint8Array(8);
NumberUtils.setBigInt64LE(bigBuffer, 0, bigValue);
const retrieved = NumberUtils.getBigInt64LE(bigBuffer, 0);
console.log(retrieved === bigValue); // trueBSON type identifiers and configuration constants.
/**
* BSON type enumeration
*/
const BSONType = Object.freeze({
double: 1,
string: 2,
object: 3,
array: 4,
binData: 5,
undefined: 6,
objectId: 7,
bool: 8,
date: 9,
null: 10,
regex: 11,
dbPointer: 12,
javascript: 13,
symbol: 14,
javascriptWithScope: 15,
int: 16,
timestamp: 17,
long: 18,
decimal: 19,
minKey: -1,
maxKey: 127
}) as const;
type BSONType = (typeof BSONType)[keyof typeof BSONType];Usage Examples:
import { BSONType } from "bson";
// Type checking and identification
function identifyBSONType(typeCode: number): string {
switch (typeCode) {
case BSONType.double:
return "64-bit floating point";
case BSONType.string:
return "UTF-8 string";
case BSONType.object:
return "Embedded document";
case BSONType.array:
return "Array";
case BSONType.objectId:
return "ObjectId";
case BSONType.long:
return "64-bit integer";
case BSONType.decimal:
return "128-bit decimal";
default:
return "Unknown type";
}
}
console.log(identifyBSONType(BSONType.objectId)); // "ObjectId"
console.log(identifyBSONType(BSONType.decimal)); // "128-bit decimal"Abstract base class for all BSON types providing common functionality.
/**
* Abstract base class for all BSON types
*/
abstract class BSONValue {
/** BSON type identifier */
abstract get _bsontype(): string;
/** Custom inspection method for Node.js util.inspect */
[Symbol.for('nodejs.util.inspect.custom')](): string;
}Usage Examples:
import { BSONValue, ObjectId, Long } from "bson";
function isBSONType(value: unknown): value is BSONValue {
return value != null &&
typeof value === 'object' &&
'_bsontype' in value;
}
const id = new ObjectId();
const number = Long.fromNumber(42);
console.log(isBSONType(id)); // true
console.log(isBSONType(number)); // true
console.log(isBSONType({})); // false
console.log(id._bsontype); // "ObjectId"
console.log(number._bsontype); // "Long"The BSON library provides structured error handling to help identify and resolve issues:
import { serialize, deserialize, BSONError, BSONRuntimeError } from "bson";
async function safeBSONOperation(data: any): Promise<any> {
try {
// Serialize data
const bytes = serialize(data, { checkKeys: true });
// Deserialize with validation
const result = deserialize(bytes, {
validation: { utf8: true }
});
return result;
} catch (error) {
if (BSONError.isBSONError(error)) {
// Handle BSON-specific errors
switch (error.name) {
case 'BSONRuntimeError':
console.error('Data validation failed:', error.message);
break;
case 'BSONVersionError':
console.error('BSON version incompatibility:', error.message);
break;
case 'BSONOffsetError':
console.error(`Parsing error at offset ${error.offset}:`, error.message);
break;
default:
console.error('BSON error:', error.message);
}
// Return null or default value instead of crashing
return null;
} else {
// Re-throw non-BSON errors
throw error;
}
}
}The utilities are designed to work across different JavaScript environments:
// Node.js environment
import { ByteUtils, NumberUtils } from "bson";
// Browser environment (ES modules)
import { ByteUtils, NumberUtils } from "./lib/bson.mjs";
// CommonJS environment
const { ByteUtils, NumberUtils } = require("bson");
// All utilities work consistently across platforms
const data = ByteUtils.fromUTF8("Hello, World!");
const base64 = ByteUtils.toBase64(data);
const restored = ByteUtils.fromBase64(base64);
// Identical behavior in Node.js, browsers, and React Native