UNPKG

hadron-document

Version:
193 lines • 6.94 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); Object.defineProperty(exports, "__esModule", { value: true }); exports.fieldStringLen = fieldStringLen; exports.objectToIdiomaticEJSON = objectToIdiomaticEJSON; exports.getDefaultValueForType = getDefaultValueForType; exports.getDisplayType = getDisplayType; const bson_1 = require("bson"); const hadron_type_checker_1 = __importStar(require("hadron-type-checker")); const UNCASTED_EMPTY_TYPE_VALUE = { Array: [], Object: {}, Decimal128: 0, Int32: 0, Int64: 0, Double: 0, MaxKey: 0, MinKey: 0, Timestamp: 0, Date: 0, String: '', Code: '', Binary: '', ObjectId: '', BSONRegExp: '', BSONSymbol: '', Boolean: false, Undefined: undefined, Null: null, UUID: '', LegacyJavaUUID: '', LegacyCSharpUUID: '', LegacyPythonUUID: '', }; const maxFourYearDate = new Date('9999-12-31T23:59:59.999Z').valueOf(); function fieldStringLen(value) { const length = String(value).length; return length === 0 ? 1 : length; } /** * Turn a BSON value into what we consider idiomatic extended JSON. * * This differs from both the relaxed and strict mode of the 'bson' * package's EJSON class: We preserve the type information for longs * via $numberLong, but redact it for $numberInt and $numberDouble. * * This may seem inconsistent, but considering that the latter two * types are exactly representable in JS and $numberLong is not, * in addition to the fact that this has been historic behavior * in Compass for a long time, this seems like a reasonable choice. * * Also turns $date.$numberLong into a date so that it will be * displayed as an iso date string since this is what Compass did * historically. Unless it is outside of the safe range. * * @param value Any BSON value. * @returns A serialized, human-readable and human-editable string. */ function objectToIdiomaticEJSON(value, options = {}) { const serialized = bson_1.EJSON.serialize(value, { relaxed: false, }); makeEJSONIdiomatic(serialized); return JSON.stringify(serialized, null, 'indent' in options ? options.indent : 2); } /** * Convert a base64 string to a UUID string (xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx). */ function base64ToUUIDString(base64) { // Decode base64 to bytes const bytes = Buffer.from(base64, 'base64'); if (bytes.length !== 16) { return ''; // Invalid UUID length } const hex = bytes.toString('hex'); // Format as UUID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx return [ hex.substring(0, 8), hex.substring(8, 12), hex.substring(12, 16), hex.substring(16, 20), hex.substring(20, 32), ].join('-'); } function makeEJSONIdiomatic(value) { if (!value || typeof value !== 'object') return; for (const key of Object.keys(value)) { const entry = value[key]; // We are only interested in object-like values, skip everything else if (typeof entry !== 'object' || entry === null) { continue; } if (entry.$numberInt) { value[key] = +entry.$numberInt; continue; } if (entry.$numberDouble) { if (Number.isFinite(+entry.$numberDouble) && !Object.is(+entry.$numberDouble, -0)) { // EJSON can represent +/-Infinity or NaN values but JSON can't // (and -0 can be parsed from JSON but not serialized by JSON.stringify). value[key] = +entry.$numberDouble; } continue; } if (entry.$date && entry.$date.$numberLong) { const number = entry.$date.$numberLong; if (number >= 0 && number <= maxFourYearDate) { entry.$date = new Date(+number).toISOString(); } } // Convert Binary subtype 04 (UUID) to $uuid format for better readability if (entry.$binary && entry.$binary.subType === '04' && entry.$binary.base64) { const uuidString = base64ToUUIDString(entry.$binary.base64); if (uuidString) { value[key] = { $uuid: uuidString }; continue; } } makeEJSONIdiomatic(entry); } } /** * Returns a default value for the BSON type passed in. */ function getDefaultValueForType(type) { return hadron_type_checker_1.default.cast(UNCASTED_EMPTY_TYPE_VALUE[type], type); } /** * Gets the display type for an element, considering legacy UUID encoding * preference. * * - For Binary subtype 3 (legacy UUID), returns the appropriate legacy UUID * type based on context. * - For Binary subtype 4 (UUID), returns 'UUID'. * - For all other types, returns the element's currentType. */ function getDisplayType(el, legacyUUIDEncoding) { // If the element already has a specific UUID type, use it if ((0, hadron_type_checker_1.isUUIDType)(el.currentType)) { return el.currentType; } // Check if this is a Binary that should be displayed as a UUID type if (el.currentType === 'Binary' && (0, hadron_type_checker_1.getBsonType)(el.currentValue) === 'Binary') { const binary = el.currentValue; if (binary.sub_type === bson_1.Binary.SUBTYPE_UUID) { return 'UUID'; } if (binary.sub_type === bson_1.Binary.SUBTYPE_UUID_OLD && binary.buffer.length === 16 && legacyUUIDEncoding) { return legacyUUIDEncoding; } } return el.currentType; } //# sourceMappingURL=utils.js.map