'use client';
import { g as getDefaultExportFromCjs } from './protobuf-OcbVtxg1.js';
import require$$0 from 'ms';

var eventemitter3 = {exports: {}};

(function (module) {

	var has = Object.prototype.hasOwnProperty
	  , prefix = '~';

	/**
	 * Constructor to create a storage for our `EE` objects.
	 * An `Events` instance is a plain object whose properties are event names.
	 *
	 * @constructor
	 * @private
	 */
	function Events() {}

	//
	// We try to not inherit from `Object.prototype`. In some engines creating an
	// instance in this way is faster than calling `Object.create(null)` directly.
	// If `Object.create(null)` is not supported we prefix the event names with a
	// character to make sure that the built-in object properties are not
	// overridden or used as an attack vector.
	//
	if (Object.create) {
	  Events.prototype = Object.create(null);

	  //
	  // This hack is needed because the `__proto__` property is still inherited in
	  // some old browsers like Android 4, iPhone 5.1, Opera 11 and Safari 5.
	  //
	  if (!new Events().__proto__) prefix = false;
	}

	/**
	 * Representation of a single event listener.
	 *
	 * @param {Function} fn The listener function.
	 * @param {*} context The context to invoke the listener with.
	 * @param {Boolean} [once=false] Specify if the listener is a one-time listener.
	 * @constructor
	 * @private
	 */
	function EE(fn, context, once) {
	  this.fn = fn;
	  this.context = context;
	  this.once = once || false;
	}

	/**
	 * Add a listener for a given event.
	 *
	 * @param {EventEmitter} emitter Reference to the `EventEmitter` instance.
	 * @param {(String|Symbol)} event The event name.
	 * @param {Function} fn The listener function.
	 * @param {*} context The context to invoke the listener with.
	 * @param {Boolean} once Specify if the listener is a one-time listener.
	 * @returns {EventEmitter}
	 * @private
	 */
	function addListener(emitter, event, fn, context, once) {
	  if (typeof fn !== 'function') {
	    throw new TypeError('The listener must be a function');
	  }

	  var listener = new EE(fn, context || emitter, once)
	    , evt = prefix ? prefix + event : event;

	  if (!emitter._events[evt]) emitter._events[evt] = listener, emitter._eventsCount++;
	  else if (!emitter._events[evt].fn) emitter._events[evt].push(listener);
	  else emitter._events[evt] = [emitter._events[evt], listener];

	  return emitter;
	}

	/**
	 * Clear event by name.
	 *
	 * @param {EventEmitter} emitter Reference to the `EventEmitter` instance.
	 * @param {(String|Symbol)} evt The Event name.
	 * @private
	 */
	function clearEvent(emitter, evt) {
	  if (--emitter._eventsCount === 0) emitter._events = new Events();
	  else delete emitter._events[evt];
	}

	/**
	 * Minimal `EventEmitter` interface that is molded against the Node.js
	 * `EventEmitter` interface.
	 *
	 * @constructor
	 * @public
	 */
	function EventEmitter() {
	  this._events = new Events();
	  this._eventsCount = 0;
	}

	/**
	 * Return an array listing the events for which the emitter has registered
	 * listeners.
	 *
	 * @returns {Array}
	 * @public
	 */
	EventEmitter.prototype.eventNames = function eventNames() {
	  var names = []
	    , events
	    , name;

	  if (this._eventsCount === 0) return names;

	  for (name in (events = this._events)) {
	    if (has.call(events, name)) names.push(prefix ? name.slice(1) : name);
	  }

	  if (Object.getOwnPropertySymbols) {
	    return names.concat(Object.getOwnPropertySymbols(events));
	  }

	  return names;
	};

	/**
	 * Return the listeners registered for a given event.
	 *
	 * @param {(String|Symbol)} event The event name.
	 * @returns {Array} The registered listeners.
	 * @public
	 */
	EventEmitter.prototype.listeners = function listeners(event) {
	  var evt = prefix ? prefix + event : event
	    , handlers = this._events[evt];

	  if (!handlers) return [];
	  if (handlers.fn) return [handlers.fn];

	  for (var i = 0, l = handlers.length, ee = new Array(l); i < l; i++) {
	    ee[i] = handlers[i].fn;
	  }

	  return ee;
	};

	/**
	 * Return the number of listeners listening to a given event.
	 *
	 * @param {(String|Symbol)} event The event name.
	 * @returns {Number} The number of listeners.
	 * @public
	 */
	EventEmitter.prototype.listenerCount = function listenerCount(event) {
	  var evt = prefix ? prefix + event : event
	    , listeners = this._events[evt];

	  if (!listeners) return 0;
	  if (listeners.fn) return 1;
	  return listeners.length;
	};

	/**
	 * Calls each of the listeners registered for a given event.
	 *
	 * @param {(String|Symbol)} event The event name.
	 * @returns {Boolean} `true` if the event had listeners, else `false`.
	 * @public
	 */
	EventEmitter.prototype.emit = function emit(event, a1, a2, a3, a4, a5) {
	  var evt = prefix ? prefix + event : event;

	  if (!this._events[evt]) return false;

	  var listeners = this._events[evt]
	    , len = arguments.length
	    , args
	    , i;

	  if (listeners.fn) {
	    if (listeners.once) this.removeListener(event, listeners.fn, undefined, true);

	    switch (len) {
	      case 1: return listeners.fn.call(listeners.context), true;
	      case 2: return listeners.fn.call(listeners.context, a1), true;
	      case 3: return listeners.fn.call(listeners.context, a1, a2), true;
	      case 4: return listeners.fn.call(listeners.context, a1, a2, a3), true;
	      case 5: return listeners.fn.call(listeners.context, a1, a2, a3, a4), true;
	      case 6: return listeners.fn.call(listeners.context, a1, a2, a3, a4, a5), true;
	    }

	    for (i = 1, args = new Array(len -1); i < len; i++) {
	      args[i - 1] = arguments[i];
	    }

	    listeners.fn.apply(listeners.context, args);
	  } else {
	    var length = listeners.length
	      , j;

	    for (i = 0; i < length; i++) {
	      if (listeners[i].once) this.removeListener(event, listeners[i].fn, undefined, true);

	      switch (len) {
	        case 1: listeners[i].fn.call(listeners[i].context); break;
	        case 2: listeners[i].fn.call(listeners[i].context, a1); break;
	        case 3: listeners[i].fn.call(listeners[i].context, a1, a2); break;
	        case 4: listeners[i].fn.call(listeners[i].context, a1, a2, a3); break;
	        default:
	          if (!args) for (j = 1, args = new Array(len -1); j < len; j++) {
	            args[j - 1] = arguments[j];
	          }

	          listeners[i].fn.apply(listeners[i].context, args);
	      }
	    }
	  }

	  return true;
	};

	/**
	 * Add a listener for a given event.
	 *
	 * @param {(String|Symbol)} event The event name.
	 * @param {Function} fn The listener function.
	 * @param {*} [context=this] The context to invoke the listener with.
	 * @returns {EventEmitter} `this`.
	 * @public
	 */
	EventEmitter.prototype.on = function on(event, fn, context) {
	  return addListener(this, event, fn, context, false);
	};

	/**
	 * Add a one-time listener for a given event.
	 *
	 * @param {(String|Symbol)} event The event name.
	 * @param {Function} fn The listener function.
	 * @param {*} [context=this] The context to invoke the listener with.
	 * @returns {EventEmitter} `this`.
	 * @public
	 */
	EventEmitter.prototype.once = function once(event, fn, context) {
	  return addListener(this, event, fn, context, true);
	};

	/**
	 * Remove the listeners of a given event.
	 *
	 * @param {(String|Symbol)} event The event name.
	 * @param {Function} fn Only remove the listeners that match this function.
	 * @param {*} context Only remove the listeners that have this context.
	 * @param {Boolean} once Only remove one-time listeners.
	 * @returns {EventEmitter} `this`.
	 * @public
	 */
	EventEmitter.prototype.removeListener = function removeListener(event, fn, context, once) {
	  var evt = prefix ? prefix + event : event;

	  if (!this._events[evt]) return this;
	  if (!fn) {
	    clearEvent(this, evt);
	    return this;
	  }

	  var listeners = this._events[evt];

	  if (listeners.fn) {
	    if (
	      listeners.fn === fn &&
	      (!once || listeners.once) &&
	      (!context || listeners.context === context)
	    ) {
	      clearEvent(this, evt);
	    }
	  } else {
	    for (var i = 0, events = [], length = listeners.length; i < length; i++) {
	      if (
	        listeners[i].fn !== fn ||
	        (once && !listeners[i].once) ||
	        (context && listeners[i].context !== context)
	      ) {
	        events.push(listeners[i]);
	      }
	    }

	    //
	    // Reset the array, or remove it completely if we have no more listeners.
	    //
	    if (events.length) this._events[evt] = events.length === 1 ? events[0] : events;
	    else clearEvent(this, evt);
	  }

	  return this;
	};

	/**
	 * Remove all listeners, or those of the specified event.
	 *
	 * @param {(String|Symbol)} [event] The event name.
	 * @returns {EventEmitter} `this`.
	 * @public
	 */
	EventEmitter.prototype.removeAllListeners = function removeAllListeners(event) {
	  var evt;

	  if (event) {
	    evt = prefix ? prefix + event : event;
	    if (this._events[evt]) clearEvent(this, evt);
	  } else {
	    this._events = new Events();
	    this._eventsCount = 0;
	  }

	  return this;
	};

	//
	// Alias methods names because people roll like that.
	//
	EventEmitter.prototype.off = EventEmitter.prototype.removeListener;
	EventEmitter.prototype.addListener = EventEmitter.prototype.on;

	//
	// Expose the prefix.
	//
	EventEmitter.prefixed = prefix;

	//
	// Allow `EventEmitter` to be imported as module namespace.
	//
	EventEmitter.EventEmitter = EventEmitter;

	//
	// Expose the module.
	//
	{
	  module.exports = EventEmitter;
	} 
} (eventemitter3));

