@thatopen/services 0.24.0 → 0.26.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.
@@ -1 +1 @@
1
- {"version":3,"file":"index.es.js","sources":["../node_modules/engine.io-parser/build/esm/commons.js","../node_modules/engine.io-parser/build/esm/encodePacket.browser.js","../node_modules/engine.io-parser/build/esm/contrib/base64-arraybuffer.js","../node_modules/engine.io-parser/build/esm/decodePacket.browser.js","../node_modules/engine.io-parser/build/esm/index.js","../node_modules/@socket.io/component-emitter/lib/esm/index.js","../node_modules/engine.io-client/build/esm/globals.js","../node_modules/engine.io-client/build/esm/util.js","../node_modules/engine.io-client/build/esm/contrib/parseqs.js","../node_modules/engine.io-client/build/esm/transport.js","../node_modules/engine.io-client/build/esm/transports/polling.js","../node_modules/engine.io-client/build/esm/contrib/has-cors.js","../node_modules/engine.io-client/build/esm/transports/polling-xhr.js","../node_modules/engine.io-client/build/esm/transports/websocket.js","../node_modules/engine.io-client/build/esm/transports/webtransport.js","../node_modules/engine.io-client/build/esm/transports/index.js","../node_modules/engine.io-client/build/esm/contrib/parseuri.js","../node_modules/engine.io-client/build/esm/socket.js","../node_modules/socket.io-client/build/esm/url.js","../node_modules/socket.io-parser/build/esm/is-binary.js","../node_modules/socket.io-parser/build/esm/binary.js","../node_modules/socket.io-parser/build/esm/index.js","../node_modules/socket.io-client/build/esm/on.js","../node_modules/socket.io-client/build/esm/socket.js","../node_modules/socket.io-client/build/esm/contrib/backo2.js","../node_modules/socket.io-client/build/esm/manager.js","../node_modules/socket.io-client/build/esm/index.js","../src/core/documents.ts","../src/core/history.ts","../src/core/recipes.ts","../src/types/batch.ts","../src/core/request-error.ts","../src/core/client.ts","../src/core/channel.ts","../src/core/platform-client.ts","../src/core/op-builder.ts","../src/types/files.ts","../src/built-in/index.ts"],"sourcesContent":["const PACKET_TYPES = Object.create(null); // no Map = no polyfill\nPACKET_TYPES[\"open\"] = \"0\";\nPACKET_TYPES[\"close\"] = \"1\";\nPACKET_TYPES[\"ping\"] = \"2\";\nPACKET_TYPES[\"pong\"] = \"3\";\nPACKET_TYPES[\"message\"] = \"4\";\nPACKET_TYPES[\"upgrade\"] = \"5\";\nPACKET_TYPES[\"noop\"] = \"6\";\nconst PACKET_TYPES_REVERSE = Object.create(null);\nObject.keys(PACKET_TYPES).forEach((key) => {\n PACKET_TYPES_REVERSE[PACKET_TYPES[key]] = key;\n});\nconst ERROR_PACKET = { type: \"error\", data: \"parser error\" };\nexport { PACKET_TYPES, PACKET_TYPES_REVERSE, ERROR_PACKET };\n","import { PACKET_TYPES } from \"./commons.js\";\nconst withNativeBlob = typeof Blob === \"function\" ||\n (typeof Blob !== \"undefined\" &&\n Object.prototype.toString.call(Blob) === \"[object BlobConstructor]\");\nconst withNativeArrayBuffer = typeof ArrayBuffer === \"function\";\n// ArrayBuffer.isView method is not defined in IE10\nconst isView = (obj) => {\n return typeof ArrayBuffer.isView === \"function\"\n ? ArrayBuffer.isView(obj)\n : obj && obj.buffer instanceof ArrayBuffer;\n};\nconst encodePacket = ({ type, data }, supportsBinary, callback) => {\n if (withNativeBlob && data instanceof Blob) {\n if (supportsBinary) {\n return callback(data);\n }\n else {\n return encodeBlobAsBase64(data, callback);\n }\n }\n else if (withNativeArrayBuffer &&\n (data instanceof ArrayBuffer || isView(data))) {\n if (supportsBinary) {\n return callback(data);\n }\n else {\n return encodeBlobAsBase64(new Blob([data]), callback);\n }\n }\n // plain string\n return callback(PACKET_TYPES[type] + (data || \"\"));\n};\nconst encodeBlobAsBase64 = (data, callback) => {\n const fileReader = new FileReader();\n fileReader.onload = function () {\n const content = fileReader.result.split(\",\")[1];\n callback(\"b\" + (content || \"\"));\n };\n return fileReader.readAsDataURL(data);\n};\nfunction toArray(data) {\n if (data instanceof Uint8Array) {\n return data;\n }\n else if (data instanceof ArrayBuffer) {\n return new Uint8Array(data);\n }\n else {\n return new Uint8Array(data.buffer, data.byteOffset, data.byteLength);\n }\n}\nlet TEXT_ENCODER;\nexport function encodePacketToBinary(packet, callback) {\n if (withNativeBlob && packet.data instanceof Blob) {\n return packet.data.arrayBuffer().then(toArray).then(callback);\n }\n else if (withNativeArrayBuffer &&\n (packet.data instanceof ArrayBuffer || isView(packet.data))) {\n return callback(toArray(packet.data));\n }\n encodePacket(packet, false, (encoded) => {\n if (!TEXT_ENCODER) {\n TEXT_ENCODER = new TextEncoder();\n }\n callback(TEXT_ENCODER.encode(encoded));\n });\n}\nexport { encodePacket };\n","// imported from https://github.com/socketio/base64-arraybuffer\nconst chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';\n// Use a lookup table to find the index.\nconst lookup = typeof Uint8Array === 'undefined' ? [] : new Uint8Array(256);\nfor (let i = 0; i < chars.length; i++) {\n lookup[chars.charCodeAt(i)] = i;\n}\nexport const encode = (arraybuffer) => {\n let bytes = new Uint8Array(arraybuffer), i, len = bytes.length, base64 = '';\n for (i = 0; i < len; i += 3) {\n base64 += chars[bytes[i] >> 2];\n base64 += chars[((bytes[i] & 3) << 4) | (bytes[i + 1] >> 4)];\n base64 += chars[((bytes[i + 1] & 15) << 2) | (bytes[i + 2] >> 6)];\n base64 += chars[bytes[i + 2] & 63];\n }\n if (len % 3 === 2) {\n base64 = base64.substring(0, base64.length - 1) + '=';\n }\n else if (len % 3 === 1) {\n base64 = base64.substring(0, base64.length - 2) + '==';\n }\n return base64;\n};\nexport const decode = (base64) => {\n let bufferLength = base64.length * 0.75, len = base64.length, i, p = 0, encoded1, encoded2, encoded3, encoded4;\n if (base64[base64.length - 1] === '=') {\n bufferLength--;\n if (base64[base64.length - 2] === '=') {\n bufferLength--;\n }\n }\n const arraybuffer = new ArrayBuffer(bufferLength), bytes = new Uint8Array(arraybuffer);\n for (i = 0; i < len; i += 4) {\n encoded1 = lookup[base64.charCodeAt(i)];\n encoded2 = lookup[base64.charCodeAt(i + 1)];\n encoded3 = lookup[base64.charCodeAt(i + 2)];\n encoded4 = lookup[base64.charCodeAt(i + 3)];\n bytes[p++] = (encoded1 << 2) | (encoded2 >> 4);\n bytes[p++] = ((encoded2 & 15) << 4) | (encoded3 >> 2);\n bytes[p++] = ((encoded3 & 3) << 6) | (encoded4 & 63);\n }\n return arraybuffer;\n};\n","import { ERROR_PACKET, PACKET_TYPES_REVERSE, } from \"./commons.js\";\nimport { decode } from \"./contrib/base64-arraybuffer.js\";\nconst withNativeArrayBuffer = typeof ArrayBuffer === \"function\";\nexport const decodePacket = (encodedPacket, binaryType) => {\n if (typeof encodedPacket !== \"string\") {\n return {\n type: \"message\",\n data: mapBinary(encodedPacket, binaryType),\n };\n }\n const type = encodedPacket.charAt(0);\n if (type === \"b\") {\n return {\n type: \"message\",\n data: decodeBase64Packet(encodedPacket.substring(1), binaryType),\n };\n }\n const packetType = PACKET_TYPES_REVERSE[type];\n if (!packetType) {\n return ERROR_PACKET;\n }\n return encodedPacket.length > 1\n ? {\n type: PACKET_TYPES_REVERSE[type],\n data: encodedPacket.substring(1),\n }\n : {\n type: PACKET_TYPES_REVERSE[type],\n };\n};\nconst decodeBase64Packet = (data, binaryType) => {\n if (withNativeArrayBuffer) {\n const decoded = decode(data);\n return mapBinary(decoded, binaryType);\n }\n else {\n return { base64: true, data }; // fallback for old browsers\n }\n};\nconst mapBinary = (data, binaryType) => {\n switch (binaryType) {\n case \"blob\":\n if (data instanceof Blob) {\n // from WebSocket + binaryType \"blob\"\n return data;\n }\n else {\n // from HTTP long-polling or WebTransport\n return new Blob([data]);\n }\n case \"arraybuffer\":\n default:\n if (data instanceof ArrayBuffer) {\n // from HTTP long-polling (base64) or WebSocket + binaryType \"arraybuffer\"\n return data;\n }\n else {\n // from WebTransport (Uint8Array)\n return data.buffer;\n }\n }\n};\n","import { encodePacket, encodePacketToBinary } from \"./encodePacket.js\";\nimport { decodePacket } from \"./decodePacket.js\";\nimport { ERROR_PACKET, } from \"./commons.js\";\nconst SEPARATOR = String.fromCharCode(30); // see https://en.wikipedia.org/wiki/Delimiter#ASCII_delimited_text\nconst encodePayload = (packets, callback) => {\n // some packets may be added to the array while encoding, so the initial length must be saved\n const length = packets.length;\n const encodedPackets = new Array(length);\n let count = 0;\n packets.forEach((packet, i) => {\n // force base64 encoding for binary packets\n encodePacket(packet, false, (encodedPacket) => {\n encodedPackets[i] = encodedPacket;\n if (++count === length) {\n callback(encodedPackets.join(SEPARATOR));\n }\n });\n });\n};\nconst decodePayload = (encodedPayload, binaryType) => {\n const encodedPackets = encodedPayload.split(SEPARATOR);\n const packets = [];\n for (let i = 0; i < encodedPackets.length; i++) {\n const decodedPacket = decodePacket(encodedPackets[i], binaryType);\n packets.push(decodedPacket);\n if (decodedPacket.type === \"error\") {\n break;\n }\n }\n return packets;\n};\nexport function createPacketEncoderStream() {\n return new TransformStream({\n transform(packet, controller) {\n encodePacketToBinary(packet, (encodedPacket) => {\n const payloadLength = encodedPacket.length;\n let header;\n // inspired by the WebSocket format: https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers#decoding_payload_length\n if (payloadLength < 126) {\n header = new Uint8Array(1);\n new DataView(header.buffer).setUint8(0, payloadLength);\n }\n else if (payloadLength < 65536) {\n header = new Uint8Array(3);\n const view = new DataView(header.buffer);\n view.setUint8(0, 126);\n view.setUint16(1, payloadLength);\n }\n else {\n header = new Uint8Array(9);\n const view = new DataView(header.buffer);\n view.setUint8(0, 127);\n view.setBigUint64(1, BigInt(payloadLength));\n }\n // first bit indicates whether the payload is plain text (0) or binary (1)\n if (packet.data && typeof packet.data !== \"string\") {\n header[0] |= 0x80;\n }\n controller.enqueue(header);\n controller.enqueue(encodedPacket);\n });\n },\n });\n}\nlet TEXT_DECODER;\nfunction totalLength(chunks) {\n return chunks.reduce((acc, chunk) => acc + chunk.length, 0);\n}\nfunction concatChunks(chunks, size) {\n if (chunks[0].length === size) {\n return chunks.shift();\n }\n const buffer = new Uint8Array(size);\n let j = 0;\n for (let i = 0; i < size; i++) {\n buffer[i] = chunks[0][j++];\n if (j === chunks[0].length) {\n chunks.shift();\n j = 0;\n }\n }\n if (chunks.length && j < chunks[0].length) {\n chunks[0] = chunks[0].slice(j);\n }\n return buffer;\n}\nexport function createPacketDecoderStream(maxPayload, binaryType) {\n if (!TEXT_DECODER) {\n TEXT_DECODER = new TextDecoder();\n }\n const chunks = [];\n let state = 0 /* State.READ_HEADER */;\n let expectedLength = -1;\n let isBinary = false;\n return new TransformStream({\n transform(chunk, controller) {\n chunks.push(chunk);\n while (true) {\n if (state === 0 /* State.READ_HEADER */) {\n if (totalLength(chunks) < 1) {\n break;\n }\n const header = concatChunks(chunks, 1);\n isBinary = (header[0] & 0x80) === 0x80;\n expectedLength = header[0] & 0x7f;\n if (expectedLength < 126) {\n state = 3 /* State.READ_PAYLOAD */;\n }\n else if (expectedLength === 126) {\n state = 1 /* State.READ_EXTENDED_LENGTH_16 */;\n }\n else {\n state = 2 /* State.READ_EXTENDED_LENGTH_64 */;\n }\n }\n else if (state === 1 /* State.READ_EXTENDED_LENGTH_16 */) {\n if (totalLength(chunks) < 2) {\n break;\n }\n const headerArray = concatChunks(chunks, 2);\n expectedLength = new DataView(headerArray.buffer, headerArray.byteOffset, headerArray.length).getUint16(0);\n state = 3 /* State.READ_PAYLOAD */;\n }\n else if (state === 2 /* State.READ_EXTENDED_LENGTH_64 */) {\n if (totalLength(chunks) < 8) {\n break;\n }\n const headerArray = concatChunks(chunks, 8);\n const view = new DataView(headerArray.buffer, headerArray.byteOffset, headerArray.length);\n const n = view.getUint32(0);\n if (n > Math.pow(2, 53 - 32) - 1) {\n // the maximum safe integer in JavaScript is 2^53 - 1\n controller.enqueue(ERROR_PACKET);\n break;\n }\n expectedLength = n * Math.pow(2, 32) + view.getUint32(4);\n state = 3 /* State.READ_PAYLOAD */;\n }\n else {\n if (totalLength(chunks) < expectedLength) {\n break;\n }\n const data = concatChunks(chunks, expectedLength);\n controller.enqueue(decodePacket(isBinary ? data : TEXT_DECODER.decode(data), binaryType));\n state = 0 /* State.READ_HEADER */;\n }\n if (expectedLength === 0 || expectedLength > maxPayload) {\n controller.enqueue(ERROR_PACKET);\n break;\n }\n }\n },\n });\n}\nexport const protocol = 4;\nexport { encodePacket, encodePayload, decodePacket, decodePayload, };\n","/**\n * Initialize a new `Emitter`.\n *\n * @api public\n */\n\nexport function Emitter(obj) {\n if (obj) return mixin(obj);\n}\n\n/**\n * Mixin the emitter properties.\n *\n * @param {Object} obj\n * @return {Object}\n * @api private\n */\n\nfunction mixin(obj) {\n for (var key in Emitter.prototype) {\n obj[key] = Emitter.prototype[key];\n }\n return obj;\n}\n\n/**\n * Listen on the given `event` with `fn`.\n *\n * @param {String} event\n * @param {Function} fn\n * @return {Emitter}\n * @api public\n */\n\nEmitter.prototype.on =\nEmitter.prototype.addEventListener = function(event, fn){\n this._callbacks = this._callbacks || {};\n (this._callbacks['$' + event] = this._callbacks['$' + event] || [])\n .push(fn);\n return this;\n};\n\n/**\n * Adds an `event` listener that will be invoked a single\n * time then automatically removed.\n *\n * @param {String} event\n * @param {Function} fn\n * @return {Emitter}\n * @api public\n */\n\nEmitter.prototype.once = function(event, fn){\n function on() {\n this.off(event, on);\n fn.apply(this, arguments);\n }\n\n on.fn = fn;\n this.on(event, on);\n return this;\n};\n\n/**\n * Remove the given callback for `event` or all\n * registered callbacks.\n *\n * @param {String} event\n * @param {Function} fn\n * @return {Emitter}\n * @api public\n */\n\nEmitter.prototype.off =\nEmitter.prototype.removeListener =\nEmitter.prototype.removeAllListeners =\nEmitter.prototype.removeEventListener = function(event, fn){\n this._callbacks = this._callbacks || {};\n\n // all\n if (0 == arguments.length) {\n this._callbacks = {};\n return this;\n }\n\n // specific event\n var callbacks = this._callbacks['$' + event];\n if (!callbacks) return this;\n\n // remove all handlers\n if (1 == arguments.length) {\n delete this._callbacks['$' + event];\n return this;\n }\n\n // remove specific handler\n var cb;\n for (var i = 0; i < callbacks.length; i++) {\n cb = callbacks[i];\n if (cb === fn || cb.fn === fn) {\n callbacks.splice(i, 1);\n break;\n }\n }\n\n // Remove event specific arrays for event types that no\n // one is subscribed for to avoid memory leak.\n if (callbacks.length === 0) {\n delete this._callbacks['$' + event];\n }\n\n return this;\n};\n\n/**\n * Emit `event` with the given args.\n *\n * @param {String} event\n * @param {Mixed} ...\n * @return {Emitter}\n */\n\nEmitter.prototype.emit = function(event){\n this._callbacks = this._callbacks || {};\n\n var args = new Array(arguments.length - 1)\n , callbacks = this._callbacks['$' + event];\n\n for (var i = 1; i < arguments.length; i++) {\n args[i - 1] = arguments[i];\n }\n\n if (callbacks) {\n callbacks = callbacks.slice(0);\n for (var i = 0, len = callbacks.length; i < len; ++i) {\n callbacks[i].apply(this, args);\n }\n }\n\n return this;\n};\n\n// alias used for reserved events (protected method)\nEmitter.prototype.emitReserved = Emitter.prototype.emit;\n\n/**\n * Return array of callbacks for `event`.\n *\n * @param {String} event\n * @return {Array}\n * @api public\n */\n\nEmitter.prototype.listeners = function(event){\n this._callbacks = this._callbacks || {};\n return this._callbacks['$' + event] || [];\n};\n\n/**\n * Check if this emitter has `event` handlers.\n *\n * @param {String} event\n * @return {Boolean}\n * @api public\n */\n\nEmitter.prototype.hasListeners = function(event){\n return !! this.listeners(event).length;\n};\n","export const nextTick = (() => {\n const isPromiseAvailable = typeof Promise === \"function\" && typeof Promise.resolve === \"function\";\n if (isPromiseAvailable) {\n return (cb) => Promise.resolve().then(cb);\n }\n else {\n return (cb, setTimeoutFn) => setTimeoutFn(cb, 0);\n }\n})();\nexport const globalThisShim = (() => {\n if (typeof self !== \"undefined\") {\n return self;\n }\n else if (typeof window !== \"undefined\") {\n return window;\n }\n else {\n return Function(\"return this\")();\n }\n})();\nexport const defaultBinaryType = \"arraybuffer\";\nexport function createCookieJar() { }\n","import { globalThisShim as globalThis } from \"./globals.node.js\";\nexport function pick(obj, ...attr) {\n return attr.reduce((acc, k) => {\n if (obj.hasOwnProperty(k)) {\n acc[k] = obj[k];\n }\n return acc;\n }, {});\n}\n// Keep a reference to the real timeout functions so they can be used when overridden\nconst NATIVE_SET_TIMEOUT = globalThis.setTimeout;\nconst NATIVE_CLEAR_TIMEOUT = globalThis.clearTimeout;\nexport function installTimerFunctions(obj, opts) {\n if (opts.useNativeTimers) {\n obj.setTimeoutFn = NATIVE_SET_TIMEOUT.bind(globalThis);\n obj.clearTimeoutFn = NATIVE_CLEAR_TIMEOUT.bind(globalThis);\n }\n else {\n obj.setTimeoutFn = globalThis.setTimeout.bind(globalThis);\n obj.clearTimeoutFn = globalThis.clearTimeout.bind(globalThis);\n }\n}\n// base64 encoded buffers are about 33% bigger (https://en.wikipedia.org/wiki/Base64)\nconst BASE64_OVERHEAD = 1.33;\n// we could also have used `new Blob([obj]).size`, but it isn't supported in IE9\nexport function byteLength(obj) {\n if (typeof obj === \"string\") {\n return utf8Length(obj);\n }\n // arraybuffer or blob\n return Math.ceil((obj.byteLength || obj.size) * BASE64_OVERHEAD);\n}\nfunction utf8Length(str) {\n let c = 0, length = 0;\n for (let i = 0, l = str.length; i < l; i++) {\n c = str.charCodeAt(i);\n if (c < 0x80) {\n length += 1;\n }\n else if (c < 0x800) {\n length += 2;\n }\n else if (c < 0xd800 || c >= 0xe000) {\n length += 3;\n }\n else {\n i++;\n length += 4;\n }\n }\n return length;\n}\n/**\n * Generates a random 8-characters string.\n */\nexport function randomString() {\n return (Date.now().toString(36).substring(3) +\n Math.random().toString(36).substring(2, 5));\n}\n","// imported from https://github.com/galkn/querystring\n/**\n * Compiles a querystring\n * Returns string representation of the object\n *\n * @param {Object}\n * @api private\n */\nexport function encode(obj) {\n let str = '';\n for (let i in obj) {\n if (obj.hasOwnProperty(i)) {\n if (str.length)\n str += '&';\n str += encodeURIComponent(i) + '=' + encodeURIComponent(obj[i]);\n }\n }\n return str;\n}\n/**\n * Parses a simple querystring into an object\n *\n * @param {String} qs\n * @api private\n */\nexport function decode(qs) {\n let qry = {};\n let pairs = qs.split('&');\n for (let i = 0, l = pairs.length; i < l; i++) {\n let pair = pairs[i].split('=');\n qry[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1]);\n }\n return qry;\n}\n","import { decodePacket } from \"engine.io-parser\";\nimport { Emitter } from \"@socket.io/component-emitter\";\nimport { installTimerFunctions } from \"./util.js\";\nimport { encode } from \"./contrib/parseqs.js\";\nexport class TransportError extends Error {\n constructor(reason, description, context) {\n super(reason);\n this.description = description;\n this.context = context;\n this.type = \"TransportError\";\n }\n}\nexport class Transport extends Emitter {\n /**\n * Transport abstract constructor.\n *\n * @param {Object} opts - options\n * @protected\n */\n constructor(opts) {\n super();\n this.writable = false;\n installTimerFunctions(this, opts);\n this.opts = opts;\n this.query = opts.query;\n this.socket = opts.socket;\n this.supportsBinary = !opts.forceBase64;\n }\n /**\n * Emits an error.\n *\n * @param {String} reason\n * @param description\n * @param context - the error context\n * @return {Transport} for chaining\n * @protected\n */\n onError(reason, description, context) {\n super.emitReserved(\"error\", new TransportError(reason, description, context));\n return this;\n }\n /**\n * Opens the transport.\n */\n open() {\n this.readyState = \"opening\";\n this.doOpen();\n return this;\n }\n /**\n * Closes the transport.\n */\n close() {\n if (this.readyState === \"opening\" || this.readyState === \"open\") {\n this.doClose();\n this.onClose();\n }\n return this;\n }\n /**\n * Sends multiple packets.\n *\n * @param {Array} packets\n */\n send(packets) {\n if (this.readyState === \"open\") {\n this.write(packets);\n }\n else {\n // this might happen if the transport was silently closed in the beforeunload event handler\n }\n }\n /**\n * Called upon open\n *\n * @protected\n */\n onOpen() {\n this.readyState = \"open\";\n this.writable = true;\n super.emitReserved(\"open\");\n }\n /**\n * Called with data.\n *\n * @param {String} data\n * @protected\n */\n onData(data) {\n const packet = decodePacket(data, this.socket.binaryType);\n this.onPacket(packet);\n }\n /**\n * Called with a decoded packet.\n *\n * @protected\n */\n onPacket(packet) {\n super.emitReserved(\"packet\", packet);\n }\n /**\n * Called upon close.\n *\n * @protected\n */\n onClose(details) {\n this.readyState = \"closed\";\n super.emitReserved(\"close\", details);\n }\n /**\n * Pauses the transport, in order not to lose packets during an upgrade.\n *\n * @param onPause\n */\n pause(onPause) { }\n createUri(schema, query = {}) {\n return (schema +\n \"://\" +\n this._hostname() +\n this._port() +\n this.opts.path +\n this._query(query));\n }\n _hostname() {\n const hostname = this.opts.hostname;\n return hostname.indexOf(\":\") === -1 ? hostname : \"[\" + hostname + \"]\";\n }\n _port() {\n if (this.opts.port &&\n ((this.opts.secure && Number(this.opts.port) !== 443) ||\n (!this.opts.secure && Number(this.opts.port) !== 80))) {\n return \":\" + this.opts.port;\n }\n else {\n return \"\";\n }\n }\n _query(query) {\n const encodedQuery = encode(query);\n return encodedQuery.length ? \"?\" + encodedQuery : \"\";\n }\n}\n","import { Transport } from \"../transport.js\";\nimport { randomString } from \"../util.js\";\nimport { encodePayload, decodePayload } from \"engine.io-parser\";\nexport class Polling extends Transport {\n constructor() {\n super(...arguments);\n this._polling = false;\n }\n get name() {\n return \"polling\";\n }\n /**\n * Opens the socket (triggers polling). We write a PING message to determine\n * when the transport is open.\n *\n * @protected\n */\n doOpen() {\n this._poll();\n }\n /**\n * Pauses polling.\n *\n * @param {Function} onPause - callback upon buffers are flushed and transport is paused\n * @package\n */\n pause(onPause) {\n this.readyState = \"pausing\";\n const pause = () => {\n this.readyState = \"paused\";\n onPause();\n };\n if (this._polling || !this.writable) {\n let total = 0;\n if (this._polling) {\n total++;\n this.once(\"pollComplete\", function () {\n --total || pause();\n });\n }\n if (!this.writable) {\n total++;\n this.once(\"drain\", function () {\n --total || pause();\n });\n }\n }\n else {\n pause();\n }\n }\n /**\n * Starts polling cycle.\n *\n * @private\n */\n _poll() {\n this._polling = true;\n this.doPoll();\n this.emitReserved(\"poll\");\n }\n /**\n * Overloads onData to detect payloads.\n *\n * @protected\n */\n onData(data) {\n const callback = (packet) => {\n // if its the first message we consider the transport open\n if (\"opening\" === this.readyState && packet.type === \"open\") {\n this.onOpen();\n }\n // if its a close packet, we close the ongoing requests\n if (\"close\" === packet.type) {\n this.onClose({ description: \"transport closed by the server\" });\n return false;\n }\n // otherwise bypass onData and handle the message\n this.onPacket(packet);\n };\n // decode payload\n decodePayload(data, this.socket.binaryType).forEach(callback);\n // if an event did not trigger closing\n if (\"closed\" !== this.readyState) {\n // if we got data we're not polling\n this._polling = false;\n this.emitReserved(\"pollComplete\");\n if (\"open\" === this.readyState) {\n this._poll();\n }\n else {\n }\n }\n }\n /**\n * For polling, send a close packet.\n *\n * @protected\n */\n doClose() {\n const close = () => {\n this.write([{ type: \"close\" }]);\n };\n if (\"open\" === this.readyState) {\n close();\n }\n else {\n // in case we're trying to close while\n // handshaking is in progress (GH-164)\n this.once(\"open\", close);\n }\n }\n /**\n * Writes a packets payload.\n *\n * @param {Array} packets - data packets\n * @protected\n */\n write(packets) {\n this.writable = false;\n encodePayload(packets, (data) => {\n this.doWrite(data, () => {\n this.writable = true;\n this.emitReserved(\"drain\");\n });\n });\n }\n /**\n * Generates uri for connection.\n *\n * @private\n */\n uri() {\n const schema = this.opts.secure ? \"https\" : \"http\";\n const query = this.query || {};\n // cache busting is forced\n if (false !== this.opts.timestampRequests) {\n query[this.opts.timestampParam] = randomString();\n }\n if (!this.supportsBinary && !query.sid) {\n query.b64 = 1;\n }\n return this.createUri(schema, query);\n }\n}\n","// imported from https://github.com/component/has-cors\nlet value = false;\ntry {\n value = typeof XMLHttpRequest !== 'undefined' &&\n 'withCredentials' in new XMLHttpRequest();\n}\ncatch (err) {\n // if XMLHttp support is disabled in IE then it will throw\n // when trying to create\n}\nexport const hasCORS = value;\n","import { Polling } from \"./polling.js\";\nimport { Emitter } from \"@socket.io/component-emitter\";\nimport { installTimerFunctions, pick } from \"../util.js\";\nimport { globalThisShim as globalThis } from \"../globals.node.js\";\nimport { hasCORS } from \"../contrib/has-cors.js\";\nfunction empty() { }\nexport class BaseXHR extends Polling {\n /**\n * XHR Polling constructor.\n *\n * @param {Object} opts\n * @package\n */\n constructor(opts) {\n super(opts);\n if (typeof location !== \"undefined\") {\n const isSSL = \"https:\" === location.protocol;\n let port = location.port;\n // some user agents have empty `location.port`\n if (!port) {\n port = isSSL ? \"443\" : \"80\";\n }\n this.xd =\n (typeof location !== \"undefined\" &&\n opts.hostname !== location.hostname) ||\n port !== opts.port;\n }\n }\n /**\n * Sends data.\n *\n * @param {String} data - data to send.\n * @param {Function} fn - called upon flush.\n * @private\n */\n doWrite(data, fn) {\n const req = this.request({\n method: \"POST\",\n data: data,\n });\n req.on(\"success\", fn);\n req.on(\"error\", (xhrStatus, context) => {\n this.onError(\"xhr post error\", xhrStatus, context);\n });\n }\n /**\n * Starts a poll cycle.\n *\n * @private\n */\n doPoll() {\n const req = this.request();\n req.on(\"data\", this.onData.bind(this));\n req.on(\"error\", (xhrStatus, context) => {\n this.onError(\"xhr poll error\", xhrStatus, context);\n });\n this.pollXhr = req;\n }\n}\nexport class Request extends Emitter {\n /**\n * Request constructor\n *\n * @param {Object} options\n * @package\n */\n constructor(createRequest, uri, opts) {\n super();\n this.createRequest = createRequest;\n installTimerFunctions(this, opts);\n this._opts = opts;\n this._method = opts.method || \"GET\";\n this._uri = uri;\n this._data = undefined !== opts.data ? opts.data : null;\n this._create();\n }\n /**\n * Creates the XHR object and sends the request.\n *\n * @private\n */\n _create() {\n var _a;\n const opts = pick(this._opts, \"agent\", \"pfx\", \"key\", \"passphrase\", \"cert\", \"ca\", \"ciphers\", \"rejectUnauthorized\", \"autoUnref\");\n opts.xdomain = !!this._opts.xd;\n const xhr = (this._xhr = this.createRequest(opts));\n try {\n xhr.open(this._method, this._uri, true);\n try {\n if (this._opts.extraHeaders) {\n // @ts-ignore\n xhr.setDisableHeaderCheck && xhr.setDisableHeaderCheck(true);\n for (let i in this._opts.extraHeaders) {\n if (this._opts.extraHeaders.hasOwnProperty(i)) {\n xhr.setRequestHeader(i, this._opts.extraHeaders[i]);\n }\n }\n }\n }\n catch (e) { }\n if (\"POST\" === this._method) {\n try {\n xhr.setRequestHeader(\"Content-type\", \"text/plain;charset=UTF-8\");\n }\n catch (e) { }\n }\n try {\n xhr.setRequestHeader(\"Accept\", \"*/*\");\n }\n catch (e) { }\n (_a = this._opts.cookieJar) === null || _a === void 0 ? void 0 : _a.addCookies(xhr);\n // ie6 check\n if (\"withCredentials\" in xhr) {\n xhr.withCredentials = this._opts.withCredentials;\n }\n if (this._opts.requestTimeout) {\n xhr.timeout = this._opts.requestTimeout;\n }\n xhr.onreadystatechange = () => {\n var _a;\n if (xhr.readyState === 3) {\n (_a = this._opts.cookieJar) === null || _a === void 0 ? void 0 : _a.parseCookies(\n // @ts-ignore\n xhr.getResponseHeader(\"set-cookie\"));\n }\n if (4 !== xhr.readyState)\n return;\n if (200 === xhr.status || 1223 === xhr.status) {\n this._onLoad();\n }\n else {\n // make sure the `error` event handler that's user-set\n // does not throw in the same tick and gets caught here\n this.setTimeoutFn(() => {\n this._onError(typeof xhr.status === \"number\" ? xhr.status : 0);\n }, 0);\n }\n };\n xhr.send(this._data);\n }\n catch (e) {\n // Need to defer since .create() is called directly from the constructor\n // and thus the 'error' event can only be only bound *after* this exception\n // occurs. Therefore, also, we cannot throw here at all.\n this.setTimeoutFn(() => {\n this._onError(e);\n }, 0);\n return;\n }\n if (typeof document !== \"undefined\") {\n this._index = Request.requestsCount++;\n Request.requests[this._index] = this;\n }\n }\n /**\n * Called upon error.\n *\n * @private\n */\n _onError(err) {\n this.emitReserved(\"error\", err, this._xhr);\n this._cleanup(true);\n }\n /**\n * Cleans up house.\n *\n * @private\n */\n _cleanup(fromError) {\n if (\"undefined\" === typeof this._xhr || null === this._xhr) {\n return;\n }\n this._xhr.onreadystatechange = empty;\n if (fromError) {\n try {\n this._xhr.abort();\n }\n catch (e) { }\n }\n if (typeof document !== \"undefined\") {\n delete Request.requests[this._index];\n }\n this._xhr = null;\n }\n /**\n * Called upon load.\n *\n * @private\n */\n _onLoad() {\n const data = this._xhr.responseText;\n if (data !== null) {\n this.emitReserved(\"data\", data);\n this.emitReserved(\"success\");\n this._cleanup();\n }\n }\n /**\n * Aborts the request.\n *\n * @package\n */\n abort() {\n this._cleanup();\n }\n}\nRequest.requestsCount = 0;\nRequest.requests = {};\n/**\n * Aborts pending requests when unloading the window. This is needed to prevent\n * memory leaks (e.g. when using IE) and to ensure that no spurious error is\n * emitted.\n */\nif (typeof document !== \"undefined\") {\n // @ts-ignore\n if (typeof attachEvent === \"function\") {\n // @ts-ignore\n attachEvent(\"onunload\", unloadHandler);\n }\n else if (typeof addEventListener === \"function\") {\n const terminationEvent = \"onpagehide\" in globalThis ? \"pagehide\" : \"unload\";\n addEventListener(terminationEvent, unloadHandler, false);\n }\n}\nfunction unloadHandler() {\n for (let i in Request.requests) {\n if (Request.requests.hasOwnProperty(i)) {\n Request.requests[i].abort();\n }\n }\n}\nconst hasXHR2 = (function () {\n const xhr = newRequest({\n xdomain: false,\n });\n return xhr && xhr.responseType !== null;\n})();\n/**\n * HTTP long-polling based on the built-in `XMLHttpRequest` object.\n *\n * Usage: browser\n *\n * @see https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest\n */\nexport class XHR extends BaseXHR {\n constructor(opts) {\n super(opts);\n const forceBase64 = opts && opts.forceBase64;\n this.supportsBinary = hasXHR2 && !forceBase64;\n }\n request(opts = {}) {\n Object.assign(opts, { xd: this.xd }, this.opts);\n return new Request(newRequest, this.uri(), opts);\n }\n}\nfunction newRequest(opts) {\n const xdomain = opts.xdomain;\n // XMLHttpRequest can be disabled on IE\n try {\n if (\"undefined\" !== typeof XMLHttpRequest && (!xdomain || hasCORS)) {\n return new XMLHttpRequest();\n }\n }\n catch (e) { }\n if (!xdomain) {\n try {\n return new globalThis[[\"Active\"].concat(\"Object\").join(\"X\")](\"Microsoft.XMLHTTP\");\n }\n catch (e) { }\n }\n}\n","import { Transport } from \"../transport.js\";\nimport { pick, randomString } from \"../util.js\";\nimport { encodePacket } from \"engine.io-parser\";\nimport { globalThisShim as globalThis, nextTick } from \"../globals.node.js\";\n// detect ReactNative environment\nconst isReactNative = typeof navigator !== \"undefined\" &&\n typeof navigator.product === \"string\" &&\n navigator.product.toLowerCase() === \"reactnative\";\nexport class BaseWS extends Transport {\n get name() {\n return \"websocket\";\n }\n doOpen() {\n const uri = this.uri();\n const protocols = this.opts.protocols;\n // React Native only supports the 'headers' option, and will print a warning if anything else is passed\n const opts = isReactNative\n ? {}\n : pick(this.opts, \"agent\", \"perMessageDeflate\", \"pfx\", \"key\", \"passphrase\", \"cert\", \"ca\", \"ciphers\", \"rejectUnauthorized\", \"localAddress\", \"protocolVersion\", \"origin\", \"maxPayload\", \"family\", \"checkServerIdentity\");\n if (this.opts.extraHeaders) {\n opts.headers = this.opts.extraHeaders;\n }\n try {\n this.ws = this.createSocket(uri, protocols, opts);\n }\n catch (err) {\n return this.emitReserved(\"error\", err);\n }\n this.ws.binaryType = this.socket.binaryType;\n this.addEventListeners();\n }\n /**\n * Adds event listeners to the socket\n *\n * @private\n */\n addEventListeners() {\n this.ws.onopen = () => {\n if (this.opts.autoUnref) {\n this.ws._socket.unref();\n }\n this.onOpen();\n };\n this.ws.onclose = (closeEvent) => this.onClose({\n description: \"websocket connection closed\",\n context: closeEvent,\n });\n this.ws.onmessage = (ev) => this.onData(ev.data);\n this.ws.onerror = (e) => this.onError(\"websocket error\", e);\n }\n write(packets) {\n this.writable = false;\n // encodePacket efficient as it uses WS framing\n // no need for encodePayload\n for (let i = 0; i < packets.length; i++) {\n const packet = packets[i];\n const lastPacket = i === packets.length - 1;\n encodePacket(packet, this.supportsBinary, (data) => {\n // Sometimes the websocket has already been closed but the browser didn't\n // have a chance of informing us about it yet, in that case send will\n // throw an error\n try {\n this.doWrite(packet, data);\n }\n catch (e) {\n }\n if (lastPacket) {\n // fake drain\n // defer to next tick to allow Socket to clear writeBuffer\n nextTick(() => {\n this.writable = true;\n this.emitReserved(\"drain\");\n }, this.setTimeoutFn);\n }\n });\n }\n }\n doClose() {\n if (typeof this.ws !== \"undefined\") {\n this.ws.onerror = () => { };\n this.ws.close();\n this.ws = null;\n }\n }\n /**\n * Generates uri for connection.\n *\n * @private\n */\n uri() {\n const schema = this.opts.secure ? \"wss\" : \"ws\";\n const query = this.query || {};\n // append timestamp to URI\n if (this.opts.timestampRequests) {\n query[this.opts.timestampParam] = randomString();\n }\n // communicate binary support capabilities\n if (!this.supportsBinary) {\n query.b64 = 1;\n }\n return this.createUri(schema, query);\n }\n}\nconst WebSocketCtor = globalThis.WebSocket || globalThis.MozWebSocket;\n/**\n * WebSocket transport based on the built-in `WebSocket` object.\n *\n * Usage: browser, Node.js (since v21), Deno, Bun\n *\n * @see https://developer.mozilla.org/en-US/docs/Web/API/WebSocket\n * @see https://caniuse.com/mdn-api_websocket\n * @see https://nodejs.org/api/globals.html#websocket\n */\nexport class WS extends BaseWS {\n createSocket(uri, protocols, opts) {\n return !isReactNative\n ? protocols\n ? new WebSocketCtor(uri, protocols)\n : new WebSocketCtor(uri)\n : new WebSocketCtor(uri, protocols, opts);\n }\n doWrite(_packet, data) {\n this.ws.send(data);\n }\n}\n","import { Transport } from \"../transport.js\";\nimport { nextTick } from \"../globals.node.js\";\nimport { createPacketDecoderStream, createPacketEncoderStream, } from \"engine.io-parser\";\n/**\n * WebTransport transport based on the built-in `WebTransport` object.\n *\n * Usage: browser, Node.js (with the `@fails-components/webtransport` package)\n *\n * @see https://developer.mozilla.org/en-US/docs/Web/API/WebTransport\n * @see https://caniuse.com/webtransport\n */\nexport class WT extends Transport {\n get name() {\n return \"webtransport\";\n }\n doOpen() {\n try {\n // @ts-ignore\n this._transport = new WebTransport(this.createUri(\"https\"), this.opts.transportOptions[this.name]);\n }\n catch (err) {\n return this.emitReserved(\"error\", err);\n }\n this._transport.closed\n .then(() => {\n this.onClose();\n })\n .catch((err) => {\n this.onError(\"webtransport error\", err);\n });\n // note: we could have used async/await, but that would require some additional polyfills\n this._transport.ready.then(() => {\n this._transport.createBidirectionalStream().then((stream) => {\n const decoderStream = createPacketDecoderStream(Number.MAX_SAFE_INTEGER, this.socket.binaryType);\n const reader = stream.readable.pipeThrough(decoderStream).getReader();\n const encoderStream = createPacketEncoderStream();\n encoderStream.readable.pipeTo(stream.writable);\n this._writer = encoderStream.writable.getWriter();\n const read = () => {\n reader\n .read()\n .then(({ done, value }) => {\n if (done) {\n return;\n }\n this.onPacket(value);\n read();\n })\n .catch((err) => {\n });\n };\n read();\n const packet = { type: \"open\" };\n if (this.query.sid) {\n packet.data = `{\"sid\":\"${this.query.sid}\"}`;\n }\n this._writer.write(packet).then(() => this.onOpen());\n });\n });\n }\n write(packets) {\n this.writable = false;\n for (let i = 0; i < packets.length; i++) {\n const packet = packets[i];\n const lastPacket = i === packets.length - 1;\n this._writer.write(packet).then(() => {\n if (lastPacket) {\n nextTick(() => {\n this.writable = true;\n this.emitReserved(\"drain\");\n }, this.setTimeoutFn);\n }\n });\n }\n }\n doClose() {\n var _a;\n (_a = this._transport) === null || _a === void 0 ? void 0 : _a.close();\n }\n}\n","import { XHR } from \"./polling-xhr.node.js\";\nimport { WS } from \"./websocket.node.js\";\nimport { WT } from \"./webtransport.js\";\nexport const transports = {\n websocket: WS,\n webtransport: WT,\n polling: XHR,\n};\n","// imported from https://github.com/galkn/parseuri\n/**\n * Parses a URI\n *\n * Note: we could also have used the built-in URL object, but it isn't supported on all platforms.\n *\n * See:\n * - https://developer.mozilla.org/en-US/docs/Web/API/URL\n * - https://caniuse.com/url\n * - https://www.rfc-editor.org/rfc/rfc3986#appendix-B\n *\n * History of the parse() method:\n * - first commit: https://github.com/socketio/socket.io-client/commit/4ee1d5d94b3906a9c052b459f1a818b15f38f91c\n * - export into its own module: https://github.com/socketio/engine.io-client/commit/de2c561e4564efeb78f1bdb1ba39ef81b2822cb3\n * - reimport: https://github.com/socketio/engine.io-client/commit/df32277c3f6d622eec5ed09f493cae3f3391d242\n *\n * @author Steven Levithan <stevenlevithan.com> (MIT license)\n * @api private\n */\nconst re = /^(?:(?![^:@\\/?#]+:[^:@\\/]*@)(http|https|ws|wss):\\/\\/)?((?:(([^:@\\/?#]*)(?::([^:@\\/?#]*))?)?@)?((?:[a-f0-9]{0,4}:){2,7}[a-f0-9]{0,4}|[^:\\/?#]*)(?::(\\d*))?)(((\\/(?:[^?#](?![^?#\\/]*\\.[^?#\\/.]+(?:[?#]|$)))*\\/?)?([^?#\\/]*))(?:\\?([^#]*))?(?:#(.*))?)/;\nconst parts = [\n 'source', 'protocol', 'authority', 'userInfo', 'user', 'password', 'host', 'port', 'relative', 'path', 'directory', 'file', 'query', 'anchor'\n];\nexport function parse(str) {\n if (str.length > 8000) {\n throw \"URI too long\";\n }\n const src = str, b = str.indexOf('['), e = str.indexOf(']');\n if (b != -1 && e != -1) {\n str = str.substring(0, b) + str.substring(b, e).replace(/:/g, ';') + str.substring(e, str.length);\n }\n let m = re.exec(str || ''), uri = {}, i = 14;\n while (i--) {\n uri[parts[i]] = m[i] || '';\n }\n if (b != -1 && e != -1) {\n uri.source = src;\n uri.host = uri.host.substring(1, uri.host.length - 1).replace(/;/g, ':');\n uri.authority = uri.authority.replace('[', '').replace(']', '').replace(/;/g, ':');\n uri.ipv6uri = true;\n }\n uri.pathNames = pathNames(uri, uri['path']);\n uri.queryKey = queryKey(uri, uri['query']);\n return uri;\n}\nfunction pathNames(obj, path) {\n const regx = /\\/{2,9}/g, names = path.replace(regx, \"/\").split(\"/\");\n if (path.slice(0, 1) == '/' || path.length === 0) {\n names.splice(0, 1);\n }\n if (path.slice(-1) == '/') {\n names.splice(names.length - 1, 1);\n }\n return names;\n}\nfunction queryKey(uri, query) {\n const data = {};\n query.replace(/(?:^|&)([^&=]*)=?([^&]*)/g, function ($0, $1, $2) {\n if ($1) {\n data[$1] = $2;\n }\n });\n return data;\n}\n","import { transports as DEFAULT_TRANSPORTS } from \"./transports/index.js\";\nimport { installTimerFunctions, byteLength } from \"./util.js\";\nimport { decode } from \"./contrib/parseqs.js\";\nimport { parse } from \"./contrib/parseuri.js\";\nimport { Emitter } from \"@socket.io/component-emitter\";\nimport { protocol } from \"engine.io-parser\";\nimport { createCookieJar, defaultBinaryType, nextTick, } from \"./globals.node.js\";\nconst withEventListeners = typeof addEventListener === \"function\" &&\n typeof removeEventListener === \"function\";\nconst OFFLINE_EVENT_LISTENERS = [];\nif (withEventListeners) {\n // within a ServiceWorker, any event handler for the 'offline' event must be added on the initial evaluation of the\n // script, so we create one single event listener here which will forward the event to the socket instances\n addEventListener(\"offline\", () => {\n OFFLINE_EVENT_LISTENERS.forEach((listener) => listener());\n }, false);\n}\n/**\n * This class provides a WebSocket-like interface to connect to an Engine.IO server. The connection will be established\n * with one of the available low-level transports, like HTTP long-polling, WebSocket or WebTransport.\n *\n * This class comes without upgrade mechanism, which means that it will keep the first low-level transport that\n * successfully establishes the connection.\n *\n * In order to allow tree-shaking, there are no transports included, that's why the `transports` option is mandatory.\n *\n * @example\n * import { SocketWithoutUpgrade, WebSocket } from \"engine.io-client\";\n *\n * const socket = new SocketWithoutUpgrade({\n * transports: [WebSocket]\n * });\n *\n * socket.on(\"open\", () => {\n * socket.send(\"hello\");\n * });\n *\n * @see SocketWithUpgrade\n * @see Socket\n */\nexport class SocketWithoutUpgrade extends Emitter {\n /**\n * Socket constructor.\n *\n * @param {String|Object} uri - uri or options\n * @param {Object} opts - options\n */\n constructor(uri, opts) {\n super();\n this.binaryType = defaultBinaryType;\n this.writeBuffer = [];\n this._prevBufferLen = 0;\n this._pingInterval = -1;\n this._pingTimeout = -1;\n this._maxPayload = -1;\n /**\n * The expiration timestamp of the {@link _pingTimeoutTimer} object is tracked, in case the timer is throttled and the\n * callback is not fired on time. This can happen for example when a laptop is suspended or when a phone is locked.\n */\n this._pingTimeoutTime = Infinity;\n if (uri && \"object\" === typeof uri) {\n opts = uri;\n uri = null;\n }\n if (uri) {\n const parsedUri = parse(uri);\n opts.hostname = parsedUri.host;\n opts.secure =\n parsedUri.protocol === \"https\" || parsedUri.protocol === \"wss\";\n opts.port = parsedUri.port;\n if (parsedUri.query)\n opts.query = parsedUri.query;\n }\n else if (opts.host) {\n opts.hostname = parse(opts.host).host;\n }\n installTimerFunctions(this, opts);\n this.secure =\n null != opts.secure\n ? opts.secure\n : typeof location !== \"undefined\" && \"https:\" === location.protocol;\n if (opts.hostname && !opts.port) {\n // if no port is specified manually, use the protocol default\n opts.port = this.secure ? \"443\" : \"80\";\n }\n this.hostname =\n opts.hostname ||\n (typeof location !== \"undefined\" ? location.hostname : \"localhost\");\n this.port =\n opts.port ||\n (typeof location !== \"undefined\" && location.port\n ? location.port\n : this.secure\n ? \"443\"\n : \"80\");\n this.transports = [];\n this._transportsByName = {};\n opts.transports.forEach((t) => {\n const transportName = t.prototype.name;\n this.transports.push(transportName);\n this._transportsByName[transportName] = t;\n });\n this.opts = Object.assign({\n path: \"/engine.io\",\n agent: false,\n withCredentials: false,\n upgrade: true,\n timestampParam: \"t\",\n rememberUpgrade: false,\n addTrailingSlash: true,\n rejectUnauthorized: true,\n perMessageDeflate: {\n threshold: 1024,\n },\n transportOptions: {},\n closeOnBeforeunload: false,\n }, opts);\n this.opts.path =\n this.opts.path.replace(/\\/$/, \"\") +\n (this.opts.addTrailingSlash ? \"/\" : \"\");\n if (typeof this.opts.query === \"string\") {\n this.opts.query = decode(this.opts.query);\n }\n if (withEventListeners) {\n if (this.opts.closeOnBeforeunload) {\n // Firefox closes the connection when the \"beforeunload\" event is emitted but not Chrome. This event listener\n // ensures every browser behaves the same (no \"disconnect\" event at the Socket.IO level when the page is\n // closed/reloaded)\n this._beforeunloadEventListener = () => {\n if (this.transport) {\n // silently close the transport\n this.transport.removeAllListeners();\n this.transport.close();\n }\n };\n addEventListener(\"beforeunload\", this._beforeunloadEventListener, false);\n }\n if (this.hostname !== \"localhost\") {\n this._offlineEventListener = () => {\n this._onClose(\"transport close\", {\n description: \"network connection lost\",\n });\n };\n OFFLINE_EVENT_LISTENERS.push(this._offlineEventListener);\n }\n }\n if (this.opts.withCredentials) {\n this._cookieJar = createCookieJar();\n }\n this._open();\n }\n /**\n * Creates transport of the given type.\n *\n * @param {String} name - transport name\n * @return {Transport}\n * @private\n */\n createTransport(name) {\n const query = Object.assign({}, this.opts.query);\n // append engine.io protocol identifier\n query.EIO = protocol;\n // transport name\n query.transport = name;\n // session id if we already have one\n if (this.id)\n query.sid = this.id;\n const opts = Object.assign({}, this.opts, {\n query,\n socket: this,\n hostname: this.hostname,\n secure: this.secure,\n port: this.port,\n }, this.opts.transportOptions[name]);\n return new this._transportsByName[name](opts);\n }\n /**\n * Initializes transport to use and starts probe.\n *\n * @private\n */\n _open() {\n if (this.transports.length === 0) {\n // Emit error on next tick so it can be listened to\n this.setTimeoutFn(() => {\n this.emitReserved(\"error\", \"No transports available\");\n }, 0);\n return;\n }\n const transportName = this.opts.rememberUpgrade &&\n SocketWithoutUpgrade.priorWebsocketSuccess &&\n this.transports.indexOf(\"websocket\") !== -1\n ? \"websocket\"\n : this.transports[0];\n this.readyState = \"opening\";\n const transport = this.createTransport(transportName);\n transport.open();\n this.setTransport(transport);\n }\n /**\n * Sets the current transport. Disables the existing one (if any).\n *\n * @private\n */\n setTransport(transport) {\n if (this.transport) {\n this.transport.removeAllListeners();\n }\n // set up transport\n this.transport = transport;\n // set up transport listeners\n transport\n .on(\"drain\", this._onDrain.bind(this))\n .on(\"packet\", this._onPacket.bind(this))\n .on(\"error\", this._onError.bind(this))\n .on(\"close\", (reason) => this._onClose(\"transport close\", reason));\n }\n /**\n * Called when connection is deemed open.\n *\n * @private\n */\n onOpen() {\n this.readyState = \"open\";\n SocketWithoutUpgrade.priorWebsocketSuccess =\n \"websocket\" === this.transport.name;\n this.emitReserved(\"open\");\n this.flush();\n }\n /**\n * Handles a packet.\n *\n * @private\n */\n _onPacket(packet) {\n if (\"opening\" === this.readyState ||\n \"open\" === this.readyState ||\n \"closing\" === this.readyState) {\n this.emitReserved(\"packet\", packet);\n // Socket is live - any packet counts\n this.emitReserved(\"heartbeat\");\n switch (packet.type) {\n case \"open\":\n this.onHandshake(JSON.parse(packet.data));\n break;\n case \"ping\":\n this._sendPacket(\"pong\");\n this.emitReserved(\"ping\");\n this.emitReserved(\"pong\");\n this._resetPingTimeout();\n break;\n case \"error\":\n const err = new Error(\"server error\");\n // @ts-ignore\n err.code = packet.data;\n this._onError(err);\n break;\n case \"message\":\n this.emitReserved(\"data\", packet.data);\n this.emitReserved(\"message\", packet.data);\n break;\n }\n }\n else {\n }\n }\n /**\n * Called upon handshake completion.\n *\n * @param {Object} data - handshake obj\n * @private\n */\n onHandshake(data) {\n this.emitReserved(\"handshake\", data);\n this.id = data.sid;\n this.transport.query.sid = data.sid;\n this._pingInterval = data.pingInterval;\n this._pingTimeout = data.pingTimeout;\n this._maxPayload = data.maxPayload;\n this.onOpen();\n // In case open handler closes socket\n if (\"closed\" === this.readyState)\n return;\n this._resetPingTimeout();\n }\n /**\n * Sets and resets ping timeout timer based on server pings.\n *\n * @private\n */\n _resetPingTimeout() {\n this.clearTimeoutFn(this._pingTimeoutTimer);\n const delay = this._pingInterval + this._pingTimeout;\n this._pingTimeoutTime = Date.now() + delay;\n this._pingTimeoutTimer = this.setTimeoutFn(() => {\n this._onClose(\"ping timeout\");\n }, delay);\n if (this.opts.autoUnref) {\n this._pingTimeoutTimer.unref();\n }\n }\n /**\n * Called on `drain` event\n *\n * @private\n */\n _onDrain() {\n this.writeBuffer.splice(0, this._prevBufferLen);\n // setting prevBufferLen = 0 is very important\n // for example, when upgrading, upgrade packet is sent over,\n // and a nonzero prevBufferLen could cause problems on `drain`\n this._prevBufferLen = 0;\n if (0 === this.writeBuffer.length) {\n this.emitReserved(\"drain\");\n }\n else {\n this.flush();\n }\n }\n /**\n * Flush write buffers.\n *\n * @private\n */\n flush() {\n if (\"closed\" !== this.readyState &&\n this.transport.writable &&\n !this.upgrading &&\n this.writeBuffer.length) {\n const packets = this._getWritablePackets();\n this.transport.send(packets);\n // keep track of current length of writeBuffer\n // splice writeBuffer and callbackBuffer on `drain`\n this._prevBufferLen = packets.length;\n this.emitReserved(\"flush\");\n }\n }\n /**\n * Ensure the encoded size of the writeBuffer is below the maxPayload value sent by the server (only for HTTP\n * long-polling)\n *\n * @private\n */\n _getWritablePackets() {\n const shouldCheckPayloadSize = this._maxPayload &&\n this.transport.name === \"polling\" &&\n this.writeBuffer.length > 1;\n if (!shouldCheckPayloadSize) {\n return this.writeBuffer;\n }\n let payloadSize = 1; // first packet type\n for (let i = 0; i < this.writeBuffer.length; i++) {\n const data = this.writeBuffer[i].data;\n if (data) {\n payloadSize += byteLength(data);\n }\n if (i > 0 && payloadSize > this._maxPayload) {\n return this.writeBuffer.slice(0, i);\n }\n payloadSize += 2; // separator + packet type\n }\n return this.writeBuffer;\n }\n /**\n * Checks whether the heartbeat timer has expired but the socket has not yet been notified.\n *\n * Note: this method is private for now because it does not really fit the WebSocket API, but if we put it in the\n * `write()` method then the message would not be buffered by the Socket.IO client.\n *\n * @return {boolean}\n * @private\n */\n /* private */ _hasPingExpired() {\n if (!this._pingTimeoutTime)\n return true;\n const hasExpired = Date.now() > this._pingTimeoutTime;\n if (hasExpired) {\n this._pingTimeoutTime = 0;\n nextTick(() => {\n this._onClose(\"ping timeout\");\n }, this.setTimeoutFn);\n }\n return hasExpired;\n }\n /**\n * Sends a message.\n *\n * @param {String} msg - message.\n * @param {Object} options.\n * @param {Function} fn - callback function.\n * @return {Socket} for chaining.\n */\n write(msg, options, fn) {\n this._sendPacket(\"message\", msg, options, fn);\n return this;\n }\n /**\n * Sends a message. Alias of {@link Socket#write}.\n *\n * @param {String} msg - message.\n * @param {Object} options.\n * @param {Function} fn - callback function.\n * @return {Socket} for chaining.\n */\n send(msg, options, fn) {\n this._sendPacket(\"message\", msg, options, fn);\n return this;\n }\n /**\n * Sends a packet.\n *\n * @param {String} type - packet type.\n * @param {String} data.\n * @param {Object} options.\n * @param {Function} fn - callback function.\n * @private\n */\n _sendPacket(type, data, options, fn) {\n if (\"function\" === typeof data) {\n fn = data;\n data = undefined;\n }\n if (\"function\" === typeof options) {\n fn = options;\n options = null;\n }\n if (\"closing\" === this.readyState || \"closed\" === this.readyState) {\n return;\n }\n options = options || {};\n options.compress = false !== options.compress;\n const packet = {\n type: type,\n data: data,\n options: options,\n };\n this.emitReserved(\"packetCreate\", packet);\n this.writeBuffer.push(packet);\n if (fn)\n this.once(\"flush\", fn);\n this.flush();\n }\n /**\n * Closes the connection.\n */\n close() {\n const close = () => {\n this._onClose(\"forced close\");\n this.transport.close();\n };\n const cleanupAndClose = () => {\n this.off(\"upgrade\", cleanupAndClose);\n this.off(\"upgradeError\", cleanupAndClose);\n close();\n };\n const waitForUpgrade = () => {\n // wait for upgrade to finish since we can't send packets while pausing a transport\n this.once(\"upgrade\", cleanupAndClose);\n this.once(\"upgradeError\", cleanupAndClose);\n };\n if (\"opening\" === this.readyState || \"open\" === this.readyState) {\n this.readyState = \"closing\";\n if (this.writeBuffer.length) {\n this.once(\"drain\", () => {\n if (this.upgrading) {\n waitForUpgrade();\n }\n else {\n close();\n }\n });\n }\n else if (this.upgrading) {\n waitForUpgrade();\n }\n else {\n close();\n }\n }\n return this;\n }\n /**\n * Called upon transport error\n *\n * @private\n */\n _onError(err) {\n SocketWithoutUpgrade.priorWebsocketSuccess = false;\n if (this.opts.tryAllTransports &&\n this.transports.length > 1 &&\n this.readyState === \"opening\") {\n this.transports.shift();\n return this._open();\n }\n this.emitReserved(\"error\", err);\n this._onClose(\"transport error\", err);\n }\n /**\n * Called upon transport close.\n *\n * @private\n */\n _onClose(reason, description) {\n if (\"opening\" === this.readyState ||\n \"open\" === this.readyState ||\n \"closing\" === this.readyState) {\n // clear timers\n this.clearTimeoutFn(this._pingTimeoutTimer);\n // stop event from firing again for transport\n this.transport.removeAllListeners(\"close\");\n // ensure transport won't stay open\n this.transport.close();\n // ignore further transport communication\n this.transport.removeAllListeners();\n if (withEventListeners) {\n if (this._beforeunloadEventListener) {\n removeEventListener(\"beforeunload\", this._beforeunloadEventListener, false);\n }\n if (this._offlineEventListener) {\n const i = OFFLINE_EVENT_LISTENERS.indexOf(this._offlineEventListener);\n if (i !== -1) {\n OFFLINE_EVENT_LISTENERS.splice(i, 1);\n }\n }\n }\n // set ready state\n this.readyState = \"closed\";\n // clear session id\n this.id = null;\n // emit close event\n this.emitReserved(\"close\", reason, description);\n // clean buffers after, so users can still\n // grab the buffers on `close` event\n this.writeBuffer = [];\n this._prevBufferLen = 0;\n }\n }\n}\nSocketWithoutUpgrade.protocol = protocol;\n/**\n * This class provides a WebSocket-like interface to connect to an Engine.IO server. The connection will be established\n * with one of the available low-level transports, like HTTP long-polling, WebSocket or WebTransport.\n *\n * This class comes with an upgrade mechanism, which means that once the connection is established with the first\n * low-level transport, it will try to upgrade to a better transport.\n *\n * In order to allow tree-shaking, there are no transports included, that's why the `transports` option is mandatory.\n *\n * @example\n * import { SocketWithUpgrade, WebSocket } from \"engine.io-client\";\n *\n * const socket = new SocketWithUpgrade({\n * transports: [WebSocket]\n * });\n *\n * socket.on(\"open\", () => {\n * socket.send(\"hello\");\n * });\n *\n * @see SocketWithoutUpgrade\n * @see Socket\n */\nexport class SocketWithUpgrade extends SocketWithoutUpgrade {\n constructor() {\n super(...arguments);\n this._upgrades = [];\n }\n onOpen() {\n super.onOpen();\n if (\"open\" === this.readyState && this.opts.upgrade) {\n for (let i = 0; i < this._upgrades.length; i++) {\n this._probe(this._upgrades[i]);\n }\n }\n }\n /**\n * Probes a transport.\n *\n * @param {String} name - transport name\n * @private\n */\n _probe(name) {\n let transport = this.createTransport(name);\n let failed = false;\n SocketWithoutUpgrade.priorWebsocketSuccess = false;\n const onTransportOpen = () => {\n if (failed)\n return;\n transport.send([{ type: \"ping\", data: \"probe\" }]);\n transport.once(\"packet\", (msg) => {\n if (failed)\n return;\n if (\"pong\" === msg.type && \"probe\" === msg.data) {\n this.upgrading = true;\n this.emitReserved(\"upgrading\", transport);\n if (!transport)\n return;\n SocketWithoutUpgrade.priorWebsocketSuccess =\n \"websocket\" === transport.name;\n this.transport.pause(() => {\n if (failed)\n return;\n if (\"closed\" === this.readyState)\n return;\n cleanup();\n this.setTransport(transport);\n transport.send([{ type: \"upgrade\" }]);\n this.emitReserved(\"upgrade\", transport);\n transport = null;\n this.upgrading = false;\n this.flush();\n });\n }\n else {\n const err = new Error(\"probe error\");\n // @ts-ignore\n err.transport = transport.name;\n this.emitReserved(\"upgradeError\", err);\n }\n });\n };\n function freezeTransport() {\n if (failed)\n return;\n // Any callback called by transport should be ignored since now\n failed = true;\n cleanup();\n transport.close();\n transport = null;\n }\n // Handle any error that happens while probing\n const onerror = (err) => {\n const error = new Error(\"probe error: \" + err);\n // @ts-ignore\n error.transport = transport.name;\n freezeTransport();\n this.emitReserved(\"upgradeError\", error);\n };\n function onTransportClose() {\n onerror(\"transport closed\");\n }\n // When the socket is closed while we're probing\n function onclose() {\n onerror(\"socket closed\");\n }\n // When the socket is upgraded while we're probing\n function onupgrade(to) {\n if (transport && to.name !== transport.name) {\n freezeTransport();\n }\n }\n // Remove all listeners on the transport and on self\n const cleanup = () => {\n transport.removeListener(\"open\", onTransportOpen);\n transport.removeListener(\"error\", onerror);\n transport.removeListener(\"close\", onTransportClose);\n this.off(\"close\", onclose);\n this.off(\"upgrading\", onupgrade);\n };\n transport.once(\"open\", onTransportOpen);\n transport.once(\"error\", onerror);\n transport.once(\"close\", onTransportClose);\n this.once(\"close\", onclose);\n this.once(\"upgrading\", onupgrade);\n if (this._upgrades.indexOf(\"webtransport\") !== -1 &&\n name !== \"webtransport\") {\n // favor WebTransport\n this.setTimeoutFn(() => {\n if (!failed) {\n transport.open();\n }\n }, 200);\n }\n else {\n transport.open();\n }\n }\n onHandshake(data) {\n this._upgrades = this._filterUpgrades(data.upgrades);\n super.onHandshake(data);\n }\n /**\n * Filters upgrades, returning only those matching client transports.\n *\n * @param {Array} upgrades - server upgrades\n * @private\n */\n _filterUpgrades(upgrades) {\n const filteredUpgrades = [];\n for (let i = 0; i < upgrades.length; i++) {\n if (~this.transports.indexOf(upgrades[i]))\n filteredUpgrades.push(upgrades[i]);\n }\n return filteredUpgrades;\n }\n}\n/**\n * This class provides a WebSocket-like interface to connect to an Engine.IO server. The connection will be established\n * with one of the available low-level transports, like HTTP long-polling, WebSocket or WebTransport.\n *\n * This class comes with an upgrade mechanism, which means that once the connection is established with the first\n * low-level transport, it will try to upgrade to a better transport.\n *\n * @example\n * import { Socket } from \"engine.io-client\";\n *\n * const socket = new Socket();\n *\n * socket.on(\"open\", () => {\n * socket.send(\"hello\");\n * });\n *\n * @see SocketWithoutUpgrade\n * @see SocketWithUpgrade\n */\nexport class Socket extends SocketWithUpgrade {\n constructor(uri, opts = {}) {\n const isOptionsOnly = typeof uri === \"object\";\n const o = isOptionsOnly ? { ...uri } : { ...opts };\n if (!o.transports ||\n (o.transports && typeof o.transports[0] === \"string\")) {\n o.transports = (o.transports || [\"polling\", \"websocket\", \"webtransport\"])\n .map((transportName) => DEFAULT_TRANSPORTS[transportName])\n .filter((t) => !!t);\n }\n super(isOptionsOnly ? o : uri, o);\n }\n}\n","import { parse } from \"engine.io-client\";\n/**\n * URL parser.\n *\n * @param uri - url\n * @param path - the request path of the connection\n * @param loc - An object meant to mimic window.location.\n * Defaults to window.location.\n * @public\n */\nexport function url(uri, path = \"\", loc) {\n let obj = uri;\n // default to window.location\n loc = loc || (typeof location !== \"undefined\" && location);\n if (null == uri)\n uri = loc.protocol + \"//\" + loc.host;\n // relative path support\n if (typeof uri === \"string\") {\n if (\"/\" === uri.charAt(0)) {\n if (\"/\" === uri.charAt(1)) {\n uri = loc.protocol + uri;\n }\n else {\n uri = loc.host + uri;\n }\n }\n if (!/^(https?|wss?):\\/\\//.test(uri)) {\n if (\"undefined\" !== typeof loc) {\n uri = loc.protocol + \"//\" + uri;\n }\n else {\n uri = \"https://\" + uri;\n }\n }\n // parse\n obj = parse(uri);\n }\n // make sure we treat `localhost:80` and `localhost` equally\n if (!obj.port) {\n if (/^(http|ws)$/.test(obj.protocol)) {\n obj.port = \"80\";\n }\n else if (/^(http|ws)s$/.test(obj.protocol)) {\n obj.port = \"443\";\n }\n }\n obj.path = obj.path || \"/\";\n const ipv6 = obj.host.indexOf(\":\") !== -1;\n const host = ipv6 ? \"[\" + obj.host + \"]\" : obj.host;\n // define unique id\n obj.id = obj.protocol + \"://\" + host + \":\" + obj.port + path;\n // define href\n obj.href =\n obj.protocol +\n \"://\" +\n host +\n (loc && loc.port === obj.port ? \"\" : \":\" + obj.port);\n return obj;\n}\n","const withNativeArrayBuffer = typeof ArrayBuffer === \"function\";\nconst isView = (obj) => {\n return typeof ArrayBuffer.isView === \"function\"\n ? ArrayBuffer.isView(obj)\n : obj.buffer instanceof ArrayBuffer;\n};\nconst toString = Object.prototype.toString;\nconst withNativeBlob = typeof Blob === \"function\" ||\n (typeof Blob !== \"undefined\" &&\n toString.call(Blob) === \"[object BlobConstructor]\");\nconst withNativeFile = typeof File === \"function\" ||\n (typeof File !== \"undefined\" &&\n toString.call(File) === \"[object FileConstructor]\");\n/**\n * Returns true if obj is a Buffer, an ArrayBuffer, a Blob or a File.\n *\n * @private\n */\nexport function isBinary(obj) {\n return ((withNativeArrayBuffer && (obj instanceof ArrayBuffer || isView(obj))) ||\n (withNativeBlob && obj instanceof Blob) ||\n (withNativeFile && obj instanceof File));\n}\nexport function hasBinary(obj, toJSON) {\n if (!obj || typeof obj !== \"object\") {\n return false;\n }\n if (Array.isArray(obj)) {\n for (let i = 0, l = obj.length; i < l; i++) {\n if (hasBinary(obj[i])) {\n return true;\n }\n }\n return false;\n }\n if (isBinary(obj)) {\n return true;\n }\n if (obj.toJSON &&\n typeof obj.toJSON === \"function\" &&\n arguments.length === 1) {\n return hasBinary(obj.toJSON(), true);\n }\n for (const key in obj) {\n if (Object.prototype.hasOwnProperty.call(obj, key) && hasBinary(obj[key])) {\n return true;\n }\n }\n return false;\n}\n","import { isBinary } from \"./is-binary.js\";\n/**\n * Replaces every Buffer | ArrayBuffer | Blob | File in packet with a numbered placeholder.\n *\n * @param {Object} packet - socket.io event packet\n * @return {Object} with deconstructed packet and list of buffers\n * @public\n */\nexport function deconstructPacket(packet) {\n const buffers = [];\n const packetData = packet.data;\n const pack = packet;\n pack.data = _deconstructPacket(packetData, buffers);\n pack.attachments = buffers.length; // number of binary 'attachments'\n return { packet: pack, buffers: buffers };\n}\nfunction _deconstructPacket(data, buffers) {\n if (!data)\n return data;\n if (isBinary(data)) {\n const placeholder = { _placeholder: true, num: buffers.length };\n buffers.push(data);\n return placeholder;\n }\n else if (Array.isArray(data)) {\n const newData = new Array(data.length);\n for (let i = 0; i < data.length; i++) {\n newData[i] = _deconstructPacket(data[i], buffers);\n }\n return newData;\n }\n else if (typeof data === \"object\" && !(data instanceof Date)) {\n const newData = {};\n for (const key in data) {\n if (Object.prototype.hasOwnProperty.call(data, key)) {\n newData[key] = _deconstructPacket(data[key], buffers);\n }\n }\n return newData;\n }\n return data;\n}\n/**\n * Reconstructs a binary packet from its placeholder packet and buffers\n *\n * @param {Object} packet - event packet with placeholders\n * @param {Array} buffers - binary buffers to put in placeholder positions\n * @return {Object} reconstructed packet\n * @public\n */\nexport function reconstructPacket(packet, buffers) {\n packet.data = _reconstructPacket(packet.data, buffers);\n delete packet.attachments; // no longer useful\n return packet;\n}\nfunction _reconstructPacket(data, buffers) {\n if (!data)\n return data;\n if (data && data._placeholder === true) {\n const isIndexValid = typeof data.num === \"number\" &&\n data.num >= 0 &&\n data.num < buffers.length;\n if (isIndexValid) {\n return buffers[data.num]; // appropriate buffer (should be natural order anyway)\n }\n else {\n throw new Error(\"illegal attachments\");\n }\n }\n else if (Array.isArray(data)) {\n for (let i = 0; i < data.length; i++) {\n data[i] = _reconstructPacket(data[i], buffers);\n }\n }\n else if (typeof data === \"object\") {\n for (const key in data) {\n if (Object.prototype.hasOwnProperty.call(data, key)) {\n data[key] = _reconstructPacket(data[key], buffers);\n }\n }\n }\n return data;\n}\n","import { Emitter } from \"@socket.io/component-emitter\";\nimport { deconstructPacket, reconstructPacket } from \"./binary.js\";\nimport { isBinary, hasBinary } from \"./is-binary.js\";\n/**\n * These strings must not be used as event names, as they have a special meaning.\n */\nconst RESERVED_EVENTS = [\n \"connect\", // used on the client side\n \"connect_error\", // used on the client side\n \"disconnect\", // used on both sides\n \"disconnecting\", // used on the server side\n \"newListener\", // used by the Node.js EventEmitter\n \"removeListener\", // used by the Node.js EventEmitter\n];\n/**\n * Protocol version.\n *\n * @public\n */\nexport const protocol = 5;\nexport var PacketType;\n(function (PacketType) {\n PacketType[PacketType[\"CONNECT\"] = 0] = \"CONNECT\";\n PacketType[PacketType[\"DISCONNECT\"] = 1] = \"DISCONNECT\";\n PacketType[PacketType[\"EVENT\"] = 2] = \"EVENT\";\n PacketType[PacketType[\"ACK\"] = 3] = \"ACK\";\n PacketType[PacketType[\"CONNECT_ERROR\"] = 4] = \"CONNECT_ERROR\";\n PacketType[PacketType[\"BINARY_EVENT\"] = 5] = \"BINARY_EVENT\";\n PacketType[PacketType[\"BINARY_ACK\"] = 6] = \"BINARY_ACK\";\n})(PacketType || (PacketType = {}));\n/**\n * A socket.io Encoder instance\n */\nexport class Encoder {\n /**\n * Encoder constructor\n *\n * @param {function} replacer - custom replacer to pass down to JSON.parse\n */\n constructor(replacer) {\n this.replacer = replacer;\n }\n /**\n * Encode a packet as a single string if non-binary, or as a\n * buffer sequence, depending on packet type.\n *\n * @param {Object} obj - packet object\n */\n encode(obj) {\n if (obj.type === PacketType.EVENT || obj.type === PacketType.ACK) {\n if (hasBinary(obj)) {\n return this.encodeAsBinary({\n type: obj.type === PacketType.EVENT\n ? PacketType.BINARY_EVENT\n : PacketType.BINARY_ACK,\n nsp: obj.nsp,\n data: obj.data,\n id: obj.id,\n });\n }\n }\n return [this.encodeAsString(obj)];\n }\n /**\n * Encode packet as string.\n */\n encodeAsString(obj) {\n // first is type\n let str = \"\" + obj.type;\n // attachments if we have them\n if (obj.type === PacketType.BINARY_EVENT ||\n obj.type === PacketType.BINARY_ACK) {\n str += obj.attachments + \"-\";\n }\n // if we have a namespace other than `/`\n // we append it followed by a comma `,`\n if (obj.nsp && \"/\" !== obj.nsp) {\n str += obj.nsp + \",\";\n }\n // immediately followed by the id\n if (null != obj.id) {\n str += obj.id;\n }\n // json data\n if (null != obj.data) {\n str += JSON.stringify(obj.data, this.replacer);\n }\n return str;\n }\n /**\n * Encode packet as 'buffer sequence' by removing blobs, and\n * deconstructing packet into object with placeholders and\n * a list of buffers.\n */\n encodeAsBinary(obj) {\n const deconstruction = deconstructPacket(obj);\n const pack = this.encodeAsString(deconstruction.packet);\n const buffers = deconstruction.buffers;\n buffers.unshift(pack); // add packet info to beginning of data list\n return buffers; // write all the buffers\n }\n}\n/**\n * A socket.io Decoder instance\n *\n * @return {Object} decoder\n */\nexport class Decoder extends Emitter {\n /**\n * Decoder constructor\n */\n constructor(opts) {\n super();\n this.opts = Object.assign({\n reviver: undefined,\n maxAttachments: 10,\n }, typeof opts === \"function\" ? { reviver: opts } : opts);\n }\n /**\n * Decodes an encoded packet string into packet JSON.\n *\n * @param {String} obj - encoded packet\n */\n add(obj) {\n let packet;\n if (typeof obj === \"string\") {\n if (this.reconstructor) {\n throw new Error(\"got plaintext data when reconstructing a packet\");\n }\n packet = this.decodeString(obj);\n const isBinaryEvent = packet.type === PacketType.BINARY_EVENT;\n if (isBinaryEvent || packet.type === PacketType.BINARY_ACK) {\n packet.type = isBinaryEvent ? PacketType.EVENT : PacketType.ACK;\n // binary packet's json\n this.reconstructor = new BinaryReconstructor(packet);\n // no attachments, labeled binary but no binary data to follow\n if (packet.attachments === 0) {\n super.emitReserved(\"decoded\", packet);\n }\n }\n else {\n // non-binary full packet\n super.emitReserved(\"decoded\", packet);\n }\n }\n else if (isBinary(obj) || obj.base64) {\n // raw binary data\n if (!this.reconstructor) {\n throw new Error(\"got binary data when not reconstructing a packet\");\n }\n else {\n packet = this.reconstructor.takeBinaryData(obj);\n if (packet) {\n // received final buffer\n this.reconstructor = null;\n super.emitReserved(\"decoded\", packet);\n }\n }\n }\n else {\n throw new Error(\"Unknown type: \" + obj);\n }\n }\n /**\n * Decode a packet String (JSON data)\n *\n * @param {String} str\n * @return {Object} packet\n */\n decodeString(str) {\n let i = 0;\n // look up type\n const p = {\n type: Number(str.charAt(0)),\n };\n if (PacketType[p.type] === undefined) {\n throw new Error(\"unknown packet type \" + p.type);\n }\n // look up attachments if type binary\n if (p.type === PacketType.BINARY_EVENT ||\n p.type === PacketType.BINARY_ACK) {\n const start = i + 1;\n while (str.charAt(++i) !== \"-\" && i != str.length) { }\n const buf = str.substring(start, i);\n if (buf != Number(buf) || str.charAt(i) !== \"-\") {\n throw new Error(\"Illegal attachments\");\n }\n const n = Number(buf);\n if (!isInteger(n) || n < 0) {\n throw new Error(\"Illegal attachments\");\n }\n else if (n > this.opts.maxAttachments) {\n throw new Error(\"too many attachments\");\n }\n p.attachments = n;\n }\n // look up namespace (if any)\n if (\"/\" === str.charAt(i + 1)) {\n const start = i + 1;\n while (++i) {\n const c = str.charAt(i);\n if (\",\" === c)\n break;\n if (i === str.length)\n break;\n }\n p.nsp = str.substring(start, i);\n }\n else {\n p.nsp = \"/\";\n }\n // look up id\n const next = str.charAt(i + 1);\n if (\"\" !== next && Number(next) == next) {\n const start = i + 1;\n while (++i) {\n const c = str.charAt(i);\n if (null == c || Number(c) != c) {\n --i;\n break;\n }\n if (i === str.length)\n break;\n }\n p.id = Number(str.substring(start, i + 1));\n }\n // look up json data\n if (str.charAt(++i)) {\n const payload = this.tryParse(str.substr(i));\n if (Decoder.isPayloadValid(p.type, payload)) {\n p.data = payload;\n }\n else {\n throw new Error(\"invalid payload\");\n }\n }\n return p;\n }\n tryParse(str) {\n try {\n return JSON.parse(str, this.opts.reviver);\n }\n catch (e) {\n return false;\n }\n }\n static isPayloadValid(type, payload) {\n switch (type) {\n case PacketType.CONNECT:\n return isObject(payload);\n case PacketType.DISCONNECT:\n return payload === undefined;\n case PacketType.CONNECT_ERROR:\n return typeof payload === \"string\" || isObject(payload);\n case PacketType.EVENT:\n case PacketType.BINARY_EVENT:\n return (Array.isArray(payload) &&\n (typeof payload[0] === \"number\" ||\n (typeof payload[0] === \"string\" &&\n RESERVED_EVENTS.indexOf(payload[0]) === -1)));\n case PacketType.ACK:\n case PacketType.BINARY_ACK:\n return Array.isArray(payload);\n }\n }\n /**\n * Deallocates a parser's resources\n */\n destroy() {\n if (this.reconstructor) {\n this.reconstructor.finishedReconstruction();\n this.reconstructor = null;\n }\n }\n}\n/**\n * A manager of a binary event's 'buffer sequence'. Should\n * be constructed whenever a packet of type BINARY_EVENT is\n * decoded.\n *\n * @param {Object} packet\n * @return {BinaryReconstructor} initialized reconstructor\n */\nclass BinaryReconstructor {\n constructor(packet) {\n this.packet = packet;\n this.buffers = [];\n this.reconPack = packet;\n }\n /**\n * Method to be called when binary data received from connection\n * after a BINARY_EVENT packet.\n *\n * @param {Buffer | ArrayBuffer} binData - the raw binary data received\n * @return {null | Object} returns null if more binary data is expected or\n * a reconstructed packet object if all buffers have been received.\n */\n takeBinaryData(binData) {\n this.buffers.push(binData);\n if (this.buffers.length === this.reconPack.attachments) {\n // done with buffer list\n const packet = reconstructPacket(this.reconPack, this.buffers);\n this.finishedReconstruction();\n return packet;\n }\n return null;\n }\n /**\n * Cleans up binary packet reconstruction variables.\n */\n finishedReconstruction() {\n this.reconPack = null;\n this.buffers = [];\n }\n}\nfunction isNamespaceValid(nsp) {\n return typeof nsp === \"string\";\n}\n// see https://caniuse.com/mdn-javascript_builtins_number_isinteger\nconst isInteger = Number.isInteger ||\n function (value) {\n return (typeof value === \"number\" &&\n isFinite(value) &&\n Math.floor(value) === value);\n };\nfunction isAckIdValid(id) {\n return id === undefined || isInteger(id);\n}\n// see https://stackoverflow.com/questions/8511281/check-if-a-value-is-an-object-in-javascript\nfunction isObject(value) {\n return Object.prototype.toString.call(value) === \"[object Object]\";\n}\nfunction isDataValid(type, payload) {\n switch (type) {\n case PacketType.CONNECT:\n return payload === undefined || isObject(payload);\n case PacketType.DISCONNECT:\n return payload === undefined;\n case PacketType.EVENT:\n return (Array.isArray(payload) &&\n (typeof payload[0] === \"number\" ||\n (typeof payload[0] === \"string\" &&\n RESERVED_EVENTS.indexOf(payload[0]) === -1)));\n case PacketType.ACK:\n return Array.isArray(payload);\n case PacketType.CONNECT_ERROR:\n return typeof payload === \"string\" || isObject(payload);\n default:\n return false;\n }\n}\nexport function isPacketValid(packet) {\n return (isNamespaceValid(packet.nsp) &&\n isAckIdValid(packet.id) &&\n isDataValid(packet.type, packet.data));\n}\n","export function on(obj, ev, fn) {\n obj.on(ev, fn);\n return function subDestroy() {\n obj.off(ev, fn);\n };\n}\n","import { PacketType } from \"socket.io-parser\";\nimport { on } from \"./on.js\";\nimport { Emitter, } from \"@socket.io/component-emitter\";\n/**\n * Internal events.\n * These events can't be emitted by the user.\n */\nconst RESERVED_EVENTS = Object.freeze({\n connect: 1,\n connect_error: 1,\n disconnect: 1,\n disconnecting: 1,\n // EventEmitter reserved events: https://nodejs.org/api/events.html#events_event_newlistener\n newListener: 1,\n removeListener: 1,\n});\n/**\n * A Socket is the fundamental class for interacting with the server.\n *\n * A Socket belongs to a certain Namespace (by default /) and uses an underlying {@link Manager} to communicate.\n *\n * @example\n * const socket = io();\n *\n * socket.on(\"connect\", () => {\n * console.log(\"connected\");\n * });\n *\n * // send an event to the server\n * socket.emit(\"foo\", \"bar\");\n *\n * socket.on(\"foobar\", () => {\n * // an event was received from the server\n * });\n *\n * // upon disconnection\n * socket.on(\"disconnect\", (reason) => {\n * console.log(`disconnected due to ${reason}`);\n * });\n */\nexport class Socket extends Emitter {\n /**\n * `Socket` constructor.\n */\n constructor(io, nsp, opts) {\n super();\n /**\n * Whether the socket is currently connected to the server.\n *\n * @example\n * const socket = io();\n *\n * socket.on(\"connect\", () => {\n * console.log(socket.connected); // true\n * });\n *\n * socket.on(\"disconnect\", () => {\n * console.log(socket.connected); // false\n * });\n */\n this.connected = false;\n /**\n * Whether the connection state was recovered after a temporary disconnection. In that case, any missed packets will\n * be transmitted by the server.\n */\n this.recovered = false;\n /**\n * Buffer for packets received before the CONNECT packet\n */\n this.receiveBuffer = [];\n /**\n * Buffer for packets that will be sent once the socket is connected\n */\n this.sendBuffer = [];\n /**\n * The queue of packets to be sent with retry in case of failure.\n *\n * Packets are sent one by one, each waiting for the server acknowledgement, in order to guarantee the delivery order.\n * @private\n */\n this._queue = [];\n /**\n * A sequence to generate the ID of the {@link QueuedPacket}.\n * @private\n */\n this._queueSeq = 0;\n this.ids = 0;\n /**\n * A map containing acknowledgement handlers.\n *\n * The `withError` attribute is used to differentiate handlers that accept an error as first argument:\n *\n * - `socket.emit(\"test\", (err, value) => { ... })` with `ackTimeout` option\n * - `socket.timeout(5000).emit(\"test\", (err, value) => { ... })`\n * - `const value = await socket.emitWithAck(\"test\")`\n *\n * From those that don't:\n *\n * - `socket.emit(\"test\", (value) => { ... });`\n *\n * In the first case, the handlers will be called with an error when:\n *\n * - the timeout is reached\n * - the socket gets disconnected\n *\n * In the second case, the handlers will be simply discarded upon disconnection, since the client will never receive\n * an acknowledgement from the server.\n *\n * @private\n */\n this.acks = {};\n this.flags = {};\n this.io = io;\n this.nsp = nsp;\n if (opts && opts.auth) {\n this.auth = opts.auth;\n }\n this._opts = Object.assign({}, opts);\n if (this.io._autoConnect)\n this.open();\n }\n /**\n * Whether the socket is currently disconnected\n *\n * @example\n * const socket = io();\n *\n * socket.on(\"connect\", () => {\n * console.log(socket.disconnected); // false\n * });\n *\n * socket.on(\"disconnect\", () => {\n * console.log(socket.disconnected); // true\n * });\n */\n get disconnected() {\n return !this.connected;\n }\n /**\n * Subscribe to open, close and packet events\n *\n * @private\n */\n subEvents() {\n if (this.subs)\n return;\n const io = this.io;\n this.subs = [\n on(io, \"open\", this.onopen.bind(this)),\n on(io, \"packet\", this.onpacket.bind(this)),\n on(io, \"error\", this.onerror.bind(this)),\n on(io, \"close\", this.onclose.bind(this)),\n ];\n }\n /**\n * Whether the Socket will try to reconnect when its Manager connects or reconnects.\n *\n * @example\n * const socket = io();\n *\n * console.log(socket.active); // true\n *\n * socket.on(\"disconnect\", (reason) => {\n * if (reason === \"io server disconnect\") {\n * // the disconnection was initiated by the server, you need to manually reconnect\n * console.log(socket.active); // false\n * }\n * // else the socket will automatically try to reconnect\n * console.log(socket.active); // true\n * });\n */\n get active() {\n return !!this.subs;\n }\n /**\n * \"Opens\" the socket.\n *\n * @example\n * const socket = io({\n * autoConnect: false\n * });\n *\n * socket.connect();\n */\n connect() {\n if (this.connected)\n return this;\n this.subEvents();\n if (!this.io[\"_reconnecting\"])\n this.io.open(); // ensure open\n if (\"open\" === this.io._readyState)\n this.onopen();\n return this;\n }\n /**\n * Alias for {@link connect()}.\n */\n open() {\n return this.connect();\n }\n /**\n * Sends a `message` event.\n *\n * This method mimics the WebSocket.send() method.\n *\n * @see https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/send\n *\n * @example\n * socket.send(\"hello\");\n *\n * // this is equivalent to\n * socket.emit(\"message\", \"hello\");\n *\n * @return self\n */\n send(...args) {\n args.unshift(\"message\");\n this.emit.apply(this, args);\n return this;\n }\n /**\n * Override `emit`.\n * If the event is in `events`, it's emitted normally.\n *\n * @example\n * socket.emit(\"hello\", \"world\");\n *\n * // all serializable datastructures are supported (no need to call JSON.stringify)\n * socket.emit(\"hello\", 1, \"2\", { 3: [\"4\"], 5: Uint8Array.from([6]) });\n *\n * // with an acknowledgement from the server\n * socket.emit(\"hello\", \"world\", (val) => {\n * // ...\n * });\n *\n * @return self\n */\n emit(ev, ...args) {\n var _a, _b, _c;\n if (RESERVED_EVENTS.hasOwnProperty(ev)) {\n throw new Error('\"' + ev.toString() + '\" is a reserved event name');\n }\n args.unshift(ev);\n if (this._opts.retries && !this.flags.fromQueue && !this.flags.volatile) {\n this._addToQueue(args);\n return this;\n }\n const packet = {\n type: PacketType.EVENT,\n data: args,\n };\n packet.options = {};\n packet.options.compress = this.flags.compress !== false;\n // event ack callback\n if (\"function\" === typeof args[args.length - 1]) {\n const id = this.ids++;\n const ack = args.pop();\n this._registerAckCallback(id, ack);\n packet.id = id;\n }\n const isTransportWritable = (_b = (_a = this.io.engine) === null || _a === void 0 ? void 0 : _a.transport) === null || _b === void 0 ? void 0 : _b.writable;\n const isConnected = this.connected && !((_c = this.io.engine) === null || _c === void 0 ? void 0 : _c._hasPingExpired());\n const discardPacket = this.flags.volatile && !isTransportWritable;\n if (discardPacket) {\n }\n else if (isConnected) {\n this.notifyOutgoingListeners(packet);\n this.packet(packet);\n }\n else {\n this.sendBuffer.push(packet);\n }\n this.flags = {};\n return this;\n }\n /**\n * @private\n */\n _registerAckCallback(id, ack) {\n var _a;\n const timeout = (_a = this.flags.timeout) !== null && _a !== void 0 ? _a : this._opts.ackTimeout;\n if (timeout === undefined) {\n this.acks[id] = ack;\n return;\n }\n // @ts-ignore\n const timer = this.io.setTimeoutFn(() => {\n delete this.acks[id];\n for (let i = 0; i < this.sendBuffer.length; i++) {\n if (this.sendBuffer[i].id === id) {\n this.sendBuffer.splice(i, 1);\n }\n }\n ack.call(this, new Error(\"operation has timed out\"));\n }, timeout);\n const fn = (...args) => {\n // @ts-ignore\n this.io.clearTimeoutFn(timer);\n ack.apply(this, args);\n };\n fn.withError = true;\n this.acks[id] = fn;\n }\n /**\n * Emits an event and waits for an acknowledgement\n *\n * @example\n * // without timeout\n * const response = await socket.emitWithAck(\"hello\", \"world\");\n *\n * // with a specific timeout\n * try {\n * const response = await socket.timeout(1000).emitWithAck(\"hello\", \"world\");\n * } catch (err) {\n * // the server did not acknowledge the event in the given delay\n * }\n *\n * @return a Promise that will be fulfilled when the server acknowledges the event\n */\n emitWithAck(ev, ...args) {\n return new Promise((resolve, reject) => {\n const fn = (arg1, arg2) => {\n return arg1 ? reject(arg1) : resolve(arg2);\n };\n fn.withError = true;\n args.push(fn);\n this.emit(ev, ...args);\n });\n }\n /**\n * Add the packet to the queue.\n * @param args\n * @private\n */\n _addToQueue(args) {\n let ack;\n if (typeof args[args.length - 1] === \"function\") {\n ack = args.pop();\n }\n const packet = {\n id: this._queueSeq++,\n tryCount: 0,\n pending: false,\n args,\n flags: Object.assign({ fromQueue: true }, this.flags),\n };\n args.push((err, ...responseArgs) => {\n if (packet !== this._queue[0]) {\n }\n const hasError = err !== null;\n if (hasError) {\n if (packet.tryCount > this._opts.retries) {\n this._queue.shift();\n if (ack) {\n ack(err);\n }\n }\n }\n else {\n this._queue.shift();\n if (ack) {\n ack(null, ...responseArgs);\n }\n }\n packet.pending = false;\n return this._drainQueue();\n });\n this._queue.push(packet);\n this._drainQueue();\n }\n /**\n * Send the first packet of the queue, and wait for an acknowledgement from the server.\n * @param force - whether to resend a packet that has not been acknowledged yet\n *\n * @private\n */\n _drainQueue(force = false) {\n if (!this.connected || this._queue.length === 0) {\n return;\n }\n const packet = this._queue[0];\n if (packet.pending && !force) {\n return;\n }\n packet.pending = true;\n packet.tryCount++;\n this.flags = packet.flags;\n this.emit.apply(this, packet.args);\n }\n /**\n * Sends a packet.\n *\n * @param packet\n * @private\n */\n packet(packet) {\n packet.nsp = this.nsp;\n this.io._packet(packet);\n }\n /**\n * Called upon engine `open`.\n *\n * @private\n */\n onopen() {\n if (typeof this.auth == \"function\") {\n this.auth((data) => {\n this._sendConnectPacket(data);\n });\n }\n else {\n this._sendConnectPacket(this.auth);\n }\n }\n /**\n * Sends a CONNECT packet to initiate the Socket.IO session.\n *\n * @param data\n * @private\n */\n _sendConnectPacket(data) {\n this.packet({\n type: PacketType.CONNECT,\n data: this._pid\n ? Object.assign({ pid: this._pid, offset: this._lastOffset }, data)\n : data,\n });\n }\n /**\n * Called upon engine or manager `error`.\n *\n * @param err\n * @private\n */\n onerror(err) {\n if (!this.connected) {\n this.emitReserved(\"connect_error\", err);\n }\n }\n /**\n * Called upon engine `close`.\n *\n * @param reason\n * @param description\n * @private\n */\n onclose(reason, description) {\n this.connected = false;\n delete this.id;\n this.emitReserved(\"disconnect\", reason, description);\n this._clearAcks();\n }\n /**\n * Clears the acknowledgement handlers upon disconnection, since the client will never receive an acknowledgement from\n * the server.\n *\n * @private\n */\n _clearAcks() {\n Object.keys(this.acks).forEach((id) => {\n const isBuffered = this.sendBuffer.some((packet) => String(packet.id) === id);\n if (!isBuffered) {\n // note: handlers that do not accept an error as first argument are ignored here\n const ack = this.acks[id];\n delete this.acks[id];\n if (ack.withError) {\n ack.call(this, new Error(\"socket has been disconnected\"));\n }\n }\n });\n }\n /**\n * Called with socket packet.\n *\n * @param packet\n * @private\n */\n onpacket(packet) {\n const sameNamespace = packet.nsp === this.nsp;\n if (!sameNamespace)\n return;\n switch (packet.type) {\n case PacketType.CONNECT:\n if (packet.data && packet.data.sid) {\n this.onconnect(packet.data.sid, packet.data.pid);\n }\n else {\n this.emitReserved(\"connect_error\", new Error(\"It seems you are trying to reach a Socket.IO server in v2.x with a v3.x client, but they are not compatible (more information here: https://socket.io/docs/v3/migrating-from-2-x-to-3-0/)\"));\n }\n break;\n case PacketType.EVENT:\n case PacketType.BINARY_EVENT:\n this.onevent(packet);\n break;\n case PacketType.ACK:\n case PacketType.BINARY_ACK:\n this.onack(packet);\n break;\n case PacketType.DISCONNECT:\n this.ondisconnect();\n break;\n case PacketType.CONNECT_ERROR:\n this.destroy();\n const err = new Error(packet.data.message);\n // @ts-ignore\n err.data = packet.data.data;\n this.emitReserved(\"connect_error\", err);\n break;\n }\n }\n /**\n * Called upon a server event.\n *\n * @param packet\n * @private\n */\n onevent(packet) {\n const args = packet.data || [];\n if (null != packet.id) {\n args.push(this.ack(packet.id));\n }\n if (this.connected) {\n this.emitEvent(args);\n }\n else {\n this.receiveBuffer.push(Object.freeze(args));\n }\n }\n emitEvent(args) {\n if (this._anyListeners && this._anyListeners.length) {\n const listeners = this._anyListeners.slice();\n for (const listener of listeners) {\n listener.apply(this, args);\n }\n }\n super.emit.apply(this, args);\n if (this._pid && args.length && typeof args[args.length - 1] === \"string\") {\n this._lastOffset = args[args.length - 1];\n }\n }\n /**\n * Produces an ack callback to emit with an event.\n *\n * @private\n */\n ack(id) {\n const self = this;\n let sent = false;\n return function (...args) {\n // prevent double callbacks\n if (sent)\n return;\n sent = true;\n self.packet({\n type: PacketType.ACK,\n id: id,\n data: args,\n });\n };\n }\n /**\n * Called upon a server acknowledgement.\n *\n * @param packet\n * @private\n */\n onack(packet) {\n const ack = this.acks[packet.id];\n if (typeof ack !== \"function\") {\n return;\n }\n delete this.acks[packet.id];\n // @ts-ignore FIXME ack is incorrectly inferred as 'never'\n if (ack.withError) {\n packet.data.unshift(null);\n }\n // @ts-ignore\n ack.apply(this, packet.data);\n }\n /**\n * Called upon server connect.\n *\n * @private\n */\n onconnect(id, pid) {\n this.id = id;\n this.recovered = pid && this._pid === pid;\n this._pid = pid; // defined only if connection state recovery is enabled\n this.connected = true;\n this.emitBuffered();\n this._drainQueue(true);\n this.emitReserved(\"connect\");\n }\n /**\n * Emit buffered events (received and emitted).\n *\n * @private\n */\n emitBuffered() {\n this.receiveBuffer.forEach((args) => this.emitEvent(args));\n this.receiveBuffer = [];\n this.sendBuffer.forEach((packet) => {\n this.notifyOutgoingListeners(packet);\n this.packet(packet);\n });\n this.sendBuffer = [];\n }\n /**\n * Called upon server disconnect.\n *\n * @private\n */\n ondisconnect() {\n this.destroy();\n this.onclose(\"io server disconnect\");\n }\n /**\n * Called upon forced client/server side disconnections,\n * this method ensures the manager stops tracking us and\n * that reconnections don't get triggered for this.\n *\n * @private\n */\n destroy() {\n if (this.subs) {\n // clean subscriptions to avoid reconnections\n this.subs.forEach((subDestroy) => subDestroy());\n this.subs = undefined;\n }\n this.io[\"_destroy\"](this);\n }\n /**\n * Disconnects the socket manually. In that case, the socket will not try to reconnect.\n *\n * If this is the last active Socket instance of the {@link Manager}, the low-level connection will be closed.\n *\n * @example\n * const socket = io();\n *\n * socket.on(\"disconnect\", (reason) => {\n * // console.log(reason); prints \"io client disconnect\"\n * });\n *\n * socket.disconnect();\n *\n * @return self\n */\n disconnect() {\n if (this.connected) {\n this.packet({ type: PacketType.DISCONNECT });\n }\n // remove socket from pool\n this.destroy();\n if (this.connected) {\n // fire events\n this.onclose(\"io client disconnect\");\n }\n return this;\n }\n /**\n * Alias for {@link disconnect()}.\n *\n * @return self\n */\n close() {\n return this.disconnect();\n }\n /**\n * Sets the compress flag.\n *\n * @example\n * socket.compress(false).emit(\"hello\");\n *\n * @param compress - if `true`, compresses the sending data\n * @return self\n */\n compress(compress) {\n this.flags.compress = compress;\n return this;\n }\n /**\n * Sets a modifier for a subsequent event emission that the event message will be dropped when this socket is not\n * ready to send messages.\n *\n * @example\n * socket.volatile.emit(\"hello\"); // the server may or may not receive it\n *\n * @returns self\n */\n get volatile() {\n this.flags.volatile = true;\n return this;\n }\n /**\n * Sets a modifier for a subsequent event emission that the callback will be called with an error when the\n * given number of milliseconds have elapsed without an acknowledgement from the server:\n *\n * @example\n * socket.timeout(5000).emit(\"my-event\", (err) => {\n * if (err) {\n * // the server did not acknowledge the event in the given delay\n * }\n * });\n *\n * @returns self\n */\n timeout(timeout) {\n this.flags.timeout = timeout;\n return this;\n }\n /**\n * Adds a listener that will be fired when any event is emitted. The event name is passed as the first argument to the\n * callback.\n *\n * @example\n * socket.onAny((event, ...args) => {\n * console.log(`got ${event}`);\n * });\n *\n * @param listener\n */\n onAny(listener) {\n this._anyListeners = this._anyListeners || [];\n this._anyListeners.push(listener);\n return this;\n }\n /**\n * Adds a listener that will be fired when any event is emitted. The event name is passed as the first argument to the\n * callback. The listener is added to the beginning of the listeners array.\n *\n * @example\n * socket.prependAny((event, ...args) => {\n * console.log(`got event ${event}`);\n * });\n *\n * @param listener\n */\n prependAny(listener) {\n this._anyListeners = this._anyListeners || [];\n this._anyListeners.unshift(listener);\n return this;\n }\n /**\n * Removes the listener that will be fired when any event is emitted.\n *\n * @example\n * const catchAllListener = (event, ...args) => {\n * console.log(`got event ${event}`);\n * }\n *\n * socket.onAny(catchAllListener);\n *\n * // remove a specific listener\n * socket.offAny(catchAllListener);\n *\n * // or remove all listeners\n * socket.offAny();\n *\n * @param listener\n */\n offAny(listener) {\n if (!this._anyListeners) {\n return this;\n }\n if (listener) {\n const listeners = this._anyListeners;\n for (let i = 0; i < listeners.length; i++) {\n if (listener === listeners[i]) {\n listeners.splice(i, 1);\n return this;\n }\n }\n }\n else {\n this._anyListeners = [];\n }\n return this;\n }\n /**\n * Returns an array of listeners that are listening for any event that is specified. This array can be manipulated,\n * e.g. to remove listeners.\n */\n listenersAny() {\n return this._anyListeners || [];\n }\n /**\n * Adds a listener that will be fired when any event is emitted. The event name is passed as the first argument to the\n * callback.\n *\n * Note: acknowledgements sent to the server are not included.\n *\n * @example\n * socket.onAnyOutgoing((event, ...args) => {\n * console.log(`sent event ${event}`);\n * });\n *\n * @param listener\n */\n onAnyOutgoing(listener) {\n this._anyOutgoingListeners = this._anyOutgoingListeners || [];\n this._anyOutgoingListeners.push(listener);\n return this;\n }\n /**\n * Adds a listener that will be fired when any event is emitted. The event name is passed as the first argument to the\n * callback. The listener is added to the beginning of the listeners array.\n *\n * Note: acknowledgements sent to the server are not included.\n *\n * @example\n * socket.prependAnyOutgoing((event, ...args) => {\n * console.log(`sent event ${event}`);\n * });\n *\n * @param listener\n */\n prependAnyOutgoing(listener) {\n this._anyOutgoingListeners = this._anyOutgoingListeners || [];\n this._anyOutgoingListeners.unshift(listener);\n return this;\n }\n /**\n * Removes the listener that will be fired when any event is emitted.\n *\n * @example\n * const catchAllListener = (event, ...args) => {\n * console.log(`sent event ${event}`);\n * }\n *\n * socket.onAnyOutgoing(catchAllListener);\n *\n * // remove a specific listener\n * socket.offAnyOutgoing(catchAllListener);\n *\n * // or remove all listeners\n * socket.offAnyOutgoing();\n *\n * @param [listener] - the catch-all listener (optional)\n */\n offAnyOutgoing(listener) {\n if (!this._anyOutgoingListeners) {\n return this;\n }\n if (listener) {\n const listeners = this._anyOutgoingListeners;\n for (let i = 0; i < listeners.length; i++) {\n if (listener === listeners[i]) {\n listeners.splice(i, 1);\n return this;\n }\n }\n }\n else {\n this._anyOutgoingListeners = [];\n }\n return this;\n }\n /**\n * Returns an array of listeners that are listening for any event that is specified. This array can be manipulated,\n * e.g. to remove listeners.\n */\n listenersAnyOutgoing() {\n return this._anyOutgoingListeners || [];\n }\n /**\n * Notify the listeners for each packet sent\n *\n * @param packet\n *\n * @private\n */\n notifyOutgoingListeners(packet) {\n if (this._anyOutgoingListeners && this._anyOutgoingListeners.length) {\n const listeners = this._anyOutgoingListeners.slice();\n for (const listener of listeners) {\n listener.apply(this, packet.data);\n }\n }\n }\n}\n","/**\n * Initialize backoff timer with `opts`.\n *\n * - `min` initial timeout in milliseconds [100]\n * - `max` max timeout [10000]\n * - `jitter` [0]\n * - `factor` [2]\n *\n * @param {Object} opts\n * @api public\n */\nexport function Backoff(opts) {\n opts = opts || {};\n this.ms = opts.min || 100;\n this.max = opts.max || 10000;\n this.factor = opts.factor || 2;\n this.jitter = opts.jitter > 0 && opts.jitter <= 1 ? opts.jitter : 0;\n this.attempts = 0;\n}\n/**\n * Return the backoff duration.\n *\n * @return {Number}\n * @api public\n */\nBackoff.prototype.duration = function () {\n var ms = this.ms * Math.pow(this.factor, this.attempts++);\n if (this.jitter) {\n var rand = Math.random();\n var deviation = Math.floor(rand * this.jitter * ms);\n ms = (Math.floor(rand * 10) & 1) == 0 ? ms - deviation : ms + deviation;\n }\n return Math.min(ms, this.max) | 0;\n};\n/**\n * Reset the number of attempts.\n *\n * @api public\n */\nBackoff.prototype.reset = function () {\n this.attempts = 0;\n};\n/**\n * Set the minimum duration\n *\n * @api public\n */\nBackoff.prototype.setMin = function (min) {\n this.ms = min;\n};\n/**\n * Set the maximum duration\n *\n * @api public\n */\nBackoff.prototype.setMax = function (max) {\n this.max = max;\n};\n/**\n * Set the jitter\n *\n * @api public\n */\nBackoff.prototype.setJitter = function (jitter) {\n this.jitter = jitter;\n};\n","import { Socket as Engine, installTimerFunctions, nextTick, } from \"engine.io-client\";\nimport { Socket } from \"./socket.js\";\nimport * as parser from \"socket.io-parser\";\nimport { on } from \"./on.js\";\nimport { Backoff } from \"./contrib/backo2.js\";\nimport { Emitter, } from \"@socket.io/component-emitter\";\nexport class Manager extends Emitter {\n constructor(uri, opts) {\n var _a;\n super();\n this.nsps = {};\n this.subs = [];\n if (uri && \"object\" === typeof uri) {\n opts = uri;\n uri = undefined;\n }\n opts = opts || {};\n opts.path = opts.path || \"/socket.io\";\n this.opts = opts;\n installTimerFunctions(this, opts);\n this.reconnection(opts.reconnection !== false);\n this.reconnectionAttempts(opts.reconnectionAttempts || Infinity);\n this.reconnectionDelay(opts.reconnectionDelay || 1000);\n this.reconnectionDelayMax(opts.reconnectionDelayMax || 5000);\n this.randomizationFactor((_a = opts.randomizationFactor) !== null && _a !== void 0 ? _a : 0.5);\n this.backoff = new Backoff({\n min: this.reconnectionDelay(),\n max: this.reconnectionDelayMax(),\n jitter: this.randomizationFactor(),\n });\n this.timeout(null == opts.timeout ? 20000 : opts.timeout);\n this._readyState = \"closed\";\n this.uri = uri;\n const _parser = opts.parser || parser;\n this.encoder = new _parser.Encoder();\n this.decoder = new _parser.Decoder();\n this._autoConnect = opts.autoConnect !== false;\n if (this._autoConnect)\n this.open();\n }\n reconnection(v) {\n if (!arguments.length)\n return this._reconnection;\n this._reconnection = !!v;\n if (!v) {\n this.skipReconnect = true;\n }\n return this;\n }\n reconnectionAttempts(v) {\n if (v === undefined)\n return this._reconnectionAttempts;\n this._reconnectionAttempts = v;\n return this;\n }\n reconnectionDelay(v) {\n var _a;\n if (v === undefined)\n return this._reconnectionDelay;\n this._reconnectionDelay = v;\n (_a = this.backoff) === null || _a === void 0 ? void 0 : _a.setMin(v);\n return this;\n }\n randomizationFactor(v) {\n var _a;\n if (v === undefined)\n return this._randomizationFactor;\n this._randomizationFactor = v;\n (_a = this.backoff) === null || _a === void 0 ? void 0 : _a.setJitter(v);\n return this;\n }\n reconnectionDelayMax(v) {\n var _a;\n if (v === undefined)\n return this._reconnectionDelayMax;\n this._reconnectionDelayMax = v;\n (_a = this.backoff) === null || _a === void 0 ? void 0 : _a.setMax(v);\n return this;\n }\n timeout(v) {\n if (!arguments.length)\n return this._timeout;\n this._timeout = v;\n return this;\n }\n /**\n * Starts trying to reconnect if reconnection is enabled and we have not\n * started reconnecting yet\n *\n * @private\n */\n maybeReconnectOnOpen() {\n // Only try to reconnect if it's the first time we're connecting\n if (!this._reconnecting &&\n this._reconnection &&\n this.backoff.attempts === 0) {\n // keeps reconnection from firing twice for the same reconnection loop\n this.reconnect();\n }\n }\n /**\n * Sets the current transport `socket`.\n *\n * @param {Function} fn - optional, callback\n * @return self\n * @public\n */\n open(fn) {\n if (~this._readyState.indexOf(\"open\"))\n return this;\n this.engine = new Engine(this.uri, this.opts);\n const socket = this.engine;\n const self = this;\n this._readyState = \"opening\";\n this.skipReconnect = false;\n // emit `open`\n const openSubDestroy = on(socket, \"open\", function () {\n self.onopen();\n fn && fn();\n });\n const onError = (err) => {\n this.cleanup();\n this._readyState = \"closed\";\n this.emitReserved(\"error\", err);\n if (fn) {\n fn(err);\n }\n else {\n // Only do this if there is no fn to handle the error\n this.maybeReconnectOnOpen();\n }\n };\n // emit `error`\n const errorSub = on(socket, \"error\", onError);\n if (false !== this._timeout) {\n const timeout = this._timeout;\n // set timer\n const timer = this.setTimeoutFn(() => {\n openSubDestroy();\n onError(new Error(\"timeout\"));\n socket.close();\n }, timeout);\n if (this.opts.autoUnref) {\n timer.unref();\n }\n this.subs.push(() => {\n this.clearTimeoutFn(timer);\n });\n }\n this.subs.push(openSubDestroy);\n this.subs.push(errorSub);\n return this;\n }\n /**\n * Alias for open()\n *\n * @return self\n * @public\n */\n connect(fn) {\n return this.open(fn);\n }\n /**\n * Called upon transport open.\n *\n * @private\n */\n onopen() {\n // clear old subs\n this.cleanup();\n // mark as open\n this._readyState = \"open\";\n this.emitReserved(\"open\");\n // add new subs\n const socket = this.engine;\n this.subs.push(on(socket, \"ping\", this.onping.bind(this)), on(socket, \"data\", this.ondata.bind(this)), on(socket, \"error\", this.onerror.bind(this)), on(socket, \"close\", this.onclose.bind(this)), \n // @ts-ignore\n on(this.decoder, \"decoded\", this.ondecoded.bind(this)));\n }\n /**\n * Called upon a ping.\n *\n * @private\n */\n onping() {\n this.emitReserved(\"ping\");\n }\n /**\n * Called with data.\n *\n * @private\n */\n ondata(data) {\n try {\n this.decoder.add(data);\n }\n catch (e) {\n this.onclose(\"parse error\", e);\n }\n }\n /**\n * Called when parser fully decodes a packet.\n *\n * @private\n */\n ondecoded(packet) {\n // the nextTick call prevents an exception in a user-provided event listener from triggering a disconnection due to a \"parse error\"\n nextTick(() => {\n this.emitReserved(\"packet\", packet);\n }, this.setTimeoutFn);\n }\n /**\n * Called upon socket error.\n *\n * @private\n */\n onerror(err) {\n this.emitReserved(\"error\", err);\n }\n /**\n * Creates a new socket for the given `nsp`.\n *\n * @return {Socket}\n * @public\n */\n socket(nsp, opts) {\n let socket = this.nsps[nsp];\n if (!socket) {\n socket = new Socket(this, nsp, opts);\n this.nsps[nsp] = socket;\n }\n else if (this._autoConnect && !socket.active) {\n socket.connect();\n }\n return socket;\n }\n /**\n * Called upon a socket close.\n *\n * @param socket\n * @private\n */\n _destroy(socket) {\n const nsps = Object.keys(this.nsps);\n for (const nsp of nsps) {\n const socket = this.nsps[nsp];\n if (socket.active) {\n return;\n }\n }\n this._close();\n }\n /**\n * Writes a packet.\n *\n * @param packet\n * @private\n */\n _packet(packet) {\n const encodedPackets = this.encoder.encode(packet);\n for (let i = 0; i < encodedPackets.length; i++) {\n this.engine.write(encodedPackets[i], packet.options);\n }\n }\n /**\n * Clean up transport subscriptions and packet buffer.\n *\n * @private\n */\n cleanup() {\n this.subs.forEach((subDestroy) => subDestroy());\n this.subs.length = 0;\n this.decoder.destroy();\n }\n /**\n * Close the current socket.\n *\n * @private\n */\n _close() {\n this.skipReconnect = true;\n this._reconnecting = false;\n this.onclose(\"forced close\");\n }\n /**\n * Alias for close()\n *\n * @private\n */\n disconnect() {\n return this._close();\n }\n /**\n * Called when:\n *\n * - the low-level engine is closed\n * - the parser encountered a badly formatted packet\n * - all sockets are disconnected\n *\n * @private\n */\n onclose(reason, description) {\n var _a;\n this.cleanup();\n (_a = this.engine) === null || _a === void 0 ? void 0 : _a.close();\n this.backoff.reset();\n this._readyState = \"closed\";\n this.emitReserved(\"close\", reason, description);\n if (this._reconnection && !this.skipReconnect) {\n this.reconnect();\n }\n }\n /**\n * Attempt a reconnection.\n *\n * @private\n */\n reconnect() {\n if (this._reconnecting || this.skipReconnect)\n return this;\n const self = this;\n if (this.backoff.attempts >= this._reconnectionAttempts) {\n this.backoff.reset();\n this.emitReserved(\"reconnect_failed\");\n this._reconnecting = false;\n }\n else {\n const delay = this.backoff.duration();\n this._reconnecting = true;\n const timer = this.setTimeoutFn(() => {\n if (self.skipReconnect)\n return;\n this.emitReserved(\"reconnect_attempt\", self.backoff.attempts);\n // check again for the case socket closed in above events\n if (self.skipReconnect)\n return;\n self.open((err) => {\n if (err) {\n self._reconnecting = false;\n self.reconnect();\n this.emitReserved(\"reconnect_error\", err);\n }\n else {\n self.onreconnect();\n }\n });\n }, delay);\n if (this.opts.autoUnref) {\n timer.unref();\n }\n this.subs.push(() => {\n this.clearTimeoutFn(timer);\n });\n }\n }\n /**\n * Called upon successful reconnect.\n *\n * @private\n */\n onreconnect() {\n const attempt = this.backoff.attempts;\n this._reconnecting = false;\n this.backoff.reset();\n this.emitReserved(\"reconnect\", attempt);\n }\n}\n","import { url } from \"./url.js\";\nimport { Manager } from \"./manager.js\";\nimport { Socket } from \"./socket.js\";\n/**\n * Managers cache.\n */\nconst cache = {};\nfunction lookup(uri, opts) {\n if (typeof uri === \"object\") {\n opts = uri;\n uri = undefined;\n }\n opts = opts || {};\n const parsed = url(uri, opts.path || \"/socket.io\");\n const source = parsed.source;\n const id = parsed.id;\n const path = parsed.path;\n const sameNamespace = cache[id] && path in cache[id][\"nsps\"];\n const newConnection = opts.forceNew ||\n opts[\"force new connection\"] ||\n false === opts.multiplex ||\n sameNamespace;\n let io;\n if (newConnection) {\n io = new Manager(source, opts);\n }\n else {\n if (!cache[id]) {\n cache[id] = new Manager(source, opts);\n }\n io = cache[id];\n }\n if (parsed.query && !opts.query) {\n opts.query = parsed.queryKey;\n }\n return io.socket(parsed.path, opts);\n}\n// so that \"lookup\" can be used both as a function (e.g. `io(...)`) and as a\n// namespace (e.g. `io.connect(...)`), for backward compatibility\nObject.assign(lookup, {\n Manager,\n Socket,\n io: lookup,\n connect: lookup,\n});\n/**\n * Protocol version.\n *\n * @public\n */\nexport { protocol } from \"socket.io-parser\";\n/**\n * Expose constructors for standalone build.\n *\n * @public\n */\nexport { Manager, Socket, lookup as io, lookup as connect, lookup as default, };\nexport { Fetch, NodeXHR, XHR, NodeWebSocket, WebSocket, WebTransport, } from \"engine.io-client\";\n","/**\n * Documents: the platform's unit of content.\n *\n * EVERY DOCUMENT IS A FOLDER. A \"file\" a person sees in the CDE — a PDF, a\n * Revit model, a point cloud — is stored as a folder holding one or more\n * actual files, plus a small descriptor (`document.json`) that says which file\n * is the document's NATIVE form and which files are its VIEWS (the\n * representations a viewer can render). The folder is an internal storage\n * detail: interfaces present the document as a single row and apply move,\n * rename, delete and permissions to the whole folder.\n *\n * READY TO VISUALIZE is the only rule a viewer needs: a document is viewable\n * when its descriptor lists a view in a format the viewer can render. There\n * is no \"derived file\" or \"linked file\" concept — a format that cannot be\n * rendered directly gets PROCESSED, and the processor's last act is\n * {@link ProjectDocuments.addView}. A document whose native format views\n * itself (a PDF, an IFC a viewer renders directly) lists the SAME fileId as\n * both `native` and a view; nothing is deduced from extensions.\n *\n * Plain files still exist: anything uploaded outside this shape simply has no\n * descriptor ({@link ProjectDocuments.descriptor} returns null) and is more\n * limited — interfaces may offer to convert it into a document.\n */\nimport type { EngineServicesClient } from './client';\n\n/** One renderable representation of a document. */\nexport interface DocumentView {\n /** The view file's item id — ids survive renames, names do not. */\n fileId: string;\n /** Lowercase format name: 'frag', 'ifc', 'potree', 'pdf'… */\n format: string;\n}\n\n/** The wire shape of `document.json`, schema `thatopen/document@1`. */\nexport interface DocumentDescriptor {\n schema: typeof DOCUMENT_SCHEMA;\n /** The document's own name — what a row shows. Not any file's name. */\n name: string;\n /**\n * The native form, when the document has one (a .rvt, a .3dm). A document\n * born on the platform (a loose .frag) may not.\n */\n native?: { fileId: string; format: string };\n /** The renderable representations, in no particular order. */\n views: DocumentView[];\n}\n\nexport const DOCUMENT_SCHEMA = 'thatopen/document@1';\nexport const DOCUMENT_FILE = 'document.json';\n\nconst versionTag = () => `v-${Date.now()}`;\n\nfunction idOf(item: { _id?: unknown; id?: unknown }): string {\n return String(item._id ?? item.id ?? '');\n}\n\n/**\n * Documents of one project. Get it from {@link EngineServicesClient.documents}.\n * Every method takes the document's FOLDER id — the id interfaces know the\n * document by.\n */\nexport class ProjectDocuments {\n constructor(\n private readonly client: EngineServicesClient,\n readonly projectId: string,\n ) {}\n\n /**\n * The document's descriptor, read and validated, or null when the folder\n * has none yet (an old folder, or a plain folder that is not a document).\n */\n async descriptor(folderId: string): Promise<DocumentDescriptor | null> {\n const file = await this.#descriptorFile(folderId);\n if (!file) return null;\n const response = await this.client.downloadFile(file.id);\n const text = await response.text();\n if (!text.trim()) return null;\n let parsed: unknown;\n try {\n parsed = JSON.parse(text);\n } catch {\n return null;\n }\n return normalize(parsed);\n }\n\n /**\n * The first view whose format appears in `formats` — searched in the ORDER\n * OF THE LIST, so the caller's preference wins (ask `['frag', 'ifc']` and a\n * document carrying both answers the frag). Null when none matches: that is\n * where an interface offers \"Process\".\n */\n async view(\n folderId: string,\n formats: string[],\n ): Promise<DocumentView | null> {\n const descriptor = await this.descriptor(folderId);\n if (!descriptor) return null;\n for (const format of formats) {\n const match = descriptor.views.find((v) => v.format === format);\n if (match) return match;\n }\n return null;\n }\n\n /**\n * Registers a renderable representation — a processor's last act. One view\n * per format: an existing view of the same format is replaced (a re-run\n * processor updates, it does not accumulate). The descriptor must exist;\n * create it first with {@link setDescriptor}.\n */\n async addView(folderId: string, view: DocumentView): Promise<void> {\n const descriptor = await this.descriptor(folderId);\n if (!descriptor) {\n throw new Error(\n 'This folder has no document descriptor yet: call setDescriptor first.',\n );\n }\n descriptor.views = [\n ...descriptor.views.filter((v) => v.format !== view.format),\n view,\n ];\n await this.setDescriptor(folderId, descriptor);\n }\n\n /** Writes the descriptor, creating or replacing `document.json`. */\n async setDescriptor(\n folderId: string,\n descriptor: Omit<DocumentDescriptor, 'schema'> &\n Partial<Pick<DocumentDescriptor, 'schema'>>,\n ): Promise<void> {\n const value: DocumentDescriptor = {\n ...descriptor,\n schema: DOCUMENT_SCHEMA,\n views: descriptor.views ?? [],\n };\n const blob = new Blob([JSON.stringify(value)], {\n type: 'application/json',\n });\n const existing = await this.#descriptorFile(folderId);\n if (existing) {\n await this.client.updateFile(existing.id, {\n file: blob,\n versionTag: versionTag(),\n });\n return;\n }\n await this.client.createFile({\n file: blob,\n name: DOCUMENT_FILE,\n versionTag: versionTag(),\n parentFolderId: folderId,\n projectId: this.projectId,\n });\n }\n\n async #descriptorFile(\n folderId: string,\n ): Promise<{ id: string } | undefined> {\n const items = await this.client.listFiles({ folderId });\n const found = items.find(\n (item) => String((item as { name?: unknown }).name ?? '') === DOCUMENT_FILE,\n );\n return found ? { id: idOf(found as never) } : undefined;\n }\n}\n\n/** Accepts only a shape that really is a descriptor; null otherwise. */\nfunction normalize(parsed: unknown): DocumentDescriptor | null {\n if (!parsed || typeof parsed !== 'object') return null;\n const raw = parsed as Record<string, unknown>;\n if (raw.schema !== DOCUMENT_SCHEMA) return null;\n if (typeof raw.name !== 'string') return null;\n const views = Array.isArray(raw.views)\n ? raw.views.filter(\n (v): v is DocumentView =>\n !!v &&\n typeof v === 'object' &&\n typeof (v as DocumentView).fileId === 'string' &&\n typeof (v as DocumentView).format === 'string',\n )\n : [];\n const native = raw.native as DocumentDescriptor['native'];\n const hasNative =\n !!native &&\n typeof native === 'object' &&\n typeof native.fileId === 'string' &&\n typeof native.format === 'string';\n return {\n schema: DOCUMENT_SCHEMA,\n name: raw.name,\n ...(hasNative ? { native: { fileId: native.fileId, format: native.format } } : {}),\n views,\n };\n}\n","/**\n * The history API: documents, versions and change requests, with the flow\n * storage encapsulated.\n *\n * The vocabulary is deliberately small and BIM-shaped:\n * - A DOC is a connected native document (a Revit model, an AutoCAD drawing).\n * - A VERSION is one sync of it: who, when, what changed.\n * - A SUGGESTION is a change request someone queued for the doc's owner to\n * accept or dismiss in the native app. Nobody writes in somebody else's\n * document.\n *\n * EVERYTHING BELOW THIS SURFACE IS PRIVATE. Today the data lives as plain\n * project files (the `bimterop` folder, `revitflow_history.json`,\n * `revitflow_ops.json`, hidden deltas) written by the flow plugins — see\n * PROTOCOL.md in the flow repo. This module is the ONLY place in consumer\n * code allowed to know that: when the platform grows a first-class history\n * API, or the layout moves into hidden storage, this file changes and its\n * callers do not.\n *\n * KNOWN LIMIT, deliberate: appending re-uploads the whole history file, and\n * the backend has no compare-and-swap, so two writers syncing the same doc at\n * the same instant can lose one version silently. `sync` narrows the window\n * by re-reading right before it writes and refusing when the head moved\n * (StaleHistoryError), but only a server-side append can close it. That is\n * the agreed phase 2.\n */\nimport type { EngineServicesClient } from './client';\nimport { ProjectDocuments, type DocumentDescriptor, type DocumentView } from './documents';\n\n/** One element mutation inside a version. Wire-compatible with the plugins. */\nexport interface FlowChange {\n /** create | update | delete. */\n type: 'create' | 'update' | 'delete' | string;\n /** The native application's own id for the element (Revit UniqueId, AutoCAD handle). */\n uniqueId: string;\n}\n\n/** Per-version change tallies. */\nexport interface FlowCounts {\n added: number;\n modified: number;\n removed: number;\n}\n\n/**\n * One sync of a document. Field names are the wire format the plugins write\n * (`revitflow_history.json`); do not rename them.\n */\nexport interface FlowVersion {\n /** Identity, minted by the writer. */\n guid: string;\n /** The versions this one was built on; absent on a root. First entry is the continued line. */\n parents?: string[] | null;\n /** The CDE's storage version number, when there is one. Data, never identity. */\n version?: number;\n /** What the author said it was for, when they said anything. */\n message?: string;\n author: string;\n /** Which application wrote it: 'revit', 'autocad', 'rhino'… */\n source: string;\n /** ISO UTC. */\n timestamp: string;\n changes: FlowChange[];\n counts: FlowCounts;\n /** Hidden-file id of the delta .frag; absent on the baseline and geometry-less versions. */\n deltaId?: string;\n /** Hidden-file id of the per-element geometry fingerprints, when the writer keeps them. */\n geomId?: string;\n /** Platform user id of the committer, when the writer knew it. */\n userId?: string;\n /** This version re-exported the whole model (the visible .frag shows it as of here). */\n full?: boolean;\n compact?: boolean;\n /** Suggestions this version applied (their opIds). */\n appliedOps?: string[];\n /** Position in the timeline, derived from the parent graph when read. Never stored. */\n ordinal?: number;\n}\n\n/** Wire shape of `revitflow_history.json`. */\ninterface FlowHistoryFile {\n model: string;\n commits: FlowVersion[];\n}\n\n/**\n * A change request queued for a document. Wire-compatible with\n * `revitflow_ops.json` (schema `revitflow/ops@1`).\n */\nexport interface FlowSuggestion {\n opId: string;\n /**\n * The application that receives and executes it: 'revit', 'autocad', or a\n * platform app like 'designer'. A suggestion without a recipient is not a\n * suggestion; absent only in entries written before this field existed,\n * where the recipient is the document's own source.\n */\n to?: string;\n /** Groups the suggestions one authored action produced across several docs. */\n batchId?: string;\n /** Hidden-file id of the payload .frag (envelope `revitflow/op@2`). */\n fragId?: string;\n title?: string;\n /** add | set | remove | mixed. */\n verb?: string;\n author?: string;\n userId?: string;\n createdAt?: string;\n /** The version this was authored against, by guid. */\n baseCommitGuid?: string;\n /** The storage version that version landed in, when known. Data only. */\n baseCommit?: number;\n /** How many elements it targets. */\n targets?: number;\n state?: 'pending' | 'applied' | 'discarded' | string;\n /** The native version that materialised it, once applied (storage version number). */\n appliedInCommit?: number | null;\n /** Native ids it touched or created, written by the plugin when it applied. */\n affectedIds?: string[];\n}\n\n/** Wire shape of `revitflow_ops.json`. */\ninterface FlowOpsFile {\n schema?: string;\n ops: FlowSuggestion[];\n}\n\n/** A connected document, as listed from the project. */\nexport interface FlowDocInfo {\n /** The native application that owns it: 'revit', 'autocad'… */\n source: string;\n /** The document's own id within that application. */\n docId: string;\n /**\n * The document folder's item id — the id the CDE and the documents API\n * ({@link EngineServicesClient.documents}) know this document by.\n */\n folderId: string;\n /** The visible model file's name, when one exists yet. */\n modelName?: string;\n /**\n * True when the folder exists but holds neither history, model nor\n * suggestion queue — a document somebody connected and never synced (a\n * plugin mid-first-publish, or an abandoned start). A legitimate state,\n * listed rather than hidden; apps decide whether to show it dimmed.\n */\n empty?: boolean;\n}\n\n/**\n * One person's current hold on a document's elements, read from the lock\n * registry the native plugins arbitrate through. Element keys are the native\n * application's own ids (Revit UniqueIds). Workset-level ownership lives in\n * Revit's own binary worksharing files (the ownership mirror) and is not\n * readable here — what IS here is every element-level claim.\n */\nexport interface FlowOwner {\n /** The native application's user name, as the plugin claimed with. */\n owner: string;\n /** The element keys this person currently holds, arbitration applied. */\n elements: string[];\n}\n\n/** What `sync` needs: the change list plus whatever the writer knows. */\nexport interface SyncInput {\n author: string;\n /** Which application/tool is writing: 'revit', 'rhino', 'recipe'… */\n source: string;\n changes: FlowChange[];\n message?: string;\n /** Delta geometry for this version, uploaded as a hidden file. */\n delta?: Blob;\n /** Re-upload of the whole model; marks the version `full`. */\n model?: Blob;\n /** Platform user id, when known. */\n userId?: string;\n /** Suggestions this version applied. */\n appliedOps?: string[];\n /**\n * The head you built on. When given and the stored head differs, `sync`\n * refuses with {@link StaleHistoryError} instead of forking silently.\n */\n expectedLatestGuid?: string;\n}\n\n/** What `suggest` needs. */\nexport interface SuggestInput {\n /**\n * The application that receives and executes it. Defaults to the document's\n * own source — the native app that owns the document.\n */\n to?: string;\n /**\n * The suggestion's id, when the caller minted it up front — a payload\n * (envelope `revitflow/op@2`) carries the opId INSIDE, so whoever builds\n * one needs the id before this call. Minted here when absent.\n */\n opId?: string;\n title: string;\n /** add | set | remove | mixed. */\n verb: string;\n author: string;\n /** The suggestion's .frag payload (envelope `revitflow/op@2`), when it has one. */\n payload?: Blob;\n targets?: number;\n batchId?: string;\n userId?: string;\n /** The version it was authored against. */\n baseCommitGuid?: string;\n}\n\n/** The head moved while a writer prepared its version. Re-read and retry. */\nexport class StaleHistoryError extends Error {\n constructor(\n readonly expectedGuid: string,\n readonly actualGuid: string | undefined,\n ) {\n super(\n 'The document history advanced while this version was being prepared: ' +\n `expected head ${expectedGuid}, found ${actualGuid ?? 'none'}. ` +\n 'Read the timeline again and rebuild on the new head.',\n );\n this.name = 'StaleHistoryError';\n }\n}\n\n// ─── The storage layout, stated once ─────────────────────────────────────────\n// PROTOCOL.md §1: project → `bimterop` → `<source>-<docId>` → files.\nconst ROOT_FOLDER = 'bimterop';\nconst HISTORY_FILE = 'revitflow_history.json';\nconst OPS_FILE = 'revitflow_ops.json';\nconst OPS_SCHEMA = 'revitflow/ops@1';\nconst LEGACY_MODEL_FILE = 'revitflow_model.frag';\n// Internal bookkeeping files that are NOT the model.\nconst INTERNAL_PREFIX = 'revitflow_';\n// The element-lock anchor: a visible file in the doc folder whose HIDDEN\n// children are live claims ({ revitflowlock: 1, user, keys[], since }), one\n// per client. Arbitration is listing order: the earliest claim naming a key\n// holds it. Written by the plugins' LockRegistry; read-only here.\nconst LOCKS_ANCHOR = 'bimterop-locks-anchor';\nconst versionTag = () => `v-${Date.now()}`;\n\ninterface StoredFile {\n id: string;\n name: string;\n}\n\n/**\n * Only the folders whose parent IS `parentId`. Needed on top of the query\n * filter because the backend ignores an unknown `parentFolderId` and answers\n * with every folder of the project.\n */\nfunction childrenOf<T extends { parentId?: unknown }>(\n folders: T[],\n parentId: string,\n): T[] {\n return folders.filter((f) => String(f.parentId ?? '') === parentId);\n}\n\n/** Normalizes the `_id`/`id` split the item endpoints disagree on. */\nfunction idOf(item: { _id?: unknown; id?: unknown }): string {\n return String(item._id ?? item.id ?? '');\n}\n\n/**\n * The history of one project. Get it from {@link EngineServicesClient.history}.\n */\nexport class ProjectHistory {\n #rootFolderId?: string;\n\n constructor(\n private readonly client: EngineServicesClient,\n readonly projectId: string,\n ) {}\n\n /** The project's connected documents. */\n async docs(): Promise<FlowDocInfo[]> {\n const root = await this.#root();\n if (!root) return [];\n const folders = await this.client.listFolders({\n parentFolderId: root,\n projectId: this.projectId,\n });\n const docs: FlowDocInfo[] = [];\n // Filtered here as well as in the query: the backend ignores an unknown\n // `parentFolderId` filter and answers with EVERY folder of the project,\n // which made any project folder with a dash in its name look like a doc.\n for (const folder of childrenOf(folders, root)) {\n const name = String(folder.name ?? '');\n const dash = name.indexOf('-');\n if (dash <= 0) continue;\n // One listing per doc, so the caller can tell a live document from a\n // never-synced shell without fetching anything else.\n const files = await this.client.listFiles({\n folderId: idOf(folder as never),\n });\n const names = files.map((f) =>\n String((f as { name?: unknown }).name ?? ''),\n );\n const model =\n names.find((n) => n === LEGACY_MODEL_FILE) ??\n names.find(\n (n) => n.endsWith('.frag') && !n.startsWith(INTERNAL_PREFIX),\n );\n const hasAny =\n names.includes(HISTORY_FILE) || names.includes(OPS_FILE) || !!model;\n docs.push({\n source: name.slice(0, dash),\n docId: name.slice(dash + 1),\n folderId: idOf(folder as never),\n modelName: model,\n ...(hasAny ? {} : { empty: true }),\n });\n }\n return docs;\n }\n\n /** One document's history. `source` and `docId` as {@link docs} lists them. */\n doc(source: string, docId: string): FlowDoc {\n return new FlowDoc(this.client, this, source, docId);\n }\n\n /** @internal The `bimterop` folder id, resolved once. */\n async rootFolderId(create = false): Promise<string | undefined> {\n if (this.#rootFolderId) return this.#rootFolderId;\n const found = await this.#root();\n if (found) return found;\n if (!create) return undefined;\n const made = await this.client.createFolder(\n ROOT_FOLDER,\n undefined,\n this.projectId,\n );\n this.#rootFolderId = idOf(made as never);\n return this.#rootFolderId;\n }\n\n async #root(): Promise<string | undefined> {\n if (this.#rootFolderId) return this.#rootFolderId;\n const folders = await this.client.listFolders({\n projectId: this.projectId,\n });\n const root = folders.find(\n (f) => String(f.name ?? '') === ROOT_FOLDER && !f.parentId,\n );\n if (root) this.#rootFolderId = idOf(root as never);\n return this.#rootFolderId;\n }\n}\n\n/**\n * One connected document: its timeline, its model, and its suggestions.\n */\nexport class FlowDoc {\n #folderId?: string;\n\n constructor(\n private readonly client: EngineServicesClient,\n private readonly project: ProjectHistory,\n readonly source: string,\n readonly docId: string,\n ) {}\n\n // ─── Reading ───────────────────────────────────────────────────────────────\n\n /**\n * The document's versions, oldest first, ordered by the parent graph (not\n * by array position, which concurrent writers do not keep meaningful).\n * Each version gets its `ordinal` filled in.\n */\n async timeline(): Promise<FlowVersion[]> {\n const history = await this.#readHistory();\n return orderByGraph(history?.commits ?? []);\n }\n\n /** The head of the timeline, or null before the first sync. */\n async latest(): Promise<FlowVersion | null> {\n const timeline = await this.timeline();\n return timeline.length ? timeline[timeline.length - 1] : null;\n }\n\n /**\n * A version's delta geometry as a .frag. The baseline (`full`) versions have\n * no delta: their geometry IS the model file — use {@link model}.\n */\n async delta(version: FlowVersion): Promise<Blob> {\n if (!version.deltaId) {\n throw new Error(\n `Version ${version.guid} carries no delta: it is a full export — read model() instead.`,\n );\n }\n const response = await this.client.downloadHiddenFile(version.deltaId);\n return await response.blob();\n }\n\n /** The visible model .frag as last fully exported. */\n async model(): Promise<Blob> {\n const file = await this.#modelFile();\n if (!file) {\n throw new Error(\n `Document ${this.source}-${this.docId} has no model file yet.`,\n );\n }\n const response = await this.client.downloadFile(file.id);\n return await response.blob();\n }\n\n /** The document folder's item id — the id the CDE knows this document by. */\n async folderId(): Promise<string> {\n return await this.#folder(false);\n }\n\n // ─── The document descriptor ───────────────────────────────────────────────\n\n /**\n * The document descriptor (`document.json`), or null when the folder does\n * not carry one yet — an old folder from before descriptors existed.\n */\n async descriptor(): Promise<DocumentDescriptor | null> {\n return await this.#documents.descriptor(await this.#folder(false));\n }\n\n /**\n * The first view whose format appears in `formats`, searched in the order\n * of the list (the caller's preference wins). Falls back to the visible\n * model .frag on a descriptor-less folder, so old documents keep viewing.\n */\n async view(formats: string[]): Promise<DocumentView | null> {\n const folderId = await this.#folder(false);\n const descriptor = await this.#documents.descriptor(folderId);\n if (descriptor) {\n for (const format of formats) {\n const match = descriptor.views.find((v) => v.format === format);\n if (match) return match;\n }\n return null;\n }\n if (!formats.includes('frag')) return null;\n const model = await this.#modelFile();\n return model ? { fileId: model.id, format: 'frag' } : null;\n }\n\n /**\n * Registers a renderable representation, creating the descriptor when the\n * folder predates them (named after the model file, or the folder itself).\n * One view per format: a same-format view is replaced, not accumulated.\n */\n async addView(view: DocumentView): Promise<void> {\n const folderId = await this.#folder(true);\n const descriptor = await this.#documents.descriptor(folderId);\n if (descriptor) {\n await this.#documents.addView(folderId, view);\n return;\n }\n const model = await this.#modelFile();\n await this.#documents.setDescriptor(folderId, {\n name: model?.name.replace(/\\.frag$/, '') ?? this.#folderName,\n views: [view],\n });\n }\n\n // ─── Ownership (element locks) ─────────────────────────────────────────────\n\n /**\n * Who currently holds which elements, read from the lock registry the\n * native plugins arbitrate through. Read-only: claiming and releasing stay\n * with the plugins. Empty when nobody holds anything (or the document has\n * no lock anchor yet). Arbitration is applied: a key contested by two\n * claims counts only for the earliest one, matching the plugins' rule.\n */\n async ownership(): Promise<FlowOwner[]> {\n const anchor = await this.#file(LOCKS_ANCHOR);\n if (!anchor) return [];\n const metas = await this.client.getHiddenFilesByParent(anchor.id);\n\n // Fetched in parallel, kept in listing order: order IS the arbitration.\n const claims = await Promise.all(\n metas.map(async (meta) => {\n try {\n const id = idOf(meta as never);\n const response = await this.client.downloadHiddenFile(id);\n const parsed = JSON.parse(await response.text()) as Record<\n string,\n unknown\n >;\n if (!parsed || typeof parsed !== 'object') return null;\n if (!('revitflowlock' in parsed)) return null;\n if (!Array.isArray(parsed.keys)) return null;\n return {\n owner: String(parsed.user ?? ''),\n keys: parsed.keys.filter((k): k is string => typeof k === 'string'),\n };\n } catch {\n return null;\n }\n }),\n );\n\n const taken = new Set<string>();\n const byOwner = new Map<string, string[]>();\n for (const claim of claims) {\n if (!claim) continue;\n for (const key of claim.keys) {\n if (!key || taken.has(key)) continue;\n taken.add(key);\n const list = byOwner.get(claim.owner) ?? [];\n list.push(key);\n byOwner.set(claim.owner, list);\n }\n }\n return [...byOwner.entries()].map(([owner, elements]) => ({\n owner,\n elements,\n }));\n }\n\n get #documents(): ProjectDocuments {\n return new ProjectDocuments(this.client, this.project.projectId);\n }\n\n // ─── Writing versions ─────────────────────────────────────────────────────\n\n /**\n * Appends one version: uploads the geometry it carries, then the updated\n * history. Give `expectedLatestGuid` whenever you built on a head you read,\n * so a concurrent writer surfaces as {@link StaleHistoryError} instead of a\n * silent fork.\n */\n async sync(input: SyncInput): Promise<FlowVersion> {\n const folderId = await this.#folder(true);\n let history = (await this.#readHistory()) ?? {\n model: this.docId,\n commits: [],\n };\n\n const head = lastByGraph(history.commits);\n if (\n input.expectedLatestGuid !== undefined &&\n head?.guid !== input.expectedLatestGuid\n ) {\n throw new StaleHistoryError(input.expectedLatestGuid, head?.guid);\n }\n\n const version: FlowVersion = {\n guid: mintGuid(),\n ...(head ? { parents: [head.guid] } : {}),\n author: input.author,\n source: input.source,\n timestamp: new Date().toISOString(),\n ...(input.message ? { message: input.message } : {}),\n ...(input.userId ? { userId: input.userId } : {}),\n ...(input.appliedOps?.length ? { appliedOps: input.appliedOps } : {}),\n changes: input.changes,\n counts: tally(input.changes),\n };\n\n if (input.model) {\n await this.#writeModel(folderId, input.model);\n version.full = true;\n }\n if (input.delta) {\n const modelFile = await this.#modelFile();\n if (!modelFile) {\n throw new Error(\n 'A delta needs the model file to hang from: sync a full model first.',\n );\n }\n const hidden = await this.client.createHiddenFile(\n input.delta,\n modelFile.id,\n );\n version.deltaId = String(\n (hidden as { _id?: unknown; id?: unknown })._id ??\n (hidden as { id?: unknown }).id,\n );\n }\n\n // Re-read right before writing: the smallest window this storage allows.\n const fresh = await this.#readHistory();\n if (fresh) {\n history = fresh;\n const freshHead = lastByGraph(history.commits);\n if (\n input.expectedLatestGuid !== undefined &&\n freshHead?.guid !== input.expectedLatestGuid\n ) {\n throw new StaleHistoryError(input.expectedLatestGuid, freshHead?.guid);\n }\n if (freshHead && !version.parents) version.parents = [freshHead.guid];\n }\n history.commits.push(version);\n await this.#writeJson(folderId, HISTORY_FILE, history);\n return version;\n }\n\n // ─── Suggestions (change requests) ────────────────────────────────────────\n\n /** Every suggestion in the document's queue, pending or resolved. */\n async suggestions(): Promise<FlowSuggestion[]> {\n const ops = await this.#readOps();\n return ops?.ops ?? [];\n }\n\n /** The suggestions still waiting for the owner, oldest first. */\n async pendingSuggestions(): Promise<FlowSuggestion[]> {\n return (await this.suggestions()).filter((op) => op.state === 'pending');\n }\n\n /**\n * Queues a change request for this document. The payload, when given, is\n * uploaded as a hidden file under the suggestions index.\n */\n async suggest(input: SuggestInput): Promise<FlowSuggestion> {\n const folderId = await this.#folder(true);\n const index = (await this.#readOps()) ?? { schema: OPS_SCHEMA, ops: [] };\n const indexFile = await this.#file(OPS_FILE);\n\n const suggestion: FlowSuggestion = {\n opId: input.opId ?? mintGuid(),\n to: input.to ?? this.source,\n title: input.title,\n verb: input.verb,\n author: input.author,\n createdAt: new Date().toISOString(),\n state: 'pending',\n ...(input.targets !== undefined ? { targets: input.targets } : {}),\n ...(input.batchId ? { batchId: input.batchId } : {}),\n ...(input.userId ? { userId: input.userId } : {}),\n ...(input.baseCommitGuid\n ? { baseCommitGuid: input.baseCommitGuid }\n : {}),\n };\n\n if (input.payload) {\n // The payload hangs from the index file, so it exists first.\n const holder =\n indexFile ??\n (await this.#createJson(folderId, OPS_FILE, index));\n const hidden = await this.client.createHiddenFile(\n input.payload,\n holder.id,\n );\n suggestion.fragId = String(\n (hidden as { _id?: unknown; id?: unknown })._id ??\n (hidden as { id?: unknown }).id,\n );\n }\n\n const fresh = (await this.#readOps()) ?? index;\n fresh.schema ??= OPS_SCHEMA;\n fresh.ops.push(suggestion);\n await this.#writeJson(folderId, OPS_FILE, fresh);\n return suggestion;\n }\n\n /** A suggestion's .frag payload. */\n async suggestionPayload(suggestion: FlowSuggestion): Promise<Blob> {\n if (!suggestion.fragId) {\n throw new Error(`Suggestion ${suggestion.opId} carries no payload.`);\n }\n const response = await this.client.downloadHiddenFile(suggestion.fragId);\n return await response.blob();\n }\n\n /**\n * Marks a suggestion applied (naming the version that materialised it) or\n * discarded. The native plugins do this themselves when they apply; apps\n * use it for `discarded`.\n */\n async resolveSuggestion(\n opId: string,\n outcome:\n | { state: 'applied'; appliedInCommit?: number; affectedIds?: string[] }\n | { state: 'discarded' },\n ): Promise<FlowSuggestion> {\n const folderId = await this.#folder(false);\n if (!folderId) throw new Error('This document has no suggestion queue.');\n const index = await this.#readOps();\n const suggestion = index?.ops.find((op) => op.opId === opId);\n if (!index || !suggestion) {\n throw new Error(`No suggestion ${opId} in this document's queue.`);\n }\n Object.assign(suggestion, outcome);\n await this.#writeJson(folderId, OPS_FILE, index);\n return suggestion;\n }\n\n // ─── The layout, below the surface ────────────────────────────────────────\n\n get #folderName(): string {\n return `${this.source}-${this.docId}`;\n }\n\n async #folder(create: boolean): Promise<string> {\n if (this.#folderId) return this.#folderId;\n const rootId = await this.project.rootFolderId(create);\n if (!rootId) {\n throw new Error(\n `Project ${this.project.projectId} has no connected documents yet.`,\n );\n }\n const folders = await this.client.listFolders({\n parentFolderId: rootId,\n projectId: this.project.projectId,\n });\n // Same defensive filter as docs(): the backend may answer with every\n // folder of the project, and a same-named folder elsewhere must not win.\n const found = childrenOf(folders, rootId).find(\n (f) => String(f.name ?? '') === this.#folderName,\n );\n if (found) {\n this.#folderId = idOf(found as never);\n return this.#folderId;\n }\n if (!create) {\n throw new Error(\n `Document ${this.#folderName} does not exist in this project.`,\n );\n }\n const made = await this.client.createFolder(\n this.#folderName,\n rootId,\n this.project.projectId,\n );\n this.#folderId = idOf(made as never);\n return this.#folderId;\n }\n\n async #files(): Promise<StoredFile[]> {\n const folderId = await this.#folder(false);\n const items = await this.client.listFiles({ folderId });\n return items.map((item) => ({\n id: idOf(item as never),\n name: String((item as { name?: unknown }).name ?? ''),\n }));\n }\n\n async #file(name: string): Promise<StoredFile | undefined> {\n try {\n return (await this.#files()).find((f) => f.name === name);\n } catch {\n return undefined;\n }\n }\n\n async #modelFile(): Promise<StoredFile | undefined> {\n try {\n const files = await this.#files();\n return (\n files.find((f) => f.name === LEGACY_MODEL_FILE) ??\n files.find(\n (f) =>\n f.name.endsWith('.frag') && !f.name.startsWith(INTERNAL_PREFIX),\n )\n );\n } catch {\n return undefined;\n }\n }\n\n async #readJson<T>(name: string): Promise<T | undefined> {\n const file = await this.#file(name);\n if (!file) return undefined;\n const response = await this.client.downloadFile(file.id);\n const text = await response.text();\n if (!text.trim()) return undefined;\n return JSON.parse(text) as T;\n }\n\n #readHistory(): Promise<FlowHistoryFile | undefined> {\n return this.#readJson<FlowHistoryFile>(HISTORY_FILE);\n }\n\n #readOps(): Promise<FlowOpsFile | undefined> {\n return this.#readJson<FlowOpsFile>(OPS_FILE);\n }\n\n async #writeJson(\n folderId: string,\n name: string,\n value: unknown,\n ): Promise<StoredFile> {\n const blob = new Blob([JSON.stringify(value)], {\n type: 'application/json',\n });\n const existing = await this.#file(name);\n if (existing) {\n await this.client.updateFile(existing.id, {\n file: blob,\n versionTag: versionTag(),\n });\n return existing;\n }\n return await this.#createJson(folderId, name, value);\n }\n\n async #createJson(\n folderId: string,\n name: string,\n value: unknown,\n ): Promise<StoredFile> {\n const blob = new Blob([JSON.stringify(value)], {\n type: 'application/json',\n });\n const created = await this.client.createFile({\n file: blob,\n name,\n versionTag: versionTag(),\n parentFolderId: folderId,\n projectId: this.project.projectId,\n });\n const item = (created as { item?: { _id?: unknown; id?: unknown } }).item;\n return { id: idOf((item ?? created) as never), name };\n }\n\n async #writeModel(folderId: string, model: Blob): Promise<StoredFile> {\n const existing = await this.#modelFile();\n if (existing) {\n await this.client.updateFile(existing.id, {\n file: model,\n versionTag: versionTag(),\n });\n return existing;\n }\n const name = `${this.#folderName}.frag`;\n const created = await this.client.createFile({\n file: model,\n name,\n versionTag: versionTag(),\n parentFolderId: folderId,\n projectId: this.project.projectId,\n });\n const item = (created as { item?: { _id?: unknown; id?: unknown } }).item;\n return { id: idOf((item ?? created) as never), name };\n }\n}\n\n// ─── Graph helpers ───────────────────────────────────────────────────────────\n\nfunction tally(changes: FlowChange[]): FlowCounts {\n const counts: FlowCounts = { added: 0, modified: 0, removed: 0 };\n for (const change of changes) {\n if (change.type === 'create') counts.added++;\n else if (change.type === 'delete') counts.removed++;\n else counts.modified++;\n }\n return counts;\n}\n\n/**\n * Orders versions by walking the parent graph from the root along first\n * parents, breaking forks by timestamp — array position is not meaningful\n * once more than one application writes. Fills `ordinal`.\n */\nexport function orderByGraph(versions: FlowVersion[]): FlowVersion[] {\n if (versions.length <= 1) {\n versions.forEach((v, i) => (v.ordinal = i));\n return [...versions];\n }\n const byGuid = new Map(versions.map((v) => [v.guid, v]));\n const children = new Map<string, FlowVersion[]>();\n const roots: FlowVersion[] = [];\n for (const version of versions) {\n const parent = version.parents?.[0];\n if (parent && byGuid.has(parent)) {\n const list = children.get(parent) ?? [];\n list.push(version);\n children.set(parent, list);\n } else {\n roots.push(version);\n }\n }\n const byTime = (a: FlowVersion, b: FlowVersion) =>\n String(a.timestamp).localeCompare(String(b.timestamp));\n roots.sort(byTime);\n\n const ordered: FlowVersion[] = [];\n const stack = [...roots].reverse();\n const seen = new Set<string>();\n while (stack.length) {\n const version = stack.pop()!;\n if (seen.has(version.guid)) continue;\n seen.add(version.guid);\n ordered.push(version);\n const next = (children.get(version.guid) ?? []).sort(byTime);\n for (let i = next.length - 1; i >= 0; i--) stack.push(next[i]);\n }\n // Anything unreachable (broken parents) still shows, by time, at the end.\n for (const version of versions) {\n if (!seen.has(version.guid)) ordered.push(version);\n }\n ordered.forEach((v, i) => (v.ordinal = i));\n return ordered;\n}\n\nfunction lastByGraph(versions: FlowVersion[]): FlowVersion | undefined {\n const ordered = orderByGraph(versions);\n return ordered[ordered.length - 1];\n}\n\n/** A random v4 guid, for version guids and suggestion opIds. */\nexport function mintGuid(): string {\n const anyCrypto = globalThis.crypto as { randomUUID?: () => string };\n if (anyCrypto?.randomUUID) return anyCrypto.randomUUID();\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {\n const r = (Math.random() * 16) | 0;\n return (c === 'x' ? r : (r & 0x3) | 0x8).toString(16);\n });\n}\n","/**\n * Recipes: scripts that write change requests (suggestions) in a native\n * application's own language.\n *\n * A recipe's whole contract is one sentence: it reads some input — another\n * document's version, platform elements, points, a spreadsheet, anything —\n * and queues a SUGGESTION for a target document, expressed in that\n * application's native vocabulary (families, types, levels, blocks, layers).\n * Nothing applies until the document's owner accepts it in the native app,\n * which is why trying a recipe is always safe.\n *\n * A recipe is defined by its contract, not by where it runs: `runtime`\n * declares the default ('browser' runs where the caller is; 'cloud' is for\n * recipes that must run with nobody in front). This module is the local\n * registry and runner; the platform-level catalog (recipes as published\n * items) is the agreed phase 2 and will sit on top of the same manifest.\n */\nimport type { EngineServicesClient } from './client';\nimport { mintGuid, type FlowDoc, type FlowSuggestion } from './history';\n\n/**\n * How a settings property says \"this names something that EXISTS\". Put it on\n * the property as `x-existing` inside {@link RecipeManifest.settingsSchema}:\n * the app resolves the candidates and renders a list — people pick, they\n * never type the name of a thing that exists.\n *\n * Resolving the candidates is the APP's job today (reading `doc.model()` of\n * the target, or the declared source file, takes the fragments toolkit, which\n * the SDK does not carry). The kinds are stable so nothing changes for\n * recipes when a shared reader lands in that toolkit.\n */\nexport interface ExistingLookup {\n /** What kind of existing thing: 'document' | 'family-type' | 'level' | 'layer' | 'workset'… */\n of: string;\n /** Where it exists: the target document, or the declared source. Default 'target'. */\n from?: 'target' | 'source';\n /**\n * Narrows the candidates: attribute equals value, against the attribute\n * names EXACTLY as the native application publishes them, no case\n * normalization. Prefer the stable machine fields over display names —\n * Revit's `Category` text is localized per install (\"Armazón estructural\"),\n * so a column filter is `{ CategoryId: '-2001330' }`, never\n * `{ Category: 'Columns' }`.\n */\n where?: Record<string, string>;\n}\n\n/** What a recipe declares about itself. Shown in catalogs, checked by apps. */\nexport interface RecipeManifest {\n /** Machine name, unique in a catalog: 'rhino-points-to-revit-columns'. */\n name: string;\n /** The human name a card shows: 'Rhino points to Revit columns'. */\n title?: string;\n /** The one sentence a non-programmer reads: what it converts into what. */\n description: string;\n /** The long-form explanation an app renders, as markdown. */\n doc?: string;\n /** The native application whose language it writes: 'revit', 'autocad'… */\n to: string;\n /** The input kinds it understands: 'rhino-model', 'platform-elements', 'points', 'csv'… */\n inputs: string[];\n /**\n * What the app should offer as the input picker, when the input is a thing\n * of the project rather than inline data: another connected document, or a\n * project file (then `extensions` narrows the listing). The picked value is\n * what arrives as `input`, and what `x-existing: { from: 'source' }`\n * lookups read.\n */\n source?:\n | { kind: 'document'; source?: string }\n | { kind: 'project-file'; extensions?: string[] };\n /** Where it runs by default. Browser unless it must run unattended. */\n runtime?: 'browser' | 'cloud';\n /**\n * JSON Schema for `settings`. Apps generate the settings form from it, so\n * anything that names an EXISTING thing (a target document, a family, a\n * level) carries `x-existing` ({@link ExistingLookup}) and renders as a\n * list the app fills — people pick, they never type names of things that\n * exist. Free text is only for what a person invents.\n */\n settingsSchema?: Record<string, unknown>;\n /**\n * The self-documentation an app renders: a \"reads → proposes\" table whose\n * rows are RULES (not objects), so a dry run can fill it with real tallies.\n */\n rules?: { reads: string; proposes: string }[];\n}\n\n/** Everything a recipe's `run` gets to work with. */\nexport interface RecipeContext<Settings = Record<string, unknown>> {\n client: EngineServicesClient;\n projectId: string;\n /** The document the suggestion is for. Read its timeline/model if needed. */\n targetDoc: FlowDoc;\n /**\n * The suggestion's id, minted BEFORE the run: the payload envelope\n * (`revitflow/op@2`) carries the opId inside, so the builder needs it.\n * When the run is only a plan, nothing is queued and the id is discarded.\n */\n opId: string;\n /** The declared input, already fetched by the caller (bytes, ids, rows…). */\n input: unknown;\n settings: Settings;\n}\n\n/** What a recipe's `run` returns: the suggestion, ready to queue. */\nexport interface RecipeResult {\n title: string;\n /** add | set | remove | mixed. */\n verb: string;\n /** The .frag payload (envelope `revitflow/op@2`), when the recipe builds one. */\n payload?: Blob;\n targets?: number;\n /** Per-rule tallies matching `manifest.rules`, filled by the run. */\n ruleTallies?: { read: number; proposed: number }[];\n}\n\n/** A recipe: its manifest plus the function that writes the suggestion. */\nexport interface Recipe<Settings = Record<string, unknown>>\n extends RecipeManifest {\n run(context: RecipeContext<Settings>): Promise<RecipeResult>;\n}\n\n/** What {@link Recipes.run} returns: the queued suggestion plus the tallies. */\nexport interface RecipeRunOutcome {\n suggestion: FlowSuggestion;\n result: RecipeResult;\n}\n\n/**\n * What {@link Recipes.plan} returns: everything needed to queue EXACTLY what\n * was planned, without running the recipe again — the payload already embeds\n * this `opId`. Hand it to {@link Recipes.queue} when the person confirms.\n */\nexport interface RecipePlan {\n opId: string;\n projectId: string;\n target: { source: string; docId: string };\n /** The head the plan was built against, for the suggestion's base. */\n baseCommitGuid?: string;\n result: RecipeResult;\n}\n\n/**\n * The local recipe registry and runner. Reach it as `client.recipes`.\n */\nexport class Recipes {\n readonly #registry = new Map<string, Recipe<never>>();\n\n constructor(private readonly client: EngineServicesClient) {}\n\n /** Registers a recipe. One per name; a second with the same name throws. */\n register<S>(recipe: Recipe<S>): void {\n if (this.#registry.has(recipe.name)) {\n throw new Error(`A recipe named \"${recipe.name}\" is already registered.`);\n }\n this.#registry.set(recipe.name, recipe as Recipe<never>);\n }\n\n /** The registered recipes, optionally filtered by target application. */\n list(filter?: { to?: string; input?: string }): RecipeManifest[] {\n const all = [...this.#registry.values()];\n return all.filter(\n (recipe) =>\n (!filter?.to || recipe.to === filter.to) &&\n (!filter?.input || recipe.inputs.includes(filter.input)),\n );\n }\n\n /** A registered recipe by name, or undefined. */\n get(name: string): RecipeManifest | undefined {\n return this.#registry.get(name);\n }\n\n /**\n * Runs a recipe WITHOUT queueing anything: the dry pass. Returns a\n * {@link RecipePlan} — the result to show (title, tallies, targets) plus\n * everything {@link queue} needs to queue EXACTLY this, payload and opId\n * included, with no second run. Discard it and the plan never happened.\n */\n async plan<S>(\n name: string,\n options: RecipeRunOptions<S>,\n ): Promise<RecipePlan> {\n const { base, opId, result } = await this.#execute(name, options);\n return {\n opId,\n projectId: options.projectId,\n target: options.target,\n ...(base?.guid ? { baseCommitGuid: base.guid } : {}),\n result,\n };\n }\n\n /**\n * Queues exactly what {@link plan} planned: same opId, same payload, no\n * second execution. The pair plan → confirm → queue is the UI flow; `run`\n * is the one-shot shortcut.\n */\n async queue(\n plan: RecipePlan,\n options: { author: string; userId?: string },\n ): Promise<RecipeRunOutcome> {\n const targetDoc = this.client\n .history(plan.projectId)\n .doc(plan.target.source, plan.target.docId);\n const suggestion = await targetDoc.suggest({\n opId: plan.opId,\n title: plan.result.title,\n verb: plan.result.verb,\n author: options.author,\n payload: plan.result.payload,\n targets: plan.result.targets,\n userId: options.userId,\n baseCommitGuid: plan.baseCommitGuid,\n });\n return { suggestion, result: plan.result };\n }\n\n /**\n * Runs a recipe and queues its suggestion on the target document. Safe to\n * call freely: nothing touches the native application until its owner\n * accepts the suggestion there. Use {@link plan} first when the app wants\n * to show the tallies before queueing.\n */\n async run<S>(\n name: string,\n options: RecipeRunOptions<S>,\n ): Promise<RecipeRunOutcome> {\n const { targetDoc, base, opId, result } = await this.#execute(\n name,\n options,\n );\n\n const suggestion = await targetDoc.suggest({\n opId,\n title: result.title,\n verb: result.verb,\n author: options.author,\n payload: result.payload,\n targets: result.targets,\n userId: options.userId,\n baseCommitGuid: base?.guid,\n });\n\n return { suggestion, result };\n }\n\n async #execute<S>(name: string, options: RecipeRunOptions<S>) {\n const recipe = this.#registry.get(name) as Recipe<S> | undefined;\n if (!recipe) throw new Error(`No recipe named \"${name}\" is registered.`);\n if (recipe.to !== options.target.source) {\n throw new Error(\n `Recipe \"${name}\" writes ${recipe.to}, but the target document belongs to ${options.target.source}.`,\n );\n }\n\n const targetDoc = this.client\n .history(options.projectId)\n .doc(options.target.source, options.target.docId);\n const base = await targetDoc.latest();\n\n // Minted BEFORE the run: the payload envelope carries the opId inside.\n const opId = mintGuid();\n const result = await recipe.run({\n client: this.client,\n projectId: options.projectId,\n targetDoc,\n opId,\n input: options.input,\n settings: (options.settings ?? {}) as S,\n });\n return { recipe, targetDoc, base, opId, result };\n }\n}\n\n/** The options {@link Recipes.plan} and {@link Recipes.run} share. */\nexport interface RecipeRunOptions<S = Record<string, unknown>> {\n projectId: string;\n /** The target document, as `client.history(projectId).docs()` lists it. */\n target: { source: string; docId: string };\n input?: unknown;\n settings?: S;\n author: string;\n userId?: string;\n}\n","import { Metadata } from './files';\nimport { ItemFolder, ItemVersion } from './items';\n\n/**\n * Maximum number of ids the API accepts in one batch request. The client\n * methods split larger inputs into chunks of this size automatically.\n */\nexport const STORAGE_BATCH_MAX = 100;\n\nexport type BatchError = {\n status: number;\n message: string;\n};\n\nexport type HiddenFileSignedUrlBatchEntry = {\n hiddenFileId: string;\n url?: string;\n expiresAt?: string;\n error?: BatchError;\n};\n\nexport type ItemVersionsBatchEntry = {\n itemId: string;\n versions?: ItemVersion[];\n error?: BatchError;\n};\n\nexport type VersionMetadataBatchRequest = {\n itemId: string;\n versionTag: string;\n};\n\nexport type VersionMetadataBatchEntry = VersionMetadataBatchRequest & {\n metadata?: Metadata;\n error?: BatchError;\n};\n\nexport type ItemFoldersBatchEntry = {\n folderId: string;\n folder?: ItemFolder;\n error?: BatchError;\n};\n","/**\n * Parses an API error body. The platform returns `{ message, code?, details? }`\n * as JSON on failures; non-JSON bodies (proxies, gateways, plain text) yield an\n * empty result so the caller falls back to the status line.\n */\nfunction parseErrorBody(body: string): {\n message?: string;\n code?: string;\n details?: unknown;\n} {\n try {\n const json: unknown = JSON.parse(body);\n if (json && typeof json === 'object') {\n const obj = json as Record<string, unknown>;\n return {\n message: typeof obj.message === 'string' ? obj.message : undefined,\n code: typeof obj.code === 'string' ? obj.code : undefined,\n details: obj.details,\n };\n }\n } catch {}\n return {};\n}\n\n/**\n * Reads `details.retryAfter` (seconds) from a parsed error body. The platform\n * puts it there on `RATE_LIMITED` responses so the value survives proxies that\n * strip the `Retry-After` header.\n */\nfunction retryAfterFromDetails(details: unknown): number | undefined {\n if (!details || typeof details !== 'object') return undefined;\n const value = (details as Record<string, unknown>).retryAfter;\n return typeof value === 'number' && Number.isFinite(value) && value >= 0\n ? value\n : undefined;\n}\n\n/**\n * Error thrown by {@link EngineServicesClient} when the platform API responds\n * with a non-2xx status. Exposes the HTTP `status` and — when the API returns a\n * structured JSON body — its `code` and `details`, so callers can react to\n * specific failures (e.g. `code === 'LIMIT_EXCEEDED'`) instead of string-\n * matching the message.\n *\n * @example\n * ```ts\n * try {\n * await client.createComponent(props);\n * } catch (err) {\n * if (err instanceof RequestError && err.code === 'LIMIT_EXCEEDED') {\n * console.error(err.message); // \"Components limit reached (10/10)...\"\n * }\n * }\n * ```\n *\n * @example Rate limiting\n * ```ts\n * catch (err) {\n * if (err instanceof RequestError && err.status === 429) {\n * console.log(err.code); // \"RATE_LIMITED\"\n * console.log(err.details); // { limit, windowSeconds, retryAfter, scope }\n * console.log(err.retryAfter); // seconds to wait before trying again\n * }\n * }\n * ```\n */\nexport class RequestError extends Error {\n readonly status: number;\n readonly code?: string;\n readonly details?: unknown;\n readonly body: string;\n\n /**\n * Seconds to wait before retrying, taken from the `Retry-After` header or\n * from `details.retryAfter`. Only present on rate-limited (429) responses.\n */\n readonly retryAfter?: number;\n\n constructor(\n status: number,\n statusText: string,\n body: string,\n retryAfter?: number,\n ) {\n const parsed = parseErrorBody(body);\n super(parsed.message ?? `${statusText || 'Request failed'} (${status})`);\n this.name = 'RequestError';\n this.status = status;\n this.code = parsed.code;\n this.details = parsed.details;\n this.body = body;\n this.retryAfter = retryAfter ?? retryAfterFromDetails(parsed.details);\n }\n}\n","import { io } from 'socket.io-client';\nimport { ProjectDocuments } from './documents';\nimport { ProjectHistory } from './history';\nimport { Recipes } from './recipes';\nimport {\n ExecutionEntity,\n ExecutionSuscriptionReturnType,\n} from '../types/execution';\nimport { UpdateItemDto, UpdateItemFolderDto } from '../types/item.dto';\nimport {\n AppVersionProps,\n ComponentVersionProps,\n ComponentItem,\n AppItem,\n Item,\n ItemFolder,\n ItemType,\n ItemVersion,\n ItemWithVersions,\n} from '../types/items';\nimport { CreateItemResponse, UpdateItemResponse } from '../types/response';\nimport {\n CreateHiddenItemResult,\n CreateHiddenItemsBatchResult,\n HiddenFileEntity,\n Metadata,\n} from '../types/files';\nimport {\n HiddenFileSignedUrlBatchEntry,\n ItemFoldersBatchEntry,\n ItemVersionsBatchEntry,\n STORAGE_BATCH_MAX,\n VersionMetadataBatchEntry,\n VersionMetadataBatchRequest,\n} from '../types/batch';\nimport { ThatOpenContext } from '../types/context';\nimport { NpmCredentials } from '../types/npm';\nimport { RequestError } from './request-error';\n\ndeclare global {\n interface Window {\n __THATOPEN_CONTEXT__?: ThatOpenContext;\n ThatOpenCompany?: Record<string, unknown>;\n }\n}\n\nconst FOLDER_PATH = 'item/folder';\nconst ITEM_PATH = 'item';\nconst PROCESS_PATH = 'processor';\nconst NPM_REGISTRY_PATH = 'npm-registry';\nconst HIDDEN_PATH = 'hidden';\nconst ITEM_TYPE_FILE = 'FILE';\nconst ITEM_TYPE_COMPONENT = 'TOOL';\nconst ITEM_TYPE_APP = 'APP';\n\nconst RETRY_BASE_DELAY_MS = 500;\nconst RETRY_MAX_DELAY_MS = 30_000;\nconst RETRY_JITTER_RATIO = 0.25;\n\nconst sleep = (ms: number) =>\n new Promise<void>((resolve) => setTimeout(resolve, ms));\n\n/**\n * Reads `Retry-After` (seconds, or an HTTP date) from a response. Returns\n * `undefined` when the header is absent, unparseable, or when the runtime\n * hands over a response-like object without headers.\n */\nfunction parseRetryAfter(response: Response): number | undefined {\n const raw = response.headers?.get?.('Retry-After');\n if (!raw) return undefined;\n const seconds = Number(raw);\n if (Number.isFinite(seconds)) return Math.max(0, seconds);\n const timestamp = Date.parse(raw);\n if (Number.isNaN(timestamp)) return undefined;\n return Math.max(0, (timestamp - Date.now()) / 1000);\n}\n\n/**\n * Only network failures, rate limits and server errors are worth repeating.\n * Retrying a 400/401/403/404 burns quota on a request that cannot succeed —\n * and on 429 it is what turns a rate limit into an outage.\n */\nfunction isRetryable(error: unknown): boolean {\n if (!(error instanceof RequestError)) return true;\n return error.status === 429 || error.status >= 500;\n}\n\n/**\n * Exponential backoff with jitter, overridden by the server's `Retry-After`\n * when it sent one. Capped at {@link RETRY_MAX_DELAY_MS} so a long server-side\n * window never parks a request for minutes.\n */\nfunction retryDelayMs(error: unknown, attempt: number): number {\n const backoff = Math.min(\n RETRY_BASE_DELAY_MS * 2 ** attempt,\n RETRY_MAX_DELAY_MS,\n );\n const jitter = backoff * RETRY_JITTER_RATIO * Math.random();\n const serverDelay =\n error instanceof RequestError && error.retryAfter != null\n ? error.retryAfter * 1000\n : undefined;\n if (serverDelay != null) {\n return Math.min(serverDelay, RETRY_MAX_DELAY_MS) + jitter;\n }\n return backoff + jitter;\n}\n\n/**\n * Minimal shape of an OBC.Components-like object.\n * Avoids hard-coupling to `@thatopen/components` at the public API level.\n */\nexport interface ComponentsLike {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any -- generic constructor pattern requires any[]\n get<T>(c: new (...args: any[]) => T): T;\n init(): void;\n}\n\n/** Properties for creating a new item (file, component, or app). */\nexport type CreateItemProps = {\n /** The file to upload (File in browsers, Blob in Node.js). */\n file: File | Blob;\n /** Display name of the item. */\n name: string;\n /** Semantic version tag (e.g. \"v1\", \"v1.0.0\"). */\n versionTag: string;\n /** Optional folder ID to place the item in. */\n parentFolderId?: string;\n /** Optional project ID to associate the item with. */\n projectId?: string;\n /** Optional free-JSON metadata stored on the first version. */\n metadata?: Metadata;\n};\n\n/** Properties for updating an existing item. Combines rename/move with optional new version upload. */\nexport type UpdateItemProps = {\n /** New display name. */\n name?: string;\n /** New parent folder ID (moves the item). */\n parentFolderId?: string;\n /** New file to upload as a new version (File in browsers, Blob in Node.js). */\n file?: File | Blob;\n /** Version tag for the new file version. */\n versionTag?: string;\n /** Optional free-JSON metadata stored on the new version. */\n metadata?: Metadata;\n};\n\n/** Properties for creating an app. Extends {@link CreateItemProps} with app-specific version props. */\nexport type CreateAppProps = CreateItemProps & {\n /** App version properties (isOnline, url). */\n appProps?: AppVersionProps;\n};\n\n/** Properties for creating a component. Extends {@link CreateItemProps} with component-specific version props. */\nexport type CreateComponentProps = CreateItemProps & {\n /** Component version properties (type, tier, isPublic, etc.). Required. */\n componentProps: ComponentVersionProps;\n};\n\n/** Properties for updating a component. Extends {@link UpdateItemProps} with component-specific version props. */\nexport type UpdateComponentProps = UpdateItemProps & {\n /** Component version properties for the new version. */\n componentProps?: ComponentVersionProps;\n};\n\n/** Options for retrieving a single item. */\nexport type GetItemProps = {\n /** If true, includes the item's version history. */\n showVersions?: boolean;\n};\n\n/** Filter/query params for listing items. */\nexport type GetItemsParams = {\n /** Filter by folder. */\n folderId?: string;\n /** If true, includes version history for each item. */\n ShowVersions?: boolean;\n};\n\n/** Parameters for downloading a specific item version. */\nexport type DownloadItemFileParams = {\n /** Download a specific version by tag instead of the latest. */\n versionTag?: string;\n /** If true, includes draft versions in resolution. */\n withDraft?: boolean;\n};\n\n/** Configuration options for the {@link EngineServicesClient} constructor. */\nexport type EngineServicesClientProps = {\n /**\n * Number of automatic retries on request failure. Default: 0.\n *\n * Retries are spaced with exponential backoff plus jitter, and honour the\n * server's `Retry-After` when it sends one. Only network failures, 429s and\n * 5xx are retried — other 4xx fail immediately.\n */\n retries?: number;\n /**\n * If true, sends the token as an `Authorization: Bearer` header instead of\n * an `accessToken` query parameter. Use this when authenticating with an\n * Auth0 JWT (e.g. inside platform apps) rather than a platform API token.\n */\n useBearer?: boolean;\n /**\n * URL of a local execution server started with `thatopen local-server`.\n * When set, execution methods (executeComponent, onExecutionProgress,\n * listExecutions, getExecution, abortExecution) are routed to this server\n * instead of the cloud API. All other methods remain unchanged.\n *\n * @example\n * ```ts\n * const client = new EngineServicesClient(token, apiUrl, {\n * localServerUrl: 'http://localhost:4001',\n * });\n * ```\n */\n localServerUrl?: string;\n};\n\n/**\n * Client for the That Open Engine Services API.\n *\n * Provides methods for managing files, folders, components, apps,\n * executions, hidden files, projects, and permissions.\n *\n * @example\n * ```ts\n * import { EngineServicesClient } from '@thatopen/services';\n *\n * const client = new EngineServicesClient('my-access-token', 'https://api.thatopen.com');\n * const files = await client.listFiles();\n * ```\n */\nexport class EngineServicesClient {\n private apiUrl: string;\n private accessToken: string;\n private wsUrl: string;\n private retries: number;\n private useBearer: boolean;\n private builtInGlobals: Record<string, unknown> | null = null;\n\n /**\n * URL of a local execution server (e.g. `http://localhost:4001`).\n * When set, execution methods are routed to this server instead of the cloud API.\n * Set to `null` to disable local routing and use the cloud API.\n */\n localServerUrl: string | null = null;\n\n /**\n * The platform context this client was created with.\n * Contains `appId`, `projectId`, `accessToken`, and `apiUrl`.\n * Populated automatically when using {@link fromPlatformContext}.\n */\n readonly context: ThatOpenContext;\n\n /**\n * Creates a client from the platform context injected into\n * `window.__THATOPEN_CONTEXT__` by the That Open Platform.\n *\n * This is the recommended way to create a client inside platform apps.\n * It automatically reads the auth context and sets `useBearer: true`.\n *\n * @param props - Optional configuration (retry count, local server URL, etc.).\n * @returns A new EngineServicesClient instance.\n *\n * @example\n * ```ts\n * const client = EngineServicesClient.fromPlatformContext();\n * console.log(client.context.projectId);\n * ```\n */\n static fromPlatformContext(\n props?: Omit<EngineServicesClientProps, 'useBearer'>,\n ): EngineServicesClient {\n const ctx: ThatOpenContext = (typeof window !== 'undefined'\n ? window.__THATOPEN_CONTEXT__\n : null) || { appId: '', projectId: '', accessToken: '', apiUrl: '' };\n const client = new EngineServicesClient(ctx.accessToken, ctx.apiUrl, {\n ...props,\n useBearer: true,\n });\n (client as { context: ThatOpenContext }).context = ctx;\n return client;\n }\n\n /**\n * Creates a new EngineServicesClient instance.\n * @param accessToken - API access token (obtained from the platform dashboard)\n * or an Auth0 JWT (when using `useBearer: true`).\n * @param apiUrl - Base URL of the API (e.g. \"https://api.thatopen.com\").\n * @param props - Optional configuration (retry count, auth mode, etc.).\n */\n constructor(\n accessToken: string,\n apiUrl: string,\n props?: EngineServicesClientProps,\n ) {\n const { retries = 0, useBearer = false, localServerUrl } = props || {};\n let url = apiUrl;\n if (url.charAt(url.length - 1) === '/') {\n url = url.slice(0, -1);\n }\n this.apiUrl = `${url}/api`;\n this.accessToken = accessToken;\n // Origin only. The credential travels in the Socket.IO auth payload at\n // connect time, never in the URL: a failing handshake prints its URL in\n // consoles and proxy logs, token included.\n this.wsUrl = url;\n this.retries = retries;\n this.useBearer = useBearer;\n this.context = { appId: '', projectId: '', accessToken, apiUrl };\n if (localServerUrl) {\n let lsUrl = localServerUrl;\n if (lsUrl.charAt(lsUrl.length - 1) === '/') {\n lsUrl = lsUrl.slice(0, -1);\n }\n this.localServerUrl = lsUrl;\n }\n }\n\n /**\n * Sets the number of automatic retries for failed requests. Retries use\n * exponential backoff with jitter and honour `Retry-After`; only network\n * failures, 429s and 5xx are retried.\n * @param retries - Number of retries (0 = no retries).\n */\n setRetries(retries: number) {\n this.retries = retries;\n }\n\n /**\n * Registers the global libraries that built-in components need at runtime.\n *\n * Call this once after importing your libraries. Then every subsequent\n * {@link initBuiltInComponent} call will use these globals automatically\n * — you no longer need to pass a `globals` argument to each one.\n *\n * @param globals - Map of global names to module namespaces. The FULL set\n * a built-in may ask for: `OBC`, `OBF`, `BUI`, `THREE`, `FRAGS`,\n * `MARKERJS` (plus `CUI` only if the app still uses the deprecated\n * `@thatopen/ui-obc`). Only `OBC` and `BUI` are strictly required by\n * `setup()`; passing everything you import is the safe default, because\n * a built-in that needs a missing one fails at init.\n *\n * @example\n * ```ts\n * import * as OBC from \"@thatopen/components\";\n * import * as OBF from \"@thatopen/components-front\";\n * import * as BUI from \"@thatopen/ui\";\n * import * as THREE from \"three\";\n * import * as FRAGS from \"@thatopen/fragments\";\n * import * as MARKERJS from \"@markerjs/markerjs3\";\n *\n * client.setBuiltInGlobals({ OBC, OBF, BUI, THREE, FRAGS, MARKERJS });\n *\n * // Now just pass the component — no globals needed:\n * await client.initBuiltInComponent(AppManager, components);\n * await client.initBuiltInComponent(ViewerToolbar, components);\n * await client.initBuiltInComponent(ModelsPanel, components);\n * ```\n */\n setBuiltInGlobals(globals: Record<string, unknown>) {\n this.builtInGlobals = globals;\n }\n\n #buildUrl(path: string) {\n return `${this.apiUrl}/${path}`;\n }\n\n /**\n * Protected extension point for subclasses that need dynamic tokens\n * (e.g. `PlatformClient` with an auth provider callback). The default\n * returns the static token captured at construction time.\n *\n * When a subclass overrides this to call an async refresh function,\n * the new token is picked up on every request — expired tokens no\n * longer stick around.\n */\n /**\n * Socket origin without namespace or query, for gateways other than the\n * execution one. Callers pass their own credential in the Socket.IO auth\n * payload, resolved at connect time so a provider-backed client is current.\n */\n protected get socketOrigin(): string {\n return this.wsUrl.split('?')[0];\n }\n\n protected async resolveAccessToken(): Promise<string> {\n return this.accessToken;\n }\n\n async #requestApi<T = object>(\n method: string,\n path: string,\n requestData?: {\n body?: BodyInit;\n query?: object;\n contentType?:\n | 'application/json'\n | 'multipart/form-data'\n | 'application/x-www-form-urlencoded';\n retries?: number;\n responseType?: 'json' | 'blob';\n retryAttempt?: number;\n },\n ): Promise<T> {\n const { body, query, contentType, retries, responseType, retryAttempt } =\n requestData || {};\n const url = this.#buildUrl(path);\n\n const cleanQuery = this.#cleanData(query);\n const token = await this.resolveAccessToken();\n\n const params = {\n ...cleanQuery,\n ...(this.useBearer ? {} : { accessToken: token }),\n };\n\n try {\n const response = await fetch(\n url + '?' + new URLSearchParams(params).toString(),\n {\n method,\n headers: {\n Accept: 'application/json',\n ...(contentType && { 'Content-Type': contentType }),\n ...(this.useBearer && { Authorization: `Bearer ${token}` }),\n },\n ...(body && { body }),\n },\n );\n if (!response.ok) {\n const textResponse = await response\n .text()\n .then((text) => text)\n .catch(() => '');\n throw new RequestError(\n response.status,\n response.statusText,\n textResponse,\n parseRetryAfter(response),\n );\n }\n\n if (responseType === 'blob') {\n return (await response.blob()) as T;\n }\n\n return response\n .json()\n .then((data) => data as T)\n .catch(() => undefined as T);\n } catch (e) {\n const retriesLeft = retries != null ? retries : this.retries;\n if (retriesLeft > 0 && isRetryable(e)) {\n const attempt = retryAttempt ?? 0;\n await sleep(retryDelayMs(e, attempt));\n return await this.#requestApi(method, path, {\n ...requestData,\n retries: retriesLeft - 1,\n retryAttempt: attempt + 1,\n });\n }\n throw e;\n }\n }\n\n /**\n * Protected extension hook for subclasses (e.g. `PlatformClient`) that\n * need to add HTTP methods against additional backend routes. Delegates\n * to the private `#requestApi` implementation so retry / auth / query-\n * cleaning logic is applied identically.\n */\n protected async request<T = object>(\n method: string,\n path: string,\n requestData?: {\n body?: BodyInit;\n query?: object;\n contentType?:\n | 'application/json'\n | 'multipart/form-data'\n | 'application/x-www-form-urlencoded';\n retries?: number;\n responseType?: 'json' | 'blob';\n },\n ): Promise<T> {\n return this.#requestApi<T>(method, path, requestData);\n }\n\n async #requestFile(path: string, requestData?: { query?: object }) {\n const { query } = requestData || {};\n const url = this.#buildUrl(path);\n const token = await this.resolveAccessToken();\n const params = {\n ...query,\n ...(this.useBearer ? {} : { accessToken: token }),\n };\n const response = await fetch(\n url + '?' + new URLSearchParams(params).toString(),\n {\n method: 'GET',\n ...(this.useBearer && {\n headers: { Authorization: `Bearer ${token}` },\n }),\n },\n );\n\n return response;\n }\n\n // ─── Files ───────────────────────────────────────────────────────\n\n /**\n * Lists all files accessible by the current token.\n * @param filters - Optional filters for folder and archive status.\n * @returns Array of file items.\n */\n async listFiles(filters?: {\n folderId?: string;\n archived?: boolean;\n /**\n * Scope the listing to a project. Requires the token owner to have\n * `STORAGE:READ` role in that project; otherwise the backend returns\n * 403. Per-entity permission overrides are applied server-side.\n */\n projectId?: string;\n }) {\n const { folderId, archived, projectId } = filters || {};\n if (folderId) {\n return await this.#requestApi<Item[]>(\n 'GET',\n `${FOLDER_PATH}/${folderId}/items`,\n { query: { itemType: ITEM_TYPE_FILE, archived } },\n );\n }\n return await this.#requestApi<Item[]>('GET', `${ITEM_PATH}`, {\n query: {\n itemType: ITEM_TYPE_FILE,\n archived,\n ...(projectId && { projectId }),\n },\n });\n }\n\n /**\n * Gets a single file by ID, optionally including version history.\n * @param fileId - The file's unique identifier.\n * @param props - Options such as whether to include versions.\n * @returns The file item, optionally with version history.\n */\n async getFile(fileId: string, props?: GetItemProps) {\n return await this.#getItem<ItemWithVersions<Item>>(fileId, props);\n }\n\n /**\n * Uploads a new file.\n * @param fileData - File content, name, and version tag.\n * @returns The created item and its first version.\n */\n async createFile(fileData: CreateItemProps) {\n return await this.#createItem(fileData, ITEM_TYPE_FILE);\n }\n\n /**\n * Updates an existing file. Can rename, move to a different folder,\n * and/or upload a new version — all in a single call.\n * @param fileId - The file's unique identifier.\n * @param fileData - Properties to update (name, folderId, file, versionTag).\n * @returns The updated item and/or the new version.\n */\n async updateFile(\n fileId: string,\n fileData: UpdateItemProps,\n ): Promise<UpdateItemResponse> {\n return await this.#updateItem(fileId, fileData);\n }\n\n /**\n * Archives (soft-deletes) a file. Can be recovered with {@link recoverFile}.\n * @param fileId - The file's unique identifier.\n */\n async archiveFile(fileId: string) {\n return await this.#requestApi<Item>('DELETE', `${ITEM_PATH}/${fileId}`);\n }\n\n /**\n * Recovers a previously archived file.\n * @param fileId - The file's unique identifier.\n */\n async recoverFile(fileId: string) {\n return await this.#requestApi<Item>(\n 'PUT',\n `${ITEM_PATH}/${fileId}/recover`,\n );\n }\n\n /**\n * Downloads a file's content. Returns the raw fetch Response.\n * @param fileId - The file's unique identifier.\n * @param params - Optional version selection parameters.\n * @returns A fetch Response containing the file data.\n */\n async downloadFile(fileId: string, params?: DownloadItemFileParams) {\n return await this.#downloadItem(fileId, params);\n }\n\n /**\n * Retrieves the free-JSON metadata for a specific file version.\n * Returns `{}` when the version exists but has no metadata.\n * @param fileId - The file's unique identifier.\n * @param versionTag - The version tag (e.g. \"v1\").\n * @param params - Optional flags such as `withDraft`.\n */\n async getFileVersionMetadata(\n fileId: string,\n versionTag: string,\n params?: { withDraft?: boolean },\n ) {\n const { withDraft } = params || {};\n return await this.#requestApi<Metadata>(\n 'GET',\n `${ITEM_PATH}/${encodeURIComponent(fileId)}/version/${encodeURIComponent(versionTag)}/metadata`,\n {\n query: {\n ...(withDraft && { withDraft: 'true' }),\n },\n },\n );\n }\n\n /**\n * Replaces the metadata of a specific file version with the provided object.\n * @param fileId - The file's unique identifier.\n * @param versionTag - The version tag.\n * @param metadata - Free-JSON object (max 200 fields, 50-char keys/values).\n */\n async updateFileVersionMetadata(\n fileId: string,\n versionTag: string,\n metadata: Metadata,\n ) {\n return await this.#requestApi<Metadata>(\n 'PUT',\n `${ITEM_PATH}/${encodeURIComponent(fileId)}/version/${encodeURIComponent(versionTag)}/metadata`,\n {\n body: JSON.stringify({ metadata }),\n contentType: 'application/json',\n },\n );\n }\n\n /**\n * Clears all metadata from a specific file version.\n * @param fileId - The file's unique identifier.\n * @param versionTag - The version tag.\n */\n async deleteFileVersionMetadata(fileId: string, versionTag: string) {\n return await this.#requestApi<{ success: boolean }>(\n 'DELETE',\n `${ITEM_PATH}/${encodeURIComponent(fileId)}/version/${encodeURIComponent(versionTag)}/metadata`,\n );\n }\n\n /**\n * Batch variant of {@link getFileVersionMetadata}. Reads the metadata of\n * many (file, version) pairs in one request instead of one request per pair,\n * which is what a file list needs when it hydrates a whole page at once.\n *\n * Inputs longer than {@link STORAGE_BATCH_MAX} are split into several\n * requests automatically. Entries come back in the order they were asked\n * for; a pair the caller cannot read carries an `error` instead of\n * `metadata`, so one bad id does not lose the whole page.\n *\n * @param entries - The `{ itemId, versionTag }` pairs to read.\n * @param params - Optional flags such as `withDraft`.\n */\n async getFileVersionMetadataBatch(\n entries: VersionMetadataBatchRequest[],\n params?: { withDraft?: boolean },\n ): Promise<VersionMetadataBatchEntry[]> {\n const { withDraft } = params || {};\n return await this.#requestBatches(\n entries,\n async (chunk) =>\n (\n await this.#requestApi<{ results: VersionMetadataBatchEntry[] }>(\n 'POST',\n `${ITEM_PATH}/batch/version-metadata`,\n {\n body: JSON.stringify({\n entries: chunk,\n ...(withDraft !== undefined && { withDraft }),\n }),\n contentType: 'application/json',\n },\n )\n ).results,\n );\n }\n\n // ─── Folders ─────────────────────────────────────────────────────\n\n /**\n * Lists all folders accessible by the current token.\n * @param params - Optional filters for parent folder and archive status.\n * @returns Array of folder items.\n */\n async listFolders(params?: {\n parentFolderId?: string;\n archived?: boolean;\n /**\n * Scope the listing to a project. Requires the token owner to have\n * `STORAGE:READ` in that project; returns 403 otherwise.\n */\n projectId?: string;\n }) {\n const { archived, parentFolderId, projectId } = params || {};\n return await this.#requestApi<ItemFolder[]>('GET', FOLDER_PATH, {\n query: {\n parentFolderId,\n archived,\n ...(projectId && { projectId }),\n },\n });\n }\n\n /**\n * Gets a single folder by ID.\n * @param folderId - The folder's unique identifier.\n */\n async getFolder(folderId: string) {\n return await this.#requestApi<ItemFolder>(\n 'GET',\n `${FOLDER_PATH}/${folderId}`,\n );\n }\n\n /**\n * Batch variant of {@link getFolder}. Resolves a known set of folder ids in\n * one request — for example the parents behind a file list's breadcrumbs.\n *\n * Reach for {@link listFolders} instead when the whole (project) tree is\n * wanted; this is for the case where the ids are already known.\n *\n * Inputs longer than {@link STORAGE_BATCH_MAX} are split into several\n * requests automatically. A folder the caller cannot read carries an\n * `error` instead of `folder`.\n *\n * @param folderIds - The folder ids to resolve.\n */\n async getFoldersBatch(folderIds: string[]): Promise<ItemFoldersBatchEntry[]> {\n return await this.#requestBatches(\n folderIds,\n async (chunk) =>\n (\n await this.#requestApi<{ results: ItemFoldersBatchEntry[] }>(\n 'POST',\n `${ITEM_PATH}/batch/folders`,\n {\n body: JSON.stringify({ folderIds: chunk }),\n contentType: 'application/json',\n },\n )\n ).results,\n );\n }\n\n /**\n * Creates a new folder.\n * @param name - Display name for the folder.\n * @param parentId - Optional parent folder ID for nesting.\n * @returns The created folder.\n */\n async createFolder(name: string, parentId?: string, projectId?: string) {\n return await this.#requestApi<ItemFolder>('POST', FOLDER_PATH, {\n body: JSON.stringify({\n name,\n ...(parentId && { parentId }),\n ...(projectId && { projectId }),\n }),\n contentType: 'application/json',\n });\n }\n\n /**\n * Renames a folder.\n * @param folderId - The folder's unique identifier.\n * @param updateFolderParams - New name for the folder.\n * @returns The updated folder.\n */\n async updateFolder(folderId: string, updateFolderParams: { name?: string }) {\n const { name } = updateFolderParams;\n return await this.#requestApi<ItemFolder>(\n 'PUT',\n `${FOLDER_PATH}/${folderId}`,\n {\n body: JSON.stringify({ name } as UpdateItemFolderDto),\n contentType: 'application/json',\n },\n );\n }\n\n /**\n * Archives (soft-deletes) a folder. Can be recovered with {@link recoverFolder}.\n * @param folderId - The folder's unique identifier.\n */\n async archiveFolder(folderId: string) {\n return await this.#requestApi<ItemFolder>(\n 'DELETE',\n `${FOLDER_PATH}/${folderId}`,\n );\n }\n\n /**\n * Recovers a previously archived folder.\n * @param folderId - The folder's unique identifier.\n */\n async recoverFolder(folderId: string) {\n return await this.#requestApi<ItemFolder>(\n 'PUT',\n `${FOLDER_PATH}/${folderId}/recover`,\n );\n }\n\n /**\n * Downloads an entire folder as a ZIP archive.\n * @param folderId - The folder's unique identifier.\n * @returns A fetch Response containing the ZIP data.\n */\n async downloadFolder(folderId: string) {\n return await this.#requestFile(`${FOLDER_PATH}/${folderId}/download`);\n }\n\n // ─── Components ──────────────────────────────────────────────────\n\n /**\n * Lists all components (tools) accessible by the current token.\n * @param params - Optional filters for folder and version inclusion.\n * @returns Array of component items.\n */\n async listComponents(params?: GetItemsParams & { projectId?: string }) {\n const { folderId, ShowVersions, projectId } = params || {};\n if (folderId) {\n return await this.#requestApi<ComponentItem[]>(\n 'GET',\n `${FOLDER_PATH}/${folderId}/items`,\n {\n query: {\n itemType: ITEM_TYPE_COMPONENT,\n ...(ShowVersions && { ShowVersions }),\n },\n },\n );\n }\n return await this.#requestApi<ComponentItem[]>('GET', `${ITEM_PATH}`, {\n query: {\n itemType: ITEM_TYPE_COMPONENT,\n ...(ShowVersions && { ShowVersions }),\n ...(projectId && { projectId }),\n },\n });\n }\n\n /**\n * Gets a single component by ID, optionally including version history.\n * @param componentId - The component's unique identifier.\n * @param props - Options such as whether to include versions.\n */\n async getComponent(componentId: string, props?: GetItemProps) {\n return await this.#getItem<ItemWithVersions<ComponentItem>>(\n componentId,\n props,\n );\n }\n\n /**\n * Creates a new component with the given file and version properties.\n * @param componentData - File content, name, version tag, and component-specific props.\n * @returns The created component item and its first version.\n */\n async createComponent(componentData: CreateComponentProps) {\n const { componentProps } = componentData;\n return await this.#createItem<ComponentItem, ComponentVersionProps>(\n componentData,\n ITEM_TYPE_COMPONENT,\n componentProps,\n );\n }\n\n /**\n * Updates an existing component. Can rename, move, and/or upload a new version.\n * @param componentId - The component's unique identifier.\n * @param componentData - Properties to update, including optional new componentProps.\n * @returns The updated item and/or new version.\n */\n async updateComponent(\n componentId: string,\n componentData: UpdateComponentProps,\n ): Promise<UpdateItemResponse<ComponentItem>> {\n const { componentProps } = componentData;\n return await this.#updateItem<ComponentItem, ComponentVersionProps>(\n componentId,\n componentData,\n componentProps,\n );\n }\n\n /**\n * Downloads a component's full ZIP file. Returns the raw fetch Response.\n * @param componentId - The component's unique identifier.\n * @param params - Optional version selection parameters.\n * @returns A fetch Response containing the ZIP data.\n */\n async downloadComponent(\n componentId: string,\n params?: DownloadItemFileParams,\n ) {\n return await this.#downloadItem(componentId, params);\n }\n\n /**\n * Downloads only the JavaScript bundle from a component's ZIP.\n * This is the extracted `bundle` entry, returned as text.\n * @param componentId - The component's unique identifier.\n * @param params - Optional version selection parameters.\n * @returns A fetch Response containing the bundle JavaScript text.\n */\n async downloadComponentBundle(\n componentId: string,\n params?: DownloadItemFileParams,\n ) {\n const { versionTag, withDraft } = params || {};\n return await this.#requestFile(\n `${ITEM_PATH}/${componentId}/download/bundle`,\n {\n query: {\n ...(versionTag && { versionTag }),\n ...(withDraft && { withDraft }),\n },\n },\n );\n }\n\n /**\n * Archives (soft-deletes) a component. Can be recovered with {@link recoverComponent}.\n * @param componentId - The component's unique identifier.\n */\n async archiveComponent(componentId: string) {\n return await this.#requestApi<ComponentItem>(\n 'DELETE',\n `${ITEM_PATH}/${componentId}`,\n );\n }\n\n /**\n * Recovers a previously archived component.\n * @param componentId - The component's unique identifier.\n */\n async recoverComponent(componentId: string) {\n return await this.#requestApi<ComponentItem>(\n 'PUT',\n `${ITEM_PATH}/${componentId}/recover`,\n );\n }\n\n // ─── Built-in Components ─────────────────────────────────────────\n\n /**\n * Fetches a built-in component's JavaScript bundle by name.\n * @param name - The built-in component name (e.g. \"hello-world\").\n * @returns The component's JavaScript source code as a string.\n */\n async getBuiltInComponent(name: string): Promise<string> {\n const response = await this.#requestFile(`built-in/${name}/bundle`);\n return await response.text();\n }\n\n /**\n * Fetches a built-in component bundle, evaluates it, and registers it\n * with the given `components` instance via `components.get()`.\n *\n * After calling this, retrieve the singleton instance with\n * `components.get(ComponentClass)`.\n *\n * @param component - The component class stub (must have a static `uuid`).\n * @param components - The OBC `Components` instance used to register the\n * component (must expose a `.get()` method).\n * @param globals - Map of global names to values that the component source\n * expects in scope (e.g. `{ OBC, BUI }`). If omitted, falls back to\n * globals registered via {@link setBuiltInGlobals}, then to\n * `window.ThatOpenCompany`.\n *\n * @example\n * ```ts\n * // Option 1: register globals once, then init without passing them\n * client.setBuiltInGlobals({ OBC, OBF, BUI, CUI, THREE, FRAGS });\n * await client.initBuiltInComponent(AppManager, components);\n * await client.initBuiltInComponent(ViewerToolbar, components);\n *\n * // Option 2: pass globals per component (still works)\n * await client.initBuiltInComponent(HelloWorld, components, { OBC, BUI });\n * ```\n */\n async initBuiltInComponent(\n component: { uuid: string },\n components: ComponentsLike,\n globals?: Record<string, unknown>,\n ): Promise<void> {\n const source = await this.getBuiltInComponent(component.uuid);\n const resolvedGlobals =\n globals ??\n this.builtInGlobals ??\n (typeof window !== 'undefined' ? window.ThatOpenCompany : {}) ??\n {};\n\n const keys = Object.keys(resolvedGlobals);\n const values = keys.map((k) => resolvedGlobals[k]);\n\n const factory = new Function(...keys, `${source}\\nreturn main;`);\n const main = factory(...values);\n\n const componentDefinition = main?.componentDefinition ?? main;\n components.get(componentDefinition);\n }\n\n /**\n * Loads multiple built-in components in parallel.\n *\n * Convenience wrapper around {@link initBuiltInComponent} that fetches\n * and registers all given component stubs concurrently.\n *\n * @param components - The OBC `Components` instance.\n * @param stubs - One or more component stubs (e.g. `AppManager`, `ViewportManager`).\n *\n * @example\n * ```ts\n * await client.initBuiltInComponents(components, AppManager, ViewportManager);\n * ```\n */\n async initBuiltInComponents(\n components: ComponentsLike,\n ...stubs: { uuid: string }[]\n ): Promise<void> {\n await Promise.all(\n stubs.map((s) => this.initBuiltInComponent(s, components)),\n );\n }\n\n /**\n * High-level helper that creates an OBC component system, initialises BUI,\n * loads built-in components, and starts the engine — all in one call.\n *\n * @param globals - Map of global names to module namespaces\n * (must include at least `OBC` and `BUI`).\n * @param builtIns - Built-in component stubs to load (e.g. `AppManager`, `ViewportManager`).\n * @returns An object containing the initialised `components` instance.\n *\n * @example\n * ```ts\n * const { components } = await client.setup(\n * { OBC, OBF, BUI, CUI, THREE, FRAGS },\n * AppManager, ViewportManager,\n * );\n *\n * const viewports = components.get(ViewportManager);\n * const { element, world } = await viewports.create();\n * ```\n */\n async setup<TComponents extends ComponentsLike = ComponentsLike>(\n globals: Record<string, unknown>,\n ...builtIns: { uuid: string }[]\n ): Promise<{ components: TComponents }> {\n const OBC = globals.OBC as\n { Components?: new () => TComponents } | undefined;\n const BUI = globals.BUI as { Manager?: { init(): void } } | undefined;\n if (!OBC?.Components)\n throw new Error('globals.OBC must include Components');\n if (!BUI?.Manager) throw new Error('globals.BUI must include Manager');\n\n const components = new OBC.Components();\n BUI.Manager.init();\n this.setBuiltInGlobals(globals);\n await this.initBuiltInComponents(components, ...builtIns);\n components.init();\n this.context.appEventOrchestrator?.appLoaded?.();\n return { components };\n }\n\n /**\n * Reports an error to the platform via the {@link AppEventOrchestrator.appError} callback.\n * @param code - Numeric error code.\n * @param data - Arbitrary error data to send to the platform.\n */\n throwError(code: number, data: Record<string, string>): void {\n this.context.appEventOrchestrator?.appError?.(code, data);\n }\n\n // ─── Apps ────────────────────────────────────────────────────────\n\n /**\n * Lists all apps accessible by the current token.\n * @param params - Optional filters for folder and version inclusion.\n * @returns Array of app items.\n */\n async listApps(params?: GetItemsParams & { projectId?: string }) {\n const { folderId, ShowVersions, projectId } = params || {};\n if (folderId) {\n return await this.#requestApi<AppItem[]>(\n 'GET',\n `${FOLDER_PATH}/${folderId}/items`,\n {\n query: {\n itemType: ITEM_TYPE_APP,\n ...(ShowVersions && { ShowVersions }),\n },\n },\n );\n }\n return await this.#requestApi<AppItem[]>('GET', `${ITEM_PATH}`, {\n query: {\n itemType: ITEM_TYPE_APP,\n ...(ShowVersions && { ShowVersions }),\n ...(projectId && { projectId }),\n },\n });\n }\n\n /**\n * Creates a new app with the given file and optional version properties.\n * @param appData - File content, name, version tag, and optional app-specific props.\n * @returns The created app item and its first version.\n */\n async createApp(appData: CreateAppProps) {\n const { appProps } = appData;\n return await this.#createItem<AppItem, AppVersionProps>(\n appData,\n ITEM_TYPE_APP,\n appProps,\n );\n }\n\n /**\n * Downloads an app's full ZIP file. Returns the raw fetch Response.\n * @param appId - The app's unique identifier.\n * @param params - Optional version selection parameters.\n * @returns A fetch Response containing the ZIP data.\n */\n async downloadApp(appId: string, params?: DownloadItemFileParams) {\n return await this.#downloadItem(appId, params);\n }\n\n /**\n * Downloads only the JavaScript bundle from an app's ZIP.\n * This is the extracted `bundle` entry, returned as text.\n * @param appId - The app's unique identifier.\n * @param params - Optional version selection parameters.\n * @returns A fetch Response containing the bundle JavaScript text.\n */\n async downloadAppBundle(appId: string, params?: DownloadItemFileParams) {\n const { versionTag, withDraft } = params || {};\n return await this.#requestFile(`${ITEM_PATH}/${appId}/download/bundle`, {\n query: {\n ...(versionTag && { versionTag }),\n ...(withDraft && { withDraft }),\n },\n });\n }\n\n /**\n * Archives (soft-deletes) an app.\n * @param appId - The app's unique identifier.\n */\n async archiveApp(appId: string) {\n return await this.#requestApi<AppItem>('DELETE', `${ITEM_PATH}/${appId}`);\n }\n\n // ─── NPM Registry ────────────────────────────────────────────────\n\n /**\n * Fetches read-only npm credentials for the private `@thatopen` Founders\n * beta packages. Gated server-side on the token owner's membership tier:\n * FOUNDING members (and admins) get the token; everyone else gets a 403\n * (`RequestError` with `status === 403`). The returned `npmrc` is a\n * ready-to-write `.npmrc` body the CLI drops into a scaffolded project.\n * @returns The registry, scope, read-only token, and assembled `.npmrc`.\n */\n async getNpmCredentials() {\n return await this.#requestApi<NpmCredentials>(\n 'GET',\n `${NPM_REGISTRY_PATH}/credentials`,\n );\n }\n\n // ─── Execution ───────────────────────────────────────────────────\n\n /**\n * Triggers server-side execution of a cloud component.\n *\n * Pass `projectId` in `executionParams` when running the component in the\n * context of a specific project. The backend validates that the component\n * is linked to that project AND that the user has execute permission\n * there; a foreign `projectId` is rejected with 403. Omit `projectId` for\n * personal executions (ownership path).\n *\n * @param componentId - The component's unique identifier.\n * @param executionParams - Arbitrary parameters passed to the component's `main()` function. Include `projectId` to scope the execution.\n * @param versionTag - Optional version to execute (defaults to latest).\n * @returns An object containing the `executionId` to track progress.\n */\n async executeComponent(\n componentId: string,\n executionParams: { projectId?: string; [key: string]: unknown },\n versionTag?: string,\n ) {\n if (this.localServerUrl) {\n const url = `${this.localServerUrl}/api/${PROCESS_PATH}/${componentId}/execute`;\n const response = await fetch(url, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(executionParams),\n });\n if (!response.ok) {\n const text = await response.text().catch(() => '');\n throw new Error(\n `Local server request failed: ${response.status} - ${text}`,\n );\n }\n return (await response.json()) as { executionId: string };\n }\n return await this.#requestApi<{ executionId: string }>(\n 'POST',\n `${PROCESS_PATH}/${componentId}/execute`,\n {\n body: JSON.stringify(executionParams),\n query: { ...(versionTag && { versionTag }) },\n contentType: 'application/json',\n },\n );\n }\n\n /**\n * Aborts a running execution.\n * @param executionId - The execution's unique identifier.\n */\n async abortExecution(executionId: string) {\n if (this.localServerUrl) {\n const url = `${this.localServerUrl}/api/${PROCESS_PATH}/progress/${executionId}/abort`;\n const response = await fetch(url, { method: 'POST' });\n if (!response.ok) {\n const text = await response.text().catch(() => '');\n throw new Error(\n `Local server request failed: ${response.status} - ${text}`,\n );\n }\n return (await response.json()) as ExecutionEntity;\n }\n return await this.#requestApi<ExecutionEntity>(\n 'POST',\n `${PROCESS_PATH}/progress/${executionId}/abort`,\n );\n }\n\n /**\n * Lists all executions for a given component.\n *\n * When `projectId` is supplied, the backend scopes the query to that\n * project — returning only executions launched in that context AND\n * enforcing that the caller has access to the component there. Without\n * `projectId`, the caller's personal executions for the component are\n * returned.\n *\n * @param componentId - The component's unique identifier.\n * @param projectId - Optional project scope.\n * @returns Array of execution entities.\n */\n async listExecutions(componentId: string, projectId?: string) {\n if (this.localServerUrl) {\n const qs = projectId ? `?projectId=${encodeURIComponent(projectId)}` : '';\n const url = `${this.localServerUrl}/api/${PROCESS_PATH}/${componentId}/progress${qs}`;\n const response = await fetch(url);\n if (!response.ok) {\n const text = await response.text().catch(() => '');\n throw new Error(\n `Local server request failed: ${response.status} - ${text}`,\n );\n }\n return (await response.json()) as ExecutionEntity[];\n }\n return await this.#requestApi<ExecutionEntity[]>(\n 'GET',\n `${PROCESS_PATH}/${componentId}/progress`,\n { query: { ...(projectId && { projectId }) } },\n );\n }\n\n /**\n * Gets details of a specific execution, including its messages.\n * @param executionId - The execution's unique identifier.\n * @returns The execution entity with progress and result info.\n */\n async getExecution(executionId: string) {\n if (this.localServerUrl) {\n const url = `${this.localServerUrl}/api/${PROCESS_PATH}/progress/${executionId}`;\n const response = await fetch(url);\n if (!response.ok) {\n const text = await response.text().catch(() => '');\n throw new Error(\n `Local server request failed: ${response.status} - ${text}`,\n );\n }\n return (await response.json()) as ExecutionEntity;\n }\n return await this.#requestApi<ExecutionEntity>(\n 'GET',\n `${PROCESS_PATH}/progress/${executionId}`,\n );\n }\n\n /**\n * Subscribes to real-time execution progress via WebSocket.\n * The callback fires on each progress update until the execution completes.\n * @param executionId - The execution's unique identifier.\n * @param onUpdateCallback - Callback invoked on each progress/result event.\n */\n async onExecutionProgress(\n executionId: string,\n onUpdateCallback: (data: ExecutionSuscriptionReturnType) => void,\n ) {\n const wsUrl = this.localServerUrl ?? this.wsUrl;\n // The token rides the auth payload of the connect packet, not the URL.\n // WebSocket-only: the long-polling handshake makes several HTTP requests,\n // and behind the platform's load balancer (no session affinity) they can\n // land on different backend instances, which kills the session before it\n // upgrades. One WebSocket is one connection, so it cannot hop.\n const socket = await io(wsUrl, {\n auth: { accessToken: this.accessToken },\n transports: ['websocket'],\n });\n\n socket.on('connect', function () {\n socket.emit('executionSubscription', JSON.stringify({ executionId }));\n socket.on('execution', (data: ExecutionSuscriptionReturnType) => {\n onUpdateCallback(data);\n });\n });\n\n socket.on('connect_error', function (e: unknown) {\n console.log(e);\n });\n }\n\n // ─── Documents, History & Recipes ────────────────────────────────\n\n /**\n * A project's documents. Every document is a FOLDER holding its files plus\n * a `document.json` descriptor naming the document, its native form and its\n * renderable views. See `src/core/documents.ts` for the model and schema.\n */\n documents(projectId: string): ProjectDocuments {\n return new ProjectDocuments(this, projectId);\n }\n\n /**\n * A project's history of connected documents (Revit models, AutoCAD\n * drawings…): their version timelines and their change requests. See\n * `src/core/history.ts` — this surface is the only supported way to read\n * or write it; the storage underneath is private and will move.\n */\n history(projectId: string): ProjectHistory {\n return new ProjectHistory(this, projectId);\n }\n\n #recipes?: Recipes;\n\n /**\n * The recipe registry and runner: scripts that write change requests in a\n * native application's language. See `src/core/recipes.ts`.\n */\n get recipes(): Recipes {\n this.#recipes ??= new Recipes(this);\n return this.#recipes;\n }\n\n // ─── Hidden Files ────────────────────────────────────────────────\n\n /**\n * Creates a hidden file attached to a parent item (e.g., dependencies, assets).\n * @param file - The file to upload.\n * @param parentFileId - The parent item's unique identifier.\n * @param tag - Optional label to tell hidden files of the same parent apart;\n * filter on it with {@link getHiddenFilesByParent}. Up to 50 characters:\n * letters, digits and `:._-`, starting with a letter or digit.\n * @returns The hidden file ID.\n */\n async createHiddenFile(\n file: File | Blob,\n parentFileId: string,\n tag?: string,\n ) {\n const formData = new FormData();\n formData.append('file', file);\n formData.append('parentItemId', parentFileId);\n if (tag != null) formData.append('tag', tag);\n\n return await this.#requestApi<CreateHiddenItemResult>(\n 'POST',\n `${ITEM_PATH}/${HIDDEN_PATH}`,\n {\n body: formData,\n },\n );\n }\n\n /**\n * Creates many hidden files attached to a parent item in a single request.\n * Use this instead of many `createHiddenFile` calls when uploading large sets\n * (e.g. 3D Tiles); upload in chunks of up to 100 files per call.\n * @param files - The files to upload.\n * @param parentFileId - The parent item's unique identifier.\n * @param tag - Optional label, as in {@link createHiddenFile}. One tag\n * applies to every file in the batch.\n * @returns One result per uploaded file, in order, each with its hidden file ID.\n */\n async createHiddenFilesBatch(\n files: (File | Blob)[],\n parentFileId: string,\n tag?: string,\n ) {\n const formData = new FormData();\n for (const file of files) {\n formData.append('files', file);\n }\n formData.append('parentItemId', parentFileId);\n if (tag != null) formData.append('tag', tag);\n\n return await this.#requestApi<CreateHiddenItemsBatchResult>(\n 'POST',\n `${ITEM_PATH}/${HIDDEN_PATH}/batch`,\n {\n body: formData,\n },\n );\n }\n\n /**\n * Deletes a hidden file by its ID.\n * @param hiddenId - The hidden file's unique identifier.\n */\n async deleteHiddenFile(hiddenId: string) {\n return await this.#requestApi<Item>(\n 'DELETE',\n `${ITEM_PATH}/${HIDDEN_PATH}/${hiddenId}`,\n );\n }\n\n /**\n * Gets metadata for a hidden file.\n * @param hiddenId - The hidden file's unique identifier.\n */\n async getHiddenFile(hiddenId: string) {\n return await this.#requestApi<HiddenFileEntity>(\n 'GET',\n `${ITEM_PATH}/${HIDDEN_PATH}/${hiddenId}`,\n );\n }\n\n /**\n * Downloads a hidden file's content. Returns the raw fetch Response.\n * @param hiddenId - The hidden file's unique identifier.\n */\n async downloadHiddenFile(hiddenId: string) {\n return await this.#requestFile(\n `${ITEM_PATH}/${HIDDEN_PATH}/${hiddenId}/download`,\n );\n }\n\n /**\n * Mints a short-lived presigned URL for a hidden file so the browser can\n * stream it directly from storage with native HTTP `Range` requests (e.g. a\n * point-cloud `octree.bin`), instead of proxying the whole object through the\n * API. Re-call to re-mint when the URL nears/passes `expiresAt`; coalesce\n * concurrent re-mints into a single in-flight call.\n *\n * The storage bucket's CORS must allow the `Range` request header and expose\n * `Content-Range`, `Accept-Ranges` and `Content-Length` for the ranged fetch\n * to succeed cross-origin.\n *\n * @param hiddenId - The hidden file's unique identifier.\n * @param expiresIn - Desired URL lifetime in seconds (60–3600). Defaults to\n * 900 (15 min) server-side; values are clamped to that range.\n * @returns `{ url, expiresAt }` — `url` is the presigned GET URL, `expiresAt`\n * an ISO timestamp when it stops working.\n */\n async getHiddenFileSignedUrl(hiddenId: string, expiresIn?: number) {\n return await this.#requestApi<{ url: string; expiresAt: string }>(\n 'GET',\n `${ITEM_PATH}/${HIDDEN_PATH}/${hiddenId}/signed-url`,\n { ...(expiresIn != null && { query: { expiresIn } }) },\n );\n }\n\n /**\n * Batch variant of {@link getHiddenFileSignedUrl}. Mints presigned URLs for\n * many hidden files in one request.\n *\n * This is the right call for tile-based viewers (splats, point clouds),\n * which mint a URL per piece as the camera moves. One request here replaces\n * up to {@link STORAGE_BATCH_MAX} single calls, which keeps a busy session\n * well under the per-endpoint rate limit.\n *\n * Inputs longer than {@link STORAGE_BATCH_MAX} are split into several\n * requests automatically. Entries come back in request order; a file that\n * is gone or not accessible carries an `error` instead of a `url`, so the\n * remaining tiles still load. Re-call to re-mint as `expiresAt` approaches.\n *\n * @param hiddenIds - The hidden files to sign.\n * @param expiresIn - Desired URL lifetime in seconds (60–3600). Defaults to\n * 900 (15 min) server-side; values are clamped to that range.\n */\n async getHiddenFileSignedUrlsBatch(\n hiddenIds: string[],\n expiresIn?: number,\n ): Promise<HiddenFileSignedUrlBatchEntry[]> {\n return await this.#requestBatches(\n hiddenIds,\n async (chunk) =>\n (\n await this.#requestApi<{ results: HiddenFileSignedUrlBatchEntry[] }>(\n 'POST',\n `${ITEM_PATH}/${HIDDEN_PATH}/signed-url/batch`,\n {\n body: JSON.stringify({\n hiddenFileIds: chunk,\n ...(expiresIn != null && { expiresIn }),\n }),\n contentType: 'application/json',\n },\n )\n ).results,\n );\n }\n\n /**\n * Lists the hidden files attached to a parent item.\n * @param parentFileId - The parent item's unique identifier.\n * @param tag - Optional filter: only hidden files uploaded with this tag. A\n * tagged listing comes back in creation order.\n * @returns Array of hidden file entities.\n */\n async getHiddenFilesByParent(parentFileId: string, tag?: string) {\n return await this.#requestApi<HiddenFileEntity[]>(\n 'GET',\n `${ITEM_PATH}/${parentFileId}/${HIDDEN_PATH}`,\n { ...(tag != null && { query: { tag } }) },\n );\n }\n\n /**\n * Deletes all hidden files attached to a parent item.\n * @param parentFileId - The parent item's unique identifier.\n */\n async deleteHiddenFilesByParent(parentFileId: string) {\n return await this.#requestApi<Item[]>(\n 'DELETE',\n `${ITEM_PATH}/${parentFileId}/${HIDDEN_PATH}`,\n );\n }\n\n // ─── Icons ───────────────────────────────────────────────────────\n\n /**\n * Uploads or replaces the icon for an item (app, component, or file).\n * Accepts PNG, WebP, or ICO images up to 512 KB.\n * @param itemId - The item's unique identifier.\n * @param icon - The icon image file (File in browsers, Blob in Node.js).\n * @returns The updated item with `iconFileId` and `iconMimeType` set.\n */\n async uploadItemIcon(itemId: string, icon: File | Blob) {\n const formData = new FormData();\n formData.append('icon', icon);\n return await this.#requestApi<Item>('PUT', `${ITEM_PATH}/${itemId}/icon`, {\n body: formData,\n });\n }\n\n /**\n * Downloads the icon for an item as a binary stream.\n * @param itemId - The item's unique identifier.\n * @returns The raw Response (use `.blob()`, `.arrayBuffer()`, or pipe the body).\n */\n async getItemIcon(itemId: string) {\n return await this.#requestFile(`${ITEM_PATH}/${itemId}/icon`);\n }\n\n /**\n * Removes the icon from an item.\n * @param itemId - The item's unique identifier.\n * @returns The updated item with icon fields removed.\n */\n async removeItemIcon(itemId: string) {\n return await this.#requestApi<Item>(\n 'DELETE',\n `${ITEM_PATH}/${itemId}/icon`,\n );\n }\n\n // ─── General Item Operations ─────────────────────────────────────\n\n /**\n * Renames or moves an item (file, component, or app) without creating a new version.\n * @param itemId - The item's unique identifier.\n * @param params - New name and/or new folder ID.\n * @returns The updated item.\n */\n async updateItem(\n itemId: string,\n params: { name?: string; folderId?: string },\n ) {\n return await this.#requestApi<Item>('PUT', `${ITEM_PATH}/${itemId}`, {\n body: JSON.stringify(params),\n contentType: 'application/json',\n });\n }\n\n /**\n * Creates a new version of an item by uploading a new file.\n * For APP and TOOL types, `extraProps` is required by the backend.\n * @param itemId - The item's unique identifier.\n * @param file - The new file to upload.\n * @param versionTag - Version tag for the new version (e.g. \"v2\").\n * @param extraProps - Version-specific properties (required for APP/TOOL types).\n * @param metadata - Optional free-JSON metadata to store on the new version.\n * @returns The created version.\n */\n async createVersion(\n itemId: string,\n file: File | Blob,\n versionTag: string,\n extraProps?: object,\n metadata?: Metadata,\n ) {\n const formData = new FormData();\n formData.append('file', file);\n formData.append('versionTag', versionTag);\n extraProps && formData.append('extraProps', JSON.stringify(extraProps));\n metadata && formData.append('metadata', JSON.stringify(metadata));\n return await this.#requestApi<ItemVersion>(\n 'POST',\n `${ITEM_PATH}/${itemId}/version`,\n { body: formData },\n );\n }\n\n /**\n * Lists versions of an item. Pass `archived: true` to fetch only archived\n * versions, `false` to fetch only active ones, or omit to receive both.\n * @param itemId - The item's unique identifier.\n * @param params - Optional `{ archived }` filter.\n * @returns Array of versions, sorted by creation date descending.\n */\n async listVersions(\n itemId: string,\n params: { archived?: boolean } = {},\n ): Promise<ItemVersion[]> {\n return await this.#requestApi<ItemVersion[]>(\n 'GET',\n `${ITEM_PATH}/${encodeURIComponent(itemId)}/versions`,\n { query: params },\n );\n }\n\n /**\n * Batch variant of {@link listVersions}. Lists the versions of many items in\n * one request, which is what a file panel needs to render a whole page.\n *\n * The returned versions are the full records, metadata included, so a list\n * that only needs version metadata does not need\n * {@link getFileVersionMetadataBatch} on top.\n *\n * Inputs longer than {@link STORAGE_BATCH_MAX} are split into several\n * requests automatically. An item the caller cannot read carries an `error`\n * instead of `versions`.\n *\n * @param itemIds - The items whose versions to list.\n * @param params - Optional `{ archived }` filter, applied to every item.\n */\n async listVersionsBatch(\n itemIds: string[],\n params: { archived?: boolean } = {},\n ): Promise<ItemVersionsBatchEntry[]> {\n const { archived } = params;\n return await this.#requestBatches(\n itemIds,\n async (chunk) =>\n (\n await this.#requestApi<{ results: ItemVersionsBatchEntry[] }>(\n 'POST',\n `${ITEM_PATH}/batch/versions`,\n {\n body: JSON.stringify({\n itemIds: chunk,\n ...(archived !== undefined && { archived }),\n }),\n contentType: 'application/json',\n },\n )\n ).results,\n );\n }\n\n /**\n * Archives a version of an item. Archived versions remain available via\n * `listVersions({ archived: true })` and can be recovered or permanently\n * deleted. Cleanup runs daily and removes archived versions older than the\n * platform retention period.\n * @param itemId - The item's unique identifier.\n * @param versionTag - The version's tag (e.g. \"v2\").\n * @returns The archived version.\n */\n async archiveVersion(itemId: string, versionTag: string) {\n return await this.#requestApi<ItemVersion>(\n 'PUT',\n `${ITEM_PATH}/${encodeURIComponent(itemId)}/version/${encodeURIComponent(versionTag)}/archive`,\n );\n }\n\n /**\n * Recovers a previously archived version, restoring it to the active list.\n * @param itemId - The item's unique identifier.\n * @param versionTag - The version's tag (e.g. \"v2\").\n * @returns The recovered version.\n */\n async recoverVersion(itemId: string, versionTag: string) {\n return await this.#requestApi<ItemVersion>(\n 'PUT',\n `${ITEM_PATH}/${encodeURIComponent(itemId)}/version/${encodeURIComponent(versionTag)}/recover`,\n );\n }\n\n /**\n * Permanently deletes a version, including its file in object storage.\n * The version must be archived first; otherwise the call is rejected.\n * @param itemId - The item's unique identifier.\n * @param versionTag - The version's tag (e.g. \"v2\").\n */\n async deleteVersion(itemId: string, versionTag: string) {\n return await this.#requestApi<{ success: boolean }>(\n 'DELETE',\n `${ITEM_PATH}/${encodeURIComponent(itemId)}/version/${encodeURIComponent(versionTag)}`,\n );\n }\n\n // Project-scoped listings happen via the main list methods — e.g.\n // `listFiles({ projectId })`, `listFolders({ projectId })`,\n // `listApps({ projectId })`, `listComponents({ projectId })`. Those call\n // `GET /item?projectId=...` / `/item/folder?projectId=...`, which accept\n // both API tokens and JWT and apply per-entity permission filtering on\n // the server.\n //\n // Methods that hit the JWT-only `/project/:id/*` and\n // `/project/permissions/check*` routes (getProject, getProjectData,\n // checkPermission, checkPermissionBatch) live on `PlatformClient` — they\n // cannot be called with an access token.\n\n // ─── Private Helpers ─────────────────────────────────────────────\n\n /**\n * Splits `inputs` into chunks the API accepts and concatenates the results,\n * so callers never have to think about the batch ceiling. Chunks go out\n * together; an empty input skips the network entirely, since the API\n * rejects an empty batch.\n */\n async #requestBatches<TInput, TEntry>(\n inputs: TInput[],\n requestChunk: (chunk: TInput[]) => Promise<TEntry[]>,\n ): Promise<TEntry[]> {\n if (!inputs.length) return [];\n\n const chunks: TInput[][] = [];\n for (let start = 0; start < inputs.length; start += STORAGE_BATCH_MAX) {\n chunks.push(inputs.slice(start, start + STORAGE_BATCH_MAX));\n }\n\n const responses = await Promise.all(chunks.map(requestChunk));\n return responses.flat();\n }\n\n async #downloadItem(itemId: string, params?: DownloadItemFileParams) {\n const { versionTag, withDraft } = params || {};\n return await this.#requestFile(`${ITEM_PATH}/${itemId}/download`, {\n query: {\n ...(versionTag && { versionTag }),\n ...(withDraft && { withDraft }),\n },\n });\n }\n\n async #createItem<T = Item, P extends object = object>(\n fileData: CreateItemProps,\n itemType: ItemType,\n extraProps?: P,\n ) {\n const { name, versionTag, parentFolderId, projectId, file, metadata } =\n fileData;\n const formData = new FormData();\n formData.append('file', file);\n formData.append('name', name);\n formData.append('versionTag', versionTag);\n formData.append('itemType', itemType);\n parentFolderId && formData.append('folderId', parentFolderId);\n projectId && formData.append('projectId', projectId);\n\n extraProps && formData.append('extraProps', JSON.stringify(extraProps));\n metadata && formData.append('metadata', JSON.stringify(metadata));\n return await this.#requestApi<CreateItemResponse<T>>('POST', ITEM_PATH, {\n body: formData,\n });\n }\n\n async #updateItem<T = Item, P extends object = object>(\n itemId: string,\n fileData: UpdateItemProps,\n extraProps?: P,\n ): Promise<UpdateItemResponse<T>> {\n const { name, versionTag, parentFolderId, file, metadata } = fileData;\n\n let item: T | undefined;\n let version: ItemVersion | undefined;\n\n if (file) {\n const formData = new FormData();\n formData.append('file', file);\n versionTag && formData.append('versionTag', versionTag);\n extraProps && formData.append('extraProps', JSON.stringify(extraProps));\n metadata && formData.append('metadata', JSON.stringify(metadata));\n version = await this.#requestApi<ItemVersion>(\n 'POST',\n `${ITEM_PATH}/${itemId}/version`,\n {\n body: formData,\n },\n );\n }\n\n if (name || parentFolderId) {\n const body: UpdateItemDto = {\n ...(name && { name }),\n ...(parentFolderId && { folderId: parentFolderId }),\n };\n\n const parsedBody = JSON.stringify(body);\n\n item = await this.#requestApi<T>('PUT', `${ITEM_PATH}/${itemId}`, {\n body: parsedBody,\n contentType: 'application/json',\n });\n }\n\n return { item, version };\n }\n\n async #getItem<T = Item>(itemId: string, props?: GetItemProps) {\n const { showVersions = false } = props || {};\n return await this.#requestApi<ItemWithVersions<T>>(\n 'GET',\n `${ITEM_PATH}/${itemId}`,\n {\n query: { showVersions },\n },\n );\n }\n\n #cleanData(data?: object) {\n return (\n data &&\n Object.entries(data)\n .filter(([, value]) => value !== undefined)\n .reduce(\n (obj, [key, value]) => {\n obj[key as string] = value;\n return obj;\n },\n {} as { [key: string]: unknown },\n )\n );\n }\n}\n","/**\n * The app side of the platform channel: rooms an app can join, and the\n * messages it exchanges through them.\n *\n * The app never holds a socket. The platform shell, outside the iframe, owns\n * the connection and relays over `postMessage`; this module is the typed\n * layer on top of that contract, reached as {@link PlatformClient.channel}.\n */\n\n/** What a command looks like: the payload it carries and the reply it expects. */\nexport interface ChannelCommandShape {\n payload?: unknown;\n reply?: unknown;\n}\n\n/**\n * The default command map, when none is given: every command name is allowed\n * and nothing is typed. Give `external<Commands>()` your own map to get\n * payloads and replies checked at compile time.\n */\nexport type AnyChannelCommands = Record<string, ChannelCommandShape>;\n\n/** The default event map for {@link CollabRoom}: any name, any payload. */\nexport type AnyChannelEvents = Record<string, unknown>;\n\ntype PayloadOf<T> = 'payload' extends keyof T ? T['payload'] : undefined;\n// A command that declares no `reply` is a notification: nothing to return.\ntype ReplyOf<T> = 'reply' extends keyof T ? T['reply'] : void;\n\n/** Someone else on the other end of a room. `kind` is set for external channels. */\nexport interface ChannelPeer {\n from: string;\n kind?: string;\n}\n\n/** Who sent a message, and when. */\nexport interface ChannelMessageMeta {\n /** The sender's connection id, stamped by the platform. */\n from: string;\n at: number;\n /** Present when the sender expects an answer. */\n requestId?: string;\n /** For an external sender that declared one: `'mcp'`, `'cli'`, `'revit'`… */\n kind?: string;\n}\n\n/** How the client talks to the shell. Replaceable, so it can be tested. */\nexport interface ChannelTransport {\n post(message: Record<string, unknown>): void;\n listen(handler: (data: unknown) => void): () => void;\n}\n\n/**\n * Talks to the platform shell through `window.parent`. Only messages whose\n * `source` is the parent window are accepted — the same check the shell makes\n * in the other direction — so another frame on the page cannot inject messages\n * into the app.\n */\nexport function windowTransport(): ChannelTransport {\n if (typeof window === 'undefined' || window.parent === window) {\n throw new Error(\n 'client.channel only works inside a That Open app, which runs in an iframe of the platform.',\n );\n }\n return {\n post: (message) => window.parent.postMessage(message, '*'),\n listen: (handler) => {\n const listener = (event: MessageEvent) => {\n if (event.source === window.parent) handler(event.data);\n };\n window.addEventListener('message', listener);\n return () => window.removeEventListener('message', listener);\n },\n };\n}\n\n/** Reserved for messages the platform itself sends. */\nconst SYSTEM_PREFIX = 'channel:';\nconst JOIN_TIMEOUT_MS = 10_000;\n\n/** A message as the platform delivers it to the app. */\nexport interface ChannelIncomingMessage {\n type: string;\n requestId?: string;\n payload?: unknown;\n at: number;\n from: string;\n scope?: 'collab' | 'external';\n kind?: string;\n}\n\n/** What a room did with a message. */\nexport type ChannelOutcome =\n | { handled: false }\n | { handled: true; value?: unknown; error?: string };\n\nfunction guard(fn: () => void) {\n try {\n fn();\n } catch (error) {\n console.error('[channel] a listener threw:', error);\n }\n}\n\ninterface Pending {\n want: 'joined' | 'left';\n resolve: () => void;\n reject: (error: Error) => void;\n timer: ReturnType<typeof setTimeout>;\n}\n\n/** What every room shares: membership, peers and presence. */\nexport abstract class ChannelRoom {\n #joined = false;\n #peers: ChannelPeer[] = [];\n #pending: Pending[] = [];\n readonly #onChange = new Set<() => void>();\n readonly #onPeerJoined = new Set<(peer: ChannelPeer) => void>();\n readonly #onPeerLeft = new Set<(peer: ChannelPeer) => void>();\n\n constructor(\n private readonly transport: ChannelTransport,\n private readonly controls: {\n join: Record<string, unknown>;\n leave: Record<string, unknown>;\n },\n ) {}\n\n /** Whether the platform has confirmed this tab is in the room. */\n get joined(): boolean {\n return this.#joined;\n }\n\n /** Who else is in the room right now, as the platform last reported. */\n get peers(): readonly ChannelPeer[] {\n return this.#peers;\n }\n\n /**\n * Enters the room. Resolves when the platform confirms; rejects if it\n * refuses or does not answer in time. Joining twice is harmless.\n */\n join(): Promise<void> {\n if (this.#joined) return Promise.resolve();\n return this.#request('joined', this.controls.join);\n }\n\n /** Leaves the room. Handlers stay registered, so `join()` resumes them. */\n leave(): Promise<void> {\n if (!this.#joined && !this.#pending.some((p) => p.want === 'joined')) {\n return Promise.resolve();\n }\n return this.#request('left', this.controls.leave);\n }\n\n /** Fires when `joined` or `peers` changes. Returns a function that stops it. */\n onChange(listener: () => void): () => void {\n this.#onChange.add(listener);\n return () => void this.#onChange.delete(listener);\n }\n\n onPeerJoined(listener: (peer: ChannelPeer) => void): () => void {\n this.#onPeerJoined.add(listener);\n return () => void this.#onPeerJoined.delete(listener);\n }\n\n onPeerLeft(listener: (peer: ChannelPeer) => void): () => void {\n this.#onPeerLeft.add(listener);\n return () => void this.#onPeerLeft.delete(listener);\n }\n\n /** @internal Does a message arriving with this scope/kind belong to this room? */\n abstract accepts(scope: string | undefined, kind: string | undefined): boolean;\n\n /** @internal */\n abstract handle(message: ChannelIncomingMessage): Promise<ChannelOutcome>;\n\n /** @internal */\n applyJoined() {\n this.#joined = true;\n this.#settle('joined');\n this.#changed();\n }\n\n /** @internal */\n applyLeft() {\n this.#joined = false;\n this.#peers = [];\n this.#settle('left');\n this.#changed();\n }\n\n /** @internal */\n applyPeers(peers: ChannelPeer[]) {\n this.#peers = peers;\n this.#changed();\n }\n\n /** @internal */\n applyPeerJoined(peer: ChannelPeer) {\n if (!this.#joined || this.#peers.some((p) => p.from === peer.from)) return;\n this.#peers = [...this.#peers, peer];\n this.#onPeerJoined.forEach((l) => guard(() => l(peer)));\n this.#changed();\n }\n\n /** @internal */\n applyPeerLeft(from: string) {\n const peer = this.#peers.find((p) => p.from === from);\n if (!peer) return;\n this.#peers = this.#peers.filter((p) => p.from !== from);\n this.#onPeerLeft.forEach((l) => guard(() => l(peer)));\n this.#changed();\n }\n\n /** @internal */\n failPending(error: Error): boolean {\n const pending = this.#pending;\n this.#pending = [];\n pending.forEach((p) => {\n clearTimeout(p.timer);\n p.reject(error);\n });\n return pending.length > 0;\n }\n\n protected post(message: Record<string, unknown>) {\n this.transport.post(message);\n }\n\n #request(want: 'joined' | 'left', control: Record<string, unknown>) {\n return new Promise<void>((resolve, reject) => {\n const entry: Pending = {\n want,\n resolve,\n reject,\n timer: setTimeout(() => {\n this.#pending = this.#pending.filter((p) => p !== entry);\n reject(\n new Error(\n `The platform did not confirm ${want === 'joined' ? 'joining' : 'leaving'} in time.`,\n ),\n );\n }, JOIN_TIMEOUT_MS),\n };\n this.#pending.push(entry);\n this.transport.post({ type: 'APP_CHANNEL_CONTROL', ...control });\n });\n }\n\n #settle(want: 'joined' | 'left') {\n const done = this.#pending.filter((p) => p.want === want);\n this.#pending = this.#pending.filter((p) => p.want !== want);\n done.forEach((p) => {\n clearTimeout(p.timer);\n p.resolve();\n });\n }\n\n #changed() {\n this.#onChange.forEach((l) => guard(l));\n }\n}\n\n/**\n * The collaboration room: every user's tab of this app that joined it, across\n * accounts. Messages here are events — nobody replies.\n *\n * `E` maps each event name to its payload, so `send` and `on` are checked.\n */\nexport class CollabRoom<E extends object = AnyChannelEvents> extends ChannelRoom {\n readonly #listeners = new Map<\n string,\n Set<(payload: never, meta: ChannelMessageMeta) => void>\n >();\n\n /** @internal Use `client.channel.collab()`. */\n constructor(transport: ChannelTransport) {\n super(transport, {\n join: { action: 'joinCollab' },\n leave: { action: 'leaveCollab' },\n });\n }\n\n /**\n * Listens for an event other tabs send. Any number of listeners per event.\n * @returns a function that removes the listener.\n */\n on<K extends keyof E & string>(\n type: K,\n listener: (payload: E[K], meta: ChannelMessageMeta) => void,\n ): () => void {\n const set = this.#listeners.get(type) ?? new Set();\n set.add(listener as never);\n this.#listeners.set(type, set);\n return () => void set.delete(listener as never);\n }\n\n /**\n * Sends an event to the other tabs in the room. Does nothing while this tab\n * is not in it, matching what the platform does with a message from outside.\n */\n send<K extends keyof E & string>(type: K, payload: E[K]): void {\n if (type.startsWith(SYSTEM_PREFIX)) {\n throw new Error(`Message types starting with '${SYSTEM_PREFIX}' are reserved.`);\n }\n if (!this.joined) return;\n this.post({ type: 'APP_CHANNEL_PUBLISH', message: { type, payload } });\n }\n\n accepts(scope: string | undefined): boolean {\n return scope === undefined || scope === 'collab';\n }\n\n async handle(message: ChannelIncomingMessage): Promise<ChannelOutcome> {\n const listeners = this.#listeners.get(message.type);\n if (!listeners?.size) return { handled: false };\n const meta = metaOf(message);\n listeners.forEach((l) => guard(() => l(message.payload as never, meta)));\n return { handled: true };\n }\n}\n\n/**\n * Commands from this account's external tools — a CLI, an MCP server, a Revit\n * plugin — of one `kind`, or of every kind when none is given.\n *\n * `C` maps each command name to `{ payload, reply }`, so a handler's argument\n * and return value are checked. A command without `reply` is a notification.\n */\nexport class ExternalRoom<\n C extends { [K in keyof C]: ChannelCommandShape } = AnyChannelCommands,\n> extends ChannelRoom {\n readonly #handlers = new Map<\n string,\n (payload: never, meta: ChannelMessageMeta) => unknown\n >();\n\n /** @internal Use `client.channel.external(kind)`. */\n constructor(\n transport: ChannelTransport,\n readonly kind?: string,\n ) {\n super(transport, {\n join: { action: 'joinExternal', kind },\n leave: { action: 'leaveExternal', kind },\n });\n }\n\n /**\n * Handles a command. When the sender asked for an answer, what you return\n * is sent back to it; if you throw, it gets an error instead of waiting for\n * a timeout. When it did not ask (a notification), the return value is\n * ignored.\n *\n * One handler per command: a second one for the same name throws, since two\n * would both try to answer.\n * @returns a function that removes the handler.\n */\n on<K extends keyof C & string>(\n type: K,\n handler: (\n payload: PayloadOf<C[K]>,\n meta: ChannelMessageMeta,\n ) => ReplyOf<C[K]> | Promise<ReplyOf<C[K]>>,\n ): () => void {\n if (this.#handlers.has(type)) {\n throw new Error(\n `\"${type}\" already has a handler in this room. Remove it first.`,\n );\n }\n this.#handlers.set(type, handler as never);\n return () => void this.#handlers.delete(type);\n }\n\n accepts(scope: string | undefined, kind: string | undefined): boolean {\n if (scope !== undefined && scope !== 'external') return false;\n return this.kind === undefined || scope === undefined || this.kind === kind;\n }\n\n /** @internal Whether this room has any handler at all. */\n get hasHandlers(): boolean {\n return this.#handlers.size > 0;\n }\n\n async handle(message: ChannelIncomingMessage): Promise<ChannelOutcome> {\n const handler = this.#handlers.get(message.type);\n if (!handler) return { handled: false };\n try {\n const value = await handler(message.payload as never, metaOf(message));\n return { handled: true, value };\n } catch (error) {\n return {\n handled: true,\n error: error instanceof Error ? error.message : String(error),\n };\n }\n }\n}\n\nfunction metaOf(message: ChannelIncomingMessage): ChannelMessageMeta {\n return {\n from: message.from,\n at: message.at,\n requestId: message.requestId,\n kind: message.kind,\n };\n}\n\nfunction readMessage(data: unknown): ChannelIncomingMessage | null {\n const envelope = data as { type?: unknown; message?: unknown } | null;\n if (envelope?.type !== 'THATOPEN_CHANNEL_MESSAGE') return null;\n const message = envelope.message as Partial<ChannelIncomingMessage> | undefined;\n if (!message || typeof message.type !== 'string') return null;\n return {\n type: message.type,\n requestId:\n typeof message.requestId === 'string' ? message.requestId : undefined,\n payload: message.payload,\n at: typeof message.at === 'number' ? message.at : Date.now(),\n from: typeof message.from === 'string' ? message.from : '',\n scope:\n message.scope === 'collab' || message.scope === 'external'\n ? message.scope\n : undefined,\n kind: typeof message.kind === 'string' ? message.kind : undefined,\n };\n}\n\n/**\n * Typed access to the platform channel from inside an app: a collaboration\n * room shared with other users, and rooms for commands from external tools.\n * Reach it as `client.channel`.\n *\n * @example\n * ```ts\n * type McpCommands = {\n * 'select-by-category': { payload: { category: string }; reply: { count: number } };\n * };\n *\n * const mcp = client.channel.external<McpCommands>('mcp');\n * mcp.on('select-by-category', async ({ category }) => ({\n * count: await selectByCategory(category),\n * }));\n * await mcp.join();\n * ```\n */\nexport class ChannelClient {\n readonly #transport: ChannelTransport;\n readonly #stop: () => void;\n #collab?: CollabRoom<never>;\n readonly #externals = new Map<string, ExternalRoom<never>>();\n readonly #answered = new Set<string>();\n\n constructor(transport: ChannelTransport) {\n this.#transport = transport;\n this.#stop = transport.listen((data) => void this.#receive(data));\n }\n\n /** The collaboration room for this app. Always the same instance. */\n collab<E extends object = AnyChannelEvents>(): CollabRoom<E> {\n this.#collab ??= new CollabRoom<never>(this.#transport);\n return this.#collab as unknown as CollabRoom<E>;\n }\n\n /**\n * The room for commands from this account's external tools of one `kind`\n * (`'mcp'`, `'cli'`, `'revit'`…), or from any of them when `kind` is omitted.\n * Always the same instance for the same kind.\n */\n external<C extends { [K in keyof C]: ChannelCommandShape } = AnyChannelCommands>(\n kind?: string,\n ): ExternalRoom<C> {\n const key = kind ?? '';\n let room = this.#externals.get(key);\n if (!room) {\n room = new ExternalRoom<never>(this.#transport, kind);\n this.#externals.set(key, room);\n }\n return room as unknown as ExternalRoom<C>;\n }\n\n /** Stops listening. For tests and teardown; an app normally never calls it. */\n dispose() {\n this.#stop();\n }\n\n #rooms(): ChannelRoom[] {\n return [...(this.#collab ? [this.#collab] : []), ...this.#externals.values()];\n }\n\n #exact(scope: unknown, kind: unknown): ChannelRoom | undefined {\n if (scope === 'collab') return this.#collab;\n if (scope === 'external') {\n return this.#externals.get(typeof kind === 'string' ? kind : '');\n }\n return undefined;\n }\n\n async #receive(data: unknown) {\n const message = readMessage(data);\n if (!message) return;\n if (message.type.startsWith(SYSTEM_PREFIX)) {\n this.#system(message);\n return;\n }\n await this.#deliver(message);\n }\n\n #system(message: ChannelIncomingMessage) {\n const info = (message.payload ?? {}) as {\n scope?: string;\n kind?: string;\n from?: string;\n peers?: ChannelPeer[];\n };\n\n switch (message.type) {\n case 'channel:joined':\n this.#exact(info.scope, info.kind)?.applyJoined();\n break;\n case 'channel:left':\n this.#exact(info.scope, info.kind)?.applyLeft();\n break;\n case 'channel:peers':\n this.#exact(info.scope, info.kind)?.applyPeers(info.peers ?? []);\n break;\n case 'channel:peer-joined':\n case 'channel:peer-left': {\n if (!info.from) break;\n // An external peer of one kind is seen by the catch-all room and by\n // the room for that kind alike.\n const rooms: (ChannelRoom | undefined)[] =\n info.scope === 'collab'\n ? [this.#collab]\n : [...this.#externals.values()].filter((r) =>\n r.accepts('external', info.kind),\n );\n for (const room of rooms) {\n if (message.type === 'channel:peer-joined') {\n room?.applyPeerJoined({ from: info.from, kind: info.kind });\n } else {\n room?.applyPeerLeft(info.from);\n }\n }\n break;\n }\n case 'channel:error': {\n const error = new Error(String(message.payload));\n // Errors are not tied to a request, so anything waiting to join or\n // leave is told; with nothing waiting, the error would vanish.\n const told = this.#rooms().map((r) => r.failPending(error));\n if (!told.some(Boolean)) console.error('[channel] error:', message.payload);\n break;\n }\n }\n }\n\n async #deliver(message: ChannelIncomingMessage) {\n // Without `scope` (a gateway that predates it) there is no telling which\n // room a message came through, so it goes to every room that can take it.\n const rooms = this.#rooms().filter((r) => r.accepts(message.scope, message.kind));\n let answered = false;\n\n for (const room of rooms) {\n const outcome = await room.handle(message);\n if (!outcome.handled) continue;\n answered = true;\n if (message.requestId) this.#reply(message.requestId, outcome);\n }\n\n // Someone asked, this app listens for that kind of sender, and nothing\n // handles the command: say so, rather than let the asker time out.\n const asked =\n message.requestId && message.scope === 'external' && rooms.length > 0;\n if (asked && !answered) {\n this.#reply(message.requestId!, {\n handled: true,\n error: `No handler for \"${message.type}\".`,\n });\n }\n }\n\n #reply(requestId: string, outcome: Extract<ChannelOutcome, { handled: true }>) {\n // Two rooms can both handle one command (the catch-all and its kind).\n // Only the first answer counts: a second reply with the same id would no\n // longer match a pending request and would leak into the collab room.\n if (this.#answered.has(requestId)) return;\n this.#answered.add(requestId);\n if (this.#answered.size > 500) {\n this.#answered.delete(this.#answered.values().next().value as string);\n }\n this.#transport.post({\n type: 'APP_CHANNEL_PUBLISH',\n message: {\n type: outcome.error === undefined ? 'reply' : 'reply-error',\n requestId,\n payload:\n outcome.error === undefined ? outcome.value : { error: outcome.error },\n },\n });\n }\n}\n","import { io } from 'socket.io-client';\nimport {\n EngineServicesClient,\n EngineServicesClientProps,\n} from './client';\nimport { Project, ProjectData, ProjectWithRole } from '../types/projects';\nimport { ThatOpenContext } from '../types/context';\nimport { ChannelClient, windowTransport } from './channel';\nimport {\n MarkNotificationsReadResultDto,\n NotificationPageDto,\n NotificationSubscriptionView,\n UnreadCountDto,\n} from '../types/notifications';\n\nconst PROJECT_PATH = 'project';\nconst NOTIFICATION_PATH = 'notifications';\n\n/**\n * What arrived on the socket. One callback for all three because a bell\n * reacts the same way to each: refresh the badge, and the list if open.\n *\n * `allRead` is one event for the whole sweep rather than one per\n * notification, so do not expect an id on it.\n */\nexport type LiveNotificationEvent =\n | { type: 'created'; id: string }\n | { type: 'read'; id: string }\n | { type: 'allRead'; batch: number };\n\n/** Per-automation opt-in. `failures` skips started events entirely. */\nexport type NotificationSubscriptionFilterInput = 'all' | 'failures';\n\nexport interface NotificationSubscriptionInput {\n filter?: NotificationSubscriptionFilterInput;\n /** Overrides the account-level channel setting for this automation only. */\n channels?: { email?: boolean };\n}\n\n/** Scope by which a permission was granted (or `'none'` if denied). */\nexport type PermissionScope = 'global' | 'project' | 'entity' | 'none';\n\n/** Result of a single permission check. */\nexport interface PermissionCheckResult {\n hasPermission: boolean;\n scope: PermissionScope;\n}\n\n/** One entry in a batch permission check. */\nexport interface PermissionCheckEntry {\n resourceType: string;\n action: string;\n resourceId?: string;\n projectId?: string;\n}\n\n/**\n * Accepts either a static JWT string or a provider function that returns the\n * current JWT. Use a provider to keep refresh in the caller's hands — the\n * client calls it on every request so expired tokens never stick.\n *\n * @example Static token (simplest):\n * ```ts\n * new PlatformClient(jwt, apiUrl)\n * ```\n *\n * @example Auth0 React:\n * ```ts\n * const { getAccessTokenSilently } = useAuth0();\n * new PlatformClient(() => getAccessTokenSilently(), apiUrl)\n * ```\n */\nexport type BearerTokenSource =\n | string\n | (() => string | Promise<string>);\n\n/**\n * Client for apps, frontends, and any caller authenticating with a user JWT.\n * Extends `EngineServicesClient` — the full API-token-compatible surface is\n * inherited. On top, it exposes the JWT-only routes `getProject`,\n * `getProjectData`, `checkPermission`, and `checkPermissionBatch`. Those hit\n * `ProjectController` which is guarded by `AccountActiveGuard +\n * ProjectAccessGuard` and is not reachable via an access token.\n *\n * **Token refresh.** The constructor accepts a function that returns a JWT\n * (sync or async); the client calls it before every request, so an Auth0\n * SDK's `getAccessTokenSilently()` or similar refreshing source Just Works.\n *\n * Use `EngineServicesClient` for components (API-token auth, local server,\n * WebSocket progress). Use `PlatformClient` when you have a user JWT and\n * need project-level reads or permission introspection.\n *\n * @example\n * ```ts\n * const client = new PlatformClient(\n * () => auth0.getAccessTokenSilently(),\n * 'https://api.thatopen.com',\n * );\n * const project = await client.getProject(projectId);\n * ```\n */\nexport class PlatformClient extends EngineServicesClient {\n readonly #tokenProvider?: () => string | Promise<string>;\n #channel?: ChannelClient;\n\n /**\n * @param token - A bearer JWT, OR a function returning the current JWT\n * (sync or async). When a function is passed, it's invoked before every\n * request — ideal for token-refreshing sources like Auth0.\n * @param apiUrl - Base URL of the API (e.g. `https://api.thatopen.com`).\n * @param props - Optional client configuration. `useBearer` is forced to\n * `true` and cannot be overridden.\n */\n constructor(\n token: BearerTokenSource,\n apiUrl: string,\n props?: Omit<EngineServicesClientProps, 'useBearer'>,\n ) {\n // Seed the parent with a string (possibly empty when a provider is\n // supplied); the override below routes each request through the\n // provider when present.\n const initialToken = typeof token === 'string' ? token : '';\n super(initialToken, apiUrl, { ...props, useBearer: true });\n if (typeof token === 'function') {\n this.#tokenProvider = token;\n }\n }\n\n protected async resolveAccessToken(): Promise<string> {\n if (this.#tokenProvider) return await this.#tokenProvider();\n return super.resolveAccessToken();\n }\n\n /**\n * Creates a client from the platform context injected into\n * `window.__THATOPEN_CONTEXT__` by the That Open Platform. Recommended\n * entry point for apps running inside the platform's iframe — the context\n * carries a fresh JWT on every navigation.\n */\n static fromPlatformContext(\n props?: Omit<EngineServicesClientProps, 'useBearer'>,\n ): PlatformClient {\n const ctx: ThatOpenContext =\n (typeof window !== 'undefined'\n ? window.__THATOPEN_CONTEXT__\n : null) || { appId: '', projectId: '', accessToken: '', apiUrl: '' };\n const client = new PlatformClient(ctx.accessToken, ctx.apiUrl, props);\n (client as { context: ThatOpenContext }).context = ctx;\n return client;\n }\n\n /**\n * The platform channel, from inside an app: a collaboration room shared with\n * other users of the app, and rooms for commands from external tools (a CLI,\n * an MCP server, a Revit plugin). Typed, and built on the `postMessage`\n * contract with the platform shell — the app never opens a socket.\n *\n * Only available in an app running in the platform's iframe; reading it\n * anywhere else throws. Created on first use.\n *\n * @example\n * ```ts\n * type McpCommands = {\n * 'select-by-category': { payload: { category: string }; reply: { count: number } };\n * };\n *\n * const mcp = client.channel.external<McpCommands>('mcp');\n * mcp.on('select-by-category', async ({ category }) => ({ count: 3 }));\n * await mcp.join();\n *\n * const collab = client.channel.collab();\n * collab.onPeerLeft(({ from }) => removeAvatar(from));\n * await collab.join();\n * ```\n */\n get channel(): ChannelClient {\n this.#channel ??= new ChannelClient(windowTransport());\n return this.#channel;\n }\n\n // ─── Projects (JWT-only backend routes) ──────────────────────────\n\n /**\n * Lists the caller's projects, each with their role in it. The discovery\n * call: everything else on this surface takes a projectId, and until this\n * method there was no way to find out which ids exist — a portfolio\n * dashboard had to be configured by hand. `ProjectWithRole` existed as a\n * type with no producer; this is the producer.\n *\n * @example\n * ```ts\n * const projects = await client.listProjects();\n * for (const { project, role } of projects) {\n * console.log(project.title, role?.name ?? 'no role');\n * }\n * ```\n */\n async listProjects() {\n return await this.request<ProjectWithRole[]>('GET', PROJECT_PATH);\n }\n\n /**\n * Gets a project by ID. JWT-only — lives here because\n * `GET /project/:id` is guarded by `AccountActiveGuard + ProjectAccessGuard`.\n */\n async getProject(projectId: string) {\n return await this.request<Project>('GET', `${PROJECT_PATH}/${projectId}`);\n }\n\n /**\n * Gets the full project data (users, roles, files, folders) for a project.\n * User data is stripped of sensitive fields server-side.\n */\n async getProjectData(projectId: string) {\n return await this.request<ProjectData>(\n 'GET',\n `${PROJECT_PATH}/${projectId}/data`,\n );\n }\n\n // ─── Account ──────────────────────────────────────────────────────\n\n /**\n * Fetches a user's profile picture as raw image bytes, for showing member\n * avatars inside an app. The route is bearer-authed, so it can't be used as\n * an `<img src>` — turn the blob into an object URL with\n * `URL.createObjectURL(blob)`. Rejects when the account has no avatar.\n */\n async getAvatar(accountId: string): Promise<Blob> {\n return await this.request<Blob>('GET', `account/${accountId}/avatar`, {\n responseType: 'blob',\n });\n }\n\n // ─── Permissions (JWT-only backend routes) ───────────────────────\n\n /**\n * Checks whether the caller has a specific permission within a project.\n * Returns `{ hasPermission, scope }` where `scope` is `'global'` for\n * admin/owner, `'project'` for a role broad grant, `'entity'` for a\n * per-entity override, `'none'` for denied.\n */\n async checkPermission(params: {\n resourceId?: string;\n resourceType: string;\n action: string;\n projectId?: string;\n }) {\n return await this.request<PermissionCheckResult>(\n 'GET',\n `${PROJECT_PATH}/permissions/check`,\n { query: params as Record<string, string | undefined> },\n );\n }\n\n /**\n * Batch variant of {@link checkPermission}. Evaluates multiple checks in a\n * single round-trip; results come back in the same order as `checks`.\n */\n async checkPermissionBatch(checks: PermissionCheckEntry[]) {\n const response = await this.request<{\n results: PermissionCheckResult[];\n }>('POST', `${PROJECT_PATH}/permissions/check/batch`, {\n body: JSON.stringify({ checks }),\n contentType: 'application/json',\n });\n return response.results;\n }\n\n // ─── Notifications ────────────────────────────────────────────────\n\n /**\n * Lists the signed-in user's notifications, newest first.\n *\n * Scoped to whoever the bearer token belongs to — an app cannot read\n * anyone else's. Muted notifications are included: muting silences the\n * badge and the delivery channels, it does not hide the record.\n *\n * Paginate by passing the previous response's `nextCursor` back in; it is\n * opaque, so do not build one by hand. A null `nextCursor` means the last\n * page.\n *\n * @example Walk every page:\n * ```ts\n * let cursor: string | undefined;\n * do {\n * const page = await client.getNotifications({ cursor });\n * render(page.items);\n * cursor = page.nextCursor ?? undefined;\n * } while (cursor);\n * ```\n */\n async getNotifications(params?: { cursor?: string; limit?: number }) {\n return await this.request<NotificationPageDto>('GET', NOTIFICATION_PATH, {\n query: {\n ...(params?.cursor !== undefined && { cursor: params.cursor }),\n ...(params?.limit !== undefined && { limit: String(params.limit) }),\n },\n });\n }\n\n /**\n * Number of unread notifications, excluding muted ones. This is the bell\n * badge count, so it is cheap to poll.\n */\n async getUnreadNotificationCount() {\n const response = await this.request<UnreadCountDto>(\n 'GET',\n `${NOTIFICATION_PATH}/unread-count`,\n );\n return response.count;\n }\n\n /**\n * Marks specific notifications as read. Ids the caller does not own are\n * ignored rather than rejected, so `updated` can be lower than the number\n * passed in.\n */\n async markNotificationsRead(notificationIds: string[]) {\n return await this.request<MarkNotificationsReadResultDto>(\n 'POST',\n `${NOTIFICATION_PATH}/mark-read`,\n {\n body: JSON.stringify({ ids: notificationIds }),\n contentType: 'application/json',\n },\n );\n }\n\n /** Marks every unread notification as read in one call. */\n async markAllNotificationsRead() {\n return await this.request<MarkNotificationsReadResultDto>(\n 'POST',\n `${NOTIFICATION_PATH}/mark-all-read`,\n );\n }\n\n /**\n * The automations this user has subscribed to. Nobody is subscribed by\n * default, so an empty list is the normal state.\n */\n async getNotificationSubscriptions() {\n return await this.request<NotificationSubscriptionView[]>(\n 'GET',\n `${NOTIFICATION_PATH}/subscriptions`,\n );\n }\n\n /**\n * Removes this user's subscription to one automation.\n *\n * Unlike subscribing, which happens through the project routes, this works\n * for any automation the user is subscribed to and keeps working after the\n * automation itself is gone — opting out must never be the thing that\n * fails.\n */\n async unsubscribeFromAutomation(hookId: string) {\n return await this.request<{ unsubscribed: boolean }>(\n 'DELETE',\n `${NOTIFICATION_PATH}/subscriptions/${hookId}`,\n );\n }\n\n /**\n * Subscribes the signed-in user to one project automation's runs.\n *\n * Nobody is subscribed by default, so this is what makes an automation\n * produce notifications for this user at all. Subscribing again is\n * harmless: it updates the existing subscription rather than duplicating.\n *\n * Read-level access to the project is enough. Someone who can see an\n * automation can follow it without being able to change it.\n *\n * @example Follow only the failures, and email me about them:\n * ```ts\n * await client.subscribeToAutomation(projectId, hookId, {\n * filter: 'failures',\n * channels: { email: true },\n * });\n * ```\n */\n async subscribeToAutomation(\n projectId: string,\n hookId: string,\n input?: NotificationSubscriptionInput,\n ) {\n return await this.request<{ subscribed: true }>(\n 'POST',\n `${PROJECT_PATH}/${projectId}/events/hooks/${hookId}/subscription`,\n {\n body: JSON.stringify(input ?? {}),\n contentType: 'application/json',\n },\n );\n }\n\n /**\n * Changes an existing subscription. Only the fields passed are touched, so\n * sending `channels` alone leaves the filter as it was.\n *\n * Throws if the user is not subscribed; use {@link subscribeToAutomation}\n * to create one.\n */\n async updateAutomationSubscription(\n projectId: string,\n hookId: string,\n changes: NotificationSubscriptionInput,\n ) {\n return await this.request<{ updated: true }>(\n 'PATCH',\n `${PROJECT_PATH}/${projectId}/events/hooks/${hookId}/subscription`,\n {\n body: JSON.stringify(changes),\n contentType: 'application/json',\n },\n );\n }\n\n /**\n * Listens for this user's notifications in real time.\n *\n * Unlike {@link EngineServicesClient.onExecutionProgress}, which follows one\n * execution and closes when it ends, this stays connected for the session:\n * the server puts the socket in a room for the signed-in account and pushes\n * anything addressed to them.\n *\n * The events carry ids rather than the notifications themselves, so treat\n * them as a signal to refresh. That keeps a burst cheap and means the\n * server is never the source of a stale render.\n *\n * Requires a user JWT. An API access token is rejected by the gateway,\n * because it identifies a token rather than a person.\n *\n * @returns a function that disconnects. Call it on unmount.\n *\n * @example\n * ```ts\n * const stop = await client.onNotification((event) => {\n * if (event.type === 'created') refreshBell();\n * });\n * // later\n * stop();\n * ```\n */\n async onNotification(\n onEvent: (event: LiveNotificationEvent) => void,\n ): Promise<() => void> {\n // Resolved per connection rather than reused from construction, so a\n // provider-backed client opens the socket with a current token. It rides\n // the auth payload, never the URL: a failing handshake prints its URL in\n // the browser console, token included.\n const token = await this.resolveAccessToken();\n const socket = io(`${this.socketOrigin}/notifications`, {\n auth: { accessToken: token },\n transports: ['websocket'],\n });\n\n socket.on('notification.created', (data: { id: string }) =>\n onEvent({ type: 'created', id: data?.id }),\n );\n socket.on('notification.read', (data: { id: string }) =>\n onEvent({ type: 'read', id: data?.id }),\n );\n socket.on('notifications.allRead', (data: { batch: number }) =>\n onEvent({ type: 'allRead', batch: data?.batch }),\n );\n\n return () => socket.disconnect();\n }\n}\n","/**\n * Authors an interoperability OPERATION — a set of deferred edits for one\n * document — and hands back the bytes to upload as a suggestion's payload.\n *\n * WHY THIS EXISTS AND WHY IT LOOKS LIKE THIS. An operation is carried as a\n * .frag with no geometry at all: the envelope in `Model.metadata`, and one\n * geometry-less item per change whose attributes ARE the change. That was\n * cheap on the C# side, which already had a writer, and it is the reason a\n * converter had to be a console tool once: nothing in the browser could\n * produce one. So the format stayed, and this builds it here instead.\n *\n * Nothing above this class needs to know any of that. You say add / set /\n * remove and get bytes for {@link FlowDoc.suggest} or a recipe's result.\n *\n * WHAT IT DOES NOT DO. It does not translate. Attributes are written exactly\n * as given, in the TARGET application's own terms and units, because data\n * that gets translated on the way in has to be untranslated on the way out\n * and the day somebody forgets a field nothing complains. Deciding what a\n * Rhino layer means in Revit is the recipe's job; this only carries the\n * answer.\n *\n * DEPENDENCIES, loaded at build() time and declared as OPTIONAL PEERS:\n * `@thatopen/fragments` (the .frag schema) and `flatbuffers`. An app that\n * authors operations has both already; everything else in this package works\n * without them.\n */\n\ntype FlatbuffersModule = typeof import('flatbuffers');\ntype FragmentsSchema = typeof import('@thatopen/fragments');\n\n/**\n * The reserved namespace. Everything under it is addressed to the applier and\n * is never data, so an applier skips the whole prefix rather than the names\n * it happens to know — which is what lets an author record something for its\n * OWN later use without the other side being taught what it means.\n */\nconst RESERVED = 'flow:';\n\n/** The verb. An instruction sitting among data, which is why it is prefixed. */\nconst OP_KEY = 'flow:op';\n\n/**\n * Where a change came from, in the author's own terms.\n *\n * NOT a link between elements — nothing is written into either model. It\n * lives on the OPERATION, which is the record of what somebody asked for,\n * and it is what lets a recipe be self-contained: \"what did I already make\n * for this object\" is answered by reading the queue the platform already\n * keeps, instead of a private file that a second machine does not have and a\n * lost machine takes with it.\n */\nconst SOURCE_KEY = 'flow:source';\n\n/** The schema this writes. An applier that speaks a different one must refuse rather than guess. */\nexport const OP_SCHEMA = 'revitflow/op@2';\n\nconst CATEGORY_CHANGE = 'REVITFLOWCHANGE';\nconst CATEGORY_OPERATION = 'REVITFLOWOPERATION';\n\nexport interface OperationTarget {\n /** Platform project id. */\n project: string;\n /** Document name within the project — the model these edits are for. */\n document: string;\n /**\n * The commit this was authored against. The elements named here existed\n * then; by the time somebody applies it they may not, and the applier\n * reports what it could not resolve.\n */\n baseCommit: number;\n /** Who authored it, for the history. */\n author?: string;\n /** Platform user id, so the same person is not two names depending on which tool wrote it. */\n userId?: string;\n /** Groups the operations one authored action produced across several models. */\n batchId?: string;\n title?: string;\n}\n\n/** Where an added item goes, and how it is turned, in the target's own terms. */\nexport interface Placement {\n /** [x, y, z] in the TARGET model's own units and axes. Not converted here. */\n position?: [number, number, number];\n /** Degrees about Z, in the target's convention. */\n rotationDeg?: number;\n /**\n * The id of the object that caused this change, in the AUTHOR's own terms —\n * a Rhino guid, a row of a spreadsheet, whatever proposed it. Optional, and\n * only useful to whoever wrote it: pass it when you expect to come back and\n * find what you created.\n */\n source?: string;\n}\n\nexport class OperationBuilder {\n private readonly changes: {\n op: 'add' | 'set' | 'remove';\n item?: string;\n attrs: Record<string, string>;\n }[] = [];\n\n constructor(private readonly target: OperationTarget) {}\n\n /** How many changes are queued. An operation with none is refused by `build`. */\n get length(): number {\n return this.changes.length;\n }\n\n // The envelope, readable. Whoever writes the queue entry has to put the SAME\n // values in it as the payload carries — an entry that disagrees with its own\n // payload is a row describing a different operation — so they are exposed\n // here rather than passed twice by every caller.\n get batchId(): string | undefined {\n return this.target.batchId;\n }\n get title(): string {\n return this.target.title ?? `${this.changes.length} change(s)`;\n }\n get author(): string {\n return this.target.author ?? 'app';\n }\n get userId(): string | undefined {\n return this.target.userId;\n }\n get baseCommit(): number {\n return this.target.baseCommit;\n }\n\n /**\n * Create something. There is no id yet: the attributes describe what it is,\n * the placement says where it goes, and the operation answers with the id\n * it got.\n */\n add(attrs: Record<string, string>, placement: Placement = {}): this {\n this.changes.push({ op: 'add', attrs: this.pack(attrs, placement) });\n return this;\n }\n\n /** Write attributes onto an item that already exists, named by the id the target published. */\n set(\n item: string,\n attrs: Record<string, string>,\n placement: Placement = {},\n ): this {\n this.requireId(item, 'set');\n this.changes.push({ op: 'set', item, attrs: this.pack(attrs, placement) });\n return this;\n }\n\n /** Delete an item. Whatever the target cascades along with it is reported, not guessed at here. */\n remove(item: string): this {\n this.requireId(item, 'remove');\n this.changes.push({ op: 'remove', item, attrs: {} });\n return this;\n }\n\n /**\n * A label for what this operation mostly does. Derived, never read to\n * decide anything: one operation may add, set and remove at once and still\n * be atomic, so what each change does is written on the change.\n */\n get summary(): 'add' | 'set' | 'remove' | 'mixed' {\n const kinds = new Set(this.changes.map((c) => c.op));\n return kinds.size === 1 ? [...kinds][0] : 'mixed';\n }\n\n /**\n * The .frag bytes, zlib-deflated, ready to upload as the operation's\n * payload.\n *\n * `opId` is taken rather than generated so the caller can put the same id\n * in the queue entry it writes next ({@link Recipes} mints it before the\n * run); an id this class invented and did not return would have to be dug\n * back out of the bytes.\n */\n async build(opId: string): Promise<Uint8Array> {\n if (this.changes.length === 0) {\n throw new Error(\n 'An operation with no changes is not an operation. Add at least one.',\n );\n }\n\n const envelope = {\n schema: OP_SCHEMA,\n opId,\n // Through the getters, so the envelope and the queue entry cannot drift\n // into disagreeing about the same operation.\n batchId: this.batchId ?? opId,\n targetProject: this.target.project,\n targetDocument: this.target.document,\n baseCommit: this.baseCommit,\n author: this.author,\n ...(this.userId ? { userId: this.userId } : {}),\n title: this.title,\n summary: this.summary,\n };\n\n const [flatbuffers, schema] = await loadDependencies();\n return deflate(\n this.flatbuffer(flatbuffers, schema, opId, JSON.stringify(envelope)),\n );\n }\n\n // ---------------------------------------------------------------------------------------------\n\n /** Placement rides in the attributes, in the same string form the target published. */\n private pack(\n attrs: Record<string, string>,\n placement: Placement,\n ): Record<string, string> {\n const out: Record<string, string> = {};\n for (const [k, v] of Object.entries(attrs ?? {})) {\n // The protocol's namespace is ours, not the data's: nobody sets it through attributes.\n if (k.startsWith(RESERVED)) continue;\n out[k] = String(v);\n }\n if (placement.position) out.Position = placement.position.map(num).join(',');\n if (placement.rotationDeg !== undefined)\n out.Rotation = num(placement.rotationDeg);\n if (placement.source) out[SOURCE_KEY] = placement.source;\n return out;\n }\n\n private requireId(item: string, verb: string): void {\n if (!item || !item.trim()) {\n throw new Error(`A '${verb}' has to name the item it acts on.`);\n }\n }\n\n /**\n * The buffer itself.\n *\n * Laid out exactly as the C# writer lays it out, because the add-in's\n * reader is the one that has to accept both: items first and the container\n * after, ids handed out by one monotonic counter, attributes as\n * `[name, value, type]` JSON triples, and a Meshes table that exists but is\n * empty.\n *\n * Empty rather than absent: the reader asks for it unconditionally, and a\n * model that draws nothing is still a model. Nothing here gets a sample —\n * an item with no triangles must not have one, because a sample's bounding\n * box would then have no size and the reader turns a box into a \"dimension\"\n * and rejects a falsy one.\n */\n private flatbuffer(\n flatbuffers: FlatbuffersModule,\n schema: FragmentsSchema,\n opId: string,\n metadata: string,\n ): Uint8Array {\n const { Attribute, Meshes, Model, SpatialStructure, Transform } = schema;\n const b = new flatbuffers.Builder(1024);\n const n = this.changes.length;\n\n // ids: one counter across everything. Changes take 1..n, the container\n // that groups them takes n+1, and max_local_id is the next free one.\n const itemIds = new Uint32Array(n);\n let next = 1;\n for (let i = 0; i < n; i++) itemIds[i] = next++;\n const containerId = next++;\n\n // ---- Meshes: present, and entirely empty. ----\n const emptyOffsets = (start: (bb: typeof b, k: number) => void) => {\n start(b, 0);\n return b.endVector();\n };\n const shells = Meshes.createShellsVector(b, []);\n const circleExtrusions = Meshes.createCircleExtrusionsVector(b, []);\n const samples = emptyOffsets(Meshes.startSamplesVector);\n const representations = emptyOffsets(Meshes.startRepresentationsVector);\n const materials = emptyOffsets(Meshes.startMaterialsVector);\n const localTransforms = emptyOffsets(Meshes.startLocalTransformsVector);\n const globalTransforms = emptyOffsets(Meshes.startGlobalTransformsVector);\n const meshesItems = Meshes.createMeshesItemsVector(b, []);\n const materialIds = Meshes.createMaterialIdsVector(b, []);\n const representationIds = Meshes.createRepresentationIdsVector(b, []);\n const sampleIds = Meshes.createSampleIdsVector(b, []);\n const localTransformIds = Meshes.createLocalTransformIdsVector(b, []);\n const globalTransformIds = Meshes.createGlobalTransformIdsVector(b, []);\n\n Meshes.startMeshes(b);\n // Written INLINE, and it has to be: a flatbuffers struct is serialised\n // into its parent, not referenced, so building it before startMeshes\n // throws \"struct must be serialized inline\". The model's own coordinate\n // system, identity because an operation places nothing globally.\n Meshes.addCoordinates(b, Transform.createTransform(b, 0, 0, 0, 1, 0, 0, 0, 1, 0));\n Meshes.addGlobalTransforms(b, globalTransforms);\n Meshes.addShells(b, shells);\n Meshes.addRepresentations(b, representations);\n Meshes.addSamples(b, samples);\n Meshes.addLocalTransforms(b, localTransforms);\n Meshes.addMaterials(b, materials);\n Meshes.addCircleExtrusions(b, circleExtrusions);\n Meshes.addMeshesItems(b, meshesItems);\n Meshes.addRepresentationIds(b, representationIds);\n Meshes.addSampleIds(b, sampleIds);\n Meshes.addMaterialIds(b, materialIds);\n Meshes.addLocalTransformIds(b, localTransformIds);\n Meshes.addGlobalTransformIds(b, globalTransformIds);\n const meshes = Meshes.endMeshes(b);\n\n const metadataOffset = b.createString(metadata);\n\n // ---- Attributes: one entry per item, changes then container. ----\n const unique = new Set<string>();\n const attributeOffsets: number[] = [];\n for (const change of this.changes) {\n const triples: number[] = [];\n const props: Record<string, string> = {\n [OP_KEY]: change.op,\n ...change.attrs,\n };\n for (const [name, value] of Object.entries(props)) {\n const json = JSON.stringify([name, value, 'IFCTEXT']);\n unique.add(json);\n triples.push(b.createString(json));\n }\n attributeOffsets.push(\n Attribute.createAttribute(b, Attribute.createDataVector(b, triples)),\n );\n }\n {\n const json = JSON.stringify(['Name', opId, 'IFCLABEL']);\n unique.add(json);\n const data = Attribute.createDataVector(b, [b.createString(json)]);\n attributeOffsets.push(Attribute.createAttribute(b, data));\n }\n const attributes = Model.createAttributesVector(b, attributeOffsets);\n const uniqueAttributes = Model.createUniqueAttributesVector(\n b,\n [...unique].map((s) => b.createString(s)),\n );\n\n // ---- Categories, parallel to local_ids. ----\n const categoryOffsets = this.changes.map(() =>\n b.createString(CATEGORY_CHANGE),\n );\n categoryOffsets.push(b.createString(CATEGORY_OPERATION));\n const categories = Model.createCategoriesVector(b, categoryOffsets);\n\n // ---- Guids: only the changes that name something. An `add` names nothing yet. ----\n const guidOffsets: number[] = [];\n const guidItems: number[] = [];\n this.changes.forEach((change, i) => {\n if (!change.item) return;\n guidOffsets.push(b.createString(change.item));\n guidItems.push(itemIds[i]);\n });\n const guids = Model.createGuidsVector(b, guidOffsets);\n const guidsItems = Model.createGuidsItemsVector(b, guidItems);\n\n const localIds = Model.createLocalIdsVector(b, [...itemIds, containerId]);\n\n // ---- Spatial structure: the operation, with every change hanging off it. ----\n const leaves = this.changes.map((_, i) =>\n SpatialStructure.createSpatialStructure(\n b,\n itemIds[i],\n b.createString(CATEGORY_CHANGE),\n 0,\n ),\n );\n const spatial = SpatialStructure.createSpatialStructure(\n b,\n containerId,\n b.createString(CATEGORY_OPERATION),\n SpatialStructure.createChildrenVector(b, leaves),\n );\n\n const modelGuid = b.createString(opId);\n\n Model.startModel(b);\n Model.addMeshes(b, meshes);\n Model.addMetadata(b, metadataOffset);\n Model.addAttributes(b, attributes);\n Model.addUniqueAttributes(b, uniqueAttributes);\n Model.addLocalIds(b, localIds);\n Model.addCategories(b, categories);\n Model.addGuidsItems(b, guidsItems);\n Model.addGuids(b, guids);\n Model.addGuid(b, modelGuid);\n Model.addSpatialStructure(b, spatial);\n Model.addMaxLocalId(b, next);\n const model = Model.endModel(b);\n\n // WITH the file identifier the schema declares. A buffer finished without\n // it is readable by something that does not check and rejected by\n // everything that does.\n Model.finishModelBuffer(b, model);\n return b.asUint8Array();\n }\n}\n\n/**\n * The optional peers, resolved when an operation is actually built — so apps\n * that never author operations pay nothing and need nothing installed.\n */\nasync function loadDependencies(): Promise<[FlatbuffersModule, FragmentsSchema]> {\n try {\n return await Promise.all([\n import('flatbuffers'),\n import('@thatopen/fragments') as Promise<FragmentsSchema>,\n ]);\n } catch (cause) {\n throw new Error(\n 'OperationBuilder needs the optional peers `flatbuffers` and ' +\n '`@thatopen/fragments` installed — add them to the app that authors ' +\n `operations. (${cause instanceof Error ? cause.message : String(cause)})`,\n );\n }\n}\n\n/**\n * The number as text, round-trippable. `Position` and `Rotation` are strings\n * because every attribute is a string; writing them with the shortest form\n * that reads back identically is what keeps \"9000 mm\" from arriving as\n * 8999.999999999998.\n */\nfunction num(v: number): string {\n return Number.isFinite(v) ? String(v) : '0';\n}\n\n/**\n * zlib, which is what the reader inflates — NOT raw deflate.\n * `CompressionStream(\"deflate\")` is the zlib-wrapped one and `\"deflate-raw\"`\n * is the bare stream, and picking the wrong one produces a file that fails at\n * the first byte with an error about the format rather than about the choice.\n *\n * Native on both sides, so this costs no dependency in the browser and none\n * in a test runner.\n */\nasync function deflate(bytes: Uint8Array): Promise<Uint8Array> {\n const stream = new Blob([bytes as BlobPart])\n .stream()\n .pipeThrough(new CompressionStream('deflate'));\n return new Uint8Array(await new Response(stream).arrayBuffer());\n}\n","import { Readable } from 'stream';\nimport { ObjectId } from './base';\n\nexport type FileType = string | Uint8Array | Buffer | Readable;\n\nexport type HiddenFileEntity = {\n fileId: string;\n _id: ObjectId;\n parentItemId: ObjectId;\n /** Label set on upload; absent on untagged files. */\n tag?: string;\n};\n\nexport type CreateHiddenItemResult = {\n hiddenFileId: string;\n};\n\nexport type CreateHiddenItemsBatchResult = {\n results: { originalName: string; hiddenFileId: string }[];\n};\n\nexport type MetadataValue = string | number | boolean | null;\n\nexport type Metadata = Record<string, MetadataValue>;\n\nexport const METADATA_LIMITS = {\n MAX_FIELDS: 200,\n MAX_KEY_LENGTH: 50,\n MAX_VALUE_LENGTH: 50,\n} as const;\n","/* eslint-disable @typescript-eslint/no-explicit-any, @typescript-eslint/no-unused-vars */\n/**\n * Built-in component types and runtime stubs.\n * Auto-generated by platform_builtin-components/scripts/distribute-types.mjs\n */\n\nimport type * as OBC from '@thatopen/components';\nimport type * as THREE from 'three';\nimport type { EngineServicesClient, Item, ItemFolder, ItemVersion, PlatformClient } from '../';\n\nexport interface CDEContext {\n client: PlatformClient;\n projectId: string;\n}\nexport interface CDEUserPermissions {\n canRead: boolean;\n canCreate: boolean;\n canUpdate: boolean;\n canDelete: boolean;\n canManage: boolean;\n}\nexport type CDEMetadataValue = string | number | boolean | null;\nexport interface CDENamingSegment {\n key: string;\n config?: {\n transform: (value: CDEMetadataValue) => string;\n };\n}\nexport interface CDENamingSchema {\n separator: string;\n segments: CDENamingSegment[];\n}\nexport interface CDEFile extends Omit<Item, 'creatingUser'> {\n createdBy: string;\n metadata: Record<string, CDEMetadataValue>;\n versions?: ItemVersion[];\n /** Tag of the file's current version (set by CDEManager from the loaded version). */\n versionTag?: string;\n}\nexport interface CDEMetadataField {\n type: \"string\" | \"number\" | \"boolean\" | \"list\";\n description?: string;\n required?: boolean;\n label: string;\n icon?: string;\n options?: {\n value: string | number | boolean;\n label: string;\n }[];\n}\nexport type CDEMetadataSchema = Record<string, CDEMetadataField>;\nexport interface CDEFileActivity {\n user: string;\n action: string;\n timestamp: string;\n}\nexport interface CDEFileHistoryEntry {\n fileId: string;\n activity: CDEFileActivity[];\n}\nexport interface CDEMetadataView {\n id: string;\n name: string;\n fields: string[];\n}\nexport type CDEPendingMetadata = Record<string, CDEMetadataValue>;\nexport type CDEPendingMetadataSchemaEdits = Record<string, CDEMetadataField | null>;\nexport type FolderPendingChange = {\n kind: \"create\";\n tempId: string;\n name: string;\n parentId: string | null;\n} | {\n kind: \"rename\";\n folderId: string;\n name: string;\n} | {\n kind: \"archive\";\n folderId: string;\n};\nexport type FolderPendingChanges = FolderPendingChange[];\nexport type CDEViewFileStatus = \"loading\" | \"ready\" | \"failed\" | \"cancelled\";\nexport type CDEMachineState = {\n kind: \"idle\";\n} | {\n kind: \"loading\";\n} | {\n kind: \"preparing\";\n files: CDEFile[];\n} | {\n kind: \"selected\";\n files: CDEFile[];\n} | {\n kind: \"viewing\";\n files: CDEFile[];\n fileStatus: Record<string, CDEViewFileStatus>;\n selectedFiles?: CDEFile[];\n} | {\n kind: \"editing\";\n files: CDEFile[];\n pendingMetadata: CDEPendingMetadata;\n} | {\n kind: \"saving\";\n files: CDEFile[];\n pendingMetadata: CDEPendingMetadata;\n} | {\n kind: \"deleting\";\n files: CDEFile[];\n} | {\n kind: \"configuringMetadataSchema\";\n pendingEdits: CDEPendingMetadataSchemaEdits;\n} | {\n kind: \"savingMetadataSchema\";\n pendingEdits: CDEPendingMetadataSchemaEdits;\n} | {\n kind: \"configuringMetadataViews\";\n pendingViews: CDEMetadataView[];\n} | {\n kind: \"savingMetadataViews\";\n pendingViews: CDEMetadataView[];\n} | {\n kind: \"dragging\";\n files: CDEFile[];\n sourceFolderId: string | null;\n previousState: CDEMachineState;\n} | {\n kind: \"movingFiles\";\n files: CDEFile[];\n targetFolderId: string;\n} | {\n kind: \"draggingFolder\";\n folderId: string;\n parentFolderId: string | null;\n previousState: CDEMachineState;\n} | {\n kind: \"movingFolder\";\n folderId: string;\n targetFolderId: string | null;\n} | {\n kind: \"editingFolders\";\n pendingChanges: FolderPendingChanges;\n} | {\n kind: \"savingFolderChanges\";\n pendingChanges: FolderPendingChanges;\n} | {\n kind: \"editingFiles\";\n pendingEdits: Record<string, Record<string, CDEMetadataValue>>;\n pendingArchives: string[];\n pendingRenames: Record<string, string>;\n previousState: {\n kind: \"idle\";\n } | {\n kind: \"selected\";\n files: CDEFile[];\n };\n} | {\n kind: \"savingFiles\";\n pendingEdits: Record<string, Record<string, CDEMetadataValue>>;\n pendingArchives: string[];\n pendingRenames: Record<string, string>;\n previousState: {\n kind: \"idle\";\n } | {\n kind: \"selected\";\n files: CDEFile[];\n };\n} | {\n kind: \"error\";\n reason: string;\n previous: CDEMachineState;\n};\nexport type CDEMachineEvent = {\n type: \"LOAD\";\n} | {\n type: \"UPLOAD\";\n} | {\n type: \"DOWNLOAD\";\n} | {\n type: \"SELECT\";\n files: CDEFile[];\n} | {\n type: \"DESELECT\";\n} | {\n type: \"VIEW\";\n} | {\n type: \"ADD_TO_VIEW\";\n file: CDEFile;\n} | {\n type: \"REMOVE_FROM_VIEW\";\n fileId: string;\n} | {\n type: \"CLOSE_VIEW\";\n} | {\n type: \"SET_VIEW_FILE_STATUS\";\n fileId: string;\n status: CDEViewFileStatus;\n} | {\n type: \"START_EDIT\";\n} | {\n type: \"UPDATE_METADATA\";\n key: string;\n value: CDEMetadataValue;\n} | {\n type: \"SAVE\";\n} | {\n type: \"CANCEL_EDIT\";\n} | {\n type: \"ARCHIVE_FILE\";\n} | {\n type: \"START_CONFIGURE_METADATA_SCHEMA\";\n} | {\n type: \"ADD_METADATA_FIELD\";\n} | {\n type: \"UPDATE_METADATA_FIELD\";\n key: string;\n value: CDEMetadataField;\n} | {\n type: \"DELETE_METADATA_FIELD\";\n key: string;\n} | {\n type: \"RESTORE_METADATA_FIELD\";\n key: string;\n} | {\n type: \"SAVE_METADATA_SCHEMA\";\n} | {\n type: \"CANCEL_CONFIGURE_METADATA_SCHEMA\";\n} | {\n type: \"START_DRAG\";\n files: CDEFile[];\n sourceFolderId: string | null;\n} | {\n type: \"END_DRAG\";\n} | {\n type: \"DROP_FILES\";\n targetFolderId: string | null;\n} | {\n type: \"START_FOLDER_DRAG\";\n folderId: string;\n parentFolderId: string | null;\n} | {\n type: \"END_FOLDER_DRAG\";\n} | {\n type: \"DROP_FOLDER\";\n targetFolderId: string | null;\n} | {\n type: \"START_EDIT_FILES\";\n} | {\n type: \"UPDATE_FILE_METADATA\";\n fileId: string;\n key: string;\n value: CDEMetadataValue;\n} | {\n type: \"REVERT_FILE_METADATA\";\n fileId: string;\n} | {\n type: \"ARCHIVE_FILE_EDIT\";\n fileId: string;\n} | {\n type: \"UNARCHIVE_FILE_EDIT\";\n fileId: string;\n} | {\n type: \"RENAME_FILE\";\n fileId: string;\n name: string;\n} | {\n type: \"RENAME_FILE_IMMEDIATE\";\n fileId: string;\n name: string;\n} | {\n type: \"SAVE_FILE_EDITS\";\n} | {\n type: \"CANCEL_EDIT_FILES\";\n} | {\n type: \"START_EDIT_FOLDERS\";\n} | {\n type: \"ADD_FOLDER\";\n tempId: string;\n name: string;\n parentId: string | null;\n} | {\n type: \"RENAME_FOLDER\";\n folderId: string;\n name: string;\n} | {\n type: \"ARCHIVE_FOLDER\";\n folderId: string;\n} | {\n type: \"SAVE_FOLDER_CHANGES\";\n} | {\n type: \"CANCEL_FOLDER_CHANGES\";\n} | {\n type: \"RESET_FOLDER\";\n folderId: string;\n} | {\n type: \"START_CONFIGURE_METADATA_VIEWS\";\n} | {\n type: \"ADD_METADATA_VIEW\";\n} | {\n type: \"UPDATE_METADATA_VIEW\";\n id: string;\n view: CDEMetadataView;\n} | {\n type: \"DELETE_METADATA_VIEW\";\n id: string;\n} | {\n type: \"SAVE_METADATA_VIEWS\";\n} | {\n type: \"CANCEL_CONFIGURE_METADATA_VIEWS\";\n} | {\n type: \"SET_ACTIVE_METADATA_VIEW\";\n id: string | null;\n} | {\n type: \"SET_GROUPS_VIEW_MODE\";\n mode: \"groups\" | \"metadata\";\n} | {\n type: \"FAIL\";\n reason: string;\n} | {\n type: \"DISMISS\";\n};\n\ndeclare class _CDEManager extends OBC.Component implements OBC.Transitionable<CDEMachineState, CDEMachineEvent> {\n static readonly uuid: \"a3f82c1d-5b74-4e9a-bc30-d7e12f894a61\";\n readonly onFilesChanged: OBC.Event<CDEFile[]>;\n readonly onFoldersChanged: OBC.Event<ItemFolder[]>;\n readonly onPermissionsChanged: OBC.Event<CDEUserPermissions>;\n readonly onSelectedGroupChanged: OBC.Event<string | null>;\n readonly onMachineStateChanged: OBC.Event<CDEMachineState>;\n readonly onMetadataViewsChanged: OBC.Event<CDEMetadataView[]>;\n readonly onGroupsViewModeChanged: OBC.Event<\"groups\" | \"metadata\">;\n readonly onMetadataGroupChanged: OBC.Event<Record<string, string> | null>;\n readonly onDownloadReady: OBC.Event<{\n blob: Blob;\n filename: string;\n }>;\n readonly onUploadCompleted: OBC.Event<{\n created: CDEFile[];\n versioned: CDEFile[];\n }>;\n readonly onFolderChangesCompleted: OBC.Event<{\n created: number;\n renamed: number;\n archived: number;\n }>;\n readonly onFilesMovedCompleted: OBC.Event<{\n files: CDEFile[];\n targetFolderName: string | null;\n }>;\n readonly onRenameCompleted: OBC.Event<{\n success: boolean;\n error?: string;\n }>;\n readonly onFolderMovedCompleted: OBC.Event<{\n folderName: string;\n targetFolderName: string | null;\n }>;\n readonly onShowArchivedChanged: OBC.Event<boolean>;\n readonly onRestoreCompleted: OBC.Event<{\n files?: CDEFile[];\n folder?: ItemFolder;\n }>;\n readonly onUploadStarted: OBC.Event<{\n count: number;\n }>;\n readonly onIfcConversionStarted: OBC.Event<{\n file: CDEFile;\n }>;\n readonly onIfcConversionProgress: OBC.Event<{\n file: CDEFile;\n progress: number;\n }>;\n readonly onIfcConversionCompleted: OBC.Event<{\n file: CDEFile;\n success: boolean;\n error?: string;\n }>;\n /** Fires when `_derivedFileIds` finishes a (re)sync — consumers that filter\n * or resolve by source↔derived link (e.g. `top-files-panel` hiding an\n * already-linked `.frag` row) should reload on this, since it can complete\n * after `onFilesChanged` already fired with the (still unsynced) list. */\n readonly onDerivedFileIdsChanged: OBC.Event<Record<string, string>>;\n readonly conversionProgress: Map<string, number>;\n enabled: boolean;\n projectName: string;\n missingMetadataPlaceholder: string;\n availableColumns: Set<string>;\n visibleColumns: Set<string>;\n ctx?: CDEContext;\n private _machineState;\n private _activeUploads;\n private _showArchived;\n private _preArchivedViewMode;\n private _archivedFiles;\n private _archivedFolders;\n private _archivedLoaded;\n viewerGroups: {\n extensions: string[];\n multiple?: boolean;\n }[];\n get viewableExtensions(): Set<string>;\n private _files;\n /** ifcFileId → its linked derivedFileId (FRAG today; other source formats\n * once they get a converter too), read from each IFC's own version\n * metadata. Kept as an in-memory cache — synced by `_syncDerivedFileIds`\n * whenever `_files` is (re)set, or right after a conversion succeeds —\n * rather than fetched live per call, so `resolveViewFile` can stay a plain\n * synchronous lookup (same contract as before, no ripple into\n * `sendMachineEvent`'s callers). */\n private _derivedFileIds;\n private _folders;\n private _fileHistory;\n private _metadataSchema;\n private _metadataViews;\n private _activeMetadataViewId;\n private _groupsViewMode;\n private _selectedGroup;\n private _selectedMetadataGroup;\n private _namingSchema;\n cacheMaxBytes: number;\n cacheExtensions: Set<string>;\n private _fileCache;\n private _fileCacheBytes;\n private _dedup;\n private _cacheKey;\n private _isCacheable;\n private _addToCache;\n downloadFile(file: CDEFile): Promise<ArrayBuffer>;\n private _permissions;\n private _projectDataFolderId;\n private _appFolderIds;\n /** In-flight folder ensures. Two concurrent first calls (user config and\n * app config load in parallel) used to each miss the cache and create a\n * second folder of the same name; the promise is the lock. */\n private _projectDataFolderPromise;\n private _appFolderPromises;\n private _excludedFolderIds;\n private _projectMembers;\n get projectMembers(): {\n fullName: string;\n email: string;\n role: string;\n }[];\n get userPermissions(): CDEUserPermissions;\n query: string | null;\n get machineState(): CDEMachineState;\n get files(): CDEFile[];\n set files(value: CDEFile[]);\n /** ifcFileId → derivedFileId — see `_derivedFileIds`. */\n get derivedFileIds(): Record<string, string>;\n get folders(): ItemFolder[];\n set folders(value: ItemFolder[]);\n get showArchived(): boolean;\n set showArchived(value: boolean);\n get fileHistory(): CDEFileHistoryEntry[];\n set fileHistory(value: CDEFileHistoryEntry[]);\n get metadataSchema(): CDEMetadataSchema;\n set metadataSchema(value: CDEMetadataSchema);\n get selectedGroup(): string | null;\n set selectedGroup(value: string | null);\n get metadataViews(): CDEMetadataView[];\n get activeMetadataViewId(): string | null;\n get activeMetadataView(): CDEMetadataView | null;\n get groupsViewMode(): \"groups\" | \"metadata\";\n get selectedMetadataGroup(): Record<string, string> | null;\n set selectedMetadataGroup(value: Record<string, string> | null);\n get visibleFiles(): CDEFile[];\n get namingSchema(): CDENamingSchema | null;\n constructor(components: OBC.Components);\n hasViewer(extension: string): boolean;\n private _groupOf;\n private _sameGroup;\n canView(files: CDEFile[]): boolean;\n canAddToView(files: CDEFile[]): boolean;\n setNamingSchema(schema: CDENamingSchema): void;\n buildFileName(file: CDEFile): string;\n getSelectedFiles(): CDEFile[];\n getActivity(fileId: string): CDEFileActivity[];\n updateFilesMetadata(fileIds: string[], updates: Record<string, string>): Promise<void>;\n /** The context this component cannot work without. Reading or writing\n * project data with no context used to resolve with null / the empty\n * string while persisting NOTHING - a call indistinguishable from\n * success, which cost an integrator days (reported 2026-10-01). A\n * missing context is a setup problem and must say so. */\n private _requireCtx;\n readProjectData(app: string, filename: string): Promise<any>;\n writeProjectData(app: string, filename: string, data: unknown): Promise<string>;\n /** Of several same-named folders, always the oldest. Duplicates exist in\n * real projects (the backend had no unique index and this class had no\n * lock), and `loadFolders` used to pick the LAST root match while the\n * ensure path picked the FIRST: reads and writes could land in different\n * folders of the same name. ObjectIds sort by creation time as strings. */\n private static _oldest;\n private _ensureProjectDataFolder;\n private _ensureAppFolder;\n private _loadPermissions;\n loadFolders(): Promise<void>;\n createFolder(name: string, parentId?: string): Promise<ItemFolder>;\n getUserId(): Promise<string | undefined>;\n loadUserConfig(): Promise<{\n visibleColumns?: string[];\n metadataViews?: CDEMetadataView[];\n hideDerivedFiles?: boolean;\n } | null>;\n saveUserConfig(config: {\n visibleColumns?: string[];\n metadataViews?: CDEMetadataView[];\n hideDerivedFiles?: boolean;\n }): Promise<string | undefined>;\n loadMetadataSchema(): Promise<void>;\n initMetadataViews(views: CDEMetadataView[], activeId: string | null): void;\n loadArchivedItems(): Promise<void>;\n restoreFiles(files: CDEFile[]): Promise<void>;\n restoreFolder(folderId: string): Promise<void>;\n detectConflicts(files: File[]): {\n file: File;\n existing: CDEFile;\n }[];\n checkMoveConflicts(files: CDEFile[], targetFolderId: string | null): {\n file: CDEFile;\n existing: CDEFile;\n }[];\n /** Which file to actually load when the user views `file` — its linked FRAG\n * if it has one, else the IFC itself. Reads `_derivedFileIds` (the IFC's\n * own version metadata, kept in sync — see `_syncDerivedFileIds`), NOT a\n * name+folder match anymore. Stays synchronous: `_derivedFileIds` is a\n * pre-synced in-memory cache, so this is a plain lookup, keeping the\n * contract every existing caller (`sendMachineEvent`'s `VIEW` case,\n * `top-files-panel`'s \"add to view\" actions) already relies on. */\n resolveViewFile(file: CDEFile): CDEFile;\n /** Populates `_derivedFileIds` from every IFC's own version metadata — the\n * source of truth for the IFC↔FRAG link (same mechanism as `models-list`'s\n * `_syncDerivedFileIds`). Reads the unified `derivedFileId` key, falling\n * back to the legacy `fragmentsFileId` key that `IfcFragmenter` still\n * stamps until it's updated (see issue #3, Task 3). Called whenever\n * `_files` is (re)set and right after a conversion succeeds — never\n * cached indefinitely, so a reconversion or manual metadata edit is picked\n * up on the next sync instead of going stale. */\n private _syncDerivedFileIds;\n private _saveConversionIndex;\n private _loadConversionIndex;\n private _resumePendingConversions;\n /** Cached id of the IfcFragmenter component, resolved by name for this session. */\n private _ifcFragmenterId?;\n /**\n * Resolves the platform IFC→FRAG cloud component's id by its stable name\n * (`IfcFragmenter`) within the current project, so it works across dev/prod\n * without a hardcoded id. Cached for the session. Returns `undefined` if no\n * such component is available in the project.\n */\n private _resolveIfcFragmenterId;\n private _triggerIfcConversions;\n uploadFiles(files: File[], folderId?: string | null, options?: {\n forceNew?: boolean;\n }): Promise<void>;\n sendMachineEvent(event: CDEMachineEvent): void;\n private _transition;\n private _getAllArchivedIds;\n private _collectTempDescendants;\n private _saveFolderChanges;\n private _moveFolder;\n moveFiles(files: CDEFile[], targetFolderId: string | null): Promise<void>;\n private _moveFiles;\n private _resolveFullName;\n private _prepareDownload;\n private _saveMetadataSchema;\n private _resolveKeys;\n private _saveFileMetadata;\n private _renameFileImmediate;\n private _saveFileEdits;\n private _applyMetadataEdits;\n private _applyMetadataSchemaEdits;\n private _saveMetadataViews;\n private _archiveFiles;\n}\n\nexport type CDEManager = InstanceType<typeof _CDEManager>;\nexport const CDEManager = { uuid: 'a3f82c1d-5b74-4e9a-bc30-d7e12f894a61' } as typeof _CDEManager & { uuid: 'a3f82c1d-5b74-4e9a-bc30-d7e12f894a61' };\n\nexport type ClashStatus = \"new\" | \"active\" | \"resolved\" | \"acknowledged\";\nexport type ClashType = \"hard\" | \"clearance\";\nexport interface ClashElement {\n guid: string;\n name: string;\n localId: number;\n modelId: string;\n}\nexport interface ClashQueryFilter {\n categories?: string[];\n attributes?: {\n aggregation?: 'exclusive' | 'inclusive';\n queries: Array<{\n name: string;\n value?: string | string[] | number | boolean;\n type?: string;\n negate?: boolean;\n }>;\n };\n relation?: {\n name: string;\n query?: ClashQueryFilter;\n };\n}\nexport interface ClashQuery {\n id: string;\n name: string;\n modelFileIds: string[];\n /** Filter conditions. Omit or leave empty to match all elements with geometry. */\n query?: ClashQueryFilter;\n}\nexport interface ClashMatrix {\n id: string;\n name: string;\n /** Ordered list of query IDs — index order = priority (0 = most constrained). */\n queryIds: string[];\n /** Active cell job IDs (subset of upper-triangle pairs). */\n jobIds: string[];\n /** Active upper-triangle pair keys in the form \"queryAId:queryBId\". */\n activePairs: string[];\n /** Clash type applied to all jobs generated by this matrix. Defaults to 'hard'. */\n jobType?: ClashType;\n /** Clearance tolerance in metres. Only used when jobType is 'clearance'. */\n tolerance?: number;\n}\nexport interface ClashJob {\n id: string;\n name: string;\n type: ClashType;\n queryAId: string;\n queryBId: string;\n matrixId?: string;\n /** Clearance tolerance in metres. Only present when type is 'clearance'. */\n tolerance?: number;\n}\nexport interface ClashRun {\n id: string;\n jobId: string;\n date: string;\n clashCount: number;\n}\ninterface ClashBase {\n /** Deterministic FNV-1a hash of the normalized pair (elementA.guid, elementB.guid). Stable across runs. */\n id: string;\n jobId: string;\n firstSeenRunId: string;\n lastSeenRunId: string;\n elementA: ClashElement;\n elementB: ClashElement;\n point: [number, number, number];\n status: ClashStatus;\n comments?: string;\n}\nexport interface HardClash extends ClashBase {\n type: \"hard\";\n volume?: number;\n}\nexport interface ClearanceClash extends ClashBase {\n type: \"clearance\";\n distance: number;\n}\nexport type Clash = HardClash | ClearanceClash;\nexport interface MarkerGroup {\n id?: string;\n point: [number, number, number];\n count: number;\n status?: ClashStatus;\n}\n\n/** `clashes.frag`'s path relative to `__project_data/`, for consumers that\n * persist it via `projectStorageContext` instead of talking to `client`\n * directly (see `buildClashBuffer`). */\nexport declare const CLASH_DATA_PATH = \"collider/clashes.frag\";\nexport interface ExecutionEntry {\n jobId: string;\n executionId: string;\n startedAt: string;\n}\n/** `cachedFileId`, when given, skips folder/file resolution (3 of the 4\n * network round-trips this normally takes) — the file's ID never changes\n * once created, so callers that already know it (see `ClashesManager`'s\n * `_clashFragFileId`) should always pass it. */\nexport declare function ensureClashFragFileId(client: PlatformClient, projectId: string, cachedFileId?: string): Promise<string>;\nexport declare function getExecutions(client: PlatformClient, projectId: string | undefined): Promise<ExecutionEntry[]>;\nexport interface ClashData {\n jobs: ClashJob[];\n runs: ClashRun[];\n clashes: Clash[];\n queries: ClashQuery[];\n matrices: ClashMatrix[];\n /** Resolved once here — callers should cache and pass back into\n * `loadClashData`/`buildClashBuffer` as `cachedFileId` to skip\n * re-resolving it (see `ensureClashFragFileId`). */\n fileId: string;\n}\nexport declare function loadClashData(client: PlatformClient, projectId: string, cachedFileId?: string): Promise<ClashData>;\n/**\n * Diffs `data` against the persisted `clashes.frag` and builds the updated\n * buffer, WITHOUT uploading it — callers decide how/where to persist the\n * result (direct `client.updateFile`, via `projectStorageContext`, etc).\n * Still reads the current file via `client` to diff against (job/id\n * reconciliation needs the previous state), same as `saveClashData` always did.\n */\nexport declare function buildClashBuffer(client: PlatformClient, projectId: string, data: {\n queries: ClashQuery[];\n matrices: ClashMatrix[];\n jobs: ClashJob[];\n clashes: Clash[];\n}, onJobsReconciled: (toAdd: ClashJob[], toRemove: Set<string>) => void, cachedFileId?: string): Promise<{\n blob: Blob;\n fileId: string;\n}>;\n/** Default persistence path: builds the buffer and uploads it straight to\n * `client`. Kept as the manager's out-of-the-box behavior for any consumer\n * that never overrides `ClashesManager.save` (e.g. doesn't route through\n * `projectStorageContext`). */\nexport declare function saveClashData(client: PlatformClient, projectId: string, data: {\n queries: ClashQuery[];\n matrices: ClashMatrix[];\n jobs: ClashJob[];\n clashes: Clash[];\n}, onJobsReconciled: (toAdd: ClashJob[], toRemove: Set<string>) => void): Promise<void>;\n\n\ndeclare class _ClashesManager extends OBC.Component {\n static readonly uuid: \"2c9f4e8d-3a1b-4c5e-9d7f-0a2b6c8e1d3f\";\n enabled: boolean;\n readonly onQueriesChanged: OBC.Event<ClashQuery[]>;\n readonly onMatricesChanged: OBC.Event<ClashMatrix[]>;\n readonly onJobsChanged: OBC.Event<ClashJob[]>;\n readonly onRunsChanged: OBC.Event<ClashRun[]>;\n readonly onClashesChanged: OBC.Event<Clash[]>;\n readonly onClashStatusChanged: OBC.Event<Clash[]>;\n /** Dispara cuando empieza el debounce de guardado (pendiente de persistir). */\n readonly onSaveStart: OBC.Event<void>;\n /** Dispara al terminar el guardado. true = éxito, false = error. */\n readonly onSaveComplete: OBC.Event<boolean>;\n world?: OBC.World;\n /** Suprimir auto-save durante carga de datos (usar loadingData = true antes, false después). */\n loadingData: boolean;\n /** Registrar desde la app host para recargar datos desde el storage al terminar una ejecución. */\n reload?: () => Promise<void>;\n /** Registrar desde la app host para consultar qué jobIds tienen ejecución activa en storage. */\n checkExecutions?: () => Promise<Set<string>>;\n /** Registrar desde la app host para persistir queries y matrices al storage del proyecto. */\n save?: () => Promise<void>;\n /** Jobs con una ejecución cloud activa. Poblado por la app host al arrancar. */\n readonly runningJobIds: Set<string>;\n /** Mapa jobId → executionId para reconectar al WebSocket. Poblado por la app host al arrancar. */\n readonly activeExecutions: Map<string, string>;\n readonly onRunningJobsChanged: OBC.Event<Set<string>>;\n readonly onRunProgress: OBC.Event<{\n message: string;\n progress: number;\n }>;\n readonly onRunComplete: OBC.Event<{\n runId: string;\n clashCount: number;\n }>;\n readonly onRunError: OBC.Event<{\n code?: string;\n message: string;\n }>;\n readonly onReloadingChanged: OBC.Event<boolean>;\n isReloading: boolean;\n /** True once init(client) has been called — safe to call run(). */\n get ready(): boolean;\n private _client?;\n private _projectId?;\n /** `clashes.frag`'s file ID, resolved once by `init()`/`reload()`'s\n * `loadClashData` call. Never changes once the file exists — passing it\n * into `buildClashBuffer` skips 3 of its 4 network round-trips. */\n private _clashFragFileId?;\n private _reconnectingJobIds;\n private _queries;\n private _matrices;\n private _saveTimer?;\n private _savePromise?;\n private _jobs;\n private _runs;\n private _clashes;\n private _markers;\n private static _geo;\n get queries(): ClashQuery[];\n set queries(value: ClashQuery[]);\n get matrices(): ClashMatrix[];\n set matrices(value: ClashMatrix[]);\n private _scheduleSave;\n /** Chains onto any save already in flight instead of firing a second,\n * concurrent `_doSave()` — two overlapping calls would race on\n * `buildClashBuffer`'s read-diff-reconcile cycle (real network I/O;\n * `onJobsReconciled` mutating `this.jobs` from two stale reads at once)\n * and on the upload itself. It also keeps `flush()` correct: it just\n * awaits `_savePromise`, so if that got overwritten by a newer, unrelated\n * save instead of chained, flush() could resolve while an earlier save\n * was still genuinely in flight. */\n private _queueSave;\n private _doSave;\n /** Cancela el debounce pendiente y ejecuta el save inmediatamente. Espera a que complete. */\n flush(): Promise<void>;\n /**\n * Builds the current `clashes.frag` buffer (diffed/reconciled against what's\n * persisted) WITHOUT uploading it. For consumers (e.g. `clashes-panel`) that\n * override `save` to persist via `projectStorageContext` instead of the\n * default direct-`client` path.\n */\n buildClashBuffer(): Promise<Blob>;\n get jobs(): ClashJob[];\n set jobs(value: ClashJob[]);\n get runs(): ClashRun[];\n set runs(value: ClashRun[]);\n get clashes(): Clash[];\n set clashes(value: Clash[]);\n queryById(id: string): ClashQuery | undefined;\n private _clashStylesRegistered;\n /** Green — elementA's highlight color. Public so consumers (e.g. \"create\n * topic from clash\") can build a matching BCF viewpoint `componentColors`\n * entry without duplicating the hex value. */\n readonly STYLE_A = \"#22c55e\";\n /** Red — elementB's highlight color. Same reasoning as `STYLE_A`. */\n readonly STYLE_B = \"#ef4444\";\n private _clashStyle;\n highlightAllClashes(clashes: Clash[]): void;\n ghostClashes(clashes: Clash[]): Promise<void>;\n ghostClash(clash: Clash): Promise<void>;\n clearGhostClash(): Promise<void>;\n highlightClash(clash: Clash): void;\n clearClashHighlight(): void;\n showMarkers(groups: MarkerGroup[]): void;\n hideMarkers(): void;\n toViewerPoint(point: [number, number, number]): THREE.Vector3;\n private _toViewer;\n private _renderMarkers;\n private _clearMarkers;\n cluster(clashes: Clash[], threshold: number): Clash[][];\n private _setHighlighterEnabled;\n private _isolatedMaterials;\n runsForJob(jobId: string): ClashRun[];\n clashesForRun(runId: string): Clash[];\n updateClash(id: string, changes: {\n status?: ClashStatus;\n comments?: string;\n }): void;\n /**\n * Initializes the manager from cloud storage: loads clash data, wires save/reload,\n * reads in-flight executions, and resolves the viewer world (non-blocking).\n * Consumer apps call this once instead of wiring all the pieces manually.\n */\n init(client: PlatformClient): Promise<void>;\n /** Launches clash detection in a Web Worker. Fires onRunProgress/onRunComplete/onRunError. */\n run(jobId: string): void;\n private _handleWorkerComplete;\n /** Reconnects to an in-flight execution when the user opens a job that was running before page load. */\n reconnectIfRunning(jobId: string): void;\n private _listenToExecution;\n private _firstWorld;\n}\n\nexport type ClashesManager = InstanceType<typeof _ClashesManager>;\nexport const ClashesManager = { uuid: '2c9f4e8d-3a1b-4c5e-9d7f-0a2b6c8e1d3f' } as typeof _ClashesManager & { uuid: '2c9f4e8d-3a1b-4c5e-9d7f-0a2b6c8e1d3f' };\n\n/**\n * Which action buttons to expose per file row. All default to `true`.\n */\nexport interface FileListActions {\n download?: boolean;\n rename?: boolean;\n delete?: boolean;\n}\n/**\n * Config passed to {@link FileList.create}.\n */\nexport interface FileListConfig {\n /** Services client used to list and mutate files. */\n client: EngineServicesClient;\n /** Optional folder ID to scope the list. If omitted, lists root files. */\n folderId?: string;\n /** Which action buttons to show per row. Defaults to all enabled. */\n actions?: FileListActions;\n /** Called when a file row is clicked (not an action button). */\n onFileClick?: (file: Item) => void;\n}\n/**\n * The result returned by {@link FileList.create}.\n */\nexport interface FileListInstance {\n /** The DOM element to mount somewhere in your layout. */\n element: HTMLElement;\n /** Reloads the list from the services client. */\n refresh: () => Promise<void>;\n /** Changes the folder scope and reloads. Pass `undefined` for the root. */\n setFolder: (folderId?: string) => Promise<void>;\n /** Removes the element and forgets the instance. */\n dispose: () => void;\n}\n\n/**\n * Built-in component that renders a file list backed by the services client,\n * with built-in download / rename / delete actions.\n *\n * The backing data comes from {@link EngineServicesClient.listFiles}, so the\n * list stays in sync with the storage service. Each call to {@link create}\n * returns an independent instance with its own DOM element.\n *\n * @example\n * ```ts\n * const fileList = components.get(FileList);\n * const { element, refresh } = fileList.create({\n * client: app.client,\n * folderId: someFolderId,\n * });\n * container.appendChild(element);\n * ```\n */\ndeclare class _FileList extends OBC.Component {\n static readonly uuid: \"b0b5e2a2-0b3a-4a6b-8b1c-0b1c4a6b8b1c\";\n enabled: boolean;\n readonly name = \"FileList\";\n private _instances;\n /**\n * Creates a new file-list instance. Returns the DOM element to mount plus a\n * `refresh` handle to reload the list, a `setFolder` to change scope, and a\n * `dispose` to remove it.\n */\n create(config: FileListConfig): FileListInstance;\n /**\n * Removes every instance this manager has created.\n */\n dispose(): void;\n}\n\n/**\n * Built-in component that renders a file list backed by the services client,\n * with built-in download / rename / delete actions.\n *\n * The backing data comes from {@link EngineServicesClient.listFiles}, so the\n * list stays in sync with the storage service. Each call to {@link create}\n * returns an independent instance with its own DOM element.\n *\n * @example\n * ```ts\n * const fileList = components.get(FileList);\n * const { element, refresh } = fileList.create({\n * client: app.client,\n * folderId: someFolderId,\n * });\n * container.appendChild(element);\n * ```\n */\nexport type FileList = InstanceType<typeof _FileList>;\n/**\n * Built-in component that renders a file list backed by the services client,\n * with built-in download / rename / delete actions.\n *\n * The backing data comes from {@link EngineServicesClient.listFiles}, so the\n * list stays in sync with the storage service. Each call to {@link create}\n * returns an independent instance with its own DOM element.\n *\n * @example\n * ```ts\n * const fileList = components.get(FileList);\n * const { element, refresh } = fileList.create({\n * client: app.client,\n * folderId: someFolderId,\n * });\n * container.appendChild(element);\n * ```\n */\nexport const FileList = { uuid: 'b0b5e2a2-0b3a-4a6b-8b1c-0b1c4a6b8b1c' } as typeof _FileList & { uuid: 'b0b5e2a2-0b3a-4a6b-8b1c-0b1c4a6b8b1c' };\n\n/** A point-layer vertex whose Z gives the surface height at that place. */\nexport interface HeightNode {\n lon: number;\n lat: number;\n z: number;\n}\n/**\n * One orthometric height per vertex, in the same nesting as the geometry's\n * coordinates: `number` for a Point, `number[]` for a LineString/MultiPoint/\n * ring, `number[][]` for a MultiLineString/Polygon, and so on.\n */\nexport type HeightTree = number | HeightTree[];\n/**\n * Which rule gave a line end its height (see `resolveLineEnds`): 1 = its own\n * property, 2 = node surface height minus depth, 3 = copied from the other end\n * (pipe drawn level), 4 = node surface height (no depth available).\n */\nexport type EndRule = 1 | 2 | 3 | 4;\nexport interface FeatureHeights {\n /**\n * \"placed\": `heights` holds the per-vertex heights. \"flat\": draw this\n * feature with the legacy flat behaviour. \"skipped\": it cannot be placed\n * and must not be drawn.\n */\n status: \"placed\" | \"flat\" | \"skipped\";\n heights?: HeightTree;\n /** \"attributes\" lines only — the rule that resolved each end. */\n startRule?: EndRule;\n endRule?: EndRule;\n}\nexport interface LayerHeights {\n /** True when the whole layer must be drawn with the legacy flat behaviour. */\n fallback: boolean;\n /** One entry per input feature, same order. Empty when `fallback`. */\n features: FeatureHeights[];\n /** Number of \"skipped\" features. */\n skipped: number;\n /** How many line ends each rule resolved (\"attributes\" layers). */\n ruleCounts: Record<EndRule, number>;\n}\n/** A value read from a property or Z is MISSING when it is not a finite number or is exactly 0. */\nexport declare function isMissingHeight(value: unknown): boolean;\n/**\n * Horizontal distance in metres between two lon/lat pairs — equirectangular\n * approximation, plenty for the sub-metre comparisons and line-length weights\n * it is used for here.\n */\nexport declare function horizontalDistance(lon1: number, lat1: number, lon2: number, lat2: number): number;\n/**\n * Spatial hash over nodes: cells are twice the snap distance wide, so any node\n * within the snap distance of a query lies in the 3×3 block of cells around\n * it — a lookup costs the same at 2,000 nodes as at 50,000.\n */\nexport declare class NodeIndex {\n private readonly _snapDistance;\n private readonly _cells;\n private readonly _cellSize;\n private readonly _lonScale;\n constructor(nodes: HeightNode[], _snapDistance: number);\n private _cell;\n private _key;\n /** The nearest node within the snap distance of (lon, lat), or null. */\n nearest(lon: number, lat: number): HeightNode | null;\n}\n/**\n * Resolves the heights of a line's two ends (rules 1–4, see `EndRule`).\n * Both ends get rules 1–2 first, so rule 3 never copies a value that itself\n * came from rule 3/4. Returns null when an end ends up with no height at all.\n */\nexport declare function resolveLineEnds(properties: GeoJSON.GeoJsonProperties, start: [number, number], end: [number, number], config: VectorLayerHeightConfig, index: NodeIndex | null): {\n start: number;\n end: number;\n startRule: EndRule;\n endRule: EndRule;\n} | null;\n/**\n * Resolves the orthometric height of every vertex of every feature in a\n * layer, following the rules documented on `VectorLayerHeightConfig` (\"geometry\"\n * and \"attributes\"). Emits at most ONE `console.warn` per call (the fallback,\n * or the skipped-feature summary), never one per vertex/feature.\n */\nexport declare function resolveLayerHeights(features: GeoJSON.Feature[], config: VectorLayerHeightConfig, nodes?: HeightNode[], layerId?: string): LayerHeights;\n\n/**\n * Pixels either side of a fat line's own stroke (`Line2`) that still count as\n * a hit — the strokes are only a couple of pixels wide, so without it a click\n * has to land on the exact pixel row of the line. three adds\n * `raycaster.params.Line2.threshold` to the material's full `linewidth` and\n * then tests against HALF of the sum, hence the doubling in\n * `pickVectorFeature()`.\n */\nexport declare const VECTOR_PICK_TOLERANCE_PX = 6;\n/** What a pick found: which feature of which layer, and where along the ray. */\nexport interface VectorPickHit {\n layerId: string;\n /** Index in the layer's `geojson.features`. */\n featureIndex: number;\n /** Distance from the ray origin (the camera, for a perspective camera). */\n distance: number;\n point: THREE.Vector3;\n}\n/**\n * Nearest vector-layer feature under a pointer, or null.\n *\n * `objects` are the roots `VectorLayers` built (each, or one of its\n * descendants, carries `userData.{layerId, featureIndex}`) — raycast directly\n * rather than through a scene, since they may live in the world's scene or in\n * the private deferred-mode one. `ndc` is the pointer in normalised device\n * coordinates; `size` is the renderer's pixel size, which fat lines need both\n * to set their `LineMaterial.resolution` and to turn\n * {@link VECTOR_PICK_TOLERANCE_PX} into world units.\n */\nexport declare function pickVectorFeature(objects: THREE.Object3D[], camera: THREE.Camera, ndc: THREE.Vector2, size: THREE.Vector2): VectorPickHit | null;\n\n/**\n * Per-layer style — `simplestyle-spec` property names, see\n * docs/adrs/vector-layer-style-property-naming.md for why. Layer-level only\n * (applies to every feature in the layer), not per-feature.\n */\nexport interface VectorLayerStyle {\n stroke?: string;\n \"stroke-width\"?: number;\n fill?: string;\n \"fill-opacity\"?: number;\n}\n/** Per-layer placement options (not styling). */\nexport interface VectorLayerOptions {\n /**\n * Height of every feature relative to the origin, in metres (negative =\n * below ground, e.g. buried utilities). Default 0.\n */\n elevation?: number;\n /**\n * Opt-in per-feature heights (see `VectorLayerHeightConfig`). When set and\n * resolvable, each vertex is placed at its own height + the project's geoid\n * undulation instead of flat at `elevation`. Absent = legacy flat drawing.\n */\n height?: VectorLayerHeightConfig;\n /** \"attributes\" heights only — surface nodes (a line end snaps to the nearest one for its surface height). */\n nodes?: HeightNode[];\n}\n/**\n * One feature's geometry in scene coordinates, for 2D consumers (the\n * minimap). `rings` holds a single vertex for points, the vertices for\n * lines, and outer ring + holes for polygons (multi-geometries are split\n * into one feature per part).\n */\nexport interface VectorMapFeature {\n type: \"point\" | \"line\" | \"polygon\";\n rings: THREE.Vector3[][];\n /** Index in the layer's `geojson.features` — the same identity a 3D pick yields, shared by every part of a multi-geometry. */\n featureIndex: number;\n}\n/** A loaded layer as seen by 2D consumers. */\nexport interface VectorMapLayer {\n id: string;\n style: {\n stroke: string;\n strokeWidth: number;\n fill?: string;\n fillOpacity: number;\n };\n features: VectorMapFeature[];\n}\nexport declare const VECTOR_HOVER_COLOR = \"#FFC107\";\nexport declare const VECTOR_SELECTION_COLOR = \"#00E5FF\";\n/**\n * Payload of `VectorLayers.onFeatureSelected`: the selected feature's identity\n * plus its attribute-table row. `properties` is the feature's own\n * `properties` object, untouched (keys keep whatever the source file has).\n */\nexport interface VectorFeatureSelection {\n layerId: string;\n layerName: string;\n /** Index in the layer's `geojson.features`. */\n featureIndex: number;\n geometryType: string;\n properties: GeoJSON.GeoJsonProperties;\n}\n/**\n * Internal submodule of `GISManager` for vector GIS layers (shapefile/GeoJSON —\n * shapefiles are converted to GeoJSON at ingestion time, see docs/adrs). Kept as\n * a plain internal class rather than a separate `OBC.Component`: `GISManager`\n * already covers \"everything GIS\", not just the basemap, so this stays behind\n * `gisManager.vectorLayers` instead of its own public component with its own\n * `components.get(...)` entry point.\n *\n * Positions features using the same georeferencing math `ReorientationPlugin`\n * uses to align the 3D Tiles (`Ellipsoid.getObjectFrame()`, WGS84 lat/lon/\n * height/azimuth -> a rigid ECEF<->scene-local transform), computed directly\n * from `GISManager`'s own origin params rather than read off the tileset's\n * `matrixWorld` — see `geoToWorld()` for why: that transform is a pure\n * function of the 4 origin parameters (confirmed by reading\n * `ReorientationPlugin.transformLatLonHeightToOrigin`, which touches nothing\n * tileset-specific besides which `group`/`ellipsoid` object to write into),\n * so vector layers don't need to wait for a tileset to exist or load, and\n * stay correct even when `GISManager.snapToGround()` changes the origin's\n * height independently of any tileset event.\n */\nexport declare class VectorLayers {\n world?: OBC.World;\n getOrigin?: () => {\n latitude: number;\n longitude: number;\n height: number;\n rotation: number;\n };\n getGeoidUndulation?: () => number;\n private static readonly _POINT_RADIUS;\n private _occlusionScene;\n /** Called once the deferred scene exists, so the owner registers its pass. */\n ensurePass?: () => void;\n /** Fires whenever layers are added, removed or rebuilt (e.g. origin change). */\n readonly onLayersChanged: OBC.Event<void>;\n /**\n * Fires with the newly selected feature, or null when the selection is\n * cleared. Not fired when the already-selected feature is selected again.\n */\n readonly onFeatureSelected: OBC.Event<VectorFeatureSelection | null>;\n getLayerName?: (id: string) => string | undefined;\n private _selected;\n private _hovered;\n private readonly _highlighted;\n private readonly _layers;\n private readonly _mapLayers;\n /** Loaded layers' geometry for 2D consumers (see `VectorMapFeature`). */\n get mapLayers(): VectorMapLayer[];\n private readonly _layerSources;\n get hasLayers(): boolean;\n /**\n * Draws every loaded layer into the renderer's current target, with fat\n * lines sized for a `width`×`height` pixel target (their width is in\n * pixels of it). Used by `GISManager`'s deferred pass; also works in\n * composer mode (objects drawn one by one). The minimap doesn't use this —\n * it draws `mapLayers` as live 2D vectors instead.\n */\n render(renderer: THREE.WebGLRenderer, camera: THREE.Camera, width: number, height: number): void;\n /**\n * @param id When given, tracks everything this call adds under that id so\n * `removeLayer(id)` can clean it up later — calling `addLayer` again with an\n * id already in use replaces it (removes the old one first), rather than\n * duplicating it. Without an id, nothing is tracked and there is nothing to\n * remove later (matches the previous, untracked behaviour).\n */\n addLayer(geojson: GeoJSON.FeatureCollection, style?: VectorLayerStyle, id?: string, options?: VectorLayerOptions): void;\n /** Removes and disposes everything the given `id`'s `addLayer()` call added. No-op if unknown/already removed. */\n removeLayer(id: string): void;\n private _dropLayer;\n /**\n * Nearest feature under a pointer (NDC), or null — see\n * `pickVectorFeature()`. Costs nothing when no layer is loaded.\n */\n pickFeature(ndc: THREE.Vector2): VectorPickHit | null;\n /** Selects (and highlights) one feature, replacing any previous selection. No event if it is already the selected one. */\n selectFeature(layerId: string, featureIndex: number): void;\n /** The current selection as the `onFeatureSelected` payload (null when nothing is selected) — for consumers created after the event fired. */\n get selection(): VectorFeatureSelection | null;\n /** Drops the selection and its highlight. No-op (no event) when nothing is selected. */\n clearSelection(): void;\n /** The currently selected / hovered feature (null = none) — read by the 2D map to draw the same states as 3D. */\n get selectedFeature(): {\n layerId: string;\n featureIndex: number;\n } | null;\n get hoveredFeature(): {\n layerId: string;\n featureIndex: number;\n } | null;\n /** Scene-space box of everything built for one feature (null if it isn't loaded), at its real resolved heights. */\n getFeatureBounds(layerId: string, featureIndex: number): THREE.Box3 | null;\n /** Hover-highlights one feature (null = none). Does not touch the selection and fires no event. */\n setHoveredFeature(hit: {\n layerId: string;\n featureIndex: number;\n } | null): void;\n /** Top-level objects built for one feature (empty if the layer/feature isn't loaded). */\n private _featureObjects;\n private _paint;\n isLayerLoaded(id: string): boolean;\n /**\n * Rebuilds every currently loaded layer's geometry from its cached\n * geojson/style, using the current `getOrigin()` — the fix for\n * loaded-layer-geometry-freezing-at-load-time: `addLayer()` only reads\n * `getOrigin()` once, at build time, so an origin change (gizmo drag,\n * lat/lon/height/rotation inputs, `snapToGround()`) otherwise never moves\n * already-loaded layers. Callers should debounce this — see\n * `GISManager.setPosition()` — since it rebuilds real geometry, not just\n * repositions existing objects.\n */\n reprojectAll(): void;\n /** Scene-space bounding box of everything `id`'s `addLayer()` call added — `null` if the id is unknown or nothing was actually added. */\n getLayerBounds(id: string): THREE.Box3 | null;\n private _disposeObject;\n private _resolveTargetScene;\n /**\n * WGS84 lat/lon/height (degrees, metres above the ellipsoid) -> scene-local\n * position, computed straight from `GISManager`'s origin params — the exact\n * same math `ReorientationPlugin.transformLatLonHeightToOrigin` runs against\n * `tiles.group.matrix` (`Ellipsoid.getObjectFrame()` for the origin's own\n * lat/lon/height/azimuth -> ECEF<->local transform, inverted), just without\n * needing a `TilesRenderer` to hold the intermediate result. No tileset\n * required, and always current — including immediately after\n * `GISManager.snapToGround()` changes the origin height, with nothing to\n * resync.\n */\n geoToWorld(lat: number, lon: number, height?: number): THREE.Vector3;\n /**\n * lon/lat (GeoJSON coordinate order) -> scene position, X/Z only — Y is the\n * layer's `elevation` (relative to the origin). This is the legacy flat\n * path, used by every layer that doesn't opt in to per-feature heights:\n * `geoToWorld`'s real Y depends on the gap between the origin's height and\n * each vertex's own height, which produced large, confusing vertical\n * offsets for raw file Z values — so for these layers per-vertex heights\n * are ignored and the whole layer sits flat at its `elevation`. Layers with\n * a `height` config go through `_toScenePosition()` instead.\n */\n private _toSceneVector;\n /**\n * One vertex's scene position: with a resolved orthometric `height`, the\n * full `geoToWorld()` result for `height + undulation` (all three\n * components, Y included); without one, the legacy flat `_toSceneVector()`.\n */\n private _toScenePosition;\n /** Renderer's current pixel size — `LineMaterial` needs it to size `linewidth` correctly. */\n private _resolution;\n private _buildFeatureObject;\n private _buildMapFeatures;\n private _buildPoint;\n private _buildLine;\n /**\n * Surface (`THREE.ShapeGeometry`, triangulated — handles non-convex rings)\n * when `fill` is set, plus the outline for every ring either way. Built in\n * local 2D (x, z) then rotated flat: `ShapeGeometry` lives in the XY plane,\n * and rotating +90° around X maps local (x, y, 0) -> scene (x, 0, y), which\n * lines up with `_toSceneVector`'s (x, 0, z) exactly; the layer's\n * `elevation` is re-applied afterwards as a plain vertical translation.\n * With per-vertex `heights` the outlines follow them, while the (planar)\n * surface sits at the average resolved height of the outer ring.\n */\n private _buildPolygonSurface;\n}\n\nexport interface GISManagerState {\n apiToken: string;\n assetId: string;\n latitude: number;\n longitude: number;\n height: number;\n rotation: number;\n tilesVisible: boolean;\n gizmoVisible: boolean;\n tilesOffsetEast: number;\n tilesOffsetNorth: number;\n tilesOffsetUp: number;\n /** See-through factor for the tiles (1 = opaque) — see `GISManager.setTilesOpacity`. */\n tilesOpacity: number;\n}\n/** One entry in the persisted vector-layer manifest — metadata only, not the geometry itself. */\nexport interface GISVectorLayerConfig {\n id: string;\n name: string;\n fileId: string;\n /**\n * File format: `\"shapefile\"` (a zip with .shp/.dbf/.prj…) or `\"geojson\"`. When\n * missing or unrecognised the downloaded bytes decide (zip signature →\n * shapefile, leading `{` → GeoJSON).\n */\n type: string;\n style: VectorLayerStyle;\n /** Opt-in per-feature heights (see `VectorLayerHeightConfig`); absent = flat. */\n height?: VectorLayerHeightConfig;\n}\n/** How a layer's features get their height. Absent = legacy behaviour: the whole layer is drawn flat. */\nexport interface VectorLayerHeightConfig {\n /**\n * \"geometry\": each vertex uses its own Z (third GeoJSON coordinate).\n * \"attributes\": lines get their start/end heights from feature properties.\n */\n source: \"geometry\" | \"attributes\";\n /** \"attributes\" only — property holding the height of a line's first vertex. */\n startProperty?: string;\n /** \"attributes\" only — property holding the height of a line's last vertex. */\n endProperty?: string;\n /** \"attributes\" only — property holding the depth below the surface at the first vertex. */\n startDepthProperty?: string;\n /** \"attributes\" only — property holding the depth below the surface at the last vertex. */\n endDepthProperty?: string;\n /** \"attributes\" only — ids of point layers (in this same manifest) whose Z gives the surface height at a line end. */\n nodeLayers?: string[];\n /** \"attributes\" only — max horizontal distance (m) between a line end and a node for them to count as the same place. Default 0.5. */\n nodeSnapDistance?: number;\n}\n/**\n * Shape of `{GISManager.uuid}.json`, the project-storage file\n * `GISManager.init()` reads. Origin lives in `ProjectManager`'s own record\n * instead (the platform's canonical project data) — this file is only the\n * vector-layer manifest.\n */\nexport interface GISPersistedConfig {\n layers: GISVectorLayerConfig[];\n /** Small local East/North/Up fine-tune offset (metres) for Google 3D\n * Tiles — see `GISManager.setTilesOffset`'s own doc comment. Optional:\n * absent means \"no offset saved yet\", same as `{0,0,0}`. */\n tilesOffset?: {\n east: number;\n north: number;\n up: number;\n };\n}\n\n/** Calls `visit` with every [lon, lat, …] vertex of a GeoJSON geometry (all supported types, collections included). */\nexport declare function forEachVertex(geometry: GeoJSON.Geometry | null, visit: (coord: number[]) => void): void;\n/**\n * Horizontal (scene X/Z) bounding box of every vertex of every given feature\n * collection, each vertex taken through `project(lat, lon)` (the real\n * `geoToWorld`). Heights are irrelevant here and left at 0. Vertices with\n * non-finite coordinates are ignored; null when nothing usable is left.\n */\nexport declare function layersBoundsXZ(collections: GeoJSON.FeatureCollection[], project: (lat: number, lon: number) => THREE.Vector3): THREE.Box3 | null;\n/** The square, in scene X/Z, that a minimap capture covers. */\nexport interface MinimapExtent {\n centerX: number;\n centerZ: number;\n /** Half the side of the square, in metres. */\n half: number;\n}\n/**\n * Extra room around the content's extent, as a FRACTION of its half-size (not\n * metres), so the outermost features don't sit exactly on the image edge.\n */\nexport declare const MINIMAP_EXTENT_MARGIN = 0.05;\n/**\n * The capture square for the vector layers' box (world space): centred on its\n * X/Z centre, with half the larger X/Z span as its half-size (the image stays\n * square), plus `margin`. With nothing usable — no box, an empty or non-finite\n * one, or content with no horizontal size at all — falls back to\n * `fallbackHalf` metres around the origin.\n */\nexport declare function computeMinimapExtent(box: THREE.Box3 | null | undefined, fallbackHalf: number, margin?: number): MinimapExtent;\n\n/**\n * What to do when the Highlighter's \"select\" style highlights something:\n * - \"undo-bim\": the highlight belongs to a click that a vector feature just\n * won (it fires inside that click's short window) — take the BIM highlight\n * back and keep the vector selection;\n * - \"clear-vector\": a genuine BIM selection (viewer, model tree, objects\n * panel, …) — the vector selection must go;\n * - \"none\": nothing to do (an empty highlight outside the window).\n */\nexport type BimHighlightAction = \"undo-bim\" | \"clear-vector\" | \"none\";\nexport declare function bimHighlightAction(insideVectorWinWindow: boolean, bimSelectionEmpty: boolean): BimHighlightAction;\n/** Whether a Highlighter selection map (`modelId → Set<localId>`) selects nothing. */\nexport declare function isModelIdMapEmpty(map: Record<string, Set<number>> | null | undefined): boolean;\n\n/**\n * What the minimap needs from `GISManager`, provided as a private hook object\n * (the minimap never reaches into `GISManager` itself).\n */\nexport interface MinimapSource {\n /**\n * Gets the Google GIS tiles ready to be drawn from `camera` (registers it\n * with the streaming renderer and waits until the content it sees has\n * loaded).\n */\n prepare(camera: THREE.OrthographicCamera, resolution: number): Promise<void>;\n /** Draws the tiles into the renderer's CURRENT render target (a fresh, transparent one). */\n draw(renderer: THREE.WebGLRenderer, camera: THREE.OrthographicCamera): void;\n /** Undoes whatever `prepare` set up. Always called, even if `prepare` threw. */\n cleanup(camera: THREE.OrthographicCamera): void;\n /**\n * Live opacity (0..1) the map applies when drawing the captured image — read\n * on every redraw, so it can change without recapturing.\n */\n opacity(): number;\n /** Horizontal world box of ALL the project's vector layers (null when there is none). */\n getVectorLayersBox(): Promise<THREE.Box3 | null>;\n}\n/**\n * Result of a capture: the image plus what's needed to map world ↔ image.\n */\nexport interface MinimapCapture {\n /** Top-down, north-up image of the GIS tiles (canvas pixels, sRGB, transparent elsewhere). */\n image: HTMLCanvasElement;\n /** Live opacity (0..1) to draw `image` with. */\n opacity: () => number;\n /** Side of the image, in pixels. */\n size: number;\n /** Copy of the camera the image was taken with, for world ↔ map conversion. */\n camera: THREE.OrthographicCamera;\n}\n/**\n * A marker drawn over the minimap (an HTML overlay on the panel's canvas,\n * following zoom and pan; hidden while there is no capture).\n */\nexport interface MinimapMarker {\n id: string;\n /** Scene coordinates. Read on every redraw, so a marker follows if this changes. */\n position: THREE.Vector3;\n label?: string;\n /**\n * Builds the marker's element. A FACTORY, not an element: a panel can be\n * destroyed and recreated (the user switching layouts), and each one needs\n * its own DOM node. A marker with one owns its click behaviour; without it\n * the panel draws a default badge with the label and reports clicks through\n * `onMarkerClicked`.\n */\n createElement?: () => HTMLElement;\n}\n/** What changed in the marker list — the panel just reconciles against `markers`. */\nexport interface MinimapMarkersChange {\n kind: \"added\" | \"updated\" | \"removed\" | \"cleared\";\n /** The marker's id (absent for \"cleared\"). */\n id?: string;\n}\n/**\n * Internal submodule of `GISManager` for the 2D minimap, same pattern as\n * `VectorLayers` (a plain internal class behind `gisManager.minimap`, not its\n * own component). Baked top-down image: renders the Google GIS tiles once,\n * from an orthographic camera looking straight down at the middle of the\n * project's vector layers, into an in-memory image (never persisted). The UI\n * (`<top-map-panel>`) draws live overlays (vector layers, camera arrow, view\n * cone) on top of that static image, game-minimap style.\n *\n * North-up: scene axes follow the codebase's +X=West, +Y=Up, +Z=North\n * convention (origin rotation fixed at 0), so the camera's \"up\" is +Z. The\n * world ↔ map conversions go through the capture camera's own projection, so\n * they stay correct without hardcoding that convention anywhere else.\n */\nexport declare class Minimap {\n private readonly _source;\n world?: OBC.World;\n /**\n * Fallback only: half the side of the captured square, in metres, centred on\n * the origin — used when the project has no usable vector layers. Otherwise\n * the area is the box of all of them.\n */\n halfExtent: number;\n /**\n * Side of the captured image, in pixels (clamped to the GPU's max texture\n * size). Fixed, so the map gets coarser as the site gets larger: the image\n * covers the whole data-driven extent. Scaling the image with the extent was\n * tried and was too slow to capture. The intended improvement is to recapture\n * only the visible area when the user zooms in on the map, so sharpness no\n * longer depends on the size of the site.\n */\n resolution: number;\n readonly onCaptured: OBC.Event<MinimapCapture>;\n /** Fires once per `addMarker` / `updateMarker` / `removeMarker` / `clearMarkers` that changed something. */\n readonly onMarkersChanged: OBC.Event<MinimapMarkersChange>;\n /** Fires with the id when the panel's DEFAULT marker (one without `createElement`) is clicked. */\n readonly onMarkerClicked: OBC.Event<string>;\n private readonly _markers;\n private _capture;\n private _capturing;\n constructor(_source: MinimapSource);\n get capture(): MinimapCapture | null;\n get capturing(): boolean;\n /** Every marker, by id (read-only). */\n get markers(): ReadonlyMap<string, MinimapMarker>;\n getMarker(id: string): MinimapMarker | undefined;\n /** Adds a marker, or replaces the one with the same id. */\n addMarker(marker: MinimapMarker): void;\n /** Changes some fields of a marker. Returns false (and fires nothing) if there is no such marker. */\n updateMarker(id: string, partial: Partial<Omit<MinimapMarker, \"id\">>): boolean;\n /** Returns false (and fires nothing) if there is no such marker. */\n removeMarker(id: string): boolean;\n clearMarkers(): void;\n /**\n * The area the next capture covers: the box of all the project's vector\n * layers (waits for them to be read as data), or `halfExtent` around the\n * origin without any.\n */\n getExtent(): Promise<MinimapExtent>;\n /** Renders the GIS tiles into a fresh image. */\n captureMap(): Promise<MinimapCapture>;\n /** World point → normalized image coords (0..1, origin top-left), or null without a capture. */\n worldToMap(point: THREE.Vector3): {\n x: number;\n y: number;\n } | null;\n /** Normalized image coords → world point on the horizontal plane at `height`. */\n mapToWorld(x: number, y: number, height?: number): THREE.Vector3 | null;\n private _render;\n dispose(): void;\n}\n\n/** The file formats a vector layer can come in (the manifest entry's `type`). */\nexport type VectorLayerFormat = \"shapefile\" | \"geojson\";\n/**\n * Which parser a downloaded layer file needs. The manifest's `type` decides\n * when it is recognised; otherwise the bytes do: a zip signature (`PK\\x03\\x04`)\n * means a shapefile, a first non-whitespace `{` means GeoJSON. Anything else\n * throws, with a message meant for the user.\n */\nexport declare function detectLayerFormat(type: string | undefined, bytes: Uint8Array): VectorLayerFormat;\ntype CrsKind = {\n kind: \"lonlat\";\n} | {\n kind: \"reproject\";\n from: string;\n} | {\n kind: \"unsupported\";\n name: string;\n};\n/**\n * Reads the legacy GeoJSON `crs` member's name. Understands the CRS84 URN,\n * EPSG URNs (with or without a version), `EPSG:<code>` and the OpenGIS http\n * form. EPSG:4326 is taken as lon/lat as-is: GDAL/QGIS write lon/lat even when\n * they label it 4326. Reprojected: EPSG:3857 and the UTM families (326xx/327xx\n * WGS84, 258xx ETRS89, 269xx NAD83), their definition built from the code.\n */\nexport declare function parseCrsName(name: string): CrsKind;\n/**\n * Parses GeoJSON text into a `FeatureCollection` in WGS84 lon/lat (`z` kept).\n * The coordinate system comes from the legacy `crs` member; without one the\n * coordinates must already be lon/lat, which is checked. Throws a clear error\n * for an unsupported CRS, or projected coordinates that don't say which CRS\n * they are in. The legacy `crs` member is dropped from the result.\n */\nexport declare function parseGeoJSONLayer(text: string): Promise<GeoJSON.FeatureCollection>;\n\n/**\n * Streams Cesium Ion 3D Tiles (Google Photorealistic 3D Tiles by default) co-located\n * with the BIM model.\n *\n * Rendering path depends on `world.renderer.postproduction.mode`:\n * - DEFERRED: the deferred G-buffer capture pass only draws objects whose material\n * carries the engine's \"capture-emission\" marker (set on Fragments/BIM surface\n * materials only) — every other object, however opaque, is hidden for the\n * duration of the capture (confirmed directly from the engine's own\n * `SurfaceCapturePass` docs). So tiles are added to a private off-scene\n * `THREE.Scene` and drawn via `addOcclusionPass` (direct mode — opaque,\n * self-occluding, same as `PointCloudLoader`), which runs AFTER the deferred\n * composite and bypasses the G-buffer requirement entirely.\n * - COMPOSER: the EffectComposer path renders the real scene graph directly, no\n * special material marker needed, so tiles are added straight to\n * `world.scene.three` like any other mesh.\n *\n * The Cesium Ion API token is kept in memory only (no persistence yet) — see\n * docs/adrs for the pending decision on where project geo-location should live.\n */\ndeclare class _GISManager extends OBC.Component {\n static readonly uuid: \"d8f3a1c2-6b4e-4f9a-8c1d-2e7b5a9f3c60\";\n enabled: boolean;\n readonly onStateChanged: OBC.Event<GISManagerState>;\n readonly onLoadError: OBC.Event<string>;\n readonly onLayersLoaded: OBC.Event<GISVectorLayerConfig[]>;\n readonly onVectorLayerError: OBC.Event<{\n id: string;\n message: string;\n }>;\n readonly onOffsetDirtyChange: OBC.Event<boolean>;\n readonly onOffsetSaveComplete: OBC.Event<boolean>;\n world?: OBC.World;\n vectorLayersConfig: GISVectorLayerConfig[];\n private _client?;\n private _projectId?;\n private _appDataStore?;\n private _offsetDirty;\n get offsetDirty(): boolean;\n readonly vectorLayers: VectorLayers;\n /**\n * Fires when a click selects a vector feature (payload: its layer, index and\n * attribute row) and with null when the selection is cleared — re-exposed\n * from `vectorLayers` for consumers (the future properties panel).\n */\n readonly onFeatureSelected: OBC.Event<VectorFeatureSelection | null>;\n /**\n * Fires on every `selectVectorFeature(..., { focus: true })`, including a\n * re-select of the already-selected feature (which fires no\n * `onFeatureSelected`) — carries the scene-space sphere the 3D camera frames,\n * so other views (the 2D map) can focus the same neighbourhood.\n */\n readonly onFocusRequested: OBC.Event<{\n layerId: string;\n featureIndex: number;\n sphere: THREE.Sphere;\n }>;\n private _apiToken;\n private _assetId;\n private _latitude;\n private _longitude;\n private _height;\n private _rotation;\n private _tilesVisible;\n private _gizmoVisible;\n private _tilesOffsetEast;\n private _tilesOffsetNorth;\n private _tilesOffsetUp;\n private _tiles;\n private _reorientation;\n private _draco;\n private _occlusionScene;\n private _usingOcclusionPass;\n private _locationControls;\n private _controlPoint;\n private _dragStartMatrix;\n private _tilesOpacity;\n private _fadeTarget;\n private _fadeQuad;\n private _horizonTarget;\n private _horizonQuad;\n /**\n * Fraction (0–1) of the camera's far distance over which the 3D tiles dissolve\n * into what is behind them, instead of ending in a hard edge at the far plane:\n * the tiles are fully visible up to `far * (1 - horizonFade)` and fully\n * transparent at `far`. Default 0.8. `0` turns it off (opaque tiles are drawn\n * straight into the frame at opacity 1, as before). Combines with\n * `setTilesOpacity`: final alpha = opacity × fade. Deferred hosts only — where\n * the tiles are added to the scene directly there is no fade. Vector layers\n * are not faded.\n */\n horizonFade: number;\n private readonly _far;\n private _farCameras;\n /**\n * Far plane (distance) the world's cameras get while the 3D tiles are loaded, so\n * the map reaches the horizon. Default `10000`. Changing it while the map is\n * loaded takes effect immediately. `horizonFade` is a fraction of this far while\n * the map is loaded (with `0.8`, the map fades from 2 km to 10 km).\n *\n * The camera's own far plane (e.g. the Settings panel's \"Far plane\") is\n * overridden while the map is loaded: it is remembered, not applied, and comes\n * back when the map is unloaded. Code that grows the far plane itself while the\n * map is loaded still works: a larger far than `mapFar` is left alone, and is\n * kept on unload.\n */\n get mapFar(): number;\n set mapFar(far: number);\n /** True while the map owns the cameras' far plane (the 3D tiles are loaded). */\n get farOverridden(): boolean;\n /** The far plane the user asked for, remembered while `farOverridden` (otherwise the cameras hold it). */\n get userCameraFar(): number;\n /** Records the far plane the user wants; not applied until the map is unloaded. Only meaningful while `farOverridden`. */\n setUserCameraFar(far: number): void;\n private _resolveFarCameras;\n /**\n * Shows a sky gradient behind everything while the 3D tiles are loaded: the\n * empty background (pixels nothing has drawn to) goes from `skyHorizonColor` at\n * the horizon to `skyZenithColor` straight up, so the tiles, dissolving with\n * `horizonFade`, melt into the horizon colour. Below the horizon it is the\n * horizon colour; an orthographic camera sees one flat colour. Default `true`;\n * `false` leaves the background untouched. Deferred hosts only — elsewhere\n * there is no sky. Drawn behind the vector layers and the tiles.\n */\n sky: boolean;\n private readonly _skyHorizon;\n private readonly _skyZenith;\n private _skyHorizonColor;\n private _skyZenithColor;\n private _skyPass;\n private static _setSkyRgb;\n /** Sky colour at the horizon (any CSS colour string, hex number or `THREE.Color`). Default `\"#d7e3ee\"`, a light hazy blue. */\n get skyHorizonColor(): THREE.ColorRepresentation;\n set skyHorizonColor(color: THREE.ColorRepresentation);\n /** Sky colour straight up. Default `\"#6a9bd1\"`, a deeper blue. */\n get skyZenithColor(): THREE.ColorRepresentation;\n set skyZenithColor(color: THREE.ColorRepresentation);\n private _passRegistered;\n private _ensureOcclusionPass;\n private readonly _occlusion;\n private _ensureFadeTarget;\n private _disposeFade;\n /** Freezes the reference frame for the upcoming gesture — see `_onControlPointMoved`. */\n private readonly _onDragStart;\n /**\n * Fires on every pointer move during the drag (live relocation). Always\n * converts the TOTAL offset since the drag began (that's what\n * `_controlPoint.position` holds throughout) through the FROZEN\n * start-of-gesture matrix, never the live `tiles.group.matrixWorld` —\n * otherwise every event would re-apply the same growing total against a frame\n * already shifted by all earlier events, compounding into runaway motion.\n *\n * Immediately resets `_controlPoint.position` back to (0,0,0) afterwards, so\n * the gizmo reads as a joystick fixed at the origin — only the terrain visibly\n * moves. This is safe precisely because of the point above: TransformControls\n * computes each event's position from its own frozen drag-start reference plus\n * the raw mouse offset, never incrementally from the object's last value, so\n * it doesn't notice or care that we reset it out from under it.\n */\n private readonly _onControlPointMoved;\n /** Gesture is over — nothing left to commit (every event already did), just clear the frozen reference. */\n private readonly _onDragEnd;\n private readonly _minimapSource;\n /** The 2D minimap (a baked top-down image of the GIS tiles over the project's vector layers) — see `Minimap`. */\n readonly minimap: Minimap;\n private readonly _onBeforeUpdate;\n private readonly _onOriginChange;\n private readonly _onCrsChange;\n private static readonly _CLICK_MAX_MOVE_PX;\n private static readonly _BIM_CLEAR_WINDOW_MS;\n private _pickDown?;\n private _clearBimUntil;\n private _bimClearHandler?;\n /**\n * Wires the click and hover handling on the viewer canvas. Window-level\n * CAPTURE listeners filtered to the canvas, so they run before the\n * Highlighter's own canvas listeners for the same event (it selects BIM\n * elements on mouse up). The canvas lives inside `top-viewer`'s shadow root,\n * where an event observed at `window` is retargeted to the shadow host — so\n * the filter compares `composedPath()[0]` (the real origin), never\n * `event.target`. The canvas itself is looked up per event rather than\n * cached: the world can resolve before its renderer exists.\n *\n * \"Nearest wins\" between a vector feature and a BIM element: on mouse DOWN,\n * only if the raycast hits a vector feature, the BIM element under the same\n * pixel is picked with `FastModelPickers` (`getItemAt` + `getPointAt`, the\n * same GPU pick the Highlighter selects with) and the two camera distances\n * are compared; the camera doesn't move during a click, so the answer is\n * ready by mouse up. On mouse up, if the vector feature won it is selected\n * and the BIM selection that same click makes is undone (the Highlighter\n * can't be told to skip a click — disabling it for one event leaves its\n * internal pointer state stuck — so its highlight is cleared the moment it\n * fires). Otherwise the vector selection is cleared and the Highlighter\n * proceeds as always. Gaussian-splat and Google 3D tiles are not considered.\n */\n private _setupFeaturePicking;\n private readonly _onHighlighterSetup;\n private get _pickCanvas();\n /** True when the event really originated on the viewer canvas (see `_setupFeaturePicking`). */\n private _isOnCanvas;\n private _hoverPoint?;\n private _hoverFrame;\n private readonly _onHoverMove;\n private readonly _runHover;\n private readonly _clearHover;\n /** Vector layers loaded and the viewer in plain select mode (no modal tool). */\n private _canPick;\n private _ensureBimClearHandler;\n private _ndc;\n private _isPickable;\n private readonly _onPickDown;\n private readonly _onPickUp;\n /**\n * Horizontal scene-space box of ALL the project's vector layers (every\n * manifest entry, displayed or not), for the minimap extent — the only thing\n * that defines it. Layers are read as data through the shared per-layer\n * cache (so nothing downloads twice and nothing is added to the scene), then\n * projected with the CURRENT origin on every call, so an origin change never\n * leaves a stale box. A layer that fails to load is skipped with one warning.\n */\n private _vectorLayersBox;\n constructor(components: OBC.Components);\n /**\n * Reads `{GISManager.uuid}.json` from project storage (same pattern as\n * `ClashesManager`/`TopicsManager`'s own `init(client)` — a plain method\n * call, not `@lit/context`).\n * Restores the origin (lat/lon/height/rotation) by composition from\n * `ProjectManager` — the platform's canonical project record — instead of\n * duplicating it into GIS's own persisted file, plus the vector-layer\n * manifest (metadata only — id/name/fileId/type/style, NOT the geometry\n * itself) from GIS's own `{GISManager.uuid}.json`. If that layers file\n * doesn't exist yet in the project, leaves the layer list empty and does\n * NOT create one — that only happens later, on an explicit save.\n *\n * Assumes `ProjectManager.init(client)` has already run by the time this is\n * called — the caller must chain `GISManager.init()` after\n * the `ProjectManager.init()` promise resolves. If `GISManager` can ever be\n * initialized in a different order/context, `ProjectManager.origin.get()`\n * below would just read stale/undefined data silently — revisit this if\n * that assumption stops holding (e.g. by awaiting `ProjectManager.init`\n * here directly, if `GISManager` can no longer rely on caller ordering).\n *\n * No-op (never throws) if there's no project context, no matching file, or\n * the read fails for any reason — the app should always be usable with\n * defaults, storage is a progressive enhancement here, not a hard\n * dependency.\n */\n init(client: PlatformClient): Promise<void>;\n /** Whether loading a vector layer also frames the camera on it. Off for now. */\n fitCameraOnLayerLoad: boolean;\n /**\n * Downloads the given layer's shapefile `.zip` from project storage\n * (`vectorLayersConfig` entry's `fileId`), parses it with `shpjs.parseZip`\n * (dynamic import — same heavy-dependency convention as the rest of this\n * component), and renders it via `vectorLayers.addLayer(geojson, style,\n * id)`. The single entry point for \"the user checked this layer's box\" —\n * callers don't need to touch storage/shpjs/`VectorLayers` directly, and\n * don't need their own try/catch: failures are reported via\n * `onVectorLayerError`, mirroring `enableTiles()`/`onLoadError`.\n */\n loadVectorLayer(id: string): Promise<void>;\n private readonly _layerGeoJSON;\n private _getLayerGeoJSON;\n /**\n * Surface nodes for a layer whose heights come from attributes: every\n * Point/MultiPoint coordinate with a finite Z in the layers named by\n * `height.nodeLayers`. Those layers are only read as data here — nothing is\n * added to the scene and the panel's checkboxes are untouched. An unknown id\n * is warned about and skipped.\n */\n private _loadHeightNodes;\n private _downloadAndParseLayer;\n /**\n * Real-world vector data can easily sit tens of km from the origin (a whole\n * shapefile's extent, not just small hand-built test shapes) —\n * far outside the default camera framing (~87 units from origin). Frames\n * the camera on the layer's actual bounding box right after it loads, same\n * `CameraControls.fitToBox()` the point-cloud loader already uses for the\n * same reason, so newly loaded data doesn't just silently look like nothing\n * rendered.\n */\n private _fitCameraToLayer;\n private static readonly _FOCUS_MIN_RADIUS;\n /**\n * The single entry point for selecting a vector feature — the 3D click and\n * the 2D map's click both come through here, so they share one selection\n * state, one `onFeatureSelected` event and one camera travel. With `focus`,\n * the camera flies to the feature: `CameraControls.fitToSphere()` (animated)\n * on the bounding sphere of what `VectorLayers` built for it, at its real\n * resolved heights; the viewing direction is kept, only the target and the\n * distance change. Selecting the already-selected feature fires no event but\n * still focuses. Clearing stays `vectorLayers.clearSelection()`.\n */\n selectVectorFeature(layerId: string, featureIndex: number, options?: {\n focus?: boolean;\n }): void;\n private _focusVectorFeature;\n /** Removes a layer loaded via `loadVectorLayer` — the \"user unchecked the box\" counterpart. */\n unloadVectorLayer(id: string): void;\n private _firstWorld;\n get apiToken(): string;\n set apiToken(value: string);\n get assetId(): string;\n set assetId(value: string);\n get latitude(): number;\n get longitude(): number;\n get height(): number;\n get rotation(): number;\n get tilesVisible(): boolean;\n get gizmoVisible(): boolean;\n get tilesOffsetEast(): number;\n get tilesOffsetNorth(): number;\n get tilesOffsetUp(): number;\n get tilesOpacity(): number;\n /**\n * See-through factor for the tiles (0..1, 1 = opaque), mirrored by the\n * minimap's terrain image. In-memory only. Applies in DEFERRED mode (the\n * viewer's default); the composer path keeps the tiles opaque.\n */\n setTilesOpacity(opacity: number): void;\n toggleGizmo(): void;\n /** Manual geo-location input (sliders) — no IFC georeferencing read yet, see docs/adrs. */\n setPosition(latitude: number, longitude: number, height?: number, rotation?: number): void;\n /**\n * Small local fine-tune offset (metres, East/North/Up) layered ON TOP of\n * the origin-derived tiles position — a manual calibration knob for Google\n * Photorealistic 3D Tiles' own (independently known) absolute-positioning\n * inaccuracy, NOT a change to `ProjectManager.origin`/real georeferencing.\n * Re-derives the tiles position from the CURRENT origin fields + this\n * offset on every call (via `_reorientation`), so repeated calls replace\n * rather than accumulate.\n *\n * NOT auto-saved — marks `offsetDirty`/fires `onOffsetDirtyChange` instead,\n * same pattern `ProjectManager.origin` uses, so a caller driving this\n * continuously (the fine-tune sliders) doesn't write to the network on\n * every tick. `saveTilesOffset()` persists explicitly.\n */\n setTilesOffset(east: number, north: number, up: number): void;\n /**\n * Persists the current tiles fine-tune offset to `{GISManager.uuid}.json`\n * (loose in `__project_data`, alongside `ProjectManager`'s own file — see\n * `_appDataStore`), preserving whatever `layers` are already in there.\n * `save()` itself is fire-and-forget/debounced — `offsetDirty` only clears\n * (and `onOffsetSaveComplete` fires) once `_appDataStore.onSaveComplete`\n * confirms the write actually succeeded (wired in `init()`), not\n * optimistically here.\n */\n saveTilesOffset(): void;\n private _applyTilesOffset;\n private _reprojectDebounce?;\n private _scheduleReprojectLayers;\n /**\n * Casts a ray straight down from high above the recentered origin against the\n * currently loaded tile geometry to find the real ground elevation at\n * (latitude, longitude), then re-applies the reorientation using that as\n * `height` so the visible terrain/rooftop lands at world (0,0,0) instead of\n * wherever `height=0` (the bare WGS84 ellipsoid, which can be hundreds of\n * meters away from the real surface at elevated locations) happened to put it.\n *\n * Relies on the ENU tangent-plane guarantee `transformLatLonHeightToOrigin`\n * gives at the origin: after recentering at some height, \"up\" from that lat/lon\n * is exactly world +Y, and world Y directly corresponds to metres of height — so\n * a hit at world Y = `dy` means the real surface is `dy` metres higher than the\n * height currently used, and re-running the transform with\n * `height + dy` should bring it to Y ≈ 0. Only accurate near the origin (a few\n * km), which is exactly the regime this is used in.\n *\n * Tries straight down first, then straight up (content can end up above OR below\n * the origin depending on how far off `height=0` was from the real surface).\n *\n * Uses `TilesRenderer.raycast()` — 3d-tiles-renderer's own documented raycasting\n * entry point — instead of a generic `THREE.Raycaster.intersectObject(tiles.group)`.\n * The library keeps its own tile-activity bookkeeping (`activeTiles`,\n * `tile.traversal.used`, per-tile bounding volumes) separate from the plain\n * Object3D tree, and only that entry point knows how to walk it; a generic\n * scene-graph raycast against `tiles.group` silently finds nothing.\n *\n * Tile traversal (`markUsedTiles` in the engine's own source) bails out\n * immediately — without even descending into children — for any tile whose\n * bounding volume isn't in the frustum of AT LEAST ONE registered camera:\n * `if (!tile.traversal.inFrustum) return;`. That branch is never visited, let\n * alone loaded or marked active, regardless of `displayActiveTiles` (which only\n * affects the final visibility toggle of tiles that already got marked active —\n * a narrower case). So if the real viewport camera isn't looking anywhere near\n * the target point, nothing here ever loads and the raycast finds nothing no\n * matter what.\n *\n * `TilesRenderer` supports multiple simultaneously-registered cameras\n * (`cameras: Camera[]`), and a tile counts as \"in frustum\" if ANY of them sees\n * it. So we register a throwaway camera positioned high above the origin,\n * looking straight down — wide FOV and far plane so its frustum (a cone\n * widening downward, centred on the target column) covers a generous height\n * range around the origin regardless of whether the real surface turns out to\n * be above or below it — force one `update()` traversal with it registered,\n * then remove it again. The real viewport camera's own registration and\n * behaviour are untouched throughout.\n *\n * Returns false if no tile geometry was found (nothing to snap to) — caller\n * should retry once more of the tileset streams in. The first call after\n * moving to a new area may land approximately rather than exactly, since the\n * newly-forced-into-frustum content is still streaming in asynchronously in\n * the background — calling it again shortly after tends to refine it further.\n */\n snapToGround(): boolean;\n /**\n * `CesiumIonAuth.fetch()`/`refreshToken()` (see `3d-tiles-renderer/core/plugins/auth/CesiumIonAuth.js`)\n * only ever throws `\"CesiumIonAuthPlugin: Failed to load data with error code {status}\"`\n * on a non-OK HTTP response — no further detail. Map the common statuses to\n * something a user can actually act on; fall back to the raw message otherwise.\n */\n private _toFriendlyLoadError;\n /**\n * Sets everything up and resolves only once the FIRST real outcome is known —\n * either actual content loaded (\"load-tileset\") or the initial fetch (auth\n * against the token/asset) failed (\"load-error\") — instead of resolving the\n * instant the TilesRenderer is constructed, before any network activity has\n * even started. `tilesVisible`/state only flips to enabled on success; on\n * failure everything set up here is torn down again and the promise rejects,\n * so the caller (the panel) never has to un-render a half-enabled state.\n */\n enableTiles(): Promise<void>;\n disableTiles(): void;\n /** Tears down everything `enableTiles()` set up, without touching `_tilesVisible`. */\n private _teardownTiles;\n dispose(): void;\n private _trigger;\n}\n\n/**\n * Streams Cesium Ion 3D Tiles (Google Photorealistic 3D Tiles by default) co-located\n * with the BIM model.\n *\n * Rendering path depends on `world.renderer.postproduction.mode`:\n * - DEFERRED: the deferred G-buffer capture pass only draws objects whose material\n * carries the engine's \"capture-emission\" marker (set on Fragments/BIM surface\n * materials only) — every other object, however opaque, is hidden for the\n * duration of the capture (confirmed directly from the engine's own\n * `SurfaceCapturePass` docs). So tiles are added to a private off-scene\n * `THREE.Scene` and drawn via `addOcclusionPass` (direct mode — opaque,\n * self-occluding, same as `PointCloudLoader`), which runs AFTER the deferred\n * composite and bypasses the G-buffer requirement entirely.\n * - COMPOSER: the EffectComposer path renders the real scene graph directly, no\n * special material marker needed, so tiles are added straight to\n * `world.scene.three` like any other mesh.\n *\n * The Cesium Ion API token is kept in memory only (no persistence yet) — see\n * docs/adrs for the pending decision on where project geo-location should live.\n */\nexport type GISManager = InstanceType<typeof _GISManager>;\n/**\n * Streams Cesium Ion 3D Tiles (Google Photorealistic 3D Tiles by default) co-located\n * with the BIM model.\n *\n * Rendering path depends on `world.renderer.postproduction.mode`:\n * - DEFERRED: the deferred G-buffer capture pass only draws objects whose material\n * carries the engine's \"capture-emission\" marker (set on Fragments/BIM surface\n * materials only) — every other object, however opaque, is hidden for the\n * duration of the capture (confirmed directly from the engine's own\n * `SurfaceCapturePass` docs). So tiles are added to a private off-scene\n * `THREE.Scene` and drawn via `addOcclusionPass` (direct mode — opaque,\n * self-occluding, same as `PointCloudLoader`), which runs AFTER the deferred\n * composite and bypasses the G-buffer requirement entirely.\n * - COMPOSER: the EffectComposer path renders the real scene graph directly, no\n * special material marker needed, so tiles are added straight to\n * `world.scene.three` like any other mesh.\n *\n * The Cesium Ion API token is kept in memory only (no persistence yet) — see\n * docs/adrs for the pending decision on where project geo-location should live.\n */\nexport const GISManager = { uuid: 'd8f3a1c2-6b4e-4f9a-8c1d-2e7b5a9f3c60' } as typeof _GISManager & { uuid: 'd8f3a1c2-6b4e-4f9a-8c1d-2e7b5a9f3c60' };\n\n/** One element mutation inside a revit-flow commit. */\nexport interface RevitFlowChange {\n /** create → element added, update → geometry/data changed, delete → removed. */\n type: \"create\" | \"update\" | \"delete\" | string;\n /** Revit UniqueId (GUID). Resolves to a fragments localId via getLocalIdsByGuids. */\n uniqueId: string;\n}\n/** Per-commit change tallies, mirrored from the add-in's `counts` block. */\nexport interface RevitFlowCounts {\n added: number;\n modified: number;\n removed: number;\n}\n/**\n * A revit-flow commit — one push of changes from the Revit add-in. `id` is a\n * monotonic integer; `parent` points at the previous commit (null for the\n * root). The first commit is the baseline: its geometry IS the visible model\n * file. Later commits carry only their delta geometry, in a HIDDEN .frag whose\n * id is `deltaId`.\n */\nexport interface RevitFlowCommit {\n /**\n * WHAT this commit is. Identity, minted by whoever wrote it, meaningful outside the model it\n * belongs to — which the old integer was not: that was the platform's storage version, a number\n * the CDE handed out. An application that does not push through a Revit central has no such\n * number, and an integer sequence asserts one line of history, which Revit's central enforces and\n * nothing else has to.\n */\n guid: string;\n /**\n * The commits this one was built on. Absent on a root.\n *\n * A LIST, because a history that can only ever be a line is a different thing from a graph. A\n * fork was already expressible with a single parent — two commits naming the same one — but a\n * MERGE means naming both lines, and that needs this. The first entry is the line the commit\n * continues, which is what lets the panel lay out lanes without guessing which side is the trunk.\n *\n * Revit never writes more than one: its central IS a single line and it merges inside itself\n * rather than in this graph. The list is for the applications that are not Revit.\n */\n parents?: string[] | null;\n /**\n * WHERE this landed in the CDE, when there is such a place. Data, never identity, and never shown\n * as the commit's name. Absent for any application with no version counter.\n */\n version?: number;\n /**\n * Position in this model's history, computed from the parent chain when the commits are read.\n *\n * Order questions — \"is this commit before the one on screen?\" — used to be asked of the integer\n * id, which meant every application had to produce a sequence to be understood. They are asked of\n * this instead: derived from the graph, so an application that has no numbers still answers them.\n */\n ordinal: number;\n /**\n * What the author said this commit was for, in their own words. Absent when nobody said\n * anything, which is most commits.\n *\n * In Revit it comes from the Comment box in its own Synchronize with Central dialog, which\n * people have been typing into for years while it went nowhere. Free text: never parsed, never\n * relied on for structure.\n */\n message?: string;\n author: string;\n source: string;\n timestamp: string;\n changes: RevitFlowChange[];\n counts: RevitFlowCounts;\n /**\n * Hidden-file id of this commit's delta .frag (created+modified geometry).\n * Absent on the baseline/first commit and on geometry-less commits. The\n * platform's hidden-file API has no queryable name, so the delta is loaded by\n * this id, never by filename.\n */\n deltaId?: string;\n /**\n * Platform user id of the committer, recorded by the add-in from its API key. Lets the\n * UI resolve the author to a real project member (avatar + name) via getProjectData,\n * instead of deriving initials from the raw Revit username. Absent on history written\n * before this was recorded, or when the key isn't a readable JWT.\n */\n userId?: string;\n /**\n * Which loaded model this commit belongs to (the model file's id == the viewer's\n * modelId). Tagged in by the manager when it reads the history: commit ids are\n * per-model version numbers, so they repeat across models and can't identify a commit\n * on their own.\n */\n modelId?: string;\n /** The model's name AS SHOWN IN PROJECT FILES, for the cards and the model filter. */\n modelName?: string;\n /**\n * This commit re-exported the WHOLE model, so the project's visible .frag shows the\n * model as of here — what anyone opening it from Project Files gets, without the\n * history panel. True for the initial capture and for the periodic full exports the\n * team publishes; ordinary commits ship only their delta.\n */\n full?: boolean;\n /**\n * Interoperability operations this commit materialised. Present only when somebody in\n * Revit pulled a deferred edit: the commit is the native half of it, and this is the\n * link back to the operation that asked for it. Ordinary hand-authored commits, which\n * are nearly all of them, carry no such key at all.\n */\n appliedOps?: string[];\n /**\n * Set when this entry is NOT a commit but a deferred edit still waiting to be applied.\n *\n * Pending operations are surfaced commit-SHAPED rather than as a parallel kind of thing, so\n * they inherit search, the user and model filters, the change-kind chips and the\n * filter-by-selection behaviour instead of needing all of it reimplemented. It also means\n * one of them can be clicked and previewed: a `modify` or `delete` names elements that\n * already exist, which is exactly what the outline machinery consumes, so you can see what\n * a change will touch before anybody applies it. A `create` has nothing to show yet, which\n * is honest rather than missing.\n *\n * Everything that treats an entry as history must check this first: it has not happened.\n */\n pendingOp?: RevitFlowOp;\n}\n/** Shape of `revitflow_history.json`. */\nexport interface RevitFlowHistory {\n model: string;\n commits: RevitFlowCommit[];\n}\n/**\n * One deferred edit waiting to be applied to a model.\n *\n * Operations are NOT commits and do not live in the graph: a commit is immutable past, an\n * operation is optional future. They sit above the model's HEAD until somebody opens the\n * model in Revit and applies one, at which point they become a commit and stop being\n * pending. Mirrors the add-in's `revitflow_ops.json`.\n */\nexport interface RevitFlowOp {\n opId: string;\n /** Groups the operations one authored action produced across several models. */\n batchId?: string;\n /** Hidden-file id of the operation's .frag payload. */\n fragId?: string;\n title?: string;\n /** add | set | remove | mixed. Older queues say modify | create | delete. */\n verb?: string;\n author?: string;\n /**\n * Platform user id of whoever authored it. Resolved to a real project member exactly as a\n * commit's is, so the same person does not appear as \"Antonio That Open\" on their commits\n * and as their raw OS username on their operations.\n */\n userId?: string;\n createdAt?: string;\n /** The commit this operation was authored against. */\n /** The commit this was authored against, by guid. What a proposal actually refers to. */\n baseCommitGuid?: string;\n /** The platform version that commit landed in. Data, for reconciling with the CDE. */\n baseCommit?: number;\n /** How many elements it targets. */\n targets?: number;\n state?: \"pending\" | \"applied\" | \"discarded\" | string;\n /** The native commit that materialised it, once applied. */\n appliedInCommit?: number | null;\n /**\n * Native ids the operation actually touched or created, written by the add-in when it applied.\n * A FLAT list: it does not say which source object produced which result, because nothing in\n * this system ties an element to an element in another application.\n *\n * It is what lets an APPLIED proposal be selected and previewed like a commit, with no payload\n * fetch at all. Note which halves that leaves blind, because they are opposite ends:\n *\n * add pending → nothing exists yet · applied → these are what it made\n * set pending → its targets · applied → the same targets\n * remove pending → its targets · applied → nothing, they are gone\n *\n * So the only case still needing the payload is a PENDING set or remove, whose target ids live\n * in the operation's .frag rather than in this index.\n */\n affectedIds?: string[];\n /** Tagged in by the manager, exactly as commits are: which model this queue belongs to. */\n modelId?: string;\n modelName?: string;\n}\n/** Shape of `revitflow_ops.json`. */\nexport interface RevitFlowOpsIndex {\n schema?: string;\n ops: RevitFlowOp[];\n}\n/** Dominant change type of a commit, used to color its timeline node. */\nexport type DominantChange = \"create\" | \"update\" | \"delete\";\n\n/** What to do with elements outside the selected commit. */\nexport type ContextMode = \"default\" | \"hidden\";\n/** The three kinds of change a commit can carry. */\nexport type ChangeKind = \"create\" | \"update\" | \"delete\";\n/**\n * Stable id for a commit across models — which is now just its guid.\n *\n * It used to have to be `${model}:${id}`, because the id was a per-model version number and every\n * model had a commit 3. A guid needs no help being unique, and that is exactly what it was for.\n */\nexport declare const commitKey: (c: {\n guid?: string;\n pendingOp?: {\n opId: string;\n };\n}) => string;\n/** How the commit is shown in 3D: review colours, or the model as it ended up. */\nexport type HighlightMode = \"colored\" | \"plain\";\n/** Dominant change type of a commit: delete → create → update. */\nexport declare function dominantChange(commit: RevitFlowCommit): DominantChange;\n/**\n * GitHistoryManager — headless engine for the revit-flow git-history built-in.\n *\n * Owns ALL viewer mutation for the change outlines. It does NOT load the model —\n * the user opens a model from the Project Files panel, and this manager reacts to\n * that load: it reads the model's hidden `revitflow_history.json` (if any) and\n * publishes the commit list. Showing a commit outlines its changed elements\n * (create → green, update → blue, delete → red) via three independently-colored\n * `OBF.Outliner` groups — a cheap post-process outline that never recolors the\n * fragment geometry. The Lit panel (`top-git-history`) is intent-only: it calls\n * these methods and subscribes to the events below.\n *\n * Data model, per loaded model (fileId == modelId), all HIDDEN children of it:\n * - revitflow_history.json — { model, commits: [{ id, parent, author, source,\n * timestamp, changes:[{type,uniqueId}], counts }] }. The first commit is the\n * INITIAL full-model capture (its geometry == the visible baseline file).\n * - revitflow_frag_<N>.frag — delta fragments for commit N (its created+modified\n * geometry), loaded on demand so created elements can be colored.\n */\ndeclare class _GitHistoryManager extends OBC.Component {\n static readonly uuid: \"3f9c1a7e-6b2d-4e18-9a5c-7d0e2f4b6c81\";\n enabled: boolean;\n readonly onCommitsChanged: OBC.Event<RevitFlowCommit[]>;\n /** {@link commitKey} of the highlighted commit, or null when cleared. */\n readonly onCommitChanged: OBC.Event<string | null>;\n readonly onLoadingChanged: OBC.Event<boolean>;\n readonly onError: OBC.Event<string>;\n /** The GUID currently selected in the 3D view (null when the selection is cleared). */\n readonly onSelectedGuidChanged: OBC.Event<string | null>;\n /** A source icon was added or replaced. */\n readonly onSourceIconsChanged: OBC.Event<void>;\n /**\n * Which mark to draw on a commit, by the application that wrote it.\n *\n * Every commit already says who made it, in `source`. The panel used to draw the Revit logo on\n * all of them regardless, which was true while Revit was the only thing that could write one and\n * became a lie the moment anything else did: a commit from another tool would claim to be a\n * Revit commit, on the one part of the row whose whole job is to say where a change came from.\n *\n * The format is deliberately open about who writes history, so the icons have to be too. This is\n * the registry. Only `revit` is built in; an application adds its own:\n *\n * const history = components.get(GitHistoryManager);\n * history.setSourceIcon(\"rhino\", \"https://…/rhino.svg\"); // a URL, or a data: URI\n * history.setSourceIcon(\"tekla\", \"<svg viewBox='0 0 24 24'>…</svg>\"); // or the markup\n *\n * A source with no icon gets a neutral one rather than somebody else's.\n */\n readonly sourceIcons: Map<string, string>;\n /**\n * @param source the commit's own `source` value, matched case-insensitively.\n * @param icon a URL, a `data:` URI, or inline `<svg>` markup.\n */\n setSourceIcon(source: string, icon: string): void;\n world?: OBC.World;\n /**\n * What happens to elements that are NOT part of the selected commit:\n * \"default\" — left as they are (the change outlines sit on the full model)\n * \"hidden\" — hidden entirely, isolating the commit's elements\n *\n * A dimmed (\"ghost\") middle ground was dropped: the fragments x-ray writes depth\n * from the pixels its screen door keeps, so dimmed geometry still occluded the very\n * elements under review — worse the denser the model in front. Fixing that properly\n * belongs in the renderer, not here, so this offers the two states that are exact.\n */\n contextMode: ContextMode;\n /**\n * Which change kinds to outline. All three by default; the panel's filter buttons\n * narrow it (e.g. only deletions) without reloading anything.\n */\n typeFilter: Set<ChangeKind>;\n /**\n * How many commits either side of the selected one to keep pre-loaded, so stepping\n * through the timeline is instant instead of fetching on every click. The window\n * slides with the selection and everything outside it is disposed, which bounds\n * memory no matter how long the history gets.\n */\n prefetchRadius: number;\n /**\n * How a commit is presented in 3D:\n * \"colored\" — outline created/edited/deleted in their colours (the review lens)\n * \"plain\" — no outlines: the model simply as it stood AFTER the commit, so the\n * deleted elements are hidden rather than painted red\n */\n highlightMode: HighlightMode;\n /** @deprecated kept so older callers still compile — maps onto contextMode. */\n get isolateChanges(): boolean;\n /** Green — created elements. */\n readonly COLOR_CREATED = \"#22c55e\";\n /** Golden yellow — modified elements. */\n readonly COLOR_MODIFIED = \"#e3b341\";\n /** Red — deleted elements. */\n readonly COLOR_DELETED = \"#ef4444\";\n readonly GROUP_CREATED = \"revitflow-created\";\n readonly GROUP_MODIFIED = \"revitflow-modified\";\n readonly GROUP_DELETED = \"revitflow-deleted\";\n private _client?;\n private _projectId?;\n /**\n * One entry per loaded revit-flow model. Commit ids are per-model version numbers, so\n * they collide across models — every commit is tagged with its modelId and a commit is\n * addressed by {@link commitKey}, never by id alone.\n */\n private _models;\n /** Which models the timeline shows. Empty = all of them. */\n private _selectedModels;\n /** `${modelId}:${id}` of the commit currently highlighted, or null. */\n private _currentKey;\n /** modelIds already probed for a sibling history (avoids re-probing). */\n private _probed;\n /** hiddenIds of delta frags this manager has loaded into the viewer. */\n private _loadedDeltas;\n /** Ghosted localIds per modelId, so isolate can be cleared/re-applied. */\n private _contextApplied;\n /** localIds hidden because the shown commit deleted them (plain mode). */\n private _hiddenDeleted;\n /** localIds hidden because a newer visible source supplies the same element. */\n private _hiddenSuperseded;\n /** True once the three named Outliner groups have been created. */\n private _groupsReady;\n private _loading;\n private _wired;\n constructor(components: OBC.Components);\n get ready(): boolean;\n get loading(): boolean;\n /**\n * Commits of the selected models, newest last, interleaved by time so a multi-model\n * timeline reads chronologically rather than model-by-model.\n */\n get commits(): RevitFlowCommit[];\n /** True when this entry is a proposal rather than something that happened. */\n isProposal(commit: RevitFlowCommit | null | undefined): boolean;\n /**\n * The entry a proposal/commit links to, in whichever direction applies: a commit points at\n * the proposal it materialised, a proposal at the commit that did it. Returns null when\n * there is no counterpart, which is the normal case for hand-authored work.\n */\n counterpart(commit: RevitFlowCommit): RevitFlowCommit | null;\n /**\n * Deferred edits still waiting to be applied, across the selected models, oldest first.\n *\n * Kept separate from {@link commits} on purpose. A commit is something that happened; a\n * pending operation is something that might. Merging them into one list would force every\n * consumer to keep asking which kind it was holding.\n */\n get pendingOps(): RevitFlowOp[];\n /** The loaded revit-flow models, for the panel's model filter. */\n get models(): Array<{\n modelId: string;\n name: string;\n commits: number;\n }>;\n get selectedModels(): Set<string>;\n get currentKey(): string | null;\n /** Name of the single loaded model, or \"\" when there are none/several. */\n get modelName(): string;\n /** The commit behind {@link currentKey}, or undefined when nothing is highlighted. */\n private _currentCommit;\n /** Restrict the timeline to these models (empty set = show all of them). */\n setSelectedModels(modelIds: Iterable<string>): Promise<void>;\n /** True when `commit` is its model's baseline (the full-model capture). */\n isBaseline(commit: RevitFlowCommit): boolean;\n /** True if `commit` has a hidden delta .frag to load. */\n hasFrag(commit: RevitFlowCommit): boolean;\n /**\n * Wire the platform client and subscribe to model loads. Does NOT load any\n * geometry: the manager only attaches to models the user opens from the Files\n * panel. Consumer panels call this once on connect.\n */\n init(client: PlatformClient): Promise<void>;\n /**\n * Follow the viewer's selection so the element view tracks whatever the user clicks in\n * 3D — no \"trace this\" button to press. The Highlighter's events appear asynchronously\n * (they're registered when the viewer sets it up), so retry briefly until they exist.\n */\n private _watchSelection;\n private _onModelSet;\n private _onModelDeleted;\n /**\n * Probe a loaded model for a sibling visible `revitflow_history.json` in its\n * folder. If present, adopt it as the active model and publish its commits.\n * Silent for non-revit models and for our own delta frags — only genuine\n * fetch/parse failures raise onError.\n */\n private _probeModel;\n /**\n * Read the model's deferred-edit queue, if it has one.\n *\n * Best effort by design: a model that has never been the target of an operation simply has\n * no queue, and that is the normal case rather than an error. A failure here must never\n * cost the user their history, which is why it cannot throw out of the probe.\n */\n private _readOps;\n /**\n * Re-scan every currently-loaded model for a hidden revit-flow history (the\n * panel's Refresh button). Clears the probe cache so models load-order edge\n * cases re-resolve.\n */\n loadHistory(): Promise<void>;\n /**\n * Show `commit`. The baseline geometry is the visible model the user already loaded, so\n * the baseline view just clears outlines. Any other commit pulls its hidden delta frag\n * in (so created elements exist) and outlines its changed elements. Fires\n * onCommitChanged. Takes the commit itself, not an id: ids repeat across models.\n */\n showCommit(commit: RevitFlowCommit): Promise<void>;\n /**\n * Keep the deltas of the commits around `centerId` loaded and drop the rest, so\n * stepping through the timeline never stalls and memory stays bounded: moving from\n * commit 10 to 11 fetches one delta and disposes one, instead of reloading a window.\n */\n private _slidePrefetchWindow;\n /**\n * Show the model as it stood AT `commit`: the visible baseline is the model at its\n * INITIAL commit, and everything created later lives in per-commit delta .frags loaded\n * as separate models. Those deltas stay loaded (the prefetch window keeps neighbours\n * warm), so stepping BACK has to hide the ones from later commits — otherwise a wall\n * added in commit 3 was still sitting there while you were looking at commit 2.\n * Only touches deltas of the commit's own model; other models keep their own state.\n */\n private _applyFutureVisibility;\n /** Which commit a loaded delta belongs to (deltas are keyed by their hidden id). */\n private _commitOfDelta;\n /** Make every loaded delta visible again (the model as of its latest commit). */\n private _showAllDeltas;\n /** Remove all revit-flow outlines + ghosting and reset the selection. */\n clear(): Promise<void>;\n /** Set what happens to non-commit elements; re-applies to the current commit. */\n setContextMode(mode: ContextMode): Promise<void>;\n /**\n * Every commit that touched `uniqueId`, oldest first, with what happened to it there.\n * The element's life story: created here, edited there, finally deleted.\n */\n elementHistory(uniqueId: string): Array<{\n commit: RevitFlowCommit;\n type: string;\n }>;\n /** Per-author totals across the (optionally date-filtered) history. */\n userActivity(since?: Date): Array<{\n author: string;\n userId?: string;\n commits: number;\n added: number;\n modified: number;\n removed: number;\n last: string;\n }>;\n /**\n * The GUID of whatever is currently selected in the viewer, so the element view can\n * follow the user's selection. Returns null when nothing (or something unresolvable)\n * is selected.\n */\n /** GUIDs of everything currently selected in the viewer (empty when nothing is). */\n selectedGuids(): Promise<string[]>;\n selectedGuid(): Promise<string | null>;\n /**\n * Select every element the commit touched, in the viewer's own selection — so the\n * usual tools (properties, isolate, zoom) work on it like any hand-made selection.\n * Honours the current type filter, so \"only deletions\" selects only those.\n * @returns how many elements ended up selected.\n */\n selectCommitElements(commit: RevitFlowCommit, zoom?: boolean): Promise<number>;\n /** Show/hide one kind of change; re-applies to the current commit. */\n setTypeVisible(kind: ChangeKind, on: boolean): Promise<void>;\n /** @deprecated use setContextMode. */\n setIsolateChanges(on: boolean): Promise<void>;\n /** The shared Outliner component (created on first access by the viewer). */\n private _outliner;\n /**\n * Create the three independently-colored outline groups once. The viewer\n * owns the Outliner's DEFAULT group (selection) — we only add our own named\n * groups and never touch \"default\".\n */\n private _ensureGroups;\n /** Clear our three outline groups only — leaves the viewer's default group. */\n private _clearOutlines;\n /**\n * Resolve each change bucket's GUIDs to localIds across every loaded model\n * and route them to the matching outline group.\n */\n private _outlineCommit;\n /**\n * Remove every localId that `_applySupersededVisibility` has hidden from a change map.\n * Returns a copy: the input maps come from `_buildMap` and are used elsewhere.\n */\n private _dropSuperseded;\n /**\n * Hide (or restore) the elements a commit deleted. Tracked separately from the context\n * modes so switching Colored↔Plain doesn't disturb ghosting or the rest of the model.\n */\n private _applyDeletedVisibility;\n /**\n * Show each element ONCE: from the newest source that supplies it.\n *\n * THE BUG THIS EXISTS FOR. The baseline .frag holds the whole model as of the first\n * commit, and every later commit ships a delta .frag with the geometry it created AND\n * the geometry it modified. Both stay in the scene. For a CREATED element that is\n * right — it exists in exactly one place. For a MODIFIED one it is not: the element is\n * in the baseline at its old shape and in the delta at its new one, and the viewer drew\n * both. Measured 2026-08-05 on a wall whose height Quim raised: the new wall stood\n * proud of the old one, with the coincident faces z-fighting into a dotted band.\n *\n * The rule is the obvious one once stated: for any element, only the newest VISIBLE\n * source may draw it. Deltas are walked newest-first, each guid is claimed by the first\n * source that has it, and every older copy — in an older delta or in the baseline — is\n * hidden. Deltas newer than the commit being shown are already hidden wholesale by\n * `_applyFutureVisibility`, so they never get to claim anything.\n *\n * Restores before it hides, like `_applyDeletedVisibility`, so stepping backwards\n * through the timeline brings the old geometry back rather than accumulating hidden\n * elements until the model is empty.\n */\n private _applySupersededVisibility;\n /** Switch between review colours and the plain post-commit model. */\n setHighlightMode(mode: HighlightMode): Promise<void>;\n /**\n * Make sure the geometry of `deleted` GUIDs is loaded. Anything already resolvable in\n * a loaded model (the usual case: the element shipped in the baseline) needs nothing;\n * for the rest, walk back through the history to the commit that CREATED each one and\n * load that commit's delta, which is the last place its geometry existed.\n */\n private _ensureDeletedGeometry;\n /** GUIDs → { modelId: Set<localId> } across the given models. */\n private _buildMap;\n private _mergeMaps;\n /**\n * Dim (\"ghost\") or hide every element that is NOT part of the shown commit, per the\n * chosen context mode. Best-effort per model: a model that doesn't support the call is\n * simply left alone — the outlines still convey the change.\n */\n private _applyContext;\n /** Undo whatever the context mode did: drop the ghost overlay and restore visibility. */\n private _clearContext;\n /**\n * Kept for the panel's connect hook. Prefetching is now driven by the SELECTION (see\n * _slidePrefetchWindow): nothing is downloaded until a commit is opened, and only its\n * neighbourhood is kept. Warming the newest N up front, as this used to do, spent\n * bandwidth on commits nobody had asked for and grew without bound.\n */\n warmDeltas(): void;\n /** Load a commit's hidden delta .frag (by its hidden id) into the viewer (modelId == hiddenId). */\n private _ensureDeltaLoaded;\n private _setLoading;\n private _firstWorld;\n}\n\n/**\n * GitHistoryManager — headless engine for the revit-flow git-history built-in.\n *\n * Owns ALL viewer mutation for the change outlines. It does NOT load the model —\n * the user opens a model from the Project Files panel, and this manager reacts to\n * that load: it reads the model's hidden `revitflow_history.json` (if any) and\n * publishes the commit list. Showing a commit outlines its changed elements\n * (create → green, update → blue, delete → red) via three independently-colored\n * `OBF.Outliner` groups — a cheap post-process outline that never recolors the\n * fragment geometry. The Lit panel (`top-git-history`) is intent-only: it calls\n * these methods and subscribes to the events below.\n *\n * Data model, per loaded model (fileId == modelId), all HIDDEN children of it:\n * - revitflow_history.json — { model, commits: [{ id, parent, author, source,\n * timestamp, changes:[{type,uniqueId}], counts }] }. The first commit is the\n * INITIAL full-model capture (its geometry == the visible baseline file).\n * - revitflow_frag_<N>.frag — delta fragments for commit N (its created+modified\n * geometry), loaded on demand so created elements can be colored.\n */\nexport type GitHistoryManager = InstanceType<typeof _GitHistoryManager>;\n/**\n * GitHistoryManager — headless engine for the revit-flow git-history built-in.\n *\n * Owns ALL viewer mutation for the change outlines. It does NOT load the model —\n * the user opens a model from the Project Files panel, and this manager reacts to\n * that load: it reads the model's hidden `revitflow_history.json` (if any) and\n * publishes the commit list. Showing a commit outlines its changed elements\n * (create → green, update → blue, delete → red) via three independently-colored\n * `OBF.Outliner` groups — a cheap post-process outline that never recolors the\n * fragment geometry. The Lit panel (`top-git-history`) is intent-only: it calls\n * these methods and subscribes to the events below.\n *\n * Data model, per loaded model (fileId == modelId), all HIDDEN children of it:\n * - revitflow_history.json — { model, commits: [{ id, parent, author, source,\n * timestamp, changes:[{type,uniqueId}], counts }] }. The first commit is the\n * INITIAL full-model capture (its geometry == the visible baseline file).\n * - revitflow_frag_<N>.frag — delta fragments for commit N (its created+modified\n * geometry), loaded on demand so created elements can be colored.\n */\nexport const GitHistoryManager = { uuid: '3f9c1a7e-6b2d-4e18-9a5c-7d0e2f4b6c81' } as typeof _GitHistoryManager & { uuid: '3f9c1a7e-6b2d-4e18-9a5c-7d0e2f4b6c81' };\n\n/**\n * A simple test component to validate the built-in component pipeline.\n * Replace this with real components once the infrastructure is verified.\n */\ndeclare class _HelloWorld extends OBC.Component {\n static readonly uuid: \"2c4ae432-fc24-43e9-9783-0c960c674e96\";\n enabled: boolean;\n readonly name = \"HelloWorld\";\n constructor(components: OBC.Components);\n /**\n * Returns a greeting message and logs it to the console.\n * @param who - The name to greet. Defaults to `\"World\"`.\n */\n greet(who?: string): string;\n}\n/**\n * PlatformComponents.import() expects a `main` variable in scope with\n * a `componentDefinition` property pointing to the OBC.Component class.\n * The IIFE build (name: 'main') assigns this to `var main = ...`.\n */\n\n/**\n * A simple test component to validate the built-in component pipeline.\n * Replace this with real components once the infrastructure is verified.\n */\nexport type HelloWorld = InstanceType<typeof _HelloWorld>;\n/**\n * A simple test component to validate the built-in component pipeline.\n * Replace this with real components once the infrastructure is verified.\n */\nexport const HelloWorld = { uuid: '2c4ae432-fc24-43e9-9783-0c960c674e96' } as typeof _HelloWorld & { uuid: '2c4ae432-fc24-43e9-9783-0c960c674e96' };\n\nexport type ProjectNamespaceKey = \"origin\" | \"georeferencing\" | \"appSettings\";\nexport interface ProjectNamespace {\n label: string;\n description?: string;\n}\nexport interface ProjectEntity<T = unknown> {\n namespaceId: ProjectNamespaceKey;\n label: string;\n description?: string;\n data: T;\n}\n/** GIS origin point that fixes the scene's (0,0,0) to a real-world coordinate. */\nexport interface OriginData {\n lat: number;\n lon: number;\n height: number;\n rotation: number;\n}\n/** Project-wide coordinate reference system + vertical datum config, shared by\n * every asset type that needs to decode raw projected coordinates (point\n * clouds, BIM) — see automatic-file-derived-georeferencing.md\n * (VisorUnificadoAqualia/docs/adrs). One value per project, not per asset:\n * every file at the same real-world site shares the same CRS/geoid. */\nexport interface CrsData {\n /** EPSG code of the project's projected CRS (e.g. 25830 for ETRS89/UTM 30N).\n * EPSG is a global registry, not region-specific — every project has an\n * applicable code, most commonly a standard UTM zone. */\n epsgCode: number;\n /** Geoid undulation in meters at the project's origin (orthometric ->\n * ellipsoidal height correction). Sampled once from a geoid model\n * (client-supplied, or a global EGM2008 fallback) — varies negligibly\n * across a single project's extent, so one scalar per project suffices. */\n geoidUndulation: number;\n}\nexport type AssetCoordinateType = \"splat\" | \"ifc\" | \"point-cloud\" | (string & {});\nexport interface AssetCoordinate {\n fileId: string;\n type: AssetCoordinateType;\n lat: number;\n lon: number;\n height: number;\n rotation: number;\n}\nexport interface GraphicsSettingsData {\n stylePreset: string;\n postproduction: boolean;\n edges: {\n enabled: boolean;\n color: string;\n opacity: number;\n };\n ambientOcclusion: {\n enabled: boolean;\n value: number;\n };\n tonalShading: {\n enabled: boolean;\n value: number;\n };\n surfaceColor: {\n enabled: boolean;\n };\n transparentBackground: {\n enabled: boolean;\n color: string;\n };\n grid: {\n enabled: boolean;\n color: string;\n };\n gridHeight: {\n auto: boolean;\n value: number;\n };\n antiAliasing: boolean;\n nativeResolution: boolean;\n adaptiveResolution: {\n enabled: boolean;\n value: number;\n };\n minResolution: number;\n renderScale: number;\n}\nexport interface ProjectManagerData {\n schemaVersion: 1;\n namespaces: Record<ProjectNamespaceKey, ProjectNamespace>;\n entities: {\n origin: ProjectEntity<OriginData>;\n crs: ProjectEntity<CrsData>;\n assetCoordinates: ProjectEntity<AssetCoordinate[]>;\n graphicsSettings: ProjectEntity<GraphicsSettingsData>;\n };\n}\nexport interface SingletonEntity<T> {\n get(): T | undefined;\n set(data: T): Promise<void>;\n update(partial: Partial<T>): Promise<void>;\n}\n/**\n * A singleton entity that also announces its own changes — for values other\n * code needs to react to live (recompute/reposition something) rather than\n * just read on demand. `onChange` fires with the new value on every\n * `set`/`update`, regardless of whether that change has been persisted yet\n * (see `ProjectManager.dirty`/`onDirtyChange`).\n */\nexport interface ReactiveSingletonEntity<T> extends SingletonEntity<T> {\n onChange: import(\"@thatopen/components\").Event<T>;\n}\nexport interface AssetCoordinatesEntity {\n getAll(): AssetCoordinate[];\n get(fileId: string): AssetCoordinate | undefined;\n getByType(type: AssetCoordinateType): AssetCoordinate[];\n set(fileId: string, data: Omit<AssetCoordinate, \"fileId\">): Promise<void>;\n remove(fileId: string): Promise<void>;\n}\n\n/**\n * ProjectManager is the platform's canonical store for project-level\n * configuration and data — origin/georeferencing/app-settings today, with\n * room to grow. It persists a single JSON file (`${ProjectManager.uuid}.json`)\n * loose directly inside `__project_data` (same folder convention `GISManager`\n * already used) — NOT in a per-app subfolder like `collider`/`cde`, which are\n * for secondary, per-builtin data. Sharing that root folder with other\n * builtins doesn't change its role: it's still the one canonical project\n * record, meant to stop each builtin from inventing its own ad-hoc\n * project-persistence pattern.\n *\n * Schema shape (see `src/types.ts` for the full rationale):\n * - `namespaces`/`entities` are maps keyed by a fixed, readable slug — a\n * closed set this code defines, never created at runtime.\n * - `origin`/`crs`/`graphicsSettings` are singletons; `assetCoordinates` is\n * a collection.\n * - `entities[id]` is a uniform envelope: `namespaceId`, mandatory `label`,\n * optional `description` (omitted, not stored empty), free-form `data`.\n */\ndeclare class _ProjectManager extends OBC.Component {\n static readonly uuid: \"6f3a9c2e-8b1d-4e6a-9c3f-1d7b5a8e2c4f\";\n enabled: boolean;\n /** True once init(client) has been called — safe to use the entity accessors. */\n get ready(): boolean;\n /** Suppress auto-save while bulk-loading data. */\n private _loadingData;\n readonly onSaveStart: OBC.Event<void>;\n readonly onSaveComplete: OBC.Event<boolean>;\n /**\n * Entity ids (e.g. `\"origin\"`) with changes not yet persisted. Most entities\n * auto-save (see `_scheduleSave`) so they're only ever dirty for the instant\n * before their debounce fires — `origin` is the exception: its `set`/`update`\n * mark it dirty WITHOUT scheduling a save (see `origin` below), so a caller\n * driving it continuously (e.g. a drag gizmo) can update it every frame\n * without spamming the network, and a UI can surface \"unsaved changes\" +\n * call `flush()` once the user explicitly confirms.\n *\n * KNOWN GAP: `_doSave()` persists the whole `_data` blob (one JSON file for\n * every entity), so an auto-saving entity's save will also flush out\n * whatever `origin` currently holds in memory, even if the user hasn't\n * confirmed it yet — there's no separate \"committed vs. draft\" copy of\n * `origin`'s data. Accepted for now as a v1 gap (same spirit as this\n * package's other documented v1 gaps, see the ProjectManager ADR); revisit\n * if that coincidence turns out to matter in practice.\n */\n private _dirtyEntities;\n /** True while any entity has unsaved changes. */\n get dirty(): boolean;\n /** Ids of entities with unsaved changes right now. */\n get dirtyEntities(): string[];\n /** Fires with the current `dirtyEntities` list every time it changes. */\n readonly onDirtyChange: OBC.Event<string[]>;\n private _markDirty;\n private _client?;\n private _fileId?;\n private _data;\n private _saveTimer?;\n private _savePromise?;\n private _scheduleSave;\n private _queueSave;\n private _doSave;\n /**\n * Cancels the pending debounce (if any) and runs the save immediately.\n * Also the only way to persist an entity that marks itself dirty WITHOUT\n * auto-scheduling (currently just `origin`) — call this once the user\n * explicitly confirms. Awaits completion.\n */\n flush(): Promise<void>;\n init(client: PlatformClient): Promise<void>;\n /**\n * NOT auto-saving, unlike every other entity below — `set`/`update` mark it\n * dirty and fire `onChange` immediately, but leave persisting up to an\n * explicit `flush()` call. This is what lets a continuous interaction (e.g.\n * a drag gizmo) update `origin` every frame — live for anyone listening to\n * `onChange` — without writing to the network on every tick, while still\n * surfacing \"there's an unconfirmed change\" via `dirty`/`onDirtyChange` for\n * a UI to gate behind an explicit save action.\n */\n origin: ReactiveSingletonEntity<OriginData>;\n crs: ReactiveSingletonEntity<CrsData>;\n graphicsSettings: SingletonEntity<GraphicsSettingsData>;\n assetCoordinates: AssetCoordinatesEntity;\n getNamespaces(): Record<ProjectNamespaceKey, ProjectNamespace>;\n getNamespace(key: ProjectNamespaceKey): Record<string, unknown>;\n}\n\n/**\n * ProjectManager is the platform's canonical store for project-level\n * configuration and data — origin/georeferencing/app-settings today, with\n * room to grow. It persists a single JSON file (`${ProjectManager.uuid}.json`)\n * loose directly inside `__project_data` (same folder convention `GISManager`\n * already used) — NOT in a per-app subfolder like `collider`/`cde`, which are\n * for secondary, per-builtin data. Sharing that root folder with other\n * builtins doesn't change its role: it's still the one canonical project\n * record, meant to stop each builtin from inventing its own ad-hoc\n * project-persistence pattern.\n *\n * Schema shape (see `src/types.ts` for the full rationale):\n * - `namespaces`/`entities` are maps keyed by a fixed, readable slug — a\n * closed set this code defines, never created at runtime.\n * - `origin`/`crs`/`graphicsSettings` are singletons; `assetCoordinates` is\n * a collection.\n * - `entities[id]` is a uniform envelope: `namespaceId`, mandatory `label`,\n * optional `description` (omitted, not stored empty), free-form `data`.\n */\nexport type ProjectManager = InstanceType<typeof _ProjectManager>;\n/**\n * ProjectManager is the platform's canonical store for project-level\n * configuration and data — origin/georeferencing/app-settings today, with\n * room to grow. It persists a single JSON file (`${ProjectManager.uuid}.json`)\n * loose directly inside `__project_data` (same folder convention `GISManager`\n * already used) — NOT in a per-app subfolder like `collider`/`cde`, which are\n * for secondary, per-builtin data. Sharing that root folder with other\n * builtins doesn't change its role: it's still the one canonical project\n * record, meant to stop each builtin from inventing its own ad-hoc\n * project-persistence pattern.\n *\n * Schema shape (see `src/types.ts` for the full rationale):\n * - `namespaces`/`entities` are maps keyed by a fixed, readable slug — a\n * closed set this code defines, never created at runtime.\n * - `origin`/`crs`/`graphicsSettings` are singletons; `assetCoordinates` is\n * a collection.\n * - `entities[id]` is a uniform envelope: `namespaceId`, mandatory `label`,\n * optional `description` (omitted, not stored empty), free-form `data`.\n */\nexport const ProjectManager = { uuid: '6f3a9c2e-8b1d-4e6a-9c3f-1d7b5a8e2c4f' } as typeof _ProjectManager & { uuid: '6f3a9c2e-8b1d-4e6a-9c3f-1d7b5a8e2c4f' };\n\n/** `main.bcf`'s path relative to `__project_data/` — shared with\n * `requestBcfSave` (`UIManager/src/utils/bcf-storage.ts`) so both sides of\n * the save/load round-trip agree on where the file lives. */\nexport declare const BCF_DATA_PATH = \"topics/main.bcf\";\n/** Downloads `__project_data/topics/main.bcf` and loads it into `BCFTopics`,\n * if it already has content. A freshly-created file is empty (0 bytes) —\n * not a valid BCF zip — so there's nothing to load yet in that case. */\nexport declare function loadBcfTopics(client: PlatformClient, projectId: string, components: OBC.Components): Promise<void>;\n\n\n/**\n * Wires up everything `top-topics-panel` (and `clashes-panel`'s \"create\n * topic from clash\" feature) needs to work out of the box: `BCFTopics`\n * configuration (version, author, assignable users — all from real project\n * data), loading whatever BCF was previously saved for this project, and\n * resolving `Viewpoints.world` — including backfilling it onto viewpoints\n * restored from a saved BCF before the 3D world existed yet (`top-viewer`\n * only creates its `World` once `top-app` finishes mounting, which is later\n * than `init()` typically runs).\n */\ndeclare class _TopicsManager extends OBC.Component {\n static readonly uuid: \"69af63aa-19ba-4fc7-b17b-75647bac1d76\";\n enabled: boolean;\n /**\n * Consumer apps call this once — same pattern as `ClashesManager.init(client)`\n * — instead of wiring `BCFTopics.setup()`, loading the saved BCF, and\n * backfilling viewpoint worlds by hand.\n */\n init(client: PlatformClient): Promise<void>;\n private _firstWorld;\n}\n\n/**\n * Wires up everything `top-topics-panel` (and `clashes-panel`'s \"create\n * topic from clash\" feature) needs to work out of the box: `BCFTopics`\n * configuration (version, author, assignable users — all from real project\n * data), loading whatever BCF was previously saved for this project, and\n * resolving `Viewpoints.world` — including backfilling it onto viewpoints\n * restored from a saved BCF before the 3D world existed yet (`top-viewer`\n * only creates its `World` once `top-app` finishes mounting, which is later\n * than `init()` typically runs).\n */\nexport type TopicsManager = InstanceType<typeof _TopicsManager>;\n/**\n * Wires up everything `top-topics-panel` (and `clashes-panel`'s \"create\n * topic from clash\" feature) needs to work out of the box: `BCFTopics`\n * configuration (version, author, assignable users — all from real project\n * data), loading whatever BCF was previously saved for this project, and\n * resolving `Viewpoints.world` — including backfilling it onto viewpoints\n * restored from a saved BCF before the 3D world existed yet (`top-viewer`\n * only creates its `World` once `top-app` finishes mounting, which is later\n * than `init()` typically runs).\n */\nexport const TopicsManager = { uuid: '69af63aa-19ba-4fc7-b17b-75647bac1d76' } as typeof _TopicsManager & { uuid: '69af63aa-19ba-4fc7-b17b-75647bac1d76' };\n\ndeclare class _UIManager extends OBC.Component {\n #private;\n static readonly uuid: \"234f1416-528d-452a-9cc9-a16c5239b2eb\";\n enabled: boolean;\n readonly name = \"UIManager\";\n init(): void;\n}\n\nexport type UIManager = InstanceType<typeof _UIManager>;\nexport const UIManager = { uuid: '234f1416-528d-452a-9cc9-a16c5239b2eb' } as typeof _UIManager & { uuid: '234f1416-528d-452a-9cc9-a16c5239b2eb' };\n"],"names":["PACKET_TYPES","PACKET_TYPES_REVERSE","key","ERROR_PACKET","withNativeBlob","withNativeArrayBuffer","isView","obj","encodePacket","type","data","supportsBinary","callback","encodeBlobAsBase64","fileReader","content","toArray","TEXT_ENCODER","encodePacketToBinary","packet","encoded","chars","lookup","i","decode","base64","bufferLength","len","p","encoded1","encoded2","encoded3","encoded4","arraybuffer","bytes","decodePacket","encodedPacket","binaryType","mapBinary","decodeBase64Packet","decoded","SEPARATOR","encodePayload","packets","length","encodedPackets","count","decodePayload","encodedPayload","decodedPacket","createPacketEncoderStream","controller","payloadLength","header","view","TEXT_DECODER","totalLength","chunks","acc","chunk","concatChunks","size","buffer","j","createPacketDecoderStream","maxPayload","state","expectedLength","isBinary","headerArray","n","protocol","Emitter","mixin","event","fn","on","callbacks","cb","args","nextTick","setTimeoutFn","globalThisShim","defaultBinaryType","pick","attr","k","NATIVE_SET_TIMEOUT","globalThis","NATIVE_CLEAR_TIMEOUT","installTimerFunctions","opts","BASE64_OVERHEAD","byteLength","utf8Length","str","c","l","randomString","encode","qs","qry","pairs","pair","TransportError","reason","description","context","Transport","details","onPause","schema","query","hostname","encodedQuery","Polling","pause","total","close","value","hasCORS","empty","BaseXHR","isSSL","port","req","xhrStatus","Request","createRequest","uri","_a","xhr","e","err","fromError","unloadHandler","terminationEvent","hasXHR2","newRequest","XHR","forceBase64","xdomain","isReactNative","BaseWS","protocols","closeEvent","ev","lastPacket","WebSocketCtor","WS","_packet","WT","stream","decoderStream","reader","encoderStream","read","done","transports","re","parts","parse","src","b","m","pathNames","queryKey","path","regx","names","$0","$1","$2","withEventListeners","OFFLINE_EVENT_LISTENERS","listener","SocketWithoutUpgrade","parsedUri","t","transportName","name","transport","delay","payloadSize","hasExpired","msg","options","cleanupAndClose","waitForUpgrade","SocketWithUpgrade","failed","onTransportOpen","cleanup","freezeTransport","onerror","error","onTransportClose","onclose","onupgrade","to","upgrades","filteredUpgrades","isOptionsOnly","o","DEFAULT_TRANSPORTS","url","loc","host","toString","withNativeFile","hasBinary","toJSON","deconstructPacket","buffers","packetData","pack","_deconstructPacket","placeholder","newData","reconstructPacket","_reconstructPacket","RESERVED_EVENTS","PacketType","Encoder","replacer","deconstruction","Decoder","isBinaryEvent","BinaryReconstructor","start","buf","isInteger","next","payload","isObject","binData","Socket","io","nsp","_b","_c","id","ack","isTransportWritable","isConnected","timeout","timer","resolve","reject","arg1","arg2","responseArgs","force","listeners","self","sent","pid","subDestroy","compress","Backoff","ms","rand","deviation","min","max","jitter","Manager","_parser","parser","v","Engine","socket","openSubDestroy","onError","errorSub","nsps","attempt","cache","parsed","source","sameNamespace","newConnection","DOCUMENT_SCHEMA","DOCUMENT_FILE","versionTag","idOf","item","_ProjectDocuments_instances","descriptorFile_fn","ProjectDocuments","client","projectId","__privateAdd","folderId","file","__privateMethod","text","normalize","formats","descriptor","format","match","blob","existing","found","raw","views","native","hasNative","StaleHistoryError","expectedGuid","actualGuid","ROOT_FOLDER","HISTORY_FILE","OPS_FILE","OPS_SCHEMA","LEGACY_MODEL_FILE","INTERNAL_PREFIX","LOCKS_ANCHOR","childrenOf","folders","parentId","f","_rootFolderId","_ProjectHistory_instances","root_fn","ProjectHistory","root","docs","folder","dash","model","hasAny","docId","FlowDoc","create","__privateGet","made","__privateSet","_folderId","_FlowDoc_instances","documents_get","folderName_get","folder_fn","files_fn","file_fn","modelFile_fn","readJson_fn","readHistory_fn","readOps_fn","writeJson_fn","createJson_fn","writeModel_fn","project","history","orderByGraph","timeline","version","anchor","metas","claims","meta","response","taken","byOwner","claim","list","owner","elements","input","head","lastByGraph","mintGuid","tally","modelFile","hidden","fresh","freshHead","ops","op","index","indexFile","suggestion","holder","opId","outcome","rootId","files","created","changes","counts","change","versions","byGuid","children","roots","parent","byTime","a","ordered","stack","seen","anyCrypto","r","_registry","_Recipes_instances","execute_fn","Recipes","recipe","filter","base","result","plan","targetDoc","STORAGE_BATCH_MAX","parseErrorBody","body","json","retryAfterFromDetails","RequestError","status","statusText","retryAfter","__publicField","FOLDER_PATH","ITEM_PATH","PROCESS_PATH","NPM_REGISTRY_PATH","HIDDEN_PATH","ITEM_TYPE_FILE","ITEM_TYPE_COMPONENT","ITEM_TYPE_APP","RETRY_BASE_DELAY_MS","RETRY_MAX_DELAY_MS","RETRY_JITTER_RATIO","sleep","parseRetryAfter","seconds","timestamp","isRetryable","retryDelayMs","backoff","serverDelay","_EngineServicesClient_instances","buildUrl_fn","requestApi_fn","requestFile_fn","_recipes","requestBatches_fn","downloadItem_fn","createItem_fn","updateItem_fn","getItem_fn","cleanData_fn","_EngineServicesClient","accessToken","apiUrl","props","retries","useBearer","localServerUrl","lsUrl","ctx","globals","method","requestData","filters","archived","fileId","fileData","params","withDraft","metadata","entries","parentFolderId","folderIds","updateFolderParams","ShowVersions","componentId","componentData","componentProps","component","components","resolvedGlobals","keys","values","main","componentDefinition","stubs","builtIns","OBC","BUI","code","appData","appProps","appId","executionParams","executionId","onUpdateCallback","wsUrl","parentFileId","tag","formData","hiddenId","expiresIn","hiddenIds","itemId","icon","extraProps","itemIds","contentType","responseType","retryAttempt","cleanQuery","token","textResponse","retriesLeft","inputs","requestChunk","itemType","parsedBody","showVersions","EngineServicesClient","windowTransport","message","handler","SYSTEM_PREFIX","JOIN_TIMEOUT_MS","guard","_joined","_peers","_pending","_onChange","_onPeerJoined","_onPeerLeft","_ChannelRoom_instances","request_fn","settle_fn","changed_fn","ChannelRoom","controls","peers","peer","from","pending","want","control","entry","_listeners","CollabRoom","set","scope","metaOf","_handlers","ExternalRoom","kind","readMessage","envelope","_transport","_stop","_collab","_externals","_answered","_ChannelClient_instances","rooms_fn","exact_fn","receive_fn","system_fn","deliver_fn","reply_fn","ChannelClient","room","info","rooms","answered","requestId","PROJECT_PATH","NOTIFICATION_PATH","_tokenProvider","_channel","_PlatformClient","accountId","checks","notificationIds","hookId","onEvent","PlatformClient","RESERVED","OP_KEY","SOURCE_KEY","OP_SCHEMA","CATEGORY_CHANGE","CATEGORY_OPERATION","OperationBuilder","target","attrs","placement","kinds","flatbuffers","loadDependencies","deflate","out","num","verb","Attribute","Meshes","Model","SpatialStructure","Transform","containerId","emptyOffsets","shells","circleExtrusions","samples","representations","materials","localTransforms","globalTransforms","meshesItems","materialIds","representationIds","sampleIds","localTransformIds","globalTransformIds","meshes","metadataOffset","unique","attributeOffsets","triples","attributes","uniqueAttributes","s","categoryOffsets","categories","guidOffsets","guidItems","guids","guidsItems","localIds","leaves","_","spatial","modelGuid","cause","METADATA_LIMITS","CDEManager","ClashesManager","FileList","GISManager","GitHistoryManager","HelloWorld","ProjectManager","TopicsManager","UIManager"],"mappings":"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","x_google_ignoreList":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26]}
1
+ {"version":3,"file":"index.es.js","sources":["../node_modules/engine.io-parser/build/esm/commons.js","../node_modules/engine.io-parser/build/esm/encodePacket.browser.js","../node_modules/engine.io-parser/build/esm/contrib/base64-arraybuffer.js","../node_modules/engine.io-parser/build/esm/decodePacket.browser.js","../node_modules/engine.io-parser/build/esm/index.js","../node_modules/@socket.io/component-emitter/lib/esm/index.js","../node_modules/engine.io-client/build/esm/globals.js","../node_modules/engine.io-client/build/esm/util.js","../node_modules/engine.io-client/build/esm/contrib/parseqs.js","../node_modules/engine.io-client/build/esm/transport.js","../node_modules/engine.io-client/build/esm/transports/polling.js","../node_modules/engine.io-client/build/esm/contrib/has-cors.js","../node_modules/engine.io-client/build/esm/transports/polling-xhr.js","../node_modules/engine.io-client/build/esm/transports/websocket.js","../node_modules/engine.io-client/build/esm/transports/webtransport.js","../node_modules/engine.io-client/build/esm/transports/index.js","../node_modules/engine.io-client/build/esm/contrib/parseuri.js","../node_modules/engine.io-client/build/esm/socket.js","../node_modules/socket.io-client/build/esm/url.js","../node_modules/socket.io-parser/build/esm/is-binary.js","../node_modules/socket.io-parser/build/esm/binary.js","../node_modules/socket.io-parser/build/esm/index.js","../node_modules/socket.io-client/build/esm/on.js","../node_modules/socket.io-client/build/esm/socket.js","../node_modules/socket.io-client/build/esm/contrib/backo2.js","../node_modules/socket.io-client/build/esm/manager.js","../node_modules/socket.io-client/build/esm/index.js","../src/core/documents.ts","../src/core/history.ts","../src/core/recipes.ts","../src/types/batch.ts","../src/core/request-error.ts","../src/core/client.ts","../src/core/channel.ts","../src/core/platform-client.ts","../src/core/frag-items.ts","../src/core/op-builder.ts","../src/core/builtin-recipes/shared.ts","../src/core/builtin-recipes/records-to-revit.ts","../src/core/builtin-recipes/rhino-to-revit.ts","../src/core/builtin-recipes/index.ts","../src/types/files.ts","../src/built-in/index.ts"],"sourcesContent":["const PACKET_TYPES = Object.create(null); // no Map = no polyfill\nPACKET_TYPES[\"open\"] = \"0\";\nPACKET_TYPES[\"close\"] = \"1\";\nPACKET_TYPES[\"ping\"] = \"2\";\nPACKET_TYPES[\"pong\"] = \"3\";\nPACKET_TYPES[\"message\"] = \"4\";\nPACKET_TYPES[\"upgrade\"] = \"5\";\nPACKET_TYPES[\"noop\"] = \"6\";\nconst PACKET_TYPES_REVERSE = Object.create(null);\nObject.keys(PACKET_TYPES).forEach((key) => {\n PACKET_TYPES_REVERSE[PACKET_TYPES[key]] = key;\n});\nconst ERROR_PACKET = { type: \"error\", data: \"parser error\" };\nexport { PACKET_TYPES, PACKET_TYPES_REVERSE, ERROR_PACKET };\n","import { PACKET_TYPES } from \"./commons.js\";\nconst withNativeBlob = typeof Blob === \"function\" ||\n (typeof Blob !== \"undefined\" &&\n Object.prototype.toString.call(Blob) === \"[object BlobConstructor]\");\nconst withNativeArrayBuffer = typeof ArrayBuffer === \"function\";\n// ArrayBuffer.isView method is not defined in IE10\nconst isView = (obj) => {\n return typeof ArrayBuffer.isView === \"function\"\n ? ArrayBuffer.isView(obj)\n : obj && obj.buffer instanceof ArrayBuffer;\n};\nconst encodePacket = ({ type, data }, supportsBinary, callback) => {\n if (withNativeBlob && data instanceof Blob) {\n if (supportsBinary) {\n return callback(data);\n }\n else {\n return encodeBlobAsBase64(data, callback);\n }\n }\n else if (withNativeArrayBuffer &&\n (data instanceof ArrayBuffer || isView(data))) {\n if (supportsBinary) {\n return callback(data);\n }\n else {\n return encodeBlobAsBase64(new Blob([data]), callback);\n }\n }\n // plain string\n return callback(PACKET_TYPES[type] + (data || \"\"));\n};\nconst encodeBlobAsBase64 = (data, callback) => {\n const fileReader = new FileReader();\n fileReader.onload = function () {\n const content = fileReader.result.split(\",\")[1];\n callback(\"b\" + (content || \"\"));\n };\n return fileReader.readAsDataURL(data);\n};\nfunction toArray(data) {\n if (data instanceof Uint8Array) {\n return data;\n }\n else if (data instanceof ArrayBuffer) {\n return new Uint8Array(data);\n }\n else {\n return new Uint8Array(data.buffer, data.byteOffset, data.byteLength);\n }\n}\nlet TEXT_ENCODER;\nexport function encodePacketToBinary(packet, callback) {\n if (withNativeBlob && packet.data instanceof Blob) {\n return packet.data.arrayBuffer().then(toArray).then(callback);\n }\n else if (withNativeArrayBuffer &&\n (packet.data instanceof ArrayBuffer || isView(packet.data))) {\n return callback(toArray(packet.data));\n }\n encodePacket(packet, false, (encoded) => {\n if (!TEXT_ENCODER) {\n TEXT_ENCODER = new TextEncoder();\n }\n callback(TEXT_ENCODER.encode(encoded));\n });\n}\nexport { encodePacket };\n","// imported from https://github.com/socketio/base64-arraybuffer\nconst chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';\n// Use a lookup table to find the index.\nconst lookup = typeof Uint8Array === 'undefined' ? [] : new Uint8Array(256);\nfor (let i = 0; i < chars.length; i++) {\n lookup[chars.charCodeAt(i)] = i;\n}\nexport const encode = (arraybuffer) => {\n let bytes = new Uint8Array(arraybuffer), i, len = bytes.length, base64 = '';\n for (i = 0; i < len; i += 3) {\n base64 += chars[bytes[i] >> 2];\n base64 += chars[((bytes[i] & 3) << 4) | (bytes[i + 1] >> 4)];\n base64 += chars[((bytes[i + 1] & 15) << 2) | (bytes[i + 2] >> 6)];\n base64 += chars[bytes[i + 2] & 63];\n }\n if (len % 3 === 2) {\n base64 = base64.substring(0, base64.length - 1) + '=';\n }\n else if (len % 3 === 1) {\n base64 = base64.substring(0, base64.length - 2) + '==';\n }\n return base64;\n};\nexport const decode = (base64) => {\n let bufferLength = base64.length * 0.75, len = base64.length, i, p = 0, encoded1, encoded2, encoded3, encoded4;\n if (base64[base64.length - 1] === '=') {\n bufferLength--;\n if (base64[base64.length - 2] === '=') {\n bufferLength--;\n }\n }\n const arraybuffer = new ArrayBuffer(bufferLength), bytes = new Uint8Array(arraybuffer);\n for (i = 0; i < len; i += 4) {\n encoded1 = lookup[base64.charCodeAt(i)];\n encoded2 = lookup[base64.charCodeAt(i + 1)];\n encoded3 = lookup[base64.charCodeAt(i + 2)];\n encoded4 = lookup[base64.charCodeAt(i + 3)];\n bytes[p++] = (encoded1 << 2) | (encoded2 >> 4);\n bytes[p++] = ((encoded2 & 15) << 4) | (encoded3 >> 2);\n bytes[p++] = ((encoded3 & 3) << 6) | (encoded4 & 63);\n }\n return arraybuffer;\n};\n","import { ERROR_PACKET, PACKET_TYPES_REVERSE, } from \"./commons.js\";\nimport { decode } from \"./contrib/base64-arraybuffer.js\";\nconst withNativeArrayBuffer = typeof ArrayBuffer === \"function\";\nexport const decodePacket = (encodedPacket, binaryType) => {\n if (typeof encodedPacket !== \"string\") {\n return {\n type: \"message\",\n data: mapBinary(encodedPacket, binaryType),\n };\n }\n const type = encodedPacket.charAt(0);\n if (type === \"b\") {\n return {\n type: \"message\",\n data: decodeBase64Packet(encodedPacket.substring(1), binaryType),\n };\n }\n const packetType = PACKET_TYPES_REVERSE[type];\n if (!packetType) {\n return ERROR_PACKET;\n }\n return encodedPacket.length > 1\n ? {\n type: PACKET_TYPES_REVERSE[type],\n data: encodedPacket.substring(1),\n }\n : {\n type: PACKET_TYPES_REVERSE[type],\n };\n};\nconst decodeBase64Packet = (data, binaryType) => {\n if (withNativeArrayBuffer) {\n const decoded = decode(data);\n return mapBinary(decoded, binaryType);\n }\n else {\n return { base64: true, data }; // fallback for old browsers\n }\n};\nconst mapBinary = (data, binaryType) => {\n switch (binaryType) {\n case \"blob\":\n if (data instanceof Blob) {\n // from WebSocket + binaryType \"blob\"\n return data;\n }\n else {\n // from HTTP long-polling or WebTransport\n return new Blob([data]);\n }\n case \"arraybuffer\":\n default:\n if (data instanceof ArrayBuffer) {\n // from HTTP long-polling (base64) or WebSocket + binaryType \"arraybuffer\"\n return data;\n }\n else {\n // from WebTransport (Uint8Array)\n return data.buffer;\n }\n }\n};\n","import { encodePacket, encodePacketToBinary } from \"./encodePacket.js\";\nimport { decodePacket } from \"./decodePacket.js\";\nimport { ERROR_PACKET, } from \"./commons.js\";\nconst SEPARATOR = String.fromCharCode(30); // see https://en.wikipedia.org/wiki/Delimiter#ASCII_delimited_text\nconst encodePayload = (packets, callback) => {\n // some packets may be added to the array while encoding, so the initial length must be saved\n const length = packets.length;\n const encodedPackets = new Array(length);\n let count = 0;\n packets.forEach((packet, i) => {\n // force base64 encoding for binary packets\n encodePacket(packet, false, (encodedPacket) => {\n encodedPackets[i] = encodedPacket;\n if (++count === length) {\n callback(encodedPackets.join(SEPARATOR));\n }\n });\n });\n};\nconst decodePayload = (encodedPayload, binaryType) => {\n const encodedPackets = encodedPayload.split(SEPARATOR);\n const packets = [];\n for (let i = 0; i < encodedPackets.length; i++) {\n const decodedPacket = decodePacket(encodedPackets[i], binaryType);\n packets.push(decodedPacket);\n if (decodedPacket.type === \"error\") {\n break;\n }\n }\n return packets;\n};\nexport function createPacketEncoderStream() {\n return new TransformStream({\n transform(packet, controller) {\n encodePacketToBinary(packet, (encodedPacket) => {\n const payloadLength = encodedPacket.length;\n let header;\n // inspired by the WebSocket format: https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers#decoding_payload_length\n if (payloadLength < 126) {\n header = new Uint8Array(1);\n new DataView(header.buffer).setUint8(0, payloadLength);\n }\n else if (payloadLength < 65536) {\n header = new Uint8Array(3);\n const view = new DataView(header.buffer);\n view.setUint8(0, 126);\n view.setUint16(1, payloadLength);\n }\n else {\n header = new Uint8Array(9);\n const view = new DataView(header.buffer);\n view.setUint8(0, 127);\n view.setBigUint64(1, BigInt(payloadLength));\n }\n // first bit indicates whether the payload is plain text (0) or binary (1)\n if (packet.data && typeof packet.data !== \"string\") {\n header[0] |= 0x80;\n }\n controller.enqueue(header);\n controller.enqueue(encodedPacket);\n });\n },\n });\n}\nlet TEXT_DECODER;\nfunction totalLength(chunks) {\n return chunks.reduce((acc, chunk) => acc + chunk.length, 0);\n}\nfunction concatChunks(chunks, size) {\n if (chunks[0].length === size) {\n return chunks.shift();\n }\n const buffer = new Uint8Array(size);\n let j = 0;\n for (let i = 0; i < size; i++) {\n buffer[i] = chunks[0][j++];\n if (j === chunks[0].length) {\n chunks.shift();\n j = 0;\n }\n }\n if (chunks.length && j < chunks[0].length) {\n chunks[0] = chunks[0].slice(j);\n }\n return buffer;\n}\nexport function createPacketDecoderStream(maxPayload, binaryType) {\n if (!TEXT_DECODER) {\n TEXT_DECODER = new TextDecoder();\n }\n const chunks = [];\n let state = 0 /* State.READ_HEADER */;\n let expectedLength = -1;\n let isBinary = false;\n return new TransformStream({\n transform(chunk, controller) {\n chunks.push(chunk);\n while (true) {\n if (state === 0 /* State.READ_HEADER */) {\n if (totalLength(chunks) < 1) {\n break;\n }\n const header = concatChunks(chunks, 1);\n isBinary = (header[0] & 0x80) === 0x80;\n expectedLength = header[0] & 0x7f;\n if (expectedLength < 126) {\n state = 3 /* State.READ_PAYLOAD */;\n }\n else if (expectedLength === 126) {\n state = 1 /* State.READ_EXTENDED_LENGTH_16 */;\n }\n else {\n state = 2 /* State.READ_EXTENDED_LENGTH_64 */;\n }\n }\n else if (state === 1 /* State.READ_EXTENDED_LENGTH_16 */) {\n if (totalLength(chunks) < 2) {\n break;\n }\n const headerArray = concatChunks(chunks, 2);\n expectedLength = new DataView(headerArray.buffer, headerArray.byteOffset, headerArray.length).getUint16(0);\n state = 3 /* State.READ_PAYLOAD */;\n }\n else if (state === 2 /* State.READ_EXTENDED_LENGTH_64 */) {\n if (totalLength(chunks) < 8) {\n break;\n }\n const headerArray = concatChunks(chunks, 8);\n const view = new DataView(headerArray.buffer, headerArray.byteOffset, headerArray.length);\n const n = view.getUint32(0);\n if (n > Math.pow(2, 53 - 32) - 1) {\n // the maximum safe integer in JavaScript is 2^53 - 1\n controller.enqueue(ERROR_PACKET);\n break;\n }\n expectedLength = n * Math.pow(2, 32) + view.getUint32(4);\n state = 3 /* State.READ_PAYLOAD */;\n }\n else {\n if (totalLength(chunks) < expectedLength) {\n break;\n }\n const data = concatChunks(chunks, expectedLength);\n controller.enqueue(decodePacket(isBinary ? data : TEXT_DECODER.decode(data), binaryType));\n state = 0 /* State.READ_HEADER */;\n }\n if (expectedLength === 0 || expectedLength > maxPayload) {\n controller.enqueue(ERROR_PACKET);\n break;\n }\n }\n },\n });\n}\nexport const protocol = 4;\nexport { encodePacket, encodePayload, decodePacket, decodePayload, };\n","/**\n * Initialize a new `Emitter`.\n *\n * @api public\n */\n\nexport function Emitter(obj) {\n if (obj) return mixin(obj);\n}\n\n/**\n * Mixin the emitter properties.\n *\n * @param {Object} obj\n * @return {Object}\n * @api private\n */\n\nfunction mixin(obj) {\n for (var key in Emitter.prototype) {\n obj[key] = Emitter.prototype[key];\n }\n return obj;\n}\n\n/**\n * Listen on the given `event` with `fn`.\n *\n * @param {String} event\n * @param {Function} fn\n * @return {Emitter}\n * @api public\n */\n\nEmitter.prototype.on =\nEmitter.prototype.addEventListener = function(event, fn){\n this._callbacks = this._callbacks || {};\n (this._callbacks['$' + event] = this._callbacks['$' + event] || [])\n .push(fn);\n return this;\n};\n\n/**\n * Adds an `event` listener that will be invoked a single\n * time then automatically removed.\n *\n * @param {String} event\n * @param {Function} fn\n * @return {Emitter}\n * @api public\n */\n\nEmitter.prototype.once = function(event, fn){\n function on() {\n this.off(event, on);\n fn.apply(this, arguments);\n }\n\n on.fn = fn;\n this.on(event, on);\n return this;\n};\n\n/**\n * Remove the given callback for `event` or all\n * registered callbacks.\n *\n * @param {String} event\n * @param {Function} fn\n * @return {Emitter}\n * @api public\n */\n\nEmitter.prototype.off =\nEmitter.prototype.removeListener =\nEmitter.prototype.removeAllListeners =\nEmitter.prototype.removeEventListener = function(event, fn){\n this._callbacks = this._callbacks || {};\n\n // all\n if (0 == arguments.length) {\n this._callbacks = {};\n return this;\n }\n\n // specific event\n var callbacks = this._callbacks['$' + event];\n if (!callbacks) return this;\n\n // remove all handlers\n if (1 == arguments.length) {\n delete this._callbacks['$' + event];\n return this;\n }\n\n // remove specific handler\n var cb;\n for (var i = 0; i < callbacks.length; i++) {\n cb = callbacks[i];\n if (cb === fn || cb.fn === fn) {\n callbacks.splice(i, 1);\n break;\n }\n }\n\n // Remove event specific arrays for event types that no\n // one is subscribed for to avoid memory leak.\n if (callbacks.length === 0) {\n delete this._callbacks['$' + event];\n }\n\n return this;\n};\n\n/**\n * Emit `event` with the given args.\n *\n * @param {String} event\n * @param {Mixed} ...\n * @return {Emitter}\n */\n\nEmitter.prototype.emit = function(event){\n this._callbacks = this._callbacks || {};\n\n var args = new Array(arguments.length - 1)\n , callbacks = this._callbacks['$' + event];\n\n for (var i = 1; i < arguments.length; i++) {\n args[i - 1] = arguments[i];\n }\n\n if (callbacks) {\n callbacks = callbacks.slice(0);\n for (var i = 0, len = callbacks.length; i < len; ++i) {\n callbacks[i].apply(this, args);\n }\n }\n\n return this;\n};\n\n// alias used for reserved events (protected method)\nEmitter.prototype.emitReserved = Emitter.prototype.emit;\n\n/**\n * Return array of callbacks for `event`.\n *\n * @param {String} event\n * @return {Array}\n * @api public\n */\n\nEmitter.prototype.listeners = function(event){\n this._callbacks = this._callbacks || {};\n return this._callbacks['$' + event] || [];\n};\n\n/**\n * Check if this emitter has `event` handlers.\n *\n * @param {String} event\n * @return {Boolean}\n * @api public\n */\n\nEmitter.prototype.hasListeners = function(event){\n return !! this.listeners(event).length;\n};\n","export const nextTick = (() => {\n const isPromiseAvailable = typeof Promise === \"function\" && typeof Promise.resolve === \"function\";\n if (isPromiseAvailable) {\n return (cb) => Promise.resolve().then(cb);\n }\n else {\n return (cb, setTimeoutFn) => setTimeoutFn(cb, 0);\n }\n})();\nexport const globalThisShim = (() => {\n if (typeof self !== \"undefined\") {\n return self;\n }\n else if (typeof window !== \"undefined\") {\n return window;\n }\n else {\n return Function(\"return this\")();\n }\n})();\nexport const defaultBinaryType = \"arraybuffer\";\nexport function createCookieJar() { }\n","import { globalThisShim as globalThis } from \"./globals.node.js\";\nexport function pick(obj, ...attr) {\n return attr.reduce((acc, k) => {\n if (obj.hasOwnProperty(k)) {\n acc[k] = obj[k];\n }\n return acc;\n }, {});\n}\n// Keep a reference to the real timeout functions so they can be used when overridden\nconst NATIVE_SET_TIMEOUT = globalThis.setTimeout;\nconst NATIVE_CLEAR_TIMEOUT = globalThis.clearTimeout;\nexport function installTimerFunctions(obj, opts) {\n if (opts.useNativeTimers) {\n obj.setTimeoutFn = NATIVE_SET_TIMEOUT.bind(globalThis);\n obj.clearTimeoutFn = NATIVE_CLEAR_TIMEOUT.bind(globalThis);\n }\n else {\n obj.setTimeoutFn = globalThis.setTimeout.bind(globalThis);\n obj.clearTimeoutFn = globalThis.clearTimeout.bind(globalThis);\n }\n}\n// base64 encoded buffers are about 33% bigger (https://en.wikipedia.org/wiki/Base64)\nconst BASE64_OVERHEAD = 1.33;\n// we could also have used `new Blob([obj]).size`, but it isn't supported in IE9\nexport function byteLength(obj) {\n if (typeof obj === \"string\") {\n return utf8Length(obj);\n }\n // arraybuffer or blob\n return Math.ceil((obj.byteLength || obj.size) * BASE64_OVERHEAD);\n}\nfunction utf8Length(str) {\n let c = 0, length = 0;\n for (let i = 0, l = str.length; i < l; i++) {\n c = str.charCodeAt(i);\n if (c < 0x80) {\n length += 1;\n }\n else if (c < 0x800) {\n length += 2;\n }\n else if (c < 0xd800 || c >= 0xe000) {\n length += 3;\n }\n else {\n i++;\n length += 4;\n }\n }\n return length;\n}\n/**\n * Generates a random 8-characters string.\n */\nexport function randomString() {\n return (Date.now().toString(36).substring(3) +\n Math.random().toString(36).substring(2, 5));\n}\n","// imported from https://github.com/galkn/querystring\n/**\n * Compiles a querystring\n * Returns string representation of the object\n *\n * @param {Object}\n * @api private\n */\nexport function encode(obj) {\n let str = '';\n for (let i in obj) {\n if (obj.hasOwnProperty(i)) {\n if (str.length)\n str += '&';\n str += encodeURIComponent(i) + '=' + encodeURIComponent(obj[i]);\n }\n }\n return str;\n}\n/**\n * Parses a simple querystring into an object\n *\n * @param {String} qs\n * @api private\n */\nexport function decode(qs) {\n let qry = {};\n let pairs = qs.split('&');\n for (let i = 0, l = pairs.length; i < l; i++) {\n let pair = pairs[i].split('=');\n qry[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1]);\n }\n return qry;\n}\n","import { decodePacket } from \"engine.io-parser\";\nimport { Emitter } from \"@socket.io/component-emitter\";\nimport { installTimerFunctions } from \"./util.js\";\nimport { encode } from \"./contrib/parseqs.js\";\nexport class TransportError extends Error {\n constructor(reason, description, context) {\n super(reason);\n this.description = description;\n this.context = context;\n this.type = \"TransportError\";\n }\n}\nexport class Transport extends Emitter {\n /**\n * Transport abstract constructor.\n *\n * @param {Object} opts - options\n * @protected\n */\n constructor(opts) {\n super();\n this.writable = false;\n installTimerFunctions(this, opts);\n this.opts = opts;\n this.query = opts.query;\n this.socket = opts.socket;\n this.supportsBinary = !opts.forceBase64;\n }\n /**\n * Emits an error.\n *\n * @param {String} reason\n * @param description\n * @param context - the error context\n * @return {Transport} for chaining\n * @protected\n */\n onError(reason, description, context) {\n super.emitReserved(\"error\", new TransportError(reason, description, context));\n return this;\n }\n /**\n * Opens the transport.\n */\n open() {\n this.readyState = \"opening\";\n this.doOpen();\n return this;\n }\n /**\n * Closes the transport.\n */\n close() {\n if (this.readyState === \"opening\" || this.readyState === \"open\") {\n this.doClose();\n this.onClose();\n }\n return this;\n }\n /**\n * Sends multiple packets.\n *\n * @param {Array} packets\n */\n send(packets) {\n if (this.readyState === \"open\") {\n this.write(packets);\n }\n else {\n // this might happen if the transport was silently closed in the beforeunload event handler\n }\n }\n /**\n * Called upon open\n *\n * @protected\n */\n onOpen() {\n this.readyState = \"open\";\n this.writable = true;\n super.emitReserved(\"open\");\n }\n /**\n * Called with data.\n *\n * @param {String} data\n * @protected\n */\n onData(data) {\n const packet = decodePacket(data, this.socket.binaryType);\n this.onPacket(packet);\n }\n /**\n * Called with a decoded packet.\n *\n * @protected\n */\n onPacket(packet) {\n super.emitReserved(\"packet\", packet);\n }\n /**\n * Called upon close.\n *\n * @protected\n */\n onClose(details) {\n this.readyState = \"closed\";\n super.emitReserved(\"close\", details);\n }\n /**\n * Pauses the transport, in order not to lose packets during an upgrade.\n *\n * @param onPause\n */\n pause(onPause) { }\n createUri(schema, query = {}) {\n return (schema +\n \"://\" +\n this._hostname() +\n this._port() +\n this.opts.path +\n this._query(query));\n }\n _hostname() {\n const hostname = this.opts.hostname;\n return hostname.indexOf(\":\") === -1 ? hostname : \"[\" + hostname + \"]\";\n }\n _port() {\n if (this.opts.port &&\n ((this.opts.secure && Number(this.opts.port) !== 443) ||\n (!this.opts.secure && Number(this.opts.port) !== 80))) {\n return \":\" + this.opts.port;\n }\n else {\n return \"\";\n }\n }\n _query(query) {\n const encodedQuery = encode(query);\n return encodedQuery.length ? \"?\" + encodedQuery : \"\";\n }\n}\n","import { Transport } from \"../transport.js\";\nimport { randomString } from \"../util.js\";\nimport { encodePayload, decodePayload } from \"engine.io-parser\";\nexport class Polling extends Transport {\n constructor() {\n super(...arguments);\n this._polling = false;\n }\n get name() {\n return \"polling\";\n }\n /**\n * Opens the socket (triggers polling). We write a PING message to determine\n * when the transport is open.\n *\n * @protected\n */\n doOpen() {\n this._poll();\n }\n /**\n * Pauses polling.\n *\n * @param {Function} onPause - callback upon buffers are flushed and transport is paused\n * @package\n */\n pause(onPause) {\n this.readyState = \"pausing\";\n const pause = () => {\n this.readyState = \"paused\";\n onPause();\n };\n if (this._polling || !this.writable) {\n let total = 0;\n if (this._polling) {\n total++;\n this.once(\"pollComplete\", function () {\n --total || pause();\n });\n }\n if (!this.writable) {\n total++;\n this.once(\"drain\", function () {\n --total || pause();\n });\n }\n }\n else {\n pause();\n }\n }\n /**\n * Starts polling cycle.\n *\n * @private\n */\n _poll() {\n this._polling = true;\n this.doPoll();\n this.emitReserved(\"poll\");\n }\n /**\n * Overloads onData to detect payloads.\n *\n * @protected\n */\n onData(data) {\n const callback = (packet) => {\n // if its the first message we consider the transport open\n if (\"opening\" === this.readyState && packet.type === \"open\") {\n this.onOpen();\n }\n // if its a close packet, we close the ongoing requests\n if (\"close\" === packet.type) {\n this.onClose({ description: \"transport closed by the server\" });\n return false;\n }\n // otherwise bypass onData and handle the message\n this.onPacket(packet);\n };\n // decode payload\n decodePayload(data, this.socket.binaryType).forEach(callback);\n // if an event did not trigger closing\n if (\"closed\" !== this.readyState) {\n // if we got data we're not polling\n this._polling = false;\n this.emitReserved(\"pollComplete\");\n if (\"open\" === this.readyState) {\n this._poll();\n }\n else {\n }\n }\n }\n /**\n * For polling, send a close packet.\n *\n * @protected\n */\n doClose() {\n const close = () => {\n this.write([{ type: \"close\" }]);\n };\n if (\"open\" === this.readyState) {\n close();\n }\n else {\n // in case we're trying to close while\n // handshaking is in progress (GH-164)\n this.once(\"open\", close);\n }\n }\n /**\n * Writes a packets payload.\n *\n * @param {Array} packets - data packets\n * @protected\n */\n write(packets) {\n this.writable = false;\n encodePayload(packets, (data) => {\n this.doWrite(data, () => {\n this.writable = true;\n this.emitReserved(\"drain\");\n });\n });\n }\n /**\n * Generates uri for connection.\n *\n * @private\n */\n uri() {\n const schema = this.opts.secure ? \"https\" : \"http\";\n const query = this.query || {};\n // cache busting is forced\n if (false !== this.opts.timestampRequests) {\n query[this.opts.timestampParam] = randomString();\n }\n if (!this.supportsBinary && !query.sid) {\n query.b64 = 1;\n }\n return this.createUri(schema, query);\n }\n}\n","// imported from https://github.com/component/has-cors\nlet value = false;\ntry {\n value = typeof XMLHttpRequest !== 'undefined' &&\n 'withCredentials' in new XMLHttpRequest();\n}\ncatch (err) {\n // if XMLHttp support is disabled in IE then it will throw\n // when trying to create\n}\nexport const hasCORS = value;\n","import { Polling } from \"./polling.js\";\nimport { Emitter } from \"@socket.io/component-emitter\";\nimport { installTimerFunctions, pick } from \"../util.js\";\nimport { globalThisShim as globalThis } from \"../globals.node.js\";\nimport { hasCORS } from \"../contrib/has-cors.js\";\nfunction empty() { }\nexport class BaseXHR extends Polling {\n /**\n * XHR Polling constructor.\n *\n * @param {Object} opts\n * @package\n */\n constructor(opts) {\n super(opts);\n if (typeof location !== \"undefined\") {\n const isSSL = \"https:\" === location.protocol;\n let port = location.port;\n // some user agents have empty `location.port`\n if (!port) {\n port = isSSL ? \"443\" : \"80\";\n }\n this.xd =\n (typeof location !== \"undefined\" &&\n opts.hostname !== location.hostname) ||\n port !== opts.port;\n }\n }\n /**\n * Sends data.\n *\n * @param {String} data - data to send.\n * @param {Function} fn - called upon flush.\n * @private\n */\n doWrite(data, fn) {\n const req = this.request({\n method: \"POST\",\n data: data,\n });\n req.on(\"success\", fn);\n req.on(\"error\", (xhrStatus, context) => {\n this.onError(\"xhr post error\", xhrStatus, context);\n });\n }\n /**\n * Starts a poll cycle.\n *\n * @private\n */\n doPoll() {\n const req = this.request();\n req.on(\"data\", this.onData.bind(this));\n req.on(\"error\", (xhrStatus, context) => {\n this.onError(\"xhr poll error\", xhrStatus, context);\n });\n this.pollXhr = req;\n }\n}\nexport class Request extends Emitter {\n /**\n * Request constructor\n *\n * @param {Object} options\n * @package\n */\n constructor(createRequest, uri, opts) {\n super();\n this.createRequest = createRequest;\n installTimerFunctions(this, opts);\n this._opts = opts;\n this._method = opts.method || \"GET\";\n this._uri = uri;\n this._data = undefined !== opts.data ? opts.data : null;\n this._create();\n }\n /**\n * Creates the XHR object and sends the request.\n *\n * @private\n */\n _create() {\n var _a;\n const opts = pick(this._opts, \"agent\", \"pfx\", \"key\", \"passphrase\", \"cert\", \"ca\", \"ciphers\", \"rejectUnauthorized\", \"autoUnref\");\n opts.xdomain = !!this._opts.xd;\n const xhr = (this._xhr = this.createRequest(opts));\n try {\n xhr.open(this._method, this._uri, true);\n try {\n if (this._opts.extraHeaders) {\n // @ts-ignore\n xhr.setDisableHeaderCheck && xhr.setDisableHeaderCheck(true);\n for (let i in this._opts.extraHeaders) {\n if (this._opts.extraHeaders.hasOwnProperty(i)) {\n xhr.setRequestHeader(i, this._opts.extraHeaders[i]);\n }\n }\n }\n }\n catch (e) { }\n if (\"POST\" === this._method) {\n try {\n xhr.setRequestHeader(\"Content-type\", \"text/plain;charset=UTF-8\");\n }\n catch (e) { }\n }\n try {\n xhr.setRequestHeader(\"Accept\", \"*/*\");\n }\n catch (e) { }\n (_a = this._opts.cookieJar) === null || _a === void 0 ? void 0 : _a.addCookies(xhr);\n // ie6 check\n if (\"withCredentials\" in xhr) {\n xhr.withCredentials = this._opts.withCredentials;\n }\n if (this._opts.requestTimeout) {\n xhr.timeout = this._opts.requestTimeout;\n }\n xhr.onreadystatechange = () => {\n var _a;\n if (xhr.readyState === 3) {\n (_a = this._opts.cookieJar) === null || _a === void 0 ? void 0 : _a.parseCookies(\n // @ts-ignore\n xhr.getResponseHeader(\"set-cookie\"));\n }\n if (4 !== xhr.readyState)\n return;\n if (200 === xhr.status || 1223 === xhr.status) {\n this._onLoad();\n }\n else {\n // make sure the `error` event handler that's user-set\n // does not throw in the same tick and gets caught here\n this.setTimeoutFn(() => {\n this._onError(typeof xhr.status === \"number\" ? xhr.status : 0);\n }, 0);\n }\n };\n xhr.send(this._data);\n }\n catch (e) {\n // Need to defer since .create() is called directly from the constructor\n // and thus the 'error' event can only be only bound *after* this exception\n // occurs. Therefore, also, we cannot throw here at all.\n this.setTimeoutFn(() => {\n this._onError(e);\n }, 0);\n return;\n }\n if (typeof document !== \"undefined\") {\n this._index = Request.requestsCount++;\n Request.requests[this._index] = this;\n }\n }\n /**\n * Called upon error.\n *\n * @private\n */\n _onError(err) {\n this.emitReserved(\"error\", err, this._xhr);\n this._cleanup(true);\n }\n /**\n * Cleans up house.\n *\n * @private\n */\n _cleanup(fromError) {\n if (\"undefined\" === typeof this._xhr || null === this._xhr) {\n return;\n }\n this._xhr.onreadystatechange = empty;\n if (fromError) {\n try {\n this._xhr.abort();\n }\n catch (e) { }\n }\n if (typeof document !== \"undefined\") {\n delete Request.requests[this._index];\n }\n this._xhr = null;\n }\n /**\n * Called upon load.\n *\n * @private\n */\n _onLoad() {\n const data = this._xhr.responseText;\n if (data !== null) {\n this.emitReserved(\"data\", data);\n this.emitReserved(\"success\");\n this._cleanup();\n }\n }\n /**\n * Aborts the request.\n *\n * @package\n */\n abort() {\n this._cleanup();\n }\n}\nRequest.requestsCount = 0;\nRequest.requests = {};\n/**\n * Aborts pending requests when unloading the window. This is needed to prevent\n * memory leaks (e.g. when using IE) and to ensure that no spurious error is\n * emitted.\n */\nif (typeof document !== \"undefined\") {\n // @ts-ignore\n if (typeof attachEvent === \"function\") {\n // @ts-ignore\n attachEvent(\"onunload\", unloadHandler);\n }\n else if (typeof addEventListener === \"function\") {\n const terminationEvent = \"onpagehide\" in globalThis ? \"pagehide\" : \"unload\";\n addEventListener(terminationEvent, unloadHandler, false);\n }\n}\nfunction unloadHandler() {\n for (let i in Request.requests) {\n if (Request.requests.hasOwnProperty(i)) {\n Request.requests[i].abort();\n }\n }\n}\nconst hasXHR2 = (function () {\n const xhr = newRequest({\n xdomain: false,\n });\n return xhr && xhr.responseType !== null;\n})();\n/**\n * HTTP long-polling based on the built-in `XMLHttpRequest` object.\n *\n * Usage: browser\n *\n * @see https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest\n */\nexport class XHR extends BaseXHR {\n constructor(opts) {\n super(opts);\n const forceBase64 = opts && opts.forceBase64;\n this.supportsBinary = hasXHR2 && !forceBase64;\n }\n request(opts = {}) {\n Object.assign(opts, { xd: this.xd }, this.opts);\n return new Request(newRequest, this.uri(), opts);\n }\n}\nfunction newRequest(opts) {\n const xdomain = opts.xdomain;\n // XMLHttpRequest can be disabled on IE\n try {\n if (\"undefined\" !== typeof XMLHttpRequest && (!xdomain || hasCORS)) {\n return new XMLHttpRequest();\n }\n }\n catch (e) { }\n if (!xdomain) {\n try {\n return new globalThis[[\"Active\"].concat(\"Object\").join(\"X\")](\"Microsoft.XMLHTTP\");\n }\n catch (e) { }\n }\n}\n","import { Transport } from \"../transport.js\";\nimport { pick, randomString } from \"../util.js\";\nimport { encodePacket } from \"engine.io-parser\";\nimport { globalThisShim as globalThis, nextTick } from \"../globals.node.js\";\n// detect ReactNative environment\nconst isReactNative = typeof navigator !== \"undefined\" &&\n typeof navigator.product === \"string\" &&\n navigator.product.toLowerCase() === \"reactnative\";\nexport class BaseWS extends Transport {\n get name() {\n return \"websocket\";\n }\n doOpen() {\n const uri = this.uri();\n const protocols = this.opts.protocols;\n // React Native only supports the 'headers' option, and will print a warning if anything else is passed\n const opts = isReactNative\n ? {}\n : pick(this.opts, \"agent\", \"perMessageDeflate\", \"pfx\", \"key\", \"passphrase\", \"cert\", \"ca\", \"ciphers\", \"rejectUnauthorized\", \"localAddress\", \"protocolVersion\", \"origin\", \"maxPayload\", \"family\", \"checkServerIdentity\");\n if (this.opts.extraHeaders) {\n opts.headers = this.opts.extraHeaders;\n }\n try {\n this.ws = this.createSocket(uri, protocols, opts);\n }\n catch (err) {\n return this.emitReserved(\"error\", err);\n }\n this.ws.binaryType = this.socket.binaryType;\n this.addEventListeners();\n }\n /**\n * Adds event listeners to the socket\n *\n * @private\n */\n addEventListeners() {\n this.ws.onopen = () => {\n if (this.opts.autoUnref) {\n this.ws._socket.unref();\n }\n this.onOpen();\n };\n this.ws.onclose = (closeEvent) => this.onClose({\n description: \"websocket connection closed\",\n context: closeEvent,\n });\n this.ws.onmessage = (ev) => this.onData(ev.data);\n this.ws.onerror = (e) => this.onError(\"websocket error\", e);\n }\n write(packets) {\n this.writable = false;\n // encodePacket efficient as it uses WS framing\n // no need for encodePayload\n for (let i = 0; i < packets.length; i++) {\n const packet = packets[i];\n const lastPacket = i === packets.length - 1;\n encodePacket(packet, this.supportsBinary, (data) => {\n // Sometimes the websocket has already been closed but the browser didn't\n // have a chance of informing us about it yet, in that case send will\n // throw an error\n try {\n this.doWrite(packet, data);\n }\n catch (e) {\n }\n if (lastPacket) {\n // fake drain\n // defer to next tick to allow Socket to clear writeBuffer\n nextTick(() => {\n this.writable = true;\n this.emitReserved(\"drain\");\n }, this.setTimeoutFn);\n }\n });\n }\n }\n doClose() {\n if (typeof this.ws !== \"undefined\") {\n this.ws.onerror = () => { };\n this.ws.close();\n this.ws = null;\n }\n }\n /**\n * Generates uri for connection.\n *\n * @private\n */\n uri() {\n const schema = this.opts.secure ? \"wss\" : \"ws\";\n const query = this.query || {};\n // append timestamp to URI\n if (this.opts.timestampRequests) {\n query[this.opts.timestampParam] = randomString();\n }\n // communicate binary support capabilities\n if (!this.supportsBinary) {\n query.b64 = 1;\n }\n return this.createUri(schema, query);\n }\n}\nconst WebSocketCtor = globalThis.WebSocket || globalThis.MozWebSocket;\n/**\n * WebSocket transport based on the built-in `WebSocket` object.\n *\n * Usage: browser, Node.js (since v21), Deno, Bun\n *\n * @see https://developer.mozilla.org/en-US/docs/Web/API/WebSocket\n * @see https://caniuse.com/mdn-api_websocket\n * @see https://nodejs.org/api/globals.html#websocket\n */\nexport class WS extends BaseWS {\n createSocket(uri, protocols, opts) {\n return !isReactNative\n ? protocols\n ? new WebSocketCtor(uri, protocols)\n : new WebSocketCtor(uri)\n : new WebSocketCtor(uri, protocols, opts);\n }\n doWrite(_packet, data) {\n this.ws.send(data);\n }\n}\n","import { Transport } from \"../transport.js\";\nimport { nextTick } from \"../globals.node.js\";\nimport { createPacketDecoderStream, createPacketEncoderStream, } from \"engine.io-parser\";\n/**\n * WebTransport transport based on the built-in `WebTransport` object.\n *\n * Usage: browser, Node.js (with the `@fails-components/webtransport` package)\n *\n * @see https://developer.mozilla.org/en-US/docs/Web/API/WebTransport\n * @see https://caniuse.com/webtransport\n */\nexport class WT extends Transport {\n get name() {\n return \"webtransport\";\n }\n doOpen() {\n try {\n // @ts-ignore\n this._transport = new WebTransport(this.createUri(\"https\"), this.opts.transportOptions[this.name]);\n }\n catch (err) {\n return this.emitReserved(\"error\", err);\n }\n this._transport.closed\n .then(() => {\n this.onClose();\n })\n .catch((err) => {\n this.onError(\"webtransport error\", err);\n });\n // note: we could have used async/await, but that would require some additional polyfills\n this._transport.ready.then(() => {\n this._transport.createBidirectionalStream().then((stream) => {\n const decoderStream = createPacketDecoderStream(Number.MAX_SAFE_INTEGER, this.socket.binaryType);\n const reader = stream.readable.pipeThrough(decoderStream).getReader();\n const encoderStream = createPacketEncoderStream();\n encoderStream.readable.pipeTo(stream.writable);\n this._writer = encoderStream.writable.getWriter();\n const read = () => {\n reader\n .read()\n .then(({ done, value }) => {\n if (done) {\n return;\n }\n this.onPacket(value);\n read();\n })\n .catch((err) => {\n });\n };\n read();\n const packet = { type: \"open\" };\n if (this.query.sid) {\n packet.data = `{\"sid\":\"${this.query.sid}\"}`;\n }\n this._writer.write(packet).then(() => this.onOpen());\n });\n });\n }\n write(packets) {\n this.writable = false;\n for (let i = 0; i < packets.length; i++) {\n const packet = packets[i];\n const lastPacket = i === packets.length - 1;\n this._writer.write(packet).then(() => {\n if (lastPacket) {\n nextTick(() => {\n this.writable = true;\n this.emitReserved(\"drain\");\n }, this.setTimeoutFn);\n }\n });\n }\n }\n doClose() {\n var _a;\n (_a = this._transport) === null || _a === void 0 ? void 0 : _a.close();\n }\n}\n","import { XHR } from \"./polling-xhr.node.js\";\nimport { WS } from \"./websocket.node.js\";\nimport { WT } from \"./webtransport.js\";\nexport const transports = {\n websocket: WS,\n webtransport: WT,\n polling: XHR,\n};\n","// imported from https://github.com/galkn/parseuri\n/**\n * Parses a URI\n *\n * Note: we could also have used the built-in URL object, but it isn't supported on all platforms.\n *\n * See:\n * - https://developer.mozilla.org/en-US/docs/Web/API/URL\n * - https://caniuse.com/url\n * - https://www.rfc-editor.org/rfc/rfc3986#appendix-B\n *\n * History of the parse() method:\n * - first commit: https://github.com/socketio/socket.io-client/commit/4ee1d5d94b3906a9c052b459f1a818b15f38f91c\n * - export into its own module: https://github.com/socketio/engine.io-client/commit/de2c561e4564efeb78f1bdb1ba39ef81b2822cb3\n * - reimport: https://github.com/socketio/engine.io-client/commit/df32277c3f6d622eec5ed09f493cae3f3391d242\n *\n * @author Steven Levithan <stevenlevithan.com> (MIT license)\n * @api private\n */\nconst re = /^(?:(?![^:@\\/?#]+:[^:@\\/]*@)(http|https|ws|wss):\\/\\/)?((?:(([^:@\\/?#]*)(?::([^:@\\/?#]*))?)?@)?((?:[a-f0-9]{0,4}:){2,7}[a-f0-9]{0,4}|[^:\\/?#]*)(?::(\\d*))?)(((\\/(?:[^?#](?![^?#\\/]*\\.[^?#\\/.]+(?:[?#]|$)))*\\/?)?([^?#\\/]*))(?:\\?([^#]*))?(?:#(.*))?)/;\nconst parts = [\n 'source', 'protocol', 'authority', 'userInfo', 'user', 'password', 'host', 'port', 'relative', 'path', 'directory', 'file', 'query', 'anchor'\n];\nexport function parse(str) {\n if (str.length > 8000) {\n throw \"URI too long\";\n }\n const src = str, b = str.indexOf('['), e = str.indexOf(']');\n if (b != -1 && e != -1) {\n str = str.substring(0, b) + str.substring(b, e).replace(/:/g, ';') + str.substring(e, str.length);\n }\n let m = re.exec(str || ''), uri = {}, i = 14;\n while (i--) {\n uri[parts[i]] = m[i] || '';\n }\n if (b != -1 && e != -1) {\n uri.source = src;\n uri.host = uri.host.substring(1, uri.host.length - 1).replace(/;/g, ':');\n uri.authority = uri.authority.replace('[', '').replace(']', '').replace(/;/g, ':');\n uri.ipv6uri = true;\n }\n uri.pathNames = pathNames(uri, uri['path']);\n uri.queryKey = queryKey(uri, uri['query']);\n return uri;\n}\nfunction pathNames(obj, path) {\n const regx = /\\/{2,9}/g, names = path.replace(regx, \"/\").split(\"/\");\n if (path.slice(0, 1) == '/' || path.length === 0) {\n names.splice(0, 1);\n }\n if (path.slice(-1) == '/') {\n names.splice(names.length - 1, 1);\n }\n return names;\n}\nfunction queryKey(uri, query) {\n const data = {};\n query.replace(/(?:^|&)([^&=]*)=?([^&]*)/g, function ($0, $1, $2) {\n if ($1) {\n data[$1] = $2;\n }\n });\n return data;\n}\n","import { transports as DEFAULT_TRANSPORTS } from \"./transports/index.js\";\nimport { installTimerFunctions, byteLength } from \"./util.js\";\nimport { decode } from \"./contrib/parseqs.js\";\nimport { parse } from \"./contrib/parseuri.js\";\nimport { Emitter } from \"@socket.io/component-emitter\";\nimport { protocol } from \"engine.io-parser\";\nimport { createCookieJar, defaultBinaryType, nextTick, } from \"./globals.node.js\";\nconst withEventListeners = typeof addEventListener === \"function\" &&\n typeof removeEventListener === \"function\";\nconst OFFLINE_EVENT_LISTENERS = [];\nif (withEventListeners) {\n // within a ServiceWorker, any event handler for the 'offline' event must be added on the initial evaluation of the\n // script, so we create one single event listener here which will forward the event to the socket instances\n addEventListener(\"offline\", () => {\n OFFLINE_EVENT_LISTENERS.forEach((listener) => listener());\n }, false);\n}\n/**\n * This class provides a WebSocket-like interface to connect to an Engine.IO server. The connection will be established\n * with one of the available low-level transports, like HTTP long-polling, WebSocket or WebTransport.\n *\n * This class comes without upgrade mechanism, which means that it will keep the first low-level transport that\n * successfully establishes the connection.\n *\n * In order to allow tree-shaking, there are no transports included, that's why the `transports` option is mandatory.\n *\n * @example\n * import { SocketWithoutUpgrade, WebSocket } from \"engine.io-client\";\n *\n * const socket = new SocketWithoutUpgrade({\n * transports: [WebSocket]\n * });\n *\n * socket.on(\"open\", () => {\n * socket.send(\"hello\");\n * });\n *\n * @see SocketWithUpgrade\n * @see Socket\n */\nexport class SocketWithoutUpgrade extends Emitter {\n /**\n * Socket constructor.\n *\n * @param {String|Object} uri - uri or options\n * @param {Object} opts - options\n */\n constructor(uri, opts) {\n super();\n this.binaryType = defaultBinaryType;\n this.writeBuffer = [];\n this._prevBufferLen = 0;\n this._pingInterval = -1;\n this._pingTimeout = -1;\n this._maxPayload = -1;\n /**\n * The expiration timestamp of the {@link _pingTimeoutTimer} object is tracked, in case the timer is throttled and the\n * callback is not fired on time. This can happen for example when a laptop is suspended or when a phone is locked.\n */\n this._pingTimeoutTime = Infinity;\n if (uri && \"object\" === typeof uri) {\n opts = uri;\n uri = null;\n }\n if (uri) {\n const parsedUri = parse(uri);\n opts.hostname = parsedUri.host;\n opts.secure =\n parsedUri.protocol === \"https\" || parsedUri.protocol === \"wss\";\n opts.port = parsedUri.port;\n if (parsedUri.query)\n opts.query = parsedUri.query;\n }\n else if (opts.host) {\n opts.hostname = parse(opts.host).host;\n }\n installTimerFunctions(this, opts);\n this.secure =\n null != opts.secure\n ? opts.secure\n : typeof location !== \"undefined\" && \"https:\" === location.protocol;\n if (opts.hostname && !opts.port) {\n // if no port is specified manually, use the protocol default\n opts.port = this.secure ? \"443\" : \"80\";\n }\n this.hostname =\n opts.hostname ||\n (typeof location !== \"undefined\" ? location.hostname : \"localhost\");\n this.port =\n opts.port ||\n (typeof location !== \"undefined\" && location.port\n ? location.port\n : this.secure\n ? \"443\"\n : \"80\");\n this.transports = [];\n this._transportsByName = {};\n opts.transports.forEach((t) => {\n const transportName = t.prototype.name;\n this.transports.push(transportName);\n this._transportsByName[transportName] = t;\n });\n this.opts = Object.assign({\n path: \"/engine.io\",\n agent: false,\n withCredentials: false,\n upgrade: true,\n timestampParam: \"t\",\n rememberUpgrade: false,\n addTrailingSlash: true,\n rejectUnauthorized: true,\n perMessageDeflate: {\n threshold: 1024,\n },\n transportOptions: {},\n closeOnBeforeunload: false,\n }, opts);\n this.opts.path =\n this.opts.path.replace(/\\/$/, \"\") +\n (this.opts.addTrailingSlash ? \"/\" : \"\");\n if (typeof this.opts.query === \"string\") {\n this.opts.query = decode(this.opts.query);\n }\n if (withEventListeners) {\n if (this.opts.closeOnBeforeunload) {\n // Firefox closes the connection when the \"beforeunload\" event is emitted but not Chrome. This event listener\n // ensures every browser behaves the same (no \"disconnect\" event at the Socket.IO level when the page is\n // closed/reloaded)\n this._beforeunloadEventListener = () => {\n if (this.transport) {\n // silently close the transport\n this.transport.removeAllListeners();\n this.transport.close();\n }\n };\n addEventListener(\"beforeunload\", this._beforeunloadEventListener, false);\n }\n if (this.hostname !== \"localhost\") {\n this._offlineEventListener = () => {\n this._onClose(\"transport close\", {\n description: \"network connection lost\",\n });\n };\n OFFLINE_EVENT_LISTENERS.push(this._offlineEventListener);\n }\n }\n if (this.opts.withCredentials) {\n this._cookieJar = createCookieJar();\n }\n this._open();\n }\n /**\n * Creates transport of the given type.\n *\n * @param {String} name - transport name\n * @return {Transport}\n * @private\n */\n createTransport(name) {\n const query = Object.assign({}, this.opts.query);\n // append engine.io protocol identifier\n query.EIO = protocol;\n // transport name\n query.transport = name;\n // session id if we already have one\n if (this.id)\n query.sid = this.id;\n const opts = Object.assign({}, this.opts, {\n query,\n socket: this,\n hostname: this.hostname,\n secure: this.secure,\n port: this.port,\n }, this.opts.transportOptions[name]);\n return new this._transportsByName[name](opts);\n }\n /**\n * Initializes transport to use and starts probe.\n *\n * @private\n */\n _open() {\n if (this.transports.length === 0) {\n // Emit error on next tick so it can be listened to\n this.setTimeoutFn(() => {\n this.emitReserved(\"error\", \"No transports available\");\n }, 0);\n return;\n }\n const transportName = this.opts.rememberUpgrade &&\n SocketWithoutUpgrade.priorWebsocketSuccess &&\n this.transports.indexOf(\"websocket\") !== -1\n ? \"websocket\"\n : this.transports[0];\n this.readyState = \"opening\";\n const transport = this.createTransport(transportName);\n transport.open();\n this.setTransport(transport);\n }\n /**\n * Sets the current transport. Disables the existing one (if any).\n *\n * @private\n */\n setTransport(transport) {\n if (this.transport) {\n this.transport.removeAllListeners();\n }\n // set up transport\n this.transport = transport;\n // set up transport listeners\n transport\n .on(\"drain\", this._onDrain.bind(this))\n .on(\"packet\", this._onPacket.bind(this))\n .on(\"error\", this._onError.bind(this))\n .on(\"close\", (reason) => this._onClose(\"transport close\", reason));\n }\n /**\n * Called when connection is deemed open.\n *\n * @private\n */\n onOpen() {\n this.readyState = \"open\";\n SocketWithoutUpgrade.priorWebsocketSuccess =\n \"websocket\" === this.transport.name;\n this.emitReserved(\"open\");\n this.flush();\n }\n /**\n * Handles a packet.\n *\n * @private\n */\n _onPacket(packet) {\n if (\"opening\" === this.readyState ||\n \"open\" === this.readyState ||\n \"closing\" === this.readyState) {\n this.emitReserved(\"packet\", packet);\n // Socket is live - any packet counts\n this.emitReserved(\"heartbeat\");\n switch (packet.type) {\n case \"open\":\n this.onHandshake(JSON.parse(packet.data));\n break;\n case \"ping\":\n this._sendPacket(\"pong\");\n this.emitReserved(\"ping\");\n this.emitReserved(\"pong\");\n this._resetPingTimeout();\n break;\n case \"error\":\n const err = new Error(\"server error\");\n // @ts-ignore\n err.code = packet.data;\n this._onError(err);\n break;\n case \"message\":\n this.emitReserved(\"data\", packet.data);\n this.emitReserved(\"message\", packet.data);\n break;\n }\n }\n else {\n }\n }\n /**\n * Called upon handshake completion.\n *\n * @param {Object} data - handshake obj\n * @private\n */\n onHandshake(data) {\n this.emitReserved(\"handshake\", data);\n this.id = data.sid;\n this.transport.query.sid = data.sid;\n this._pingInterval = data.pingInterval;\n this._pingTimeout = data.pingTimeout;\n this._maxPayload = data.maxPayload;\n this.onOpen();\n // In case open handler closes socket\n if (\"closed\" === this.readyState)\n return;\n this._resetPingTimeout();\n }\n /**\n * Sets and resets ping timeout timer based on server pings.\n *\n * @private\n */\n _resetPingTimeout() {\n this.clearTimeoutFn(this._pingTimeoutTimer);\n const delay = this._pingInterval + this._pingTimeout;\n this._pingTimeoutTime = Date.now() + delay;\n this._pingTimeoutTimer = this.setTimeoutFn(() => {\n this._onClose(\"ping timeout\");\n }, delay);\n if (this.opts.autoUnref) {\n this._pingTimeoutTimer.unref();\n }\n }\n /**\n * Called on `drain` event\n *\n * @private\n */\n _onDrain() {\n this.writeBuffer.splice(0, this._prevBufferLen);\n // setting prevBufferLen = 0 is very important\n // for example, when upgrading, upgrade packet is sent over,\n // and a nonzero prevBufferLen could cause problems on `drain`\n this._prevBufferLen = 0;\n if (0 === this.writeBuffer.length) {\n this.emitReserved(\"drain\");\n }\n else {\n this.flush();\n }\n }\n /**\n * Flush write buffers.\n *\n * @private\n */\n flush() {\n if (\"closed\" !== this.readyState &&\n this.transport.writable &&\n !this.upgrading &&\n this.writeBuffer.length) {\n const packets = this._getWritablePackets();\n this.transport.send(packets);\n // keep track of current length of writeBuffer\n // splice writeBuffer and callbackBuffer on `drain`\n this._prevBufferLen = packets.length;\n this.emitReserved(\"flush\");\n }\n }\n /**\n * Ensure the encoded size of the writeBuffer is below the maxPayload value sent by the server (only for HTTP\n * long-polling)\n *\n * @private\n */\n _getWritablePackets() {\n const shouldCheckPayloadSize = this._maxPayload &&\n this.transport.name === \"polling\" &&\n this.writeBuffer.length > 1;\n if (!shouldCheckPayloadSize) {\n return this.writeBuffer;\n }\n let payloadSize = 1; // first packet type\n for (let i = 0; i < this.writeBuffer.length; i++) {\n const data = this.writeBuffer[i].data;\n if (data) {\n payloadSize += byteLength(data);\n }\n if (i > 0 && payloadSize > this._maxPayload) {\n return this.writeBuffer.slice(0, i);\n }\n payloadSize += 2; // separator + packet type\n }\n return this.writeBuffer;\n }\n /**\n * Checks whether the heartbeat timer has expired but the socket has not yet been notified.\n *\n * Note: this method is private for now because it does not really fit the WebSocket API, but if we put it in the\n * `write()` method then the message would not be buffered by the Socket.IO client.\n *\n * @return {boolean}\n * @private\n */\n /* private */ _hasPingExpired() {\n if (!this._pingTimeoutTime)\n return true;\n const hasExpired = Date.now() > this._pingTimeoutTime;\n if (hasExpired) {\n this._pingTimeoutTime = 0;\n nextTick(() => {\n this._onClose(\"ping timeout\");\n }, this.setTimeoutFn);\n }\n return hasExpired;\n }\n /**\n * Sends a message.\n *\n * @param {String} msg - message.\n * @param {Object} options.\n * @param {Function} fn - callback function.\n * @return {Socket} for chaining.\n */\n write(msg, options, fn) {\n this._sendPacket(\"message\", msg, options, fn);\n return this;\n }\n /**\n * Sends a message. Alias of {@link Socket#write}.\n *\n * @param {String} msg - message.\n * @param {Object} options.\n * @param {Function} fn - callback function.\n * @return {Socket} for chaining.\n */\n send(msg, options, fn) {\n this._sendPacket(\"message\", msg, options, fn);\n return this;\n }\n /**\n * Sends a packet.\n *\n * @param {String} type - packet type.\n * @param {String} data.\n * @param {Object} options.\n * @param {Function} fn - callback function.\n * @private\n */\n _sendPacket(type, data, options, fn) {\n if (\"function\" === typeof data) {\n fn = data;\n data = undefined;\n }\n if (\"function\" === typeof options) {\n fn = options;\n options = null;\n }\n if (\"closing\" === this.readyState || \"closed\" === this.readyState) {\n return;\n }\n options = options || {};\n options.compress = false !== options.compress;\n const packet = {\n type: type,\n data: data,\n options: options,\n };\n this.emitReserved(\"packetCreate\", packet);\n this.writeBuffer.push(packet);\n if (fn)\n this.once(\"flush\", fn);\n this.flush();\n }\n /**\n * Closes the connection.\n */\n close() {\n const close = () => {\n this._onClose(\"forced close\");\n this.transport.close();\n };\n const cleanupAndClose = () => {\n this.off(\"upgrade\", cleanupAndClose);\n this.off(\"upgradeError\", cleanupAndClose);\n close();\n };\n const waitForUpgrade = () => {\n // wait for upgrade to finish since we can't send packets while pausing a transport\n this.once(\"upgrade\", cleanupAndClose);\n this.once(\"upgradeError\", cleanupAndClose);\n };\n if (\"opening\" === this.readyState || \"open\" === this.readyState) {\n this.readyState = \"closing\";\n if (this.writeBuffer.length) {\n this.once(\"drain\", () => {\n if (this.upgrading) {\n waitForUpgrade();\n }\n else {\n close();\n }\n });\n }\n else if (this.upgrading) {\n waitForUpgrade();\n }\n else {\n close();\n }\n }\n return this;\n }\n /**\n * Called upon transport error\n *\n * @private\n */\n _onError(err) {\n SocketWithoutUpgrade.priorWebsocketSuccess = false;\n if (this.opts.tryAllTransports &&\n this.transports.length > 1 &&\n this.readyState === \"opening\") {\n this.transports.shift();\n return this._open();\n }\n this.emitReserved(\"error\", err);\n this._onClose(\"transport error\", err);\n }\n /**\n * Called upon transport close.\n *\n * @private\n */\n _onClose(reason, description) {\n if (\"opening\" === this.readyState ||\n \"open\" === this.readyState ||\n \"closing\" === this.readyState) {\n // clear timers\n this.clearTimeoutFn(this._pingTimeoutTimer);\n // stop event from firing again for transport\n this.transport.removeAllListeners(\"close\");\n // ensure transport won't stay open\n this.transport.close();\n // ignore further transport communication\n this.transport.removeAllListeners();\n if (withEventListeners) {\n if (this._beforeunloadEventListener) {\n removeEventListener(\"beforeunload\", this._beforeunloadEventListener, false);\n }\n if (this._offlineEventListener) {\n const i = OFFLINE_EVENT_LISTENERS.indexOf(this._offlineEventListener);\n if (i !== -1) {\n OFFLINE_EVENT_LISTENERS.splice(i, 1);\n }\n }\n }\n // set ready state\n this.readyState = \"closed\";\n // clear session id\n this.id = null;\n // emit close event\n this.emitReserved(\"close\", reason, description);\n // clean buffers after, so users can still\n // grab the buffers on `close` event\n this.writeBuffer = [];\n this._prevBufferLen = 0;\n }\n }\n}\nSocketWithoutUpgrade.protocol = protocol;\n/**\n * This class provides a WebSocket-like interface to connect to an Engine.IO server. The connection will be established\n * with one of the available low-level transports, like HTTP long-polling, WebSocket or WebTransport.\n *\n * This class comes with an upgrade mechanism, which means that once the connection is established with the first\n * low-level transport, it will try to upgrade to a better transport.\n *\n * In order to allow tree-shaking, there are no transports included, that's why the `transports` option is mandatory.\n *\n * @example\n * import { SocketWithUpgrade, WebSocket } from \"engine.io-client\";\n *\n * const socket = new SocketWithUpgrade({\n * transports: [WebSocket]\n * });\n *\n * socket.on(\"open\", () => {\n * socket.send(\"hello\");\n * });\n *\n * @see SocketWithoutUpgrade\n * @see Socket\n */\nexport class SocketWithUpgrade extends SocketWithoutUpgrade {\n constructor() {\n super(...arguments);\n this._upgrades = [];\n }\n onOpen() {\n super.onOpen();\n if (\"open\" === this.readyState && this.opts.upgrade) {\n for (let i = 0; i < this._upgrades.length; i++) {\n this._probe(this._upgrades[i]);\n }\n }\n }\n /**\n * Probes a transport.\n *\n * @param {String} name - transport name\n * @private\n */\n _probe(name) {\n let transport = this.createTransport(name);\n let failed = false;\n SocketWithoutUpgrade.priorWebsocketSuccess = false;\n const onTransportOpen = () => {\n if (failed)\n return;\n transport.send([{ type: \"ping\", data: \"probe\" }]);\n transport.once(\"packet\", (msg) => {\n if (failed)\n return;\n if (\"pong\" === msg.type && \"probe\" === msg.data) {\n this.upgrading = true;\n this.emitReserved(\"upgrading\", transport);\n if (!transport)\n return;\n SocketWithoutUpgrade.priorWebsocketSuccess =\n \"websocket\" === transport.name;\n this.transport.pause(() => {\n if (failed)\n return;\n if (\"closed\" === this.readyState)\n return;\n cleanup();\n this.setTransport(transport);\n transport.send([{ type: \"upgrade\" }]);\n this.emitReserved(\"upgrade\", transport);\n transport = null;\n this.upgrading = false;\n this.flush();\n });\n }\n else {\n const err = new Error(\"probe error\");\n // @ts-ignore\n err.transport = transport.name;\n this.emitReserved(\"upgradeError\", err);\n }\n });\n };\n function freezeTransport() {\n if (failed)\n return;\n // Any callback called by transport should be ignored since now\n failed = true;\n cleanup();\n transport.close();\n transport = null;\n }\n // Handle any error that happens while probing\n const onerror = (err) => {\n const error = new Error(\"probe error: \" + err);\n // @ts-ignore\n error.transport = transport.name;\n freezeTransport();\n this.emitReserved(\"upgradeError\", error);\n };\n function onTransportClose() {\n onerror(\"transport closed\");\n }\n // When the socket is closed while we're probing\n function onclose() {\n onerror(\"socket closed\");\n }\n // When the socket is upgraded while we're probing\n function onupgrade(to) {\n if (transport && to.name !== transport.name) {\n freezeTransport();\n }\n }\n // Remove all listeners on the transport and on self\n const cleanup = () => {\n transport.removeListener(\"open\", onTransportOpen);\n transport.removeListener(\"error\", onerror);\n transport.removeListener(\"close\", onTransportClose);\n this.off(\"close\", onclose);\n this.off(\"upgrading\", onupgrade);\n };\n transport.once(\"open\", onTransportOpen);\n transport.once(\"error\", onerror);\n transport.once(\"close\", onTransportClose);\n this.once(\"close\", onclose);\n this.once(\"upgrading\", onupgrade);\n if (this._upgrades.indexOf(\"webtransport\") !== -1 &&\n name !== \"webtransport\") {\n // favor WebTransport\n this.setTimeoutFn(() => {\n if (!failed) {\n transport.open();\n }\n }, 200);\n }\n else {\n transport.open();\n }\n }\n onHandshake(data) {\n this._upgrades = this._filterUpgrades(data.upgrades);\n super.onHandshake(data);\n }\n /**\n * Filters upgrades, returning only those matching client transports.\n *\n * @param {Array} upgrades - server upgrades\n * @private\n */\n _filterUpgrades(upgrades) {\n const filteredUpgrades = [];\n for (let i = 0; i < upgrades.length; i++) {\n if (~this.transports.indexOf(upgrades[i]))\n filteredUpgrades.push(upgrades[i]);\n }\n return filteredUpgrades;\n }\n}\n/**\n * This class provides a WebSocket-like interface to connect to an Engine.IO server. The connection will be established\n * with one of the available low-level transports, like HTTP long-polling, WebSocket or WebTransport.\n *\n * This class comes with an upgrade mechanism, which means that once the connection is established with the first\n * low-level transport, it will try to upgrade to a better transport.\n *\n * @example\n * import { Socket } from \"engine.io-client\";\n *\n * const socket = new Socket();\n *\n * socket.on(\"open\", () => {\n * socket.send(\"hello\");\n * });\n *\n * @see SocketWithoutUpgrade\n * @see SocketWithUpgrade\n */\nexport class Socket extends SocketWithUpgrade {\n constructor(uri, opts = {}) {\n const isOptionsOnly = typeof uri === \"object\";\n const o = isOptionsOnly ? { ...uri } : { ...opts };\n if (!o.transports ||\n (o.transports && typeof o.transports[0] === \"string\")) {\n o.transports = (o.transports || [\"polling\", \"websocket\", \"webtransport\"])\n .map((transportName) => DEFAULT_TRANSPORTS[transportName])\n .filter((t) => !!t);\n }\n super(isOptionsOnly ? o : uri, o);\n }\n}\n","import { parse } from \"engine.io-client\";\n/**\n * URL parser.\n *\n * @param uri - url\n * @param path - the request path of the connection\n * @param loc - An object meant to mimic window.location.\n * Defaults to window.location.\n * @public\n */\nexport function url(uri, path = \"\", loc) {\n let obj = uri;\n // default to window.location\n loc = loc || (typeof location !== \"undefined\" && location);\n if (null == uri)\n uri = loc.protocol + \"//\" + loc.host;\n // relative path support\n if (typeof uri === \"string\") {\n if (\"/\" === uri.charAt(0)) {\n if (\"/\" === uri.charAt(1)) {\n uri = loc.protocol + uri;\n }\n else {\n uri = loc.host + uri;\n }\n }\n if (!/^(https?|wss?):\\/\\//.test(uri)) {\n if (\"undefined\" !== typeof loc) {\n uri = loc.protocol + \"//\" + uri;\n }\n else {\n uri = \"https://\" + uri;\n }\n }\n // parse\n obj = parse(uri);\n }\n // make sure we treat `localhost:80` and `localhost` equally\n if (!obj.port) {\n if (/^(http|ws)$/.test(obj.protocol)) {\n obj.port = \"80\";\n }\n else if (/^(http|ws)s$/.test(obj.protocol)) {\n obj.port = \"443\";\n }\n }\n obj.path = obj.path || \"/\";\n const ipv6 = obj.host.indexOf(\":\") !== -1;\n const host = ipv6 ? \"[\" + obj.host + \"]\" : obj.host;\n // define unique id\n obj.id = obj.protocol + \"://\" + host + \":\" + obj.port + path;\n // define href\n obj.href =\n obj.protocol +\n \"://\" +\n host +\n (loc && loc.port === obj.port ? \"\" : \":\" + obj.port);\n return obj;\n}\n","const withNativeArrayBuffer = typeof ArrayBuffer === \"function\";\nconst isView = (obj) => {\n return typeof ArrayBuffer.isView === \"function\"\n ? ArrayBuffer.isView(obj)\n : obj.buffer instanceof ArrayBuffer;\n};\nconst toString = Object.prototype.toString;\nconst withNativeBlob = typeof Blob === \"function\" ||\n (typeof Blob !== \"undefined\" &&\n toString.call(Blob) === \"[object BlobConstructor]\");\nconst withNativeFile = typeof File === \"function\" ||\n (typeof File !== \"undefined\" &&\n toString.call(File) === \"[object FileConstructor]\");\n/**\n * Returns true if obj is a Buffer, an ArrayBuffer, a Blob or a File.\n *\n * @private\n */\nexport function isBinary(obj) {\n return ((withNativeArrayBuffer && (obj instanceof ArrayBuffer || isView(obj))) ||\n (withNativeBlob && obj instanceof Blob) ||\n (withNativeFile && obj instanceof File));\n}\nexport function hasBinary(obj, toJSON) {\n if (!obj || typeof obj !== \"object\") {\n return false;\n }\n if (Array.isArray(obj)) {\n for (let i = 0, l = obj.length; i < l; i++) {\n if (hasBinary(obj[i])) {\n return true;\n }\n }\n return false;\n }\n if (isBinary(obj)) {\n return true;\n }\n if (obj.toJSON &&\n typeof obj.toJSON === \"function\" &&\n arguments.length === 1) {\n return hasBinary(obj.toJSON(), true);\n }\n for (const key in obj) {\n if (Object.prototype.hasOwnProperty.call(obj, key) && hasBinary(obj[key])) {\n return true;\n }\n }\n return false;\n}\n","import { isBinary } from \"./is-binary.js\";\n/**\n * Replaces every Buffer | ArrayBuffer | Blob | File in packet with a numbered placeholder.\n *\n * @param {Object} packet - socket.io event packet\n * @return {Object} with deconstructed packet and list of buffers\n * @public\n */\nexport function deconstructPacket(packet) {\n const buffers = [];\n const packetData = packet.data;\n const pack = packet;\n pack.data = _deconstructPacket(packetData, buffers);\n pack.attachments = buffers.length; // number of binary 'attachments'\n return { packet: pack, buffers: buffers };\n}\nfunction _deconstructPacket(data, buffers) {\n if (!data)\n return data;\n if (isBinary(data)) {\n const placeholder = { _placeholder: true, num: buffers.length };\n buffers.push(data);\n return placeholder;\n }\n else if (Array.isArray(data)) {\n const newData = new Array(data.length);\n for (let i = 0; i < data.length; i++) {\n newData[i] = _deconstructPacket(data[i], buffers);\n }\n return newData;\n }\n else if (typeof data === \"object\" && !(data instanceof Date)) {\n const newData = {};\n for (const key in data) {\n if (Object.prototype.hasOwnProperty.call(data, key)) {\n newData[key] = _deconstructPacket(data[key], buffers);\n }\n }\n return newData;\n }\n return data;\n}\n/**\n * Reconstructs a binary packet from its placeholder packet and buffers\n *\n * @param {Object} packet - event packet with placeholders\n * @param {Array} buffers - binary buffers to put in placeholder positions\n * @return {Object} reconstructed packet\n * @public\n */\nexport function reconstructPacket(packet, buffers) {\n packet.data = _reconstructPacket(packet.data, buffers);\n delete packet.attachments; // no longer useful\n return packet;\n}\nfunction _reconstructPacket(data, buffers) {\n if (!data)\n return data;\n if (data && data._placeholder === true) {\n const isIndexValid = typeof data.num === \"number\" &&\n data.num >= 0 &&\n data.num < buffers.length;\n if (isIndexValid) {\n return buffers[data.num]; // appropriate buffer (should be natural order anyway)\n }\n else {\n throw new Error(\"illegal attachments\");\n }\n }\n else if (Array.isArray(data)) {\n for (let i = 0; i < data.length; i++) {\n data[i] = _reconstructPacket(data[i], buffers);\n }\n }\n else if (typeof data === \"object\") {\n for (const key in data) {\n if (Object.prototype.hasOwnProperty.call(data, key)) {\n data[key] = _reconstructPacket(data[key], buffers);\n }\n }\n }\n return data;\n}\n","import { Emitter } from \"@socket.io/component-emitter\";\nimport { deconstructPacket, reconstructPacket } from \"./binary.js\";\nimport { isBinary, hasBinary } from \"./is-binary.js\";\n/**\n * These strings must not be used as event names, as they have a special meaning.\n */\nconst RESERVED_EVENTS = [\n \"connect\", // used on the client side\n \"connect_error\", // used on the client side\n \"disconnect\", // used on both sides\n \"disconnecting\", // used on the server side\n \"newListener\", // used by the Node.js EventEmitter\n \"removeListener\", // used by the Node.js EventEmitter\n];\n/**\n * Protocol version.\n *\n * @public\n */\nexport const protocol = 5;\nexport var PacketType;\n(function (PacketType) {\n PacketType[PacketType[\"CONNECT\"] = 0] = \"CONNECT\";\n PacketType[PacketType[\"DISCONNECT\"] = 1] = \"DISCONNECT\";\n PacketType[PacketType[\"EVENT\"] = 2] = \"EVENT\";\n PacketType[PacketType[\"ACK\"] = 3] = \"ACK\";\n PacketType[PacketType[\"CONNECT_ERROR\"] = 4] = \"CONNECT_ERROR\";\n PacketType[PacketType[\"BINARY_EVENT\"] = 5] = \"BINARY_EVENT\";\n PacketType[PacketType[\"BINARY_ACK\"] = 6] = \"BINARY_ACK\";\n})(PacketType || (PacketType = {}));\n/**\n * A socket.io Encoder instance\n */\nexport class Encoder {\n /**\n * Encoder constructor\n *\n * @param {function} replacer - custom replacer to pass down to JSON.parse\n */\n constructor(replacer) {\n this.replacer = replacer;\n }\n /**\n * Encode a packet as a single string if non-binary, or as a\n * buffer sequence, depending on packet type.\n *\n * @param {Object} obj - packet object\n */\n encode(obj) {\n if (obj.type === PacketType.EVENT || obj.type === PacketType.ACK) {\n if (hasBinary(obj)) {\n return this.encodeAsBinary({\n type: obj.type === PacketType.EVENT\n ? PacketType.BINARY_EVENT\n : PacketType.BINARY_ACK,\n nsp: obj.nsp,\n data: obj.data,\n id: obj.id,\n });\n }\n }\n return [this.encodeAsString(obj)];\n }\n /**\n * Encode packet as string.\n */\n encodeAsString(obj) {\n // first is type\n let str = \"\" + obj.type;\n // attachments if we have them\n if (obj.type === PacketType.BINARY_EVENT ||\n obj.type === PacketType.BINARY_ACK) {\n str += obj.attachments + \"-\";\n }\n // if we have a namespace other than `/`\n // we append it followed by a comma `,`\n if (obj.nsp && \"/\" !== obj.nsp) {\n str += obj.nsp + \",\";\n }\n // immediately followed by the id\n if (null != obj.id) {\n str += obj.id;\n }\n // json data\n if (null != obj.data) {\n str += JSON.stringify(obj.data, this.replacer);\n }\n return str;\n }\n /**\n * Encode packet as 'buffer sequence' by removing blobs, and\n * deconstructing packet into object with placeholders and\n * a list of buffers.\n */\n encodeAsBinary(obj) {\n const deconstruction = deconstructPacket(obj);\n const pack = this.encodeAsString(deconstruction.packet);\n const buffers = deconstruction.buffers;\n buffers.unshift(pack); // add packet info to beginning of data list\n return buffers; // write all the buffers\n }\n}\n/**\n * A socket.io Decoder instance\n *\n * @return {Object} decoder\n */\nexport class Decoder extends Emitter {\n /**\n * Decoder constructor\n */\n constructor(opts) {\n super();\n this.opts = Object.assign({\n reviver: undefined,\n maxAttachments: 10,\n }, typeof opts === \"function\" ? { reviver: opts } : opts);\n }\n /**\n * Decodes an encoded packet string into packet JSON.\n *\n * @param {String} obj - encoded packet\n */\n add(obj) {\n let packet;\n if (typeof obj === \"string\") {\n if (this.reconstructor) {\n throw new Error(\"got plaintext data when reconstructing a packet\");\n }\n packet = this.decodeString(obj);\n const isBinaryEvent = packet.type === PacketType.BINARY_EVENT;\n if (isBinaryEvent || packet.type === PacketType.BINARY_ACK) {\n packet.type = isBinaryEvent ? PacketType.EVENT : PacketType.ACK;\n // binary packet's json\n this.reconstructor = new BinaryReconstructor(packet);\n // no attachments, labeled binary but no binary data to follow\n if (packet.attachments === 0) {\n super.emitReserved(\"decoded\", packet);\n }\n }\n else {\n // non-binary full packet\n super.emitReserved(\"decoded\", packet);\n }\n }\n else if (isBinary(obj) || obj.base64) {\n // raw binary data\n if (!this.reconstructor) {\n throw new Error(\"got binary data when not reconstructing a packet\");\n }\n else {\n packet = this.reconstructor.takeBinaryData(obj);\n if (packet) {\n // received final buffer\n this.reconstructor = null;\n super.emitReserved(\"decoded\", packet);\n }\n }\n }\n else {\n throw new Error(\"Unknown type: \" + obj);\n }\n }\n /**\n * Decode a packet String (JSON data)\n *\n * @param {String} str\n * @return {Object} packet\n */\n decodeString(str) {\n let i = 0;\n // look up type\n const p = {\n type: Number(str.charAt(0)),\n };\n if (PacketType[p.type] === undefined) {\n throw new Error(\"unknown packet type \" + p.type);\n }\n // look up attachments if type binary\n if (p.type === PacketType.BINARY_EVENT ||\n p.type === PacketType.BINARY_ACK) {\n const start = i + 1;\n while (str.charAt(++i) !== \"-\" && i != str.length) { }\n const buf = str.substring(start, i);\n if (buf != Number(buf) || str.charAt(i) !== \"-\") {\n throw new Error(\"Illegal attachments\");\n }\n const n = Number(buf);\n if (!isInteger(n) || n < 0) {\n throw new Error(\"Illegal attachments\");\n }\n else if (n > this.opts.maxAttachments) {\n throw new Error(\"too many attachments\");\n }\n p.attachments = n;\n }\n // look up namespace (if any)\n if (\"/\" === str.charAt(i + 1)) {\n const start = i + 1;\n while (++i) {\n const c = str.charAt(i);\n if (\",\" === c)\n break;\n if (i === str.length)\n break;\n }\n p.nsp = str.substring(start, i);\n }\n else {\n p.nsp = \"/\";\n }\n // look up id\n const next = str.charAt(i + 1);\n if (\"\" !== next && Number(next) == next) {\n const start = i + 1;\n while (++i) {\n const c = str.charAt(i);\n if (null == c || Number(c) != c) {\n --i;\n break;\n }\n if (i === str.length)\n break;\n }\n p.id = Number(str.substring(start, i + 1));\n }\n // look up json data\n if (str.charAt(++i)) {\n const payload = this.tryParse(str.substr(i));\n if (Decoder.isPayloadValid(p.type, payload)) {\n p.data = payload;\n }\n else {\n throw new Error(\"invalid payload\");\n }\n }\n return p;\n }\n tryParse(str) {\n try {\n return JSON.parse(str, this.opts.reviver);\n }\n catch (e) {\n return false;\n }\n }\n static isPayloadValid(type, payload) {\n switch (type) {\n case PacketType.CONNECT:\n return isObject(payload);\n case PacketType.DISCONNECT:\n return payload === undefined;\n case PacketType.CONNECT_ERROR:\n return typeof payload === \"string\" || isObject(payload);\n case PacketType.EVENT:\n case PacketType.BINARY_EVENT:\n return (Array.isArray(payload) &&\n (typeof payload[0] === \"number\" ||\n (typeof payload[0] === \"string\" &&\n RESERVED_EVENTS.indexOf(payload[0]) === -1)));\n case PacketType.ACK:\n case PacketType.BINARY_ACK:\n return Array.isArray(payload);\n }\n }\n /**\n * Deallocates a parser's resources\n */\n destroy() {\n if (this.reconstructor) {\n this.reconstructor.finishedReconstruction();\n this.reconstructor = null;\n }\n }\n}\n/**\n * A manager of a binary event's 'buffer sequence'. Should\n * be constructed whenever a packet of type BINARY_EVENT is\n * decoded.\n *\n * @param {Object} packet\n * @return {BinaryReconstructor} initialized reconstructor\n */\nclass BinaryReconstructor {\n constructor(packet) {\n this.packet = packet;\n this.buffers = [];\n this.reconPack = packet;\n }\n /**\n * Method to be called when binary data received from connection\n * after a BINARY_EVENT packet.\n *\n * @param {Buffer | ArrayBuffer} binData - the raw binary data received\n * @return {null | Object} returns null if more binary data is expected or\n * a reconstructed packet object if all buffers have been received.\n */\n takeBinaryData(binData) {\n this.buffers.push(binData);\n if (this.buffers.length === this.reconPack.attachments) {\n // done with buffer list\n const packet = reconstructPacket(this.reconPack, this.buffers);\n this.finishedReconstruction();\n return packet;\n }\n return null;\n }\n /**\n * Cleans up binary packet reconstruction variables.\n */\n finishedReconstruction() {\n this.reconPack = null;\n this.buffers = [];\n }\n}\nfunction isNamespaceValid(nsp) {\n return typeof nsp === \"string\";\n}\n// see https://caniuse.com/mdn-javascript_builtins_number_isinteger\nconst isInteger = Number.isInteger ||\n function (value) {\n return (typeof value === \"number\" &&\n isFinite(value) &&\n Math.floor(value) === value);\n };\nfunction isAckIdValid(id) {\n return id === undefined || isInteger(id);\n}\n// see https://stackoverflow.com/questions/8511281/check-if-a-value-is-an-object-in-javascript\nfunction isObject(value) {\n return Object.prototype.toString.call(value) === \"[object Object]\";\n}\nfunction isDataValid(type, payload) {\n switch (type) {\n case PacketType.CONNECT:\n return payload === undefined || isObject(payload);\n case PacketType.DISCONNECT:\n return payload === undefined;\n case PacketType.EVENT:\n return (Array.isArray(payload) &&\n (typeof payload[0] === \"number\" ||\n (typeof payload[0] === \"string\" &&\n RESERVED_EVENTS.indexOf(payload[0]) === -1)));\n case PacketType.ACK:\n return Array.isArray(payload);\n case PacketType.CONNECT_ERROR:\n return typeof payload === \"string\" || isObject(payload);\n default:\n return false;\n }\n}\nexport function isPacketValid(packet) {\n return (isNamespaceValid(packet.nsp) &&\n isAckIdValid(packet.id) &&\n isDataValid(packet.type, packet.data));\n}\n","export function on(obj, ev, fn) {\n obj.on(ev, fn);\n return function subDestroy() {\n obj.off(ev, fn);\n };\n}\n","import { PacketType } from \"socket.io-parser\";\nimport { on } from \"./on.js\";\nimport { Emitter, } from \"@socket.io/component-emitter\";\n/**\n * Internal events.\n * These events can't be emitted by the user.\n */\nconst RESERVED_EVENTS = Object.freeze({\n connect: 1,\n connect_error: 1,\n disconnect: 1,\n disconnecting: 1,\n // EventEmitter reserved events: https://nodejs.org/api/events.html#events_event_newlistener\n newListener: 1,\n removeListener: 1,\n});\n/**\n * A Socket is the fundamental class for interacting with the server.\n *\n * A Socket belongs to a certain Namespace (by default /) and uses an underlying {@link Manager} to communicate.\n *\n * @example\n * const socket = io();\n *\n * socket.on(\"connect\", () => {\n * console.log(\"connected\");\n * });\n *\n * // send an event to the server\n * socket.emit(\"foo\", \"bar\");\n *\n * socket.on(\"foobar\", () => {\n * // an event was received from the server\n * });\n *\n * // upon disconnection\n * socket.on(\"disconnect\", (reason) => {\n * console.log(`disconnected due to ${reason}`);\n * });\n */\nexport class Socket extends Emitter {\n /**\n * `Socket` constructor.\n */\n constructor(io, nsp, opts) {\n super();\n /**\n * Whether the socket is currently connected to the server.\n *\n * @example\n * const socket = io();\n *\n * socket.on(\"connect\", () => {\n * console.log(socket.connected); // true\n * });\n *\n * socket.on(\"disconnect\", () => {\n * console.log(socket.connected); // false\n * });\n */\n this.connected = false;\n /**\n * Whether the connection state was recovered after a temporary disconnection. In that case, any missed packets will\n * be transmitted by the server.\n */\n this.recovered = false;\n /**\n * Buffer for packets received before the CONNECT packet\n */\n this.receiveBuffer = [];\n /**\n * Buffer for packets that will be sent once the socket is connected\n */\n this.sendBuffer = [];\n /**\n * The queue of packets to be sent with retry in case of failure.\n *\n * Packets are sent one by one, each waiting for the server acknowledgement, in order to guarantee the delivery order.\n * @private\n */\n this._queue = [];\n /**\n * A sequence to generate the ID of the {@link QueuedPacket}.\n * @private\n */\n this._queueSeq = 0;\n this.ids = 0;\n /**\n * A map containing acknowledgement handlers.\n *\n * The `withError` attribute is used to differentiate handlers that accept an error as first argument:\n *\n * - `socket.emit(\"test\", (err, value) => { ... })` with `ackTimeout` option\n * - `socket.timeout(5000).emit(\"test\", (err, value) => { ... })`\n * - `const value = await socket.emitWithAck(\"test\")`\n *\n * From those that don't:\n *\n * - `socket.emit(\"test\", (value) => { ... });`\n *\n * In the first case, the handlers will be called with an error when:\n *\n * - the timeout is reached\n * - the socket gets disconnected\n *\n * In the second case, the handlers will be simply discarded upon disconnection, since the client will never receive\n * an acknowledgement from the server.\n *\n * @private\n */\n this.acks = {};\n this.flags = {};\n this.io = io;\n this.nsp = nsp;\n if (opts && opts.auth) {\n this.auth = opts.auth;\n }\n this._opts = Object.assign({}, opts);\n if (this.io._autoConnect)\n this.open();\n }\n /**\n * Whether the socket is currently disconnected\n *\n * @example\n * const socket = io();\n *\n * socket.on(\"connect\", () => {\n * console.log(socket.disconnected); // false\n * });\n *\n * socket.on(\"disconnect\", () => {\n * console.log(socket.disconnected); // true\n * });\n */\n get disconnected() {\n return !this.connected;\n }\n /**\n * Subscribe to open, close and packet events\n *\n * @private\n */\n subEvents() {\n if (this.subs)\n return;\n const io = this.io;\n this.subs = [\n on(io, \"open\", this.onopen.bind(this)),\n on(io, \"packet\", this.onpacket.bind(this)),\n on(io, \"error\", this.onerror.bind(this)),\n on(io, \"close\", this.onclose.bind(this)),\n ];\n }\n /**\n * Whether the Socket will try to reconnect when its Manager connects or reconnects.\n *\n * @example\n * const socket = io();\n *\n * console.log(socket.active); // true\n *\n * socket.on(\"disconnect\", (reason) => {\n * if (reason === \"io server disconnect\") {\n * // the disconnection was initiated by the server, you need to manually reconnect\n * console.log(socket.active); // false\n * }\n * // else the socket will automatically try to reconnect\n * console.log(socket.active); // true\n * });\n */\n get active() {\n return !!this.subs;\n }\n /**\n * \"Opens\" the socket.\n *\n * @example\n * const socket = io({\n * autoConnect: false\n * });\n *\n * socket.connect();\n */\n connect() {\n if (this.connected)\n return this;\n this.subEvents();\n if (!this.io[\"_reconnecting\"])\n this.io.open(); // ensure open\n if (\"open\" === this.io._readyState)\n this.onopen();\n return this;\n }\n /**\n * Alias for {@link connect()}.\n */\n open() {\n return this.connect();\n }\n /**\n * Sends a `message` event.\n *\n * This method mimics the WebSocket.send() method.\n *\n * @see https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/send\n *\n * @example\n * socket.send(\"hello\");\n *\n * // this is equivalent to\n * socket.emit(\"message\", \"hello\");\n *\n * @return self\n */\n send(...args) {\n args.unshift(\"message\");\n this.emit.apply(this, args);\n return this;\n }\n /**\n * Override `emit`.\n * If the event is in `events`, it's emitted normally.\n *\n * @example\n * socket.emit(\"hello\", \"world\");\n *\n * // all serializable datastructures are supported (no need to call JSON.stringify)\n * socket.emit(\"hello\", 1, \"2\", { 3: [\"4\"], 5: Uint8Array.from([6]) });\n *\n * // with an acknowledgement from the server\n * socket.emit(\"hello\", \"world\", (val) => {\n * // ...\n * });\n *\n * @return self\n */\n emit(ev, ...args) {\n var _a, _b, _c;\n if (RESERVED_EVENTS.hasOwnProperty(ev)) {\n throw new Error('\"' + ev.toString() + '\" is a reserved event name');\n }\n args.unshift(ev);\n if (this._opts.retries && !this.flags.fromQueue && !this.flags.volatile) {\n this._addToQueue(args);\n return this;\n }\n const packet = {\n type: PacketType.EVENT,\n data: args,\n };\n packet.options = {};\n packet.options.compress = this.flags.compress !== false;\n // event ack callback\n if (\"function\" === typeof args[args.length - 1]) {\n const id = this.ids++;\n const ack = args.pop();\n this._registerAckCallback(id, ack);\n packet.id = id;\n }\n const isTransportWritable = (_b = (_a = this.io.engine) === null || _a === void 0 ? void 0 : _a.transport) === null || _b === void 0 ? void 0 : _b.writable;\n const isConnected = this.connected && !((_c = this.io.engine) === null || _c === void 0 ? void 0 : _c._hasPingExpired());\n const discardPacket = this.flags.volatile && !isTransportWritable;\n if (discardPacket) {\n }\n else if (isConnected) {\n this.notifyOutgoingListeners(packet);\n this.packet(packet);\n }\n else {\n this.sendBuffer.push(packet);\n }\n this.flags = {};\n return this;\n }\n /**\n * @private\n */\n _registerAckCallback(id, ack) {\n var _a;\n const timeout = (_a = this.flags.timeout) !== null && _a !== void 0 ? _a : this._opts.ackTimeout;\n if (timeout === undefined) {\n this.acks[id] = ack;\n return;\n }\n // @ts-ignore\n const timer = this.io.setTimeoutFn(() => {\n delete this.acks[id];\n for (let i = 0; i < this.sendBuffer.length; i++) {\n if (this.sendBuffer[i].id === id) {\n this.sendBuffer.splice(i, 1);\n }\n }\n ack.call(this, new Error(\"operation has timed out\"));\n }, timeout);\n const fn = (...args) => {\n // @ts-ignore\n this.io.clearTimeoutFn(timer);\n ack.apply(this, args);\n };\n fn.withError = true;\n this.acks[id] = fn;\n }\n /**\n * Emits an event and waits for an acknowledgement\n *\n * @example\n * // without timeout\n * const response = await socket.emitWithAck(\"hello\", \"world\");\n *\n * // with a specific timeout\n * try {\n * const response = await socket.timeout(1000).emitWithAck(\"hello\", \"world\");\n * } catch (err) {\n * // the server did not acknowledge the event in the given delay\n * }\n *\n * @return a Promise that will be fulfilled when the server acknowledges the event\n */\n emitWithAck(ev, ...args) {\n return new Promise((resolve, reject) => {\n const fn = (arg1, arg2) => {\n return arg1 ? reject(arg1) : resolve(arg2);\n };\n fn.withError = true;\n args.push(fn);\n this.emit(ev, ...args);\n });\n }\n /**\n * Add the packet to the queue.\n * @param args\n * @private\n */\n _addToQueue(args) {\n let ack;\n if (typeof args[args.length - 1] === \"function\") {\n ack = args.pop();\n }\n const packet = {\n id: this._queueSeq++,\n tryCount: 0,\n pending: false,\n args,\n flags: Object.assign({ fromQueue: true }, this.flags),\n };\n args.push((err, ...responseArgs) => {\n if (packet !== this._queue[0]) {\n }\n const hasError = err !== null;\n if (hasError) {\n if (packet.tryCount > this._opts.retries) {\n this._queue.shift();\n if (ack) {\n ack(err);\n }\n }\n }\n else {\n this._queue.shift();\n if (ack) {\n ack(null, ...responseArgs);\n }\n }\n packet.pending = false;\n return this._drainQueue();\n });\n this._queue.push(packet);\n this._drainQueue();\n }\n /**\n * Send the first packet of the queue, and wait for an acknowledgement from the server.\n * @param force - whether to resend a packet that has not been acknowledged yet\n *\n * @private\n */\n _drainQueue(force = false) {\n if (!this.connected || this._queue.length === 0) {\n return;\n }\n const packet = this._queue[0];\n if (packet.pending && !force) {\n return;\n }\n packet.pending = true;\n packet.tryCount++;\n this.flags = packet.flags;\n this.emit.apply(this, packet.args);\n }\n /**\n * Sends a packet.\n *\n * @param packet\n * @private\n */\n packet(packet) {\n packet.nsp = this.nsp;\n this.io._packet(packet);\n }\n /**\n * Called upon engine `open`.\n *\n * @private\n */\n onopen() {\n if (typeof this.auth == \"function\") {\n this.auth((data) => {\n this._sendConnectPacket(data);\n });\n }\n else {\n this._sendConnectPacket(this.auth);\n }\n }\n /**\n * Sends a CONNECT packet to initiate the Socket.IO session.\n *\n * @param data\n * @private\n */\n _sendConnectPacket(data) {\n this.packet({\n type: PacketType.CONNECT,\n data: this._pid\n ? Object.assign({ pid: this._pid, offset: this._lastOffset }, data)\n : data,\n });\n }\n /**\n * Called upon engine or manager `error`.\n *\n * @param err\n * @private\n */\n onerror(err) {\n if (!this.connected) {\n this.emitReserved(\"connect_error\", err);\n }\n }\n /**\n * Called upon engine `close`.\n *\n * @param reason\n * @param description\n * @private\n */\n onclose(reason, description) {\n this.connected = false;\n delete this.id;\n this.emitReserved(\"disconnect\", reason, description);\n this._clearAcks();\n }\n /**\n * Clears the acknowledgement handlers upon disconnection, since the client will never receive an acknowledgement from\n * the server.\n *\n * @private\n */\n _clearAcks() {\n Object.keys(this.acks).forEach((id) => {\n const isBuffered = this.sendBuffer.some((packet) => String(packet.id) === id);\n if (!isBuffered) {\n // note: handlers that do not accept an error as first argument are ignored here\n const ack = this.acks[id];\n delete this.acks[id];\n if (ack.withError) {\n ack.call(this, new Error(\"socket has been disconnected\"));\n }\n }\n });\n }\n /**\n * Called with socket packet.\n *\n * @param packet\n * @private\n */\n onpacket(packet) {\n const sameNamespace = packet.nsp === this.nsp;\n if (!sameNamespace)\n return;\n switch (packet.type) {\n case PacketType.CONNECT:\n if (packet.data && packet.data.sid) {\n this.onconnect(packet.data.sid, packet.data.pid);\n }\n else {\n this.emitReserved(\"connect_error\", new Error(\"It seems you are trying to reach a Socket.IO server in v2.x with a v3.x client, but they are not compatible (more information here: https://socket.io/docs/v3/migrating-from-2-x-to-3-0/)\"));\n }\n break;\n case PacketType.EVENT:\n case PacketType.BINARY_EVENT:\n this.onevent(packet);\n break;\n case PacketType.ACK:\n case PacketType.BINARY_ACK:\n this.onack(packet);\n break;\n case PacketType.DISCONNECT:\n this.ondisconnect();\n break;\n case PacketType.CONNECT_ERROR:\n this.destroy();\n const err = new Error(packet.data.message);\n // @ts-ignore\n err.data = packet.data.data;\n this.emitReserved(\"connect_error\", err);\n break;\n }\n }\n /**\n * Called upon a server event.\n *\n * @param packet\n * @private\n */\n onevent(packet) {\n const args = packet.data || [];\n if (null != packet.id) {\n args.push(this.ack(packet.id));\n }\n if (this.connected) {\n this.emitEvent(args);\n }\n else {\n this.receiveBuffer.push(Object.freeze(args));\n }\n }\n emitEvent(args) {\n if (this._anyListeners && this._anyListeners.length) {\n const listeners = this._anyListeners.slice();\n for (const listener of listeners) {\n listener.apply(this, args);\n }\n }\n super.emit.apply(this, args);\n if (this._pid && args.length && typeof args[args.length - 1] === \"string\") {\n this._lastOffset = args[args.length - 1];\n }\n }\n /**\n * Produces an ack callback to emit with an event.\n *\n * @private\n */\n ack(id) {\n const self = this;\n let sent = false;\n return function (...args) {\n // prevent double callbacks\n if (sent)\n return;\n sent = true;\n self.packet({\n type: PacketType.ACK,\n id: id,\n data: args,\n });\n };\n }\n /**\n * Called upon a server acknowledgement.\n *\n * @param packet\n * @private\n */\n onack(packet) {\n const ack = this.acks[packet.id];\n if (typeof ack !== \"function\") {\n return;\n }\n delete this.acks[packet.id];\n // @ts-ignore FIXME ack is incorrectly inferred as 'never'\n if (ack.withError) {\n packet.data.unshift(null);\n }\n // @ts-ignore\n ack.apply(this, packet.data);\n }\n /**\n * Called upon server connect.\n *\n * @private\n */\n onconnect(id, pid) {\n this.id = id;\n this.recovered = pid && this._pid === pid;\n this._pid = pid; // defined only if connection state recovery is enabled\n this.connected = true;\n this.emitBuffered();\n this._drainQueue(true);\n this.emitReserved(\"connect\");\n }\n /**\n * Emit buffered events (received and emitted).\n *\n * @private\n */\n emitBuffered() {\n this.receiveBuffer.forEach((args) => this.emitEvent(args));\n this.receiveBuffer = [];\n this.sendBuffer.forEach((packet) => {\n this.notifyOutgoingListeners(packet);\n this.packet(packet);\n });\n this.sendBuffer = [];\n }\n /**\n * Called upon server disconnect.\n *\n * @private\n */\n ondisconnect() {\n this.destroy();\n this.onclose(\"io server disconnect\");\n }\n /**\n * Called upon forced client/server side disconnections,\n * this method ensures the manager stops tracking us and\n * that reconnections don't get triggered for this.\n *\n * @private\n */\n destroy() {\n if (this.subs) {\n // clean subscriptions to avoid reconnections\n this.subs.forEach((subDestroy) => subDestroy());\n this.subs = undefined;\n }\n this.io[\"_destroy\"](this);\n }\n /**\n * Disconnects the socket manually. In that case, the socket will not try to reconnect.\n *\n * If this is the last active Socket instance of the {@link Manager}, the low-level connection will be closed.\n *\n * @example\n * const socket = io();\n *\n * socket.on(\"disconnect\", (reason) => {\n * // console.log(reason); prints \"io client disconnect\"\n * });\n *\n * socket.disconnect();\n *\n * @return self\n */\n disconnect() {\n if (this.connected) {\n this.packet({ type: PacketType.DISCONNECT });\n }\n // remove socket from pool\n this.destroy();\n if (this.connected) {\n // fire events\n this.onclose(\"io client disconnect\");\n }\n return this;\n }\n /**\n * Alias for {@link disconnect()}.\n *\n * @return self\n */\n close() {\n return this.disconnect();\n }\n /**\n * Sets the compress flag.\n *\n * @example\n * socket.compress(false).emit(\"hello\");\n *\n * @param compress - if `true`, compresses the sending data\n * @return self\n */\n compress(compress) {\n this.flags.compress = compress;\n return this;\n }\n /**\n * Sets a modifier for a subsequent event emission that the event message will be dropped when this socket is not\n * ready to send messages.\n *\n * @example\n * socket.volatile.emit(\"hello\"); // the server may or may not receive it\n *\n * @returns self\n */\n get volatile() {\n this.flags.volatile = true;\n return this;\n }\n /**\n * Sets a modifier for a subsequent event emission that the callback will be called with an error when the\n * given number of milliseconds have elapsed without an acknowledgement from the server:\n *\n * @example\n * socket.timeout(5000).emit(\"my-event\", (err) => {\n * if (err) {\n * // the server did not acknowledge the event in the given delay\n * }\n * });\n *\n * @returns self\n */\n timeout(timeout) {\n this.flags.timeout = timeout;\n return this;\n }\n /**\n * Adds a listener that will be fired when any event is emitted. The event name is passed as the first argument to the\n * callback.\n *\n * @example\n * socket.onAny((event, ...args) => {\n * console.log(`got ${event}`);\n * });\n *\n * @param listener\n */\n onAny(listener) {\n this._anyListeners = this._anyListeners || [];\n this._anyListeners.push(listener);\n return this;\n }\n /**\n * Adds a listener that will be fired when any event is emitted. The event name is passed as the first argument to the\n * callback. The listener is added to the beginning of the listeners array.\n *\n * @example\n * socket.prependAny((event, ...args) => {\n * console.log(`got event ${event}`);\n * });\n *\n * @param listener\n */\n prependAny(listener) {\n this._anyListeners = this._anyListeners || [];\n this._anyListeners.unshift(listener);\n return this;\n }\n /**\n * Removes the listener that will be fired when any event is emitted.\n *\n * @example\n * const catchAllListener = (event, ...args) => {\n * console.log(`got event ${event}`);\n * }\n *\n * socket.onAny(catchAllListener);\n *\n * // remove a specific listener\n * socket.offAny(catchAllListener);\n *\n * // or remove all listeners\n * socket.offAny();\n *\n * @param listener\n */\n offAny(listener) {\n if (!this._anyListeners) {\n return this;\n }\n if (listener) {\n const listeners = this._anyListeners;\n for (let i = 0; i < listeners.length; i++) {\n if (listener === listeners[i]) {\n listeners.splice(i, 1);\n return this;\n }\n }\n }\n else {\n this._anyListeners = [];\n }\n return this;\n }\n /**\n * Returns an array of listeners that are listening for any event that is specified. This array can be manipulated,\n * e.g. to remove listeners.\n */\n listenersAny() {\n return this._anyListeners || [];\n }\n /**\n * Adds a listener that will be fired when any event is emitted. The event name is passed as the first argument to the\n * callback.\n *\n * Note: acknowledgements sent to the server are not included.\n *\n * @example\n * socket.onAnyOutgoing((event, ...args) => {\n * console.log(`sent event ${event}`);\n * });\n *\n * @param listener\n */\n onAnyOutgoing(listener) {\n this._anyOutgoingListeners = this._anyOutgoingListeners || [];\n this._anyOutgoingListeners.push(listener);\n return this;\n }\n /**\n * Adds a listener that will be fired when any event is emitted. The event name is passed as the first argument to the\n * callback. The listener is added to the beginning of the listeners array.\n *\n * Note: acknowledgements sent to the server are not included.\n *\n * @example\n * socket.prependAnyOutgoing((event, ...args) => {\n * console.log(`sent event ${event}`);\n * });\n *\n * @param listener\n */\n prependAnyOutgoing(listener) {\n this._anyOutgoingListeners = this._anyOutgoingListeners || [];\n this._anyOutgoingListeners.unshift(listener);\n return this;\n }\n /**\n * Removes the listener that will be fired when any event is emitted.\n *\n * @example\n * const catchAllListener = (event, ...args) => {\n * console.log(`sent event ${event}`);\n * }\n *\n * socket.onAnyOutgoing(catchAllListener);\n *\n * // remove a specific listener\n * socket.offAnyOutgoing(catchAllListener);\n *\n * // or remove all listeners\n * socket.offAnyOutgoing();\n *\n * @param [listener] - the catch-all listener (optional)\n */\n offAnyOutgoing(listener) {\n if (!this._anyOutgoingListeners) {\n return this;\n }\n if (listener) {\n const listeners = this._anyOutgoingListeners;\n for (let i = 0; i < listeners.length; i++) {\n if (listener === listeners[i]) {\n listeners.splice(i, 1);\n return this;\n }\n }\n }\n else {\n this._anyOutgoingListeners = [];\n }\n return this;\n }\n /**\n * Returns an array of listeners that are listening for any event that is specified. This array can be manipulated,\n * e.g. to remove listeners.\n */\n listenersAnyOutgoing() {\n return this._anyOutgoingListeners || [];\n }\n /**\n * Notify the listeners for each packet sent\n *\n * @param packet\n *\n * @private\n */\n notifyOutgoingListeners(packet) {\n if (this._anyOutgoingListeners && this._anyOutgoingListeners.length) {\n const listeners = this._anyOutgoingListeners.slice();\n for (const listener of listeners) {\n listener.apply(this, packet.data);\n }\n }\n }\n}\n","/**\n * Initialize backoff timer with `opts`.\n *\n * - `min` initial timeout in milliseconds [100]\n * - `max` max timeout [10000]\n * - `jitter` [0]\n * - `factor` [2]\n *\n * @param {Object} opts\n * @api public\n */\nexport function Backoff(opts) {\n opts = opts || {};\n this.ms = opts.min || 100;\n this.max = opts.max || 10000;\n this.factor = opts.factor || 2;\n this.jitter = opts.jitter > 0 && opts.jitter <= 1 ? opts.jitter : 0;\n this.attempts = 0;\n}\n/**\n * Return the backoff duration.\n *\n * @return {Number}\n * @api public\n */\nBackoff.prototype.duration = function () {\n var ms = this.ms * Math.pow(this.factor, this.attempts++);\n if (this.jitter) {\n var rand = Math.random();\n var deviation = Math.floor(rand * this.jitter * ms);\n ms = (Math.floor(rand * 10) & 1) == 0 ? ms - deviation : ms + deviation;\n }\n return Math.min(ms, this.max) | 0;\n};\n/**\n * Reset the number of attempts.\n *\n * @api public\n */\nBackoff.prototype.reset = function () {\n this.attempts = 0;\n};\n/**\n * Set the minimum duration\n *\n * @api public\n */\nBackoff.prototype.setMin = function (min) {\n this.ms = min;\n};\n/**\n * Set the maximum duration\n *\n * @api public\n */\nBackoff.prototype.setMax = function (max) {\n this.max = max;\n};\n/**\n * Set the jitter\n *\n * @api public\n */\nBackoff.prototype.setJitter = function (jitter) {\n this.jitter = jitter;\n};\n","import { Socket as Engine, installTimerFunctions, nextTick, } from \"engine.io-client\";\nimport { Socket } from \"./socket.js\";\nimport * as parser from \"socket.io-parser\";\nimport { on } from \"./on.js\";\nimport { Backoff } from \"./contrib/backo2.js\";\nimport { Emitter, } from \"@socket.io/component-emitter\";\nexport class Manager extends Emitter {\n constructor(uri, opts) {\n var _a;\n super();\n this.nsps = {};\n this.subs = [];\n if (uri && \"object\" === typeof uri) {\n opts = uri;\n uri = undefined;\n }\n opts = opts || {};\n opts.path = opts.path || \"/socket.io\";\n this.opts = opts;\n installTimerFunctions(this, opts);\n this.reconnection(opts.reconnection !== false);\n this.reconnectionAttempts(opts.reconnectionAttempts || Infinity);\n this.reconnectionDelay(opts.reconnectionDelay || 1000);\n this.reconnectionDelayMax(opts.reconnectionDelayMax || 5000);\n this.randomizationFactor((_a = opts.randomizationFactor) !== null && _a !== void 0 ? _a : 0.5);\n this.backoff = new Backoff({\n min: this.reconnectionDelay(),\n max: this.reconnectionDelayMax(),\n jitter: this.randomizationFactor(),\n });\n this.timeout(null == opts.timeout ? 20000 : opts.timeout);\n this._readyState = \"closed\";\n this.uri = uri;\n const _parser = opts.parser || parser;\n this.encoder = new _parser.Encoder();\n this.decoder = new _parser.Decoder();\n this._autoConnect = opts.autoConnect !== false;\n if (this._autoConnect)\n this.open();\n }\n reconnection(v) {\n if (!arguments.length)\n return this._reconnection;\n this._reconnection = !!v;\n if (!v) {\n this.skipReconnect = true;\n }\n return this;\n }\n reconnectionAttempts(v) {\n if (v === undefined)\n return this._reconnectionAttempts;\n this._reconnectionAttempts = v;\n return this;\n }\n reconnectionDelay(v) {\n var _a;\n if (v === undefined)\n return this._reconnectionDelay;\n this._reconnectionDelay = v;\n (_a = this.backoff) === null || _a === void 0 ? void 0 : _a.setMin(v);\n return this;\n }\n randomizationFactor(v) {\n var _a;\n if (v === undefined)\n return this._randomizationFactor;\n this._randomizationFactor = v;\n (_a = this.backoff) === null || _a === void 0 ? void 0 : _a.setJitter(v);\n return this;\n }\n reconnectionDelayMax(v) {\n var _a;\n if (v === undefined)\n return this._reconnectionDelayMax;\n this._reconnectionDelayMax = v;\n (_a = this.backoff) === null || _a === void 0 ? void 0 : _a.setMax(v);\n return this;\n }\n timeout(v) {\n if (!arguments.length)\n return this._timeout;\n this._timeout = v;\n return this;\n }\n /**\n * Starts trying to reconnect if reconnection is enabled and we have not\n * started reconnecting yet\n *\n * @private\n */\n maybeReconnectOnOpen() {\n // Only try to reconnect if it's the first time we're connecting\n if (!this._reconnecting &&\n this._reconnection &&\n this.backoff.attempts === 0) {\n // keeps reconnection from firing twice for the same reconnection loop\n this.reconnect();\n }\n }\n /**\n * Sets the current transport `socket`.\n *\n * @param {Function} fn - optional, callback\n * @return self\n * @public\n */\n open(fn) {\n if (~this._readyState.indexOf(\"open\"))\n return this;\n this.engine = new Engine(this.uri, this.opts);\n const socket = this.engine;\n const self = this;\n this._readyState = \"opening\";\n this.skipReconnect = false;\n // emit `open`\n const openSubDestroy = on(socket, \"open\", function () {\n self.onopen();\n fn && fn();\n });\n const onError = (err) => {\n this.cleanup();\n this._readyState = \"closed\";\n this.emitReserved(\"error\", err);\n if (fn) {\n fn(err);\n }\n else {\n // Only do this if there is no fn to handle the error\n this.maybeReconnectOnOpen();\n }\n };\n // emit `error`\n const errorSub = on(socket, \"error\", onError);\n if (false !== this._timeout) {\n const timeout = this._timeout;\n // set timer\n const timer = this.setTimeoutFn(() => {\n openSubDestroy();\n onError(new Error(\"timeout\"));\n socket.close();\n }, timeout);\n if (this.opts.autoUnref) {\n timer.unref();\n }\n this.subs.push(() => {\n this.clearTimeoutFn(timer);\n });\n }\n this.subs.push(openSubDestroy);\n this.subs.push(errorSub);\n return this;\n }\n /**\n * Alias for open()\n *\n * @return self\n * @public\n */\n connect(fn) {\n return this.open(fn);\n }\n /**\n * Called upon transport open.\n *\n * @private\n */\n onopen() {\n // clear old subs\n this.cleanup();\n // mark as open\n this._readyState = \"open\";\n this.emitReserved(\"open\");\n // add new subs\n const socket = this.engine;\n this.subs.push(on(socket, \"ping\", this.onping.bind(this)), on(socket, \"data\", this.ondata.bind(this)), on(socket, \"error\", this.onerror.bind(this)), on(socket, \"close\", this.onclose.bind(this)), \n // @ts-ignore\n on(this.decoder, \"decoded\", this.ondecoded.bind(this)));\n }\n /**\n * Called upon a ping.\n *\n * @private\n */\n onping() {\n this.emitReserved(\"ping\");\n }\n /**\n * Called with data.\n *\n * @private\n */\n ondata(data) {\n try {\n this.decoder.add(data);\n }\n catch (e) {\n this.onclose(\"parse error\", e);\n }\n }\n /**\n * Called when parser fully decodes a packet.\n *\n * @private\n */\n ondecoded(packet) {\n // the nextTick call prevents an exception in a user-provided event listener from triggering a disconnection due to a \"parse error\"\n nextTick(() => {\n this.emitReserved(\"packet\", packet);\n }, this.setTimeoutFn);\n }\n /**\n * Called upon socket error.\n *\n * @private\n */\n onerror(err) {\n this.emitReserved(\"error\", err);\n }\n /**\n * Creates a new socket for the given `nsp`.\n *\n * @return {Socket}\n * @public\n */\n socket(nsp, opts) {\n let socket = this.nsps[nsp];\n if (!socket) {\n socket = new Socket(this, nsp, opts);\n this.nsps[nsp] = socket;\n }\n else if (this._autoConnect && !socket.active) {\n socket.connect();\n }\n return socket;\n }\n /**\n * Called upon a socket close.\n *\n * @param socket\n * @private\n */\n _destroy(socket) {\n const nsps = Object.keys(this.nsps);\n for (const nsp of nsps) {\n const socket = this.nsps[nsp];\n if (socket.active) {\n return;\n }\n }\n this._close();\n }\n /**\n * Writes a packet.\n *\n * @param packet\n * @private\n */\n _packet(packet) {\n const encodedPackets = this.encoder.encode(packet);\n for (let i = 0; i < encodedPackets.length; i++) {\n this.engine.write(encodedPackets[i], packet.options);\n }\n }\n /**\n * Clean up transport subscriptions and packet buffer.\n *\n * @private\n */\n cleanup() {\n this.subs.forEach((subDestroy) => subDestroy());\n this.subs.length = 0;\n this.decoder.destroy();\n }\n /**\n * Close the current socket.\n *\n * @private\n */\n _close() {\n this.skipReconnect = true;\n this._reconnecting = false;\n this.onclose(\"forced close\");\n }\n /**\n * Alias for close()\n *\n * @private\n */\n disconnect() {\n return this._close();\n }\n /**\n * Called when:\n *\n * - the low-level engine is closed\n * - the parser encountered a badly formatted packet\n * - all sockets are disconnected\n *\n * @private\n */\n onclose(reason, description) {\n var _a;\n this.cleanup();\n (_a = this.engine) === null || _a === void 0 ? void 0 : _a.close();\n this.backoff.reset();\n this._readyState = \"closed\";\n this.emitReserved(\"close\", reason, description);\n if (this._reconnection && !this.skipReconnect) {\n this.reconnect();\n }\n }\n /**\n * Attempt a reconnection.\n *\n * @private\n */\n reconnect() {\n if (this._reconnecting || this.skipReconnect)\n return this;\n const self = this;\n if (this.backoff.attempts >= this._reconnectionAttempts) {\n this.backoff.reset();\n this.emitReserved(\"reconnect_failed\");\n this._reconnecting = false;\n }\n else {\n const delay = this.backoff.duration();\n this._reconnecting = true;\n const timer = this.setTimeoutFn(() => {\n if (self.skipReconnect)\n return;\n this.emitReserved(\"reconnect_attempt\", self.backoff.attempts);\n // check again for the case socket closed in above events\n if (self.skipReconnect)\n return;\n self.open((err) => {\n if (err) {\n self._reconnecting = false;\n self.reconnect();\n this.emitReserved(\"reconnect_error\", err);\n }\n else {\n self.onreconnect();\n }\n });\n }, delay);\n if (this.opts.autoUnref) {\n timer.unref();\n }\n this.subs.push(() => {\n this.clearTimeoutFn(timer);\n });\n }\n }\n /**\n * Called upon successful reconnect.\n *\n * @private\n */\n onreconnect() {\n const attempt = this.backoff.attempts;\n this._reconnecting = false;\n this.backoff.reset();\n this.emitReserved(\"reconnect\", attempt);\n }\n}\n","import { url } from \"./url.js\";\nimport { Manager } from \"./manager.js\";\nimport { Socket } from \"./socket.js\";\n/**\n * Managers cache.\n */\nconst cache = {};\nfunction lookup(uri, opts) {\n if (typeof uri === \"object\") {\n opts = uri;\n uri = undefined;\n }\n opts = opts || {};\n const parsed = url(uri, opts.path || \"/socket.io\");\n const source = parsed.source;\n const id = parsed.id;\n const path = parsed.path;\n const sameNamespace = cache[id] && path in cache[id][\"nsps\"];\n const newConnection = opts.forceNew ||\n opts[\"force new connection\"] ||\n false === opts.multiplex ||\n sameNamespace;\n let io;\n if (newConnection) {\n io = new Manager(source, opts);\n }\n else {\n if (!cache[id]) {\n cache[id] = new Manager(source, opts);\n }\n io = cache[id];\n }\n if (parsed.query && !opts.query) {\n opts.query = parsed.queryKey;\n }\n return io.socket(parsed.path, opts);\n}\n// so that \"lookup\" can be used both as a function (e.g. `io(...)`) and as a\n// namespace (e.g. `io.connect(...)`), for backward compatibility\nObject.assign(lookup, {\n Manager,\n Socket,\n io: lookup,\n connect: lookup,\n});\n/**\n * Protocol version.\n *\n * @public\n */\nexport { protocol } from \"socket.io-parser\";\n/**\n * Expose constructors for standalone build.\n *\n * @public\n */\nexport { Manager, Socket, lookup as io, lookup as connect, lookup as default, };\nexport { Fetch, NodeXHR, XHR, NodeWebSocket, WebSocket, WebTransport, } from \"engine.io-client\";\n","/**\n * Documents: the platform's unit of content.\n *\n * EVERY DOCUMENT IS A FOLDER. A \"file\" a person sees in the CDE — a PDF, a\n * Revit model, a point cloud — is stored as a folder holding one or more\n * actual files, plus a small descriptor (`document.json`) that says which file\n * is the document's NATIVE form and which files are its VIEWS (the\n * representations a viewer can render). The folder is an internal storage\n * detail: interfaces present the document as a single row and apply move,\n * rename, delete and permissions to the whole folder.\n *\n * READY TO VISUALIZE is the only rule a viewer needs: a document is viewable\n * when its descriptor lists a view in a format the viewer can render. There\n * is no \"derived file\" or \"linked file\" concept — a format that cannot be\n * rendered directly gets PROCESSED, and the processor's last act is\n * {@link ProjectDocuments.addView}. A document whose native format views\n * itself (a PDF, an IFC a viewer renders directly) lists the SAME fileId as\n * both `native` and a view; nothing is deduced from extensions.\n *\n * Plain files still exist: anything uploaded outside this shape simply has no\n * descriptor ({@link ProjectDocuments.descriptor} returns null) and is more\n * limited — interfaces may offer to convert it into a document.\n */\nimport type { EngineServicesClient } from './client';\n\n/** One renderable representation of a document. */\nexport interface DocumentView {\n /** The view file's item id — ids survive renames, names do not. */\n fileId: string;\n /** Lowercase format name: 'frag', 'ifc', 'potree', 'pdf'… */\n format: string;\n}\n\n/** The wire shape of `document.json`, schema `thatopen/document@1`. */\nexport interface DocumentDescriptor {\n schema: typeof DOCUMENT_SCHEMA;\n /** The document's own name — what a row shows. Not any file's name. */\n name: string;\n /**\n * The native form, when the document has one (a .rvt, a .3dm). A document\n * born on the platform (a loose .frag) may not.\n */\n native?: { fileId: string; format: string };\n /** The renderable representations, in no particular order. */\n views: DocumentView[];\n}\n\nexport const DOCUMENT_SCHEMA = 'thatopen/document@1';\nexport const DOCUMENT_FILE = 'document.json';\n\n/**\n * Formats whose native file IS its own definitive view (the PDF rule): when\n * {@link ProjectDocuments.fromFile} converts one, the same fileId is written\n * as `native` and as `views[0]`. Deliberately NOT here: 'ifc' — its proper 3D\n * view is the processed frag, so a converted IFC without one shows \"Process\"\n * instead of opening a worse view.\n */\nexport const SELF_VIEWING_FORMATS = [\n 'pdf',\n 'txt',\n 'md',\n 'json',\n 'csv',\n 'tsv',\n 'frag',\n];\n\n/** One listed document: the folder, and what its descriptor says. */\nexport interface DocumentInfo {\n /** The document folder's item id — the id interfaces know the document by. */\n folderId: string;\n descriptor: DocumentDescriptor;\n}\n\nconst versionTag = () => `v-${Date.now()}`;\n\nfunction idOf(item: { _id?: unknown; id?: unknown }): string {\n return String(item._id ?? item.id ?? '');\n}\n\n/**\n * Documents of one project. Get it from {@link EngineServicesClient.documents}.\n * Every method takes the document's FOLDER id — the id interfaces know the\n * document by.\n */\nexport class ProjectDocuments {\n constructor(\n private readonly client: EngineServicesClient,\n readonly projectId: string,\n ) {}\n\n /**\n * Every document of the project: the folders that carry a descriptor.\n * Plain folders and loose files simply do not appear. One folder listing\n * for the project plus one file listing and one descriptor download per\n * folder, fetched in parallel — the storage offers nothing cheaper yet.\n */\n async list(): Promise<DocumentInfo[]> {\n const folders = await this.client.listFolders({\n projectId: this.projectId,\n });\n const found = await Promise.all(\n folders.map(async (folder) => {\n const folderId = idOf(folder as never);\n const descriptor = await this.descriptor(folderId);\n return descriptor ? { folderId, descriptor } : null;\n }),\n );\n return found.filter((d): d is DocumentInfo => d !== null);\n }\n\n /**\n * Converts a loose file into a document: creates the document folder next\n * to the file, moves the file inside (moving preserves its id), and writes\n * the descriptor with the file as `native` — and as `views[0]` too when its\n * format views itself ({@link SELF_VIEWING_FORMATS}; override per call with\n * `selfView`).\n *\n * A file that carries a processed derivative (the old `derivedFileId` link\n * in its version metadata — an IFC's frag, a LAS's potree) brings it along:\n * the derivative moves into the same folder and becomes a view, so the\n * document is born ready to visualize and the link concept retires.\n */\n async fromFile(\n fileId: string,\n options?: { name?: string; selfView?: boolean },\n ): Promise<DocumentInfo> {\n const item = await this.client.getFile(fileId);\n const fileName = String(item.name ?? '');\n const format = formatOf(fileName, item.fileExtension);\n const name =\n options?.name ?? fileName.replace(/\\.[^.]+$/, '') ?? fileName;\n\n const folder = await this.client.createFolder(\n name,\n item.folderId ? String(item.folderId) : undefined,\n this.projectId,\n );\n const folderId = idOf(folder as never);\n await this.client.updateFile(fileId, { parentFolderId: folderId });\n\n const views: DocumentView[] = [];\n const derivedId = await this.#derivedFileId(item);\n if (derivedId) {\n try {\n const derived = await this.client.getFile(derivedId);\n await this.client.updateFile(derivedId, { parentFolderId: folderId });\n views.push({\n fileId: derivedId,\n format: formatOf(String(derived.name ?? ''), derived.fileExtension),\n });\n } catch {\n // A dangling link names a file that no longer exists; the document is\n // still valid, just not visualizable until somebody processes it.\n }\n }\n const selfViews = options?.selfView ?? SELF_VIEWING_FORMATS.includes(format);\n if (selfViews) views.push({ fileId, format });\n\n const descriptor: DocumentDescriptor = {\n schema: DOCUMENT_SCHEMA,\n name,\n native: { fileId, format },\n views,\n };\n await this.setDescriptor(folderId, descriptor);\n return { folderId, descriptor };\n }\n\n /**\n * The document's descriptor, read and validated, or null when the folder\n * has none yet (an old folder, or a plain folder that is not a document).\n */\n async descriptor(folderId: string): Promise<DocumentDescriptor | null> {\n const file = await this.#descriptorFile(folderId);\n if (!file) return null;\n const response = await this.client.downloadFile(file.id);\n const text = await response.text();\n if (!text.trim()) return null;\n let parsed: unknown;\n try {\n parsed = JSON.parse(text);\n } catch {\n return null;\n }\n return normalize(parsed);\n }\n\n /**\n * The first view whose format appears in `formats` — searched in the ORDER\n * OF THE LIST, so the caller's preference wins (ask `['frag', 'ifc']` and a\n * document carrying both answers the frag). Null when none matches: that is\n * where an interface offers \"Process\".\n */\n async view(\n folderId: string,\n formats: string[],\n ): Promise<DocumentView | null> {\n const descriptor = await this.descriptor(folderId);\n if (!descriptor) return null;\n for (const format of formats) {\n const match = descriptor.views.find((v) => v.format === format);\n if (match) return match;\n }\n return null;\n }\n\n /**\n * Registers a renderable representation — a processor's last act. One view\n * per format: an existing view of the same format is replaced (a re-run\n * processor updates, it does not accumulate). The descriptor must exist;\n * create it first with {@link setDescriptor}.\n */\n async addView(folderId: string, view: DocumentView): Promise<void> {\n const descriptor = await this.descriptor(folderId);\n if (!descriptor) {\n throw new Error(\n 'This folder has no document descriptor yet: call setDescriptor first.',\n );\n }\n descriptor.views = [\n ...descriptor.views.filter((v) => v.format !== view.format),\n view,\n ];\n await this.setDescriptor(folderId, descriptor);\n }\n\n /** Writes the descriptor, creating or replacing `document.json`. */\n async setDescriptor(\n folderId: string,\n descriptor: Omit<DocumentDescriptor, 'schema'> &\n Partial<Pick<DocumentDescriptor, 'schema'>>,\n ): Promise<void> {\n const value: DocumentDescriptor = {\n ...descriptor,\n schema: DOCUMENT_SCHEMA,\n views: descriptor.views ?? [],\n };\n const blob = new Blob([JSON.stringify(value)], {\n type: 'application/json',\n });\n const existing = await this.#descriptorFile(folderId);\n if (existing) {\n await this.client.updateFile(existing.id, {\n file: blob,\n versionTag: versionTag(),\n });\n return;\n }\n await this.client.createFile({\n file: blob,\n name: DOCUMENT_FILE,\n versionTag: versionTag(),\n parentFolderId: folderId,\n projectId: this.projectId,\n });\n }\n\n /**\n * The legacy `derivedFileId` link, read from the newest version metadata\n * that carries one. Only `fromFile` looks at it, to migrate the link into\n * the folder-document shape; nothing writes it any more.\n */\n async #derivedFileId(item: {\n versions?: { tag: string; createdAt?: unknown }[];\n _id?: unknown;\n id?: unknown;\n }): Promise<string | undefined> {\n const versions = [...(item.versions ?? [])].sort((a, b) =>\n String(b.createdAt ?? '').localeCompare(String(a.createdAt ?? '')),\n );\n for (const version of versions) {\n try {\n const metadata = await this.client.getFileVersionMetadata(\n idOf(item),\n version.tag,\n );\n const derived = (metadata as Record<string, unknown>)?.derivedFileId;\n if (typeof derived === 'string' && derived) return derived;\n } catch {\n // A version without metadata answers an error on some backends.\n }\n }\n return undefined;\n }\n\n async #descriptorFile(\n folderId: string,\n ): Promise<{ id: string } | undefined> {\n const items = await this.client.listFiles({ folderId });\n const found = items.find(\n (item) => String((item as { name?: unknown }).name ?? '') === DOCUMENT_FILE,\n );\n return found ? { id: idOf(found as never) } : undefined;\n }\n}\n\n/** The lowercase, dot-less format a file's name declares. */\nfunction formatOf(fileName: string, extension?: string): string {\n const fromExt = (extension ?? '').replace(/^\\./, '').toLowerCase();\n if (fromExt) return fromExt;\n const dot = fileName.lastIndexOf('.');\n return dot > 0 ? fileName.slice(dot + 1).toLowerCase() : '';\n}\n\n/** Accepts only a shape that really is a descriptor; null otherwise. */\nfunction normalize(parsed: unknown): DocumentDescriptor | null {\n if (!parsed || typeof parsed !== 'object') return null;\n const raw = parsed as Record<string, unknown>;\n if (raw.schema !== DOCUMENT_SCHEMA) return null;\n if (typeof raw.name !== 'string') return null;\n const views = Array.isArray(raw.views)\n ? raw.views.filter(\n (v): v is DocumentView =>\n !!v &&\n typeof v === 'object' &&\n typeof (v as DocumentView).fileId === 'string' &&\n typeof (v as DocumentView).format === 'string',\n )\n : [];\n const native = raw.native as DocumentDescriptor['native'];\n const hasNative =\n !!native &&\n typeof native === 'object' &&\n typeof native.fileId === 'string' &&\n typeof native.format === 'string';\n return {\n schema: DOCUMENT_SCHEMA,\n name: raw.name,\n ...(hasNative ? { native: { fileId: native.fileId, format: native.format } } : {}),\n views,\n };\n}\n","/**\n * The history API: documents, versions and change requests, with the flow\n * storage encapsulated.\n *\n * The vocabulary is deliberately small and BIM-shaped:\n * - A DOC is a connected native document (a Revit model, an AutoCAD drawing).\n * - A VERSION is one sync of it: who, when, what changed.\n * - A SUGGESTION is a change request someone queued for the doc's owner to\n * accept or dismiss in the native app. Nobody writes in somebody else's\n * document.\n *\n * EVERYTHING BELOW THIS SURFACE IS PRIVATE. Today the data lives as plain\n * project files (the `bimterop` folder, `revitflow_history.json`,\n * `revitflow_ops.json`, hidden deltas) written by the flow plugins — see\n * PROTOCOL.md in the flow repo. This module is the ONLY place in consumer\n * code allowed to know that: when the platform grows a first-class history\n * API, or the layout moves into hidden storage, this file changes and its\n * callers do not.\n *\n * KNOWN LIMIT, deliberate: appending re-uploads the whole history file, and\n * the backend has no compare-and-swap, so two writers syncing the same doc at\n * the same instant can lose one version silently. `sync` narrows the window\n * by re-reading right before it writes and refusing when the head moved\n * (StaleHistoryError), but only a server-side append can close it. That is\n * the agreed phase 2.\n */\nimport type { EngineServicesClient } from './client';\nimport { ProjectDocuments, type DocumentDescriptor, type DocumentView } from './documents';\n\n/** One element mutation inside a version. Wire-compatible with the plugins. */\nexport interface FlowChange {\n /** create | update | delete. */\n type: 'create' | 'update' | 'delete' | string;\n /** The native application's own id for the element (Revit UniqueId, AutoCAD handle). */\n uniqueId: string;\n}\n\n/** Per-version change tallies. */\nexport interface FlowCounts {\n added: number;\n modified: number;\n removed: number;\n}\n\n/**\n * One sync of a document. Field names are the wire format the plugins write\n * (`revitflow_history.json`); do not rename them.\n */\nexport interface FlowVersion {\n /** Identity, minted by the writer. */\n guid: string;\n /** The versions this one was built on; absent on a root. First entry is the continued line. */\n parents?: string[] | null;\n /** The CDE's storage version number, when there is one. Data, never identity. */\n version?: number;\n /** What the author said it was for, when they said anything. */\n message?: string;\n author: string;\n /** Which application wrote it: 'revit', 'autocad', 'rhino'… */\n source: string;\n /** ISO UTC. */\n timestamp: string;\n changes: FlowChange[];\n counts: FlowCounts;\n /** Hidden-file id of the delta .frag; absent on the baseline and geometry-less versions. */\n deltaId?: string;\n /** Hidden-file id of the per-element geometry fingerprints, when the writer keeps them. */\n geomId?: string;\n /** Platform user id of the committer, when the writer knew it. */\n userId?: string;\n /** This version re-exported the whole model (the visible .frag shows it as of here). */\n full?: boolean;\n compact?: boolean;\n /** Suggestions this version applied (their opIds). */\n appliedOps?: string[];\n /** Position in the timeline, derived from the parent graph when read. Never stored. */\n ordinal?: number;\n}\n\n/** Wire shape of `revitflow_history.json`. */\ninterface FlowHistoryFile {\n model: string;\n commits: FlowVersion[];\n}\n\n/**\n * A change request queued for a document. Wire-compatible with\n * `revitflow_ops.json` (schema `revitflow/ops@1`).\n */\nexport interface FlowSuggestion {\n opId: string;\n /**\n * The application that receives and executes it: 'revit', 'autocad', or a\n * platform app like 'designer'. A suggestion without a recipient is not a\n * suggestion; absent only in entries written before this field existed,\n * where the recipient is the document's own source.\n */\n to?: string;\n /** Groups the suggestions one authored action produced across several docs. */\n batchId?: string;\n /** Hidden-file id of the payload .frag (envelope `revitflow/op@2`). */\n fragId?: string;\n title?: string;\n /** add | set | remove | mixed. */\n verb?: string;\n author?: string;\n userId?: string;\n createdAt?: string;\n /** The version this was authored against, by guid. */\n baseCommitGuid?: string;\n /** The storage version that version landed in, when known. Data only. */\n baseCommit?: number;\n /** How many elements it targets. */\n targets?: number;\n state?: 'pending' | 'applied' | 'discarded' | string;\n /** The native version that materialised it, once applied (storage version number). */\n appliedInCommit?: number | null;\n /** Native ids it touched or created, written by the plugin when it applied. */\n affectedIds?: string[];\n}\n\n/** Wire shape of `revitflow_ops.json`. */\ninterface FlowOpsFile {\n schema?: string;\n ops: FlowSuggestion[];\n}\n\n/** A connected document, as listed from the project. */\nexport interface FlowDocInfo {\n /** The native application that owns it: 'revit', 'autocad'… */\n source: string;\n /** The document's own id within that application. */\n docId: string;\n /**\n * The document folder's item id — the id the CDE and the documents API\n * ({@link EngineServicesClient.documents}) know this document by.\n */\n folderId: string;\n /** The visible model file's name, when one exists yet. */\n modelName?: string;\n /**\n * True when the folder exists but holds neither history, model nor\n * suggestion queue — a document somebody connected and never synced (a\n * plugin mid-first-publish, or an abandoned start). A legitimate state,\n * listed rather than hidden; apps decide whether to show it dimmed.\n */\n empty?: boolean;\n}\n\n/**\n * One person's current hold on a document's elements, read from the lock\n * registry the native plugins arbitrate through. Element keys are the native\n * application's own ids (Revit UniqueIds). Workset-level ownership lives in\n * Revit's own binary worksharing files (the ownership mirror) and is not\n * readable here — what IS here is every element-level claim.\n */\nexport interface FlowOwner {\n /** The native application's user name, as the plugin claimed with. */\n owner: string;\n /** The element keys this person currently holds, arbitration applied. */\n elements: string[];\n}\n\n/** What `sync` needs: the change list plus whatever the writer knows. */\nexport interface SyncInput {\n author: string;\n /** Which application/tool is writing: 'revit', 'rhino', 'recipe'… */\n source: string;\n changes: FlowChange[];\n message?: string;\n /** Delta geometry for this version, uploaded as a hidden file. */\n delta?: Blob;\n /** Re-upload of the whole model; marks the version `full`. */\n model?: Blob;\n /** Platform user id, when known. */\n userId?: string;\n /** Suggestions this version applied. */\n appliedOps?: string[];\n /**\n * The head you built on. When given and the stored head differs, `sync`\n * refuses with {@link StaleHistoryError} instead of forking silently.\n */\n expectedLatestGuid?: string;\n}\n\n/** What `suggest` needs. */\nexport interface SuggestInput {\n /**\n * The application that receives and executes it. Defaults to the document's\n * own source — the native app that owns the document.\n */\n to?: string;\n /**\n * The suggestion's id, when the caller minted it up front — a payload\n * (envelope `revitflow/op@2`) carries the opId INSIDE, so whoever builds\n * one needs the id before this call. Minted here when absent.\n */\n opId?: string;\n title: string;\n /** add | set | remove | mixed. */\n verb: string;\n author: string;\n /** The suggestion's .frag payload (envelope `revitflow/op@2`), when it has one. */\n payload?: Blob;\n targets?: number;\n batchId?: string;\n userId?: string;\n /** The version it was authored against. */\n baseCommitGuid?: string;\n}\n\n/** The head moved while a writer prepared its version. Re-read and retry. */\nexport class StaleHistoryError extends Error {\n constructor(\n readonly expectedGuid: string,\n readonly actualGuid: string | undefined,\n ) {\n super(\n 'The document history advanced while this version was being prepared: ' +\n `expected head ${expectedGuid}, found ${actualGuid ?? 'none'}. ` +\n 'Read the timeline again and rebuild on the new head.',\n );\n this.name = 'StaleHistoryError';\n }\n}\n\n// ─── The storage layout, stated once ─────────────────────────────────────────\n// PROTOCOL.md §1: project → `bimterop` → `<source>-<docId>` → files.\nconst ROOT_FOLDER = 'bimterop';\nconst HISTORY_FILE = 'revitflow_history.json';\nconst OPS_FILE = 'revitflow_ops.json';\nconst OPS_SCHEMA = 'revitflow/ops@1';\nconst LEGACY_MODEL_FILE = 'revitflow_model.frag';\n// Internal bookkeeping files that are NOT the model.\nconst INTERNAL_PREFIX = 'revitflow_';\n// The element-lock anchor: a visible file in the doc folder whose HIDDEN\n// children are live claims ({ revitflowlock: 1, user, keys[], since }), one\n// per client. Arbitration is listing order: the earliest claim naming a key\n// holds it. Written by the plugins' LockRegistry; read-only here.\nconst LOCKS_ANCHOR = 'bimterop-locks-anchor';\nconst versionTag = () => `v-${Date.now()}`;\n\ninterface StoredFile {\n id: string;\n name: string;\n}\n\n/**\n * Only the folders whose parent IS `parentId`. Needed on top of the query\n * filter because the backend ignores an unknown `parentFolderId` and answers\n * with every folder of the project.\n */\nfunction childrenOf<T extends { parentId?: unknown }>(\n folders: T[],\n parentId: string,\n): T[] {\n return folders.filter((f) => String(f.parentId ?? '') === parentId);\n}\n\n/** Normalizes the `_id`/`id` split the item endpoints disagree on. */\nfunction idOf(item: { _id?: unknown; id?: unknown }): string {\n return String(item._id ?? item.id ?? '');\n}\n\n/**\n * The history of one project. Get it from {@link EngineServicesClient.history}.\n */\nexport class ProjectHistory {\n #rootFolderId?: string;\n\n constructor(\n private readonly client: EngineServicesClient,\n readonly projectId: string,\n ) {}\n\n /** The project's connected documents. */\n async docs(): Promise<FlowDocInfo[]> {\n const root = await this.#root();\n if (!root) return [];\n const folders = await this.client.listFolders({\n parentFolderId: root,\n projectId: this.projectId,\n });\n const docs: FlowDocInfo[] = [];\n // Filtered here as well as in the query: the backend ignores an unknown\n // `parentFolderId` filter and answers with EVERY folder of the project,\n // which made any project folder with a dash in its name look like a doc.\n for (const folder of childrenOf(folders, root)) {\n const name = String(folder.name ?? '');\n const dash = name.indexOf('-');\n if (dash <= 0) continue;\n // One listing per doc, so the caller can tell a live document from a\n // never-synced shell without fetching anything else.\n const files = await this.client.listFiles({\n folderId: idOf(folder as never),\n });\n const names = files.map((f) =>\n String((f as { name?: unknown }).name ?? ''),\n );\n const model =\n names.find((n) => n === LEGACY_MODEL_FILE) ??\n names.find(\n (n) => n.endsWith('.frag') && !n.startsWith(INTERNAL_PREFIX),\n );\n const hasAny =\n names.includes(HISTORY_FILE) || names.includes(OPS_FILE) || !!model;\n docs.push({\n source: name.slice(0, dash),\n docId: name.slice(dash + 1),\n folderId: idOf(folder as never),\n modelName: model,\n ...(hasAny ? {} : { empty: true }),\n });\n }\n return docs;\n }\n\n /** One document's history. `source` and `docId` as {@link docs} lists them. */\n doc(source: string, docId: string): FlowDoc {\n return new FlowDoc(this.client, this, source, docId);\n }\n\n /** @internal The `bimterop` folder id, resolved once. */\n async rootFolderId(create = false): Promise<string | undefined> {\n if (this.#rootFolderId) return this.#rootFolderId;\n const found = await this.#root();\n if (found) return found;\n if (!create) return undefined;\n const made = await this.client.createFolder(\n ROOT_FOLDER,\n undefined,\n this.projectId,\n );\n this.#rootFolderId = idOf(made as never);\n return this.#rootFolderId;\n }\n\n async #root(): Promise<string | undefined> {\n if (this.#rootFolderId) return this.#rootFolderId;\n const folders = await this.client.listFolders({\n projectId: this.projectId,\n });\n const root = folders.find(\n (f) => String(f.name ?? '') === ROOT_FOLDER && !f.parentId,\n );\n if (root) this.#rootFolderId = idOf(root as never);\n return this.#rootFolderId;\n }\n}\n\n/**\n * One connected document: its timeline, its model, and its suggestions.\n */\nexport class FlowDoc {\n #folderId?: string;\n\n constructor(\n private readonly client: EngineServicesClient,\n private readonly project: ProjectHistory,\n readonly source: string,\n readonly docId: string,\n ) {}\n\n // ─── Reading ───────────────────────────────────────────────────────────────\n\n /**\n * The document's versions, oldest first, ordered by the parent graph (not\n * by array position, which concurrent writers do not keep meaningful).\n * Each version gets its `ordinal` filled in.\n */\n async timeline(): Promise<FlowVersion[]> {\n const history = await this.#readHistory();\n return orderByGraph(history?.commits ?? []);\n }\n\n /** The head of the timeline, or null before the first sync. */\n async latest(): Promise<FlowVersion | null> {\n const timeline = await this.timeline();\n return timeline.length ? timeline[timeline.length - 1] : null;\n }\n\n /**\n * A version's delta geometry as a .frag. The baseline (`full`) versions have\n * no delta: their geometry IS the model file — use {@link model}.\n */\n async delta(version: FlowVersion): Promise<Blob> {\n if (!version.deltaId) {\n throw new Error(\n `Version ${version.guid} carries no delta: it is a full export — read model() instead.`,\n );\n }\n const response = await this.client.downloadHiddenFile(version.deltaId);\n return await response.blob();\n }\n\n /** The visible model .frag as last fully exported. */\n async model(): Promise<Blob> {\n const file = await this.#modelFile();\n if (!file) {\n throw new Error(\n `Document ${this.source}-${this.docId} has no model file yet.`,\n );\n }\n const response = await this.client.downloadFile(file.id);\n return await response.blob();\n }\n\n /** The document folder's item id — the id the CDE knows this document by. */\n async folderId(): Promise<string> {\n return await this.#folder(false);\n }\n\n // ─── The document descriptor ───────────────────────────────────────────────\n\n /**\n * The document descriptor (`document.json`), or null when the folder does\n * not carry one yet — an old folder from before descriptors existed.\n */\n async descriptor(): Promise<DocumentDescriptor | null> {\n return await this.#documents.descriptor(await this.#folder(false));\n }\n\n /**\n * The first view whose format appears in `formats`, searched in the order\n * of the list (the caller's preference wins). Falls back to the visible\n * model .frag on a descriptor-less folder, so old documents keep viewing.\n */\n async view(formats: string[]): Promise<DocumentView | null> {\n const folderId = await this.#folder(false);\n const descriptor = await this.#documents.descriptor(folderId);\n if (descriptor) {\n for (const format of formats) {\n const match = descriptor.views.find((v) => v.format === format);\n if (match) return match;\n }\n return null;\n }\n if (!formats.includes('frag')) return null;\n const model = await this.#modelFile();\n return model ? { fileId: model.id, format: 'frag' } : null;\n }\n\n /**\n * Registers a renderable representation, creating the descriptor when the\n * folder predates them (named after the model file, or the folder itself).\n * One view per format: a same-format view is replaced, not accumulated.\n */\n async addView(view: DocumentView): Promise<void> {\n const folderId = await this.#folder(true);\n const descriptor = await this.#documents.descriptor(folderId);\n if (descriptor) {\n await this.#documents.addView(folderId, view);\n return;\n }\n const model = await this.#modelFile();\n await this.#documents.setDescriptor(folderId, {\n name: model?.name.replace(/\\.frag$/, '') ?? this.#folderName,\n views: [view],\n });\n }\n\n // ─── Ownership (element locks) ─────────────────────────────────────────────\n\n /**\n * Who currently holds which elements, read from the lock registry the\n * native plugins arbitrate through. Read-only: claiming and releasing stay\n * with the plugins. Empty when nobody holds anything (or the document has\n * no lock anchor yet). Arbitration is applied: a key contested by two\n * claims counts only for the earliest one, matching the plugins' rule.\n */\n async ownership(): Promise<FlowOwner[]> {\n const anchor = await this.#file(LOCKS_ANCHOR);\n if (!anchor) return [];\n const metas = await this.client.getHiddenFilesByParent(anchor.id);\n\n // Fetched in parallel, kept in listing order: order IS the arbitration.\n const claims = await Promise.all(\n metas.map(async (meta) => {\n try {\n const id = idOf(meta as never);\n const response = await this.client.downloadHiddenFile(id);\n const parsed = JSON.parse(await response.text()) as Record<\n string,\n unknown\n >;\n if (!parsed || typeof parsed !== 'object') return null;\n if (!('revitflowlock' in parsed)) return null;\n if (!Array.isArray(parsed.keys)) return null;\n return {\n owner: String(parsed.user ?? ''),\n keys: parsed.keys.filter((k): k is string => typeof k === 'string'),\n };\n } catch {\n return null;\n }\n }),\n );\n\n const taken = new Set<string>();\n const byOwner = new Map<string, string[]>();\n for (const claim of claims) {\n if (!claim) continue;\n for (const key of claim.keys) {\n if (!key || taken.has(key)) continue;\n taken.add(key);\n const list = byOwner.get(claim.owner) ?? [];\n list.push(key);\n byOwner.set(claim.owner, list);\n }\n }\n return [...byOwner.entries()].map(([owner, elements]) => ({\n owner,\n elements,\n }));\n }\n\n get #documents(): ProjectDocuments {\n return new ProjectDocuments(this.client, this.project.projectId);\n }\n\n // ─── Writing versions ─────────────────────────────────────────────────────\n\n /**\n * Appends one version: uploads the geometry it carries, then the updated\n * history. Give `expectedLatestGuid` whenever you built on a head you read,\n * so a concurrent writer surfaces as {@link StaleHistoryError} instead of a\n * silent fork.\n */\n async sync(input: SyncInput): Promise<FlowVersion> {\n const folderId = await this.#folder(true);\n let history = (await this.#readHistory()) ?? {\n model: this.docId,\n commits: [],\n };\n\n const head = lastByGraph(history.commits);\n if (\n input.expectedLatestGuid !== undefined &&\n head?.guid !== input.expectedLatestGuid\n ) {\n throw new StaleHistoryError(input.expectedLatestGuid, head?.guid);\n }\n\n const version: FlowVersion = {\n guid: mintGuid(),\n ...(head ? { parents: [head.guid] } : {}),\n author: input.author,\n source: input.source,\n timestamp: new Date().toISOString(),\n ...(input.message ? { message: input.message } : {}),\n ...(input.userId ? { userId: input.userId } : {}),\n ...(input.appliedOps?.length ? { appliedOps: input.appliedOps } : {}),\n changes: input.changes,\n counts: tally(input.changes),\n };\n\n if (input.model) {\n await this.#writeModel(folderId, input.model);\n version.full = true;\n }\n if (input.delta) {\n const modelFile = await this.#modelFile();\n if (!modelFile) {\n throw new Error(\n 'A delta needs the model file to hang from: sync a full model first.',\n );\n }\n const hidden = await this.client.createHiddenFile(\n input.delta,\n modelFile.id,\n );\n version.deltaId = String(\n (hidden as { _id?: unknown; id?: unknown })._id ??\n (hidden as { id?: unknown }).id,\n );\n }\n\n // Re-read right before writing: the smallest window this storage allows.\n const fresh = await this.#readHistory();\n if (fresh) {\n history = fresh;\n const freshHead = lastByGraph(history.commits);\n if (\n input.expectedLatestGuid !== undefined &&\n freshHead?.guid !== input.expectedLatestGuid\n ) {\n throw new StaleHistoryError(input.expectedLatestGuid, freshHead?.guid);\n }\n if (freshHead && !version.parents) version.parents = [freshHead.guid];\n }\n history.commits.push(version);\n await this.#writeJson(folderId, HISTORY_FILE, history);\n return version;\n }\n\n // ─── Suggestions (change requests) ────────────────────────────────────────\n\n /** Every suggestion in the document's queue, pending or resolved. */\n async suggestions(): Promise<FlowSuggestion[]> {\n const ops = await this.#readOps();\n return ops?.ops ?? [];\n }\n\n /** The suggestions still waiting for the owner, oldest first. */\n async pendingSuggestions(): Promise<FlowSuggestion[]> {\n return (await this.suggestions()).filter((op) => op.state === 'pending');\n }\n\n /**\n * Queues a change request for this document. The payload, when given, is\n * uploaded as a hidden file under the suggestions index.\n */\n async suggest(input: SuggestInput): Promise<FlowSuggestion> {\n const folderId = await this.#folder(true);\n const index = (await this.#readOps()) ?? { schema: OPS_SCHEMA, ops: [] };\n const indexFile = await this.#file(OPS_FILE);\n\n const suggestion: FlowSuggestion = {\n opId: input.opId ?? mintGuid(),\n to: input.to ?? this.source,\n title: input.title,\n verb: input.verb,\n author: input.author,\n createdAt: new Date().toISOString(),\n state: 'pending',\n ...(input.targets !== undefined ? { targets: input.targets } : {}),\n ...(input.batchId ? { batchId: input.batchId } : {}),\n ...(input.userId ? { userId: input.userId } : {}),\n ...(input.baseCommitGuid\n ? { baseCommitGuid: input.baseCommitGuid }\n : {}),\n };\n\n if (input.payload) {\n // The payload hangs from the index file, so it exists first.\n const holder =\n indexFile ??\n (await this.#createJson(folderId, OPS_FILE, index));\n const hidden = await this.client.createHiddenFile(\n input.payload,\n holder.id,\n );\n suggestion.fragId = String(\n (hidden as { _id?: unknown; id?: unknown })._id ??\n (hidden as { id?: unknown }).id,\n );\n }\n\n const fresh = (await this.#readOps()) ?? index;\n fresh.schema ??= OPS_SCHEMA;\n fresh.ops.push(suggestion);\n await this.#writeJson(folderId, OPS_FILE, fresh);\n return suggestion;\n }\n\n /** A suggestion's .frag payload. */\n async suggestionPayload(suggestion: FlowSuggestion): Promise<Blob> {\n if (!suggestion.fragId) {\n throw new Error(`Suggestion ${suggestion.opId} carries no payload.`);\n }\n const response = await this.client.downloadHiddenFile(suggestion.fragId);\n return await response.blob();\n }\n\n /**\n * Marks a suggestion applied (naming the version that materialised it) or\n * discarded. The native plugins do this themselves when they apply; apps\n * use it for `discarded`.\n */\n async resolveSuggestion(\n opId: string,\n outcome:\n | { state: 'applied'; appliedInCommit?: number; affectedIds?: string[] }\n | { state: 'discarded' },\n ): Promise<FlowSuggestion> {\n const folderId = await this.#folder(false);\n if (!folderId) throw new Error('This document has no suggestion queue.');\n const index = await this.#readOps();\n const suggestion = index?.ops.find((op) => op.opId === opId);\n if (!index || !suggestion) {\n throw new Error(`No suggestion ${opId} in this document's queue.`);\n }\n Object.assign(suggestion, outcome);\n await this.#writeJson(folderId, OPS_FILE, index);\n return suggestion;\n }\n\n // ─── The layout, below the surface ────────────────────────────────────────\n\n get #folderName(): string {\n return `${this.source}-${this.docId}`;\n }\n\n async #folder(create: boolean): Promise<string> {\n if (this.#folderId) return this.#folderId;\n const rootId = await this.project.rootFolderId(create);\n if (!rootId) {\n throw new Error(\n `Project ${this.project.projectId} has no connected documents yet.`,\n );\n }\n const folders = await this.client.listFolders({\n parentFolderId: rootId,\n projectId: this.project.projectId,\n });\n // Same defensive filter as docs(): the backend may answer with every\n // folder of the project, and a same-named folder elsewhere must not win.\n const found = childrenOf(folders, rootId).find(\n (f) => String(f.name ?? '') === this.#folderName,\n );\n if (found) {\n this.#folderId = idOf(found as never);\n return this.#folderId;\n }\n if (!create) {\n throw new Error(\n `Document ${this.#folderName} does not exist in this project.`,\n );\n }\n const made = await this.client.createFolder(\n this.#folderName,\n rootId,\n this.project.projectId,\n );\n this.#folderId = idOf(made as never);\n return this.#folderId;\n }\n\n async #files(): Promise<StoredFile[]> {\n const folderId = await this.#folder(false);\n const items = await this.client.listFiles({ folderId });\n return items.map((item) => ({\n id: idOf(item as never),\n name: String((item as { name?: unknown }).name ?? ''),\n }));\n }\n\n async #file(name: string): Promise<StoredFile | undefined> {\n try {\n return (await this.#files()).find((f) => f.name === name);\n } catch {\n return undefined;\n }\n }\n\n async #modelFile(): Promise<StoredFile | undefined> {\n try {\n const files = await this.#files();\n return (\n files.find((f) => f.name === LEGACY_MODEL_FILE) ??\n files.find(\n (f) =>\n f.name.endsWith('.frag') && !f.name.startsWith(INTERNAL_PREFIX),\n )\n );\n } catch {\n return undefined;\n }\n }\n\n async #readJson<T>(name: string): Promise<T | undefined> {\n const file = await this.#file(name);\n if (!file) return undefined;\n const response = await this.client.downloadFile(file.id);\n const text = await response.text();\n if (!text.trim()) return undefined;\n return JSON.parse(text) as T;\n }\n\n #readHistory(): Promise<FlowHistoryFile | undefined> {\n return this.#readJson<FlowHistoryFile>(HISTORY_FILE);\n }\n\n #readOps(): Promise<FlowOpsFile | undefined> {\n return this.#readJson<FlowOpsFile>(OPS_FILE);\n }\n\n async #writeJson(\n folderId: string,\n name: string,\n value: unknown,\n ): Promise<StoredFile> {\n const blob = new Blob([JSON.stringify(value)], {\n type: 'application/json',\n });\n const existing = await this.#file(name);\n if (existing) {\n await this.client.updateFile(existing.id, {\n file: blob,\n versionTag: versionTag(),\n });\n return existing;\n }\n return await this.#createJson(folderId, name, value);\n }\n\n async #createJson(\n folderId: string,\n name: string,\n value: unknown,\n ): Promise<StoredFile> {\n const blob = new Blob([JSON.stringify(value)], {\n type: 'application/json',\n });\n const created = await this.client.createFile({\n file: blob,\n name,\n versionTag: versionTag(),\n parentFolderId: folderId,\n projectId: this.project.projectId,\n });\n const item = (created as { item?: { _id?: unknown; id?: unknown } }).item;\n return { id: idOf((item ?? created) as never), name };\n }\n\n async #writeModel(folderId: string, model: Blob): Promise<StoredFile> {\n const existing = await this.#modelFile();\n if (existing) {\n await this.client.updateFile(existing.id, {\n file: model,\n versionTag: versionTag(),\n });\n return existing;\n }\n const name = `${this.#folderName}.frag`;\n const created = await this.client.createFile({\n file: model,\n name,\n versionTag: versionTag(),\n parentFolderId: folderId,\n projectId: this.project.projectId,\n });\n const item = (created as { item?: { _id?: unknown; id?: unknown } }).item;\n return { id: idOf((item ?? created) as never), name };\n }\n}\n\n// ─── Graph helpers ───────────────────────────────────────────────────────────\n\nfunction tally(changes: FlowChange[]): FlowCounts {\n const counts: FlowCounts = { added: 0, modified: 0, removed: 0 };\n for (const change of changes) {\n if (change.type === 'create') counts.added++;\n else if (change.type === 'delete') counts.removed++;\n else counts.modified++;\n }\n return counts;\n}\n\n/**\n * Orders versions by walking the parent graph from the root along first\n * parents, breaking forks by timestamp — array position is not meaningful\n * once more than one application writes. Fills `ordinal`.\n */\nexport function orderByGraph(versions: FlowVersion[]): FlowVersion[] {\n if (versions.length <= 1) {\n versions.forEach((v, i) => (v.ordinal = i));\n return [...versions];\n }\n const byGuid = new Map(versions.map((v) => [v.guid, v]));\n const children = new Map<string, FlowVersion[]>();\n const roots: FlowVersion[] = [];\n for (const version of versions) {\n const parent = version.parents?.[0];\n if (parent && byGuid.has(parent)) {\n const list = children.get(parent) ?? [];\n list.push(version);\n children.set(parent, list);\n } else {\n roots.push(version);\n }\n }\n const byTime = (a: FlowVersion, b: FlowVersion) =>\n String(a.timestamp).localeCompare(String(b.timestamp));\n roots.sort(byTime);\n\n const ordered: FlowVersion[] = [];\n const stack = [...roots].reverse();\n const seen = new Set<string>();\n while (stack.length) {\n const version = stack.pop()!;\n if (seen.has(version.guid)) continue;\n seen.add(version.guid);\n ordered.push(version);\n const next = (children.get(version.guid) ?? []).sort(byTime);\n for (let i = next.length - 1; i >= 0; i--) stack.push(next[i]);\n }\n // Anything unreachable (broken parents) still shows, by time, at the end.\n for (const version of versions) {\n if (!seen.has(version.guid)) ordered.push(version);\n }\n ordered.forEach((v, i) => (v.ordinal = i));\n return ordered;\n}\n\nfunction lastByGraph(versions: FlowVersion[]): FlowVersion | undefined {\n const ordered = orderByGraph(versions);\n return ordered[ordered.length - 1];\n}\n\n/** A random v4 guid, for version guids and suggestion opIds. */\nexport function mintGuid(): string {\n const anyCrypto = globalThis.crypto as { randomUUID?: () => string };\n if (anyCrypto?.randomUUID) return anyCrypto.randomUUID();\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {\n const r = (Math.random() * 16) | 0;\n return (c === 'x' ? r : (r & 0x3) | 0x8).toString(16);\n });\n}\n","/**\n * Recipes: scripts that write change requests (suggestions) in a native\n * application's own language.\n *\n * A recipe's whole contract is one sentence: it reads some input — another\n * document's version, platform elements, points, a spreadsheet, anything —\n * and queues a SUGGESTION for a target document, expressed in that\n * application's native vocabulary (families, types, levels, blocks, layers).\n * Nothing applies until the document's owner accepts it in the native app,\n * which is why trying a recipe is always safe.\n *\n * A recipe is defined by its contract, not by where it runs: `runtime`\n * declares the default ('browser' runs where the caller is; 'cloud' is for\n * recipes that must run with nobody in front). This module is the local\n * registry and runner; the platform-level catalog (recipes as published\n * items) is the agreed phase 2 and will sit on top of the same manifest.\n */\nimport type { EngineServicesClient } from './client';\nimport { mintGuid, type FlowDoc, type FlowSuggestion } from './history';\n\n/**\n * How a settings property says \"this names something that EXISTS\". Put it on\n * the property as `x-existing` inside {@link RecipeManifest.settingsSchema}:\n * the app resolves the candidates and renders a list — people pick, they\n * never type the name of a thing that exists.\n *\n * Resolving the candidates is the APP's job today (reading `doc.model()` of\n * the target, or the declared source file, takes the fragments toolkit, which\n * the SDK does not carry). The kinds are stable so nothing changes for\n * recipes when a shared reader lands in that toolkit.\n */\nexport interface ExistingLookup {\n /** What kind of existing thing: 'document' | 'family-type' | 'level' | 'layer' | 'workset'… */\n of: string;\n /** Where it exists: the target document, or the declared source. Default 'target'. */\n from?: 'target' | 'source';\n /**\n * Narrows the candidates: attribute equals value, against the attribute\n * names EXACTLY as the native application publishes them, no case\n * normalization. Prefer the stable machine fields over display names —\n * Revit's `Category` text is localized per install (\"Armazón estructural\"),\n * so a column filter is `{ CategoryId: '-2001330' }`, never\n * `{ Category: 'Columns' }`.\n */\n where?: Record<string, string>;\n}\n\n/** What a recipe declares about itself. Shown in catalogs, checked by apps. */\nexport interface RecipeManifest {\n /** Machine name, unique in a catalog: 'rhino-points-to-revit-columns'. */\n name: string;\n /** The human name a card shows: 'Rhino points to Revit columns'. */\n title?: string;\n /** The one sentence a non-programmer reads: what it converts into what. */\n description: string;\n /** The long-form explanation an app renders, as markdown. */\n doc?: string;\n /** The native application whose language it writes: 'revit', 'autocad'… */\n to: string;\n /** The input kinds it understands: 'rhino-model', 'platform-elements', 'points', 'csv'… */\n inputs: string[];\n /**\n * What the app should offer as the input picker, when the input is a thing\n * of the project rather than inline data: another connected document, or a\n * project file (then `extensions` narrows the listing). The picked value is\n * what arrives as `input`, and what `x-existing: { from: 'source' }`\n * lookups read.\n */\n source?:\n | { kind: 'document'; source?: string }\n | { kind: 'project-file'; extensions?: string[] };\n /** Where it runs by default. Browser unless it must run unattended. */\n runtime?: 'browser' | 'cloud';\n /**\n * JSON Schema for `settings`. Apps generate the settings form from it, so\n * anything that names an EXISTING thing (a target document, a family, a\n * level) carries `x-existing` ({@link ExistingLookup}) and renders as a\n * list the app fills — people pick, they never type names of things that\n * exist. Free text is only for what a person invents.\n */\n settingsSchema?: Record<string, unknown>;\n /**\n * The self-documentation an app renders: a \"reads → proposes\" table whose\n * rows are RULES (not objects), so a dry run can fill it with real tallies.\n */\n rules?: { reads: string; proposes: string }[];\n}\n\n/** Everything a recipe's `run` gets to work with. */\nexport interface RecipeContext<Settings = Record<string, unknown>> {\n client: EngineServicesClient;\n projectId: string;\n /** The document the suggestion is for. Read its timeline/model if needed. */\n targetDoc: FlowDoc;\n /**\n * The suggestion's id, minted BEFORE the run: the payload envelope\n * (`revitflow/op@2`) carries the opId inside, so the builder needs it.\n * When the run is only a plan, nothing is queued and the id is discarded.\n */\n opId: string;\n /** The declared input, already fetched by the caller (bytes, ids, rows…). */\n input: unknown;\n settings: Settings;\n}\n\n/** What a recipe's `run` returns: the suggestion, ready to queue. */\nexport interface RecipeResult {\n title: string;\n /** add | set | remove | mixed. */\n verb: string;\n /** The .frag payload (envelope `revitflow/op@2`), when the recipe builds one. */\n payload?: Blob;\n targets?: number;\n /** Per-rule tallies matching `manifest.rules`, filled by the run. */\n ruleTallies?: { read: number; proposed: number }[];\n}\n\n/** A recipe: its manifest plus the function that writes the suggestion. */\nexport interface Recipe<Settings = Record<string, unknown>>\n extends RecipeManifest {\n run(context: RecipeContext<Settings>): Promise<RecipeResult>;\n}\n\n/** What {@link Recipes.run} returns: the queued suggestion plus the tallies. */\nexport interface RecipeRunOutcome {\n suggestion: FlowSuggestion;\n result: RecipeResult;\n}\n\n/**\n * What {@link Recipes.plan} returns: everything needed to queue EXACTLY what\n * was planned, without running the recipe again — the payload already embeds\n * this `opId`. Hand it to {@link Recipes.queue} when the person confirms.\n */\nexport interface RecipePlan {\n opId: string;\n projectId: string;\n target: { source: string; docId: string };\n /** The head the plan was built against, for the suggestion's base. */\n baseCommitGuid?: string;\n result: RecipeResult;\n}\n\n/**\n * The local recipe registry and runner. Reach it as `client.recipes`.\n */\nexport class Recipes {\n readonly #registry = new Map<string, Recipe<never>>();\n\n constructor(private readonly client: EngineServicesClient) {}\n\n /** Registers a recipe. One per name; a second with the same name throws. */\n register<S>(recipe: Recipe<S>): void {\n if (this.#registry.has(recipe.name)) {\n throw new Error(`A recipe named \"${recipe.name}\" is already registered.`);\n }\n this.#registry.set(recipe.name, recipe as Recipe<never>);\n }\n\n /** The registered recipes, optionally filtered by target application. */\n list(filter?: { to?: string; input?: string }): RecipeManifest[] {\n const all = [...this.#registry.values()];\n return all.filter(\n (recipe) =>\n (!filter?.to || recipe.to === filter.to) &&\n (!filter?.input || recipe.inputs.includes(filter.input)),\n );\n }\n\n /** A registered recipe by name, or undefined. */\n get(name: string): RecipeManifest | undefined {\n return this.#registry.get(name);\n }\n\n /**\n * Runs a recipe WITHOUT queueing anything: the dry pass. Returns a\n * {@link RecipePlan} — the result to show (title, tallies, targets) plus\n * everything {@link queue} needs to queue EXACTLY this, payload and opId\n * included, with no second run. Discard it and the plan never happened.\n */\n async plan<S>(\n name: string,\n options: RecipeRunOptions<S>,\n ): Promise<RecipePlan> {\n const { base, opId, result } = await this.#execute(name, options);\n return {\n opId,\n projectId: options.projectId,\n target: options.target,\n ...(base?.guid ? { baseCommitGuid: base.guid } : {}),\n result,\n };\n }\n\n /**\n * Queues exactly what {@link plan} planned: same opId, same payload, no\n * second execution. The pair plan → confirm → queue is the UI flow; `run`\n * is the one-shot shortcut.\n */\n async queue(\n plan: RecipePlan,\n options: { author: string; userId?: string },\n ): Promise<RecipeRunOutcome> {\n const targetDoc = this.client\n .history(plan.projectId)\n .doc(plan.target.source, plan.target.docId);\n const suggestion = await targetDoc.suggest({\n opId: plan.opId,\n title: plan.result.title,\n verb: plan.result.verb,\n author: options.author,\n payload: plan.result.payload,\n targets: plan.result.targets,\n userId: options.userId,\n baseCommitGuid: plan.baseCommitGuid,\n });\n return { suggestion, result: plan.result };\n }\n\n /**\n * Runs a recipe and queues its suggestion on the target document. Safe to\n * call freely: nothing touches the native application until its owner\n * accepts the suggestion there. Use {@link plan} first when the app wants\n * to show the tallies before queueing.\n */\n async run<S>(\n name: string,\n options: RecipeRunOptions<S>,\n ): Promise<RecipeRunOutcome> {\n const { targetDoc, base, opId, result } = await this.#execute(\n name,\n options,\n );\n\n const suggestion = await targetDoc.suggest({\n opId,\n title: result.title,\n verb: result.verb,\n author: options.author,\n payload: result.payload,\n targets: result.targets,\n userId: options.userId,\n baseCommitGuid: base?.guid,\n });\n\n return { suggestion, result };\n }\n\n async #execute<S>(name: string, options: RecipeRunOptions<S>) {\n const recipe = this.#registry.get(name) as Recipe<S> | undefined;\n if (!recipe) throw new Error(`No recipe named \"${name}\" is registered.`);\n if (recipe.to !== options.target.source) {\n throw new Error(\n `Recipe \"${name}\" writes ${recipe.to}, but the target document belongs to ${options.target.source}.`,\n );\n }\n\n const targetDoc = this.client\n .history(options.projectId)\n .doc(options.target.source, options.target.docId);\n const base = await targetDoc.latest();\n\n // Minted BEFORE the run: the payload envelope carries the opId inside.\n const opId = mintGuid();\n const result = await recipe.run({\n client: this.client,\n projectId: options.projectId,\n targetDoc,\n opId,\n input: options.input,\n settings: (options.settings ?? {}) as S,\n });\n return { recipe, targetDoc, base, opId, result };\n }\n}\n\n/** The options {@link Recipes.plan} and {@link Recipes.run} share. */\nexport interface RecipeRunOptions<S = Record<string, unknown>> {\n projectId: string;\n /** The target document, as `client.history(projectId).docs()` lists it. */\n target: { source: string; docId: string };\n input?: unknown;\n settings?: S;\n author: string;\n userId?: string;\n}\n","import { Metadata } from './files';\nimport { ItemFolder, ItemVersion } from './items';\n\n/**\n * Maximum number of ids the API accepts in one batch request. The client\n * methods split larger inputs into chunks of this size automatically.\n */\nexport const STORAGE_BATCH_MAX = 100;\n\nexport type BatchError = {\n status: number;\n message: string;\n};\n\nexport type HiddenFileSignedUrlBatchEntry = {\n hiddenFileId: string;\n url?: string;\n expiresAt?: string;\n error?: BatchError;\n};\n\nexport type ItemVersionsBatchEntry = {\n itemId: string;\n versions?: ItemVersion[];\n error?: BatchError;\n};\n\nexport type VersionMetadataBatchRequest = {\n itemId: string;\n versionTag: string;\n};\n\nexport type VersionMetadataBatchEntry = VersionMetadataBatchRequest & {\n metadata?: Metadata;\n error?: BatchError;\n};\n\nexport type ItemFoldersBatchEntry = {\n folderId: string;\n folder?: ItemFolder;\n error?: BatchError;\n};\n","/**\n * Parses an API error body. The platform returns `{ message, code?, details? }`\n * as JSON on failures; non-JSON bodies (proxies, gateways, plain text) yield an\n * empty result so the caller falls back to the status line.\n */\nfunction parseErrorBody(body: string): {\n message?: string;\n code?: string;\n details?: unknown;\n} {\n try {\n const json: unknown = JSON.parse(body);\n if (json && typeof json === 'object') {\n const obj = json as Record<string, unknown>;\n return {\n message: typeof obj.message === 'string' ? obj.message : undefined,\n code: typeof obj.code === 'string' ? obj.code : undefined,\n details: obj.details,\n };\n }\n } catch {}\n return {};\n}\n\n/**\n * Reads `details.retryAfter` (seconds) from a parsed error body. The platform\n * puts it there on `RATE_LIMITED` responses so the value survives proxies that\n * strip the `Retry-After` header.\n */\nfunction retryAfterFromDetails(details: unknown): number | undefined {\n if (!details || typeof details !== 'object') return undefined;\n const value = (details as Record<string, unknown>).retryAfter;\n return typeof value === 'number' && Number.isFinite(value) && value >= 0\n ? value\n : undefined;\n}\n\n/**\n * Error thrown by {@link EngineServicesClient} when the platform API responds\n * with a non-2xx status. Exposes the HTTP `status` and — when the API returns a\n * structured JSON body — its `code` and `details`, so callers can react to\n * specific failures (e.g. `code === 'LIMIT_EXCEEDED'`) instead of string-\n * matching the message.\n *\n * @example\n * ```ts\n * try {\n * await client.createComponent(props);\n * } catch (err) {\n * if (err instanceof RequestError && err.code === 'LIMIT_EXCEEDED') {\n * console.error(err.message); // \"Components limit reached (10/10)...\"\n * }\n * }\n * ```\n *\n * @example Rate limiting\n * ```ts\n * catch (err) {\n * if (err instanceof RequestError && err.status === 429) {\n * console.log(err.code); // \"RATE_LIMITED\"\n * console.log(err.details); // { limit, windowSeconds, retryAfter, scope }\n * console.log(err.retryAfter); // seconds to wait before trying again\n * }\n * }\n * ```\n */\nexport class RequestError extends Error {\n readonly status: number;\n readonly code?: string;\n readonly details?: unknown;\n readonly body: string;\n\n /**\n * Seconds to wait before retrying, taken from the `Retry-After` header or\n * from `details.retryAfter`. Only present on rate-limited (429) responses.\n */\n readonly retryAfter?: number;\n\n constructor(\n status: number,\n statusText: string,\n body: string,\n retryAfter?: number,\n ) {\n const parsed = parseErrorBody(body);\n super(parsed.message ?? `${statusText || 'Request failed'} (${status})`);\n this.name = 'RequestError';\n this.status = status;\n this.code = parsed.code;\n this.details = parsed.details;\n this.body = body;\n this.retryAfter = retryAfter ?? retryAfterFromDetails(parsed.details);\n }\n}\n","import { io } from 'socket.io-client';\nimport { ProjectDocuments } from './documents';\nimport { ProjectHistory } from './history';\nimport { Recipes } from './recipes';\nimport {\n ExecutionEntity,\n ExecutionSuscriptionReturnType,\n} from '../types/execution';\nimport { UpdateItemDto, UpdateItemFolderDto } from '../types/item.dto';\nimport {\n AppVersionProps,\n ComponentVersionProps,\n ComponentItem,\n AppItem,\n Item,\n ItemFolder,\n ItemType,\n ItemVersion,\n ItemWithVersions,\n} from '../types/items';\nimport { CreateItemResponse, UpdateItemResponse } from '../types/response';\nimport {\n CreateHiddenItemResult,\n CreateHiddenItemsBatchResult,\n HiddenFileEntity,\n Metadata,\n} from '../types/files';\nimport {\n HiddenFileSignedUrlBatchEntry,\n ItemFoldersBatchEntry,\n ItemVersionsBatchEntry,\n STORAGE_BATCH_MAX,\n VersionMetadataBatchEntry,\n VersionMetadataBatchRequest,\n} from '../types/batch';\nimport { ThatOpenContext } from '../types/context';\nimport { NpmCredentials } from '../types/npm';\nimport { RequestError } from './request-error';\n\ndeclare global {\n interface Window {\n __THATOPEN_CONTEXT__?: ThatOpenContext;\n ThatOpenCompany?: Record<string, unknown>;\n }\n}\n\nconst FOLDER_PATH = 'item/folder';\nconst ITEM_PATH = 'item';\nconst PROCESS_PATH = 'processor';\nconst NPM_REGISTRY_PATH = 'npm-registry';\nconst HIDDEN_PATH = 'hidden';\nconst ITEM_TYPE_FILE = 'FILE';\nconst ITEM_TYPE_COMPONENT = 'TOOL';\nconst ITEM_TYPE_APP = 'APP';\n\nconst RETRY_BASE_DELAY_MS = 500;\nconst RETRY_MAX_DELAY_MS = 30_000;\nconst RETRY_JITTER_RATIO = 0.25;\n\nconst sleep = (ms: number) =>\n new Promise<void>((resolve) => setTimeout(resolve, ms));\n\n/**\n * Reads `Retry-After` (seconds, or an HTTP date) from a response. Returns\n * `undefined` when the header is absent, unparseable, or when the runtime\n * hands over a response-like object without headers.\n */\nfunction parseRetryAfter(response: Response): number | undefined {\n const raw = response.headers?.get?.('Retry-After');\n if (!raw) return undefined;\n const seconds = Number(raw);\n if (Number.isFinite(seconds)) return Math.max(0, seconds);\n const timestamp = Date.parse(raw);\n if (Number.isNaN(timestamp)) return undefined;\n return Math.max(0, (timestamp - Date.now()) / 1000);\n}\n\n/**\n * Only network failures, rate limits and server errors are worth repeating.\n * Retrying a 400/401/403/404 burns quota on a request that cannot succeed —\n * and on 429 it is what turns a rate limit into an outage.\n */\nfunction isRetryable(error: unknown): boolean {\n if (!(error instanceof RequestError)) return true;\n return error.status === 429 || error.status >= 500;\n}\n\n/**\n * Exponential backoff with jitter, overridden by the server's `Retry-After`\n * when it sent one. Capped at {@link RETRY_MAX_DELAY_MS} so a long server-side\n * window never parks a request for minutes.\n */\nfunction retryDelayMs(error: unknown, attempt: number): number {\n const backoff = Math.min(\n RETRY_BASE_DELAY_MS * 2 ** attempt,\n RETRY_MAX_DELAY_MS,\n );\n const jitter = backoff * RETRY_JITTER_RATIO * Math.random();\n const serverDelay =\n error instanceof RequestError && error.retryAfter != null\n ? error.retryAfter * 1000\n : undefined;\n if (serverDelay != null) {\n return Math.min(serverDelay, RETRY_MAX_DELAY_MS) + jitter;\n }\n return backoff + jitter;\n}\n\n/**\n * Minimal shape of an OBC.Components-like object.\n * Avoids hard-coupling to `@thatopen/components` at the public API level.\n */\nexport interface ComponentsLike {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any -- generic constructor pattern requires any[]\n get<T>(c: new (...args: any[]) => T): T;\n init(): void;\n}\n\n/** Properties for creating a new item (file, component, or app). */\nexport type CreateItemProps = {\n /** The file to upload (File in browsers, Blob in Node.js). */\n file: File | Blob;\n /** Display name of the item. */\n name: string;\n /** Semantic version tag (e.g. \"v1\", \"v1.0.0\"). */\n versionTag: string;\n /** Optional folder ID to place the item in. */\n parentFolderId?: string;\n /** Optional project ID to associate the item with. */\n projectId?: string;\n /** Optional free-JSON metadata stored on the first version. */\n metadata?: Metadata;\n};\n\n/** Properties for updating an existing item. Combines rename/move with optional new version upload. */\nexport type UpdateItemProps = {\n /** New display name. */\n name?: string;\n /** New parent folder ID (moves the item). */\n parentFolderId?: string;\n /** New file to upload as a new version (File in browsers, Blob in Node.js). */\n file?: File | Blob;\n /** Version tag for the new file version. */\n versionTag?: string;\n /** Optional free-JSON metadata stored on the new version. */\n metadata?: Metadata;\n};\n\n/** Properties for creating an app. Extends {@link CreateItemProps} with app-specific version props. */\nexport type CreateAppProps = CreateItemProps & {\n /** App version properties (isOnline, url). */\n appProps?: AppVersionProps;\n};\n\n/** Properties for creating a component. Extends {@link CreateItemProps} with component-specific version props. */\nexport type CreateComponentProps = CreateItemProps & {\n /** Component version properties (type, tier, isPublic, etc.). Required. */\n componentProps: ComponentVersionProps;\n};\n\n/** Properties for updating a component. Extends {@link UpdateItemProps} with component-specific version props. */\nexport type UpdateComponentProps = UpdateItemProps & {\n /** Component version properties for the new version. */\n componentProps?: ComponentVersionProps;\n};\n\n/** Options for retrieving a single item. */\nexport type GetItemProps = {\n /** If true, includes the item's version history. */\n showVersions?: boolean;\n};\n\n/** Filter/query params for listing items. */\nexport type GetItemsParams = {\n /** Filter by folder. */\n folderId?: string;\n /** If true, includes version history for each item. */\n ShowVersions?: boolean;\n};\n\n/** Parameters for downloading a specific item version. */\nexport type DownloadItemFileParams = {\n /** Download a specific version by tag instead of the latest. */\n versionTag?: string;\n /** If true, includes draft versions in resolution. */\n withDraft?: boolean;\n};\n\n/** Configuration options for the {@link EngineServicesClient} constructor. */\nexport type EngineServicesClientProps = {\n /**\n * Number of automatic retries on request failure. Default: 0.\n *\n * Retries are spaced with exponential backoff plus jitter, and honour the\n * server's `Retry-After` when it sends one. Only network failures, 429s and\n * 5xx are retried — other 4xx fail immediately.\n */\n retries?: number;\n /**\n * If true, sends the token as an `Authorization: Bearer` header instead of\n * an `accessToken` query parameter. Use this when authenticating with an\n * Auth0 JWT (e.g. inside platform apps) rather than a platform API token.\n */\n useBearer?: boolean;\n /**\n * URL of a local execution server started with `thatopen local-server`.\n * When set, execution methods (executeComponent, onExecutionProgress,\n * listExecutions, getExecution, abortExecution) are routed to this server\n * instead of the cloud API. All other methods remain unchanged.\n *\n * @example\n * ```ts\n * const client = new EngineServicesClient(token, apiUrl, {\n * localServerUrl: 'http://localhost:4001',\n * });\n * ```\n */\n localServerUrl?: string;\n};\n\n/**\n * Client for the That Open Engine Services API.\n *\n * Provides methods for managing files, folders, components, apps,\n * executions, hidden files, projects, and permissions.\n *\n * @example\n * ```ts\n * import { EngineServicesClient } from '@thatopen/services';\n *\n * const client = new EngineServicesClient('my-access-token', 'https://api.thatopen.com');\n * const files = await client.listFiles();\n * ```\n */\nexport class EngineServicesClient {\n private apiUrl: string;\n private accessToken: string;\n private wsUrl: string;\n private retries: number;\n private useBearer: boolean;\n private builtInGlobals: Record<string, unknown> | null = null;\n\n /**\n * URL of a local execution server (e.g. `http://localhost:4001`).\n * When set, execution methods are routed to this server instead of the cloud API.\n * Set to `null` to disable local routing and use the cloud API.\n */\n localServerUrl: string | null = null;\n\n /**\n * The platform context this client was created with.\n * Contains `appId`, `projectId`, `accessToken`, and `apiUrl`.\n * Populated automatically when using {@link fromPlatformContext}.\n */\n readonly context: ThatOpenContext;\n\n /**\n * Creates a client from the platform context injected into\n * `window.__THATOPEN_CONTEXT__` by the That Open Platform.\n *\n * This is the recommended way to create a client inside platform apps.\n * It automatically reads the auth context and sets `useBearer: true`.\n *\n * @param props - Optional configuration (retry count, local server URL, etc.).\n * @returns A new EngineServicesClient instance.\n *\n * @example\n * ```ts\n * const client = EngineServicesClient.fromPlatformContext();\n * console.log(client.context.projectId);\n * ```\n */\n static fromPlatformContext(\n props?: Omit<EngineServicesClientProps, 'useBearer'>,\n ): EngineServicesClient {\n const ctx: ThatOpenContext = (typeof window !== 'undefined'\n ? window.__THATOPEN_CONTEXT__\n : null) || { appId: '', projectId: '', accessToken: '', apiUrl: '' };\n const client = new EngineServicesClient(ctx.accessToken, ctx.apiUrl, {\n ...props,\n useBearer: true,\n });\n (client as { context: ThatOpenContext }).context = ctx;\n return client;\n }\n\n /**\n * Creates a new EngineServicesClient instance.\n * @param accessToken - API access token (obtained from the platform dashboard)\n * or an Auth0 JWT (when using `useBearer: true`).\n * @param apiUrl - Base URL of the API (e.g. \"https://api.thatopen.com\").\n * @param props - Optional configuration (retry count, auth mode, etc.).\n */\n constructor(\n accessToken: string,\n apiUrl: string,\n props?: EngineServicesClientProps,\n ) {\n const { retries = 0, useBearer = false, localServerUrl } = props || {};\n let url = apiUrl;\n if (url.charAt(url.length - 1) === '/') {\n url = url.slice(0, -1);\n }\n this.apiUrl = `${url}/api`;\n this.accessToken = accessToken;\n // Origin only. The credential travels in the Socket.IO auth payload at\n // connect time, never in the URL: a failing handshake prints its URL in\n // consoles and proxy logs, token included.\n this.wsUrl = url;\n this.retries = retries;\n this.useBearer = useBearer;\n this.context = { appId: '', projectId: '', accessToken, apiUrl };\n if (localServerUrl) {\n let lsUrl = localServerUrl;\n if (lsUrl.charAt(lsUrl.length - 1) === '/') {\n lsUrl = lsUrl.slice(0, -1);\n }\n this.localServerUrl = lsUrl;\n }\n }\n\n /**\n * Sets the number of automatic retries for failed requests. Retries use\n * exponential backoff with jitter and honour `Retry-After`; only network\n * failures, 429s and 5xx are retried.\n * @param retries - Number of retries (0 = no retries).\n */\n setRetries(retries: number) {\n this.retries = retries;\n }\n\n /**\n * Registers the global libraries that built-in components need at runtime.\n *\n * Call this once after importing your libraries. Then every subsequent\n * {@link initBuiltInComponent} call will use these globals automatically\n * — you no longer need to pass a `globals` argument to each one.\n *\n * @param globals - Map of global names to module namespaces. The FULL set\n * a built-in may ask for: `OBC`, `OBF`, `BUI`, `THREE`, `FRAGS`,\n * `MARKERJS` (plus `CUI` only if the app still uses the deprecated\n * `@thatopen/ui-obc`). Only `OBC` and `BUI` are strictly required by\n * `setup()`; passing everything you import is the safe default, because\n * a built-in that needs a missing one fails at init.\n *\n * @example\n * ```ts\n * import * as OBC from \"@thatopen/components\";\n * import * as OBF from \"@thatopen/components-front\";\n * import * as BUI from \"@thatopen/ui\";\n * import * as THREE from \"three\";\n * import * as FRAGS from \"@thatopen/fragments\";\n * import * as MARKERJS from \"@markerjs/markerjs3\";\n *\n * client.setBuiltInGlobals({ OBC, OBF, BUI, THREE, FRAGS, MARKERJS });\n *\n * // Now just pass the component — no globals needed:\n * await client.initBuiltInComponent(AppManager, components);\n * await client.initBuiltInComponent(ViewerToolbar, components);\n * await client.initBuiltInComponent(ModelsPanel, components);\n * ```\n */\n setBuiltInGlobals(globals: Record<string, unknown>) {\n this.builtInGlobals = globals;\n }\n\n #buildUrl(path: string) {\n return `${this.apiUrl}/${path}`;\n }\n\n /**\n * Protected extension point for subclasses that need dynamic tokens\n * (e.g. `PlatformClient` with an auth provider callback). The default\n * returns the static token captured at construction time.\n *\n * When a subclass overrides this to call an async refresh function,\n * the new token is picked up on every request — expired tokens no\n * longer stick around.\n */\n /**\n * Socket origin without namespace or query, for gateways other than the\n * execution one. Callers pass their own credential in the Socket.IO auth\n * payload, resolved at connect time so a provider-backed client is current.\n */\n protected get socketOrigin(): string {\n return this.wsUrl.split('?')[0];\n }\n\n protected async resolveAccessToken(): Promise<string> {\n return this.accessToken;\n }\n\n async #requestApi<T = object>(\n method: string,\n path: string,\n requestData?: {\n body?: BodyInit;\n query?: object;\n contentType?:\n | 'application/json'\n | 'multipart/form-data'\n | 'application/x-www-form-urlencoded';\n retries?: number;\n responseType?: 'json' | 'blob';\n retryAttempt?: number;\n },\n ): Promise<T> {\n const { body, query, contentType, retries, responseType, retryAttempt } =\n requestData || {};\n const url = this.#buildUrl(path);\n\n const cleanQuery = this.#cleanData(query);\n const token = await this.resolveAccessToken();\n\n const params = {\n ...cleanQuery,\n ...(this.useBearer ? {} : { accessToken: token }),\n };\n\n try {\n const response = await fetch(\n url + '?' + new URLSearchParams(params).toString(),\n {\n method,\n headers: {\n Accept: 'application/json',\n ...(contentType && { 'Content-Type': contentType }),\n ...(this.useBearer && { Authorization: `Bearer ${token}` }),\n },\n ...(body && { body }),\n },\n );\n if (!response.ok) {\n const textResponse = await response\n .text()\n .then((text) => text)\n .catch(() => '');\n throw new RequestError(\n response.status,\n response.statusText,\n textResponse,\n parseRetryAfter(response),\n );\n }\n\n if (responseType === 'blob') {\n return (await response.blob()) as T;\n }\n\n return response\n .json()\n .then((data) => data as T)\n .catch(() => undefined as T);\n } catch (e) {\n const retriesLeft = retries != null ? retries : this.retries;\n if (retriesLeft > 0 && isRetryable(e)) {\n const attempt = retryAttempt ?? 0;\n await sleep(retryDelayMs(e, attempt));\n return await this.#requestApi(method, path, {\n ...requestData,\n retries: retriesLeft - 1,\n retryAttempt: attempt + 1,\n });\n }\n throw e;\n }\n }\n\n /**\n * Protected extension hook for subclasses (e.g. `PlatformClient`) that\n * need to add HTTP methods against additional backend routes. Delegates\n * to the private `#requestApi` implementation so retry / auth / query-\n * cleaning logic is applied identically.\n */\n protected async request<T = object>(\n method: string,\n path: string,\n requestData?: {\n body?: BodyInit;\n query?: object;\n contentType?:\n | 'application/json'\n | 'multipart/form-data'\n | 'application/x-www-form-urlencoded';\n retries?: number;\n responseType?: 'json' | 'blob';\n },\n ): Promise<T> {\n return this.#requestApi<T>(method, path, requestData);\n }\n\n async #requestFile(path: string, requestData?: { query?: object }) {\n const { query } = requestData || {};\n const url = this.#buildUrl(path);\n const token = await this.resolveAccessToken();\n const params = {\n ...query,\n ...(this.useBearer ? {} : { accessToken: token }),\n };\n const response = await fetch(\n url + '?' + new URLSearchParams(params).toString(),\n {\n method: 'GET',\n ...(this.useBearer && {\n headers: { Authorization: `Bearer ${token}` },\n }),\n },\n );\n\n return response;\n }\n\n // ─── Files ───────────────────────────────────────────────────────\n\n /**\n * Lists all files accessible by the current token.\n * @param filters - Optional filters for folder and archive status.\n * @returns Array of file items.\n */\n async listFiles(filters?: {\n folderId?: string;\n archived?: boolean;\n /**\n * Scope the listing to a project. Requires the token owner to have\n * `STORAGE:READ` role in that project; otherwise the backend returns\n * 403. Per-entity permission overrides are applied server-side.\n */\n projectId?: string;\n }) {\n const { folderId, archived, projectId } = filters || {};\n if (folderId) {\n return await this.#requestApi<Item[]>(\n 'GET',\n `${FOLDER_PATH}/${folderId}/items`,\n { query: { itemType: ITEM_TYPE_FILE, archived } },\n );\n }\n return await this.#requestApi<Item[]>('GET', `${ITEM_PATH}`, {\n query: {\n itemType: ITEM_TYPE_FILE,\n archived,\n ...(projectId && { projectId }),\n },\n });\n }\n\n /**\n * Gets a single file by ID, optionally including version history.\n * @param fileId - The file's unique identifier.\n * @param props - Options such as whether to include versions.\n * @returns The file item, optionally with version history.\n */\n async getFile(fileId: string, props?: GetItemProps) {\n return await this.#getItem<ItemWithVersions<Item>>(fileId, props);\n }\n\n /**\n * Uploads a new file.\n * @param fileData - File content, name, and version tag.\n * @returns The created item and its first version.\n */\n async createFile(fileData: CreateItemProps) {\n return await this.#createItem(fileData, ITEM_TYPE_FILE);\n }\n\n /**\n * Updates an existing file. Can rename, move to a different folder,\n * and/or upload a new version — all in a single call.\n * @param fileId - The file's unique identifier.\n * @param fileData - Properties to update (name, folderId, file, versionTag).\n * @returns The updated item and/or the new version.\n */\n async updateFile(\n fileId: string,\n fileData: UpdateItemProps,\n ): Promise<UpdateItemResponse> {\n return await this.#updateItem(fileId, fileData);\n }\n\n /**\n * Archives (soft-deletes) a file. Can be recovered with {@link recoverFile}.\n * @param fileId - The file's unique identifier.\n */\n async archiveFile(fileId: string) {\n return await this.#requestApi<Item>('DELETE', `${ITEM_PATH}/${fileId}`);\n }\n\n /**\n * Recovers a previously archived file.\n * @param fileId - The file's unique identifier.\n */\n async recoverFile(fileId: string) {\n return await this.#requestApi<Item>(\n 'PUT',\n `${ITEM_PATH}/${fileId}/recover`,\n );\n }\n\n /**\n * Downloads a file's content. Returns the raw fetch Response.\n * @param fileId - The file's unique identifier.\n * @param params - Optional version selection parameters.\n * @returns A fetch Response containing the file data.\n */\n async downloadFile(fileId: string, params?: DownloadItemFileParams) {\n return await this.#downloadItem(fileId, params);\n }\n\n /**\n * Retrieves the free-JSON metadata for a specific file version.\n * Returns `{}` when the version exists but has no metadata.\n * @param fileId - The file's unique identifier.\n * @param versionTag - The version tag (e.g. \"v1\").\n * @param params - Optional flags such as `withDraft`.\n */\n async getFileVersionMetadata(\n fileId: string,\n versionTag: string,\n params?: { withDraft?: boolean },\n ) {\n const { withDraft } = params || {};\n return await this.#requestApi<Metadata>(\n 'GET',\n `${ITEM_PATH}/${encodeURIComponent(fileId)}/version/${encodeURIComponent(versionTag)}/metadata`,\n {\n query: {\n ...(withDraft && { withDraft: 'true' }),\n },\n },\n );\n }\n\n /**\n * Replaces the metadata of a specific file version with the provided object.\n * @param fileId - The file's unique identifier.\n * @param versionTag - The version tag.\n * @param metadata - Free-JSON object (max 200 fields, 50-char keys/values).\n */\n async updateFileVersionMetadata(\n fileId: string,\n versionTag: string,\n metadata: Metadata,\n ) {\n return await this.#requestApi<Metadata>(\n 'PUT',\n `${ITEM_PATH}/${encodeURIComponent(fileId)}/version/${encodeURIComponent(versionTag)}/metadata`,\n {\n body: JSON.stringify({ metadata }),\n contentType: 'application/json',\n },\n );\n }\n\n /**\n * Clears all metadata from a specific file version.\n * @param fileId - The file's unique identifier.\n * @param versionTag - The version tag.\n */\n async deleteFileVersionMetadata(fileId: string, versionTag: string) {\n return await this.#requestApi<{ success: boolean }>(\n 'DELETE',\n `${ITEM_PATH}/${encodeURIComponent(fileId)}/version/${encodeURIComponent(versionTag)}/metadata`,\n );\n }\n\n /**\n * Batch variant of {@link getFileVersionMetadata}. Reads the metadata of\n * many (file, version) pairs in one request instead of one request per pair,\n * which is what a file list needs when it hydrates a whole page at once.\n *\n * Inputs longer than {@link STORAGE_BATCH_MAX} are split into several\n * requests automatically. Entries come back in the order they were asked\n * for; a pair the caller cannot read carries an `error` instead of\n * `metadata`, so one bad id does not lose the whole page.\n *\n * @param entries - The `{ itemId, versionTag }` pairs to read.\n * @param params - Optional flags such as `withDraft`.\n */\n async getFileVersionMetadataBatch(\n entries: VersionMetadataBatchRequest[],\n params?: { withDraft?: boolean },\n ): Promise<VersionMetadataBatchEntry[]> {\n const { withDraft } = params || {};\n return await this.#requestBatches(\n entries,\n async (chunk) =>\n (\n await this.#requestApi<{ results: VersionMetadataBatchEntry[] }>(\n 'POST',\n `${ITEM_PATH}/batch/version-metadata`,\n {\n body: JSON.stringify({\n entries: chunk,\n ...(withDraft !== undefined && { withDraft }),\n }),\n contentType: 'application/json',\n },\n )\n ).results,\n );\n }\n\n // ─── Folders ─────────────────────────────────────────────────────\n\n /**\n * Lists all folders accessible by the current token.\n * @param params - Optional filters for parent folder and archive status.\n * @returns Array of folder items.\n */\n async listFolders(params?: {\n parentFolderId?: string;\n archived?: boolean;\n /**\n * Scope the listing to a project. Requires the token owner to have\n * `STORAGE:READ` in that project; returns 403 otherwise.\n */\n projectId?: string;\n }) {\n const { archived, parentFolderId, projectId } = params || {};\n return await this.#requestApi<ItemFolder[]>('GET', FOLDER_PATH, {\n query: {\n parentFolderId,\n archived,\n ...(projectId && { projectId }),\n },\n });\n }\n\n /**\n * Gets a single folder by ID.\n * @param folderId - The folder's unique identifier.\n */\n async getFolder(folderId: string) {\n return await this.#requestApi<ItemFolder>(\n 'GET',\n `${FOLDER_PATH}/${folderId}`,\n );\n }\n\n /**\n * Batch variant of {@link getFolder}. Resolves a known set of folder ids in\n * one request — for example the parents behind a file list's breadcrumbs.\n *\n * Reach for {@link listFolders} instead when the whole (project) tree is\n * wanted; this is for the case where the ids are already known.\n *\n * Inputs longer than {@link STORAGE_BATCH_MAX} are split into several\n * requests automatically. A folder the caller cannot read carries an\n * `error` instead of `folder`.\n *\n * @param folderIds - The folder ids to resolve.\n */\n async getFoldersBatch(folderIds: string[]): Promise<ItemFoldersBatchEntry[]> {\n return await this.#requestBatches(\n folderIds,\n async (chunk) =>\n (\n await this.#requestApi<{ results: ItemFoldersBatchEntry[] }>(\n 'POST',\n `${ITEM_PATH}/batch/folders`,\n {\n body: JSON.stringify({ folderIds: chunk }),\n contentType: 'application/json',\n },\n )\n ).results,\n );\n }\n\n /**\n * Creates a new folder.\n * @param name - Display name for the folder.\n * @param parentId - Optional parent folder ID for nesting.\n * @returns The created folder.\n */\n async createFolder(name: string, parentId?: string, projectId?: string) {\n return await this.#requestApi<ItemFolder>('POST', FOLDER_PATH, {\n body: JSON.stringify({\n name,\n ...(parentId && { parentId }),\n ...(projectId && { projectId }),\n }),\n contentType: 'application/json',\n });\n }\n\n /**\n * Renames a folder.\n * @param folderId - The folder's unique identifier.\n * @param updateFolderParams - New name for the folder.\n * @returns The updated folder.\n */\n async updateFolder(folderId: string, updateFolderParams: { name?: string }) {\n const { name } = updateFolderParams;\n return await this.#requestApi<ItemFolder>(\n 'PUT',\n `${FOLDER_PATH}/${folderId}`,\n {\n body: JSON.stringify({ name } as UpdateItemFolderDto),\n contentType: 'application/json',\n },\n );\n }\n\n /**\n * Archives (soft-deletes) a folder. Can be recovered with {@link recoverFolder}.\n * @param folderId - The folder's unique identifier.\n */\n async archiveFolder(folderId: string) {\n return await this.#requestApi<ItemFolder>(\n 'DELETE',\n `${FOLDER_PATH}/${folderId}`,\n );\n }\n\n /**\n * Recovers a previously archived folder.\n * @param folderId - The folder's unique identifier.\n */\n async recoverFolder(folderId: string) {\n return await this.#requestApi<ItemFolder>(\n 'PUT',\n `${FOLDER_PATH}/${folderId}/recover`,\n );\n }\n\n /**\n * Downloads an entire folder as a ZIP archive.\n * @param folderId - The folder's unique identifier.\n * @returns A fetch Response containing the ZIP data.\n */\n async downloadFolder(folderId: string) {\n return await this.#requestFile(`${FOLDER_PATH}/${folderId}/download`);\n }\n\n // ─── Components ──────────────────────────────────────────────────\n\n /**\n * Lists all components (tools) accessible by the current token.\n * @param params - Optional filters for folder and version inclusion.\n * @returns Array of component items.\n */\n async listComponents(params?: GetItemsParams & { projectId?: string }) {\n const { folderId, ShowVersions, projectId } = params || {};\n if (folderId) {\n return await this.#requestApi<ComponentItem[]>(\n 'GET',\n `${FOLDER_PATH}/${folderId}/items`,\n {\n query: {\n itemType: ITEM_TYPE_COMPONENT,\n ...(ShowVersions && { ShowVersions }),\n },\n },\n );\n }\n return await this.#requestApi<ComponentItem[]>('GET', `${ITEM_PATH}`, {\n query: {\n itemType: ITEM_TYPE_COMPONENT,\n ...(ShowVersions && { ShowVersions }),\n ...(projectId && { projectId }),\n },\n });\n }\n\n /**\n * Gets a single component by ID, optionally including version history.\n * @param componentId - The component's unique identifier.\n * @param props - Options such as whether to include versions.\n */\n async getComponent(componentId: string, props?: GetItemProps) {\n return await this.#getItem<ItemWithVersions<ComponentItem>>(\n componentId,\n props,\n );\n }\n\n /**\n * Creates a new component with the given file and version properties.\n * @param componentData - File content, name, version tag, and component-specific props.\n * @returns The created component item and its first version.\n */\n async createComponent(componentData: CreateComponentProps) {\n const { componentProps } = componentData;\n return await this.#createItem<ComponentItem, ComponentVersionProps>(\n componentData,\n ITEM_TYPE_COMPONENT,\n componentProps,\n );\n }\n\n /**\n * Updates an existing component. Can rename, move, and/or upload a new version.\n * @param componentId - The component's unique identifier.\n * @param componentData - Properties to update, including optional new componentProps.\n * @returns The updated item and/or new version.\n */\n async updateComponent(\n componentId: string,\n componentData: UpdateComponentProps,\n ): Promise<UpdateItemResponse<ComponentItem>> {\n const { componentProps } = componentData;\n return await this.#updateItem<ComponentItem, ComponentVersionProps>(\n componentId,\n componentData,\n componentProps,\n );\n }\n\n /**\n * Downloads a component's full ZIP file. Returns the raw fetch Response.\n * @param componentId - The component's unique identifier.\n * @param params - Optional version selection parameters.\n * @returns A fetch Response containing the ZIP data.\n */\n async downloadComponent(\n componentId: string,\n params?: DownloadItemFileParams,\n ) {\n return await this.#downloadItem(componentId, params);\n }\n\n /**\n * Downloads only the JavaScript bundle from a component's ZIP.\n * This is the extracted `bundle` entry, returned as text.\n * @param componentId - The component's unique identifier.\n * @param params - Optional version selection parameters.\n * @returns A fetch Response containing the bundle JavaScript text.\n */\n async downloadComponentBundle(\n componentId: string,\n params?: DownloadItemFileParams,\n ) {\n const { versionTag, withDraft } = params || {};\n return await this.#requestFile(\n `${ITEM_PATH}/${componentId}/download/bundle`,\n {\n query: {\n ...(versionTag && { versionTag }),\n ...(withDraft && { withDraft }),\n },\n },\n );\n }\n\n /**\n * Archives (soft-deletes) a component. Can be recovered with {@link recoverComponent}.\n * @param componentId - The component's unique identifier.\n */\n async archiveComponent(componentId: string) {\n return await this.#requestApi<ComponentItem>(\n 'DELETE',\n `${ITEM_PATH}/${componentId}`,\n );\n }\n\n /**\n * Recovers a previously archived component.\n * @param componentId - The component's unique identifier.\n */\n async recoverComponent(componentId: string) {\n return await this.#requestApi<ComponentItem>(\n 'PUT',\n `${ITEM_PATH}/${componentId}/recover`,\n );\n }\n\n // ─── Built-in Components ─────────────────────────────────────────\n\n /**\n * Fetches a built-in component's JavaScript bundle by name.\n * @param name - The built-in component name (e.g. \"hello-world\").\n * @returns The component's JavaScript source code as a string.\n */\n async getBuiltInComponent(name: string): Promise<string> {\n const response = await this.#requestFile(`built-in/${name}/bundle`);\n return await response.text();\n }\n\n /**\n * Fetches a built-in component bundle, evaluates it, and registers it\n * with the given `components` instance via `components.get()`.\n *\n * After calling this, retrieve the singleton instance with\n * `components.get(ComponentClass)`.\n *\n * @param component - The component class stub (must have a static `uuid`).\n * @param components - The OBC `Components` instance used to register the\n * component (must expose a `.get()` method).\n * @param globals - Map of global names to values that the component source\n * expects in scope (e.g. `{ OBC, BUI }`). If omitted, falls back to\n * globals registered via {@link setBuiltInGlobals}, then to\n * `window.ThatOpenCompany`.\n *\n * @example\n * ```ts\n * // Option 1: register globals once, then init without passing them\n * client.setBuiltInGlobals({ OBC, OBF, BUI, CUI, THREE, FRAGS });\n * await client.initBuiltInComponent(AppManager, components);\n * await client.initBuiltInComponent(ViewerToolbar, components);\n *\n * // Option 2: pass globals per component (still works)\n * await client.initBuiltInComponent(HelloWorld, components, { OBC, BUI });\n * ```\n */\n async initBuiltInComponent(\n component: { uuid: string },\n components: ComponentsLike,\n globals?: Record<string, unknown>,\n ): Promise<void> {\n const source = await this.getBuiltInComponent(component.uuid);\n const resolvedGlobals =\n globals ??\n this.builtInGlobals ??\n (typeof window !== 'undefined' ? window.ThatOpenCompany : {}) ??\n {};\n\n const keys = Object.keys(resolvedGlobals);\n const values = keys.map((k) => resolvedGlobals[k]);\n\n const factory = new Function(...keys, `${source}\\nreturn main;`);\n const main = factory(...values);\n\n const componentDefinition = main?.componentDefinition ?? main;\n components.get(componentDefinition);\n }\n\n /**\n * Loads multiple built-in components in parallel.\n *\n * Convenience wrapper around {@link initBuiltInComponent} that fetches\n * and registers all given component stubs concurrently.\n *\n * @param components - The OBC `Components` instance.\n * @param stubs - One or more component stubs (e.g. `AppManager`, `ViewportManager`).\n *\n * @example\n * ```ts\n * await client.initBuiltInComponents(components, AppManager, ViewportManager);\n * ```\n */\n async initBuiltInComponents(\n components: ComponentsLike,\n ...stubs: { uuid: string }[]\n ): Promise<void> {\n await Promise.all(\n stubs.map((s) => this.initBuiltInComponent(s, components)),\n );\n }\n\n /**\n * High-level helper that creates an OBC component system, initialises BUI,\n * loads built-in components, and starts the engine — all in one call.\n *\n * @param globals - Map of global names to module namespaces\n * (must include at least `OBC` and `BUI`).\n * @param builtIns - Built-in component stubs to load (e.g. `AppManager`, `ViewportManager`).\n * @returns An object containing the initialised `components` instance.\n *\n * @example\n * ```ts\n * const { components } = await client.setup(\n * { OBC, OBF, BUI, CUI, THREE, FRAGS },\n * AppManager, ViewportManager,\n * );\n *\n * const viewports = components.get(ViewportManager);\n * const { element, world } = await viewports.create();\n * ```\n */\n async setup<TComponents extends ComponentsLike = ComponentsLike>(\n globals: Record<string, unknown>,\n ...builtIns: { uuid: string }[]\n ): Promise<{ components: TComponents }> {\n const OBC = globals.OBC as\n { Components?: new () => TComponents } | undefined;\n const BUI = globals.BUI as { Manager?: { init(): void } } | undefined;\n if (!OBC?.Components)\n throw new Error('globals.OBC must include Components');\n if (!BUI?.Manager) throw new Error('globals.BUI must include Manager');\n\n const components = new OBC.Components();\n BUI.Manager.init();\n this.setBuiltInGlobals(globals);\n await this.initBuiltInComponents(components, ...builtIns);\n components.init();\n this.context.appEventOrchestrator?.appLoaded?.();\n return { components };\n }\n\n /**\n * Reports an error to the platform via the {@link AppEventOrchestrator.appError} callback.\n * @param code - Numeric error code.\n * @param data - Arbitrary error data to send to the platform.\n */\n throwError(code: number, data: Record<string, string>): void {\n this.context.appEventOrchestrator?.appError?.(code, data);\n }\n\n // ─── Apps ────────────────────────────────────────────────────────\n\n /**\n * Lists all apps accessible by the current token.\n * @param params - Optional filters for folder and version inclusion.\n * @returns Array of app items.\n */\n async listApps(params?: GetItemsParams & { projectId?: string }) {\n const { folderId, ShowVersions, projectId } = params || {};\n if (folderId) {\n return await this.#requestApi<AppItem[]>(\n 'GET',\n `${FOLDER_PATH}/${folderId}/items`,\n {\n query: {\n itemType: ITEM_TYPE_APP,\n ...(ShowVersions && { ShowVersions }),\n },\n },\n );\n }\n return await this.#requestApi<AppItem[]>('GET', `${ITEM_PATH}`, {\n query: {\n itemType: ITEM_TYPE_APP,\n ...(ShowVersions && { ShowVersions }),\n ...(projectId && { projectId }),\n },\n });\n }\n\n /**\n * Creates a new app with the given file and optional version properties.\n * @param appData - File content, name, version tag, and optional app-specific props.\n * @returns The created app item and its first version.\n */\n async createApp(appData: CreateAppProps) {\n const { appProps } = appData;\n return await this.#createItem<AppItem, AppVersionProps>(\n appData,\n ITEM_TYPE_APP,\n appProps,\n );\n }\n\n /**\n * Downloads an app's full ZIP file. Returns the raw fetch Response.\n * @param appId - The app's unique identifier.\n * @param params - Optional version selection parameters.\n * @returns A fetch Response containing the ZIP data.\n */\n async downloadApp(appId: string, params?: DownloadItemFileParams) {\n return await this.#downloadItem(appId, params);\n }\n\n /**\n * Downloads only the JavaScript bundle from an app's ZIP.\n * This is the extracted `bundle` entry, returned as text.\n * @param appId - The app's unique identifier.\n * @param params - Optional version selection parameters.\n * @returns A fetch Response containing the bundle JavaScript text.\n */\n async downloadAppBundle(appId: string, params?: DownloadItemFileParams) {\n const { versionTag, withDraft } = params || {};\n return await this.#requestFile(`${ITEM_PATH}/${appId}/download/bundle`, {\n query: {\n ...(versionTag && { versionTag }),\n ...(withDraft && { withDraft }),\n },\n });\n }\n\n /**\n * Archives (soft-deletes) an app.\n * @param appId - The app's unique identifier.\n */\n async archiveApp(appId: string) {\n return await this.#requestApi<AppItem>('DELETE', `${ITEM_PATH}/${appId}`);\n }\n\n // ─── NPM Registry ────────────────────────────────────────────────\n\n /**\n * Fetches read-only npm credentials for the private `@thatopen` Founders\n * beta packages. Gated server-side on the token owner's membership tier:\n * FOUNDING members (and admins) get the token; everyone else gets a 403\n * (`RequestError` with `status === 403`). The returned `npmrc` is a\n * ready-to-write `.npmrc` body the CLI drops into a scaffolded project.\n * @returns The registry, scope, read-only token, and assembled `.npmrc`.\n */\n async getNpmCredentials() {\n return await this.#requestApi<NpmCredentials>(\n 'GET',\n `${NPM_REGISTRY_PATH}/credentials`,\n );\n }\n\n // ─── Execution ───────────────────────────────────────────────────\n\n /**\n * Triggers server-side execution of a cloud component.\n *\n * Pass `projectId` in `executionParams` when running the component in the\n * context of a specific project. The backend validates that the component\n * is linked to that project AND that the user has execute permission\n * there; a foreign `projectId` is rejected with 403. Omit `projectId` for\n * personal executions (ownership path).\n *\n * @param componentId - The component's unique identifier.\n * @param executionParams - Arbitrary parameters passed to the component's `main()` function. Include `projectId` to scope the execution.\n * @param versionTag - Optional version to execute (defaults to latest).\n * @returns An object containing the `executionId` to track progress.\n */\n async executeComponent(\n componentId: string,\n executionParams: { projectId?: string; [key: string]: unknown },\n versionTag?: string,\n ) {\n if (this.localServerUrl) {\n const url = `${this.localServerUrl}/api/${PROCESS_PATH}/${componentId}/execute`;\n const response = await fetch(url, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(executionParams),\n });\n if (!response.ok) {\n const text = await response.text().catch(() => '');\n throw new Error(\n `Local server request failed: ${response.status} - ${text}`,\n );\n }\n return (await response.json()) as { executionId: string };\n }\n return await this.#requestApi<{ executionId: string }>(\n 'POST',\n `${PROCESS_PATH}/${componentId}/execute`,\n {\n body: JSON.stringify(executionParams),\n query: { ...(versionTag && { versionTag }) },\n contentType: 'application/json',\n },\n );\n }\n\n /**\n * Aborts a running execution.\n * @param executionId - The execution's unique identifier.\n */\n async abortExecution(executionId: string) {\n if (this.localServerUrl) {\n const url = `${this.localServerUrl}/api/${PROCESS_PATH}/progress/${executionId}/abort`;\n const response = await fetch(url, { method: 'POST' });\n if (!response.ok) {\n const text = await response.text().catch(() => '');\n throw new Error(\n `Local server request failed: ${response.status} - ${text}`,\n );\n }\n return (await response.json()) as ExecutionEntity;\n }\n return await this.#requestApi<ExecutionEntity>(\n 'POST',\n `${PROCESS_PATH}/progress/${executionId}/abort`,\n );\n }\n\n /**\n * Lists all executions for a given component.\n *\n * When `projectId` is supplied, the backend scopes the query to that\n * project — returning only executions launched in that context AND\n * enforcing that the caller has access to the component there. Without\n * `projectId`, the caller's personal executions for the component are\n * returned.\n *\n * @param componentId - The component's unique identifier.\n * @param projectId - Optional project scope.\n * @returns Array of execution entities.\n */\n async listExecutions(componentId: string, projectId?: string) {\n if (this.localServerUrl) {\n const qs = projectId ? `?projectId=${encodeURIComponent(projectId)}` : '';\n const url = `${this.localServerUrl}/api/${PROCESS_PATH}/${componentId}/progress${qs}`;\n const response = await fetch(url);\n if (!response.ok) {\n const text = await response.text().catch(() => '');\n throw new Error(\n `Local server request failed: ${response.status} - ${text}`,\n );\n }\n return (await response.json()) as ExecutionEntity[];\n }\n return await this.#requestApi<ExecutionEntity[]>(\n 'GET',\n `${PROCESS_PATH}/${componentId}/progress`,\n { query: { ...(projectId && { projectId }) } },\n );\n }\n\n /**\n * Gets details of a specific execution, including its messages.\n * @param executionId - The execution's unique identifier.\n * @returns The execution entity with progress and result info.\n */\n async getExecution(executionId: string) {\n if (this.localServerUrl) {\n const url = `${this.localServerUrl}/api/${PROCESS_PATH}/progress/${executionId}`;\n const response = await fetch(url);\n if (!response.ok) {\n const text = await response.text().catch(() => '');\n throw new Error(\n `Local server request failed: ${response.status} - ${text}`,\n );\n }\n return (await response.json()) as ExecutionEntity;\n }\n return await this.#requestApi<ExecutionEntity>(\n 'GET',\n `${PROCESS_PATH}/progress/${executionId}`,\n );\n }\n\n /**\n * Subscribes to real-time execution progress via WebSocket.\n * The callback fires on each progress update until the execution completes.\n * @param executionId - The execution's unique identifier.\n * @param onUpdateCallback - Callback invoked on each progress/result event.\n */\n async onExecutionProgress(\n executionId: string,\n onUpdateCallback: (data: ExecutionSuscriptionReturnType) => void,\n ) {\n const wsUrl = this.localServerUrl ?? this.wsUrl;\n // The token rides the auth payload of the connect packet, not the URL.\n // WebSocket-only: the long-polling handshake makes several HTTP requests,\n // and behind the platform's load balancer (no session affinity) they can\n // land on different backend instances, which kills the session before it\n // upgrades. One WebSocket is one connection, so it cannot hop.\n const socket = await io(wsUrl, {\n auth: { accessToken: this.accessToken },\n transports: ['websocket'],\n });\n\n socket.on('connect', function () {\n socket.emit('executionSubscription', JSON.stringify({ executionId }));\n socket.on('execution', (data: ExecutionSuscriptionReturnType) => {\n onUpdateCallback(data);\n });\n });\n\n socket.on('connect_error', function (e: unknown) {\n console.log(e);\n });\n }\n\n // ─── Documents, History & Recipes ────────────────────────────────\n\n /**\n * A project's documents. Every document is a FOLDER holding its files plus\n * a `document.json` descriptor naming the document, its native form and its\n * renderable views. See `src/core/documents.ts` for the model and schema.\n */\n documents(projectId: string): ProjectDocuments {\n return new ProjectDocuments(this, projectId);\n }\n\n /**\n * A project's history of connected documents (Revit models, AutoCAD\n * drawings…): their version timelines and their change requests. See\n * `src/core/history.ts` — this surface is the only supported way to read\n * or write it; the storage underneath is private and will move.\n */\n history(projectId: string): ProjectHistory {\n return new ProjectHistory(this, projectId);\n }\n\n #recipes?: Recipes;\n\n /**\n * The recipe registry and runner: scripts that write change requests in a\n * native application's language. See `src/core/recipes.ts`.\n */\n get recipes(): Recipes {\n this.#recipes ??= new Recipes(this);\n return this.#recipes;\n }\n\n // ─── Hidden Files ────────────────────────────────────────────────\n\n /**\n * Creates a hidden file attached to a parent item (e.g., dependencies, assets).\n * @param file - The file to upload.\n * @param parentFileId - The parent item's unique identifier.\n * @param tag - Optional label to tell hidden files of the same parent apart;\n * filter on it with {@link getHiddenFilesByParent}. Up to 50 characters:\n * letters, digits and `:._-`, starting with a letter or digit.\n * @returns The hidden file ID.\n */\n async createHiddenFile(\n file: File | Blob,\n parentFileId: string,\n tag?: string,\n ) {\n const formData = new FormData();\n formData.append('file', file);\n formData.append('parentItemId', parentFileId);\n if (tag != null) formData.append('tag', tag);\n\n return await this.#requestApi<CreateHiddenItemResult>(\n 'POST',\n `${ITEM_PATH}/${HIDDEN_PATH}`,\n {\n body: formData,\n },\n );\n }\n\n /**\n * Creates many hidden files attached to a parent item in a single request.\n * Use this instead of many `createHiddenFile` calls when uploading large sets\n * (e.g. 3D Tiles); upload in chunks of up to 100 files per call.\n * @param files - The files to upload.\n * @param parentFileId - The parent item's unique identifier.\n * @param tag - Optional label, as in {@link createHiddenFile}. One tag\n * applies to every file in the batch.\n * @returns One result per uploaded file, in order, each with its hidden file ID.\n */\n async createHiddenFilesBatch(\n files: (File | Blob)[],\n parentFileId: string,\n tag?: string,\n ) {\n const formData = new FormData();\n for (const file of files) {\n formData.append('files', file);\n }\n formData.append('parentItemId', parentFileId);\n if (tag != null) formData.append('tag', tag);\n\n return await this.#requestApi<CreateHiddenItemsBatchResult>(\n 'POST',\n `${ITEM_PATH}/${HIDDEN_PATH}/batch`,\n {\n body: formData,\n },\n );\n }\n\n /**\n * Deletes a hidden file by its ID.\n * @param hiddenId - The hidden file's unique identifier.\n */\n async deleteHiddenFile(hiddenId: string) {\n return await this.#requestApi<Item>(\n 'DELETE',\n `${ITEM_PATH}/${HIDDEN_PATH}/${hiddenId}`,\n );\n }\n\n /**\n * Gets metadata for a hidden file.\n * @param hiddenId - The hidden file's unique identifier.\n */\n async getHiddenFile(hiddenId: string) {\n return await this.#requestApi<HiddenFileEntity>(\n 'GET',\n `${ITEM_PATH}/${HIDDEN_PATH}/${hiddenId}`,\n );\n }\n\n /**\n * Downloads a hidden file's content. Returns the raw fetch Response.\n * @param hiddenId - The hidden file's unique identifier.\n */\n async downloadHiddenFile(hiddenId: string) {\n return await this.#requestFile(\n `${ITEM_PATH}/${HIDDEN_PATH}/${hiddenId}/download`,\n );\n }\n\n /**\n * Mints a short-lived presigned URL for a hidden file so the browser can\n * stream it directly from storage with native HTTP `Range` requests (e.g. a\n * point-cloud `octree.bin`), instead of proxying the whole object through the\n * API. Re-call to re-mint when the URL nears/passes `expiresAt`; coalesce\n * concurrent re-mints into a single in-flight call.\n *\n * The storage bucket's CORS must allow the `Range` request header and expose\n * `Content-Range`, `Accept-Ranges` and `Content-Length` for the ranged fetch\n * to succeed cross-origin.\n *\n * @param hiddenId - The hidden file's unique identifier.\n * @param expiresIn - Desired URL lifetime in seconds (60–3600). Defaults to\n * 900 (15 min) server-side; values are clamped to that range.\n * @returns `{ url, expiresAt }` — `url` is the presigned GET URL, `expiresAt`\n * an ISO timestamp when it stops working.\n */\n async getHiddenFileSignedUrl(hiddenId: string, expiresIn?: number) {\n return await this.#requestApi<{ url: string; expiresAt: string }>(\n 'GET',\n `${ITEM_PATH}/${HIDDEN_PATH}/${hiddenId}/signed-url`,\n { ...(expiresIn != null && { query: { expiresIn } }) },\n );\n }\n\n /**\n * Batch variant of {@link getHiddenFileSignedUrl}. Mints presigned URLs for\n * many hidden files in one request.\n *\n * This is the right call for tile-based viewers (splats, point clouds),\n * which mint a URL per piece as the camera moves. One request here replaces\n * up to {@link STORAGE_BATCH_MAX} single calls, which keeps a busy session\n * well under the per-endpoint rate limit.\n *\n * Inputs longer than {@link STORAGE_BATCH_MAX} are split into several\n * requests automatically. Entries come back in request order; a file that\n * is gone or not accessible carries an `error` instead of a `url`, so the\n * remaining tiles still load. Re-call to re-mint as `expiresAt` approaches.\n *\n * @param hiddenIds - The hidden files to sign.\n * @param expiresIn - Desired URL lifetime in seconds (60–3600). Defaults to\n * 900 (15 min) server-side; values are clamped to that range.\n */\n async getHiddenFileSignedUrlsBatch(\n hiddenIds: string[],\n expiresIn?: number,\n ): Promise<HiddenFileSignedUrlBatchEntry[]> {\n return await this.#requestBatches(\n hiddenIds,\n async (chunk) =>\n (\n await this.#requestApi<{ results: HiddenFileSignedUrlBatchEntry[] }>(\n 'POST',\n `${ITEM_PATH}/${HIDDEN_PATH}/signed-url/batch`,\n {\n body: JSON.stringify({\n hiddenFileIds: chunk,\n ...(expiresIn != null && { expiresIn }),\n }),\n contentType: 'application/json',\n },\n )\n ).results,\n );\n }\n\n /**\n * Lists the hidden files attached to a parent item.\n * @param parentFileId - The parent item's unique identifier.\n * @param tag - Optional filter: only hidden files uploaded with this tag. A\n * tagged listing comes back in creation order.\n * @returns Array of hidden file entities.\n */\n async getHiddenFilesByParent(parentFileId: string, tag?: string) {\n return await this.#requestApi<HiddenFileEntity[]>(\n 'GET',\n `${ITEM_PATH}/${parentFileId}/${HIDDEN_PATH}`,\n { ...(tag != null && { query: { tag } }) },\n );\n }\n\n /**\n * Deletes all hidden files attached to a parent item.\n * @param parentFileId - The parent item's unique identifier.\n */\n async deleteHiddenFilesByParent(parentFileId: string) {\n return await this.#requestApi<Item[]>(\n 'DELETE',\n `${ITEM_PATH}/${parentFileId}/${HIDDEN_PATH}`,\n );\n }\n\n // ─── Icons ───────────────────────────────────────────────────────\n\n /**\n * Uploads or replaces the icon for an item (app, component, or file).\n * Accepts PNG, WebP, or ICO images up to 512 KB.\n * @param itemId - The item's unique identifier.\n * @param icon - The icon image file (File in browsers, Blob in Node.js).\n * @returns The updated item with `iconFileId` and `iconMimeType` set.\n */\n async uploadItemIcon(itemId: string, icon: File | Blob) {\n const formData = new FormData();\n formData.append('icon', icon);\n return await this.#requestApi<Item>('PUT', `${ITEM_PATH}/${itemId}/icon`, {\n body: formData,\n });\n }\n\n /**\n * Downloads the icon for an item as a binary stream.\n * @param itemId - The item's unique identifier.\n * @returns The raw Response (use `.blob()`, `.arrayBuffer()`, or pipe the body).\n */\n async getItemIcon(itemId: string) {\n return await this.#requestFile(`${ITEM_PATH}/${itemId}/icon`);\n }\n\n /**\n * Removes the icon from an item.\n * @param itemId - The item's unique identifier.\n * @returns The updated item with icon fields removed.\n */\n async removeItemIcon(itemId: string) {\n return await this.#requestApi<Item>(\n 'DELETE',\n `${ITEM_PATH}/${itemId}/icon`,\n );\n }\n\n // ─── General Item Operations ─────────────────────────────────────\n\n /**\n * Renames or moves an item (file, component, or app) without creating a new version.\n * @param itemId - The item's unique identifier.\n * @param params - New name and/or new folder ID.\n * @returns The updated item.\n */\n async updateItem(\n itemId: string,\n params: { name?: string; folderId?: string },\n ) {\n return await this.#requestApi<Item>('PUT', `${ITEM_PATH}/${itemId}`, {\n body: JSON.stringify(params),\n contentType: 'application/json',\n });\n }\n\n /**\n * Creates a new version of an item by uploading a new file.\n * For APP and TOOL types, `extraProps` is required by the backend.\n * @param itemId - The item's unique identifier.\n * @param file - The new file to upload.\n * @param versionTag - Version tag for the new version (e.g. \"v2\").\n * @param extraProps - Version-specific properties (required for APP/TOOL types).\n * @param metadata - Optional free-JSON metadata to store on the new version.\n * @returns The created version.\n */\n async createVersion(\n itemId: string,\n file: File | Blob,\n versionTag: string,\n extraProps?: object,\n metadata?: Metadata,\n ) {\n const formData = new FormData();\n formData.append('file', file);\n formData.append('versionTag', versionTag);\n extraProps && formData.append('extraProps', JSON.stringify(extraProps));\n metadata && formData.append('metadata', JSON.stringify(metadata));\n return await this.#requestApi<ItemVersion>(\n 'POST',\n `${ITEM_PATH}/${itemId}/version`,\n { body: formData },\n );\n }\n\n /**\n * Lists versions of an item. Pass `archived: true` to fetch only archived\n * versions, `false` to fetch only active ones, or omit to receive both.\n * @param itemId - The item's unique identifier.\n * @param params - Optional `{ archived }` filter.\n * @returns Array of versions, sorted by creation date descending.\n */\n async listVersions(\n itemId: string,\n params: { archived?: boolean } = {},\n ): Promise<ItemVersion[]> {\n return await this.#requestApi<ItemVersion[]>(\n 'GET',\n `${ITEM_PATH}/${encodeURIComponent(itemId)}/versions`,\n { query: params },\n );\n }\n\n /**\n * Batch variant of {@link listVersions}. Lists the versions of many items in\n * one request, which is what a file panel needs to render a whole page.\n *\n * The returned versions are the full records, metadata included, so a list\n * that only needs version metadata does not need\n * {@link getFileVersionMetadataBatch} on top.\n *\n * Inputs longer than {@link STORAGE_BATCH_MAX} are split into several\n * requests automatically. An item the caller cannot read carries an `error`\n * instead of `versions`.\n *\n * @param itemIds - The items whose versions to list.\n * @param params - Optional `{ archived }` filter, applied to every item.\n */\n async listVersionsBatch(\n itemIds: string[],\n params: { archived?: boolean } = {},\n ): Promise<ItemVersionsBatchEntry[]> {\n const { archived } = params;\n return await this.#requestBatches(\n itemIds,\n async (chunk) =>\n (\n await this.#requestApi<{ results: ItemVersionsBatchEntry[] }>(\n 'POST',\n `${ITEM_PATH}/batch/versions`,\n {\n body: JSON.stringify({\n itemIds: chunk,\n ...(archived !== undefined && { archived }),\n }),\n contentType: 'application/json',\n },\n )\n ).results,\n );\n }\n\n /**\n * Archives a version of an item. Archived versions remain available via\n * `listVersions({ archived: true })` and can be recovered or permanently\n * deleted. Cleanup runs daily and removes archived versions older than the\n * platform retention period.\n * @param itemId - The item's unique identifier.\n * @param versionTag - The version's tag (e.g. \"v2\").\n * @returns The archived version.\n */\n async archiveVersion(itemId: string, versionTag: string) {\n return await this.#requestApi<ItemVersion>(\n 'PUT',\n `${ITEM_PATH}/${encodeURIComponent(itemId)}/version/${encodeURIComponent(versionTag)}/archive`,\n );\n }\n\n /**\n * Recovers a previously archived version, restoring it to the active list.\n * @param itemId - The item's unique identifier.\n * @param versionTag - The version's tag (e.g. \"v2\").\n * @returns The recovered version.\n */\n async recoverVersion(itemId: string, versionTag: string) {\n return await this.#requestApi<ItemVersion>(\n 'PUT',\n `${ITEM_PATH}/${encodeURIComponent(itemId)}/version/${encodeURIComponent(versionTag)}/recover`,\n );\n }\n\n /**\n * Permanently deletes a version, including its file in object storage.\n * The version must be archived first; otherwise the call is rejected.\n * @param itemId - The item's unique identifier.\n * @param versionTag - The version's tag (e.g. \"v2\").\n */\n async deleteVersion(itemId: string, versionTag: string) {\n return await this.#requestApi<{ success: boolean }>(\n 'DELETE',\n `${ITEM_PATH}/${encodeURIComponent(itemId)}/version/${encodeURIComponent(versionTag)}`,\n );\n }\n\n // Project-scoped listings happen via the main list methods — e.g.\n // `listFiles({ projectId })`, `listFolders({ projectId })`,\n // `listApps({ projectId })`, `listComponents({ projectId })`. Those call\n // `GET /item?projectId=...` / `/item/folder?projectId=...`, which accept\n // both API tokens and JWT and apply per-entity permission filtering on\n // the server.\n //\n // Methods that hit the JWT-only `/project/:id/*` and\n // `/project/permissions/check*` routes (getProject, getProjectData,\n // checkPermission, checkPermissionBatch) live on `PlatformClient` — they\n // cannot be called with an access token.\n\n // ─── Private Helpers ─────────────────────────────────────────────\n\n /**\n * Splits `inputs` into chunks the API accepts and concatenates the results,\n * so callers never have to think about the batch ceiling. Chunks go out\n * together; an empty input skips the network entirely, since the API\n * rejects an empty batch.\n */\n async #requestBatches<TInput, TEntry>(\n inputs: TInput[],\n requestChunk: (chunk: TInput[]) => Promise<TEntry[]>,\n ): Promise<TEntry[]> {\n if (!inputs.length) return [];\n\n const chunks: TInput[][] = [];\n for (let start = 0; start < inputs.length; start += STORAGE_BATCH_MAX) {\n chunks.push(inputs.slice(start, start + STORAGE_BATCH_MAX));\n }\n\n const responses = await Promise.all(chunks.map(requestChunk));\n return responses.flat();\n }\n\n async #downloadItem(itemId: string, params?: DownloadItemFileParams) {\n const { versionTag, withDraft } = params || {};\n return await this.#requestFile(`${ITEM_PATH}/${itemId}/download`, {\n query: {\n ...(versionTag && { versionTag }),\n ...(withDraft && { withDraft }),\n },\n });\n }\n\n async #createItem<T = Item, P extends object = object>(\n fileData: CreateItemProps,\n itemType: ItemType,\n extraProps?: P,\n ) {\n const { name, versionTag, parentFolderId, projectId, file, metadata } =\n fileData;\n const formData = new FormData();\n formData.append('file', file);\n formData.append('name', name);\n formData.append('versionTag', versionTag);\n formData.append('itemType', itemType);\n parentFolderId && formData.append('folderId', parentFolderId);\n projectId && formData.append('projectId', projectId);\n\n extraProps && formData.append('extraProps', JSON.stringify(extraProps));\n metadata && formData.append('metadata', JSON.stringify(metadata));\n return await this.#requestApi<CreateItemResponse<T>>('POST', ITEM_PATH, {\n body: formData,\n });\n }\n\n async #updateItem<T = Item, P extends object = object>(\n itemId: string,\n fileData: UpdateItemProps,\n extraProps?: P,\n ): Promise<UpdateItemResponse<T>> {\n const { name, versionTag, parentFolderId, file, metadata } = fileData;\n\n let item: T | undefined;\n let version: ItemVersion | undefined;\n\n if (file) {\n const formData = new FormData();\n formData.append('file', file);\n versionTag && formData.append('versionTag', versionTag);\n extraProps && formData.append('extraProps', JSON.stringify(extraProps));\n metadata && formData.append('metadata', JSON.stringify(metadata));\n version = await this.#requestApi<ItemVersion>(\n 'POST',\n `${ITEM_PATH}/${itemId}/version`,\n {\n body: formData,\n },\n );\n }\n\n if (name || parentFolderId) {\n const body: UpdateItemDto = {\n ...(name && { name }),\n ...(parentFolderId && { folderId: parentFolderId }),\n };\n\n const parsedBody = JSON.stringify(body);\n\n item = await this.#requestApi<T>('PUT', `${ITEM_PATH}/${itemId}`, {\n body: parsedBody,\n contentType: 'application/json',\n });\n }\n\n return { item, version };\n }\n\n async #getItem<T = Item>(itemId: string, props?: GetItemProps) {\n const { showVersions = false } = props || {};\n return await this.#requestApi<ItemWithVersions<T>>(\n 'GET',\n `${ITEM_PATH}/${itemId}`,\n {\n query: { showVersions },\n },\n );\n }\n\n #cleanData(data?: object) {\n return (\n data &&\n Object.entries(data)\n .filter(([, value]) => value !== undefined)\n .reduce(\n (obj, [key, value]) => {\n obj[key as string] = value;\n return obj;\n },\n {} as { [key: string]: unknown },\n )\n );\n }\n}\n","/**\n * The app side of the platform channel: rooms an app can join, and the\n * messages it exchanges through them.\n *\n * The app never holds a socket. The platform shell, outside the iframe, owns\n * the connection and relays over `postMessage`; this module is the typed\n * layer on top of that contract, reached as {@link PlatformClient.channel}.\n */\n\n/** What a command looks like: the payload it carries and the reply it expects. */\nexport interface ChannelCommandShape {\n payload?: unknown;\n reply?: unknown;\n}\n\n/**\n * The default command map, when none is given: every command name is allowed\n * and nothing is typed. Give `external<Commands>()` your own map to get\n * payloads and replies checked at compile time.\n */\nexport type AnyChannelCommands = Record<string, ChannelCommandShape>;\n\n/** The default event map for {@link CollabRoom}: any name, any payload. */\nexport type AnyChannelEvents = Record<string, unknown>;\n\ntype PayloadOf<T> = 'payload' extends keyof T ? T['payload'] : undefined;\n// A command that declares no `reply` is a notification: nothing to return.\ntype ReplyOf<T> = 'reply' extends keyof T ? T['reply'] : void;\n\n/** Someone else on the other end of a room. `kind` is set for external channels. */\nexport interface ChannelPeer {\n from: string;\n kind?: string;\n}\n\n/** Who sent a message, and when. */\nexport interface ChannelMessageMeta {\n /** The sender's connection id, stamped by the platform. */\n from: string;\n at: number;\n /** Present when the sender expects an answer. */\n requestId?: string;\n /** For an external sender that declared one: `'mcp'`, `'cli'`, `'revit'`… */\n kind?: string;\n}\n\n/** How the client talks to the shell. Replaceable, so it can be tested. */\nexport interface ChannelTransport {\n post(message: Record<string, unknown>): void;\n listen(handler: (data: unknown) => void): () => void;\n}\n\n/**\n * Talks to the platform shell through `window.parent`. Only messages whose\n * `source` is the parent window are accepted — the same check the shell makes\n * in the other direction — so another frame on the page cannot inject messages\n * into the app.\n */\nexport function windowTransport(): ChannelTransport {\n if (typeof window === 'undefined' || window.parent === window) {\n throw new Error(\n 'client.channel only works inside a That Open app, which runs in an iframe of the platform.',\n );\n }\n return {\n post: (message) => window.parent.postMessage(message, '*'),\n listen: (handler) => {\n const listener = (event: MessageEvent) => {\n if (event.source === window.parent) handler(event.data);\n };\n window.addEventListener('message', listener);\n return () => window.removeEventListener('message', listener);\n },\n };\n}\n\n/** Reserved for messages the platform itself sends. */\nconst SYSTEM_PREFIX = 'channel:';\nconst JOIN_TIMEOUT_MS = 10_000;\n\n/** A message as the platform delivers it to the app. */\nexport interface ChannelIncomingMessage {\n type: string;\n requestId?: string;\n payload?: unknown;\n at: number;\n from: string;\n scope?: 'collab' | 'external';\n kind?: string;\n}\n\n/** What a room did with a message. */\nexport type ChannelOutcome =\n | { handled: false }\n | { handled: true; value?: unknown; error?: string };\n\nfunction guard(fn: () => void) {\n try {\n fn();\n } catch (error) {\n console.error('[channel] a listener threw:', error);\n }\n}\n\ninterface Pending {\n want: 'joined' | 'left';\n resolve: () => void;\n reject: (error: Error) => void;\n timer: ReturnType<typeof setTimeout>;\n}\n\n/** What every room shares: membership, peers and presence. */\nexport abstract class ChannelRoom {\n #joined = false;\n #peers: ChannelPeer[] = [];\n #pending: Pending[] = [];\n readonly #onChange = new Set<() => void>();\n readonly #onPeerJoined = new Set<(peer: ChannelPeer) => void>();\n readonly #onPeerLeft = new Set<(peer: ChannelPeer) => void>();\n\n constructor(\n private readonly transport: ChannelTransport,\n private readonly controls: {\n join: Record<string, unknown>;\n leave: Record<string, unknown>;\n },\n ) {}\n\n /** Whether the platform has confirmed this tab is in the room. */\n get joined(): boolean {\n return this.#joined;\n }\n\n /** Who else is in the room right now, as the platform last reported. */\n get peers(): readonly ChannelPeer[] {\n return this.#peers;\n }\n\n /**\n * Enters the room. Resolves when the platform confirms; rejects if it\n * refuses or does not answer in time. Joining twice is harmless.\n */\n join(): Promise<void> {\n if (this.#joined) return Promise.resolve();\n return this.#request('joined', this.controls.join);\n }\n\n /** Leaves the room. Handlers stay registered, so `join()` resumes them. */\n leave(): Promise<void> {\n if (!this.#joined && !this.#pending.some((p) => p.want === 'joined')) {\n return Promise.resolve();\n }\n return this.#request('left', this.controls.leave);\n }\n\n /** Fires when `joined` or `peers` changes. Returns a function that stops it. */\n onChange(listener: () => void): () => void {\n this.#onChange.add(listener);\n return () => void this.#onChange.delete(listener);\n }\n\n onPeerJoined(listener: (peer: ChannelPeer) => void): () => void {\n this.#onPeerJoined.add(listener);\n return () => void this.#onPeerJoined.delete(listener);\n }\n\n onPeerLeft(listener: (peer: ChannelPeer) => void): () => void {\n this.#onPeerLeft.add(listener);\n return () => void this.#onPeerLeft.delete(listener);\n }\n\n /** @internal Does a message arriving with this scope/kind belong to this room? */\n abstract accepts(scope: string | undefined, kind: string | undefined): boolean;\n\n /** @internal */\n abstract handle(message: ChannelIncomingMessage): Promise<ChannelOutcome>;\n\n /** @internal */\n applyJoined() {\n this.#joined = true;\n this.#settle('joined');\n this.#changed();\n }\n\n /** @internal */\n applyLeft() {\n this.#joined = false;\n this.#peers = [];\n this.#settle('left');\n this.#changed();\n }\n\n /** @internal */\n applyPeers(peers: ChannelPeer[]) {\n this.#peers = peers;\n this.#changed();\n }\n\n /** @internal */\n applyPeerJoined(peer: ChannelPeer) {\n if (!this.#joined || this.#peers.some((p) => p.from === peer.from)) return;\n this.#peers = [...this.#peers, peer];\n this.#onPeerJoined.forEach((l) => guard(() => l(peer)));\n this.#changed();\n }\n\n /** @internal */\n applyPeerLeft(from: string) {\n const peer = this.#peers.find((p) => p.from === from);\n if (!peer) return;\n this.#peers = this.#peers.filter((p) => p.from !== from);\n this.#onPeerLeft.forEach((l) => guard(() => l(peer)));\n this.#changed();\n }\n\n /** @internal */\n failPending(error: Error): boolean {\n const pending = this.#pending;\n this.#pending = [];\n pending.forEach((p) => {\n clearTimeout(p.timer);\n p.reject(error);\n });\n return pending.length > 0;\n }\n\n protected post(message: Record<string, unknown>) {\n this.transport.post(message);\n }\n\n #request(want: 'joined' | 'left', control: Record<string, unknown>) {\n return new Promise<void>((resolve, reject) => {\n const entry: Pending = {\n want,\n resolve,\n reject,\n timer: setTimeout(() => {\n this.#pending = this.#pending.filter((p) => p !== entry);\n reject(\n new Error(\n `The platform did not confirm ${want === 'joined' ? 'joining' : 'leaving'} in time.`,\n ),\n );\n }, JOIN_TIMEOUT_MS),\n };\n this.#pending.push(entry);\n this.transport.post({ type: 'APP_CHANNEL_CONTROL', ...control });\n });\n }\n\n #settle(want: 'joined' | 'left') {\n const done = this.#pending.filter((p) => p.want === want);\n this.#pending = this.#pending.filter((p) => p.want !== want);\n done.forEach((p) => {\n clearTimeout(p.timer);\n p.resolve();\n });\n }\n\n #changed() {\n this.#onChange.forEach((l) => guard(l));\n }\n}\n\n/**\n * The collaboration room: every user's tab of this app that joined it, across\n * accounts. Messages here are events — nobody replies.\n *\n * `E` maps each event name to its payload, so `send` and `on` are checked.\n */\nexport class CollabRoom<E extends object = AnyChannelEvents> extends ChannelRoom {\n readonly #listeners = new Map<\n string,\n Set<(payload: never, meta: ChannelMessageMeta) => void>\n >();\n\n /** @internal Use `client.channel.collab()`. */\n constructor(transport: ChannelTransport) {\n super(transport, {\n join: { action: 'joinCollab' },\n leave: { action: 'leaveCollab' },\n });\n }\n\n /**\n * Listens for an event other tabs send. Any number of listeners per event.\n * @returns a function that removes the listener.\n */\n on<K extends keyof E & string>(\n type: K,\n listener: (payload: E[K], meta: ChannelMessageMeta) => void,\n ): () => void {\n const set = this.#listeners.get(type) ?? new Set();\n set.add(listener as never);\n this.#listeners.set(type, set);\n return () => void set.delete(listener as never);\n }\n\n /**\n * Sends an event to the other tabs in the room. Does nothing while this tab\n * is not in it, matching what the platform does with a message from outside.\n */\n send<K extends keyof E & string>(type: K, payload: E[K]): void {\n if (type.startsWith(SYSTEM_PREFIX)) {\n throw new Error(`Message types starting with '${SYSTEM_PREFIX}' are reserved.`);\n }\n if (!this.joined) return;\n this.post({ type: 'APP_CHANNEL_PUBLISH', message: { type, payload } });\n }\n\n accepts(scope: string | undefined): boolean {\n return scope === undefined || scope === 'collab';\n }\n\n async handle(message: ChannelIncomingMessage): Promise<ChannelOutcome> {\n const listeners = this.#listeners.get(message.type);\n if (!listeners?.size) return { handled: false };\n const meta = metaOf(message);\n listeners.forEach((l) => guard(() => l(message.payload as never, meta)));\n return { handled: true };\n }\n}\n\n/**\n * Commands from this account's external tools — a CLI, an MCP server, a Revit\n * plugin — of one `kind`, or of every kind when none is given.\n *\n * `C` maps each command name to `{ payload, reply }`, so a handler's argument\n * and return value are checked. A command without `reply` is a notification.\n */\nexport class ExternalRoom<\n C extends { [K in keyof C]: ChannelCommandShape } = AnyChannelCommands,\n> extends ChannelRoom {\n readonly #handlers = new Map<\n string,\n (payload: never, meta: ChannelMessageMeta) => unknown\n >();\n\n /** @internal Use `client.channel.external(kind)`. */\n constructor(\n transport: ChannelTransport,\n readonly kind?: string,\n ) {\n super(transport, {\n join: { action: 'joinExternal', kind },\n leave: { action: 'leaveExternal', kind },\n });\n }\n\n /**\n * Handles a command. When the sender asked for an answer, what you return\n * is sent back to it; if you throw, it gets an error instead of waiting for\n * a timeout. When it did not ask (a notification), the return value is\n * ignored.\n *\n * One handler per command: a second one for the same name throws, since two\n * would both try to answer.\n * @returns a function that removes the handler.\n */\n on<K extends keyof C & string>(\n type: K,\n handler: (\n payload: PayloadOf<C[K]>,\n meta: ChannelMessageMeta,\n ) => ReplyOf<C[K]> | Promise<ReplyOf<C[K]>>,\n ): () => void {\n if (this.#handlers.has(type)) {\n throw new Error(\n `\"${type}\" already has a handler in this room. Remove it first.`,\n );\n }\n this.#handlers.set(type, handler as never);\n return () => void this.#handlers.delete(type);\n }\n\n accepts(scope: string | undefined, kind: string | undefined): boolean {\n if (scope !== undefined && scope !== 'external') return false;\n return this.kind === undefined || scope === undefined || this.kind === kind;\n }\n\n /** @internal Whether this room has any handler at all. */\n get hasHandlers(): boolean {\n return this.#handlers.size > 0;\n }\n\n async handle(message: ChannelIncomingMessage): Promise<ChannelOutcome> {\n const handler = this.#handlers.get(message.type);\n if (!handler) return { handled: false };\n try {\n const value = await handler(message.payload as never, metaOf(message));\n return { handled: true, value };\n } catch (error) {\n return {\n handled: true,\n error: error instanceof Error ? error.message : String(error),\n };\n }\n }\n}\n\nfunction metaOf(message: ChannelIncomingMessage): ChannelMessageMeta {\n return {\n from: message.from,\n at: message.at,\n requestId: message.requestId,\n kind: message.kind,\n };\n}\n\nfunction readMessage(data: unknown): ChannelIncomingMessage | null {\n const envelope = data as { type?: unknown; message?: unknown } | null;\n if (envelope?.type !== 'THATOPEN_CHANNEL_MESSAGE') return null;\n const message = envelope.message as Partial<ChannelIncomingMessage> | undefined;\n if (!message || typeof message.type !== 'string') return null;\n return {\n type: message.type,\n requestId:\n typeof message.requestId === 'string' ? message.requestId : undefined,\n payload: message.payload,\n at: typeof message.at === 'number' ? message.at : Date.now(),\n from: typeof message.from === 'string' ? message.from : '',\n scope:\n message.scope === 'collab' || message.scope === 'external'\n ? message.scope\n : undefined,\n kind: typeof message.kind === 'string' ? message.kind : undefined,\n };\n}\n\n/**\n * Typed access to the platform channel from inside an app: a collaboration\n * room shared with other users, and rooms for commands from external tools.\n * Reach it as `client.channel`.\n *\n * @example\n * ```ts\n * type McpCommands = {\n * 'select-by-category': { payload: { category: string }; reply: { count: number } };\n * };\n *\n * const mcp = client.channel.external<McpCommands>('mcp');\n * mcp.on('select-by-category', async ({ category }) => ({\n * count: await selectByCategory(category),\n * }));\n * await mcp.join();\n * ```\n */\nexport class ChannelClient {\n readonly #transport: ChannelTransport;\n readonly #stop: () => void;\n #collab?: CollabRoom<never>;\n readonly #externals = new Map<string, ExternalRoom<never>>();\n readonly #answered = new Set<string>();\n\n constructor(transport: ChannelTransport) {\n this.#transport = transport;\n this.#stop = transport.listen((data) => void this.#receive(data));\n }\n\n /** The collaboration room for this app. Always the same instance. */\n collab<E extends object = AnyChannelEvents>(): CollabRoom<E> {\n this.#collab ??= new CollabRoom<never>(this.#transport);\n return this.#collab as unknown as CollabRoom<E>;\n }\n\n /**\n * The room for commands from this account's external tools of one `kind`\n * (`'mcp'`, `'cli'`, `'revit'`…), or from any of them when `kind` is omitted.\n * Always the same instance for the same kind.\n */\n external<C extends { [K in keyof C]: ChannelCommandShape } = AnyChannelCommands>(\n kind?: string,\n ): ExternalRoom<C> {\n const key = kind ?? '';\n let room = this.#externals.get(key);\n if (!room) {\n room = new ExternalRoom<never>(this.#transport, kind);\n this.#externals.set(key, room);\n }\n return room as unknown as ExternalRoom<C>;\n }\n\n /** Stops listening. For tests and teardown; an app normally never calls it. */\n dispose() {\n this.#stop();\n }\n\n #rooms(): ChannelRoom[] {\n return [...(this.#collab ? [this.#collab] : []), ...this.#externals.values()];\n }\n\n #exact(scope: unknown, kind: unknown): ChannelRoom | undefined {\n if (scope === 'collab') return this.#collab;\n if (scope === 'external') {\n return this.#externals.get(typeof kind === 'string' ? kind : '');\n }\n return undefined;\n }\n\n async #receive(data: unknown) {\n const message = readMessage(data);\n if (!message) return;\n if (message.type.startsWith(SYSTEM_PREFIX)) {\n this.#system(message);\n return;\n }\n await this.#deliver(message);\n }\n\n #system(message: ChannelIncomingMessage) {\n const info = (message.payload ?? {}) as {\n scope?: string;\n kind?: string;\n from?: string;\n peers?: ChannelPeer[];\n };\n\n switch (message.type) {\n case 'channel:joined':\n this.#exact(info.scope, info.kind)?.applyJoined();\n break;\n case 'channel:left':\n this.#exact(info.scope, info.kind)?.applyLeft();\n break;\n case 'channel:peers':\n this.#exact(info.scope, info.kind)?.applyPeers(info.peers ?? []);\n break;\n case 'channel:peer-joined':\n case 'channel:peer-left': {\n if (!info.from) break;\n // An external peer of one kind is seen by the catch-all room and by\n // the room for that kind alike.\n const rooms: (ChannelRoom | undefined)[] =\n info.scope === 'collab'\n ? [this.#collab]\n : [...this.#externals.values()].filter((r) =>\n r.accepts('external', info.kind),\n );\n for (const room of rooms) {\n if (message.type === 'channel:peer-joined') {\n room?.applyPeerJoined({ from: info.from, kind: info.kind });\n } else {\n room?.applyPeerLeft(info.from);\n }\n }\n break;\n }\n case 'channel:error': {\n const error = new Error(String(message.payload));\n // Errors are not tied to a request, so anything waiting to join or\n // leave is told; with nothing waiting, the error would vanish.\n const told = this.#rooms().map((r) => r.failPending(error));\n if (!told.some(Boolean)) console.error('[channel] error:', message.payload);\n break;\n }\n }\n }\n\n async #deliver(message: ChannelIncomingMessage) {\n // Without `scope` (a gateway that predates it) there is no telling which\n // room a message came through, so it goes to every room that can take it.\n const rooms = this.#rooms().filter((r) => r.accepts(message.scope, message.kind));\n let answered = false;\n\n for (const room of rooms) {\n const outcome = await room.handle(message);\n if (!outcome.handled) continue;\n answered = true;\n if (message.requestId) this.#reply(message.requestId, outcome);\n }\n\n // Someone asked, this app listens for that kind of sender, and nothing\n // handles the command: say so, rather than let the asker time out.\n const asked =\n message.requestId && message.scope === 'external' && rooms.length > 0;\n if (asked && !answered) {\n this.#reply(message.requestId!, {\n handled: true,\n error: `No handler for \"${message.type}\".`,\n });\n }\n }\n\n #reply(requestId: string, outcome: Extract<ChannelOutcome, { handled: true }>) {\n // Two rooms can both handle one command (the catch-all and its kind).\n // Only the first answer counts: a second reply with the same id would no\n // longer match a pending request and would leak into the collab room.\n if (this.#answered.has(requestId)) return;\n this.#answered.add(requestId);\n if (this.#answered.size > 500) {\n this.#answered.delete(this.#answered.values().next().value as string);\n }\n this.#transport.post({\n type: 'APP_CHANNEL_PUBLISH',\n message: {\n type: outcome.error === undefined ? 'reply' : 'reply-error',\n requestId,\n payload:\n outcome.error === undefined ? outcome.value : { error: outcome.error },\n },\n });\n }\n}\n","import { io } from 'socket.io-client';\nimport {\n EngineServicesClient,\n EngineServicesClientProps,\n} from './client';\nimport { Project, ProjectData, ProjectWithRole } from '../types/projects';\nimport { ThatOpenContext } from '../types/context';\nimport { ChannelClient, windowTransport } from './channel';\nimport {\n MarkNotificationsReadResultDto,\n NotificationPageDto,\n NotificationSubscriptionView,\n UnreadCountDto,\n} from '../types/notifications';\n\nconst PROJECT_PATH = 'project';\nconst NOTIFICATION_PATH = 'notifications';\n\n/**\n * What arrived on the socket. One callback for all three because a bell\n * reacts the same way to each: refresh the badge, and the list if open.\n *\n * `allRead` is one event for the whole sweep rather than one per\n * notification, so do not expect an id on it.\n */\nexport type LiveNotificationEvent =\n | { type: 'created'; id: string }\n | { type: 'read'; id: string }\n | { type: 'allRead'; batch: number };\n\n/** Per-automation opt-in. `failures` skips started events entirely. */\nexport type NotificationSubscriptionFilterInput = 'all' | 'failures';\n\nexport interface NotificationSubscriptionInput {\n filter?: NotificationSubscriptionFilterInput;\n /** Overrides the account-level channel setting for this automation only. */\n channels?: { email?: boolean };\n}\n\n/** Scope by which a permission was granted (or `'none'` if denied). */\nexport type PermissionScope = 'global' | 'project' | 'entity' | 'none';\n\n/** Result of a single permission check. */\nexport interface PermissionCheckResult {\n hasPermission: boolean;\n scope: PermissionScope;\n}\n\n/** One entry in a batch permission check. */\nexport interface PermissionCheckEntry {\n resourceType: string;\n action: string;\n resourceId?: string;\n projectId?: string;\n}\n\n/**\n * Accepts either a static JWT string or a provider function that returns the\n * current JWT. Use a provider to keep refresh in the caller's hands — the\n * client calls it on every request so expired tokens never stick.\n *\n * @example Static token (simplest):\n * ```ts\n * new PlatformClient(jwt, apiUrl)\n * ```\n *\n * @example Auth0 React:\n * ```ts\n * const { getAccessTokenSilently } = useAuth0();\n * new PlatformClient(() => getAccessTokenSilently(), apiUrl)\n * ```\n */\nexport type BearerTokenSource =\n | string\n | (() => string | Promise<string>);\n\n/**\n * Client for apps, frontends, and any caller authenticating with a user JWT.\n * Extends `EngineServicesClient` — the full API-token-compatible surface is\n * inherited. On top, it exposes the JWT-only routes `getProject`,\n * `getProjectData`, `checkPermission`, and `checkPermissionBatch`. Those hit\n * `ProjectController` which is guarded by `AccountActiveGuard +\n * ProjectAccessGuard` and is not reachable via an access token.\n *\n * **Token refresh.** The constructor accepts a function that returns a JWT\n * (sync or async); the client calls it before every request, so an Auth0\n * SDK's `getAccessTokenSilently()` or similar refreshing source Just Works.\n *\n * Use `EngineServicesClient` for components (API-token auth, local server,\n * WebSocket progress). Use `PlatformClient` when you have a user JWT and\n * need project-level reads or permission introspection.\n *\n * @example\n * ```ts\n * const client = new PlatformClient(\n * () => auth0.getAccessTokenSilently(),\n * 'https://api.thatopen.com',\n * );\n * const project = await client.getProject(projectId);\n * ```\n */\nexport class PlatformClient extends EngineServicesClient {\n readonly #tokenProvider?: () => string | Promise<string>;\n #channel?: ChannelClient;\n\n /**\n * @param token - A bearer JWT, OR a function returning the current JWT\n * (sync or async). When a function is passed, it's invoked before every\n * request — ideal for token-refreshing sources like Auth0.\n * @param apiUrl - Base URL of the API (e.g. `https://api.thatopen.com`).\n * @param props - Optional client configuration. `useBearer` is forced to\n * `true` and cannot be overridden.\n */\n constructor(\n token: BearerTokenSource,\n apiUrl: string,\n props?: Omit<EngineServicesClientProps, 'useBearer'>,\n ) {\n // Seed the parent with a string (possibly empty when a provider is\n // supplied); the override below routes each request through the\n // provider when present.\n const initialToken = typeof token === 'string' ? token : '';\n super(initialToken, apiUrl, { ...props, useBearer: true });\n if (typeof token === 'function') {\n this.#tokenProvider = token;\n }\n }\n\n protected async resolveAccessToken(): Promise<string> {\n if (this.#tokenProvider) return await this.#tokenProvider();\n return super.resolveAccessToken();\n }\n\n /**\n * Creates a client from the platform context injected into\n * `window.__THATOPEN_CONTEXT__` by the That Open Platform. Recommended\n * entry point for apps running inside the platform's iframe — the context\n * carries a fresh JWT on every navigation.\n */\n static fromPlatformContext(\n props?: Omit<EngineServicesClientProps, 'useBearer'>,\n ): PlatformClient {\n const ctx: ThatOpenContext =\n (typeof window !== 'undefined'\n ? window.__THATOPEN_CONTEXT__\n : null) || { appId: '', projectId: '', accessToken: '', apiUrl: '' };\n const client = new PlatformClient(ctx.accessToken, ctx.apiUrl, props);\n (client as { context: ThatOpenContext }).context = ctx;\n return client;\n }\n\n /**\n * The platform channel, from inside an app: a collaboration room shared with\n * other users of the app, and rooms for commands from external tools (a CLI,\n * an MCP server, a Revit plugin). Typed, and built on the `postMessage`\n * contract with the platform shell — the app never opens a socket.\n *\n * Only available in an app running in the platform's iframe; reading it\n * anywhere else throws. Created on first use.\n *\n * @example\n * ```ts\n * type McpCommands = {\n * 'select-by-category': { payload: { category: string }; reply: { count: number } };\n * };\n *\n * const mcp = client.channel.external<McpCommands>('mcp');\n * mcp.on('select-by-category', async ({ category }) => ({ count: 3 }));\n * await mcp.join();\n *\n * const collab = client.channel.collab();\n * collab.onPeerLeft(({ from }) => removeAvatar(from));\n * await collab.join();\n * ```\n */\n get channel(): ChannelClient {\n this.#channel ??= new ChannelClient(windowTransport());\n return this.#channel;\n }\n\n // ─── Projects (JWT-only backend routes) ──────────────────────────\n\n /**\n * Lists the caller's projects, each with their role in it. The discovery\n * call: everything else on this surface takes a projectId, and until this\n * method there was no way to find out which ids exist — a portfolio\n * dashboard had to be configured by hand. `ProjectWithRole` existed as a\n * type with no producer; this is the producer.\n *\n * @example\n * ```ts\n * const projects = await client.listProjects();\n * for (const { project, role } of projects) {\n * console.log(project.title, role?.name ?? 'no role');\n * }\n * ```\n */\n async listProjects() {\n return await this.request<ProjectWithRole[]>('GET', PROJECT_PATH);\n }\n\n /**\n * Gets a project by ID. JWT-only — lives here because\n * `GET /project/:id` is guarded by `AccountActiveGuard + ProjectAccessGuard`.\n */\n async getProject(projectId: string) {\n return await this.request<Project>('GET', `${PROJECT_PATH}/${projectId}`);\n }\n\n /**\n * Gets the full project data (users, roles, files, folders) for a project.\n * User data is stripped of sensitive fields server-side.\n */\n async getProjectData(projectId: string) {\n return await this.request<ProjectData>(\n 'GET',\n `${PROJECT_PATH}/${projectId}/data`,\n );\n }\n\n // ─── Account ──────────────────────────────────────────────────────\n\n /**\n * Fetches a user's profile picture as raw image bytes, for showing member\n * avatars inside an app. The route is bearer-authed, so it can't be used as\n * an `<img src>` — turn the blob into an object URL with\n * `URL.createObjectURL(blob)`. Rejects when the account has no avatar.\n */\n async getAvatar(accountId: string): Promise<Blob> {\n return await this.request<Blob>('GET', `account/${accountId}/avatar`, {\n responseType: 'blob',\n });\n }\n\n // ─── Permissions (JWT-only backend routes) ───────────────────────\n\n /**\n * Checks whether the caller has a specific permission within a project.\n * Returns `{ hasPermission, scope }` where `scope` is `'global'` for\n * admin/owner, `'project'` for a role broad grant, `'entity'` for a\n * per-entity override, `'none'` for denied.\n */\n async checkPermission(params: {\n resourceId?: string;\n resourceType: string;\n action: string;\n projectId?: string;\n }) {\n return await this.request<PermissionCheckResult>(\n 'GET',\n `${PROJECT_PATH}/permissions/check`,\n { query: params as Record<string, string | undefined> },\n );\n }\n\n /**\n * Batch variant of {@link checkPermission}. Evaluates multiple checks in a\n * single round-trip; results come back in the same order as `checks`.\n */\n async checkPermissionBatch(checks: PermissionCheckEntry[]) {\n const response = await this.request<{\n results: PermissionCheckResult[];\n }>('POST', `${PROJECT_PATH}/permissions/check/batch`, {\n body: JSON.stringify({ checks }),\n contentType: 'application/json',\n });\n return response.results;\n }\n\n // ─── Notifications ────────────────────────────────────────────────\n\n /**\n * Lists the signed-in user's notifications, newest first.\n *\n * Scoped to whoever the bearer token belongs to — an app cannot read\n * anyone else's. Muted notifications are included: muting silences the\n * badge and the delivery channels, it does not hide the record.\n *\n * Paginate by passing the previous response's `nextCursor` back in; it is\n * opaque, so do not build one by hand. A null `nextCursor` means the last\n * page.\n *\n * @example Walk every page:\n * ```ts\n * let cursor: string | undefined;\n * do {\n * const page = await client.getNotifications({ cursor });\n * render(page.items);\n * cursor = page.nextCursor ?? undefined;\n * } while (cursor);\n * ```\n */\n async getNotifications(params?: { cursor?: string; limit?: number }) {\n return await this.request<NotificationPageDto>('GET', NOTIFICATION_PATH, {\n query: {\n ...(params?.cursor !== undefined && { cursor: params.cursor }),\n ...(params?.limit !== undefined && { limit: String(params.limit) }),\n },\n });\n }\n\n /**\n * Number of unread notifications, excluding muted ones. This is the bell\n * badge count, so it is cheap to poll.\n */\n async getUnreadNotificationCount() {\n const response = await this.request<UnreadCountDto>(\n 'GET',\n `${NOTIFICATION_PATH}/unread-count`,\n );\n return response.count;\n }\n\n /**\n * Marks specific notifications as read. Ids the caller does not own are\n * ignored rather than rejected, so `updated` can be lower than the number\n * passed in.\n */\n async markNotificationsRead(notificationIds: string[]) {\n return await this.request<MarkNotificationsReadResultDto>(\n 'POST',\n `${NOTIFICATION_PATH}/mark-read`,\n {\n body: JSON.stringify({ ids: notificationIds }),\n contentType: 'application/json',\n },\n );\n }\n\n /** Marks every unread notification as read in one call. */\n async markAllNotificationsRead() {\n return await this.request<MarkNotificationsReadResultDto>(\n 'POST',\n `${NOTIFICATION_PATH}/mark-all-read`,\n );\n }\n\n /**\n * The automations this user has subscribed to. Nobody is subscribed by\n * default, so an empty list is the normal state.\n */\n async getNotificationSubscriptions() {\n return await this.request<NotificationSubscriptionView[]>(\n 'GET',\n `${NOTIFICATION_PATH}/subscriptions`,\n );\n }\n\n /**\n * Removes this user's subscription to one automation.\n *\n * Unlike subscribing, which happens through the project routes, this works\n * for any automation the user is subscribed to and keeps working after the\n * automation itself is gone — opting out must never be the thing that\n * fails.\n */\n async unsubscribeFromAutomation(hookId: string) {\n return await this.request<{ unsubscribed: boolean }>(\n 'DELETE',\n `${NOTIFICATION_PATH}/subscriptions/${hookId}`,\n );\n }\n\n /**\n * Subscribes the signed-in user to one project automation's runs.\n *\n * Nobody is subscribed by default, so this is what makes an automation\n * produce notifications for this user at all. Subscribing again is\n * harmless: it updates the existing subscription rather than duplicating.\n *\n * Read-level access to the project is enough. Someone who can see an\n * automation can follow it without being able to change it.\n *\n * @example Follow only the failures, and email me about them:\n * ```ts\n * await client.subscribeToAutomation(projectId, hookId, {\n * filter: 'failures',\n * channels: { email: true },\n * });\n * ```\n */\n async subscribeToAutomation(\n projectId: string,\n hookId: string,\n input?: NotificationSubscriptionInput,\n ) {\n return await this.request<{ subscribed: true }>(\n 'POST',\n `${PROJECT_PATH}/${projectId}/events/hooks/${hookId}/subscription`,\n {\n body: JSON.stringify(input ?? {}),\n contentType: 'application/json',\n },\n );\n }\n\n /**\n * Changes an existing subscription. Only the fields passed are touched, so\n * sending `channels` alone leaves the filter as it was.\n *\n * Throws if the user is not subscribed; use {@link subscribeToAutomation}\n * to create one.\n */\n async updateAutomationSubscription(\n projectId: string,\n hookId: string,\n changes: NotificationSubscriptionInput,\n ) {\n return await this.request<{ updated: true }>(\n 'PATCH',\n `${PROJECT_PATH}/${projectId}/events/hooks/${hookId}/subscription`,\n {\n body: JSON.stringify(changes),\n contentType: 'application/json',\n },\n );\n }\n\n /**\n * Listens for this user's notifications in real time.\n *\n * Unlike {@link EngineServicesClient.onExecutionProgress}, which follows one\n * execution and closes when it ends, this stays connected for the session:\n * the server puts the socket in a room for the signed-in account and pushes\n * anything addressed to them.\n *\n * The events carry ids rather than the notifications themselves, so treat\n * them as a signal to refresh. That keeps a burst cheap and means the\n * server is never the source of a stale render.\n *\n * Requires a user JWT. An API access token is rejected by the gateway,\n * because it identifies a token rather than a person.\n *\n * @returns a function that disconnects. Call it on unmount.\n *\n * @example\n * ```ts\n * const stop = await client.onNotification((event) => {\n * if (event.type === 'created') refreshBell();\n * });\n * // later\n * stop();\n * ```\n */\n async onNotification(\n onEvent: (event: LiveNotificationEvent) => void,\n ): Promise<() => void> {\n // Resolved per connection rather than reused from construction, so a\n // provider-backed client opens the socket with a current token. It rides\n // the auth payload, never the URL: a failing handshake prints its URL in\n // the browser console, token included.\n const token = await this.resolveAccessToken();\n const socket = io(`${this.socketOrigin}/notifications`, {\n auth: { accessToken: token },\n transports: ['websocket'],\n });\n\n socket.on('notification.created', (data: { id: string }) =>\n onEvent({ type: 'created', id: data?.id }),\n );\n socket.on('notification.read', (data: { id: string }) =>\n onEvent({ type: 'read', id: data?.id }),\n );\n socket.on('notifications.allRead', (data: { batch: number }) =>\n onEvent({ type: 'allRead', batch: data?.batch }),\n );\n\n return () => socket.disconnect();\n }\n}\n","/**\n * Reads what a .frag SAYS — its metadata and its items' guids, categories and\n * attributes — without loading it as something to look at.\n *\n * The fragments model loader is for models somebody will render: it starts\n * workers, builds tiles and boxes, and streams geometry. A recipe wants none\n * of that. It wants the data, it wants it synchronously enough to loop over,\n * and it wants it for files that may have no geometry at all.\n *\n * So this walks the flatbuffer directly, using the same schema the writer\n * uses, which also keeps the two honest about each other. The schema comes\n * from the OPTIONAL PEER `@thatopen/fragments` (plus `flatbuffers`), loaded\n * when `readFrag` runs — same arrangement as {@link OperationBuilder}.\n */\n\ntype FlatbuffersModule = typeof import('flatbuffers');\ntype FragmentsSchema = typeof import('@thatopen/fragments');\n\nexport interface FragItem {\n localId: number;\n /** The publisher's own id for this thing — a Rhino object guid, a Revit UniqueId. */\n guid: string | null;\n category: string | null;\n attrs: Record<string, string>;\n}\n\nexport interface FragContents {\n /** Whatever the publisher declared: units, axes, application. Parsed, or `{}` if unreadable. */\n metadata: Record<string, unknown>;\n /** In file order, which for an operation payload is the order the ids come back in. */\n items: FragItem[];\n}\n\nexport async function readFrag(bytes: Uint8Array): Promise<FragContents> {\n const [flatbuffers, schema] = await loadFragDependencies();\n const model = schema.Model.getRootAsModel(\n new flatbuffers.ByteBuffer(await inflate(bytes)),\n );\n\n let metadata: Record<string, unknown> = {};\n try {\n metadata = JSON.parse(model.metadata() ?? '{}');\n } catch {\n // Unreadable metadata is worth carrying on past: the items are still the\n // point, and a caller that needs the units will say so itself when it\n // cannot find them.\n }\n\n // Sparse: guids_items[k] names the local_id that owns guids[k].\n const guidByLocalId = new Map<number, string>();\n for (let k = 0; k < model.guidsLength(); k++) {\n const owner = model.guidsItems(k);\n const guid = model.guids(k);\n if (owner !== null && guid) guidByLocalId.set(owner, guid);\n }\n\n const items: FragItem[] = [];\n for (let i = 0; i < model.attributesLength(); i++) {\n const localId = model.localIds(i);\n if (localId === null) continue;\n\n const attrs: Record<string, string> = {};\n const attribute = model.attributes(i);\n for (let d = 0; d < (attribute?.dataLength() ?? 0); d++) {\n const triple = attribute!.data(d);\n if (!triple) continue;\n try {\n // [name, value, type]. The type is the format's business.\n const [name, value] = JSON.parse(triple) as [string, string, string];\n attrs[name] = value;\n } catch {\n /* one unreadable attribute must not cost the item it belongs to */\n }\n }\n\n items.push({\n localId,\n guid: guidByLocalId.get(localId) ?? null,\n category: model.categories(i) ?? null,\n attrs,\n });\n }\n\n return { metadata, items };\n}\n\n/**\n * The optional peers, resolved on first read. In an app they are installed\n * (and often aliased); in plain Node the fragments root also pulls what IT\n * imports (web-ifc, three) — the error says so instead of hiding it.\n */\nasync function loadFragDependencies(): Promise<\n [FlatbuffersModule, FragmentsSchema]\n> {\n try {\n return await Promise.all([\n import('flatbuffers'),\n import('@thatopen/fragments') as Promise<FragmentsSchema>,\n ]);\n } catch (cause) {\n throw new Error(\n 'readFrag needs the optional peers `flatbuffers` and ' +\n '`@thatopen/fragments` resolvable (in Node, fragments also pulls its ' +\n `own imports, e.g. web-ifc). (${cause instanceof Error ? cause.message : String(cause)})`,\n );\n }\n}\n\n/** zlib, matching every writer of this format. `deflate-raw` fails on the first byte. */\nasync function inflate(bytes: Uint8Array): Promise<Uint8Array> {\n const stream = new Blob([bytes as BlobPart])\n .stream()\n .pipeThrough(new DecompressionStream('deflate'));\n return new Uint8Array(await new Response(stream).arrayBuffer());\n}\n","/**\n * Authors an interoperability OPERATION — a set of deferred edits for one\n * document — and hands back the bytes to upload as a suggestion's payload.\n *\n * WHY THIS EXISTS AND WHY IT LOOKS LIKE THIS. An operation is carried as a\n * .frag with no geometry at all: the envelope in `Model.metadata`, and one\n * geometry-less item per change whose attributes ARE the change. That was\n * cheap on the C# side, which already had a writer, and it is the reason a\n * converter had to be a console tool once: nothing in the browser could\n * produce one. So the format stayed, and this builds it here instead.\n *\n * Nothing above this class needs to know any of that. You say add / set /\n * remove and get bytes for {@link FlowDoc.suggest} or a recipe's result.\n *\n * WHAT IT DOES NOT DO. It does not translate. Attributes are written exactly\n * as given, in the TARGET application's own terms and units, because data\n * that gets translated on the way in has to be untranslated on the way out\n * and the day somebody forgets a field nothing complains. Deciding what a\n * Rhino layer means in Revit is the recipe's job; this only carries the\n * answer.\n *\n * DEPENDENCIES, loaded at build() time and declared as OPTIONAL PEERS:\n * `@thatopen/fragments` (the .frag schema) and `flatbuffers`. An app that\n * authors operations has both already; everything else in this package works\n * without them.\n */\n\ntype FlatbuffersModule = typeof import('flatbuffers');\ntype FragmentsSchema = typeof import('@thatopen/fragments');\n\n/**\n * The reserved namespace. Everything under it is addressed to the applier and\n * is never data, so an applier skips the whole prefix rather than the names\n * it happens to know — which is what lets an author record something for its\n * OWN later use without the other side being taught what it means.\n */\nconst RESERVED = 'flow:';\n\n/** The verb. An instruction sitting among data, which is why it is prefixed. */\nconst OP_KEY = 'flow:op';\n\n/**\n * Where a change came from, in the author's own terms.\n *\n * NOT a link between elements — nothing is written into either model. It\n * lives on the OPERATION, which is the record of what somebody asked for,\n * and it is what lets a recipe be self-contained: \"what did I already make\n * for this object\" is answered by reading the queue the platform already\n * keeps, instead of a private file that a second machine does not have and a\n * lost machine takes with it.\n */\nconst SOURCE_KEY = 'flow:source';\n\n/** The schema this writes. An applier that speaks a different one must refuse rather than guess. */\nexport const OP_SCHEMA = 'revitflow/op@2';\n\nconst CATEGORY_CHANGE = 'REVITFLOWCHANGE';\nconst CATEGORY_OPERATION = 'REVITFLOWOPERATION';\n\nexport interface OperationTarget {\n /** Platform project id. */\n project: string;\n /** Document name within the project — the model these edits are for. */\n document: string;\n /**\n * The commit this was authored against. The elements named here existed\n * then; by the time somebody applies it they may not, and the applier\n * reports what it could not resolve.\n */\n baseCommit: number;\n /** Who authored it, for the history. */\n author?: string;\n /** Platform user id, so the same person is not two names depending on which tool wrote it. */\n userId?: string;\n /** Groups the operations one authored action produced across several models. */\n batchId?: string;\n title?: string;\n}\n\n/** Where an added item goes, and how it is turned, in the target's own terms. */\nexport interface Placement {\n /** [x, y, z] in the TARGET model's own units and axes. Not converted here. */\n position?: [number, number, number];\n /** Degrees about Z, in the target's convention. */\n rotationDeg?: number;\n /**\n * The id of the object that caused this change, in the AUTHOR's own terms —\n * a Rhino guid, a row of a spreadsheet, whatever proposed it. Optional, and\n * only useful to whoever wrote it: pass it when you expect to come back and\n * find what you created.\n */\n source?: string;\n}\n\nexport class OperationBuilder {\n private readonly changes: {\n op: 'add' | 'set' | 'remove';\n item?: string;\n attrs: Record<string, string>;\n }[] = [];\n\n constructor(private readonly target: OperationTarget) {}\n\n /** How many changes are queued. An operation with none is refused by `build`. */\n get length(): number {\n return this.changes.length;\n }\n\n // The envelope, readable. Whoever writes the queue entry has to put the SAME\n // values in it as the payload carries — an entry that disagrees with its own\n // payload is a row describing a different operation — so they are exposed\n // here rather than passed twice by every caller.\n get batchId(): string | undefined {\n return this.target.batchId;\n }\n get title(): string {\n return this.target.title ?? `${this.changes.length} change(s)`;\n }\n get author(): string {\n return this.target.author ?? 'app';\n }\n get userId(): string | undefined {\n return this.target.userId;\n }\n get baseCommit(): number {\n return this.target.baseCommit;\n }\n\n /**\n * Create something. There is no id yet: the attributes describe what it is,\n * the placement says where it goes, and the operation answers with the id\n * it got.\n */\n add(attrs: Record<string, string>, placement: Placement = {}): this {\n this.changes.push({ op: 'add', attrs: this.pack(attrs, placement) });\n return this;\n }\n\n /** Write attributes onto an item that already exists, named by the id the target published. */\n set(\n item: string,\n attrs: Record<string, string>,\n placement: Placement = {},\n ): this {\n this.requireId(item, 'set');\n this.changes.push({ op: 'set', item, attrs: this.pack(attrs, placement) });\n return this;\n }\n\n /** Delete an item. Whatever the target cascades along with it is reported, not guessed at here. */\n remove(item: string): this {\n this.requireId(item, 'remove');\n this.changes.push({ op: 'remove', item, attrs: {} });\n return this;\n }\n\n /**\n * A label for what this operation mostly does. Derived, never read to\n * decide anything: one operation may add, set and remove at once and still\n * be atomic, so what each change does is written on the change.\n */\n get summary(): 'add' | 'set' | 'remove' | 'mixed' {\n const kinds = new Set(this.changes.map((c) => c.op));\n return kinds.size === 1 ? [...kinds][0] : 'mixed';\n }\n\n /**\n * The .frag bytes, zlib-deflated, ready to upload as the operation's\n * payload.\n *\n * `opId` is taken rather than generated so the caller can put the same id\n * in the queue entry it writes next ({@link Recipes} mints it before the\n * run); an id this class invented and did not return would have to be dug\n * back out of the bytes.\n */\n async build(opId: string): Promise<Uint8Array> {\n if (this.changes.length === 0) {\n throw new Error(\n 'An operation with no changes is not an operation. Add at least one.',\n );\n }\n\n const envelope = {\n schema: OP_SCHEMA,\n opId,\n // Through the getters, so the envelope and the queue entry cannot drift\n // into disagreeing about the same operation.\n batchId: this.batchId ?? opId,\n targetProject: this.target.project,\n targetDocument: this.target.document,\n baseCommit: this.baseCommit,\n author: this.author,\n ...(this.userId ? { userId: this.userId } : {}),\n title: this.title,\n summary: this.summary,\n };\n\n const [flatbuffers, schema] = await loadDependencies();\n return deflate(\n this.flatbuffer(flatbuffers, schema, opId, JSON.stringify(envelope)),\n );\n }\n\n // ---------------------------------------------------------------------------------------------\n\n /** Placement rides in the attributes, in the same string form the target published. */\n private pack(\n attrs: Record<string, string>,\n placement: Placement,\n ): Record<string, string> {\n const out: Record<string, string> = {};\n for (const [k, v] of Object.entries(attrs ?? {})) {\n // The protocol's namespace is ours, not the data's: nobody sets it through attributes.\n if (k.startsWith(RESERVED)) continue;\n out[k] = String(v);\n }\n if (placement.position) out.Position = placement.position.map(num).join(',');\n if (placement.rotationDeg !== undefined)\n out.Rotation = num(placement.rotationDeg);\n if (placement.source) out[SOURCE_KEY] = placement.source;\n return out;\n }\n\n private requireId(item: string, verb: string): void {\n if (!item || !item.trim()) {\n throw new Error(`A '${verb}' has to name the item it acts on.`);\n }\n }\n\n /**\n * The buffer itself.\n *\n * Laid out exactly as the C# writer lays it out, because the add-in's\n * reader is the one that has to accept both: items first and the container\n * after, ids handed out by one monotonic counter, attributes as\n * `[name, value, type]` JSON triples, and a Meshes table that exists but is\n * empty.\n *\n * Empty rather than absent: the reader asks for it unconditionally, and a\n * model that draws nothing is still a model. Nothing here gets a sample —\n * an item with no triangles must not have one, because a sample's bounding\n * box would then have no size and the reader turns a box into a \"dimension\"\n * and rejects a falsy one.\n */\n private flatbuffer(\n flatbuffers: FlatbuffersModule,\n schema: FragmentsSchema,\n opId: string,\n metadata: string,\n ): Uint8Array {\n const { Attribute, Meshes, Model, SpatialStructure, Transform } = schema;\n const b = new flatbuffers.Builder(1024);\n const n = this.changes.length;\n\n // ids: one counter across everything. Changes take 1..n, the container\n // that groups them takes n+1, and max_local_id is the next free one.\n const itemIds = new Uint32Array(n);\n let next = 1;\n for (let i = 0; i < n; i++) itemIds[i] = next++;\n const containerId = next++;\n\n // ---- Meshes: present, and entirely empty. ----\n const emptyOffsets = (start: (bb: typeof b, k: number) => void) => {\n start(b, 0);\n return b.endVector();\n };\n const shells = Meshes.createShellsVector(b, []);\n const circleExtrusions = Meshes.createCircleExtrusionsVector(b, []);\n const samples = emptyOffsets(Meshes.startSamplesVector);\n const representations = emptyOffsets(Meshes.startRepresentationsVector);\n const materials = emptyOffsets(Meshes.startMaterialsVector);\n const localTransforms = emptyOffsets(Meshes.startLocalTransformsVector);\n const globalTransforms = emptyOffsets(Meshes.startGlobalTransformsVector);\n const meshesItems = Meshes.createMeshesItemsVector(b, []);\n const materialIds = Meshes.createMaterialIdsVector(b, []);\n const representationIds = Meshes.createRepresentationIdsVector(b, []);\n const sampleIds = Meshes.createSampleIdsVector(b, []);\n const localTransformIds = Meshes.createLocalTransformIdsVector(b, []);\n const globalTransformIds = Meshes.createGlobalTransformIdsVector(b, []);\n\n Meshes.startMeshes(b);\n // Written INLINE, and it has to be: a flatbuffers struct is serialised\n // into its parent, not referenced, so building it before startMeshes\n // throws \"struct must be serialized inline\". The model's own coordinate\n // system, identity because an operation places nothing globally.\n Meshes.addCoordinates(b, Transform.createTransform(b, 0, 0, 0, 1, 0, 0, 0, 1, 0));\n Meshes.addGlobalTransforms(b, globalTransforms);\n Meshes.addShells(b, shells);\n Meshes.addRepresentations(b, representations);\n Meshes.addSamples(b, samples);\n Meshes.addLocalTransforms(b, localTransforms);\n Meshes.addMaterials(b, materials);\n Meshes.addCircleExtrusions(b, circleExtrusions);\n Meshes.addMeshesItems(b, meshesItems);\n Meshes.addRepresentationIds(b, representationIds);\n Meshes.addSampleIds(b, sampleIds);\n Meshes.addMaterialIds(b, materialIds);\n Meshes.addLocalTransformIds(b, localTransformIds);\n Meshes.addGlobalTransformIds(b, globalTransformIds);\n const meshes = Meshes.endMeshes(b);\n\n const metadataOffset = b.createString(metadata);\n\n // ---- Attributes: one entry per item, changes then container. ----\n const unique = new Set<string>();\n const attributeOffsets: number[] = [];\n for (const change of this.changes) {\n const triples: number[] = [];\n const props: Record<string, string> = {\n [OP_KEY]: change.op,\n ...change.attrs,\n };\n for (const [name, value] of Object.entries(props)) {\n const json = JSON.stringify([name, value, 'IFCTEXT']);\n unique.add(json);\n triples.push(b.createString(json));\n }\n attributeOffsets.push(\n Attribute.createAttribute(b, Attribute.createDataVector(b, triples)),\n );\n }\n {\n const json = JSON.stringify(['Name', opId, 'IFCLABEL']);\n unique.add(json);\n const data = Attribute.createDataVector(b, [b.createString(json)]);\n attributeOffsets.push(Attribute.createAttribute(b, data));\n }\n const attributes = Model.createAttributesVector(b, attributeOffsets);\n const uniqueAttributes = Model.createUniqueAttributesVector(\n b,\n [...unique].map((s) => b.createString(s)),\n );\n\n // ---- Categories, parallel to local_ids. ----\n const categoryOffsets = this.changes.map(() =>\n b.createString(CATEGORY_CHANGE),\n );\n categoryOffsets.push(b.createString(CATEGORY_OPERATION));\n const categories = Model.createCategoriesVector(b, categoryOffsets);\n\n // ---- Guids: only the changes that name something. An `add` names nothing yet. ----\n const guidOffsets: number[] = [];\n const guidItems: number[] = [];\n this.changes.forEach((change, i) => {\n if (!change.item) return;\n guidOffsets.push(b.createString(change.item));\n guidItems.push(itemIds[i]);\n });\n const guids = Model.createGuidsVector(b, guidOffsets);\n const guidsItems = Model.createGuidsItemsVector(b, guidItems);\n\n const localIds = Model.createLocalIdsVector(b, [...itemIds, containerId]);\n\n // ---- Spatial structure: the operation, with every change hanging off it. ----\n const leaves = this.changes.map((_, i) =>\n SpatialStructure.createSpatialStructure(\n b,\n itemIds[i],\n b.createString(CATEGORY_CHANGE),\n 0,\n ),\n );\n const spatial = SpatialStructure.createSpatialStructure(\n b,\n containerId,\n b.createString(CATEGORY_OPERATION),\n SpatialStructure.createChildrenVector(b, leaves),\n );\n\n const modelGuid = b.createString(opId);\n\n Model.startModel(b);\n Model.addMeshes(b, meshes);\n Model.addMetadata(b, metadataOffset);\n Model.addAttributes(b, attributes);\n Model.addUniqueAttributes(b, uniqueAttributes);\n Model.addLocalIds(b, localIds);\n Model.addCategories(b, categories);\n Model.addGuidsItems(b, guidsItems);\n Model.addGuids(b, guids);\n Model.addGuid(b, modelGuid);\n Model.addSpatialStructure(b, spatial);\n Model.addMaxLocalId(b, next);\n const model = Model.endModel(b);\n\n // WITH the file identifier the schema declares. A buffer finished without\n // it is readable by something that does not check and rejected by\n // everything that does.\n Model.finishModelBuffer(b, model);\n return b.asUint8Array();\n }\n}\n\n/**\n * The optional peers, resolved when an operation is actually built — so apps\n * that never author operations pay nothing and need nothing installed.\n */\nasync function loadDependencies(): Promise<[FlatbuffersModule, FragmentsSchema]> {\n try {\n return await Promise.all([\n import('flatbuffers'),\n import('@thatopen/fragments') as Promise<FragmentsSchema>,\n ]);\n } catch (cause) {\n throw new Error(\n 'OperationBuilder needs the optional peers `flatbuffers` and ' +\n '`@thatopen/fragments` installed — add them to the app that authors ' +\n `operations. (${cause instanceof Error ? cause.message : String(cause)})`,\n );\n }\n}\n\n/**\n * The number as text, round-trippable. `Position` and `Rotation` are strings\n * because every attribute is a string; writing them with the shortest form\n * that reads back identically is what keeps \"9000 mm\" from arriving as\n * 8999.999999999998.\n */\nfunction num(v: number): string {\n return Number.isFinite(v) ? String(v) : '0';\n}\n\n/**\n * zlib, which is what the reader inflates — NOT raw deflate.\n * `CompressionStream(\"deflate\")` is the zlib-wrapped one and `\"deflate-raw\"`\n * is the bare stream, and picking the wrong one produces a file that fails at\n * the first byte with an error about the format rather than about the choice.\n *\n * Native on both sides, so this costs no dependency in the browser and none\n * in a test runner.\n */\nasync function deflate(bytes: Uint8Array): Promise<Uint8Array> {\n const stream = new Blob([bytes as BlobPart])\n .stream()\n .pipeThrough(new CompressionStream('deflate'));\n return new Uint8Array(await new Response(stream).arrayBuffer());\n}\n","/**\n * What every built-in recipe shares: reading the platform's own semantic\n * records out of a .frag, finding what a recipe already made, and the unit\n * and axis conversions into Revit.\n *\n * THE RECORDS. A .frag that went through the platform's editable converter\n * (or was modelled here) carries each element as JSON inside two item\n * attributes: `Element` (the item's own record) and `Carried` (records with\n * no body of their own: openings, levels). The field names are the modeling\n * engine's contract (`element-attributes.ts`: ELEMENT_FIELD, CARRIED_FIELD).\n * A .frag imported with the plain IfcImporter has NEITHER — only IFC\n * attributes — and the recipes refuse it by name rather than guess.\n *\n * UNITS AND AXES. Records are in METRES and radians; curve points are plane\n * [x, y] and placements [x, y, height]. Revit's API is FEET, Z up — so\n * [x, y, h] maps to Revit [x·s, y·s, h·s] with s = feet-per-metre. Item ids\n * like `run:0` are DOCUMENT-scoped, not GUIDs: a reconcile key must carry the\n * source file's identity next to them.\n */\nimport type { RecipeContext } from '../recipes';\nimport type { FlowSuggestion } from '../history';\nimport { readFrag, type FragItem } from '../frag-items';\n\n/** The modeling engine's attribute names (its `element-attributes.ts`). */\nexport const ELEMENT_FIELD = 'Element';\nexport const CARRIED_FIELD = 'Carried';\n\n/** Revit's internal length unit: where every position has to end up. */\nexport const FEET_PER_METRE = 1 / 0.3048;\n\n/** One semantic record, as saved: `params` carries the kind-specific fields. */\nexport interface OurRecord {\n id: string;\n kind: string;\n params: Record<string, unknown>;\n /** The item it rode in (its guid is the publisher's id, when it has one). */\n item: FragItem;\n}\n\n/** Every record of a read .frag: items' `Element` plus their `Carried` lists. */\nexport function recordsOf(items: FragItem[]): OurRecord[] {\n const records: OurRecord[] = [];\n for (const item of items) {\n for (const field of [ELEMENT_FIELD, CARRIED_FIELD]) {\n const raw = item.attrs[field];\n if (!raw) continue;\n try {\n const parsed = JSON.parse(raw) as unknown;\n for (const one of Array.isArray(parsed) ? parsed : [parsed]) {\n const record = one as {\n id?: unknown;\n kind?: unknown;\n params?: unknown;\n };\n if (typeof record?.id !== 'string' || typeof record?.kind !== 'string')\n continue;\n records.push({\n id: record.id,\n kind: record.kind,\n params: (record.params ?? {}) as Record<string, unknown>,\n item,\n });\n }\n } catch {\n // One broken record costs itself, never the file.\n }\n }\n }\n return records;\n}\n\n/**\n * A param the converter double-encodes (`params.run`, `params.member`,\n * `params.definition`… are JSON IN TEXT inside the record's JSON).\n */\nexport function innerJson<T>(record: OurRecord, param: string): T | null {\n const raw = record.params[param];\n if (typeof raw !== 'string') return null;\n try {\n return JSON.parse(raw) as T;\n } catch {\n return null;\n }\n}\n\n/** Level id (`datum:N`) → its name, from the document's datum records. */\nexport function levelNames(records: OurRecord[]): Map<string, string> {\n const names = new Map<string, string>();\n for (const record of records) {\n if (record.kind !== 'datum' || record.params.of !== 'level') continue;\n const named = record.params.named;\n if (typeof named === 'string') names.set(record.id, named);\n }\n return names;\n}\n\n/**\n * Source id → what this recipe already made for it, read back from its own\n * APPLIED suggestions: the i-th id the target answered with is what the i-th\n * change made. It keeps nothing of its own, so it behaves the same whoever\n * runs it and wherever (the pattern the first end-to-end conversion proved).\n */\nexport async function whatItMadeBefore(\n context: RecipeContext<never> | RecipeContext<unknown>,\n author: string,\n): Promise<Map<string, string>> {\n const made = new Map<string, string>();\n const applied = (await context.targetDoc.suggestions())\n .filter(\n (one: FlowSuggestion) =>\n one.author === author &&\n one.state === 'applied' &&\n one.fragId &&\n (one.affectedIds?.length ?? 0) > 0,\n )\n .sort((a, b) => String(a.createdAt).localeCompare(String(b.createdAt)));\n for (const suggestion of applied) {\n try {\n const payload = await context.targetDoc.suggestionPayload(suggestion);\n const { items } = await readFrag(\n new Uint8Array(await payload.arrayBuffer()),\n );\n // The changes, in payload order; the item that groups them has no verb.\n const changes = items.filter((item) => item.attrs['flow:op']);\n const ids = suggestion.affectedIds ?? [];\n for (let i = 0; i < changes.length && i < ids.length; i++) {\n const source = changes[i].attrs['flow:source'];\n if (!source) continue;\n if (changes[i].attrs['flow:op'] === 'remove') made.delete(source);\n else made.set(source, ids[i]);\n }\n } catch {\n // A payload that cannot be read costs its pairings and nothing else:\n // the worst that follows is a duplicate, never a wrong model.\n }\n }\n return made;\n}\n\n/** The project file the person picked as a recipe's source. */\nexport interface PickedFile {\n fileId: string;\n name: string;\n}\n\n/** Downloads and reads the picked .frag, with the errors a person can act on. */\nexport async function readPickedFrag(\n context: RecipeContext<unknown>,\n picked: PickedFile | undefined,\n) {\n if (!picked?.fileId) throw new Error('Choose the model file to read.');\n const bytes = new Uint8Array(\n await (await context.client.downloadFile(picked.fileId)).arrayBuffer(),\n );\n return { picked, contents: await readFrag(bytes) };\n}\n","/**\n * The platform's own records become Revit change requests: one engine, two\n * recipes. `frag-to-revit` reads a model made or edited here (Designer);\n * `ifc-to-revit` reads the frag an IFC was converted into. Same records,\n * same rules — the only difference is where the file came from, and the\n * recipe saying so to the person.\n *\n * WHAT IT PROPOSES TODAY, honestly: the Revit add-in's applier creates\n * point-placed family instances and edits/removes by id — nothing else yet.\n * So columns (member records) and free-standing family instances become\n * proposals; walls, slabs, stairs and everything with a body are READ and\n * TALLIED but propose nothing, and the rules table says so. As the applier\n * grows (walls and floors by native creation are agreed), rules light up here\n * without the recipes changing shape.\n */\nimport type { Recipe, RecipeContext } from '../recipes';\nimport { OperationBuilder } from '../op-builder';\nimport {\n FEET_PER_METRE,\n innerJson,\n levelNames,\n readPickedFrag,\n recordsOf,\n whatItMadeBefore,\n type OurRecord,\n type PickedFile,\n} from './shared';\n\n/** A family type of the target, as the target publishes it. */\ninterface RevitType {\n categoryId: string;\n family: string;\n type: string;\n}\n\ninterface Settings {\n /** The Revit type every proposed column gets. */\n columnType?: RevitType;\n /**\n * Trust the records' own style names instead: `lookRef`\n * \"Family:Type\" becomes the proposal's Family and Type verbatim. Revit\n * matches a type exactly and refuses the whole request when one is missing\n * — right for a model that came FROM this Revit, wrong for anything else.\n */\n trustStyleNames?: boolean;\n /** Also propose free-standing family instances (furniture, equipment). Needs trustStyleNames. */\n includeInstances?: boolean;\n}\n\n/** The saved member's inner JSON (`params.member`). */\ninterface MemberBody {\n of?: string;\n lookRef?: string;\n start?: [number, number, number];\n end?: [number, number, number];\n roll?: number;\n level?: string;\n}\n\n/** The saved instance's inner JSON (`params.instance`). */\ninterface InstanceBody {\n placement?: {\n at?: [number, number, number];\n right?: [number, number, number];\n };\n host?: string | null;\n}\n\nconst DEGREES = 180 / Math.PI;\n\n/** \"Family:Type\" as the styles name things; null when it does not split. */\nfunction familyAndType(lookRef: unknown): { family: string; type: string } | null {\n if (typeof lookRef !== 'string') return null;\n const colon = lookRef.indexOf(':');\n if (colon <= 0 || colon === lookRef.length - 1) return null;\n return { family: lookRef.slice(0, colon), type: lookRef.slice(colon + 1) };\n}\n\nfunction sharedRun(to: 'frag' | 'ifc') {\n return async (context: RecipeContext<Settings>) => {\n const { picked, contents } = await readPickedFrag(\n context,\n context.input as PickedFile | undefined,\n );\n const records = recordsOf(contents.items);\n if (records.length === 0) {\n throw new Error(\n to === 'ifc'\n ? `\"${picked.name}\" carries no platform records: it was imported without the editable converter. ` +\n 'Process the IFC with the editable converter first; a plain import only has IFC attributes, and guessing geometry is not this recipe.'\n : `\"${picked.name}\" carries no platform records, so there is nothing semantic to convert.`,\n );\n }\n\n const { columnType, trustStyleNames, includeInstances } = context.settings;\n if (!columnType && !trustStyleNames) {\n throw new Error(\n 'Choose the Revit column type, or trust the model style names.',\n );\n }\n if (includeInstances && !trustStyleNames) {\n throw new Error(\n 'Free-standing instances can only be proposed by their style names: turn trustStyleNames on.',\n );\n }\n\n const levels = levelNames(records);\n const author = `recipe:${to}-to-revit`;\n const made = await whatItMadeBefore(context, author);\n const head = await context.targetDoc.latest();\n const operation = new OperationBuilder({\n project: context.projectId,\n document: context.targetDoc.docId,\n baseCommit: head?.version ?? 0,\n author,\n });\n // Records are metres; Revit is feet. Plane [x, y] + height is Revit\n // [x, y, z] directly — both are Z up in these records.\n const s = FEET_PER_METRE;\n const sourceKey = (record: OurRecord) => `${picked.fileId}:${record.id}`;\n\n let columns = 0;\n let instances = 0;\n let bodies = 0;\n const seen = new Set<string>();\n const propose = (\n record: OurRecord,\n attrs: Record<string, string>,\n position: [number, number, number],\n rotationDeg: number,\n ) => {\n const key = sourceKey(record);\n seen.add(key);\n const existing = made.get(key);\n if (existing) {\n operation.set(existing, {}, { position, rotationDeg, source: key });\n } else {\n operation.add(attrs, { position, rotationDeg, source: key });\n }\n };\n\n for (const record of records) {\n if (record.kind === 'member' && record.params.of === 'column') {\n const body = innerJson<MemberBody>(record, 'member');\n const at = body?.start;\n if (!at || at.length !== 3) continue;\n const named = trustStyleNames ? familyAndType(record.params.lookRef) : null;\n // A style name that does not split names nothing proposable.\n if (trustStyleNames && !named) continue;\n const family = named ?? {\n family: columnType!.family,\n type: columnType!.type,\n };\n const level = levels.get(String(body?.level ?? ''));\n propose(\n record,\n {\n ...(columnType && !trustStyleNames\n ? { CategoryId: columnType.categoryId }\n : {}),\n Family: family.family,\n Type: family.type,\n ...(level ? { Level: level } : {}),\n },\n [at[0] * s, at[1] * s, at[2] * s],\n (Number(body?.roll ?? 0) || 0) * DEGREES,\n );\n columns++;\n continue;\n }\n if (\n includeInstances &&\n record.kind === 'familyInstance' &&\n !record.params.host\n ) {\n const body = innerJson<InstanceBody>(record, 'instance');\n const at = body?.placement?.at;\n if (!at || at.length !== 3 || body?.host) continue;\n const named = familyAndType(record.params.type);\n if (!named) continue;\n const right = body?.placement?.right;\n const rotation = right ? Math.atan2(right[1], right[0]) * DEGREES : 0;\n propose(\n record,\n { Family: named.family, Type: named.type },\n [at[0] * s, at[1] * s, at[2] * s],\n rotation,\n );\n instances++;\n continue;\n }\n // Everything with a body the applier cannot create yet: counted, so the\n // person sees what the model holds and what still waits on the applier.\n if (\n record.kind === 'run' ||\n record.kind === 'extrusion' ||\n record.kind === 'stair' ||\n record.kind === 'footing' ||\n record.kind === 'ramp'\n ) {\n bodies++;\n }\n }\n\n // What this recipe made before and whose record is gone now.\n let removed = 0;\n for (const [key, madeId] of made) {\n if (!key.startsWith(`${picked.fileId}:`) || seen.has(key)) continue;\n operation.remove(madeId);\n removed++;\n }\n\n if (operation.length === 0) {\n throw new Error(\n `Nothing the Revit applier can do yet: \"${picked.name}\" has ${bodies} element(s) with a body ` +\n '(walls, slabs, stairs…) and no column or free-standing instance. Those arrive as the applier grows.',\n );\n }\n\n const words = [\n columns ? `${columns} column(s)` : '',\n instances ? `${instances} instance(s)` : '',\n removed ? `${removed} gone` : '',\n ].filter(Boolean);\n return {\n title: `${to === 'ifc' ? 'IFC' : 'Model'} to Revit: ${words.join(', ')}`,\n verb: operation.summary,\n targets: operation.length,\n payload: new Blob([(await operation.build(context.opId)) as BlobPart]),\n ruleTallies: [\n { read: columns, proposed: columns },\n { read: instances, proposed: instances },\n { read: removed, proposed: removed },\n { read: bodies, proposed: 0 },\n ],\n };\n };\n}\n\nconst sharedSchema = {\n type: 'object',\n properties: {\n columnType: {\n type: 'object',\n title: 'Column type',\n // Revit's id of the Columns category: `Category` is a name in the\n // language of whoever installed Revit, and cannot be compared.\n 'x-existing': {\n of: 'family-type',\n from: 'target',\n where: { CategoryId: '-2001330' },\n },\n },\n trustStyleNames: {\n type: 'boolean',\n title: 'Use the model’s own style names as Family:Type',\n default: false,\n },\n includeInstances: {\n type: 'boolean',\n title: 'Also propose free-standing instances (needs style names)',\n default: false,\n },\n },\n};\n\nconst sharedRules = [\n {\n reads: 'Column records (members) with no proposal yet',\n proposes: 'A new Revit column at each, on its level',\n },\n {\n reads: 'Free-standing family instances (when turned on)',\n proposes: 'A new instance of the same-named type, placed and turned',\n },\n {\n reads: 'Things this recipe made whose record is gone',\n proposes: 'That element removed',\n },\n {\n reads: 'Walls, slabs, stairs and every element with a body',\n proposes: 'Nothing yet — waits on the Revit applier growing',\n },\n];\n\nexport const fragToRevit: Recipe<Settings> = {\n name: 'frag-to-revit',\n title: 'Platform model to Revit',\n description:\n 'Turns the platform records of a .frag into change requests for a Revit document.',\n to: 'revit',\n inputs: ['frag-model'],\n source: { kind: 'project-file', extensions: ['frag'] },\n runtime: 'browser',\n settingsSchema: sharedSchema,\n rules: sharedRules,\n doc: `\n## What it does\n\nIt reads a .frag made or edited on the platform and asks a Revit document for\nthe elements its records describe. Nothing changes in Revit until the owner of\nthat document accepts the request there.\n\n## What it can ask for today\n\nThe Revit applier creates point-placed family instances and edits or removes\nby id. So columns and (optionally) free-standing instances become proposals;\nwalls, slabs and stairs are counted and reported, and start proposing the day\nthe applier learns native creation for them.\n\n## It reconciles, it does not push\n\nRun it again after the model changed and it asks only for the difference. It\ncan only ever ask to remove what it asked for itself; elements a person made\nin Revit are invisible to it. What it made is read back from its own applied\nrequests — it keeps nothing of its own.\n\n## Units and axes\n\nRecords are metres, Z up; proposals are written in Revit's feet. Types are\nmatched exactly by name; Revit refuses the whole request when one is missing.\n`,\n run: sharedRun('frag'),\n};\n\nexport const ifcToRevit: Recipe<Settings> = {\n ...fragToRevit,\n name: 'ifc-to-revit',\n title: 'IFC to Revit',\n description:\n 'Turns an IFC — through the frag the platform converted it into — into change requests for a Revit document.',\n inputs: ['ifc-model'],\n doc: `\n## What it does\n\nIt reads the .frag your IFC was PROCESSED into (the IFC document's view) and\nasks a Revit document for the elements its records describe. Point it at that\nfrag: a plain IFC import carries only IFC attributes and is refused by name —\nthe editable converter is what gives an IFC real records.\n\n## What it can ask for today\n\nThe Revit applier creates point-placed family instances and edits or removes\nby id. So columns and (optionally) free-standing instances become proposals;\nwalls, slabs and stairs are counted and reported, and start proposing the day\nthe applier learns native creation for them.\n\n## It reconciles, it does not push\n\nRun it again after a reconversion and it asks only for the difference. It can\nonly ever ask to remove what it asked for itself. What it made is read back\nfrom its own applied requests — it keeps nothing of its own.\n\n## Units and axes\n\nRecords are metres, Z up; proposals are written in Revit's feet. Types are\nmatched exactly by name; Revit refuses the whole request when one is missing.\n`,\n run: sharedRun('ifc'),\n};\n","/**\n * A Rhino layer becomes Revit family instances: the built-in form of the one\n * conversion proven end to end (flow, 2026-07-30). Each object of the chosen\n * layer that declares a `Position` asks for an instance of the chosen Revit\n * type where it stands — the porch colonnade: Rhino drives WHERE, Revit owns\n * WHAT.\n */\nimport type { Recipe, RecipeContext } from '../recipes';\nimport { OperationBuilder } from '../op-builder';\nimport type { FragItem } from '../frag-items';\nimport {\n FEET_PER_METRE,\n readPickedFrag,\n whatItMadeBefore,\n type PickedFile,\n} from './shared';\n\n/** What each unit name means in metres. Read from the source, never assumed. */\nconst METRES_PER_UNIT: Record<string, number> = {\n millimeters: 0.001,\n millimetres: 0.001,\n mm: 0.001,\n centimeters: 0.01,\n centimetres: 0.01,\n cm: 0.01,\n meters: 1,\n metres: 1,\n m: 1,\n inches: 0.0254,\n in: 0.0254,\n feet: 0.3048,\n ft: 0.3048,\n};\n\n/** A family type of the target, as the target publishes it. */\ninterface RevitType {\n categoryId: string;\n family: string;\n type: string;\n}\n\ninterface Settings {\n /** The Rhino layer that drives placement. */\n layer: string;\n /** The Revit type every placed object becomes. */\n instanceType: RevitType;\n}\n\nconst NAME = 'rhino-to-revit';\nconst AUTHOR = `recipe:${NAME}`;\n\n/** `Position` is \"x,y,z\" in the publisher's own units. */\nfunction positionOf(item: FragItem): [number, number, number] | null {\n const parts = (item.attrs.Position ?? '')\n .split(',')\n .map((part) => Number(part.trim()));\n if (parts.length !== 3 || parts.some((v) => !Number.isFinite(v))) return null;\n return [parts[0], parts[1], parts[2]];\n}\n\nexport const rhinoToRevit: Recipe<Settings> = {\n name: NAME,\n title: 'Rhino to Revit',\n description:\n 'Turns the placed objects of a Rhino layer into change requests for Revit instances of a chosen type.',\n to: 'revit',\n inputs: ['rhino-model'],\n source: { kind: 'project-file', extensions: ['frag'] },\n runtime: 'browser',\n settingsSchema: {\n type: 'object',\n properties: {\n layer: {\n type: 'string',\n title: 'Rhino layer',\n 'x-existing': { of: 'layer', from: 'source' },\n },\n instanceType: {\n type: 'object',\n title: 'Revit type',\n 'x-existing': { of: 'family-type', from: 'target' },\n },\n },\n required: ['layer', 'instanceType'],\n },\n rules: [\n {\n reads: 'Objects on the chosen layer with no instance yet',\n proposes: 'A new instance of the chosen type at each',\n },\n {\n reads: 'Objects whose instance already exists',\n proposes: 'That instance moved to where the object is now',\n },\n {\n reads: 'Instances whose object is gone from Rhino',\n proposes: 'That instance removed',\n },\n { reads: 'Everything on other layers', proposes: 'Nothing' },\n ],\n doc: `\n## What it does\n\nIt reads a model published from Rhino and asks a Revit document for instances\nof one type: one where each placed object of a layer stands. It never touches\nthe Rhino model, and nothing changes in Revit until the owner of that document\naccepts the request there.\n\n## It reconciles, it does not push\n\nRun it again after the Rhino model changed and it asks only for the\ndifference: new objects become new instances, moved objects move theirs, and\nan object that is gone asks for its instance to be removed. It can only ever\nask to remove an instance it asked for itself — elements a person made in\nRevit are invisible to it. What it made is read back from its own applied\nrequests; it keeps nothing of its own.\n\n## What it assumes\n\n- The Rhino model declares its units. One that does not is refused, not guessed.\n- Both models are Z up. A different axis convention is refused.\n- The Revit type exists in the target. Revit matches a type exactly and\n refuses the whole request when one is missing.\n\n## What it does not know\n\nWhere an object becomes an instance, Revit decides the level: the nearest one\nat or below the point. For a level-based family the level wins over the\npoint's height.\n`,\n\n async run(context: RecipeContext<Settings>) {\n const { picked, contents } = await readPickedFrag(\n context,\n context.input as PickedFile | undefined,\n );\n const { layer, instanceType } = context.settings;\n if (!layer || !instanceType)\n throw new Error('Choose the layer and the Revit type.');\n\n // Refused rather than guessed: a length read in the wrong unit is off by\n // a thousand and still looks plausible.\n const data = contents.metadata?.data as\n | { units?: unknown; axes?: unknown }\n | undefined;\n const declared = data?.units;\n const metres =\n typeof declared === 'string'\n ? METRES_PER_UNIT[declared.trim().toLowerCase()]\n : undefined;\n if (!metres) {\n throw new Error(\n `\"${picked.name}\" does not say what units its data is in` +\n `${declared ? ` (\"${String(declared)}\" is not one this recipe knows)` : ''}, so nothing can be converted from it.`,\n );\n }\n const axes = String(data?.axes ?? 'z-up').toLowerCase();\n if (axes !== 'z-up') {\n throw new Error(\n `\"${picked.name}\" declares its data as \"${axes}\"; this recipe only converts Z up.`,\n );\n }\n const scale = metres * FEET_PER_METRE;\n\n const made = await whatItMadeBefore(context, AUTHOR);\n const head = await context.targetDoc.latest();\n const operation = new OperationBuilder({\n project: context.projectId,\n document: context.targetDoc.docId,\n baseCommit: head?.version ?? 0,\n author: AUTHOR,\n });\n\n // ORDER IS THE CONTRACT: the ids come back in the order the changes are\n // written, and every change carries the object it answers to.\n let added = 0;\n let moved = 0;\n let elsewhere = 0;\n const seen = new Set<string>();\n const moves: { instance: string; object: string; position: [number, number, number] }[] = [];\n for (const item of contents.items) {\n if (!item.guid || Object.keys(item.attrs).length === 0) continue;\n if ((item.attrs.Layer ?? '') !== layer) {\n elsewhere++;\n continue;\n }\n const at = positionOf(item);\n if (!at) continue; // something with no position is not placeable\n seen.add(item.guid);\n const position: [number, number, number] = [\n at[0] * scale,\n at[1] * scale,\n at[2] * scale,\n ];\n const instance = made.get(item.guid);\n if (instance) {\n moves.push({ instance, object: item.guid, position });\n } else {\n operation.add(\n {\n CategoryId: instanceType.categoryId,\n Family: instanceType.family,\n Type: instanceType.type,\n },\n { position, source: item.guid },\n );\n added++;\n }\n }\n for (const move of moves) {\n operation.set(move.instance, {}, { position: move.position, source: move.object });\n moved++;\n }\n let removed = 0;\n for (const [object, instance] of made) {\n if (seen.has(object)) continue;\n operation.remove(instance);\n removed++;\n }\n\n const total = added + moved + removed;\n if (total === 0) {\n throw new Error(\n `Nothing to ask for: layer \"${layer}\" of \"${picked.name}\" has no placed object, and nothing of this recipe is left to remove.`,\n );\n }\n\n const words = [\n added ? `${added} new` : '',\n moved ? `${moved} moved` : '',\n removed ? `${removed} gone` : '',\n ].filter(Boolean);\n return {\n title: `From Rhino: ${words.join(', ')}`,\n verb: operation.summary,\n targets: total,\n payload: new Blob([(await operation.build(context.opId)) as BlobPart]),\n ruleTallies: [\n { read: added, proposed: added },\n { read: moved, proposed: moved },\n { read: removed, proposed: removed },\n { read: elsewhere, proposed: 0 },\n ],\n };\n },\n};\n","/**\n * The recipes the platform ships with: proof that interoperability works\n * without writing anything, and templates to copy.\n *\n * What is NOT here yet, and why: `revit-to-rhino` waits on the Rhino plugin\n * growing a suggestion applier (today it only exports and publishes) — a\n * recipe whose payload vocabulary nobody reads would fix a contract blind.\n * `frag-to-autocad` (our drawings to DWG) is agreed as optional and comes\n * after. Both land here when their appliers exist.\n */\nimport type { EngineServicesClient } from '../client';\nimport type { Recipe } from '../recipes';\nimport { fragToRevit, ifcToRevit } from './records-to-revit';\nimport { rhinoToRevit } from './rhino-to-revit';\n\nexport { fragToRevit, ifcToRevit } from './records-to-revit';\nexport { rhinoToRevit } from './rhino-to-revit';\n\n/** The built-in recipes, in catalog order. */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any -- a heterogeneous catalog erases its settings types\nexport const builtinRecipes: Recipe<any>[] = [\n rhinoToRevit,\n ifcToRevit,\n fragToRevit,\n];\n\n/** Registers every built-in recipe on the client's registry. */\nexport function registerBuiltinRecipes(client: EngineServicesClient): void {\n for (const recipe of builtinRecipes) client.recipes.register(recipe);\n}\n","import { Readable } from 'stream';\nimport { ObjectId } from './base';\n\nexport type FileType = string | Uint8Array | Buffer | Readable;\n\nexport type HiddenFileEntity = {\n fileId: string;\n _id: ObjectId;\n parentItemId: ObjectId;\n /** Label set on upload; absent on untagged files. */\n tag?: string;\n};\n\nexport type CreateHiddenItemResult = {\n hiddenFileId: string;\n};\n\nexport type CreateHiddenItemsBatchResult = {\n results: { originalName: string; hiddenFileId: string }[];\n};\n\nexport type MetadataValue = string | number | boolean | null;\n\nexport type Metadata = Record<string, MetadataValue>;\n\nexport const METADATA_LIMITS = {\n MAX_FIELDS: 200,\n MAX_KEY_LENGTH: 50,\n MAX_VALUE_LENGTH: 50,\n} as const;\n","/* eslint-disable @typescript-eslint/no-explicit-any, @typescript-eslint/no-unused-vars */\n/**\n * Built-in component types and runtime stubs.\n * Auto-generated by platform_builtin-components/scripts/distribute-types.mjs\n */\n\nimport type * as OBC from '@thatopen/components';\nimport type * as THREE from 'three';\nimport type { EngineServicesClient, Item, ItemFolder, ItemVersion, PlatformClient } from '../';\n\nexport interface CDEContext {\n client: PlatformClient;\n projectId: string;\n}\nexport interface CDEUserPermissions {\n canRead: boolean;\n canCreate: boolean;\n canUpdate: boolean;\n canDelete: boolean;\n canManage: boolean;\n}\nexport type CDEMetadataValue = string | number | boolean | null;\nexport interface CDENamingSegment {\n key: string;\n config?: {\n transform: (value: CDEMetadataValue) => string;\n };\n}\nexport interface CDENamingSchema {\n separator: string;\n segments: CDENamingSegment[];\n}\nexport interface CDEFile extends Omit<Item, 'creatingUser'> {\n createdBy: string;\n metadata: Record<string, CDEMetadataValue>;\n versions?: ItemVersion[];\n /** Tag of the file's current version (set by CDEManager from the loaded version). */\n versionTag?: string;\n}\nexport interface CDEMetadataField {\n type: \"string\" | \"number\" | \"boolean\" | \"list\";\n description?: string;\n required?: boolean;\n label: string;\n icon?: string;\n options?: {\n value: string | number | boolean;\n label: string;\n }[];\n}\nexport type CDEMetadataSchema = Record<string, CDEMetadataField>;\nexport interface CDEFileActivity {\n user: string;\n action: string;\n timestamp: string;\n}\nexport interface CDEFileHistoryEntry {\n fileId: string;\n activity: CDEFileActivity[];\n}\nexport interface CDEMetadataView {\n id: string;\n name: string;\n fields: string[];\n}\nexport type CDEPendingMetadata = Record<string, CDEMetadataValue>;\nexport type CDEPendingMetadataSchemaEdits = Record<string, CDEMetadataField | null>;\nexport type FolderPendingChange = {\n kind: \"create\";\n tempId: string;\n name: string;\n parentId: string | null;\n} | {\n kind: \"rename\";\n folderId: string;\n name: string;\n} | {\n kind: \"archive\";\n folderId: string;\n};\nexport type FolderPendingChanges = FolderPendingChange[];\nexport type CDEViewFileStatus = \"loading\" | \"ready\" | \"failed\" | \"cancelled\";\nexport type CDEMachineState = {\n kind: \"idle\";\n} | {\n kind: \"loading\";\n} | {\n kind: \"preparing\";\n files: CDEFile[];\n} | {\n kind: \"selected\";\n files: CDEFile[];\n} | {\n kind: \"viewing\";\n files: CDEFile[];\n fileStatus: Record<string, CDEViewFileStatus>;\n selectedFiles?: CDEFile[];\n} | {\n kind: \"editing\";\n files: CDEFile[];\n pendingMetadata: CDEPendingMetadata;\n} | {\n kind: \"saving\";\n files: CDEFile[];\n pendingMetadata: CDEPendingMetadata;\n} | {\n kind: \"deleting\";\n files: CDEFile[];\n} | {\n kind: \"configuringMetadataSchema\";\n pendingEdits: CDEPendingMetadataSchemaEdits;\n} | {\n kind: \"savingMetadataSchema\";\n pendingEdits: CDEPendingMetadataSchemaEdits;\n} | {\n kind: \"configuringMetadataViews\";\n pendingViews: CDEMetadataView[];\n} | {\n kind: \"savingMetadataViews\";\n pendingViews: CDEMetadataView[];\n} | {\n kind: \"dragging\";\n files: CDEFile[];\n sourceFolderId: string | null;\n previousState: CDEMachineState;\n} | {\n kind: \"movingFiles\";\n files: CDEFile[];\n targetFolderId: string;\n} | {\n kind: \"draggingFolder\";\n folderId: string;\n parentFolderId: string | null;\n previousState: CDEMachineState;\n} | {\n kind: \"movingFolder\";\n folderId: string;\n targetFolderId: string | null;\n} | {\n kind: \"editingFolders\";\n pendingChanges: FolderPendingChanges;\n} | {\n kind: \"savingFolderChanges\";\n pendingChanges: FolderPendingChanges;\n} | {\n kind: \"editingFiles\";\n pendingEdits: Record<string, Record<string, CDEMetadataValue>>;\n pendingArchives: string[];\n pendingRenames: Record<string, string>;\n previousState: {\n kind: \"idle\";\n } | {\n kind: \"selected\";\n files: CDEFile[];\n };\n} | {\n kind: \"savingFiles\";\n pendingEdits: Record<string, Record<string, CDEMetadataValue>>;\n pendingArchives: string[];\n pendingRenames: Record<string, string>;\n previousState: {\n kind: \"idle\";\n } | {\n kind: \"selected\";\n files: CDEFile[];\n };\n} | {\n kind: \"error\";\n reason: string;\n previous: CDEMachineState;\n};\nexport type CDEMachineEvent = {\n type: \"LOAD\";\n} | {\n type: \"UPLOAD\";\n} | {\n type: \"DOWNLOAD\";\n} | {\n type: \"SELECT\";\n files: CDEFile[];\n} | {\n type: \"DESELECT\";\n} | {\n type: \"VIEW\";\n} | {\n type: \"ADD_TO_VIEW\";\n file: CDEFile;\n} | {\n type: \"REMOVE_FROM_VIEW\";\n fileId: string;\n} | {\n type: \"CLOSE_VIEW\";\n} | {\n type: \"SET_VIEW_FILE_STATUS\";\n fileId: string;\n status: CDEViewFileStatus;\n} | {\n type: \"START_EDIT\";\n} | {\n type: \"UPDATE_METADATA\";\n key: string;\n value: CDEMetadataValue;\n} | {\n type: \"SAVE\";\n} | {\n type: \"CANCEL_EDIT\";\n} | {\n type: \"ARCHIVE_FILE\";\n} | {\n type: \"START_CONFIGURE_METADATA_SCHEMA\";\n} | {\n type: \"ADD_METADATA_FIELD\";\n} | {\n type: \"UPDATE_METADATA_FIELD\";\n key: string;\n value: CDEMetadataField;\n} | {\n type: \"DELETE_METADATA_FIELD\";\n key: string;\n} | {\n type: \"RESTORE_METADATA_FIELD\";\n key: string;\n} | {\n type: \"SAVE_METADATA_SCHEMA\";\n} | {\n type: \"CANCEL_CONFIGURE_METADATA_SCHEMA\";\n} | {\n type: \"START_DRAG\";\n files: CDEFile[];\n sourceFolderId: string | null;\n} | {\n type: \"END_DRAG\";\n} | {\n type: \"DROP_FILES\";\n targetFolderId: string | null;\n} | {\n type: \"START_FOLDER_DRAG\";\n folderId: string;\n parentFolderId: string | null;\n} | {\n type: \"END_FOLDER_DRAG\";\n} | {\n type: \"DROP_FOLDER\";\n targetFolderId: string | null;\n} | {\n type: \"START_EDIT_FILES\";\n} | {\n type: \"UPDATE_FILE_METADATA\";\n fileId: string;\n key: string;\n value: CDEMetadataValue;\n} | {\n type: \"REVERT_FILE_METADATA\";\n fileId: string;\n} | {\n type: \"ARCHIVE_FILE_EDIT\";\n fileId: string;\n} | {\n type: \"UNARCHIVE_FILE_EDIT\";\n fileId: string;\n} | {\n type: \"RENAME_FILE\";\n fileId: string;\n name: string;\n} | {\n type: \"RENAME_FILE_IMMEDIATE\";\n fileId: string;\n name: string;\n} | {\n type: \"SAVE_FILE_EDITS\";\n} | {\n type: \"CANCEL_EDIT_FILES\";\n} | {\n type: \"START_EDIT_FOLDERS\";\n} | {\n type: \"ADD_FOLDER\";\n tempId: string;\n name: string;\n parentId: string | null;\n} | {\n type: \"RENAME_FOLDER\";\n folderId: string;\n name: string;\n} | {\n type: \"ARCHIVE_FOLDER\";\n folderId: string;\n} | {\n type: \"SAVE_FOLDER_CHANGES\";\n} | {\n type: \"CANCEL_FOLDER_CHANGES\";\n} | {\n type: \"RESET_FOLDER\";\n folderId: string;\n} | {\n type: \"START_CONFIGURE_METADATA_VIEWS\";\n} | {\n type: \"ADD_METADATA_VIEW\";\n} | {\n type: \"UPDATE_METADATA_VIEW\";\n id: string;\n view: CDEMetadataView;\n} | {\n type: \"DELETE_METADATA_VIEW\";\n id: string;\n} | {\n type: \"SAVE_METADATA_VIEWS\";\n} | {\n type: \"CANCEL_CONFIGURE_METADATA_VIEWS\";\n} | {\n type: \"SET_ACTIVE_METADATA_VIEW\";\n id: string | null;\n} | {\n type: \"SET_GROUPS_VIEW_MODE\";\n mode: \"groups\" | \"metadata\";\n} | {\n type: \"FAIL\";\n reason: string;\n} | {\n type: \"DISMISS\";\n};\n\ndeclare class _CDEManager extends OBC.Component implements OBC.Transitionable<CDEMachineState, CDEMachineEvent> {\n static readonly uuid: \"a3f82c1d-5b74-4e9a-bc30-d7e12f894a61\";\n readonly onFilesChanged: OBC.Event<CDEFile[]>;\n readonly onFoldersChanged: OBC.Event<ItemFolder[]>;\n readonly onPermissionsChanged: OBC.Event<CDEUserPermissions>;\n readonly onSelectedGroupChanged: OBC.Event<string | null>;\n readonly onMachineStateChanged: OBC.Event<CDEMachineState>;\n readonly onMetadataViewsChanged: OBC.Event<CDEMetadataView[]>;\n readonly onGroupsViewModeChanged: OBC.Event<\"groups\" | \"metadata\">;\n readonly onMetadataGroupChanged: OBC.Event<Record<string, string> | null>;\n readonly onDownloadReady: OBC.Event<{\n blob: Blob;\n filename: string;\n }>;\n readonly onUploadCompleted: OBC.Event<{\n created: CDEFile[];\n versioned: CDEFile[];\n }>;\n readonly onFolderChangesCompleted: OBC.Event<{\n created: number;\n renamed: number;\n archived: number;\n }>;\n readonly onFilesMovedCompleted: OBC.Event<{\n files: CDEFile[];\n targetFolderName: string | null;\n }>;\n readonly onRenameCompleted: OBC.Event<{\n success: boolean;\n error?: string;\n }>;\n readonly onFolderMovedCompleted: OBC.Event<{\n folderName: string;\n targetFolderName: string | null;\n }>;\n readonly onShowArchivedChanged: OBC.Event<boolean>;\n readonly onRestoreCompleted: OBC.Event<{\n files?: CDEFile[];\n folder?: ItemFolder;\n }>;\n readonly onUploadStarted: OBC.Event<{\n count: number;\n }>;\n readonly onIfcConversionStarted: OBC.Event<{\n file: CDEFile;\n }>;\n readonly onIfcConversionProgress: OBC.Event<{\n file: CDEFile;\n progress: number;\n }>;\n readonly onIfcConversionCompleted: OBC.Event<{\n file: CDEFile;\n success: boolean;\n error?: string;\n }>;\n /** Fires when `_derivedFileIds` finishes a (re)sync — consumers that filter\n * or resolve by source↔derived link (e.g. `top-files-panel` hiding an\n * already-linked `.frag` row) should reload on this, since it can complete\n * after `onFilesChanged` already fired with the (still unsynced) list. */\n readonly onDerivedFileIdsChanged: OBC.Event<Record<string, string>>;\n readonly conversionProgress: Map<string, number>;\n enabled: boolean;\n projectName: string;\n missingMetadataPlaceholder: string;\n availableColumns: Set<string>;\n visibleColumns: Set<string>;\n ctx?: CDEContext;\n private _machineState;\n private _activeUploads;\n private _showArchived;\n private _preArchivedViewMode;\n private _archivedFiles;\n private _archivedFolders;\n private _archivedLoaded;\n viewerGroups: {\n extensions: string[];\n multiple?: boolean;\n }[];\n get viewableExtensions(): Set<string>;\n private _files;\n /** ifcFileId → its linked derivedFileId (FRAG today; other source formats\n * once they get a converter too), read from each IFC's own version\n * metadata. Kept as an in-memory cache — synced by `_syncDerivedFileIds`\n * whenever `_files` is (re)set, or right after a conversion succeeds —\n * rather than fetched live per call, so `resolveViewFile` can stay a plain\n * synchronous lookup (same contract as before, no ripple into\n * `sendMachineEvent`'s callers). */\n private _derivedFileIds;\n private _folders;\n private _fileHistory;\n private _metadataSchema;\n private _metadataViews;\n private _activeMetadataViewId;\n private _groupsViewMode;\n private _selectedGroup;\n private _selectedMetadataGroup;\n private _namingSchema;\n cacheMaxBytes: number;\n cacheExtensions: Set<string>;\n private _fileCache;\n private _fileCacheBytes;\n private _dedup;\n private _cacheKey;\n private _isCacheable;\n private _addToCache;\n downloadFile(file: CDEFile): Promise<ArrayBuffer>;\n private _permissions;\n private _projectDataFolderId;\n private _appFolderIds;\n /** In-flight folder ensures. Two concurrent first calls (user config and\n * app config load in parallel) used to each miss the cache and create a\n * second folder of the same name; the promise is the lock. */\n private _projectDataFolderPromise;\n private _appFolderPromises;\n private _excludedFolderIds;\n private _projectMembers;\n get projectMembers(): {\n fullName: string;\n email: string;\n role: string;\n }[];\n get userPermissions(): CDEUserPermissions;\n query: string | null;\n get machineState(): CDEMachineState;\n get files(): CDEFile[];\n set files(value: CDEFile[]);\n /** ifcFileId → derivedFileId — see `_derivedFileIds`. */\n get derivedFileIds(): Record<string, string>;\n get folders(): ItemFolder[];\n set folders(value: ItemFolder[]);\n get showArchived(): boolean;\n set showArchived(value: boolean);\n get fileHistory(): CDEFileHistoryEntry[];\n set fileHistory(value: CDEFileHistoryEntry[]);\n get metadataSchema(): CDEMetadataSchema;\n set metadataSchema(value: CDEMetadataSchema);\n get selectedGroup(): string | null;\n set selectedGroup(value: string | null);\n get metadataViews(): CDEMetadataView[];\n get activeMetadataViewId(): string | null;\n get activeMetadataView(): CDEMetadataView | null;\n get groupsViewMode(): \"groups\" | \"metadata\";\n get selectedMetadataGroup(): Record<string, string> | null;\n set selectedMetadataGroup(value: Record<string, string> | null);\n get visibleFiles(): CDEFile[];\n get namingSchema(): CDENamingSchema | null;\n constructor(components: OBC.Components);\n hasViewer(extension: string): boolean;\n private _groupOf;\n private _sameGroup;\n canView(files: CDEFile[]): boolean;\n canAddToView(files: CDEFile[]): boolean;\n setNamingSchema(schema: CDENamingSchema): void;\n buildFileName(file: CDEFile): string;\n getSelectedFiles(): CDEFile[];\n getActivity(fileId: string): CDEFileActivity[];\n updateFilesMetadata(fileIds: string[], updates: Record<string, string>): Promise<void>;\n /** The context this component cannot work without. Reading or writing\n * project data with no context used to resolve with null / the empty\n * string while persisting NOTHING - a call indistinguishable from\n * success, which cost an integrator days (reported 2026-10-01). A\n * missing context is a setup problem and must say so. */\n private _requireCtx;\n readProjectData(app: string, filename: string): Promise<any>;\n writeProjectData(app: string, filename: string, data: unknown): Promise<string>;\n /** Of several same-named folders, always the oldest. Duplicates exist in\n * real projects (the backend had no unique index and this class had no\n * lock), and `loadFolders` used to pick the LAST root match while the\n * ensure path picked the FIRST: reads and writes could land in different\n * folders of the same name. ObjectIds sort by creation time as strings. */\n private static _oldest;\n private _ensureProjectDataFolder;\n private _ensureAppFolder;\n private _loadPermissions;\n loadFolders(): Promise<void>;\n createFolder(name: string, parentId?: string): Promise<ItemFolder>;\n getUserId(): Promise<string | undefined>;\n loadUserConfig(): Promise<{\n visibleColumns?: string[];\n metadataViews?: CDEMetadataView[];\n hideDerivedFiles?: boolean;\n } | null>;\n saveUserConfig(config: {\n visibleColumns?: string[];\n metadataViews?: CDEMetadataView[];\n hideDerivedFiles?: boolean;\n }): Promise<string | undefined>;\n loadMetadataSchema(): Promise<void>;\n initMetadataViews(views: CDEMetadataView[], activeId: string | null): void;\n loadArchivedItems(): Promise<void>;\n restoreFiles(files: CDEFile[]): Promise<void>;\n restoreFolder(folderId: string): Promise<void>;\n detectConflicts(files: File[]): {\n file: File;\n existing: CDEFile;\n }[];\n checkMoveConflicts(files: CDEFile[], targetFolderId: string | null): {\n file: CDEFile;\n existing: CDEFile;\n }[];\n /** Which file to actually load when the user views `file` — its linked FRAG\n * if it has one, else the IFC itself. Reads `_derivedFileIds` (the IFC's\n * own version metadata, kept in sync — see `_syncDerivedFileIds`), NOT a\n * name+folder match anymore. Stays synchronous: `_derivedFileIds` is a\n * pre-synced in-memory cache, so this is a plain lookup, keeping the\n * contract every existing caller (`sendMachineEvent`'s `VIEW` case,\n * `top-files-panel`'s \"add to view\" actions) already relies on. */\n resolveViewFile(file: CDEFile): CDEFile;\n /** Populates `_derivedFileIds` from every IFC's own version metadata — the\n * source of truth for the IFC↔FRAG link (same mechanism as `models-list`'s\n * `_syncDerivedFileIds`). Reads the unified `derivedFileId` key, falling\n * back to the legacy `fragmentsFileId` key that `IfcFragmenter` still\n * stamps until it's updated (see issue #3, Task 3). Called whenever\n * `_files` is (re)set and right after a conversion succeeds — never\n * cached indefinitely, so a reconversion or manual metadata edit is picked\n * up on the next sync instead of going stale. */\n private _syncDerivedFileIds;\n private _saveConversionIndex;\n private _loadConversionIndex;\n private _resumePendingConversions;\n /** Cached id of the IfcFragmenter component, resolved by name for this session. */\n private _ifcFragmenterId?;\n /**\n * Resolves the platform IFC→FRAG cloud component's id by its stable name\n * (`IfcFragmenter`) within the current project, so it works across dev/prod\n * without a hardcoded id. Cached for the session. Returns `undefined` if no\n * such component is available in the project.\n */\n private _resolveIfcFragmenterId;\n private _triggerIfcConversions;\n uploadFiles(files: File[], folderId?: string | null, options?: {\n forceNew?: boolean;\n }): Promise<void>;\n sendMachineEvent(event: CDEMachineEvent): void;\n private _transition;\n private _getAllArchivedIds;\n private _collectTempDescendants;\n private _saveFolderChanges;\n private _moveFolder;\n moveFiles(files: CDEFile[], targetFolderId: string | null): Promise<void>;\n private _moveFiles;\n private _resolveFullName;\n private _prepareDownload;\n private _saveMetadataSchema;\n private _resolveKeys;\n private _saveFileMetadata;\n private _renameFileImmediate;\n private _saveFileEdits;\n private _applyMetadataEdits;\n private _applyMetadataSchemaEdits;\n private _saveMetadataViews;\n private _archiveFiles;\n}\n\nexport type CDEManager = InstanceType<typeof _CDEManager>;\nexport const CDEManager = { uuid: 'a3f82c1d-5b74-4e9a-bc30-d7e12f894a61' } as typeof _CDEManager & { uuid: 'a3f82c1d-5b74-4e9a-bc30-d7e12f894a61' };\n\nexport type ClashStatus = \"new\" | \"active\" | \"resolved\" | \"acknowledged\";\nexport type ClashType = \"hard\" | \"clearance\";\nexport interface ClashElement {\n guid: string;\n name: string;\n localId: number;\n modelId: string;\n}\nexport interface ClashQueryFilter {\n categories?: string[];\n attributes?: {\n aggregation?: 'exclusive' | 'inclusive';\n queries: Array<{\n name: string;\n value?: string | string[] | number | boolean;\n type?: string;\n negate?: boolean;\n }>;\n };\n relation?: {\n name: string;\n query?: ClashQueryFilter;\n };\n}\nexport interface ClashQuery {\n id: string;\n name: string;\n modelFileIds: string[];\n /** Filter conditions. Omit or leave empty to match all elements with geometry. */\n query?: ClashQueryFilter;\n}\nexport interface ClashMatrix {\n id: string;\n name: string;\n /** Ordered list of query IDs — index order = priority (0 = most constrained). */\n queryIds: string[];\n /** Active cell job IDs (subset of upper-triangle pairs). */\n jobIds: string[];\n /** Active upper-triangle pair keys in the form \"queryAId:queryBId\". */\n activePairs: string[];\n /** Clash type applied to all jobs generated by this matrix. Defaults to 'hard'. */\n jobType?: ClashType;\n /** Clearance tolerance in metres. Only used when jobType is 'clearance'. */\n tolerance?: number;\n}\nexport interface ClashJob {\n id: string;\n name: string;\n type: ClashType;\n queryAId: string;\n queryBId: string;\n matrixId?: string;\n /** Clearance tolerance in metres. Only present when type is 'clearance'. */\n tolerance?: number;\n}\nexport interface ClashRun {\n id: string;\n jobId: string;\n date: string;\n clashCount: number;\n}\ninterface ClashBase {\n /** Deterministic FNV-1a hash of the normalized pair (elementA.guid, elementB.guid). Stable across runs. */\n id: string;\n jobId: string;\n firstSeenRunId: string;\n lastSeenRunId: string;\n elementA: ClashElement;\n elementB: ClashElement;\n point: [number, number, number];\n status: ClashStatus;\n comments?: string;\n}\nexport interface HardClash extends ClashBase {\n type: \"hard\";\n volume?: number;\n}\nexport interface ClearanceClash extends ClashBase {\n type: \"clearance\";\n distance: number;\n}\nexport type Clash = HardClash | ClearanceClash;\nexport interface MarkerGroup {\n id?: string;\n point: [number, number, number];\n count: number;\n status?: ClashStatus;\n}\n\n/** `clashes.frag`'s path relative to `__project_data/`, for consumers that\n * persist it via `projectStorageContext` instead of talking to `client`\n * directly (see `buildClashBuffer`). */\nexport declare const CLASH_DATA_PATH = \"collider/clashes.frag\";\nexport interface ExecutionEntry {\n jobId: string;\n executionId: string;\n startedAt: string;\n}\n/** `cachedFileId`, when given, skips folder/file resolution (3 of the 4\n * network round-trips this normally takes) — the file's ID never changes\n * once created, so callers that already know it (see `ClashesManager`'s\n * `_clashFragFileId`) should always pass it. */\nexport declare function ensureClashFragFileId(client: PlatformClient, projectId: string, cachedFileId?: string): Promise<string>;\nexport declare function getExecutions(client: PlatformClient, projectId: string | undefined): Promise<ExecutionEntry[]>;\nexport interface ClashData {\n jobs: ClashJob[];\n runs: ClashRun[];\n clashes: Clash[];\n queries: ClashQuery[];\n matrices: ClashMatrix[];\n /** Resolved once here — callers should cache and pass back into\n * `loadClashData`/`buildClashBuffer` as `cachedFileId` to skip\n * re-resolving it (see `ensureClashFragFileId`). */\n fileId: string;\n}\nexport declare function loadClashData(client: PlatformClient, projectId: string, cachedFileId?: string): Promise<ClashData>;\n/**\n * Diffs `data` against the persisted `clashes.frag` and builds the updated\n * buffer, WITHOUT uploading it — callers decide how/where to persist the\n * result (direct `client.updateFile`, via `projectStorageContext`, etc).\n * Still reads the current file via `client` to diff against (job/id\n * reconciliation needs the previous state), same as `saveClashData` always did.\n */\nexport declare function buildClashBuffer(client: PlatformClient, projectId: string, data: {\n queries: ClashQuery[];\n matrices: ClashMatrix[];\n jobs: ClashJob[];\n clashes: Clash[];\n}, onJobsReconciled: (toAdd: ClashJob[], toRemove: Set<string>) => void, cachedFileId?: string): Promise<{\n blob: Blob;\n fileId: string;\n}>;\n/** Default persistence path: builds the buffer and uploads it straight to\n * `client`. Kept as the manager's out-of-the-box behavior for any consumer\n * that never overrides `ClashesManager.save` (e.g. doesn't route through\n * `projectStorageContext`). */\nexport declare function saveClashData(client: PlatformClient, projectId: string, data: {\n queries: ClashQuery[];\n matrices: ClashMatrix[];\n jobs: ClashJob[];\n clashes: Clash[];\n}, onJobsReconciled: (toAdd: ClashJob[], toRemove: Set<string>) => void): Promise<void>;\n\n\ndeclare class _ClashesManager extends OBC.Component {\n static readonly uuid: \"2c9f4e8d-3a1b-4c5e-9d7f-0a2b6c8e1d3f\";\n enabled: boolean;\n readonly onQueriesChanged: OBC.Event<ClashQuery[]>;\n readonly onMatricesChanged: OBC.Event<ClashMatrix[]>;\n readonly onJobsChanged: OBC.Event<ClashJob[]>;\n readonly onRunsChanged: OBC.Event<ClashRun[]>;\n readonly onClashesChanged: OBC.Event<Clash[]>;\n readonly onClashStatusChanged: OBC.Event<Clash[]>;\n /** Dispara cuando empieza el debounce de guardado (pendiente de persistir). */\n readonly onSaveStart: OBC.Event<void>;\n /** Dispara al terminar el guardado. true = éxito, false = error. */\n readonly onSaveComplete: OBC.Event<boolean>;\n world?: OBC.World;\n /** Suprimir auto-save durante carga de datos (usar loadingData = true antes, false después). */\n loadingData: boolean;\n /** Registrar desde la app host para recargar datos desde el storage al terminar una ejecución. */\n reload?: () => Promise<void>;\n /** Registrar desde la app host para consultar qué jobIds tienen ejecución activa en storage. */\n checkExecutions?: () => Promise<Set<string>>;\n /** Registrar desde la app host para persistir queries y matrices al storage del proyecto. */\n save?: () => Promise<void>;\n /** Jobs con una ejecución cloud activa. Poblado por la app host al arrancar. */\n readonly runningJobIds: Set<string>;\n /** Mapa jobId → executionId para reconectar al WebSocket. Poblado por la app host al arrancar. */\n readonly activeExecutions: Map<string, string>;\n readonly onRunningJobsChanged: OBC.Event<Set<string>>;\n readonly onRunProgress: OBC.Event<{\n message: string;\n progress: number;\n }>;\n readonly onRunComplete: OBC.Event<{\n runId: string;\n clashCount: number;\n }>;\n readonly onRunError: OBC.Event<{\n code?: string;\n message: string;\n }>;\n readonly onReloadingChanged: OBC.Event<boolean>;\n isReloading: boolean;\n /** True once init(client) has been called — safe to call run(). */\n get ready(): boolean;\n private _client?;\n private _projectId?;\n /** `clashes.frag`'s file ID, resolved once by `init()`/`reload()`'s\n * `loadClashData` call. Never changes once the file exists — passing it\n * into `buildClashBuffer` skips 3 of its 4 network round-trips. */\n private _clashFragFileId?;\n private _reconnectingJobIds;\n private _queries;\n private _matrices;\n private _saveTimer?;\n private _savePromise?;\n private _jobs;\n private _runs;\n private _clashes;\n private _markers;\n private static _geo;\n get queries(): ClashQuery[];\n set queries(value: ClashQuery[]);\n get matrices(): ClashMatrix[];\n set matrices(value: ClashMatrix[]);\n private _scheduleSave;\n /** Chains onto any save already in flight instead of firing a second,\n * concurrent `_doSave()` — two overlapping calls would race on\n * `buildClashBuffer`'s read-diff-reconcile cycle (real network I/O;\n * `onJobsReconciled` mutating `this.jobs` from two stale reads at once)\n * and on the upload itself. It also keeps `flush()` correct: it just\n * awaits `_savePromise`, so if that got overwritten by a newer, unrelated\n * save instead of chained, flush() could resolve while an earlier save\n * was still genuinely in flight. */\n private _queueSave;\n private _doSave;\n /** Cancela el debounce pendiente y ejecuta el save inmediatamente. Espera a que complete. */\n flush(): Promise<void>;\n /**\n * Builds the current `clashes.frag` buffer (diffed/reconciled against what's\n * persisted) WITHOUT uploading it. For consumers (e.g. `clashes-panel`) that\n * override `save` to persist via `projectStorageContext` instead of the\n * default direct-`client` path.\n */\n buildClashBuffer(): Promise<Blob>;\n get jobs(): ClashJob[];\n set jobs(value: ClashJob[]);\n get runs(): ClashRun[];\n set runs(value: ClashRun[]);\n get clashes(): Clash[];\n set clashes(value: Clash[]);\n queryById(id: string): ClashQuery | undefined;\n private _clashStylesRegistered;\n /** Green — elementA's highlight color. Public so consumers (e.g. \"create\n * topic from clash\") can build a matching BCF viewpoint `componentColors`\n * entry without duplicating the hex value. */\n readonly STYLE_A = \"#22c55e\";\n /** Red — elementB's highlight color. Same reasoning as `STYLE_A`. */\n readonly STYLE_B = \"#ef4444\";\n private _clashStyle;\n highlightAllClashes(clashes: Clash[]): void;\n ghostClashes(clashes: Clash[]): Promise<void>;\n ghostClash(clash: Clash): Promise<void>;\n clearGhostClash(): Promise<void>;\n highlightClash(clash: Clash): void;\n clearClashHighlight(): void;\n showMarkers(groups: MarkerGroup[]): void;\n hideMarkers(): void;\n toViewerPoint(point: [number, number, number]): THREE.Vector3;\n private _toViewer;\n private _renderMarkers;\n private _clearMarkers;\n cluster(clashes: Clash[], threshold: number): Clash[][];\n private _setHighlighterEnabled;\n private _isolatedMaterials;\n runsForJob(jobId: string): ClashRun[];\n clashesForRun(runId: string): Clash[];\n updateClash(id: string, changes: {\n status?: ClashStatus;\n comments?: string;\n }): void;\n /**\n * Initializes the manager from cloud storage: loads clash data, wires save/reload,\n * reads in-flight executions, and resolves the viewer world (non-blocking).\n * Consumer apps call this once instead of wiring all the pieces manually.\n */\n init(client: PlatformClient): Promise<void>;\n /** Launches clash detection in a Web Worker. Fires onRunProgress/onRunComplete/onRunError. */\n run(jobId: string): void;\n private _handleWorkerComplete;\n /** Reconnects to an in-flight execution when the user opens a job that was running before page load. */\n reconnectIfRunning(jobId: string): void;\n private _listenToExecution;\n private _firstWorld;\n}\n\nexport type ClashesManager = InstanceType<typeof _ClashesManager>;\nexport const ClashesManager = { uuid: '2c9f4e8d-3a1b-4c5e-9d7f-0a2b6c8e1d3f' } as typeof _ClashesManager & { uuid: '2c9f4e8d-3a1b-4c5e-9d7f-0a2b6c8e1d3f' };\n\n/**\n * Which action buttons to expose per file row. All default to `true`.\n */\nexport interface FileListActions {\n download?: boolean;\n rename?: boolean;\n delete?: boolean;\n}\n/**\n * Config passed to {@link FileList.create}.\n */\nexport interface FileListConfig {\n /** Services client used to list and mutate files. */\n client: EngineServicesClient;\n /** Optional folder ID to scope the list. If omitted, lists root files. */\n folderId?: string;\n /** Which action buttons to show per row. Defaults to all enabled. */\n actions?: FileListActions;\n /** Called when a file row is clicked (not an action button). */\n onFileClick?: (file: Item) => void;\n}\n/**\n * The result returned by {@link FileList.create}.\n */\nexport interface FileListInstance {\n /** The DOM element to mount somewhere in your layout. */\n element: HTMLElement;\n /** Reloads the list from the services client. */\n refresh: () => Promise<void>;\n /** Changes the folder scope and reloads. Pass `undefined` for the root. */\n setFolder: (folderId?: string) => Promise<void>;\n /** Removes the element and forgets the instance. */\n dispose: () => void;\n}\n\n/**\n * Built-in component that renders a file list backed by the services client,\n * with built-in download / rename / delete actions.\n *\n * The backing data comes from {@link EngineServicesClient.listFiles}, so the\n * list stays in sync with the storage service. Each call to {@link create}\n * returns an independent instance with its own DOM element.\n *\n * @example\n * ```ts\n * const fileList = components.get(FileList);\n * const { element, refresh } = fileList.create({\n * client: app.client,\n * folderId: someFolderId,\n * });\n * container.appendChild(element);\n * ```\n */\ndeclare class _FileList extends OBC.Component {\n static readonly uuid: \"b0b5e2a2-0b3a-4a6b-8b1c-0b1c4a6b8b1c\";\n enabled: boolean;\n readonly name = \"FileList\";\n private _instances;\n /**\n * Creates a new file-list instance. Returns the DOM element to mount plus a\n * `refresh` handle to reload the list, a `setFolder` to change scope, and a\n * `dispose` to remove it.\n */\n create(config: FileListConfig): FileListInstance;\n /**\n * Removes every instance this manager has created.\n */\n dispose(): void;\n}\n\n/**\n * Built-in component that renders a file list backed by the services client,\n * with built-in download / rename / delete actions.\n *\n * The backing data comes from {@link EngineServicesClient.listFiles}, so the\n * list stays in sync with the storage service. Each call to {@link create}\n * returns an independent instance with its own DOM element.\n *\n * @example\n * ```ts\n * const fileList = components.get(FileList);\n * const { element, refresh } = fileList.create({\n * client: app.client,\n * folderId: someFolderId,\n * });\n * container.appendChild(element);\n * ```\n */\nexport type FileList = InstanceType<typeof _FileList>;\n/**\n * Built-in component that renders a file list backed by the services client,\n * with built-in download / rename / delete actions.\n *\n * The backing data comes from {@link EngineServicesClient.listFiles}, so the\n * list stays in sync with the storage service. Each call to {@link create}\n * returns an independent instance with its own DOM element.\n *\n * @example\n * ```ts\n * const fileList = components.get(FileList);\n * const { element, refresh } = fileList.create({\n * client: app.client,\n * folderId: someFolderId,\n * });\n * container.appendChild(element);\n * ```\n */\nexport const FileList = { uuid: 'b0b5e2a2-0b3a-4a6b-8b1c-0b1c4a6b8b1c' } as typeof _FileList & { uuid: 'b0b5e2a2-0b3a-4a6b-8b1c-0b1c4a6b8b1c' };\n\n/** A point-layer vertex whose Z gives the surface height at that place. */\nexport interface HeightNode {\n lon: number;\n lat: number;\n z: number;\n}\n/**\n * One orthometric height per vertex, in the same nesting as the geometry's\n * coordinates: `number` for a Point, `number[]` for a LineString/MultiPoint/\n * ring, `number[][]` for a MultiLineString/Polygon, and so on.\n */\nexport type HeightTree = number | HeightTree[];\n/**\n * Which rule gave a line end its height (see `resolveLineEnds`): 1 = its own\n * property, 2 = node surface height minus depth, 3 = copied from the other end\n * (pipe drawn level), 4 = node surface height (no depth available).\n */\nexport type EndRule = 1 | 2 | 3 | 4;\nexport interface FeatureHeights {\n /**\n * \"placed\": `heights` holds the per-vertex heights. \"flat\": draw this\n * feature with the legacy flat behaviour. \"skipped\": it cannot be placed\n * and must not be drawn.\n */\n status: \"placed\" | \"flat\" | \"skipped\";\n heights?: HeightTree;\n /** \"attributes\" lines only — the rule that resolved each end. */\n startRule?: EndRule;\n endRule?: EndRule;\n}\nexport interface LayerHeights {\n /** True when the whole layer must be drawn with the legacy flat behaviour. */\n fallback: boolean;\n /** One entry per input feature, same order. Empty when `fallback`. */\n features: FeatureHeights[];\n /** Number of \"skipped\" features. */\n skipped: number;\n /** How many line ends each rule resolved (\"attributes\" layers). */\n ruleCounts: Record<EndRule, number>;\n}\n/** A value read from a property or Z is MISSING when it is not a finite number or is exactly 0. */\nexport declare function isMissingHeight(value: unknown): boolean;\n/**\n * Horizontal distance in metres between two lon/lat pairs — equirectangular\n * approximation, plenty for the sub-metre comparisons and line-length weights\n * it is used for here.\n */\nexport declare function horizontalDistance(lon1: number, lat1: number, lon2: number, lat2: number): number;\n/**\n * Spatial hash over nodes: cells are twice the snap distance wide, so any node\n * within the snap distance of a query lies in the 3×3 block of cells around\n * it — a lookup costs the same at 2,000 nodes as at 50,000.\n */\nexport declare class NodeIndex {\n private readonly _snapDistance;\n private readonly _cells;\n private readonly _cellSize;\n private readonly _lonScale;\n constructor(nodes: HeightNode[], _snapDistance: number);\n private _cell;\n private _key;\n /** The nearest node within the snap distance of (lon, lat), or null. */\n nearest(lon: number, lat: number): HeightNode | null;\n}\n/**\n * Resolves the heights of a line's two ends (rules 1–4, see `EndRule`).\n * Both ends get rules 1–2 first, so rule 3 never copies a value that itself\n * came from rule 3/4. Returns null when an end ends up with no height at all.\n */\nexport declare function resolveLineEnds(properties: GeoJSON.GeoJsonProperties, start: [number, number], end: [number, number], config: VectorLayerHeightConfig, index: NodeIndex | null): {\n start: number;\n end: number;\n startRule: EndRule;\n endRule: EndRule;\n} | null;\n/**\n * Resolves the orthometric height of every vertex of every feature in a\n * layer, following the rules documented on `VectorLayerHeightConfig` (\"geometry\"\n * and \"attributes\"). Emits at most ONE `console.warn` per call (the fallback,\n * or the skipped-feature summary), never one per vertex/feature.\n */\nexport declare function resolveLayerHeights(features: GeoJSON.Feature[], config: VectorLayerHeightConfig, nodes?: HeightNode[], layerId?: string): LayerHeights;\n\n/**\n * Pixels either side of a fat line's own stroke (`Line2`) that still count as\n * a hit — the strokes are only a couple of pixels wide, so without it a click\n * has to land on the exact pixel row of the line. three adds\n * `raycaster.params.Line2.threshold` to the material's full `linewidth` and\n * then tests against HALF of the sum, hence the doubling in\n * `pickVectorFeature()`.\n */\nexport declare const VECTOR_PICK_TOLERANCE_PX = 6;\n/** What a pick found: which feature of which layer, and where along the ray. */\nexport interface VectorPickHit {\n layerId: string;\n /** Index in the layer's `geojson.features`. */\n featureIndex: number;\n /** Distance from the ray origin (the camera, for a perspective camera). */\n distance: number;\n point: THREE.Vector3;\n}\n/**\n * Nearest vector-layer feature under a pointer, or null.\n *\n * `objects` are the roots `VectorLayers` built (each, or one of its\n * descendants, carries `userData.{layerId, featureIndex}`) — raycast directly\n * rather than through a scene, since they may live in the world's scene or in\n * the private deferred-mode one. `ndc` is the pointer in normalised device\n * coordinates; `size` is the renderer's pixel size, which fat lines need both\n * to set their `LineMaterial.resolution` and to turn\n * {@link VECTOR_PICK_TOLERANCE_PX} into world units.\n */\nexport declare function pickVectorFeature(objects: THREE.Object3D[], camera: THREE.Camera, ndc: THREE.Vector2, size: THREE.Vector2): VectorPickHit | null;\n\n/**\n * Per-layer style — `simplestyle-spec` property names, see\n * docs/adrs/vector-layer-style-property-naming.md for why. Layer-level only\n * (applies to every feature in the layer), not per-feature.\n */\nexport interface VectorLayerStyle {\n stroke?: string;\n \"stroke-width\"?: number;\n fill?: string;\n \"fill-opacity\"?: number;\n}\n/** Per-layer placement options (not styling). */\nexport interface VectorLayerOptions {\n /**\n * Height of every feature relative to the origin, in metres (negative =\n * below ground, e.g. buried utilities). Default 0.\n */\n elevation?: number;\n /**\n * Opt-in per-feature heights (see `VectorLayerHeightConfig`). When set and\n * resolvable, each vertex is placed at its own height + the project's geoid\n * undulation instead of flat at `elevation`. Absent = legacy flat drawing.\n */\n height?: VectorLayerHeightConfig;\n /** \"attributes\" heights only — surface nodes (a line end snaps to the nearest one for its surface height). */\n nodes?: HeightNode[];\n}\n/**\n * One feature's geometry in scene coordinates, for 2D consumers (the\n * minimap). `rings` holds a single vertex for points, the vertices for\n * lines, and outer ring + holes for polygons (multi-geometries are split\n * into one feature per part).\n */\nexport interface VectorMapFeature {\n type: \"point\" | \"line\" | \"polygon\";\n rings: THREE.Vector3[][];\n /** Index in the layer's `geojson.features` — the same identity a 3D pick yields, shared by every part of a multi-geometry. */\n featureIndex: number;\n}\n/** A loaded layer as seen by 2D consumers. */\nexport interface VectorMapLayer {\n id: string;\n style: {\n stroke: string;\n strokeWidth: number;\n fill?: string;\n fillOpacity: number;\n };\n features: VectorMapFeature[];\n}\nexport declare const VECTOR_HOVER_COLOR = \"#FFC107\";\nexport declare const VECTOR_SELECTION_COLOR = \"#00E5FF\";\n/**\n * Payload of `VectorLayers.onFeatureSelected`: the selected feature's identity\n * plus its attribute-table row. `properties` is the feature's own\n * `properties` object, untouched (keys keep whatever the source file has).\n */\nexport interface VectorFeatureSelection {\n layerId: string;\n layerName: string;\n /** Index in the layer's `geojson.features`. */\n featureIndex: number;\n geometryType: string;\n properties: GeoJSON.GeoJsonProperties;\n}\n/**\n * Internal submodule of `GISManager` for vector GIS layers (shapefile/GeoJSON —\n * shapefiles are converted to GeoJSON at ingestion time, see docs/adrs). Kept as\n * a plain internal class rather than a separate `OBC.Component`: `GISManager`\n * already covers \"everything GIS\", not just the basemap, so this stays behind\n * `gisManager.vectorLayers` instead of its own public component with its own\n * `components.get(...)` entry point.\n *\n * Positions features using the same georeferencing math `ReorientationPlugin`\n * uses to align the 3D Tiles (`Ellipsoid.getObjectFrame()`, WGS84 lat/lon/\n * height/azimuth -> a rigid ECEF<->scene-local transform), computed directly\n * from `GISManager`'s own origin params rather than read off the tileset's\n * `matrixWorld` — see `geoToWorld()` for why: that transform is a pure\n * function of the 4 origin parameters (confirmed by reading\n * `ReorientationPlugin.transformLatLonHeightToOrigin`, which touches nothing\n * tileset-specific besides which `group`/`ellipsoid` object to write into),\n * so vector layers don't need to wait for a tileset to exist or load, and\n * stay correct even when `GISManager.snapToGround()` changes the origin's\n * height independently of any tileset event.\n */\nexport declare class VectorLayers {\n world?: OBC.World;\n getOrigin?: () => {\n latitude: number;\n longitude: number;\n height: number;\n rotation: number;\n };\n getGeoidUndulation?: () => number;\n private static readonly _POINT_RADIUS;\n private _occlusionScene;\n /** Called once the deferred scene exists, so the owner registers its pass. */\n ensurePass?: () => void;\n /** Fires whenever layers are added, removed or rebuilt (e.g. origin change). */\n readonly onLayersChanged: OBC.Event<void>;\n /**\n * Fires with the newly selected feature, or null when the selection is\n * cleared. Not fired when the already-selected feature is selected again.\n */\n readonly onFeatureSelected: OBC.Event<VectorFeatureSelection | null>;\n getLayerName?: (id: string) => string | undefined;\n private _selected;\n private _hovered;\n private readonly _highlighted;\n private readonly _layers;\n private readonly _mapLayers;\n /** Loaded layers' geometry for 2D consumers (see `VectorMapFeature`). */\n get mapLayers(): VectorMapLayer[];\n private readonly _layerSources;\n get hasLayers(): boolean;\n /**\n * Draws every loaded layer into the renderer's current target, with fat\n * lines sized for a `width`×`height` pixel target (their width is in\n * pixels of it). Used by `GISManager`'s deferred pass; also works in\n * composer mode (objects drawn one by one). The minimap doesn't use this —\n * it draws `mapLayers` as live 2D vectors instead.\n */\n render(renderer: THREE.WebGLRenderer, camera: THREE.Camera, width: number, height: number): void;\n /**\n * @param id When given, tracks everything this call adds under that id so\n * `removeLayer(id)` can clean it up later — calling `addLayer` again with an\n * id already in use replaces it (removes the old one first), rather than\n * duplicating it. Without an id, nothing is tracked and there is nothing to\n * remove later (matches the previous, untracked behaviour).\n */\n addLayer(geojson: GeoJSON.FeatureCollection, style?: VectorLayerStyle, id?: string, options?: VectorLayerOptions): void;\n /** Removes and disposes everything the given `id`'s `addLayer()` call added. No-op if unknown/already removed. */\n removeLayer(id: string): void;\n private _dropLayer;\n /**\n * Nearest feature under a pointer (NDC), or null — see\n * `pickVectorFeature()`. Costs nothing when no layer is loaded.\n */\n pickFeature(ndc: THREE.Vector2): VectorPickHit | null;\n /** Selects (and highlights) one feature, replacing any previous selection. No event if it is already the selected one. */\n selectFeature(layerId: string, featureIndex: number): void;\n /** The current selection as the `onFeatureSelected` payload (null when nothing is selected) — for consumers created after the event fired. */\n get selection(): VectorFeatureSelection | null;\n /** Drops the selection and its highlight. No-op (no event) when nothing is selected. */\n clearSelection(): void;\n /** The currently selected / hovered feature (null = none) — read by the 2D map to draw the same states as 3D. */\n get selectedFeature(): {\n layerId: string;\n featureIndex: number;\n } | null;\n get hoveredFeature(): {\n layerId: string;\n featureIndex: number;\n } | null;\n /** Scene-space box of everything built for one feature (null if it isn't loaded), at its real resolved heights. */\n getFeatureBounds(layerId: string, featureIndex: number): THREE.Box3 | null;\n /** Hover-highlights one feature (null = none). Does not touch the selection and fires no event. */\n setHoveredFeature(hit: {\n layerId: string;\n featureIndex: number;\n } | null): void;\n /** Top-level objects built for one feature (empty if the layer/feature isn't loaded). */\n private _featureObjects;\n private _paint;\n isLayerLoaded(id: string): boolean;\n /**\n * Rebuilds every currently loaded layer's geometry from its cached\n * geojson/style, using the current `getOrigin()` — the fix for\n * loaded-layer-geometry-freezing-at-load-time: `addLayer()` only reads\n * `getOrigin()` once, at build time, so an origin change (gizmo drag,\n * lat/lon/height/rotation inputs, `snapToGround()`) otherwise never moves\n * already-loaded layers. Callers should debounce this — see\n * `GISManager.setPosition()` — since it rebuilds real geometry, not just\n * repositions existing objects.\n */\n reprojectAll(): void;\n /** Scene-space bounding box of everything `id`'s `addLayer()` call added — `null` if the id is unknown or nothing was actually added. */\n getLayerBounds(id: string): THREE.Box3 | null;\n private _disposeObject;\n private _resolveTargetScene;\n /**\n * WGS84 lat/lon/height (degrees, metres above the ellipsoid) -> scene-local\n * position, computed straight from `GISManager`'s origin params — the exact\n * same math `ReorientationPlugin.transformLatLonHeightToOrigin` runs against\n * `tiles.group.matrix` (`Ellipsoid.getObjectFrame()` for the origin's own\n * lat/lon/height/azimuth -> ECEF<->local transform, inverted), just without\n * needing a `TilesRenderer` to hold the intermediate result. No tileset\n * required, and always current — including immediately after\n * `GISManager.snapToGround()` changes the origin height, with nothing to\n * resync.\n */\n geoToWorld(lat: number, lon: number, height?: number): THREE.Vector3;\n /**\n * lon/lat (GeoJSON coordinate order) -> scene position, X/Z only — Y is the\n * layer's `elevation` (relative to the origin). This is the legacy flat\n * path, used by every layer that doesn't opt in to per-feature heights:\n * `geoToWorld`'s real Y depends on the gap between the origin's height and\n * each vertex's own height, which produced large, confusing vertical\n * offsets for raw file Z values — so for these layers per-vertex heights\n * are ignored and the whole layer sits flat at its `elevation`. Layers with\n * a `height` config go through `_toScenePosition()` instead.\n */\n private _toSceneVector;\n /**\n * One vertex's scene position: with a resolved orthometric `height`, the\n * full `geoToWorld()` result for `height + undulation` (all three\n * components, Y included); without one, the legacy flat `_toSceneVector()`.\n */\n private _toScenePosition;\n /** Renderer's current pixel size — `LineMaterial` needs it to size `linewidth` correctly. */\n private _resolution;\n private _buildFeatureObject;\n private _buildMapFeatures;\n private _buildPoint;\n private _buildLine;\n /**\n * Surface (`THREE.ShapeGeometry`, triangulated — handles non-convex rings)\n * when `fill` is set, plus the outline for every ring either way. Built in\n * local 2D (x, z) then rotated flat: `ShapeGeometry` lives in the XY plane,\n * and rotating +90° around X maps local (x, y, 0) -> scene (x, 0, y), which\n * lines up with `_toSceneVector`'s (x, 0, z) exactly; the layer's\n * `elevation` is re-applied afterwards as a plain vertical translation.\n * With per-vertex `heights` the outlines follow them, while the (planar)\n * surface sits at the average resolved height of the outer ring.\n */\n private _buildPolygonSurface;\n}\n\nexport interface GISManagerState {\n apiToken: string;\n assetId: string;\n latitude: number;\n longitude: number;\n height: number;\n rotation: number;\n tilesVisible: boolean;\n gizmoVisible: boolean;\n tilesOffsetEast: number;\n tilesOffsetNorth: number;\n tilesOffsetUp: number;\n /** See-through factor for the tiles (1 = opaque) — see `GISManager.setTilesOpacity`. */\n tilesOpacity: number;\n}\n/** One entry in the persisted vector-layer manifest — metadata only, not the geometry itself. */\nexport interface GISVectorLayerConfig {\n id: string;\n name: string;\n fileId: string;\n /**\n * File format: `\"shapefile\"` (a zip with .shp/.dbf/.prj…) or `\"geojson\"`. When\n * missing or unrecognised the downloaded bytes decide (zip signature →\n * shapefile, leading `{` → GeoJSON).\n */\n type: string;\n style: VectorLayerStyle;\n /** Opt-in per-feature heights (see `VectorLayerHeightConfig`); absent = flat. */\n height?: VectorLayerHeightConfig;\n}\n/** How a layer's features get their height. Absent = legacy behaviour: the whole layer is drawn flat. */\nexport interface VectorLayerHeightConfig {\n /**\n * \"geometry\": each vertex uses its own Z (third GeoJSON coordinate).\n * \"attributes\": lines get their start/end heights from feature properties.\n */\n source: \"geometry\" | \"attributes\";\n /** \"attributes\" only — property holding the height of a line's first vertex. */\n startProperty?: string;\n /** \"attributes\" only — property holding the height of a line's last vertex. */\n endProperty?: string;\n /** \"attributes\" only — property holding the depth below the surface at the first vertex. */\n startDepthProperty?: string;\n /** \"attributes\" only — property holding the depth below the surface at the last vertex. */\n endDepthProperty?: string;\n /** \"attributes\" only — ids of point layers (in this same manifest) whose Z gives the surface height at a line end. */\n nodeLayers?: string[];\n /** \"attributes\" only — max horizontal distance (m) between a line end and a node for them to count as the same place. Default 0.5. */\n nodeSnapDistance?: number;\n}\n/**\n * Shape of `{GISManager.uuid}.json`, the project-storage file\n * `GISManager.init()` reads. Origin lives in `ProjectManager`'s own record\n * instead (the platform's canonical project data) — this file is only the\n * vector-layer manifest.\n */\nexport interface GISPersistedConfig {\n layers: GISVectorLayerConfig[];\n /** Small local East/North/Up fine-tune offset (metres) for Google 3D\n * Tiles — see `GISManager.setTilesOffset`'s own doc comment. Optional:\n * absent means \"no offset saved yet\", same as `{0,0,0}`. */\n tilesOffset?: {\n east: number;\n north: number;\n up: number;\n };\n}\n\n/** Calls `visit` with every [lon, lat, …] vertex of a GeoJSON geometry (all supported types, collections included). */\nexport declare function forEachVertex(geometry: GeoJSON.Geometry | null, visit: (coord: number[]) => void): void;\n/**\n * Horizontal (scene X/Z) bounding box of every vertex of every given feature\n * collection, each vertex taken through `project(lat, lon)` (the real\n * `geoToWorld`). Heights are irrelevant here and left at 0. Vertices with\n * non-finite coordinates are ignored; null when nothing usable is left.\n */\nexport declare function layersBoundsXZ(collections: GeoJSON.FeatureCollection[], project: (lat: number, lon: number) => THREE.Vector3): THREE.Box3 | null;\n/** The square, in scene X/Z, that a minimap capture covers. */\nexport interface MinimapExtent {\n centerX: number;\n centerZ: number;\n /** Half the side of the square, in metres. */\n half: number;\n}\n/**\n * Extra room around the content's extent, as a FRACTION of its half-size (not\n * metres), so the outermost features don't sit exactly on the image edge.\n */\nexport declare const MINIMAP_EXTENT_MARGIN = 0.05;\n/**\n * The capture square for the vector layers' box (world space): centred on its\n * X/Z centre, with half the larger X/Z span as its half-size (the image stays\n * square), plus `margin`. With nothing usable — no box, an empty or non-finite\n * one, or content with no horizontal size at all — falls back to\n * `fallbackHalf` metres around the origin.\n */\nexport declare function computeMinimapExtent(box: THREE.Box3 | null | undefined, fallbackHalf: number, margin?: number): MinimapExtent;\n\n/**\n * What to do when the Highlighter's \"select\" style highlights something:\n * - \"undo-bim\": the highlight belongs to a click that a vector feature just\n * won (it fires inside that click's short window) — take the BIM highlight\n * back and keep the vector selection;\n * - \"clear-vector\": a genuine BIM selection (viewer, model tree, objects\n * panel, …) — the vector selection must go;\n * - \"none\": nothing to do (an empty highlight outside the window).\n */\nexport type BimHighlightAction = \"undo-bim\" | \"clear-vector\" | \"none\";\nexport declare function bimHighlightAction(insideVectorWinWindow: boolean, bimSelectionEmpty: boolean): BimHighlightAction;\n/** Whether a Highlighter selection map (`modelId → Set<localId>`) selects nothing. */\nexport declare function isModelIdMapEmpty(map: Record<string, Set<number>> | null | undefined): boolean;\n\n/**\n * What the minimap needs from `GISManager`, provided as a private hook object\n * (the minimap never reaches into `GISManager` itself).\n */\nexport interface MinimapSource {\n /**\n * Gets the Google GIS tiles ready to be drawn from `camera` (registers it\n * with the streaming renderer and waits until the content it sees has\n * loaded).\n */\n prepare(camera: THREE.OrthographicCamera, resolution: number): Promise<void>;\n /** Draws the tiles into the renderer's CURRENT render target (a fresh, transparent one). */\n draw(renderer: THREE.WebGLRenderer, camera: THREE.OrthographicCamera): void;\n /** Undoes whatever `prepare` set up. Always called, even if `prepare` threw. */\n cleanup(camera: THREE.OrthographicCamera): void;\n /**\n * Live opacity (0..1) the map applies when drawing the captured image — read\n * on every redraw, so it can change without recapturing.\n */\n opacity(): number;\n /** Horizontal world box of ALL the project's vector layers (null when there is none). */\n getVectorLayersBox(): Promise<THREE.Box3 | null>;\n}\n/**\n * Result of a capture: the image plus what's needed to map world ↔ image.\n */\nexport interface MinimapCapture {\n /** Top-down, north-up image of the GIS tiles (canvas pixels, sRGB, transparent elsewhere). */\n image: HTMLCanvasElement;\n /** Live opacity (0..1) to draw `image` with. */\n opacity: () => number;\n /** Side of the image, in pixels. */\n size: number;\n /** Copy of the camera the image was taken with, for world ↔ map conversion. */\n camera: THREE.OrthographicCamera;\n}\n/**\n * A marker drawn over the minimap (an HTML overlay on the panel's canvas,\n * following zoom and pan; hidden while there is no capture).\n */\nexport interface MinimapMarker {\n id: string;\n /** Scene coordinates. Read on every redraw, so a marker follows if this changes. */\n position: THREE.Vector3;\n label?: string;\n /**\n * Builds the marker's element. A FACTORY, not an element: a panel can be\n * destroyed and recreated (the user switching layouts), and each one needs\n * its own DOM node. A marker with one owns its click behaviour; without it\n * the panel draws a default badge with the label and reports clicks through\n * `onMarkerClicked`.\n */\n createElement?: () => HTMLElement;\n}\n/** What changed in the marker list — the panel just reconciles against `markers`. */\nexport interface MinimapMarkersChange {\n kind: \"added\" | \"updated\" | \"removed\" | \"cleared\";\n /** The marker's id (absent for \"cleared\"). */\n id?: string;\n}\n/**\n * Internal submodule of `GISManager` for the 2D minimap, same pattern as\n * `VectorLayers` (a plain internal class behind `gisManager.minimap`, not its\n * own component). Baked top-down image: renders the Google GIS tiles once,\n * from an orthographic camera looking straight down at the middle of the\n * project's vector layers, into an in-memory image (never persisted). The UI\n * (`<top-map-panel>`) draws live overlays (vector layers, camera arrow, view\n * cone) on top of that static image, game-minimap style.\n *\n * North-up: scene axes follow the codebase's +X=West, +Y=Up, +Z=North\n * convention (origin rotation fixed at 0), so the camera's \"up\" is +Z. The\n * world ↔ map conversions go through the capture camera's own projection, so\n * they stay correct without hardcoding that convention anywhere else.\n */\nexport declare class Minimap {\n private readonly _source;\n world?: OBC.World;\n /**\n * Fallback only: half the side of the captured square, in metres, centred on\n * the origin — used when the project has no usable vector layers. Otherwise\n * the area is the box of all of them.\n */\n halfExtent: number;\n /**\n * Side of the captured image, in pixels (clamped to the GPU's max texture\n * size). Fixed, so the map gets coarser as the site gets larger: the image\n * covers the whole data-driven extent. Scaling the image with the extent was\n * tried and was too slow to capture. The intended improvement is to recapture\n * only the visible area when the user zooms in on the map, so sharpness no\n * longer depends on the size of the site.\n */\n resolution: number;\n readonly onCaptured: OBC.Event<MinimapCapture>;\n /** Fires once per `addMarker` / `updateMarker` / `removeMarker` / `clearMarkers` that changed something. */\n readonly onMarkersChanged: OBC.Event<MinimapMarkersChange>;\n /** Fires with the id when the panel's DEFAULT marker (one without `createElement`) is clicked. */\n readonly onMarkerClicked: OBC.Event<string>;\n private readonly _markers;\n private _capture;\n private _capturing;\n constructor(_source: MinimapSource);\n get capture(): MinimapCapture | null;\n get capturing(): boolean;\n /** Every marker, by id (read-only). */\n get markers(): ReadonlyMap<string, MinimapMarker>;\n getMarker(id: string): MinimapMarker | undefined;\n /** Adds a marker, or replaces the one with the same id. */\n addMarker(marker: MinimapMarker): void;\n /** Changes some fields of a marker. Returns false (and fires nothing) if there is no such marker. */\n updateMarker(id: string, partial: Partial<Omit<MinimapMarker, \"id\">>): boolean;\n /** Returns false (and fires nothing) if there is no such marker. */\n removeMarker(id: string): boolean;\n clearMarkers(): void;\n /**\n * The area the next capture covers: the box of all the project's vector\n * layers (waits for them to be read as data), or `halfExtent` around the\n * origin without any.\n */\n getExtent(): Promise<MinimapExtent>;\n /** Renders the GIS tiles into a fresh image. */\n captureMap(): Promise<MinimapCapture>;\n /** World point → normalized image coords (0..1, origin top-left), or null without a capture. */\n worldToMap(point: THREE.Vector3): {\n x: number;\n y: number;\n } | null;\n /** Normalized image coords → world point on the horizontal plane at `height`. */\n mapToWorld(x: number, y: number, height?: number): THREE.Vector3 | null;\n private _render;\n dispose(): void;\n}\n\n/** The file formats a vector layer can come in (the manifest entry's `type`). */\nexport type VectorLayerFormat = \"shapefile\" | \"geojson\";\n/**\n * Which parser a downloaded layer file needs. The manifest's `type` decides\n * when it is recognised; otherwise the bytes do: a zip signature (`PK\\x03\\x04`)\n * means a shapefile, a first non-whitespace `{` means GeoJSON. Anything else\n * throws, with a message meant for the user.\n */\nexport declare function detectLayerFormat(type: string | undefined, bytes: Uint8Array): VectorLayerFormat;\ntype CrsKind = {\n kind: \"lonlat\";\n} | {\n kind: \"reproject\";\n from: string;\n} | {\n kind: \"unsupported\";\n name: string;\n};\n/**\n * Reads the legacy GeoJSON `crs` member's name. Understands the CRS84 URN,\n * EPSG URNs (with or without a version), `EPSG:<code>` and the OpenGIS http\n * form. EPSG:4326 is taken as lon/lat as-is: GDAL/QGIS write lon/lat even when\n * they label it 4326. Reprojected: EPSG:3857 and the UTM families (326xx/327xx\n * WGS84, 258xx ETRS89, 269xx NAD83), their definition built from the code.\n */\nexport declare function parseCrsName(name: string): CrsKind;\n/**\n * Parses GeoJSON text into a `FeatureCollection` in WGS84 lon/lat (`z` kept).\n * The coordinate system comes from the legacy `crs` member; without one the\n * coordinates must already be lon/lat, which is checked. Throws a clear error\n * for an unsupported CRS, or projected coordinates that don't say which CRS\n * they are in. The legacy `crs` member is dropped from the result.\n */\nexport declare function parseGeoJSONLayer(text: string): Promise<GeoJSON.FeatureCollection>;\n\n/**\n * Streams Cesium Ion 3D Tiles (Google Photorealistic 3D Tiles by default) co-located\n * with the BIM model.\n *\n * Rendering path depends on `world.renderer.postproduction.mode`:\n * - DEFERRED: the deferred G-buffer capture pass only draws objects whose material\n * carries the engine's \"capture-emission\" marker (set on Fragments/BIM surface\n * materials only) — every other object, however opaque, is hidden for the\n * duration of the capture (confirmed directly from the engine's own\n * `SurfaceCapturePass` docs). So tiles are added to a private off-scene\n * `THREE.Scene` and drawn via `addOcclusionPass` (direct mode — opaque,\n * self-occluding, same as `PointCloudLoader`), which runs AFTER the deferred\n * composite and bypasses the G-buffer requirement entirely.\n * - COMPOSER: the EffectComposer path renders the real scene graph directly, no\n * special material marker needed, so tiles are added straight to\n * `world.scene.three` like any other mesh.\n *\n * The Cesium Ion API token is kept in memory only (no persistence yet) — see\n * docs/adrs for the pending decision on where project geo-location should live.\n */\ndeclare class _GISManager extends OBC.Component {\n static readonly uuid: \"d8f3a1c2-6b4e-4f9a-8c1d-2e7b5a9f3c60\";\n enabled: boolean;\n readonly onStateChanged: OBC.Event<GISManagerState>;\n readonly onLoadError: OBC.Event<string>;\n readonly onLayersLoaded: OBC.Event<GISVectorLayerConfig[]>;\n readonly onVectorLayerError: OBC.Event<{\n id: string;\n message: string;\n }>;\n readonly onOffsetDirtyChange: OBC.Event<boolean>;\n readonly onOffsetSaveComplete: OBC.Event<boolean>;\n world?: OBC.World;\n vectorLayersConfig: GISVectorLayerConfig[];\n private _client?;\n private _projectId?;\n private _appDataStore?;\n private _offsetDirty;\n get offsetDirty(): boolean;\n readonly vectorLayers: VectorLayers;\n /**\n * Fires when a click selects a vector feature (payload: its layer, index and\n * attribute row) and with null when the selection is cleared — re-exposed\n * from `vectorLayers` for consumers (the future properties panel).\n */\n readonly onFeatureSelected: OBC.Event<VectorFeatureSelection | null>;\n /**\n * Fires on every `selectVectorFeature(..., { focus: true })`, including a\n * re-select of the already-selected feature (which fires no\n * `onFeatureSelected`) — carries the scene-space sphere the 3D camera frames,\n * so other views (the 2D map) can focus the same neighbourhood.\n */\n readonly onFocusRequested: OBC.Event<{\n layerId: string;\n featureIndex: number;\n sphere: THREE.Sphere;\n }>;\n private _apiToken;\n private _assetId;\n private _latitude;\n private _longitude;\n private _height;\n private _rotation;\n private _tilesVisible;\n private _gizmoVisible;\n private _tilesOffsetEast;\n private _tilesOffsetNorth;\n private _tilesOffsetUp;\n private _tiles;\n private _reorientation;\n private _draco;\n private _occlusionScene;\n private _usingOcclusionPass;\n private _locationControls;\n private _controlPoint;\n private _dragStartMatrix;\n private _tilesOpacity;\n private _fadeTarget;\n private _fadeQuad;\n private _horizonTarget;\n private _horizonQuad;\n /**\n * Fraction (0–1) of the camera's far distance over which the 3D tiles dissolve\n * into what is behind them, instead of ending in a hard edge at the far plane:\n * the tiles are fully visible up to `far * (1 - horizonFade)` and fully\n * transparent at `far`. Default 0.8. `0` turns it off (opaque tiles are drawn\n * straight into the frame at opacity 1, as before). Combines with\n * `setTilesOpacity`: final alpha = opacity × fade. Deferred hosts only — where\n * the tiles are added to the scene directly there is no fade. Vector layers\n * are not faded.\n */\n horizonFade: number;\n private readonly _far;\n private _farCameras;\n /**\n * Far plane (distance) the world's cameras get while the 3D tiles are loaded, so\n * the map reaches the horizon. Default `10000`. Changing it while the map is\n * loaded takes effect immediately. `horizonFade` is a fraction of this far while\n * the map is loaded (with `0.8`, the map fades from 2 km to 10 km).\n *\n * The camera's own far plane (e.g. the Settings panel's \"Far plane\") is\n * overridden while the map is loaded: it is remembered, not applied, and comes\n * back when the map is unloaded. Code that grows the far plane itself while the\n * map is loaded still works: a larger far than `mapFar` is left alone, and is\n * kept on unload.\n */\n get mapFar(): number;\n set mapFar(far: number);\n /** True while the map owns the cameras' far plane (the 3D tiles are loaded). */\n get farOverridden(): boolean;\n /** The far plane the user asked for, remembered while `farOverridden` (otherwise the cameras hold it). */\n get userCameraFar(): number;\n /** Records the far plane the user wants; not applied until the map is unloaded. Only meaningful while `farOverridden`. */\n setUserCameraFar(far: number): void;\n private _resolveFarCameras;\n /**\n * Shows a sky gradient behind everything while the 3D tiles are loaded: the\n * empty background (pixels nothing has drawn to) goes from `skyHorizonColor` at\n * the horizon to `skyZenithColor` straight up, so the tiles, dissolving with\n * `horizonFade`, melt into the horizon colour. Below the horizon it is the\n * horizon colour; an orthographic camera sees one flat colour. Default `true`;\n * `false` leaves the background untouched. Deferred hosts only — elsewhere\n * there is no sky. Drawn behind the vector layers and the tiles.\n */\n sky: boolean;\n private readonly _skyHorizon;\n private readonly _skyZenith;\n private _skyHorizonColor;\n private _skyZenithColor;\n private _skyPass;\n private static _setSkyRgb;\n /** Sky colour at the horizon (any CSS colour string, hex number or `THREE.Color`). Default `\"#d7e3ee\"`, a light hazy blue. */\n get skyHorizonColor(): THREE.ColorRepresentation;\n set skyHorizonColor(color: THREE.ColorRepresentation);\n /** Sky colour straight up. Default `\"#6a9bd1\"`, a deeper blue. */\n get skyZenithColor(): THREE.ColorRepresentation;\n set skyZenithColor(color: THREE.ColorRepresentation);\n private _passRegistered;\n private _ensureOcclusionPass;\n private readonly _occlusion;\n private _ensureFadeTarget;\n private _disposeFade;\n /** Freezes the reference frame for the upcoming gesture — see `_onControlPointMoved`. */\n private readonly _onDragStart;\n /**\n * Fires on every pointer move during the drag (live relocation). Always\n * converts the TOTAL offset since the drag began (that's what\n * `_controlPoint.position` holds throughout) through the FROZEN\n * start-of-gesture matrix, never the live `tiles.group.matrixWorld` —\n * otherwise every event would re-apply the same growing total against a frame\n * already shifted by all earlier events, compounding into runaway motion.\n *\n * Immediately resets `_controlPoint.position` back to (0,0,0) afterwards, so\n * the gizmo reads as a joystick fixed at the origin — only the terrain visibly\n * moves. This is safe precisely because of the point above: TransformControls\n * computes each event's position from its own frozen drag-start reference plus\n * the raw mouse offset, never incrementally from the object's last value, so\n * it doesn't notice or care that we reset it out from under it.\n */\n private readonly _onControlPointMoved;\n /** Gesture is over — nothing left to commit (every event already did), just clear the frozen reference. */\n private readonly _onDragEnd;\n private readonly _minimapSource;\n /** The 2D minimap (a baked top-down image of the GIS tiles over the project's vector layers) — see `Minimap`. */\n readonly minimap: Minimap;\n private readonly _onBeforeUpdate;\n private readonly _onOriginChange;\n private readonly _onCrsChange;\n private static readonly _CLICK_MAX_MOVE_PX;\n private static readonly _BIM_CLEAR_WINDOW_MS;\n private _pickDown?;\n private _clearBimUntil;\n private _bimClearHandler?;\n /**\n * Wires the click and hover handling on the viewer canvas. Window-level\n * CAPTURE listeners filtered to the canvas, so they run before the\n * Highlighter's own canvas listeners for the same event (it selects BIM\n * elements on mouse up). The canvas lives inside `top-viewer`'s shadow root,\n * where an event observed at `window` is retargeted to the shadow host — so\n * the filter compares `composedPath()[0]` (the real origin), never\n * `event.target`. The canvas itself is looked up per event rather than\n * cached: the world can resolve before its renderer exists.\n *\n * \"Nearest wins\" between a vector feature and a BIM element: on mouse DOWN,\n * only if the raycast hits a vector feature, the BIM element under the same\n * pixel is picked with `FastModelPickers` (`getItemAt` + `getPointAt`, the\n * same GPU pick the Highlighter selects with) and the two camera distances\n * are compared; the camera doesn't move during a click, so the answer is\n * ready by mouse up. On mouse up, if the vector feature won it is selected\n * and the BIM selection that same click makes is undone (the Highlighter\n * can't be told to skip a click — disabling it for one event leaves its\n * internal pointer state stuck — so its highlight is cleared the moment it\n * fires). Otherwise the vector selection is cleared and the Highlighter\n * proceeds as always. Gaussian-splat and Google 3D tiles are not considered.\n */\n private _setupFeaturePicking;\n private readonly _onHighlighterSetup;\n private get _pickCanvas();\n /** True when the event really originated on the viewer canvas (see `_setupFeaturePicking`). */\n private _isOnCanvas;\n private _hoverPoint?;\n private _hoverFrame;\n private readonly _onHoverMove;\n private readonly _runHover;\n private readonly _clearHover;\n /** Vector layers loaded and the viewer in plain select mode (no modal tool). */\n private _canPick;\n private _ensureBimClearHandler;\n private _ndc;\n private _isPickable;\n private readonly _onPickDown;\n private readonly _onPickUp;\n /**\n * Horizontal scene-space box of ALL the project's vector layers (every\n * manifest entry, displayed or not), for the minimap extent — the only thing\n * that defines it. Layers are read as data through the shared per-layer\n * cache (so nothing downloads twice and nothing is added to the scene), then\n * projected with the CURRENT origin on every call, so an origin change never\n * leaves a stale box. A layer that fails to load is skipped with one warning.\n */\n private _vectorLayersBox;\n constructor(components: OBC.Components);\n /**\n * Reads `{GISManager.uuid}.json` from project storage (same pattern as\n * `ClashesManager`/`TopicsManager`'s own `init(client)` — a plain method\n * call, not `@lit/context`).\n * Restores the origin (lat/lon/height/rotation) by composition from\n * `ProjectManager` — the platform's canonical project record — instead of\n * duplicating it into GIS's own persisted file, plus the vector-layer\n * manifest (metadata only — id/name/fileId/type/style, NOT the geometry\n * itself) from GIS's own `{GISManager.uuid}.json`. If that layers file\n * doesn't exist yet in the project, leaves the layer list empty and does\n * NOT create one — that only happens later, on an explicit save.\n *\n * Assumes `ProjectManager.init(client)` has already run by the time this is\n * called — the caller must chain `GISManager.init()` after\n * the `ProjectManager.init()` promise resolves. If `GISManager` can ever be\n * initialized in a different order/context, `ProjectManager.origin.get()`\n * below would just read stale/undefined data silently — revisit this if\n * that assumption stops holding (e.g. by awaiting `ProjectManager.init`\n * here directly, if `GISManager` can no longer rely on caller ordering).\n *\n * No-op (never throws) if there's no project context, no matching file, or\n * the read fails for any reason — the app should always be usable with\n * defaults, storage is a progressive enhancement here, not a hard\n * dependency.\n */\n init(client: PlatformClient): Promise<void>;\n /** Whether loading a vector layer also frames the camera on it. Off for now. */\n fitCameraOnLayerLoad: boolean;\n /**\n * Downloads the given layer's shapefile `.zip` from project storage\n * (`vectorLayersConfig` entry's `fileId`), parses it with `shpjs.parseZip`\n * (dynamic import — same heavy-dependency convention as the rest of this\n * component), and renders it via `vectorLayers.addLayer(geojson, style,\n * id)`. The single entry point for \"the user checked this layer's box\" —\n * callers don't need to touch storage/shpjs/`VectorLayers` directly, and\n * don't need their own try/catch: failures are reported via\n * `onVectorLayerError`, mirroring `enableTiles()`/`onLoadError`.\n */\n loadVectorLayer(id: string): Promise<void>;\n private readonly _layerGeoJSON;\n private _getLayerGeoJSON;\n /**\n * Surface nodes for a layer whose heights come from attributes: every\n * Point/MultiPoint coordinate with a finite Z in the layers named by\n * `height.nodeLayers`. Those layers are only read as data here — nothing is\n * added to the scene and the panel's checkboxes are untouched. An unknown id\n * is warned about and skipped.\n */\n private _loadHeightNodes;\n private _downloadAndParseLayer;\n /**\n * Real-world vector data can easily sit tens of km from the origin (a whole\n * shapefile's extent, not just small hand-built test shapes) —\n * far outside the default camera framing (~87 units from origin). Frames\n * the camera on the layer's actual bounding box right after it loads, same\n * `CameraControls.fitToBox()` the point-cloud loader already uses for the\n * same reason, so newly loaded data doesn't just silently look like nothing\n * rendered.\n */\n private _fitCameraToLayer;\n private static readonly _FOCUS_MIN_RADIUS;\n /**\n * The single entry point for selecting a vector feature — the 3D click and\n * the 2D map's click both come through here, so they share one selection\n * state, one `onFeatureSelected` event and one camera travel. With `focus`,\n * the camera flies to the feature: `CameraControls.fitToSphere()` (animated)\n * on the bounding sphere of what `VectorLayers` built for it, at its real\n * resolved heights; the viewing direction is kept, only the target and the\n * distance change. Selecting the already-selected feature fires no event but\n * still focuses. Clearing stays `vectorLayers.clearSelection()`.\n */\n selectVectorFeature(layerId: string, featureIndex: number, options?: {\n focus?: boolean;\n }): void;\n private _focusVectorFeature;\n /** Removes a layer loaded via `loadVectorLayer` — the \"user unchecked the box\" counterpart. */\n unloadVectorLayer(id: string): void;\n private _firstWorld;\n get apiToken(): string;\n set apiToken(value: string);\n get assetId(): string;\n set assetId(value: string);\n get latitude(): number;\n get longitude(): number;\n get height(): number;\n get rotation(): number;\n get tilesVisible(): boolean;\n get gizmoVisible(): boolean;\n get tilesOffsetEast(): number;\n get tilesOffsetNorth(): number;\n get tilesOffsetUp(): number;\n get tilesOpacity(): number;\n /**\n * See-through factor for the tiles (0..1, 1 = opaque), mirrored by the\n * minimap's terrain image. In-memory only. Applies in DEFERRED mode (the\n * viewer's default); the composer path keeps the tiles opaque.\n */\n setTilesOpacity(opacity: number): void;\n toggleGizmo(): void;\n /** Manual geo-location input (sliders) — no IFC georeferencing read yet, see docs/adrs. */\n setPosition(latitude: number, longitude: number, height?: number, rotation?: number): void;\n /**\n * Small local fine-tune offset (metres, East/North/Up) layered ON TOP of\n * the origin-derived tiles position — a manual calibration knob for Google\n * Photorealistic 3D Tiles' own (independently known) absolute-positioning\n * inaccuracy, NOT a change to `ProjectManager.origin`/real georeferencing.\n * Re-derives the tiles position from the CURRENT origin fields + this\n * offset on every call (via `_reorientation`), so repeated calls replace\n * rather than accumulate.\n *\n * NOT auto-saved — marks `offsetDirty`/fires `onOffsetDirtyChange` instead,\n * same pattern `ProjectManager.origin` uses, so a caller driving this\n * continuously (the fine-tune sliders) doesn't write to the network on\n * every tick. `saveTilesOffset()` persists explicitly.\n */\n setTilesOffset(east: number, north: number, up: number): void;\n /**\n * Persists the current tiles fine-tune offset to `{GISManager.uuid}.json`\n * (loose in `__project_data`, alongside `ProjectManager`'s own file — see\n * `_appDataStore`), preserving whatever `layers` are already in there.\n * `save()` itself is fire-and-forget/debounced — `offsetDirty` only clears\n * (and `onOffsetSaveComplete` fires) once `_appDataStore.onSaveComplete`\n * confirms the write actually succeeded (wired in `init()`), not\n * optimistically here.\n */\n saveTilesOffset(): void;\n private _applyTilesOffset;\n private _reprojectDebounce?;\n private _scheduleReprojectLayers;\n /**\n * Casts a ray straight down from high above the recentered origin against the\n * currently loaded tile geometry to find the real ground elevation at\n * (latitude, longitude), then re-applies the reorientation using that as\n * `height` so the visible terrain/rooftop lands at world (0,0,0) instead of\n * wherever `height=0` (the bare WGS84 ellipsoid, which can be hundreds of\n * meters away from the real surface at elevated locations) happened to put it.\n *\n * Relies on the ENU tangent-plane guarantee `transformLatLonHeightToOrigin`\n * gives at the origin: after recentering at some height, \"up\" from that lat/lon\n * is exactly world +Y, and world Y directly corresponds to metres of height — so\n * a hit at world Y = `dy` means the real surface is `dy` metres higher than the\n * height currently used, and re-running the transform with\n * `height + dy` should bring it to Y ≈ 0. Only accurate near the origin (a few\n * km), which is exactly the regime this is used in.\n *\n * Tries straight down first, then straight up (content can end up above OR below\n * the origin depending on how far off `height=0` was from the real surface).\n *\n * Uses `TilesRenderer.raycast()` — 3d-tiles-renderer's own documented raycasting\n * entry point — instead of a generic `THREE.Raycaster.intersectObject(tiles.group)`.\n * The library keeps its own tile-activity bookkeeping (`activeTiles`,\n * `tile.traversal.used`, per-tile bounding volumes) separate from the plain\n * Object3D tree, and only that entry point knows how to walk it; a generic\n * scene-graph raycast against `tiles.group` silently finds nothing.\n *\n * Tile traversal (`markUsedTiles` in the engine's own source) bails out\n * immediately — without even descending into children — for any tile whose\n * bounding volume isn't in the frustum of AT LEAST ONE registered camera:\n * `if (!tile.traversal.inFrustum) return;`. That branch is never visited, let\n * alone loaded or marked active, regardless of `displayActiveTiles` (which only\n * affects the final visibility toggle of tiles that already got marked active —\n * a narrower case). So if the real viewport camera isn't looking anywhere near\n * the target point, nothing here ever loads and the raycast finds nothing no\n * matter what.\n *\n * `TilesRenderer` supports multiple simultaneously-registered cameras\n * (`cameras: Camera[]`), and a tile counts as \"in frustum\" if ANY of them sees\n * it. So we register a throwaway camera positioned high above the origin,\n * looking straight down — wide FOV and far plane so its frustum (a cone\n * widening downward, centred on the target column) covers a generous height\n * range around the origin regardless of whether the real surface turns out to\n * be above or below it — force one `update()` traversal with it registered,\n * then remove it again. The real viewport camera's own registration and\n * behaviour are untouched throughout.\n *\n * Returns false if no tile geometry was found (nothing to snap to) — caller\n * should retry once more of the tileset streams in. The first call after\n * moving to a new area may land approximately rather than exactly, since the\n * newly-forced-into-frustum content is still streaming in asynchronously in\n * the background — calling it again shortly after tends to refine it further.\n */\n snapToGround(): boolean;\n /**\n * `CesiumIonAuth.fetch()`/`refreshToken()` (see `3d-tiles-renderer/core/plugins/auth/CesiumIonAuth.js`)\n * only ever throws `\"CesiumIonAuthPlugin: Failed to load data with error code {status}\"`\n * on a non-OK HTTP response — no further detail. Map the common statuses to\n * something a user can actually act on; fall back to the raw message otherwise.\n */\n private _toFriendlyLoadError;\n /**\n * Sets everything up and resolves only once the FIRST real outcome is known —\n * either actual content loaded (\"load-tileset\") or the initial fetch (auth\n * against the token/asset) failed (\"load-error\") — instead of resolving the\n * instant the TilesRenderer is constructed, before any network activity has\n * even started. `tilesVisible`/state only flips to enabled on success; on\n * failure everything set up here is torn down again and the promise rejects,\n * so the caller (the panel) never has to un-render a half-enabled state.\n */\n enableTiles(): Promise<void>;\n disableTiles(): void;\n /** Tears down everything `enableTiles()` set up, without touching `_tilesVisible`. */\n private _teardownTiles;\n dispose(): void;\n private _trigger;\n}\n\n/**\n * Streams Cesium Ion 3D Tiles (Google Photorealistic 3D Tiles by default) co-located\n * with the BIM model.\n *\n * Rendering path depends on `world.renderer.postproduction.mode`:\n * - DEFERRED: the deferred G-buffer capture pass only draws objects whose material\n * carries the engine's \"capture-emission\" marker (set on Fragments/BIM surface\n * materials only) — every other object, however opaque, is hidden for the\n * duration of the capture (confirmed directly from the engine's own\n * `SurfaceCapturePass` docs). So tiles are added to a private off-scene\n * `THREE.Scene` and drawn via `addOcclusionPass` (direct mode — opaque,\n * self-occluding, same as `PointCloudLoader`), which runs AFTER the deferred\n * composite and bypasses the G-buffer requirement entirely.\n * - COMPOSER: the EffectComposer path renders the real scene graph directly, no\n * special material marker needed, so tiles are added straight to\n * `world.scene.three` like any other mesh.\n *\n * The Cesium Ion API token is kept in memory only (no persistence yet) — see\n * docs/adrs for the pending decision on where project geo-location should live.\n */\nexport type GISManager = InstanceType<typeof _GISManager>;\n/**\n * Streams Cesium Ion 3D Tiles (Google Photorealistic 3D Tiles by default) co-located\n * with the BIM model.\n *\n * Rendering path depends on `world.renderer.postproduction.mode`:\n * - DEFERRED: the deferred G-buffer capture pass only draws objects whose material\n * carries the engine's \"capture-emission\" marker (set on Fragments/BIM surface\n * materials only) — every other object, however opaque, is hidden for the\n * duration of the capture (confirmed directly from the engine's own\n * `SurfaceCapturePass` docs). So tiles are added to a private off-scene\n * `THREE.Scene` and drawn via `addOcclusionPass` (direct mode — opaque,\n * self-occluding, same as `PointCloudLoader`), which runs AFTER the deferred\n * composite and bypasses the G-buffer requirement entirely.\n * - COMPOSER: the EffectComposer path renders the real scene graph directly, no\n * special material marker needed, so tiles are added straight to\n * `world.scene.three` like any other mesh.\n *\n * The Cesium Ion API token is kept in memory only (no persistence yet) — see\n * docs/adrs for the pending decision on where project geo-location should live.\n */\nexport const GISManager = { uuid: 'd8f3a1c2-6b4e-4f9a-8c1d-2e7b5a9f3c60' } as typeof _GISManager & { uuid: 'd8f3a1c2-6b4e-4f9a-8c1d-2e7b5a9f3c60' };\n\n/** One element mutation inside a revit-flow commit. */\nexport interface RevitFlowChange {\n /** create → element added, update → geometry/data changed, delete → removed. */\n type: \"create\" | \"update\" | \"delete\" | string;\n /** Revit UniqueId (GUID). Resolves to a fragments localId via getLocalIdsByGuids. */\n uniqueId: string;\n}\n/** Per-commit change tallies, mirrored from the add-in's `counts` block. */\nexport interface RevitFlowCounts {\n added: number;\n modified: number;\n removed: number;\n}\n/**\n * A revit-flow commit — one push of changes from the Revit add-in. `id` is a\n * monotonic integer; `parent` points at the previous commit (null for the\n * root). The first commit is the baseline: its geometry IS the visible model\n * file. Later commits carry only their delta geometry, in a HIDDEN .frag whose\n * id is `deltaId`.\n */\nexport interface RevitFlowCommit {\n /**\n * WHAT this commit is. Identity, minted by whoever wrote it, meaningful outside the model it\n * belongs to — which the old integer was not: that was the platform's storage version, a number\n * the CDE handed out. An application that does not push through a Revit central has no such\n * number, and an integer sequence asserts one line of history, which Revit's central enforces and\n * nothing else has to.\n */\n guid: string;\n /**\n * The commits this one was built on. Absent on a root.\n *\n * A LIST, because a history that can only ever be a line is a different thing from a graph. A\n * fork was already expressible with a single parent — two commits naming the same one — but a\n * MERGE means naming both lines, and that needs this. The first entry is the line the commit\n * continues, which is what lets the panel lay out lanes without guessing which side is the trunk.\n *\n * Revit never writes more than one: its central IS a single line and it merges inside itself\n * rather than in this graph. The list is for the applications that are not Revit.\n */\n parents?: string[] | null;\n /**\n * WHERE this landed in the CDE, when there is such a place. Data, never identity, and never shown\n * as the commit's name. Absent for any application with no version counter.\n */\n version?: number;\n /**\n * Position in this model's history, computed from the parent chain when the commits are read.\n *\n * Order questions — \"is this commit before the one on screen?\" — used to be asked of the integer\n * id, which meant every application had to produce a sequence to be understood. They are asked of\n * this instead: derived from the graph, so an application that has no numbers still answers them.\n */\n ordinal: number;\n /**\n * What the author said this commit was for, in their own words. Absent when nobody said\n * anything, which is most commits.\n *\n * In Revit it comes from the Comment box in its own Synchronize with Central dialog, which\n * people have been typing into for years while it went nowhere. Free text: never parsed, never\n * relied on for structure.\n */\n message?: string;\n author: string;\n source: string;\n timestamp: string;\n changes: RevitFlowChange[];\n counts: RevitFlowCounts;\n /**\n * Hidden-file id of this commit's delta .frag (created+modified geometry).\n * Absent on the baseline/first commit and on geometry-less commits. The\n * platform's hidden-file API has no queryable name, so the delta is loaded by\n * this id, never by filename.\n */\n deltaId?: string;\n /**\n * Platform user id of the committer, recorded by the add-in from its API key. Lets the\n * UI resolve the author to a real project member (avatar + name) via getProjectData,\n * instead of deriving initials from the raw Revit username. Absent on history written\n * before this was recorded, or when the key isn't a readable JWT.\n */\n userId?: string;\n /**\n * Which loaded model this commit belongs to (the model file's id == the viewer's\n * modelId). Tagged in by the manager when it reads the history: commit ids are\n * per-model version numbers, so they repeat across models and can't identify a commit\n * on their own.\n */\n modelId?: string;\n /** The model's name AS SHOWN IN PROJECT FILES, for the cards and the model filter. */\n modelName?: string;\n /**\n * This commit re-exported the WHOLE model, so the project's visible .frag shows the\n * model as of here — what anyone opening it from Project Files gets, without the\n * history panel. True for the initial capture and for the periodic full exports the\n * team publishes; ordinary commits ship only their delta.\n */\n full?: boolean;\n /**\n * Interoperability operations this commit materialised. Present only when somebody in\n * Revit pulled a deferred edit: the commit is the native half of it, and this is the\n * link back to the operation that asked for it. Ordinary hand-authored commits, which\n * are nearly all of them, carry no such key at all.\n */\n appliedOps?: string[];\n /**\n * Set when this entry is NOT a commit but a deferred edit still waiting to be applied.\n *\n * Pending operations are surfaced commit-SHAPED rather than as a parallel kind of thing, so\n * they inherit search, the user and model filters, the change-kind chips and the\n * filter-by-selection behaviour instead of needing all of it reimplemented. It also means\n * one of them can be clicked and previewed: a `modify` or `delete` names elements that\n * already exist, which is exactly what the outline machinery consumes, so you can see what\n * a change will touch before anybody applies it. A `create` has nothing to show yet, which\n * is honest rather than missing.\n *\n * Everything that treats an entry as history must check this first: it has not happened.\n */\n pendingOp?: RevitFlowOp;\n}\n/** Shape of `revitflow_history.json`. */\nexport interface RevitFlowHistory {\n model: string;\n commits: RevitFlowCommit[];\n}\n/**\n * One deferred edit waiting to be applied to a model.\n *\n * Operations are NOT commits and do not live in the graph: a commit is immutable past, an\n * operation is optional future. They sit above the model's HEAD until somebody opens the\n * model in Revit and applies one, at which point they become a commit and stop being\n * pending. Mirrors the add-in's `revitflow_ops.json`.\n */\nexport interface RevitFlowOp {\n opId: string;\n /** Groups the operations one authored action produced across several models. */\n batchId?: string;\n /** Hidden-file id of the operation's .frag payload. */\n fragId?: string;\n title?: string;\n /** add | set | remove | mixed. Older queues say modify | create | delete. */\n verb?: string;\n author?: string;\n /**\n * Platform user id of whoever authored it. Resolved to a real project member exactly as a\n * commit's is, so the same person does not appear as \"Antonio That Open\" on their commits\n * and as their raw OS username on their operations.\n */\n userId?: string;\n createdAt?: string;\n /** The commit this operation was authored against. */\n /** The commit this was authored against, by guid. What a proposal actually refers to. */\n baseCommitGuid?: string;\n /** The platform version that commit landed in. Data, for reconciling with the CDE. */\n baseCommit?: number;\n /** How many elements it targets. */\n targets?: number;\n state?: \"pending\" | \"applied\" | \"discarded\" | string;\n /** The native commit that materialised it, once applied. */\n appliedInCommit?: number | null;\n /**\n * Native ids the operation actually touched or created, written by the add-in when it applied.\n * A FLAT list: it does not say which source object produced which result, because nothing in\n * this system ties an element to an element in another application.\n *\n * It is what lets an APPLIED proposal be selected and previewed like a commit, with no payload\n * fetch at all. Note which halves that leaves blind, because they are opposite ends:\n *\n * add pending → nothing exists yet · applied → these are what it made\n * set pending → its targets · applied → the same targets\n * remove pending → its targets · applied → nothing, they are gone\n *\n * So the only case still needing the payload is a PENDING set or remove, whose target ids live\n * in the operation's .frag rather than in this index.\n */\n affectedIds?: string[];\n /** Tagged in by the manager, exactly as commits are: which model this queue belongs to. */\n modelId?: string;\n modelName?: string;\n}\n/** Shape of `revitflow_ops.json`. */\nexport interface RevitFlowOpsIndex {\n schema?: string;\n ops: RevitFlowOp[];\n}\n/** Dominant change type of a commit, used to color its timeline node. */\nexport type DominantChange = \"create\" | \"update\" | \"delete\";\n\n/** What to do with elements outside the selected commit. */\nexport type ContextMode = \"default\" | \"hidden\";\n/** The three kinds of change a commit can carry. */\nexport type ChangeKind = \"create\" | \"update\" | \"delete\";\n/**\n * Stable id for a commit across models — which is now just its guid.\n *\n * It used to have to be `${model}:${id}`, because the id was a per-model version number and every\n * model had a commit 3. A guid needs no help being unique, and that is exactly what it was for.\n */\nexport declare const commitKey: (c: {\n guid?: string;\n pendingOp?: {\n opId: string;\n };\n}) => string;\n/** How the commit is shown in 3D: review colours, or the model as it ended up. */\nexport type HighlightMode = \"colored\" | \"plain\";\n/** Dominant change type of a commit: delete → create → update. */\nexport declare function dominantChange(commit: RevitFlowCommit): DominantChange;\n/**\n * GitHistoryManager — headless engine for the revit-flow git-history built-in.\n *\n * Owns ALL viewer mutation for the change outlines. It does NOT load the model —\n * the user opens a model from the Project Files panel, and this manager reacts to\n * that load: it reads the model's hidden `revitflow_history.json` (if any) and\n * publishes the commit list. Showing a commit outlines its changed elements\n * (create → green, update → blue, delete → red) via three independently-colored\n * `OBF.Outliner` groups — a cheap post-process outline that never recolors the\n * fragment geometry. The Lit panel (`top-git-history`) is intent-only: it calls\n * these methods and subscribes to the events below.\n *\n * Data model, per loaded model (fileId == modelId), all HIDDEN children of it:\n * - revitflow_history.json — { model, commits: [{ id, parent, author, source,\n * timestamp, changes:[{type,uniqueId}], counts }] }. The first commit is the\n * INITIAL full-model capture (its geometry == the visible baseline file).\n * - revitflow_frag_<N>.frag — delta fragments for commit N (its created+modified\n * geometry), loaded on demand so created elements can be colored.\n */\ndeclare class _GitHistoryManager extends OBC.Component {\n static readonly uuid: \"3f9c1a7e-6b2d-4e18-9a5c-7d0e2f4b6c81\";\n enabled: boolean;\n readonly onCommitsChanged: OBC.Event<RevitFlowCommit[]>;\n /** {@link commitKey} of the highlighted commit, or null when cleared. */\n readonly onCommitChanged: OBC.Event<string | null>;\n readonly onLoadingChanged: OBC.Event<boolean>;\n readonly onError: OBC.Event<string>;\n /** The GUID currently selected in the 3D view (null when the selection is cleared). */\n readonly onSelectedGuidChanged: OBC.Event<string | null>;\n /** A source icon was added or replaced. */\n readonly onSourceIconsChanged: OBC.Event<void>;\n /**\n * Which mark to draw on a commit, by the application that wrote it.\n *\n * Every commit already says who made it, in `source`. The panel used to draw the Revit logo on\n * all of them regardless, which was true while Revit was the only thing that could write one and\n * became a lie the moment anything else did: a commit from another tool would claim to be a\n * Revit commit, on the one part of the row whose whole job is to say where a change came from.\n *\n * The format is deliberately open about who writes history, so the icons have to be too. This is\n * the registry. Only `revit` is built in; an application adds its own:\n *\n * const history = components.get(GitHistoryManager);\n * history.setSourceIcon(\"rhino\", \"https://…/rhino.svg\"); // a URL, or a data: URI\n * history.setSourceIcon(\"tekla\", \"<svg viewBox='0 0 24 24'>…</svg>\"); // or the markup\n *\n * A source with no icon gets a neutral one rather than somebody else's.\n */\n readonly sourceIcons: Map<string, string>;\n /**\n * @param source the commit's own `source` value, matched case-insensitively.\n * @param icon a URL, a `data:` URI, or inline `<svg>` markup.\n */\n setSourceIcon(source: string, icon: string): void;\n world?: OBC.World;\n /**\n * What happens to elements that are NOT part of the selected commit:\n * \"default\" — left as they are (the change outlines sit on the full model)\n * \"hidden\" — hidden entirely, isolating the commit's elements\n *\n * A dimmed (\"ghost\") middle ground was dropped: the fragments x-ray writes depth\n * from the pixels its screen door keeps, so dimmed geometry still occluded the very\n * elements under review — worse the denser the model in front. Fixing that properly\n * belongs in the renderer, not here, so this offers the two states that are exact.\n */\n contextMode: ContextMode;\n /**\n * Which change kinds to outline. All three by default; the panel's filter buttons\n * narrow it (e.g. only deletions) without reloading anything.\n */\n typeFilter: Set<ChangeKind>;\n /**\n * How many commits either side of the selected one to keep pre-loaded, so stepping\n * through the timeline is instant instead of fetching on every click. The window\n * slides with the selection and everything outside it is disposed, which bounds\n * memory no matter how long the history gets.\n */\n prefetchRadius: number;\n /**\n * How a commit is presented in 3D:\n * \"colored\" — outline created/edited/deleted in their colours (the review lens)\n * \"plain\" — no outlines: the model simply as it stood AFTER the commit, so the\n * deleted elements are hidden rather than painted red\n */\n highlightMode: HighlightMode;\n /** @deprecated kept so older callers still compile — maps onto contextMode. */\n get isolateChanges(): boolean;\n /** Green — created elements. */\n readonly COLOR_CREATED = \"#22c55e\";\n /** Golden yellow — modified elements. */\n readonly COLOR_MODIFIED = \"#e3b341\";\n /** Red — deleted elements. */\n readonly COLOR_DELETED = \"#ef4444\";\n readonly GROUP_CREATED = \"revitflow-created\";\n readonly GROUP_MODIFIED = \"revitflow-modified\";\n readonly GROUP_DELETED = \"revitflow-deleted\";\n private _client?;\n private _projectId?;\n /**\n * One entry per loaded revit-flow model. Commit ids are per-model version numbers, so\n * they collide across models — every commit is tagged with its modelId and a commit is\n * addressed by {@link commitKey}, never by id alone.\n */\n private _models;\n /** Which models the timeline shows. Empty = all of them. */\n private _selectedModels;\n /** `${modelId}:${id}` of the commit currently highlighted, or null. */\n private _currentKey;\n /** modelIds already probed for a sibling history (avoids re-probing). */\n private _probed;\n /** hiddenIds of delta frags this manager has loaded into the viewer. */\n private _loadedDeltas;\n /** Ghosted localIds per modelId, so isolate can be cleared/re-applied. */\n private _contextApplied;\n /** localIds hidden because the shown commit deleted them (plain mode). */\n private _hiddenDeleted;\n /** localIds hidden because a newer visible source supplies the same element. */\n private _hiddenSuperseded;\n /** True once the three named Outliner groups have been created. */\n private _groupsReady;\n private _loading;\n private _wired;\n constructor(components: OBC.Components);\n get ready(): boolean;\n get loading(): boolean;\n /**\n * Commits of the selected models, newest last, interleaved by time so a multi-model\n * timeline reads chronologically rather than model-by-model.\n */\n get commits(): RevitFlowCommit[];\n /** True when this entry is a proposal rather than something that happened. */\n isProposal(commit: RevitFlowCommit | null | undefined): boolean;\n /**\n * The entry a proposal/commit links to, in whichever direction applies: a commit points at\n * the proposal it materialised, a proposal at the commit that did it. Returns null when\n * there is no counterpart, which is the normal case for hand-authored work.\n */\n counterpart(commit: RevitFlowCommit): RevitFlowCommit | null;\n /**\n * Deferred edits still waiting to be applied, across the selected models, oldest first.\n *\n * Kept separate from {@link commits} on purpose. A commit is something that happened; a\n * pending operation is something that might. Merging them into one list would force every\n * consumer to keep asking which kind it was holding.\n */\n get pendingOps(): RevitFlowOp[];\n /** The loaded revit-flow models, for the panel's model filter. */\n get models(): Array<{\n modelId: string;\n name: string;\n commits: number;\n }>;\n get selectedModels(): Set<string>;\n get currentKey(): string | null;\n /** Name of the single loaded model, or \"\" when there are none/several. */\n get modelName(): string;\n /** The commit behind {@link currentKey}, or undefined when nothing is highlighted. */\n private _currentCommit;\n /** Restrict the timeline to these models (empty set = show all of them). */\n setSelectedModels(modelIds: Iterable<string>): Promise<void>;\n /** True when `commit` is its model's baseline (the full-model capture). */\n isBaseline(commit: RevitFlowCommit): boolean;\n /** True if `commit` has a hidden delta .frag to load. */\n hasFrag(commit: RevitFlowCommit): boolean;\n /**\n * Wire the platform client and subscribe to model loads. Does NOT load any\n * geometry: the manager only attaches to models the user opens from the Files\n * panel. Consumer panels call this once on connect.\n */\n init(client: PlatformClient): Promise<void>;\n /**\n * Follow the viewer's selection so the element view tracks whatever the user clicks in\n * 3D — no \"trace this\" button to press. The Highlighter's events appear asynchronously\n * (they're registered when the viewer sets it up), so retry briefly until they exist.\n */\n private _watchSelection;\n private _onModelSet;\n private _onModelDeleted;\n /**\n * Probe a loaded model for a sibling visible `revitflow_history.json` in its\n * folder. If present, adopt it as the active model and publish its commits.\n * Silent for non-revit models and for our own delta frags — only genuine\n * fetch/parse failures raise onError.\n */\n private _probeModel;\n /**\n * Read the model's deferred-edit queue, if it has one.\n *\n * Best effort by design: a model that has never been the target of an operation simply has\n * no queue, and that is the normal case rather than an error. A failure here must never\n * cost the user their history, which is why it cannot throw out of the probe.\n */\n private _readOps;\n /**\n * Re-scan every currently-loaded model for a hidden revit-flow history (the\n * panel's Refresh button). Clears the probe cache so models load-order edge\n * cases re-resolve.\n */\n loadHistory(): Promise<void>;\n /**\n * Show `commit`. The baseline geometry is the visible model the user already loaded, so\n * the baseline view just clears outlines. Any other commit pulls its hidden delta frag\n * in (so created elements exist) and outlines its changed elements. Fires\n * onCommitChanged. Takes the commit itself, not an id: ids repeat across models.\n */\n showCommit(commit: RevitFlowCommit): Promise<void>;\n /**\n * Keep the deltas of the commits around `centerId` loaded and drop the rest, so\n * stepping through the timeline never stalls and memory stays bounded: moving from\n * commit 10 to 11 fetches one delta and disposes one, instead of reloading a window.\n */\n private _slidePrefetchWindow;\n /**\n * Show the model as it stood AT `commit`: the visible baseline is the model at its\n * INITIAL commit, and everything created later lives in per-commit delta .frags loaded\n * as separate models. Those deltas stay loaded (the prefetch window keeps neighbours\n * warm), so stepping BACK has to hide the ones from later commits — otherwise a wall\n * added in commit 3 was still sitting there while you were looking at commit 2.\n * Only touches deltas of the commit's own model; other models keep their own state.\n */\n private _applyFutureVisibility;\n /** Which commit a loaded delta belongs to (deltas are keyed by their hidden id). */\n private _commitOfDelta;\n /** Make every loaded delta visible again (the model as of its latest commit). */\n private _showAllDeltas;\n /** Remove all revit-flow outlines + ghosting and reset the selection. */\n clear(): Promise<void>;\n /** Set what happens to non-commit elements; re-applies to the current commit. */\n setContextMode(mode: ContextMode): Promise<void>;\n /**\n * Every commit that touched `uniqueId`, oldest first, with what happened to it there.\n * The element's life story: created here, edited there, finally deleted.\n */\n elementHistory(uniqueId: string): Array<{\n commit: RevitFlowCommit;\n type: string;\n }>;\n /** Per-author totals across the (optionally date-filtered) history. */\n userActivity(since?: Date): Array<{\n author: string;\n userId?: string;\n commits: number;\n added: number;\n modified: number;\n removed: number;\n last: string;\n }>;\n /**\n * The GUID of whatever is currently selected in the viewer, so the element view can\n * follow the user's selection. Returns null when nothing (or something unresolvable)\n * is selected.\n */\n /** GUIDs of everything currently selected in the viewer (empty when nothing is). */\n selectedGuids(): Promise<string[]>;\n selectedGuid(): Promise<string | null>;\n /**\n * Select every element the commit touched, in the viewer's own selection — so the\n * usual tools (properties, isolate, zoom) work on it like any hand-made selection.\n * Honours the current type filter, so \"only deletions\" selects only those.\n * @returns how many elements ended up selected.\n */\n selectCommitElements(commit: RevitFlowCommit, zoom?: boolean): Promise<number>;\n /** Show/hide one kind of change; re-applies to the current commit. */\n setTypeVisible(kind: ChangeKind, on: boolean): Promise<void>;\n /** @deprecated use setContextMode. */\n setIsolateChanges(on: boolean): Promise<void>;\n /** The shared Outliner component (created on first access by the viewer). */\n private _outliner;\n /**\n * Create the three independently-colored outline groups once. The viewer\n * owns the Outliner's DEFAULT group (selection) — we only add our own named\n * groups and never touch \"default\".\n */\n private _ensureGroups;\n /** Clear our three outline groups only — leaves the viewer's default group. */\n private _clearOutlines;\n /**\n * Resolve each change bucket's GUIDs to localIds across every loaded model\n * and route them to the matching outline group.\n */\n private _outlineCommit;\n /**\n * Remove every localId that `_applySupersededVisibility` has hidden from a change map.\n * Returns a copy: the input maps come from `_buildMap` and are used elsewhere.\n */\n private _dropSuperseded;\n /**\n * Hide (or restore) the elements a commit deleted. Tracked separately from the context\n * modes so switching Colored↔Plain doesn't disturb ghosting or the rest of the model.\n */\n private _applyDeletedVisibility;\n /**\n * Show each element ONCE: from the newest source that supplies it.\n *\n * THE BUG THIS EXISTS FOR. The baseline .frag holds the whole model as of the first\n * commit, and every later commit ships a delta .frag with the geometry it created AND\n * the geometry it modified. Both stay in the scene. For a CREATED element that is\n * right — it exists in exactly one place. For a MODIFIED one it is not: the element is\n * in the baseline at its old shape and in the delta at its new one, and the viewer drew\n * both. Measured 2026-08-05 on a wall whose height Quim raised: the new wall stood\n * proud of the old one, with the coincident faces z-fighting into a dotted band.\n *\n * The rule is the obvious one once stated: for any element, only the newest VISIBLE\n * source may draw it. Deltas are walked newest-first, each guid is claimed by the first\n * source that has it, and every older copy — in an older delta or in the baseline — is\n * hidden. Deltas newer than the commit being shown are already hidden wholesale by\n * `_applyFutureVisibility`, so they never get to claim anything.\n *\n * Restores before it hides, like `_applyDeletedVisibility`, so stepping backwards\n * through the timeline brings the old geometry back rather than accumulating hidden\n * elements until the model is empty.\n */\n private _applySupersededVisibility;\n /** Switch between review colours and the plain post-commit model. */\n setHighlightMode(mode: HighlightMode): Promise<void>;\n /**\n * Make sure the geometry of `deleted` GUIDs is loaded. Anything already resolvable in\n * a loaded model (the usual case: the element shipped in the baseline) needs nothing;\n * for the rest, walk back through the history to the commit that CREATED each one and\n * load that commit's delta, which is the last place its geometry existed.\n */\n private _ensureDeletedGeometry;\n /** GUIDs → { modelId: Set<localId> } across the given models. */\n private _buildMap;\n private _mergeMaps;\n /**\n * Dim (\"ghost\") or hide every element that is NOT part of the shown commit, per the\n * chosen context mode. Best-effort per model: a model that doesn't support the call is\n * simply left alone — the outlines still convey the change.\n */\n private _applyContext;\n /** Undo whatever the context mode did: drop the ghost overlay and restore visibility. */\n private _clearContext;\n /**\n * Kept for the panel's connect hook. Prefetching is now driven by the SELECTION (see\n * _slidePrefetchWindow): nothing is downloaded until a commit is opened, and only its\n * neighbourhood is kept. Warming the newest N up front, as this used to do, spent\n * bandwidth on commits nobody had asked for and grew without bound.\n */\n warmDeltas(): void;\n /** Load a commit's hidden delta .frag (by its hidden id) into the viewer (modelId == hiddenId). */\n private _ensureDeltaLoaded;\n private _setLoading;\n private _firstWorld;\n}\n\n/**\n * GitHistoryManager — headless engine for the revit-flow git-history built-in.\n *\n * Owns ALL viewer mutation for the change outlines. It does NOT load the model —\n * the user opens a model from the Project Files panel, and this manager reacts to\n * that load: it reads the model's hidden `revitflow_history.json` (if any) and\n * publishes the commit list. Showing a commit outlines its changed elements\n * (create → green, update → blue, delete → red) via three independently-colored\n * `OBF.Outliner` groups — a cheap post-process outline that never recolors the\n * fragment geometry. The Lit panel (`top-git-history`) is intent-only: it calls\n * these methods and subscribes to the events below.\n *\n * Data model, per loaded model (fileId == modelId), all HIDDEN children of it:\n * - revitflow_history.json — { model, commits: [{ id, parent, author, source,\n * timestamp, changes:[{type,uniqueId}], counts }] }. The first commit is the\n * INITIAL full-model capture (its geometry == the visible baseline file).\n * - revitflow_frag_<N>.frag — delta fragments for commit N (its created+modified\n * geometry), loaded on demand so created elements can be colored.\n */\nexport type GitHistoryManager = InstanceType<typeof _GitHistoryManager>;\n/**\n * GitHistoryManager — headless engine for the revit-flow git-history built-in.\n *\n * Owns ALL viewer mutation for the change outlines. It does NOT load the model —\n * the user opens a model from the Project Files panel, and this manager reacts to\n * that load: it reads the model's hidden `revitflow_history.json` (if any) and\n * publishes the commit list. Showing a commit outlines its changed elements\n * (create → green, update → blue, delete → red) via three independently-colored\n * `OBF.Outliner` groups — a cheap post-process outline that never recolors the\n * fragment geometry. The Lit panel (`top-git-history`) is intent-only: it calls\n * these methods and subscribes to the events below.\n *\n * Data model, per loaded model (fileId == modelId), all HIDDEN children of it:\n * - revitflow_history.json — { model, commits: [{ id, parent, author, source,\n * timestamp, changes:[{type,uniqueId}], counts }] }. The first commit is the\n * INITIAL full-model capture (its geometry == the visible baseline file).\n * - revitflow_frag_<N>.frag — delta fragments for commit N (its created+modified\n * geometry), loaded on demand so created elements can be colored.\n */\nexport const GitHistoryManager = { uuid: '3f9c1a7e-6b2d-4e18-9a5c-7d0e2f4b6c81' } as typeof _GitHistoryManager & { uuid: '3f9c1a7e-6b2d-4e18-9a5c-7d0e2f4b6c81' };\n\n/**\n * A simple test component to validate the built-in component pipeline.\n * Replace this with real components once the infrastructure is verified.\n */\ndeclare class _HelloWorld extends OBC.Component {\n static readonly uuid: \"2c4ae432-fc24-43e9-9783-0c960c674e96\";\n enabled: boolean;\n readonly name = \"HelloWorld\";\n constructor(components: OBC.Components);\n /**\n * Returns a greeting message and logs it to the console.\n * @param who - The name to greet. Defaults to `\"World\"`.\n */\n greet(who?: string): string;\n}\n/**\n * PlatformComponents.import() expects a `main` variable in scope with\n * a `componentDefinition` property pointing to the OBC.Component class.\n * The IIFE build (name: 'main') assigns this to `var main = ...`.\n */\n\n/**\n * A simple test component to validate the built-in component pipeline.\n * Replace this with real components once the infrastructure is verified.\n */\nexport type HelloWorld = InstanceType<typeof _HelloWorld>;\n/**\n * A simple test component to validate the built-in component pipeline.\n * Replace this with real components once the infrastructure is verified.\n */\nexport const HelloWorld = { uuid: '2c4ae432-fc24-43e9-9783-0c960c674e96' } as typeof _HelloWorld & { uuid: '2c4ae432-fc24-43e9-9783-0c960c674e96' };\n\nexport type ProjectNamespaceKey = \"origin\" | \"georeferencing\" | \"appSettings\";\nexport interface ProjectNamespace {\n label: string;\n description?: string;\n}\nexport interface ProjectEntity<T = unknown> {\n namespaceId: ProjectNamespaceKey;\n label: string;\n description?: string;\n data: T;\n}\n/** GIS origin point that fixes the scene's (0,0,0) to a real-world coordinate. */\nexport interface OriginData {\n lat: number;\n lon: number;\n height: number;\n rotation: number;\n}\n/** Project-wide coordinate reference system + vertical datum config, shared by\n * every asset type that needs to decode raw projected coordinates (point\n * clouds, BIM) — see automatic-file-derived-georeferencing.md\n * (VisorUnificadoAqualia/docs/adrs). One value per project, not per asset:\n * every file at the same real-world site shares the same CRS/geoid. */\nexport interface CrsData {\n /** EPSG code of the project's projected CRS (e.g. 25830 for ETRS89/UTM 30N).\n * EPSG is a global registry, not region-specific — every project has an\n * applicable code, most commonly a standard UTM zone. */\n epsgCode: number;\n /** Geoid undulation in meters at the project's origin (orthometric ->\n * ellipsoidal height correction). Sampled once from a geoid model\n * (client-supplied, or a global EGM2008 fallback) — varies negligibly\n * across a single project's extent, so one scalar per project suffices. */\n geoidUndulation: number;\n}\nexport type AssetCoordinateType = \"splat\" | \"ifc\" | \"point-cloud\" | (string & {});\nexport interface AssetCoordinate {\n fileId: string;\n type: AssetCoordinateType;\n lat: number;\n lon: number;\n height: number;\n rotation: number;\n}\nexport interface GraphicsSettingsData {\n stylePreset: string;\n postproduction: boolean;\n edges: {\n enabled: boolean;\n color: string;\n opacity: number;\n };\n ambientOcclusion: {\n enabled: boolean;\n value: number;\n };\n tonalShading: {\n enabled: boolean;\n value: number;\n };\n surfaceColor: {\n enabled: boolean;\n };\n transparentBackground: {\n enabled: boolean;\n color: string;\n };\n grid: {\n enabled: boolean;\n color: string;\n };\n gridHeight: {\n auto: boolean;\n value: number;\n };\n antiAliasing: boolean;\n nativeResolution: boolean;\n adaptiveResolution: {\n enabled: boolean;\n value: number;\n };\n minResolution: number;\n renderScale: number;\n}\nexport interface ProjectManagerData {\n schemaVersion: 1;\n namespaces: Record<ProjectNamespaceKey, ProjectNamespace>;\n entities: {\n origin: ProjectEntity<OriginData>;\n crs: ProjectEntity<CrsData>;\n assetCoordinates: ProjectEntity<AssetCoordinate[]>;\n graphicsSettings: ProjectEntity<GraphicsSettingsData>;\n };\n}\nexport interface SingletonEntity<T> {\n get(): T | undefined;\n set(data: T): Promise<void>;\n update(partial: Partial<T>): Promise<void>;\n}\n/**\n * A singleton entity that also announces its own changes — for values other\n * code needs to react to live (recompute/reposition something) rather than\n * just read on demand. `onChange` fires with the new value on every\n * `set`/`update`, regardless of whether that change has been persisted yet\n * (see `ProjectManager.dirty`/`onDirtyChange`).\n */\nexport interface ReactiveSingletonEntity<T> extends SingletonEntity<T> {\n onChange: import(\"@thatopen/components\").Event<T>;\n}\nexport interface AssetCoordinatesEntity {\n getAll(): AssetCoordinate[];\n get(fileId: string): AssetCoordinate | undefined;\n getByType(type: AssetCoordinateType): AssetCoordinate[];\n set(fileId: string, data: Omit<AssetCoordinate, \"fileId\">): Promise<void>;\n remove(fileId: string): Promise<void>;\n}\n\n/**\n * ProjectManager is the platform's canonical store for project-level\n * configuration and data — origin/georeferencing/app-settings today, with\n * room to grow. It persists a single JSON file (`${ProjectManager.uuid}.json`)\n * loose directly inside `__project_data` (same folder convention `GISManager`\n * already used) — NOT in a per-app subfolder like `collider`/`cde`, which are\n * for secondary, per-builtin data. Sharing that root folder with other\n * builtins doesn't change its role: it's still the one canonical project\n * record, meant to stop each builtin from inventing its own ad-hoc\n * project-persistence pattern.\n *\n * Schema shape (see `src/types.ts` for the full rationale):\n * - `namespaces`/`entities` are maps keyed by a fixed, readable slug — a\n * closed set this code defines, never created at runtime.\n * - `origin`/`crs`/`graphicsSettings` are singletons; `assetCoordinates` is\n * a collection.\n * - `entities[id]` is a uniform envelope: `namespaceId`, mandatory `label`,\n * optional `description` (omitted, not stored empty), free-form `data`.\n */\ndeclare class _ProjectManager extends OBC.Component {\n static readonly uuid: \"6f3a9c2e-8b1d-4e6a-9c3f-1d7b5a8e2c4f\";\n enabled: boolean;\n /** True once init(client) has been called — safe to use the entity accessors. */\n get ready(): boolean;\n /** Suppress auto-save while bulk-loading data. */\n private _loadingData;\n readonly onSaveStart: OBC.Event<void>;\n readonly onSaveComplete: OBC.Event<boolean>;\n /**\n * Entity ids (e.g. `\"origin\"`) with changes not yet persisted. Most entities\n * auto-save (see `_scheduleSave`) so they're only ever dirty for the instant\n * before their debounce fires — `origin` is the exception: its `set`/`update`\n * mark it dirty WITHOUT scheduling a save (see `origin` below), so a caller\n * driving it continuously (e.g. a drag gizmo) can update it every frame\n * without spamming the network, and a UI can surface \"unsaved changes\" +\n * call `flush()` once the user explicitly confirms.\n *\n * KNOWN GAP: `_doSave()` persists the whole `_data` blob (one JSON file for\n * every entity), so an auto-saving entity's save will also flush out\n * whatever `origin` currently holds in memory, even if the user hasn't\n * confirmed it yet — there's no separate \"committed vs. draft\" copy of\n * `origin`'s data. Accepted for now as a v1 gap (same spirit as this\n * package's other documented v1 gaps, see the ProjectManager ADR); revisit\n * if that coincidence turns out to matter in practice.\n */\n private _dirtyEntities;\n /** True while any entity has unsaved changes. */\n get dirty(): boolean;\n /** Ids of entities with unsaved changes right now. */\n get dirtyEntities(): string[];\n /** Fires with the current `dirtyEntities` list every time it changes. */\n readonly onDirtyChange: OBC.Event<string[]>;\n private _markDirty;\n private _client?;\n private _fileId?;\n private _data;\n private _saveTimer?;\n private _savePromise?;\n private _scheduleSave;\n private _queueSave;\n private _doSave;\n /**\n * Cancels the pending debounce (if any) and runs the save immediately.\n * Also the only way to persist an entity that marks itself dirty WITHOUT\n * auto-scheduling (currently just `origin`) — call this once the user\n * explicitly confirms. Awaits completion.\n */\n flush(): Promise<void>;\n init(client: PlatformClient): Promise<void>;\n /**\n * NOT auto-saving, unlike every other entity below — `set`/`update` mark it\n * dirty and fire `onChange` immediately, but leave persisting up to an\n * explicit `flush()` call. This is what lets a continuous interaction (e.g.\n * a drag gizmo) update `origin` every frame — live for anyone listening to\n * `onChange` — without writing to the network on every tick, while still\n * surfacing \"there's an unconfirmed change\" via `dirty`/`onDirtyChange` for\n * a UI to gate behind an explicit save action.\n */\n origin: ReactiveSingletonEntity<OriginData>;\n crs: ReactiveSingletonEntity<CrsData>;\n graphicsSettings: SingletonEntity<GraphicsSettingsData>;\n assetCoordinates: AssetCoordinatesEntity;\n getNamespaces(): Record<ProjectNamespaceKey, ProjectNamespace>;\n getNamespace(key: ProjectNamespaceKey): Record<string, unknown>;\n}\n\n/**\n * ProjectManager is the platform's canonical store for project-level\n * configuration and data — origin/georeferencing/app-settings today, with\n * room to grow. It persists a single JSON file (`${ProjectManager.uuid}.json`)\n * loose directly inside `__project_data` (same folder convention `GISManager`\n * already used) — NOT in a per-app subfolder like `collider`/`cde`, which are\n * for secondary, per-builtin data. Sharing that root folder with other\n * builtins doesn't change its role: it's still the one canonical project\n * record, meant to stop each builtin from inventing its own ad-hoc\n * project-persistence pattern.\n *\n * Schema shape (see `src/types.ts` for the full rationale):\n * - `namespaces`/`entities` are maps keyed by a fixed, readable slug — a\n * closed set this code defines, never created at runtime.\n * - `origin`/`crs`/`graphicsSettings` are singletons; `assetCoordinates` is\n * a collection.\n * - `entities[id]` is a uniform envelope: `namespaceId`, mandatory `label`,\n * optional `description` (omitted, not stored empty), free-form `data`.\n */\nexport type ProjectManager = InstanceType<typeof _ProjectManager>;\n/**\n * ProjectManager is the platform's canonical store for project-level\n * configuration and data — origin/georeferencing/app-settings today, with\n * room to grow. It persists a single JSON file (`${ProjectManager.uuid}.json`)\n * loose directly inside `__project_data` (same folder convention `GISManager`\n * already used) — NOT in a per-app subfolder like `collider`/`cde`, which are\n * for secondary, per-builtin data. Sharing that root folder with other\n * builtins doesn't change its role: it's still the one canonical project\n * record, meant to stop each builtin from inventing its own ad-hoc\n * project-persistence pattern.\n *\n * Schema shape (see `src/types.ts` for the full rationale):\n * - `namespaces`/`entities` are maps keyed by a fixed, readable slug — a\n * closed set this code defines, never created at runtime.\n * - `origin`/`crs`/`graphicsSettings` are singletons; `assetCoordinates` is\n * a collection.\n * - `entities[id]` is a uniform envelope: `namespaceId`, mandatory `label`,\n * optional `description` (omitted, not stored empty), free-form `data`.\n */\nexport const ProjectManager = { uuid: '6f3a9c2e-8b1d-4e6a-9c3f-1d7b5a8e2c4f' } as typeof _ProjectManager & { uuid: '6f3a9c2e-8b1d-4e6a-9c3f-1d7b5a8e2c4f' };\n\n/** `main.bcf`'s path relative to `__project_data/` — shared with\n * `requestBcfSave` (`UIManager/src/utils/bcf-storage.ts`) so both sides of\n * the save/load round-trip agree on where the file lives. */\nexport declare const BCF_DATA_PATH = \"topics/main.bcf\";\n/** Downloads `__project_data/topics/main.bcf` and loads it into `BCFTopics`,\n * if it already has content. A freshly-created file is empty (0 bytes) —\n * not a valid BCF zip — so there's nothing to load yet in that case. */\nexport declare function loadBcfTopics(client: PlatformClient, projectId: string, components: OBC.Components): Promise<void>;\n\n\n/**\n * Wires up everything `top-topics-panel` (and `clashes-panel`'s \"create\n * topic from clash\" feature) needs to work out of the box: `BCFTopics`\n * configuration (version, author, assignable users — all from real project\n * data), loading whatever BCF was previously saved for this project, and\n * resolving `Viewpoints.world` — including backfilling it onto viewpoints\n * restored from a saved BCF before the 3D world existed yet (`top-viewer`\n * only creates its `World` once `top-app` finishes mounting, which is later\n * than `init()` typically runs).\n */\ndeclare class _TopicsManager extends OBC.Component {\n static readonly uuid: \"69af63aa-19ba-4fc7-b17b-75647bac1d76\";\n enabled: boolean;\n /**\n * Consumer apps call this once — same pattern as `ClashesManager.init(client)`\n * — instead of wiring `BCFTopics.setup()`, loading the saved BCF, and\n * backfilling viewpoint worlds by hand.\n */\n init(client: PlatformClient): Promise<void>;\n private _firstWorld;\n}\n\n/**\n * Wires up everything `top-topics-panel` (and `clashes-panel`'s \"create\n * topic from clash\" feature) needs to work out of the box: `BCFTopics`\n * configuration (version, author, assignable users — all from real project\n * data), loading whatever BCF was previously saved for this project, and\n * resolving `Viewpoints.world` — including backfilling it onto viewpoints\n * restored from a saved BCF before the 3D world existed yet (`top-viewer`\n * only creates its `World` once `top-app` finishes mounting, which is later\n * than `init()` typically runs).\n */\nexport type TopicsManager = InstanceType<typeof _TopicsManager>;\n/**\n * Wires up everything `top-topics-panel` (and `clashes-panel`'s \"create\n * topic from clash\" feature) needs to work out of the box: `BCFTopics`\n * configuration (version, author, assignable users — all from real project\n * data), loading whatever BCF was previously saved for this project, and\n * resolving `Viewpoints.world` — including backfilling it onto viewpoints\n * restored from a saved BCF before the 3D world existed yet (`top-viewer`\n * only creates its `World` once `top-app` finishes mounting, which is later\n * than `init()` typically runs).\n */\nexport const TopicsManager = { uuid: '69af63aa-19ba-4fc7-b17b-75647bac1d76' } as typeof _TopicsManager & { uuid: '69af63aa-19ba-4fc7-b17b-75647bac1d76' };\n\ndeclare class _UIManager extends OBC.Component {\n #private;\n static readonly uuid: \"234f1416-528d-452a-9cc9-a16c5239b2eb\";\n enabled: boolean;\n readonly name = \"UIManager\";\n init(): void;\n}\n\nexport type UIManager = InstanceType<typeof _UIManager>;\nexport const UIManager = { uuid: '234f1416-528d-452a-9cc9-a16c5239b2eb' } as typeof _UIManager & { uuid: '234f1416-528d-452a-9cc9-a16c5239b2eb' };\n"],"names":["PACKET_TYPES","PACKET_TYPES_REVERSE","key","ERROR_PACKET","withNativeBlob","withNativeArrayBuffer","isView","obj","encodePacket","type","data","supportsBinary","callback","encodeBlobAsBase64","fileReader","content","toArray","TEXT_ENCODER","encodePacketToBinary","packet","encoded","chars","lookup","i","decode","base64","bufferLength","len","p","encoded1","encoded2","encoded3","encoded4","arraybuffer","bytes","decodePacket","encodedPacket","binaryType","mapBinary","decodeBase64Packet","decoded","SEPARATOR","encodePayload","packets","length","encodedPackets","count","decodePayload","encodedPayload","decodedPacket","createPacketEncoderStream","controller","payloadLength","header","view","TEXT_DECODER","totalLength","chunks","acc","chunk","concatChunks","size","buffer","j","createPacketDecoderStream","maxPayload","state","expectedLength","isBinary","headerArray","n","protocol","Emitter","mixin","event","fn","on","callbacks","cb","args","nextTick","setTimeoutFn","globalThisShim","defaultBinaryType","pick","attr","k","NATIVE_SET_TIMEOUT","globalThis","NATIVE_CLEAR_TIMEOUT","installTimerFunctions","opts","BASE64_OVERHEAD","byteLength","utf8Length","str","c","l","randomString","encode","qs","qry","pairs","pair","TransportError","reason","description","context","Transport","details","onPause","schema","query","hostname","encodedQuery","Polling","pause","total","close","value","hasCORS","empty","BaseXHR","isSSL","port","req","xhrStatus","Request","createRequest","uri","_a","xhr","e","err","fromError","unloadHandler","terminationEvent","hasXHR2","newRequest","XHR","forceBase64","xdomain","isReactNative","BaseWS","protocols","closeEvent","ev","lastPacket","WebSocketCtor","WS","_packet","WT","stream","decoderStream","reader","encoderStream","read","done","transports","re","parts","parse","src","b","m","pathNames","queryKey","path","regx","names","$0","$1","$2","withEventListeners","OFFLINE_EVENT_LISTENERS","listener","SocketWithoutUpgrade","parsedUri","t","transportName","name","transport","delay","payloadSize","hasExpired","msg","options","cleanupAndClose","waitForUpgrade","SocketWithUpgrade","failed","onTransportOpen","cleanup","freezeTransport","onerror","error","onTransportClose","onclose","onupgrade","to","upgrades","filteredUpgrades","isOptionsOnly","o","DEFAULT_TRANSPORTS","url","loc","host","toString","withNativeFile","hasBinary","toJSON","deconstructPacket","buffers","packetData","pack","_deconstructPacket","placeholder","newData","reconstructPacket","_reconstructPacket","RESERVED_EVENTS","PacketType","Encoder","replacer","deconstruction","Decoder","isBinaryEvent","BinaryReconstructor","start","buf","isInteger","next","payload","isObject","binData","Socket","io","nsp","_b","_c","id","ack","isTransportWritable","isConnected","timeout","timer","resolve","reject","arg1","arg2","responseArgs","force","listeners","self","sent","pid","subDestroy","compress","Backoff","ms","rand","deviation","min","max","jitter","Manager","_parser","parser","v","Engine","socket","openSubDestroy","onError","errorSub","nsps","attempt","cache","parsed","source","sameNamespace","newConnection","DOCUMENT_SCHEMA","DOCUMENT_FILE","SELF_VIEWING_FORMATS","versionTag","idOf","item","_ProjectDocuments_instances","derivedFileId_fn","descriptorFile_fn","ProjectDocuments","client","projectId","__privateAdd","folders","folder","folderId","descriptor","d","fileId","fileName","format","formatOf","views","derivedId","__privateMethod","derived","file","text","normalize","formats","match","blob","existing","versions","a","version","metadata","found","extension","fromExt","dot","raw","native","hasNative","StaleHistoryError","expectedGuid","actualGuid","ROOT_FOLDER","HISTORY_FILE","OPS_FILE","OPS_SCHEMA","LEGACY_MODEL_FILE","INTERNAL_PREFIX","LOCKS_ANCHOR","childrenOf","parentId","f","_rootFolderId","_ProjectHistory_instances","root_fn","ProjectHistory","root","docs","dash","model","hasAny","docId","FlowDoc","create","__privateGet","made","__privateSet","_folderId","_FlowDoc_instances","documents_get","folderName_get","folder_fn","files_fn","file_fn","modelFile_fn","readJson_fn","readHistory_fn","readOps_fn","writeJson_fn","createJson_fn","writeModel_fn","project","history","orderByGraph","timeline","anchor","metas","claims","meta","response","taken","byOwner","claim","list","owner","elements","input","head","lastByGraph","mintGuid","tally","modelFile","hidden","fresh","freshHead","ops","op","index","indexFile","suggestion","holder","opId","outcome","rootId","files","created","changes","counts","change","byGuid","children","roots","parent","byTime","ordered","stack","seen","anyCrypto","r","_registry","_Recipes_instances","execute_fn","Recipes","recipe","filter","base","result","plan","targetDoc","STORAGE_BATCH_MAX","parseErrorBody","body","json","retryAfterFromDetails","RequestError","status","statusText","retryAfter","__publicField","FOLDER_PATH","ITEM_PATH","PROCESS_PATH","NPM_REGISTRY_PATH","HIDDEN_PATH","ITEM_TYPE_FILE","ITEM_TYPE_COMPONENT","ITEM_TYPE_APP","RETRY_BASE_DELAY_MS","RETRY_MAX_DELAY_MS","RETRY_JITTER_RATIO","sleep","parseRetryAfter","seconds","timestamp","isRetryable","retryDelayMs","backoff","serverDelay","_EngineServicesClient_instances","buildUrl_fn","requestApi_fn","requestFile_fn","_recipes","requestBatches_fn","downloadItem_fn","createItem_fn","updateItem_fn","getItem_fn","cleanData_fn","_EngineServicesClient","accessToken","apiUrl","props","retries","useBearer","localServerUrl","lsUrl","ctx","globals","method","requestData","filters","archived","fileData","params","withDraft","entries","parentFolderId","folderIds","updateFolderParams","ShowVersions","componentId","componentData","componentProps","component","components","resolvedGlobals","keys","values","main","componentDefinition","stubs","builtIns","OBC","BUI","code","appData","appProps","appId","executionParams","executionId","onUpdateCallback","wsUrl","parentFileId","tag","formData","hiddenId","expiresIn","hiddenIds","itemId","icon","extraProps","itemIds","contentType","responseType","retryAttempt","cleanQuery","token","textResponse","retriesLeft","inputs","requestChunk","itemType","parsedBody","showVersions","EngineServicesClient","windowTransport","message","handler","SYSTEM_PREFIX","JOIN_TIMEOUT_MS","guard","_joined","_peers","_pending","_onChange","_onPeerJoined","_onPeerLeft","_ChannelRoom_instances","request_fn","settle_fn","changed_fn","ChannelRoom","controls","peers","peer","from","pending","want","control","entry","_listeners","CollabRoom","set","scope","metaOf","_handlers","ExternalRoom","kind","readMessage","envelope","_transport","_stop","_collab","_externals","_answered","_ChannelClient_instances","rooms_fn","exact_fn","receive_fn","system_fn","deliver_fn","reply_fn","ChannelClient","room","info","rooms","answered","requestId","PROJECT_PATH","NOTIFICATION_PATH","_tokenProvider","_channel","_PlatformClient","accountId","checks","notificationIds","hookId","onEvent","PlatformClient","readFrag","flatbuffers","loadFragDependencies","inflate","guidByLocalId","guid","items","localId","attrs","attribute","triple","cause","RESERVED","OP_KEY","SOURCE_KEY","OP_SCHEMA","CATEGORY_CHANGE","CATEGORY_OPERATION","OperationBuilder","target","placement","kinds","loadDependencies","deflate","out","num","verb","Attribute","Meshes","Model","SpatialStructure","Transform","containerId","emptyOffsets","shells","circleExtrusions","samples","representations","materials","localTransforms","globalTransforms","meshesItems","materialIds","representationIds","sampleIds","localTransformIds","globalTransformIds","meshes","metadataOffset","unique","attributeOffsets","triples","attributes","uniqueAttributes","s","categoryOffsets","categories","guidOffsets","guidItems","guids","guidsItems","localIds","leaves","_","spatial","modelGuid","ELEMENT_FIELD","CARRIED_FIELD","FEET_PER_METRE","recordsOf","records","field","one","record","innerJson","param","levelNames","named","whatItMadeBefore","author","applied","ids","readPickedFrag","picked","DEGREES","familyAndType","lookRef","colon","sharedRun","contents","columnType","trustStyleNames","includeInstances","levels","operation","sourceKey","columns","instances","bodies","propose","position","rotationDeg","at","family","level","right","rotation","removed","madeId","words","sharedSchema","sharedRules","fragToRevit","ifcToRevit","METRES_PER_UNIT","NAME","AUTHOR","positionOf","part","rhinoToRevit","layer","instanceType","declared","metres","axes","scale","added","moved","elsewhere","moves","instance","move","object","builtinRecipes","registerBuiltinRecipes","METADATA_LIMITS","CDEManager","ClashesManager","FileList","GISManager","GitHistoryManager","HelloWorld","ProjectManager","TopicsManager","UIManager"],"mappings":"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","x_google_ignoreList":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26]}