babymongo 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +27 -0
- package/README.md +712 -0
- package/dist/babymongo-browser.min.js +2 -0
- package/dist/babymongo-browser.min.js.map +1 -0
- package/dist/babymongo-node.min.js +2 -0
- package/dist/babymongo-node.min.js.map +1 -0
- package/dist/babymongo-server-worker.js +2 -0
- package/dist/babymongo-server-worker.js.map +1 -0
- package/package.json +70 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"babymongo-server-worker.js","sources":["../node_modules/events/events.js","../node_modules/@belteshazzar/binjson/src/binjson.js","../src/utils.js","../src/errors.js","../src/server/Cursor.js","../src/server/SortedCursor.js","../node_modules/stemmer/index.js","../node_modules/@belteshazzar/binjson/src/bplustree.js","../node_modules/@belteshazzar/binjson/src/textindex.js","../src/server/aggregationExpressions.js","../src/server/queryMatcher.js","../src/server/updates.js","../src/server/indexes/Index.js","../src/server/opfsVersioning.js","../src/server/indexes/RegularCollectionIndex.js","../src/server/indexes/TextCollectionIndex.js","../node_modules/@belteshazzar/binjson/src/rtree.js","../src/server/indexes/GeospatialIndex.js","../src/server/QueryPlanner.js","../src/server/ChangeStream.js","../src/PerformanceTimer.js","../src/server/Collection.js","../src/server/DB.js","../src/server/Server.js","../src/server/ServerWorker.js"],"sourcesContent":["// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// copy of this software and associated documentation files (the\n// \"Software\"), to deal in the Software without restriction, including\n// without limitation the rights to use, copy, modify, merge, publish,\n// distribute, sublicense, and/or sell copies of the Software, and to permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n'use strict';\n\nvar R = typeof Reflect === 'object' ? Reflect : null\nvar ReflectApply = R && typeof R.apply === 'function'\n ? R.apply\n : function ReflectApply(target, receiver, args) {\n return Function.prototype.apply.call(target, receiver, args);\n }\n\nvar ReflectOwnKeys\nif (R && typeof R.ownKeys === 'function') {\n ReflectOwnKeys = R.ownKeys\n} else if (Object.getOwnPropertySymbols) {\n ReflectOwnKeys = function ReflectOwnKeys(target) {\n return Object.getOwnPropertyNames(target)\n .concat(Object.getOwnPropertySymbols(target));\n };\n} else {\n ReflectOwnKeys = function ReflectOwnKeys(target) {\n return Object.getOwnPropertyNames(target);\n };\n}\n\nfunction ProcessEmitWarning(warning) {\n if (console && console.warn) console.warn(warning);\n}\n\nvar NumberIsNaN = Number.isNaN || function NumberIsNaN(value) {\n return value !== value;\n}\n\nfunction EventEmitter() {\n EventEmitter.init.call(this);\n}\nmodule.exports = EventEmitter;\nmodule.exports.once = once;\n\n// Backwards-compat with node 0.10.x\nEventEmitter.EventEmitter = EventEmitter;\n\nEventEmitter.prototype._events = undefined;\nEventEmitter.prototype._eventsCount = 0;\nEventEmitter.prototype._maxListeners = undefined;\n\n// By default EventEmitters will print a warning if more than 10 listeners are\n// added to it. This is a useful default which helps finding memory leaks.\nvar defaultMaxListeners = 10;\n\nfunction checkListener(listener) {\n if (typeof listener !== 'function') {\n throw new TypeError('The \"listener\" argument must be of type Function. Received type ' + typeof listener);\n }\n}\n\nObject.defineProperty(EventEmitter, 'defaultMaxListeners', {\n enumerable: true,\n get: function() {\n return defaultMaxListeners;\n },\n set: function(arg) {\n if (typeof arg !== 'number' || arg < 0 || NumberIsNaN(arg)) {\n throw new RangeError('The value of \"defaultMaxListeners\" is out of range. It must be a non-negative number. Received ' + arg + '.');\n }\n defaultMaxListeners = arg;\n }\n});\n\nEventEmitter.init = function() {\n\n if (this._events === undefined ||\n this._events === Object.getPrototypeOf(this)._events) {\n this._events = Object.create(null);\n this._eventsCount = 0;\n }\n\n this._maxListeners = this._maxListeners || undefined;\n};\n\n// Obviously not all Emitters should be limited to 10. This function allows\n// that to be increased. Set to zero for unlimited.\nEventEmitter.prototype.setMaxListeners = function setMaxListeners(n) {\n if (typeof n !== 'number' || n < 0 || NumberIsNaN(n)) {\n throw new RangeError('The value of \"n\" is out of range. It must be a non-negative number. Received ' + n + '.');\n }\n this._maxListeners = n;\n return this;\n};\n\nfunction _getMaxListeners(that) {\n if (that._maxListeners === undefined)\n return EventEmitter.defaultMaxListeners;\n return that._maxListeners;\n}\n\nEventEmitter.prototype.getMaxListeners = function getMaxListeners() {\n return _getMaxListeners(this);\n};\n\nEventEmitter.prototype.emit = function emit(type) {\n var args = [];\n for (var i = 1; i < arguments.length; i++) args.push(arguments[i]);\n var doError = (type === 'error');\n\n var events = this._events;\n if (events !== undefined)\n doError = (doError && events.error === undefined);\n else if (!doError)\n return false;\n\n // If there is no 'error' event listener then throw.\n if (doError) {\n var er;\n if (args.length > 0)\n er = args[0];\n if (er instanceof Error) {\n // Note: The comments on the `throw` lines are intentional, they show\n // up in Node's output if this results in an unhandled exception.\n throw er; // Unhandled 'error' event\n }\n // At least give some kind of context to the user\n var err = new Error('Unhandled error.' + (er ? ' (' + er.message + ')' : ''));\n err.context = er;\n throw err; // Unhandled 'error' event\n }\n\n var handler = events[type];\n\n if (handler === undefined)\n return false;\n\n if (typeof handler === 'function') {\n ReflectApply(handler, this, args);\n } else {\n var len = handler.length;\n var listeners = arrayClone(handler, len);\n for (var i = 0; i < len; ++i)\n ReflectApply(listeners[i], this, args);\n }\n\n return true;\n};\n\nfunction _addListener(target, type, listener, prepend) {\n var m;\n var events;\n var existing;\n\n checkListener(listener);\n\n events = target._events;\n if (events === undefined) {\n events = target._events = Object.create(null);\n target._eventsCount = 0;\n } else {\n // To avoid recursion in the case that type === \"newListener\"! Before\n // adding it to the listeners, first emit \"newListener\".\n if (events.newListener !== undefined) {\n target.emit('newListener', type,\n listener.listener ? listener.listener : listener);\n\n // Re-assign `events` because a newListener handler could have caused the\n // this._events to be assigned to a new object\n events = target._events;\n }\n existing = events[type];\n }\n\n if (existing === undefined) {\n // Optimize the case of one listener. Don't need the extra array object.\n existing = events[type] = listener;\n ++target._eventsCount;\n } else {\n if (typeof existing === 'function') {\n // Adding the second element, need to change to array.\n existing = events[type] =\n prepend ? [listener, existing] : [existing, listener];\n // If we've already got an array, just append.\n } else if (prepend) {\n existing.unshift(listener);\n } else {\n existing.push(listener);\n }\n\n // Check for listener leak\n m = _getMaxListeners(target);\n if (m > 0 && existing.length > m && !existing.warned) {\n existing.warned = true;\n // No error code for this since it is a Warning\n // eslint-disable-next-line no-restricted-syntax\n var w = new Error('Possible EventEmitter memory leak detected. ' +\n existing.length + ' ' + String(type) + ' listeners ' +\n 'added. Use emitter.setMaxListeners() to ' +\n 'increase limit');\n w.name = 'MaxListenersExceededWarning';\n w.emitter = target;\n w.type = type;\n w.count = existing.length;\n ProcessEmitWarning(w);\n }\n }\n\n return target;\n}\n\nEventEmitter.prototype.addListener = function addListener(type, listener) {\n return _addListener(this, type, listener, false);\n};\n\nEventEmitter.prototype.on = EventEmitter.prototype.addListener;\n\nEventEmitter.prototype.prependListener =\n function prependListener(type, listener) {\n return _addListener(this, type, listener, true);\n };\n\nfunction onceWrapper() {\n if (!this.fired) {\n this.target.removeListener(this.type, this.wrapFn);\n this.fired = true;\n if (arguments.length === 0)\n return this.listener.call(this.target);\n return this.listener.apply(this.target, arguments);\n }\n}\n\nfunction _onceWrap(target, type, listener) {\n var state = { fired: false, wrapFn: undefined, target: target, type: type, listener: listener };\n var wrapped = onceWrapper.bind(state);\n wrapped.listener = listener;\n state.wrapFn = wrapped;\n return wrapped;\n}\n\nEventEmitter.prototype.once = function once(type, listener) {\n checkListener(listener);\n this.on(type, _onceWrap(this, type, listener));\n return this;\n};\n\nEventEmitter.prototype.prependOnceListener =\n function prependOnceListener(type, listener) {\n checkListener(listener);\n this.prependListener(type, _onceWrap(this, type, listener));\n return this;\n };\n\n// Emits a 'removeListener' event if and only if the listener was removed.\nEventEmitter.prototype.removeListener =\n function removeListener(type, listener) {\n var list, events, position, i, originalListener;\n\n checkListener(listener);\n\n events = this._events;\n if (events === undefined)\n return this;\n\n list = events[type];\n if (list === undefined)\n return this;\n\n if (list === listener || list.listener === listener) {\n if (--this._eventsCount === 0)\n this._events = Object.create(null);\n else {\n delete events[type];\n if (events.removeListener)\n this.emit('removeListener', type, list.listener || listener);\n }\n } else if (typeof list !== 'function') {\n position = -1;\n\n for (i = list.length - 1; i >= 0; i--) {\n if (list[i] === listener || list[i].listener === listener) {\n originalListener = list[i].listener;\n position = i;\n break;\n }\n }\n\n if (position < 0)\n return this;\n\n if (position === 0)\n list.shift();\n else {\n spliceOne(list, position);\n }\n\n if (list.length === 1)\n events[type] = list[0];\n\n if (events.removeListener !== undefined)\n this.emit('removeListener', type, originalListener || listener);\n }\n\n return this;\n };\n\nEventEmitter.prototype.off = EventEmitter.prototype.removeListener;\n\nEventEmitter.prototype.removeAllListeners =\n function removeAllListeners(type) {\n var listeners, events, i;\n\n events = this._events;\n if (events === undefined)\n return this;\n\n // not listening for removeListener, no need to emit\n if (events.removeListener === undefined) {\n if (arguments.length === 0) {\n this._events = Object.create(null);\n this._eventsCount = 0;\n } else if (events[type] !== undefined) {\n if (--this._eventsCount === 0)\n this._events = Object.create(null);\n else\n delete events[type];\n }\n return this;\n }\n\n // emit removeListener for all listeners on all events\n if (arguments.length === 0) {\n var keys = Object.keys(events);\n var key;\n for (i = 0; i < keys.length; ++i) {\n key = keys[i];\n if (key === 'removeListener') continue;\n this.removeAllListeners(key);\n }\n this.removeAllListeners('removeListener');\n this._events = Object.create(null);\n this._eventsCount = 0;\n return this;\n }\n\n listeners = events[type];\n\n if (typeof listeners === 'function') {\n this.removeListener(type, listeners);\n } else if (listeners !== undefined) {\n // LIFO order\n for (i = listeners.length - 1; i >= 0; i--) {\n this.removeListener(type, listeners[i]);\n }\n }\n\n return this;\n };\n\nfunction _listeners(target, type, unwrap) {\n var events = target._events;\n\n if (events === undefined)\n return [];\n\n var evlistener = events[type];\n if (evlistener === undefined)\n return [];\n\n if (typeof evlistener === 'function')\n return unwrap ? [evlistener.listener || evlistener] : [evlistener];\n\n return unwrap ?\n unwrapListeners(evlistener) : arrayClone(evlistener, evlistener.length);\n}\n\nEventEmitter.prototype.listeners = function listeners(type) {\n return _listeners(this, type, true);\n};\n\nEventEmitter.prototype.rawListeners = function rawListeners(type) {\n return _listeners(this, type, false);\n};\n\nEventEmitter.listenerCount = function(emitter, type) {\n if (typeof emitter.listenerCount === 'function') {\n return emitter.listenerCount(type);\n } else {\n return listenerCount.call(emitter, type);\n }\n};\n\nEventEmitter.prototype.listenerCount = listenerCount;\nfunction listenerCount(type) {\n var events = this._events;\n\n if (events !== undefined) {\n var evlistener = events[type];\n\n if (typeof evlistener === 'function') {\n return 1;\n } else if (evlistener !== undefined) {\n return evlistener.length;\n }\n }\n\n return 0;\n}\n\nEventEmitter.prototype.eventNames = function eventNames() {\n return this._eventsCount > 0 ? ReflectOwnKeys(this._events) : [];\n};\n\nfunction arrayClone(arr, n) {\n var copy = new Array(n);\n for (var i = 0; i < n; ++i)\n copy[i] = arr[i];\n return copy;\n}\n\nfunction spliceOne(list, index) {\n for (; index + 1 < list.length; index++)\n list[index] = list[index + 1];\n list.pop();\n}\n\nfunction unwrapListeners(arr) {\n var ret = new Array(arr.length);\n for (var i = 0; i < ret.length; ++i) {\n ret[i] = arr[i].listener || arr[i];\n }\n return ret;\n}\n\nfunction once(emitter, name) {\n return new Promise(function (resolve, reject) {\n function errorListener(err) {\n emitter.removeListener(name, resolver);\n reject(err);\n }\n\n function resolver() {\n if (typeof emitter.removeListener === 'function') {\n emitter.removeListener('error', errorListener);\n }\n resolve([].slice.call(arguments));\n };\n\n eventTargetAgnosticAddListener(emitter, name, resolver, { once: true });\n if (name !== 'error') {\n addErrorHandlerIfEventEmitter(emitter, errorListener, { once: true });\n }\n });\n}\n\nfunction addErrorHandlerIfEventEmitter(emitter, handler, flags) {\n if (typeof emitter.on === 'function') {\n eventTargetAgnosticAddListener(emitter, 'error', handler, flags);\n }\n}\n\nfunction eventTargetAgnosticAddListener(emitter, name, listener, flags) {\n if (typeof emitter.on === 'function') {\n if (flags.once) {\n emitter.once(name, listener);\n } else {\n emitter.on(name, listener);\n }\n } else if (typeof emitter.addEventListener === 'function') {\n // EventTarget does not have `error` event semantics like Node\n // EventEmitters, we do not listen for `error` events here.\n emitter.addEventListener(name, function wrapListener(arg) {\n // IE does not have builtin `{ once: true }` support so we\n // have to do it manually.\n if (flags.once) {\n emitter.removeEventListener(name, wrapListener);\n }\n listener(arg);\n });\n } else {\n throw new TypeError('The \"emitter\" argument must be of type EventEmitter. Received type ' + typeof emitter);\n }\n}\n","/**\n * Binary JSON Encoder/Decoder\n * \n * Encodes JavaScript values to a compact binary format compatible with\n * Origin Private File System (OPFS).\n */\n\nconst TYPE = {\n NULL: 0x00,\n FALSE: 0x01,\n TRUE: 0x02,\n INT: 0x03,\n FLOAT: 0x04,\n STRING: 0x05,\n OID: 0x06,\n DATE: 0x07,\n POINTER: 0x08,\n BINARY: 0x09,\n ARRAY: 0x10,\n OBJECT: 0x11\n};\n\n\n/**\n * ObjectId class - MongoDB-compatible 24-character hex string identifier\n * Format: 8-char timestamp + 16-char random data\n */\nclass ObjectId {\n constructor(id) {\n if (id === undefined || id === null) {\n // Generate new ObjectId\n this.id = ObjectId.generate();\n } else if (typeof id === 'string') {\n // Create from hex string\n if (!ObjectId.isValid(id)) {\n throw new Error(`Argument passed in must be a string of 24 hex characters, got: ${id}`);\n }\n this.id = id.toLowerCase();\n } else if (id instanceof Uint8Array && id.length === 12) {\n this.id = Array.from(id).map(b => b.toString(16).padStart(2, '0')).join('');\n } else if (id instanceof ObjectId) {\n // Copy constructor\n this.id = id.id;\n } else {\n throw new Error(`Argument passed in must be a string of 24 hex characters or an ObjectId`);\n }\n }\n\n /**\n * Returns the ObjectId as a 24-character hex string\n */\n toString() {\n return this.id;\n }\n\n /**\n * Returns the ObjectId as a 24-character hex string (alias for toString)\n */\n toHexString() {\n return this.id;\n }\n\n /**\n * Returns the timestamp portion of the ObjectId as a Date\n */\n getTimestamp() {\n const timestamp = parseInt(this.id.substring(0, 8), 16);\n return new Date(timestamp * 1000);\n }\n\n equals(other) {\n if (!(other instanceof ObjectId)) {\n throw new Error('Can only compare with another ObjectId');\n }\n return this.id === other.id;\n }\n\n /**\n * Compares this ObjectId with another for equality\n */\n compare(other) {\n if (!(other instanceof ObjectId)) {\n throw new Error('Can only compare with another ObjectId');\n }\n\n return this.id.localeCompare(other.id);\n }\n\n /**\n * Returns the ObjectId in JSON format (as hex string)\n */\n toJSON() {\n return this.id;\n }\n\n /**\n * Custom inspect for Node.js console.log\n */\n inspect() {\n return `ObjectId(\"${this.id}\")`;\n }\n\n toBytes() {\n const bytes = new Uint8Array(12);\n for (let i = 0; i < 12; i++) {\n bytes[i] = parseInt(this.id.substring(i * 2, i * 2 + 2), 16);\n }\n return bytes;\n }\n\n /**\n * Validates if a string is a valid ObjectId hex string\n */\n static isValid(id) {\n if (!id) return false;\n if (typeof id !== 'string') return false;\n if (id.length !== 24) return false;\n return /^[0-9a-fA-F]{24}$/.test(id);\n }\n\n /**\n * Creates an ObjectId from a timestamp\n */\n static createFromTime(timestamp) {\n const ts = Math.floor(timestamp / 1000);\n const tsHex = ('00000000' + ts.toString(16)).slice(-8);\n const tail = '0000000000000000'; // Zero out the random portion\n return new ObjectId(tsHex + tail);\n }\n\n /**\n * Generates a new ObjectId hex string\n * Format: 8-char timestamp (4 bytes) + 16-char random data (8 bytes)\n */\n static generate() {\n const ts = Math.floor(Date.now() / 1000);\n \n // Generate 8 random bytes\n const rand = typeof crypto !== 'undefined' && crypto.getRandomValues ? new Uint8Array(8) : null;\n let tail = '';\n \n if (rand) {\n crypto.getRandomValues(rand);\n for (let i = 0; i < rand.length; i++) {\n tail += ('0' + rand[i].toString(16)).slice(-2);\n }\n } else {\n // Fallback for environments without crypto\n // Generate two 8-character hex strings\n tail = Math.random().toString(16).slice(2).padEnd(8, '0').slice(0, 8) +\n Math.random().toString(16).slice(2).padEnd(8, '0').slice(0, 8);\n }\n \n const tsHex = ('00000000' + ts.toString(16)).slice(-8);\n return (tsHex + tail).slice(0, 24);\n }\n}\n\n/**\n * Pointer class - represents a 64-bit file offset pointer\n * Used to store file offsets for referenced data structures\n */\nclass Pointer {\n constructor(offset) {\n if (offset === undefined || offset === null) {\n throw new Error('Pointer offset must be a number');\n }\n if (typeof offset !== 'number') {\n throw new Error('Pointer offset must be a number');\n }\n if (!Number.isInteger(offset)) {\n throw new Error('Pointer offset must be an integer');\n }\n if (offset < 0) {\n throw new Error('Pointer offset must be non-negative');\n }\n if (offset > Number.MAX_SAFE_INTEGER) {\n throw new Error('Pointer offset exceeds maximum safe integer');\n }\n this.offset = offset;\n }\n\n /**\n * Returns the pointer offset as a number\n */\n valueOf() {\n return this.offset;\n }\n\n /**\n * Returns the pointer offset as a string\n */\n toString() {\n return this.offset.toString();\n }\n\n /**\n * Returns the pointer in JSON format (as number)\n */\n toJSON() {\n return this.offset;\n }\n\n /**\n * Custom inspect for Node.js console.log\n */\n inspect() {\n return `Pointer(${this.offset})`;\n }\n\n /**\n * Compares this Pointer with another for equality\n */\n equals(other) {\n if (!(other instanceof Pointer)) {\n return false;\n }\n return this.offset === other.offset;\n }\n}\n\n/**\n * Encode a JavaScript value to binary format\n */\nfunction encode(value) {\n const buffers = [];\n\n function encodeValue(val) {\n if (val === null) {\n buffers.push(new Uint8Array([TYPE.NULL]));\n } else if (val === false) {\n buffers.push(new Uint8Array([TYPE.FALSE]));\n } else if (val === true) {\n buffers.push(new Uint8Array([TYPE.TRUE]));\n } else if (val instanceof ObjectId) {\n buffers.push(new Uint8Array([TYPE.OID]));\n buffers.push(val.toBytes());\n } else if (val instanceof Date) {\n buffers.push(new Uint8Array([TYPE.DATE]));\n const buffer = new ArrayBuffer(8);\n const view = new DataView(buffer);\n view.setBigInt64(0, BigInt(val.getTime()), true); // little-endian\n buffers.push(new Uint8Array(buffer));\n } else if (val instanceof Pointer) {\n buffers.push(new Uint8Array([TYPE.POINTER]));\n const buffer = new ArrayBuffer(8);\n const view = new DataView(buffer);\n view.setBigUint64(0, BigInt(val.offset), true); // little-endian\n buffers.push(new Uint8Array(buffer));\n } else if (val instanceof Uint8Array) {\n buffers.push(new Uint8Array([TYPE.BINARY]));\n // Store length as 32-bit integer\n const lengthBuffer = new ArrayBuffer(4);\n const lengthView = new DataView(lengthBuffer);\n lengthView.setUint32(0, val.length, true);\n buffers.push(new Uint8Array(lengthBuffer));\n buffers.push(val);\n } else if (typeof val === 'number') {\n if (Number.isInteger(val) && Number.isSafeInteger(val)) {\n // 64-bit signed integer (stored as BigInt64)\n buffers.push(new Uint8Array([TYPE.INT]));\n const buffer = new ArrayBuffer(8);\n const view = new DataView(buffer);\n view.setBigInt64(0, BigInt(val), true); // little-endian\n buffers.push(new Uint8Array(buffer));\n } else {\n // 64-bit float\n buffers.push(new Uint8Array([TYPE.FLOAT]));\n const buffer = new ArrayBuffer(8);\n const view = new DataView(buffer);\n view.setFloat64(0, val, true); // little-endian\n buffers.push(new Uint8Array(buffer));\n }\n } else if (typeof val === 'string') {\n buffers.push(new Uint8Array([TYPE.STRING]));\n const encoded = new TextEncoder().encode(val);\n // Store length as 32-bit integer\n const lengthBuffer = new ArrayBuffer(4);\n const lengthView = new DataView(lengthBuffer);\n lengthView.setUint32(0, encoded.length, true);\n buffers.push(new Uint8Array(lengthBuffer));\n buffers.push(encoded);\n } else if (Array.isArray(val)) {\n // Encode array to temporary buffer to determine size\n const tempBuffers = [];\n \n // Store array length as 32-bit integer\n const lengthBuffer = new ArrayBuffer(4);\n const lengthView = new DataView(lengthBuffer);\n lengthView.setUint32(0, val.length, true);\n tempBuffers.push(new Uint8Array(lengthBuffer));\n \n // Encode each element into temp buffer\n const startLength = buffers.length;\n for (const item of val) {\n encodeValue(item);\n }\n // Collect encoded elements\n const elementBuffers = buffers.splice(startLength);\n tempBuffers.push(...elementBuffers);\n \n // Calculate total size of array content\n const contentSize = tempBuffers.reduce((sum, buf) => sum + buf.length, 0);\n \n // Now write: TYPE + SIZE + CONTENT\n buffers.push(new Uint8Array([TYPE.ARRAY]));\n const sizeBuffer = new ArrayBuffer(4);\n const sizeView = new DataView(sizeBuffer);\n sizeView.setUint32(0, contentSize, true);\n buffers.push(new Uint8Array(sizeBuffer));\n buffers.push(...tempBuffers);\n } else if (typeof val === 'object') {\n // Encode object to temporary buffer to determine size\n const tempBuffers = [];\n \n const keys = Object.keys(val);\n // Store number of keys as 32-bit integer\n const lengthBuffer = new ArrayBuffer(4);\n const lengthView = new DataView(lengthBuffer);\n lengthView.setUint32(0, keys.length, true);\n tempBuffers.push(new Uint8Array(lengthBuffer));\n \n // Encode each key-value pair into temp buffer\n const startLength = buffers.length;\n for (const key of keys) {\n // Encode key as string (without type byte)\n const encoded = new TextEncoder().encode(key);\n const keyLengthBuffer = new ArrayBuffer(4);\n const keyLengthView = new DataView(keyLengthBuffer);\n keyLengthView.setUint32(0, encoded.length, true);\n buffers.push(new Uint8Array(keyLengthBuffer));\n buffers.push(encoded);\n // Encode value\n encodeValue(val[key]);\n }\n // Collect encoded key-value pairs\n const kvBuffers = buffers.splice(startLength);\n tempBuffers.push(...kvBuffers);\n \n // Calculate total size of object content\n const contentSize = tempBuffers.reduce((sum, buf) => sum + buf.length, 0);\n \n // Now write: TYPE + SIZE + CONTENT\n buffers.push(new Uint8Array([TYPE.OBJECT]));\n const sizeBuffer = new ArrayBuffer(4);\n const sizeView = new DataView(sizeBuffer);\n sizeView.setUint32(0, contentSize, true);\n buffers.push(new Uint8Array(sizeBuffer));\n buffers.push(...tempBuffers);\n } else {\n throw new Error(`Unsupported type: ${typeof val}`);\n }\n }\n\n encodeValue(value);\n\n // Combine all buffers\n const totalLength = buffers.reduce((sum, buf) => sum + buf.length, 0);\n const result = new Uint8Array(totalLength);\n let offset = 0;\n for (const buf of buffers) {\n result.set(buf, offset);\n offset += buf.length;\n }\n\n return result;\n}\n\n/**\n * Decode binary data to JavaScript value\n */\nfunction decode(data) {\n let offset = 0;\n\n function decodeValue() {\n if (offset >= data.length) {\n throw new Error('Unexpected end of data');\n }\n\n const type = data[offset++];\n\n switch (type) {\n case TYPE.NULL:\n return null;\n \n case TYPE.FALSE:\n return false;\n \n case TYPE.TRUE:\n return true;\n \n case TYPE.INT: {\n if (offset + 4 > data.length) {\n throw new Error('Unexpected end of data for INT');\n }\n const view = new DataView(data.buffer, data.byteOffset + offset, 8);\n const value = view.getBigInt64(0, true);\n offset += 8;\n if (value < BigInt(Number.MIN_SAFE_INTEGER) || value > BigInt(Number.MAX_SAFE_INTEGER)) {\n throw new Error('Decoded integer exceeds safe range');\n }\n return Number(value);\n }\n \n case TYPE.FLOAT: {\n if (offset + 8 > data.length) {\n throw new Error('Unexpected end of data for FLOAT');\n }\n const view = new DataView(data.buffer, data.byteOffset + offset, 8);\n const value = view.getFloat64(0, true);\n offset += 8;\n return value;\n }\n \n case TYPE.STRING: {\n if (offset + 4 > data.length) {\n throw new Error('Unexpected end of data for STRING length');\n }\n const lengthView = new DataView(data.buffer, data.byteOffset + offset, 4);\n const length = lengthView.getUint32(0, true);\n offset += 4;\n \n if (offset + length > data.length) {\n throw new Error('Unexpected end of data for STRING content');\n }\n const stringData = data.slice(offset, offset + length);\n offset += length;\n return new TextDecoder().decode(stringData);\n }\n \n case TYPE.OID: {\n if (offset + 12 > data.length) {\n throw new Error('Unexpected end of data for OID');\n }\n const oidBytes = data.slice(offset, offset + 12);\n offset += 12;\n return new ObjectId(oidBytes);\n }\n\n case TYPE.DATE: {\n if (offset + 8 > data.length) {\n throw new Error('Unexpected end of data for DATE');\n }\n const view = new DataView(data.buffer, data.byteOffset + offset, 8);\n const timestamp = view.getBigInt64(0, true);\n offset += 8;\n return new Date(Number(timestamp));\n }\n \n case TYPE.POINTER: {\n if (offset + 8 > data.length) {\n throw new Error('Unexpected end of data for POINTER');\n }\n const view = new DataView(data.buffer, data.byteOffset + offset, 8);\n const pointerOffset = view.getBigUint64(0, true);\n offset += 8;\n // Validate offset is within safe integer range\n if (pointerOffset > BigInt(Number.MAX_SAFE_INTEGER)) {\n throw new Error('Pointer offset out of valid range');\n }\n return new Pointer(Number(pointerOffset));\n }\n \n case TYPE.BINARY: {\n if (offset + 4 > data.length) {\n throw new Error('Unexpected end of data for BINARY length');\n }\n const lengthView = new DataView(data.buffer, data.byteOffset + offset, 4);\n const length = lengthView.getUint32(0, true);\n offset += 4;\n \n if (offset + length > data.length) {\n throw new Error('Unexpected end of data for BINARY content');\n }\n const binaryData = data.slice(offset, offset + length);\n offset += length;\n return binaryData;\n }\n \n case TYPE.ARRAY: {\n if (offset + 4 > data.length) {\n throw new Error('Unexpected end of data for ARRAY size');\n }\n // Read size in bytes\n const sizeView = new DataView(data.buffer, data.byteOffset + offset, 4);\n const size = sizeView.getUint32(0, true);\n offset += 4;\n \n if (offset + size > data.length) {\n throw new Error('Unexpected end of data for ARRAY content');\n }\n \n // Read array length\n const lengthView = new DataView(data.buffer, data.byteOffset + offset, 4);\n const length = lengthView.getUint32(0, true);\n offset += 4;\n \n const arr = [];\n for (let i = 0; i < length; i++) {\n arr.push(decodeValue());\n }\n return arr;\n }\n \n case TYPE.OBJECT: {\n if (offset + 4 > data.length) {\n throw new Error('Unexpected end of data for OBJECT size');\n }\n // Read size in bytes\n const sizeView = new DataView(data.buffer, data.byteOffset + offset, 4);\n const size = sizeView.getUint32(0, true);\n offset += 4;\n \n if (offset + size > data.length) {\n throw new Error('Unexpected end of data for OBJECT content');\n }\n \n // Read number of keys\n const lengthView = new DataView(data.buffer, data.byteOffset + offset, 4);\n const length = lengthView.getUint32(0, true);\n offset += 4;\n \n const obj = {};\n for (let i = 0; i < length; i++) {\n // Decode key\n if (offset + 4 > data.length) {\n throw new Error('Unexpected end of data for OBJECT key length');\n }\n const keyLengthView = new DataView(data.buffer, data.byteOffset + offset, 4);\n const keyLength = keyLengthView.getUint32(0, true);\n offset += 4;\n \n if (offset + keyLength > data.length) {\n throw new Error('Unexpected end of data for OBJECT key');\n }\n const keyData = data.slice(offset, offset + keyLength);\n offset += keyLength;\n const key = new TextDecoder().decode(keyData);\n \n // Decode value\n obj[key] = decodeValue();\n }\n return obj;\n }\n \n default:\n throw new Error(`Unknown type byte: 0x${type.toString(16)}`);\n }\n }\n\n return decodeValue();\n}\n\n/**\n * OPFS File Operations using FileSystemSyncAccessHandle\n * \n * IMPORTANT: This class wraps FileSystemSyncAccessHandle which is only available\n * in Web Workers. It provides synchronous file operations with explicit flush control.\n */\nclass BinJsonFile {\n constructor(syncAccessHandle) {\n if (!syncAccessHandle) {\n throw new Error('FileSystemSyncAccessHandle is required');\n }\n this.syncAccessHandle = syncAccessHandle;\n }\n\n\n /**\n * Read a range of bytes from the file\n */\n #readRange(start, length) {\n const buffer = new Uint8Array(length);\n const bytesRead = this.syncAccessHandle.read(buffer, { at: start });\n if (bytesRead < length) {\n // Return only the bytes that were actually read\n return buffer.slice(0, bytesRead);\n }\n return buffer;\n }\n\n /**\n * Get the current file size\n */\n getFileSize() {\n return this.syncAccessHandle.getSize();\n }\n\n /**\n * Write data to file, truncating existing content\n * @param {*} data - Data to encode and write\n */\n write(data) {\n // Encode data to binary\n const binaryData = encode(data);\n \n // Truncate file to 0 bytes (clear existing content)\n this.syncAccessHandle.truncate(0);\n \n // Write data at beginning of file\n this.syncAccessHandle.write(binaryData, { at: 0 });\n }\n\n /**\n * Read and decode data from file starting at optional pointer offset\n * @param {Pointer} pointer - Optional offset to start reading from (default: 0)\n * @returns {*} - Decoded data\n */\n read(pointer = new Pointer(0)) {\n const fileSize = this.getFileSize();\n \n if (fileSize === 0) {\n throw new Error('File is empty');\n }\n\n const pointerValue = pointer.valueOf();\n \n // Validate pointer offset\n if (pointerValue < 0 || pointerValue >= fileSize) {\n throw new Error(`Pointer offset ${pointer} out of file bounds [0, ${fileSize})`);\n }\n \n // Read from pointer offset to end of file\n const binaryData = this.#readRange(pointerValue, fileSize - pointerValue);\n \n // Decode and return the first value\n return decode(binaryData);\n }\n\n /**\n * Append data to file without truncating existing content\n * @param {*} data - Data to encode and append\n */\n append(data) {\n // Encode new data to binary\n const binaryData = encode(data);\n \n // Get current file size\n const existingSize = this.getFileSize();\n \n // Write new data at end of file\n this.syncAccessHandle.write(binaryData, { at: existingSize });\n }\n\n /**\n * Explicitly flush any pending writes to disk\n */\n flush() {\n this.syncAccessHandle.flush();\n }\n\n /**\n * Generator to scan through all records in the file\n * Each record is decoded and yielded one at a time\n */\n *scan() {\n const fileSize = this.getFileSize();\n \n if (fileSize === 0) {\n return;\n }\n \n let offset = 0;\n \n // Scan through and yield each top-level value\n while (offset < fileSize) {\n // Helper function to determine how many bytes a value occupies\n const getValueSize = (readPosition) => {\n // Read 1 byte for type\n let tempData = this.#readRange(readPosition, 1);\n let pos = 1;\n const type = tempData[0];\n \n switch (type) {\n case TYPE.NULL:\n case TYPE.FALSE:\n case TYPE.TRUE:\n return 1;\n \n case TYPE.INT:\n case TYPE.FLOAT:\n case TYPE.DATE:\n case TYPE.POINTER:\n return 1 + 8;\n\n case TYPE.OID:\n return 1 + 12;\n \n case TYPE.STRING: {\n // Read length (4 bytes)\n tempData = this.#readRange(readPosition + 1, 4);\n const view = new DataView(tempData.buffer, tempData.byteOffset, 4);\n const length = view.getUint32(0, true);\n return 1 + 4 + length;\n }\n \n case TYPE.BINARY: {\n // Read length (4 bytes)\n tempData = this.#readRange(readPosition + 1, 4);\n const view = new DataView(tempData.buffer, tempData.byteOffset, 4);\n const length = view.getUint32(0, true);\n return 1 + 4 + length;\n }\n \n case TYPE.ARRAY: {\n // Read size in bytes (4 bytes)\n tempData = this.#readRange(readPosition + 1, 4);\n const view = new DataView(tempData.buffer, tempData.byteOffset, 4);\n const size = view.getUint32(0, true);\n return 1 + 4 + size; // type + size + content\n }\n \n case TYPE.OBJECT: {\n // Read size in bytes (4 bytes)\n tempData = this.#readRange(readPosition + 1, 4);\n const view = new DataView(tempData.buffer, tempData.byteOffset, 4);\n const size = view.getUint32(0, true);\n return 1 + 4 + size; // type + size + content\n }\n \n default:\n throw new Error(`Unknown type byte: 0x${type.toString(16)}`);\n }\n };\n \n // Determine size of the current value\n const valueSize = getValueSize(offset);\n \n // Read only the bytes needed for this value\n const valueData = this.#readRange(offset, valueSize);\n offset += valueSize;\n \n // Decode and yield this value\n yield decode(valueData);\n }\n }\n}\n\n/**\n * Check if a file exists in OPFS\n * @param {FileSystemFileHandle} fileHandle - The file handle to check\n * @returns {boolean} - True if file exists and is readable\n */\nfunction exists(fileHandle) {\n try {\n // If we have a handle, the file exists\n return fileHandle !== null && fileHandle !== undefined;\n } catch {\n return false;\n }\n}\n\n/**\n * Delete a file from OPFS\n * @param {FileSystemDirectoryHandle} dirHandle - The directory handle\n * @param {string} filename - Name of the file to delete\n */\nasync function deleteFile(dirHandle, filename) {\n try {\n await dirHandle.removeEntry(filename);\n } catch (error) {\n if (error.name === 'NotFoundError') {\n // File doesn't exist, nothing to delete\n return;\n }\n throw error;\n }\n}\n\n/**\n * Get or create a file handle from a directory\n * @param {FileSystemDirectoryHandle} dirHandle - The directory handle\n * @param {string} filename - Name of the file\n * @param {Object} options - Options for getFileHandle\n * @returns {FileSystemFileHandle} - The file handle\n */\nasync function getFileHandle(dirHandle, filename, options = {}) {\n return dirHandle.getFileHandle(filename, options);\n}\n\nexport {\n TYPE,\n ObjectId,\n Pointer,\n encode,\n decode,\n BinJsonFile,\n exists,\n deleteFile,\n getFileHandle\n};\n","/**\n * Utility functions for MicroMongoDB\n */\n\nimport { ObjectId } from '@belteshazzar/binjson';\n\n/**\n * Compare two values for equality, handling ObjectId instances\n */\nfunction valuesEqual(a, b) {\n\t// Handle ObjectId comparison\n\tif (a instanceof ObjectId || b instanceof ObjectId) {\n\t\tif (a instanceof ObjectId && b instanceof ObjectId) {\n\t\t\treturn a.equals(b);\n\t\t}\n\t\tif (a instanceof ObjectId && typeof b === 'string') {\n\t\t\treturn a.equals(b);\n\t\t}\n\t\tif (b instanceof ObjectId && typeof a === 'string') {\n\t\t\treturn b.equals(a);\n\t\t}\n\t\treturn false;\n\t}\n\t\n\t// Regular equality\n\treturn a == b;\n}\n\n/**\n * Deep copy an object or array\n */\nexport function copy(o) {\n\t// Handle primitives that shouldn't be deep-copied\n\tif (typeof o !== 'object' || o === null) {\n\t\treturn o;\n\t}\n\t\n\t// Handle ObjectId\n\tif (o instanceof ObjectId) {\n\t\treturn new ObjectId(o.id);\n\t}\n\t\n\t// Handle Date\n\tif (o instanceof Date) {\n\t\treturn new Date(o.getTime());\n\t}\n\t\n\tvar out, v, key;\n\tout = Array.isArray(o) ? [] : {};\n\tfor (key in o) {\n\t\tv = o[key];\n\t\tout[key] = (typeof v === \"object\" && v !== null) ? copy(v) : v;\n\t}\n\treturn out;\n}\n\n/**\n * Get a property from an object using dot notation\n * Supports array element access via numeric indices (e.g., \"items.0.name\")\n */\nexport function getProp(obj, name) {\n\tvar path = name.split(\".\");\n\tvar result = obj[path[0]];\n\tfor (var i = 1; i < path.length; i++) {\n\t\tif (result == undefined || result == null) return result;\n\t\t\n\t\t// Check if this path segment is a numeric index\n\t\tvar pathSegment = path[i];\n\t\tvar numericIndex = parseInt(pathSegment, 10);\n\t\t\n\t\t// If it's a valid array index, use it\n\t\tif (isArray(result) && !isNaN(numericIndex) && numericIndex >= 0 && numericIndex < result.length) {\n\t\t\tresult = result[numericIndex];\n\t\t} else {\n\t\t\tresult = result[pathSegment];\n\t\t}\n\t}\n\treturn result;\n}\n\n/**\n * Get field values for query matching, handling MongoDB-style array traversal\n * When a path traverses an array, this returns all matching values from array elements\n * Returns an array of values if array traversal occurred, otherwise the single value\n * \n * Example:\n * doc = { items: [{ price: 10 }, { price: 20 }] }\n * getFieldValues(doc, 'items.price') -> [10, 20]\n */\nexport function getFieldValues(obj, name) {\n\tvar path = name.split(\".\");\n\tvar results = [obj];\n\t\n\tfor (var i = 0; i < path.length; i++) {\n\t\tvar pathSegment = path[i];\n\t\tvar numericIndex = parseInt(pathSegment, 10);\n\t\tvar newResults = [];\n\t\t\n\t\tfor (var j = 0; j < results.length; j++) {\n\t\t\tvar current = results[j];\n\t\t\tif (current == undefined || current == null) continue;\n\t\t\t\n\t\t\t// If this is a numeric index and current is an array, access that element\n\t\t\tif (isArray(current) && !isNaN(numericIndex) && numericIndex >= 0) {\n\t\t\t\tif (numericIndex < current.length) {\n\t\t\t\t\tnewResults.push(current[numericIndex]);\n\t\t\t\t}\n\t\t\t}\n\t\t\t// If current is an array but path segment is not numeric, traverse all elements\n\t\t\telse if (isArray(current)) {\n\t\t\t\tfor (var k = 0; k < current.length; k++) {\n\t\t\t\t\tif (current[k] != undefined && current[k] != null && typeof current[k] === 'object') {\n\t\t\t\t\t\tnewResults.push(current[k][pathSegment]);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Otherwise, normal property access\n\t\t\telse if (typeof current === 'object') {\n\t\t\t\tnewResults.push(current[pathSegment]);\n\t\t\t}\n\t\t}\n\t\t\n\t\tresults = newResults;\n\t}\n\t\n\t// Filter out undefined values\n\tresults = results.filter(function(v) { return v !== undefined; });\n\t\n\t// If we have multiple values, return the array\n\t// If we have exactly one, return it directly\n\t// If we have none, return undefined\n\tif (results.length === 0) return undefined;\n\tif (results.length === 1) return results[0];\n\treturn results;\n}\n\n/**\n * Set a property on an object using dot notation\n * Creates intermediate objects as needed\n * Supports array element access via numeric indices\n * Supports $[] operator to update all array elements\n */\nexport function setProp(obj, name, value) {\n\t// Check if path contains $[] operator\n\tif (name.indexOf('$[]') !== -1) {\n\t\treturn setPropWithAllPositional(obj, name, value);\n\t}\n\t\n\tvar path = name.split(\".\");\n\tvar current = obj;\n\t\n\tfor (var i = 0; i < path.length - 1; i++) {\n\t\tvar pathSegment = path[i];\n\t\tvar numericIndex = parseInt(pathSegment, 10);\n\t\t\n\t\t// If this is a numeric index and current is an array\n\t\tif (isArray(current) && !isNaN(numericIndex) && numericIndex >= 0) {\n\t\t\t// Ensure the array is large enough\n\t\t\twhile (current.length <= numericIndex) {\n\t\t\t\tcurrent.push(undefined);\n\t\t\t}\n\t\t\t// If the element doesn't exist, create an object\n\t\t\tif (current[numericIndex] == undefined || current[numericIndex] == null) {\n\t\t\t\t// Look ahead to see if next segment is numeric (array) or not (object)\n\t\t\t\tvar nextSegment = path[i + 1];\n\t\t\t\tvar nextNumeric = parseInt(nextSegment, 10);\n\t\t\t\tif (!isNaN(nextNumeric) && nextNumeric >= 0) {\n\t\t\t\t\tcurrent[numericIndex] = [];\n\t\t\t\t} else {\n\t\t\t\t\tcurrent[numericIndex] = {};\n\t\t\t\t}\n\t\t\t}\n\t\t\tcurrent = current[numericIndex];\n\t\t}\n\t\t// Regular property access\n\t\telse {\n\t\t\tif (current[pathSegment] == undefined || current[pathSegment] == null) {\n\t\t\t\t// Look ahead to see if next segment is numeric (array) or not (object)\n\t\t\t\tvar nextSegment = path[i + 1];\n\t\t\t\tvar nextNumeric = parseInt(nextSegment, 10);\n\t\t\t\tif (!isNaN(nextNumeric) && nextNumeric >= 0) {\n\t\t\t\t\tcurrent[pathSegment] = [];\n\t\t\t\t} else {\n\t\t\t\t\tcurrent[pathSegment] = {};\n\t\t\t\t}\n\t\t\t}\n\t\t\tcurrent = current[pathSegment];\n\t\t}\n\t}\n\t\n\t// Set the final value\n\tvar lastSegment = path[path.length - 1];\n\tvar lastNumericIndex = parseInt(lastSegment, 10);\n\t\n\tif (isArray(current) && !isNaN(lastNumericIndex) && lastNumericIndex >= 0) {\n\t\twhile (current.length <= lastNumericIndex) {\n\t\t\tcurrent.push(undefined);\n\t\t}\n\t\tcurrent[lastNumericIndex] = value;\n\t} else {\n\t\tcurrent[lastSegment] = value;\n\t}\n}\n\n/**\n * Set a property using the $[] all positional operator\n * Updates all elements in an array\n */\nfunction setPropWithAllPositional(obj, name, value) {\n\tvar path = name.split(\".\");\n\tvar current = obj;\n\t\n\t// Navigate to the $[] operator\n\tfor (var i = 0; i < path.length; i++) {\n\t\tvar pathSegment = path[i];\n\t\t\n\t\tif (pathSegment === '$[]') {\n\t\t\t// Current should be an array - update all elements\n\t\t\tif (!Array.isArray(current)) {\n\t\t\t\tthrow new Error(\"The positional operator did not find the match needed from the query.\");\n\t\t\t}\n\t\t\t\n\t\t\t// Build the remaining path after $[]\n\t\t\tvar remainingPath = path.slice(i + 1).join('.');\n\t\t\t\n\t\t\t// Update all array elements\n\t\t\tfor (var j = 0; j < current.length; j++) {\n\t\t\t\tif (remainingPath) {\n\t\t\t\t\t// There's more path after $[], recursively set on each element\n\t\t\t\t\tsetProp(current[j], remainingPath, value);\n\t\t\t\t} else {\n\t\t\t\t\t// $[] is the last segment, replace each element with value\n\t\t\t\t\tcurrent[j] = value;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\t\n\t\t// Navigate to the next level\n\t\tvar numericIndex = parseInt(pathSegment, 10);\n\t\t\n\t\tif (isArray(current) && !isNaN(numericIndex) && numericIndex >= 0) {\n\t\t\tcurrent = current[numericIndex];\n\t\t} else {\n\t\t\tif (current[pathSegment] == undefined || current[pathSegment] == null) {\n\t\t\t\t// Create intermediate object or array\n\t\t\t\tvar nextSegment = i + 1 < path.length ? path[i + 1] : null;\n\t\t\t\tif (nextSegment === '$[]') {\n\t\t\t\t\tcurrent[pathSegment] = [];\n\t\t\t\t} else {\n\t\t\t\t\tvar nextNumeric = parseInt(nextSegment, 10);\n\t\t\t\t\tif (!isNaN(nextNumeric) && nextNumeric >= 0) {\n\t\t\t\t\t\tcurrent[pathSegment] = [];\n\t\t\t\t\t} else {\n\t\t\t\t\t\tcurrent[pathSegment] = {};\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tcurrent = current[pathSegment];\n\t\t}\n\t}\n}\n\n/**\n * Check if value is an array\n */\nexport function isArray(o) {\n\treturn Array == o.constructor;\n}\n\n/**\n * Convert object to array of key-value pairs\n */\nexport function toArray(obj) {\n\tvar arr = [];\n\tfor (var key in obj) {\n\t\tif (obj.hasOwnProperty(key)) {\n\t\t\tvar el = {};\n\t\t\tel[key] = obj[key];\n\t\t\tarr.push(el);\n\t\t}\n\t}\n\treturn arr;\n}\n\n/**\n * Check if a value is in an array\n */\nexport function isIn(val, values) {\n\tfor (var i = 0; i < values.length; i++) {\n\t\tif (valuesEqual(values[i], val)) return true;\n\t}\n\treturn false;\n}\n\n/**\n * Check if two arrays match\n */\nexport function arrayMatches(x, y) {\n\tif (x.length != y.length) return false;\n\tfor (var i = 0; i < x.length; i++) {\n\t\tif (valuesEqual(x[i], y[i])) continue;\n\t\tif (typeof (x[i]) != typeof (y[i])) return false;\n\t\tif (typeof (x[i]) == \"object\" && x[i] !== null) {\n\t\t\tif (isArray(x[i])) {\n\t\t\t\tif (!arrayMatches(x[i], y[i])) return false;\n\t\t\t} else {\n\t\t\t\tif (!objectMatches(x[i], y[i])) return false;\n\t\t\t}\n\t\t} else {\n\t\t\tif (!valuesEqual(x[i], y[i])) return false;\n\t\t}\n\t}\n\treturn true;\n}\n\n/**\n * Check if two objects match\n */\nexport function objectMatches(x, y) {\n\tfor (var p in x) {\n\t\tif (!x.hasOwnProperty(p)) continue;\n\t\tif (!y.hasOwnProperty(p)) return false;\n\t\tif (valuesEqual(x[p], y[p])) continue;\n\t\tif (typeof (x[p]) != typeof (y[p])) return false;\n\t\tif (typeof (x[p]) == \"object\" && x[p] !== null) {\n\t\t\tif (isArray(x[p])) {\n\t\t\t\tif (!arrayMatches(x[p], y[p])) return false;\n\t\t\t} else {\n\t\t\t\tif (!objectMatches(x[p], y[p])) return false;\n\t\t\t}\n\t\t} else {\n\t\t\tif (!valuesEqual(x[p], y[p])) return false;\n\t\t}\n\t}\n\tfor (var p in y) {\n\t\tif (y.hasOwnProperty(p) && !x.hasOwnProperty(p)) return false;\n\t}\n\treturn true;\n}\n\n/**\n * Apply projection to a document\n */\nexport function applyProjection(projection, doc) {\n\tvar result = {};\n\tvar keys = Object.keys(projection);\n\tif (keys.length == 0) return doc;\n\t\n\t// Check for mixed inclusion/exclusion (except _id which can be excluded in inclusion projection)\n\tvar hasInclusion = false;\n\tvar hasExclusion = false;\n\tfor (var i = 0; i < keys.length; i++) {\n\t\tif (keys[i] === '_id') continue; // _id is special\n\t\tif (projection[keys[i]]) hasInclusion = true;\n\t\telse hasExclusion = true;\n\t}\n\t\n\tif (hasInclusion && hasExclusion) {\n\t\tthrow { $err: \"Can't canonicalize query: BadValue Projection cannot have a mix of inclusion and exclusion.\", code: 17287 };\n\t}\n\t\n\tif (projection[keys[0]] || hasInclusion) {\n\t\t// Inclusion projection\n\t\t// Include _id unless explicitly excluded\n\t\tif (projection._id !== 0 && projection._id !== false) {\n\t\t\tresult._id = copy(doc._id);\n\t\t}\n\t\t\n\t\tfor (var i = 0; i < keys.length; i++) {\n\t\t\tif (keys[i] === '_id') continue;\n\t\t\tif (!projection[keys[i]]) continue;\n\t\t\t\n\t\t\tvar fieldPath = keys[i];\n\t\t\tvar value = getProp(doc, fieldPath);\n\t\t\t\n\t\t\tif (value !== undefined) {\n\t\t\t\t// Use setProp to create nested structure\n\t\t\t\tsetProp(result, fieldPath, copy(value));\n\t\t\t}\n\t\t}\n\t} else {\n\t\t// Exclusion projection - start with a copy of the document\n\t\tfor (var key in doc) {\n\t\t\tif (doc.hasOwnProperty(key)) {\n\t\t\t\t// Deep copy the value\n\t\t\t\tvar val = doc[key];\n\t\t\t\tif (typeof val === 'object' && val !== null && !isArray(val)) {\n\t\t\t\t\tresult[key] = copy(val);\n\t\t\t\t} else if (isArray(val)) {\n\t\t\t\t\tresult[key] = val.slice(); // shallow copy array\n\t\t\t\t} else {\n\t\t\t\t\tresult[key] = val;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t\n\t\t// Remove excluded fields\n\t\tfor (var i = 0; i < keys.length; i++) {\n\t\t\tif (projection[keys[i]]) continue; // Skip if value is truthy\n\t\t\t\n\t\t\tvar fieldPath = keys[i];\n\t\t\tvar pathParts = fieldPath.split('.');\n\t\t\t\n\t\t\t// Navigate to the parent object and delete the final property\n\t\t\tif (pathParts.length === 1) {\n\t\t\t\tdelete result[fieldPath];\n\t\t\t} else {\n\t\t\t\tvar parent = result;\n\t\t\t\tfor (var j = 0; j < pathParts.length - 1; j++) {\n\t\t\t\t\tif (parent == undefined || parent == null) break;\n\t\t\t\t\tparent = parent[pathParts[j]];\n\t\t\t\t}\n\t\t\t\tif (parent != undefined && parent != null) {\n\t\t\t\t\tdelete parent[pathParts[pathParts.length - 1]];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn result;\n}\n\n/**\n * Convert bbox to GeoJSON\n */\nexport function bboxToGeojson(bbox) {\n\tconst minLon = bbox[0][0];\n\tconst maxLat = bbox[0][1];\n\tconst maxLon = bbox[1][0];\n\tconst minLat = bbox[1][1];\n\treturn {\n\t\ttype: 'FeatureCollection',\n\t\tfeatures: [{\n\t\t\ttype: 'Feature',\n\t\t\tproperties: {},\n\t\t\tgeometry: {\n\t\t\t\ttype: 'Polygon',\n\t\t\t\tcoordinates: [[\n\t\t\t\t\t[minLon, maxLat],\n\t\t\t\t\t[minLon, minLat],\n\t\t\t\t\t[maxLon, minLat],\n\t\t\t\t\t[maxLon, maxLat],\n\t\t\t\t\t[minLon, maxLat]\n\t\t\t\t]]\n\t\t\t}\n\t\t}]\n\t};\n}\n","/**\n * MongoDB Error Classes\n * \n * Structured error hierarchy compatible with MongoDB driver\n */\n\n/**\n * Error codes matching MongoDB error codes\n */\nexport const ErrorCodes = {\n\t// General errors\n\tOK: 0,\n\tINTERNAL_ERROR: 1,\n\tBAD_VALUE: 2,\n\tNO_SUCH_KEY: 4,\n\tGRAPH_CONTAINS_CYCLE: 5,\n\tHOST_UNREACHABLE: 6,\n\tHOST_NOT_FOUND: 7,\n\tUNKNOWN_ERROR: 8,\n\tFAILED_TO_PARSE: 17287, // Using test-compatible error code\n\tCANNOT_MUTATE_OBJECT: 10,\n\tUSER_NOT_FOUND: 11,\n\tUNSUPPORTED_FORMAT: 12,\n\tUNAUTHORIZED: 13,\n\tTYPE_MISMATCH: 14,\n\tOVERFLOW: 15,\n\tINVALID_LENGTH: 16,\n\tPROTOCOL_ERROR: 17,\n\tAUTHENTICATION_FAILED: 18,\n\tILLEGAL_OPERATION: 20,\n\tNAMESPACE_NOT_FOUND: 26,\n\tINDEX_NOT_FOUND: 27,\n\tPATH_NOT_VIABLE: 28,\n\tCANNOT_CREATE_INDEX: 67,\n\tINDEX_ALREADY_EXISTS: 68,\n\tINDEX_EXISTS: 68,\n\tCOMMAND_NOT_FOUND: 59,\n\tNAMESPACE_EXISTS: 48,\n\tINVALID_NAMESPACE: 73,\n\tINDEX_OPTIONS_CONFLICT: 85,\n\tINVALID_INDEX_SPECIFICATION_OPTION: 197,\n\t\n\t// Write errors\n\tWRITE_CONFLICT: 112,\n\tDUPLICATE_KEY: 11000,\n\tDUPLICATE_KEY_UPDATE: 11001,\n\t\n\t// Validation errors\n\tDOCUMENT_VALIDATION_FAILURE: 121,\n\t\n\t// Query errors\n\tBAD_QUERY: 2,\n\tCANNOT_INDEX_PARALLEL_ARRAYS: 171,\n\t\n\t// Cursor errors\n\tCURSOR_NOT_FOUND: 43,\n\t\n\t// Collection errors\n\tCOLLECTION_IS_EMPTY: 26,\n CANNOT_DO_EXCLUSION_ON_FIELD_ID_IN_INCLUSION_PROJECTION: 31254,\n\t\n\t// Not implemented (custom code)\n\tNOT_IMPLEMENTED: 999,\n\tOPERATION_NOT_SUPPORTED: 998\n};\n\n/**\n * Base class for all MongoDB errors\n */\nexport class MongoError extends Error {\n\tconstructor(message, options = {}) {\n\t\tsuper(message);\n\t\tthis.name = 'MongoError';\n\t\tthis.code = options.code || ErrorCodes.UNKNOWN_ERROR;\n\t\tthis.codeName = this._getCodeName(this.code);\n\t\t\n\t\t// Backward compatibility: add $err property matching old error format\n\t\tthis.$err = message;\n\t\t\n\t\t// Additional context\n\t\tif (options.collection) this.collection = options.collection;\n\t\tif (options.database) this.database = options.database;\n\t\tif (options.operation) this.operation = options.operation;\n\t\tif (options.query) this.query = options.query;\n\t\tif (options.document) this.document = options.document;\n\t\tif (options.field) this.field = options.field;\n\t\tif (options.index) this.index = options.index;\n\t\t\n\t\t// Capture stack trace\n\t\tif (Error.captureStackTrace) {\n\t\t\tError.captureStackTrace(this, this.constructor);\n\t\t}\n\t}\n\t\n\t_getCodeName(code) {\n\t\tconst codeToName = {\n\t\t\t0: 'OK',\n\t\t\t1: 'InternalError',\n\t\t\t2: 'BadValue',\n\t\t\t4: 'NoSuchKey',\n\t\t\t5: 'GraphContainsCycle',\n\t\t\t6: 'HostUnreachable',\n\t\t\t7: 'HostNotFound',\n\t\t\t8: 'UnknownError',\n\t\t\t10: 'CannotMutateObject',\n\t\t\t11: 'UserNotFound',\n\t\t\t12: 'UnsupportedFormat',\n\t\t\t13: 'Unauthorized',\n\t\t\t14: 'TypeMismatch',\n\t\t\t15: 'Overflow',\n\t\t\t16: 'InvalidLength',\n\t\t\t17: 'ProtocolError',\n\t\t\t18: 'AuthenticationFailed',\n\t\t\t20: 'IllegalOperation',\n\t\t\t26: 'NamespaceNotFound',\n\t\t\t27: 'IndexNotFound',\n\t\t\t28: 'PathNotViable',\n\t\t\t43: 'CursorNotFound',\n\t\t\t48: 'NamespaceExists',\n\t\t\t59: 'CommandNotFound',\n\t\t\t67: 'CannotCreateIndex',\n\t\t\t68: 'IndexExists',\n\t\t\t73: 'InvalidNamespace',\n\t\t\t85: 'IndexOptionsConflict',\n\t\t\t112: 'WriteConflict',\n\t\t\t121: 'DocumentValidationFailure',\n\t\t\t171: 'CannotIndexParallelArrays',\n\t\t\t197: 'InvalidIndexSpecificationOption',\n\t\t\t998: 'OperationNotSupported',\n\t\t\t999: 'NotImplemented',\n\t\t\t11000: 'DuplicateKey',\n\t\t\t11001: 'DuplicateKeyUpdate',\n\t\t\t17287: 'FailedToParse'\n\t\t};\n\t\treturn codeToName[code] || 'UnknownError';\n\t}\n\t\n\ttoJSON() {\n\t\tconst json = {\n\t\t\tname: this.name,\n\t\t\tmessage: this.message,\n\t\t\tcode: this.code,\n\t\t\tcodeName: this.codeName\n\t\t};\n\t\t\n\t\t// Include all enumerable properties\n\t\tif (this.collection) json.collection = this.collection;\n\t\tif (this.database) json.database = this.database;\n\t\tif (this.operation) json.operation = this.operation;\n\t\tif (this.index) json.index = this.index;\n\t\tif (this.indexName) json.indexName = this.indexName;\n\t\tif (this.field) json.field = this.field;\n\t\tif (this.query) json.query = this.query;\n\t\tif (this.document) json.document = this.document;\n\t\tif (this.namespace) json.namespace = this.namespace;\n\t\tif (this.cursorId) json.cursorId = this.cursorId;\n\t\tif (this.feature) json.feature = this.feature;\n\t\tif (this.keyPattern) json.keyPattern = this.keyPattern;\n\t\tif (this.keyValue) json.keyValue = this.keyValue;\n\t\tif (this.writeErrors) json.writeErrors = this.writeErrors;\n\t\t\n\t\treturn json;\n\t}\n}\n\n/**\n * Server-side errors\n */\nexport class MongoServerError extends MongoError {\n\tconstructor(message, options = {}) {\n\t\tsuper(message, options);\n\t\tthis.name = 'MongoServerError';\n\t}\n}\n\n/**\n * Driver-side errors (client errors)\n */\nexport class MongoDriverError extends MongoError {\n\tconstructor(message, options = {}) {\n\t\tsuper(message, options);\n\t\tthis.name = 'MongoDriverError';\n\t\tthis.code = options.code || ErrorCodes.INTERNAL_ERROR;\n\t}\n}\n\n/**\n * Write operation errors\n */\nexport class WriteError extends MongoError {\n\tconstructor(message, options = {}) {\n\t\tsuper(message, options);\n\t\tthis.name = 'WriteError';\n\t\tthis.code = options.code || ErrorCodes.WRITE_CONFLICT;\n\t}\n}\n\n/**\n * Duplicate key error\n */\nexport class DuplicateKeyError extends WriteError {\n\tconstructor(key, options = {}) {\n\t\tconst keyStr = JSON.stringify(key);\n\t\tconst message = `E11000 duplicate key error${options.collection ? ` collection: ${options.collection}` : ''} index: ${keyStr} dup key: ${keyStr}`;\n\t\tsuper(message, { ...options, code: ErrorCodes.DUPLICATE_KEY });\n\t\tthis.name = 'DuplicateKeyError';\n\t\tthis.keyPattern = key;\n\t\tthis.keyValue = options.keyValue || key;\n\t}\n}\n\n/**\n * Document validation errors\n */\nexport class ValidationError extends MongoError {\n\tconstructor(message, options = {}) {\n\t\tsuper(message, options);\n\t\tthis.name = 'ValidationError';\n\t\tthis.code = options.code || ErrorCodes.DOCUMENT_VALIDATION_FAILURE;\n\t\tthis.validationErrors = options.validationErrors || [];\n\t}\n}\n\n/**\n * Index-related errors\n */\nexport class IndexError extends MongoError {\n\tconstructor(message, options = {}) {\n\t\tsuper(message, options);\n\t\tthis.name = 'IndexError';\n\t}\n}\n\n/**\n * Index already exists error\n */\nexport class IndexExistsError extends IndexError {\n\tconstructor(indexName, options = {}) {\n\t\tsuper(`Index with name '${indexName}' already exists`, {\n\t\t\t...options,\n\t\t\tcode: ErrorCodes.INDEX_EXISTS\n\t\t});\n\t\tthis.name = 'IndexExistsError';\n\t\tthis.indexName = indexName;\n\t}\n}\n\n/**\n * Index not found error\n */\nexport class IndexNotFoundError extends IndexError {\n\tconstructor(indexName, options = {}) {\n\t\tsuper(`Index '${indexName}' not found`, {\n\t\t\t...options,\n\t\t\tcode: ErrorCodes.INDEX_NOT_FOUND,\n\t\t\tindex: indexName\n\t\t});\n\t\tthis.name = 'IndexNotFoundError';\n\t\tthis.indexName = indexName;\n\t}\n}\n\n/**\n * Cannot create index error\n */\nexport class CannotCreateIndexError extends IndexError {\n\tconstructor(reason, options = {}) {\n\t\tsuper(`Cannot create index: ${reason}`, {\n\t\t\t...options,\n\t\t\tcode: ErrorCodes.CANNOT_CREATE_INDEX\n\t\t});\n\t\tthis.name = 'CannotCreateIndexError';\n\t}\n}\n\n/**\n * Query errors\n */\nexport class QueryError extends MongoError {\n\tconstructor(message, options = {}) {\n\t\tsuper(message, options);\n\t\tthis.name = 'QueryError';\n\t\tthis.code = options.code || ErrorCodes.BAD_QUERY;\n\t}\n}\n\n/**\n * Type mismatch error\n */\nexport class TypeMismatchError extends MongoError {\n\tconstructor(field, expectedType, actualType, options = {}) {\n\t\tsuper(\n\t\t\t`Type mismatch for field '${field}': expected ${expectedType}, got ${actualType}`,\n\t\t\t{ ...options, code: ErrorCodes.TYPE_MISMATCH, field }\n\t\t);\n\t\tthis.name = 'TypeMismatchError';\n\t\tthis.expectedType = expectedType;\n\t\tthis.actualType = actualType;\n\t}\n}\n\n/**\n * Namespace errors\n */\nexport class NamespaceError extends MongoError {\n\tconstructor(message, options = {}) {\n\t\tsuper(message, options);\n\t\tthis.name = 'NamespaceError';\n\t}\n}\n\n/**\n * Namespace not found\n */\nexport class NamespaceNotFoundError extends NamespaceError {\n\tconstructor(namespace, options = {}) {\n\t\tsuper(`Namespace '${namespace}' not found`, {\n\t\t\t...options,\n\t\t\tcode: ErrorCodes.NAMESPACE_NOT_FOUND\n\t\t});\n\t\tthis.name = 'NamespaceNotFoundError';\n\t\tthis.namespace = namespace;\n\t}\n}\n\n/**\n * Invalid namespace\n */\nexport class InvalidNamespaceError extends NamespaceError {\n\tconstructor(namespace, reason, options = {}) {\n\t\t// Handle case where reason is actually options\n\t\tif (typeof reason === 'object' && !options) {\n\t\t\toptions = reason;\n\t\t\treason = undefined;\n\t\t}\n\t\tconst msg = reason ? `Invalid namespace '${namespace}': ${reason}` : `Invalid namespace '${namespace}'`;\n\t\tsuper(msg, {\n\t\t\t...options,\n\t\t\tcode: ErrorCodes.INVALID_NAMESPACE\n\t\t});\n\t\tthis.name = 'InvalidNamespaceError';\n\t\tthis.namespace = namespace;\n\t}\n}\n\n/**\n * Cursor errors\n */\nexport class CursorError extends MongoError {\n\tconstructor(message, options = {}) {\n\t\tsuper(message, options);\n\t\tthis.name = 'CursorError';\n\t}\n}\n\n/**\n * Cursor not found\n */\nexport class CursorNotFoundError extends CursorError {\n\tconstructor(cursorId, options = {}) {\n\t\tsuper(`Cursor ${cursorId} not found`, {\n\t\t\t...options,\n\t\t\tcode: ErrorCodes.CURSOR_NOT_FOUND\n\t\t});\n\t\tthis.name = 'CursorNotFoundError';\n\t\tthis.cursorId = cursorId;\n\t}\n}\n\n/**\n * Not implemented error\n */\nexport class NotImplementedError extends MongoError {\n\tconstructor(feature, options = {}) {\n\t\tsuper(`${feature} is not implemented in babymongo`, {\n\t\t\t...options,\n\t\t\tcode: ErrorCodes.NOT_IMPLEMENTED\n\t\t});\n\t\tthis.name = 'NotImplementedError';\n\t\tthis.feature = feature;\n\t}\n}\n\n/**\n * Operation not supported\n */\nexport class OperationNotSupportedError extends MongoError {\n\tconstructor(operation, reason, options = {}) {\n\t\t// Handle case where reason is actually options\n\t\tif (typeof reason === 'object' && !options) {\n\t\t\toptions = reason;\n\t\t\treason = undefined;\n\t\t}\n\t\tconst msg = reason ? `Operation '${operation}' is not supported: ${reason}` : `Operation '${operation}' is not supported`;\n\t\tsuper(msg, {\n\t\t\t...options,\n\t\t\tcode: ErrorCodes.OPERATION_NOT_SUPPORTED,\n\t\t\toperation\n\t\t});\n\t\tthis.name = 'OperationNotSupportedError';\n\t}\n}\n\n/**\n * Bad value error\n */\nexport class BadValueError extends MongoError {\n\tconstructor(field, value, reason, options = {}) {\n\t\tsuper(`Bad value for field '${field}': ${reason}`, {\n\t\t\t...options,\n\t\t\tcode: ErrorCodes.BAD_VALUE,\n\t\t\tfield\n\t\t});\n\t\tthis.name = 'BadValueError';\n\t\tthis.value = value;\n\t}\n}\n\n/**\n * Bulk write error\n */\nexport class BulkWriteError extends MongoError {\n\tconstructor(writeErrors = [], options = {}) {\n\t\tconst message = `Bulk write operation error: ${writeErrors.length} error(s)`;\n\t\tsuper(message, options);\n\t\tthis.name = 'BulkWriteError';\n\t\tthis.writeErrors = writeErrors;\n\t\tthis.code = options.code || ErrorCodes.WRITE_CONFLICT;\n\t}\n}\n\n/**\n * Network error (for API compatibility, not functional in babymongo)\n */\nexport class MongoNetworkError extends MongoError {\n\tconstructor(message, options = {}) {\n\t\tsuper(message, options);\n\t\tthis.name = 'MongoNetworkError';\n\t\tthis.code = options.code || ErrorCodes.HOST_UNREACHABLE;\n\t}\n}\n\n/**\n * Helper function to create appropriate error\n */\nexport function createError(type, ...args) {\n\tswitch (type) {\n\t\tcase 'duplicate_key':\n\t\t\treturn new DuplicateKeyError(...args);\n\t\tcase 'validation':\n\t\t\treturn new ValidationError(...args);\n\t\tcase 'index_exists':\n\t\t\treturn new IndexExistsError(...args);\n\t\tcase 'index_not_found':\n\t\t\treturn new IndexNotFoundError(...args);\n\t\tcase 'cannot_create_index':\n\t\t\treturn new CannotCreateIndexError(...args);\n\t\tcase 'query':\n\t\t\treturn new QueryError(...args);\n\t\tcase 'type_mismatch':\n\t\t\treturn new TypeMismatchError(...args);\n\t\tcase 'namespace_not_found':\n\t\t\treturn new NamespaceNotFoundError(...args);\n\t\tcase 'invalid_namespace':\n\t\t\treturn new InvalidNamespaceError(...args);\n\t\tcase 'cursor_not_found':\n\t\t\treturn new CursorNotFoundError(...args);\n\t\tcase 'not_implemented':\n\t\t\treturn new NotImplementedError(...args);\n\t\tcase 'operation_not_supported':\n\t\t\treturn new OperationNotSupportedError(...args);\n\t\tcase 'bad_value':\n\t\t\treturn new BadValueError(...args);\n\t\tcase 'write':\n\t\t\treturn new WriteError(...args);\n\t\tdefault:\n\t\t\treturn new MongoError(...args);\n\t}\n}\n","import { applyProjection } from '../utils.js';\nimport { NotImplementedError, QueryError, ErrorCodes } from '../errors.js';\n\n/**\n * Cursor class for iterating over query results\n * Supports both synchronous iteration (after await) and async methods\n */\nexport class Cursor {\n\tconstructor(collection, query, projection, documentsOrPromise, SortedCursor) {\n\t\tthis.collection = collection;\n\t\tthis.query = query;\n\t\tthis.projection = projection;\n\t\t// Support both Promise<Array> and Array for backward compatibility\n\t\tthis._documentsPromise = documentsOrPromise instanceof Promise ? documentsOrPromise : Promise.resolve(documentsOrPromise);\n\t\tthis.documents = null; // Will be populated when _ensureInitialized() is called\n\t\tthis._initialized = false;\n\t\tthis.SortedCursor = SortedCursor;\n\n\t\t// Validate projection if provided\n\t\tif (projection && Object.keys(projection).length > 0) {\n\t\t\tconst keys = Object.keys(projection);\n\t\t\tlet hasInclusion = false;\n\t\t\tlet hasExclusion = false;\n\t\t\tfor (let i = 0; i < keys.length; i++) {\n\t\t\t\tif (keys[i] === '_id') continue; // _id is special\n\t\t\t\tif (projection[keys[i]]) hasInclusion = true;\n\t\t\t\telse hasExclusion = true;\n\t\t\t}\n\t\t\t\n\t\t\tif (hasInclusion && hasExclusion) {\n\t\t\t\tthrow new QueryError(\"Can't canonicalize query: BadValue Projection cannot have a mix of inclusion and exclusion.\", { \n\t\t\t\t\tcode: ErrorCodes.FAILED_TO_PARSE,\n\t\t\t\t\tcollection: collection.name \n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t\t\n\t\tthis.pos = 0;\n\t\tthis._limit = 0;\n\t\tthis._skip = 0;\n\t\tthis._closed = false;\n\t}\n\n\t/**\n\t * Ensure documents are loaded from the promise\n\t * @private\n\t */\n\tasync _ensureInitialized() {\n\t\tif (!this._initialized) {\n\t\t\tthis.documents = await this._documentsPromise;\n\t\t\tthis._initialized = true;\n\t\t}\n\t}\n\n\tbatchSize(size) { \n\t\t// No-op for in-memory database, but return this for chaining\n\t\tthis._batchSize = size;\n\t\treturn this;\n\t}\n\tclose() {\n\t\tthis._closed = true;\n\t\t// Move to end when documents are loaded\n\t\tif (this.documents) {\n\t\t\tthis.pos = this.documents.length;\n\t\t}\n\t\treturn undefined;\n\t}\n\tcomment(commentString) {\n\t\tthis._comment = commentString;\n\t\treturn this;\n\t}\n\t\n\tasync count() {\n\t\t// Return total count without considering skip/limit applied to this cursor\n\t\tawait this._ensureInitialized();\n\t\treturn this.documents.length;\n\t}\n\t\n\texplain(verbosity = 'queryPlanner') {\n\t\t// Return basic query execution info\n\t\treturn {\n\t\t\tqueryPlanner: {\n\t\t\t\tplannerVersion: 1,\n\t\t\t\tnamespace: `${this.collection.db?.name || 'db'}.${this.collection.name}`,\n\t\t\t\tindexFilterSet: false,\n\t\t\t\tparsedQuery: this.query,\n\t\t\t\twinningPlan: {\n\t\t\t\t\tstage: 'COLLSCAN',\n\t\t\t\t\tfilter: this.query,\n\t\t\t\t\tdirection: 'forward'\n\t\t\t\t}\n\t\t\t},\n\t\t\texecutionStats: verbosity === 'executionStats' || verbosity === 'allPlansExecution' ? {\n\t\t\t\texecutionSuccess: true,\n\t\t\t\tnReturned: this.documents ? this.documents.length : 0,\n\t\t\t\texecutionTimeMillis: 0,\n\t\t\t\ttotalKeysExamined: 0,\n\t\t\t\ttotalDocsExamined: this.documents ? this.documents.length : 0\n\t\t\t} : undefined,\n\t\t\tok: 1\n\t\t};\n\t}\n\t\n\tasync forEach(fn) {\n\t\tawait this._ensureInitialized();\n\t\twhile (await this.hasNext()) {\n\t\t\tawait fn(await this.next());\n\t\t}\n\t}\n\t\n\tasync hasNext() {\n\t\tif (this._closed) return false;\n\n await this._ensureInitialized();\n\n // Apply skip on first access if not yet applied\n\t\tif (this.pos === 0 && this._skip > 0) {\n\t\t\tthis.pos = Math.min(this._skip, this.documents.length);\n\t\t}\n\t\t// Calculate effective max position: skip + limit or total docs\n\t\tlet effectiveMax;\n\t\tif (this._limit > 0) {\n\t\t\teffectiveMax = Math.min(this._skip + this._limit, this.documents.length);\n\t\t} else {\n\t\t\teffectiveMax = this.documents.length;\n\t\t}\n\t\treturn this.pos < effectiveMax;\n\t}\n\t\n\thint(index) {\n\t\t// Store hint for query planner (informational in babymongo)\n\t\tthis._hint = index;\n\t\treturn this;\n\t}\n\tasync itcount() {\n\t\tawait this._ensureInitialized();\n\t\tlet count = 0;\n\t\twhile (await this.hasNext()) {\n\t\t\tawait this.next();\n\t\t\tcount++;\n\t\t}\n\t\treturn count;\n\t}\n\t\n\tlimit(_max) {\n\t\tthis._limit = _max;\n\t\treturn this;\n\t}\n\t\n\tasync map(fn) {\n\t\tawait this._ensureInitialized();\n\t\tconst results = [];\n\t\twhile (await this.hasNext()) {\n\t\t\tresults.push(await fn(await this.next()));\n\t\t}\n\t\treturn results;\n\t}\n\t\n\tmaxScan(maxScan) {\n\t\t// Set maximum number of documents to scan (deprecated in MongoDB 4.0)\n\t\tthis._maxScan = maxScan;\n\t\treturn this;\n\t}\n\tmaxTimeMS(ms) {\n\t\t// Set maximum execution time (informational in babymongo)\n\t\tthis._maxTimeMS = ms;\n\t\treturn this;\n\t}\n\tmax(indexBounds) {\n\t\t// Set maximum index bound (informational in babymongo)\n\t\tthis._maxIndexBounds = indexBounds;\n\t\treturn this;\n\t}\n\tmin(indexBounds) {\n\t\t// Set minimum index bound (informational in babymongo)\n\t\tthis._minIndexBounds = indexBounds;\n\t\treturn this;\n\t}\n\t\n\tasync next() {\n\t\tif (!await this.hasNext()) {\n\t\t\tthrow new QueryError(\"Error: error hasNext: false\", { \n\t\t\t\tcollection: this.collection.name \n\t\t\t});\n\t\t}\n\t\tconst result = this.documents[this.pos++];\n\t\tif (this.projection) {\n\t\t\treturn applyProjection(this.projection, result);\n\t\t}\n\t\treturn result;\n\t}\n\t\n\tnoCursorTimeout() {\n\t\t// Prevent cursor timeout (no-op for in-memory)\n\t\tthis._noCursorTimeout = true;\n\t\treturn this;\n\t}\n\tobjsLeftInBatch() {\n\t\t// Return number of objects left in current batch\n\t\t// For in-memory, this is same as remaining documents\n\t\t// Note: This is synchronous but may return 0 if documents not yet loaded\n\t\tif (!this.documents) return 0;\n\t\treturn this.size();\n\t}\n\tpretty() {\n\t\t// Enable pretty printing (no-op but return this for chaining)\n\t\tthis._pretty = true;\n\t\treturn this;\n\t}\n\treadConcern(level) {\n\t\t// Set read concern (no-op for in-memory database)\n\t\tthis._readConcern = level;\n\t\treturn this;\n\t}\n\treadPref(mode, tagSet) {\n\t\t// Set read preference (no-op for in-memory database)\n\t\tthis._readPref = { mode, tagSet };\n\t\treturn this;\n\t}\n\treturnKey(enabled = true) {\n\t\t// Return only the index key (informational in babymongo)\n\t\tthis._returnKey = enabled;\n\t\treturn this;\n\t}\n\tshowRecordId(enabled = true) {\n\t\t// Show record ID in results\n\t\tthis._showRecordId = enabled;\n\t\treturn this;\n\t}\n\tsize() {\n\t\t// Return count considering skip and limit\n\t\t// Note: This is synchronous but may return 0 if documents not yet loaded\n\t\tif (!this.documents) return 0;\n\t\tconst remaining = this.documents.length - this.pos;\n\t\tif (this._limit > 0) {\n\t\t\t// Calculate how many docs left based on skip+limit boundary\n\t\t\tconst maxPos = this._skip + this._limit;\n\t\t\treturn Math.min(maxPos - this.pos, remaining);\n\t\t}\n\t\treturn remaining;\n\t}\n\t\n\tskip(num) {\n\t\tthis._skip = num;\n\t\t// Move initial position to skip point\n\t\tif (this.pos === 0) {\n\t\t\t// Note: If documents not yet loaded, this will be applied when hasNext() is called\n\t\t\tif (this.documents) {\n\t\t\t\tthis.pos = Math.min(num, this.documents.length);\n\t\t\t}\n\t\t}\n\t\treturn this;\n\t}\n\t\n\tisClosed() {\n\t\treturn this._closed === true;\n\t}\n\t\n\tsnapshot() { throw new NotImplementedError('snapshot'); }\n\t\n\tsort(s) {\n\t\treturn new this.SortedCursor(this.collection, this.query, this, s);\n\t}\n\t\n\tallowDiskUse(enabled = true) {\n\t\t// Allow disk use for sorts (no-op for in-memory)\n\t\tthis._allowDiskUse = enabled;\n\t\treturn this;\n\t}\n\t\n\tcollation(collationDocument) {\n\t\t// Set collation (no-op for babymongo)\n\t\tthis._collation = collationDocument;\n\t\treturn this;\n\t}\n\t\n\ttailable() { throw new NotImplementedError('tailable'); }\n\t\n\tasync toArray() {\n\t\tawait this._ensureInitialized();\n\t\tconst results = [];\n\t\twhile (await this.hasNext()) {\n\t\t\tresults.push(await this.next());\n\t\t}\n\t\treturn results;\n\t}\n\t\n\t// Support for async iteration (for await...of)\n\tasync *[Symbol.asyncIterator]() {\n\t\tawait this._ensureInitialized();\n\t\twhile (await this.hasNext()) {\n\t\t\tyield await this.next();\n\t\t}\n\t}\n}\n","/**\n * SortedCursor class for iterating over sorted query results\n */\nimport { QueryError } from '../errors.js';\n\nexport class SortedCursor {\n\tconstructor(collection, query, cursor, sort) {\n\t\tthis.collection = collection;\n\t\tthis.query = query;\n\t\tthis.sortSpec = sort;\n\t\tthis.pos = 0;\n\t\tthis._cursor = cursor;\n\t\tthis._sort = sort;\n\t\tthis._initialized = false;\n\t\t// Items will be populated lazily when first accessed\n\t\tthis.items = null;\n\t}\n\n\tasync _ensureInitialized() {\n\t\tif (this._initialized) return;\n\t\t\n\t\t// Ensure parent cursor is initialized\n\t\tawait this._cursor._ensureInitialized();\n\t\t\n\t\tthis.items = [];\n\t\t// Collect all items from the cursor\n\t\twhile (await this._cursor.hasNext()) {\n\t\t\tthis.items.push(await this._cursor.next());\n\t\t}\n\t\t\n\t\t// Sort the items\n\t\tconst sortKeys = Object.keys(this._sort);\n\t\tthis.items.sort(function(a, b) {\n\t\t\tfor (let i = 0; i < sortKeys.length; i++) {\n\t\t\t\tif (a[sortKeys[i]] == undefined && b[sortKeys[i]] != undefined) return -1 * this._sort[sortKeys[i]];\n\t\t\t\tif (a[sortKeys[i]] != undefined && b[sortKeys[i]] == undefined) return 1 * this._sort[sortKeys[i]];\n\t\t\t\tif (a[sortKeys[i]] < b[sortKeys[i]]) return -1 * this._sort[sortKeys[i]];\n\t\t\t\tif (a[sortKeys[i]] > b[sortKeys[i]]) return 1 * this._sort[sortKeys[i]];\n\t\t\t}\n\t\t\treturn 0;\n\t\t}.bind(this));\n\t\t\n\t\tthis._initialized = true;\n\t}\n\n\tbatchSize() { throw \"Not Implemented\"; }\n\tclose() { throw \"Not Implemented\"; }\n\tcomment() { throw \"Not Implemented\"; }\n\t\n\tasync count() {\n\t\tawait this._ensureInitialized();\n\t\treturn this.items.length;\n\t}\n\t\n\texplain() { throw \"Not Implemented\"; }\n\t\n\tasync forEach(fn) {\n\t\tawait this._ensureInitialized();\n\t\twhile (await this.hasNext()) {\n\t\t\tawait fn(await this.next());\n\t\t}\n\t}\n\t\n\tasync hasNext() {\n\t\tawait this._ensureInitialized();\n\t\treturn this.pos < this.items.length;\n\t}\n\t\n\thint() { throw \"Not Implemented\"; }\n\titcount() { throw \"Not Implemented\"; }\n\t\n\tasync limit(max) {\n\t\tawait this._ensureInitialized();\n\t\tthis.items = this.items.slice(0, max);\n\t\treturn this;\n\t}\n\t\n\tasync map(fn) {\n\t\tawait this._ensureInitialized();\n\t\tconst results = [];\n\t\twhile (await this.hasNext()) {\n\t\t\tresults.push(await fn(await this.next()));\n\t\t}\n\t\treturn results;\n\t}\n\t\n\tmaxScan() { throw \"Not Implemented\"; }\n\tmaxTimeMS() { throw \"Not Implemented\"; }\n\tmax() { throw \"Not Implemented\"; }\n\tmin() { throw \"Not Implemented\"; }\n\t\n\tasync next() {\n\t\tawait this._ensureInitialized();\n\t\treturn this.items[this.pos++];\n\t}\n\t\n\tnoCursorTimeout() { throw \"Not Implemented\"; }\n\tobjsLeftInBatch() { throw \"Not Implemented\"; }\n\tpretty() { throw \"Not Implemented\"; }\n\treadConcern() { throw \"Not Implemented\"; }\n\treadPref() { throw \"Not Implemented\"; }\n\treturnKey() { throw \"Not Implemented\"; }\n\tshowRecordId() { throw \"Not Implemented\"; }\n\tsize() { throw \"Not Implemented\"; }\n\t\n\tasync skip(num) {\n\t\tawait this._ensureInitialized();\n\t\twhile (num > 0) {\n\t\t\tawait this.next();\n\t\t\tnum--;\n\t\t}\n\t\treturn this;\n\t}\n\t\n\tsnapshot() { throw \"Not Implemented\"; }\n\t\n\tsort(s) {\n\t\treturn new SortedCursor(this.collection, this.query, this, s);\n\t}\n\t\n\ttailable() { throw \"Not Implemented\"; }\n\t\n\tasync toArray() {\n\t\tawait this._ensureInitialized();\n\t\tconst results = [];\n\t\twhile (await this.hasNext()) {\n\t\t\tresults.push(this.next());\n\t\t}\n\t\treturn results;\n\t}\n\t\n\t// Support for async iteration (for await...of)\n\tasync *[Symbol.asyncIterator]() {\n\t\tawait this._ensureInitialized();\n\t\twhile (await this.hasNext()) {\n\t\t\tyield await this.next();\n\t\t}\n\t}\n}\n","// Standard suffix manipulations.\n/** @type {Record<string, string>} */\nconst step2list = {\n ational: 'ate',\n tional: 'tion',\n enci: 'ence',\n anci: 'ance',\n izer: 'ize',\n bli: 'ble',\n alli: 'al',\n entli: 'ent',\n eli: 'e',\n ousli: 'ous',\n ization: 'ize',\n ation: 'ate',\n ator: 'ate',\n alism: 'al',\n iveness: 'ive',\n fulness: 'ful',\n ousness: 'ous',\n aliti: 'al',\n iviti: 'ive',\n biliti: 'ble',\n logi: 'log'\n}\n\n/** @type {Record<string, string>} */\nconst step3list = {\n icate: 'ic',\n ative: '',\n alize: 'al',\n iciti: 'ic',\n ical: 'ic',\n ful: '',\n ness: ''\n}\n\n// Consonant-vowel sequences.\nconst consonant = '[^aeiou]'\nconst vowel = '[aeiouy]'\nconst consonants = '(' + consonant + '[^aeiouy]*)'\nconst vowels = '(' + vowel + '[aeiou]*)'\n\nconst gt0 = new RegExp('^' + consonants + '?' + vowels + consonants)\nconst eq1 = new RegExp(\n '^' + consonants + '?' + vowels + consonants + vowels + '?$'\n)\nconst gt1 = new RegExp('^' + consonants + '?(' + vowels + consonants + '){2,}')\nconst vowelInStem = new RegExp('^' + consonants + '?' + vowel)\nconst consonantLike = new RegExp('^' + consonants + vowel + '[^aeiouwxy]$')\n\n// Exception expressions.\nconst sfxLl = /ll$/\nconst sfxE = /^(.+?)e$/\nconst sfxY = /^(.+?)y$/\nconst sfxIon = /^(.+?(s|t))(ion)$/\nconst sfxEdOrIng = /^(.+?)(ed|ing)$/\nconst sfxAtOrBlOrIz = /(at|bl|iz)$/\nconst sfxEED = /^(.+?)eed$/\nconst sfxS = /^.+?[^s]s$/\nconst sfxSsesOrIes = /^.+?(ss|i)es$/\nconst sfxMultiConsonantLike = /([^aeiouylsz])\\1$/\nconst step2 =\n /^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$/\nconst step3 = /^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$/\nconst step4 =\n /^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$/\n\n/**\n * Get the stem from a given value.\n *\n * @param {string} value\n * Value to stem.\n * @returns {string}\n * Stem for `value`\n */\n// eslint-disable-next-line complexity\nexport function stemmer(value) {\n let result = String(value).toLowerCase()\n\n // Exit early.\n if (result.length < 3) {\n return result\n }\n\n /** @type {boolean} */\n let firstCharacterWasLowerCaseY = false\n\n // Detect initial `y`, make sure it never matches.\n if (\n result.codePointAt(0) === 121 // Lowercase Y\n ) {\n firstCharacterWasLowerCaseY = true\n result = 'Y' + result.slice(1)\n }\n\n // Step 1a.\n if (sfxSsesOrIes.test(result)) {\n // Remove last two characters.\n result = result.slice(0, -2)\n } else if (sfxS.test(result)) {\n // Remove last character.\n result = result.slice(0, -1)\n }\n\n /** @type {RegExpMatchArray|null} */\n let match\n\n // Step 1b.\n if ((match = sfxEED.exec(result))) {\n if (gt0.test(match[1])) {\n // Remove last character.\n result = result.slice(0, -1)\n }\n } else if ((match = sfxEdOrIng.exec(result)) && vowelInStem.test(match[1])) {\n result = match[1]\n\n if (sfxAtOrBlOrIz.test(result)) {\n // Append `e`.\n result += 'e'\n } else if (sfxMultiConsonantLike.test(result)) {\n // Remove last character.\n result = result.slice(0, -1)\n } else if (consonantLike.test(result)) {\n // Append `e`.\n result += 'e'\n }\n }\n\n // Step 1c.\n if ((match = sfxY.exec(result)) && vowelInStem.test(match[1])) {\n // Remove suffixing `y` and append `i`.\n result = match[1] + 'i'\n }\n\n // Step 2.\n if ((match = step2.exec(result)) && gt0.test(match[1])) {\n result = match[1] + step2list[match[2]]\n }\n\n // Step 3.\n if ((match = step3.exec(result)) && gt0.test(match[1])) {\n result = match[1] + step3list[match[2]]\n }\n\n // Step 4.\n if ((match = step4.exec(result))) {\n if (gt1.test(match[1])) {\n result = match[1]\n }\n } else if ((match = sfxIon.exec(result)) && gt1.test(match[1])) {\n result = match[1]\n }\n\n // Step 5.\n if (\n (match = sfxE.exec(result)) &&\n (gt1.test(match[1]) ||\n (eq1.test(match[1]) && !consonantLike.test(match[1])))\n ) {\n result = match[1]\n }\n\n if (sfxLl.test(result) && gt1.test(result)) {\n result = result.slice(0, -1)\n }\n\n // Turn initial `Y` back to `y`.\n if (firstCharacterWasLowerCaseY) {\n result = 'y' + result.slice(1)\n }\n\n return result\n}\n","/**\n * BPlusTree - Persistent immutable B+ tree with BinJsonFile storage\n * \n * Usage pattern:\n * const tree = new BPlusTree('tree.bj');\n * await tree.open();\n * await tree.add(key, value);\n * await tree.close();\n */\n\nimport { BinJsonFile, Pointer, getFileHandle, deleteFile } from './binjson.js';\n\n/**\n * Node for persistent storage\n * @private\n */\nclass NodeData {\n /**\n * Creates a node data object for serialization\n * @param {number} id - Unique node ID\n * @param {boolean} isLeaf - Leaf flag\n * @param {Array} keys - Key array\n * @param {Array} values - Value array (leaf nodes)\n * @param {Array} children - Child pointers (internal nodes)\n * @param {Pointer} next - Pointer to next leaf\n */\n constructor(id, isLeaf, keys, values, children, next) {\n this.id = id;\n this.isLeaf = isLeaf;\n this.keys = keys;\n this.values = values;\n this.children = children;\n for (let v of children) {\n if (!(v instanceof Pointer)) {\n throw new Error('Children must be Pointer objects');\n }\n }\n this.next = next;\n }\n}\n\n/**\n * Persistent immutable B+ tree with append-only file storage\n */\nexport class BPlusTree {\n /**\n * Creates a new persistent B+ tree\n * @param {FileSystemSyncAccessHandle} syncHandle - Sync access handle to storage file\n * @param {number} order - Tree order (default: 3)\n */\n constructor(syncHandle, order = 3) {\n if (order < 3) {\n throw new Error('B+ tree order must be at least 3');\n }\n this.file = new BinJsonFile(syncHandle);\n this.order = order;\n this.minKeys = Math.ceil(order / 2) - 1;\n \n this.isOpen = false;\n \n // Metadata\n this.rootPointer = null;\n this.nextNodeId = 0;\n this._size = 0;\n }\n\n /**\n * Open the tree (load or initialize metadata)\n */\n async open() {\n if (this.isOpen) {\n throw new Error('Tree is already open');\n }\n\n // Check if file has content\n const fileSize = this.file.getFileSize();\n const exists = fileSize > 0;\n\n if (exists) {\n this._loadMetadata();\n } else {\n this._initializeNewTree();\n }\n\n this.isOpen = true;\n }\n\n /**\n * Close the tree and save metadata\n */\n async close() {\n if (this.isOpen) {\n if (this.file && this.file.syncAccessHandle) {\n this.file.flush();\n await this.file.syncAccessHandle.close();\n }\n this.isOpen = false;\n }\n }\n\n /**\n * Initialize a new empty tree\n */\n _initializeNewTree() {\n const rootNode = new NodeData(0, true, [], [], [], null);\n this.nextNodeId = 1;\n this._size = 0;\n\n const rootPointer = this._saveNode(rootNode);\n this.rootPointer = rootPointer;\n\n this._saveMetadata();\n }\n\n /**\n * Save metadata to file\n */\n _saveMetadata() {\n const metadata = {\n version: 1,\n maxEntries: this.order, // Renamed to match RTree size\n minEntries: this.minKeys, // Renamed to match RTree size\n size: this._size,\n rootPointer: this.rootPointer,\n nextId: this.nextNodeId // Renamed to match RTree size\n };\n\n this.file.append(metadata);\n }\n\n /**\n * Load metadata from file\n */\n _loadMetadata() {\n const fileSize = this.file.getFileSize();\n // Metadata object has 6 INT fields (now encoded as 8-byte ints) plus keys\n const METADATA_SIZE = 135;\n \n if (fileSize < METADATA_SIZE) {\n throw new Error('Invalid tree file');\n }\n\n const metadataOffset = fileSize - METADATA_SIZE;\n const metadata = this.file.read(metadataOffset);\n\n if (!metadata || typeof metadata.maxEntries === 'undefined') {\n throw new Error(`Failed to read metadata: missing required fields`);\n }\n\n this.order = metadata.maxEntries;\n this.minKeys = metadata.minEntries;\n this._size = metadata.size;\n this.nextNodeId = metadata.nextId;\n this.rootPointer = metadata.rootPointer;\n }\n\n /**\n * Save a node to disk\n */\n _saveNode(node) {\n const offset = this.file.getFileSize();\n this.file.append(node);\n return new Pointer(offset);\n }\n\n /**\n * Load a node from disk\n */\n _loadNode(pointer) {\n if (!(pointer instanceof Pointer)) {\n throw new Error('Expected Pointer object');\n }\n\n const data = this.file.read(pointer);\n return new NodeData(\n data.id,\n data.isLeaf,\n data.keys,\n data.values,\n data.children,\n data.next\n );\n }\n\n /**\n * Load root node\n */\n _loadRoot() {\n return this._loadNode(this.rootPointer);\n }\n\n /**\n * Search for a key\n */\n search(key) {\n const root = this._loadRoot();\n return this._searchNode(root, key);\n }\n\n /**\n * Internal search\n */\n _searchNode(node, key) {\n if (node.isLeaf) {\n for (let i = 0; i < node.keys.length; i++) {\n if (key === node.keys[i]) {\n return node.values[i];\n }\n }\n return undefined;\n } else {\n let i = 0;\n while (i < node.keys.length && key >= node.keys[i]) {\n i++;\n }\n const child = this._loadNode(node.children[i]);\n return this._searchNode(child, key);\n }\n }\n\n /**\n * Insert a key-value pair\n */\n add(key, value) {\n const root = this._loadRoot();\n const result = this._addToNode(root, key, value);\n\n let newRoot;\n if (result.newNode) {\n newRoot = result.newNode;\n } else {\n // Split occurred - save the split nodes and create new root with pointers\n const leftPointer = this._saveNode(result.left);\n const rightPointer = this._saveNode(result.right);\n newRoot = new NodeData(\n this.nextNodeId++,\n false,\n [result.splitKey],\n [],\n [leftPointer, rightPointer],\n null\n );\n }\n\n const rootPointer = this._saveNode(newRoot);\n this.rootPointer = rootPointer;\n\n this._size++;\n this._saveMetadata();\n }\n\n /**\n * Internal add\n */\n _addToNode(node, key, value) {\n if (node.isLeaf) {\n const keys = [...node.keys];\n const values = [...node.values];\n\n const existingIdx = keys.indexOf(key);\n if (existingIdx !== -1) {\n values[existingIdx] = value;\n return {\n newNode: new NodeData(node.id, true, keys, values, [], null)\n };\n }\n\n let insertIdx = 0;\n while (insertIdx < keys.length && key > keys[insertIdx]) {\n insertIdx++;\n }\n keys.splice(insertIdx, 0, key);\n values.splice(insertIdx, 0, value);\n\n if (keys.length < this.order) {\n return {\n newNode: new NodeData(node.id, true, keys, values, [], null)\n };\n } else {\n const mid = Math.ceil(keys.length / 2);\n const leftKeys = keys.slice(0, mid);\n const leftValues = values.slice(0, mid);\n const rightKeys = keys.slice(mid);\n const rightValues = values.slice(mid);\n\n const rightNode = new NodeData(this.nextNodeId++, true, rightKeys, rightValues, [], null);\n const leftNode = new NodeData(node.id, true, leftKeys, leftValues, [], null);\n\n return {\n left: leftNode,\n right: rightNode,\n splitKey: rightKeys[0]\n };\n }\n } else {\n const keys = [...node.keys];\n const children = [...node.children];\n\n let childIdx = 0;\n while (childIdx < keys.length && key >= keys[childIdx]) {\n childIdx++;\n }\n\n const childNode = this._loadNode(children[childIdx]);\n const result = this._addToNode(childNode, key, value);\n\n if (result.newNode) {\n const newChildPointer = this._saveNode(result.newNode);\n children[childIdx] = newChildPointer;\n return {\n newNode: new NodeData(node.id, false, keys, [], children, null)\n };\n } else {\n const leftPointer = this._saveNode(result.left);\n const rightPointer = this._saveNode(result.right);\n\n keys.splice(childIdx, 0, result.splitKey);\n children.splice(childIdx, 1, leftPointer, rightPointer);\n\n if (keys.length < this.order) {\n return {\n newNode: new NodeData(node.id, false, keys, [], children, null)\n };\n } else {\n const mid = Math.ceil(keys.length / 2) - 1;\n const splitKey = keys[mid];\n const leftKeys = keys.slice(0, mid);\n const rightKeys = keys.slice(mid + 1);\n const leftChildren = children.slice(0, mid + 1);\n const rightChildren = children.slice(mid + 1);\n\n const leftNode = new NodeData(node.id, false, leftKeys, [], leftChildren, null);\n const rightNode = new NodeData(this.nextNodeId++, false, rightKeys, [], rightChildren, null);\n\n return {\n left: leftNode,\n right: rightNode,\n splitKey: splitKey\n };\n }\n }\n }\n }\n\n /**\n * Delete a key\n */\n delete(key) {\n const root = this._loadRoot();\n const newRoot = this._deleteFromNode(root, key);\n\n if (!newRoot) {\n return; // Key not found\n }\n\n let finalRoot = newRoot;\n if (finalRoot.keys.length === 0 && !finalRoot.isLeaf && finalRoot.children.length > 0) {\n finalRoot = this._loadNode(finalRoot.children[0]);\n }\n\n const rootPointer = this._saveNode(finalRoot);\n this.rootPointer = rootPointer;\n\n this._size--;\n this._saveMetadata();\n }\n\n /**\n * Internal delete\n */\n _deleteFromNode(node, key) {\n if (node.isLeaf) {\n const keyIndex = node.keys.indexOf(key);\n\n if (keyIndex === -1) {\n return null;\n }\n\n const newKeys = [...node.keys];\n const newValues = [...node.values];\n newKeys.splice(keyIndex, 1);\n newValues.splice(keyIndex, 1);\n\n return new NodeData(node.id, true, newKeys, newValues, [], node.next);\n } else {\n let i = 0;\n while (i < node.keys.length && key >= node.keys[i]) {\n i++;\n }\n\n const childNode = this._loadNode(node.children[i]);\n const newChild = this._deleteFromNode(childNode, key);\n\n if (!newChild) {\n return null;\n }\n\n const newChildren = [...node.children];\n const newChildPointer = this._saveNode(newChild);\n newChildren[i] = newChildPointer;\n\n return new NodeData(node.id, false, [...node.keys], [], newChildren, null);\n }\n }\n\n /**\n * Get all entries as array\n */\n toArray() {\n const result = [];\n this._collectAllEntries(this._loadRoot(), result);\n return result;\n }\n\n /**\n * Async iterator for efficiently traversing all entries without loading everything into memory\n * Enables usage: `for await (const entry of tree) { ... }`\n * Each entry has shape: { key, value }\n */\n async *[Symbol.asyncIterator]() {\n if (!this.isOpen) {\n throw new Error('Tree must be open before iteration');\n }\n\n if (this._size === 0) {\n return;\n }\n\n // Use a stack-based traversal instead of relying on next pointers\n // since the persistent/immutable structure makes maintaining leaf links complex\n yield* this._iterateNode(this._loadRoot());\n }\n\n /**\n * Helper generator to recursively iterate through a node\n * @private\n */\n *_iterateNode(node) {\n if (node.isLeaf) {\n // Yield all entries in this leaf\n for (let i = 0; i < node.keys.length; i++) {\n yield {\n key: node.keys[i],\n value: node.values[i]\n };\n }\n } else {\n // Recursively iterate through all children in order\n for (const childPointer of node.children) {\n const child = this._loadNode(childPointer);\n yield* this._iterateNode(child);\n }\n }\n }\n\n /**\n * Collect all entries in sorted order by traversing tree\n * @private\n */\n _collectAllEntries(node, result) {\n if (node.isLeaf) {\n for (let i = 0; i < node.keys.length; i++) {\n result.push({\n key: node.keys[i],\n value: node.values[i]\n });\n }\n } else {\n for (const childPointer of node.children) {\n const child = this._loadNode(childPointer);\n this._collectAllEntries(child, result);\n }\n }\n }\n\n /**\n * Get tree size\n */\n size() {\n return this._size;\n }\n\n /**\n * Check if empty\n */\n isEmpty() {\n return this._size === 0;\n }\n\n /**\n * Range search\n */\n rangeSearch(minKey, maxKey) {\n const result = [];\n this._rangeSearchNode(this._loadRoot(), minKey, maxKey, result);\n return result;\n }\n\n /**\n * Range search helper that traverses tree\n * @private\n */\n _rangeSearchNode(node, minKey, maxKey, result) {\n if (node.isLeaf) {\n for (let i = 0; i < node.keys.length; i++) {\n if (node.keys[i] >= minKey && node.keys[i] <= maxKey) {\n result.push({\n key: node.keys[i],\n value: node.values[i]\n });\n }\n }\n } else {\n for (const childPointer of node.children) {\n const child = this._loadNode(childPointer);\n this._rangeSearchNode(child, minKey, maxKey, result);\n }\n }\n }\n\n /**\n * Get tree height\n */\n getHeight() {\n let height = 0;\n let current = this._loadRoot();\n\n while (!current.isLeaf) {\n height++;\n current = this._loadNode(current.children[0]);\n }\n\n return height;\n }\n\n /**\n * Compact the tree by copying all live entries into a new file.\n * Returns size metrics so callers can see how much space was reclaimed.\n * @param {FileSystemSyncAccessHandle} destSyncHandle - Sync handle for destination file\n * @returns {Promise<{oldSize:number,newSize:number,bytesSaved:number}>}\n */\n async compact(destSyncHandle) {\n if (!this.isOpen) {\n throw new Error('Tree file is not open');\n }\n if (!destSyncHandle) {\n throw new Error('Destination sync handle is required for compaction');\n }\n\n // Make sure the current file has up-to-date metadata before measuring size\n const oldSize = this.file.getFileSize();\n\n // Rebuild a fresh tree with only the live entries\n const entries = this.toArray();\n \n const newTree = new BPlusTree(destSyncHandle, this.order);\n await newTree.open();\n for (const entry of entries) {\n await newTree.add(entry.key, entry.value);\n }\n \n // Measure new file size before closing\n const newSize = newTree.file.getFileSize();\n \n await newTree.close();\n\n return {\n oldSize,\n newSize,\n bytesSaved: Math.max(0, oldSize - newSize)\n };\n }\n}\n","import { stemmer } from 'stemmer';\nimport { BPlusTree } from './bplustree.js';\nimport { getFileHandle } from './binjson.js';\n\n// Common English stop words that don't add semantic value to searches\nconst STOPWORDS = new Set([\n 'a', 'about', 'after', 'all', 'also', 'am', 'an', 'and', 'another', 'any', 'are', \n 'around', 'as', 'at', 'be', 'because', 'been', 'before', 'being', 'between', 'both', \n 'but', 'by', 'came', 'can', 'come', 'could', 'did', 'do', 'each', 'for', 'from', \n 'get', 'got', 'has', 'had', 'he', 'have', 'her', 'here', 'him', 'himself', 'his', \n 'how', 'i', 'if', 'in', 'into', 'is', 'it', 'like', 'make', 'many', 'me', 'might', \n 'more', 'most', 'much', 'must', 'my', 'never', 'now', 'of', 'on', 'only', 'or', \n 'other', 'our', 'out', 'over', 'said', 'same', 'see', 'should', 'since', 'some', \n 'still', 'such', 'take', 'than', 'that', 'the', 'their', 'them', 'then', 'there', \n 'these', 'they', 'this', 'those', 'through', 'to', 'too', 'under', 'up', 'very', \n 'was', 'way', 'we', 'well', 'were', 'what', 'where', 'which', 'while', 'who', \n 'with', 'would', 'you', 'your'\n]);\n\n/**\n * Tokenize text into individual words\n * @param {string} text - The text to tokenize\n * @returns {string[]} Array of words\n */\nexport function tokenize(text) {\n if (typeof text !== 'string') {\n return [];\n }\n // Split on non-word characters and filter out empty strings\n const words = text.toLowerCase()\n .split(/\\W+/)\n .filter(word => word.length > 0);\n \n // Filter stop words\n return words.filter(word => !STOPWORDS.has(word));\n}\n\n/**\n * TextIndex - A text index implementation using Porter stemmer algorithm\n * \n * This class provides full-text search capabilities by indexing terms\n * and associating them with document IDs. It uses the Porter stemmer\n * algorithm to normalize words to their root forms.\n */\nexport class TextIndex {\n constructor(options = {}) {\n const {\n order = 16,\n trees\n } = options;\n\n this.order = order;\n this.index = trees?.index || null;\n this.documentTerms = trees?.documentTerms || null;\n this.documentLengths = trees?.documentLengths || null;\n this.isOpen = false;\n }\n\n async open() {\n if (this.isOpen) {\n throw new Error('TextIndex is already open');\n }\n\n if (!this.index || !this.documentTerms || !this.documentLengths) {\n throw new Error('Trees must be initialized before opening');\n }\n\n await Promise.all([\n this.index.open(),\n this.documentTerms.open(),\n this.documentLengths.open()\n ]);\n\n this.isOpen = true;\n }\n\n async close() {\n if (!this.isOpen) {\n return;\n }\n\n await Promise.all([\n this.index.close(),\n this.documentTerms.close(),\n this.documentLengths.close()\n ]);\n\n this.isOpen = false;\n }\n\n _ensureOpen() {\n if (!this.isOpen) {\n throw new Error('TextIndex is not open');\n }\n }\n\n /**\n * Add terms from text to the index for a given document ID\n * @param {string} docId - The document identifier\n * @param {string} text - The text content to index\n */\n async add(docId, text) {\n this._ensureOpen();\n\n if (!docId) {\n throw new Error('Document ID is required');\n }\n\n const words = tokenize(text);\n const termFrequency = new Map();\n\n words.forEach(word => {\n const stem = stemmer(word);\n termFrequency.set(stem, (termFrequency.get(stem) || 0) + 1);\n });\n\n for (const [stem, frequency] of termFrequency.entries()) {\n const postings = (await this.index.search(stem)) || {};\n postings[docId] = frequency;\n await this.index.add(stem, postings);\n }\n\n const existingTerms = (await this.documentTerms.search(docId)) || {};\n const mergedTerms = { ...existingTerms };\n termFrequency.forEach((frequency, stem) => {\n mergedTerms[stem] = frequency;\n });\n\n const docLength = Object.values(mergedTerms).reduce((sum, count) => sum + count, 0);\n\n await this.documentTerms.add(docId, mergedTerms);\n await this.documentLengths.add(docId, docLength);\n }\n\n /**\n * Remove all indexed terms for a given document ID\n * @param {string} docId - The document identifier to remove\n * @returns {boolean} True if document was found and removed, false otherwise\n */\n async remove(docId) {\n this._ensureOpen();\n\n const terms = await this.documentTerms.search(docId);\n if (!terms) {\n return false;\n }\n\n for (const [term] of Object.entries(terms)) {\n const postings = (await this.index.search(term)) || {};\n delete postings[docId];\n\n if (Object.keys(postings).length === 0) {\n await this.index.delete(term);\n } else {\n await this.index.add(term, postings);\n }\n }\n\n await this.documentTerms.delete(docId);\n await this.documentLengths.delete(docId);\n return true;\n }\n\n /**\n * Query the index for documents containing the given terms with relevance scoring\n * @param {string} queryText - The search query text\n * @param {Object} options - Query options\n * @param {boolean} options.scored - If true, return scored results; if false, return just IDs (default: true)\n * @param {boolean} options.requireAll - If true, require ALL terms; if false, rank by relevance (default: false)\n * @returns {Array} Array of document IDs (if scored=false) or objects with {id, score} (if scored=true)\n */\n async query(queryText, options = { scored: true, requireAll: false }) {\n this._ensureOpen();\n\n const words = tokenize(queryText);\n if (words.length === 0) {\n return [];\n }\n\n const stemmedTerms = words.map(word => stemmer(word));\n const uniqueTerms = [...new Set(stemmedTerms)];\n\n if (options.requireAll) {\n const docSets = [];\n for (const term of uniqueTerms) {\n const termDocs = await this.index.search(term);\n docSets.push(new Set(Object.keys(termDocs || {})));\n }\n\n if (docSets.length === 0) {\n return [];\n }\n\n const intersection = new Set(docSets[0]);\n for (let i = 1; i < docSets.length; i++) {\n for (const docId of [...intersection]) {\n if (!docSets[i].has(docId)) {\n intersection.delete(docId);\n }\n }\n }\n\n return Array.from(intersection);\n }\n\n const docLengthEntries = await this.documentLengths.toArray();\n const docLengthMap = new Map(docLengthEntries.map(({ key, value }) => [String(key), value || 1]));\n const totalDocs = docLengthEntries.length;\n\n const idf = new Map();\n for (const term of uniqueTerms) {\n const termDocs = await this.index.search(term);\n const docsWithTerm = termDocs ? Object.keys(termDocs).length : 0;\n if (docsWithTerm > 0) {\n idf.set(term, Math.log(totalDocs / docsWithTerm));\n }\n }\n\n const docScores = new Map();\n for (const term of uniqueTerms) {\n const termDocs = await this.index.search(term);\n if (!termDocs) {\n continue;\n }\n\n for (const [docId, termFreq] of Object.entries(termDocs)) {\n const docLength = docLengthMap.get(docId) || 1;\n const tf = termFreq / docLength;\n const termIdf = idf.get(term) || 0;\n const prev = docScores.get(docId) || 0;\n docScores.set(docId, prev + tf * termIdf);\n }\n }\n\n for (const [docId, score] of docScores.entries()) {\n const docTerms = (await this.documentTerms.search(docId)) || {};\n const matchingTerms = uniqueTerms.filter(term => !!docTerms[term]).length;\n const coverage = matchingTerms / uniqueTerms.length;\n docScores.set(docId, score * (1 + coverage));\n }\n\n const results = Array.from(docScores.entries())\n .map(([id, score]) => ({ id, score }))\n .sort((a, b) => b.score - a.score);\n\n if (options.scored === false) {\n return results.map(r => r.id);\n }\n \n return results;\n }\n\n /**\n * Get the number of unique terms in the index\n * @returns {number} Number of unique terms\n */\n async getTermCount() {\n this._ensureOpen();\n const terms = await this.index.toArray();\n return terms.length;\n }\n\n /**\n * Get the number of documents in the index\n * @returns {number} Number of indexed documents\n */\n async getDocumentCount() {\n this._ensureOpen();\n const docs = await this.documentTerms.toArray();\n return docs.length;\n }\n\n /**\n * Clear all data from the index\n */\n async clear() {\n this._ensureOpen();\n\n const [terms, docs, lengths] = await Promise.all([\n this.index.toArray(),\n this.documentTerms.toArray(),\n this.documentLengths.toArray()\n ]);\n\n // Run deletes sequentially to avoid overlapping writes on the same underlying file\n for (const entry of terms) {\n await this.index.delete(entry.key);\n }\n\n for (const entry of docs) {\n await this.documentTerms.delete(entry.key);\n }\n\n for (const entry of lengths) {\n await this.documentLengths.delete(entry.key);\n }\n }\n\n /**\n * Compact all internal B+ trees using provided destination tree instances.\n * The destination trees should be freshly created (unopened) with new sync handles.\n * After compaction completes, the destination sync handles will be closed.\n * @param {Object} options - Compaction options \n * @param {BPlusTree} options.index - Fresh destination tree for index data\n * @param {BPlusTree} options.documentTerms - Fresh destination tree for document terms\n * @param {BPlusTree} options.documentLengths - Fresh destination tree for document lengths\n * @returns {Promise<{terms: object, documents: object, lengths: object}>}\n */\n async compact({ index: destIndex, documentTerms: destDocTerms, documentLengths: destDocLengths }) {\n this._ensureOpen();\n\n if (!destIndex || !destDocTerms || !destDocLengths) {\n throw new Error('Destination trees must be provided for compaction');\n }\n\n // Compact the trees. Note: BPlusTree.compact() will close the destination sync handle\n // when finished, so these destination trees should be disposable after this call\n const termsResult = await this.index.compact(destIndex.file.syncAccessHandle);\n const documentsResult = await this.documentTerms.compact(destDocTerms.file.syncAccessHandle);\n const lengthsResult = await this.documentLengths.compact(destDocLengths.file.syncAccessHandle);\n\n // Close the old trees - now the index is closed\n await this.close();\n this.isOpen = false;\n\n return {\n terms: termsResult,\n documents: documentsResult,\n lengths: lengthsResult\n };\n }\n\n}\n\n// Re-export the stemmer so consumers can share the exact same implementation\nexport { stemmer };\n","/**\n * Aggregation Expression Evaluator\n * \n * Implements MongoDB aggregation expression operators for use in\n * $project, $addFields, $set, $group, and other pipeline stages.\n */\n\nimport { getProp } from '../utils.js';\n\n/**\n * Evaluate an aggregation expression against a document\n * @param {*} expr - The expression to evaluate (can be literal, field reference, or expression object)\n * @param {Object} doc - The document to evaluate against\n * @returns {*} The evaluated result\n */\nexport function evaluateExpression(expr, doc) {\n\t// Literal values (strings not starting with $, numbers, booleans, null)\n\tif (expr === null || expr === undefined) {\n\t\treturn expr;\n\t}\n\t\n\tif (typeof expr === 'boolean' || typeof expr === 'number') {\n\t\treturn expr;\n\t}\n\t\n\t// Field reference ($fieldName) or variable reference ($$variableName)\n\tif (typeof expr === 'string') {\n\t\tif (expr.startsWith('$$')) {\n\t\t\t// Special system variables for $redact\n\t\t\tif (expr === '$$KEEP' || expr === '$$PRUNE' || expr === '$$DESCEND') {\n\t\t\t\treturn expr;\n\t\t\t}\n\t\t\t// Variable reference ($$var)\n\t\t\treturn getProp(doc, expr.substring(2));\n\t\t} else if (expr.charAt(0) === '$') {\n\t\t\t// Field reference ($field)\n\t\t\treturn getProp(doc, expr.substring(1));\n\t\t}\n\t\treturn expr; // Literal string\n\t}\n\t\n\t// Expression object\n\tif (typeof expr === 'object') {\n\t\t// Check if it's an array literal\n\t\tif (Array.isArray(expr)) {\n\t\t\treturn expr.map(item => evaluateExpression(item, doc));\n\t\t}\n\t\t\n\t\t// Expression operator\n\t\tconst keys = Object.keys(expr);\n\t\tif (keys.length === 0) {\n\t\t\treturn expr; // Empty object literal\n\t\t}\n\t\t\n\t\tconst operator = keys[0];\n\t\t\n\t\t// Check if this is an operator (starts with $) or an object literal\n\t\tif (operator.charAt(0) === '$') {\n\t\t\t// This is an expression operator\n\t\t\tconst operand = expr[operator];\n\t\t\treturn evaluateOperator(operator, operand, doc);\n\t\t} else {\n\t\t\t// This is an object literal - evaluate each field\n\t\t\tconst result = {};\n\t\t\tfor (const key of keys) {\n\t\t\t\tresult[key] = evaluateExpression(expr[key], doc);\n\t\t\t}\n\t\t\treturn result;\n\t\t}\n\t}\n\t\n\treturn expr;\n}\n\n/**\n * Evaluate a specific operator\n */\nfunction evaluateOperator(operator, operand, doc) {\n\tswitch (operator) {\n\t\t// Arithmetic operators\n\t\tcase '$add': return evalAdd(operand, doc);\n\t\tcase '$subtract': return evalSubtract(operand, doc);\n\t\tcase '$multiply': return evalMultiply(operand, doc);\n\t\tcase '$divide': return evalDivide(operand, doc);\n\t\tcase '$mod': return evalMod(operand, doc);\n\t\tcase '$pow': return evalPow(operand, doc);\n\t\tcase '$sqrt': return evalSqrt(operand, doc);\n\t\tcase '$abs': return evalAbs(operand, doc);\n\t\tcase '$ceil': return evalCeil(operand, doc);\n\t\tcase '$floor': return evalFloor(operand, doc);\n\t\tcase '$trunc': return evalTrunc(operand, doc);\n\t\tcase '$round': return evalRound(operand, doc);\n\t\t\n\t\t// String operators\n\t\tcase '$concat': return evalConcat(operand, doc);\n\t\tcase '$substr': return evalSubstr(operand, doc);\n\t\tcase '$toLower': return evalToLower(operand, doc);\n\t\tcase '$toUpper': return evalToUpper(operand, doc);\n\t\tcase '$trim': return evalTrim(operand, doc);\n\t\tcase '$ltrim': return evalLtrim(operand, doc);\n\t\tcase '$rtrim': return evalRtrim(operand, doc);\n\t\tcase '$split': return evalSplit(operand, doc);\n\t\tcase '$strLenCP': return evalStrLenCP(operand, doc);\n\t\tcase '$strcasecmp': return evalStrcasecmp(operand, doc);\n\t\tcase '$indexOfCP': return evalIndexOfCP(operand, doc);\n\t\tcase '$replaceOne': return evalReplaceOne(operand, doc);\n\t\tcase '$replaceAll': return evalReplaceAll(operand, doc);\n\t\t\n\t\t// Comparison operators\n\t\tcase '$cmp': return evalCmp(operand, doc);\n\t\tcase '$eq': return evalEq(operand, doc);\n\t\tcase '$ne': return evalNe(operand, doc);\n\t\tcase '$gt': return evalGt(operand, doc);\n\t\tcase '$gte': return evalGte(operand, doc);\n\t\tcase '$lt': return evalLt(operand, doc);\n\t\tcase '$lte': return evalLte(operand, doc);\n\t\t\n\t\t// Logical operators\n\t\tcase '$and': return evalAnd(operand, doc);\n\t\tcase '$or': return evalOr(operand, doc);\n\t\tcase '$not': return evalNot(operand, doc);\n\t\t\n\t\t// Conditional operators\n\t\tcase '$cond': return evalCond(operand, doc);\n\t\tcase '$ifNull': return evalIfNull(operand, doc);\n\t\tcase '$switch': return evalSwitch(operand, doc);\n\t\t\n\t\t// Date operators\n\t\tcase '$year': return evalYear(operand, doc);\n\t\tcase '$month': return evalMonth(operand, doc);\n\t\tcase '$dayOfMonth': return evalDayOfMonth(operand, doc);\n\t\tcase '$dayOfWeek': return evalDayOfWeek(operand, doc);\n\t\tcase '$dayOfYear': return evalDayOfYear(operand, doc);\n\t\tcase '$hour': return evalHour(operand, doc);\n\t\tcase '$minute': return evalMinute(operand, doc);\n\t\tcase '$second': return evalSecond(operand, doc);\n\t\tcase '$millisecond': return evalMillisecond(operand, doc);\n\t\tcase '$week': return evalWeek(operand, doc);\n\t\tcase '$isoWeek': return evalIsoWeek(operand, doc);\n\t\tcase '$isoWeekYear': return evalIsoWeekYear(operand, doc);\n\t\tcase '$dateToString': return evalDateToString(operand, doc);\n\t\tcase '$toDate': return evalToDate(operand, doc);\n\t\t\n\t\t// Array operators\n\t\tcase '$arrayElemAt': return evalArrayElemAt(operand, doc);\n\t\tcase '$concatArrays': return evalConcatArrays(operand, doc);\n\t\tcase '$filter': return evalFilter(operand, doc);\n\t\tcase '$in': return evalIn(operand, doc);\n\t\tcase '$indexOfArray': return evalIndexOfArray(operand, doc);\n\t\tcase '$isArray': return evalIsArray(operand, doc);\n\t\tcase '$map': return evalMap(operand, doc);\n\t\tcase '$reduce': return evalReduce(operand, doc);\n\t\tcase '$size': return evalSize(operand, doc);\n\t\tcase '$slice': return evalSlice(operand, doc);\n\t\tcase '$reverseArray': return evalReverseArray(operand, doc);\n\t\tcase '$zip': return evalZip(operand, doc);\n\t\t\n\t\t// Type operators\n\t\tcase '$type': return evalType(operand, doc);\n\t\tcase '$convert': return evalConvert(operand, doc);\n\t\tcase '$toBool': return evalToBool(operand, doc);\n\t\tcase '$toDecimal': return evalToDecimal(operand, doc);\n\t\tcase '$toDouble': return evalToDouble(operand, doc);\n\t\tcase '$toInt': return evalToInt(operand, doc);\n\t\tcase '$toLong': return evalToLong(operand, doc);\n\t\tcase '$toString': return evalToString(operand, doc);\n\t\t\n\t\t// Object operators\n\t\tcase '$objectToArray': return evalObjectToArray(operand, doc);\n\t\tcase '$arrayToObject': return evalArrayToObject(operand, doc);\n\t\tcase '$mergeObjects': return evalMergeObjects(operand, doc);\n\t\t\n\t\t// Literal operator\n\t\tcase '$literal': return operand;\n\t\t\n\t\tdefault:\n\t\t\tthrow new Error(`Unsupported aggregation operator: ${operator}`);\n\t}\n}\n\n// ============================================================================\n// ARITHMETIC OPERATORS\n// ============================================================================\n\nfunction evalAdd(operands, doc) {\n\tif (!Array.isArray(operands)) return null;\n\tlet sum = 0;\n\tfor (const operand of operands) {\n\t\tconst val = evaluateExpression(operand, doc);\n\t\tif (val instanceof Date) {\n\t\t\tsum += val.getTime();\n\t\t} else if (typeof val === 'number') {\n\t\t\tsum += val;\n\t\t}\n\t}\n\treturn sum;\n}\n\nfunction evalSubtract(operands, doc) {\n\tif (!Array.isArray(operands) || operands.length !== 2) return null;\n\tconst val1 = evaluateExpression(operands[0], doc);\n\tconst val2 = evaluateExpression(operands[1], doc);\n\t\n\tif (val1 instanceof Date && val2 instanceof Date) {\n\t\treturn val1.getTime() - val2.getTime();\n\t} else if (val1 instanceof Date && typeof val2 === 'number') {\n\t\treturn new Date(val1.getTime() - val2);\n\t} else if (typeof val1 === 'number' && typeof val2 === 'number') {\n\t\treturn val1 - val2;\n\t}\n\treturn null;\n}\n\nfunction evalMultiply(operands, doc) {\n\tif (!Array.isArray(operands)) return null;\n\tlet product = 1;\n\tfor (const operand of operands) {\n\t\tconst val = evaluateExpression(operand, doc);\n\t\tif (typeof val === 'number') {\n\t\t\tproduct *= val;\n\t\t}\n\t}\n\treturn product;\n}\n\nfunction evalDivide(operands, doc) {\n\tif (!Array.isArray(operands) || operands.length !== 2) return null;\n\tconst val1 = evaluateExpression(operands[0], doc);\n\tconst val2 = evaluateExpression(operands[1], doc);\n\tif (typeof val1 === 'number' && typeof val2 === 'number' && val2 !== 0) {\n\t\treturn val1 / val2;\n\t}\n\treturn null;\n}\n\nfunction evalMod(operands, doc) {\n\tif (!Array.isArray(operands) || operands.length !== 2) return null;\n\tconst val1 = evaluateExpression(operands[0], doc);\n\tconst val2 = evaluateExpression(operands[1], doc);\n\tif (typeof val1 === 'number' && typeof val2 === 'number' && val2 !== 0) {\n\t\treturn val1 % val2;\n\t}\n\treturn null;\n}\n\nfunction evalPow(operands, doc) {\n\tif (!Array.isArray(operands) || operands.length !== 2) return null;\n\tconst base = evaluateExpression(operands[0], doc);\n\tconst exponent = evaluateExpression(operands[1], doc);\n\tif (typeof base === 'number' && typeof exponent === 'number') {\n\t\treturn Math.pow(base, exponent);\n\t}\n\treturn null;\n}\n\nfunction evalSqrt(operand, doc) {\n\tconst val = evaluateExpression(operand, doc);\n\tif (typeof val === 'number' && val >= 0) {\n\t\treturn Math.sqrt(val);\n\t}\n\treturn null;\n}\n\nfunction evalAbs(operand, doc) {\n\tconst val = evaluateExpression(operand, doc);\n\tif (typeof val === 'number') {\n\t\treturn Math.abs(val);\n\t}\n\treturn null;\n}\n\nfunction evalCeil(operand, doc) {\n\tconst val = evaluateExpression(operand, doc);\n\tif (typeof val === 'number') {\n\t\treturn Math.ceil(val);\n\t}\n\treturn null;\n}\n\nfunction evalFloor(operand, doc) {\n\tconst val = evaluateExpression(operand, doc);\n\tif (typeof val === 'number') {\n\t\treturn Math.floor(val);\n\t}\n\treturn null;\n}\n\nfunction evalTrunc(operand, doc) {\n\tconst val = evaluateExpression(operand, doc);\n\tif (typeof val === 'number') {\n\t\treturn Math.trunc(val);\n\t}\n\treturn null;\n}\n\nfunction evalRound(operands, doc) {\n\tconst val = evaluateExpression(Array.isArray(operands) ? operands[0] : operands, doc);\n\tconst place = Array.isArray(operands) && operands[1] !== undefined \n\t\t? evaluateExpression(operands[1], doc) \n\t\t: 0;\n\t\n\tif (typeof val === 'number' && typeof place === 'number') {\n\t\tconst multiplier = Math.pow(10, place);\n\t\treturn Math.round(val * multiplier) / multiplier;\n\t}\n\treturn null;\n}\n\n// ============================================================================\n// STRING OPERATORS\n// ============================================================================\n\nfunction evalConcat(operands, doc) {\n\tif (!Array.isArray(operands)) return null;\n\tlet result = '';\n\tfor (const operand of operands) {\n\t\tconst val = evaluateExpression(operand, doc);\n\t\tif (val !== null && val !== undefined) {\n\t\t\tresult += String(val);\n\t\t}\n\t}\n\treturn result;\n}\n\nfunction evalSubstr(operands, doc) {\n\tif (!Array.isArray(operands) || operands.length < 3) return null;\n\tconst str = String(evaluateExpression(operands[0], doc) || '');\n\tconst start = evaluateExpression(operands[1], doc);\n\tconst length = evaluateExpression(operands[2], doc);\n\tif (typeof start === 'number' && typeof length === 'number') {\n\t\treturn str.substr(start, length);\n\t}\n\treturn null;\n}\n\nfunction evalToLower(operand, doc) {\n\tconst val = evaluateExpression(operand, doc);\n\treturn val !== null && val !== undefined ? String(val).toLowerCase() : '';\n}\n\nfunction evalToUpper(operand, doc) {\n\tconst val = evaluateExpression(operand, doc);\n\treturn val !== null && val !== undefined ? String(val).toUpperCase() : '';\n}\n\nfunction evalTrim(operand, doc) {\n\tconst val = evaluateExpression(typeof operand === 'object' && operand.input ? operand.input : operand, doc);\n\tconst chars = operand.chars ? evaluateExpression(operand.chars, doc) : null;\n\t\n\tlet str = val !== null && val !== undefined ? String(val) : '';\n\t\n\tif (chars) {\n\t\tconst charsRegex = new RegExp(`^[${escapeRegex(chars)}]+|[${escapeRegex(chars)}]+$`, 'g');\n\t\treturn str.replace(charsRegex, '');\n\t}\n\treturn str.trim();\n}\n\nfunction evalLtrim(operand, doc) {\n\tconst val = evaluateExpression(typeof operand === 'object' && operand.input ? operand.input : operand, doc);\n\tconst chars = operand.chars ? evaluateExpression(operand.chars, doc) : null;\n\t\n\tlet str = val !== null && val !== undefined ? String(val) : '';\n\t\n\tif (chars) {\n\t\tconst charsRegex = new RegExp(`^[${escapeRegex(chars)}]+`, 'g');\n\t\treturn str.replace(charsRegex, '');\n\t}\n\treturn str.replace(/^\\s+/, '');\n}\n\nfunction evalRtrim(operand, doc) {\n\tconst val = evaluateExpression(typeof operand === 'object' && operand.input ? operand.input : operand, doc);\n\tconst chars = operand.chars ? evaluateExpression(operand.chars, doc) : null;\n\t\n\tlet str = val !== null && val !== undefined ? String(val) : '';\n\t\n\tif (chars) {\n\t\tconst charsRegex = new RegExp(`[${escapeRegex(chars)}]+$`, 'g');\n\t\treturn str.replace(charsRegex, '');\n\t}\n\treturn str.replace(/\\s+$/, '');\n}\n\nfunction evalSplit(operands, doc) {\n\tif (!Array.isArray(operands) || operands.length !== 2) return null;\n\tconst str = String(evaluateExpression(operands[0], doc) || '');\n\tconst delimiter = String(evaluateExpression(operands[1], doc) || '');\n\treturn str.split(delimiter);\n}\n\nfunction evalStrLenCP(operand, doc) {\n\tconst val = evaluateExpression(operand, doc);\n\treturn val !== null && val !== undefined ? String(val).length : 0;\n}\n\nfunction evalStrcasecmp(operands, doc) {\n\tif (!Array.isArray(operands) || operands.length !== 2) return null;\n\tconst str1 = String(evaluateExpression(operands[0], doc) || '').toLowerCase();\n\tconst str2 = String(evaluateExpression(operands[1], doc) || '').toLowerCase();\n\t\n\tif (str1 < str2) return -1;\n\tif (str1 > str2) return 1;\n\treturn 0;\n}\n\nfunction evalIndexOfCP(operands, doc) {\n\tif (!Array.isArray(operands) || operands.length < 2) return null;\n\tconst str = String(evaluateExpression(operands[0], doc) || '');\n\tconst substr = String(evaluateExpression(operands[1], doc) || '');\n\tconst start = operands[2] !== undefined ? evaluateExpression(operands[2], doc) : 0;\n\tconst end = operands[3] !== undefined ? evaluateExpression(operands[3], doc) : str.length;\n\t\n\tconst searchStr = str.substring(start, end);\n\tconst index = searchStr.indexOf(substr);\n\treturn index === -1 ? -1 : index + start;\n}\n\nfunction evalReplaceOne(operand, doc) {\n\tconst input = String(evaluateExpression(operand.input, doc) || '');\n\tconst find = String(evaluateExpression(operand.find, doc) || '');\n\tconst replacement = String(evaluateExpression(operand.replacement, doc) || '');\n\t\n\treturn input.replace(find, replacement);\n}\n\nfunction evalReplaceAll(operand, doc) {\n\tconst input = String(evaluateExpression(operand.input, doc) || '');\n\tconst find = String(evaluateExpression(operand.find, doc) || '');\n\tconst replacement = String(evaluateExpression(operand.replacement, doc) || '');\n\t\n\treturn input.split(find).join(replacement);\n}\n\nfunction escapeRegex(str) {\n\treturn str.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n\n// ============================================================================\n// COMPARISON OPERATORS\n// ============================================================================\n\nfunction evalCmp(operands, doc) {\n\tif (!Array.isArray(operands) || operands.length !== 2) return null;\n\tconst val1 = evaluateExpression(operands[0], doc);\n\tconst val2 = evaluateExpression(operands[1], doc);\n\t\n\tif (val1 < val2) return -1;\n\tif (val1 > val2) return 1;\n\treturn 0;\n}\n\nfunction evalEq(operands, doc) {\n\tif (!Array.isArray(operands) || operands.length !== 2) return null;\n\tconst val1 = evaluateExpression(operands[0], doc);\n\tconst val2 = evaluateExpression(operands[1], doc);\n\treturn val1 === val2;\n}\n\nfunction evalNe(operands, doc) {\n\tif (!Array.isArray(operands) || operands.length !== 2) return null;\n\tconst val1 = evaluateExpression(operands[0], doc);\n\tconst val2 = evaluateExpression(operands[1], doc);\n\treturn val1 !== val2;\n}\n\nfunction evalGt(operands, doc) {\n\tif (!Array.isArray(operands) || operands.length !== 2) return null;\n\tconst val1 = evaluateExpression(operands[0], doc);\n\tconst val2 = evaluateExpression(operands[1], doc);\n\treturn val1 > val2;\n}\n\nfunction evalGte(operands, doc) {\n\tif (!Array.isArray(operands) || operands.length !== 2) return null;\n\tconst val1 = evaluateExpression(operands[0], doc);\n\tconst val2 = evaluateExpression(operands[1], doc);\n\treturn val1 >= val2;\n}\n\nfunction evalLt(operands, doc) {\n\tif (!Array.isArray(operands) || operands.length !== 2) return null;\n\tconst val1 = evaluateExpression(operands[0], doc);\n\tconst val2 = evaluateExpression(operands[1], doc);\n\treturn val1 < val2;\n}\n\nfunction evalLte(operands, doc) {\n\tif (!Array.isArray(operands) || operands.length !== 2) return null;\n\tconst val1 = evaluateExpression(operands[0], doc);\n\tconst val2 = evaluateExpression(operands[1], doc);\n\treturn val1 <= val2;\n}\n\n// ============================================================================\n// LOGICAL OPERATORS\n// ============================================================================\n\nfunction evalAnd(operands, doc) {\n\tif (!Array.isArray(operands)) return null;\n\tfor (const operand of operands) {\n\t\tconst val = evaluateExpression(operand, doc);\n\t\tif (!val) return false;\n\t}\n\treturn true;\n}\n\nfunction evalOr(operands, doc) {\n\tif (!Array.isArray(operands)) return null;\n\tfor (const operand of operands) {\n\t\tconst val = evaluateExpression(operand, doc);\n\t\tif (val) return true;\n\t}\n\treturn false;\n}\n\nfunction evalNot(operand, doc) {\n\tconst val = evaluateExpression(Array.isArray(operand) ? operand[0] : operand, doc);\n\treturn !val;\n}\n\n// ============================================================================\n// CONDITIONAL OPERATORS\n// ============================================================================\n\nfunction evalCond(operand, doc) {\n\t// Supports both array form [if, then, else] and object form {if, then, else}\n\tlet ifExpr, thenExpr, elseExpr;\n\t\n\tif (Array.isArray(operand)) {\n\t\tif (operand.length !== 3) return null;\n\t\t[ifExpr, thenExpr, elseExpr] = operand;\n\t} else if (typeof operand === 'object') {\n\t\tifExpr = operand.if;\n\t\tthenExpr = operand.then;\n\t\telseExpr = operand.else;\n\t} else {\n\t\treturn null;\n\t}\n\t\n\tconst condition = evaluateExpression(ifExpr, doc);\n\treturn condition ? evaluateExpression(thenExpr, doc) : evaluateExpression(elseExpr, doc);\n}\n\nfunction evalIfNull(operands, doc) {\n\tif (!Array.isArray(operands) || operands.length < 2) return null;\n\t\n\tfor (let i = 0; i < operands.length; i++) {\n\t\tconst val = evaluateExpression(operands[i], doc);\n\t\tif (val !== null && val !== undefined) {\n\t\t\treturn val;\n\t\t}\n\t}\n\treturn null;\n}\n\nfunction evalSwitch(operand, doc) {\n\tif (typeof operand !== 'object' || !Array.isArray(operand.branches)) {\n\t\treturn null;\n\t}\n\t\n\tfor (const branch of operand.branches) {\n\t\tconst caseResult = evaluateExpression(branch.case, doc);\n\t\tif (caseResult) {\n\t\t\treturn evaluateExpression(branch.then, doc);\n\t\t}\n\t}\n\t\n\treturn operand.default !== undefined ? evaluateExpression(operand.default, doc) : null;\n}\n\n// ============================================================================\n// DATE OPERATORS\n// ============================================================================\n\nfunction evalYear(operand, doc) {\n\tconst date = evaluateExpression(operand, doc);\n\tif (date instanceof Date) {\n\t\treturn date.getUTCFullYear();\n\t}\n\treturn null;\n}\n\nfunction evalMonth(operand, doc) {\n\tconst date = evaluateExpression(operand, doc);\n\tif (date instanceof Date) {\n\t\treturn date.getUTCMonth() + 1; // MongoDB returns 1-12\n\t}\n\treturn null;\n}\n\nfunction evalDayOfMonth(operand, doc) {\n\tconst date = evaluateExpression(operand, doc);\n\tif (date instanceof Date) {\n\t\treturn date.getUTCDate();\n\t}\n\treturn null;\n}\n\nfunction evalDayOfWeek(operand, doc) {\n\tconst date = evaluateExpression(operand, doc);\n\tif (date instanceof Date) {\n\t\treturn date.getUTCDay() + 1; // MongoDB returns 1-7 (Sunday is 1)\n\t}\n\treturn null;\n}\n\nfunction evalDayOfYear(operand, doc) {\n\tconst date = evaluateExpression(operand, doc);\n\tif (date instanceof Date) {\n\t\tconst start = new Date(Date.UTC(date.getUTCFullYear(), 0, 0));\n\t\tconst diff = date - start;\n\t\tconst oneDay = 1000 * 60 * 60 * 24;\n\t\treturn Math.floor(diff / oneDay);\n\t}\n\treturn null;\n}\n\nfunction evalHour(operand, doc) {\n\tconst date = evaluateExpression(operand, doc);\n\tif (date instanceof Date) {\n\t\treturn date.getUTCHours();\n\t}\n\treturn null;\n}\n\nfunction evalMinute(operand, doc) {\n\tconst date = evaluateExpression(operand, doc);\n\tif (date instanceof Date) {\n\t\treturn date.getUTCMinutes();\n\t}\n\treturn null;\n}\n\nfunction evalSecond(operand, doc) {\n\tconst date = evaluateExpression(operand, doc);\n\tif (date instanceof Date) {\n\t\treturn date.getUTCSeconds();\n\t}\n\treturn null;\n}\n\nfunction evalMillisecond(operand, doc) {\n\tconst date = evaluateExpression(operand, doc);\n\tif (date instanceof Date) {\n\t\treturn date.getUTCMilliseconds();\n\t}\n\treturn null;\n}\n\nfunction evalWeek(operand, doc) {\n\tconst date = evaluateExpression(operand, doc);\n\tif (date instanceof Date) {\n\t\tconst onejan = new Date(Date.UTC(date.getUTCFullYear(), 0, 1));\n\t\tconst week = Math.ceil((((date - onejan) / 86400000) + onejan.getUTCDay() + 1) / 7);\n\t\treturn week - 1; // MongoDB weeks are 0-indexed\n\t}\n\treturn null;\n}\n\nfunction evalIsoWeek(operand, doc) {\n\tconst date = evaluateExpression(operand, doc);\n\tif (date instanceof Date) {\n\t\tconst target = new Date(date.valueOf());\n\t\tconst dayNr = (date.getUTCDay() + 6) % 7;\n\t\ttarget.setUTCDate(target.getUTCDate() - dayNr + 3);\n\t\tconst firstThursday = target.valueOf();\n\t\ttarget.setUTCMonth(0, 1);\n\t\tif (target.getUTCDay() !== 4) {\n\t\t\ttarget.setUTCMonth(0, 1 + ((4 - target.getUTCDay()) + 7) % 7);\n\t\t}\n\t\treturn 1 + Math.ceil((firstThursday - target) / 604800000);\n\t}\n\treturn null;\n}\n\nfunction evalIsoWeekYear(operand, doc) {\n\tconst date = evaluateExpression(operand, doc);\n\tif (date instanceof Date) {\n\t\tconst target = new Date(date.valueOf());\n\t\ttarget.setUTCDate(target.getUTCDate() - ((date.getUTCDay() + 6) % 7) + 3);\n\t\treturn target.getUTCFullYear();\n\t}\n\treturn null;\n}\n\nfunction evalDateToString(operand, doc) {\n\tconst format = operand.format ? evaluateExpression(operand.format, doc) : '%Y-%m-%dT%H:%M:%S.%LZ';\n\tconst date = evaluateExpression(operand.date, doc);\n\t\n\tif (!(date instanceof Date)) return null;\n\t\n\t// Simple format string implementation using UTC methods\n\treturn format\n\t\t.replace('%Y', date.getUTCFullYear())\n\t\t.replace('%m', String(date.getUTCMonth() + 1).padStart(2, '0'))\n\t\t.replace('%d', String(date.getUTCDate()).padStart(2, '0'))\n\t\t.replace('%H', String(date.getUTCHours()).padStart(2, '0'))\n\t\t.replace('%M', String(date.getUTCMinutes()).padStart(2, '0'))\n\t\t.replace('%S', String(date.getUTCSeconds()).padStart(2, '0'))\n\t\t.replace('%L', String(date.getUTCMilliseconds()).padStart(3, '0'));\n}\n\nfunction evalToDate(operand, doc) {\n\tconst val = evaluateExpression(operand, doc);\n\tif (val instanceof Date) return val;\n\tif (typeof val === 'string' || typeof val === 'number') {\n\t\tconst date = new Date(val);\n\t\treturn isNaN(date.getTime()) ? null : date;\n\t}\n\treturn null;\n}\n\n// ============================================================================\n// ARRAY OPERATORS\n// ============================================================================\n\nfunction evalArrayElemAt(operands, doc) {\n\tif (!Array.isArray(operands) || operands.length !== 2) return null;\n\tconst arr = evaluateExpression(operands[0], doc);\n\tconst idx = evaluateExpression(operands[1], doc);\n\t\n\tif (!Array.isArray(arr) || typeof idx !== 'number') return null;\n\t\n\tconst index = idx < 0 ? arr.length + idx : idx;\n\treturn arr[index];\n}\n\nfunction evalConcatArrays(operands, doc) {\n\tif (!Array.isArray(operands)) return null;\n\tconst result = [];\n\tfor (const operand of operands) {\n\t\tconst arr = evaluateExpression(operand, doc);\n\t\tif (Array.isArray(arr)) {\n\t\t\tresult.push(...arr);\n\t\t}\n\t}\n\treturn result;\n}\n\nfunction evalFilter(operand, doc) {\n\tconst input = evaluateExpression(operand.input, doc);\n\tconst asVar = operand.as || 'this';\n\tconst cond = operand.cond;\n\t\n\tif (!Array.isArray(input)) return null;\n\t\n\treturn input.filter(item => {\n\t\tconst itemDoc = { ...doc, [asVar]: item };\n\t\treturn evaluateExpression(cond, itemDoc);\n\t});\n}\n\nfunction evalIn(operands, doc) {\n\tif (!Array.isArray(operands) || operands.length !== 2) return null;\n\tconst value = evaluateExpression(operands[0], doc);\n\tconst arr = evaluateExpression(operands[1], doc);\n\t\n\tif (!Array.isArray(arr)) return false;\n\treturn arr.includes(value);\n}\n\nfunction evalIndexOfArray(operands, doc) {\n\tif (!Array.isArray(operands) || operands.length < 2) return null;\n\tconst arr = evaluateExpression(operands[0], doc);\n\tconst search = evaluateExpression(operands[1], doc);\n\tconst start = operands[2] !== undefined ? evaluateExpression(operands[2], doc) : 0;\n\tconst end = operands[3] !== undefined ? evaluateExpression(operands[3], doc) : arr.length;\n\t\n\tif (!Array.isArray(arr)) return null;\n\t\n\tfor (let i = start; i < end && i < arr.length; i++) {\n\t\tif (arr[i] === search) return i;\n\t}\n\treturn -1;\n}\n\nfunction evalIsArray(operand, doc) {\n\tconst val = evaluateExpression(operand, doc);\n\treturn Array.isArray(val);\n}\n\nfunction evalMap(operand, doc) {\n\tconst input = evaluateExpression(operand.input, doc);\n\tconst asVar = operand.as || 'this';\n\tconst inExpr = operand.in;\n\t\n\tif (!Array.isArray(input)) return null;\n\t\n\treturn input.map(item => {\n\t\tconst itemDoc = { ...doc, [asVar]: item };\n\t\treturn evaluateExpression(inExpr, itemDoc);\n\t});\n}\n\nfunction evalReduce(operand, doc) {\n\tconst input = evaluateExpression(operand.input, doc);\n\tconst initialValue = evaluateExpression(operand.initialValue, doc);\n\tconst inExpr = operand.in;\n\t\n\tif (!Array.isArray(input)) return null;\n\t\n\tlet value = initialValue;\n\tfor (const item of input) {\n\t\tconst itemDoc = { ...doc, value, this: item };\n\t\tvalue = evaluateExpression(inExpr, itemDoc);\n\t}\n\treturn value;\n}\n\nfunction evalSize(operand, doc) {\n\tconst arr = evaluateExpression(operand, doc);\n\treturn Array.isArray(arr) ? arr.length : null;\n}\n\nfunction evalSlice(operands, doc) {\n\tif (!Array.isArray(operands) || operands.length < 2) return null;\n\tconst arr = evaluateExpression(operands[0], doc);\n\t\n\tif (!Array.isArray(arr)) return null;\n\t\n\tif (operands.length === 2) {\n\t\tconst n = evaluateExpression(operands[1], doc);\n\t\treturn n >= 0 ? arr.slice(0, n) : arr.slice(n);\n\t} else {\n\t\tconst position = evaluateExpression(operands[1], doc);\n\t\tconst n = evaluateExpression(operands[2], doc);\n\t\treturn arr.slice(position, position + n);\n\t}\n}\n\nfunction evalReverseArray(operand, doc) {\n\tconst arr = evaluateExpression(operand, doc);\n\treturn Array.isArray(arr) ? arr.slice().reverse() : null;\n}\n\nfunction evalZip(operand, doc) {\n\tconst inputs = operand.inputs ? evaluateExpression(operand.inputs, doc) : null;\n\tconst useLongestLength = operand.useLongestLength || false;\n\tconst defaults = operand.defaults;\n\t\n\tif (!Array.isArray(inputs)) return null;\n\t\n\tconst arrays = inputs.map(input => evaluateExpression(input, doc));\n\tif (!arrays.every(arr => Array.isArray(arr))) return null;\n\t\n\tconst maxLength = Math.max(...arrays.map(arr => arr.length));\n\tconst length = useLongestLength ? maxLength : Math.min(...arrays.map(arr => arr.length));\n\t\n\tconst result = [];\n\tfor (let i = 0; i < length; i++) {\n\t\tconst tuple = [];\n\t\tfor (let j = 0; j < arrays.length; j++) {\n\t\t\tif (i < arrays[j].length) {\n\t\t\t\ttuple.push(arrays[j][i]);\n\t\t\t} else if (defaults && j < defaults.length) {\n\t\t\t\ttuple.push(defaults[j]);\n\t\t\t} else {\n\t\t\t\ttuple.push(null);\n\t\t\t}\n\t\t}\n\t\tresult.push(tuple);\n\t}\n\treturn result;\n}\n\n// ============================================================================\n// TYPE OPERATORS\n// ============================================================================\n\nfunction evalType(operand, doc) {\n\tconst val = evaluateExpression(operand, doc);\n\t\n\tif (val === null) return 'null';\n\tif (val === undefined) return 'missing';\n\tif (typeof val === 'boolean') return 'bool';\n\tif (typeof val === 'number') return Number.isInteger(val) ? 'int' : 'double';\n\tif (typeof val === 'string') return 'string';\n\tif (val instanceof Date) return 'date';\n\tif (Array.isArray(val)) return 'array';\n\tif (typeof val === 'object') return 'object';\n\t\n\treturn 'unknown';\n}\n\nfunction evalConvert(operand, doc) {\n\tconst input = evaluateExpression(operand.input, doc);\n\tconst to = operand.to;\n\tconst onError = operand.onError;\n\tconst onNull = operand.onNull;\n\t\n\tif (input === null) {\n\t\treturn onNull !== undefined ? evaluateExpression(onNull, doc) : null;\n\t}\n\t\n\ttry {\n\t\tswitch (to) {\n\t\t\tcase 'double':\n\t\t\tcase 'decimal':\n\t\t\t\treturn parseFloat(input);\n\t\t\tcase 'int':\n\t\t\tcase 'long':\n\t\t\t\treturn parseInt(input);\n\t\t\tcase 'bool':\n\t\t\t\treturn Boolean(input);\n\t\t\tcase 'string':\n\t\t\t\treturn String(input);\n\t\t\tcase 'date':\n\t\t\t\treturn new Date(input);\n\t\t\tdefault:\n\t\t\t\treturn input;\n\t\t}\n\t} catch (e) {\n\t\treturn onError !== undefined ? evaluateExpression(onError, doc) : null;\n\t}\n}\n\nfunction evalToBool(operand, doc) {\n\tconst val = evaluateExpression(operand, doc);\n\treturn Boolean(val);\n}\n\nfunction evalToDecimal(operand, doc) {\n\tconst val = evaluateExpression(operand, doc);\n\treturn parseFloat(val);\n}\n\nfunction evalToDouble(operand, doc) {\n\tconst val = evaluateExpression(operand, doc);\n\treturn parseFloat(val);\n}\n\nfunction evalToInt(operand, doc) {\n\tconst val = evaluateExpression(operand, doc);\n\treturn parseInt(val);\n}\n\nfunction evalToLong(operand, doc) {\n\tconst val = evaluateExpression(operand, doc);\n\treturn parseInt(val);\n}\n\nfunction evalToString(operand, doc) {\n\tconst val = evaluateExpression(operand, doc);\n\tif (val === null || val === undefined) return null;\n\treturn String(val);\n}\n\n// ============================================================================\n// OBJECT OPERATORS\n// ============================================================================\n\nfunction evalObjectToArray(operand, doc) {\n\tconst obj = evaluateExpression(operand, doc);\n\tif (typeof obj !== 'object' || obj === null || Array.isArray(obj)) {\n\t\treturn null;\n\t}\n\t\n\treturn Object.keys(obj).map(key => ({ k: key, v: obj[key] }));\n}\n\nfunction evalArrayToObject(operand, doc) {\n\tconst arr = evaluateExpression(operand, doc);\n\tif (!Array.isArray(arr)) return null;\n\t\n\tconst result = {};\n\tfor (const item of arr) {\n\t\tif (Array.isArray(item) && item.length === 2) {\n\t\t\tresult[item[0]] = item[1];\n\t\t} else if (typeof item === 'object' && item.k !== undefined && item.v !== undefined) {\n\t\t\tresult[item.k] = item.v;\n\t\t}\n\t}\n\treturn result;\n}\n\nfunction evalMergeObjects(operands, doc) {\n\tif (!Array.isArray(operands)) {\n\t\t// Single object\n\t\treturn evaluateExpression(operands, doc);\n\t}\n\t\n\tconst result = {};\n\tfor (const operand of operands) {\n\t\tconst obj = evaluateExpression(operand, doc);\n\t\tif (typeof obj === 'object' && obj !== null && !Array.isArray(obj)) {\n\t\t\tObject.assign(result, obj);\n\t\t}\n\t}\n\treturn result;\n}\n","import { getProp, getFieldValues, isArray, arrayMatches, objectMatches, toArray, isIn, bboxToGeojson } from '../utils.js';\nimport { stemmer, tokenize } from '@belteshazzar/binjson/textindex';\nimport { ObjectId } from '@belteshazzar/binjson';\nimport { evaluateExpression } from './aggregationExpressions.js';\n\n/**\n * BSON type mappings for $type operator\n */\nconst BSON_TYPES = {\n\t1: 'double',\n\t2: 'string',\n\t3: 'object',\n\t4: 'array',\n\t5: 'binData',\n\t6: 'undefined',\n\t7: 'objectId',\n\t8: 'bool',\n\t9: 'date',\n\t10: 'null',\n\t11: 'regex',\n\t13: 'javascript',\n\t15: 'javascriptWithScope',\n\t16: 'int',\n\t17: 'timestamp',\n\t18: 'long',\n\t19: 'decimal',\n\t127: 'maxKey',\n\t'-1': 'minKey'\n};\n\n// Reverse mapping from alias to code\nconst TYPE_ALIASES = Object.entries(BSON_TYPES).reduce((acc, [code, name]) => {\n\tacc[name] = parseInt(code);\n\treturn acc;\n}, {});\n\n/**\n * Check if a value matches a BSON type or type code\n */\nfunction matchesType(value, typeSpec) {\n\t// Handle array of types\n\tif (isArray(typeSpec)) {\n\t\tfor (let i = 0; i < typeSpec.length; i++) {\n\t\t\tif (matchesType(value, typeSpec[i])) return true;\n\t\t}\n\t\treturn false;\n\t}\n\t\n\t// Get type code from spec (can be number or string alias)\n\tconst typeCode = typeof typeSpec === 'number' ? typeSpec : TYPE_ALIASES[typeSpec];\n\tconst typeName = BSON_TYPES[typeCode] || typeSpec;\n\t\n\t// Check value type\n\tif (value === null) return typeName === 'null' || typeCode === 10;\n\tif (value === undefined) return typeName === 'undefined' || typeCode === 6;\n\tif (typeof value === 'number') {\n\t\tif (Number.isInteger(value)) return typeName === 'int' || typeCode === 16;\n\t\treturn typeName === 'double' || typeCode === 1;\n\t}\n\tif (typeof value === 'string') return typeName === 'string' || typeCode === 2;\n\tif (typeof value === 'boolean') return typeName === 'bool' || typeCode === 8;\n\tif (value instanceof Date) return typeName === 'date' || typeCode === 9;\n\tif (value instanceof ObjectId) return typeName === 'objectId' || typeCode === 7;\n\tif (value instanceof RegExp) return typeName === 'regex' || typeCode === 11;\n\tif (isArray(value)) return typeName === 'array' || typeCode === 4;\n\tif (typeof value === 'object') return typeName === 'object' || typeCode === 3;\n\t\n\t// Fallback to simple type check\n\treturn typeof value === typeSpec;\n}\n\n/**\n * Bit query operator helpers\n */\nfunction toBitMask(positions) {\n\tif (isArray(positions)) {\n\t\t// Array of bit positions\n\t\tlet mask = 0;\n\t\tfor (let i = 0; i < positions.length; i++) {\n\t\t\tmask |= (1 << positions[i]);\n\t\t}\n\t\treturn mask;\n\t} else if (typeof positions === 'number') {\n\t\t// Bitmask directly\n\t\treturn positions;\n\t}\n\treturn 0;\n}\n\nfunction matchesBitsAllSet(value, positions) {\n\tif (typeof value !== 'number') return false;\n\tconst mask = toBitMask(positions);\n\treturn (value & mask) === mask;\n}\n\nfunction matchesBitsAllClear(value, positions) {\n\tif (typeof value !== 'number') return false;\n\tconst mask = toBitMask(positions);\n\treturn (value & mask) === 0;\n}\n\nfunction matchesBitsAnySet(value, positions) {\n\tif (typeof value !== 'number') return false;\n\tconst mask = toBitMask(positions);\n\treturn (value & mask) !== 0;\n}\n\nfunction matchesBitsAnyClear(value, positions) {\n\tif (typeof value !== 'number') return false;\n\tconst mask = toBitMask(positions);\n\treturn (value & mask) !== mask;\n}\n\n/**\n * JSON Schema validator (simplified)\n */\nfunction validateJsonSchema(doc, schema) {\n\t// Basic JSON Schema validation\n\tif (schema.type) {\n\t\tconst docType = isArray(doc) ? 'array' : (doc === null ? 'null' : typeof doc);\n\t\tif (schema.type !== docType) return false;\n\t}\n\t\n\tif (schema.required && isArray(schema.required)) {\n\t\tfor (let i = 0; i < schema.required.length; i++) {\n\t\t\tif (!(schema.required[i] in doc)) return false;\n\t\t}\n\t}\n\t\n\tif (schema.properties) {\n\t\tfor (const key in schema.properties) {\n\t\t\t// When using $jsonSchema as a query operator, properties must exist to match\n\t\t\t// (This is different from standard JSON Schema validation where properties are optional)\n\t\t\tif (!(key in doc)) return false;\n\t\t\t\n\t\t\tconst propSchema = schema.properties[key];\n\t\t\tif (!validateJsonSchema(doc[key], propSchema)) return false;\n\t\t}\n\t}\n\t\n\tif (schema.minimum !== undefined && typeof doc === 'number') {\n\t\tif (doc < schema.minimum) return false;\n\t}\n\t\n\tif (schema.maximum !== undefined && typeof doc === 'number') {\n\t\tif (doc > schema.maximum) return false;\n\t}\n\t\n\tif (schema.minLength !== undefined && typeof doc === 'string') {\n\t\tif (doc.length < schema.minLength) return false;\n\t}\n\t\n\tif (schema.maxLength !== undefined && typeof doc === 'string') {\n\t\tif (doc.length > schema.maxLength) return false;\n\t}\n\t\n\tif (schema.pattern && typeof doc === 'string') {\n\t\tconst regex = new RegExp(schema.pattern);\n\t\tif (!regex.test(doc)) return false;\n\t}\n\t\n\tif (schema.enum && isArray(schema.enum)) {\n\t\tif (!schema.enum.includes(doc)) return false;\n\t}\n\t\n\treturn true;\n}\n\n/**\n * Compare two values for equality, handling ObjectId instances\n */\nfunction valuesEqual(a, b) {\n\t// Handle ObjectId comparison\n\tif (a instanceof ObjectId && b instanceof ObjectId) {\n return a.equals(b);\n\t}\n\t\n\t// Regular equality\n\treturn a == b;\n}\n\n/**\n * Compare two values with a comparison operator, handling ObjectId instances\n */\nfunction compareValues(a, b, operator) {\n\t// Convert ObjectIds to comparable values (use timestamp for ordering)\n\tlet aVal = a;\n\tlet bVal = b;\n\t\n\tif (a instanceof ObjectId) {\n\t\taVal = a.toString();\n\t}\n\tif (b instanceof ObjectId) {\n\t\tbVal = b.toString();\n\t}\n\t\n\tswitch(operator) {\n\t\tcase '>': return aVal > bVal;\n\t\tcase '>=': return aVal >= bVal;\n\t\tcase '<': return aVal < bVal;\n\t\tcase '<=': return aVal <= bVal;\n\t\tdefault: return false;\n\t}\n}\n\n/**\n * Check if a field value (possibly from array traversal) matches a condition\n * Handles both single values and arrays of values (from array traversal)\n */\nfunction fieldValueMatches(fieldValue, checkFn) {\n\t// Use strict equality to allow null values through\n\tif (fieldValue === undefined) return false;\n\t\n\t// Check for null before isArray to avoid crash\n\tif (fieldValue === null) return checkFn(fieldValue);\n\t\n\t// If fieldValue is an array (from array traversal), check if ANY element matches\n\tif (isArray(fieldValue)) {\n\t\tfor (var i = 0; i < fieldValue.length; i++) {\n\t\t\tif (checkFn(fieldValue[i])) return true;\n\t\t}\n\t\treturn false;\n\t}\n\t\n\t// Otherwise check the single value\n\treturn checkFn(fieldValue);\n}\n\n/**\n * Tokenize text for search\n */\nfunction tokenizeText(text) {\n\tif (typeof text !== 'string') return [];\n\n const words = tokenize(text);\n\treturn words.map(w => stemmer(w));\n}\n\n/**\n * Text search helper\n * Matches if the property contains tokens from the query\n */\nexport function text(prop, queryText) {\n\tif (typeof prop !== 'string') return false;\n\t\n\tconst propTokens = new Set(tokenizeText(prop));\n\tconst queryTokens = tokenizeText(queryText);\n\t\n\t// Match if any query term is in the document\n\treturn queryTokens.some(term => propTokens.has(term));\n}\n\n/**\n * Text search across all string fields in a document\n * Used for top-level $text operator\n */\nfunction textSearchDocument(doc, searchText) {\n\tif (!doc || typeof doc !== 'object') return false;\n\t\n\t// Recursively search all string fields\n\tfunction searchObject(obj) {\n\t\tif (typeof obj === 'string') {\n\t\t\treturn text(obj, searchText);\n\t\t}\n\t\t\n\t\tif (typeof obj !== 'object' || obj === null) {\n\t\t\treturn false;\n\t\t}\n\t\t\n\t\t// Check arrays\n\t\tif (isArray(obj)) {\n\t\t\tfor (let i = 0; i < obj.length; i++) {\n\t\t\t\tif (searchObject(obj[i])) return true;\n\t\t\t}\n\t\t\treturn false;\n\t\t}\n\t\t\n\t\t// Check object properties\n\t\tfor (const key in obj) {\n\t\t\tif (obj.hasOwnProperty(key)) {\n\t\t\t\tif (searchObject(obj[key])) return true;\n\t\t\t}\n\t\t}\n\t\t\n\t\treturn false;\n\t}\n\t\n\treturn searchObject(doc);\n}\n\n/**\n * Geo within helper - using bounding box logic instead of de9im\n * This is a simpler implementation that doesn't require de9im dependency\n */\nexport function geoWithin(prop, query) {\n\ttry {\n\t\t// bbox format: [[minLon, maxLat], [maxLon, minLat]]\n\t\tif (!Array.isArray(query) || query.length !== 2) {\n\t\t\treturn false;\n\t\t}\n\n\t\tconst minLon = query[0][0];\n\t\tconst maxLat = query[0][1];\n\t\tconst maxLon = query[1][0];\n\t\tconst minLat = query[1][1];\n\n\t\t// Check if geometry is within bounding box\n\t\treturn isGeometryWithinBBox(prop, minLon, maxLon, minLat, maxLat);\n\t} catch (e) {\n\t\treturn false;\n\t}\n}\n\n/**\n * Check if a GeoJSON geometry is within a bounding box\n * For Points: checks if the point is within the bbox\n * For Polygons: checks if ALL vertices are within the bbox\n */\nfunction isGeometryWithinBBox(geoJson, minLon, maxLon, minLat, maxLat) {\n\tif (!geoJson) return false;\n\n\t// Handle GeoJSON FeatureCollection\n\tif (geoJson.type === 'FeatureCollection' && geoJson.features && geoJson.features.length > 0) {\n\t\t// All features must be within the bbox\n\t\tfor (const feature of geoJson.features) {\n\t\t\tif (feature.geometry) {\n\t\t\t\tif (!isGeometryWithinBBox(feature.geometry, minLon, maxLon, minLat, maxLat)) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn true;\n\t}\n\n\t// Handle GeoJSON Feature\n\tif (geoJson.type === 'Feature' && geoJson.geometry) {\n\t\treturn isGeometryWithinBBox(geoJson.geometry, minLon, maxLon, minLat, maxLat);\n\t}\n\n\t// Handle GeoJSON Point\n\tif (geoJson.type === 'Point' && geoJson.coordinates) {\n\t\tconst [lng, lat] = geoJson.coordinates;\n\t\tif (typeof lng === 'number' && typeof lat === 'number') {\n\t\t\treturn lng >= minLon && lng <= maxLon && lat >= minLat && lat <= maxLat;\n\t\t}\n\t}\n\n\t// Handle GeoJSON Polygon - ALL vertices must be within the bbox\n\tif (geoJson.type === 'Polygon' && geoJson.coordinates && geoJson.coordinates.length > 0) {\n\t\tfor (const ring of geoJson.coordinates) {\n\t\t\tfor (const coord of ring) {\n\t\t\t\tconst lng = coord[0];\n\t\t\t\tconst lat = coord[1];\n\t\t\t\tif (lng < minLon || lng > maxLon || lat < minLat || lat > maxLat) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn true;\n\t}\n\n\treturn false;\n}\n\n/**\n * Extract coordinates from a GeoJSON object for indexing purposes\n * This uses centroid for polygons to get a single point to index\n * @param {Object} geoJson - The GeoJSON object\n * @returns {Object|null} Object with lat and lng, or null if invalid\n */\nfunction extractCoordinatesFromGeoJSON(geoJson) {\n\tif (!geoJson) return null;\n\n\t// Handle GeoJSON FeatureCollection\n\tif (geoJson.type === 'FeatureCollection' && geoJson.features && geoJson.features.length > 0) {\n\t\tconst feature = geoJson.features[0];\n\t\tif (feature.geometry) {\n\t\t\treturn extractCoordinatesFromGeoJSON(feature.geometry);\n\t\t}\n\t}\n\n\t// Handle GeoJSON Feature\n\tif (geoJson.type === 'Feature' && geoJson.geometry) {\n\t\treturn extractCoordinatesFromGeoJSON(geoJson.geometry);\n\t}\n\n\t// Handle GeoJSON Point\n\tif (geoJson.type === 'Point' && geoJson.coordinates) {\n\t\tconst [lng, lat] = geoJson.coordinates;\n\t\tif (typeof lng === 'number' && typeof lat === 'number') {\n\t\t\treturn { lat, lng };\n\t\t}\n\t}\n\n\t// Handle GeoJSON Polygon - use centroid of first coordinate ring\n\tif (geoJson.type === 'Polygon' && geoJson.coordinates && geoJson.coordinates.length > 0) {\n\t\tconst ring = geoJson.coordinates[0];\n\t\tif (ring.length > 0) {\n\t\t\tlet sumLat = 0, sumLng = 0;\n\t\t\tfor (const coord of ring) {\n\t\t\t\tsumLng += coord[0];\n\t\t\t\tsumLat += coord[1];\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tlat: sumLat / ring.length,\n\t\t\t\tlng: sumLng / ring.length\n\t\t\t};\n\t\t}\n\t}\n\n\treturn null;\n}\n\n/**\n * Calculate haversine distance between two points in kilometers\n */\nfunction haversineDistance(lat1, lng1, lat2, lng2) {\n\tconst R = 6371; // Earth's radius in kilometers\n\tconst dLat = (lat2 - lat1) * Math.PI / 180;\n\tconst dLng = (lng2 - lng1) * Math.PI / 180;\n\tconst a = \n\t\tMath.sin(dLat / 2) * Math.sin(dLat / 2) +\n\t\tMath.cos(lat1 * Math.PI / 180) * Math.cos(lat2 * Math.PI / 180) *\n\t\tMath.sin(dLng / 2) * Math.sin(dLng / 2);\n\tconst c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));\n\treturn R * c;\n}\n\n/**\n * Check if a point is within a certain distance (in meters) of a reference point\n */\nfunction isNear(geoJson, refLng, refLat, maxDistanceMeters) {\n\tconst coords = extractCoordinatesFromGeoJSON(geoJson);\n\tif (!coords) return false;\n\tconst distanceKm = haversineDistance(coords.lat, coords.lng, refLat, refLng);\n\tconst distanceM = distanceKm * 1000;\n\treturn distanceM <= maxDistanceMeters;\n}\n\n/**\n * Check if geometries intersect (simple implementation)\n */\nfunction geoIntersects(geoJson, queryGeo) {\n\tif (!geoJson || !queryGeo) return false;\n\t\n\t// Get coordinates from query geometry\n\tconst queryCoords = extractCoordinatesFromGeoJSON(queryGeo);\n\tif (!queryCoords) return false;\n\t\n\t// Get coordinates from document geometry\n\tconst docCoords = extractCoordinatesFromGeoJSON(geoJson);\n\tif (!docCoords) return false;\n\t\n\t// For now, simple point-in-polygon check for polygons\n\t// If query is a polygon, check if document point is inside\n\tif (queryGeo.type === 'Polygon' && geoJson.type === 'Point') {\n\t\treturn pointInPolygon(docCoords.lng, docCoords.lat, queryGeo.coordinates[0]);\n\t}\n\t\n\t// If document is a polygon and query is a point, check if point is inside\n\tif (geoJson.type === 'Polygon' && queryGeo.type === 'Point') {\n\t\tconst queryPt = queryGeo.coordinates;\n\t\treturn pointInPolygon(queryPt[0], queryPt[1], geoJson.coordinates[0]);\n\t}\n\t\n\t// For points, check if they're the same or very close\n\tif (geoJson.type === 'Point' && queryGeo.type === 'Point') {\n\t\tconst dist = haversineDistance(docCoords.lat, docCoords.lng, queryCoords.lat, queryCoords.lng);\n\t\treturn dist < 0.001; // Within about 1 meter\n\t}\n\t\n\treturn false;\n}\n\n/**\n * Point-in-polygon test using ray casting algorithm\n */\nfunction pointInPolygon(lng, lat, ring) {\n\tlet inside = false;\n\tfor (let i = 0, j = ring.length - 1; i < ring.length; j = i++) {\n\t\tconst xi = ring[i][0], yi = ring[i][1];\n\t\tconst xj = ring[j][0], yj = ring[j][1];\n\t\tconst intersect = ((yi > lat) !== (yj > lat)) && (lng < (xj - xi) * (lat - yi) / (yj - yi) + xi);\n\t\tif (intersect) inside = !inside;\n\t}\n\treturn inside;\n}\n\n/**\n * $where operator implementation\n * SECURITY NOTE: This uses Function constructor which can execute arbitrary code.\n * This is acceptable for a local/in-memory database but should NOT be used\n * in environments where untrusted user input is processed.\n */\nexport function where(doc, value) {\n\tif (typeof value === 'function') {\n\t\ttry {\n\t\t\treturn value.call(doc);\n\t\t} catch (e) {\n\t\t\treturn false;\n\t\t}\n\t} else if (typeof value === 'string') {\n\t\t// Evaluate the string as a function\n\t\ttry {\n\t\t\tvar fn = new Function('return ' + value);\n\t\t\treturn fn.call(doc);\n\t\t} catch (e) {\n\t\t\treturn false;\n\t\t}\n\t}\n\treturn false;\n}\n\n/**\n * Top-level match function\n */\nexport function tlMatches(doc, query) {\n\tvar key = Object.keys(query)[0];\n\tvar value = query[key];\n\tif (key.charAt(0) == \"$\") {\n\t\tif (key == \"$and\") return and(doc, value);\n\t\telse if (key == \"$or\") return or(doc, value);\n\t\telse if (key == \"$not\") return not(doc, value);\n\t\telse if (key == \"$nor\") return nor(doc, value);\n\t\telse if (key == \"$where\") return where(doc, value);\n\t\telse if (key == \"$comment\") return true; // $comment is metadata, doesn't filter\n\t\telse if (key == \"$jsonSchema\") return validateJsonSchema(doc, value); // Top-level schema validation\n\t\telse if (key == \"$text\") {\n\t\t\t// Handle $text as top-level operator\n\t\t\t// Searches across all string fields in the document\n\t\t\tconst searchText = value.$search || value;\n\t\t\treturn textSearchDocument(doc, searchText);\n\t\t}\n\t\telse if (key == \"$expr\") {\n\t\t\t// Handle $expr at top level\n\t\t\ttry {\n\t\t\t\treturn evaluateExpression(value, doc);\n\t\t\t} catch (e) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t\telse throw { $err: \"Can't canonicalize query: BadValue unknown top level operator: \" + key, code: 17287 };\n\t} else {\n\t\treturn opMatches(doc, key, value);\n\t}\n}\n\n/**\n * Operator match function\n */\nexport function opMatches(doc, key, value) {\n\t// Get field value using array-aware traversal\n\tvar fieldValue = getFieldValues(doc, key);\n\t\n\tif (typeof (value) == \"string\") return fieldValueMatches(fieldValue, function(v) { return valuesEqual(v, value); });\n\telse if (typeof (value) == \"number\") return fieldValueMatches(fieldValue, function(v) { return valuesEqual(v, value); });\n\telse if (typeof (value) == \"boolean\") return fieldValueMatches(fieldValue, function(v) { return valuesEqual(v, value); });\n\telse if (value instanceof ObjectId) return fieldValueMatches(fieldValue, function(v) { return valuesEqual(v, value); });\n\telse if (typeof (value) == \"object\") {\n\t\tif (value instanceof RegExp) return fieldValue != undefined && fieldValueMatches(fieldValue, function(v) { return v && v.match(value); });\n\t\telse if (isArray(value)) return fieldValue != undefined && fieldValueMatches(fieldValue, function(v) { return v && arrayMatches(v, value); });\n\t\telse {\n\t\t\tvar keys = Object.keys(value);\n\t\t\tif (keys[0].charAt(0) == \"$\") {\n\t\t\t\tfor (var i = 0; i < keys.length; i++) {\n\t\t\t\t\tvar operator = Object.keys(value)[i];\n\t\t\t\t\tvar operand = value[operator];\n\t\t\t\t\tif (operator == \"$eq\") {\n\t\t\t\t\t\tif (!fieldValueMatches(fieldValue, function(v) { return valuesEqual(v, operand); })) return false;\n\t\t\t\t\t} else if (operator == \"$gt\") {\n\t\t\t\t\t\tif (!fieldValueMatches(fieldValue, function(v) { return compareValues(v, operand, '>'); })) return false;\n\t\t\t\t\t} else if (operator == \"$gte\") {\n\t\t\t\t\t\tif (!fieldValueMatches(fieldValue, function(v) { return compareValues(v, operand, '>='); })) return false;\n\t\t\t\t\t} else if (operator == \"$lt\") {\n\t\t\t\t\t\tif (!fieldValueMatches(fieldValue, function(v) { return compareValues(v, operand, '<'); })) return false;\n\t\t\t\t\t} else if (operator == \"$lte\") {\n\t\t\t\t\t\tif (!fieldValueMatches(fieldValue, function(v) { return compareValues(v, operand, '<='); })) return false;\n\t\t\t\t\t} else if (operator == \"$ne\") {\n\t\t\t\t\t\tif (!fieldValueMatches(fieldValue, function(v) { return !valuesEqual(v, operand); })) return false;\n\t\t\t\t\t} else if (operator == \"$in\") {\n\t\t\t\t\t\tif (!fieldValueMatches(fieldValue, function(v) { return isIn(v, operand); })) return false;\n\t\t\t\t\t} else if (operator == \"$nin\") {\n\t\t\t\t\t\tif (fieldValueMatches(fieldValue, function(v) { return isIn(v, operand); })) return false;\n\t\t\t\t\t} else if (operator == \"$exists\") {\n\t\t\t\t\t\t// For $exists, we need to use getProp which returns undefined if field doesn't exist\n\t\t\t\t\t\t// getFieldValues might return an array which would be truthy\n\t\t\t\t\tvar rawValue = getProp(doc, key);\n\t\t\t\t\tif (operand ? rawValue == undefined : rawValue != undefined) return false;\n\t\t\t\t} else if (operator == \"$type\") {\n\t\t\t\t\t// Support both BSON type codes and aliases\n\t\t\t\t\t// Note: $type checks the field value itself, not array elements\n\t\t\t\t\t// If field doesn't exist (undefined), it can only match type 'undefined' (6)\n\t\t\t\t\tif (fieldValue === undefined) {\n\t\t\t\t\t\tconst expectedTypeCode = typeof operand === 'number' ? operand : TYPE_ALIASES[operand];\n\t\t\t\t\t\tif (expectedTypeCode !== 6) return false;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (!matchesType(fieldValue, operand)) return false;\n\t\t\t\t\t}\n\t\t\t\t} else if (operator == \"$mod\") {\n\t\t\t\t\tif (operand.length != 2) throw { $err: \"Can't canonicalize query: BadValue malformed mod, not enough elements\", code: 17287 };\n\t\t\t\t\tif (!fieldValueMatches(fieldValue, function(v) { return v != undefined && (v % operand[0] == operand[1]); })) return false;\n\t\t\t\t} else if (operator == \"$regex\") {\n\t\t\t\t\t// Support string pattern with optional $options\n\t\t\t\t\tvar pattern = operand;\n\t\t\t\t\tvar flags = value.$options || '';\n\t\t\t\t\tvar regex = (typeof pattern === 'string') ? new RegExp(pattern, flags) : pattern;\n\t\t\t\t\tif (!fieldValueMatches(fieldValue, function(v) { return v != undefined && regex.test(v); })) return false;\n\t\t\t\t} else if (operator == \"$options\") {\n\t\t\t\t\t// $options is handled with $regex, skip here\n\t\t\t\t\tcontinue;\n\t\t\t\t} else if (operator == \"$text\") {\n\t\t\t\t\tif (!fieldValueMatches(fieldValue, function(v) { return v != undefined && text(v, operand); })) return false;\n\t\t\t\t} else if (operator == \"$expr\") {\n\t\t\t\t\t// Evaluate aggregation expression against the document\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst result = evaluateExpression(operand, doc);\n\t\t\t\t\t\tif (!result) return false;\n\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\t// If expression evaluation fails, don't match\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t} else if (operator == \"$geoWithin\") {\n\t\t\t\t\t\tif (!fieldValueMatches(fieldValue, function(v) { return v != undefined && geoWithin(v, operand); })) return false;\n\t\t\t\t\t} else if (operator == \"$near\" || operator == \"$nearSphere\") {\n\t\t\t\t\t\t// Handle $near and $nearSphere with distance calculation\n\t\t\t\t\t\tlet coordinates;\n\t\t\t\t\t\tif (operand.$geometry) {\n\t\t\t\t\t\t\tcoordinates = operand.$geometry.coordinates;\n\t\t\t\t\t\t} else if (operand.coordinates) {\n\t\t\t\t\t\t\tcoordinates = operand.coordinates;\n\t\t\t\t\t\t} else if (Array.isArray(operand)) {\n\t\t\t\t\t\t\tcoordinates = operand;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t\tif (coordinates && coordinates.length >= 2) {\n\t\t\t\t\t\t\tconst [lng, lat] = coordinates;\n\t\t\t\t\t\t\tconst maxDistanceMeters = operand.$maxDistance || 1000000; // Default to 1000km\n\t\t\t\t\t\t\tif (!fieldValueMatches(fieldValue, function(v) { return v != undefined && isNear(v, lng, lat, maxDistanceMeters); })) return false;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (operator == \"$geoIntersects\") {\n\t\t\t\t\t\t// Handle $geoIntersects\n\t\t\t\t\t\tconst geometry = operand.$geometry || operand;\n\t\t\t\t\t\tif (!fieldValueMatches(fieldValue, function(v) { return v != undefined && geoIntersects(v, geometry); })) return false;\n\t\t\t\t\t} else if (operator == \"$not\") {\n\t\t\t\t\t\tif (opMatches(doc, key, operand)) return false;\n\t\t\t\t\t} else if (operator == \"$all\") {\n\t\t\t\t\t\t// $all requires the field to be an array, use getProp not getFieldValues\n\t\t\t\t\t\tvar arrayFieldValue = getProp(doc, key);\n\t\t\t\t\t\tif (arrayFieldValue == undefined || !isArray(arrayFieldValue)) return false;\n\t\t\t\t\t\tfor (var j = 0; j < operand.length; j++) {\n\t\t\t\t\t\t\tif (!isIn(operand[j], arrayFieldValue)) return false;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (operator == \"$elemMatch\") {\n\t\t\t\t\t\t// $elemMatch requires the field to be an array, use getProp not getFieldValues\n\t\t\t\t\t\tvar arrayFieldValue = getProp(doc, key);\n\t\t\t\t\t\tif (arrayFieldValue == undefined || !isArray(arrayFieldValue)) return false;\n\t\t\t\t\t\tvar found = false;\n\t\t\t\t\t\tfor (var j = 0; j < arrayFieldValue.length; j++) {\n\t\t\t\t\t\t\tvar element = arrayFieldValue[j];\n\t\t\t\t\t\t\t// Check if element matches the query\n\t\t\t\t\t\t\tif (typeof element === 'object' && !isArray(element)) {\n\t\t\t\t\t\t\t\t// For objects, use matches\n\t\t\t\t\t\t\t\tif (matches(element, operand)) {\n\t\t\t\t\t\t\t\t\tfound = true;\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t// For primitive values, check operators directly\n\t\t\t\t\t\t\t\tvar matchesPrimitive = true;\n\t\t\t\t\t\t\t\tvar opKeys = Object.keys(operand);\n\t\t\t\t\t\t\t\tfor (var k = 0; k < opKeys.length; k++) {\n\t\t\t\t\t\t\t\t\tvar op = opKeys[k];\n\t\t\t\t\t\t\t\t\tvar opValue = operand[op];\n\t\t\t\t\t\t\t\t\tif (op == \"$gte\" && !(element >= opValue)) matchesPrimitive = false;\n\t\t\t\t\t\t\t\t\telse if (op == \"$gt\" && !(element > opValue)) matchesPrimitive = false;\n\t\t\t\t\t\t\t\t\telse if (op == \"$lte\" && !(element <= opValue)) matchesPrimitive = false;\n\t\t\t\t\t\t\t\t\telse if (op == \"$lt\" && !(element < opValue)) matchesPrimitive = false;\n\t\t\t\t\t\t\t\t\telse if (op == \"$eq\" && !(element == opValue)) matchesPrimitive = false;\n\t\t\t\t\t\t\t\t\telse if (op == \"$ne\" && !(element != opValue)) matchesPrimitive = false;\n\t\t\t\t\t\t\t\t\telse if (op == \"$in\" && !isIn(element, opValue)) matchesPrimitive = false;\n\t\t\t\t\t\t\t\t\telse if (op == \"$nin\" && isIn(element, opValue)) matchesPrimitive = false;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (matchesPrimitive) {\n\t\t\t\t\t\t\t\t\tfound = true;\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (!found) return false;\n\t\t\t\t} else if (operator == \"$size\") {\n\t\t\t\t\tvar sizeFieldValue = getProp(doc, key);\n\t\t\t\t\tif (sizeFieldValue == undefined || !isArray(sizeFieldValue)) return false;\n\t\t\t\t\tif (sizeFieldValue.length != operand) return false;\n\t\t\t\t} else if (operator == \"$bitsAllSet\") {\n\t\t\t\t\tif (!fieldValueMatches(fieldValue, function(v) { return matchesBitsAllSet(v, operand); })) return false;\n\t\t\t\t} else if (operator == \"$bitsAllClear\") {\n\t\t\t\t\tif (!fieldValueMatches(fieldValue, function(v) { return matchesBitsAllClear(v, operand); })) return false;\n\t\t\t\t} else if (operator == \"$bitsAnySet\") {\n\t\t\t\t\tif (!fieldValueMatches(fieldValue, function(v) { return matchesBitsAnySet(v, operand); })) return false;\n\t\t\t\t} else if (operator == \"$bitsAnyClear\") {\n\t\t\t\t\tif (!fieldValueMatches(fieldValue, function(v) { return matchesBitsAnyClear(v, operand); })) return false;\n\t\t\t\t} else {\n\t\t\t\t\t\tthrow { $err: \"Can't canonicalize query: BadValue unknown operator: \" + operator, code: 17287 };\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t} else {\n\t\t\t\treturn getProp(doc, key) && objectMatches(getProp(doc, key), value);\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * $not operator\n */\nexport function not(doc, value) {\n\treturn !tlMatches(doc, value);\n}\n\n/**\n * $and operator\n */\nexport function and(doc, els) {\n\tfor (var i = 0; i < els.length; i++) {\n\t\tif (!tlMatches(doc, els[i])) {\n\t\t\treturn false;\n\t\t}\n\t}\n\treturn true;\n}\n\n/**\n * $or operator\n */\nexport function or(doc, els) {\n\tfor (var i = 0; i < els.length; i++) {\n\t\tif (tlMatches(doc, els[i])) return true;\n\t}\n\treturn false;\n}\n\n/**\n * $nor operator\n */\nexport function nor(doc, els) {\n\tfor (var i = 0; i < els.length; i++) {\n\t\tif (tlMatches(doc, els[i])) return false;\n\t}\n\treturn true;\n}\n\n/**\n * Main matches function - query structure: (top level operators ( \"age\" : (operators) ))\n * top, top level query, implicit $and\n */\nexport function matches(doc, query) {\n\treturn and(doc, toArray(query));\n}\n\n/**\n * Enhanced matching function that also tracks which array index matched for positional operator ($)\n * Returns an object with:\n * - matched: boolean indicating if the query matched\n * - arrayFilters: object mapping field paths to the first matched array index\n * \n * Example: if query is { \"grades\": { $gte: 85 } } and doc is { grades: [80, 90, 85] }\n * Returns: { matched: true, arrayFilters: { \"grades\": 1 } } (index 1 is 90, first to match)\n */\nexport function matchWithArrayIndices(doc, query) {\n\tconst arrayFilters = {};\n\tconst matched = andWithTracking(doc, toArray(query), arrayFilters);\n\treturn { matched, arrayFilters };\n}\n\n/**\n * Helper to track array indices during AND matching\n */\nfunction andWithTracking(doc, els, arrayFilters) {\n\tfor (var i = 0; i < els.length; i++) {\n\t\tif (!tlMatchesWithTracking(doc, els[i], arrayFilters)) {\n\t\t\treturn false;\n\t\t}\n\t}\n\treturn true;\n}\n\n/**\n * Top level match with tracking\n */\nfunction tlMatchesWithTracking(doc, query, arrayFilters) {\n\tvar key = Object.keys(query)[0];\n\tvar value = query[key];\n\tif (key.charAt(0) == \"$\") {\n\t\tif (key == \"$and\") return andWithTracking(doc, value, arrayFilters);\n\t\telse if (key == \"$or\") return orWithTracking(doc, value, arrayFilters);\n\t\telse if (key == \"$not\") {\n\t\t\t// For $not, we don't track positions as it's a negation\n\t\t\treturn !tlMatches(doc, value);\n\t\t}\n\t\telse if (key == \"$nor\") return norWithTracking(doc, value, arrayFilters);\n\t\telse if (key == \"$where\") return where(doc, value);\n\t\telse if (key == \"$comment\") return true;\n\t\telse if (key == \"$jsonSchema\") return validateJsonSchema(doc, value);\n\t\telse if (key == \"$expr\") {\n\t\t\ttry {\n\t\t\t\treturn evaluateExpression(value, doc);\n\t\t\t} catch (e) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t\telse throw { $err: \"Can't canonicalize query: BadValue unknown top level operator: \" + key, code: 17287 };\n\t} else {\n\t\treturn opMatchesWithTracking(doc, key, value, arrayFilters);\n\t}\n}\n\n/**\n * OR operator with tracking - track positions from the first matching clause\n */\nfunction orWithTracking(doc, els, arrayFilters) {\n\tfor (var i = 0; i < els.length; i++) {\n\t\tif (tlMatchesWithTracking(doc, els[i], arrayFilters)) {\n\t\t\treturn true;\n\t\t}\n\t}\n\treturn false;\n}\n\n/**\n * NOR operator with tracking\n */\nfunction norWithTracking(doc, els, arrayFilters) {\n\tfor (var i = 0; i < els.length; i++) {\n\t\tif (tlMatchesWithTracking(doc, els[i], arrayFilters)) {\n\t\t\treturn false;\n\t\t}\n\t}\n\treturn true;\n}\n\n/**\n * Operator match with array index tracking\n */\nfunction opMatchesWithTracking(doc, key, value, arrayFilters) {\n\t// Get the base field (before any dots)\n\tconst baseField = key.split('.')[0];\n\tconst fieldValue = getFieldValues(doc, key);\n\t\n\t// Helper to track which index matched\n\tconst trackMatchingIndex = (fieldValue, checkFn) => {\n\t\tif (fieldValue === undefined) return false;\n\t\tif (fieldValue === null) return checkFn(fieldValue);\n\t\t\n\t\t// If fieldValue is an array from array traversal\n\t\tif (isArray(fieldValue)) {\n\t\t\t// Check if the base field itself is an array in the document\n\t\t\tconst baseValue = getProp(doc, baseField);\n\t\t\tif (isArray(baseValue)) {\n\t\t\t\t// Find first matching index\n\t\t\t\tfor (var i = 0; i < fieldValue.length; i++) {\n\t\t\t\t\tif (checkFn(fieldValue[i])) {\n\t\t\t\t\t\t// Track this as the matched index for this field\n\t\t\t\t\t\tarrayFilters[key] = i;\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t\t\n\t\t// Otherwise use regular matching\n\t\treturn fieldValueMatches(fieldValue, checkFn);\n\t};\n\t\n\t// Now perform the actual matching with tracking\n\tif (typeof (value) == \"string\") return trackMatchingIndex(fieldValue, function(v) { return valuesEqual(v, value); });\n\telse if (typeof (value) == \"number\") return trackMatchingIndex(fieldValue, function(v) { return valuesEqual(v, value); });\n\telse if (typeof (value) == \"boolean\") return trackMatchingIndex(fieldValue, function(v) { return valuesEqual(v, value); });\n\telse if (value instanceof ObjectId) return trackMatchingIndex(fieldValue, function(v) { return valuesEqual(v, value); });\n\telse if (typeof (value) == \"object\") {\n\t\tif (value instanceof RegExp) return fieldValue != undefined && trackMatchingIndex(fieldValue, function(v) { return v && v.match(value); });\n\t\telse if (isArray(value)) return fieldValue != undefined && trackMatchingIndex(fieldValue, function(v) { return v && arrayMatches(v, value); });\n\t\telse {\n\t\t\tvar keys = Object.keys(value);\n\t\t\tif (keys[0].charAt(0) == \"$\") {\n\t\t\t\t// Handle operators\n\t\t\t\tfor (var i = 0; i < keys.length; i++) {\n\t\t\t\t\tvar operator = keys[i];\n\t\t\t\t\tvar operand = value[operator];\n\t\t\t\t\tif (operator == \"$eq\") {\n\t\t\t\t\t\tif (!trackMatchingIndex(fieldValue, function(v) { return valuesEqual(v, operand); })) return false;\n\t\t\t\t\t} else if (operator == \"$gt\") {\n\t\t\t\t\t\tif (!trackMatchingIndex(fieldValue, function(v) { return compareValues(v, operand, '>'); })) return false;\n\t\t\t\t\t} else if (operator == \"$gte\") {\n\t\t\t\t\t\tif (!trackMatchingIndex(fieldValue, function(v) { return compareValues(v, operand, '>='); })) return false;\n\t\t\t\t\t} else if (operator == \"$lt\") {\n\t\t\t\t\t\tif (!trackMatchingIndex(fieldValue, function(v) { return compareValues(v, operand, '<'); })) return false;\n\t\t\t\t\t} else if (operator == \"$lte\") {\n\t\t\t\t\t\tif (!trackMatchingIndex(fieldValue, function(v) { return compareValues(v, operand, '<='); })) return false;\n\t\t\t\t\t} else if (operator == \"$ne\") {\n\t\t\t\t\t\tif (!trackMatchingIndex(fieldValue, function(v) { return !valuesEqual(v, operand); })) return false;\n\t\t\t\t\t} else if (operator == \"$in\") {\n\t\t\t\t\t\tif (!trackMatchingIndex(fieldValue, function(v) { return isIn(v, operand); })) return false;\n\t\t\t\t\t} else if (operator == \"$nin\") {\n\t\t\t\t\t\tif (trackMatchingIndex(fieldValue, function(v) { return isIn(v, operand); })) return false;\n\t\t\t\t\t} else if (operator == \"$elemMatch\") {\n\t\t\t\t\t\t// Special handling for $elemMatch\n\t\t\t\t\t\tvar arrayFieldValue = getProp(doc, key);\n\t\t\t\t\t\tif (arrayFieldValue == undefined || !isArray(arrayFieldValue)) return false;\n\t\t\t\t\t\tfor (var j = 0; j < arrayFieldValue.length; j++) {\n\t\t\t\t\t\t\tvar element = arrayFieldValue[j];\n\t\t\t\t\t\t\t// Check if element matches the query\n\t\t\t\t\t\t\tif (typeof element === 'object' && !isArray(element)) {\n\t\t\t\t\t\t\t\t// For objects, use matches\n\t\t\t\t\t\t\t\tif (matches(element, operand)) {\n\t\t\t\t\t\t\t\t\tarrayFilters[key] = j;\n\t\t\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t// For primitive values, check operators directly\n\t\t\t\t\t\t\t\tvar matchesPrimitive = true;\n\t\t\t\t\t\t\t\tvar opKeys = Object.keys(operand);\n\t\t\t\t\t\t\t\tfor (var k = 0; k < opKeys.length; k++) {\n\t\t\t\t\t\t\t\t\tvar op = opKeys[k];\n\t\t\t\t\t\t\t\t\tvar opValue = operand[op];\n\t\t\t\t\t\t\t\t\tif (op == \"$gte\" && !(element >= opValue)) matchesPrimitive = false;\n\t\t\t\t\t\t\t\t\telse if (op == \"$gt\" && !(element > opValue)) matchesPrimitive = false;\n\t\t\t\t\t\t\t\t\telse if (op == \"$lte\" && !(element <= opValue)) matchesPrimitive = false;\n\t\t\t\t\t\t\t\t\telse if (op == \"$lt\" && !(element < opValue)) matchesPrimitive = false;\n\t\t\t\t\t\t\t\t\telse if (op == \"$eq\" && element != opValue) matchesPrimitive = false;\n\t\t\t\t\t\t\t\t\telse if (op == \"$ne\" && element == opValue) matchesPrimitive = false;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (matchesPrimitive) {\n\t\t\t\t\t\t\t\t\tarrayFilters[key] = j;\n\t\t\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// For other operators, use standard matching\n\t\t\t\t\t\tif (!opMatches(doc, key, value)) return false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t} else {\n\t\t\t\t// Object equality\n\t\t\t\treturn fieldValue != undefined && trackMatchingIndex(fieldValue, function(v) { return objectMatches(v, value); });\n\t\t\t}\n\t\t}\n\t}\n\treturn false;\n}\n","/**\n * Update operations module\n */\n\nimport { setProp, getProp, isArray } from '../utils.js';\nimport { opMatches, matches } from './queryMatcher.js';\n\n/**\n * Extract identifier from a filtered positional operator pattern like $[identifier]\n * Returns null if not a filtered positional operator\n */\nfunction extractFilteredPositionalIdentifier(pathSegment) {\n\tconst match = pathSegment.match(/^\\$\\[([^\\]]+)\\]$/);\n\treturn match ? match[1] : null;\n}\n\n/**\n * Parse a field path and extract filtered positional identifiers\n * Returns an array of path segments with metadata about which are filtered positional operators\n */\nfunction parseFieldPath(fieldPath) {\n\tconst segments = fieldPath.split('.');\n\treturn segments.map(segment => {\n\t\tconst identifier = extractFilteredPositionalIdentifier(segment);\n\t\treturn {\n\t\t\tsegment: segment,\n\t\t\tisFilteredPositional: identifier !== null,\n\t\t\tidentifier: identifier\n\t\t};\n\t});\n}\n\n/**\n * Apply an update operation to array elements matching arrayFilters\n */\nfunction applyToFilteredArrayElements(doc, parsedPath, value, operation, arrayFilters) {\n\t// Navigate through the path and apply updates to matching array elements\n\tfunction traverse(current, pathIndex, filterContext) {\n\t\tif (pathIndex >= parsedPath.length) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst pathInfo = parsedPath[pathIndex];\n\t\tconst isLastSegment = pathIndex === parsedPath.length - 1;\n\n\t\tif (pathInfo.isFilteredPositional) {\n\t\t\t// This is a filtered positional operator like $[elem]\n\t\t\tconst identifier = pathInfo.identifier;\n\t\t\tconst filter = arrayFilters ? arrayFilters.find(f => {\n\t\t\t\t// Find the filter that uses this identifier\n\t\t\t\tconst filterKeys = Object.keys(f);\n\t\t\t\treturn filterKeys.some(key => key.startsWith(identifier + '.') || key === identifier);\n\t\t\t}) : null;\n\n\t\t\t// If arrayFilters is not provided, treat $[identifier] as a literal field name\n\t\t\tif (!arrayFilters) {\n\t\t\t\tif (!current[pathInfo.segment]) {\n\t\t\t\t\t// Create intermediate object/array as needed\n\t\t\t\t\tconst nextPath = parsedPath[pathIndex + 1];\n\t\t\t\t\tif (nextPath && nextPath.isFilteredPositional) {\n\t\t\t\t\t\tcurrent[pathInfo.segment] = [];\n\t\t\t\t\t} else {\n\t\t\t\t\t\tcurrent[pathInfo.segment] = {};\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (isLastSegment) {\n\t\t\t\t\tapplyOperationToValue(current, pathInfo.segment, value, operation);\n\t\t\t\t} else {\n\t\t\t\t\ttraverse(current[pathInfo.segment], pathIndex + 1, filterContext);\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (!isArray(current)) {\n\t\t\t\t// If current is not an array, create it as an object property\n\t\t\t\tif (!current[pathInfo.segment]) {\n\t\t\t\t\tcurrent[pathInfo.segment] = {};\n\t\t\t\t}\n\t\t\t\tif (isLastSegment) {\n\t\t\t\t\tapplyOperationToValue(current, pathInfo.segment, value, operation);\n\t\t\t\t} else {\n\t\t\t\t\ttraverse(current[pathInfo.segment], pathIndex + 1, filterContext);\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Iterate through array elements and apply to matching ones\n\t\t\tfor (let i = 0; i < current.length; i++) {\n\t\t\t\tconst element = current[i];\n\t\t\t\t\n\t\t\t\t// Check if this element matches the filter\n\t\t\t\tlet shouldUpdate = true;\n\t\t\t\tif (filter) {\n\t\t\t\t\t// Transform filter to check against the element\n\t\t\t\t\t// If filter has identifier.field, check element.field\n\t\t\t\t\t// If filter has just identifier, check element directly\n\t\t\t\t\tlet transformedFilter = {};\n\t\t\t\t\tlet hasDirectMatch = false;\n\t\t\t\t\t\n\t\t\t\t\tObject.keys(filter).forEach(key => {\n\t\t\t\t\t\tif (key.startsWith(identifier + '.')) {\n\t\t\t\t\t\t\t// Replace \"identifier.field\" with just \"field\" for matching against element\n\t\t\t\t\t\t\tconst fieldPath = key.substring(identifier.length + 1);\n\t\t\t\t\t\t\ttransformedFilter[fieldPath] = filter[key];\n\t\t\t\t\t\t} else if (key === identifier) {\n\t\t\t\t\t\t\t// Direct identifier match - the filter condition applies to the element value itself\n\t\t\t\t\t\t\ttransformedFilter = filter[key];\n\t\t\t\t\t\t\thasDirectMatch = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t\t\n\t\t\t\t\t// Check if element matches the filter\n\t\t\t\t\tif (hasDirectMatch) {\n\t\t\t\t\t\t// For primitive values, we need to check against the condition directly\n\t\t\t\t\t\t// Create a wrapper to use the matches function\n\t\t\t\t\t\tconst testDoc = { value: element };\n\t\t\t\t\t\tconst testFilter = { value: transformedFilter };\n\t\t\t\t\t\tshouldUpdate = matches(testDoc, testFilter);\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// For object properties, match against the element as a document\n\t\t\t\t\t\tshouldUpdate = matches(element, transformedFilter);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (shouldUpdate) {\n\t\t\t\t\tif (isLastSegment) {\n\t\t\t\t\t\t// Apply the operation to this array element\n\t\t\t\t\t\tapplyOperationToValue(current, i, value, operation);\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Continue traversing deeper\n\t\t\t\t\t\tif (element !== null && element !== undefined) {\n\t\t\t\t\t\t\ttraverse(current[i], pathIndex + 1, filterContext);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\t// Regular path segment\n\t\t\tif (current[pathInfo.segment] === undefined || current[pathInfo.segment] === null) {\n\t\t\t\tif (!isLastSegment) {\n\t\t\t\t\t// Create intermediate object/array\n\t\t\t\t\tconst nextPath = parsedPath[pathIndex + 1];\n\t\t\t\t\tif (nextPath && nextPath.isFilteredPositional) {\n\t\t\t\t\t\tcurrent[pathInfo.segment] = [];\n\t\t\t\t\t} else {\n\t\t\t\t\t\tcurrent[pathInfo.segment] = {};\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (isLastSegment) {\n\t\t\t\tapplyOperationToValue(current, pathInfo.segment, value, operation);\n\t\t\t} else {\n\t\t\t\tif (current[pathInfo.segment] !== undefined && current[pathInfo.segment] !== null) {\n\t\t\t\t\ttraverse(current[pathInfo.segment], pathIndex + 1, filterContext);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\ttraverse(doc, 0, {});\n}\n\n/**\n * Apply a specific operation to a value (for use with filtered positional operators)\n */\nfunction applyOperationToValue(container, key, value, operation) {\n\tswitch (operation) {\n\t\tcase '$set':\n\t\t\tcontainer[key] = value;\n\t\t\tbreak;\n\t\tcase '$inc':\n\t\t\tif (container[key] === undefined) container[key] = 0;\n\t\t\tcontainer[key] += value;\n\t\t\tbreak;\n\t\tcase '$mul':\n\t\t\tcontainer[key] = container[key] * value;\n\t\t\tbreak;\n\t\tcase '$min':\n\t\t\tcontainer[key] = Math.min(container[key], value);\n\t\t\tbreak;\n\t\tcase '$max':\n\t\t\tcontainer[key] = Math.max(container[key], value);\n\t\t\tbreak;\n\t\tcase '$unset':\n\t\t\tdelete container[key];\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tcontainer[key] = value;\n\t}\n}\n\n/**\n * Check if a field path contains a filtered positional operator\n */\nfunction hasFilteredPositionalOperator(fieldPath) {\n\treturn /\\$\\[[^\\]]+\\]/.test(fieldPath);\n}\n\n/**\n * Deep equality check for objects\n */\nfunction objectEquals(a, b) {\n\tif (a === b) return true;\n\tif (a == null || b == null) return false;\n\tif (typeof a !== 'object' || typeof b !== 'object') return false;\n\t\n\t// Handle arrays\n\tif (Array.isArray(a) && Array.isArray(b)) {\n\t\tif (a.length !== b.length) return false;\n\t\tfor (var i = 0; i < a.length; i++) {\n\t\t\tif (!objectEquals(a[i], b[i])) return false;\n\t\t}\n\t\treturn true;\n\t}\n\t\n\t// Handle dates\n\tif (a instanceof Date && b instanceof Date) {\n\t\treturn a.getTime() === b.getTime();\n\t}\n\t\n\t// One is array, the other is not\n\tif (Array.isArray(a) !== Array.isArray(b)) return false;\n\t\n\tvar keysA = Object.keys(a);\n\tvar keysB = Object.keys(b);\n\t\n\tif (keysA.length !== keysB.length) return false;\n\t\n\tfor (var i = 0; i < keysA.length; i++) {\n\t\tvar key = keysA[i];\n\t\tif (!keysB.includes(key)) return false;\n\t\tif (!objectEquals(a[key], b[key])) return false;\n\t}\n\t\n\treturn true;\n}\n\n/**\n * Check if a field path contains the $[] positional operator\n */\nfunction hasAllPositional(field) {\n\treturn field.indexOf('$[]') !== -1;\n}\n\n/**\n * Apply an update function to all elements matching $[] operator\n * This is used for operators like $inc, $mul that need to read-modify-write\n */\nfunction applyToAllPositional(doc, field, updateFn) {\n\tvar path = field.split(\".\");\n\tvar current = doc;\n\t\n\t// Navigate to the first $[] operator\n\tfor (var i = 0; i < path.length; i++) {\n\t\tvar pathSegment = path[i];\n\t\t\n\t\tif (pathSegment === '$[]') {\n\t\t\t// Current should be an array\n\t\t\tif (!Array.isArray(current)) {\n\t\t\t\treturn; // Skip if not an array\n\t\t\t}\n\t\t\t\n\t\t\t// Build the remaining path after this $[]\n\t\t\tvar remainingPath = path.slice(i + 1).join('.');\n\t\t\t\n\t\t\t// Process each array element\n\t\t\tfor (var j = 0; j < current.length; j++) {\n\t\t\t\tif (remainingPath) {\n\t\t\t\t\t// There's more path after $[], recursively apply\n\t\t\t\t\tif (remainingPath.indexOf('$[]') !== -1) {\n\t\t\t\t\t\t// Nested $[] operator\n\t\t\t\t\t\tapplyToAllPositional(current[j], remainingPath, updateFn);\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// No more $[], apply the update function\n\t\t\t\t\t\tvar currentValue = getProp(current[j], remainingPath);\n\t\t\t\t\t\tvar newValue = updateFn(currentValue);\n\t\t\t\t\t\tsetProp(current[j], remainingPath, newValue);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t// $[] is the last segment, apply to each element directly\n\t\t\t\t\tcurrent[j] = updateFn(current[j]);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\t\n\t\t// Navigate to next level\n\t\tif (current == null || current == undefined) return;\n\t\tcurrent = current[pathSegment];\n\t}\n}\n\n/**\n * Replace $ positional operator in a field path with the matched array index\n * \n * @param {string} fieldPath - The field path potentially containing $\n * @param {object} arrayFilters - Map of field paths to matched array indices\n * @returns {string} The field path with $ replaced by the matched index\n */\nfunction replacePositionalOperator(fieldPath, arrayFilters) {\n\tif (!arrayFilters || !fieldPath.includes('$')) {\n\t\treturn fieldPath;\n\t}\n\t\n\t// Split the path to find the $ placeholder\n\tconst parts = fieldPath.split('.');\n\tconst dollarIndex = parts.indexOf('$');\n\t\n\tif (dollarIndex === -1) {\n\t\treturn fieldPath;\n\t}\n\t\n\t// Build the field path up to the $\n\tconst pathBeforeDollar = parts.slice(0, dollarIndex).join('.');\n\t\n\t// Find the matched index for this field path\n\t// We need to check if we have a match for the field before $\n\tlet matchedIndex = null;\n\t\n\t// Try to find a matching filter by checking various possible field paths\n\t// The query could be on the array itself or a nested field\n\tfor (const filterPath in arrayFilters) {\n\t\t// Check if the filter path matches the beginning of our field path\n\t\tif (filterPath === pathBeforeDollar || filterPath.startsWith(pathBeforeDollar + '.')) {\n\t\t\tmatchedIndex = arrayFilters[filterPath];\n\t\t\tbreak;\n\t\t}\n\t}\n\t\n\t// If we found a matched index, replace $ with it\n\tif (matchedIndex !== null && matchedIndex !== undefined) {\n\t\tparts[dollarIndex] = matchedIndex.toString();\n\t\treturn parts.join('.');\n\t}\n\t\n\t// If no matched index found, return original path (update will likely be a no-op)\n\treturn fieldPath;\n}\n\n/**\n * Apply update operators to a document\n * \n * @param {object} updates - The update operators to apply\n * @param {object} doc - The document to update\n * @param {boolean} setOnInsert - Whether to apply $setOnInsert\n * @param {object} arrayFilters - Optional map of field paths to matched array indices for $ operator\n */\nexport function applyUpdates(updates, doc, setOnInsert, positionalMatchInfo, userArrayFilters) {\n\tvar keys = Object.keys(updates);\n\tfor (var i = 0; i < keys.length; i++) {\n\t\tvar key = keys[i];\n\t\tvar value = updates[key];\n\t\tif (key == \"$inc\") {\n\t\t\tvar fields = Object.keys(value);\n\t\t\tfor (var j = 0; j < fields.length; j++) {\n\t\t\t\tvar field = replacePositionalOperator(fields[j], positionalMatchInfo);\n\t\t\t\tvar amount = value[fields[j]];\n\t\t\t\t\n\t\t\t\t// Check if this field uses filtered positional operator\n\t\t\t\tif (hasFilteredPositionalOperator(field)) {\n\t\t\t\t\tif (!userArrayFilters) {\n\t\t\t\t\t\tthrow new Error('arrayFilters option is required when using filtered positional operator $[<identifier>]');\n\t\t\t\t\t}\n\t\t\t\t\tconst parsedPath = parseFieldPath(field);\n\t\t\t\t\tapplyToFilteredArrayElements(doc, parsedPath, amount, '$inc', userArrayFilters);\n\t\t\t\t} else if (hasAllPositional(field)) {\n\t\t\t\t\t// Handle $[] all-positional operator\n\t\t\t\t\tapplyToAllPositional(doc, field, function(val) {\n\t\t\t\t\t\treturn (val === undefined ? 0 : val) + amount;\n\t\t\t\t\t});\n\t\t\t\t} else {\n\t\t\t\t\tvar currentValue = getProp(doc, field);\n\t\t\t\t\tif (currentValue == undefined) currentValue = 0;\n\t\t\t\t\tsetProp(doc, field, currentValue + amount);\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (key == \"$mul\") {\n\t\t\tvar fields = Object.keys(value);\n\t\t\tfor (var j = 0; j < fields.length; j++) {\n\t\t\t\tvar field = replacePositionalOperator(fields[j], positionalMatchInfo);\n\t\t\t\tvar amount = value[fields[j]];\n\t\t\t\t\n\t\t\t\t// Check if this field uses filtered positional operator\n\t\t\t\tif (hasFilteredPositionalOperator(field)) {\n\t\t\t\t\tif (!userArrayFilters) {\n\t\t\t\t\t\tthrow new Error('arrayFilters option is required when using filtered positional operator $[<identifier>]');\n\t\t\t\t\t}\n\t\t\t\t\tconst parsedPath = parseFieldPath(field);\n\t\t\t\t\tapplyToFilteredArrayElements(doc, parsedPath, amount, '$mul', userArrayFilters);\n\t\t\t\t} else if (hasAllPositional(field)) {\n\t\t\t\t\t// Handle $[] all-positional operator\n\t\t\t\t\tapplyToAllPositional(doc, field, function(val) {\n\t\t\t\t\t\treturn val * amount;\n\t\t\t\t\t});\n\t\t\t\t} else {\n\t\t\t\t\tvar currentValue = getProp(doc, field);\n\t\t\t\t\tif (currentValue == undefined) currentValue = 0;\n\t\t\t\t\tsetProp(doc, field, currentValue * amount);\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (key == \"$rename\") {\n\t\t\tvar fields = Object.keys(value);\n\t\t\tfor (var j = 0; j < fields.length; j++) {\n\t\t\t\tvar field = replacePositionalOperator(fields[j], positionalMatchInfo);\n\t\t\t\tvar newName = replacePositionalOperator(value[fields[j]], positionalMatchInfo);\n\t\t\t\tdoc[newName] = doc[field];\n\t\t\t\tdelete doc[field];\n\t\t\t}\n\t\t} else if (key == \"$setOnInsert\" && setOnInsert) {\n\t\t\tvar fields = Object.keys(value);\n\t\t\tfor (var j = 0; j < fields.length; j++) {\n\t\t\t\tvar field = replacePositionalOperator(fields[j], positionalMatchInfo);\n\t\t\t\tdoc[field] = value[fields[j]];\n\t\t\t}\n\t\t} else if (key == \"$set\") {\n\t\t\tvar fields = Object.keys(value);\n\t\t\tfor (var j = 0; j < fields.length; j++) {\n\t\t\t\tvar field = replacePositionalOperator(fields[j], positionalMatchInfo);\n\t\t\t\t\n\t\t\t\t// Check if this field uses filtered positional operator\n\t\t\t\tif (hasFilteredPositionalOperator(field)) {\n\t\t\t\t\tif (!userArrayFilters) {\n\t\t\t\t\t\tthrow new Error('arrayFilters option is required when using filtered positional operator $[<identifier>]');\n\t\t\t\t\t}\n\t\t\t\t\tconst parsedPath = parseFieldPath(field);\n\t\t\t\t\tapplyToFilteredArrayElements(doc, parsedPath, value[fields[j]], '$set', userArrayFilters);\n\t\t\t\t} else {\n\t\t\t\t\tsetProp(doc, field, value[fields[j]]);\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (key == \"$unset\") {\n\t\t\tvar fields = Object.keys(value);\n\t\t\tfor (var j = 0; j < fields.length; j++) {\n\t\t\t\tvar field = replacePositionalOperator(fields[j], positionalMatchInfo);\n\t\t\t\tdelete doc[field];\n\t\t\t}\n\t\t} else if (key == \"$min\") {\n\t\t\tvar fields = Object.keys(value);\n\t\t\tfor (var j = 0; j < fields.length; j++) {\n\t\t\t\tvar field = replacePositionalOperator(fields[j], positionalMatchInfo);\n\t\t\t\tvar amount = value[fields[j]];\n\t\t\t\t\n\t\t\t\t// Check if this field uses filtered positional operator\n\t\t\t\tif (hasFilteredPositionalOperator(field)) {\n\t\t\t\t\tif (!userArrayFilters) {\n\t\t\t\t\t\tthrow new Error('arrayFilters option is required when using filtered positional operator $[<identifier>]');\n\t\t\t\t\t}\n\t\t\t\t\tconst parsedPath = parseFieldPath(field);\n\t\t\t\t\tapplyToFilteredArrayElements(doc, parsedPath, amount, '$min', userArrayFilters);\n\t\t\t\t} else if (hasAllPositional(field)) {\n\t\t\t\t\t// Handle $[] all-positional operator\n\t\t\t\t\tapplyToAllPositional(doc, field, function(val) {\n\t\t\t\t\t\treturn Math.min(val, amount);\n\t\t\t\t\t});\n\t\t\t\t} else {\n\t\t\t\t\tvar currentValue = getProp(doc, field);\n\t\t\t\t\tsetProp(doc, field, Math.min(currentValue, amount));\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (key == \"$max\") {\n\t\t\tvar fields = Object.keys(value);\n\t\t\tfor (var j = 0; j < fields.length; j++) {\n\t\t\t\tvar field = replacePositionalOperator(fields[j], positionalMatchInfo);\n\t\t\t\tvar amount = value[fields[j]];\n\t\t\t\t\n\t\t\t\t// Check if this field uses filtered positional operator\n\t\t\t\tif (hasFilteredPositionalOperator(field)) {\n\t\t\t\t\tif (!userArrayFilters) {\n\t\t\t\t\t\tthrow new Error('arrayFilters option is required when using filtered positional operator $[<identifier>]');\n\t\t\t\t\t}\n\t\t\t\t\tconst parsedPath = parseFieldPath(field);\n\t\t\t\t\tapplyToFilteredArrayElements(doc, parsedPath, amount, '$max', userArrayFilters);\n\t\t\t\t} else if (hasAllPositional(field)) {\n\t\t\t\t\t// Handle $[] all-positional operator\n\t\t\t\t\tapplyToAllPositional(doc, field, function(val) {\n\t\t\t\t\t\treturn Math.max(val, amount);\n\t\t\t\t\t});\n\t\t\t\t} else {\n\t\t\t\t\tvar currentValue = getProp(doc, field);\n\t\t\t\t\tsetProp(doc, field, Math.max(currentValue, amount));\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (key == \"$currentDate\") {\n\t\t\tvar fields = Object.keys(value);\n\t\t\tfor (var j = 0; j < fields.length; j++) {\n\t\t\t\tvar field = replacePositionalOperator(fields[j], positionalMatchInfo);\n\t\t\t\tvar typeSpec = value[fields[j]];\n\t\t\t\t\n\t\t\t\t// Handle boolean true or { $type: \"date\" }\n\t\t\t\tif (typeSpec === true || (typeof typeSpec === 'object' && typeSpec.$type === 'date')) {\n\t\t\t\t\tsetProp(doc, field, new Date());\n\t\t\t\t}\n\t\t\t\t// Default to Date for backwards compatibility\n\t\t\t\telse {\n\t\t\t\t\tsetProp(doc, field, new Date());\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (key == \"$addToSet\") {\n\t\t\tvar fields = Object.keys(value);\n\t\t\tfor (var j = 0; j < fields.length; j++) {\n\t\t\t\tvar field = replacePositionalOperator(fields[j], positionalMatchInfo);\n\t\t\t\tvar addValue = value[fields[j]];\n\t\t\t\tvar currentArray = getProp(doc, field);\n\t\t\t\tif (currentArray && Array.isArray(currentArray)) {\n\t\t\t\t\tcurrentArray.push(addValue);\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (key == \"$pop\") {\n\t\t\tvar fields = Object.keys(value);\n\t\t\tfor (var j = 0; j < fields.length; j++) {\n\t\t\t\tvar field = replacePositionalOperator(fields[j], positionalMatchInfo);\n\t\t\t\tvar popValue = value[fields[j]];\n\t\t\t\tvar currentArray = getProp(doc, field);\n\t\t\t\tif (currentArray && Array.isArray(currentArray)) {\n\t\t\t\t\tif (popValue == 1) {\n\t\t\t\t\t\tcurrentArray.pop();\n\t\t\t\t\t} else if (popValue == -1) {\n\t\t\t\t\t\tcurrentArray.shift();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (key == \"$pull\") {\n\t\t\tvar fields = Object.keys(value);\n\t\t\tfor (var j = 0; j < fields.length; j++) {\n\t\t\t\tvar field = replacePositionalOperator(fields[j], positionalMatchInfo);\n\t\t\t\tvar condition = value[fields[j]];\n\t\t\t\tvar src = getProp(doc, field);\n\t\t\t\t\n\t\t\t\t// Skip if field doesn't exist or is not an array\n\t\t\t\tif (src == undefined || !Array.isArray(src)) continue;\n\t\t\t\t\n\t\t\t\tvar notRemoved = [];\n\t\t\t\tfor (var k = 0; k < src.length; k++) {\n\t\t\t\t\tvar element = src[k];\n\t\t\t\t\tvar shouldRemove = false;\n\t\t\t\t\t\n\t\t\t\t\t// Determine how to match the condition against the element\n\t\t\t\t\tif (typeof condition === 'object' && condition !== null && !Array.isArray(condition)) {\n\t\t\t\t\t\t// Condition is an object (could be a query or a value to match)\n\t\t\t\t\t\tif (typeof element === 'object' && element !== null && !Array.isArray(element)) {\n\t\t\t\t\t\t\t// Element is also an object - use query matching\n\t\t\t\t\t\t\t// This handles both {price: null}, {name: \"test\"}, and {price: {$gte: 10}}\n\t\t\t\t\t\t\tshouldRemove = matches(element, condition);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// Element is a primitive but condition is an object with operators like {$gte: 5}\n\t\t\t\t\t\t\tvar tempDoc = { __temp: element };\n\t\t\t\t\t\t\tshouldRemove = opMatches(tempDoc, \"__temp\", condition);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Condition is a simple value (string, number, boolean, null, etc.)\n\t\t\t\t\t\t// Do direct comparison\n\t\t\t\t\t\tshouldRemove = element == condition;\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tif (!shouldRemove) notRemoved.push(element);\n\t\t\t\t}\n\t\t\t\tsetProp(doc, field, notRemoved);\n\t\t\t}\n\t\t} else if (key == \"$pullAll\") {\n\t\t\tvar fields = Object.keys(value);\n\t\t\tfor (var j = 0; j < fields.length; j++) {\n\t\t\t\tvar field = replacePositionalOperator(fields[j], positionalMatchInfo);\n\t\t\t\tvar src = getProp(doc, field);\n\t\t\t\tvar toRemove = value[fields[j]];\n\t\t\t\tvar notRemoved = [];\n\t\t\t\tfor (var k = 0; k < src.length; k++) {\n\t\t\t\t\tvar removed = false;\n\t\t\t\t\tfor (var l = 0; l < toRemove.length; l++) {\n\t\t\t\t\t\tif (src[k] == toRemove[l]) {\n\t\t\t\t\t\t\tremoved = true;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (!removed) notRemoved.push(src[k]);\n\t\t\t\t}\n\t\t\t\tsetProp(doc, field, notRemoved);\n\t\t\t}\n\t\t} else if (key == \"$pushAll\") {\n\t\t\tvar fields = Object.keys(value);\n\t\t\tfor (var j = 0; j < fields.length; j++) {\n\t\t\t\tvar field = replacePositionalOperator(fields[j], positionalMatchInfo);\n\t\t\t\tvar values = value[fields[j]];\n\t\t\t\tvar currentArray = getProp(doc, field);\n\t\t\t\tif (currentArray && Array.isArray(currentArray)) {\n\t\t\t\t\tfor (var k = 0; k < values.length; k++) {\n\t\t\t\t\t\tcurrentArray.push(values[k]);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (key == \"$push\") {\n\t\t\tvar fields = Object.keys(value);\n\t\t\tfor (var j = 0; j < fields.length; j++) {\n\t\t\t\tvar field = replacePositionalOperator(fields[j], positionalMatchInfo);\n\t\t\t\tvar pushValue = value[fields[j]];\n\t\t\t\t\n\t\t\t\t// Check if this is a modifier-based push\n\t\t\t\tvar isModifierPush = pushValue !== null && typeof pushValue === 'object' && \n\t\t\t\t\t(pushValue.$each !== undefined || pushValue.$position !== undefined || \n\t\t\t\t\t pushValue.$slice !== undefined || pushValue.$sort !== undefined);\n\t\t\t\t\n\t\t\t\tif (isModifierPush) {\n\t\t\t\t\t// Initialize array if it doesn't exist\n\t\t\t\t\tvar currentArray = getProp(doc, field);\n\t\t\t\t\tif (!currentArray) {\n\t\t\t\t\t\tcurrentArray = [];\n\t\t\t\t\t\tsetProp(doc, field, currentArray);\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\t// Get the values to push (either from $each or wrap single value)\n\t\t\t\t\tvar valuesToPush = pushValue.$each !== undefined ? pushValue.$each : [pushValue];\n\t\t\t\t\t\n\t\t\t\t\t// Get position (default to end of array)\n\t\t\t\t\tvar position = pushValue.$position !== undefined ? pushValue.$position : currentArray.length;\n\t\t\t\t\t\n\t\t\t\t\t// Handle negative position (from end)\n\t\t\t\t\tif (position < 0) {\n\t\t\t\t\t\tposition = Math.max(0, currentArray.length + position);\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\t// Insert values at specified position\n\t\t\t\t\tcurrentArray.splice(position, 0, ...valuesToPush);\n\t\t\t\t\t\n\t\t\t\t\t// Apply $sort if specified\n\t\t\t\t\tif (pushValue.$sort !== undefined) {\n\t\t\t\t\t\tvar sortSpec = pushValue.$sort;\n\t\t\t\t\t\tif (typeof sortSpec === 'number') {\n\t\t\t\t\t\t\t// Simple numeric sort\n\t\t\t\t\t\t\tcurrentArray.sort(function(a, b) {\n\t\t\t\t\t\t\t\tif (a < b) return sortSpec > 0 ? -1 : 1;\n\t\t\t\t\t\t\t\tif (a > b) return sortSpec > 0 ? 1 : -1;\n\t\t\t\t\t\t\t\treturn 0;\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t} else if (typeof sortSpec === 'object') {\n\t\t\t\t\t\t\t// Sort by subdocument fields\n\t\t\t\t\t\t\tcurrentArray.sort(function(a, b) {\n\t\t\t\t\t\t\t\tvar sortKeys = Object.keys(sortSpec);\n\t\t\t\t\t\t\t\tfor (var k = 0; k < sortKeys.length; k++) {\n\t\t\t\t\t\t\t\t\tvar sortKey = sortKeys[k];\n\t\t\t\t\t\t\t\t\tvar sortDir = sortSpec[sortKey];\n\t\t\t\t\t\t\t\t\tvar aVal = getProp(a, sortKey);\n\t\t\t\t\t\t\t\t\tvar bVal = getProp(b, sortKey);\n\t\t\t\t\t\t\t\t\tif (aVal < bVal) return sortDir > 0 ? -1 : 1;\n\t\t\t\t\t\t\t\t\tif (aVal > bVal) return sortDir > 0 ? 1 : -1;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\treturn 0;\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\t// Apply $slice if specified\n\t\t\t\t\tif (pushValue.$slice !== undefined) {\n\t\t\t\t\t\tvar sliceValue = pushValue.$slice;\n\t\t\t\t\t\tif (sliceValue < 0) {\n\t\t\t\t\t\t\t// Keep last N elements\n\t\t\t\t\t\t\tvar sliced = currentArray.slice(sliceValue);\n\t\t\t\t\t\t\tsetProp(doc, field, sliced);\n\t\t\t\t\t\t} else if (sliceValue === 0) {\n\t\t\t\t\t\t\t// Empty the array\n\t\t\t\t\t\t\tsetProp(doc, field, []);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// Keep first N elements\n\t\t\t\t\t\t\tvar sliced = currentArray.slice(0, sliceValue);\n\t\t\t\t\t\t\tsetProp(doc, field, sliced);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t// Simple push (original behavior)\n\t\t\t\t\tvar currentArray = getProp(doc, field);\n\t\t\t\t\tif (currentArray && Array.isArray(currentArray)) {\n\t\t\t\t\t\tcurrentArray.push(pushValue);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (key == \"$bit\") {\n\t\t\tvar fields = Object.keys(value);\n\t\t\tvar field = replacePositionalOperator(fields[0], positionalMatchInfo);\n\t\t\tvar operation = value[fields[0]];\n\t\t\tvar operator = Object.keys(operation)[0];\n\t\t\tvar operand = operation[operator];\n\t\t\tvar currentValue = getProp(doc, field);\n\t\t\tif (operator == \"and\") {\n\t\t\t\tsetProp(doc, field, currentValue & operand);\n\t\t\t} else if (operator == \"or\") {\n\t\t\t\tsetProp(doc, field, currentValue | operand);\n\t\t\t} else if (operator == \"xor\") {\n\t\t\t\tsetProp(doc, field, currentValue ^ operand);\n\t\t\t} else {\n\t\t\t\tthrow \"unknown $bit operator: \" + operator;\n\t\t\t}\n\t\t} else {\n\t\t\tthrow \"unknown update operator: \" + key;\n\t\t}\n\t}\n}\n\n/**\n * Create a new document from query and update operators for upsert\n */\nexport function createDocFromUpdate(query, updates, id) {\n\tvar newDoc = { _id: id };\n\tvar onlyFields = true;\n\tvar updateKeys = Object.keys(updates);\n\tfor (var i = 0; i < updateKeys.length; i++) {\n\t\tif (updateKeys[i].charAt(0) == \"$\") {\n\t\t\tonlyFields = false;\n\t\t\tbreak;\n\t\t}\n\t}\n\tif (onlyFields) {\n\t\tfor (var i = 0; i < updateKeys.length; i++) {\n\t\t\tnewDoc[updateKeys[i]] = updates[updateKeys[i]];\n\t\t}\n\t} else {\n\t\tvar queryKeys = Object.keys(query);\n\t\tfor (var i = 0; i < queryKeys.length; i++) {\n\t\t\tnewDoc[queryKeys[i]] = query[queryKeys[i]];\n\t\t}\n\t\tapplyUpdates(updates, newDoc, true);\n\t}\n\treturn newDoc;\n}\n","/**\n * Base class for collection indexes\n * Provides a common interface for different types of indexes (e.g., regular, text, geo)\n */\nexport class Index {\n\tconstructor(name, keys, storage, options = {}) {\n // TODO: remove and put into subclasses\n\t\tthis.name = name;\n\t\tthis.keys = keys;\n\t\tthis.storage = storage;\n\t\tthis.options = options;\n\t}\n\n\t/**\n\t * Add a document to the index\n\t * @param {Object} doc - The document to index\n\t */\n\tadd(doc) {\n\t\tthrow new Error('add() must be implemented by subclass');\n\t}\n\n\t/**\n\t * Remove a document from the index\n\t * @param {Object} doc - The document to remove\n\t */\n\tremove(doc) {\n\t\tthrow new Error('remove() must be implemented by subclass');\n\t}\n\n\t/**\n\t * Update a document in the index (remove old, add new)\n\t * @param {Object} oldDoc - The old document\n\t * @param {Object} newDoc - The new document\n\t */\n\tupdate(oldDoc, newDoc) {\n\t\tthis.remove(oldDoc);\n\t\tthis.add(newDoc);\n\t}\n\n\t/**\n\t * Query the index\n\t * @param {*} query - The query to execute\n\t * @returns {Array} Array of document IDs or null if index cannot satisfy query\n\t */\n\tquery(query) {\n\t\tthrow new Error('query() must be implemented by subclass');\n\t}\n\n\t/**\n\t * Clear all data from the index\n\t */\n\tclear() {\n\t\tthrow new Error('clear() must be implemented by subclass');\n\t}\n\n\t/**\n\t * Get index specification (for getIndexes())\n\t */\n\tgetSpec() {\n // TODO: remove and put into subclasses\n\t\treturn {\n\t\t\tname: this.name,\n\t\t\tkey: this.keys\n\t\t};\n\t}\n\n}\n","const VERSION_METADATA_SUFFIX = '.version.json';\nconst VERSION_SUFFIX = '.v';\n\nexport const DEFAULT_COMPACTION_MIN_BYTES = 16 * 1024;\n\nfunction buildVersionedPath(basePath, version) {\n const numericVersion = Number(version);\n if (!Number.isFinite(numericVersion)) {\n throw new Error(`Invalid version value: ${version}`);\n }\n if (numericVersion < 0) {\n throw new Error(`Version must be non-negative: ${numericVersion}`);\n }\n if (numericVersion === 0) {\n return basePath;\n }\n return `${basePath}${VERSION_SUFFIX}${numericVersion}`;\n}\n\nfunction normalizeMetadata(data) {\n const metadata = { currentVersion: 0, refCounts: {} };\n if (!data || typeof data !== 'object') return metadata;\n\n const version = Number(data.currentVersion);\n metadata.currentVersion = Number.isFinite(version) ? version : 0;\n\n if (data.refCounts && typeof data.refCounts === 'object') {\n for (const [key, value] of Object.entries(data.refCounts)) {\n const count = Number(value);\n if (Number.isFinite(count) && count > 0) {\n metadata.refCounts[String(key)] = count;\n } else if (!Number.isFinite(count) || count < 0) {\n console.warn(`Ignoring invalid ref count for version ${key}: ${value}`);\n }\n }\n }\n\n return metadata;\n}\n\nfunction splitPath(filePath) {\n const parts = filePath.split('/').filter(Boolean);\n const filename = parts.pop();\n if (!filename) {\n throw new Error(`Invalid storage path: ${filePath}`);\n }\n return { parts, filename };\n}\n\nasync function getDirectoryHandle(pathParts, create) {\n let dir = await globalThis.navigator.storage.getDirectory();\n for (const part of pathParts) {\n dir = await dir.getDirectoryHandle(part, { create });\n }\n return dir;\n}\n\nasync function ensureDirectoryForFile(filePath) {\n const { parts } = splitPath(filePath);\n if (parts.length === 0) return;\n await getDirectoryHandle(parts, true);\n}\n\nasync function getFileHandle(filePath, { create } = {}) {\n const { parts, filename } = splitPath(filePath);\n const dir = await getDirectoryHandle(parts, !!create);\n return dir.getFileHandle(filename, { create });\n}\n\nasync function readMetadata(basePath) {\n const metadataPath = `${basePath}${VERSION_METADATA_SUFFIX}`;\n try {\n const fileHandle = await getFileHandle(metadataPath, { create: false });\n const file = await fileHandle.getFile();\n const text = await file.text();\n if (!text || text.trim() === '') {\n return normalizeMetadata();\n }\n return normalizeMetadata(JSON.parse(text));\n } catch (error) {\n if (error?.name === 'NotFoundError' || error?.code === 'ENOENT') {\n return normalizeMetadata();\n }\n throw error;\n }\n}\n\nasync function writeMetadata(basePath, metadata) {\n const metadataPath = `${basePath}${VERSION_METADATA_SUFFIX}`;\n await ensureDirectoryForFile(metadataPath);\n const fileHandle = await getFileHandle(metadataPath, { create: true });\n const writable = await fileHandle.createWritable();\n await writable.write(JSON.stringify(metadata));\n await writable.close();\n}\n\nasync function deleteVersionedFiles(basePath, version, suffixes) {\n const versionedBase = buildVersionedPath(basePath, version);\n for (const suffix of suffixes) {\n const filePath = suffix ? `${versionedBase}${suffix}` : versionedBase;\n await removeFile(filePath);\n }\n}\n\nasync function cleanupVersionIfUnreferenced(basePath, version, metadata, suffixes) {\n if (version === metadata.currentVersion) return;\n const key = String(version);\n if (metadata.refCounts[key]) return;\n await deleteVersionedFiles(basePath, version, suffixes);\n}\n\nexport async function acquireVersionedPath(basePath) {\n const metadata = await readMetadata(basePath);\n const currentVersion = metadata.currentVersion;\n const key = String(currentVersion);\n metadata.refCounts[key] = (metadata.refCounts[key] || 0) + 1;\n await writeMetadata(basePath, metadata);\n return {\n version: currentVersion,\n path: buildVersionedPath(basePath, currentVersion)\n };\n}\n\nexport async function releaseVersionedPath(basePath, version, { suffixes = [''] } = {}) {\n const metadata = await readMetadata(basePath);\n const key = String(version);\n if (metadata.refCounts[key]) {\n metadata.refCounts[key] -= 1;\n if (metadata.refCounts[key] <= 0) {\n delete metadata.refCounts[key];\n }\n }\n await cleanupVersionIfUnreferenced(basePath, version, metadata, suffixes);\n await writeMetadata(basePath, metadata);\n}\n\nexport async function promoteVersion(basePath, newVersion, oldVersion, { suffixes = [''] } = {}) {\n const metadata = await readMetadata(basePath);\n const nextVersion = Number(newVersion);\n metadata.currentVersion = Number.isFinite(nextVersion) ? nextVersion : metadata.currentVersion;\n const key = String(metadata.currentVersion);\n if (!metadata.refCounts[key]) {\n metadata.refCounts[key] = 0;\n }\n await cleanupVersionIfUnreferenced(basePath, oldVersion, metadata, suffixes);\n await writeMetadata(basePath, metadata);\n}\n\nexport async function getCurrentVersion(basePath) {\n const metadata = await readMetadata(basePath);\n return metadata.currentVersion;\n}\n\nexport async function removeFile(filePath) {\n try {\n const { parts, filename } = splitPath(filePath);\n const dir = await getDirectoryHandle(parts, false);\n await dir.removeEntry(filename);\n } catch (error) {\n if (error?.name === 'NotFoundError' || error?.code === 'ENOENT') {\n return;\n }\n throw error;\n }\n}\n\nexport async function createSyncAccessHandle(filePath, { reset = false } = {}) {\n if (reset) {\n await removeFile(filePath);\n }\n await ensureDirectoryForFile(filePath);\n const fileHandle = await getFileHandle(filePath, { create: true });\n return fileHandle.createSyncAccessHandle();\n}\n\nexport { buildVersionedPath };\n","import { Index } from './Index.js';\nimport { getProp } from '../../utils.js';\nimport { BPlusTree } from '@belteshazzar/binjson/bplustree';\nimport {\n\tacquireVersionedPath,\n\tbuildVersionedPath,\n\tcreateSyncAccessHandle,\n\tDEFAULT_COMPACTION_MIN_BYTES,\n\tgetCurrentVersion,\n\tpromoteVersion,\n\treleaseVersionedPath\n} from '../opfsVersioning.js';\n\n/**\n * Regular index using bjson's persistent BPlusTree with OPFS backing\n * All operations are async\n */\nexport class RegularCollectionIndex extends Index {\n\tconstructor(name, keys, storageFilePath, options = {}) {\n\t\tsuper(name, keys, storageFilePath, options);\n\t\t// Store path for later initialization\n\t\tthis.storageFilePath = storageFilePath;\n\t\tthis.storageVersionedPath = null;\n\t\tthis.storageVersion = 0;\n\t\tthis._releaseStorage = null;\n\t\tthis.data = null;\n\t\tthis.syncHandle = null;\n\t\tthis.isOpen = false;\n\t}\n\n\t/**\n\t * Open the index file\n\t * Must be called before using the index\n\t */\n\tasync open() {\n\t\tif (this.isOpen) {\n\t\t\treturn;\n\t\t}\n\t\ttry {\n\t\t\tconst { version, path: versionedPath } = await acquireVersionedPath(this.storageFilePath);\n\t\t\tthis.storageVersion = version;\n\t\t\tthis.storageVersionedPath = versionedPath;\n\t\t\tthis._releaseStorage = () => releaseVersionedPath(this.storageFilePath, version);\n\n\t\t\t// Parse path to get directory and filename\n\t\t\tconst pathParts = this.storageVersionedPath.split('/').filter(Boolean);\n\t\t\tconst filename = pathParts.pop();\n\t\t\t\n\t\t\tif (!filename) {\n\t\t\t\tthrow new Error(`Invalid storage path: ${this.storageVersionedPath}`);\n\t\t\t}\n\t\t\t\n\t\t\t// Navigate to directory\n\t\t\tlet dirHandle = await globalThis.navigator.storage.getDirectory();\n\t\t\tfor (const part of pathParts) {\n\t\t\t\tdirHandle = await dirHandle.getDirectoryHandle(part, { create: true });\n\t\t\t}\n\t\t\t\n\t\t\t// Get file handle and create sync access handle using native OPFS\n\t\t\tconst fileHandle = await dirHandle.getFileHandle(filename, { create: true });\n\t\t\tthis.syncHandle = await fileHandle.createSyncAccessHandle();\n\t\t\t\n\t\t\t// Create BPlusTree with sync handle\n\t\t\tthis.data = new BPlusTree(this.syncHandle, 50);\n\t\t\tawait this.data.open();\n\t\t\tthis.isOpen = true;\n\t\t} catch (error) {\n\t\t\t// If file is corrupted, delete and recreate\n\t\t\tif (error.message && (error.message.includes('Unknown type byte') || \n\t\t\t\t\terror.message.includes('Failed to read metadata') ||\n\t\t\t\t\terror.message.includes('Invalid tree file'))) {\n\t\t\t\t// Close sync handle if open\n\t\t\t\tif (this.syncHandle) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tawait this.syncHandle.close();\n\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\t// Ignore close errors\n\t\t\t\t\t}\n\t\t\t\t\tthis.syncHandle = null;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t// Parse path to get directory and filename\n\t\t\t\tconst pathParts = this.storageVersionedPath.split('/').filter(Boolean);\n\t\t\t\tconst filename = pathParts.pop();\n\t\t\t\t\n\t\t\t\tif (!filename) {\n\t\t\t\t\tthrow new Error(`Invalid storage path: ${this.storageVersionedPath}`);\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t// Navigate to directory\n\t\t\t\tlet dirHandle = await globalThis.navigator.storage.getDirectory();\n\t\t\t\tfor (const part of pathParts) {\n\t\t\t\t\tdirHandle = await dirHandle.getDirectoryHandle(part, { create: true });\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t// Try to delete the corrupted file\n\t\t\t\ttry {\n\t\t\t\t\tawait dirHandle.removeEntry(filename);\n\t\t\t\t} catch (e) {\n\t\t\t\t\t// File might not exist, ignore\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t// Get new file handle and create sync access handle using native OPFS\n\t\t\t\tconst fileHandle = await dirHandle.getFileHandle(filename, { create: true });\n\t\t\t\tthis.syncHandle = await fileHandle.createSyncAccessHandle();\n\t\t\t\t\n\t\t\t\t// Create fresh BPlusTree\n\t\t\t\tthis.data = new BPlusTree(this.syncHandle, 50);\n\t\t\t\tawait this.data.open();\n\t\t\t\tthis.isOpen = true;\n\t\t\t} else {\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Close the index file\n\t */\n\tasync close() {\n\t\tif (!this.isOpen) {\n\t\t\tif (this._releaseStorage) {\n\t\t\t\tawait this._releaseStorage();\n\t\t\t\tthis._releaseStorage = null;\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\ttry {\n\t\t\tawait this._maybeCompact();\n\t\t\tawait this.data.close();\n\t\t} catch (error) {\n\t\t\t// Ignore errors from already-closed files\n\t\t\tif (!error.message || !error.message.includes('File is not open')) {\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t}\n\t\tthis.isOpen = false;\n\t\tif (this._releaseStorage) {\n\t\t\tawait this._releaseStorage();\n\t\t\tthis._releaseStorage = null;\n\t\t}\n\t}\n\n\tasync _maybeCompact() {\n\t\tif (!this.data || !this.data.file) return;\n\t\tconst currentVersion = await getCurrentVersion(this.storageFilePath);\n\t\tif (currentVersion !== this.storageVersion) return;\n\t\tconst fileSize = this.data.file.getFileSize();\n\t\tif (!fileSize || fileSize < DEFAULT_COMPACTION_MIN_BYTES) return;\n\n\t\tconst nextVersion = currentVersion + 1;\n\t\tconst compactPath = buildVersionedPath(this.storageFilePath, nextVersion);\n\t\tconst destSyncHandle = await createSyncAccessHandle(compactPath, { reset: true });\n\t\tawait this.data.compact(destSyncHandle);\n\t\tawait promoteVersion(this.storageFilePath, nextVersion, currentVersion);\n\t}\n\n\t/**\n\t * Extract index key value from a document\n\t */\n\textractIndexKey(doc) {\n\t\tconst keyFields = Object.keys(this.keys);\n\t\tif (keyFields.length === 0) return null;\n\n\t\t// For simple single-field index\n\t\tif (keyFields.length === 1) {\n\t\t\tconst field = keyFields[0];\n\t\t\tconst value = getProp(doc, field);\n\t\t\tif (value === undefined) return null;\n\t\t\t// Preserve type information in the key\n\t\t\treturn value; //JSON.stringify({ t: typeof value, v: value });\n\t\t}\n\n\t\t// For compound index, concatenate values with type preservation\n\t\tconst keyParts = [];\n\t\tfor (let i = 0; i < keyFields.length; i++) {\n\t\t\tconst value = getProp(doc, keyFields[i]);\n\t\t\tif (value === undefined) return null;\n\t\t\tkeyParts.push(value /*JSON.stringify(value) */);\n\t\t}\n\t\t// Use a separator that won't appear in JSON\n\t\treturn keyParts.join('\\x00');\n\t}\n\n\t/**\n\t * Add a document to the index\n * \n\t * @param {Object} doc - The document to index\n\t */\n\tasync add(doc) {\n\t\tif (!this.isOpen) {\n\t\t\tawait this.open();\n\t\t}\n\t\tconst indexKey = this.extractIndexKey(doc);\n\t\tif (indexKey !== null) {\n\t\t\tconst docId = doc._id.toString();\n\t\t\t// Get existing doc IDs for this key (if any)\n\t\t\tconst existing = await this.data.search(indexKey);\n\t\t\tlet docIds;\n\t\t\tif (Array.isArray(existing)) {\n\t\t\t\t// Avoid duplicates\n\t\t\t\tif (!existing.includes(docId)) {\n\t\t\t\t\tdocIds = [...existing, docId];\n\t\t\t\t} else {\n\t\t\t\t\treturn; // Already indexed\n\t\t\t\t}\n\t\t\t} else if (existing) {\n\t\t\t\t// Single value, convert to array\n\t\t\t\tdocIds = existing === docId ? [existing] : [existing, docId];\n\t\t\t} else {\n\t\t\t\t// No existing value\n\t\t\t\tdocIds = [docId];\n\t\t\t}\n\t\t\tawait this.data.add(indexKey, docIds);\n\t\t}\n\t}\n\n\t/**\n\t * Remove a document from the index\n * \n\t * @param {Object} doc - The document to remove\n\t */\n\tasync remove(doc) {\n\t\tif (!this.isOpen) {\n\t\t\tawait this.open();\n\t\t}\n\t\tconst indexKey = this.extractIndexKey(doc);\n\t\tif (indexKey !== null) {\n\t\t\tconst docId = doc._id.toString();\n\t\t\tconst existing = await this.data.search(indexKey);\n\t\t\tif (Array.isArray(existing)) {\n\t\t\t\tconst filtered = existing.filter(id => id !== docId);\n\t\t\t\tif (filtered.length > 0) {\n\t\t\t\t\tawait this.data.add(indexKey, filtered);\n\t\t\t\t} else {\n\t\t\t\t\tawait this.data.delete(indexKey);\n\t\t\t\t}\n\t\t\t} else if (existing === docId) {\n\t\t\t\tawait this.data.delete(indexKey);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Query the index\n * \n\t * @param {*} query - The query object\n\t * @returns {Promise<Array|null>} Array of document IDs or null if index cannot satisfy query\n\t */\n\tasync query(query) {\n\t\tconst queryKeys = Object.keys(query);\n\t\tconst indexFields = Object.keys(this.keys);\n\n\t\t// Only support single-field index queries for now\n\t\tif (indexFields.length !== 1) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst field = indexFields[0];\n\t\t\n\t\t// Check if query has this field\n\t\tif (queryKeys.indexOf(field) === -1) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst queryValue = query[field];\n\n\t\t// Case 1: Simple equality\n\t\tif (typeof queryValue !== 'object' || queryValue === null) {\n\t\t\tconst indexKey = queryValue;\n\t\t\tconst result = await this.data.search(indexKey);\n\t\t\t// Result might be an array of doc IDs or undefined\n\t\t\treturn result || [];\n\t\t}\n\n\t\t// Case 2: Query with operators\n\t\tif (typeof queryValue === 'object' && !Array.isArray(queryValue)) {\n\t\t\treturn await this._queryWithOperators(field, queryValue);\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t/**\n\t * Query index with comparison operators\n * \n\t * @private\n\t */\n\tasync _queryWithOperators(field, operators) {\n\t\tconst ops = Object.keys(operators);\n\t\tconst results = new Set();\n\n\t\t// Handle range queries: $gt, $gte, $lt, $lte\n\t\tconst hasRangeOp = ops.some(op => ['$gt', '$gte', '$lt', '$lte'].includes(op));\n\t\t\n\t\tif (hasRangeOp) {\n\t\t\t// Use B+ tree's efficient range search if we have both bounds\n\t\t\tconst hasGt = ops.includes('$gt') || ops.includes('$gte');\n\t\t\tconst hasLt = ops.includes('$lt') || ops.includes('$lte');\n\t\t\t\n\t\t\tif (hasGt && hasLt) {\n\t\t\t\t// Determine min and max bounds\n\t\t\t\tconst minValue = ops.includes('$gte') ? operators['$gte'] : \n\t\t\t\t ops.includes('$gt') ? operators['$gt'] : -Infinity;\n\t\t\t\tconst maxValue = ops.includes('$lte') ? operators['$lte'] : \n\t\t\t\t ops.includes('$lt') ? operators['$lt'] : Infinity;\n\t\t\t\t\n\t\t\t\tconst rangeResults = await this.data.rangeSearch(minValue, maxValue);\n\t\t\t\t\n\t\t\t\tfor (const entry of rangeResults) {\n\t\t\t\t\tconst keyValue = entry.key;\n\t\t\t\t\tconst value = entry.value;\n\t\t\t\t\t\n\t\t\t\t\t// Apply exact operator semantics\n\t\t\t\t\tlet matches = true;\n\t\t\t\t\tif (ops.includes('$gt') && !(keyValue > operators['$gt'])) matches = false;\n\t\t\t\t\tif (ops.includes('$gte') && !(keyValue >= operators['$gte'])) matches = false;\n\t\t\t\t\tif (ops.includes('$lt') && !(keyValue < operators['$lt'])) matches = false;\n\t\t\t\t\tif (ops.includes('$lte') && !(keyValue <= operators['$lte'])) matches = false;\n\t\t\t\t\t\n\t\t\t\t\tif (matches && value) {\n\t\t\t\t\t\t// value is an array of document IDs\n\t\t\t\t\t\tif (Array.isArray(value)) {\n\t\t\t\t\t\t\tvalue.forEach(id => results.add(id));\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tresults.add(value);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn Array.from(results);\n\t\t\t} else {\n\t\t\t\t// Scan all entries if we don't have both bounds\n\t\t\t\tconst allEntries = await this.data.toArray();\n\t\t\t\t\n\t\t\t\tfor (const entry of allEntries) {\n\t\t\t\t\tconst keyValue = entry.key;\n\t\t\t\t\tconst value = entry.value;\n\t\t\t\t\t\n\t\t\t\t\t// Check if value matches all operators\n\t\t\t\t\tlet matches = true;\n\t\t\t\t\tfor (const op of ops) {\n\t\t\t\t\t\tconst operand = operators[op];\n\t\t\t\t\t\tif (op === '$gt' && !(keyValue > operand)) matches = false;\n\t\t\t\t\t\telse if (op === '$gte' && !(keyValue >= operand)) matches = false;\n\t\t\t\t\t\telse if (op === '$lt' && !(keyValue < operand)) matches = false;\n\t\t\t\t\t\telse if (op === '$lte' && !(keyValue <= operand)) matches = false;\n\t\t\t\t\t\telse if (op === '$eq' && !(keyValue === operand)) matches = false;\n\t\t\t\t\t\telse if (op === '$ne' && !(keyValue !== operand)) matches = false;\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tif (matches && value) {\n\t\t\t\t\t\t// value is an array of document IDs\n\t\t\t\t\t\tif (Array.isArray(value)) {\n\t\t\t\t\t\t\tvalue.forEach(id => results.add(id));\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tresults.add(value);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn Array.from(results);\n\t\t\t}\n\t\t}\n\n\t\t// Handle $in operator\n\t\tif (ops.includes('$in')) {\n\t\t\tconst values = operators['$in'];\n\t\t\tif (Array.isArray(values)) {\n\t\t\t\tfor (const value of values) {\n\t\t\t\t\tconst result = await this.data.search(value);\n\t\t\t\t\tif (result) {\n\t\t\t\t\t\tif (Array.isArray(result)) {\n\t\t\t\t\t\t\tresult.forEach(id => results.add(id));\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tresults.add(result);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn Array.from(results);\n\t\t\t}\n\t\t}\n\n\t\t// Handle $eq operator\n\t\tif (ops.includes('$eq')) {\n\t\t\tconst value = operators['$eq'];\n\t\t\tconst result = await this.data.search(value);\n\t\t\tif (result) {\n\t\t\t\treturn Array.isArray(result) ? result : [result];\n\t\t\t}\n\t\t\treturn [];\n\t\t}\n\n\t\t// Handle $ne operator (requires full scan, not optimal)\n\t\tif (ops.includes('$ne')) {\n\t\t\tconst excludeValue = operators['$ne'];\n\t\t\tconst allEntries = await this.data.toArray();\n\t\t\t\n\t\t\tfor (const entry of allEntries) {\n\t\t\t\tif (entry.key !== excludeValue && entry.value) {\n\t\t\t\t\t// value is an array of document IDs\n\t\t\t\t\tif (Array.isArray(entry.value)) {\n\t\t\t\t\t\tentry.value.forEach(id => results.add(id));\n\t\t\t\t\t} else {\n\t\t\t\t\t\tresults.add(entry.value);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn Array.from(results);\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t/**\n\t * Clear all entries from the index\n\t */\n\tasync clear() {\n\t\t// For persistent storage, close and recreate the tree\n\t\tif (this.isOpen) {\n\t\t\tawait this.close();\n\t\t}\n\t\tconst currentVersion = await getCurrentVersion(this.storageFilePath);\n\t\tconst targetPath = buildVersionedPath(this.storageFilePath, currentVersion);\n\n\t\t// Parse path to get directory and filename\n\t\tconst pathParts = targetPath.split('/').filter(Boolean);\n\t\tconst filename = pathParts.pop();\n\t\t\n\t\t// Navigate to directory\n\t\tlet dirHandle = await globalThis.navigator.storage.getDirectory();\n\t\tfor (const part of pathParts) {\n\t\t\tdirHandle = await dirHandle.getDirectoryHandle(part, { create: true });\n\t\t}\n\t\t\n\t\t// Delete the old file\n\t\ttry {\n\t\t\tawait dirHandle.removeEntry(filename);\n\t\t} catch (e) {\n\t\t\t// File might not exist, ignore\n\t\t}\n\t\t\n\t\t// Recreate with new sync handle\n\t\tawait this.open();\n\t}\n}\n","import { Index } from './Index.js';\nimport { TextIndex } from '@belteshazzar/binjson/textindex';\nimport { BPlusTree } from '@belteshazzar/binjson/bplustree';\nimport { getProp } from '../../utils.js';\nimport {\n\tacquireVersionedPath,\n\tbuildVersionedPath,\n\tcreateSyncAccessHandle,\n\tDEFAULT_COMPACTION_MIN_BYTES,\n\tgetCurrentVersion,\n\tpromoteVersion,\n\treleaseVersionedPath\n} from '../opfsVersioning.js';\n\nconst TEXT_INDEX_SUFFIXES = ['-terms.bj', '-documents.bj', '-lengths.bj'];\n\n/**\n * Text index implementation\n * OPFS-backed async implementation using bjson TextIndex\n */\nexport class TextCollectionIndex extends Index {\n\tconstructor(name, keys, storage, options = {}) {\n\t\tsuper(name, keys, storage);\n\t\tthis.storageBasePath = storage;\n\t\tthis.storageVersion = 0;\n\t\tthis.versionedBasePath = null;\n\t\tthis._releaseStorage = null;\n\t\tthis.textIndex = null;\n\t\tthis.syncHandles = [];\n\t\tthis.isOpen = false;\n\t\t// Track which fields are indexed\n\t\tthis.indexedFields = [];\n\t\tfor (const field in keys) {\n\t\t\tif (keys[field] === 'text') {\n\t\t\t\tthis.indexedFields.push(field);\n\t\t\t}\n\t\t}\n\t\tif (this.indexedFields.length === 0) {\n\t\t\tthrow new Error('Text index must have at least one field with type \"text\"');\n\t\t}\n\t}\n\n\t/**\n\t * Open the index files\n\t * Must be called before using the index\n\t */\n\tasync open() {\n\t\tif (this.isOpen) {\n\t\t\treturn;\n\t\t}\n\t\ttry {\n\t\t\tconst { version, path: versionedBasePath } = await acquireVersionedPath(this.storageBasePath);\n\t\t\tthis.storageVersion = version;\n\t\t\tthis.versionedBasePath = versionedBasePath;\n\t\t\tthis._releaseStorage = () => releaseVersionedPath(this.storageBasePath, version, { suffixes: TEXT_INDEX_SUFFIXES });\n\n\t\t\t// Create three BPlusTree instances for the TextIndex\n\t\t\tconst indexTree = await this._createBPlusTree(this._getActiveBasePath() + '-terms.bj');\n\t\t\tconst docTermsTree = await this._createBPlusTree(this._getActiveBasePath() + '-documents.bj');\n\t\t\tconst lengthsTree = await this._createBPlusTree(this._getActiveBasePath() + '-lengths.bj');\n\t\t\t\n\t\t\tthis.textIndex = new TextIndex({\n\t\t\t\torder: 16,\n\t\t\t\ttrees: {\n\t\t\t\t\tindex: indexTree,\n\t\t\t\t\tdocumentTerms: docTermsTree,\n\t\t\t\t\tdocumentLengths: lengthsTree\n\t\t\t\t}\n\t\t\t});\n\t\t\t\n\t\t\tawait this.textIndex.open();\n\t\t\tthis.isOpen = true;\n\t\t} catch (error) {\n\t\t\t// Handle missing or corrupted files\n\t\t\tif (error.code === 'ENOENT' ||\n\t\t\t\t\t(error.message && (error.message.includes('Failed to read metadata') ||\n\t\t\t\t\terror.message.includes('missing required fields') ||\n\t\t\t\t\terror.message.includes('Unknown type byte') ||\n\t\t\t\t\terror.message.includes('Invalid') ||\n\t\t\t\t\terror.message.includes('file too small')))) {\n\t\t\t\t// Close any open sync handles\n\t\t\t\tawait this._closeSyncHandles();\n\t\t\t\t\n\t\t\t\t// Delete corrupted files and ensure directory exists\n\t\t\t\tawait this._deleteIndexFiles();\n\t\t\t\tawait this._ensureDirectoryForFile(this._getActiveBasePath() + '-terms.bj');\n\t\t\t\t\n\t\t\t\t// Create fresh TextIndex for new/corrupted files\n\t\t\t\tconst indexTree = await this._createBPlusTree(this._getActiveBasePath() + '-terms.bj');\n\t\t\t\tconst docTermsTree = await this._createBPlusTree(this._getActiveBasePath() + '-documents.bj');\n\t\t\t\tconst lengthsTree = await this._createBPlusTree(this._getActiveBasePath() + '-lengths.bj');\n\t\t\t\t\n\t\t\t\tthis.textIndex = new TextIndex({\n\t\t\t\t\torder: 16,\n\t\t\t\t\ttrees: {\n\t\t\t\t\t\tindex: indexTree,\n\t\t\t\t\t\tdocumentTerms: docTermsTree,\n\t\t\t\t\t\tdocumentLengths: lengthsTree\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\t\n\t\t\t\tawait this.textIndex.open();\n\t\t\t\tthis.isOpen = true;\n\t\t\t} else {\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t}\n\t}\n\t\n\tasync _createBPlusTree(filePath) {\n\t\t// Parse path to get directory and filename\n\t\tconst pathParts = filePath.split('/').filter(Boolean);\n\t\tconst filename = pathParts.pop();\n\t\t\n\t\tif (!filename) {\n\t\t\tthrow new Error(`Invalid storage path: ${filePath}`);\n\t\t}\n\t\t\n\t\t// Navigate to directory\n\t\tlet dirHandle = await globalThis.navigator.storage.getDirectory();\n\t\tfor (const part of pathParts) {\n\t\t\tdirHandle = await dirHandle.getDirectoryHandle(part, { create: true });\n\t\t}\n\t\t\n\t\t// Get file handle and create sync access handle using native OPFS\n\t\tconst fileHandle = await dirHandle.getFileHandle(filename, { create: true });\n\t\tconst syncHandle = await fileHandle.createSyncAccessHandle();\n\t\t\n\t\t// Store sync handle for cleanup\n\t\tthis.syncHandles.push(syncHandle);\n\t\t\n\t\t// Create BPlusTree with sync handle\n\t\treturn new BPlusTree(syncHandle, 16);\n\t}\n\t\n\tasync _closeSyncHandles() {\n\t\tfor (const handle of this.syncHandles) {\n\t\t\ttry {\n\t\t\t\tawait handle.close();\n\t\t\t} catch (e) {\n\t\t\t\t// Ignore errors\n\t\t\t}\n\t\t}\n\t\tthis.syncHandles = [];\n\t}\n\t\n\t_getActiveBasePath() {\n\t\treturn this.versionedBasePath || this.storageBasePath;\n\t}\n\n\tasync _deleteIndexFiles(basePath = this._getActiveBasePath()) {\n\t\t// TextIndex creates multiple files: -terms.bj, -documents.bj, -lengths.bj\n\t\tfor (const suffix of TEXT_INDEX_SUFFIXES) {\n\t\t\tawait this._deleteFile(basePath + suffix);\n\t\t}\n\t}\n\n\tasync _deleteFile(filePath) {\n\t\tif (!filePath) return;\n\t\ttry {\n\t\t\tconst pathParts = filePath.split('/').filter(Boolean);\n\t\t\tconst filename = pathParts.pop();\n\t\t\t\n\t\t\tif (!filename) {\n\t\t\t\tthrow new Error(`Invalid storage path: ${filePath}`);\n\t\t\t}\n\t\t\t\n\t\t\tlet dir = await globalThis.navigator.storage.getDirectory();\n\t\t\tfor (const part of pathParts) {\n\t\t\t\tdir = await dir.getDirectoryHandle(part, { create: false });\n\t\t\t}\n\t\t\tawait dir.removeEntry(filename);\n\t\t} catch (error) {\n\t\t\t// Ignore errors - file might not exist\n\t\t}\n\t}\n\n\tasync _ensureDirectoryForFile(filePath) {\n\t\tif (!filePath) return;\n\t\tconst pathParts = filePath.split('/').filter(Boolean);\n\t\t// Remove filename, keep only directory parts\n\t\tpathParts.pop();\n\t\t\n\t\tif (pathParts.length === 0) return;\n\t\t\n\t\ttry {\n\t\t\tlet dir = await globalThis.navigator.storage.getDirectory();\n\t\t\tfor (const part of pathParts) {\n\t\t\t\tdir = await dir.getDirectoryHandle(part, { create: true });\n\t\t\t}\n\t\t} catch (error) {\n\t\t\t// Ignore EEXIST - directory already exists\n\t\t\tif (error.code !== 'EEXIST') {\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Close the index files\n\t */\n\tasync close() {\n\t\tif (this.isOpen) {\n\t\t\tawait this._maybeCompact();\n\t\t\tif (this.textIndex?.isOpen) {\n\t\t\t\ttry {\n\t\t\t\t\tawait this.textIndex.close();\n\t\t\t\t} catch (error) {\n\t\t\t\t\t// Ignore errors from already-closed files\n\t\t\t\t\tif (!error.message || !error.message.includes('File is not open')) {\n\t\t\t\t\t\tthrow error;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis.isOpen = false;\n\t\t}\n\t\tif (this._releaseStorage) {\n\t\t\tawait this._releaseStorage();\n\t\t\tthis._releaseStorage = null;\n\t\t}\n\t}\n\n\tasync _maybeCompact() {\n\t\tif (!this.textIndex?.index?.file || !this.textIndex?.documentTerms?.file || !this.textIndex?.documentLengths?.file) {\n\t\t\treturn false;\n\t\t}\n\t\tconst currentVersion = await getCurrentVersion(this.storageBasePath);\n\t\tif (currentVersion !== this.storageVersion) return false;\n\n\t\tconst totalSize = this.textIndex.index.file.getFileSize()\n\t\t\t+ this.textIndex.documentTerms.file.getFileSize()\n\t\t\t+ this.textIndex.documentLengths.file.getFileSize();\n\t\tif (!totalSize || totalSize < DEFAULT_COMPACTION_MIN_BYTES) return false;\n\n\t\tconst nextVersion = currentVersion + 1;\n\t\tconst compactBase = buildVersionedPath(this.storageBasePath, nextVersion);\n\t\tconst indexHandle = await createSyncAccessHandle(`${compactBase}-terms.bj`, { reset: true });\n\t\tconst docTermsHandle = await createSyncAccessHandle(`${compactBase}-documents.bj`, { reset: true });\n\t\tconst lengthsHandle = await createSyncAccessHandle(`${compactBase}-lengths.bj`, { reset: true });\n\t\tconst indexTree = new BPlusTree(indexHandle, 16);\n\t\tconst docTermsTree = new BPlusTree(docTermsHandle, 16);\n\t\tconst lengthsTree = new BPlusTree(lengthsHandle, 16);\n\n\t\tawait this.textIndex.compact({\n\t\t\tindex: indexTree,\n\t\t\tdocumentTerms: docTermsTree,\n\t\t\tdocumentLengths: lengthsTree\n\t\t});\n\t\t// Note: textIndex.compact() closes the underlying trees and leaves the index in a closed state.\n\t\tawait promoteVersion(this.storageBasePath, nextVersion, currentVersion, { suffixes: TEXT_INDEX_SUFFIXES });\n\t\tawait this._closeSyncHandles();\n\t\treturn true;\n\t}\n\n\t/**\n\t * Extract text content from a document for the indexed fields\n\t * @param {Object} doc - The document\n\t * @returns {string} Combined text from all indexed fields\n\t */\n\t_extractText(doc) {\n\t\tconst textParts = [];\n\t\tfor (const field of this.indexedFields) {\n\t\t\tconst value = getProp(doc, field);\n\t\t\tif (value !== undefined && value !== null) {\n\t\t\t\ttextParts.push(String(value));\n\t\t\t}\n\t\t}\n\t\treturn textParts.join(' ');\n\t}\n\n\t/**\n\t * Add a document to the text index\n\t * @param {Object} doc - The document to index\n\t */\n\tasync add(doc) {\n\t\tif (!doc._id) {\n\t\t\tthrow new Error('Document must have an _id field');\n\t\t}\n\t\tconst text = this._extractText(doc);\n\t\tif (text) {\n\t\t\tawait this.textIndex.add(String(doc._id), text);\n\t\t}\n\t}\n\n\t/**\n\t * Remove a document from the text index\n\t * @param {Object} doc - The document to remove\n\t */\n\tasync remove(doc) {\n\t\tif (!doc._id) {\n\t\t\treturn;\n\t\t}\n\t\tawait this.textIndex.remove(String(doc._id));\n\t}\n\n\t/**\n\t * Query the text index\n\t * @param {*} query - The query object\n\t * @returns {Array|null} Array of document IDs or null if query is not a text search\n\t */\n\tquery(query) {\n\t\t// This method is used for query planning\n\t\t// Text queries are handled separately in queryMatcher\n\t\treturn null;\n\t}\n\n\t/**\n\t * Search the text index\n\t * @param {string} searchText - The text to search for\n\t * @param {Object} options - Search options\n\t * @returns {Promise<Array>} Array of document IDs\n\t */\n\tasync search(searchText, options = {}) {\n\t\tconst results = await this.textIndex.query(searchText, { scored: false, ...options });\n\t\treturn results;\n\t}\n\n\t/**\n\t * Clear all data from the index\n\t */\n // TODO: Recreate the index empty or delete\n\tasync clear() {\n\t\t// Recreate the index by closing and reopening\n\t\tif (this.isOpen) {\n\t\t\tawait this.close();\n\t\t}\n\n\t\tconst currentVersion = await getCurrentVersion(this.storageBasePath);\n\t\tconst basePath = buildVersionedPath(this.storageBasePath, currentVersion);\n\t\t\n\t\t// Delete old files\n\t\tawait this._deleteIndexFiles(basePath);\n\t\t\n\t\t// Reopen (will create new files)\n\t\tawait this.open();\n\t}\n\n\t/**\n\t * Get index specification\n\t */\n\tgetSpec() {\n\t\treturn {\n\t\t\tname: this.name,\n\t\t\tkey: this.keys,\n\t\t\ttextIndexVersion: 3,\n\t\t\tweights: this._getWeights()\n\t\t};\n\t}\n\n\t/**\n\t * Get field weights (all default to 1 for now)\n\t */\n\t_getWeights() {\n\t\tconst weights = {};\n\t\tfor (const field of this.indexedFields) {\n\t\t\tweights[field] = 1;\n\t\t}\n\t\treturn weights;\n\t}\n\n}\n","/**\n * On-Disk R-tree implementation using BinJsonFile\n * \n * This implementation stores all data in an append-only binjson file:\n * - Nodes are stored as binjson records\n * - Node references use Pointer objects for file offsets\n * - Updates append new versions rather than modifying in place\n * - An in-memory index tracks the latest offset for each node ID\n * \n * File format:\n * - Record 0: Metadata (version, maxEntries, size, rootPointer, nextId)\n * - Records 1+: Node data (id, isLeaf, children, bbox)\n * - For internal nodes: children are Pointer objects to child nodes\n * - For leaf nodes: children are data entries with {bbox, lat, lng, data}\n */\n\nimport { BinJsonFile, Pointer, ObjectId, getFileHandle, deleteFile } from './binjson.js';\n\n/**\n * Calculate distance between two points using Haversine formula\n */\nexport function haversineDistance(lat1, lng1, lat2, lng2) {\n\tconst R = 6371; // Earth's radius in kilometers\n\tconst dLat = (lat2 - lat1) * Math.PI / 180;\n\tconst dLng = (lng2 - lng1) * Math.PI / 180;\n\tconst a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +\n\t\tMath.cos(lat1 * Math.PI / 180) * Math.cos(lat2 * Math.PI / 180) *\n\t\tMath.sin(dLng / 2) * Math.sin(dLng / 2);\n\tconst c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));\n\treturn R * c;\n}\n\n/**\n * Convert radius query to bounding box\n */\nfunction radiusToBoundingBox(lat, lng, radiusKm) {\n\tconst latDelta = radiusKm / 111;\n\tconst lngDelta = radiusKm / (111 * Math.cos(lat * Math.PI / 180));\n\t\n\treturn {\n\t\tminLat: lat - latDelta,\n\t\tmaxLat: lat + latDelta,\n\t\tminLng: lng - lngDelta,\n\t\tmaxLng: lng + lngDelta\n\t};\n}\n\n/**\n * Check if two bounding boxes intersect\n */\nfunction intersects(bbox1, bbox2) {\n\treturn !(bbox1.maxLat < bbox2.minLat ||\n\t\tbbox1.minLat > bbox2.maxLat ||\n\t\tbbox1.maxLng < bbox2.minLng ||\n\t\tbbox1.minLng > bbox2.maxLng);\n}\n\n/**\n * Calculate the area of a bounding box\n */\nfunction area(bbox) {\n\treturn (bbox.maxLat - bbox.minLat) * (bbox.maxLng - bbox.minLng);\n}\n\n/**\n * Calculate the bounding box that contains both input boxes\n */\nfunction union(bbox1, bbox2) {\n\treturn {\n\t\tminLat: Math.min(bbox1.minLat, bbox2.minLat),\n\t\tmaxLat: Math.max(bbox1.maxLat, bbox2.maxLat),\n\t\tminLng: Math.min(bbox1.minLng, bbox2.minLng),\n\t\tmaxLng: Math.max(bbox1.maxLng, bbox2.maxLng)\n\t};\n}\n\n/**\n * Calculate the enlargement needed to include bbox2 in bbox1\n */\nfunction enlargement(bbox1, bbox2) {\n\tconst unionBox = union(bbox1, bbox2);\n\treturn area(unionBox) - area(bbox1);\n}\n\n/**\n * R-tree node stored on disk\n */\nclass RTreeNode {\n\tconstructor(rtree, nodeData) {\n\t\tthis.rtree = rtree;\n\t\tthis.id = nodeData.id;\n\t\tthis.isLeaf = nodeData.isLeaf;\n\t\tthis.children = nodeData.children || [];\n\t\tthis.bbox = nodeData.bbox;\n\t}\n\n\t/**\n\t * Update the bounding box to contain all children\n\t */\n\tupdateBBox() {\n\t\tif (this.children.length === 0) {\n\t\t\tthis.bbox = null;\n\t\t\treturn;\n\t\t}\n\n\t\tlet minLat = Infinity, maxLat = -Infinity;\n\t\tlet minLng = Infinity, maxLng = -Infinity;\n\n\t\tfor (const child of this.children) {\n\t\t\tlet bbox;\n\t\t\tif (this.isLeaf) {\n\t\t\t\t// Leaf node: children are data entries\n\t\t\t\tbbox = child.bbox;\n\t\t\t} else {\n\t\t\t\t// Internal node: children are Pointers - need to load child nodes\n\t\t\t\tconst childNode = this.rtree._loadNode(child);\n\t\t\t\tbbox = childNode.bbox;\n\t\t\t}\n\n\t\t\tif (bbox) {\n\t\t\t\tminLat = Math.min(minLat, bbox.minLat);\n\t\t\t\tmaxLat = Math.max(maxLat, bbox.maxLat);\n\t\t\t\tminLng = Math.min(minLng, bbox.minLng);\n\t\t\t\tmaxLng = Math.max(maxLng, bbox.maxLng);\n\t\t\t}\n\t\t}\n\n\t\tthis.bbox = { minLat, maxLat, minLng, maxLng };\n\t\t\n\t\t// Save updated node to disk\n\t\tthis.rtree._saveNode(this);\n\t}\n\n\t/**\n\t * Convert node to plain object for serialization\n\t */\n\ttoJSON() {\n\t\treturn {\n\t\t\tid: this.id,\n\t\t\tisLeaf: this.isLeaf,\n\t\t\tchildren: this.children,\n\t\t\tbbox: this.bbox\n\t\t};\n\t}\n}\n\n/**\n * On-disk R-tree implementation\n */\nexport class RTree {\n\tconstructor(syncHandle, maxEntries = 9) {\n\t\tthis.file = new BinJsonFile(syncHandle);\n\t\tthis.maxEntries = maxEntries;\n\t\tthis.minEntries = Math.max(2, Math.ceil(maxEntries / 2));\n\t\t\n\t\t// Metadata\n\t\tthis.rootPointer = null;\n\t\tthis.nextId = 1;\n\t\tthis._size = 0;\n\t\t\n\t\tthis.isOpen = false;\n\t}\n\n\t/**\n\t * Open the R-tree (load or initialize metadata)\n\t */\n\tasync open() {\n\t\tif (this.isOpen) {\n\t\t\tthrow new Error('R-tree is already open');\n\t\t}\n\n\t\tconst fileSize = this.file.getFileSize();\n\t\tconst exists = fileSize > 0;\n\n\t\tif (exists) {\n\t\t\t// Load existing tree\n\t\t\tthis._loadFromFile();\n\t\t} else {\n\t\t\t// Create new tree\n\t\t\tthis._initializeNewTree();\n\t\t}\n\t\t\n\t\tthis.isOpen = true;\n\t}\n\n\t/**\n\t * Close the R-tree\n\t */\n\tasync close() {\n\t\tif (this.isOpen) {\n\t\t\tthis._writeMetadata();\n\t\t\tif (this.file && this.file.syncAccessHandle) {\n\t\t\t\tthis.file.flush();\n\t\t\t\tawait this.file.syncAccessHandle.close();\n\t\t\t}\n\t\t\tthis.isOpen = false;\n\t\t}\n\t}\n\n\t/**\n\t * Initialize a new empty tree\n\t */\n\t_initializeNewTree() {\n\t\t// Create root node\n\t\tconst rootNode = new RTreeNode(this, {\n\t\t\tid: 0,\n\t\t\tisLeaf: true,\n\t\t\tchildren: [],\n\t\t\tbbox: null\n\t\t});\n\t\t\n\t\tthis.nextId = 1;\n\t\tthis._size = 0;\n\t\t\n\t\t// Save root node\n\t\tthis.rootPointer = this._saveNode(rootNode);\n\t\t\n\t\t// Write metadata as first record\n\t\tthis._writeMetadata();\n\t}\n\n\t/**\n\t * Write metadata record to file\n\t */\n\t_writeMetadata() {\n\t\tconst metadata = {\n\t\t\tversion: 1,\n\t\t\tmaxEntries: this.maxEntries,\n\t\t\tminEntries: this.minEntries,\n\t\t\tsize: this._size,\n\t\t\trootPointer: this.rootPointer,\n\t\t\tnextId: this.nextId\n\t\t};\n\t\t\n\t\t// Append metadata to file (don't use write which truncates)\n\t\tthis.file.append(metadata);\n\t}\n\n\t/**\n\t * Load tree from existing file\n\t */\n\t_loadFromFile() {\n\t\t// Calculate fixed metadata size:\n\t\t// Metadata object has 6 fields: version, maxEntries, minEntries, size, rootPointer, nextId\n\t\t// All are INT type encoded as 8-byte ints (1 type byte + 8 bytes payload)\n\t\t// Object encoding: TYPE (1) + SIZE (4) + COUNT (4) + key-value pairs\n\t\t// Total size with 8-byte ints: 135 bytes\n\t\tconst METADATA_SIZE = 135;\n\t\t\n\t\tconst fileSize = this.file.getFileSize();\n\t\tif (fileSize < METADATA_SIZE) {\n\t\t\tthrow new Error('Invalid R-tree file format: file too small for metadata');\n\t\t}\n\t\t\n\t\t// Read metadata from the end of the file\n\t\tconst metadataOffset = fileSize - METADATA_SIZE;\n\t\tconst metadata = this.file.read(metadataOffset);\n\t\t\n\t\tthis.maxEntries = metadata.maxEntries;\n\t\tthis.minEntries = metadata.minEntries;\n\t\tthis._size = metadata.size;\n\t\tthis.rootPointer = metadata.rootPointer;\n\t\tthis.nextId = metadata.nextId;\n\t}\n\n\t/**\n\t * Save a node to disk and return its Pointer\n\t */\n\t_saveNode(node) {\n\t\tconst nodeData = node.toJSON();\n\t\t\n\t\t// Get current file size (this is where the node will be stored)\n\t\tconst offset = this.file.getFileSize();\n\t\t\n\t\t// Append node to file\n\t\tthis.file.append(nodeData);\n\t\t\n\t\t// Return pointer to the saved node\n\t\treturn new Pointer(offset);\n\t}\n\n\t/**\n\t * Load a node from disk by Pointer\n\t */\n\t_loadNode(pointer) {\n\t\tif (!(pointer instanceof Pointer)) {\n\t\t\tthrow new Error('Expected Pointer object');\n\t\t}\n\t\t\n\t\tconst offset = pointer.valueOf();\n\t\t\n\t\t// Read the node from file at this offset\n\t\tconst nodeData = this.file.read(offset);\n\t\t\n\t\treturn new RTreeNode(this, nodeData);\n\t}\n\n\t/**\n\t * Load the root node\n\t */\n\t_loadRoot() {\n\t\treturn this._loadNode(this.rootPointer);\n\t}\n\n\t/**\n\t * Insert a point into the R-tree with an ObjectId\n\t */\n\tinsert(lat, lng, objectId) {\n\t\tif (!this.isOpen) {\n\t\t\tthrow new Error('R-tree file must be opened before use');\n\t\t}\n\n if (!(objectId instanceof ObjectId)) {\n throw new Error('objectId must be an instance of ObjectId to insert into rtree');\n }\n\n\t\tconst bbox = {\n\t\t\tminLat: lat,\n\t\t\tmaxLat: lat,\n\t\t\tminLng: lng,\n\t\t\tmaxLng: lng\n\t\t};\n\n\t\tconst entry = { bbox, lat, lng, objectId };\n\t\t\n\t\tconst root = this._loadRoot();\n\t\tconst result = this._insert(entry, root, 1);\n\t\t\n\t\tif (result.split) {\n\t\t\t// Root was split, create new root\n\t\t\tconst newRoot = new RTreeNode(this, {\n\t\t\t\tid: this.nextId++,\n\t\t\t\tisLeaf: false,\n\t\t\t\tchildren: result.pointers,\n\t\t\t\tbbox: null\n\t\t\t});\n\t\t\t\n\t\t\tnewRoot.updateBBox();\n\t\t\tthis.rootPointer = this._saveNode(newRoot);\n\t\t} else {\n\t\t\t// Root was updated but not split, update the pointer\n\t\t\tthis.rootPointer = result.pointer;\n\t\t}\n\t\t\n\t\tthis._size++;\n\t\tthis._writeMetadata();\n\t}\n\n\t/**\n\t * Internal insert method - returns splitPointers if split occurred, else returns updated node pointer\n\t */\n\t_insert(entry, node, level) {\n\t\tif (node.isLeaf) {\n\t\t\tnode.children.push(entry);\n\t\t\tnode.updateBBox();\n\n\t\t\tif (node.children.length > this.maxEntries) {\n\t\t\t\tconst [pointer1, pointer2] = this._split(node);\n\t\t\t\treturn { split: true, pointers: [pointer1, pointer2] };\n\t\t\t}\n\t\t\t\n\t\t\t// Save updated leaf node\n\t\t\tconst pointer = this._saveNode(node);\n\t\t\treturn { split: false, pointer };\n\t\t} else {\n\t\t\t// Choose subtree\n\t\t\tconst targetPointer = this._chooseSubtree(entry.bbox, node);\n\t\t\tconst targetNode = this._loadNode(targetPointer);\n\t\t\tconst result = this._insert(entry, targetNode, level + 1);\n\n\t\t\tif (result.split) {\n\t\t\t\t// Child was split, find and replace it\n\t\t\t\tlet childIndex = -1;\n\t\t\t\tfor (let i = 0; i < node.children.length; i++) {\n\t\t\t\t\tif (node.children[i].valueOf() === targetPointer.valueOf()) {\n\t\t\t\t\t\tchildIndex = i;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif (childIndex !== -1) {\n\t\t\t\t\t// Replace the old child with both new children\n\t\t\t\t\tnode.children[childIndex] = result.pointers[0];\n\t\t\t\t\tnode.children.push(result.pointers[1]);\n\t\t\t\t} else {\n\t\t\t\t\t// Shouldn't happen, but add both if we can't find\n\t\t\t\t\tnode.children.push(result.pointers[0]);\n\t\t\t\t\tnode.children.push(result.pointers[1]);\n\t\t\t\t}\n\t\t\t\tnode.updateBBox();\n\n\t\t\t\tif (node.children.length > this.maxEntries) {\n\t\t\t\t\tconst [pointer1, pointer2] = this._split(node);\n\t\t\t\t\treturn { split: true, pointers: [pointer1, pointer2] };\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// Child was not split, but may have been updated with new pointer\n\t\t\t\t// Update the child pointer in this node's children\n\t\t\t\tlet childIndex = -1;\n\t\t\t\tfor (let i = 0; i < node.children.length; i++) {\n\t\t\t\t\tif (node.children[i].valueOf() === targetPointer.valueOf()) {\n\t\t\t\t\t\tchildIndex = i;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif (childIndex !== -1) {\n\t\t\t\t\t// Update child pointer to point to the new version\n\t\t\t\t\tnode.children[childIndex] = result.pointer;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t// Update this node's bbox (use the current children pointers)\n\t\t\t\tnode.updateBBox();\n\t\t\t}\n\t\t\t\n\t\t// Save updated internal node\n\t\tconst pointer = this._saveNode(node);\n\t\treturn { split: false, pointer };\n }\n\t}\n\n\t/**\n\t * Choose the best subtree to insert an entry\n\t */\n\t_chooseSubtree(bbox, node) {\n\t\tlet minEnlargement = Infinity;\n\t\tlet minArea = Infinity;\n\t\tlet targetPointer = null;\n\n for (const childPointer of node.children) {\n\t\t\t// Debug: check if we have a Pointer\n\t\t\tif (!(childPointer instanceof Pointer)) {\n\t\t\t\tthrow new Error(`Expected Pointer in _chooseSubtree, got: ${typeof childPointer}`);\n\t\t\t}\n\t\t\t\n\t\t\tconst childNode = this._loadNode(childPointer);\n\t\t\tconst enl = enlargement(childNode.bbox, bbox);\n\t\t\tconst ar = area(childNode.bbox);\n\n\t\t\tif (enl < minEnlargement || (enl === minEnlargement && ar < minArea)) {\n\t\t\t\tminEnlargement = enl;\n\t\t\t\tminArea = ar;\n\t\t\t\ttargetPointer = childPointer;\n\t\t\t}\n\t\t}\n\n\t\treturn targetPointer;\n\t}\n\n\t/**\n\t * Split an overflowing node\n\t */\n\t_split(node) {\n\t\tconst children = node.children;\n\t\tconst isLeaf = node.isLeaf;\n\n\t\t// Find two seeds (most distant entries)\n\t\tlet maxDist = -Infinity;\n\t\tlet seed1Idx = 0, seed2Idx = 1;\n\n\t\tfor (let i = 0; i < children.length; i++) {\n\t\t\tfor (let j = i + 1; j < children.length; j++) {\n\t\t\t\tlet bbox1, bbox2;\n\t\t\t\t\n\t\t\t\tif (isLeaf) {\n\t\t\t\t\tbbox1 = children[i].bbox;\n\t\t\t\t\tbbox2 = children[j].bbox;\n\t\t\t\t} else {\n\t\t\t\t\tconst node1 = this._loadNode(children[i]);\n\t\t\t\t\tconst node2 = this._loadNode(children[j]);\n\t\t\t\t\tbbox1 = node1.bbox;\n\t\t\t\t\tbbox2 = node2.bbox;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tconst dist = area(union(bbox1, bbox2));\n\t\t\t\tif (dist > maxDist) {\n\t\t\t\t\tmaxDist = dist;\n\t\t\t\t\tseed1Idx = i;\n\t\t\t\t\tseed2Idx = j;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Create two new nodes\n\t\tconst node1 = new RTreeNode(this, {\n\t\t\tid: this.nextId++,\n\t\t\tisLeaf: isLeaf,\n\t\t\tchildren: [children[seed1Idx]],\n\t\t\tbbox: null\n\t\t});\n\n\t\tconst node2 = new RTreeNode(this, {\n\t\t\tid: this.nextId++,\n\t\t\tisLeaf: isLeaf,\n\t\t\tchildren: [children[seed2Idx]],\n\t\t\tbbox: null\n\t\t});\n\n\t\t// Distribute remaining entries\n\t\tfor (let i = 0; i < children.length; i++) {\n\t\t\tif (i === seed1Idx || i === seed2Idx) continue;\n\n\t\t\tconst child = children[i];\n\t\t\t\n\t\t\tlet bbox;\n\t\t\tif (isLeaf) {\n\t\t\t\tbbox = child.bbox;\n\t\t\t} else {\n\t\t\t\tconst childNode = this._loadNode(child);\n\t\t\t\tbbox = childNode.bbox;\n\t\t\t}\n\t\t\t\n\t\t\tnode1.updateBBox();\n\t\t\tnode2.updateBBox();\n\t\t\t\n\t\t\tconst enl1 = node1.bbox ? enlargement(node1.bbox, bbox) : 0;\n\t\t\tconst enl2 = node2.bbox ? enlargement(node2.bbox, bbox) : 0;\n\n\t\t\tif (enl1 < enl2) {\n\t\t\t\tnode1.children.push(child);\n\t\t\t} else if (enl2 < enl1) {\n\t\t\t\tnode2.children.push(child);\n\t\t\t} else {\n\t\t\t\t// Equal enlargement, choose one with fewer children\n\t\t\t\tif (node1.children.length <= node2.children.length) {\n\t\t\t\t\tnode1.children.push(child);\n\t\t\t\t} else {\n\t\t\t\t\tnode2.children.push(child);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tnode1.updateBBox();\n\t\tnode2.updateBBox();\n\n\t\t// Save both nodes (don't reuse the original node)\n\t\tconst pointer1 = this._saveNode(node1);\n\t\tconst pointer2 = this._saveNode(node2);\n\n\t\t// Return both pointers\n\t\treturn [pointer1, pointer2];\n\t}\n\n\t/**\n\t * Search for points within a bounding box, returning entries with coords\n\t */\n\tsearchBBox(bbox) {\n\t\tif (!this.isOpen) {\n\t\t\tthrow new Error('R-tree file must be opened before use');\n\t\t}\n\n\t\tconst results = [];\n\t\tconst root = this._loadRoot();\n\t\tthis._searchBBox(bbox, root, results);\n\t\treturn results;\n\t}\n\n\t/**\n\t * Internal bounding box search\n\t */\n\t_searchBBox(bbox, node, results) {\n\t\tif (!node.bbox || !intersects(bbox, node.bbox)) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (node.isLeaf) {\n\t\t\tfor (const entry of node.children) {\n\t\t\t\tif (intersects(bbox, entry.bbox)) {\n\t\t\t\t\tresults.push({\n\t\t\t\t\t\tobjectId: entry.objectId,\n\t\t\t\t\t\tlat: entry.lat,\n\t\t\t\t\t\tlng: entry.lng\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tfor (const childPointer of node.children) {\n\t\t\t\tconst childNode = this._loadNode(childPointer);\n\t\t\t\tthis._searchBBox(bbox, childNode, results);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Search for points within a radius of a location, returning ObjectIds with distances\n\t */\n\tsearchRadius(lat, lng, radiusKm) {\n\t\tconst bbox = radiusToBoundingBox(lat, lng, radiusKm);\n\t\tconst root = this._loadRoot();\n\t\tconst entries = [];\n\t\tthis._searchBBoxEntries(bbox, root, entries);\n\n\t\tconst results = [];\n\t\tfor (const entry of entries) {\n\t\t\tconst dist = haversineDistance(lat, lng, entry.lat, entry.lng);\n\t\t\tif (dist <= radiusKm) {\n\t\t\t\tresults.push({\n\t\t\t\t\tobjectId: entry.objectId,\n\t\t\t\t\tlat: entry.lat,\n\t\t\t\t\tlng: entry.lng,\n\t\t\t\t\tdistance: dist\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\treturn results;\n\t}\n\n\t/**\n\t * Internal bounding box search that returns full entries (used by radius search)\n\t */\n\t_searchBBoxEntries(bbox, node, results) {\n\t\tif (!node.bbox || !intersects(bbox, node.bbox)) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (node.isLeaf) {\n\t\t\tfor (const entry of node.children) {\n\t\t\t\tif (intersects(bbox, entry.bbox)) {\n\t\t\t\t\tresults.push(entry);\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tfor (const childPointer of node.children) {\n\t\t\t\tconst childNode = this._loadNode(childPointer);\n\t\t\t\tthis._searchBBoxEntries(bbox, childNode, results);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Remove an entry from the R-tree by ObjectId\n\t */\n\tremove(objectId) {\n\t\tif (!this.isOpen) {\n\t\t\tthrow new Error('R-tree file must be opened before use');\n\t\t}\n\n if (!(objectId instanceof ObjectId)) {\n throw new Error('objectId must be an instance of ObjectId to remove from rtree');\n }\n\n\t\tconst root = this._loadRoot();\n\t\tconst result = this._remove(objectId, root);\n\n\t\tif (!result.found) {\n\t\t\treturn false; // Entry not found\n\t\t}\n\n\t\tif (result.underflow && result.children) {\n\t\t\t// Root underflowed and has children\n\t\t\tif (result.children.length === 0) {\n\t\t\t\t// Tree is now empty, create new empty root\n\t\t\t\tconst newRoot = new RTreeNode(this, {\n\t\t\t\t\tid: this.nextId++,\n\t\t\t\t\tisLeaf: true,\n\t\t\t\t\tchildren: [],\n\t\t\t\t\tbbox: null\n\t\t\t\t});\n\t\t\t\tthis.rootPointer = this._saveNode(newRoot);\n\t\t\t} else if (result.children.length === 1 && !result.isLeaf) {\n\t\t\t\t// Root has only one child and is internal node - make child the new root\n\t\t\t\tthis.rootPointer = result.children[0];\n\t\t\t} else {\n\t\t\t\t// Root underflowed but still has multiple children, save it\n\t\t\t\tconst newRoot = new RTreeNode(this, {\n\t\t\t\t\tid: root.id,\n\t\t\t\t\tisLeaf: result.isLeaf,\n\t\t\t\t\tchildren: result.children,\n\t\t\t\t\tbbox: null\n\t\t\t\t});\n\t\t\t\tnewRoot.updateBBox();\n\t\t\t\tthis.rootPointer = this._saveNode(newRoot);\n\t\t\t}\n\t\t} else if (result.pointer) {\n\t\t\t// Root was updated\n\t\t\tthis.rootPointer = result.pointer;\n\t\t}\n\n\t\tthis._size--;\n\t\tthis._writeMetadata();\n\t\treturn true;\n\t}\n\n\t/**\n\t * Internal remove method\n\t * Returns: { found: boolean, underflow: boolean, pointer: Pointer, children: Array, isLeaf: boolean }\n\t */\n\t_remove(objectId, node) {\n\t\tif (node.isLeaf) {\n\t\t\t// Find and remove the entry\n\t\t\tconst initialLength = node.children.length;\n\t\t\tnode.children = node.children.filter(entry => \n\t\t\t\t!entry.objectId.equals(objectId)\n\t\t\t);\n\n\t\t\tif (node.children.length === initialLength) {\n\t\t\t\t// Entry not found\n\t\t\t\treturn { found: false };\n\t\t\t}\n\n\t\t\tnode.updateBBox();\n\t\t\tconst pointer = this._saveNode(node);\n\n\t\t\t// Check for underflow\n\t\t\tconst underflow = node.children.length < this.minEntries && node.children.length > 0;\n\t\t\t\n\t\t\treturn {\n\t\t\t\tfound: true,\n\t\t\t\tunderflow,\n\t\t\t\tpointer,\n\t\t\t\tchildren: node.children,\n\t\t\t\tisLeaf: true\n\t\t\t};\n\t\t} else {\n\t\t\t// Internal node - search children\n\t\t\tlet found = false;\n\t\t\tlet updatedChildren = [...node.children];\n\n\t\t\tfor (let i = 0; i < updatedChildren.length; i++) {\n\t\t\t\tconst childPointer = updatedChildren[i];\n\t\t\t\tconst childNode = this._loadNode(childPointer);\n\n\t\t\t\t// Check if the child's bbox could contain the entry\n\t\t\t\t// For internal nodes, we need to check all children since we don't store exact coordinates\n\t\t\t\tconst result = this._remove(objectId, childNode);\n\n\t\t\t\tif (result.found) {\n\t\t\t\t\tfound = true;\n\n\t\t\t\t\tif (result.underflow) {\n\t\t\t\t\t\t// Child underflowed, try to handle it\n\t\t\t\t\t\tconst handled = this._handleUnderflow(node, i, childNode, result);\n\t\t\t\t\t\t\n\t\t\t\t\t\tif (handled.merged) {\n\t\t\t\t\t\t\t// Node was merged or redistributed, update children array\n\t\t\t\t\t\t\tupdatedChildren = handled.children;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// Just update the pointer\n\t\t\t\t\t\t\tupdatedChildren[i] = result.pointer;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Update child pointer\n\t\t\t\t\t\tupdatedChildren[i] = result.pointer;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Update this node\n\t\t\t\t\tconst updatedNode = new RTreeNode(this, {\n\t\t\t\t\t\tid: node.id,\n\t\t\t\t\t\tisLeaf: false,\n\t\t\t\t\t\tchildren: updatedChildren,\n\t\t\t\t\t\tbbox: null\n\t\t\t\t\t});\n\t\t\t\t\tupdatedNode.updateBBox();\n\t\t\t\t\tconst pointer = this._saveNode(updatedNode);\n\n\t\t\t\t\t// Check if this node now underflows\n\t\t\t\t\tconst underflow = updatedChildren.length < this.minEntries && updatedChildren.length > 0;\n\n\t\t\t\t\treturn {\n\t\t\t\t\t\tfound: true,\n\t\t\t\t\t\tunderflow,\n\t\t\t\t\t\tpointer,\n\t\t\t\t\t\tchildren: updatedChildren,\n\t\t\t\t\t\tisLeaf: false\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Entry not found in any child\n\t\t\treturn { found: false };\n\t\t}\n\t}\n\n\t/**\n\t * Handle underflow in a child node by merging or redistributing\n\t */\n\t_handleUnderflow(parentNode, childIndex, childNode, childResult) {\n\t\tconst siblings = [];\n\n\t\t// Find siblings (nodes before and after)\n\t\tif (childIndex > 0) {\n\t\t\tconst prevPointer = parentNode.children[childIndex - 1];\n\t\t\tconst prevNode = this._loadNode(prevPointer);\n\t\t\tsiblings.push({ index: childIndex - 1, node: prevNode, pointer: prevPointer });\n\t\t}\n\t\tif (childIndex < parentNode.children.length - 1) {\n\t\t\tconst nextPointer = parentNode.children[childIndex + 1];\n\t\t\tconst nextNode = this._loadNode(nextPointer);\n\t\t\tsiblings.push({ index: childIndex + 1, node: nextNode, pointer: nextPointer });\n\t\t}\n\n\t\t// Try to borrow from a sibling\n\t\tfor (const sibling of siblings) {\n\t\t\tif (sibling.node.children.length > this.minEntries) {\n\t\t\t\t// Sibling has extra entries, redistribute\n\t\t\t\tconst allChildren = [\n\t\t\t\t\t...childResult.children,\n\t\t\t\t\t...sibling.node.children\n\t\t\t\t];\n\n\t\t\t\tconst mid = Math.ceil(allChildren.length / 2);\n\t\t\t\tconst newChild1Children = allChildren.slice(0, mid);\n\t\t\t\tconst newChild2Children = allChildren.slice(mid);\n\n\t\t\t\tconst newChild1 = new RTreeNode(this, {\n\t\t\t\t\tid: childNode.id,\n\t\t\t\t\tisLeaf: childResult.isLeaf,\n\t\t\t\t\tchildren: newChild1Children,\n\t\t\t\t\tbbox: null\n\t\t\t\t});\n\t\t\t\tnewChild1.updateBBox();\n\n\t\t\t\tconst newChild2 = new RTreeNode(this, {\n\t\t\t\t\tid: sibling.node.id,\n\t\t\t\t\tisLeaf: sibling.node.isLeaf,\n\t\t\t\t\tchildren: newChild2Children,\n\t\t\t\t\tbbox: null\n\t\t\t\t});\n\t\t\t\tnewChild2.updateBBox();\n\n\t\t\t\tconst pointer1 = this._saveNode(newChild1);\n\t\t\t\tconst pointer2 = this._saveNode(newChild2);\n\n\t\t\t\t// Update parent's children\n\t\t\t\tconst newChildren = [...parentNode.children];\n\t\t\t\tconst minIndex = Math.min(childIndex, sibling.index);\n\t\t\t\tconst maxIndex = Math.max(childIndex, sibling.index);\n\t\t\t\t\n\t\t\t\tnewChildren[minIndex] = pointer1;\n\t\t\t\tnewChildren[maxIndex] = pointer2;\n\n\t\t\t\treturn { merged: true, children: newChildren };\n\t\t\t}\n\t\t}\n\n\t\t// Can't borrow, merge with a sibling\n\t\tif (siblings.length > 0) {\n\t\t\tconst sibling = siblings[0];\n\t\t\tconst mergedChildren = [\n\t\t\t\t...childResult.children,\n\t\t\t\t...sibling.node.children\n\t\t\t];\n\n\t\t\tconst mergedNode = new RTreeNode(this, {\n\t\t\t\tid: this.nextId++,\n\t\t\t\tisLeaf: childResult.isLeaf,\n\t\t\t\tchildren: mergedChildren,\n\t\t\t\tbbox: null\n\t\t\t});\n\t\t\tmergedNode.updateBBox();\n\t\t\tconst mergedPointer = this._saveNode(mergedNode);\n\n\t\t\t// Update parent's children - remove both old nodes, add merged\n\t\t\tconst newChildren = parentNode.children.filter((_, i) => \n\t\t\t\ti !== childIndex && i !== sibling.index\n\t\t\t);\n\t\t\tnewChildren.push(mergedPointer);\n\n\t\t\treturn { merged: true, children: newChildren };\n\t\t}\n\n\t\t// No siblings (shouldn't happen except for root)\n\t\treturn { merged: false };\n\t}\n\n\t/**\n\t * Get the number of entries in the tree\n\t */\n\tsize() {\n\t\treturn this._size;\n\t}\n\n\t/**\n\t * Clear all entries from the tree by appending a new empty root node\n\t * Preserves the append-only file structure\n\t */\n\tasync clear() {\n\t\t// Create a new empty root node and append it to the file\n\t\tconst newRoot = new RTreeNode(this, {\n\t\t\tid: this.nextId++,\n\t\t\tisLeaf: true,\n\t\t\tchildren: [],\n\t\t\tbbox: null\n\t\t});\n\t\t\n\t\tthis.rootPointer = this._saveNode(newRoot);\n\t\tthis._size = 0;\n\t\tthis._writeMetadata();\n\t}\n\n\t/**\n\t * Compact the R-tree by copying the current root and all reachable nodes into a new file.\n\t * Returns size metrics to show reclaimed space.\n\t * @param {FileSystemSyncAccessHandle} destSyncHandle - Sync handle for destination file\n\t */\n\tasync compact(destSyncHandle) {\n\t\tif (!this.isOpen) {\n\t\t\tthrow new Error('R-tree file must be opened before use');\n\t\t}\n\t\tif (!destSyncHandle) {\n\t\t\tthrow new Error('Destination sync handle is required for compaction');\n\t\t}\n\n\t\t// Flush current metadata so size reflects latest state\n\t\tthis._writeMetadata();\n\t\tconst oldSize = this.file.getFileSize();\n\n\t\tconst dest = new RTree(destSyncHandle, this.maxEntries);\n\t\tawait dest.open();\n\t\t\n\t\t// After opening, set the properties we want to preserve\n\t\tdest.minEntries = this.minEntries;\n\t\tdest.nextId = this.nextId;\n\t\tdest._size = this._size;\n\n\t\tconst pointerMap = new Map();\n\n\t\tconst cloneNode = (pointer) => {\n\t\t\tconst offset = pointer.valueOf();\n\t\t\tif (pointerMap.has(offset)) {\n\t\t\t\treturn pointerMap.get(offset);\n\t\t\t}\n\n\t\t\tconst sourceNode = this._loadNode(pointer);\n\t\t\tconst clonedChildren = [];\n\n\t\t\tif (sourceNode.isLeaf) {\n\t\t\t\t// Leaf children are plain entries\n\t\t\t\tfor (const child of sourceNode.children) {\n\t\t\t\t\tclonedChildren.push(child);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfor (const childPointer of sourceNode.children) {\n\t\t\t\t\tconst newChildPtr = cloneNode(childPointer);\n\t\t\t\t\tclonedChildren.push(newChildPtr);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst clonedNode = new RTreeNode(dest, {\n\t\t\t\tid: sourceNode.id,\n\t\t\t\tisLeaf: sourceNode.isLeaf,\n\t\t\t\tchildren: clonedChildren,\n\t\t\t\tbbox: sourceNode.bbox\n\t\t\t});\n\n\t\t\tconst newPointer = dest._saveNode(clonedNode);\n\t\t\tpointerMap.set(offset, newPointer);\n\t\t\treturn newPointer;\n\t\t};\n\n\t\tconst newRootPointer = cloneNode(this.rootPointer);\n\t\tdest.rootPointer = newRootPointer;\n\n\t\tdest._writeMetadata();\n\t\t\n\t\t// Get size of destination file BEFORE closing\n\t\tconst newSize = dest.file.getFileSize();\n\t\t\n\t\tawait dest.close();\n\n\t\treturn {\n\t\t\toldSize,\n\t\t\tnewSize,\n\t\t\tbytesSaved: Math.max(0, oldSize - newSize)\n\t\t};\n\t}\n}\n\nexport default RTree;\n","import { Index } from './Index.js';\nimport { RTree, haversineDistance } from '@belteshazzar/binjson/rtree';\nimport { getProp } from '../../utils.js';\nimport { ObjectId } from '@belteshazzar/binjson';\n\n/**\n * Geospatial index implementation\n * OPFS-backed async implementation using bjson RTree\n */\nexport class GeospatialIndex extends Index {\n\tconstructor(indexName, keys, storageFile, options = {}) {\n super(indexName, keys, storageFile, options);\n\n this.geoField = Object.keys(keys)[0]; // Assume single geospatial field\n this.storageFilePath = storageFile;\n this.rtree = null;\n this.syncHandle = null;\n\t\tthis.isOpen = false;\n\t}\n\n\t/**\n\t * Open the index file\n\t * Must be called before using the index\n\t */\n\tasync open() {\n\t\tif (this.isOpen) {\n\t\t\treturn;\n\t\t}\n\t\ttry {\n\t\t\t// Parse path to get directory and filename\n\t\t\tconst pathParts = this.storageFilePath.split('/').filter(Boolean);\n\t\t\tconst filename = pathParts.pop();\n\t\t\t\n\t\t\tif (!filename) {\n\t\t\t\tthrow new Error(`Invalid storage path: ${this.storageFilePath}`);\n\t\t\t}\n\t\t\t\n\t\t\t// Navigate to directory\n\t\t\tlet dirHandle = await globalThis.navigator.storage.getDirectory();\n\t\t\tfor (const part of pathParts) {\n\t\t\t\tdirHandle = await dirHandle.getDirectoryHandle(part, { create: true });\n\t\t\t}\n\t\t\t\n\t\t\t// Get file handle and create sync access handle using native OPFS\n\t\t\tconst fileHandle = await dirHandle.getFileHandle(filename, { create: true });\n\t\t\tthis.syncHandle = await fileHandle.createSyncAccessHandle();\n\t\t\t\n\t\t\t// Create RTree with sync handle\n\t\t\tthis.rtree = new RTree(this.syncHandle, 9);\n\t\t\tawait this.rtree.open();\n\t\t\tthis.isOpen = true;\n\t\t} catch (error) {\n\t\t\t// Handle missing or corrupted files\n\t\t\tif (error.code === 'ENOENT' ||\n\t\t\t\t\t(error.message && (error.message.includes('Invalid R-tree') ||\n\t\t\t\t\terror.message.includes('file too small') ||\n\t\t\t\t\terror.message.includes('Failed to read metadata') ||\n\t\t\t\t\terror.message.includes('Unknown type byte')))) {\n\t\t\t\t// Close sync handle if open\n\t\t\t\tif (this.syncHandle) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tawait this.syncHandle.close();\n\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\t// Ignore close errors\n\t\t\t\t\t}\n\t\t\t\t\tthis.syncHandle = null;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t// Parse path to get directory and filename\n\t\t\t\tconst pathParts = this.storageFilePath.split('/').filter(Boolean);\n\t\t\t\tconst filename = pathParts.pop();\n\t\t\t\t\n\t\t\t\tif (!filename) {\n\t\t\t\t\tthrow new Error(`Invalid storage path: ${this.storageFilePath}`);\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t// Navigate to directory\n\t\t\t\tlet dirHandle = await globalThis.navigator.storage.getDirectory();\n\t\t\t\tfor (const part of pathParts) {\n\t\t\t\t\tdirHandle = await dirHandle.getDirectoryHandle(part, { create: true });\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t// Try to delete the corrupted file\n\t\t\t\ttry {\n\t\t\t\t\tawait dirHandle.removeEntry(filename);\n\t\t\t\t} catch (e) {\n\t\t\t\t\t// File might not exist, ignore\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t// Get new file handle and create sync access handle using native OPFS\n\t\t\t\tconst fileHandle = await dirHandle.getFileHandle(filename, { create: true });\n\t\t\t\tthis.syncHandle = await fileHandle.createSyncAccessHandle();\n\t\t\t\t\n\t\t\t\t// Create fresh RTree\n\t\t\t\tthis.rtree = new RTree(this.syncHandle, 9);\n\t\t\t\tawait this.rtree.open();\n\t\t\t\tthis.isOpen = true;\n\t\t\t} else {\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Close the index file\n\t */\n\tasync close() {\n\t\tif (this.isOpen) {\n\t\t\ttry {\n\t\t\t\tawait this.rtree.close();\n\t\t\t} catch (error) {\n\t\t\t\t// Ignore errors from already-closed files\n\t\t\t\tif (!error.message || !error.message.includes('File is not open')) {\n\t\t\t\t\tthrow error;\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis.isOpen = false;\n\t\t}\n\t}\n\n\t/**\n\t * Extract coordinates from a GeoJSON object\n\t * @param {Object} geoJson - The GeoJSON object\n\t * @returns {Object|null} Object with lat and lng, or null if invalid\n\t */\n\t_extractCoordinates(geoJson) {\n\t\tif (!geoJson) return null;\n\n\t\t// Handle GeoJSON FeatureCollection\n\t\tif (geoJson.type === 'FeatureCollection' && geoJson.features && geoJson.features.length > 0) {\n\t\t\tconst feature = geoJson.features[0];\n\t\t\tif (feature.geometry) {\n\t\t\t\treturn this._extractCoordinates(feature.geometry);\n\t\t\t}\n\t\t}\n\n\t\t// Handle GeoJSON Feature\n\t\tif (geoJson.type === 'Feature' && geoJson.geometry) {\n\t\t\treturn this._extractCoordinates(geoJson.geometry);\n\t\t}\n\n\t\t// Handle GeoJSON Point\n\t\tif (geoJson.type === 'Point' && geoJson.coordinates) {\n\t\t\tconst [lng, lat] = geoJson.coordinates;\n\t\t\tif (typeof lng === 'number' && typeof lat === 'number') {\n\t\t\t\treturn { lat, lng };\n\t\t\t}\n\t\t}\n\n\t\t// Handle GeoJSON Polygon - use centroid of first coordinate\n\t\tif (geoJson.type === 'Polygon' && geoJson.coordinates && geoJson.coordinates.length > 0) {\n\t\t\tconst ring = geoJson.coordinates[0];\n\t\t\tif (ring.length > 0) {\n\t\t\t\tlet sumLat = 0, sumLng = 0;\n\t\t\t\tfor (const coord of ring) {\n\t\t\t\t\tsumLng += coord[0];\n\t\t\t\t\tsumLat += coord[1];\n\t\t\t\t}\n\t\t\t\treturn {\n\t\t\t\t\tlat: sumLat / ring.length,\n\t\t\t\t\tlng: sumLng / ring.length\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t/**\n\t * Add a document to the geospatial index\n\t * @param {Object} doc - The document to index\n\t */\n\tasync add(doc) {\n\t\tif (!doc._id) {\n\t\t\tthrow new Error('Document must have an _id field');\n\t\t}\n\t\tconst geoValue = getProp(doc, this.geoField);\n\t\tconst coords = this._extractCoordinates(geoValue);\n\t\tif (coords) {\n\t\t\t// RTree.insert expects (lat, lng, objectId)\n\t\t\tawait this.rtree.insert(coords.lat, coords.lng, doc._id);\n\t\t}\n\t}\n\n\t/**\n\t * Remove a document from the geospatial index\n\t * @param {Object} doc - The document to remove\n\t */\n\tasync remove(doc) {\n\t\tif (!doc._id) {\n\t\t\treturn;\n\t\t}\n\n\t\t// RTree.remove expects just the ObjectId (or compatible value)\n if (!(doc._id instanceof ObjectId)) {\n console.error(doc);\n throw new Error('Document _id must be an ObjectId to remove from geospatial index');\n }\n\n\t\tawait this.rtree.remove(doc._id);\n\t}\n\n\t/**\n\t * Query the geospatial index\n\t * @param {*} query - The query object\n\t * @returns {Promise<Array|null>} Array of document IDs or null if query is not a geospatial query\n\t */\n\tasync query(query) {\n\t\t// Ensure the index is open before querying\n\t\tif (!this.isOpen) {\n\t\t\tawait this.open();\n\t\t}\n\n\t\t// Check if this is a geospatial query on our indexed field\n\t\tif (!query[this.geoField]) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst geoQuery = query[this.geoField];\n\n\t\t// Handle $geoWithin with bounding box\n\t\tif (geoQuery.$geoWithin) {\n\t\t\tconst bbox = geoQuery.$geoWithin;\n\t\t\t// bbox format: [[minLon, maxLat], [maxLon, minLat]]\n\t\t\tif (Array.isArray(bbox) && bbox.length === 2) {\n\t\t\t\tconst minLon = bbox[0][0];\n\t\t\t\tconst maxLat = bbox[0][1];\n\t\t\t\tconst maxLon = bbox[1][0];\n\t\t\t\tconst minLat = bbox[1][1];\n\n\t\t\t\tconst results = await this.rtree.searchBBox({\n\t\t\t\t\tminLat: minLat,\n\t\t\t\t\tmaxLat: maxLat,\n\t\t\t\t\tminLng: minLon,\n\t\t\t\t\tmaxLng: maxLon\n\t\t\t\t});\n\n\t\t\t\t// searchBBox returns entries with coords - convert ObjectIds to strings\n\t\t\t\treturn results.map(entry => entry.objectId.toString());\n\t\t\t}\n\t\t}\n\n\t\t// Handle $near with radius\n\t\tif (geoQuery.$near) {\n\t\t\tconst nearQuery = geoQuery.$near;\n\t\t\t\n\t\t\t// Extract geometry from $geometry or use direct coordinates\n\t\t\tlet coordinates;\n\t\t\tif (nearQuery.$geometry) {\n\t\t\t\tcoordinates = nearQuery.$geometry.coordinates;\n\t\t\t} else if (nearQuery.coordinates) {\n\t\t\t\tcoordinates = nearQuery.coordinates;\n\t\t\t} else if (Array.isArray(nearQuery)) {\n\t\t\t\tcoordinates = nearQuery;\n\t\t\t} else {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\tif (!coordinates || coordinates.length < 2) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\tconst [lng, lat] = coordinates;\n\t\t\t\n\t\t\t// $maxDistance in meters (default to 1000km if not specified)\n\t\t\tconst maxDistanceMeters = nearQuery.$maxDistance || 1000000;\n\t\t\tconst maxDistanceKm = maxDistanceMeters / 1000;\n\n\t\t\t// Use rtree.searchRadius to find points within distance\n\t\t\t// Returns array of { objectId, lat, lng, distance }\n\t\t\tconst results = await this.rtree.searchRadius(lat, lng, maxDistanceKm);\n\n\t\t\t// Sort by distance (ascending)\n\t\t\tresults.sort((a, b) => a.distance - b.distance);\n\n\t\t\t// Return just the document IDs - convert ObjectIds to strings\n\t\t\treturn results.map(entry => entry.objectId.toString());\n\t\t}\n\n\t\t// Handle $nearSphere with radius (uses spherical distance, same as $near)\n\t\tif (geoQuery.$nearSphere) {\n\t\t\tconst nearQuery = geoQuery.$nearSphere;\n\t\t\t\n\t\t\t// Extract geometry from $geometry or use direct coordinates\n\t\t\tlet coordinates;\n\t\t\tif (nearQuery.$geometry) {\n\t\t\t\tcoordinates = nearQuery.$geometry.coordinates;\n\t\t\t} else if (nearQuery.coordinates) {\n\t\t\t\tcoordinates = nearQuery.coordinates;\n\t\t\t} else if (Array.isArray(nearQuery)) {\n\t\t\t\tcoordinates = nearQuery;\n\t\t\t} else {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\tif (!coordinates || coordinates.length < 2) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\tconst [lng, lat] = coordinates;\n\t\t\t\n\t\t\t// $maxDistance in meters (default to 1000km if not specified)\n\t\t\tconst maxDistanceMeters = nearQuery.$maxDistance || 1000000;\n\t\t\tconst maxDistanceKm = maxDistanceMeters / 1000;\n\n\t\t\t// Use rtree.searchRadius to find points within distance (already uses Haversine)\n\t\t\t// Returns array of { objectId, lat, lng, distance }\n\t\t\tconst results = await this.rtree.searchRadius(lat, lng, maxDistanceKm);\n\n\t\t\t// Sort by distance (ascending)\n\t\t\tresults.sort((a, b) => a.distance - b.distance);\n\n\t\t\t// Return just the document IDs - convert ObjectIds to strings\n\t\t\treturn results.map(entry => entry.objectId.toString());\n\t\t}\n\n\t\t// Handle $geoIntersects\n\t\tif (geoQuery.$geoIntersects) {\n\t\t\tconst intersectsQuery = geoQuery.$geoIntersects;\n\t\t\t\n\t\t\t// Extract geometry\n\t\t\tlet geometry;\n\t\t\tif (intersectsQuery.$geometry) {\n\t\t\t\tgeometry = intersectsQuery.$geometry;\n\t\t\t} else {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\tif (!geometry || !geometry.type) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\t// For now, support Point and Polygon geometries\n\t\t\tif (geometry.type === 'Point') {\n\t\t\t\tconst [lng, lat] = geometry.coordinates;\n\t\t\t\t\n\t\t\t\t// Search for points at this exact location\n\t\t\t\t// Use a very small bounding box\n\t\t\t\tconst epsilon = 0.0001; // ~11 meters\n\t\t\t\tconst results = await this.rtree.searchBBox({\n\t\t\t\t\tminLat: lat - epsilon,\n\t\t\t\t\tmaxLat: lat + epsilon,\n\t\t\t\t\tminLng: lng - epsilon,\n\t\t\t\t\tmaxLng: lng + epsilon\n\t\t\t\t});\n\n\t\t\t\t// searchBBox returns entries with coords - convert ObjectIds to strings\n\t\t\t\treturn results.map(entry => entry.objectId.toString());\n\t\t\t} else if (geometry.type === 'Polygon') {\n\t\t\t\tconst coordinates = geometry.coordinates;\n\t\t\t\tif (!coordinates || coordinates.length === 0) {\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\n\t\t\t\t// Get the exterior ring\n\t\t\t\tconst ring = coordinates[0];\n\t\t\t\tif (!ring || ring.length < 3) {\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\n\t\t\t\t// Calculate bounding box of the polygon\n\t\t\t\tlet minLat = Infinity, maxLat = -Infinity;\n\t\t\t\tlet minLng = Infinity, maxLng = -Infinity;\n\t\t\t\t\n\t\t\t\tfor (const coord of ring) {\n\t\t\t\t\tconst [lng, lat] = coord;\n\t\t\t\t\tminLat = Math.min(minLat, lat);\n\t\t\t\t\tmaxLat = Math.max(maxLat, lat);\n\t\t\t\t\tminLng = Math.min(minLng, lng);\n\t\t\t\t\tmaxLng = Math.max(maxLng, lng);\n\t\t\t\t}\n\n\t\t\t\t// Search for points within the bounding box\n\t\t\t\tconst candidates = await this.rtree.searchBBox({\n\t\t\t\t\tminLat,\n\t\t\t\t\tmaxLat,\n\t\t\t\t\tminLng,\n\t\t\t\t\tmaxLng\n\t\t\t\t});\n\n\t\t\t\t// Filter by actual point-in-polygon test using returned coordinates\n\t\t\t\tconst results = candidates.filter(entry => this._pointInPolygon(entry.lat, entry.lng, ring));\n\n\t\t\t\t// Convert ObjectIds to strings\n\t\t\t\treturn results.map(entry => entry.objectId.toString());\n\t\t\t}\n\n\t\t\treturn null;\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t// /**\n\t// * Calculate distance between two points using Haversine formula\n\t// * @param {number} lat1 - Latitude of first point\n\t// * @param {number} lng1 - Longitude of first point\n\t// * @param {number} lat2 - Latitude of second point\n\t// * @param {number} lng2 - Longitude of second point\n\t// * @returns {number} Distance in kilometers\n\t// */\n\t// _haversineDistance(lat1, lng1, lat2, lng2) {\n\t// \tconst R = 6371; // Earth's radius in kilometers\n\t// \tconst dLat = (lat2 - lat1) * Math.PI / 180;\n\t// \tconst dLng = (lng2 - lng1) * Math.PI / 180;\n\t// \tconst a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +\n\t// \t\tMath.cos(lat1 * Math.PI / 180) * Math.cos(lat2 * Math.PI / 180) *\n\t// \t\tMath.sin(dLng / 2) * Math.sin(dLng / 2);\n\t// \tconst c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));\n\t// \treturn R * c;\n\t// }\n\n\t/**\n\t * Test if a point is inside a polygon using ray casting algorithm\n\t * @param {number} lat - Point latitude\n\t * @param {number} lng - Point longitude\n\t * @param {Array} ring - Polygon ring as array of [lng, lat] coordinates\n\t * @returns {boolean} True if point is inside polygon\n\t */\n\t_pointInPolygon(lat, lng, ring) {\n\t\tlet inside = false;\n\t\t\n\t\tfor (let i = 0, j = ring.length - 1; i < ring.length; j = i++) {\n\t\t\tconst [xi, yi] = ring[i];\n\t\t\tconst [xj, yj] = ring[j];\n\t\t\t\n\t\t\tconst intersect = ((yi > lat) !== (yj > lat)) &&\n\t\t\t\t(lng < (xj - xi) * (lat - yi) / (yj - yi) + xi);\n\t\t\t\n\t\t\tif (intersect) {\n\t\t\t\tinside = !inside;\n\t\t\t}\n\t\t}\n\t\t\n\t\treturn inside;\n\t}\n\n\t/**\n\t * Clear all data from the index\n\t */\n // TODO: dont' delete the file or just clear the RTree contents\n\tasync clear() {\n await this.close();\n\n // Delete existing on-disk tree to avoid stale entries\n\t\ttry {\n\t\t\t// Parse path to get directory and filename\n\t\t\tconst pathParts = this.storageFilePath.split('/').filter(Boolean);\n\t\t\tconst filename = pathParts.pop();\n\t\t\t\n\t\t\t// Navigate to directory\n\t\t\tlet dirHandle = await globalThis.navigator.storage.getDirectory();\n\t\t\tfor (const part of pathParts) {\n\t\t\t\tdirHandle = await dirHandle.getDirectoryHandle(part, { create: false });\n\t\t\t}\n\t\t\t\n\t\t\t// Delete the file\n\t\t\tawait dirHandle.removeEntry(filename);\n\t\t} catch (err) {\n\t\t\t// Ignore if file doesn't exist; rethrow other errors\n\t\t\tif (!err || err.name !== 'NotFoundError') {\n\t\t\t\tthrow err;\n\t\t\t}\n\t\t}\n\n // Recreate the RTree\n\t\tawait this.open();\n\t}\n\n\t/**\n\t * Get index specification\n\t */\n\tgetSpec() {\n\t\treturn {\n\t\t\tname: this.name,\n\t\t\tkey: this.keys,\n\t\t\t'2dsphereIndexVersion': 3\n\t\t};\n\t}\n\n}\n","import { TextCollectionIndex } from './indexes/TextCollectionIndex.js';\nimport { GeospatialIndex } from './indexes/GeospatialIndex.js';\n\n/**\n * Query execution plan\n */\nclass QueryPlan {\n\tconstructor() {\n\t\tthis.type = 'full_scan'; // 'full_scan', 'index_scan', 'index_intersection', 'index_union'\n\t\tthis.indexes = []; // Indexes to use\n\t\tthis.indexScans = []; // Array of { indexName, docIds }\n\t\tthis.estimatedCost = Infinity;\n\t\tthis.indexOnly = false; // If true, only use index results (no full scan fallback)\n\t}\n}\n\n/**\n * Query planner - analyzes queries and generates optimal execution plans\n */\nexport class QueryPlanner {\n\tconstructor(indexes) {\n\t\tthis.indexes = indexes; // Map<string, CollectionIndex>\n\t}\n\n\t/**\n\t * Generate an execution plan for a query\n\t * @param {Object} query - MongoDB query object\n\t * @returns {QueryPlan} Execution plan\n\t */\n\tplan(query) {\n\t\tconst plan = new QueryPlan();\n\n\t\t// Empty query - full scan\n\t\tif (!query || Object.keys(query).length === 0) {\n\t\t\treturn plan;\n\t\t}\n\n\t\t// Analyze query structure\n\t\tconst analysis = this._analyzeQuery(query);\n\n\t\t// Check for text search\n\t\tif (analysis.hasTextSearch) {\n\t\t\tconst textPlan = this._planTextSearch(query, analysis);\n\t\t\tif (textPlan) {\n\t\t\t\treturn textPlan;\n\t\t\t}\n\t\t}\n\n\t\t// Check for geospatial query\n\t\tif (analysis.hasGeoQuery) {\n\t\t\tconst geoPlan = this._planGeoQuery(query, analysis);\n\t\t\tif (geoPlan) {\n\t\t\t\treturn geoPlan;\n\t\t\t}\n\t\t}\n\n\t\t// Check for $and queries - can use index intersection\n\t\tif (analysis.type === 'and') {\n\t\t\tconst andPlan = this._planAndQuery(query, analysis);\n\t\t\tif (andPlan.type !== 'full_scan') {\n\t\t\t\treturn andPlan;\n\t\t\t}\n\t\t}\n\n\t\t// Check for $or queries - can use index union\n\t\tif (analysis.type === 'or') {\n\t\t\tconst orPlan = this._planOrQuery(query, analysis);\n\t\t\tif (orPlan.type !== 'full_scan') {\n\t\t\t\treturn orPlan;\n\t\t\t}\n\t\t}\n\n\t\t// Try to find a single index for simple queries\n\t\tconst simplePlan = this._planSimpleQuery(query);\n\t\tif (simplePlan.type !== 'full_scan') {\n\t\t\treturn simplePlan;\n\t\t}\n\n\t\t// Fall back to full scan\n\t\treturn plan;\n\t}\n\n\t/**\n\t * Analyze query structure\n\t * @private\n\t */\n\t_analyzeQuery(query) {\n\t\tconst analysis = {\n\t\t\ttype: 'simple', // 'simple', 'and', 'or', 'complex'\n\t\t\tfields: [],\n\t\t\toperators: {},\n\t\t\thasTextSearch: false,\n\t\t\thasGeoQuery: false,\n\t\t\tconditions: []\n\t\t};\n\n\t\tconst keys = Object.keys(query);\n\n\t\t// Check for top-level logical operators\n\t\tif (keys.length === 1) {\n\t\t\tconst key = keys[0];\n\t\t\tif (key === '$and') {\n\t\t\t\tanalysis.type = 'and';\n\t\t\t\tanalysis.conditions = query.$and;\n\t\t\t\t// Analyze each condition\n\t\t\t\tfor (const condition of analysis.conditions) {\n\t\t\t\t\tconst subAnalysis = this._analyzeQuery(condition);\n\t\t\t\t\tanalysis.fields.push(...subAnalysis.fields);\n\t\t\t\t\tif (subAnalysis.hasTextSearch) analysis.hasTextSearch = true;\n\t\t\t\t\tif (subAnalysis.hasGeoQuery) analysis.hasGeoQuery = true;\n\t\t\t\t}\n\t\t\t\treturn analysis;\n\t\t\t} else if (key === '$or') {\n\t\t\t\tanalysis.type = 'or';\n\t\t\t\tanalysis.conditions = query.$or;\n\t\t\t\t// Analyze each condition\n\t\t\t\tfor (const condition of analysis.conditions) {\n\t\t\t\t\tconst subAnalysis = this._analyzeQuery(condition);\n\t\t\t\t\tanalysis.fields.push(...subAnalysis.fields);\n\t\t\t\t\tif (subAnalysis.hasTextSearch) analysis.hasTextSearch = true;\n\t\t\t\t\tif (subAnalysis.hasGeoQuery) analysis.hasGeoQuery = true;\n\t\t\t\t}\n\t\t\t\treturn analysis;\n\t\t\t}\n\t\t}\n\n\t\t// Analyze simple field conditions\n\t\tfor (const field of keys) {\n\t\t\tif (field.startsWith('$')) {\n\t\t\t\tcontinue; // Skip top-level operators we don't handle yet\n\t\t\t}\n\n\t\t\tanalysis.fields.push(field);\n\t\t\tconst value = query[field];\n\n\t\t\t// Check for operators\n\t\t\tif (typeof value === 'object' && value !== null && !Array.isArray(value)) {\n\t\t\t\tconst ops = Object.keys(value);\n\t\t\t\tanalysis.operators[field] = ops;\n\n\t\t\t\t// Check for text search\n\t\t\t\tif (ops.includes('$text')) {\n\t\t\t\t\tanalysis.hasTextSearch = true;\n\t\t\t\t}\n\n\t\t\t\t// Check for geospatial operators\n\t\t\t\tif (ops.some(op => ['$geoWithin', '$geoIntersects', '$near', '$nearSphere'].includes(op))) {\n\t\t\t\t\tanalysis.hasGeoQuery = true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// If multiple fields, it's an implicit $and\n\t\tif (keys.length > 1) {\n\t\t\tanalysis.type = 'and';\n\t\t}\n\n\t\treturn analysis;\n\t}\n\n\t/**\n\t * Plan for text search queries\n\t * @private\n\t */\n\t_planTextSearch(query, analysis) {\n\t\t// Find text index\n\t\tfor (const [indexName,index] of this.indexes) {\n\t\t\tif (index instanceof TextCollectionIndex) {\n\t\t\t\t// Look for $text operator in query\n\t\t\t\tconst textQuery = this._extractTextQuery(query);\n\t\t\t\tif (textQuery) {\n\t\t\t\t\tconst plan = new QueryPlan();\n\t\t\t\t\tplan.type = 'index_scan';\n\t\t\t\t\tplan.indexes = [indexName];\n\t\t\t\t\t// Store query info for execution phase, don't execute yet\n\t\t\t\t\tplan.indexScans = [{ indexName, index, textQuery }];\n\t\t\t\t\tplan.estimatedCost = 100; // Rough estimate without executing\n\t\t\t\t\tplan.indexOnly = true; // Text search must use index\n\t\t\t\t\treturn plan;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn null;\n\t}\n\n\t/**\n\t * Extract $text query from query object\n\t * @private\n\t */\n\t_extractTextQuery(query) {\n\t\tfor (const field in query) {\n\t\t\tconst value = query[field];\n\t\t\tif (typeof value === 'object' && value !== null && value.$text) {\n\t\t\t\treturn typeof value.$text === 'string' ? value.$text : value.$text.$search;\n\t\t\t}\n\t\t}\n\t\treturn null;\n\t}\n\n\t/**\n\t * Plan for geospatial queries\n\t * @private\n\t */\n\t_planGeoQuery(query, analysis) {\n\t\t// Find geospatial index\n\t\tfor (const [indexName,index] of this.indexes) {\n\t\t\tif (index instanceof GeospatialIndex) {\n\t\t\t\t// Check if this index can handle the query (don't execute yet)\n\t\t\t\tconst plan = new QueryPlan();\n\t\t\t\tplan.type = 'index_scan';\n\t\t\t\tplan.indexes = [indexName];\n\t\t\t\t// Store query info for execution phase, don't execute yet\n\t\t\t\tplan.indexScans = [{ indexName, index, query }];\n\t\t\t\tplan.estimatedCost = 100; // Rough estimate without executing\n\t\t\t\tplan.indexOnly = true; // Geospatial queries must use index\n\t\t\t\treturn plan;\n\t\t\t}\n\t\t}\n\t\treturn null;\n\t}\n\n\t/**\n\t * Plan for $and queries (index intersection)\n\t * @private\n\t */\n\t_planAndQuery(query, analysis) {\n\t\tconst plan = new QueryPlan();\n\n\t\t// Extract conditions\n\t\tlet conditions;\n\t\tif (query.$and) {\n\t\t\tconditions = query.$and;\n\t\t} else {\n\t\t\t// Implicit AND - convert to array of conditions\n\t\t\tconditions = Object.keys(query).map(field => ({ [field]: query[field] }));\n\t\t}\n\n\t\t// Try to find indexes for each condition\n\t\tconst indexableConditions = [];\n\t\tfor (const condition of conditions) {\n\t\t\tconst conditionPlan = this._planSimpleQuery(condition);\n\t\t\tif (conditionPlan.type === 'index_scan') {\n\t\t\t\tindexableConditions.push(conditionPlan.indexScans[0]);\n\t\t\t}\n\t\t}\n\n\t\t// If we have multiple indexable conditions, use index intersection\n\t\tif (indexableConditions.length > 1) {\n\t\t\tplan.type = 'index_intersection';\n\t\t\tplan.indexScans = indexableConditions;\n\t\t\tplan.indexes = indexableConditions.map(scan => scan.indexName);\n\t\t\t\n\t\t\t// Estimate cost (rough estimate without executing)\n\t\t\tplan.estimatedCost = 50; // Intersection typically reduces result set\n\t\t\treturn plan;\n\t\t}\n\n\t\t// If we have one indexable condition, use it\n\t\tif (indexableConditions.length === 1) {\n\t\t\tplan.type = 'index_scan';\n\t\t\tplan.indexScans = [indexableConditions[0]];\n\t\t\tplan.indexes = [indexableConditions[0].indexName];\n\t\t\tplan.estimatedCost = 50; // Rough estimate without executing\n\t\t\treturn plan;\n\t\t}\n\n\t\treturn plan; // full_scan\n\t}\n\n\t/**\n\t * Plan for $or queries (index union)\n\t * @private\n\t */\n\t_planOrQuery(query, analysis) {\n\t\tconst plan = new QueryPlan();\n\n\t\tif (!query.$or) {\n\t\t\treturn plan;\n\t\t}\n\n\t\tconst conditions = query.$or;\n\n\t\t// Try to find indexes for each condition\n\t\tconst indexableConditions = [];\n\t\tfor (const condition of conditions) {\n\t\t\tconst conditionPlan = this._planSimpleQuery(condition);\n\t\t\tif (conditionPlan.type === 'index_scan') {\n\t\t\t\tindexableConditions.push(conditionPlan.indexScans[0]);\n\t\t\t}\n\t\t}\n\n\t\t// If we have at least one indexable condition, use index union\n\t\tif (indexableConditions.length > 0) {\n\t\t\tplan.type = 'index_union';\n\t\t\tplan.indexScans = indexableConditions;\n\t\t\tplan.indexes = indexableConditions.map(scan => scan.indexName);\n\t\t\t\n\t\t\t// Estimate cost (rough estimate without executing)\n\t\t\tplan.estimatedCost = 100 * indexableConditions.length; // Union typically increases result set\n\t\t\treturn plan;\n\t\t}\n\n\t\treturn plan; // full_scan\n\t}\n\n\t/**\n\t * Plan for simple single-field queries\n\t * @private\n\t */\n\t_planSimpleQuery(query) {\n\t\tconst plan = new QueryPlan();\n\t\tconst queryKeys = Object.keys(query);\n\n\t\tif (queryKeys.length === 0) {\n\t\t\treturn plan;\n\t\t}\n\n\t\t// Try each index\n\t\tfor (const [indexName,index] of this.indexes) {\n\n\t\t\t// Skip special index types (they have their own planning)\n\t\t\tif (index instanceof TextCollectionIndex || index instanceof GeospatialIndex) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Check if this index CAN handle the query (don't execute yet)\n\t\t\tif (this._canIndexHandleQuery(index, query)) {\n\t\t\t\tplan.type = 'index_scan';\n\t\t\t\tplan.indexes = [indexName];\n\t\t\t\t// Store query info for execution phase, don't execute yet\n\t\t\t\tplan.indexScans = [{ indexName, index, query }];\n\t\t\t\tplan.estimatedCost = 50; // Rough estimate without executing\n\t\t\t\treturn plan;\n\t\t\t}\n\t\t}\n\n\t\treturn plan; // full_scan\n\t}\n\n\t/**\n\t * Execute a single index scan that was deferred from planning\n\t * @private\n\t */\n\tasync _executeIndexScan(scan) {\n\t\tconst { index, query, textQuery } = scan;\n\t\t\n\t\t// Ensure async indexes are open before use\n\t\tif (typeof index.open === 'function' && typeof index.isOpen !== 'undefined' && !index.isOpen) {\n\t\t\tawait index.open();\n\t\t}\n\t\t\n\t\t// Handle text search\n\t\tif (textQuery !== undefined) {\n\t\t\treturn await index.search(textQuery);\n\t\t}\n\t\t\n\t\t// Handle regular index query\n\t\tif (query !== undefined) {\n\t\t\tconst docIds = await index.query(query);\n\t\t\treturn docIds !== null ? docIds : [];\n\t\t}\n\t\t\n\t\t// Fallback: if docIds were already computed (backward compatibility)\n\t\tif (scan.docIds !== undefined) {\n\t\t\treturn scan.docIds;\n\t\t}\n\t\t\n\t\treturn [];\n\t}\n\n\t/**\n\t * Check if an index can handle a query (without executing it)\n\t * @private\n\t */\n\t_canIndexHandleQuery(index, query) {\n\t\tconst queryKeys = Object.keys(query);\n\t\tconst indexFields = Object.keys(index.keys);\n\n\t\t// Only support single-field index queries for now\n\t\tif (indexFields.length !== 1) {\n\t\t\treturn false;\n\t\t}\n\n\t\tconst field = indexFields[0];\n\t\t\n\t\t// Check if query has this field\n\t\tif (queryKeys.indexOf(field) === -1) {\n\t\t\treturn false;\n\t\t}\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * Execute a query plan and return document IDs\n\t * @param {QueryPlan} plan - The execution plan\n\t * @returns {Promise<Array|null>} Array of document IDs or null for full scan\n\t */\n\tasync execute(plan) {\n\t\tif (plan.type === 'full_scan') {\n\t\t\treturn null; // Signals cursor to do full scan\n\t\t}\n\n\t\tif (plan.type === 'index_scan') {\n\t\t\t// Execute the query now\n\t\t\tconst scan = plan.indexScans[0];\n\t\t\treturn await this._executeIndexScan(scan);\n\t\t}\n\n\t\tif (plan.type === 'index_intersection') {\n\t\t\t// Intersection: docs must be in ALL index results\n\t\t\tif (plan.indexScans.length === 0) return null;\n\t\t\t\n\t\t\t// Execute all scans\n\t\t\tconst results = [];\n\t\t\tfor (const scan of plan.indexScans) {\n\t\t\t\tresults.push({\n\t\t\t\t\tdocIds: await this._executeIndexScan(scan),\n\t\t\t\t\tindexName: scan.indexName\n\t\t\t\t});\n\t\t\t}\n\t\t\t\n\t\t\t// Start with the smallest set for efficiency\n\t\t\tconst sorted = results.slice().sort((a, b) => a.docIds.length - b.docIds.length);\n\t\t\tlet result = new Set(sorted[0].docIds);\n\t\t\t\n\t\t\t// Intersect with each subsequent set\n\t\t\tfor (let i = 1; i < sorted.length; i++) {\n\t\t\t\tconst currentSet = new Set(sorted[i].docIds);\n\t\t\t\tresult = new Set([...result].filter(id => currentSet.has(id)));\n\t\t\t\t\n\t\t\t\t// Early exit if intersection becomes empty\n\t\t\t\tif (result.size === 0) break;\n\t\t\t}\n\t\t\t\n\t\t\treturn Array.from(result);\n\t\t}\n\n\t\tif (plan.type === 'index_union') {\n\t\t\t// Union: docs in ANY index result\n\t\t\tconst result = new Set();\n\t\t\tfor (const scan of plan.indexScans) {\n\t\t\t\tconst docIds = await this._executeIndexScan(scan);\n\t\t\t\tdocIds.forEach(id => result.add(id));\n\t\t\t}\n\t\t\treturn Array.from(result);\n\t\t}\n\n\t\treturn null;\n\t}\n}\n","import { EventEmitter } from 'events';\nimport { matches } from './queryMatcher.js';\n\n/**\n * ChangeStream watches for changes in collections and emits change events\n * Compatible with MongoDB Change Streams API\n */\nexport class ChangeStream extends EventEmitter {\n\tconstructor(target, pipeline = [], options = {}) {\n\t\tsuper();\n\t\t\n\t\tthis.target = target; // MongoClient, DB, or Collection\n\t\tthis.pipeline = pipeline;\n\t\tthis.options = options;\n\t\tthis.closed = false;\n\t\tthis._listeners = new Map();\n\t\tthis._changeCounter = 0;\n\t\t\n\t\t// Start watching immediately (synchronously)\n\t\tthis._startWatching();\n\t}\n\n\t/**\n\t * Check if target is a DB instance (handles Proxies and minification)\n\t */\n\t_isDB(target) {\n\t\t// Check for DB-specific properties that won't trigger collection creation\n\t\t// Use hasOwnProperty or check the collections Map directly\n\t\treturn target && \n\t\t\ttypeof target.dbName === 'string' && \n\t\t\ttypeof target.getCollectionNames === 'function' &&\n\t\t\ttarget.collections instanceof Map;\n\t}\n\n\t/**\n\t * Check if target is a Server instance\n\t */\n\t_isServer(target) {\n\t\treturn target && \n\t\t\ttarget.databases instanceof Map &&\n\t\t\ttypeof target._getDB === 'function';\n\t}\n\n\t/**\n\t * Check if target is a MongoClient instance\n\t */\n\t_isMongoClient(target) {\n\t\treturn target && \n\t\t\ttypeof target.connect === 'function' &&\n\t\t\ttypeof target.db === 'function' &&\n\t\t\ttarget.constructor.name === 'MongoClient'; // MongoClient is not minified same way\n\t}\n\n\t/**\n\t * Start watching for changes\n\t * @private\n\t */\n\t_startWatching() {\n\t\tif (this.closed) return;\n\t\t\n\t\tconst collections = this._getCollectionsToWatch();\n\t\t\n\t\tfor (const collection of collections) {\n\t\t\tthis._watchCollection(collection);\n\t\t}\n\t\t\n\t\t// For Server watching, intercept _getDB calls\n\t\tif (this._isServer(this.target)) {\n\t\t\tthis._interceptServerDBCreation();\n\t\t}\n\t\t\n\t\t// For DB watching, we also need to intercept new collection creation\n\t\tif (this._isDB(this.target)) {\n\t\t\tthis._interceptDBCollectionCreation();\n\t\t}\n\t\t\n\t\t// For MongoClient watching, intercept db() calls\n\t\tif (this._isMongoClient(this.target)) {\n\t\t\tthis._interceptClientDBCreation();\n\t\t}\n\t}\n\n\t/**\n\t * Get collections to watch based on target type\n\t * @private\n\t */\n\t_getCollectionsToWatch() {\n\t\tconst collections = [];\n\t\t\n\t\t// Server - watch all collections in all databases\n\t\tif (this._isServer(this.target)) {\n\t\t\t// Watch all existing databases\n\t\t\tfor (const [dbName, db] of this.target.databases) {\n\t\t\t\tconst collectionNames = db.getCollectionNames();\n\t\t\t\tfor (const name of collectionNames) {\n\t\t\t\t\tconst collection = db[name];\n\t\t\t\t\tif (collection && collection.isCollection) {\n\t\t\t\t\t\tcollections.push(collection);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn collections;\n\t\t}\n\t\t\n\t\t// MongoClient - watch all collections in all databases\n\t\tif (this._isMongoClient(this.target)) {\n\t\t\t// Store reference to monitor for new databases/collections\n\t\t\tthis._monitorClient();\n\t\t\treturn collections;\n\t\t}\n\t\t\n\t\t// DB - watch all collections in the database\n\t\tif (this._isDB(this.target)) {\n\t\t\tconst collectionNames = this.target.getCollectionNames();\n\t\t\tfor (const name of collectionNames) {\n\t\t\t\tconst collection = this.target[name];\n\t\t\t\tif (collection && collection.isCollection) {\n\t\t\t\t\tcollections.push(collection);\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Also monitor for new collections\n\t\t\tthis._monitorDB();\n\t\t}\n\t\t\n\t\t// Collection - watch specific collection\n\t\tif (this.target.isCollection) {\n\t\t\tcollections.push(this.target);\n\t\t}\n\t\t\n\t\treturn collections;\n\t}\n\n\t/**\n\t * Watch a specific collection for changes\n\t * @private\n\t */\n\t_watchCollection(collection) {\n\t\tif (this.closed) return;\n\t\tif (!collection) return; // Skip null/undefined\n\t\tif (typeof collection.on !== 'function') return; // Skip non-EventEmitters\n\t\tif (!collection.isCollection) return; // Skip non-collections\n\t\tif (this._listeners.has(collection)) return; // Already watching\n\t\t\n\t\tconst handlers = {\n\t\t\tinsert: (doc) => this._emitChange('insert', collection, doc),\n\t\t\tupdate: (doc, updateDescription) => this._emitChange('update', collection, doc, updateDescription),\n\t\t\treplace: (doc) => this._emitChange('replace', collection, doc),\n\t\t\tdelete: (doc) => this._emitChange('delete', collection, doc)\n\t\t};\n\t\t\n\t\t// Store handlers for cleanup\n\t\tthis._listeners.set(collection, handlers);\n\t\t\n\t\t// Listen to collection change events\n\t\tcollection.on('insert', handlers.insert);\n\t\tcollection.on('update', handlers.update);\n\t\tcollection.on('replace', handlers.replace);\n\t\tcollection.on('delete', handlers.delete);\n\t}\n\n\t/**\n\t * Emit a change event\n\t * @private\n\t */\n\t_emitChange(operationType, collection, doc, updateDescription = null) {\n\t\tif (this.closed) return;\n\t\t\n\t\tconst changeEvent = this._createChangeEvent(\n\t\t\toperationType,\n\t\t\tcollection,\n\t\t\tdoc,\n\t\t\tupdateDescription\n\t\t);\n\t\t\n\t\t// Apply pipeline filters if any\n\t\tif (!this._matchesPipeline(changeEvent)) {\n\t\t\treturn;\n\t\t}\n\t\t\n\t\tthis.emit('change', changeEvent);\n\t}\n\n\t/**\n\t * Create a MongoDB-compatible change event document\n\t * @private\n\t */\n\t_createChangeEvent(operationType, collection, doc, updateDescription) {\n\t\tconst event = {\n\t\t\t_id: {\n\t\t\t\t_data: btoa(String(++this._changeCounter))\n\t\t\t},\n\t\t\toperationType,\n\t\t\tclusterTime: new Date(),\n\t\t\tns: {\n\t\t\t\tdb: collection.db.dbName,\n\t\t\t\tcoll: collection.name\n\t\t\t},\n\t\t\tdocumentKey: {\n\t\t\t\t_id: doc._id\n\t\t\t}\n\t\t};\n\t\t\n\t\tswitch (operationType) {\n\t\t\tcase 'insert':\n\t\t\t\tevent.fullDocument = doc;\n\t\t\t\tbreak;\n\t\t\t\t\n\t\t\tcase 'update':\n\t\t\t\tevent.updateDescription = updateDescription || {\n\t\t\t\t\tupdatedFields: {},\n\t\t\t\t\tremovedFields: [],\n\t\t\t\t\ttruncatedArrays: []\n\t\t\t\t};\n\t\t\t\t// Include full document if requested\n\t\t\t\tif (this.options.fullDocument === 'updateLookup') {\n\t\t\t\t\tevent.fullDocument = doc;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t\t\n\t\t\tcase 'replace':\n\t\t\t\tevent.fullDocument = doc;\n\t\t\t\tbreak;\n\t\t\t\t\n\t\t\tcase 'delete':\n\t\t\t\t// For delete, doc contains the deleted document's _id\n\t\t\t\tbreak;\n\t\t}\n\t\t\n\t\treturn event;\n\t}\n\n\t/**\n\t * Check if change event matches pipeline filters\n\t * @private\n\t */\n\t_matchesPipeline(changeEvent) {\n\t\tif (!this.pipeline || this.pipeline.length === 0) {\n\t\t\treturn true;\n\t\t}\n\t\t\n\t\t// Process pipeline stages\n\t\tfor (const stage of this.pipeline) {\n\t\t\tif (stage.$match) {\n\t\t\t\t// Use the same query matcher as find()\n\t\t\t\t// Note: matches(document, query) - document first, query second\n\t\t\t\tif (!matches(changeEvent, stage.$match)) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t\n\t\treturn true;\n\t}\n\n\t/**\n\t * Get nested value from object using dot notation\n\t * @private\n\t */\n\t_getNestedValue(obj, path) {\n\t\treturn path.split('.').reduce((current, part) => current?.[part], obj);\n\t}\n\n\t/**\n\t * Monitor client for new databases/collections (simplified)\n\t * @private\n\t */\n\t_monitorClient() {\n\t\t// Handled by _interceptClientDBCreation\n\t}\n\n\t/**\n\t * Intercept DB creation on a MongoClient\n\t * @private\n\t */\n\t_interceptClientDBCreation() {\n\t\tconst client = this.target;\n\t\tconst originalDb = client.db.bind(client);\n\t\tconst self = this;\n\t\t\n\t\t// Track databases we're watching\n\t\tthis._watchedDBs = new Map();\n\t\t\n\t\t// Override db() method to watch new databases\n\t\tclient.db = function(name, opts) {\n\t\t\tconst database = originalDb(name, opts);\n\t\t\tconst dbName = database.dbName;\n\t\t\t\n\t\t\t// Only set up watch once per database\n\t\t\tif (!self._watchedDBs.has(dbName)) {\n\t\t\t\tself._watchedDBs.set(dbName, database);\n\t\t\t\t\n\t\t\t\t// Watch existing collections in this database\n\t\t\t\tconst collectionNames = database.getCollectionNames();\n\t\t\t\tfor (const colName of collectionNames) {\n\t\t\t\t\tconst col = database[colName];\n\t\t\t\t\tif (col && col.isCollection && !self._listeners.has(col)) {\n\t\t\t\t\t\tself._watchCollection(col);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t// Intercept new collection creation on this database\n\t\t\t\tself._interceptDBCollectionCreationForClient(database);\n\t\t\t}\n\t\t\t\n\t\t\treturn database;\n\t\t};\n\t\t\n\t\t// Store original for cleanup\n\t\tthis._originalClientMethods = { db: originalDb };\n\t}\n\n\t/**\n\t * Intercept DB creation on a Server\n\t * @private\n\t */\n\t_interceptServerDBCreation() {\n\t\tconst server = this.target;\n\t\tconst originalGetDB = server._getDB.bind(server);\n\t\tconst self = this;\n\t\t\n\t\t// Track databases we're watching\n\t\tthis._watchedDBs = new Map();\n\t\t\n\t\t// Override _getDB() method to watch new databases\n\t\tserver._getDB = function(dbName) {\n\t\t\tconst db = originalGetDB(dbName);\n\t\t\t\n\t\t\t// Only set up watch once per database\n\t\t\tif (!self._watchedDBs.has(dbName)) {\n\t\t\t\tself._watchedDBs.set(dbName, db);\n\t\t\t\t\n\t\t\t\t// Watch existing collections in this database\n\t\t\t\tconst collectionNames = db.getCollectionNames();\n\t\t\t\tfor (const colName of collectionNames) {\n\t\t\t\t\tconst col = db[colName];\n\t\t\t\t\tif (col && col.isCollection && !self._listeners.has(col)) {\n\t\t\t\t\t\tself._watchCollection(col);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t// Intercept new collection creation on this database\n\t\t\t\tself._interceptDBCollectionCreationForServer(db);\n\t\t\t}\n\t\t\t\n\t\t\treturn db;\n\t\t};\n\t\t\n\t\t// Store original for cleanup\n\t\tthis._originalServerMethods = { _getDB: originalGetDB };\n\t}\n\n\t/**\n\t * Intercept collection creation for a database in server watch mode\n\t * @private\n\t */\n\t_interceptDBCollectionCreationForServer(db) {\n\t\tconst originalCollection = db.collection.bind(db);\n\t\tconst originalCreateCollection = db.createCollection.bind(db);\n\t\tconst self = this;\n\t\t\n\t\tdb.collection = function(name) {\n\t\t\tconst col = originalCollection(name);\n\t\t\tif (col && col.isCollection && !self._listeners.has(col)) {\n\t\t\t\tself._watchCollection(col);\n\t\t\t}\n\t\t\treturn col;\n\t\t};\n\t\t\n\t\tdb.createCollection = function(name) {\n\t\t\toriginalCreateCollection(name);\n\t\t\tconst col = db[name];\n\t\t\tif (col && col.isCollection && !self._listeners.has(col)) {\n\t\t\t\tself._watchCollection(col);\n\t\t\t}\n\t\t};\n\t}\n\n\t/**\n\t * Intercept collection creation for a database in client watch mode\n\t * @private\n\t */\n\t_interceptDBCollectionCreationForClient(db) {\n\t\tconst originalCollection = db.collection.bind(db);\n\t\tconst originalCreateCollection = db.createCollection.bind(db);\n\t\tconst self = this;\n\t\t\n\t\tdb.collection = function(name) {\n\t\t\tconst col = originalCollection(name);\n\t\t\tif (col && col.isCollection && !self._listeners.has(col)) {\n\t\t\t\tself._watchCollection(col);\n\t\t\t}\n\t\t\treturn col;\n\t\t};\n\t\t\n\t\tdb.createCollection = function(name) {\n\t\t\toriginalCreateCollection(name);\n\t\t\tconst col = db[name];\n\t\t\tif (col && col.isCollection && !self._listeners.has(col)) {\n\t\t\t\tself._watchCollection(col);\n\t\t\t}\n\t\t};\n\t}\n\n\t/**\n\t * Monitor database for new collections\n\t * @private\n\t */\n\t_monitorDB() {\n\t\t// Handled by _interceptDBCollectionCreation\n\t}\n\n\t/**\n\t * Intercept new collection creation on a DB\n\t * @private\n\t */\n\t_interceptDBCollectionCreation() {\n\t\t// Since DB is a Proxy, we need to override getCollection() on the target, not collection() on the proxy\n\t\t// The Proxy's get trap will always return methods from the target via Reflect.get\n\t\tconst db = this.target;\n\t\t\n\t\t// Get the actual DB instance (not the proxy) by accessing _proxy property or finding it\n\t\t// The DB constructor stores 'this' before returning the proxy, so we can access it\n\t\tlet actualDB = db;\n\t\t// If db has _proxy, it means db IS the proxy and we need to get through to the real target\n\t\t// But we can't easily do that. Instead, we need to override on the object itself.\n\t\t// The trick is to override getCollection, since that's what collection() calls\n\t\t\n\t\tconst originalGetCollection = db.getCollection.bind(db);\n\t\tconst originalCreateCollection = db.createCollection ? db.createCollection.bind(db) : null;\n\t\tconst self = this;\n\t\t\n\t\t// Override getCollection() method to watch new collections\n\t\tdb.getCollection = function(name) {\n\t\t\tconst col = originalGetCollection(name);\n\t\t\t// Watch this collection if we haven't already\n\t\t\tif (col && col.isCollection && !self._listeners.has(col)) {\n\t\t\t\tself._watchCollection(col);\n\t\t\t}\n\t\t\treturn col;\n\t\t};\n\t\t\n\t\t// Override createCollection() method if it exists\n\t\tif (originalCreateCollection) {\n\t\t\tdb.createCollection = function(name) {\n\t\t\t\toriginalCreateCollection(name);\n\t\t\t\tconst col = db[name];\n\t\t\t\tif (col && col.isCollection && !self._listeners.has(col)) {\n\t\t\t\t\tself._watchCollection(col);\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\t\t\n\t\t// Store originals for cleanup\n\t\tthis._originalDBMethods = { \n\t\t\tgetCollection: originalGetCollection, \n\t\t\tcreateCollection: originalCreateCollection \n\t\t};\n\t}\n\n\t/**\n\t * Close the change stream\n\t */\n\tclose() {\n\t\tif (this.closed) return;\n\t\t\n\t\tthis.closed = true;\n\t\t\n\t\t// Remove all collection listeners\n\t\tfor (const [collection, handlers] of this._listeners) {\n\t\t\tcollection.off('insert', handlers.insert);\n\t\t\tcollection.off('update', handlers.update);\n\t\t\tcollection.off('replace', handlers.replace);\n\t\t\tcollection.off('delete', handlers.delete);\n\t\t}\n\t\t\n\t\tthis._listeners.clear();\n\t\t\n\t\t// Restore original Server methods if we intercepted them\n\t\tif (this._originalServerMethods && this.target.constructor.name === 'Server') {\n\t\t\tthis.target._getDB = this._originalServerMethods._getDB;\n\t\t}\n\t\t\n\t\t// Restore original DB methods if we intercepted them\n\t\tif (this._originalDBMethods && this.target.constructor.name === 'DB') {\n\t\t\tthis.target.collection = this._originalDBMethods.collection;\n\t\t\tthis.target.createCollection = this._originalDBMethods.createCollection;\n\t\t}\n\t\t\n\t\t// Restore original MongoClient methods if we intercepted them\n\t\tif (this._originalClientMethods && this.target.constructor.name === 'MongoClient') {\n\t\t\tthis.target.db = this._originalClientMethods.db;\n\t\t}\n\t\t\n\t\t// Emit close before removing all listeners\n\t\tthis.emit('close');\n\t\tthis.removeAllListeners();\n\t}\n\n\t/**\n\t * Check if the stream is closed\n\t */\n\tget isClosed() {\n\t\treturn this.closed;\n\t}\n\n\t/**\n\t * Async iterator support for for-await-of loops\n\t */\n\tasync *[Symbol.asyncIterator]() {\n\t\tconst queue = [];\n\t\tlet resolveNext = null;\n\t\tlet streamClosed = false;\n\t\t\n\t\tconst onChange = (change) => {\n\t\t\tif (resolveNext) {\n\t\t\t\tresolveNext({ value: change, done: false });\n\t\t\t\tresolveNext = null;\n\t\t\t} else {\n\t\t\t\tqueue.push(change);\n\t\t\t}\n\t\t};\n\t\t\n\t\tconst onClose = () => {\n\t\t\tstreamClosed = true;\n\t\t\tif (resolveNext) {\n\t\t\t\tresolveNext({ done: true });\n\t\t\t\tresolveNext = null;\n\t\t\t}\n\t\t};\n\t\t\n\t\tconst onError = (error) => {\n\t\t\tif (resolveNext) {\n\t\t\t\tresolveNext(Promise.reject(error));\n\t\t\t\tresolveNext = null;\n\t\t\t}\n\t\t};\n\t\t\n\t\tthis.on('change', onChange);\n\t\tthis.on('close', onClose);\n\t\tthis.on('error', onError);\n\t\t\n\t\ttry {\n\t\t\twhile (!streamClosed) {\n\t\t\t\tif (queue.length > 0) {\n\t\t\t\t\tyield queue.shift();\n\t\t\t\t} else {\n\t\t\t\t\tconst next = await new Promise((resolve) => {\n\t\t\t\t\t\tresolveNext = resolve;\n\t\t\t\t\t\t// Check if stream was closed while waiting\n\t\t\t\t\t\tif (streamClosed) {\n\t\t\t\t\t\t\tresolve({ done: true });\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t\t\n\t\t\t\t\tif (next.done) break;\n\t\t\t\t\tyield next.value;\n\t\t\t\t}\n\t\t\t}\n\t\t} finally {\n\t\t\tthis.off('change', onChange);\n\t\t\tthis.off('close', onClose);\n\t\t\tthis.off('error', onError);\n\t\t}\n\t}\n\n\t/**\n\t * Get next change (for compatibility)\n\t */\n\tasync next() {\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tconst onChange = (change) => {\n\t\t\t\tcleanup();\n\t\t\t\tresolve(change);\n\t\t\t};\n\t\t\t\n\t\t\tconst onClose = () => {\n\t\t\t\tcleanup();\n\t\t\t\tresolve(null);\n\t\t\t};\n\t\t\t\n\t\t\tconst onError = (error) => {\n\t\t\t\tcleanup();\n\t\t\t\treject(error);\n\t\t\t};\n\t\t\t\n\t\t\tconst cleanup = () => {\n\t\t\t\tthis.off('change', onChange);\n\t\t\t\tthis.off('close', onClose);\n\t\t\t\tthis.off('error', onError);\n\t\t\t};\n\t\t\t\n\t\t\tif (this.closed) {\n\t\t\t\tresolve(null);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t\n\t\t\tthis.once('change', onChange);\n\t\t\tthis.once('close', onClose);\n\t\t\tthis.once('error', onError);\n\t\t});\n\t}\n}\n","/**\n * Performance timing utility for tracking operation durations\n */\nexport class PerformanceTimer {\n constructor(enabled = false) {\n this.enabled = enabled;\n this.timings = [];\n this.nestedLevel = 0;\n }\n\n /**\n * Enable or disable timing collection\n */\n setEnabled(enabled) {\n this.enabled = enabled;\n }\n\n /**\n * Start timing an operation\n */\n start(category, operation, details = {}) {\n if (!this.enabled) return null;\n\n return {\n category,\n operation,\n details,\n startTime: performance.now(),\n nestedLevel: this.nestedLevel++\n };\n }\n\n /**\n * End timing an operation\n */\n end(timer, additionalDetails = {}) {\n if (!this.enabled || !timer) return;\n\n // Decrement nested level regardless of whether we record timing\n // This ensures nesting doesn't get permanently corrupted even if end() is called without valid timer\n if (this.nestedLevel > 0) {\n this.nestedLevel--;\n }\n \n const endTime = performance.now();\n const duration = endTime - timer.startTime;\n\n this.timings.push({\n category: timer.category,\n operation: timer.operation,\n duration,\n details: { ...timer.details, ...additionalDetails },\n nestedLevel: timer.nestedLevel,\n timestamp: timer.startTime\n });\n }\n\n /**\n * Get all collected timings\n */\n getTimings() {\n return this.timings;\n }\n\n /**\n * Get timings grouped by category\n */\n getTimingsByCategory() {\n const grouped = {};\n for (const timing of this.timings) {\n if (!grouped[timing.category]) {\n grouped[timing.category] = [];\n }\n grouped[timing.category].push(timing);\n }\n return grouped;\n }\n\n /**\n * Get summary statistics\n */\n getSummary() {\n const summary = {};\n \n for (const timing of this.timings) {\n const key = `${timing.category}.${timing.operation}`;\n if (!summary[key]) {\n summary[key] = {\n category: timing.category,\n operation: timing.operation,\n count: 0,\n total: 0,\n min: Infinity,\n max: -Infinity,\n avg: 0\n };\n }\n \n const stats = summary[key];\n stats.count++;\n stats.total += timing.duration;\n stats.min = Math.min(stats.min, timing.duration);\n stats.max = Math.max(stats.max, timing.duration);\n stats.avg = stats.total / stats.count;\n }\n \n return Object.values(summary);\n }\n\n /**\n * Clear all timings\n */\n clear() {\n this.timings = [];\n this.nestedLevel = 0;\n }\n\n /**\n * Format timings as a human-readable string\n */\n formatTimings() {\n const summary = this.getSummary();\n \n if (summary.length === 0) {\n return 'No timing data collected';\n }\n\n let output = '\\n' + '='.repeat(80) + '\\n';\n output += 'PERFORMANCE TIMING REPORT\\n';\n output += '='.repeat(80) + '\\n\\n';\n\n // Group by category\n const byCategory = {};\n for (const stat of summary) {\n if (!byCategory[stat.category]) {\n byCategory[stat.category] = [];\n }\n byCategory[stat.category].push(stat);\n }\n\n for (const [category, stats] of Object.entries(byCategory)) {\n output += `${category.toUpperCase()}\\n`;\n output += '-'.repeat(80) + '\\n';\n output += 'Operation'.padEnd(30) + 'Count'.padStart(8) + 'Total(ms)'.padStart(12) + \n 'Avg(ms)'.padStart(12) + 'Min(ms)'.padStart(12) + 'Max(ms)'.padStart(12) + '\\n';\n output += '-'.repeat(80) + '\\n';\n\n for (const stat of stats) {\n output += stat.operation.padEnd(30) +\n stat.count.toString().padStart(8) +\n stat.total.toFixed(3).padStart(12) +\n stat.avg.toFixed(3).padStart(12) +\n stat.min.toFixed(3).padStart(12) +\n stat.max.toFixed(3).padStart(12) + '\\n';\n }\n output += '\\n';\n }\n\n output += '='.repeat(80) + '\\n';\n return output;\n }\n}\n\n// Global instance that can be accessed from anywhere\nexport const globalTimer = new PerformanceTimer(false);\n","import { EventEmitter } from 'events';\nimport { Cursor } from './Cursor.js';\nimport { SortedCursor } from './SortedCursor.js';\nimport { isArray, getProp, applyProjection, copy } from '../utils.js';\nimport { matches, matchWithArrayIndices } from './queryMatcher.js';\nimport { applyUpdates, createDocFromUpdate } from './updates.js';\nimport { RegularCollectionIndex } from './indexes/RegularCollectionIndex.js';\nimport { TextCollectionIndex } from './indexes/TextCollectionIndex.js';\nimport { GeospatialIndex } from './indexes/GeospatialIndex.js';\nimport { QueryPlanner } from './QueryPlanner.js';\nimport { evaluateExpression } from './aggregationExpressions.js';\nimport { ChangeStream } from './ChangeStream.js';\nimport {\n acquireVersionedPath,\n buildVersionedPath,\n createSyncAccessHandle,\n DEFAULT_COMPACTION_MIN_BYTES,\n getCurrentVersion,\n promoteVersion,\n releaseVersionedPath\n} from './opfsVersioning.js';\nimport {\n NotImplementedError,\n QueryError,\n BadValueError,\n IndexError,\n IndexNotFoundError,\n ErrorCodes\n} from '../errors.js';\nimport { ObjectId } from '@belteshazzar/binjson';\nimport { BPlusTree } from '@belteshazzar/binjson/bplustree';\nimport { globalTimer } from '../PerformanceTimer.js';\n\n/**\n * Collection class\n */\nexport class Collection extends EventEmitter {\n constructor(db, name, options = {}) {\n super();\n this.db = db;\n this.name = name;\n this.path = `${this.db.baseFolder}/${this.db.dbName}/${this.name}`\n this.documentsPath = `${this.path}/documents.bj`;\n this.documentsVersionedPath = null;\n this.documentsVersion = 0;\n this._releaseDocuments = null;\n this.order = options.bPlusTreeOrder || 50; // B+ tree order\n this.documents = null; // Initialized in async _initialize()\n this.indexes = new Map(); // Index storage - map of index name to index structure\n this._initialized = false;\n this.isCollection = true; // Flag for ChangeStream to identify collections\n\n this.queryPlanner = new QueryPlanner(this.indexes); // Query planner\n }\n\n async _initialize() {\n if (this._initialized) return;\n\n if (!globalThis.navigator || !globalThis.navigator.storage || typeof globalThis.navigator.storage.getDirectory !== 'function') {\n throw new Error('OPFS not available: navigator.storage.getDirectory is missing');\n }\n\n const { version, path: versionedPath } = await acquireVersionedPath(this.documentsPath);\n this.documentsVersion = version;\n this.documentsVersionedPath = versionedPath;\n this._releaseDocuments = () => releaseVersionedPath(this.documentsPath, version);\n\n // Ensure directory exists and get directory handle\n let dirHandle = await this._ensureDirectoryForFile(this.documentsVersionedPath);\n \n // If no directory parts, use root directory\n if (!dirHandle) {\n dirHandle = await globalThis.navigator.storage.getDirectory();\n }\n \n // Get file name from path - safely extract just the filename\n const pathParts = this.documentsVersionedPath.split('/').filter(Boolean);\n const filename = pathParts[pathParts.length - 1];\n \n if (!filename) {\n throw new Error(`Invalid documents path: ${this.documentsVersionedPath}`);\n }\n \n // Get file handle and create sync access handle using native OPFS\n const fileHandle = await dirHandle.getFileHandle(filename, { create: true });\n const syncHandle = await fileHandle.createSyncAccessHandle();\n \n this.documents = new BPlusTree(syncHandle, this.order);\n await this.documents.open();\n\n await this._loadIndexes();\n\n this._initialized = true;\n }\n\n async _ensureDirectoryForFile(filePath) {\n if (!filePath) return;\n const pathParts = filePath.split('/').filter(Boolean);\n // Remove filename, keep only directory parts\n pathParts.pop();\n\n if (pathParts.length === 0) return;\n\n try {\n let dir = await globalThis.navigator.storage.getDirectory();\n for (const part of pathParts) {\n dir = await dir.getDirectoryHandle(part, { create: true });\n }\n return dir; // Return the directory handle\n } catch (error) {\n // Ignore EEXIST - directory already exists\n if (error.code !== 'EEXIST') {\n throw error;\n }\n }\n }\n\n async _loadIndexes() {\n // Scan the collection folder for persisted index files and recreate them.\n // Supported filenames:\n // <name>.textindex -> TextCollectionIndex\n // <name>.rtree.bj -> GeospatialIndex\n // <name>.bplustree.bj -> RegularCollectionIndex\n\n // Navigate to the collection directory inside OPFS\n let dirHandle;\n try {\n const parts = this.path.split('/').filter(Boolean);\n let handle = await globalThis.navigator.storage.getDirectory();\n for (const part of parts) {\n handle = await handle.getDirectoryHandle(part, { create: false });\n }\n dirHandle = handle;\n } catch (err) {\n // If the collection folder doesn't exist yet, there is nothing to load\n if (err?.name === 'NotFoundError' || err?.code === 'ENOENT') {\n return;\n }\n throw err;\n }\n\n for await (const [entryName, entryHandle] of dirHandle.entries()) {\n if (entryHandle.kind !== 'file') continue;\n\n const versionSuffixPattern = /\\.v\\d+(?=-|$)/; // Strip \".vN\" suffixes before \"-\" or end of filename.\n const normalizedName = entryName.replace(versionSuffixPattern, '');\n\n let type;\n if (normalizedName.endsWith('.textindex-documents.bj')) {\n type = 'text';\n } else if (normalizedName.endsWith('.rtree.bj')) {\n type = 'geospatial';\n } else if (normalizedName.endsWith('.bplustree.bj')) {\n type = 'regular';\n } else {\n continue; // Not an index file we understand\n }\n\n const indexName = normalizedName\n .replace(/\\.textindex-documents\\.bj$/, '')\n .replace(/\\.rtree\\.bj$/, '')\n .replace(/\\.bplustree\\.bj$/, '');\n\n // Skip if already loaded (avoid duplicates)\n if (this.indexes.has(indexName)) {\n continue;\n }\n\n const keys = this._parseIndexName(indexName, type);\n if (!keys) {\n // Can't recover keys for custom index names; skip to avoid broken indexes\n continue;\n }\n\n let index;\n if (type === 'text') {\n const storageFile = await this._getIndexPath(indexName, type);\n index = new TextCollectionIndex(indexName, keys, storageFile, {});\n } else if (type === 'geospatial') {\n const storageFile = await this._getIndexPath(indexName, type);\n index = new GeospatialIndex(indexName, keys, storageFile, {});\n } else {\n const storageFile = await this._getIndexPath(indexName, type);\n index = new RegularCollectionIndex(indexName, keys, storageFile, {});\n }\n\n try {\n await index.open();\n this.indexes.set(indexName, index);\n } catch (err) {\n // If an index file is corrupted, skip it but don't block collection init\n }\n }\n }\n\n _parseIndexName(indexName, type) {\n // Reconstruct key spec from default generated index names like \"field_1\" or \"a_1_b_-1\".\n const tokens = indexName.split('_');\n if (tokens.length < 2 || tokens.length % 2 !== 0) return null;\n\n const keys = {};\n for (let i = 0; i < tokens.length; i += 2) {\n const field = tokens[i];\n const dir = tokens[i + 1];\n\n if (!field || dir === undefined) return null;\n\n if (type === 'text' || dir === 'text') {\n keys[field] = 'text';\n } else if (type === 'geospatial' || dir === '2dsphere' || dir === '2d') {\n keys[field] = dir === '2d' ? '2d' : '2dsphere';\n } else {\n const num = Number(dir);\n if (Number.isNaN(num) || (num !== 1 && num !== -1)) {\n return null;\n }\n keys[field] = num;\n }\n }\n return keys;\n }\n\n\n /**\n * Close all indexes\n */\n async close() {\n if (!this._initialized) return;\n\n for (const [indexName, index] of this.indexes) {\n await index.close();\n }\n await this._maybeCompactDocuments();\n await this.documents.close();\n if (this._releaseDocuments) {\n await this._releaseDocuments();\n this._releaseDocuments = null;\n }\n }\n\n async _maybeCompactDocuments() {\n if (!this.documents || !this.documents.file) return;\n const currentVersion = await getCurrentVersion(this.documentsPath);\n if (currentVersion !== this.documentsVersion) return;\n const fileSize = this.documents.file.getFileSize();\n if (!fileSize || fileSize < DEFAULT_COMPACTION_MIN_BYTES) return;\n\n const nextVersion = currentVersion + 1;\n const compactPath = buildVersionedPath(this.documentsPath, nextVersion);\n const destSyncHandle = await createSyncAccessHandle(compactPath, { reset: true });\n await this.documents.compact(destSyncHandle);\n await promoteVersion(this.documentsPath, nextVersion, currentVersion);\n }\n\n /**\n * Generate index name from keys\n */\n generateIndexName(keys) {\n const parts = [];\n for (const field in keys) {\n if (keys.hasOwnProperty(field)) {\n parts.push(field + '_' + keys[field]);\n }\n }\n return parts.join('_');\n }\n\n /**\n * Determine if keys specify a text index\n */\n isTextIndex(keys) {\n for (const field in keys) {\n if (keys[field] === 'text') {\n return true;\n }\n }\n return false;\n }\n\n /**\n * Determine if keys specify a geospatial index\n */\n isGeospatialIndex(keys) {\n for (const field in keys) {\n if (keys[field] === '2dsphere' || keys[field] === '2d') {\n return true;\n }\n }\n return false;\n }\n\n async _getIndexPath(indexName, type) {\n // Create index files directly in the collection folder\n const sanitize = value => String(value).replace(/[^a-zA-Z0-9_-]/g, '_');\n const sanitizedIndexName = sanitize(indexName);\n \n if (type === 'text') {\n return `${this.path}/${sanitizedIndexName}.textindex`;\n }\n if (type === 'geospatial') {\n return `${this.path}/${sanitizedIndexName}.rtree.bj`;\n }\n // Regular index uses B+ tree\n return `${this.path}/${sanitizedIndexName}.bplustree.bj`;\n }\n\n /**\n * dist/rebuild an index\n */\n async _buildIndex(indexName, keys, options = {}) {\n if (!this._initialized) await this._initialize();\n\n let index;\n let storageFile;\n let type;\n\n // Create appropriate index type\n if (this.isTextIndex(keys)) {\n type = 'text';\n storageFile = await this._getIndexPath(indexName, type);\n index = new TextCollectionIndex(indexName, keys, storageFile, options);\n } else if (this.isGeospatialIndex(keys)) {\n type = 'geospatial';\n storageFile = await this._getIndexPath(indexName, type);\n index = new GeospatialIndex(indexName, keys, storageFile, options);\n } else {\n type = 'regular';\n storageFile = await this._getIndexPath(indexName, type);\n index = new RegularCollectionIndex(indexName, keys, storageFile, options);\n }\n\n // Open the index for use\n await index.open();\n\n // Rebuild from a clean slate to avoid stale persisted entries\n if (typeof index.clear === 'function') {\n await index.clear();\n }\n\n // Build index by scanning all documents from the B+ tree\n for await (const entry of this.documents) {\n if (entry && entry.value) {\n await index.add(entry.value);\n }\n }\n\n this.indexes.set(indexName, index);\n return index;\n }\n\n /**\n * Update indexes when a document is inserted\n */\n async updateIndexesOnInsert(doc) {\n const promises = [];\n for (const [indexName, index] of this.indexes) {\n promises.push((async () => {\n await this._ensureIndexOpen(index);\n await index.add(doc);\n })());\n }\n // Wait for all index operations to complete\n if (promises.length > 0) {\n await Promise.all(promises);\n }\n }\n\n /**\n * Update indexes when a document is deleted\n */\n async updateIndexesOnDelete(doc) {\n const promises = [];\n for (const [indexName, index] of this.indexes) {\n promises.push((async () => {\n await this._ensureIndexOpen(index);\n await index.remove(doc);\n })());\n }\n // Wait for all index operations to complete\n if (promises.length > 0) {\n await Promise.all(promises);\n }\n }\n\n /**\n * Ensure an index is open before using it\n * @private\n */\n async _ensureIndexOpen(index) {\n if (index && typeof index.open === 'function' && !index.isOpen) {\n await index.open();\n }\n }\n\n /**\n * Query planner - analyze query and determine optimal execution plan\n */\n planQuery(query) {\n const plan = this.queryPlanner.plan(query);\n // Note: With OPFS storage, indexes are async. Callers should use planQueryAsync\n // For now, we return null docIds to signal full scan\n // Actual async query execution happens via planQueryAsync\n\n return {\n useIndex: plan.type !== 'full_scan',\n planType: plan.type,\n indexNames: plan.indexes,\n docIds: null, // Force full scan for now - use planQueryAsync for index results\n estimatedCost: plan.estimatedCost,\n indexOnly: plan.indexOnly || false\n };\n }\n\n /**\n * Async version of query planner - for use with async indexes\n */\n async planQueryAsync(query) {\n const plan = this.queryPlanner.plan(query);\n const docIds = await this.queryPlanner.execute(plan);\n\n return {\n useIndex: plan.type !== 'full_scan',\n planType: plan.type,\n indexNames: plan.indexes,\n docIds: docIds,\n estimatedCost: plan.estimatedCost,\n indexOnly: plan.indexOnly || false\n };\n }\n\n /**\n * Get a text index for the given field\n * @param {string} field - The field name\n * @returns {TextCollectionIndex|null} The text index or null if not found\n */\n getTextIndex(field) {\n for (const [indexName, index] of this.indexes) {\n if (index instanceof TextCollectionIndex) {\n // Check if this field is indexed\n if (index.indexedFields.includes(field)) {\n return index;\n }\n }\n }\n return null;\n }\n\n // Collection methods\n async aggregate(pipeline) {\n const timer = globalTimer.start('collection', 'aggregate', { collection: this.name, stageCount: pipeline?.length || 0 });\n \n if (!pipeline || !isArray(pipeline)) {\n throw new QueryError('Pipeline must be an array', {\n collection: this.name,\n code: ErrorCodes.FAILED_TO_PARSE\n });\n }\n\n // Start with all documents\n const loadTimer = globalTimer.start('collection', 'aggregate.loadDocuments');\n let results = [];\n const cursor = this.find({});\n await cursor._ensureInitialized();\n // TODO: Optimize by applying $match stages during iteration\n while (await cursor.hasNext()) {\n results.push(await cursor.next());\n }\n globalTimer.end(loadTimer, { docCount: results.length });\n\n // Process each stage in the pipeline\n for (let i = 0; i < pipeline.length; i++) {\n const stage = pipeline[i];\n const stageKeys = Object.keys(stage);\n if (stageKeys.length !== 1) {\n throw new QueryError('Each pipeline stage must have exactly one key', {\n collection: this.name,\n code: ErrorCodes.FAILED_TO_PARSE\n });\n }\n const stageType = stageKeys[0];\n const stageSpec = stage[stageType];\n \n const stageTimer = globalTimer.start('collection', `aggregate.${stageType}`, { inputDocs: results.length });\n\n if (stageType === \"$match\") {\n // Filter documents based on query\n const matched = [];\n for (let j = 0; j < results.length; j++) {\n if (matches(results[j], stageSpec)) {\n matched.push(results[j]);\n }\n }\n results = matched;\n globalTimer.end(stageTimer, { outputDocs: results.length });\n } else if (stageType === \"$project\") {\n // Reshape documents with expression support\n const projected = [];\n for (let j = 0; j < results.length; j++) {\n projected.push(applyProjectionWithExpressions(stageSpec, results[j]));\n }\n results = projected;\n globalTimer.end(stageTimer, { outputDocs: results.length });\n } else if (stageType === \"$addFields\" || stageType === \"$set\") {\n // Add/set fields with computed expressions\n const modified = [];\n for (let j = 0; j < results.length; j++) {\n const doc = copy(results[j]);\n for (const field in stageSpec) {\n const expr = stageSpec[field];\n doc[field] = evaluateExpression(expr, results[j]);\n }\n modified.push(doc);\n }\n results = modified;\n globalTimer.end(stageTimer, { outputDocs: results.length });\n } else if (stageType === \"$unset\") {\n // Remove fields from documents\n const modified = [];\n // $unset can be a string (single field), array of strings, or object\n let fieldsToRemove = [];\n if (typeof stageSpec === 'string') {\n fieldsToRemove = [stageSpec];\n } else if (Array.isArray(stageSpec)) {\n fieldsToRemove = stageSpec;\n } else if (typeof stageSpec === 'object') {\n // Object form: { field1: \"\", field2: \"\" } or { field1: 1, field2: 1 }\n fieldsToRemove = Object.keys(stageSpec);\n }\n\n for (let j = 0; j < results.length; j++) {\n const doc = copy(results[j]);\n for (let k = 0; k < fieldsToRemove.length; k++) {\n const field = fieldsToRemove[k];\n // Support dot notation for nested field removal\n const pathParts = field.split('.');\n if (pathParts.length === 1) {\n delete doc[field];\n } else {\n // Navigate to parent and delete nested field\n let parent = doc;\n for (let m = 0; m < pathParts.length - 1; m++) {\n if (parent == undefined || parent == null) break;\n parent = parent[pathParts[m]];\n }\n if (parent != undefined && parent != null) {\n delete parent[pathParts[pathParts.length - 1]];\n }\n }\n }\n modified.push(doc);\n }\n results = modified;\n globalTimer.end(stageTimer, { outputDocs: results.length });\n } else if (stageType === \"$sort\") {\n // Sort documents\n const sortKeys = Object.keys(stageSpec);\n results.sort(function (a, b) {\n for (let k = 0; k < sortKeys.length; k++) {\n const key = sortKeys[k];\n if (a[key] === undefined && b[key] !== undefined) return -1 * stageSpec[key];\n if (a[key] !== undefined && b[key] === undefined) return 1 * stageSpec[key];\n if (a[key] < b[key]) return -1 * stageSpec[key];\n if (a[key] > b[key]) return 1 * stageSpec[key];\n }\n return 0;\n });\n globalTimer.end(stageTimer, { outputDocs: results.length });\n } else if (stageType === \"$limit\") {\n // Limit number of documents\n results = results.slice(0, stageSpec);\n globalTimer.end(stageTimer, { outputDocs: results.length });\n } else if (stageType === \"$skip\") {\n // Skip documents\n results = results.slice(stageSpec);\n globalTimer.end(stageTimer, { outputDocs: results.length });\n } else if (stageType === \"$group\") {\n // Group documents\n const groups = {};\n const groupId = stageSpec._id;\n\n for (let j = 0; j < results.length; j++) {\n const doc = results[j];\n let key;\n\n // Compute group key using expression evaluator\n if (groupId === null || groupId === undefined) {\n key = null;\n } else {\n key = evaluateExpression(groupId, doc);\n }\n\n const keyStr = JSON.stringify(key);\n\n // Initialize group\n if (!groups[keyStr]) {\n groups[keyStr] = {\n _id: key,\n docs: [],\n accumulators: {}\n };\n }\n\n groups[keyStr].docs.push(doc);\n }\n\n // Apply accumulators\n const grouped = [];\n for (const groupKey in groups) {\n const group = groups[groupKey];\n const result = { _id: group._id };\n\n // Process each accumulator field\n for (const field in stageSpec) {\n if (field === '_id') continue;\n\n const accumulator = stageSpec[field];\n const accKeys = Object.keys(accumulator);\n if (accKeys.length !== 1) continue;\n\n const accType = accKeys[0];\n const accExpr = accumulator[accType];\n\n if (accType === '$sum') {\n let sum = 0;\n for (let k = 0; k < group.docs.length; k++) {\n const val = evaluateExpression(accExpr, group.docs[k]);\n if (typeof val === 'number') {\n sum += val;\n } else if (val !== null && val !== undefined) {\n sum += Number(val) || 0;\n }\n }\n result[field] = sum;\n } else if (accType === '$avg') {\n let sum = 0;\n let count = 0;\n for (let k = 0; k < group.docs.length; k++) {\n const val = evaluateExpression(accExpr, group.docs[k]);\n if (val !== undefined && val !== null) {\n sum += Number(val) || 0;\n count++;\n }\n }\n result[field] = count > 0 ? sum / count : 0;\n } else if (accType === '$min') {\n let min = undefined;\n for (let k = 0; k < group.docs.length; k++) {\n const val = evaluateExpression(accExpr, group.docs[k]);\n if (val !== undefined && (min === undefined || val < min)) {\n min = val;\n }\n }\n result[field] = min;\n } else if (accType === '$max') {\n let max = undefined;\n for (let k = 0; k < group.docs.length; k++) {\n const val = evaluateExpression(accExpr, group.docs[k]);\n if (val !== undefined && (max === undefined || val > max)) {\n max = val;\n }\n }\n result[field] = max;\n } else if (accType === '$push') {\n const arr = [];\n for (let k = 0; k < group.docs.length; k++) {\n const val = evaluateExpression(accExpr, group.docs[k]);\n arr.push(val);\n }\n result[field] = arr;\n } else if (accType === '$addToSet') {\n const set = {};\n for (let k = 0; k < group.docs.length; k++) {\n const val = evaluateExpression(accExpr, group.docs[k]);\n set[JSON.stringify(val)] = val;\n }\n const arr = [];\n for (const valKey in set) {\n arr.push(set[valKey]);\n }\n result[field] = arr;\n } else if (accType === '$first') {\n if (group.docs.length > 0) {\n result[field] = evaluateExpression(accExpr, group.docs[0]);\n }\n } else if (accType === '$last') {\n if (group.docs.length > 0) {\n result[field] = evaluateExpression(accExpr, group.docs[group.docs.length - 1]);\n }\n } else if (accType === '$stdDevPop') {\n // Population standard deviation\n const values = [];\n for (let k = 0; k < group.docs.length; k++) {\n const val = evaluateExpression(accExpr, group.docs[k]);\n if (typeof val === 'number') {\n values.push(val);\n }\n }\n if (values.length > 0) {\n const mean = values.reduce((a, b) => a + b, 0) / values.length;\n const variance = values.reduce((sum, val) => sum + Math.pow(val - mean, 2), 0) / values.length;\n result[field] = Math.sqrt(variance);\n } else {\n result[field] = 0;\n }\n } else if (accType === '$stdDevSamp') {\n // Sample standard deviation\n const values = [];\n for (let k = 0; k < group.docs.length; k++) {\n const val = evaluateExpression(accExpr, group.docs[k]);\n if (typeof val === 'number') {\n values.push(val);\n }\n }\n if (values.length > 1) {\n const mean = values.reduce((a, b) => a + b, 0) / values.length;\n const variance = values.reduce((sum, val) => sum + Math.pow(val - mean, 2), 0) / (values.length - 1);\n result[field] = Math.sqrt(variance);\n } else {\n result[field] = 0;\n }\n } else if (accType === '$mergeObjects') {\n // Merge objects from all documents in group\n const merged = {};\n for (let k = 0; k < group.docs.length; k++) {\n const val = evaluateExpression(accExpr, group.docs[k]);\n if (typeof val === 'object' && val !== null && !Array.isArray(val)) {\n Object.assign(merged, val);\n }\n }\n result[field] = merged;\n }\n }\n\n grouped.push(result);\n }\n results = grouped;\n globalTimer.end(stageTimer, { outputDocs: results.length, groupCount: Object.keys(groups).length });\n } else if (stageType === \"$count\") {\n // Count documents and return single document with count\n results = [{ [stageSpec]: results.length }];\n globalTimer.end(stageTimer, { outputDocs: results.length });\n } else if (stageType === \"$unwind\") {\n // Unwind array field\n const unwound = [];\n let fieldPath = stageSpec;\n if (typeof fieldPath === 'string' && fieldPath.charAt(0) === '$') {\n fieldPath = fieldPath.substring(1);\n }\n\n for (let j = 0; j < results.length; j++) {\n const doc = results[j];\n const arr = getProp(doc, fieldPath);\n\n if (arr && isArray(arr) && arr.length > 0) {\n for (let k = 0; k < arr.length; k++) {\n const unwoundDoc = copy(doc);\n // Set the unwound value\n const parts = fieldPath.split('.');\n let target = unwoundDoc;\n for (let l = 0; l < parts.length - 1; l++) {\n if (!target[parts[l]]) {\n target[parts[l]] = {};\n }\n target = target[parts[l]];\n }\n target[parts[parts.length - 1]] = arr[k];\n unwound.push(unwoundDoc);\n }\n }\n // MongoDB's default behavior: skip documents where field is missing, null, empty array, or not an array\n }\n results = unwound;\n globalTimer.end(stageTimer, { outputDocs: results.length });\n } else if (stageType === \"$sortByCount\") {\n // Group by expression value and count occurrences, sorted descending by count\n const groups = {};\n\n for (let j = 0; j < results.length; j++) {\n const doc = results[j];\n const value = evaluateExpression(stageSpec, doc);\n const key = JSON.stringify(value);\n\n if (!groups[key]) {\n groups[key] = {\n _id: value,\n count: 0\n };\n }\n groups[key].count++;\n }\n\n // Convert to array and sort by count descending\n results = Object.values(groups).sort((a, b) => b.count - a.count);\n } else if (stageType === \"$replaceRoot\" || stageType === \"$replaceWith\") {\n // Replace root document with specified document\n const modified = [];\n const newRootSpec = stageType === \"$replaceRoot\" ? stageSpec.newRoot : stageSpec;\n\n for (let j = 0; j < results.length; j++) {\n const newRoot = evaluateExpression(newRootSpec, results[j]);\n if (typeof newRoot === 'object' && newRoot !== null && !Array.isArray(newRoot)) {\n modified.push(newRoot);\n } else {\n throw new QueryError('$replaceRoot expression must evaluate to an object', {\n collection: this.name,\n code: ErrorCodes.FAILED_TO_PARSE\n });\n }\n }\n results = modified;\n } else if (stageType === \"$sample\") {\n // Random sampling of documents\n const size = stageSpec.size || 1;\n if (typeof size !== 'number' || size < 0) {\n throw new QueryError('$sample size must be a non-negative number', {\n collection: this.name,\n code: ErrorCodes.FAILED_TO_PARSE\n });\n }\n\n // Shuffle using Fisher-Yates algorithm and take first 'size' elements\n const shuffled = [...results];\n for (let j = shuffled.length - 1; j > 0; j--) {\n const k = Math.floor(Math.random() * (j + 1));\n [shuffled[j], shuffled[k]] = [shuffled[k], shuffled[j]];\n }\n results = shuffled.slice(0, Math.min(size, shuffled.length));\n } else if (stageType === \"$bucket\") {\n // Categorize documents into buckets based on boundaries\n if (!stageSpec.groupBy || !stageSpec.boundaries) {\n throw new QueryError('$bucket requires groupBy and boundaries', {\n collection: this.name,\n code: ErrorCodes.FAILED_TO_PARSE\n });\n }\n\n const boundaries = stageSpec.boundaries;\n const defaultBucket = stageSpec.default;\n const output = stageSpec.output || { count: { $sum: 1 } };\n\n // Initialize buckets\n const buckets = {};\n for (let j = 0; j < boundaries.length - 1; j++) {\n const key = JSON.stringify(boundaries[j]);\n buckets[key] = {\n _id: boundaries[j],\n docs: []\n };\n }\n if (defaultBucket !== undefined) {\n buckets['default'] = {\n _id: defaultBucket,\n docs: []\n };\n }\n\n // Categorize documents into buckets\n for (let j = 0; j < results.length; j++) {\n const doc = results[j];\n const value = evaluateExpression(stageSpec.groupBy, doc);\n\n let placed = false;\n for (let k = 0; k < boundaries.length - 1; k++) {\n if (value >= boundaries[k] && value < boundaries[k + 1]) {\n const key = JSON.stringify(boundaries[k]);\n buckets[key].docs.push(doc);\n placed = true;\n break;\n }\n }\n\n if (!placed && defaultBucket !== undefined) {\n buckets['default'].docs.push(doc);\n }\n }\n\n // Apply output accumulators\n const bucketed = [];\n for (const bucketKey in buckets) {\n const bucket = buckets[bucketKey];\n if (bucket.docs.length === 0) continue; // Skip empty buckets\n\n const result = { _id: bucket._id };\n\n for (const field in output) {\n const accumulator = output[field];\n const accKeys = Object.keys(accumulator);\n if (accKeys.length !== 1) continue;\n\n const accType = accKeys[0];\n const accExpr = accumulator[accType];\n\n // Apply accumulator (reuse $group logic)\n if (accType === '$sum') {\n let sum = 0;\n for (let k = 0; k < bucket.docs.length; k++) {\n const val = evaluateExpression(accExpr, bucket.docs[k]);\n if (typeof val === 'number') {\n sum += val;\n } else if (val !== null && val !== undefined) {\n sum += Number(val) || 0;\n }\n }\n result[field] = sum;\n } else if (accType === '$avg') {\n let sum = 0;\n let count = 0;\n for (let k = 0; k < bucket.docs.length; k++) {\n const val = evaluateExpression(accExpr, bucket.docs[k]);\n if (val !== undefined && val !== null) {\n sum += Number(val) || 0;\n count++;\n }\n }\n result[field] = count > 0 ? sum / count : 0;\n } else if (accType === '$push') {\n const arr = [];\n for (let k = 0; k < bucket.docs.length; k++) {\n const val = evaluateExpression(accExpr, bucket.docs[k]);\n arr.push(val);\n }\n result[field] = arr;\n } else if (accType === '$addToSet') {\n const set = {};\n for (let k = 0; k < bucket.docs.length; k++) {\n const val = evaluateExpression(accExpr, bucket.docs[k]);\n set[JSON.stringify(val)] = val;\n }\n result[field] = Object.values(set);\n }\n }\n\n bucketed.push(result);\n }\n\n // Sort by _id (bucket boundary)\n results = bucketed.sort((a, b) => {\n if (a._id < b._id) return -1;\n if (a._id > b._id) return 1;\n return 0;\n });\n } else if (stageType === \"$bucketAuto\") {\n // Auto-calculate bucket boundaries and categorize documents\n if (!stageSpec.groupBy || !stageSpec.buckets) {\n throw new QueryError('$bucketAuto requires groupBy and buckets', {\n collection: this.name,\n code: ErrorCodes.FAILED_TO_PARSE\n });\n }\n\n const numBuckets = stageSpec.buckets;\n const output = stageSpec.output || { count: { $sum: 1 } };\n\n if (results.length === 0) {\n results = [];\n } else {\n // Extract and sort values\n const values = results.map(doc => ({\n value: evaluateExpression(stageSpec.groupBy, doc),\n doc: doc\n })).sort((a, b) => {\n if (a.value < b.value) return -1;\n if (a.value > b.value) return 1;\n return 0;\n });\n\n // Calculate bucket size\n const bucketSize = Math.ceil(values.length / numBuckets);\n const buckets = [];\n\n for (let j = 0; j < numBuckets && j * bucketSize < values.length; j++) {\n const startIdx = j * bucketSize;\n const endIdx = Math.min((j + 1) * bucketSize, values.length);\n const bucketDocs = values.slice(startIdx, endIdx);\n\n if (bucketDocs.length === 0) continue;\n\n const bucket = {\n _id: {\n min: bucketDocs[0].value,\n max: endIdx < values.length ? bucketDocs[bucketDocs.length - 1].value : bucketDocs[bucketDocs.length - 1].value\n },\n docs: bucketDocs.map(v => v.doc)\n };\n buckets.push(bucket);\n }\n\n // Apply output accumulators\n const bucketed = [];\n for (let j = 0; j < buckets.length; j++) {\n const bucket = buckets[j];\n const result = { _id: bucket._id };\n\n for (const field in output) {\n const accumulator = output[field];\n const accKeys = Object.keys(accumulator);\n if (accKeys.length !== 1) continue;\n\n const accType = accKeys[0];\n const accExpr = accumulator[accType];\n\n if (accType === '$sum') {\n let sum = 0;\n for (let k = 0; k < bucket.docs.length; k++) {\n const val = evaluateExpression(accExpr, bucket.docs[k]);\n if (typeof val === 'number') {\n sum += val;\n } else if (val !== null && val !== undefined) {\n sum += Number(val) || 0;\n }\n }\n result[field] = sum;\n } else if (accType === '$avg') {\n let sum = 0;\n let count = 0;\n for (let k = 0; k < bucket.docs.length; k++) {\n const val = evaluateExpression(accExpr, bucket.docs[k]);\n if (val !== undefined && val !== null) {\n sum += Number(val) || 0;\n count++;\n }\n }\n result[field] = count > 0 ? sum / count : 0;\n } else if (accType === '$push') {\n const arr = [];\n for (let k = 0; k < bucket.docs.length; k++) {\n const val = evaluateExpression(accExpr, bucket.docs[k]);\n arr.push(val);\n }\n result[field] = arr;\n }\n }\n\n bucketed.push(result);\n }\n\n results = bucketed;\n }\n } else if (stageType === \"$out\") {\n // Output results to a collection (replaces existing collection)\n const targetCollectionName = stageSpec;\n\n if (typeof targetCollectionName !== 'string') {\n throw new QueryError('$out requires a string collection name', {\n collection: this.name,\n code: ErrorCodes.FAILED_TO_PARSE\n });\n }\n\n // Drop target collection if it exists\n if (this.db.collections.has(targetCollectionName)) {\n await this.db.dropCollection(targetCollectionName);\n }\n\n // Access collection via proxy (will auto-create)\n const targetCollection = this.db[targetCollectionName];\n\n // Insert all results into target collection\n for (let j = 0; j < results.length; j++) {\n const doc = results[j];\n const docId = doc._id;\n const key = (typeof docId === 'object' && docId.toString) ? docId.toString() : String(docId);\n await targetCollection.insertOne(doc);\n }\n\n // $out returns empty results (MongoDB behavior)\n results = [];\n } else if (stageType === \"$merge\") {\n // Merge results into a collection (MongoDB 4.2+)\n let targetCollectionName;\n let on = '_id';\n let whenMatched = 'merge';\n let whenNotMatched = 'insert';\n\n if (typeof stageSpec === 'string') {\n targetCollectionName = stageSpec;\n } else if (typeof stageSpec === 'object') {\n targetCollectionName = stageSpec.into;\n on = stageSpec.on || on;\n whenMatched = stageSpec.whenMatched || whenMatched;\n whenNotMatched = stageSpec.whenNotMatched || whenNotMatched;\n }\n\n if (!targetCollectionName) {\n throw new QueryError('$merge requires a target collection', {\n collection: this.name,\n code: ErrorCodes.FAILED_TO_PARSE\n });\n }\n\n // Access collection via proxy (will auto-create if needed)\n const targetCollection = this.db[targetCollectionName];\n\n // Merge documents\n for (let j = 0; j < results.length; j++) {\n const doc = results[j];\n const matchField = typeof on === 'string' ? on : on[0];\n const matchValue = getProp(doc, matchField);\n\n // Find existing document\n const existingCursor = targetCollection.find({ [matchField]: matchValue });\n await existingCursor._ensureInitialized();\n const existing = await existingCursor.hasNext() ? await existingCursor.next() : null;\n\n if (existing) {\n if (whenMatched === 'replace') {\n await targetCollection.replaceOne({ _id: existing._id }, doc);\n } else if (whenMatched === 'merge') {\n const merged = Object.assign({}, existing, doc);\n await targetCollection.replaceOne({ _id: existing._id }, merged);\n } else if (whenMatched === 'keepExisting') {\n // Do nothing\n } else if (whenMatched === 'fail') {\n throw new QueryError('$merge failed: duplicate key', {\n collection: this.name,\n code: ErrorCodes.DUPLICATE_KEY\n });\n }\n } else {\n if (whenNotMatched === 'insert') {\n await targetCollection.insertOne(doc);\n } else if (whenNotMatched === 'discard') {\n // Do nothing\n } else if (whenNotMatched === 'fail') {\n throw new QueryError('$merge failed: document not found', {\n collection: this.name,\n code: ErrorCodes.FAILED_TO_PARSE\n });\n }\n }\n }\n\n // $merge returns empty results (MongoDB behavior)\n results = [];\n } else if (stageType === \"$lookup\") {\n // Left outer join with another collection\n if (!stageSpec.from || !stageSpec.localField || !stageSpec.foreignField || !stageSpec.as) {\n throw new QueryError('$lookup requires from, localField, foreignField, and as', {\n collection: this.name,\n code: ErrorCodes.FAILED_TO_PARSE\n });\n }\n\n // Check if collection exists without triggering auto-creation\n const collectionNames = this.db.getCollectionNames();\n if (!collectionNames.includes(stageSpec.from)) {\n throw new QueryError('$lookup: collection not found: ' + stageSpec.from, {\n collection: this.name,\n code: ErrorCodes.NAMESPACE_NOT_FOUND\n });\n }\n\n const fromCollection = this.db[stageSpec.from];\n\n const joined = [];\n for (let j = 0; j < results.length; j++) {\n const doc = copy(results[j]);\n const localValue = getProp(doc, stageSpec.localField);\n\n // Find matching documents in foreign collection\n const matches = [];\n const foreignCursor = fromCollection.find({ [stageSpec.foreignField]: localValue });\n await foreignCursor._ensureInitialized();\n while (await foreignCursor.hasNext()) {\n matches.push(await foreignCursor.next());\n }\n\n doc[stageSpec.as] = matches;\n joined.push(doc);\n }\n results = joined;\n } else if (stageType === \"$graphLookup\") {\n // Recursive graph lookup\n if (!stageSpec.from || !stageSpec.startWith || !stageSpec.connectFromField ||\n !stageSpec.connectToField || !stageSpec.as) {\n throw new QueryError('$graphLookup requires from, startWith, connectFromField, connectToField, and as', {\n collection: this.name,\n code: ErrorCodes.FAILED_TO_PARSE\n });\n }\n\n // Check if collection exists without triggering auto-creation\n const collectionNames = this.db.getCollectionNames();\n if (!collectionNames.includes(stageSpec.from)) {\n throw new QueryError('$graphLookup: collection not found: ' + stageSpec.from, {\n collection: this.name,\n code: ErrorCodes.NAMESPACE_NOT_FOUND\n });\n }\n\n const fromCollection = this.db[stageSpec.from];\n\n const maxDepth = stageSpec.maxDepth !== undefined ? stageSpec.maxDepth : Number.MAX_SAFE_INTEGER;\n const depthField = stageSpec.depthField;\n const restrictSearchWithMatch = stageSpec.restrictSearchWithMatch;\n\n const graphed = [];\n for (let j = 0; j < results.length; j++) {\n const doc = copy(results[j]);\n const startValue = evaluateExpression(stageSpec.startWith, results[j]);\n\n // Recursive lookup\n const visited = new Set();\n const matches = [];\n const queue = [{ value: startValue, depth: 0 }];\n\n while (queue.length > 0) {\n const { value, depth } = queue.shift();\n if (depth > maxDepth) continue;\n\n const valueKey = JSON.stringify(value);\n if (visited.has(valueKey)) continue;\n visited.add(valueKey);\n\n // Find matching documents\n let query = { [stageSpec.connectToField]: value };\n if (restrictSearchWithMatch) {\n query = { $and: [query, restrictSearchWithMatch] };\n }\n\n const cursor = fromCollection.find(query);\n await cursor._ensureInitialized();\n while (await cursor.hasNext()) {\n const match = await cursor.next();\n const matchCopy = copy(match);\n\n if (depthField) {\n matchCopy[depthField] = depth;\n }\n\n matches.push(matchCopy);\n\n // Add connected value to queue for next iteration\n const nextValue = getProp(match, stageSpec.connectFromField);\n if (nextValue !== undefined && nextValue !== null) {\n queue.push({ value: nextValue, depth: depth + 1 });\n }\n }\n }\n\n doc[stageSpec.as] = matches;\n graphed.push(doc);\n }\n results = graphed;\n } else if (stageType === \"$facet\") {\n // Multiple parallel pipelines\n if (typeof stageSpec !== 'object' || Array.isArray(stageSpec)) {\n throw new QueryError('$facet requires an object with pipeline definitions', {\n collection: this.name,\n code: ErrorCodes.FAILED_TO_PARSE\n });\n }\n\n const facetResult = {};\n\n for (const facetName in stageSpec) {\n const facetPipeline = stageSpec[facetName];\n\n if (!Array.isArray(facetPipeline)) {\n throw new QueryError('$facet pipeline must be an array', {\n collection: this.name,\n code: ErrorCodes.FAILED_TO_PARSE\n });\n }\n\n // Execute the sub-pipeline on a copy of current results\n let facetResults = results.map(r => copy(r));\n\n for (let k = 0; k < facetPipeline.length; k++) {\n const facetStage = facetPipeline[k];\n const facetStageKeys = Object.keys(facetStage);\n if (facetStageKeys.length !== 1) {\n throw new QueryError('Each pipeline stage must have exactly one key', {\n collection: this.name,\n code: ErrorCodes.FAILED_TO_PARSE\n });\n }\n\n const facetStageType = facetStageKeys[0];\n const facetStageSpec = facetStage[facetStageType];\n\n // Process facet stage (recursive call to aggregation logic)\n // We need to inline the stage processing here\n if (facetStageType === \"$match\") {\n const matched = [];\n for (let m = 0; m < facetResults.length; m++) {\n if (matches(facetResults[m], facetStageSpec)) {\n matched.push(facetResults[m]);\n }\n }\n facetResults = matched;\n } else if (facetStageType === \"$project\") {\n const projected = [];\n for (let m = 0; m < facetResults.length; m++) {\n projected.push(applyProjectionWithExpressions(facetStageSpec, facetResults[m]));\n }\n facetResults = projected;\n } else if (facetStageType === \"$limit\") {\n facetResults = facetResults.slice(0, facetStageSpec);\n } else if (facetStageType === \"$skip\") {\n facetResults = facetResults.slice(facetStageSpec);\n } else if (facetStageType === \"$sort\") {\n const sortKeys = Object.keys(facetStageSpec);\n facetResults.sort(function (a, b) {\n for (let n = 0; n < sortKeys.length; n++) {\n const key = sortKeys[n];\n if (a[key] === undefined && b[key] !== undefined) return -1 * facetStageSpec[key];\n if (a[key] !== undefined && b[key] === undefined) return 1 * facetStageSpec[key];\n if (a[key] < b[key]) return -1 * facetStageSpec[key];\n if (a[key] > b[key]) return 1 * facetStageSpec[key];\n }\n return 0;\n });\n } else if (facetStageType === \"$count\") {\n facetResults = [{ [facetStageSpec]: facetResults.length }];\n } else if (facetStageType === \"$group\") {\n // Handle $group in facet sub-pipelines\n const groups = {};\n const groupId = facetStageSpec._id;\n\n for (let m = 0; m < facetResults.length; m++) {\n const doc = facetResults[m];\n let key;\n\n if (groupId === null || groupId === undefined) {\n key = null;\n } else {\n key = evaluateExpression(groupId, doc);\n }\n\n const keyStr = JSON.stringify(key);\n\n if (!groups[keyStr]) {\n groups[keyStr] = {\n _id: key,\n docs: [],\n accumulators: {}\n };\n }\n\n groups[keyStr].docs.push(doc);\n }\n\n // Apply accumulators (simplified version)\n const grouped = [];\n for (const groupKey in groups) {\n const group = groups[groupKey];\n const result = { _id: group._id };\n\n for (const field in facetStageSpec) {\n if (field === '_id') continue;\n\n const accumulator = facetStageSpec[field];\n const accKeys = Object.keys(accumulator);\n if (accKeys.length !== 1) continue;\n\n const accType = accKeys[0];\n const accExpr = accumulator[accType];\n\n if (accType === '$sum') {\n let sum = 0;\n for (let n = 0; n < group.docs.length; n++) {\n const val = evaluateExpression(accExpr, group.docs[n]);\n if (typeof val === 'number') {\n sum += val;\n } else if (val !== null && val !== undefined) {\n sum += Number(val) || 0;\n }\n }\n result[field] = sum;\n } else if (accType === '$avg') {\n let sum = 0;\n let count = 0;\n for (let n = 0; n < group.docs.length; n++) {\n const val = evaluateExpression(accExpr, group.docs[n]);\n if (val !== undefined && val !== null) {\n sum += Number(val) || 0;\n count++;\n }\n }\n result[field] = count > 0 ? sum / count : 0;\n } else if (accType === '$max') {\n let max = undefined;\n for (let n = 0; n < group.docs.length; n++) {\n const val = evaluateExpression(accExpr, group.docs[n]);\n if (val !== undefined && (max === undefined || val > max)) {\n max = val;\n }\n }\n result[field] = max;\n }\n }\n\n grouped.push(result);\n }\n facetResults = grouped;\n } else if (facetStageType === \"$sortByCount\") {\n // Handle $sortByCount in facet sub-pipelines\n const groups = {};\n\n for (let m = 0; m < facetResults.length; m++) {\n const doc = facetResults[m];\n const value = evaluateExpression(facetStageSpec, doc);\n const key = JSON.stringify(value);\n\n if (!groups[key]) {\n groups[key] = {\n _id: value,\n count: 0\n };\n }\n groups[key].count++;\n }\n\n facetResults = Object.values(groups).sort((a, b) => b.count - a.count);\n } else if (facetStageType === \"$sample\") {\n // Handle $sample in facet sub-pipelines\n const size = facetStageSpec.size || 1;\n const shuffled = [...facetResults];\n for (let m = shuffled.length - 1; m > 0; m--) {\n const k = Math.floor(Math.random() * (m + 1));\n [shuffled[m], shuffled[k]] = [shuffled[k], shuffled[m]];\n }\n facetResults = shuffled.slice(0, Math.min(size, shuffled.length));\n } else if (facetStageType === \"$bucket\") {\n // Handle $bucket in facet sub-pipelines\n const boundaries = facetStageSpec.boundaries;\n const defaultBucket = facetStageSpec.default;\n const output = facetStageSpec.output || { count: { $sum: 1 } };\n\n const buckets = {};\n for (let m = 0; m < boundaries.length - 1; m++) {\n const key = JSON.stringify(boundaries[m]);\n buckets[key] = {\n _id: boundaries[m],\n docs: []\n };\n }\n if (defaultBucket !== undefined) {\n buckets['default'] = {\n _id: defaultBucket,\n docs: []\n };\n }\n\n // Categorize documents\n for (let m = 0; m < facetResults.length; m++) {\n const doc = facetResults[m];\n const value = evaluateExpression(facetStageSpec.groupBy, doc);\n\n let placed = false;\n for (let n = 0; n < boundaries.length - 1; n++) {\n if (value >= boundaries[n] && value < boundaries[n + 1]) {\n const key = JSON.stringify(boundaries[n]);\n buckets[key].docs.push(doc);\n placed = true;\n break;\n }\n }\n\n if (!placed && defaultBucket !== undefined) {\n buckets['default'].docs.push(doc);\n }\n }\n\n // Apply accumulators\n const bucketed = [];\n for (const bucketKey in buckets) {\n const bucket = buckets[bucketKey];\n if (bucket.docs.length === 0) continue;\n\n const result = { _id: bucket._id };\n\n for (const field in output) {\n const accumulator = output[field];\n const accKeys = Object.keys(accumulator);\n if (accKeys.length !== 1) continue;\n\n const accType = accKeys[0];\n const accExpr = accumulator[accType];\n\n if (accType === '$sum') {\n let sum = 0;\n for (let n = 0; n < bucket.docs.length; n++) {\n const val = evaluateExpression(accExpr, bucket.docs[n]);\n if (typeof val === 'number') {\n sum += val;\n } else if (val !== null && val !== undefined) {\n sum += Number(val) || 0;\n }\n }\n result[field] = sum;\n }\n }\n\n bucketed.push(result);\n }\n\n facetResults = bucketed.sort((a, b) => {\n if (a._id < b._id) return -1;\n if (a._id > b._id) return 1;\n return 0;\n });\n }\n // Add more stage types as needed for facet sub-pipelines\n }\n\n facetResult[facetName] = facetResults;\n }\n\n results = [facetResult];\n } else if (stageType === \"$redact\") {\n // Conditionally filter or redact document content\n const redacted = [];\n\n for (let j = 0; j < results.length; j++) {\n const doc = results[j];\n const decision = evaluateExpression(stageSpec, doc);\n\n if (decision === '$$DESCEND') {\n // Include document and recurse into subdocuments (simplified: just include)\n redacted.push(doc);\n } else if (decision === '$$PRUNE') {\n // Exclude this document\n continue;\n } else if (decision === '$$KEEP') {\n // Include this document\n redacted.push(doc);\n } else {\n // If result is a conditional expression, evaluate it\n if (decision) {\n redacted.push(doc);\n }\n }\n }\n results = redacted;\n } else if (stageType === \"$geoNear\") {\n // Geospatial aggregation with distance calculation\n if (!stageSpec.near || !stageSpec.distanceField) {\n throw new QueryError('$geoNear requires near and distanceField', {\n collection: this.name,\n code: ErrorCodes.FAILED_TO_PARSE\n });\n }\n\n const near = stageSpec.near;\n const distanceField = stageSpec.distanceField;\n const maxDistance = stageSpec.maxDistance;\n const minDistance = stageSpec.minDistance || 0;\n const spherical = stageSpec.spherical !== false;\n const key = stageSpec.key || 'location';\n\n // Calculate distance for each document\n const withDistances = [];\n for (let j = 0; j < results.length; j++) {\n const doc = copy(results[j]);\n const location = getProp(doc, key);\n\n if (!location || !Array.isArray(location) || location.length < 2) {\n continue;\n }\n\n // Calculate distance (using Haversine formula for spherical or Euclidean for planar)\n let distance;\n if (spherical) {\n // Haversine formula for great circle distance\n const R = 6371000; // Earth radius in meters\n const lat1 = near[1] * Math.PI / 180;\n const lat2 = location[1] * Math.PI / 180;\n const deltaLat = (location[1] - near[1]) * Math.PI / 180;\n const deltaLon = (location[0] - near[0]) * Math.PI / 180;\n\n const a = Math.sin(deltaLat / 2) * Math.sin(deltaLat / 2) +\n Math.cos(lat1) * Math.cos(lat2) *\n Math.sin(deltaLon / 2) * Math.sin(deltaLon / 2);\n const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));\n distance = R * c;\n } else {\n // Euclidean distance\n const dx = location[0] - near[0];\n const dy = location[1] - near[1];\n distance = Math.sqrt(dx * dx + dy * dy);\n }\n\n // Filter by distance\n if (distance >= minDistance && (!maxDistance || distance <= maxDistance)) {\n doc[distanceField] = distance;\n withDistances.push(doc);\n }\n }\n\n // Sort by distance (nearest first)\n withDistances.sort((a, b) => a[distanceField] - b[distanceField]);\n\n // Apply limit if specified\n if (stageSpec.limit) {\n results = withDistances.slice(0, stageSpec.limit);\n } else {\n results = withDistances;\n }\n \n globalTimer.end(stageTimer, { outputDocs: results.length });\n } else {\n globalTimer.end(stageTimer, { error: true, stageType });\n throw new QueryError('Unsupported aggregation stage: ' + stageType, {\n collection: this.name,\n code: ErrorCodes.FAILED_TO_PARSE\n });\n }\n }\n\n globalTimer.end(timer, { resultCount: results.length });\n return results;\n }\n\n async bulkWrite() { throw new NotImplementedError('bulkWrite', { collection: this.name }); }\n\n async count() {\n if (!this._initialized) await this._initialize();\n\n let count = 0;\n for await (const _ of this.documents) {\n count++;\n }\n return count;\n }\n\n async copyTo(destCollectionName) {\n // Create the destination collection explicitly to ensure it's registered\n this.db.createCollection(destCollectionName);\n const destCol = this.db.getCollection(destCollectionName);\n let numCopied = 0;\n const c = this.find({});\n await c._ensureInitialized();\n while (await c.hasNext()) {\n await destCol.insertOne(await c.next());\n numCopied++;\n }\n\n return numCopied;\n }\n\n async createIndex(keys, options) {\n if (!this._initialized) await this._initialize();\n\n // MongoDB-compliant createIndex\n // keys: { fieldName: 1 } for ascending, { fieldName: -1 } for descending, { fieldName: 'text' } for text\n // options: { name: \"indexName\", unique: true, ... }\n\n if (!keys || typeof keys !== 'object' || Array.isArray(keys)) {\n throw new BadValueError('keys', keys, 'createIndex requires a key specification object', {\n collection: this.name\n });\n }\n\n const indexName = (options && options.name) ? options.name : this.generateIndexName(keys);\n\n // Check if index already exists\n if (this.indexes.has(indexName)) {\n // MongoDB checks for key specification conflicts\n const existingIndex = this.indexes.get(indexName);\n const existingKeys = JSON.stringify(existingIndex.keys);\n const newKeys = JSON.stringify(keys);\n if (existingKeys !== newKeys) {\n throw new IndexError(\n \"Index with name '\" + indexName + \"' already exists with a different key specification\",\n {\n code: ErrorCodes.INDEX_OPTIONS_CONFLICT,\n index: indexName,\n collection: this.name\n }\n );\n }\n // Same index, return without error\n return indexName;\n }\n\n // Build the index\n await this._buildIndex(indexName, keys, options);\n\n return indexName;\n }\n\n dataSize() { throw new NotImplementedError('dataSize', { collection: this.name }); }\n\n async deleteOne(query) {\n const doc = await this.findOne(query);\n if (doc) {\n await this.updateIndexesOnDelete(doc);\n await this.documents.delete(doc._id.toString());\n this.emit('delete', { _id: doc._id });\n return { deletedCount: 1 };\n } else {\n return { deletedCount: 0 };\n }\n }\n\n async deleteMany(query) {\n const c = this.find(query);\n await c._ensureInitialized();\n const ids = [];\n const docs = [];\n while (await c.hasNext()) {\n const doc = await c.next();\n ids.push(doc._id);\n docs.push(doc);\n }\n const deletedCount = ids.length;\n for (let i = 0; i < ids.length; i++) {\n await this.updateIndexesOnDelete(docs[i]);\n this.documents.delete(ids[i].toString());\n this.emit('delete', { _id: ids[i] });\n }\n return { deletedCount: deletedCount };\n }\n\n async distinct(field, query) {\n const vals = {};\n const c = this.find(query);\n await c._ensureInitialized();\n while (await c.hasNext()) {\n const d = await c.next();\n if (d[field]) {\n vals[d[field]] = true;\n }\n }\n return Object.keys(vals);\n }\n\n async drop() {\n if (!this._initialized) await this._initialize();\n\n // Close all indexes first\n for (const [indexName, index] of this.indexes) {\n if (index && typeof index.close === 'function') {\n await index.close();\n }\n }\n\n // Close the documents B+ tree\n if (this.documents && typeof this.documents.close === 'function') {\n await this.documents.close();\n }\n if (this._releaseDocuments) {\n await this._releaseDocuments();\n this._releaseDocuments = null;\n }\n\n // Explicitly delete all files in the collection directory before removing it\n // This ensures proper cleanup in OPFS environments\n try {\n const pathParts = this.path.split('/').filter(Boolean);\n let collectionDir = await globalThis.navigator.storage.getDirectory();\n \n // Navigate to collection directory\n for (const part of pathParts) {\n collectionDir = await collectionDir.getDirectoryHandle(part, { create: false });\n }\n\n // Delete all files in the directory\n const entriesToDelete = [];\n for await (const [entryName, entryHandle] of collectionDir.entries()) {\n entriesToDelete.push(entryName);\n }\n \n for (const entryName of entriesToDelete) {\n try {\n await collectionDir.removeEntry(entryName, { recursive: false });\n } catch (e) {\n // Continue deleting other files even if one fails\n }\n }\n } catch (error) {\n // Directory might not exist yet if collection was never initialized\n }\n\n // Now remove the collection directory itself\n const pathParts = this.path.split('/').filter(Boolean);\n const filename = pathParts.pop();\n\n try {\n let dir = await globalThis.navigator.storage.getDirectory();\n for (const part of pathParts) {\n dir = await dir.getDirectoryHandle(part, { create: false });\n }\n // Try recursive removal first\n try {\n await dir.removeEntry(filename, { recursive: true });\n } catch (e) {\n // If recursive not supported, try non-recursive (should work now that directory is empty)\n if (e.name === 'TypeError' || e.message?.includes('recursive')) {\n await dir.removeEntry(filename);\n } else {\n throw e;\n }\n }\n } catch (error) {\n // Directory might not exist yet if collection was never initialized\n if (error.name !== 'NotFoundError' && error.code !== 'ENOENT') {\n throw error;\n }\n }\n\n // Clear state\n this.documents = null;\n this.indexes.clear();\n this._initialized = false;\n\n // remove from db's collection list\n this.db.collections.delete(this.name);\n\n this.emit('drop', { collection: this.name });\n return { ok: 1 };\n }\n\n async dropIndex(indexName) {\n if (!this.indexes.has(indexName)) {\n throw new IndexNotFoundError(indexName, { collection: this.name });\n }\n\n const index = this.indexes.get(indexName);\n if (index && typeof index.clear === 'function') {\n await index.clear();\n }\n if (index && typeof index.close === 'function') {\n await index.close();\n }\n\n this.indexes.delete(indexName);\n return { nIndexesWas: this.indexes.size + 1, ok: 1 };\n }\n\n async dropIndexes() {\n const count = this.indexes.size;\n for (const [_, index] of this.indexes) {\n if (index && typeof index.clear === 'function') {\n await index.clear();\n }\n if (index && typeof index.close === 'function') {\n await index.close();\n }\n }\n this.indexes.clear();\n return { nIndexesWas: count, msg: \"non-_id indexes dropped\", ok: 1 };\n }\n ensureIndex() { throw new NotImplementedError('ensureIndex', { collection: this.name }); }\n explain() { throw new NotImplementedError('explain', { collection: this.name }); }\n\n find(query, projection) {\n this._validateProjection(projection);\n // Return cursor immediately with promise for documents\n const documentsPromise = this._findInternal(query, projection);\n return new Cursor(\n this,\n query,\n projection,\n documentsPromise,\n SortedCursor\n );\n }\n\n _validateProjection(projection) {\n if (!projection || Object.keys(projection).length === 0) return;\n\n const keys = Object.keys(projection);\n let hasInclusion = false;\n let hasExclusion = false;\n\n for (const key of keys) {\n if (key === '_id') continue; // _id can appear with either style\n if (projection[key]) hasInclusion = true; else hasExclusion = true;\n if (hasInclusion && hasExclusion) break;\n }\n\n if (hasInclusion && hasExclusion) {\n throw new QueryError(\"Cannot do exclusion on field in inclusion projection\", {\n code: ErrorCodes.CANNOT_DO_EXCLUSION_ON_FIELD_ID_IN_INCLUSION_PROJECTION,\n collection: this.name\n });\n }\n }\n\n async _findInternal(query, projection) {\n const timer = globalTimer.start('collection', 'find', { collection: this.name });\n \n if (!this._initialized) await this._initialize();\n\n const normalizedQuery = query == undefined ? {} : query;\n const nearSpec = this._extractNearSpec(normalizedQuery);\n\n const documents = [];\n const seen = {}; // Track which docs we've seen to avoid duplicates\n\n // Try to use indexes if available\n if (this.indexes.size > 0) {\n const planTimer = globalTimer.start('collection', 'find.queryPlanning');\n const queryPlan = await this.planQueryAsync(normalizedQuery);\n globalTimer.end(planTimer, { useIndex: queryPlan.useIndex, docIdsCount: queryPlan.docIds?.length || 0 });\n \n if (queryPlan.useIndex && queryPlan.docIds && queryPlan.docIds.length > 0) {\n // Use index results\n const indexLookupTimer = globalTimer.start('collection', 'find.indexLookup');\n for (const docId of queryPlan.docIds) {\n if (!seen[docId]) {\n const doc = await this.documents.search(docId);\n // Always verify match - index may return candidates or query may have\n // additional conditions not covered by the index\n if (doc && matches(doc, normalizedQuery)) {\n seen[docId] = true;\n documents.push(doc);\n }\n }\n }\n globalTimer.end(indexLookupTimer, { docsFound: documents.length });\n } else {\n // Fall back to full scan if index couldn't be used or returned no results\n const fullScanTimer = globalTimer.start('collection', 'find.fullScan');\n for await (const entry of this.documents) {\n if (entry && entry.value && !seen[entry.value._id] && matches(entry.value, normalizedQuery)) {\n seen[entry.value._id] = true;\n documents.push(entry.value);\n }\n }\n globalTimer.end(fullScanTimer, { docsFound: documents.length });\n }\n } else {\n // No indexes available, do full scan\n const fullScanTimer = globalTimer.start('collection', 'find.fullScan');\n for await (const entry of this.documents) {\n if (entry && entry.value && !seen[entry.value._id] && matches(entry.value, normalizedQuery)) {\n seen[entry.value._id] = true;\n documents.push(entry.value);\n }\n }\n globalTimer.end(fullScanTimer, { docsFound: documents.length });\n }\n\n // Apply $near sorting if applicable\n if (nearSpec) {\n const sortTimer = globalTimer.start('collection', 'find.nearSort');\n this._sortByNearDistance(documents, nearSpec);\n globalTimer.end(sortTimer);\n }\n\n // Apply projection if provided\n const projectionTimer = globalTimer.start('collection', 'find.projection');\n const result = documents.map(doc => projection ? applyProjection(projection, copy(doc)) : copy(doc));\n globalTimer.end(projectionTimer, { docsProcessed: result.length });\n\n globalTimer.end(timer, { docsReturned: result.length, hasIndexes: this.indexes.size > 0 });\n \n // Return projected/copied documents\n return result;\n }\n\n _extractNearSpec(query) {\n for (const field of Object.keys(query || {})) {\n if (field.startsWith('$')) continue;\n const value = query[field];\n if (!value || typeof value !== 'object') continue;\n\n if (value.$near) {\n const coords = this._parseNearCoordinates(value.$near);\n if (coords) return { field, ...coords };\n }\n\n if (value.$nearSphere) {\n const coords = this._parseNearCoordinates(value.$nearSphere);\n if (coords) return { field, ...coords };\n }\n }\n return null;\n }\n\n _parseNearCoordinates(spec) {\n let coordinates;\n if (spec && typeof spec === 'object') {\n if (spec.$geometry && spec.$geometry.coordinates) {\n coordinates = spec.$geometry.coordinates;\n } else if (spec.coordinates) {\n coordinates = spec.coordinates;\n } else if (Array.isArray(spec)) {\n coordinates = spec;\n }\n }\n\n if (!coordinates || coordinates.length < 2) {\n return null;\n }\n\n const [lng, lat] = coordinates;\n if (typeof lat !== 'number' || typeof lng !== 'number') {\n return null;\n }\n\n return { lat, lng };\n }\n\n _extractPointCoordinates(value) {\n if (!value) return null;\n\n // Handle GeoJSON FeatureCollection\n if (value.type === 'FeatureCollection' && Array.isArray(value.features) && value.features.length > 0) {\n return this._extractPointCoordinates(value.features[0].geometry);\n }\n\n // Handle GeoJSON Feature\n if (value.type === 'Feature' && value.geometry) {\n return this._extractPointCoordinates(value.geometry);\n }\n\n // Handle GeoJSON Point\n if (value.type === 'Point' && Array.isArray(value.coordinates) && value.coordinates.length >= 2) {\n const [lng, lat] = value.coordinates;\n if (typeof lat === 'number' && typeof lng === 'number') {\n return { lat, lng };\n }\n }\n\n return null;\n }\n\n _sortByNearDistance(documents, nearSpec) {\n const { field, lat: targetLat, lng: targetLng } = nearSpec;\n documents.sort((a, b) => {\n const aPoint = this._extractPointCoordinates(getProp(a, field));\n const bPoint = this._extractPointCoordinates(getProp(b, field));\n\n const aDist = aPoint ? this._haversineDistance(aPoint.lat, aPoint.lng, targetLat, targetLng) : Infinity;\n const bDist = bPoint ? this._haversineDistance(bPoint.lat, bPoint.lng, targetLat, targetLng) : Infinity;\n\n return aDist - bDist;\n });\n }\n\n _haversineDistance(lat1, lng1, lat2, lng2) {\n const R = 6371; // Earth's radius in kilometers\n const dLat = (lat2 - lat1) * Math.PI / 180;\n const dLng = (lng2 - lng1) * Math.PI / 180;\n const a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +\n Math.cos(lat1 * Math.PI / 180) * Math.cos(lat2 * Math.PI / 180) *\n Math.sin(dLng / 2) * Math.sin(dLng / 2);\n const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));\n return R * c;\n }\n\n findAndModify() { throw new NotImplementedError('findAndModify', { collection: this.name }); }\n\n async findOne(query, projection) {\n const cursor = this.find(query, projection);\n await cursor._ensureInitialized();\n if (await cursor.hasNext()) {\n return await cursor.next();\n } else {\n return null;\n }\n }\n\n async findOneAndDelete(filter, options) {\n let c = this.find(filter);\n if (options && options.sort) {\n c = c.sort(options.sort);\n await c._ensureInitialized();\n } else {\n await c._ensureInitialized();\n }\n if (!await c.hasNext()) return null;\n const doc = await c.next();\n await this.documents.delete(doc._id.toString());\n if (options && options.projection) return applyProjection(options.projection, doc);\n else return doc;\n }\n\n async findOneAndReplace(filter, replacement, options) {\n let c = this.find(filter);\n if (options && options.sort) {\n c = c.sort(options.sort);\n await c._ensureInitialized();\n } else {\n await c._ensureInitialized();\n }\n if (!await c.hasNext()) return null;\n const doc = await c.next();\n replacement._id = doc._id;\n await this.documents.add(doc._id.toString(), replacement);\n if (options && options.returnNewDocument) {\n if (options && options.projection) return applyProjection(options.projection, replacement);\n else return replacement;\n } else {\n if (options && options.projection) return applyProjection(options.projection, doc);\n else return doc;\n }\n }\n\n async findOneAndUpdate(filter, update, options) {\n let c = this.find(filter);\n if (options && options.sort) {\n c = c.sort(options.sort);\n await c._ensureInitialized();\n } else {\n await c._ensureInitialized();\n }\n if (!await c.hasNext()) return null;\n const doc = await c.next();\n const clone = Object.assign({}, doc);\n\n // Get array filter information for positional operator support\n const matchInfo = matchWithArrayIndices(doc, filter);\n const positionalMatchInfo = matchInfo.arrayFilters;\n const userArrayFilters = options && options.arrayFilters;\n\n applyUpdates(update, clone, false, positionalMatchInfo, userArrayFilters);\n await this.documents.add(doc._id.toString(), clone);\n if (options && options.returnNewDocument) {\n if (options && options.projection) return applyProjection(options.projection, clone);\n else return clone;\n } else {\n if (options && options.projection) return applyProjection(options.projection, doc);\n else return doc;\n }\n }\n\n getIndexes() {\n // Return array of index specifications\n const result = [];\n for (const [indexName, index] of this.indexes) {\n result.push(index.getSpec());\n }\n return result;\n }\n\n getShardDistribution() { throw new NotImplementedError('getShardDistribution', { collection: this.name }); }\n getShardVersion() { throw new NotImplementedError('getShardVersion', { collection: this.name }); }\n\n // non-mongo\n getStore() {\n return this.documents;\n }\n\n group() { throw new NotImplementedError('group', { collection: this.name }); }\n\n async insert(doc) {\n if (Array == doc.constructor) {\n return await this.insertMany(doc);\n } else {\n return await this.insertOne(doc);\n }\n }\n\n async insertOne(doc) {\n const timer = globalTimer.start('collection', 'insertOne', { collection: this.name });\n \n if (!this._initialized) await this._initialize();\n\n if (doc._id == undefined) doc._id = new ObjectId();\n \n const storeTimer = globalTimer.start('collection', 'insertOne.store');\n await this.documents.add(doc._id.toString(), doc);\n globalTimer.end(storeTimer);\n \n const indexTimer = globalTimer.start('collection', 'insertOne.updateIndexes');\n await this.updateIndexesOnInsert(doc);\n globalTimer.end(indexTimer, { indexCount: this.indexes.size });\n \n this.emit('insert', doc);\n \n globalTimer.end(timer);\n return { insertedId: doc._id };\n }\n\n async insertMany(docs) {\n const timer = globalTimer.start('collection', 'insertMany', { collection: this.name, docCount: docs.length });\n \n if (!this._initialized) await this._initialize();\n\n const insertedIds = [];\n for (let i = 0; i < docs.length; i++) {\n const result = await this.insertOne(docs[i]);\n insertedIds.push(result.insertedId);\n }\n \n globalTimer.end(timer, { insertedCount: insertedIds.length });\n return { insertedIds: insertedIds };\n }\n\n isCapped() { throw new NotImplementedError('isCapped', { collection: this.name }); }\n mapReduce() { throw new NotImplementedError('mapReduce', { collection: this.name }); }\n reIndex() { throw new NotImplementedError('reIndex', { collection: this.name }); }\n\n async replaceOne(query, replacement, options) { // only replace\n // first\n const result = {};\n const c = this.find(query);\n await c._ensureInitialized();\n result.matchedCount = await c.count();\n if (result.matchedCount == 0) {\n result.modifiedCount = 0;\n if (options && options.upsert) {\n const newDoc = replacement;\n newDoc._id = new ObjectId();\n await this.documents.add(newDoc._id.toString(), newDoc);\n await this.updateIndexesOnInsert(newDoc);\n this.emit('insert', newDoc);\n result.upsertedId = newDoc._id;\n }\n } else {\n result.modifiedCount = 1;\n const doc = await c.next();\n await this.updateIndexesOnDelete(doc);\n replacement._id = doc._id;\n this.documents.add(doc._id.toString(), replacement);\n await this.updateIndexesOnInsert(replacement);\n this.emit('replace', replacement);\n }\n return result;\n }\n\n async remove(query, options) {\n const c = this.find(query);\n await c._ensureInitialized();\n if (!await c.hasNext()) return;\n if (options === true || (options && options.justOne)) {\n const doc = await c.next();\n await this.updateIndexesOnDelete(doc);\n this.documents.delete(doc._id.toString());\n } else {\n while (await c.hasNext()) {\n const doc = await c.next();\n await this.updateIndexesOnDelete(doc);\n this.documents.delete(doc._id.toString());\n }\n }\n }\n\n renameCollection() { throw new NotImplementedError('renameCollection', { collection: this.name }); }\n save() { throw new NotImplementedError('save', { collection: this.name }); }\n stats() { throw new NotImplementedError('stats', { collection: this.name }); }\n storageSize() { throw new NotImplementedError('storageSize', { collection: this.name }); }\n totalSize() { throw new NotImplementedError('totalSize', { collection: this.name }); }\n totalIndexSize() { throw new NotImplementedError('totalIndexSize', { collection: this.name }); }\n\n async update(query, updates, options) {\n const c = this.find(query);\n await c._ensureInitialized();\n if (await c.hasNext()) {\n if (options && options.multi) {\n while (await c.hasNext()) {\n const doc = await c.next();\n\n // Get array filter information for positional operator support\n const matchInfo = matchWithArrayIndices(doc, query);\n const positionalMatchInfo = matchInfo.arrayFilters;\n const userArrayFilters = options && options.arrayFilters;\n\n await this.updateIndexesOnDelete(doc);\n applyUpdates(updates, doc, false, positionalMatchInfo, userArrayFilters);\n await this.documents.add(doc._id.toString(), doc);\n await this.updateIndexesOnInsert(doc);\n }\n } else {\n const doc = await c.next();\n\n // Get array filter information for positional operator support\n const matchInfo = matchWithArrayIndices(doc, query);\n const positionalMatchInfo = matchInfo.arrayFilters;\n const userArrayFilters = options && options.arrayFilters;\n\n await this.updateIndexesOnDelete(doc);\n applyUpdates(updates, doc, false, positionalMatchInfo, userArrayFilters);\n await this.documents.add(doc._id.toString(), doc);\n await this.updateIndexesOnInsert(doc);\n }\n } else {\n if (options && options.upsert) {\n const newDoc = createDocFromUpdate(query, updates, new ObjectId());\n await this.documents.add(newDoc._id.toString(), newDoc);\n await this.updateIndexesOnInsert(newDoc);\n }\n }\n }\n\n async updateOne(query, updates, options) {\n const timer = globalTimer.start('collection', 'updateOne', { collection: this.name });\n \n const findTimer = globalTimer.start('collection', 'updateOne.find');\n const c = this.find(query);\n await c._ensureInitialized();\n globalTimer.end(findTimer);\n \n if (await c.hasNext()) {\n const doc = await c.next();\n const originalDoc = JSON.parse(JSON.stringify(doc));\n\n // Get array filter information for positional operator support\n const matchInfo = matchWithArrayIndices(doc, query);\n const positionalMatchInfo = matchInfo.arrayFilters;\n const userArrayFilters = options && options.arrayFilters;\n\n const indexDelTimer = globalTimer.start('collection', 'updateOne.updateIndexesOnDelete');\n await this.updateIndexesOnDelete(doc);\n globalTimer.end(indexDelTimer);\n \n const applyTimer = globalTimer.start('collection', 'updateOne.applyUpdates');\n applyUpdates(updates, doc, false, positionalMatchInfo, userArrayFilters);\n globalTimer.end(applyTimer);\n \n const storeTimer = globalTimer.start('collection', 'updateOne.store');\n this.documents.add(doc._id.toString(), doc);\n globalTimer.end(storeTimer);\n \n const indexInsTimer = globalTimer.start('collection', 'updateOne.updateIndexesOnInsert');\n await this.updateIndexesOnInsert(doc);\n globalTimer.end(indexInsTimer, { indexCount: this.indexes.size });\n \n const updateDescription = this._getUpdateDescription(originalDoc, doc);\n this.emit('update', doc, updateDescription);\n } else {\n if (options && options.upsert) {\n const newDoc = createDocFromUpdate(query, updates, new ObjectId());\n this.documents.add(newDoc._id.toString(), newDoc);\n await this.updateIndexesOnInsert(newDoc);\n this.emit('insert', newDoc);\n }\n }\n \n globalTimer.end(timer);\n }\n\n async updateMany(query, updates, options) {\n const timer = globalTimer.start('collection', 'updateMany', { collection: this.name });\n \n const findTimer = globalTimer.start('collection', 'updateMany.find');\n const c = this.find(query);\n await c._ensureInitialized();\n globalTimer.end(findTimer);\n \n let updateCount = 0;\n if (await c.hasNext()) {\n while (await c.hasNext()) {\n const doc = await c.next();\n const originalDoc = JSON.parse(JSON.stringify(doc));\n\n // Get array filter information for positional operator support\n const matchInfo = matchWithArrayIndices(doc, query);\n const positionalMatchInfo = matchInfo.arrayFilters;\n const userArrayFilters = options && options.arrayFilters;\n\n await this.updateIndexesOnDelete(doc);\n applyUpdates(updates, doc, false, positionalMatchInfo, userArrayFilters);\n this.documents.add(doc._id.toString(), doc);\n await this.updateIndexesOnInsert(doc);\n const updateDescription = this._getUpdateDescription(originalDoc, doc);\n this.emit('update', doc, updateDescription);\n updateCount++;\n }\n } else {\n if (options && options.upsert) {\n const newDoc = createDocFromUpdate(query, updates, new ObjectId());\n this.documents.add(newDoc._id.toString(), newDoc);\n await this.updateIndexesOnInsert(newDoc);\n this.emit('insert', newDoc);\n }\n }\n \n globalTimer.end(timer, { updatedCount: updateCount });\n }\n\n validate() { throw new NotImplementedError('validate', { collection: this.name }); }\n\n /**\n * Generate updateDescription for change events\n * Compares original and updated documents to track changes\n */\n _getUpdateDescription(originalDoc, updatedDoc) {\n const updatedFields = {};\n const removedFields = [];\n\n // Find updated and new fields\n for (const key in updatedDoc) {\n if (key === '_id') continue;\n if (JSON.stringify(originalDoc[key]) !== JSON.stringify(updatedDoc[key])) {\n updatedFields[key] = updatedDoc[key];\n }\n }\n\n // Find removed fields\n for (const key in originalDoc) {\n if (key === '_id') continue;\n if (!(key in updatedDoc)) {\n removedFields.push(key);\n }\n }\n\n return {\n updatedFields,\n removedFields,\n truncatedArrays: [] // Not implemented in micro-mongo\n };\n }\n\n /**\n * Watch for changes to this collection\n * @param {Array} pipeline - Aggregation pipeline to filter changes\n * @param {Object} options - Watch options (fullDocument, etc.)\n * @returns {ChangeStream} A change stream instance\n */\n watch(pipeline = [], options = {}) {\n return new ChangeStream(this, pipeline, options);\n }\n\n}\n\n/**\n * Apply projection with expression support\n * Enhanced version of applyProjection that supports computed expressions\n */\nfunction applyProjectionWithExpressions(projection, doc) {\n const result = {};\n const keys = Object.keys(projection);\n\n // Check if this is an inclusion or exclusion projection\n let isInclusion = false;\n let isExclusion = false;\n let hasComputedFields = false;\n\n for (const key of keys) {\n if (key === '_id') continue;\n const value = projection[key];\n\n if (value === 1 || value === true) {\n isInclusion = true;\n } else if (value === 0 || value === false) {\n isExclusion = true;\n } else {\n // Computed field (expression)\n hasComputedFields = true;\n }\n }\n\n // Handle computed fields - they imply inclusion mode\n if (hasComputedFields || isInclusion) {\n // Inclusion mode: only include specified fields\n // Always include _id unless explicitly excluded\n if (projection._id !== 0 && projection._id !== false) {\n result._id = doc._id;\n }\n\n for (const key of keys) {\n const value = projection[key];\n\n if (key === '_id') {\n if (value === 0 || value === false) {\n delete result._id;\n }\n } else if (value === 1 || value === true) {\n // Simple field inclusion\n result[key] = getProp(doc, key);\n } else {\n // Computed field (expression)\n result[key] = evaluateExpression(value, doc);\n }\n }\n } else {\n // Exclusion mode: include all fields except specified ones\n for (const key in doc) {\n if (doc.hasOwnProperty(key)) {\n result[key] = doc[key];\n }\n }\n\n for (const key of keys) {\n if (projection[key] === 0 || projection[key] === false) {\n delete result[key];\n }\n }\n }\n\n return result;\n}\n","import { Collection } from './Collection.js';\nimport { ObjectId } from '@belteshazzar/binjson';\nimport { ChangeStream } from './ChangeStream.js';\nimport { NotImplementedError } from '../errors.js';\n\n/**\n * DB class\n */\nexport class DB {\n\tconstructor(options) {\n\t\tthis.options = options || {};\n this.baseFolder = this.options.baseFolder || 'babymongo';\n\t\tthis.dbName = this.options.dbName || 'default';\n\t\tthis.dbFolder = `${this.baseFolder}/${this.dbName}`;\n this.collections = new Map();\n\n\t\t// Return a Proxy to enable dynamic collection creation\n\t\tconst proxy = new Proxy(this, {\n\t\t\tget(target, property, receiver) {\n\t\t\t\t// If property exists on target (including undefined values), return it\n\t\t\t\tif (property in target) {\n\t\t\t\t\treturn Reflect.get(target, property, receiver);\n\t\t\t\t}\n\n\t\t\t\t// If property is a symbol or special property, return undefined\n\t\t\t\tif (typeof property === 'symbol' || property.startsWith('_')) {\n\t\t\t\t\treturn undefined;\n\t\t\t\t}\n\n // Only auto-create if it's a valid collection name and doesn't already exist\n if (typeof property === 'string') {\n return target.getCollection(property);\n }\n\n return undefined;\n\t\t\t}\n\t\t});\n\t\t\n\t\t// Store reference to proxy for use in getCollection\n\t\tthis._proxy = proxy;\n\t\t\n\t\treturn proxy;\n\t}\n\n\t/**\n\t * Close all collections\n\t */\n\tasync close() {\n for (const [_, collection] of this.collections) {\n await collection.close();\n\t\t}\n\t}\n\n\t// DB Methods\n\tcloneCollection() { throw new NotImplementedError('cloneCollection', { database: this.dbName }); }\n\tcloneDatabase() { throw new NotImplementedError('cloneDatabase', { database: this.dbName }); }\n\tcommandHelp() { throw new NotImplementedError('commandHelp', { database: this.dbName }); }\n\tcopyDatabase() { throw new NotImplementedError('copyDatabase', { database: this.dbName }); }\n\n\tcreateCollection(name) {\n if (!this.collections.has(name)) {\n this.collections.set(name, new Collection(this, name));\n }\n return {ok:1};\n }\n\n\tcurrentOp() { throw new NotImplementedError('currentOp', { database: this.dbName }); }\n\n\tasync dropCollection(collectionName) {\n if (this.collections.has(collectionName)) {\n const collection = this.collections.get(collectionName);\n if (typeof collection.drop === 'function') {\n await collection.drop();\n }\n this.collections.delete(collectionName);\n }\n }\n\n\tasync dropDatabase() {\n for (const [_, collection] of this.collections) {\n await collection.drop();\n\t\t}\n this.collections.clear();\n \n const pathParts = this.dbFolder.split('/').filter(Boolean);\n const dbFolder = pathParts.pop();\n\n try {\n let dir = await globalThis.navigator.storage.getDirectory();\n for (const part of pathParts) {\n dir = await dir.getDirectoryHandle(part, { create: false });\n }\n \n await dir.removeEntry(dbFolder, { recursive: true });\n } catch (error) {\n // Ignore not found errors - directory might not exist yet\n if (error.name !== 'NotFoundError' && error.code !== 'ENOENT') {\n throw error;\n }\n }\n return {ok: 1};\n }\n\n\teval() { throw new NotImplementedError('eval', { database: this.dbName }); }\n\tfsyncLock() { throw new NotImplementedError('fsyncLock', { database: this.dbName }); }\n\tfsyncUnlock() { throw new NotImplementedError('fsyncUnlock', { database: this.dbName }); }\n\n getCollection(name) { \n // For collection names, create the collection if it doesn't exist\n if (!this.collections.has(name)) {\n // Pass the proxy (if available) so collections can access other collections via db\n const dbRef = this._proxy || this;\n this.collections.set(name, new Collection(dbRef, name));\n }\n\n return this.collections.get(name);\n }\n \n // Alias for getCollection for MongoDB API compatibility\n collection(name) {\n return this.getCollection(name);\n }\n\n getCollectionInfos() { throw new NotImplementedError('getCollectionInfos', { database: this.dbName }); }\n getCollectionNames() {\n return Array.from(this.collections.keys());\n }\n\tgetLastError() { throw new NotImplementedError('getLastError', { database: this.dbName }); }\n\tgetLastErrorObj() { throw new NotImplementedError('getLastErrorObj', { database: this.dbName }); }\n\tgetLogComponents() { throw new NotImplementedError('getLogComponents', { database: this.dbName }); }\n\tgetMongo() { throw new NotImplementedError('getMongo', { database: this.dbName }); }\n\tgetName() { throw new NotImplementedError('getName', { database: this.dbName }); }\n\tgetPrevError() { throw new NotImplementedError('getPrevError', { database: this.dbName }); }\n\tgetProfilingLevel() { throw new NotImplementedError('getProfilingLevel', { database: this.dbName }); }\n\tgetProfilingStatus() { throw new NotImplementedError('getProfilingStatus', { database: this.dbName }); }\n\tgetReplicationInfo() { throw new NotImplementedError('getReplicationInfo', { database: this.dbName }); }\n\tgetSiblingDB() { throw new NotImplementedError('getSiblingDB', { database: this.dbName }); }\n\n\thelp() {\n\t\tconsole.log(\" help mr mapreduce\");\n\t\tconsole.log(\" db.foo.find() list objects in collection foo\");\n\t\tconsole.log(\" db.foo.find( { a : 1 } ) list objects in foo where a == 1\");\n\t\tconsole.log(\" it result of the last line evaluated; use to further iterate\");\n\t}\n\n\thostInfo() { throw new NotImplementedError('hostInfo', { database: this.dbName }); }\n\tisMaster() { throw new NotImplementedError('isMaster', { database: this.dbName }); }\n\tkillOp() { throw new NotImplementedError('killOp', { database: this.dbName }); }\n\tlistCommands() { throw new NotImplementedError('listCommands', { database: this.dbName }); }\n\tloadServerScripts() { throw new NotImplementedError('loadServerScripts', { database: this.dbName }); }\n\tlogout() { throw new NotImplementedError('logout', { database: this.dbName }); }\n\tprintCollectionStats() { throw new NotImplementedError('printCollectionStats', { database: this.dbName }); }\n\tprintReplicationInfo() { throw new NotImplementedError('printReplicationInfo', { database: this.dbName }); }\n\tprintShardingStatus() { throw new NotImplementedError('printShardingStatus', { database: this.dbName }); }\n\tprintSlaveReplicationInfo() { throw new NotImplementedError('printSlaveReplicationInfo', { database: this.dbName }); }\n\trepairDatabase() { throw new NotImplementedError('repairDatabase', { database: this.dbName }); }\n\tresetError() { throw new NotImplementedError('resetError', { database: this.dbName }); }\n\trunCommand() { throw new NotImplementedError('runCommand', { database: this.dbName }); }\n\tserverBuildInfo() { throw new NotImplementedError('serverBuildInfo', { database: this.dbName }); }\n\tserverCmdLineOpts() { throw new NotImplementedError('serverCmdLineOpts', { database: this.dbName }); }\n\tserverStatus() { throw new NotImplementedError('serverStatus', { database: this.dbName }); }\n\tsetLogLevel() { throw new NotImplementedError('setLogLevel', { database: this.dbName }); }\n\tsetProfilingLevel() { throw new NotImplementedError('setProfilingLevel', { database: this.dbName }); }\n\tshutdownServer() { throw new NotImplementedError('shutdownServer', { database: this.dbName }); }\n\tstats() { throw new NotImplementedError('stats', { database: this.dbName }); }\n\tversion() { throw new NotImplementedError('version', { database: this.dbName }); }\n\tupgradeCheck() { throw new NotImplementedError('upgradeCheck', { database: this.dbName }); }\n\tupgradeCheckAllDBs() { throw new NotImplementedError('upgradeCheckAllDBs', { database: this.dbName }); }\n\n\t/**\n\t * Watch for changes across all collections in this database\n\t * @param {Array} pipeline - Aggregation pipeline to filter changes\n\t * @param {Object} options - Watch options\n\t * @returns {ChangeStream} A change stream instance\n\t */\n\twatch(pipeline = [], options = {}) {\n\t\treturn new ChangeStream(this, pipeline, options);\n\t}\n}\n","import { DB } from './DB.js';\nimport { ChangeStream } from './ChangeStream.js';\n\n/**\n * Server runs inside a worker and routes requests to DB/Collection instances.\n */\nexport class Server {\n constructor(options = {}, postEvent = () => {}) {\n this.options = options;\n this.databases = new Map();\n this.postEvent = postEvent;\n\n this.cursors = new Map();\n this.cursorCounter = 1;\n\n this.streams = new Map();\n this.streamCounter = 1;\n }\n\n async dispatch(request) {\n const { target, database, collection, method, args = [], cursorId, streamId, cursorOpts } = request;\n if (target === 'cursor') {\n return await this._cursorOp(cursorId, method, args);\n }\n if (target === 'changestream') {\n return await this._changeStreamOp(streamId, method, args);\n }\n\n // Handle client-level operations (e.g., client.watch())\n if (target === 'client') {\n return await this._call(this, method, args);\n }\n\n if (!target || !database || !method) {\n throw new Error('Invalid request payload');\n }\n\n const db = this._getDB(database);\n\n if (target === 'db') {\n return await this._call(db, method, args);\n }\n\n if (target === 'collection') {\n if (!collection) {\n throw new Error('Collection name required for collection target');\n }\n const col = db.collection(collection);\n return await this._call(col, method, args, cursorOpts);\n }\n\n throw new Error(`Unknown target: ${target}`);\n }\n\n _getDB(dbName) {\n if (this.databases.has(dbName)) return this.databases.get(dbName);\n const db = new DB({ ...this.options, dbName });\n this.databases.set(dbName, db);\n return db;\n }\n\n async _call(target, method, args, cursorOpts) {\n if (typeof target[method] !== 'function') {\n throw new Error(`Method ${method} not found on target`);\n }\n const result = target[method](...(args || []));\n const awaited = (result && typeof result.then === 'function') ? await result : result;\n\n // Handle cursors (find/aggregate) by registering and returning first batch\n if (awaited && typeof awaited.hasNext === 'function' && typeof awaited.next === 'function') {\n return await this._registerCursor(awaited, cursorOpts);\n }\n\n // For aggregate(), wrap the array results in a cursor-like object\n if (method === 'aggregate' && Array.isArray(awaited)) {\n return await this._registerArrayAsCursor(awaited);\n }\n\n // Handle change streams\n if (awaited && awaited.constructor?.name === 'ChangeStream') {\n return this._registerChangeStream(awaited);\n }\n \n // Also check if it's an EventEmitter with specific ChangeStream properties\n if (awaited && typeof awaited.on === 'function' && awaited.hasOwnProperty('pipeline') && awaited.hasOwnProperty('_changeCounter')) {\n return this._registerChangeStream(awaited);\n }\n\n return awaited;\n }\n\n async _registerCursor(cursor, cursorOpts = {}) {\n // Apply cursor modifiers before fetching results\n // Note: some modifiers like sort() return a new cursor instance\n if (cursorOpts.sort) cursor = cursor.sort(cursorOpts.sort);\n if (cursorOpts.skip) cursor = await cursor.skip(cursorOpts.skip);\n if (cursorOpts.limit) cursor = await cursor.limit(cursorOpts.limit);\n if (cursorOpts.min && cursor.min) cursor = cursor.min(cursorOpts.min);\n if (cursorOpts.max && cursor.max) cursor = cursor.max(cursorOpts.max);\n if (cursorOpts.hint && cursor.hint) cursor = cursor.hint(cursorOpts.hint);\n if (cursorOpts.comment && cursor.comment) cursor = cursor.comment(cursorOpts.comment);\n if (cursorOpts.maxTimeMS && cursor.maxTimeMS) cursor = cursor.maxTimeMS(cursorOpts.maxTimeMS);\n if (cursorOpts.maxScan && cursor.maxScan) cursor = cursor.maxScan(cursorOpts.maxScan);\n if (cursorOpts.returnKey && cursor.returnKey) cursor = cursor.returnKey(cursorOpts.returnKey);\n if (cursorOpts.showRecordId && cursor.showRecordId) cursor = cursor.showRecordId(cursorOpts.showRecordId);\n if (cursorOpts.collation && cursor.collation) cursor = cursor.collation(cursorOpts.collation);\n \n const id = `cur_${this.cursorCounter++}`;\n const batchSize = this.options.batchSize || 100;\n const batch = [];\n\n while (batch.length < batchSize && await cursor.hasNext()) {\n batch.push(await cursor.next());\n }\n\n const exhausted = !(await cursor.hasNext());\n if (!exhausted) {\n this.cursors.set(id, cursor);\n }\n\n return { cursorId: id, batch, exhausted, batchSize };\n }\n\n async _registerArrayAsCursor(resultsArray) {\n const id = `cur_${this.cursorCounter++}`;\n const batchSize = this.options.batchSize || 100;\n \n // Take first batch from the array\n const batch = resultsArray.slice(0, batchSize);\n const exhausted = resultsArray.length <= batchSize;\n \n // If there are more results, create a cursor-like object to track remaining items\n if (!exhausted) {\n const cursor = {\n position: batchSize,\n array: resultsArray,\n async hasNext() {\n return this.position < this.array.length;\n },\n async next() {\n if (this.position >= this.array.length) throw new Error('No more documents');\n return this.array[this.position++];\n }\n };\n this.cursors.set(id, cursor);\n }\n \n return { cursorId: id, batch, exhausted, batchSize };\n }\n\n async _cursorOp(cursorId, method, args = []) {\n if (!cursorId) throw new Error('cursorId required');\n const cursor = this.cursors.get(cursorId);\n if (!cursor) {\n if (method === 'close') return { closed: true };\n throw new Error(`Cursor not found: ${cursorId}`);\n }\n\n if (method === 'close') {\n this.cursors.delete(cursorId);\n return { closed: true };\n }\n\n if (method === 'getMore') {\n const opts = args?.[0] || {};\n const batchSize = opts.batchSize || 100;\n const batch = [];\n while (batch.length < batchSize && await cursor.hasNext()) {\n batch.push(await cursor.next());\n }\n const exhausted = !(await cursor.hasNext());\n if (exhausted) {\n this.cursors.delete(cursorId);\n }\n return { batch, exhausted, batchSize };\n }\n\n throw new Error(`Unknown cursor method: ${method}`);\n }\n\n _registerChangeStream(stream) {\n const id = `cs_${this.streamCounter++}`;\n const handlers = {\n change: (change) => this.postEvent({\n type: 'event',\n event: 'changeStream',\n payload: { streamId: id, type: 'change', data: change }\n }),\n error: (err) => this.postEvent({\n type: 'event',\n event: 'changeStream',\n payload: { streamId: id, type: 'error', data: {\n name: err?.name,\n message: err?.message,\n stack: err?.stack\n }}\n }),\n close: () => this.postEvent({\n type: 'event',\n event: 'changeStream',\n payload: { streamId: id, type: 'close' }\n })\n };\n\n stream.on('change', handlers.change);\n stream.on('error', handlers.error);\n stream.on('close', handlers.close);\n\n this.streams.set(id, { stream, handlers });\n return { streamId: id };\n }\n\n async _changeStreamOp(streamId, method) {\n if (!streamId) throw new Error('streamId required');\n const entry = this.streams.get(streamId);\n if (!entry) return { closed: true };\n\n if (method === 'close') {\n const { stream, handlers } = entry;\n stream.off('change', handlers.change);\n stream.off('error', handlers.error);\n stream.off('close', handlers.close);\n if (typeof stream.close === 'function') {\n await stream.close();\n }\n this.streams.delete(streamId);\n return { closed: true };\n }\n\n throw new Error(`Unknown change stream method: ${method}`);\n }\n\n /**\n * Watch for changes across all databases and collections\n * @param {Array} pipeline - Aggregation pipeline to filter changes\n * @param {Object} options - Watch options\n * @returns {ChangeStream} A change stream instance\n */\n watch(pipeline = [], options = {}) {\n return new ChangeStream(this, pipeline, options);\n }\n}\n","import { Server } from './Server.js';\nimport { ObjectId } from '@belteshazzar/binjson';\n\n/**\n * Serialize ObjectId and Date instances for worker communication\n */\nfunction serializePayload(obj, seen = new WeakSet()) {\n if (obj === null || obj === undefined) return obj;\n if (typeof obj === 'function') {\n return { __function: obj.toString() };\n }\n \n // Check for ObjectId instances - try toString() first as it's the most reliable way\n if (obj && typeof obj === 'object' && typeof obj.toString === 'function') {\n try {\n const str = obj.toString();\n // bjson ObjectIds produce 24-character hex strings\n if (str && str.length === 24 && /^[0-9a-f]{24}$/i.test(str) && obj.constructor && obj.constructor.name === 'ObjectId') {\n return { __objectId: str };\n }\n } catch (e) {\n // toString() failed, continue to next check\n }\n }\n \n // Traditional instanceof check (may fail across worker boundaries in some cases)\n if (obj instanceof ObjectId) {\n return { __objectId: obj.toString() };\n }\n \n if (obj instanceof Date) {\n return { __date: obj.toISOString() };\n }\n \n // Check for circular references\n if (typeof obj === 'object') {\n if (seen.has(obj)) {\n return undefined; // Skip circular references\n }\n seen.add(obj);\n }\n \n if (Array.isArray(obj)) {\n return obj.map(item => serializePayload(item, seen));\n }\n if (typeof obj === 'object') {\n const result = {};\n for (const [key, value] of Object.entries(obj)) {\n result[key] = serializePayload(value, seen);\n }\n return result;\n }\n return obj;\n}\n\n/**\n * Deserialize ObjectId and Date instances from worker communication\n */\nfunction deserializePayload(obj) {\n if (obj === null || obj === undefined) return obj;\n if (typeof obj === 'object' && obj.__function) {\n return typeof obj.__function === 'string' ? `(${obj.__function}).call(this)` : undefined;\n }\n if (typeof obj === 'object' && obj.__objectId) {\n return new ObjectId(obj.__objectId);\n }\n if (typeof obj === 'object' && obj.__date) {\n return new Date(obj.__date);\n }\n if (Array.isArray(obj)) {\n return obj.map(deserializePayload);\n }\n if (typeof obj === 'object') {\n const result = {};\n for (const [key, value] of Object.entries(obj)) {\n result[key] = deserializePayload(value);\n }\n return result;\n }\n return obj;\n}\n\nconst isNode = typeof process !== 'undefined' && !!process.versions?.node;\nlet server;\nlet initPromise = null;\n\n// Set up OPFS polyfill for Node.js worker threads\nif (isNode) {\n initPromise = Promise.resolve().then(() => {\n // Dynamically construct import to avoid static analysis by Vite\n const importFunc = new Function('spec', 'return import(spec)');\n return Promise.all([\n importFunc('path'),\n importFunc('url'),\n importFunc('node-opfs')\n ]);\n }).then(([pathModule, urlModule, opfsModule]) => {\n const path = pathModule.default;\n const { fileURLToPath } = urlModule;\n const { StorageManager } = opfsModule;\n \n // Get project root directory for .opfs location\n const __filename = fileURLToPath(import.meta.url);\n const __dirname = path.dirname(__filename);\n const projectRoot = path.resolve(__dirname, '..');\n const opfsDir = path.join(projectRoot, '.opfs');\n \n // Configure node-opfs to use project-local .opfs directory\n const customStorage = new StorageManager(opfsDir);\n const opfsNavigator = {\n storage: {\n getDirectory: () => customStorage.getDirectory()\n }\n };\n \n // Ensure bjson sees OPFS APIs in Node worker\n if (typeof globalThis.navigator === 'undefined') {\n globalThis.navigator = opfsNavigator;\n } else {\n globalThis.navigator.storage = opfsNavigator.storage;\n }\n }).catch(() => {\n // Ignore - likely dependencies not available or browser environment\n });\n}\n\nfunction createServer(post) {\n if (!server) {\n // Use empty options - will default to in-memory storage\n server = new Server({}, post);\n }\n return server;\n}\n\nasync function handleMessage(message, post) {\n if (!message || message.type !== 'request') return;\n \n // Wait for OPFS initialization in Node.js before processing\n if (initPromise) {\n await initPromise;\n }\n \n const { id, payload } = message;\n const deserializedPayload = deserializePayload(payload);\n const srv = createServer(post);\n\n try {\n const result = await srv.dispatch(deserializedPayload);\n const serializedResult = serializePayload(result);\n post({ type: 'response', id, success: true, result: serializedResult });\n } catch (error) {\n post({\n type: 'response',\n id,\n success: false,\n error: {\n name: error?.name,\n message: error?.message,\n stack: error?.stack,\n code: error?.code,\n $err: error?.$err\n }\n });\n }\n}\n\nasync function initializeWorker() {\n if (isNode) {\n const { parentPort } = await import('worker_threads');\n const post = (resp) => parentPort.postMessage(resp);\n parentPort.on('message', (msg) => handleMessage(msg, post));\n } else {\n const post = (resp) => self.postMessage(resp);\n self.onmessage = (event) => handleMessage(event.data, post);\n }\n}\n\n// Initialize on load\ninitializeWorker().catch(err => {\n console.error('Worker initialization failed:', err);\n if (typeof process !== 'undefined') {\n process.exit(1);\n } else {\n self.postMessage({ type: 'error', error: err.message });\n }\n});\n"],"names":["ReflectOwnKeys","R","Reflect","ReflectApply","apply","target","receiver","args","Function","prototype","call","ownKeys","Object","getOwnPropertySymbols","getOwnPropertyNames","concat","NumberIsNaN","Number","isNaN","value","EventEmitter","init","this","eventsModule","exports","once","emitter","name","Promise","resolve","reject","errorListener","err","removeListener","resolver","slice","arguments","eventTargetAgnosticAddListener","handler","flags","on","addErrorHandlerIfEventEmitter","_events","_eventsCount","_maxListeners","defaultMaxListeners","checkListener","listener","TypeError","_getMaxListeners","that","_addListener","type","prepend","m","events","existing","warning","create","newListener","emit","unshift","push","length","warned","w","Error","String","count","console","warn","onceWrapper","fired","wrapFn","_onceWrap","state","wrapped","bind","_listeners","unwrap","evlistener","arr","ret","Array","i","unwrapListeners","arrayClone","listenerCount","n","copy","addEventListener","wrapListener","arg","removeEventListener","defineProperty","enumerable","get","set","RangeError","getPrototypeOf","setMaxListeners","getMaxListeners","doError","error","er","message","context","len","listeners","addListener","prependListener","prependOnceListener","list","position","originalListener","shift","index","pop","spliceOne","off","removeAllListeners","key","keys","rawListeners","eventNames","TYPE","ObjectId","constructor","id","generate","isValid","toLowerCase","Uint8Array","from","map","b","toString","padStart","join","toHexString","getTimestamp","timestamp","parseInt","substring","Date","equals","other","compare","localeCompare","toJSON","inspect","toBytes","bytes","test","createFromTime","tsHex","Math","floor","ts","now","rand","crypto","getRandomValues","tail","random","padEnd","Pointer","offset","isInteger","MAX_SAFE_INTEGER","valueOf","encode","buffers","encodeValue","val","buffer","ArrayBuffer","DataView","setBigInt64","BigInt","getTime","setBigUint64","lengthBuffer","setUint32","isSafeInteger","setFloat64","encoded","TextEncoder","isArray","tempBuffers","startLength","item","elementBuffers","splice","contentSize","reduce","sum","buf","sizeBuffer","keyLengthBuffer","kvBuffers","totalLength","result","decode","data","decodeValue","byteOffset","getBigInt64","MIN_SAFE_INTEGER","getFloat64","getUint32","stringData","TextDecoder","oidBytes","pointerOffset","getBigUint64","binaryData","size","obj","keyLength","keyData","BinJsonFile","syncAccessHandle","readRange","start","bytesRead","read","at","getFileSize","getSize","write","truncate","pointer","fileSize","pointerValue","append","existingSize","flush","scan","valueSize","readPosition","tempData","getValueSize","valueData","valuesEqual","a","o","out","v","getProp","path","split","pathSegment","numericIndex","getFieldValues","results","newResults","j","current","k","filter","setProp","indexOf","remainingPath","nextSegment","nextNumeric","setPropWithAllPositional","lastSegment","lastNumericIndex","toArray","hasOwnProperty","el","isIn","values","arrayMatches","x","y","objectMatches","p","applyProjection","projection","doc","hasInclusion","hasExclusion","$err","code","_id","fieldPath","pathParts","parent","ErrorCodes","MongoError","options","super","codeName","_getCodeName","collection","database","operation","query","document","field","captureStackTrace","json","indexName","namespace","cursorId","feature","keyPattern","keyValue","writeErrors","IndexError","IndexNotFoundError","QueryError","NotImplementedError","BadValueError","reason","Cursor","documentsOrPromise","SortedCursor","_documentsPromise","documents","_initialized","pos","_limit","_skip","_closed","_ensureInitialized","batchSize","_batchSize","close","comment","commentString","_comment","explain","verbosity","queryPlanner","plannerVersion","db","indexFilterSet","parsedQuery","winningPlan","stage","direction","executionStats","executionSuccess","nReturned","executionTimeMillis","totalKeysExamined","totalDocsExamined","ok","forEach","fn","hasNext","next","effectiveMax","min","hint","_hint","itcount","limit","_max","maxScan","_maxScan","maxTimeMS","ms","_maxTimeMS","max","indexBounds","_maxIndexBounds","_minIndexBounds","noCursorTimeout","_noCursorTimeout","objsLeftInBatch","pretty","_pretty","readConcern","level","_readConcern","readPref","mode","tagSet","_readPref","returnKey","enabled","_returnKey","showRecordId","_showRecordId","remaining","maxPos","skip","num","isClosed","snapshot","sort","s","allowDiskUse","_allowDiskUse","collation","collationDocument","_collation","tailable","Symbol","asyncIterator","cursor","sortSpec","_cursor","_sort","items","sortKeys","step2list","ational","tional","enci","anci","izer","bli","alli","entli","eli","ousli","ization","ation","ator","alism","iveness","fulness","ousness","aliti","iviti","biliti","logi","step3list","icate","ative","alize","iciti","ical","ful","ness","vowel","consonants","vowels","gt0","RegExp","eq1","gt1","vowelInStem","consonantLike","sfxLl","sfxE","sfxY","sfxIon","sfxEdOrIng","sfxAtOrBlOrIz","sfxEED","sfxS","sfxSsesOrIes","sfxMultiConsonantLike","step2","step3","step4","stemmer","match","firstCharacterWasLowerCaseY","codePointAt","exec","NodeData","isLeaf","children","BPlusTree","syncHandle","order","file","minKeys","ceil","isOpen","rootPointer","nextNodeId","_size","open","_loadMetadata","_initializeNewTree","rootNode","_saveNode","_saveMetadata","metadata","version","maxEntries","minEntries","nextId","metadataOffset","node","_loadNode","_loadRoot","search","root","_searchNode","child","add","_addToNode","newRoot","newNode","leftPointer","left","rightPointer","right","splitKey","existingIdx","insertIdx","mid","leftKeys","leftValues","rightKeys","rightValues","rightNode","childIdx","childNode","newChildPointer","leftChildren","rightChildren","_deleteFromNode","finalRoot","keyIndex","newKeys","newValues","newChild","newChildren","_collectAllEntries","_iterateNode","childPointer","isEmpty","rangeSearch","minKey","maxKey","_rangeSearchNode","getHeight","height","compact","destSyncHandle","oldSize","entries","newTree","entry","newSize","bytesSaved","STOPWORDS","Set","tokenize","text","word","has","TextIndex","trees","documentTerms","documentLengths","all","_ensureOpen","docId","words","termFrequency","Map","stem","frequency","postings","mergedTerms","docLength","remove","terms","term","delete","queryText","scored","requireAll","stemmedTerms","uniqueTerms","docSets","termDocs","intersection","docLengthEntries","docLengthMap","totalDocs","idf","docsWithTerm","log","docScores","termFreq","tf","termIdf","prev","score","docTerms","coverage","r","getTermCount","getDocumentCount","clear","docs","lengths","destIndex","destDocTerms","destDocLengths","termsResult","documentsResult","lengthsResult","evaluateExpression","expr","startsWith","charAt","operator","operand","operands","evalAdd","val1","val2","evalSubtract","product","evalMultiply","evalDivide","evalMod","base","exponent","pow","evalPow","sqrt","evalSqrt","abs","evalAbs","evalCeil","evalFloor","trunc","evalTrunc","place","multiplier","round","evalRound","evalConcat","str","substr","evalSubstr","evalToLower","toUpperCase","evalToUpper","input","chars","charsRegex","escapeRegex","replace","trim","evalTrim","evalLtrim","evalRtrim","delimiter","evalSplit","evalStrLenCP","str1","str2","evalStrcasecmp","end","evalIndexOfCP","find","replacement","evalReplaceOne","evalReplaceAll","evalCmp","evalEq","evalNe","evalGt","evalGte","evalLt","evalLte","evalAnd","evalOr","evalNot","ifExpr","thenExpr","elseExpr","if","then","else","condition","evalCond","evalIfNull","branches","branch","case","default","evalSwitch","date","getUTCFullYear","evalYear","getUTCMonth","evalMonth","getUTCDate","evalDayOfMonth","getUTCDay","evalDayOfWeek","UTC","diff","oneDay","evalDayOfYear","getUTCHours","evalHour","getUTCMinutes","evalMinute","getUTCSeconds","evalSecond","getUTCMilliseconds","evalMillisecond","onejan","evalWeek","dayNr","setUTCDate","firstThursday","setUTCMonth","evalIsoWeek","evalIsoWeekYear","format","evalDateToString","evalToDate","idx","evalArrayElemAt","evalConcatArrays","asVar","as","cond","itemDoc","evalFilter","includes","evalIn","evalIndexOfArray","evalIsArray","inExpr","in","evalMap","initialValue","evalReduce","evalSize","evalSlice","reverse","evalReverseArray","inputs","useLongestLength","defaults","arrays","every","maxLength","tuple","evalZip","evalType","to","onError","onNull","parseFloat","Boolean","e","evalConvert","evalToBool","evalToDecimal","evalToDouble","evalToInt","evalToLong","evalToString","evalObjectToArray","evalArrayToObject","assign","evalMergeObjects","evaluateOperator","BSON_TYPES","TYPE_ALIASES","acc","matchesType","typeSpec","typeCode","typeName","toBitMask","positions","mask","matchesBitsAllSet","matchesBitsAllClear","matchesBitsAnySet","matchesBitsAnyClear","validateJsonSchema","schema","docType","required","properties","propSchema","minimum","maximum","minLength","pattern","enum","compareValues","aVal","bVal","fieldValueMatches","fieldValue","checkFn","tokenizeText","prop","propTokens","some","geoWithin","minLon","maxLat","maxLon","isGeometryWithinBBox","geoJson","minLat","features","geometry","coordinates","lng","lat","ring","coord","extractCoordinatesFromGeoJSON","sumLat","sumLng","haversineDistance","lat1","lng1","lat2","lng2","dLat","PI","dLng","sin","cos","atan2","isNear","refLng","refLat","maxDistanceMeters","coords","geoIntersects","queryGeo","queryCoords","docCoords","pointInPolygon","queryPt","inside","xi","yi","xj","yj","where","tlMatches","opMatches","and","els","or","not","nor","searchText","searchObject","textSearchDocument","$search","rawValue","$options","regex","$geometry","$maxDistance","arrayFieldValue","found","element","matchesPrimitive","opKeys","op","opValue","matches","sizeFieldValue","matchWithArrayIndices","arrayFilters","matched","andWithTracking","tlMatchesWithTracking","baseField","trackMatchingIndex","opMatchesWithTracking","orWithTracking","norWithTracking","parseFieldPath","segment","identifier","extractFilteredPositionalIdentifier","isFilteredPositional","applyToFilteredArrayElements","parsedPath","traverse","pathIndex","filterContext","pathInfo","isLastSegment","f","nextPath","applyOperationToValue","shouldUpdate","transformedFilter","hasDirectMatch","container","hasFilteredPositionalOperator","hasAllPositional","applyToAllPositional","updateFn","newValue","replacePositionalOperator","parts","dollarIndex","pathBeforeDollar","matchedIndex","filterPath","applyUpdates","updates","setOnInsert","positionalMatchInfo","userArrayFilters","fields","amount","currentValue","$type","addValue","currentArray","popValue","src","notRemoved","shouldRemove","__temp","toRemove","removed","l","pushValue","$each","$position","$slice","$sort","valuesToPush","sortKey","sortDir","sliceValue","createDocFromUpdate","newDoc","onlyFields","updateKeys","queryKeys","Index","storage","update","oldDoc","getSpec","VERSION_METADATA_SUFFIX","DEFAULT_COMPACTION_MIN_BYTES","buildVersionedPath","basePath","numericVersion","isFinite","normalizeMetadata","currentVersion","refCounts","splitPath","filePath","filename","async","getDirectoryHandle","dir","globalThis","navigator","getDirectory","part","ensureDirectoryForFile","getFileHandle","readMetadata","metadataPath","fileHandle","getFile","JSON","parse","writeMetadata","writable","createWritable","stringify","cleanupVersionIfUnreferenced","suffixes","versionedBase","suffix","removeFile","deleteVersionedFiles","acquireVersionedPath","releaseVersionedPath","promoteVersion","newVersion","oldVersion","nextVersion","getCurrentVersion","removeEntry","createSyncAccessHandle","reset","RegularCollectionIndex","storageFilePath","storageVersionedPath","storageVersion","_releaseStorage","versionedPath","dirHandle","_maybeCompact","compactPath","extractIndexKey","keyFields","keyParts","indexKey","docIds","filtered","indexFields","queryValue","_queryWithOperators","operators","ops","hasGt","hasLt","minValue","Infinity","maxValue","rangeResults","allEntries","excludeValue","TEXT_INDEX_SUFFIXES","TextCollectionIndex","storageBasePath","versionedBasePath","textIndex","syncHandles","indexedFields","indexTree","_createBPlusTree","_getActiveBasePath","docTermsTree","lengthsTree","_closeSyncHandles","_deleteIndexFiles","_ensureDirectoryForFile","handle","_deleteFile","totalSize","compactBase","indexHandle","docTermsHandle","lengthsHandle","_extractText","textParts","textIndexVersion","weights","_getWeights","intersects","bbox1","bbox2","maxLng","minLng","area","bbox","union","enlargement","RTreeNode","rtree","nodeData","updateBBox","RTree","_loadFromFile","_writeMetadata","insert","objectId","_insert","pointers","pointer1","pointer2","_split","targetPointer","_chooseSubtree","targetNode","childIndex","minEnlargement","minArea","enl","ar","maxDist","seed1Idx","seed2Idx","node1","node2","dist","enl1","enl2","searchBBox","_searchBBox","searchRadius","radiusKm","latDelta","lngDelta","radiusToBoundingBox","_searchBBoxEntries","distance","_remove","underflow","initialLength","updatedChildren","handled","_handleUnderflow","merged","updatedNode","parentNode","childResult","siblings","prevPointer","prevNode","nextPointer","nextNode","sibling","allChildren","newChild1Children","newChild2Children","newChild1","newChild2","minIndex","maxIndex","mergedChildren","mergedNode","mergedPointer","_","dest","pointerMap","cloneNode","sourceNode","clonedChildren","newChildPtr","clonedNode","newPointer","newRootPointer","GeospatialIndex","storageFile","geoField","_extractCoordinates","geoValue","geoQuery","$geoWithin","$near","nearQuery","maxDistanceKm","$nearSphere","$geoIntersects","intersectsQuery","epsilon","_pointInPolygon","QueryPlan","indexes","indexScans","estimatedCost","indexOnly","QueryPlanner","plan","analysis","_analyzeQuery","hasTextSearch","textPlan","_planTextSearch","hasGeoQuery","geoPlan","_planGeoQuery","andPlan","_planAndQuery","orPlan","_planOrQuery","simplePlan","_planSimpleQuery","conditions","$and","subAnalysis","$or","textQuery","_extractTextQuery","$text","indexableConditions","conditionPlan","_canIndexHandleQuery","_executeIndexScan","execute","sorted","currentSet","ChangeStream","pipeline","closed","_changeCounter","_startWatching","_isDB","dbName","getCollectionNames","collections","_isServer","databases","_getDB","_isMongoClient","connect","_getCollectionsToWatch","_watchCollection","_interceptServerDBCreation","_interceptDBCollectionCreation","_interceptClientDBCreation","collectionNames","isCollection","_monitorClient","_monitorDB","handlers","_emitChange","updateDescription","operationType","changeEvent","_createChangeEvent","_matchesPipeline","event","_data","btoa","clusterTime","ns","coll","documentKey","fullDocument","updatedFields","removedFields","truncatedArrays","$match","_getNestedValue","client","originalDb","self","_watchedDBs","opts","colName","col","_interceptDBCollectionCreationForClient","_originalClientMethods","server","originalGetDB","_interceptDBCollectionCreationForServer","_originalServerMethods","originalCollection","originalCreateCollection","createCollection","originalGetCollection","getCollection","_originalDBMethods","queue","resolveNext","streamClosed","onChange","change","done","onClose","cleanup","globalTimer","timings","nestedLevel","setEnabled","category","details","startTime","performance","timer","additionalDetails","duration","getTimings","getTimingsByCategory","grouped","timing","getSummary","summary","total","avg","stats","formatTimings","output","repeat","byCategory","stat","toFixed","Collection","baseFolder","documentsPath","documentsVersionedPath","documentsVersion","_releaseDocuments","bPlusTreeOrder","_initialize","_loadIndexes","entryName","entryHandle","kind","versionSuffixPattern","normalizedName","endsWith","_parseIndexName","_getIndexPath","tokens","_maybeCompactDocuments","generateIndexName","isTextIndex","isGeospatialIndex","sanitizedIndexName","_buildIndex","updateIndexesOnInsert","promises","_ensureIndexOpen","updateIndexesOnDelete","planQuery","useIndex","planType","indexNames","planQueryAsync","getTextIndex","aggregate","stageCount","loadTimer","docCount","stageKeys","stageType","stageSpec","stageTimer","inputDocs","outputDocs","projected","applyProjectionWithExpressions","modified","fieldsToRemove","groups","groupId","keyStr","accumulators","groupKey","group","accumulator","accKeys","accType","accExpr","valKey","mean","variance","groupCount","unwound","unwoundDoc","newRootSpec","shuffled","groupBy","boundaries","defaultBucket","$sum","buckets","placed","bucketed","bucketKey","bucket","numBuckets","bucketSize","startIdx","endIdx","bucketDocs","targetCollectionName","dropCollection","targetCollection","insertOne","whenMatched","whenNotMatched","into","matchField","matchValue","existingCursor","replaceOne","localField","foreignField","fromCollection","joined","localValue","foreignCursor","startWith","connectFromField","connectToField","maxDepth","depthField","restrictSearchWithMatch","graphed","startValue","visited","depth","valueKey","matchCopy","nextValue","facetResult","facetName","facetPipeline","facetResults","facetStage","facetStageKeys","facetStageType","facetStageSpec","redacted","decision","near","distanceField","maxDistance","minDistance","spherical","withDistances","location","deltaLat","deltaLon","dx","dy","resultCount","bulkWrite","copyTo","destCollectionName","destCol","numCopied","c","createIndex","existingIndex","dataSize","deleteOne","findOne","deletedCount","deleteMany","ids","distinct","vals","d","drop","collectionDir","entriesToDelete","recursive","dropIndex","nIndexesWas","dropIndexes","msg","ensureIndex","_validateProjection","documentsPromise","_findInternal","normalizedQuery","nearSpec","_extractNearSpec","seen","planTimer","queryPlan","docIdsCount","indexLookupTimer","docsFound","fullScanTimer","sortTimer","_sortByNearDistance","projectionTimer","docsProcessed","docsReturned","hasIndexes","_parseNearCoordinates","spec","_extractPointCoordinates","targetLat","targetLng","aPoint","bPoint","_haversineDistance","findAndModify","findOneAndDelete","findOneAndReplace","returnNewDocument","findOneAndUpdate","clone","getIndexes","getShardDistribution","getShardVersion","getStore","insertMany","storeTimer","indexTimer","indexCount","insertedId","insertedIds","insertedCount","isCapped","mapReduce","reIndex","matchedCount","modifiedCount","upsert","upsertedId","justOne","renameCollection","save","storageSize","totalIndexSize","multi","updateOne","findTimer","originalDoc","indexDelTimer","applyTimer","indexInsTimer","_getUpdateDescription","updateMany","updateCount","updatedCount","validate","updatedDoc","watch","isInclusion","hasComputedFields","DB","dbFolder","proxy","Proxy","property","_proxy","cloneCollection","cloneDatabase","commandHelp","copyDatabase","currentOp","collectionName","dropDatabase","eval","fsyncLock","fsyncUnlock","dbRef","getCollectionInfos","getLastError","getLastErrorObj","getLogComponents","getMongo","getName","getPrevError","getProfilingLevel","getProfilingStatus","getReplicationInfo","getSiblingDB","help","hostInfo","isMaster","killOp","listCommands","loadServerScripts","logout","printCollectionStats","printReplicationInfo","printShardingStatus","printSlaveReplicationInfo","repairDatabase","resetError","runCommand","serverBuildInfo","serverCmdLineOpts","serverStatus","setLogLevel","setProfilingLevel","shutdownServer","upgradeCheck","upgradeCheckAllDBs","Server","postEvent","cursors","cursorCounter","streams","streamCounter","dispatch","request","method","streamId","cursorOpts","_cursorOp","_changeStreamOp","_call","awaited","_registerCursor","_registerArrayAsCursor","_registerChangeStream","batch","exhausted","resultsArray","array","stream","payload","stack","serializePayload","WeakSet","__function","__objectId","__date","toISOString","deserializePayload","isNode","process","versions","initPromise","handleMessage","post","deserializedPayload","srv","createServer","success","importFunc","pathModule","urlModule","opfsModule","fileURLToPath","StorageManager","__filename","url","__dirname","dirname","projectRoot","customStorage","opfsNavigator","catch","parentPort","import","resp","postMessage","onmessage","initializeWorker","exit"],"mappings":"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","x_google_ignoreList":[0,1,6,7,8,16]}
|