var eventemitter3Exports = eventemitter3.exports;
var EventEmitter = /*@__PURE__*/getDefaultExportFromCjs(eventemitter3Exports);

var BinaryOpcode;
(function (BinaryOpcode) {
    BinaryOpcode[BinaryOpcode["MESSAGE_DATA"] = 1] = "MESSAGE_DATA";
    BinaryOpcode[BinaryOpcode["TIME"] = 2] = "TIME";
    BinaryOpcode[BinaryOpcode["SERVICE_CALL_RESPONSE"] = 3] = "SERVICE_CALL_RESPONSE";
    BinaryOpcode[BinaryOpcode["FETCH_ASSET_RESPONSE"] = 4] = "FETCH_ASSET_RESPONSE";
})(BinaryOpcode || (BinaryOpcode = {}));
var ClientBinaryOpcode;
(function (ClientBinaryOpcode) {
    ClientBinaryOpcode[ClientBinaryOpcode["MESSAGE_DATA"] = 1] = "MESSAGE_DATA";
    ClientBinaryOpcode[ClientBinaryOpcode["SERVICE_CALL_REQUEST"] = 2] = "SERVICE_CALL_REQUEST";
})(ClientBinaryOpcode || (ClientBinaryOpcode = {}));
var StatusLevel;
(function (StatusLevel) {
    StatusLevel[StatusLevel["INFO"] = 0] = "INFO";
    StatusLevel[StatusLevel["WARNING"] = 1] = "WARNING";
    StatusLevel[StatusLevel["ERROR"] = 2] = "ERROR";
})(StatusLevel || (StatusLevel = {}));
var ServerCapability;
(function (ServerCapability) {
    ServerCapability["clientPublish"] = "clientPublish";
    ServerCapability["time"] = "time";
    ServerCapability["parameters"] = "parameters";
    ServerCapability["parametersSubscribe"] = "parametersSubscribe";
    ServerCapability["services"] = "services";
    ServerCapability["connectionGraph"] = "connectionGraph";
    ServerCapability["assets"] = "assets";
})(ServerCapability || (ServerCapability = {}));
var FetchAssetStatus;
(function (FetchAssetStatus) {
    FetchAssetStatus[FetchAssetStatus["SUCCESS"] = 0] = "SUCCESS";
    FetchAssetStatus[FetchAssetStatus["ERROR"] = 1] = "ERROR";
})(FetchAssetStatus || (FetchAssetStatus = {}));

