UNPKG

@tybys/oid

Version:

Use MongoDB ObjectID without installing bson.

804 lines (790 loc) 31.8 kB
(function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : typeof define === 'function' && define.amd ? define(['exports'], factory) : (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.oid = {})); }(this, (function (exports) { 'use strict'; var _Symbol; if (typeof Symbol === 'function') { _Symbol = Symbol; } else { _Symbol = function (id) { return "Symbol(" + id + ")"; }; _Symbol["for"] = function (id) { return "Symbol(" + id + ")"; }; } /* eslint-disable */ function tryGetRequireFunction() { var nativeRequire; if (typeof __webpack_public_path__ !== 'undefined') { nativeRequire = (function () { return typeof __non_webpack_require__ !== 'undefined' ? __non_webpack_require__ : undefined; })(); } else { nativeRequire = (function () { return typeof __webpack_public_path__ !== 'undefined' ? (typeof __non_webpack_require__ !== 'undefined' ? __non_webpack_require__ : undefined) : (typeof require !== 'undefined' ? require : undefined); })(); } return nativeRequire; } var _require$1 = tryGetRequireFunction(); // eslint-disable-next-line @typescript-eslint/naming-convention var __Buffer; if (typeof _require$1 === 'function') { try { __Buffer = _require$1('buffer').Buffer; } catch (_) { } } function numberIsNaN(obj) { if (Number.isNaN) { return Number.isNaN(obj); } return typeof obj === 'number' && isNaN(obj); } var toString = Object.prototype.toString; function isArray(o) { if (Array.isArray) { return Array.isArray(o); } return (toString.call(o) === '[object Array]'); } function isBufferOrArray(o) { return (typeof Uint8Array !== 'undefined' && o instanceof Uint8Array) || (toString.call(o) === '[object Uint8Array]') || isArray(o); } function bufferAlloc(len) { if (__Buffer) { return __Buffer.alloc(len); } var i; if (typeof Uint8Array !== 'undefined') { return new Uint8Array(len); } var arr = []; for (i = 0; i < len; i++) { arr[i] = 0; } return arr; } function bufferFrom(buf) { var _a; if (__Buffer) { return __Buffer.from(buf); } var i; if (typeof ArrayBuffer === 'function') { if (buf instanceof ArrayBuffer) { return new Uint8Array(buf); } if (((_a = ArrayBuffer.isView) === null || _a === void 0 ? void 0 : _a.call(ArrayBuffer, buf)) || buf instanceof Uint8Array) { if (typeof Uint8Array.from === 'function') { return Uint8Array.from(buf); } else { var origin_1 = new Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength); var uint8arr = new Uint8Array(buf.byteLength); for (i = 0; i < buf.byteLength; i++) { uint8arr[i] = origin_1[i]; } return uint8arr; } } if (isArray(buf)) { if (typeof Uint8Array.from === 'function') { return Uint8Array.from(buf); } else { return new Uint8Array(buf); } } if (typeof buf === 'string') { var bytes = utf8ToBytes(buf); return bufferFrom(bytes); } } if (typeof buf === 'string') { return utf8ToBytes(buf); } var arr = []; for (i = 0; i < buf.length; i++) { arr[i] = buf[i]; } return arr; } function bufferFromHex(buf) { if (__Buffer) { return __Buffer.from(buf, 'hex'); } var arr; if (typeof Uint8Array === 'function') { arr = new Uint8Array(Math.floor(buf.length / 2)); } else { arr = new Array(Math.floor(buf.length / 2)); } hexWrite(arr, buf); for (var i = 0; i < arr.length; i++) { arr[i] = parseInt(buf.substring(i * 2, i * 2 + 2), 16); } return arr; } function readUInt32BE(offset) { if (offset === void 0) { offset = 0; } if (__Buffer === null || __Buffer === void 0 ? void 0 : __Buffer.isBuffer(this)) { return this.readUInt32BE(offset); } var type = typeof offset; if (type !== 'number') { throw new TypeError('The offset argument must be of type number. Received type ' + type); } var first = this[offset]; var last = this[offset + 3]; if (first === undefined || last === undefined) { throw new RangeError('Attempt to write outside buffer bounds'); } return first * Math.pow(2, 24) + this[++offset] * Math.pow(2, 16) + this[++offset] * Math.pow(2, 8) + last; } function readInt32BE(offset) { if (offset === void 0) { offset = 0; } if (__Buffer === null || __Buffer === void 0 ? void 0 : __Buffer.isBuffer(this)) { return this.readInt32BE(offset); } var type = typeof offset; if (type !== 'number') { throw new TypeError('The offset argument must be of type number. Received type ' + type); } var first = this[offset]; var last = this[offset + 3]; if (first === undefined || last === undefined) { throw new RangeError('Attempt to write outside buffer bounds'); } return (first << 24) + // Overflow this[++offset] * Math.pow(2, 16) + this[++offset] * Math.pow(2, 8) + last; } function checkInt(value, min, max, buf, offset, byteLength) { if (value > max || value < min) { var n = typeof min === 'bigint' ? 'n' : ''; var range = void 0; if (byteLength > 3) { if (min === 0 || (typeof BigInt === 'function' ? (BigInt(min) === BigInt(0)) : false)) { range = ">= 0" + n + " and < 2" + n + " ** " + (byteLength + 1) * 8 + n; } else { range = ">= -(2" + n + " ** " + ((byteLength + 1) * 8 - 1) + n + ") and < 2 ** " + ("" + ((byteLength + 1) * 8 - 1) + n); } } else { range = ">= " + min + n + " and <= " + max + n; } throw new RangeError('value' + range); } if (buf[offset] === undefined || buf[offset + byteLength] === undefined) { throw new RangeError('Attempt to write outside buffer bounds'); } } // eslint-disable-next-line @typescript-eslint/naming-convention function writeU_Int32BE(buf, value, offset, min, max) { value = +value; checkInt(value, min, max, buf, offset, 3); buf[offset + 3] = value & 0xff; value = value >>> 8; buf[offset + 2] = value & 0xff; value = value >>> 8; buf[offset + 1] = value & 0xff; value = value >>> 8; buf[offset] = value & 0xff; return offset + 4; } function writeUInt32BE(value, offset) { if (offset === void 0) { offset = 0; } return writeU_Int32BE(this, value, offset, 0, 0xffffffff); } function bufferEquals(target) { if (!isBufferOrArray(target)) { throw new TypeError('The "target" argument must be one of type Buffer or Uint8Array. ' + 'Received type ' + (typeof target)); } if (this === target) return true; if (this.length !== target.length) return false; for (var i = 0; i < this.length; i++) { if (this[i] !== target[i]) return false; } return true; } function bufferToString(encoding) { if (__Buffer) { return __Buffer.from(this).toString(encoding); } var res = ''; var i = 0; if (encoding === 'hex') { res = ''; for (i = 0; i < this.length; i++) { var hex = this[i].toString(16); res += (hex.length === 1 ? ('0' + hex) : hex); } return res; } else if (encoding === 'binary' || encoding === 'latin1') { res = ''; for (i = 0; i < this.length; i++) { res += String.fromCharCode((this[i] >>> 0) & 0xff); } return res; } else { var out = void 0, c = void 0; var char2 = void 0, char3 = void 0; out = ''; var len = this.length; i = 0; while (i < len) { c = this[i++]; switch (c >> 4) { case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: // 0xxxxxxx out += String.fromCharCode(c); break; case 12: case 13: // 110x xxxx 10xx xxxx char2 = this[i++]; out += String.fromCharCode(((c & 0x1F) << 6) | (char2 & 0x3F)); break; case 14: // 1110 xxxx 10xx xxxx 10xx xxxx char2 = this[i++]; char3 = this[i++]; out += String.fromCharCode(((c & 0x0F) << 12) | ((char2 & 0x3F) << 6) | ((char3 & 0x3F) << 0)); break; } } return out; } } function utf8ToBytes(string, units) { if (units === void 0) { units = Infinity; } var codePoint; var length = string.length; var leadSurrogate = null; var bytes = []; for (var i = 0; i < length; ++i) { codePoint = string.charCodeAt(i); // is surrogate component if (codePoint > 0xD7FF && codePoint < 0xE000) { // last char was a lead if (!leadSurrogate) { // no lead yet if (codePoint > 0xDBFF) { // unexpected trail if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD); continue; } else if (i + 1 === length) { // unpaired lead if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD); continue; } // valid lead leadSurrogate = codePoint; continue; } // 2 leads in a row if (codePoint < 0xDC00) { if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD); leadSurrogate = codePoint; continue; } // valid surrogate pair codePoint = (leadSurrogate - 0xD800 << 10 | codePoint - 0xDC00) + 0x10000; } else if (leadSurrogate) { // valid bmp char, but last char was a lead if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD); } leadSurrogate = null; // encode utf8 if (codePoint < 0x80) { if ((units -= 1) < 0) break; bytes.push(codePoint); } else if (codePoint < 0x800) { if ((units -= 2) < 0) break; bytes.push(codePoint >> 0x6 | 0xC0, codePoint & 0x3F | 0x80); } else if (codePoint < 0x10000) { if ((units -= 3) < 0) break; bytes.push(codePoint >> 0xC | 0xE0, codePoint >> 0x6 & 0x3F | 0x80, codePoint & 0x3F | 0x80); } else if (codePoint < 0x110000) { if ((units -= 4) < 0) break; bytes.push(codePoint >> 0x12 | 0xF0, codePoint >> 0xC & 0x3F | 0x80, codePoint >> 0x6 & 0x3F | 0x80, codePoint & 0x3F | 0x80); } else { throw new Error('Invalid code point'); } } return bytes; } function hexWrite(buf, string, offset) { if (offset === void 0) { offset = 0; } var remaining = buf.length - offset; var length = remaining; var strLen = string.length; if (length > strLen / 2) { length = strLen / 2; } var i; for (i = 0; i < length; ++i) { var parsed = parseInt(string.substring(i * 2, i * 2 + 2), 16); if (numberIsNaN(parsed)) return i; buf[offset + i] = parsed; } return i; } var _require = tryGetRequireFunction(); var isReactNative = typeof navigator === 'object' && navigator.product === 'ReactNative'; var insecureWarning = isReactNative ? 'BSON: For React Native please polyfill crypto.getRandomValues, e.g. using: https://www.npmjs.com/package/react-native-get-random-values.' : 'BSON: No cryptographic implementation for random bytes present, falling back to a less secure implementation.'; var insecureRandomBytes = function insecureRandomBytes(size) { if (typeof console !== 'undefined') console.warn(insecureWarning); var result = bufferAlloc(size); for (var i = 0; i < size; ++i) result[i] = Math.floor(Math.random() * 256); return result; }; var detectRandomBytes = function () { if (typeof window !== 'undefined') { // browser crypto implementation(s) var target_1 = window.crypto || window.msCrypto; // allow for IE11 if (target_1 === null || target_1 === void 0 ? void 0 : target_1.getRandomValues) { return function (size) { return target_1.getRandomValues(new Uint8Array(size)); }; } } if (typeof crypto !== 'undefined' && crypto.getRandomValues) { // allow for RN packages such as https://www.npmjs.com/package/react-native-get-random-values to populate global return function (size) { return crypto.getRandomValues(new Uint8Array(size)); }; } var requiredRandomBytes; try { // eslint-disable-next-line @typescript-eslint/no-var-requires requiredRandomBytes = _require('crypto').randomBytes; } catch (e) { // keep the fallback } // NOTE: in transpiled cases the above require might return null/undefined return requiredRandomBytes !== null && requiredRandomBytes !== void 0 ? requiredRandomBytes : insecureRandomBytes; }; var randomBytes = detectRandomBytes(); function isAnyArrayBuffer(value) { return ['[object ArrayBuffer]', '[object SharedArrayBuffer]'].indexOf(Object.prototype.toString.call(value)) !== -1; } function deprecate(fn, message) { if (typeof _require === 'function') { return _require('util').deprecate(fn, message); } var warned = false; function deprecated() { var args = []; for (var _i = 0; _i < arguments.length; _i++) { args[_i] = arguments[_i]; } if (!warned) { if (typeof console !== 'undefined') console.warn(message); warned = true; } return fn.apply(this, args); } return deprecated; } /** * Makes sure that, if a Uint8Array is passed in, it is wrapped in a Buffer. * * @param potentialBuffer - The potential buffer * @returns Buffer the input if potentialBuffer is a buffer, or a buffer that * wraps a passed in Uint8Array * @throws TypeError If anything other than a Buffer or Uint8Array is passed in */ function ensureBuffer(potentialBuffer) { var _a; if ((typeof ArrayBuffer === 'function' && typeof Uint8Array === 'function') && (((_a = ArrayBuffer.isView) === null || _a === void 0 ? void 0 : _a.call(ArrayBuffer, potentialBuffer)) || potentialBuffer instanceof Uint8Array)) { return new Uint8Array(potentialBuffer.buffer, potentialBuffer.byteOffset, potentialBuffer.byteLength); } if (isAnyArrayBuffer(potentialBuffer)) { return bufferFrom(potentialBuffer); } throw new TypeError('Must use either ArrayBuffer or TypedArray'); } // eslint-disable-next-line spaced-comment var supportDefineProperty = (function () { try { Object.defineProperty({}, 'a', { value: 0 }); return true; } catch (_) { return false; } })(); // eslint-disable-next-line spaced-comment var defValue = (function () { return supportDefineProperty ? function (obj, key, desc) { return Object.defineProperty(obj, key, desc); } : function (obj, key, desc) { obj[key] = desc.value; return obj; }; })(); // constants var PROCESS_UNIQUE = randomBytes(5); // Regular expression that checks for hex value var checkForHexRegExp = /^[0-9a-fA-F]{24}$/; // Precomputed hex table enables speedy hex string conversion var hexTable = []; for (var i_1 = 0; i_1 < 256; i_1++) { hexTable[i_1] = (i_1 <= 15 ? '0' : '') + i_1.toString(16); } // Lookup tables var decodeLookup = []; var i = 0; while (i < 10) decodeLookup[0x30 + i] = i++; while (i < 16) decodeLookup[0x41 - 10 + i] = decodeLookup[0x61 - 10 + i] = i++; var kId = _Symbol('id'); /** * A class representation of the BSON ObjectId type. * @public */ var ObjectId = /*#__PURE__*/ (function () { /** * Create an ObjectId type * * @param id - Can be a 24 character hex string, 12 byte binary Buffer, or a number. */ function ObjectId(id) { var _a; if (!(this instanceof ObjectId)) return new ObjectId(id); // Duck-typing to support ObjectId from different npm packages if (id instanceof ObjectId) { this[kId] = id.id; if ('__id' in id) { this.__id = id.__id; } } if (typeof id === 'object' && id && 'id' in id) { if ('toHexString' in id && typeof id.toHexString === 'function') { this[kId] = bufferFromHex(id.toHexString()); } else { this[kId] = typeof id.id === 'string' ? bufferFrom(id.id) : id.id; } } // The most common use case (blank id, new objectId instance) if (id == null || typeof id === 'number') { // Generate a new id this[kId] = ObjectId.generate(typeof id === 'number' ? id : undefined); // If we are caching the hex string if (ObjectId.cacheHexString) { this.__id = bufferToString.call(this.id, 'hex'); } } if (typeof ArrayBuffer === 'function' ? ((((_a = ArrayBuffer.isView) === null || _a === void 0 ? void 0 : _a.call(ArrayBuffer, id)) || id instanceof Uint8Array) && id.byteLength === 12) : false) { this[kId] = ensureBuffer(id); } if (isBufferOrArray(id)) { if (id.length === 12) { this[kId] = bufferFrom(id); } else { throw new TypeError('Argument passed in must be a Buffer or string of 12 bytes or a string of 24 hex characters'); } } if (typeof id === 'string') { if (id.length === 12) { var bytes = bufferFrom(id); if (bytes.length === 12) { this[kId] = bytes; } else { throw new TypeError('Argument passed in must be a Buffer or string of 12 bytes or a string of 24 hex characters'); } } else if (id.length === 24 && checkForHexRegExp.test(id)) { this[kId] = bufferFromHex(id); } else { throw new TypeError('Argument passed in must be a Buffer or string of 12 bytes or a string of 24 hex characters'); } } if (!supportDefineProperty) { this.id = this[kId]; this.generationTime = readInt32BE.call(this.id, 0); } if (ObjectId.cacheHexString) { this.__id = bufferToString.call(this.id, 'hex'); } } /** Returns the ObjectId id as a 24 character hex string representation */ ObjectId.prototype.toHexString = function () { if (ObjectId.cacheHexString && this.__id) { return this.__id; } var hexString = bufferToString.call(this.id, 'hex'); if (ObjectId.cacheHexString && !this.__id) { this.__id = hexString; } return hexString; }; /** * Update the ObjectId index * @privateRemarks * Used in generating new ObjectId's on the driver * @internal */ ObjectId.getInc = function () { return (ObjectId.index = (ObjectId.index + 1) % 0xffffff); }; /** * Generate a 12 byte id buffer used in ObjectId's * * @param time - pass in a second based timestamp. */ ObjectId.generate = function (time) { if (typeof time !== 'number') { time = ~~(Date.now() / 1000); } var inc = ObjectId.getInc(); var buffer = bufferAlloc(12); // 4-byte timestamp writeUInt32BE.call(buffer, time, 0); // 5-byte process unique buffer[4] = PROCESS_UNIQUE[0]; buffer[5] = PROCESS_UNIQUE[1]; buffer[6] = PROCESS_UNIQUE[2]; buffer[7] = PROCESS_UNIQUE[3]; buffer[8] = PROCESS_UNIQUE[4]; // 3-byte counter buffer[11] = inc & 0xff; buffer[10] = (inc >> 8) & 0xff; buffer[9] = (inc >> 16) & 0xff; return buffer; }; /** * Converts the id into a 24 character hex string for printing * * @param format - The Buffer toString format parameter. * @internal */ ObjectId.prototype.toString = function (format) { // Is the id a buffer then use the buffer toString method to return the format if (format) return bufferToString.call(this.id, format); return this.toHexString(); }; /** * Converts to its JSON the 24 character hex string representation. * @internal */ ObjectId.prototype.toJSON = function () { return this.toHexString(); }; /** * Compares the equality of this ObjectId with `otherID`. * * @param otherId - ObjectId instance to compare against. */ ObjectId.prototype.equals = function (otherId) { if (otherId === undefined || otherId === null) { return false; } if (otherId instanceof ObjectId) { return this.toString() === otherId.toString(); } if (typeof otherId === 'string' && ObjectId.isValid(otherId) && otherId.length === 12 && isBufferOrArray(this.id)) { return otherId === bufferToString.call(this.id, 'latin1'); } if (typeof otherId === 'string' && ObjectId.isValid(otherId) && otherId.length === 24) { return otherId.toLowerCase() === this.toHexString(); } if (typeof otherId === 'string' && ObjectId.isValid(otherId) && otherId.length === 12) { return bufferEquals.call(bufferFrom(otherId), this.id); } if (typeof otherId === 'object' && 'toHexString' in otherId && typeof otherId.toHexString === 'function') { return otherId.toHexString() === this.toHexString(); } return false; }; /** Returns the generation date (accurate up to the second) that this ID was generated. */ ObjectId.prototype.getTimestamp = function () { var timestamp = new Date(); var time = readUInt32BE.call(this.id, 0); timestamp.setTime(Math.floor(time) * 1000); return timestamp; }; /** @internal */ ObjectId.createPk = function () { return new ObjectId(); }; /** * Creates an ObjectId from a second based number, with the rest of the ObjectId zeroed out. Used for comparisons or sorting the ObjectId. * * @param time - an integer number representing a number of seconds. */ ObjectId.createFromTime = function (time) { var buffer = bufferFrom([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]); // Encode time into first 4 bytes writeUInt32BE.call(buffer, time, 0); // Return the new objectId return new ObjectId(buffer); }; /** * Creates an ObjectId from a hex string representation of an ObjectId. * * @param hexString - create a ObjectId from a passed in 24 character hexstring. */ ObjectId.createFromHexString = function (hexString) { // Throw an error if it's not a valid setup if (typeof hexString === 'undefined' || (hexString != null && hexString.length !== 24)) { throw new TypeError('Argument passed in must be a single String of 12 bytes or a string of 24 hex characters'); } return new ObjectId(bufferFromHex(hexString)); }; /** * Checks if a value is a valid bson ObjectId * * @param id - ObjectId instance to validate. */ ObjectId.isValid = function (id) { if (id == null) return false; if (typeof id === 'number') { return true; } if (typeof id === 'string') { return id.length === 12 || (id.length === 24 && checkForHexRegExp.test(id)); } if (id instanceof ObjectId) { return true; } if (isBufferOrArray(id) && id.length === 12) { return true; } // Duck-Typing detection of ObjectId like objects if (typeof id === 'object' && 'toHexString' in id && typeof id.toHexString === 'function') { if (typeof id.id === 'string') { return id.id.length === 12; } return id.toHexString().length === 24 && checkForHexRegExp.test(bufferToString.call(id.id, 'hex')); } return false; }; /** @internal */ ObjectId.prototype.toExtendedJSON = function () { if (this.toHexString) return { $oid: this.toHexString() }; return { $oid: this.toString('hex') }; }; /** @internal */ ObjectId.fromExtendedJSON = function (doc) { return new ObjectId(doc.$oid); }; /** * Converts to a string representation of this Id. * * @returns return the 24 character hex string representation. * @internal */ ObjectId.prototype[_Symbol["for"]('nodejs.util.inspect.custom')] = function () { return this.inspect(); }; ObjectId.prototype.inspect = function () { return "new ObjectId(\"" + this.toHexString() + "\")"; }; /** @internal */ ObjectId.index = ~~(Math.random() * 0xffffff); return ObjectId; }()); try { Object.defineProperty(ObjectId.prototype, 'id', { configurable: true, enumerable: true, get: function () { return this[kId]; }, set: function (value) { this[kId] = value; if (ObjectId.cacheHexString) { this.__id = bufferToString.call(value, 'hex'); } } }); Object.defineProperty(ObjectId.prototype, 'generationTime', { configurable: true, enumerable: true, get: function () { return readInt32BE.call(this.id, 0); }, set: function (value) { // Encode time into first 4 bytes writeUInt32BE.call(this.id, value, 0); } }); } catch (_) { } // Deprecated methods defValue(ObjectId.prototype, 'generate', { value: deprecate(function (time) { return ObjectId.generate(time); }, 'Please use the static `ObjectId.generate(time)` instead') }); defValue(ObjectId.prototype, 'getInc', { value: deprecate(function () { return ObjectId.getInc(); }, 'Please use the static `ObjectId.getInc()` instead') }); defValue(ObjectId.prototype, 'get_inc', { value: deprecate(function () { return ObjectId.getInc(); }, 'Please use the static `ObjectId.getInc()` instead') }); defValue(ObjectId, 'get_inc', { value: deprecate(function () { return ObjectId.getInc(); }, 'Please use the static `ObjectId.getInc()` instead') }); defValue(ObjectId.prototype, '_bsontype', { value: 'ObjectID' }); exports.ObjectId = ObjectId; try{Object.defineProperty(exports,'__esModule',{value:true})}catch(_){exports.__esModule=true} })));