function bytesOf(value) { if (value == null) return null; if (typeof Buffer !== 'undefined' && Buffer.isBuffer(value)) { return value.length === 12 ? value : null; } if (value instanceof Uint8Array) { return value.byteLength === 12 ? Buffer.from(value) : null; } if ( value && value.type === 'Buffer' && Array.isArray(value.data) && value.data.length === 12 ) { return Buffer.from(value.data); } if (typeof value !== 'object' || Array.isArray(value) || value instanceof Date) { return null; } const keys = Object.keys(value); if (keys.length !== 12) return null; const bytes = Buffer.alloc(12); for (let index = 0; index < 12; index += 1) { if (!Object.prototype.hasOwnProperty.call(value, index)) return null; const byte = Number(value[index]); if (!Number.isInteger(byte) || byte < 0 || byte > 255) return null; bytes[index] = byte; } return bytes; } const PURE_REF_KEYS = new Set(['_id', 'id', 'buffer', '$oid']); function isPureRef(value) { if (value == null || typeof value !== 'object') return false; if (typeof value.toHexString === 'function') return true; if (Array.isArray(value) || value instanceof Date) return false; const keys = Object.keys(value); return keys.length > 0 && keys.every(key => PURE_REF_KEYS.has(key)) && refId(value) != null; } function isBinaryPayload(value) { if (value == null || typeof value !== 'object') return false; if (typeof Buffer !== 'undefined' && Buffer.isBuffer(value)) return true; if (value instanceof Uint8Array || value instanceof ArrayBuffer) return true; const name = value.constructor?.name; return name === 'Blob' || name === 'File'; } // Object ids are always hex strings on the wire. File buffers are left alone. export function stringifyIds(value) { if (value == null) return value; if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') { return value; } if (typeof value.toHexString === 'function') return value.toHexString(); if (value instanceof Date || typeof value === 'function') return value; if (isBinaryPayload(value)) return value; if (Array.isArray(value)) return value.map(item => stringifyIds(item)); if (typeof value === 'object') { if (isPureRef(value)) { const id = refId(value); if (typeof id === 'string') return id; } const copy = {}; for (const [key, child] of Object.entries(value)) { copy[key] = stringifyIds(child); } return copy; } return value; } export function refId(value) { if (value == null || value === '') return null; if (typeof value === 'string') return value; if (typeof value === 'object' && typeof value.toHexString === 'function') { return value.toHexString(); } if (typeof value !== 'object' || Array.isArray(value) || value instanceof Date) { return null; } if (typeof value.$oid === 'string') return refId(value.$oid); const keys = Object.keys(value); if ( keys.length > 0 && keys.every(key => key === 'buffer' || key === 'id' || key === 'type' || key === 'data') ) { const bytes = bytesOf(value.buffer) || bytesOf(value.id) || bytesOf(value); if (bytes) return bytes.toString('hex'); } if (value._id != null) return refId(value._id); return null; }