const textDecoder = new TextDecoder();
function parseServerMessage(buffer) {
    const view = new DataView(buffer);
    let offset = 0;
    const op = view.getUint8(offset);
    offset += 1;
    switch (op) {
        case BinaryOpcode.MESSAGE_DATA: {
            const subscriptionId = view.getUint32(offset, true);
            offset += 4;
            const timestamp = view.getBigUint64(offset, true);
            offset += 8;
            const data = new DataView(buffer, offset);
            return { op, subscriptionId, timestamp, data };
        }
        case BinaryOpcode.TIME: {
            const timestamp = view.getBigUint64(offset, true);
            return { op, timestamp };
        }
        case BinaryOpcode.SERVICE_CALL_RESPONSE: {
            const serviceId = view.getUint32(offset, true);
            offset += 4;
            const callId = view.getUint32(offset, true);
            offset += 4;
            const encodingLength = view.getUint32(offset, true);
            offset += 4;
            const encodingBytes = new DataView(buffer, offset, encodingLength);
            const encoding = textDecoder.decode(encodingBytes);
            offset += encodingLength;
            const data = new DataView(buffer, offset, buffer.byteLength - offset);
            return { op, serviceId, callId, encoding, data };
        }
        case BinaryOpcode.FETCH_ASSET_RESPONSE: {
            const requestId = view.getUint32(offset, true);
            offset += 4;
            const status = view.getUint8(offset);
            offset += 1;
            const errorMsgLength = view.getUint32(offset, true);
            offset += 4;
            const error = textDecoder.decode(new DataView(buffer, offset, errorMsgLength));
            offset += errorMsgLength;
            switch (status) {
                case FetchAssetStatus.SUCCESS: {
                    const data = new DataView(buffer, offset, buffer.byteLength - offset);
                    return { op, requestId, status, data };
                }
                case FetchAssetStatus.ERROR:
                    return { op, requestId, status, error };
                default:
                    throw new Error(`Unrecognized fetch asset status: ${status}`);
            }
        }
    }
    throw new Error(`Unrecognized server opcode in binary message: ${op.toString(16)}`);
}

const textEncoder = new TextEncoder();
class FoxgloveClient {
    static SUPPORTED_SUBPROTOCOL = "foxglove.websocket.v1";
    #emitter = new EventEmitter();
    #ws;
    #nextSubscriptionId = 0;
    #nextAdvertisementId = 0;
    constructor({ ws }) {
        this.#ws = ws;
        this.#reconnect();
    }
    on(name, listener) {
        this.#emitter.on(name, listener);
    }
    off(name, listener) {
        this.#emitter.off(name, listener);
    }
    #reconnect() {
        this.#ws.binaryType = "arraybuffer";
        this.#ws.onerror = (event) => {
            this.#emitter.emit("error", event.error);
        };
        this.#ws.onopen = (_event) => {
            if (this.#ws.protocol !== FoxgloveClient.SUPPORTED_SUBPROTOCOL) {
                throw new Error(`Expected subprotocol ${FoxgloveClient.SUPPORTED_SUBPROTOCOL}, got '${this.#ws.protocol}'`);
            }
            this.#emitter.emit("open");
        };
        this.#ws.onmessage = (event) => {
            let message;
            try {
                if (event.data instanceof ArrayBuffer) {
                    message = parseServerMessage(event.data);
                }
                else {
                    message = JSON.parse(event.data);
                }
            }
            catch (error) {
                this.#emitter.emit("error", error);
                return;
            }
            switch (message.op) {
                case "serverInfo":
                    this.#emitter.emit("serverInfo", message);
                    return;
                case "status":
                    this.#emitter.emit("status", message);
                    return;
                case "advertise":
                    this.#emitter.emit("advertise", message.channels);
                    return;
                case "unadvertise":
                    this.#emitter.emit("unadvertise", message.channelIds);
                    return;
                case "parameterValues":
                    this.#emitter.emit("parameterValues", message);
                    return;
                case "advertiseServices":
                    this.#emitter.emit("advertiseServices", message.services);
                    return;
                case "unadvertiseServices":
                    this.#emitter.emit("unadvertiseServices", message.serviceIds);
                    return;
                case "connectionGraphUpdate":
                    this.#emitter.emit("connectionGraphUpdate", message);
                    return;
                case BinaryOpcode.MESSAGE_DATA:
                    this.#emitter.emit("message", message);
                    return;
                case BinaryOpcode.TIME:
                    this.#emitter.emit("time", message);
                    return;
                case BinaryOpcode.SERVICE_CALL_RESPONSE:
                    this.#emitter.emit("serviceCallResponse", message);
                    return;
                case BinaryOpcode.FETCH_ASSET_RESPONSE:
                    this.#emitter.emit("fetchAssetResponse", message);
                    return;
            }
            this.#emitter.emit("error", new Error(`Unrecognized server opcode: ${message.op}`));
        };
        this.#ws.onclose = (event) => {
            this.#emitter.emit("close", event);
        };
    }
    close() {
        this.#ws.close();
    }
    subscribe(channelId) {
        const id = this.#nextSubscriptionId++;
        const subscriptions = [{ id, channelId }];
        this.#send({ op: "subscribe", subscriptions });
        return id;
    }
    unsubscribe(subscriptionId) {
        this.#send({ op: "unsubscribe", subscriptionIds: [subscriptionId] });
    }
    advertise(clientChannel) {
        const id = ++this.#nextAdvertisementId;
        const channels = [{ id, ...clientChannel }];
        this.#send({ op: "advertise", channels });
        return id;
    }
    unadvertise(channelId) {
        this.#send({ op: "unadvertise", channelIds: [channelId] });
    }
    getParameters(parameterNames, id) {
        this.#send({ op: "getParameters", parameterNames, id });
    }
    setParameters(parameters, id) {
        this.#send({ op: "setParameters", parameters, id });
    }
    subscribeParameterUpdates(parameterNames) {
        this.#send({ op: "subscribeParameterUpdates", parameterNames });
    }
    unsubscribeParameterUpdates(parameterNames) {
        this.#send({ op: "unsubscribeParameterUpdates", parameterNames });
    }
    sendMessage(channelId, data) {
        const payload = new Uint8Array(5 + data.byteLength);
        const view = new DataView(payload.buffer, payload.byteOffset, payload.byteLength);
        view.setUint8(0, ClientBinaryOpcode.MESSAGE_DATA);
        view.setUint32(1, channelId, true);
        payload.set(data, 5);
        this.#ws.send(payload);
    }
    sendServiceCallRequest(request) {
        const encoding = textEncoder.encode(request.encoding);
        const payload = new Uint8Array(1 + 4 + 4 + 4 + encoding.length + request.data.byteLength);
        const view = new DataView(payload.buffer, payload.byteOffset, payload.byteLength);
        let offset = 0;
        view.setUint8(offset, ClientBinaryOpcode.SERVICE_CALL_REQUEST);
        offset += 1;
        view.setUint32(offset, request.serviceId, true);
        offset += 4;
        view.setUint32(offset, request.callId, true);
        offset += 4;
        view.setUint32(offset, request.encoding.length, true);
        offset += 4;
        payload.set(encoding, offset);
        offset += encoding.length;
        const data = new Uint8Array(request.data.buffer, request.data.byteOffset, request.data.byteLength);
        payload.set(data, offset);
        this.#ws.send(payload);
    }
    subscribeConnectionGraph() {
        this.#send({ op: "subscribeConnectionGraph" });
    }
    unsubscribeConnectionGraph() {
        this.#send({ op: "unsubscribeConnectionGraph" });
    }
    fetchAsset(uri, requestId) {
        this.#send({ op: "fetchAsset", uri, requestId });
    }
    /**
     * @deprecated Use `sendServiceCallRequest` instead
     */
    sendCallServiceRequest(request) {
        this.sendServiceCallRequest(request);
    }
    #send(message) {
        this.#ws.send(JSON.stringify(message));
    }
}

var browser = {exports: {}};

/**
 * This is the common logic for both the Node.js and web browser
 * implementations of `debug()`.
 */

function setup(env) {
	createDebug.debug = createDebug;
	createDebug.default = createDebug;
	createDebug.coerce = coerce;
	createDebug.disable = disable;
	createDebug.enable = enable;
	createDebug.enabled = enabled;
	createDebug.humanize = require$$0;
	createDebug.destroy = destroy;

	Object.keys(env).forEach(key => {
		createDebug[key] = env[key];
	});

	/**
	* The currently active debug mode names, and names to skip.
	*/

	createDebug.names = [];
	createDebug.skips = [];

	/**
	* Map of special "%n" handling functions, for the debug "format" argument.
	*
	* Valid key names are a single, lower or upper-case letter, i.e. "n" and "N".
	*/
	createDebug.formatters = {};

	/**
	* Selects a color for a debug namespace
	* @param {String} namespace The namespace string for the debug instance to be colored
	* @return {Number|String} An ANSI color code for the given namespace
	* @api private
	*/
	function selectColor(namespace) {
		let hash = 0;

		for (let i = 0; i < namespace.length; i++) {
			hash = ((hash << 5) - hash) + namespace.charCodeAt(i);
			hash |= 0; // Convert to 32bit integer
		}

		return createDebug.colors[Math.abs(hash) % createDebug.colors.length];
	}
	createDebug.selectColor = selectColor;

	/**
	* Create a debugger with the given `namespace`.
	*
	* @param {String} namespace
	* @return {Function}
	* @api public
	*/
	function createDebug(namespace) {
		let prevTime;
		let enableOverride = null;
		let namespacesCache;
		let enabledCache;

		function debug(...args) {
			// Disabled?
			if (!debug.enabled) {
				return;
			}

			const self = debug;

			// Set `diff` timestamp
			const curr = Number(new Date());
			const ms = curr - (prevTime || curr);
			self.diff = ms;
			self.prev = prevTime;
			self.curr = curr;
			prevTime = curr;

			args[0] = createDebug.coerce(args[0]);

			if (typeof args[0] !== 'string') {
				// Anything else let's inspect with %O
				args.unshift('%O');
			}

			// Apply any `formatters` transformations
			let index = 0;
			args[0] = args[0].replace(/%([a-zA-Z%])/g, (match, format) => {
				// If we encounter an escaped % then don't increase the array index
				if (match === '%%') {
					return '%';
				}
				index++;
				const formatter = createDebug.formatters[format];
				if (typeof formatter === 'function') {
					const val = args[index];
					match = formatter.call(self, val);

					// Now we need to remove `args[index]` since it's inlined in the `format`
					args.splice(index, 1);
					index--;
				}
				return match;
			});

			// Apply env-specific formatting (colors, etc.)
			createDebug.formatArgs.call(self, args);

			const logFn = self.log || createDebug.log;
			logFn.apply(self, args);
		}

		debug.namespace = namespace;
		debug.useColors = createDebug.useColors();
		debug.color = createDebug.selectColor(namespace);
		debug.extend = extend;
		debug.destroy = createDebug.destroy; // XXX Temporary. Will be removed in the next major release.

		Object.defineProperty(debug, 'enabled', {
			enumerable: true,
			configurable: false,
			get: () => {
				if (enableOverride !== null) {
					return enableOverride;
				}
				if (namespacesCache !== createDebug.namespaces) {
					namespacesCache = createDebug.namespaces;
					enabledCache = createDebug.enabled(namespace);
				}

				return enabledCache;
			},
			set: v => {
				enableOverride = v;
			}
		});

		// Env-specific initialization logic for debug instances
		if (typeof createDebug.init === 'function') {
			createDebug.init(debug);
		}

		return debug;
	}

	function extend(namespace, delimiter) {
		const newDebug = createDebug(this.namespace + (typeof delimiter === 'undefined' ? ':' : delimiter) + namespace);
		newDebug.log = this.log;
		return newDebug;
	}

	/**
	* Enables a debug mode by namespaces. This can include modes
	* separated by a colon and wildcards.
	*
	* @param {String} namespaces
	* @api public
	*/
	function enable(namespaces) {
		createDebug.save(namespaces);
		createDebug.namespaces = namespaces;

		createDebug.names = [];
		createDebug.skips = [];

		const split = (typeof namespaces === 'string' ? namespaces : '')
			.trim()
			.replace(/\s+/g, ',')
			.split(',')
			.filter(Boolean);

		for (const ns of split) {
			if (ns[0] === '-') {
				createDebug.skips.push(ns.slice(1));
			} else {
				createDebug.names.push(ns);
			}
		}
	}

	/**
	 * Checks if the given string matches a namespace template, honoring
	 * asterisks as wildcards.
	 *
	 * @param {String} search
	 * @param {String} template
	 * @return {Boolean}
	 */
	function matchesTemplate(search, template) {
		let searchIndex = 0;
		let templateIndex = 0;
		let starIndex = -1;
		let matchIndex = 0;

		while (searchIndex < search.length) {
			if (templateIndex < template.length && (template[templateIndex] === search[searchIndex] || template[templateIndex] === '*')) {
				// Match character or proceed with wildcard
				if (template[templateIndex] === '*') {
					starIndex = templateIndex;
					matchIndex = searchIndex;
					templateIndex++; // Skip the '*'
				} else {
					searchIndex++;
					templateIndex++;
				}
			} else if (starIndex !== -1) { // eslint-disable-line no-negated-condition
				// Backtrack to the last '*' and try to match more characters
				templateIndex = starIndex + 1;
				matchIndex++;
				searchIndex = matchIndex;
			} else {
				return false; // No match
			}
		}

		// Handle trailing '*' in template
		while (templateIndex < template.length && template[templateIndex] === '*') {
			templateIndex++;
		}

		return templateIndex === template.length;
	}

	/**
	* Disable debug output.
	*
	* @return {String} namespaces
	* @api public
	*/
	function disable() {
		const namespaces = [
			...createDebug.names,
			...createDebug.skips.map(namespace => '-' + namespace)
		].join(',');
		createDebug.enable('');
		return namespaces;
	}

	/**
	* Returns true if the given mode name is enabled, false otherwise.
	*
	* @param {String} name
	* @return {Boolean}
	* @api public
	*/
	function enabled(name) {
		for (const skip of createDebug.skips) {
			if (matchesTemplate(name, skip)) {
				return false;
			}
		}

		for (const ns of createDebug.names) {
			if (matchesTemplate(name, ns)) {
				return true;
			}
		}

		return false;
	}

	/**
	* Coerce `val`.
	*
	* @param {Mixed} val
	* @return {Mixed}
	* @api private
	*/
	function coerce(val) {
		if (val instanceof Error) {
			return val.stack || val.message;
		}
		return val;
	}

	/**
	* XXX DO NOT USE. This is a temporary stub function.
	* XXX It WILL be removed in the next major release.
	*/
	function destroy() {
		console.warn('Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.');
	}

	createDebug.enable(createDebug.load());

	return createDebug;
}

var common = setup;

/* eslint-env browser */

(function (module, exports) {
	/**
	 * This is the web browser implementation of `debug()`.
	 */

	exports.formatArgs = formatArgs;
	exports.save = save;
	exports.load = load;
	exports.useColors = useColors;
	exports.storage = localstorage();
	exports.destroy = (() => {
		let warned = false;

		return () => {
			if (!warned) {
				warned = true;
				console.warn('Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.');
			}
		};
	})();

	/**
	 * Colors.
	 */

	exports.colors = [
		'#0000CC',
		'#0000FF',
		'#0033CC',
		'#0033FF',
		'#0066CC',
		'#0066FF',
		'#0099CC',
		'#0099FF',
		'#00CC00',
		'#00CC33',
		'#00CC66',
		'#00CC99',
		'#00CCCC',
		'#00CCFF',
		'#3300CC',
		'#3300FF',
		'#3333CC',
		'#3333FF',
		'#3366CC',
		'#3366FF',
		'#3399CC',
		'#3399FF',
		'#33CC00',
		'#33CC33',
		'#33CC66',
		'#33CC99',
		'#33CCCC',
		'#33CCFF',
		'#6600CC',
		'#6600FF',
		'#6633CC',
		'#6633FF',
		'#66CC00',
		'#66CC33',
		'#9900CC',
		'#9900FF',
		'#9933CC',
		'#9933FF',
		'#99CC00',
		'#99CC33',
		'#CC0000',
		'#CC0033',
		'#CC0066',
		'#CC0099',
		'#CC00CC',
		'#CC00FF',
		'#CC3300',
		'#CC3333',
		'#CC3366',
		'#CC3399',
		'#CC33CC',
		'#CC33FF',
		'#CC6600',
		'#CC6633',
		'#CC9900',
		'#CC9933',
		'#CCCC00',
		'#CCCC33',
		'#FF0000',
		'#FF0033',
		'#FF0066',
		'#FF0099',
		'#FF00CC',
		'#FF00FF',
		'#FF3300',
		'#FF3333',
		'#FF3366',
		'#FF3399',
		'#FF33CC',
		'#FF33FF',
		'#FF6600',
		'#FF6633',
		'#FF9900',
		'#FF9933',
		'#FFCC00',
		'#FFCC33'
	];

	/**
	 * Currently only WebKit-based Web Inspectors, Firefox >= v31,
	 * and the Firebug extension (any Firefox version) are known
	 * to support "%c" CSS customizations.
	 *
	 * TODO: add a `localStorage` variable to explicitly enable/disable colors
	 */

	// eslint-disable-next-line complexity
	function useColors() {
		// NB: In an Electron preload script, document will be defined but not fully
		// initialized. Since we know we're in Chrome, we'll just detect this case
		// explicitly
		if (typeof window !== 'undefined' && window.process && (window.process.type === 'renderer' || window.process.__nwjs)) {
			return true;
		}

		// Internet Explorer and Edge do not support colors.
		if (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/(edge|trident)\/(\d+)/)) {
			return false;
		}

		let m;

		// Is webkit? http://stackoverflow.com/a/16459606/376773
		// document is undefined in react-native: https://github.com/facebook/react-native/pull/1632
		// eslint-disable-next-line no-return-assign
		return (typeof document !== 'undefined' && document.documentElement && document.documentElement.style && document.documentElement.style.WebkitAppearance) ||
			// Is firebug? http://stackoverflow.com/a/398120/376773
			(typeof window !== 'undefined' && window.console && (window.console.firebug || (window.console.exception && window.console.table))) ||
			// Is firefox >= v31?
			// https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages
			(typeof navigator !== 'undefined' && navigator.userAgent && (m = navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/)) && parseInt(m[1], 10) >= 31) ||
			// Double check webkit in userAgent just in case we are in a worker
			(typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/));
	}

	/**
	 * Colorize log arguments if enabled.
	 *
	 * @api public
	 */

	function formatArgs(args) {
		args[0] = (this.useColors ? '%c' : '') +
			this.namespace +
			(this.useColors ? ' %c' : ' ') +
			args[0] +
			(this.useColors ? '%c ' : ' ') +
			'+' + module.exports.humanize(this.diff);

		if (!this.useColors) {
			return;
		}

		const c = 'color: ' + this.color;
		args.splice(1, 0, c, 'color: inherit');

		// The final "%c" is somewhat tricky, because there could be other
		// arguments passed either before or after the %c, so we need to
		// figure out the correct index to insert the CSS into
		let index = 0;
		let lastC = 0;
		args[0].replace(/%[a-zA-Z%]/g, match => {
			if (match === '%%') {
				return;
			}
			index++;
			if (match === '%c') {
				// We only are interested in the *last* %c
				// (the user may have provided their own)
				lastC = index;
			}
		});

		args.splice(lastC, 0, c);
	}

	/**
	 * Invokes `console.debug()` when available.
	 * No-op when `console.debug` is not a "function".
	 * If `console.debug` is not available, falls back
	 * to `console.log`.
	 *
	 * @api public
	 */
	exports.log = console.debug || console.log || (() => {});

	/**
	 * Save `namespaces`.
	 *
	 * @param {String} namespaces
	 * @api private
	 */
	function save(namespaces) {
		try {
			if (namespaces) {
				exports.storage.setItem('debug', namespaces);
			} else {
				exports.storage.removeItem('debug');
			}
		} catch (error) {
			// Swallow
			// XXX (@Qix-) should we be logging these?
		}
	}

	/**
	 * Load `namespaces`.
	 *
	 * @return {String} returns the previously persisted debug modes
	 * @api private
	 */
	function load() {
		let r;
		try {
			r = exports.storage.getItem('debug') || exports.storage.getItem('DEBUG') ;
		} catch (error) {
			// Swallow
			// XXX (@Qix-) should we be logging these?
		}

		// If debug isn't set in LS, and we're in Electron, try to load $DEBUG
		if (!r && typeof process !== 'undefined' && 'env' in process) {
			r = process.env.DEBUG;
		}

		return r;
	}

	/**
	 * Localstorage attempts to return the localstorage.
	 *
	 * This is necessary because safari throws
	 * when a user disables cookies/localstorage
	 * and you attempt to access it.
	 *
	 * @return {LocalStorage}
	 * @api private
	 */

	function localstorage() {
		try {
			// TVMLKit (Apple TV JS Runtime) does not have a window object, just localStorage in the global context
			// The Browser also has localStorage in the global context.
			return localStorage;
		} catch (error) {
			// Swallow
			// XXX (@Qix-) should we be logging these?
		}
	}

	module.exports = common(exports);

	const {formatters} = module.exports;

	/**
	 * Map %j to `JSON.stringify()`, since no Web Inspectors do that by default.
	 */

	formatters.j = function (v) {
		try {
			return JSON.stringify(v);
		} catch (error) {
			return '[UnexpectedJSONParseError]: ' + error.message;
		}
	}; 
} (browser, browser.exports));

var browserExports = browser.exports;
var createDebug = /*@__PURE__*/getDefaultExportFromCjs(browserExports);

createDebug("foxglove:server");
new TextEncoder();
({
    subscribe: undefined,
    unsubscribe: undefined,
    advertise: ServerCapability.clientPublish,
    unadvertise: ServerCapability.clientPublish,
    [ClientBinaryOpcode.MESSAGE_DATA]: ServerCapability.clientPublish,
    getParameters: ServerCapability.parameters,
    setParameters: ServerCapability.parameters,
    subscribeParameterUpdates: ServerCapability.parametersSubscribe,
    unsubscribeParameterUpdates: ServerCapability.parametersSubscribe,
    [ClientBinaryOpcode.SERVICE_CALL_REQUEST]: ServerCapability.services,
    subscribeConnectionGraph: ServerCapability.connectionGraph,
    unsubscribeConnectionGraph: ServerCapability.connectionGraph,
    fetchAsset: ServerCapability.assets,
});

export { BinaryOpcode as B, ClientBinaryOpcode as C, EventEmitter as E, FoxgloveClient as F };
