import { createRequire } from 'node:module'; const require = createRequire(import.meta.url);
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
  get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
}) : x)(function(x) {
  if (typeof require !== "undefined") return require.apply(this, arguments);
  throw Error('Dynamic require of "' + x + '" is not supported');
});
var __commonJS = (cb, mod) => function __require2() {
  return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
};
var __export = (target, all) => {
  for (var name in all)
    __defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except2, desc2) => {
  if (from && typeof from === "object" || typeof from === "function") {
    for (let key of __getOwnPropNames(from))
      if (!__hasOwnProp.call(to, key) && key !== except2)
        __defProp(to, key, { get: () => from[key], enumerable: !(desc2 = __getOwnPropDesc(from, key)) || desc2.enumerable });
  }
  return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
  // If the importer is in node compatibility mode or this is not an ESM
  // file that has been converted to a CommonJS file using a Babel-
  // compatible transform (i.e. "__esModule" has not been set), then set
  // "default" to the CommonJS "module.exports" for node compatibility.
  isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
  mod
));

// ../../node_modules/.pnpm/ws@8.21.0/node_modules/ws/lib/constants.js
var require_constants = __commonJS({
  "../../node_modules/.pnpm/ws@8.21.0/node_modules/ws/lib/constants.js"(exports, module) {
    "use strict";
    var BINARY_TYPES = ["nodebuffer", "arraybuffer", "fragments"];
    var hasBlob = typeof Blob !== "undefined";
    if (hasBlob) BINARY_TYPES.push("blob");
    module.exports = {
      BINARY_TYPES,
      CLOSE_TIMEOUT: 3e4,
      EMPTY_BUFFER: Buffer.alloc(0),
      GUID: "258EAFA5-E914-47DA-95CA-C5AB0DC85B11",
      hasBlob,
      kForOnEventAttribute: Symbol("kIsForOnEventAttribute"),
      kListener: Symbol("kListener"),
      kStatusCode: Symbol("status-code"),
      kWebSocket: Symbol("websocket"),
      NOOP: () => {
      }
    };
  }
});

// ../../node_modules/.pnpm/ws@8.21.0/node_modules/ws/lib/buffer-util.js
var require_buffer_util = __commonJS({
  "../../node_modules/.pnpm/ws@8.21.0/node_modules/ws/lib/buffer-util.js"(exports, module) {
    "use strict";
    var { EMPTY_BUFFER } = require_constants();
    var FastBuffer = Buffer[Symbol.species];
    function concat(list, totalLength) {
      if (list.length === 0) return EMPTY_BUFFER;
      if (list.length === 1) return list[0];
      const target = Buffer.allocUnsafe(totalLength);
      let offset = 0;
      for (let i = 0; i < list.length; i++) {
        const buf = list[i];
        target.set(buf, offset);
        offset += buf.length;
      }
      if (offset < totalLength) {
        return new FastBuffer(target.buffer, target.byteOffset, offset);
      }
      return target;
    }
    function _mask(source, mask, output, offset, length) {
      for (let i = 0; i < length; i++) {
        output[offset + i] = source[i] ^ mask[i & 3];
      }
    }
    function _unmask(buffer, mask) {
      for (let i = 0; i < buffer.length; i++) {
        buffer[i] ^= mask[i & 3];
      }
    }
    function toArrayBuffer(buf) {
      if (buf.length === buf.buffer.byteLength) {
        return buf.buffer;
      }
      return buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.length);
    }
    function toBuffer(data) {
      toBuffer.readOnly = true;
      if (Buffer.isBuffer(data)) return data;
      let buf;
      if (data instanceof ArrayBuffer) {
        buf = new FastBuffer(data);
      } else if (ArrayBuffer.isView(data)) {
        buf = new FastBuffer(data.buffer, data.byteOffset, data.byteLength);
      } else {
        buf = Buffer.from(data);
        toBuffer.readOnly = false;
      }
      return buf;
    }
    module.exports = {
      concat,
      mask: _mask,
      toArrayBuffer,
      toBuffer,
      unmask: _unmask
    };
    if (!process.env.WS_NO_BUFFER_UTIL) {
      try {
        const bufferUtil = __require("bufferutil");
        module.exports.mask = function(source, mask, output, offset, length) {
          if (length < 48) _mask(source, mask, output, offset, length);
          else bufferUtil.mask(source, mask, output, offset, length);
        };
        module.exports.unmask = function(buffer, mask) {
          if (buffer.length < 32) _unmask(buffer, mask);
          else bufferUtil.unmask(buffer, mask);
        };
      } catch (e) {
      }
    }
  }
});

// ../../node_modules/.pnpm/ws@8.21.0/node_modules/ws/lib/limiter.js
var require_limiter = __commonJS({
  "../../node_modules/.pnpm/ws@8.21.0/node_modules/ws/lib/limiter.js"(exports, module) {
    "use strict";
    var kDone = Symbol("kDone");
    var kRun = Symbol("kRun");
    var Limiter = class {
      /**
       * Creates a new `Limiter`.
       *
       * @param {Number} [concurrency=Infinity] The maximum number of jobs allowed
       *     to run concurrently
       */
      constructor(concurrency) {
        this[kDone] = () => {
          this.pending--;
          this[kRun]();
        };
        this.concurrency = concurrency || Infinity;
        this.jobs = [];
        this.pending = 0;
      }
      /**
       * Adds a job to the queue.
       *
       * @param {Function} job The job to run
       * @public
       */
      add(job) {
        this.jobs.push(job);
        this[kRun]();
      }
      /**
       * Removes a job from the queue and runs it if possible.
       *
       * @private
       */
      [kRun]() {
        if (this.pending === this.concurrency) return;
        if (this.jobs.length) {
          const job = this.jobs.shift();
          this.pending++;
          job(this[kDone]);
        }
      }
    };
    module.exports = Limiter;
  }
});

// ../../node_modules/.pnpm/ws@8.21.0/node_modules/ws/lib/permessage-deflate.js
var require_permessage_deflate = __commonJS({
  "../../node_modules/.pnpm/ws@8.21.0/node_modules/ws/lib/permessage-deflate.js"(exports, module) {
    "use strict";
    var zlib = __require("zlib");
    var bufferUtil = require_buffer_util();
    var Limiter = require_limiter();
    var { kStatusCode } = require_constants();
    var FastBuffer = Buffer[Symbol.species];
    var TRAILER = Buffer.from([0, 0, 255, 255]);
    var kPerMessageDeflate = Symbol("permessage-deflate");
    var kTotalLength = Symbol("total-length");
    var kCallback = Symbol("callback");
    var kBuffers = Symbol("buffers");
    var kError = Symbol("error");
    var zlibLimiter;
    var PerMessageDeflate2 = class {
      /**
       * Creates a PerMessageDeflate instance.
       *
       * @param {Object} [options] Configuration options
       * @param {(Boolean|Number)} [options.clientMaxWindowBits] Advertise support
       *     for, or request, a custom client window size
       * @param {Boolean} [options.clientNoContextTakeover=false] Advertise/
       *     acknowledge disabling of client context takeover
       * @param {Number} [options.concurrencyLimit=10] The number of concurrent
       *     calls to zlib
       * @param {Boolean} [options.isServer=false] Create the instance in either
       *     server or client mode
       * @param {Number} [options.maxPayload=0] The maximum allowed message length
       * @param {(Boolean|Number)} [options.serverMaxWindowBits] Request/confirm the
       *     use of a custom server window size
       * @param {Boolean} [options.serverNoContextTakeover=false] Request/accept
       *     disabling of server context takeover
       * @param {Number} [options.threshold=1024] Size (in bytes) below which
       *     messages should not be compressed if context takeover is disabled
       * @param {Object} [options.zlibDeflateOptions] Options to pass to zlib on
       *     deflate
       * @param {Object} [options.zlibInflateOptions] Options to pass to zlib on
       *     inflate
       */
      constructor(options) {
        this._options = options || {};
        this._threshold = this._options.threshold !== void 0 ? this._options.threshold : 1024;
        this._maxPayload = this._options.maxPayload | 0;
        this._isServer = !!this._options.isServer;
        this._deflate = null;
        this._inflate = null;
        this.params = null;
        if (!zlibLimiter) {
          const concurrency = this._options.concurrencyLimit !== void 0 ? this._options.concurrencyLimit : 10;
          zlibLimiter = new Limiter(concurrency);
        }
      }
      /**
       * @type {String}
       */
      static get extensionName() {
        return "permessage-deflate";
      }
      /**
       * Create an extension negotiation offer.
       *
       * @return {Object} Extension parameters
       * @public
       */
      offer() {
        const params = {};
        if (this._options.serverNoContextTakeover) {
          params.server_no_context_takeover = true;
        }
        if (this._options.clientNoContextTakeover) {
          params.client_no_context_takeover = true;
        }
        if (this._options.serverMaxWindowBits) {
          params.server_max_window_bits = this._options.serverMaxWindowBits;
        }
        if (this._options.clientMaxWindowBits) {
          params.client_max_window_bits = this._options.clientMaxWindowBits;
        } else if (this._options.clientMaxWindowBits == null) {
          params.client_max_window_bits = true;
        }
        return params;
      }
      /**
       * Accept an extension negotiation offer/response.
       *
       * @param {Array} configurations The extension negotiation offers/reponse
       * @return {Object} Accepted configuration
       * @public
       */
      accept(configurations) {
        configurations = this.normalizeParams(configurations);
        this.params = this._isServer ? this.acceptAsServer(configurations) : this.acceptAsClient(configurations);
        return this.params;
      }
      /**
       * Releases all resources used by the extension.
       *
       * @public
       */
      cleanup() {
        if (this._inflate) {
          this._inflate.close();
          this._inflate = null;
        }
        if (this._deflate) {
          const callback = this._deflate[kCallback];
          this._deflate.close();
          this._deflate = null;
          if (callback) {
            callback(
              new Error(
                "The deflate stream was closed while data was being processed"
              )
            );
          }
        }
      }
      /**
       *  Accept an extension negotiation offer.
       *
       * @param {Array} offers The extension negotiation offers
       * @return {Object} Accepted configuration
       * @private
       */
      acceptAsServer(offers) {
        const opts = this._options;
        const accepted = offers.find((params) => {
          if (opts.serverNoContextTakeover === false && params.server_no_context_takeover || params.server_max_window_bits && (opts.serverMaxWindowBits === false || typeof opts.serverMaxWindowBits === "number" && opts.serverMaxWindowBits > params.server_max_window_bits) || typeof opts.clientMaxWindowBits === "number" && !params.client_max_window_bits) {
            return false;
          }
          return true;
        });
        if (!accepted) {
          throw new Error("None of the extension offers can be accepted");
        }
        if (opts.serverNoContextTakeover) {
          accepted.server_no_context_takeover = true;
        }
        if (opts.clientNoContextTakeover) {
          accepted.client_no_context_takeover = true;
        }
        if (typeof opts.serverMaxWindowBits === "number") {
          accepted.server_max_window_bits = opts.serverMaxWindowBits;
        }
        if (typeof opts.clientMaxWindowBits === "number") {
          accepted.client_max_window_bits = opts.clientMaxWindowBits;
        } else if (accepted.client_max_window_bits === true || opts.clientMaxWindowBits === false) {
          delete accepted.client_max_window_bits;
        }
        return accepted;
      }
      /**
       * Accept the extension negotiation response.
       *
       * @param {Array} response The extension negotiation response
       * @return {Object} Accepted configuration
       * @private
       */
      acceptAsClient(response) {
        const params = response[0];
        if (this._options.clientNoContextTakeover === false && params.client_no_context_takeover) {
          throw new Error('Unexpected parameter "client_no_context_takeover"');
        }
        if (!params.client_max_window_bits) {
          if (typeof this._options.clientMaxWindowBits === "number") {
            params.client_max_window_bits = this._options.clientMaxWindowBits;
          }
        } else if (this._options.clientMaxWindowBits === false || typeof this._options.clientMaxWindowBits === "number" && params.client_max_window_bits > this._options.clientMaxWindowBits) {
          throw new Error(
            'Unexpected or invalid parameter "client_max_window_bits"'
          );
        }
        return params;
      }
      /**
       * Normalize parameters.
       *
       * @param {Array} configurations The extension negotiation offers/reponse
       * @return {Array} The offers/response with normalized parameters
       * @private
       */
      normalizeParams(configurations) {
        configurations.forEach((params) => {
          Object.keys(params).forEach((key) => {
            let value = params[key];
            if (value.length > 1) {
              throw new Error(`Parameter "${key}" must have only a single value`);
            }
            value = value[0];
            if (key === "client_max_window_bits") {
              if (value !== true) {
                const num = +value;
                if (!Number.isInteger(num) || num < 8 || num > 15) {
                  throw new TypeError(
                    `Invalid value for parameter "${key}": ${value}`
                  );
                }
                value = num;
              } else if (!this._isServer) {
                throw new TypeError(
                  `Invalid value for parameter "${key}": ${value}`
                );
              }
            } else if (key === "server_max_window_bits") {
              const num = +value;
              if (!Number.isInteger(num) || num < 8 || num > 15) {
                throw new TypeError(
                  `Invalid value for parameter "${key}": ${value}`
                );
              }
              value = num;
            } else if (key === "client_no_context_takeover" || key === "server_no_context_takeover") {
              if (value !== true) {
                throw new TypeError(
                  `Invalid value for parameter "${key}": ${value}`
                );
              }
            } else {
              throw new Error(`Unknown parameter "${key}"`);
            }
            params[key] = value;
          });
        });
        return configurations;
      }
      /**
       * Decompress data. Concurrency limited.
       *
       * @param {Buffer} data Compressed data
       * @param {Boolean} fin Specifies whether or not this is the last fragment
       * @param {Function} callback Callback
       * @public
       */
      decompress(data, fin, callback) {
        zlibLimiter.add((done) => {
          this._decompress(data, fin, (err, result) => {
            done();
            callback(err, result);
          });
        });
      }
      /**
       * Compress data. Concurrency limited.
       *
       * @param {(Buffer|String)} data Data to compress
       * @param {Boolean} fin Specifies whether or not this is the last fragment
       * @param {Function} callback Callback
       * @public
       */
      compress(data, fin, callback) {
        zlibLimiter.add((done) => {
          this._compress(data, fin, (err, result) => {
            done();
            callback(err, result);
          });
        });
      }
      /**
       * Decompress data.
       *
       * @param {Buffer} data Compressed data
       * @param {Boolean} fin Specifies whether or not this is the last fragment
       * @param {Function} callback Callback
       * @private
       */
      _decompress(data, fin, callback) {
        const endpoint = this._isServer ? "client" : "server";
        if (!this._inflate) {
          const key = `${endpoint}_max_window_bits`;
          const windowBits = typeof this.params[key] !== "number" ? zlib.Z_DEFAULT_WINDOWBITS : this.params[key];
          this._inflate = zlib.createInflateRaw({
            ...this._options.zlibInflateOptions,
            windowBits
          });
          this._inflate[kPerMessageDeflate] = this;
          this._inflate[kTotalLength] = 0;
          this._inflate[kBuffers] = [];
          this._inflate.on("error", inflateOnError);
          this._inflate.on("data", inflateOnData);
        }
        this._inflate[kCallback] = callback;
        this._inflate.write(data);
        if (fin) this._inflate.write(TRAILER);
        this._inflate.flush(() => {
          const err = this._inflate[kError];
          if (err) {
            this._inflate.close();
            this._inflate = null;
            callback(err);
            return;
          }
          const data2 = bufferUtil.concat(
            this._inflate[kBuffers],
            this._inflate[kTotalLength]
          );
          if (this._inflate._readableState.endEmitted) {
            this._inflate.close();
            this._inflate = null;
          } else {
            this._inflate[kTotalLength] = 0;
            this._inflate[kBuffers] = [];
            if (fin && this.params[`${endpoint}_no_context_takeover`]) {
              this._inflate.reset();
            }
          }
          callback(null, data2);
        });
      }
      /**
       * Compress data.
       *
       * @param {(Buffer|String)} data Data to compress
       * @param {Boolean} fin Specifies whether or not this is the last fragment
       * @param {Function} callback Callback
       * @private
       */
      _compress(data, fin, callback) {
        const endpoint = this._isServer ? "server" : "client";
        if (!this._deflate) {
          const key = `${endpoint}_max_window_bits`;
          const windowBits = typeof this.params[key] !== "number" ? zlib.Z_DEFAULT_WINDOWBITS : this.params[key];
          this._deflate = zlib.createDeflateRaw({
            ...this._options.zlibDeflateOptions,
            windowBits
          });
          this._deflate[kTotalLength] = 0;
          this._deflate[kBuffers] = [];
          this._deflate.on("data", deflateOnData);
        }
        this._deflate[kCallback] = callback;
        this._deflate.write(data);
        this._deflate.flush(zlib.Z_SYNC_FLUSH, () => {
          if (!this._deflate) {
            return;
          }
          let data2 = bufferUtil.concat(
            this._deflate[kBuffers],
            this._deflate[kTotalLength]
          );
          if (fin) {
            data2 = new FastBuffer(data2.buffer, data2.byteOffset, data2.length - 4);
          }
          this._deflate[kCallback] = null;
          this._deflate[kTotalLength] = 0;
          this._deflate[kBuffers] = [];
          if (fin && this.params[`${endpoint}_no_context_takeover`]) {
            this._deflate.reset();
          }
          callback(null, data2);
        });
      }
    };
    module.exports = PerMessageDeflate2;
    function deflateOnData(chunk) {
      this[kBuffers].push(chunk);
      this[kTotalLength] += chunk.length;
    }
    function inflateOnData(chunk) {
      this[kTotalLength] += chunk.length;
      if (this[kPerMessageDeflate]._maxPayload < 1 || this[kTotalLength] <= this[kPerMessageDeflate]._maxPayload) {
        this[kBuffers].push(chunk);
        return;
      }
      this[kError] = new RangeError("Max payload size exceeded");
      this[kError].code = "WS_ERR_UNSUPPORTED_MESSAGE_LENGTH";
      this[kError][kStatusCode] = 1009;
      this.removeListener("data", inflateOnData);
      this.reset();
    }
    function inflateOnError(err) {
      this[kPerMessageDeflate]._inflate = null;
      if (this[kError]) {
        this[kCallback](this[kError]);
        return;
      }
      err[kStatusCode] = 1007;
      this[kCallback](err);
    }
  }
});

// ../../node_modules/.pnpm/ws@8.21.0/node_modules/ws/lib/validation.js
var require_validation = __commonJS({
  "../../node_modules/.pnpm/ws@8.21.0/node_modules/ws/lib/validation.js"(exports, module) {
    "use strict";
    var { isUtf8 } = __require("buffer");
    var { hasBlob } = require_constants();
    var tokenChars = [
      0,
      0,
      0,
      0,
      0,
      0,
      0,
      0,
      0,
      0,
      0,
      0,
      0,
      0,
      0,
      0,
      // 0 - 15
      0,
      0,
      0,
      0,
      0,
      0,
      0,
      0,
      0,
      0,
      0,
      0,
      0,
      0,
      0,
      0,
      // 16 - 31
      0,
      1,
      0,
      1,
      1,
      1,
      1,
      1,
      0,
      0,
      1,
      1,
      0,
      1,
      1,
      0,
      // 32 - 47
      1,
      1,
      1,
      1,
      1,
      1,
      1,
      1,
      1,
      1,
      0,
      0,
      0,
      0,
      0,
      0,
      // 48 - 63
      0,
      1,
      1,
      1,
      1,
      1,
      1,
      1,
      1,
      1,
      1,
      1,
      1,
      1,
      1,
      1,
      // 64 - 79
      1,
      1,
      1,
      1,
      1,
      1,
      1,
      1,
      1,
      1,
      1,
      0,
      0,
      0,
      1,
      1,
      // 80 - 95
      1,
      1,
      1,
      1,
      1,
      1,
      1,
      1,
      1,
      1,
      1,
      1,
      1,
      1,
      1,
      1,
      // 96 - 111
      1,
      1,
      1,
      1,
      1,
      1,
      1,
      1,
      1,
      1,
      1,
      0,
      1,
      0,
      1,
      0
      // 112 - 127
    ];
    function isValidStatusCode(code) {
      return code >= 1e3 && code <= 1014 && code !== 1004 && code !== 1005 && code !== 1006 || code >= 3e3 && code <= 4999;
    }
    function _isValidUTF8(buf) {
      const len = buf.length;
      let i = 0;
      while (i < len) {
        if ((buf[i] & 128) === 0) {
          i++;
        } else if ((buf[i] & 224) === 192) {
          if (i + 1 === len || (buf[i + 1] & 192) !== 128 || (buf[i] & 254) === 192) {
            return false;
          }
          i += 2;
        } else if ((buf[i] & 240) === 224) {
          if (i + 2 >= len || (buf[i + 1] & 192) !== 128 || (buf[i + 2] & 192) !== 128 || buf[i] === 224 && (buf[i + 1] & 224) === 128 || // Overlong
          buf[i] === 237 && (buf[i + 1] & 224) === 160) {
            return false;
          }
          i += 3;
        } else if ((buf[i] & 248) === 240) {
          if (i + 3 >= len || (buf[i + 1] & 192) !== 128 || (buf[i + 2] & 192) !== 128 || (buf[i + 3] & 192) !== 128 || buf[i] === 240 && (buf[i + 1] & 240) === 128 || // Overlong
          buf[i] === 244 && buf[i + 1] > 143 || buf[i] > 244) {
            return false;
          }
          i += 4;
        } else {
          return false;
        }
      }
      return true;
    }
    function isBlob(value) {
      return hasBlob && typeof value === "object" && typeof value.arrayBuffer === "function" && typeof value.type === "string" && typeof value.stream === "function" && (value[Symbol.toStringTag] === "Blob" || value[Symbol.toStringTag] === "File");
    }
    module.exports = {
      isBlob,
      isValidStatusCode,
      isValidUTF8: _isValidUTF8,
      tokenChars
    };
    if (isUtf8) {
      module.exports.isValidUTF8 = function(buf) {
        return buf.length < 24 ? _isValidUTF8(buf) : isUtf8(buf);
      };
    } else if (!process.env.WS_NO_UTF_8_VALIDATE) {
      try {
        const isValidUTF8 = __require("utf-8-validate");
        module.exports.isValidUTF8 = function(buf) {
          return buf.length < 32 ? _isValidUTF8(buf) : isValidUTF8(buf);
        };
      } catch (e) {
      }
    }
  }
});

// ../../node_modules/.pnpm/ws@8.21.0/node_modules/ws/lib/receiver.js
var require_receiver = __commonJS({
  "../../node_modules/.pnpm/ws@8.21.0/node_modules/ws/lib/receiver.js"(exports, module) {
    "use strict";
    var { Writable } = __require("stream");
    var PerMessageDeflate2 = require_permessage_deflate();
    var {
      BINARY_TYPES,
      EMPTY_BUFFER,
      kStatusCode,
      kWebSocket
    } = require_constants();
    var { concat, toArrayBuffer, unmask } = require_buffer_util();
    var { isValidStatusCode, isValidUTF8 } = require_validation();
    var FastBuffer = Buffer[Symbol.species];
    var GET_INFO = 0;
    var GET_PAYLOAD_LENGTH_16 = 1;
    var GET_PAYLOAD_LENGTH_64 = 2;
    var GET_MASK = 3;
    var GET_DATA = 4;
    var INFLATING = 5;
    var DEFER_EVENT = 6;
    var Receiver2 = class extends Writable {
      /**
       * Creates a Receiver instance.
       *
       * @param {Object} [options] Options object
       * @param {Boolean} [options.allowSynchronousEvents=true] Specifies whether
       *     any of the `'message'`, `'ping'`, and `'pong'` events can be emitted
       *     multiple times in the same tick
       * @param {String} [options.binaryType=nodebuffer] The type for binary data
       * @param {Object} [options.extensions] An object containing the negotiated
       *     extensions
       * @param {Boolean} [options.isServer=false] Specifies whether to operate in
       *     client or server mode
       * @param {Number} [options.maxBufferedChunks=0] The maximum number of
       *     buffered data chunks
       * @param {Number} [options.maxFragments=0] The maximum number of message
       *     fragments
       * @param {Number} [options.maxPayload=0] The maximum allowed message length
       * @param {Boolean} [options.skipUTF8Validation=false] Specifies whether or
       *     not to skip UTF-8 validation for text and close messages
       */
      constructor(options = {}) {
        super();
        this._allowSynchronousEvents = options.allowSynchronousEvents !== void 0 ? options.allowSynchronousEvents : true;
        this._binaryType = options.binaryType || BINARY_TYPES[0];
        this._extensions = options.extensions || {};
        this._isServer = !!options.isServer;
        this._maxBufferedChunks = options.maxBufferedChunks | 0;
        this._maxFragments = options.maxFragments | 0;
        this._maxPayload = options.maxPayload | 0;
        this._skipUTF8Validation = !!options.skipUTF8Validation;
        this[kWebSocket] = void 0;
        this._bufferedBytes = 0;
        this._buffers = [];
        this._compressed = false;
        this._payloadLength = 0;
        this._mask = void 0;
        this._fragmented = 0;
        this._masked = false;
        this._fin = false;
        this._opcode = 0;
        this._totalPayloadLength = 0;
        this._messageLength = 0;
        this._fragments = [];
        this._errored = false;
        this._loop = false;
        this._state = GET_INFO;
      }
      /**
       * Implements `Writable.prototype._write()`.
       *
       * @param {Buffer} chunk The chunk of data to write
       * @param {String} encoding The character encoding of `chunk`
       * @param {Function} cb Callback
       * @private
       */
      _write(chunk, encoding, cb) {
        if (this._opcode === 8 && this._state == GET_INFO) return cb();
        if (this._maxBufferedChunks > 0 && this._buffers.length >= this._maxBufferedChunks) {
          cb(
            this.createError(
              RangeError,
              "Too many buffered chunks",
              false,
              1008,
              "WS_ERR_TOO_MANY_BUFFERED_PARTS"
            )
          );
          return;
        }
        this._bufferedBytes += chunk.length;
        this._buffers.push(chunk);
        this.startLoop(cb);
      }
      /**
       * Consumes `n` bytes from the buffered data.
       *
       * @param {Number} n The number of bytes to consume
       * @return {Buffer} The consumed bytes
       * @private
       */
      consume(n) {
        this._bufferedBytes -= n;
        if (n === this._buffers[0].length) return this._buffers.shift();
        if (n < this._buffers[0].length) {
          const buf = this._buffers[0];
          this._buffers[0] = new FastBuffer(
            buf.buffer,
            buf.byteOffset + n,
            buf.length - n
          );
          return new FastBuffer(buf.buffer, buf.byteOffset, n);
        }
        const dst = Buffer.allocUnsafe(n);
        do {
          const buf = this._buffers[0];
          const offset = dst.length - n;
          if (n >= buf.length) {
            dst.set(this._buffers.shift(), offset);
          } else {
            dst.set(new Uint8Array(buf.buffer, buf.byteOffset, n), offset);
            this._buffers[0] = new FastBuffer(
              buf.buffer,
              buf.byteOffset + n,
              buf.length - n
            );
          }
          n -= buf.length;
        } while (n > 0);
        return dst;
      }
      /**
       * Starts the parsing loop.
       *
       * @param {Function} cb Callback
       * @private
       */
      startLoop(cb) {
        this._loop = true;
        do {
          switch (this._state) {
            case GET_INFO:
              this.getInfo(cb);
              break;
            case GET_PAYLOAD_LENGTH_16:
              this.getPayloadLength16(cb);
              break;
            case GET_PAYLOAD_LENGTH_64:
              this.getPayloadLength64(cb);
              break;
            case GET_MASK:
              this.getMask();
              break;
            case GET_DATA:
              this.getData(cb);
              break;
            case INFLATING:
            case DEFER_EVENT:
              this._loop = false;
              return;
          }
        } while (this._loop);
        if (!this._errored) cb();
      }
      /**
       * Reads the first two bytes of a frame.
       *
       * @param {Function} cb Callback
       * @private
       */
      getInfo(cb) {
        if (this._bufferedBytes < 2) {
          this._loop = false;
          return;
        }
        const buf = this.consume(2);
        if ((buf[0] & 48) !== 0) {
          const error = this.createError(
            RangeError,
            "RSV2 and RSV3 must be clear",
            true,
            1002,
            "WS_ERR_UNEXPECTED_RSV_2_3"
          );
          cb(error);
          return;
        }
        const compressed = (buf[0] & 64) === 64;
        if (compressed && !this._extensions[PerMessageDeflate2.extensionName]) {
          const error = this.createError(
            RangeError,
            "RSV1 must be clear",
            true,
            1002,
            "WS_ERR_UNEXPECTED_RSV_1"
          );
          cb(error);
          return;
        }
        this._fin = (buf[0] & 128) === 128;
        this._opcode = buf[0] & 15;
        this._payloadLength = buf[1] & 127;
        if (this._opcode === 0) {
          if (compressed) {
            const error = this.createError(
              RangeError,
              "RSV1 must be clear",
              true,
              1002,
              "WS_ERR_UNEXPECTED_RSV_1"
            );
            cb(error);
            return;
          }
          if (!this._fragmented) {
            const error = this.createError(
              RangeError,
              "invalid opcode 0",
              true,
              1002,
              "WS_ERR_INVALID_OPCODE"
            );
            cb(error);
            return;
          }
          this._opcode = this._fragmented;
        } else if (this._opcode === 1 || this._opcode === 2) {
          if (this._fragmented) {
            const error = this.createError(
              RangeError,
              `invalid opcode ${this._opcode}`,
              true,
              1002,
              "WS_ERR_INVALID_OPCODE"
            );
            cb(error);
            return;
          }
          this._compressed = compressed;
        } else if (this._opcode > 7 && this._opcode < 11) {
          if (!this._fin) {
            const error = this.createError(
              RangeError,
              "FIN must be set",
              true,
              1002,
              "WS_ERR_EXPECTED_FIN"
            );
            cb(error);
            return;
          }
          if (compressed) {
            const error = this.createError(
              RangeError,
              "RSV1 must be clear",
              true,
              1002,
              "WS_ERR_UNEXPECTED_RSV_1"
            );
            cb(error);
            return;
          }
          if (this._payloadLength > 125 || this._opcode === 8 && this._payloadLength === 1) {
            const error = this.createError(
              RangeError,
              `invalid payload length ${this._payloadLength}`,
              true,
              1002,
              "WS_ERR_INVALID_CONTROL_PAYLOAD_LENGTH"
            );
            cb(error);
            return;
          }
        } else {
          const error = this.createError(
            RangeError,
            `invalid opcode ${this._opcode}`,
            true,
            1002,
            "WS_ERR_INVALID_OPCODE"
          );
          cb(error);
          return;
        }
        if (!this._fin && !this._fragmented) this._fragmented = this._opcode;
        this._masked = (buf[1] & 128) === 128;
        if (this._isServer) {
          if (!this._masked) {
            const error = this.createError(
              RangeError,
              "MASK must be set",
              true,
              1002,
              "WS_ERR_EXPECTED_MASK"
            );
            cb(error);
            return;
          }
        } else if (this._masked) {
          const error = this.createError(
            RangeError,
            "MASK must be clear",
            true,
            1002,
            "WS_ERR_UNEXPECTED_MASK"
          );
          cb(error);
          return;
        }
        if (this._payloadLength === 126) this._state = GET_PAYLOAD_LENGTH_16;
        else if (this._payloadLength === 127) this._state = GET_PAYLOAD_LENGTH_64;
        else this.haveLength(cb);
      }
      /**
       * Gets extended payload length (7+16).
       *
       * @param {Function} cb Callback
       * @private
       */
      getPayloadLength16(cb) {
        if (this._bufferedBytes < 2) {
          this._loop = false;
          return;
        }
        this._payloadLength = this.consume(2).readUInt16BE(0);
        this.haveLength(cb);
      }
      /**
       * Gets extended payload length (7+64).
       *
       * @param {Function} cb Callback
       * @private
       */
      getPayloadLength64(cb) {
        if (this._bufferedBytes < 8) {
          this._loop = false;
          return;
        }
        const buf = this.consume(8);
        const num = buf.readUInt32BE(0);
        if (num > Math.pow(2, 53 - 32) - 1) {
          const error = this.createError(
            RangeError,
            "Unsupported WebSocket frame: payload length > 2^53 - 1",
            false,
            1009,
            "WS_ERR_UNSUPPORTED_DATA_PAYLOAD_LENGTH"
          );
          cb(error);
          return;
        }
        this._payloadLength = num * Math.pow(2, 32) + buf.readUInt32BE(4);
        this.haveLength(cb);
      }
      /**
       * Payload length has been read.
       *
       * @param {Function} cb Callback
       * @private
       */
      haveLength(cb) {
        if (this._payloadLength && this._opcode < 8) {
          this._totalPayloadLength += this._payloadLength;
          if (this._totalPayloadLength > this._maxPayload && this._maxPayload > 0) {
            const error = this.createError(
              RangeError,
              "Max payload size exceeded",
              false,
              1009,
              "WS_ERR_UNSUPPORTED_MESSAGE_LENGTH"
            );
            cb(error);
            return;
          }
        }
        if (this._masked) this._state = GET_MASK;
        else this._state = GET_DATA;
      }
      /**
       * Reads mask bytes.
       *
       * @private
       */
      getMask() {
        if (this._bufferedBytes < 4) {
          this._loop = false;
          return;
        }
        this._mask = this.consume(4);
        this._state = GET_DATA;
      }
      /**
       * Reads data bytes.
       *
       * @param {Function} cb Callback
       * @private
       */
      getData(cb) {
        let data = EMPTY_BUFFER;
        if (this._payloadLength) {
          if (this._bufferedBytes < this._payloadLength) {
            this._loop = false;
            return;
          }
          data = this.consume(this._payloadLength);
          if (this._masked && (this._mask[0] | this._mask[1] | this._mask[2] | this._mask[3]) !== 0) {
            unmask(data, this._mask);
          }
        }
        if (this._opcode > 7) {
          this.controlMessage(data, cb);
          return;
        }
        if (this._compressed) {
          this._state = INFLATING;
          this.decompress(data, cb);
          return;
        }
        if (data.length) {
          if (this._maxFragments > 0 && this._fragments.length >= this._maxFragments) {
            const error = this.createError(
              RangeError,
              "Too many message fragments",
              false,
              1008,
              "WS_ERR_TOO_MANY_BUFFERED_PARTS"
            );
            cb(error);
            return;
          }
          this._messageLength = this._totalPayloadLength;
          this._fragments.push(data);
        }
        this.dataMessage(cb);
      }
      /**
       * Decompresses data.
       *
       * @param {Buffer} data Compressed data
       * @param {Function} cb Callback
       * @private
       */
      decompress(data, cb) {
        const perMessageDeflate = this._extensions[PerMessageDeflate2.extensionName];
        perMessageDeflate.decompress(data, this._fin, (err, buf) => {
          if (err) return cb(err);
          if (buf.length) {
            this._messageLength += buf.length;
            if (this._messageLength > this._maxPayload && this._maxPayload > 0) {
              const error = this.createError(
                RangeError,
                "Max payload size exceeded",
                false,
                1009,
                "WS_ERR_UNSUPPORTED_MESSAGE_LENGTH"
              );
              cb(error);
              return;
            }
            if (this._maxFragments > 0 && this._fragments.length >= this._maxFragments) {
              const error = this.createError(
                RangeError,
                "Too many message fragments",
                false,
                1008,
                "WS_ERR_TOO_MANY_BUFFERED_PARTS"
              );
              cb(error);
              return;
            }
            this._fragments.push(buf);
          }
          this.dataMessage(cb);
          if (this._state === GET_INFO) this.startLoop(cb);
        });
      }
      /**
       * Handles a data message.
       *
       * @param {Function} cb Callback
       * @private
       */
      dataMessage(cb) {
        if (!this._fin) {
          this._state = GET_INFO;
          return;
        }
        const messageLength = this._messageLength;
        const fragments = this._fragments;
        this._totalPayloadLength = 0;
        this._messageLength = 0;
        this._fragmented = 0;
        this._fragments = [];
        if (this._opcode === 2) {
          let data;
          if (this._binaryType === "nodebuffer") {
            data = concat(fragments, messageLength);
          } else if (this._binaryType === "arraybuffer") {
            data = toArrayBuffer(concat(fragments, messageLength));
          } else if (this._binaryType === "blob") {
            data = new Blob(fragments);
          } else {
            data = fragments;
          }
          if (this._allowSynchronousEvents) {
            this.emit("message", data, true);
            this._state = GET_INFO;
          } else {
            this._state = DEFER_EVENT;
            setImmediate(() => {
              this.emit("message", data, true);
              this._state = GET_INFO;
              this.startLoop(cb);
            });
          }
        } else {
          const buf = concat(fragments, messageLength);
          if (!this._skipUTF8Validation && !isValidUTF8(buf)) {
            const error = this.createError(
              Error,
              "invalid UTF-8 sequence",
              true,
              1007,
              "WS_ERR_INVALID_UTF8"
            );
            cb(error);
            return;
          }
          if (this._state === INFLATING || this._allowSynchronousEvents) {
            this.emit("message", buf, false);
            this._state = GET_INFO;
          } else {
            this._state = DEFER_EVENT;
            setImmediate(() => {
              this.emit("message", buf, false);
              this._state = GET_INFO;
              this.startLoop(cb);
            });
          }
        }
      }
      /**
       * Handles a control message.
       *
       * @param {Buffer} data Data to handle
       * @return {(Error|RangeError|undefined)} A possible error
       * @private
       */
      controlMessage(data, cb) {
        if (this._opcode === 8) {
          if (data.length === 0) {
            this._loop = false;
            this.emit("conclude", 1005, EMPTY_BUFFER);
            this.end();
          } else {
            const code = data.readUInt16BE(0);
            if (!isValidStatusCode(code)) {
              const error = this.createError(
                RangeError,
                `invalid status code ${code}`,
                true,
                1002,
                "WS_ERR_INVALID_CLOSE_CODE"
              );
              cb(error);
              return;
            }
            const buf = new FastBuffer(
              data.buffer,
              data.byteOffset + 2,
              data.length - 2
            );
            if (!this._skipUTF8Validation && !isValidUTF8(buf)) {
              const error = this.createError(
                Error,
                "invalid UTF-8 sequence",
                true,
                1007,
                "WS_ERR_INVALID_UTF8"
              );
              cb(error);
              return;
            }
            this._loop = false;
            this.emit("conclude", code, buf);
            this.end();
          }
          this._state = GET_INFO;
          return;
        }
        if (this._allowSynchronousEvents) {
          this.emit(this._opcode === 9 ? "ping" : "pong", data);
          this._state = GET_INFO;
        } else {
          this._state = DEFER_EVENT;
          setImmediate(() => {
            this.emit(this._opcode === 9 ? "ping" : "pong", data);
            this._state = GET_INFO;
            this.startLoop(cb);
          });
        }
      }
      /**
       * Builds an error object.
       *
       * @param {function(new:Error|RangeError)} ErrorCtor The error constructor
       * @param {String} message The error message
       * @param {Boolean} prefix Specifies whether or not to add a default prefix to
       *     `message`
       * @param {Number} statusCode The status code
       * @param {String} errorCode The exposed error code
       * @return {(Error|RangeError)} The error
       * @private
       */
      createError(ErrorCtor, message, prefix, statusCode, errorCode) {
        this._loop = false;
        this._errored = true;
        const err = new ErrorCtor(
          prefix ? `Invalid WebSocket frame: ${message}` : message
        );
        Error.captureStackTrace(err, this.createError);
        err.code = errorCode;
        err[kStatusCode] = statusCode;
        return err;
      }
    };
    module.exports = Receiver2;
  }
});

// ../../node_modules/.pnpm/ws@8.21.0/node_modules/ws/lib/sender.js
var require_sender = __commonJS({
  "../../node_modules/.pnpm/ws@8.21.0/node_modules/ws/lib/sender.js"(exports, module) {
    "use strict";
    var { Duplex } = __require("stream");
    var { randomFillSync } = __require("crypto");
    var {
      types: { isUint8Array }
    } = __require("util");
    var PerMessageDeflate2 = require_permessage_deflate();
    var { EMPTY_BUFFER, kWebSocket, NOOP } = require_constants();
    var { isBlob, isValidStatusCode } = require_validation();
    var { mask: applyMask, toBuffer } = require_buffer_util();
    var kByteLength = Symbol("kByteLength");
    var maskBuffer = Buffer.alloc(4);
    var RANDOM_POOL_SIZE = 8 * 1024;
    var randomPool;
    var randomPoolPointer = RANDOM_POOL_SIZE;
    var DEFAULT = 0;
    var DEFLATING = 1;
    var GET_BLOB_DATA = 2;
    var Sender2 = class _Sender {
      /**
       * Creates a Sender instance.
       *
       * @param {Duplex} socket The connection socket
       * @param {Object} [extensions] An object containing the negotiated extensions
       * @param {Function} [generateMask] The function used to generate the masking
       *     key
       */
      constructor(socket, extensions, generateMask) {
        this._extensions = extensions || {};
        if (generateMask) {
          this._generateMask = generateMask;
          this._maskBuffer = Buffer.alloc(4);
        }
        this._socket = socket;
        this._firstFragment = true;
        this._compress = false;
        this._bufferedBytes = 0;
        this._queue = [];
        this._state = DEFAULT;
        this.onerror = NOOP;
        this[kWebSocket] = void 0;
      }
      /**
       * Frames a piece of data according to the HyBi WebSocket protocol.
       *
       * @param {(Buffer|String)} data The data to frame
       * @param {Object} options Options object
       * @param {Boolean} [options.fin=false] Specifies whether or not to set the
       *     FIN bit
       * @param {Function} [options.generateMask] The function used to generate the
       *     masking key
       * @param {Boolean} [options.mask=false] Specifies whether or not to mask
       *     `data`
       * @param {Buffer} [options.maskBuffer] The buffer used to store the masking
       *     key
       * @param {Number} options.opcode The opcode
       * @param {Boolean} [options.readOnly=false] Specifies whether `data` can be
       *     modified
       * @param {Boolean} [options.rsv1=false] Specifies whether or not to set the
       *     RSV1 bit
       * @return {(Buffer|String)[]} The framed data
       * @public
       */
      static frame(data, options) {
        let mask;
        let merge = false;
        let offset = 2;
        let skipMasking = false;
        if (options.mask) {
          mask = options.maskBuffer || maskBuffer;
          if (options.generateMask) {
            options.generateMask(mask);
          } else {
            if (randomPoolPointer === RANDOM_POOL_SIZE) {
              if (randomPool === void 0) {
                randomPool = Buffer.alloc(RANDOM_POOL_SIZE);
              }
              randomFillSync(randomPool, 0, RANDOM_POOL_SIZE);
              randomPoolPointer = 0;
            }
            mask[0] = randomPool[randomPoolPointer++];
            mask[1] = randomPool[randomPoolPointer++];
            mask[2] = randomPool[randomPoolPointer++];
            mask[3] = randomPool[randomPoolPointer++];
          }
          skipMasking = (mask[0] | mask[1] | mask[2] | mask[3]) === 0;
          offset = 6;
        }
        let dataLength;
        if (typeof data === "string") {
          if ((!options.mask || skipMasking) && options[kByteLength] !== void 0) {
            dataLength = options[kByteLength];
          } else {
            data = Buffer.from(data);
            dataLength = data.length;
          }
        } else {
          dataLength = data.length;
          merge = options.mask && options.readOnly && !skipMasking;
        }
        let payloadLength = dataLength;
        if (dataLength >= 65536) {
          offset += 8;
          payloadLength = 127;
        } else if (dataLength > 125) {
          offset += 2;
          payloadLength = 126;
        }
        const target = Buffer.allocUnsafe(merge ? dataLength + offset : offset);
        target[0] = options.fin ? options.opcode | 128 : options.opcode;
        if (options.rsv1) target[0] |= 64;
        target[1] = payloadLength;
        if (payloadLength === 126) {
          target.writeUInt16BE(dataLength, 2);
        } else if (payloadLength === 127) {
          target[2] = target[3] = 0;
          target.writeUIntBE(dataLength, 4, 6);
        }
        if (!options.mask) return [target, data];
        target[1] |= 128;
        target[offset - 4] = mask[0];
        target[offset - 3] = mask[1];
        target[offset - 2] = mask[2];
        target[offset - 1] = mask[3];
        if (skipMasking) return [target, data];
        if (merge) {
          applyMask(data, mask, target, offset, dataLength);
          return [target];
        }
        applyMask(data, mask, data, 0, dataLength);
        return [target, data];
      }
      /**
       * Sends a close message to the other peer.
       *
       * @param {Number} [code] The status code component of the body
       * @param {(String|Buffer)} [data] The message component of the body
       * @param {Boolean} [mask=false] Specifies whether or not to mask the message
       * @param {Function} [cb] Callback
       * @public
       */
      close(code, data, mask, cb) {
        let buf;
        if (code === void 0) {
          buf = EMPTY_BUFFER;
        } else if (typeof code !== "number" || !isValidStatusCode(code)) {
          throw new TypeError("First argument must be a valid error code number");
        } else if (data === void 0 || !data.length) {
          buf = Buffer.allocUnsafe(2);
          buf.writeUInt16BE(code, 0);
        } else {
          const length = Buffer.byteLength(data);
          if (length > 123) {
            throw new RangeError("The message must not be greater than 123 bytes");
          }
          buf = Buffer.allocUnsafe(2 + length);
          buf.writeUInt16BE(code, 0);
          if (typeof data === "string") {
            buf.write(data, 2);
          } else if (isUint8Array(data)) {
            buf.set(data, 2);
          } else {
            throw new TypeError("Second argument must be a string or a Uint8Array");
          }
        }
        const options = {
          [kByteLength]: buf.length,
          fin: true,
          generateMask: this._generateMask,
          mask,
          maskBuffer: this._maskBuffer,
          opcode: 8,
          readOnly: false,
          rsv1: false
        };
        if (this._state !== DEFAULT) {
          this.enqueue([this.dispatch, buf, false, options, cb]);
        } else {
          this.sendFrame(_Sender.frame(buf, options), cb);
        }
      }
      /**
       * Sends a ping message to the other peer.
       *
       * @param {*} data The message to send
       * @param {Boolean} [mask=false] Specifies whether or not to mask `data`
       * @param {Function} [cb] Callback
       * @public
       */
      ping(data, mask, cb) {
        let byteLength;
        let readOnly;
        if (typeof data === "string") {
          byteLength = Buffer.byteLength(data);
          readOnly = false;
        } else if (isBlob(data)) {
          byteLength = data.size;
          readOnly = false;
        } else {
          data = toBuffer(data);
          byteLength = data.length;
          readOnly = toBuffer.readOnly;
        }
        if (byteLength > 125) {
          throw new RangeError("The data size must not be greater than 125 bytes");
        }
        const options = {
          [kByteLength]: byteLength,
          fin: true,
          generateMask: this._generateMask,
          mask,
          maskBuffer: this._maskBuffer,
          opcode: 9,
          readOnly,
          rsv1: false
        };
        if (isBlob(data)) {
          if (this._state !== DEFAULT) {
            this.enqueue([this.getBlobData, data, false, options, cb]);
          } else {
            this.getBlobData(data, false, options, cb);
          }
        } else if (this._state !== DEFAULT) {
          this.enqueue([this.dispatch, data, false, options, cb]);
        } else {
          this.sendFrame(_Sender.frame(data, options), cb);
        }
      }
      /**
       * Sends a pong message to the other peer.
       *
       * @param {*} data The message to send
       * @param {Boolean} [mask=false] Specifies whether or not to mask `data`
       * @param {Function} [cb] Callback
       * @public
       */
      pong(data, mask, cb) {
        let byteLength;
        let readOnly;
        if (typeof data === "string") {
          byteLength = Buffer.byteLength(data);
          readOnly = false;
        } else if (isBlob(data)) {
          byteLength = data.size;
          readOnly = false;
        } else {
          data = toBuffer(data);
          byteLength = data.length;
          readOnly = toBuffer.readOnly;
        }
        if (byteLength > 125) {
          throw new RangeError("The data size must not be greater than 125 bytes");
        }
        const options = {
          [kByteLength]: byteLength,
          fin: true,
          generateMask: this._generateMask,
          mask,
          maskBuffer: this._maskBuffer,
          opcode: 10,
          readOnly,
          rsv1: false
        };
        if (isBlob(data)) {
          if (this._state !== DEFAULT) {
            this.enqueue([this.getBlobData, data, false, options, cb]);
          } else {
            this.getBlobData(data, false, options, cb);
          }
        } else if (this._state !== DEFAULT) {
          this.enqueue([this.dispatch, data, false, options, cb]);
        } else {
          this.sendFrame(_Sender.frame(data, options), cb);
        }
      }
      /**
       * Sends a data message to the other peer.
       *
       * @param {*} data The message to send
       * @param {Object} options Options object
       * @param {Boolean} [options.binary=false] Specifies whether `data` is binary
       *     or text
       * @param {Boolean} [options.compress=false] Specifies whether or not to
       *     compress `data`
       * @param {Boolean} [options.fin=false] Specifies whether the fragment is the
       *     last one
       * @param {Boolean} [options.mask=false] Specifies whether or not to mask
       *     `data`
       * @param {Function} [cb] Callback
       * @public
       */
      send(data, options, cb) {
        const perMessageDeflate = this._extensions[PerMessageDeflate2.extensionName];
        let opcode = options.binary ? 2 : 1;
        let rsv1 = options.compress;
        let byteLength;
        let readOnly;
        if (typeof data === "string") {
          byteLength = Buffer.byteLength(data);
          readOnly = false;
        } else if (isBlob(data)) {
          byteLength = data.size;
          readOnly = false;
        } else {
          data = toBuffer(data);
          byteLength = data.length;
          readOnly = toBuffer.readOnly;
        }
        if (this._firstFragment) {
          this._firstFragment = false;
          if (rsv1 && perMessageDeflate && perMessageDeflate.params[perMessageDeflate._isServer ? "server_no_context_takeover" : "client_no_context_takeover"]) {
            rsv1 = byteLength >= perMessageDeflate._threshold;
          }
          this._compress = rsv1;
        } else {
          rsv1 = false;
          opcode = 0;
        }
        if (options.fin) this._firstFragment = true;
        const opts = {
          [kByteLength]: byteLength,
          fin: options.fin,
          generateMask: this._generateMask,
          mask: options.mask,
          maskBuffer: this._maskBuffer,
          opcode,
          readOnly,
          rsv1
        };
        if (isBlob(data)) {
          if (this._state !== DEFAULT) {
            this.enqueue([this.getBlobData, data, this._compress, opts, cb]);
          } else {
            this.getBlobData(data, this._compress, opts, cb);
          }
        } else if (this._state !== DEFAULT) {
          this.enqueue([this.dispatch, data, this._compress, opts, cb]);
        } else {
          this.dispatch(data, this._compress, opts, cb);
        }
      }
      /**
       * Gets the contents of a blob as binary data.
       *
       * @param {Blob} blob The blob
       * @param {Boolean} [compress=false] Specifies whether or not to compress
       *     the data
       * @param {Object} options Options object
       * @param {Boolean} [options.fin=false] Specifies whether or not to set the
       *     FIN bit
       * @param {Function} [options.generateMask] The function used to generate the
       *     masking key
       * @param {Boolean} [options.mask=false] Specifies whether or not to mask
       *     `data`
       * @param {Buffer} [options.maskBuffer] The buffer used to store the masking
       *     key
       * @param {Number} options.opcode The opcode
       * @param {Boolean} [options.readOnly=false] Specifies whether `data` can be
       *     modified
       * @param {Boolean} [options.rsv1=false] Specifies whether or not to set the
       *     RSV1 bit
       * @param {Function} [cb] Callback
       * @private
       */
      getBlobData(blob2, compress, options, cb) {
        this._bufferedBytes += options[kByteLength];
        this._state = GET_BLOB_DATA;
        blob2.arrayBuffer().then((arrayBuffer) => {
          if (this._socket.destroyed) {
            const err = new Error(
              "The socket was closed while the blob was being read"
            );
            process.nextTick(callCallbacks, this, err, cb);
            return;
          }
          this._bufferedBytes -= options[kByteLength];
          const data = toBuffer(arrayBuffer);
          if (!compress) {
            this._state = DEFAULT;
            this.sendFrame(_Sender.frame(data, options), cb);
            this.dequeue();
          } else {
            this.dispatch(data, compress, options, cb);
          }
        }).catch((err) => {
          process.nextTick(onError, this, err, cb);
        });
      }
      /**
       * Dispatches a message.
       *
       * @param {(Buffer|String)} data The message to send
       * @param {Boolean} [compress=false] Specifies whether or not to compress
       *     `data`
       * @param {Object} options Options object
       * @param {Boolean} [options.fin=false] Specifies whether or not to set the
       *     FIN bit
       * @param {Function} [options.generateMask] The function used to generate the
       *     masking key
       * @param {Boolean} [options.mask=false] Specifies whether or not to mask
       *     `data`
       * @param {Buffer} [options.maskBuffer] The buffer used to store the masking
       *     key
       * @param {Number} options.opcode The opcode
       * @param {Boolean} [options.readOnly=false] Specifies whether `data` can be
       *     modified
       * @param {Boolean} [options.rsv1=false] Specifies whether or not to set the
       *     RSV1 bit
       * @param {Function} [cb] Callback
       * @private
       */
      dispatch(data, compress, options, cb) {
        if (!compress) {
          this.sendFrame(_Sender.frame(data, options), cb);
          return;
        }
        const perMessageDeflate = this._extensions[PerMessageDeflate2.extensionName];
        this._bufferedBytes += options[kByteLength];
        this._state = DEFLATING;
        perMessageDeflate.compress(data, options.fin, (_, buf) => {
          if (this._socket.destroyed) {
            const err = new Error(
              "The socket was closed while data was being compressed"
            );
            callCallbacks(this, err, cb);
            return;
          }
          this._bufferedBytes -= options[kByteLength];
          this._state = DEFAULT;
          options.readOnly = false;
          this.sendFrame(_Sender.frame(buf, options), cb);
          this.dequeue();
        });
      }
      /**
       * Executes queued send operations.
       *
       * @private
       */
      dequeue() {
        while (this._state === DEFAULT && this._queue.length) {
          const params = this._queue.shift();
          this._bufferedBytes -= params[3][kByteLength];
          Reflect.apply(params[0], this, params.slice(1));
        }
      }
      /**
       * Enqueues a send operation.
       *
       * @param {Array} params Send operation parameters.
       * @private
       */
      enqueue(params) {
        this._bufferedBytes += params[3][kByteLength];
        this._queue.push(params);
      }
      /**
       * Sends a frame.
       *
       * @param {(Buffer | String)[]} list The frame to send
       * @param {Function} [cb] Callback
       * @private
       */
      sendFrame(list, cb) {
        if (list.length === 2) {
          this._socket.cork();
          this._socket.write(list[0]);
          this._socket.write(list[1], cb);
          this._socket.uncork();
        } else {
          this._socket.write(list[0], cb);
        }
      }
    };
    module.exports = Sender2;
    function callCallbacks(sender, err, cb) {
      if (typeof cb === "function") cb(err);
      for (let i = 0; i < sender._queue.length; i++) {
        const params = sender._queue[i];
        const callback = params[params.length - 1];
        if (typeof callback === "function") callback(err);
      }
    }
    function onError(sender, err, cb) {
      callCallbacks(sender, err, cb);
      sender.onerror(err);
    }
  }
});

// ../../node_modules/.pnpm/ws@8.21.0/node_modules/ws/lib/event-target.js
var require_event_target = __commonJS({
  "../../node_modules/.pnpm/ws@8.21.0/node_modules/ws/lib/event-target.js"(exports, module) {
    "use strict";
    var { kForOnEventAttribute, kListener } = require_constants();
    var kCode = Symbol("kCode");
    var kData = Symbol("kData");
    var kError = Symbol("kError");
    var kMessage = Symbol("kMessage");
    var kReason = Symbol("kReason");
    var kTarget = Symbol("kTarget");
    var kType = Symbol("kType");
    var kWasClean = Symbol("kWasClean");
    var Event = class {
      /**
       * Create a new `Event`.
       *
       * @param {String} type The name of the event
       * @throws {TypeError} If the `type` argument is not specified
       */
      constructor(type) {
        this[kTarget] = null;
        this[kType] = type;
      }
      /**
       * @type {*}
       */
      get target() {
        return this[kTarget];
      }
      /**
       * @type {String}
       */
      get type() {
        return this[kType];
      }
    };
    Object.defineProperty(Event.prototype, "target", { enumerable: true });
    Object.defineProperty(Event.prototype, "type", { enumerable: true });
    var CloseEvent = class extends Event {
      /**
       * Create a new `CloseEvent`.
       *
       * @param {String} type The name of the event
       * @param {Object} [options] A dictionary object that allows for setting
       *     attributes via object members of the same name
       * @param {Number} [options.code=0] The status code explaining why the
       *     connection was closed
       * @param {String} [options.reason=''] A human-readable string explaining why
       *     the connection was closed
       * @param {Boolean} [options.wasClean=false] Indicates whether or not the
       *     connection was cleanly closed
       */
      constructor(type, options = {}) {
        super(type);
        this[kCode] = options.code === void 0 ? 0 : options.code;
        this[kReason] = options.reason === void 0 ? "" : options.reason;
        this[kWasClean] = options.wasClean === void 0 ? false : options.wasClean;
      }
      /**
       * @type {Number}
       */
      get code() {
        return this[kCode];
      }
      /**
       * @type {String}
       */
      get reason() {
        return this[kReason];
      }
      /**
       * @type {Boolean}
       */
      get wasClean() {
        return this[kWasClean];
      }
    };
    Object.defineProperty(CloseEvent.prototype, "code", { enumerable: true });
    Object.defineProperty(CloseEvent.prototype, "reason", { enumerable: true });
    Object.defineProperty(CloseEvent.prototype, "wasClean", { enumerable: true });
    var ErrorEvent = class extends Event {
      /**
       * Create a new `ErrorEvent`.
       *
       * @param {String} type The name of the event
       * @param {Object} [options] A dictionary object that allows for setting
       *     attributes via object members of the same name
       * @param {*} [options.error=null] The error that generated this event
       * @param {String} [options.message=''] The error message
       */
      constructor(type, options = {}) {
        super(type);
        this[kError] = options.error === void 0 ? null : options.error;
        this[kMessage] = options.message === void 0 ? "" : options.message;
      }
      /**
       * @type {*}
       */
      get error() {
        return this[kError];
      }
      /**
       * @type {String}
       */
      get message() {
        return this[kMessage];
      }
    };
    Object.defineProperty(ErrorEvent.prototype, "error", { enumerable: true });
    Object.defineProperty(ErrorEvent.prototype, "message", { enumerable: true });
    var MessageEvent = class extends Event {
      /**
       * Create a new `MessageEvent`.
       *
       * @param {String} type The name of the event
       * @param {Object} [options] A dictionary object that allows for setting
       *     attributes via object members of the same name
       * @param {*} [options.data=null] The message content
       */
      constructor(type, options = {}) {
        super(type);
        this[kData] = options.data === void 0 ? null : options.data;
      }
      /**
       * @type {*}
       */
      get data() {
        return this[kData];
      }
    };
    Object.defineProperty(MessageEvent.prototype, "data", { enumerable: true });
    var EventTarget = {
      /**
       * Register an event listener.
       *
       * @param {String} type A string representing the event type to listen for
       * @param {(Function|Object)} handler The listener to add
       * @param {Object} [options] An options object specifies characteristics about
       *     the event listener
       * @param {Boolean} [options.once=false] A `Boolean` indicating that the
       *     listener should be invoked at most once after being added. If `true`,
       *     the listener would be automatically removed when invoked.
       * @public
       */
      addEventListener(type, handler, options = {}) {
        for (const listener of this.listeners(type)) {
          if (!options[kForOnEventAttribute] && listener[kListener] === handler && !listener[kForOnEventAttribute]) {
            return;
          }
        }
        let wrapper;
        if (type === "message") {
          wrapper = function onMessage(data, isBinary) {
            const event = new MessageEvent("message", {
              data: isBinary ? data : data.toString()
            });
            event[kTarget] = this;
            callListener(handler, this, event);
          };
        } else if (type === "close") {
          wrapper = function onClose(code, message) {
            const event = new CloseEvent("close", {
              code,
              reason: message.toString(),
              wasClean: this._closeFrameReceived && this._closeFrameSent
            });
            event[kTarget] = this;
            callListener(handler, this, event);
          };
        } else if (type === "error") {
          wrapper = function onError(error) {
            const event = new ErrorEvent("error", {
              error,
              message: error.message
            });
            event[kTarget] = this;
            callListener(handler, this, event);
          };
        } else if (type === "open") {
          wrapper = function onOpen() {
            const event = new Event("open");
            event[kTarget] = this;
            callListener(handler, this, event);
          };
        } else {
          return;
        }
        wrapper[kForOnEventAttribute] = !!options[kForOnEventAttribute];
        wrapper[kListener] = handler;
        if (options.once) {
          this.once(type, wrapper);
        } else {
          this.on(type, wrapper);
        }
      },
      /**
       * Remove an event listener.
       *
       * @param {String} type A string representing the event type to remove
       * @param {(Function|Object)} handler The listener to remove
       * @public
       */
      removeEventListener(type, handler) {
        for (const listener of this.listeners(type)) {
          if (listener[kListener] === handler && !listener[kForOnEventAttribute]) {
            this.removeListener(type, listener);
            break;
          }
        }
      }
    };
    module.exports = {
      CloseEvent,
      ErrorEvent,
      Event,
      EventTarget,
      MessageEvent
    };
    function callListener(listener, thisArg, event) {
      if (typeof listener === "object" && listener.handleEvent) {
        listener.handleEvent.call(listener, event);
      } else {
        listener.call(thisArg, event);
      }
    }
  }
});

// ../../node_modules/.pnpm/ws@8.21.0/node_modules/ws/lib/extension.js
var require_extension = __commonJS({
  "../../node_modules/.pnpm/ws@8.21.0/node_modules/ws/lib/extension.js"(exports, module) {
    "use strict";
    var { tokenChars } = require_validation();
    function push(dest, name, elem) {
      if (dest[name] === void 0) dest[name] = [elem];
      else dest[name].push(elem);
    }
    function parse2(header) {
      const offers = /* @__PURE__ */ Object.create(null);
      let params = /* @__PURE__ */ Object.create(null);
      let mustUnescape = false;
      let isEscaping = false;
      let inQuotes = false;
      let extensionName;
      let paramName;
      let start = -1;
      let code = -1;
      let end = -1;
      let i = 0;
      for (; i < header.length; i++) {
        code = header.charCodeAt(i);
        if (extensionName === void 0) {
          if (end === -1 && tokenChars[code] === 1) {
            if (start === -1) start = i;
          } else if (i !== 0 && (code === 32 || code === 9)) {
            if (end === -1 && start !== -1) end = i;
          } else if (code === 59 || code === 44) {
            if (start === -1) {
              throw new SyntaxError(`Unexpected character at index ${i}`);
            }
            if (end === -1) end = i;
            const name = header.slice(start, end);
            if (code === 44) {
              push(offers, name, params);
              params = /* @__PURE__ */ Object.create(null);
            } else {
              extensionName = name;
            }
            start = end = -1;
          } else {
            throw new SyntaxError(`Unexpected character at index ${i}`);
          }
        } else if (paramName === void 0) {
          if (end === -1 && tokenChars[code] === 1) {
            if (start === -1) start = i;
          } else if (code === 32 || code === 9) {
            if (end === -1 && start !== -1) end = i;
          } else if (code === 59 || code === 44) {
            if (start === -1) {
              throw new SyntaxError(`Unexpected character at index ${i}`);
            }
            if (end === -1) end = i;
            push(params, header.slice(start, end), true);
            if (code === 44) {
              push(offers, extensionName, params);
              params = /* @__PURE__ */ Object.create(null);
              extensionName = void 0;
            }
            start = end = -1;
          } else if (code === 61 && start !== -1 && end === -1) {
            paramName = header.slice(start, i);
            start = end = -1;
          } else {
            throw new SyntaxError(`Unexpected character at index ${i}`);
          }
        } else {
          if (isEscaping) {
            if (tokenChars[code] !== 1) {
              throw new SyntaxError(`Unexpected character at index ${i}`);
            }
            if (start === -1) start = i;
            else if (!mustUnescape) mustUnescape = true;
            isEscaping = false;
          } else if (inQuotes) {
            if (tokenChars[code] === 1) {
              if (start === -1) start = i;
            } else if (code === 34 && start !== -1) {
              inQuotes = false;
              end = i;
            } else if (code === 92) {
              isEscaping = true;
            } else {
              throw new SyntaxError(`Unexpected character at index ${i}`);
            }
          } else if (code === 34 && header.charCodeAt(i - 1) === 61) {
            inQuotes = true;
          } else if (end === -1 && tokenChars[code] === 1) {
            if (start === -1) start = i;
          } else if (start !== -1 && (code === 32 || code === 9)) {
            if (end === -1) end = i;
          } else if (code === 59 || code === 44) {
            if (start === -1) {
              throw new SyntaxError(`Unexpected character at index ${i}`);
            }
            if (end === -1) end = i;
            let value = header.slice(start, end);
            if (mustUnescape) {
              value = value.replace(/\\/g, "");
              mustUnescape = false;
            }
            push(params, paramName, value);
            if (code === 44) {
              push(offers, extensionName, params);
              params = /* @__PURE__ */ Object.create(null);
              extensionName = void 0;
            }
            paramName = void 0;
            start = end = -1;
          } else {
            throw new SyntaxError(`Unexpected character at index ${i}`);
          }
        }
      }
      if (start === -1 || inQuotes || code === 32 || code === 9) {
        throw new SyntaxError("Unexpected end of input");
      }
      if (end === -1) end = i;
      const token = header.slice(start, end);
      if (extensionName === void 0) {
        push(offers, token, params);
      } else {
        if (paramName === void 0) {
          push(params, token, true);
        } else if (mustUnescape) {
          push(params, paramName, token.replace(/\\/g, ""));
        } else {
          push(params, paramName, token);
        }
        push(offers, extensionName, params);
      }
      return offers;
    }
    function format(extensions) {
      return Object.keys(extensions).map((extension2) => {
        let configurations = extensions[extension2];
        if (!Array.isArray(configurations)) configurations = [configurations];
        return configurations.map((params) => {
          return [extension2].concat(
            Object.keys(params).map((k) => {
              let values = params[k];
              if (!Array.isArray(values)) values = [values];
              return values.map((v) => v === true ? k : `${k}=${v}`).join("; ");
            })
          ).join("; ");
        }).join(", ");
      }).join(", ");
    }
    module.exports = { format, parse: parse2 };
  }
});

// ../../node_modules/.pnpm/ws@8.21.0/node_modules/ws/lib/websocket.js
var require_websocket = __commonJS({
  "../../node_modules/.pnpm/ws@8.21.0/node_modules/ws/lib/websocket.js"(exports, module) {
    "use strict";
    var EventEmitter2 = __require("events");
    var https = __require("https");
    var http = __require("http");
    var net = __require("net");
    var tls = __require("tls");
    var { randomBytes: randomBytes3, createHash: createHash4 } = __require("crypto");
    var { Duplex, Readable: Readable2 } = __require("stream");
    var { URL: URL2 } = __require("url");
    var PerMessageDeflate2 = require_permessage_deflate();
    var Receiver2 = require_receiver();
    var Sender2 = require_sender();
    var { isBlob } = require_validation();
    var {
      BINARY_TYPES,
      CLOSE_TIMEOUT,
      EMPTY_BUFFER,
      GUID,
      kForOnEventAttribute,
      kListener,
      kStatusCode,
      kWebSocket,
      NOOP
    } = require_constants();
    var {
      EventTarget: { addEventListener: addEventListener2, removeEventListener }
    } = require_event_target();
    var { format, parse: parse2 } = require_extension();
    var { toBuffer } = require_buffer_util();
    var kAborted = Symbol("kAborted");
    var protocolVersions = [8, 13];
    var readyStates = ["CONNECTING", "OPEN", "CLOSING", "CLOSED"];
    var subprotocolRegex = /^[!#$%&'*+\-.0-9A-Z^_`|a-z~]+$/;
    var WebSocket2 = class _WebSocket extends EventEmitter2 {
      /**
       * Create a new `WebSocket`.
       *
       * @param {(String|URL)} address The URL to which to connect
       * @param {(String|String[])} [protocols] The subprotocols
       * @param {Object} [options] Connection options
       */
      constructor(address, protocols, options) {
        super();
        this._binaryType = BINARY_TYPES[0];
        this._closeCode = 1006;
        this._closeFrameReceived = false;
        this._closeFrameSent = false;
        this._closeMessage = EMPTY_BUFFER;
        this._closeTimer = null;
        this._errorEmitted = false;
        this._extensions = {};
        this._paused = false;
        this._protocol = "";
        this._readyState = _WebSocket.CONNECTING;
        this._receiver = null;
        this._sender = null;
        this._socket = null;
        if (address !== null) {
          this._bufferedAmount = 0;
          this._isServer = false;
          this._redirects = 0;
          if (protocols === void 0) {
            protocols = [];
          } else if (!Array.isArray(protocols)) {
            if (typeof protocols === "object" && protocols !== null) {
              options = protocols;
              protocols = [];
            } else {
              protocols = [protocols];
            }
          }
          initAsClient(this, address, protocols, options);
        } else {
          this._autoPong = options.autoPong;
          this._closeTimeout = options.closeTimeout;
          this._isServer = true;
        }
      }
      /**
       * For historical reasons, the custom "nodebuffer" type is used by the default
       * instead of "blob".
       *
       * @type {String}
       */
      get binaryType() {
        return this._binaryType;
      }
      set binaryType(type) {
        if (!BINARY_TYPES.includes(type)) return;
        this._binaryType = type;
        if (this._receiver) this._receiver._binaryType = type;
      }
      /**
       * @type {Number}
       */
      get bufferedAmount() {
        if (!this._socket) return this._bufferedAmount;
        return this._socket._writableState.length + this._sender._bufferedBytes;
      }
      /**
       * @type {String}
       */
      get extensions() {
        return Object.keys(this._extensions).join();
      }
      /**
       * @type {Boolean}
       */
      get isPaused() {
        return this._paused;
      }
      /**
       * @type {Function}
       */
      /* istanbul ignore next */
      get onclose() {
        return null;
      }
      /**
       * @type {Function}
       */
      /* istanbul ignore next */
      get onerror() {
        return null;
      }
      /**
       * @type {Function}
       */
      /* istanbul ignore next */
      get onopen() {
        return null;
      }
      /**
       * @type {Function}
       */
      /* istanbul ignore next */
      get onmessage() {
        return null;
      }
      /**
       * @type {String}
       */
      get protocol() {
        return this._protocol;
      }
      /**
       * @type {Number}
       */
      get readyState() {
        return this._readyState;
      }
      /**
       * @type {String}
       */
      get url() {
        return this._url;
      }
      /**
       * Set up the socket and the internal resources.
       *
       * @param {Duplex} socket The network socket between the server and client
       * @param {Buffer} head The first packet of the upgraded stream
       * @param {Object} options Options object
       * @param {Boolean} [options.allowSynchronousEvents=false] Specifies whether
       *     any of the `'message'`, `'ping'`, and `'pong'` events can be emitted
       *     multiple times in the same tick
       * @param {Function} [options.generateMask] The function used to generate the
       *     masking key
       * @param {Number} [options.maxBufferedChunks=0] The maximum number of
       *     buffered data chunks
       * @param {Number} [options.maxFragments=0] The maximum number of message
       *     fragments
       * @param {Number} [options.maxPayload=0] The maximum allowed message size
       * @param {Boolean} [options.skipUTF8Validation=false] Specifies whether or
       *     not to skip UTF-8 validation for text and close messages
       * @private
       */
      setSocket(socket, head, options) {
        const receiver = new Receiver2({
          allowSynchronousEvents: options.allowSynchronousEvents,
          binaryType: this.binaryType,
          extensions: this._extensions,
          isServer: this._isServer,
          maxBufferedChunks: options.maxBufferedChunks,
          maxFragments: options.maxFragments,
          maxPayload: options.maxPayload,
          skipUTF8Validation: options.skipUTF8Validation
        });
        const sender = new Sender2(socket, this._extensions, options.generateMask);
        this._receiver = receiver;
        this._sender = sender;
        this._socket = socket;
        receiver[kWebSocket] = this;
        sender[kWebSocket] = this;
        socket[kWebSocket] = this;
        receiver.on("conclude", receiverOnConclude);
        receiver.on("drain", receiverOnDrain);
        receiver.on("error", receiverOnError);
        receiver.on("message", receiverOnMessage);
        receiver.on("ping", receiverOnPing);
        receiver.on("pong", receiverOnPong);
        sender.onerror = senderOnError;
        if (socket.setTimeout) socket.setTimeout(0);
        if (socket.setNoDelay) socket.setNoDelay();
        if (head.length > 0) socket.unshift(head);
        socket.on("close", socketOnClose);
        socket.on("data", socketOnData);
        socket.on("end", socketOnEnd);
        socket.on("error", socketOnError);
        this._readyState = _WebSocket.OPEN;
        this.emit("open");
      }
      /**
       * Emit the `'close'` event.
       *
       * @private
       */
      emitClose() {
        if (!this._socket) {
          this._readyState = _WebSocket.CLOSED;
          this.emit("close", this._closeCode, this._closeMessage);
          return;
        }
        if (this._extensions[PerMessageDeflate2.extensionName]) {
          this._extensions[PerMessageDeflate2.extensionName].cleanup();
        }
        this._receiver.removeAllListeners();
        this._readyState = _WebSocket.CLOSED;
        this.emit("close", this._closeCode, this._closeMessage);
      }
      /**
       * Start a closing handshake.
       *
       *          +----------+   +-----------+   +----------+
       *     - - -|ws.close()|-->|close frame|-->|ws.close()|- - -
       *    |     +----------+   +-----------+   +----------+     |
       *          +----------+   +-----------+         |
       * CLOSING  |ws.close()|<--|close frame|<--+-----+       CLOSING
       *          +----------+   +-----------+   |
       *    |           |                        |   +---+        |
       *                +------------------------+-->|fin| - - - -
       *    |         +---+                      |   +---+
       *     - - - - -|fin|<---------------------+
       *              +---+
       *
       * @param {Number} [code] Status code explaining why the connection is closing
       * @param {(String|Buffer)} [data] The reason why the connection is
       *     closing
       * @public
       */
      close(code, data) {
        if (this.readyState === _WebSocket.CLOSED) return;
        if (this.readyState === _WebSocket.CONNECTING) {
          const msg = "WebSocket was closed before the connection was established";
          abortHandshake(this, this._req, msg);
          return;
        }
        if (this.readyState === _WebSocket.CLOSING) {
          if (this._closeFrameSent && (this._closeFrameReceived || this._receiver._writableState.errorEmitted)) {
            this._socket.end();
          }
          return;
        }
        this._readyState = _WebSocket.CLOSING;
        this._sender.close(code, data, !this._isServer, (err) => {
          if (err) return;
          this._closeFrameSent = true;
          if (this._closeFrameReceived || this._receiver._writableState.errorEmitted) {
            this._socket.end();
          }
        });
        setCloseTimer(this);
      }
      /**
       * Pause the socket.
       *
       * @public
       */
      pause() {
        if (this.readyState === _WebSocket.CONNECTING || this.readyState === _WebSocket.CLOSED) {
          return;
        }
        this._paused = true;
        this._socket.pause();
      }
      /**
       * Send a ping.
       *
       * @param {*} [data] The data to send
       * @param {Boolean} [mask] Indicates whether or not to mask `data`
       * @param {Function} [cb] Callback which is executed when the ping is sent
       * @public
       */
      ping(data, mask, cb) {
        if (this.readyState === _WebSocket.CONNECTING) {
          throw new Error("WebSocket is not open: readyState 0 (CONNECTING)");
        }
        if (typeof data === "function") {
          cb = data;
          data = mask = void 0;
        } else if (typeof mask === "function") {
          cb = mask;
          mask = void 0;
        }
        if (typeof data === "number") data = data.toString();
        if (this.readyState !== _WebSocket.OPEN) {
          sendAfterClose(this, data, cb);
          return;
        }
        if (mask === void 0) mask = !this._isServer;
        this._sender.ping(data || EMPTY_BUFFER, mask, cb);
      }
      /**
       * Send a pong.
       *
       * @param {*} [data] The data to send
       * @param {Boolean} [mask] Indicates whether or not to mask `data`
       * @param {Function} [cb] Callback which is executed when the pong is sent
       * @public
       */
      pong(data, mask, cb) {
        if (this.readyState === _WebSocket.CONNECTING) {
          throw new Error("WebSocket is not open: readyState 0 (CONNECTING)");
        }
        if (typeof data === "function") {
          cb = data;
          data = mask = void 0;
        } else if (typeof mask === "function") {
          cb = mask;
          mask = void 0;
        }
        if (typeof data === "number") data = data.toString();
        if (this.readyState !== _WebSocket.OPEN) {
          sendAfterClose(this, data, cb);
          return;
        }
        if (mask === void 0) mask = !this._isServer;
        this._sender.pong(data || EMPTY_BUFFER, mask, cb);
      }
      /**
       * Resume the socket.
       *
       * @public
       */
      resume() {
        if (this.readyState === _WebSocket.CONNECTING || this.readyState === _WebSocket.CLOSED) {
          return;
        }
        this._paused = false;
        if (!this._receiver._writableState.needDrain) this._socket.resume();
      }
      /**
       * Send a data message.
       *
       * @param {*} data The message to send
       * @param {Object} [options] Options object
       * @param {Boolean} [options.binary] Specifies whether `data` is binary or
       *     text
       * @param {Boolean} [options.compress] Specifies whether or not to compress
       *     `data`
       * @param {Boolean} [options.fin=true] Specifies whether the fragment is the
       *     last one
       * @param {Boolean} [options.mask] Specifies whether or not to mask `data`
       * @param {Function} [cb] Callback which is executed when data is written out
       * @public
       */
      send(data, options, cb) {
        if (this.readyState === _WebSocket.CONNECTING) {
          throw new Error("WebSocket is not open: readyState 0 (CONNECTING)");
        }
        if (typeof options === "function") {
          cb = options;
          options = {};
        }
        if (typeof data === "number") data = data.toString();
        if (this.readyState !== _WebSocket.OPEN) {
          sendAfterClose(this, data, cb);
          return;
        }
        const opts = {
          binary: typeof data !== "string",
          mask: !this._isServer,
          compress: true,
          fin: true,
          ...options
        };
        if (!this._extensions[PerMessageDeflate2.extensionName]) {
          opts.compress = false;
        }
        this._sender.send(data || EMPTY_BUFFER, opts, cb);
      }
      /**
       * Forcibly close the connection.
       *
       * @public
       */
      terminate() {
        if (this.readyState === _WebSocket.CLOSED) return;
        if (this.readyState === _WebSocket.CONNECTING) {
          const msg = "WebSocket was closed before the connection was established";
          abortHandshake(this, this._req, msg);
          return;
        }
        if (this._socket) {
          this._readyState = _WebSocket.CLOSING;
          this._socket.destroy();
        }
      }
    };
    Object.defineProperty(WebSocket2, "CONNECTING", {
      enumerable: true,
      value: readyStates.indexOf("CONNECTING")
    });
    Object.defineProperty(WebSocket2.prototype, "CONNECTING", {
      enumerable: true,
      value: readyStates.indexOf("CONNECTING")
    });
    Object.defineProperty(WebSocket2, "OPEN", {
      enumerable: true,
      value: readyStates.indexOf("OPEN")
    });
    Object.defineProperty(WebSocket2.prototype, "OPEN", {
      enumerable: true,
      value: readyStates.indexOf("OPEN")
    });
    Object.defineProperty(WebSocket2, "CLOSING", {
      enumerable: true,
      value: readyStates.indexOf("CLOSING")
    });
    Object.defineProperty(WebSocket2.prototype, "CLOSING", {
      enumerable: true,
      value: readyStates.indexOf("CLOSING")
    });
    Object.defineProperty(WebSocket2, "CLOSED", {
      enumerable: true,
      value: readyStates.indexOf("CLOSED")
    });
    Object.defineProperty(WebSocket2.prototype, "CLOSED", {
      enumerable: true,
      value: readyStates.indexOf("CLOSED")
    });
    [
      "binaryType",
      "bufferedAmount",
      "extensions",
      "isPaused",
      "protocol",
      "readyState",
      "url"
    ].forEach((property) => {
      Object.defineProperty(WebSocket2.prototype, property, { enumerable: true });
    });
    ["open", "error", "close", "message"].forEach((method) => {
      Object.defineProperty(WebSocket2.prototype, `on${method}`, {
        enumerable: true,
        get() {
          for (const listener of this.listeners(method)) {
            if (listener[kForOnEventAttribute]) return listener[kListener];
          }
          return null;
        },
        set(handler) {
          for (const listener of this.listeners(method)) {
            if (listener[kForOnEventAttribute]) {
              this.removeListener(method, listener);
              break;
            }
          }
          if (typeof handler !== "function") return;
          this.addEventListener(method, handler, {
            [kForOnEventAttribute]: true
          });
        }
      });
    });
    WebSocket2.prototype.addEventListener = addEventListener2;
    WebSocket2.prototype.removeEventListener = removeEventListener;
    module.exports = WebSocket2;
    function initAsClient(websocket, address, protocols, options) {
      const opts = {
        allowSynchronousEvents: true,
        autoPong: true,
        closeTimeout: CLOSE_TIMEOUT,
        protocolVersion: protocolVersions[1],
        maxBufferedChunks: 1024 * 1024,
        maxFragments: 128 * 1024,
        maxPayload: 100 * 1024 * 1024,
        skipUTF8Validation: false,
        perMessageDeflate: true,
        followRedirects: false,
        maxRedirects: 10,
        ...options,
        socketPath: void 0,
        hostname: void 0,
        protocol: void 0,
        timeout: void 0,
        method: "GET",
        host: void 0,
        path: void 0,
        port: void 0
      };
      websocket._autoPong = opts.autoPong;
      websocket._closeTimeout = opts.closeTimeout;
      if (!protocolVersions.includes(opts.protocolVersion)) {
        throw new RangeError(
          `Unsupported protocol version: ${opts.protocolVersion} (supported versions: ${protocolVersions.join(", ")})`
        );
      }
      let parsedUrl;
      if (address instanceof URL2) {
        parsedUrl = address;
      } else {
        try {
          parsedUrl = new URL2(address);
        } catch {
          throw new SyntaxError(`Invalid URL: ${address}`);
        }
      }
      if (parsedUrl.protocol === "http:") {
        parsedUrl.protocol = "ws:";
      } else if (parsedUrl.protocol === "https:") {
        parsedUrl.protocol = "wss:";
      }
      websocket._url = parsedUrl.href;
      const isSecure = parsedUrl.protocol === "wss:";
      const isIpcUrl = parsedUrl.protocol === "ws+unix:";
      let invalidUrlMessage;
      if (parsedUrl.protocol !== "ws:" && !isSecure && !isIpcUrl) {
        invalidUrlMessage = `The URL's protocol must be one of "ws:", "wss:", "http:", "https:", or "ws+unix:"`;
      } else if (isIpcUrl && !parsedUrl.pathname) {
        invalidUrlMessage = "The URL's pathname is empty";
      } else if (parsedUrl.hash) {
        invalidUrlMessage = "The URL contains a fragment identifier";
      }
      if (invalidUrlMessage) {
        const err = new SyntaxError(invalidUrlMessage);
        if (websocket._redirects === 0) {
          throw err;
        } else {
          emitErrorAndClose(websocket, err);
          return;
        }
      }
      const defaultPort = isSecure ? 443 : 80;
      const key = randomBytes3(16).toString("base64");
      const request = isSecure ? https.request : http.request;
      const protocolSet = /* @__PURE__ */ new Set();
      let perMessageDeflate;
      opts.createConnection = opts.createConnection || (isSecure ? tlsConnect : netConnect);
      opts.defaultPort = opts.defaultPort || defaultPort;
      opts.port = parsedUrl.port || defaultPort;
      opts.host = parsedUrl.hostname.startsWith("[") ? parsedUrl.hostname.slice(1, -1) : parsedUrl.hostname;
      opts.headers = {
        ...opts.headers,
        "Sec-WebSocket-Version": opts.protocolVersion,
        "Sec-WebSocket-Key": key,
        Connection: "Upgrade",
        Upgrade: "websocket"
      };
      opts.path = parsedUrl.pathname + parsedUrl.search;
      opts.timeout = opts.handshakeTimeout;
      if (opts.perMessageDeflate) {
        perMessageDeflate = new PerMessageDeflate2({
          ...opts.perMessageDeflate,
          isServer: false,
          maxPayload: opts.maxPayload
        });
        opts.headers["Sec-WebSocket-Extensions"] = format({
          [PerMessageDeflate2.extensionName]: perMessageDeflate.offer()
        });
      }
      if (protocols.length) {
        for (const protocol of protocols) {
          if (typeof protocol !== "string" || !subprotocolRegex.test(protocol) || protocolSet.has(protocol)) {
            throw new SyntaxError(
              "An invalid or duplicated subprotocol was specified"
            );
          }
          protocolSet.add(protocol);
        }
        opts.headers["Sec-WebSocket-Protocol"] = protocols.join(",");
      }
      if (opts.origin) {
        if (opts.protocolVersion < 13) {
          opts.headers["Sec-WebSocket-Origin"] = opts.origin;
        } else {
          opts.headers.Origin = opts.origin;
        }
      }
      if (parsedUrl.username || parsedUrl.password) {
        opts.auth = `${parsedUrl.username}:${parsedUrl.password}`;
      }
      if (isIpcUrl) {
        const parts = opts.path.split(":");
        opts.socketPath = parts[0];
        opts.path = parts[1];
      }
      let req;
      if (opts.followRedirects) {
        if (websocket._redirects === 0) {
          websocket._originalIpc = isIpcUrl;
          websocket._originalSecure = isSecure;
          websocket._originalHostOrSocketPath = isIpcUrl ? opts.socketPath : parsedUrl.host;
          const headers = options && options.headers;
          options = { ...options, headers: {} };
          if (headers) {
            for (const [key2, value] of Object.entries(headers)) {
              options.headers[key2.toLowerCase()] = value;
            }
          }
        } else if (websocket.listenerCount("redirect") === 0) {
          const isSameHost = isIpcUrl ? websocket._originalIpc ? opts.socketPath === websocket._originalHostOrSocketPath : false : websocket._originalIpc ? false : parsedUrl.host === websocket._originalHostOrSocketPath;
          if (!isSameHost || websocket._originalSecure && !isSecure) {
            delete opts.headers.authorization;
            delete opts.headers.cookie;
            if (!isSameHost) delete opts.headers.host;
            opts.auth = void 0;
          }
        }
        if (opts.auth && !options.headers.authorization) {
          options.headers.authorization = "Basic " + Buffer.from(opts.auth).toString("base64");
        }
        req = websocket._req = request(opts);
        if (websocket._redirects) {
          websocket.emit("redirect", websocket.url, req);
        }
      } else {
        req = websocket._req = request(opts);
      }
      if (opts.timeout) {
        req.on("timeout", () => {
          abortHandshake(websocket, req, "Opening handshake has timed out");
        });
      }
      req.on("error", (err) => {
        if (req === null || req[kAborted]) return;
        req = websocket._req = null;
        emitErrorAndClose(websocket, err);
      });
      req.on("response", (res) => {
        const location = res.headers.location;
        const statusCode = res.statusCode;
        if (location && opts.followRedirects && statusCode >= 300 && statusCode < 400) {
          if (++websocket._redirects > opts.maxRedirects) {
            abortHandshake(websocket, req, "Maximum redirects exceeded");
            return;
          }
          req.abort();
          let addr;
          try {
            addr = new URL2(location, address);
          } catch (e) {
            const err = new SyntaxError(`Invalid URL: ${location}`);
            emitErrorAndClose(websocket, err);
            return;
          }
          initAsClient(websocket, addr, protocols, options);
        } else if (!websocket.emit("unexpected-response", req, res)) {
          abortHandshake(
            websocket,
            req,
            `Unexpected server response: ${res.statusCode}`
          );
        }
      });
      req.on("upgrade", (res, socket, head) => {
        websocket.emit("upgrade", res);
        if (websocket.readyState !== WebSocket2.CONNECTING) return;
        req = websocket._req = null;
        const upgrade = res.headers.upgrade;
        if (upgrade === void 0 || upgrade.toLowerCase() !== "websocket") {
          abortHandshake(websocket, socket, "Invalid Upgrade header");
          return;
        }
        const digest = createHash4("sha1").update(key + GUID).digest("base64");
        if (res.headers["sec-websocket-accept"] !== digest) {
          abortHandshake(websocket, socket, "Invalid Sec-WebSocket-Accept header");
          return;
        }
        const serverProt = res.headers["sec-websocket-protocol"];
        let protError;
        if (serverProt !== void 0) {
          if (!protocolSet.size) {
            protError = "Server sent a subprotocol but none was requested";
          } else if (!protocolSet.has(serverProt)) {
            protError = "Server sent an invalid subprotocol";
          }
        } else if (protocolSet.size) {
          protError = "Server sent no subprotocol";
        }
        if (protError) {
          abortHandshake(websocket, socket, protError);
          return;
        }
        if (serverProt) websocket._protocol = serverProt;
        const secWebSocketExtensions = res.headers["sec-websocket-extensions"];
        if (secWebSocketExtensions !== void 0) {
          if (!perMessageDeflate) {
            const message = "Server sent a Sec-WebSocket-Extensions header but no extension was requested";
            abortHandshake(websocket, socket, message);
            return;
          }
          let extensions;
          try {
            extensions = parse2(secWebSocketExtensions);
          } catch (err) {
            const message = "Invalid Sec-WebSocket-Extensions header";
            abortHandshake(websocket, socket, message);
            return;
          }
          const extensionNames = Object.keys(extensions);
          if (extensionNames.length !== 1 || extensionNames[0] !== PerMessageDeflate2.extensionName) {
            const message = "Server indicated an extension that was not requested";
            abortHandshake(websocket, socket, message);
            return;
          }
          try {
            perMessageDeflate.accept(extensions[PerMessageDeflate2.extensionName]);
          } catch (err) {
            const message = "Invalid Sec-WebSocket-Extensions header";
            abortHandshake(websocket, socket, message);
            return;
          }
          websocket._extensions[PerMessageDeflate2.extensionName] = perMessageDeflate;
        }
        websocket.setSocket(socket, head, {
          allowSynchronousEvents: opts.allowSynchronousEvents,
          generateMask: opts.generateMask,
          maxBufferedChunks: opts.maxBufferedChunks,
          maxFragments: opts.maxFragments,
          maxPayload: opts.maxPayload,
          skipUTF8Validation: opts.skipUTF8Validation
        });
      });
      if (opts.finishRequest) {
        opts.finishRequest(req, websocket);
      } else {
        req.end();
      }
    }
    function emitErrorAndClose(websocket, err) {
      websocket._readyState = WebSocket2.CLOSING;
      websocket._errorEmitted = true;
      websocket.emit("error", err);
      websocket.emitClose();
    }
    function netConnect(options) {
      options.path = options.socketPath;
      return net.connect(options);
    }
    function tlsConnect(options) {
      options.path = void 0;
      if (!options.servername && options.servername !== "") {
        options.servername = net.isIP(options.host) ? "" : options.host;
      }
      return tls.connect(options);
    }
    function abortHandshake(websocket, stream, message) {
      websocket._readyState = WebSocket2.CLOSING;
      const err = new Error(message);
      Error.captureStackTrace(err, abortHandshake);
      if (stream.setHeader) {
        stream[kAborted] = true;
        stream.abort();
        if (stream.socket && !stream.socket.destroyed) {
          stream.socket.destroy();
        }
        process.nextTick(emitErrorAndClose, websocket, err);
      } else {
        stream.destroy(err);
        stream.once("error", websocket.emit.bind(websocket, "error"));
        stream.once("close", websocket.emitClose.bind(websocket));
      }
    }
    function sendAfterClose(websocket, data, cb) {
      if (data) {
        const length = isBlob(data) ? data.size : toBuffer(data).length;
        if (websocket._socket) websocket._sender._bufferedBytes += length;
        else websocket._bufferedAmount += length;
      }
      if (cb) {
        const err = new Error(
          `WebSocket is not open: readyState ${websocket.readyState} (${readyStates[websocket.readyState]})`
        );
        process.nextTick(cb, err);
      }
    }
    function receiverOnConclude(code, reason) {
      const websocket = this[kWebSocket];
      websocket._closeFrameReceived = true;
      websocket._closeMessage = reason;
      websocket._closeCode = code;
      if (websocket._socket[kWebSocket] === void 0) return;
      websocket._socket.removeListener("data", socketOnData);
      process.nextTick(resume, websocket._socket);
      if (code === 1005) websocket.close();
      else websocket.close(code, reason);
    }
    function receiverOnDrain() {
      const websocket = this[kWebSocket];
      if (!websocket.isPaused) websocket._socket.resume();
    }
    function receiverOnError(err) {
      const websocket = this[kWebSocket];
      if (websocket._socket[kWebSocket] !== void 0) {
        websocket._socket.removeListener("data", socketOnData);
        process.nextTick(resume, websocket._socket);
        websocket.close(err[kStatusCode]);
      }
      if (!websocket._errorEmitted) {
        websocket._errorEmitted = true;
        websocket.emit("error", err);
      }
    }
    function receiverOnFinish() {
      this[kWebSocket].emitClose();
    }
    function receiverOnMessage(data, isBinary) {
      this[kWebSocket].emit("message", data, isBinary);
    }
    function receiverOnPing(data) {
      const websocket = this[kWebSocket];
      if (websocket._autoPong) websocket.pong(data, !this._isServer, NOOP);
      websocket.emit("ping", data);
    }
    function receiverOnPong(data) {
      this[kWebSocket].emit("pong", data);
    }
    function resume(stream) {
      stream.resume();
    }
    function senderOnError(err) {
      const websocket = this[kWebSocket];
      if (websocket.readyState === WebSocket2.CLOSED) return;
      if (websocket.readyState === WebSocket2.OPEN) {
        websocket._readyState = WebSocket2.CLOSING;
        setCloseTimer(websocket);
      }
      this._socket.end();
      if (!websocket._errorEmitted) {
        websocket._errorEmitted = true;
        websocket.emit("error", err);
      }
    }
    function setCloseTimer(websocket) {
      websocket._closeTimer = setTimeout(
        websocket._socket.destroy.bind(websocket._socket),
        websocket._closeTimeout
      );
    }
    function socketOnClose() {
      const websocket = this[kWebSocket];
      this.removeListener("close", socketOnClose);
      this.removeListener("data", socketOnData);
      this.removeListener("end", socketOnEnd);
      websocket._readyState = WebSocket2.CLOSING;
      if (!this._readableState.endEmitted && !websocket._closeFrameReceived && !websocket._receiver._writableState.errorEmitted && this._readableState.length !== 0) {
        const chunk = this.read(this._readableState.length);
        websocket._receiver.write(chunk);
      }
      websocket._receiver.end();
      this[kWebSocket] = void 0;
      clearTimeout(websocket._closeTimer);
      if (websocket._receiver._writableState.finished || websocket._receiver._writableState.errorEmitted) {
        websocket.emitClose();
      } else {
        websocket._receiver.on("error", receiverOnFinish);
        websocket._receiver.on("finish", receiverOnFinish);
      }
    }
    function socketOnData(chunk) {
      if (!this[kWebSocket]._receiver.write(chunk)) {
        this.pause();
      }
    }
    function socketOnEnd() {
      const websocket = this[kWebSocket];
      websocket._readyState = WebSocket2.CLOSING;
      websocket._receiver.end();
      this.end();
    }
    function socketOnError() {
      const websocket = this[kWebSocket];
      this.removeListener("error", socketOnError);
      this.on("error", NOOP);
      if (websocket) {
        websocket._readyState = WebSocket2.CLOSING;
        this.destroy();
      }
    }
  }
});

// ../../node_modules/.pnpm/ws@8.21.0/node_modules/ws/lib/stream.js
var require_stream = __commonJS({
  "../../node_modules/.pnpm/ws@8.21.0/node_modules/ws/lib/stream.js"(exports, module) {
    "use strict";
    var WebSocket2 = require_websocket();
    var { Duplex } = __require("stream");
    function emitClose(stream) {
      stream.emit("close");
    }
    function duplexOnEnd() {
      if (!this.destroyed && this._writableState.finished) {
        this.destroy();
      }
    }
    function duplexOnError(err) {
      this.removeListener("error", duplexOnError);
      this.destroy();
      if (this.listenerCount("error") === 0) {
        this.emit("error", err);
      }
    }
    function createWebSocketStream2(ws, options) {
      let terminateOnDestroy = true;
      const duplex = new Duplex({
        ...options,
        autoDestroy: false,
        emitClose: false,
        objectMode: false,
        writableObjectMode: false
      });
      ws.on("message", function message(msg, isBinary) {
        const data = !isBinary && duplex._readableState.objectMode ? msg.toString() : msg;
        if (!duplex.push(data)) ws.pause();
      });
      ws.once("error", function error(err) {
        if (duplex.destroyed) return;
        terminateOnDestroy = false;
        duplex.destroy(err);
      });
      ws.once("close", function close() {
        if (duplex.destroyed) return;
        duplex.push(null);
      });
      duplex._destroy = function(err, callback) {
        if (ws.readyState === ws.CLOSED) {
          callback(err);
          process.nextTick(emitClose, duplex);
          return;
        }
        let called = false;
        ws.once("error", function error(err2) {
          called = true;
          callback(err2);
        });
        ws.once("close", function close() {
          if (!called) callback(err);
          process.nextTick(emitClose, duplex);
        });
        if (terminateOnDestroy) ws.terminate();
      };
      duplex._final = function(callback) {
        if (ws.readyState === ws.CONNECTING) {
          ws.once("open", function open() {
            duplex._final(callback);
          });
          return;
        }
        if (ws._socket === null) return;
        if (ws._socket._writableState.finished) {
          callback();
          if (duplex._readableState.endEmitted) duplex.destroy();
        } else {
          ws._socket.once("finish", function finish() {
            callback();
          });
          ws.close();
        }
      };
      duplex._read = function() {
        if (ws.isPaused) ws.resume();
      };
      duplex._write = function(chunk, encoding, callback) {
        if (ws.readyState === ws.CONNECTING) {
          ws.once("open", function open() {
            duplex._write(chunk, encoding, callback);
          });
          return;
        }
        ws.send(chunk, callback);
      };
      duplex.on("end", duplexOnEnd);
      duplex.on("error", duplexOnError);
      return duplex;
    }
    module.exports = createWebSocketStream2;
  }
});

// ../../node_modules/.pnpm/ws@8.21.0/node_modules/ws/lib/subprotocol.js
var require_subprotocol = __commonJS({
  "../../node_modules/.pnpm/ws@8.21.0/node_modules/ws/lib/subprotocol.js"(exports, module) {
    "use strict";
    var { tokenChars } = require_validation();
    function parse2(header) {
      const protocols = /* @__PURE__ */ new Set();
      let start = -1;
      let end = -1;
      let i = 0;
      for (i; i < header.length; i++) {
        const code = header.charCodeAt(i);
        if (end === -1 && tokenChars[code] === 1) {
          if (start === -1) start = i;
        } else if (i !== 0 && (code === 32 || code === 9)) {
          if (end === -1 && start !== -1) end = i;
        } else if (code === 44) {
          if (start === -1) {
            throw new SyntaxError(`Unexpected character at index ${i}`);
          }
          if (end === -1) end = i;
          const protocol2 = header.slice(start, end);
          if (protocols.has(protocol2)) {
            throw new SyntaxError(`The "${protocol2}" subprotocol is duplicated`);
          }
          protocols.add(protocol2);
          start = end = -1;
        } else {
          throw new SyntaxError(`Unexpected character at index ${i}`);
        }
      }
      if (start === -1 || end !== -1) {
        throw new SyntaxError("Unexpected end of input");
      }
      const protocol = header.slice(start, i);
      if (protocols.has(protocol)) {
        throw new SyntaxError(`The "${protocol}" subprotocol is duplicated`);
      }
      protocols.add(protocol);
      return protocols;
    }
    module.exports = { parse: parse2 };
  }
});

// ../../node_modules/.pnpm/ws@8.21.0/node_modules/ws/lib/websocket-server.js
var require_websocket_server = __commonJS({
  "../../node_modules/.pnpm/ws@8.21.0/node_modules/ws/lib/websocket-server.js"(exports, module) {
    "use strict";
    var EventEmitter2 = __require("events");
    var http = __require("http");
    var { Duplex } = __require("stream");
    var { createHash: createHash4 } = __require("crypto");
    var extension2 = require_extension();
    var PerMessageDeflate2 = require_permessage_deflate();
    var subprotocol2 = require_subprotocol();
    var WebSocket2 = require_websocket();
    var { CLOSE_TIMEOUT, GUID, kWebSocket } = require_constants();
    var keyRegex = /^[+/0-9A-Za-z]{22}==$/;
    var RUNNING = 0;
    var CLOSING = 1;
    var CLOSED = 2;
    var WebSocketServer2 = class extends EventEmitter2 {
      /**
       * Create a `WebSocketServer` instance.
       *
       * @param {Object} options Configuration options
       * @param {Boolean} [options.allowSynchronousEvents=true] Specifies whether
       *     any of the `'message'`, `'ping'`, and `'pong'` events can be emitted
       *     multiple times in the same tick
       * @param {Boolean} [options.autoPong=true] Specifies whether or not to
       *     automatically send a pong in response to a ping
       * @param {Number} [options.backlog=511] The maximum length of the queue of
       *     pending connections
       * @param {Boolean} [options.clientTracking=true] Specifies whether or not to
       *     track clients
       * @param {Number} [options.closeTimeout=30000] Duration in milliseconds to
       *     wait for the closing handshake to finish after `websocket.close()` is
       *     called
       * @param {Function} [options.handleProtocols] A hook to handle protocols
       * @param {String} [options.host] The hostname where to bind the server
       * @param {Number} [options.maxBufferedChunks=1048576] The maximum number of
       *     buffered data chunks
       * @param {Number} [options.maxFragments=131072] The maximum number of message
       *     fragments
       * @param {Number} [options.maxPayload=104857600] The maximum allowed message
       *     size
       * @param {Boolean} [options.noServer=false] Enable no server mode
       * @param {String} [options.path] Accept only connections matching this path
       * @param {(Boolean|Object)} [options.perMessageDeflate=false] Enable/disable
       *     permessage-deflate
       * @param {Number} [options.port] The port where to bind the server
       * @param {(http.Server|https.Server)} [options.server] A pre-created HTTP/S
       *     server to use
       * @param {Boolean} [options.skipUTF8Validation=false] Specifies whether or
       *     not to skip UTF-8 validation for text and close messages
       * @param {Function} [options.verifyClient] A hook to reject connections
       * @param {Function} [options.WebSocket=WebSocket] Specifies the `WebSocket`
       *     class to use. It must be the `WebSocket` class or class that extends it
       * @param {Function} [callback] A listener for the `listening` event
       */
      constructor(options, callback) {
        super();
        options = {
          allowSynchronousEvents: true,
          autoPong: true,
          maxBufferedChunks: 1024 * 1024,
          maxFragments: 128 * 1024,
          maxPayload: 100 * 1024 * 1024,
          skipUTF8Validation: false,
          perMessageDeflate: false,
          handleProtocols: null,
          clientTracking: true,
          closeTimeout: CLOSE_TIMEOUT,
          verifyClient: null,
          noServer: false,
          backlog: null,
          // use default (511 as implemented in net.js)
          server: null,
          host: null,
          path: null,
          port: null,
          WebSocket: WebSocket2,
          ...options
        };
        if (options.port == null && !options.server && !options.noServer || options.port != null && (options.server || options.noServer) || options.server && options.noServer) {
          throw new TypeError(
            'One and only one of the "port", "server", or "noServer" options must be specified'
          );
        }
        if (options.port != null) {
          this._server = http.createServer((req, res) => {
            const body = http.STATUS_CODES[426];
            res.writeHead(426, {
              "Content-Length": body.length,
              "Content-Type": "text/plain"
            });
            res.end(body);
          });
          this._server.listen(
            options.port,
            options.host,
            options.backlog,
            callback
          );
        } else if (options.server) {
          this._server = options.server;
        }
        if (this._server) {
          const emitConnection = this.emit.bind(this, "connection");
          this._removeListeners = addListeners(this._server, {
            listening: this.emit.bind(this, "listening"),
            error: this.emit.bind(this, "error"),
            upgrade: (req, socket, head) => {
              this.handleUpgrade(req, socket, head, emitConnection);
            }
          });
        }
        if (options.perMessageDeflate === true) options.perMessageDeflate = {};
        if (options.clientTracking) {
          this.clients = /* @__PURE__ */ new Set();
          this._shouldEmitClose = false;
        }
        this.options = options;
        this._state = RUNNING;
      }
      /**
       * Returns the bound address, the address family name, and port of the server
       * as reported by the operating system if listening on an IP socket.
       * If the server is listening on a pipe or UNIX domain socket, the name is
       * returned as a string.
       *
       * @return {(Object|String|null)} The address of the server
       * @public
       */
      address() {
        if (this.options.noServer) {
          throw new Error('The server is operating in "noServer" mode');
        }
        if (!this._server) return null;
        return this._server.address();
      }
      /**
       * Stop the server from accepting new connections and emit the `'close'` event
       * when all existing connections are closed.
       *
       * @param {Function} [cb] A one-time listener for the `'close'` event
       * @public
       */
      close(cb) {
        if (this._state === CLOSED) {
          if (cb) {
            this.once("close", () => {
              cb(new Error("The server is not running"));
            });
          }
          process.nextTick(emitClose, this);
          return;
        }
        if (cb) this.once("close", cb);
        if (this._state === CLOSING) return;
        this._state = CLOSING;
        if (this.options.noServer || this.options.server) {
          if (this._server) {
            this._removeListeners();
            this._removeListeners = this._server = null;
          }
          if (this.clients) {
            if (!this.clients.size) {
              process.nextTick(emitClose, this);
            } else {
              this._shouldEmitClose = true;
            }
          } else {
            process.nextTick(emitClose, this);
          }
        } else {
          const server2 = this._server;
          this._removeListeners();
          this._removeListeners = this._server = null;
          server2.close(() => {
            emitClose(this);
          });
        }
      }
      /**
       * See if a given request should be handled by this server instance.
       *
       * @param {http.IncomingMessage} req Request object to inspect
       * @return {Boolean} `true` if the request is valid, else `false`
       * @public
       */
      shouldHandle(req) {
        if (this.options.path) {
          const index2 = req.url.indexOf("?");
          const pathname = index2 !== -1 ? req.url.slice(0, index2) : req.url;
          if (pathname !== this.options.path) return false;
        }
        return true;
      }
      /**
       * Handle a HTTP Upgrade request.
       *
       * @param {http.IncomingMessage} req The request object
       * @param {Duplex} socket The network socket between the server and client
       * @param {Buffer} head The first packet of the upgraded stream
       * @param {Function} cb Callback
       * @public
       */
      handleUpgrade(req, socket, head, cb) {
        socket.on("error", socketOnError);
        const key = req.headers["sec-websocket-key"];
        const upgrade = req.headers.upgrade;
        const version2 = +req.headers["sec-websocket-version"];
        if (req.method !== "GET") {
          const message = "Invalid HTTP method";
          abortHandshakeOrEmitwsClientError(this, req, socket, 405, message);
          return;
        }
        if (upgrade === void 0 || upgrade.toLowerCase() !== "websocket") {
          const message = "Invalid Upgrade header";
          abortHandshakeOrEmitwsClientError(this, req, socket, 400, message);
          return;
        }
        if (key === void 0 || !keyRegex.test(key)) {
          const message = "Missing or invalid Sec-WebSocket-Key header";
          abortHandshakeOrEmitwsClientError(this, req, socket, 400, message);
          return;
        }
        if (version2 !== 13 && version2 !== 8) {
          const message = "Missing or invalid Sec-WebSocket-Version header";
          abortHandshakeOrEmitwsClientError(this, req, socket, 400, message, {
            "Sec-WebSocket-Version": "13, 8"
          });
          return;
        }
        if (!this.shouldHandle(req)) {
          abortHandshake(socket, 400);
          return;
        }
        const secWebSocketProtocol = req.headers["sec-websocket-protocol"];
        let protocols = /* @__PURE__ */ new Set();
        if (secWebSocketProtocol !== void 0) {
          try {
            protocols = subprotocol2.parse(secWebSocketProtocol);
          } catch (err) {
            const message = "Invalid Sec-WebSocket-Protocol header";
            abortHandshakeOrEmitwsClientError(this, req, socket, 400, message);
            return;
          }
        }
        const secWebSocketExtensions = req.headers["sec-websocket-extensions"];
        const extensions = {};
        if (this.options.perMessageDeflate && secWebSocketExtensions !== void 0) {
          const perMessageDeflate = new PerMessageDeflate2({
            ...this.options.perMessageDeflate,
            isServer: true,
            maxPayload: this.options.maxPayload
          });
          try {
            const offers = extension2.parse(secWebSocketExtensions);
            if (offers[PerMessageDeflate2.extensionName]) {
              perMessageDeflate.accept(offers[PerMessageDeflate2.extensionName]);
              extensions[PerMessageDeflate2.extensionName] = perMessageDeflate;
            }
          } catch (err) {
            const message = "Invalid or unacceptable Sec-WebSocket-Extensions header";
            abortHandshakeOrEmitwsClientError(this, req, socket, 400, message);
            return;
          }
        }
        if (this.options.verifyClient) {
          const info = {
            origin: req.headers[`${version2 === 8 ? "sec-websocket-origin" : "origin"}`],
            secure: !!(req.socket.authorized || req.socket.encrypted),
            req
          };
          if (this.options.verifyClient.length === 2) {
            this.options.verifyClient(info, (verified, code, message, headers) => {
              if (!verified) {
                return abortHandshake(socket, code || 401, message, headers);
              }
              this.completeUpgrade(
                extensions,
                key,
                protocols,
                req,
                socket,
                head,
                cb
              );
            });
            return;
          }
          if (!this.options.verifyClient(info)) return abortHandshake(socket, 401);
        }
        this.completeUpgrade(extensions, key, protocols, req, socket, head, cb);
      }
      /**
       * Upgrade the connection to WebSocket.
       *
       * @param {Object} extensions The accepted extensions
       * @param {String} key The value of the `Sec-WebSocket-Key` header
       * @param {Set} protocols The subprotocols
       * @param {http.IncomingMessage} req The request object
       * @param {Duplex} socket The network socket between the server and client
       * @param {Buffer} head The first packet of the upgraded stream
       * @param {Function} cb Callback
       * @throws {Error} If called more than once with the same socket
       * @private
       */
      completeUpgrade(extensions, key, protocols, req, socket, head, cb) {
        if (!socket.readable || !socket.writable) return socket.destroy();
        if (socket[kWebSocket]) {
          throw new Error(
            "server.handleUpgrade() was called more than once with the same socket, possibly due to a misconfiguration"
          );
        }
        if (this._state > RUNNING) return abortHandshake(socket, 503);
        const digest = createHash4("sha1").update(key + GUID).digest("base64");
        const headers = [
          "HTTP/1.1 101 Switching Protocols",
          "Upgrade: websocket",
          "Connection: Upgrade",
          `Sec-WebSocket-Accept: ${digest}`
        ];
        const ws = new this.options.WebSocket(null, void 0, this.options);
        if (protocols.size) {
          const protocol = this.options.handleProtocols ? this.options.handleProtocols(protocols, req) : protocols.values().next().value;
          if (protocol) {
            headers.push(`Sec-WebSocket-Protocol: ${protocol}`);
            ws._protocol = protocol;
          }
        }
        if (extensions[PerMessageDeflate2.extensionName]) {
          const params = extensions[PerMessageDeflate2.extensionName].params;
          const value = extension2.format({
            [PerMessageDeflate2.extensionName]: [params]
          });
          headers.push(`Sec-WebSocket-Extensions: ${value}`);
          ws._extensions = extensions;
        }
        this.emit("headers", headers, req);
        socket.write(headers.concat("\r\n").join("\r\n"));
        socket.removeListener("error", socketOnError);
        ws.setSocket(socket, head, {
          allowSynchronousEvents: this.options.allowSynchronousEvents,
          maxBufferedChunks: this.options.maxBufferedChunks,
          maxFragments: this.options.maxFragments,
          maxPayload: this.options.maxPayload,
          skipUTF8Validation: this.options.skipUTF8Validation
        });
        if (this.clients) {
          this.clients.add(ws);
          ws.on("close", () => {
            this.clients.delete(ws);
            if (this._shouldEmitClose && !this.clients.size) {
              process.nextTick(emitClose, this);
            }
          });
        }
        cb(ws, req);
      }
    };
    module.exports = WebSocketServer2;
    function addListeners(server2, map) {
      for (const event of Object.keys(map)) server2.on(event, map[event]);
      return function removeListeners() {
        for (const event of Object.keys(map)) {
          server2.removeListener(event, map[event]);
        }
      };
    }
    function emitClose(server2) {
      server2._state = CLOSED;
      server2.emit("close");
    }
    function socketOnError() {
      this.destroy();
    }
    function abortHandshake(socket, code, message, headers) {
      message = message || http.STATUS_CODES[code];
      headers = {
        Connection: "close",
        "Content-Type": "text/html",
        "Content-Length": Buffer.byteLength(message),
        ...headers
      };
      socket.once("finish", socket.destroy);
      socket.end(
        `HTTP/1.1 ${code} ${http.STATUS_CODES[code]}\r
` + Object.keys(headers).map((h) => `${h}: ${headers[h]}`).join("\r\n") + "\r\n\r\n" + message
      );
    }
    function abortHandshakeOrEmitwsClientError(server2, req, socket, code, message, headers) {
      if (server2.listenerCount("wsClientError")) {
        const err = new Error(message);
        Error.captureStackTrace(err, abortHandshakeOrEmitwsClientError);
        server2.emit("wsClientError", err, socket, req);
      } else {
        abortHandshake(socket, code, message, headers);
      }
    }
  }
});

// dist/index.js
import { dirname as dirname3, join as join2 } from "node:path";

// ../../node_modules/.pnpm/@hono+node-server@1.19.14_hono@4.12.27/node_modules/@hono/node-server/dist/index.mjs
import { createServer as createServerHTTP } from "http";
import { Http2ServerRequest as Http2ServerRequest2, constants as h2constants } from "http2";
import { Http2ServerRequest } from "http2";
import { Readable } from "stream";
import crypto2 from "crypto";
var RequestError = class extends Error {
  constructor(message, options) {
    super(message, options);
    this.name = "RequestError";
  }
};
var toRequestError = (e) => {
  if (e instanceof RequestError) {
    return e;
  }
  return new RequestError(e.message, { cause: e });
};
var GlobalRequest = global.Request;
var Request2 = class extends GlobalRequest {
  constructor(input, options) {
    if (typeof input === "object" && getRequestCache in input) {
      input = input[getRequestCache]();
    }
    if (typeof options?.body?.getReader !== "undefined") {
      ;
      options.duplex ??= "half";
    }
    super(input, options);
  }
};
var newHeadersFromIncoming = (incoming) => {
  const headerRecord = [];
  const rawHeaders = incoming.rawHeaders;
  for (let i = 0; i < rawHeaders.length; i += 2) {
    const { [i]: key, [i + 1]: value } = rawHeaders;
    if (key.charCodeAt(0) !== /*:*/
    58) {
      headerRecord.push([key, value]);
    }
  }
  return new Headers(headerRecord);
};
var wrapBodyStream = Symbol("wrapBodyStream");
var newRequestFromIncoming = (method, url, headers, incoming, abortController) => {
  const init = {
    method,
    headers,
    signal: abortController.signal
  };
  if (method === "TRACE") {
    init.method = "GET";
    const req = new Request2(url, init);
    Object.defineProperty(req, "method", {
      get() {
        return "TRACE";
      }
    });
    return req;
  }
  if (!(method === "GET" || method === "HEAD")) {
    if ("rawBody" in incoming && incoming.rawBody instanceof Buffer) {
      init.body = new ReadableStream({
        start(controller) {
          controller.enqueue(incoming.rawBody);
          controller.close();
        }
      });
    } else if (incoming[wrapBodyStream]) {
      let reader;
      init.body = new ReadableStream({
        async pull(controller) {
          try {
            reader ||= Readable.toWeb(incoming).getReader();
            const { done, value } = await reader.read();
            if (done) {
              controller.close();
            } else {
              controller.enqueue(value);
            }
          } catch (error) {
            controller.error(error);
          }
        }
      });
    } else {
      init.body = Readable.toWeb(incoming);
    }
  }
  return new Request2(url, init);
};
var getRequestCache = Symbol("getRequestCache");
var requestCache = Symbol("requestCache");
var incomingKey = Symbol("incomingKey");
var urlKey = Symbol("urlKey");
var headersKey = Symbol("headersKey");
var abortControllerKey = Symbol("abortControllerKey");
var getAbortController = Symbol("getAbortController");
var requestPrototype = {
  get method() {
    return this[incomingKey].method || "GET";
  },
  get url() {
    return this[urlKey];
  },
  get headers() {
    return this[headersKey] ||= newHeadersFromIncoming(this[incomingKey]);
  },
  [getAbortController]() {
    this[getRequestCache]();
    return this[abortControllerKey];
  },
  [getRequestCache]() {
    this[abortControllerKey] ||= new AbortController();
    return this[requestCache] ||= newRequestFromIncoming(
      this.method,
      this[urlKey],
      this.headers,
      this[incomingKey],
      this[abortControllerKey]
    );
  }
};
[
  "body",
  "bodyUsed",
  "cache",
  "credentials",
  "destination",
  "integrity",
  "mode",
  "redirect",
  "referrer",
  "referrerPolicy",
  "signal",
  "keepalive"
].forEach((k) => {
  Object.defineProperty(requestPrototype, k, {
    get() {
      return this[getRequestCache]()[k];
    }
  });
});
["arrayBuffer", "blob", "clone", "formData", "json", "text"].forEach((k) => {
  Object.defineProperty(requestPrototype, k, {
    value: function() {
      return this[getRequestCache]()[k]();
    }
  });
});
Object.defineProperty(requestPrototype, Symbol.for("nodejs.util.inspect.custom"), {
  value: function(depth, options, inspectFn) {
    const props = {
      method: this.method,
      url: this.url,
      headers: this.headers,
      nativeRequest: this[requestCache]
    };
    return `Request (lightweight) ${inspectFn(props, { ...options, depth: depth == null ? null : depth - 1 })}`;
  }
});
Object.setPrototypeOf(requestPrototype, Request2.prototype);
var newRequest = (incoming, defaultHostname) => {
  const req = Object.create(requestPrototype);
  req[incomingKey] = incoming;
  const incomingUrl = incoming.url || "";
  if (incomingUrl[0] !== "/" && // short-circuit for performance. most requests are relative URL.
  (incomingUrl.startsWith("http://") || incomingUrl.startsWith("https://"))) {
    if (incoming instanceof Http2ServerRequest) {
      throw new RequestError("Absolute URL for :path is not allowed in HTTP/2");
    }
    try {
      const url2 = new URL(incomingUrl);
      req[urlKey] = url2.href;
    } catch (e) {
      throw new RequestError("Invalid absolute URL", { cause: e });
    }
    return req;
  }
  const host = (incoming instanceof Http2ServerRequest ? incoming.authority : incoming.headers.host) || defaultHostname;
  if (!host) {
    throw new RequestError("Missing host header");
  }
  let scheme;
  if (incoming instanceof Http2ServerRequest) {
    scheme = incoming.scheme;
    if (!(scheme === "http" || scheme === "https")) {
      throw new RequestError("Unsupported scheme");
    }
  } else {
    scheme = incoming.socket && incoming.socket.encrypted ? "https" : "http";
  }
  const url = new URL(`${scheme}://${host}${incomingUrl}`);
  if (url.hostname.length !== host.length && url.hostname !== host.replace(/:\d+$/, "")) {
    throw new RequestError("Invalid host header");
  }
  req[urlKey] = url.href;
  return req;
};
var responseCache = Symbol("responseCache");
var getResponseCache = Symbol("getResponseCache");
var cacheKey = Symbol("cache");
var GlobalResponse = global.Response;
var Response2 = class _Response {
  #body;
  #init;
  [getResponseCache]() {
    delete this[cacheKey];
    return this[responseCache] ||= new GlobalResponse(this.#body, this.#init);
  }
  constructor(body, init) {
    let headers;
    this.#body = body;
    if (init instanceof _Response) {
      const cachedGlobalResponse = init[responseCache];
      if (cachedGlobalResponse) {
        this.#init = cachedGlobalResponse;
        this[getResponseCache]();
        return;
      } else {
        this.#init = init.#init;
        headers = new Headers(init.#init.headers);
      }
    } else {
      this.#init = init;
    }
    if (typeof body === "string" || typeof body?.getReader !== "undefined" || body instanceof Blob || body instanceof Uint8Array) {
      ;
      this[cacheKey] = [init?.status || 200, body, headers || init?.headers];
    }
  }
  get headers() {
    const cache = this[cacheKey];
    if (cache) {
      if (!(cache[2] instanceof Headers)) {
        cache[2] = new Headers(
          cache[2] || { "content-type": "text/plain; charset=UTF-8" }
        );
      }
      return cache[2];
    }
    return this[getResponseCache]().headers;
  }
  get status() {
    return this[cacheKey]?.[0] ?? this[getResponseCache]().status;
  }
  get ok() {
    const status = this.status;
    return status >= 200 && status < 300;
  }
};
["body", "bodyUsed", "redirected", "statusText", "trailers", "type", "url"].forEach((k) => {
  Object.defineProperty(Response2.prototype, k, {
    get() {
      return this[getResponseCache]()[k];
    }
  });
});
["arrayBuffer", "blob", "clone", "formData", "json", "text"].forEach((k) => {
  Object.defineProperty(Response2.prototype, k, {
    value: function() {
      return this[getResponseCache]()[k]();
    }
  });
});
Object.defineProperty(Response2.prototype, Symbol.for("nodejs.util.inspect.custom"), {
  value: function(depth, options, inspectFn) {
    const props = {
      status: this.status,
      headers: this.headers,
      ok: this.ok,
      nativeResponse: this[responseCache]
    };
    return `Response (lightweight) ${inspectFn(props, { ...options, depth: depth == null ? null : depth - 1 })}`;
  }
});
Object.setPrototypeOf(Response2, GlobalResponse);
Object.setPrototypeOf(Response2.prototype, GlobalResponse.prototype);
async function readWithoutBlocking(readPromise) {
  return Promise.race([readPromise, Promise.resolve().then(() => Promise.resolve(void 0))]);
}
function writeFromReadableStreamDefaultReader(reader, writable, currentReadPromise) {
  const cancel = (error) => {
    reader.cancel(error).catch(() => {
    });
  };
  writable.on("close", cancel);
  writable.on("error", cancel);
  (currentReadPromise ?? reader.read()).then(flow, handleStreamError);
  return reader.closed.finally(() => {
    writable.off("close", cancel);
    writable.off("error", cancel);
  });
  function handleStreamError(error) {
    if (error) {
      writable.destroy(error);
    }
  }
  function onDrain() {
    reader.read().then(flow, handleStreamError);
  }
  function flow({ done, value }) {
    try {
      if (done) {
        writable.end();
      } else if (!writable.write(value)) {
        writable.once("drain", onDrain);
      } else {
        return reader.read().then(flow, handleStreamError);
      }
    } catch (e) {
      handleStreamError(e);
    }
  }
}
function writeFromReadableStream(stream, writable) {
  if (stream.locked) {
    throw new TypeError("ReadableStream is locked.");
  } else if (writable.destroyed) {
    return;
  }
  return writeFromReadableStreamDefaultReader(stream.getReader(), writable);
}
var buildOutgoingHttpHeaders = (headers) => {
  const res = {};
  if (!(headers instanceof Headers)) {
    headers = new Headers(headers ?? void 0);
  }
  const cookies = [];
  for (const [k, v] of headers) {
    if (k === "set-cookie") {
      cookies.push(v);
    } else {
      res[k] = v;
    }
  }
  if (cookies.length > 0) {
    res["set-cookie"] = cookies;
  }
  res["content-type"] ??= "text/plain; charset=UTF-8";
  return res;
};
var X_ALREADY_SENT = "x-hono-already-sent";
if (typeof global.crypto === "undefined") {
  global.crypto = crypto2;
}
var outgoingEnded = Symbol("outgoingEnded");
var incomingDraining = Symbol("incomingDraining");
var DRAIN_TIMEOUT_MS = 500;
var MAX_DRAIN_BYTES = 64 * 1024 * 1024;
var drainIncoming = (incoming) => {
  const incomingWithDrainState = incoming;
  if (incoming.destroyed || incomingWithDrainState[incomingDraining]) {
    return;
  }
  incomingWithDrainState[incomingDraining] = true;
  if (incoming instanceof Http2ServerRequest2) {
    try {
      ;
      incoming.stream?.close?.(h2constants.NGHTTP2_NO_ERROR);
    } catch {
    }
    return;
  }
  let bytesRead = 0;
  const cleanup = () => {
    clearTimeout(timer);
    incoming.off("data", onData);
    incoming.off("end", cleanup);
    incoming.off("error", cleanup);
  };
  const forceClose = () => {
    cleanup();
    const socket = incoming.socket;
    if (socket && !socket.destroyed) {
      socket.destroySoon();
    }
  };
  const timer = setTimeout(forceClose, DRAIN_TIMEOUT_MS);
  timer.unref?.();
  const onData = (chunk) => {
    bytesRead += chunk.length;
    if (bytesRead > MAX_DRAIN_BYTES) {
      forceClose();
    }
  };
  incoming.on("data", onData);
  incoming.on("end", cleanup);
  incoming.on("error", cleanup);
  incoming.resume();
};
var handleRequestError = () => new Response(null, {
  status: 400
});
var handleFetchError = (e) => new Response(null, {
  status: e instanceof Error && (e.name === "TimeoutError" || e.constructor.name === "TimeoutError") ? 504 : 500
});
var handleResponseError = (e, outgoing) => {
  const err = e instanceof Error ? e : new Error("unknown error", { cause: e });
  if (err.code === "ERR_STREAM_PREMATURE_CLOSE") {
    console.info("The user aborted a request.");
  } else {
    console.error(e);
    if (!outgoing.headersSent) {
      outgoing.writeHead(500, { "Content-Type": "text/plain" });
    }
    outgoing.end(`Error: ${err.message}`);
    outgoing.destroy(err);
  }
};
var flushHeaders = (outgoing) => {
  if ("flushHeaders" in outgoing && outgoing.writable) {
    outgoing.flushHeaders();
  }
};
var responseViaCache = async (res, outgoing) => {
  let [status, body, header] = res[cacheKey];
  let hasContentLength = false;
  if (!header) {
    header = { "content-type": "text/plain; charset=UTF-8" };
  } else if (header instanceof Headers) {
    hasContentLength = header.has("content-length");
    header = buildOutgoingHttpHeaders(header);
  } else if (Array.isArray(header)) {
    const headerObj = new Headers(header);
    hasContentLength = headerObj.has("content-length");
    header = buildOutgoingHttpHeaders(headerObj);
  } else {
    for (const key in header) {
      if (key.length === 14 && key.toLowerCase() === "content-length") {
        hasContentLength = true;
        break;
      }
    }
  }
  if (!hasContentLength) {
    if (typeof body === "string") {
      header["Content-Length"] = Buffer.byteLength(body);
    } else if (body instanceof Uint8Array) {
      header["Content-Length"] = body.byteLength;
    } else if (body instanceof Blob) {
      header["Content-Length"] = body.size;
    }
  }
  outgoing.writeHead(status, header);
  if (typeof body === "string" || body instanceof Uint8Array) {
    outgoing.end(body);
  } else if (body instanceof Blob) {
    outgoing.end(new Uint8Array(await body.arrayBuffer()));
  } else {
    flushHeaders(outgoing);
    await writeFromReadableStream(body, outgoing)?.catch(
      (e) => handleResponseError(e, outgoing)
    );
  }
  ;
  outgoing[outgoingEnded]?.();
};
var isPromise = (res) => typeof res.then === "function";
var responseViaResponseObject = async (res, outgoing, options = {}) => {
  if (isPromise(res)) {
    if (options.errorHandler) {
      try {
        res = await res;
      } catch (err) {
        const errRes = await options.errorHandler(err);
        if (!errRes) {
          return;
        }
        res = errRes;
      }
    } else {
      res = await res.catch(handleFetchError);
    }
  }
  if (cacheKey in res) {
    return responseViaCache(res, outgoing);
  }
  const resHeaderRecord = buildOutgoingHttpHeaders(res.headers);
  if (res.body) {
    const reader = res.body.getReader();
    const values = [];
    let done = false;
    let currentReadPromise = void 0;
    if (resHeaderRecord["transfer-encoding"] !== "chunked") {
      let maxReadCount = 2;
      for (let i = 0; i < maxReadCount; i++) {
        currentReadPromise ||= reader.read();
        const chunk = await readWithoutBlocking(currentReadPromise).catch((e) => {
          console.error(e);
          done = true;
        });
        if (!chunk) {
          if (i === 1) {
            await new Promise((resolve) => setTimeout(resolve));
            maxReadCount = 3;
            continue;
          }
          break;
        }
        currentReadPromise = void 0;
        if (chunk.value) {
          values.push(chunk.value);
        }
        if (chunk.done) {
          done = true;
          break;
        }
      }
      if (done && !("content-length" in resHeaderRecord)) {
        resHeaderRecord["content-length"] = values.reduce((acc, value) => acc + value.length, 0);
      }
    }
    outgoing.writeHead(res.status, resHeaderRecord);
    values.forEach((value) => {
      ;
      outgoing.write(value);
    });
    if (done) {
      outgoing.end();
    } else {
      if (values.length === 0) {
        flushHeaders(outgoing);
      }
      await writeFromReadableStreamDefaultReader(reader, outgoing, currentReadPromise);
    }
  } else if (resHeaderRecord[X_ALREADY_SENT]) {
  } else {
    outgoing.writeHead(res.status, resHeaderRecord);
    outgoing.end();
  }
  ;
  outgoing[outgoingEnded]?.();
};
var getRequestListener = (fetchCallback, options = {}) => {
  const autoCleanupIncoming = options.autoCleanupIncoming ?? true;
  if (options.overrideGlobalObjects !== false && global.Request !== Request2) {
    Object.defineProperty(global, "Request", {
      value: Request2
    });
    Object.defineProperty(global, "Response", {
      value: Response2
    });
  }
  return async (incoming, outgoing) => {
    let res, req;
    try {
      req = newRequest(incoming, options.hostname);
      let incomingEnded = !autoCleanupIncoming || incoming.method === "GET" || incoming.method === "HEAD";
      if (!incomingEnded) {
        ;
        incoming[wrapBodyStream] = true;
        incoming.on("end", () => {
          incomingEnded = true;
        });
        if (incoming instanceof Http2ServerRequest2) {
          ;
          outgoing[outgoingEnded] = () => {
            if (!incomingEnded) {
              setTimeout(() => {
                if (!incomingEnded) {
                  setTimeout(() => {
                    drainIncoming(incoming);
                  });
                }
              });
            }
          };
        }
        outgoing.on("finish", () => {
          if (!incomingEnded) {
            drainIncoming(incoming);
          }
        });
      }
      outgoing.on("close", () => {
        const abortController = req[abortControllerKey];
        if (abortController) {
          if (incoming.errored) {
            req[abortControllerKey].abort(incoming.errored.toString());
          } else if (!outgoing.writableFinished) {
            req[abortControllerKey].abort("Client connection prematurely closed.");
          }
        }
        if (!incomingEnded) {
          setTimeout(() => {
            if (!incomingEnded) {
              setTimeout(() => {
                drainIncoming(incoming);
              });
            }
          });
        }
      });
      res = fetchCallback(req, { incoming, outgoing });
      if (cacheKey in res) {
        return responseViaCache(res, outgoing);
      }
    } catch (e) {
      if (!res) {
        if (options.errorHandler) {
          res = await options.errorHandler(req ? e : toRequestError(e));
          if (!res) {
            return;
          }
        } else if (!req) {
          res = handleRequestError();
        } else {
          res = handleFetchError(e);
        }
      } else {
        return handleResponseError(e, outgoing);
      }
    }
    try {
      return await responseViaResponseObject(res, outgoing, options);
    } catch (e) {
      return handleResponseError(e, outgoing);
    }
  };
};
var createAdaptorServer = (options) => {
  const fetchCallback = options.fetch;
  const requestListener = getRequestListener(fetchCallback, {
    hostname: options.hostname,
    overrideGlobalObjects: options.overrideGlobalObjects,
    autoCleanupIncoming: options.autoCleanupIncoming
  });
  const createServer = options.createServer || createServerHTTP;
  const server2 = createServer(options.serverOptions || {}, requestListener);
  return server2;
};
var serve = (options, listeningListener) => {
  const server2 = createAdaptorServer(options);
  server2.listen(options?.port ?? 3e3, options.hostname, () => {
    const serverInfo = server2.address();
    listeningListener && listeningListener(serverInfo);
  });
  return server2;
};

// dist/db.js
import { mkdirSync, existsSync } from "node:fs";
import { dirname } from "node:path";
import Database from "better-sqlite3";

// ../../node_modules/.pnpm/drizzle-orm@0.44.7_@electri_170ce7fb4153736f6f8b6fe6a8fee8b5/node_modules/drizzle-orm/entity.js
var entityKind = Symbol.for("drizzle:entityKind");
var hasOwnEntityKind = Symbol.for("drizzle:hasOwnEntityKind");
function is(value, type) {
  if (!value || typeof value !== "object") {
    return false;
  }
  if (value instanceof type) {
    return true;
  }
  if (!Object.prototype.hasOwnProperty.call(type, entityKind)) {
    throw new Error(
      `Class "${type.name ?? "<unknown>"}" doesn't look like a Drizzle entity. If this is incorrect and the class is provided by Drizzle, please report this as a bug.`
    );
  }
  let cls = Object.getPrototypeOf(value).constructor;
  if (cls) {
    while (cls) {
      if (entityKind in cls && cls[entityKind] === type[entityKind]) {
        return true;
      }
      cls = Object.getPrototypeOf(cls);
    }
  }
  return false;
}

// ../../node_modules/.pnpm/drizzle-orm@0.44.7_@electri_170ce7fb4153736f6f8b6fe6a8fee8b5/node_modules/drizzle-orm/column.js
var Column = class {
  constructor(table, config2) {
    this.table = table;
    this.config = config2;
    this.name = config2.name;
    this.keyAsName = config2.keyAsName;
    this.notNull = config2.notNull;
    this.default = config2.default;
    this.defaultFn = config2.defaultFn;
    this.onUpdateFn = config2.onUpdateFn;
    this.hasDefault = config2.hasDefault;
    this.primary = config2.primaryKey;
    this.isUnique = config2.isUnique;
    this.uniqueName = config2.uniqueName;
    this.uniqueType = config2.uniqueType;
    this.dataType = config2.dataType;
    this.columnType = config2.columnType;
    this.generated = config2.generated;
    this.generatedIdentity = config2.generatedIdentity;
  }
  static [entityKind] = "Column";
  name;
  keyAsName;
  primary;
  notNull;
  default;
  defaultFn;
  onUpdateFn;
  hasDefault;
  isUnique;
  uniqueName;
  uniqueType;
  dataType;
  columnType;
  enumValues = void 0;
  generated = void 0;
  generatedIdentity = void 0;
  config;
  mapFromDriverValue(value) {
    return value;
  }
  mapToDriverValue(value) {
    return value;
  }
  // ** @internal */
  shouldDisableInsert() {
    return this.config.generated !== void 0 && this.config.generated.type !== "byDefault";
  }
};

// ../../node_modules/.pnpm/drizzle-orm@0.44.7_@electri_170ce7fb4153736f6f8b6fe6a8fee8b5/node_modules/drizzle-orm/column-builder.js
var ColumnBuilder = class {
  static [entityKind] = "ColumnBuilder";
  config;
  constructor(name, dataType, columnType) {
    this.config = {
      name,
      keyAsName: name === "",
      notNull: false,
      default: void 0,
      hasDefault: false,
      primaryKey: false,
      isUnique: false,
      uniqueName: void 0,
      uniqueType: void 0,
      dataType,
      columnType,
      generated: void 0
    };
  }
  /**
   * Changes the data type of the column. Commonly used with `json` columns. Also, useful for branded types.
   *
   * @example
   * ```ts
   * const users = pgTable('users', {
   * 	id: integer('id').$type<UserId>().primaryKey(),
   * 	details: json('details').$type<UserDetails>().notNull(),
   * });
   * ```
   */
  $type() {
    return this;
  }
  /**
   * Adds a `not null` clause to the column definition.
   *
   * Affects the `select` model of the table - columns *without* `not null` will be nullable on select.
   */
  notNull() {
    this.config.notNull = true;
    return this;
  }
  /**
   * Adds a `default <value>` clause to the column definition.
   *
   * Affects the `insert` model of the table - columns *with* `default` are optional on insert.
   *
   * If you need to set a dynamic default value, use {@link $defaultFn} instead.
   */
  default(value) {
    this.config.default = value;
    this.config.hasDefault = true;
    return this;
  }
  /**
   * Adds a dynamic default value to the column.
   * The function will be called when the row is inserted, and the returned value will be used as the column value.
   *
   * **Note:** This value does not affect the `drizzle-kit` behavior, it is only used at runtime in `drizzle-orm`.
   */
  $defaultFn(fn) {
    this.config.defaultFn = fn;
    this.config.hasDefault = true;
    return this;
  }
  /**
   * Alias for {@link $defaultFn}.
   */
  $default = this.$defaultFn;
  /**
   * Adds a dynamic update value to the column.
   * The function will be called when the row is updated, and the returned value will be used as the column value if none is provided.
   * If no `default` (or `$defaultFn`) value is provided, the function will be called when the row is inserted as well, and the returned value will be used as the column value.
   *
   * **Note:** This value does not affect the `drizzle-kit` behavior, it is only used at runtime in `drizzle-orm`.
   */
  $onUpdateFn(fn) {
    this.config.onUpdateFn = fn;
    this.config.hasDefault = true;
    return this;
  }
  /**
   * Alias for {@link $onUpdateFn}.
   */
  $onUpdate = this.$onUpdateFn;
  /**
   * Adds a `primary key` clause to the column definition. This implicitly makes the column `not null`.
   *
   * In SQLite, `integer primary key` implicitly makes the column auto-incrementing.
   */
  primaryKey() {
    this.config.primaryKey = true;
    this.config.notNull = true;
    return this;
  }
  /** @internal Sets the name of the column to the key within the table definition if a name was not given. */
  setName(name) {
    if (this.config.name !== "") return;
    this.config.name = name;
  }
};

// ../../node_modules/.pnpm/drizzle-orm@0.44.7_@electri_170ce7fb4153736f6f8b6fe6a8fee8b5/node_modules/drizzle-orm/table.utils.js
var TableName = Symbol.for("drizzle:Name");

// ../../node_modules/.pnpm/drizzle-orm@0.44.7_@electri_170ce7fb4153736f6f8b6fe6a8fee8b5/node_modules/drizzle-orm/pg-core/foreign-keys.js
var ForeignKeyBuilder = class {
  static [entityKind] = "PgForeignKeyBuilder";
  /** @internal */
  reference;
  /** @internal */
  _onUpdate = "no action";
  /** @internal */
  _onDelete = "no action";
  constructor(config2, actions) {
    this.reference = () => {
      const { name, columns, foreignColumns } = config2();
      return { name, columns, foreignTable: foreignColumns[0].table, foreignColumns };
    };
    if (actions) {
      this._onUpdate = actions.onUpdate;
      this._onDelete = actions.onDelete;
    }
  }
  onUpdate(action) {
    this._onUpdate = action === void 0 ? "no action" : action;
    return this;
  }
  onDelete(action) {
    this._onDelete = action === void 0 ? "no action" : action;
    return this;
  }
  /** @internal */
  build(table) {
    return new ForeignKey(table, this);
  }
};
var ForeignKey = class {
  constructor(table, builder) {
    this.table = table;
    this.reference = builder.reference;
    this.onUpdate = builder._onUpdate;
    this.onDelete = builder._onDelete;
  }
  static [entityKind] = "PgForeignKey";
  reference;
  onUpdate;
  onDelete;
  getName() {
    const { name, columns, foreignColumns } = this.reference();
    const columnNames = columns.map((column) => column.name);
    const foreignColumnNames = foreignColumns.map((column) => column.name);
    const chunks = [
      this.table[TableName],
      ...columnNames,
      foreignColumns[0].table[TableName],
      ...foreignColumnNames
    ];
    return name ?? `${chunks.join("_")}_fk`;
  }
};

// ../../node_modules/.pnpm/drizzle-orm@0.44.7_@electri_170ce7fb4153736f6f8b6fe6a8fee8b5/node_modules/drizzle-orm/tracing-utils.js
function iife(fn, ...args) {
  return fn(...args);
}

// ../../node_modules/.pnpm/drizzle-orm@0.44.7_@electri_170ce7fb4153736f6f8b6fe6a8fee8b5/node_modules/drizzle-orm/pg-core/unique-constraint.js
function uniqueKeyName(table, columns) {
  return `${table[TableName]}_${columns.join("_")}_unique`;
}
var UniqueConstraintBuilder = class {
  constructor(columns, name) {
    this.name = name;
    this.columns = columns;
  }
  static [entityKind] = "PgUniqueConstraintBuilder";
  /** @internal */
  columns;
  /** @internal */
  nullsNotDistinctConfig = false;
  nullsNotDistinct() {
    this.nullsNotDistinctConfig = true;
    return this;
  }
  /** @internal */
  build(table) {
    return new UniqueConstraint(table, this.columns, this.nullsNotDistinctConfig, this.name);
  }
};
var UniqueOnConstraintBuilder = class {
  static [entityKind] = "PgUniqueOnConstraintBuilder";
  /** @internal */
  name;
  constructor(name) {
    this.name = name;
  }
  on(...columns) {
    return new UniqueConstraintBuilder(columns, this.name);
  }
};
var UniqueConstraint = class {
  constructor(table, columns, nullsNotDistinct, name) {
    this.table = table;
    this.columns = columns;
    this.name = name ?? uniqueKeyName(this.table, this.columns.map((column) => column.name));
    this.nullsNotDistinct = nullsNotDistinct;
  }
  static [entityKind] = "PgUniqueConstraint";
  columns;
  name;
  nullsNotDistinct = false;
  getName() {
    return this.name;
  }
};

// ../../node_modules/.pnpm/drizzle-orm@0.44.7_@electri_170ce7fb4153736f6f8b6fe6a8fee8b5/node_modules/drizzle-orm/pg-core/utils/array.js
function parsePgArrayValue(arrayString, startFrom, inQuotes) {
  for (let i = startFrom; i < arrayString.length; i++) {
    const char = arrayString[i];
    if (char === "\\") {
      i++;
      continue;
    }
    if (char === '"') {
      return [arrayString.slice(startFrom, i).replace(/\\/g, ""), i + 1];
    }
    if (inQuotes) {
      continue;
    }
    if (char === "," || char === "}") {
      return [arrayString.slice(startFrom, i).replace(/\\/g, ""), i];
    }
  }
  return [arrayString.slice(startFrom).replace(/\\/g, ""), arrayString.length];
}
function parsePgNestedArray(arrayString, startFrom = 0) {
  const result = [];
  let i = startFrom;
  let lastCharIsComma = false;
  while (i < arrayString.length) {
    const char = arrayString[i];
    if (char === ",") {
      if (lastCharIsComma || i === startFrom) {
        result.push("");
      }
      lastCharIsComma = true;
      i++;
      continue;
    }
    lastCharIsComma = false;
    if (char === "\\") {
      i += 2;
      continue;
    }
    if (char === '"') {
      const [value2, startFrom2] = parsePgArrayValue(arrayString, i + 1, true);
      result.push(value2);
      i = startFrom2;
      continue;
    }
    if (char === "}") {
      return [result, i + 1];
    }
    if (char === "{") {
      const [value2, startFrom2] = parsePgNestedArray(arrayString, i + 1);
      result.push(value2);
      i = startFrom2;
      continue;
    }
    const [value, newStartFrom] = parsePgArrayValue(arrayString, i, false);
    result.push(value);
    i = newStartFrom;
  }
  return [result, i];
}
function parsePgArray(arrayString) {
  const [result] = parsePgNestedArray(arrayString, 1);
  return result;
}
function makePgArray(array) {
  return `{${array.map((item) => {
    if (Array.isArray(item)) {
      return makePgArray(item);
    }
    if (typeof item === "string") {
      return `"${item.replace(/\\/g, "\\\\").replace(/"/g, '\\"')}"`;
    }
    return `${item}`;
  }).join(",")}}`;
}

// ../../node_modules/.pnpm/drizzle-orm@0.44.7_@electri_170ce7fb4153736f6f8b6fe6a8fee8b5/node_modules/drizzle-orm/pg-core/columns/common.js
var PgColumnBuilder = class extends ColumnBuilder {
  foreignKeyConfigs = [];
  static [entityKind] = "PgColumnBuilder";
  array(size) {
    return new PgArrayBuilder(this.config.name, this, size);
  }
  references(ref, actions = {}) {
    this.foreignKeyConfigs.push({ ref, actions });
    return this;
  }
  unique(name, config2) {
    this.config.isUnique = true;
    this.config.uniqueName = name;
    this.config.uniqueType = config2?.nulls;
    return this;
  }
  generatedAlwaysAs(as) {
    this.config.generated = {
      as,
      type: "always",
      mode: "stored"
    };
    return this;
  }
  /** @internal */
  buildForeignKeys(column, table) {
    return this.foreignKeyConfigs.map(({ ref, actions }) => {
      return iife(
        (ref2, actions2) => {
          const builder = new ForeignKeyBuilder(() => {
            const foreignColumn = ref2();
            return { columns: [column], foreignColumns: [foreignColumn] };
          });
          if (actions2.onUpdate) {
            builder.onUpdate(actions2.onUpdate);
          }
          if (actions2.onDelete) {
            builder.onDelete(actions2.onDelete);
          }
          return builder.build(table);
        },
        ref,
        actions
      );
    });
  }
  /** @internal */
  buildExtraConfigColumn(table) {
    return new ExtraConfigColumn(table, this.config);
  }
};
var PgColumn = class extends Column {
  constructor(table, config2) {
    if (!config2.uniqueName) {
      config2.uniqueName = uniqueKeyName(table, [config2.name]);
    }
    super(table, config2);
    this.table = table;
  }
  static [entityKind] = "PgColumn";
};
var ExtraConfigColumn = class extends PgColumn {
  static [entityKind] = "ExtraConfigColumn";
  getSQLType() {
    return this.getSQLType();
  }
  indexConfig = {
    order: this.config.order ?? "asc",
    nulls: this.config.nulls ?? "last",
    opClass: this.config.opClass
  };
  defaultConfig = {
    order: "asc",
    nulls: "last",
    opClass: void 0
  };
  asc() {
    this.indexConfig.order = "asc";
    return this;
  }
  desc() {
    this.indexConfig.order = "desc";
    return this;
  }
  nullsFirst() {
    this.indexConfig.nulls = "first";
    return this;
  }
  nullsLast() {
    this.indexConfig.nulls = "last";
    return this;
  }
  /**
   * ### PostgreSQL documentation quote
   *
   * > An operator class with optional parameters can be specified for each column of an index.
   * The operator class identifies the operators to be used by the index for that column.
   * For example, a B-tree index on four-byte integers would use the int4_ops class;
   * this operator class includes comparison functions for four-byte integers.
   * In practice the default operator class for the column's data type is usually sufficient.
   * The main point of having operator classes is that for some data types, there could be more than one meaningful ordering.
   * For example, we might want to sort a complex-number data type either by absolute value or by real part.
   * We could do this by defining two operator classes for the data type and then selecting the proper class when creating an index.
   * More information about operator classes check:
   *
   * ### Useful links
   * https://www.postgresql.org/docs/current/sql-createindex.html
   *
   * https://www.postgresql.org/docs/current/indexes-opclass.html
   *
   * https://www.postgresql.org/docs/current/xindex.html
   *
   * ### Additional types
   * If you have the `pg_vector` extension installed in your database, you can use the
   * `vector_l2_ops`, `vector_ip_ops`, `vector_cosine_ops`, `vector_l1_ops`, `bit_hamming_ops`, `bit_jaccard_ops`, `halfvec_l2_ops`, `sparsevec_l2_ops` options, which are predefined types.
   *
   * **You can always specify any string you want in the operator class, in case Drizzle doesn't have it natively in its types**
   *
   * @param opClass
   * @returns
   */
  op(opClass) {
    this.indexConfig.opClass = opClass;
    return this;
  }
};
var IndexedColumn = class {
  static [entityKind] = "IndexedColumn";
  constructor(name, keyAsName, type, indexConfig) {
    this.name = name;
    this.keyAsName = keyAsName;
    this.type = type;
    this.indexConfig = indexConfig;
  }
  name;
  keyAsName;
  type;
  indexConfig;
};
var PgArrayBuilder = class extends PgColumnBuilder {
  static [entityKind] = "PgArrayBuilder";
  constructor(name, baseBuilder, size) {
    super(name, "array", "PgArray");
    this.config.baseBuilder = baseBuilder;
    this.config.size = size;
  }
  /** @internal */
  build(table) {
    const baseColumn = this.config.baseBuilder.build(table);
    return new PgArray(
      table,
      this.config,
      baseColumn
    );
  }
};
var PgArray = class _PgArray extends PgColumn {
  constructor(table, config2, baseColumn, range) {
    super(table, config2);
    this.baseColumn = baseColumn;
    this.range = range;
    this.size = config2.size;
  }
  size;
  static [entityKind] = "PgArray";
  getSQLType() {
    return `${this.baseColumn.getSQLType()}[${typeof this.size === "number" ? this.size : ""}]`;
  }
  mapFromDriverValue(value) {
    if (typeof value === "string") {
      value = parsePgArray(value);
    }
    return value.map((v) => this.baseColumn.mapFromDriverValue(v));
  }
  mapToDriverValue(value, isNestedArray = false) {
    const a = value.map(
      (v) => v === null ? null : is(this.baseColumn, _PgArray) ? this.baseColumn.mapToDriverValue(v, true) : this.baseColumn.mapToDriverValue(v)
    );
    if (isNestedArray) return a;
    return makePgArray(a);
  }
};

// ../../node_modules/.pnpm/drizzle-orm@0.44.7_@electri_170ce7fb4153736f6f8b6fe6a8fee8b5/node_modules/drizzle-orm/pg-core/columns/enum.js
var PgEnumObjectColumnBuilder = class extends PgColumnBuilder {
  static [entityKind] = "PgEnumObjectColumnBuilder";
  constructor(name, enumInstance) {
    super(name, "string", "PgEnumObjectColumn");
    this.config.enum = enumInstance;
  }
  /** @internal */
  build(table) {
    return new PgEnumObjectColumn(
      table,
      this.config
    );
  }
};
var PgEnumObjectColumn = class extends PgColumn {
  static [entityKind] = "PgEnumObjectColumn";
  enum;
  enumValues = this.config.enum.enumValues;
  constructor(table, config2) {
    super(table, config2);
    this.enum = config2.enum;
  }
  getSQLType() {
    return this.enum.enumName;
  }
};
var isPgEnumSym = Symbol.for("drizzle:isPgEnum");
function isPgEnum(obj) {
  return !!obj && typeof obj === "function" && isPgEnumSym in obj && obj[isPgEnumSym] === true;
}
var PgEnumColumnBuilder = class extends PgColumnBuilder {
  static [entityKind] = "PgEnumColumnBuilder";
  constructor(name, enumInstance) {
    super(name, "string", "PgEnumColumn");
    this.config.enum = enumInstance;
  }
  /** @internal */
  build(table) {
    return new PgEnumColumn(
      table,
      this.config
    );
  }
};
var PgEnumColumn = class extends PgColumn {
  static [entityKind] = "PgEnumColumn";
  enum = this.config.enum;
  enumValues = this.config.enum.enumValues;
  constructor(table, config2) {
    super(table, config2);
    this.enum = config2.enum;
  }
  getSQLType() {
    return this.enum.enumName;
  }
};

// ../../node_modules/.pnpm/drizzle-orm@0.44.7_@electri_170ce7fb4153736f6f8b6fe6a8fee8b5/node_modules/drizzle-orm/subquery.js
var Subquery = class {
  static [entityKind] = "Subquery";
  constructor(sql2, fields, alias, isWith = false, usedTables = []) {
    this._ = {
      brand: "Subquery",
      sql: sql2,
      selectedFields: fields,
      alias,
      isWith,
      usedTables
    };
  }
  // getSQL(): SQL<unknown> {
  // 	return new SQL([this]);
  // }
};
var WithSubquery = class extends Subquery {
  static [entityKind] = "WithSubquery";
};

// ../../node_modules/.pnpm/drizzle-orm@0.44.7_@electri_170ce7fb4153736f6f8b6fe6a8fee8b5/node_modules/drizzle-orm/version.js
var version = "0.44.7";

// ../../node_modules/.pnpm/drizzle-orm@0.44.7_@electri_170ce7fb4153736f6f8b6fe6a8fee8b5/node_modules/drizzle-orm/tracing.js
var otel;
var rawTracer;
var tracer = {
  startActiveSpan(name, fn) {
    if (!otel) {
      return fn();
    }
    if (!rawTracer) {
      rawTracer = otel.trace.getTracer("drizzle-orm", version);
    }
    return iife(
      (otel2, rawTracer2) => rawTracer2.startActiveSpan(
        name,
        (span) => {
          try {
            return fn(span);
          } catch (e) {
            span.setStatus({
              code: otel2.SpanStatusCode.ERROR,
              message: e instanceof Error ? e.message : "Unknown error"
              // eslint-disable-line no-instanceof/no-instanceof
            });
            throw e;
          } finally {
            span.end();
          }
        }
      ),
      otel,
      rawTracer
    );
  }
};

// ../../node_modules/.pnpm/drizzle-orm@0.44.7_@electri_170ce7fb4153736f6f8b6fe6a8fee8b5/node_modules/drizzle-orm/view-common.js
var ViewBaseConfig = Symbol.for("drizzle:ViewBaseConfig");

// ../../node_modules/.pnpm/drizzle-orm@0.44.7_@electri_170ce7fb4153736f6f8b6fe6a8fee8b5/node_modules/drizzle-orm/table.js
var Schema = Symbol.for("drizzle:Schema");
var Columns = Symbol.for("drizzle:Columns");
var ExtraConfigColumns = Symbol.for("drizzle:ExtraConfigColumns");
var OriginalName = Symbol.for("drizzle:OriginalName");
var BaseName = Symbol.for("drizzle:BaseName");
var IsAlias = Symbol.for("drizzle:IsAlias");
var ExtraConfigBuilder = Symbol.for("drizzle:ExtraConfigBuilder");
var IsDrizzleTable = Symbol.for("drizzle:IsDrizzleTable");
var Table = class {
  static [entityKind] = "Table";
  /** @internal */
  static Symbol = {
    Name: TableName,
    Schema,
    OriginalName,
    Columns,
    ExtraConfigColumns,
    BaseName,
    IsAlias,
    ExtraConfigBuilder
  };
  /**
   * @internal
   * Can be changed if the table is aliased.
   */
  [TableName];
  /**
   * @internal
   * Used to store the original name of the table, before any aliasing.
   */
  [OriginalName];
  /** @internal */
  [Schema];
  /** @internal */
  [Columns];
  /** @internal */
  [ExtraConfigColumns];
  /**
   *  @internal
   * Used to store the table name before the transformation via the `tableCreator` functions.
   */
  [BaseName];
  /** @internal */
  [IsAlias] = false;
  /** @internal */
  [IsDrizzleTable] = true;
  /** @internal */
  [ExtraConfigBuilder] = void 0;
  constructor(name, schema, baseName) {
    this[TableName] = this[OriginalName] = name;
    this[Schema] = schema;
    this[BaseName] = baseName;
  }
};
function getTableName(table) {
  return table[TableName];
}
function getTableUniqueName(table) {
  return `${table[Schema] ?? "public"}.${table[TableName]}`;
}

// ../../node_modules/.pnpm/drizzle-orm@0.44.7_@electri_170ce7fb4153736f6f8b6fe6a8fee8b5/node_modules/drizzle-orm/sql/sql.js
var FakePrimitiveParam = class {
  static [entityKind] = "FakePrimitiveParam";
};
function isSQLWrapper(value) {
  return value !== null && value !== void 0 && typeof value.getSQL === "function";
}
function mergeQueries(queries) {
  const result = { sql: "", params: [] };
  for (const query of queries) {
    result.sql += query.sql;
    result.params.push(...query.params);
    if (query.typings?.length) {
      if (!result.typings) {
        result.typings = [];
      }
      result.typings.push(...query.typings);
    }
  }
  return result;
}
var StringChunk = class {
  static [entityKind] = "StringChunk";
  value;
  constructor(value) {
    this.value = Array.isArray(value) ? value : [value];
  }
  getSQL() {
    return new SQL([this]);
  }
};
var SQL = class _SQL {
  constructor(queryChunks) {
    this.queryChunks = queryChunks;
    for (const chunk of queryChunks) {
      if (is(chunk, Table)) {
        const schemaName = chunk[Table.Symbol.Schema];
        this.usedTables.push(
          schemaName === void 0 ? chunk[Table.Symbol.Name] : schemaName + "." + chunk[Table.Symbol.Name]
        );
      }
    }
  }
  static [entityKind] = "SQL";
  /** @internal */
  decoder = noopDecoder;
  shouldInlineParams = false;
  /** @internal */
  usedTables = [];
  append(query) {
    this.queryChunks.push(...query.queryChunks);
    return this;
  }
  toQuery(config2) {
    return tracer.startActiveSpan("drizzle.buildSQL", (span) => {
      const query = this.buildQueryFromSourceParams(this.queryChunks, config2);
      span?.setAttributes({
        "drizzle.query.text": query.sql,
        "drizzle.query.params": JSON.stringify(query.params)
      });
      return query;
    });
  }
  buildQueryFromSourceParams(chunks, _config) {
    const config2 = Object.assign({}, _config, {
      inlineParams: _config.inlineParams || this.shouldInlineParams,
      paramStartIndex: _config.paramStartIndex || { value: 0 }
    });
    const {
      casing,
      escapeName,
      escapeParam,
      prepareTyping,
      inlineParams,
      paramStartIndex
    } = config2;
    return mergeQueries(chunks.map((chunk) => {
      if (is(chunk, StringChunk)) {
        return { sql: chunk.value.join(""), params: [] };
      }
      if (is(chunk, Name)) {
        return { sql: escapeName(chunk.value), params: [] };
      }
      if (chunk === void 0) {
        return { sql: "", params: [] };
      }
      if (Array.isArray(chunk)) {
        const result = [new StringChunk("(")];
        for (const [i, p] of chunk.entries()) {
          result.push(p);
          if (i < chunk.length - 1) {
            result.push(new StringChunk(", "));
          }
        }
        result.push(new StringChunk(")"));
        return this.buildQueryFromSourceParams(result, config2);
      }
      if (is(chunk, _SQL)) {
        return this.buildQueryFromSourceParams(chunk.queryChunks, {
          ...config2,
          inlineParams: inlineParams || chunk.shouldInlineParams
        });
      }
      if (is(chunk, Table)) {
        const schemaName = chunk[Table.Symbol.Schema];
        const tableName = chunk[Table.Symbol.Name];
        return {
          sql: schemaName === void 0 || chunk[IsAlias] ? escapeName(tableName) : escapeName(schemaName) + "." + escapeName(tableName),
          params: []
        };
      }
      if (is(chunk, Column)) {
        const columnName = casing.getColumnCasing(chunk);
        if (_config.invokeSource === "indexes") {
          return { sql: escapeName(columnName), params: [] };
        }
        const schemaName = chunk.table[Table.Symbol.Schema];
        return {
          sql: chunk.table[IsAlias] || schemaName === void 0 ? escapeName(chunk.table[Table.Symbol.Name]) + "." + escapeName(columnName) : escapeName(schemaName) + "." + escapeName(chunk.table[Table.Symbol.Name]) + "." + escapeName(columnName),
          params: []
        };
      }
      if (is(chunk, View)) {
        const schemaName = chunk[ViewBaseConfig].schema;
        const viewName = chunk[ViewBaseConfig].name;
        return {
          sql: schemaName === void 0 || chunk[ViewBaseConfig].isAlias ? escapeName(viewName) : escapeName(schemaName) + "." + escapeName(viewName),
          params: []
        };
      }
      if (is(chunk, Param)) {
        if (is(chunk.value, Placeholder)) {
          return { sql: escapeParam(paramStartIndex.value++, chunk), params: [chunk], typings: ["none"] };
        }
        const mappedValue = chunk.value === null ? null : chunk.encoder.mapToDriverValue(chunk.value);
        if (is(mappedValue, _SQL)) {
          return this.buildQueryFromSourceParams([mappedValue], config2);
        }
        if (inlineParams) {
          return { sql: this.mapInlineParam(mappedValue, config2), params: [] };
        }
        let typings = ["none"];
        if (prepareTyping) {
          typings = [prepareTyping(chunk.encoder)];
        }
        return { sql: escapeParam(paramStartIndex.value++, mappedValue), params: [mappedValue], typings };
      }
      if (is(chunk, Placeholder)) {
        return { sql: escapeParam(paramStartIndex.value++, chunk), params: [chunk], typings: ["none"] };
      }
      if (is(chunk, _SQL.Aliased) && chunk.fieldAlias !== void 0) {
        return { sql: escapeName(chunk.fieldAlias), params: [] };
      }
      if (is(chunk, Subquery)) {
        if (chunk._.isWith) {
          return { sql: escapeName(chunk._.alias), params: [] };
        }
        return this.buildQueryFromSourceParams([
          new StringChunk("("),
          chunk._.sql,
          new StringChunk(") "),
          new Name(chunk._.alias)
        ], config2);
      }
      if (isPgEnum(chunk)) {
        if (chunk.schema) {
          return { sql: escapeName(chunk.schema) + "." + escapeName(chunk.enumName), params: [] };
        }
        return { sql: escapeName(chunk.enumName), params: [] };
      }
      if (isSQLWrapper(chunk)) {
        if (chunk.shouldOmitSQLParens?.()) {
          return this.buildQueryFromSourceParams([chunk.getSQL()], config2);
        }
        return this.buildQueryFromSourceParams([
          new StringChunk("("),
          chunk.getSQL(),
          new StringChunk(")")
        ], config2);
      }
      if (inlineParams) {
        return { sql: this.mapInlineParam(chunk, config2), params: [] };
      }
      return { sql: escapeParam(paramStartIndex.value++, chunk), params: [chunk], typings: ["none"] };
    }));
  }
  mapInlineParam(chunk, { escapeString }) {
    if (chunk === null) {
      return "null";
    }
    if (typeof chunk === "number" || typeof chunk === "boolean") {
      return chunk.toString();
    }
    if (typeof chunk === "string") {
      return escapeString(chunk);
    }
    if (typeof chunk === "object") {
      const mappedValueAsString = chunk.toString();
      if (mappedValueAsString === "[object Object]") {
        return escapeString(JSON.stringify(chunk));
      }
      return escapeString(mappedValueAsString);
    }
    throw new Error("Unexpected param value: " + chunk);
  }
  getSQL() {
    return this;
  }
  as(alias) {
    if (alias === void 0) {
      return this;
    }
    return new _SQL.Aliased(this, alias);
  }
  mapWith(decoder) {
    this.decoder = typeof decoder === "function" ? { mapFromDriverValue: decoder } : decoder;
    return this;
  }
  inlineParams() {
    this.shouldInlineParams = true;
    return this;
  }
  /**
   * This method is used to conditionally include a part of the query.
   *
   * @param condition - Condition to check
   * @returns itself if the condition is `true`, otherwise `undefined`
   */
  if(condition) {
    return condition ? this : void 0;
  }
};
var Name = class {
  constructor(value) {
    this.value = value;
  }
  static [entityKind] = "Name";
  brand;
  getSQL() {
    return new SQL([this]);
  }
};
function isDriverValueEncoder(value) {
  return typeof value === "object" && value !== null && "mapToDriverValue" in value && typeof value.mapToDriverValue === "function";
}
var noopDecoder = {
  mapFromDriverValue: (value) => value
};
var noopEncoder = {
  mapToDriverValue: (value) => value
};
var noopMapper = {
  ...noopDecoder,
  ...noopEncoder
};
var Param = class {
  /**
   * @param value - Parameter value
   * @param encoder - Encoder to convert the value to a driver parameter
   */
  constructor(value, encoder = noopEncoder) {
    this.value = value;
    this.encoder = encoder;
  }
  static [entityKind] = "Param";
  brand;
  getSQL() {
    return new SQL([this]);
  }
};
function sql(strings, ...params) {
  const queryChunks = [];
  if (params.length > 0 || strings.length > 0 && strings[0] !== "") {
    queryChunks.push(new StringChunk(strings[0]));
  }
  for (const [paramIndex, param2] of params.entries()) {
    queryChunks.push(param2, new StringChunk(strings[paramIndex + 1]));
  }
  return new SQL(queryChunks);
}
((sql2) => {
  function empty() {
    return new SQL([]);
  }
  sql2.empty = empty;
  function fromList(list) {
    return new SQL(list);
  }
  sql2.fromList = fromList;
  function raw2(str) {
    return new SQL([new StringChunk(str)]);
  }
  sql2.raw = raw2;
  function join3(chunks, separator) {
    const result = [];
    for (const [i, chunk] of chunks.entries()) {
      if (i > 0 && separator !== void 0) {
        result.push(separator);
      }
      result.push(chunk);
    }
    return new SQL(result);
  }
  sql2.join = join3;
  function identifier(value) {
    return new Name(value);
  }
  sql2.identifier = identifier;
  function placeholder2(name2) {
    return new Placeholder(name2);
  }
  sql2.placeholder = placeholder2;
  function param2(value, encoder) {
    return new Param(value, encoder);
  }
  sql2.param = param2;
})(sql || (sql = {}));
((SQL2) => {
  class Aliased {
    constructor(sql2, fieldAlias) {
      this.sql = sql2;
      this.fieldAlias = fieldAlias;
    }
    static [entityKind] = "SQL.Aliased";
    /** @internal */
    isSelectionField = false;
    getSQL() {
      return this.sql;
    }
    /** @internal */
    clone() {
      return new Aliased(this.sql, this.fieldAlias);
    }
  }
  SQL2.Aliased = Aliased;
})(SQL || (SQL = {}));
var Placeholder = class {
  constructor(name2) {
    this.name = name2;
  }
  static [entityKind] = "Placeholder";
  getSQL() {
    return new SQL([this]);
  }
};
function fillPlaceholders(params, values) {
  return params.map((p) => {
    if (is(p, Placeholder)) {
      if (!(p.name in values)) {
        throw new Error(`No value for placeholder "${p.name}" was provided`);
      }
      return values[p.name];
    }
    if (is(p, Param) && is(p.value, Placeholder)) {
      if (!(p.value.name in values)) {
        throw new Error(`No value for placeholder "${p.value.name}" was provided`);
      }
      return p.encoder.mapToDriverValue(values[p.value.name]);
    }
    return p;
  });
}
var IsDrizzleView = Symbol.for("drizzle:IsDrizzleView");
var View = class {
  static [entityKind] = "View";
  /** @internal */
  [ViewBaseConfig];
  /** @internal */
  [IsDrizzleView] = true;
  constructor({ name: name2, schema, selectedFields, query }) {
    this[ViewBaseConfig] = {
      name: name2,
      originalName: name2,
      schema,
      selectedFields,
      query,
      isExisting: !query,
      isAlias: false
    };
  }
  getSQL() {
    return new SQL([this]);
  }
};
Column.prototype.getSQL = function() {
  return new SQL([this]);
};
Table.prototype.getSQL = function() {
  return new SQL([this]);
};
Subquery.prototype.getSQL = function() {
  return new SQL([this]);
};

// ../../node_modules/.pnpm/drizzle-orm@0.44.7_@electri_170ce7fb4153736f6f8b6fe6a8fee8b5/node_modules/drizzle-orm/alias.js
var ColumnAliasProxyHandler = class {
  constructor(table) {
    this.table = table;
  }
  static [entityKind] = "ColumnAliasProxyHandler";
  get(columnObj, prop) {
    if (prop === "table") {
      return this.table;
    }
    return columnObj[prop];
  }
};
var TableAliasProxyHandler = class {
  constructor(alias, replaceOriginalName) {
    this.alias = alias;
    this.replaceOriginalName = replaceOriginalName;
  }
  static [entityKind] = "TableAliasProxyHandler";
  get(target, prop) {
    if (prop === Table.Symbol.IsAlias) {
      return true;
    }
    if (prop === Table.Symbol.Name) {
      return this.alias;
    }
    if (this.replaceOriginalName && prop === Table.Symbol.OriginalName) {
      return this.alias;
    }
    if (prop === ViewBaseConfig) {
      return {
        ...target[ViewBaseConfig],
        name: this.alias,
        isAlias: true
      };
    }
    if (prop === Table.Symbol.Columns) {
      const columns = target[Table.Symbol.Columns];
      if (!columns) {
        return columns;
      }
      const proxiedColumns = {};
      Object.keys(columns).map((key) => {
        proxiedColumns[key] = new Proxy(
          columns[key],
          new ColumnAliasProxyHandler(new Proxy(target, this))
        );
      });
      return proxiedColumns;
    }
    const value = target[prop];
    if (is(value, Column)) {
      return new Proxy(value, new ColumnAliasProxyHandler(new Proxy(target, this)));
    }
    return value;
  }
};
var RelationTableAliasProxyHandler = class {
  constructor(alias) {
    this.alias = alias;
  }
  static [entityKind] = "RelationTableAliasProxyHandler";
  get(target, prop) {
    if (prop === "sourceTable") {
      return aliasedTable(target.sourceTable, this.alias);
    }
    return target[prop];
  }
};
function aliasedTable(table, tableAlias) {
  return new Proxy(table, new TableAliasProxyHandler(tableAlias, false));
}
function aliasedTableColumn(column, tableAlias) {
  return new Proxy(
    column,
    new ColumnAliasProxyHandler(new Proxy(column.table, new TableAliasProxyHandler(tableAlias, false)))
  );
}
function mapColumnsInAliasedSQLToAlias(query, alias) {
  return new SQL.Aliased(mapColumnsInSQLToAlias(query.sql, alias), query.fieldAlias);
}
function mapColumnsInSQLToAlias(query, alias) {
  return sql.join(query.queryChunks.map((c) => {
    if (is(c, Column)) {
      return aliasedTableColumn(c, alias);
    }
    if (is(c, SQL)) {
      return mapColumnsInSQLToAlias(c, alias);
    }
    if (is(c, SQL.Aliased)) {
      return mapColumnsInAliasedSQLToAlias(c, alias);
    }
    return c;
  }));
}

// ../../node_modules/.pnpm/drizzle-orm@0.44.7_@electri_170ce7fb4153736f6f8b6fe6a8fee8b5/node_modules/drizzle-orm/errors.js
var DrizzleError = class extends Error {
  static [entityKind] = "DrizzleError";
  constructor({ message, cause }) {
    super(message);
    this.name = "DrizzleError";
    this.cause = cause;
  }
};
var DrizzleQueryError = class _DrizzleQueryError extends Error {
  constructor(query, params, cause) {
    super(`Failed query: ${query}
params: ${params}`);
    this.query = query;
    this.params = params;
    this.cause = cause;
    Error.captureStackTrace(this, _DrizzleQueryError);
    if (cause) this.cause = cause;
  }
};
var TransactionRollbackError = class extends DrizzleError {
  static [entityKind] = "TransactionRollbackError";
  constructor() {
    super({ message: "Rollback" });
  }
};

// ../../node_modules/.pnpm/drizzle-orm@0.44.7_@electri_170ce7fb4153736f6f8b6fe6a8fee8b5/node_modules/drizzle-orm/logger.js
var ConsoleLogWriter = class {
  static [entityKind] = "ConsoleLogWriter";
  write(message) {
    console.log(message);
  }
};
var DefaultLogger = class {
  static [entityKind] = "DefaultLogger";
  writer;
  constructor(config2) {
    this.writer = config2?.writer ?? new ConsoleLogWriter();
  }
  logQuery(query, params) {
    const stringifiedParams = params.map((p) => {
      try {
        return JSON.stringify(p);
      } catch {
        return String(p);
      }
    });
    const paramsStr = stringifiedParams.length ? ` -- params: [${stringifiedParams.join(", ")}]` : "";
    this.writer.write(`Query: ${query}${paramsStr}`);
  }
};
var NoopLogger = class {
  static [entityKind] = "NoopLogger";
  logQuery() {
  }
};

// ../../node_modules/.pnpm/drizzle-orm@0.44.7_@electri_170ce7fb4153736f6f8b6fe6a8fee8b5/node_modules/drizzle-orm/query-promise.js
var QueryPromise = class {
  static [entityKind] = "QueryPromise";
  [Symbol.toStringTag] = "QueryPromise";
  catch(onRejected) {
    return this.then(void 0, onRejected);
  }
  finally(onFinally) {
    return this.then(
      (value) => {
        onFinally?.();
        return value;
      },
      (reason) => {
        onFinally?.();
        throw reason;
      }
    );
  }
  then(onFulfilled, onRejected) {
    return this.execute().then(onFulfilled, onRejected);
  }
};

// ../../node_modules/.pnpm/drizzle-orm@0.44.7_@electri_170ce7fb4153736f6f8b6fe6a8fee8b5/node_modules/drizzle-orm/utils.js
function mapResultRow(columns, row, joinsNotNullableMap) {
  const nullifyMap = {};
  const result = columns.reduce(
    (result2, { path, field }, columnIndex) => {
      let decoder;
      if (is(field, Column)) {
        decoder = field;
      } else if (is(field, SQL)) {
        decoder = field.decoder;
      } else {
        decoder = field.sql.decoder;
      }
      let node = result2;
      for (const [pathChunkIndex, pathChunk] of path.entries()) {
        if (pathChunkIndex < path.length - 1) {
          if (!(pathChunk in node)) {
            node[pathChunk] = {};
          }
          node = node[pathChunk];
        } else {
          const rawValue = row[columnIndex];
          const value = node[pathChunk] = rawValue === null ? null : decoder.mapFromDriverValue(rawValue);
          if (joinsNotNullableMap && is(field, Column) && path.length === 2) {
            const objectName = path[0];
            if (!(objectName in nullifyMap)) {
              nullifyMap[objectName] = value === null ? getTableName(field.table) : false;
            } else if (typeof nullifyMap[objectName] === "string" && nullifyMap[objectName] !== getTableName(field.table)) {
              nullifyMap[objectName] = false;
            }
          }
        }
      }
      return result2;
    },
    {}
  );
  if (joinsNotNullableMap && Object.keys(nullifyMap).length > 0) {
    for (const [objectName, tableName] of Object.entries(nullifyMap)) {
      if (typeof tableName === "string" && !joinsNotNullableMap[tableName]) {
        result[objectName] = null;
      }
    }
  }
  return result;
}
function orderSelectedFields(fields, pathPrefix) {
  return Object.entries(fields).reduce((result, [name, field]) => {
    if (typeof name !== "string") {
      return result;
    }
    const newPath = pathPrefix ? [...pathPrefix, name] : [name];
    if (is(field, Column) || is(field, SQL) || is(field, SQL.Aliased)) {
      result.push({ path: newPath, field });
    } else if (is(field, Table)) {
      result.push(...orderSelectedFields(field[Table.Symbol.Columns], newPath));
    } else {
      result.push(...orderSelectedFields(field, newPath));
    }
    return result;
  }, []);
}
function haveSameKeys(left, right) {
  const leftKeys = Object.keys(left);
  const rightKeys = Object.keys(right);
  if (leftKeys.length !== rightKeys.length) {
    return false;
  }
  for (const [index2, key] of leftKeys.entries()) {
    if (key !== rightKeys[index2]) {
      return false;
    }
  }
  return true;
}
function mapUpdateSet(table, values) {
  const entries = Object.entries(values).filter(([, value]) => value !== void 0).map(([key, value]) => {
    if (is(value, SQL) || is(value, Column)) {
      return [key, value];
    } else {
      return [key, new Param(value, table[Table.Symbol.Columns][key])];
    }
  });
  if (entries.length === 0) {
    throw new Error("No values to set");
  }
  return Object.fromEntries(entries);
}
function applyMixins(baseClass, extendedClasses) {
  for (const extendedClass of extendedClasses) {
    for (const name of Object.getOwnPropertyNames(extendedClass.prototype)) {
      if (name === "constructor") continue;
      Object.defineProperty(
        baseClass.prototype,
        name,
        Object.getOwnPropertyDescriptor(extendedClass.prototype, name) || /* @__PURE__ */ Object.create(null)
      );
    }
  }
}
function getTableColumns(table) {
  return table[Table.Symbol.Columns];
}
function getTableLikeName(table) {
  return is(table, Subquery) ? table._.alias : is(table, View) ? table[ViewBaseConfig].name : is(table, SQL) ? void 0 : table[Table.Symbol.IsAlias] ? table[Table.Symbol.Name] : table[Table.Symbol.BaseName];
}
function getColumnNameAndConfig(a, b) {
  return {
    name: typeof a === "string" && a.length > 0 ? a : "",
    config: typeof a === "object" ? a : b
  };
}
function isConfig(data) {
  if (typeof data !== "object" || data === null) return false;
  if (data.constructor.name !== "Object") return false;
  if ("logger" in data) {
    const type = typeof data["logger"];
    if (type !== "boolean" && (type !== "object" || typeof data["logger"]["logQuery"] !== "function") && type !== "undefined") return false;
    return true;
  }
  if ("schema" in data) {
    const type = typeof data["schema"];
    if (type !== "object" && type !== "undefined") return false;
    return true;
  }
  if ("casing" in data) {
    const type = typeof data["casing"];
    if (type !== "string" && type !== "undefined") return false;
    return true;
  }
  if ("mode" in data) {
    if (data["mode"] !== "default" || data["mode"] !== "planetscale" || data["mode"] !== void 0) return false;
    return true;
  }
  if ("connection" in data) {
    const type = typeof data["connection"];
    if (type !== "string" && type !== "object" && type !== "undefined") return false;
    return true;
  }
  if ("client" in data) {
    const type = typeof data["client"];
    if (type !== "object" && type !== "function" && type !== "undefined") return false;
    return true;
  }
  if (Object.keys(data).length === 0) return true;
  return false;
}
var textDecoder = typeof TextDecoder === "undefined" ? null : new TextDecoder();

// ../../node_modules/.pnpm/drizzle-orm@0.44.7_@electri_170ce7fb4153736f6f8b6fe6a8fee8b5/node_modules/drizzle-orm/pg-core/table.js
var InlineForeignKeys = Symbol.for("drizzle:PgInlineForeignKeys");
var EnableRLS = Symbol.for("drizzle:EnableRLS");
var PgTable = class extends Table {
  static [entityKind] = "PgTable";
  /** @internal */
  static Symbol = Object.assign({}, Table.Symbol, {
    InlineForeignKeys,
    EnableRLS
  });
  /**@internal */
  [InlineForeignKeys] = [];
  /** @internal */
  [EnableRLS] = false;
  /** @internal */
  [Table.Symbol.ExtraConfigBuilder] = void 0;
  /** @internal */
  [Table.Symbol.ExtraConfigColumns] = {};
};

// ../../node_modules/.pnpm/drizzle-orm@0.44.7_@electri_170ce7fb4153736f6f8b6fe6a8fee8b5/node_modules/drizzle-orm/pg-core/primary-keys.js
var PrimaryKeyBuilder = class {
  static [entityKind] = "PgPrimaryKeyBuilder";
  /** @internal */
  columns;
  /** @internal */
  name;
  constructor(columns, name) {
    this.columns = columns;
    this.name = name;
  }
  /** @internal */
  build(table) {
    return new PrimaryKey(table, this.columns, this.name);
  }
};
var PrimaryKey = class {
  constructor(table, columns, name) {
    this.table = table;
    this.columns = columns;
    this.name = name;
  }
  static [entityKind] = "PgPrimaryKey";
  columns;
  name;
  getName() {
    return this.name ?? `${this.table[PgTable.Symbol.Name]}_${this.columns.map((column) => column.name).join("_")}_pk`;
  }
};

// ../../node_modules/.pnpm/drizzle-orm@0.44.7_@electri_170ce7fb4153736f6f8b6fe6a8fee8b5/node_modules/drizzle-orm/sql/expressions/conditions.js
function bindIfParam(value, column) {
  if (isDriverValueEncoder(column) && !isSQLWrapper(value) && !is(value, Param) && !is(value, Placeholder) && !is(value, Column) && !is(value, Table) && !is(value, View)) {
    return new Param(value, column);
  }
  return value;
}
var eq = (left, right) => {
  return sql`${left} = ${bindIfParam(right, left)}`;
};
var ne = (left, right) => {
  return sql`${left} <> ${bindIfParam(right, left)}`;
};
function and(...unfilteredConditions) {
  const conditions = unfilteredConditions.filter(
    (c) => c !== void 0
  );
  if (conditions.length === 0) {
    return void 0;
  }
  if (conditions.length === 1) {
    return new SQL(conditions);
  }
  return new SQL([
    new StringChunk("("),
    sql.join(conditions, new StringChunk(" and ")),
    new StringChunk(")")
  ]);
}
function or(...unfilteredConditions) {
  const conditions = unfilteredConditions.filter(
    (c) => c !== void 0
  );
  if (conditions.length === 0) {
    return void 0;
  }
  if (conditions.length === 1) {
    return new SQL(conditions);
  }
  return new SQL([
    new StringChunk("("),
    sql.join(conditions, new StringChunk(" or ")),
    new StringChunk(")")
  ]);
}
function not(condition) {
  return sql`not ${condition}`;
}
var gt = (left, right) => {
  return sql`${left} > ${bindIfParam(right, left)}`;
};
var gte = (left, right) => {
  return sql`${left} >= ${bindIfParam(right, left)}`;
};
var lt = (left, right) => {
  return sql`${left} < ${bindIfParam(right, left)}`;
};
var lte = (left, right) => {
  return sql`${left} <= ${bindIfParam(right, left)}`;
};
function inArray(column, values) {
  if (Array.isArray(values)) {
    if (values.length === 0) {
      return sql`false`;
    }
    return sql`${column} in ${values.map((v) => bindIfParam(v, column))}`;
  }
  return sql`${column} in ${bindIfParam(values, column)}`;
}
function notInArray(column, values) {
  if (Array.isArray(values)) {
    if (values.length === 0) {
      return sql`true`;
    }
    return sql`${column} not in ${values.map((v) => bindIfParam(v, column))}`;
  }
  return sql`${column} not in ${bindIfParam(values, column)}`;
}
function isNull(value) {
  return sql`${value} is null`;
}
function isNotNull(value) {
  return sql`${value} is not null`;
}
function exists(subquery) {
  return sql`exists ${subquery}`;
}
function notExists(subquery) {
  return sql`not exists ${subquery}`;
}
function between(column, min, max) {
  return sql`${column} between ${bindIfParam(min, column)} and ${bindIfParam(
    max,
    column
  )}`;
}
function notBetween(column, min, max) {
  return sql`${column} not between ${bindIfParam(
    min,
    column
  )} and ${bindIfParam(max, column)}`;
}
function like(column, value) {
  return sql`${column} like ${value}`;
}
function notLike(column, value) {
  return sql`${column} not like ${value}`;
}
function ilike(column, value) {
  return sql`${column} ilike ${value}`;
}
function notIlike(column, value) {
  return sql`${column} not ilike ${value}`;
}

// ../../node_modules/.pnpm/drizzle-orm@0.44.7_@electri_170ce7fb4153736f6f8b6fe6a8fee8b5/node_modules/drizzle-orm/sql/expressions/select.js
function asc(column) {
  return sql`${column} asc`;
}
function desc(column) {
  return sql`${column} desc`;
}

// ../../node_modules/.pnpm/drizzle-orm@0.44.7_@electri_170ce7fb4153736f6f8b6fe6a8fee8b5/node_modules/drizzle-orm/relations.js
var Relation = class {
  constructor(sourceTable, referencedTable, relationName) {
    this.sourceTable = sourceTable;
    this.referencedTable = referencedTable;
    this.relationName = relationName;
    this.referencedTableName = referencedTable[Table.Symbol.Name];
  }
  static [entityKind] = "Relation";
  referencedTableName;
  fieldName;
};
var Relations = class {
  constructor(table, config2) {
    this.table = table;
    this.config = config2;
  }
  static [entityKind] = "Relations";
};
var One = class _One extends Relation {
  constructor(sourceTable, referencedTable, config2, isNullable) {
    super(sourceTable, referencedTable, config2?.relationName);
    this.config = config2;
    this.isNullable = isNullable;
  }
  static [entityKind] = "One";
  withFieldName(fieldName) {
    const relation = new _One(
      this.sourceTable,
      this.referencedTable,
      this.config,
      this.isNullable
    );
    relation.fieldName = fieldName;
    return relation;
  }
};
var Many = class _Many extends Relation {
  constructor(sourceTable, referencedTable, config2) {
    super(sourceTable, referencedTable, config2?.relationName);
    this.config = config2;
  }
  static [entityKind] = "Many";
  withFieldName(fieldName) {
    const relation = new _Many(
      this.sourceTable,
      this.referencedTable,
      this.config
    );
    relation.fieldName = fieldName;
    return relation;
  }
};
function getOperators() {
  return {
    and,
    between,
    eq,
    exists,
    gt,
    gte,
    ilike,
    inArray,
    isNull,
    isNotNull,
    like,
    lt,
    lte,
    ne,
    not,
    notBetween,
    notExists,
    notLike,
    notIlike,
    notInArray,
    or,
    sql
  };
}
function getOrderByOperators() {
  return {
    sql,
    asc,
    desc
  };
}
function extractTablesRelationalConfig(schema, configHelpers) {
  if (Object.keys(schema).length === 1 && "default" in schema && !is(schema["default"], Table)) {
    schema = schema["default"];
  }
  const tableNamesMap = {};
  const relationsBuffer = {};
  const tablesConfig = {};
  for (const [key, value] of Object.entries(schema)) {
    if (is(value, Table)) {
      const dbName = getTableUniqueName(value);
      const bufferedRelations = relationsBuffer[dbName];
      tableNamesMap[dbName] = key;
      tablesConfig[key] = {
        tsName: key,
        dbName: value[Table.Symbol.Name],
        schema: value[Table.Symbol.Schema],
        columns: value[Table.Symbol.Columns],
        relations: bufferedRelations?.relations ?? {},
        primaryKey: bufferedRelations?.primaryKey ?? []
      };
      for (const column of Object.values(
        value[Table.Symbol.Columns]
      )) {
        if (column.primary) {
          tablesConfig[key].primaryKey.push(column);
        }
      }
      const extraConfig = value[Table.Symbol.ExtraConfigBuilder]?.(value[Table.Symbol.ExtraConfigColumns]);
      if (extraConfig) {
        for (const configEntry of Object.values(extraConfig)) {
          if (is(configEntry, PrimaryKeyBuilder)) {
            tablesConfig[key].primaryKey.push(...configEntry.columns);
          }
        }
      }
    } else if (is(value, Relations)) {
      const dbName = getTableUniqueName(value.table);
      const tableName = tableNamesMap[dbName];
      const relations2 = value.config(
        configHelpers(value.table)
      );
      let primaryKey;
      for (const [relationName, relation] of Object.entries(relations2)) {
        if (tableName) {
          const tableConfig = tablesConfig[tableName];
          tableConfig.relations[relationName] = relation;
          if (primaryKey) {
            tableConfig.primaryKey.push(...primaryKey);
          }
        } else {
          if (!(dbName in relationsBuffer)) {
            relationsBuffer[dbName] = {
              relations: {},
              primaryKey
            };
          }
          relationsBuffer[dbName].relations[relationName] = relation;
        }
      }
    }
  }
  return { tables: tablesConfig, tableNamesMap };
}
function createOne(sourceTable) {
  return function one(table, config2) {
    return new One(
      sourceTable,
      table,
      config2,
      config2?.fields.reduce((res, f) => res && f.notNull, true) ?? false
    );
  };
}
function createMany(sourceTable) {
  return function many(referencedTable, config2) {
    return new Many(sourceTable, referencedTable, config2);
  };
}
function normalizeRelation(schema, tableNamesMap, relation) {
  if (is(relation, One) && relation.config) {
    return {
      fields: relation.config.fields,
      references: relation.config.references
    };
  }
  const referencedTableTsName = tableNamesMap[getTableUniqueName(relation.referencedTable)];
  if (!referencedTableTsName) {
    throw new Error(
      `Table "${relation.referencedTable[Table.Symbol.Name]}" not found in schema`
    );
  }
  const referencedTableConfig = schema[referencedTableTsName];
  if (!referencedTableConfig) {
    throw new Error(`Table "${referencedTableTsName}" not found in schema`);
  }
  const sourceTable = relation.sourceTable;
  const sourceTableTsName = tableNamesMap[getTableUniqueName(sourceTable)];
  if (!sourceTableTsName) {
    throw new Error(
      `Table "${sourceTable[Table.Symbol.Name]}" not found in schema`
    );
  }
  const reverseRelations = [];
  for (const referencedTableRelation of Object.values(
    referencedTableConfig.relations
  )) {
    if (relation.relationName && relation !== referencedTableRelation && referencedTableRelation.relationName === relation.relationName || !relation.relationName && referencedTableRelation.referencedTable === relation.sourceTable) {
      reverseRelations.push(referencedTableRelation);
    }
  }
  if (reverseRelations.length > 1) {
    throw relation.relationName ? new Error(
      `There are multiple relations with name "${relation.relationName}" in table "${referencedTableTsName}"`
    ) : new Error(
      `There are multiple relations between "${referencedTableTsName}" and "${relation.sourceTable[Table.Symbol.Name]}". Please specify relation name`
    );
  }
  if (reverseRelations[0] && is(reverseRelations[0], One) && reverseRelations[0].config) {
    return {
      fields: reverseRelations[0].config.references,
      references: reverseRelations[0].config.fields
    };
  }
  throw new Error(
    `There is not enough information to infer relation "${sourceTableTsName}.${relation.fieldName}"`
  );
}
function createTableRelationsHelpers(sourceTable) {
  return {
    one: createOne(sourceTable),
    many: createMany(sourceTable)
  };
}
function mapRelationalRow(tablesConfig, tableConfig, row, buildQueryResultSelection, mapColumnValue = (value) => value) {
  const result = {};
  for (const [
    selectionItemIndex,
    selectionItem
  ] of buildQueryResultSelection.entries()) {
    if (selectionItem.isJson) {
      const relation = tableConfig.relations[selectionItem.tsKey];
      const rawSubRows = row[selectionItemIndex];
      const subRows = typeof rawSubRows === "string" ? JSON.parse(rawSubRows) : rawSubRows;
      result[selectionItem.tsKey] = is(relation, One) ? subRows && mapRelationalRow(
        tablesConfig,
        tablesConfig[selectionItem.relationTableTsKey],
        subRows,
        selectionItem.selection,
        mapColumnValue
      ) : subRows.map(
        (subRow) => mapRelationalRow(
          tablesConfig,
          tablesConfig[selectionItem.relationTableTsKey],
          subRow,
          selectionItem.selection,
          mapColumnValue
        )
      );
    } else {
      const value = mapColumnValue(row[selectionItemIndex]);
      const field = selectionItem.field;
      let decoder;
      if (is(field, Column)) {
        decoder = field;
      } else if (is(field, SQL)) {
        decoder = field.decoder;
      } else {
        decoder = field.sql.decoder;
      }
      result[selectionItem.tsKey] = value === null ? null : decoder.mapFromDriverValue(value);
    }
  }
  return result;
}

// ../../node_modules/.pnpm/drizzle-orm@0.44.7_@electri_170ce7fb4153736f6f8b6fe6a8fee8b5/node_modules/drizzle-orm/better-sqlite3/driver.js
import Client from "better-sqlite3";

// ../../node_modules/.pnpm/drizzle-orm@0.44.7_@electri_170ce7fb4153736f6f8b6fe6a8fee8b5/node_modules/drizzle-orm/selection-proxy.js
var SelectionProxyHandler = class _SelectionProxyHandler {
  static [entityKind] = "SelectionProxyHandler";
  config;
  constructor(config2) {
    this.config = { ...config2 };
  }
  get(subquery, prop) {
    if (prop === "_") {
      return {
        ...subquery["_"],
        selectedFields: new Proxy(
          subquery._.selectedFields,
          this
        )
      };
    }
    if (prop === ViewBaseConfig) {
      return {
        ...subquery[ViewBaseConfig],
        selectedFields: new Proxy(
          subquery[ViewBaseConfig].selectedFields,
          this
        )
      };
    }
    if (typeof prop === "symbol") {
      return subquery[prop];
    }
    const columns = is(subquery, Subquery) ? subquery._.selectedFields : is(subquery, View) ? subquery[ViewBaseConfig].selectedFields : subquery;
    const value = columns[prop];
    if (is(value, SQL.Aliased)) {
      if (this.config.sqlAliasedBehavior === "sql" && !value.isSelectionField) {
        return value.sql;
      }
      const newValue = value.clone();
      newValue.isSelectionField = true;
      return newValue;
    }
    if (is(value, SQL)) {
      if (this.config.sqlBehavior === "sql") {
        return value;
      }
      throw new Error(
        `You tried to reference "${prop}" field from a subquery, which is a raw SQL field, but it doesn't have an alias declared. Please add an alias to the field using ".as('alias')" method.`
      );
    }
    if (is(value, Column)) {
      if (this.config.alias) {
        return new Proxy(
          value,
          new ColumnAliasProxyHandler(
            new Proxy(
              value.table,
              new TableAliasProxyHandler(this.config.alias, this.config.replaceOriginalName ?? false)
            )
          )
        );
      }
      return value;
    }
    if (typeof value !== "object" || value === null) {
      return value;
    }
    return new Proxy(value, new _SelectionProxyHandler(this.config));
  }
};

// ../../node_modules/.pnpm/drizzle-orm@0.44.7_@electri_170ce7fb4153736f6f8b6fe6a8fee8b5/node_modules/drizzle-orm/sqlite-core/foreign-keys.js
var ForeignKeyBuilder2 = class {
  static [entityKind] = "SQLiteForeignKeyBuilder";
  /** @internal */
  reference;
  /** @internal */
  _onUpdate;
  /** @internal */
  _onDelete;
  constructor(config2, actions) {
    this.reference = () => {
      const { name, columns, foreignColumns } = config2();
      return { name, columns, foreignTable: foreignColumns[0].table, foreignColumns };
    };
    if (actions) {
      this._onUpdate = actions.onUpdate;
      this._onDelete = actions.onDelete;
    }
  }
  onUpdate(action) {
    this._onUpdate = action;
    return this;
  }
  onDelete(action) {
    this._onDelete = action;
    return this;
  }
  /** @internal */
  build(table) {
    return new ForeignKey2(table, this);
  }
};
var ForeignKey2 = class {
  constructor(table, builder) {
    this.table = table;
    this.reference = builder.reference;
    this.onUpdate = builder._onUpdate;
    this.onDelete = builder._onDelete;
  }
  static [entityKind] = "SQLiteForeignKey";
  reference;
  onUpdate;
  onDelete;
  getName() {
    const { name, columns, foreignColumns } = this.reference();
    const columnNames = columns.map((column) => column.name);
    const foreignColumnNames = foreignColumns.map((column) => column.name);
    const chunks = [
      this.table[TableName],
      ...columnNames,
      foreignColumns[0].table[TableName],
      ...foreignColumnNames
    ];
    return name ?? `${chunks.join("_")}_fk`;
  }
};

// ../../node_modules/.pnpm/drizzle-orm@0.44.7_@electri_170ce7fb4153736f6f8b6fe6a8fee8b5/node_modules/drizzle-orm/sqlite-core/unique-constraint.js
function uniqueKeyName2(table, columns) {
  return `${table[TableName]}_${columns.join("_")}_unique`;
}
var UniqueConstraintBuilder2 = class {
  constructor(columns, name) {
    this.name = name;
    this.columns = columns;
  }
  static [entityKind] = "SQLiteUniqueConstraintBuilder";
  /** @internal */
  columns;
  /** @internal */
  build(table) {
    return new UniqueConstraint2(table, this.columns, this.name);
  }
};
var UniqueOnConstraintBuilder2 = class {
  static [entityKind] = "SQLiteUniqueOnConstraintBuilder";
  /** @internal */
  name;
  constructor(name) {
    this.name = name;
  }
  on(...columns) {
    return new UniqueConstraintBuilder2(columns, this.name);
  }
};
var UniqueConstraint2 = class {
  constructor(table, columns, name) {
    this.table = table;
    this.columns = columns;
    this.name = name ?? uniqueKeyName2(this.table, this.columns.map((column) => column.name));
  }
  static [entityKind] = "SQLiteUniqueConstraint";
  columns;
  name;
  getName() {
    return this.name;
  }
};

// ../../node_modules/.pnpm/drizzle-orm@0.44.7_@electri_170ce7fb4153736f6f8b6fe6a8fee8b5/node_modules/drizzle-orm/sqlite-core/columns/common.js
var SQLiteColumnBuilder = class extends ColumnBuilder {
  static [entityKind] = "SQLiteColumnBuilder";
  foreignKeyConfigs = [];
  references(ref, actions = {}) {
    this.foreignKeyConfigs.push({ ref, actions });
    return this;
  }
  unique(name) {
    this.config.isUnique = true;
    this.config.uniqueName = name;
    return this;
  }
  generatedAlwaysAs(as, config2) {
    this.config.generated = {
      as,
      type: "always",
      mode: config2?.mode ?? "virtual"
    };
    return this;
  }
  /** @internal */
  buildForeignKeys(column, table) {
    return this.foreignKeyConfigs.map(({ ref, actions }) => {
      return ((ref2, actions2) => {
        const builder = new ForeignKeyBuilder2(() => {
          const foreignColumn = ref2();
          return { columns: [column], foreignColumns: [foreignColumn] };
        });
        if (actions2.onUpdate) {
          builder.onUpdate(actions2.onUpdate);
        }
        if (actions2.onDelete) {
          builder.onDelete(actions2.onDelete);
        }
        return builder.build(table);
      })(ref, actions);
    });
  }
};
var SQLiteColumn = class extends Column {
  constructor(table, config2) {
    if (!config2.uniqueName) {
      config2.uniqueName = uniqueKeyName2(table, [config2.name]);
    }
    super(table, config2);
    this.table = table;
  }
  static [entityKind] = "SQLiteColumn";
};

// ../../node_modules/.pnpm/drizzle-orm@0.44.7_@electri_170ce7fb4153736f6f8b6fe6a8fee8b5/node_modules/drizzle-orm/sqlite-core/columns/blob.js
var SQLiteBigIntBuilder = class extends SQLiteColumnBuilder {
  static [entityKind] = "SQLiteBigIntBuilder";
  constructor(name) {
    super(name, "bigint", "SQLiteBigInt");
  }
  /** @internal */
  build(table) {
    return new SQLiteBigInt(table, this.config);
  }
};
var SQLiteBigInt = class extends SQLiteColumn {
  static [entityKind] = "SQLiteBigInt";
  getSQLType() {
    return "blob";
  }
  mapFromDriverValue(value) {
    if (typeof Buffer !== "undefined" && Buffer.from) {
      const buf = Buffer.isBuffer(value) ? value : value instanceof ArrayBuffer ? Buffer.from(value) : value.buffer ? Buffer.from(value.buffer, value.byteOffset, value.byteLength) : Buffer.from(value);
      return BigInt(buf.toString("utf8"));
    }
    return BigInt(textDecoder.decode(value));
  }
  mapToDriverValue(value) {
    return Buffer.from(value.toString());
  }
};
var SQLiteBlobJsonBuilder = class extends SQLiteColumnBuilder {
  static [entityKind] = "SQLiteBlobJsonBuilder";
  constructor(name) {
    super(name, "json", "SQLiteBlobJson");
  }
  /** @internal */
  build(table) {
    return new SQLiteBlobJson(
      table,
      this.config
    );
  }
};
var SQLiteBlobJson = class extends SQLiteColumn {
  static [entityKind] = "SQLiteBlobJson";
  getSQLType() {
    return "blob";
  }
  mapFromDriverValue(value) {
    if (typeof Buffer !== "undefined" && Buffer.from) {
      const buf = Buffer.isBuffer(value) ? value : value instanceof ArrayBuffer ? Buffer.from(value) : value.buffer ? Buffer.from(value.buffer, value.byteOffset, value.byteLength) : Buffer.from(value);
      return JSON.parse(buf.toString("utf8"));
    }
    return JSON.parse(textDecoder.decode(value));
  }
  mapToDriverValue(value) {
    return Buffer.from(JSON.stringify(value));
  }
};
var SQLiteBlobBufferBuilder = class extends SQLiteColumnBuilder {
  static [entityKind] = "SQLiteBlobBufferBuilder";
  constructor(name) {
    super(name, "buffer", "SQLiteBlobBuffer");
  }
  /** @internal */
  build(table) {
    return new SQLiteBlobBuffer(table, this.config);
  }
};
var SQLiteBlobBuffer = class extends SQLiteColumn {
  static [entityKind] = "SQLiteBlobBuffer";
  mapFromDriverValue(value) {
    if (Buffer.isBuffer(value)) {
      return value;
    }
    return Buffer.from(value);
  }
  getSQLType() {
    return "blob";
  }
};
function blob(a, b) {
  const { name, config: config2 } = getColumnNameAndConfig(a, b);
  if (config2?.mode === "json") {
    return new SQLiteBlobJsonBuilder(name);
  }
  if (config2?.mode === "bigint") {
    return new SQLiteBigIntBuilder(name);
  }
  return new SQLiteBlobBufferBuilder(name);
}

// ../../node_modules/.pnpm/drizzle-orm@0.44.7_@electri_170ce7fb4153736f6f8b6fe6a8fee8b5/node_modules/drizzle-orm/sqlite-core/columns/custom.js
var SQLiteCustomColumnBuilder = class extends SQLiteColumnBuilder {
  static [entityKind] = "SQLiteCustomColumnBuilder";
  constructor(name, fieldConfig, customTypeParams) {
    super(name, "custom", "SQLiteCustomColumn");
    this.config.fieldConfig = fieldConfig;
    this.config.customTypeParams = customTypeParams;
  }
  /** @internal */
  build(table) {
    return new SQLiteCustomColumn(
      table,
      this.config
    );
  }
};
var SQLiteCustomColumn = class extends SQLiteColumn {
  static [entityKind] = "SQLiteCustomColumn";
  sqlName;
  mapTo;
  mapFrom;
  constructor(table, config2) {
    super(table, config2);
    this.sqlName = config2.customTypeParams.dataType(config2.fieldConfig);
    this.mapTo = config2.customTypeParams.toDriver;
    this.mapFrom = config2.customTypeParams.fromDriver;
  }
  getSQLType() {
    return this.sqlName;
  }
  mapFromDriverValue(value) {
    return typeof this.mapFrom === "function" ? this.mapFrom(value) : value;
  }
  mapToDriverValue(value) {
    return typeof this.mapTo === "function" ? this.mapTo(value) : value;
  }
};
function customType(customTypeParams) {
  return (a, b) => {
    const { name, config: config2 } = getColumnNameAndConfig(a, b);
    return new SQLiteCustomColumnBuilder(
      name,
      config2,
      customTypeParams
    );
  };
}

// ../../node_modules/.pnpm/drizzle-orm@0.44.7_@electri_170ce7fb4153736f6f8b6fe6a8fee8b5/node_modules/drizzle-orm/sqlite-core/columns/integer.js
var SQLiteBaseIntegerBuilder = class extends SQLiteColumnBuilder {
  static [entityKind] = "SQLiteBaseIntegerBuilder";
  constructor(name, dataType, columnType) {
    super(name, dataType, columnType);
    this.config.autoIncrement = false;
  }
  primaryKey(config2) {
    if (config2?.autoIncrement) {
      this.config.autoIncrement = true;
    }
    this.config.hasDefault = true;
    return super.primaryKey();
  }
};
var SQLiteBaseInteger = class extends SQLiteColumn {
  static [entityKind] = "SQLiteBaseInteger";
  autoIncrement = this.config.autoIncrement;
  getSQLType() {
    return "integer";
  }
};
var SQLiteIntegerBuilder = class extends SQLiteBaseIntegerBuilder {
  static [entityKind] = "SQLiteIntegerBuilder";
  constructor(name) {
    super(name, "number", "SQLiteInteger");
  }
  build(table) {
    return new SQLiteInteger(
      table,
      this.config
    );
  }
};
var SQLiteInteger = class extends SQLiteBaseInteger {
  static [entityKind] = "SQLiteInteger";
};
var SQLiteTimestampBuilder = class extends SQLiteBaseIntegerBuilder {
  static [entityKind] = "SQLiteTimestampBuilder";
  constructor(name, mode) {
    super(name, "date", "SQLiteTimestamp");
    this.config.mode = mode;
  }
  /**
   * @deprecated Use `default()` with your own expression instead.
   *
   * Adds `DEFAULT (cast((julianday('now') - 2440587.5)*86400000 as integer))` to the column, which is the current epoch timestamp in milliseconds.
   */
  defaultNow() {
    return this.default(sql`(cast((julianday('now') - 2440587.5)*86400000 as integer))`);
  }
  build(table) {
    return new SQLiteTimestamp(
      table,
      this.config
    );
  }
};
var SQLiteTimestamp = class extends SQLiteBaseInteger {
  static [entityKind] = "SQLiteTimestamp";
  mode = this.config.mode;
  mapFromDriverValue(value) {
    if (this.config.mode === "timestamp") {
      return new Date(value * 1e3);
    }
    return new Date(value);
  }
  mapToDriverValue(value) {
    const unix = value.getTime();
    if (this.config.mode === "timestamp") {
      return Math.floor(unix / 1e3);
    }
    return unix;
  }
};
var SQLiteBooleanBuilder = class extends SQLiteBaseIntegerBuilder {
  static [entityKind] = "SQLiteBooleanBuilder";
  constructor(name, mode) {
    super(name, "boolean", "SQLiteBoolean");
    this.config.mode = mode;
  }
  build(table) {
    return new SQLiteBoolean(
      table,
      this.config
    );
  }
};
var SQLiteBoolean = class extends SQLiteBaseInteger {
  static [entityKind] = "SQLiteBoolean";
  mode = this.config.mode;
  mapFromDriverValue(value) {
    return Number(value) === 1;
  }
  mapToDriverValue(value) {
    return value ? 1 : 0;
  }
};
function integer(a, b) {
  const { name, config: config2 } = getColumnNameAndConfig(a, b);
  if (config2?.mode === "timestamp" || config2?.mode === "timestamp_ms") {
    return new SQLiteTimestampBuilder(name, config2.mode);
  }
  if (config2?.mode === "boolean") {
    return new SQLiteBooleanBuilder(name, config2.mode);
  }
  return new SQLiteIntegerBuilder(name);
}

// ../../node_modules/.pnpm/drizzle-orm@0.44.7_@electri_170ce7fb4153736f6f8b6fe6a8fee8b5/node_modules/drizzle-orm/sqlite-core/columns/numeric.js
var SQLiteNumericBuilder = class extends SQLiteColumnBuilder {
  static [entityKind] = "SQLiteNumericBuilder";
  constructor(name) {
    super(name, "string", "SQLiteNumeric");
  }
  /** @internal */
  build(table) {
    return new SQLiteNumeric(
      table,
      this.config
    );
  }
};
var SQLiteNumeric = class extends SQLiteColumn {
  static [entityKind] = "SQLiteNumeric";
  mapFromDriverValue(value) {
    if (typeof value === "string") return value;
    return String(value);
  }
  getSQLType() {
    return "numeric";
  }
};
var SQLiteNumericNumberBuilder = class extends SQLiteColumnBuilder {
  static [entityKind] = "SQLiteNumericNumberBuilder";
  constructor(name) {
    super(name, "number", "SQLiteNumericNumber");
  }
  /** @internal */
  build(table) {
    return new SQLiteNumericNumber(
      table,
      this.config
    );
  }
};
var SQLiteNumericNumber = class extends SQLiteColumn {
  static [entityKind] = "SQLiteNumericNumber";
  mapFromDriverValue(value) {
    if (typeof value === "number") return value;
    return Number(value);
  }
  mapToDriverValue = String;
  getSQLType() {
    return "numeric";
  }
};
var SQLiteNumericBigIntBuilder = class extends SQLiteColumnBuilder {
  static [entityKind] = "SQLiteNumericBigIntBuilder";
  constructor(name) {
    super(name, "bigint", "SQLiteNumericBigInt");
  }
  /** @internal */
  build(table) {
    return new SQLiteNumericBigInt(
      table,
      this.config
    );
  }
};
var SQLiteNumericBigInt = class extends SQLiteColumn {
  static [entityKind] = "SQLiteNumericBigInt";
  mapFromDriverValue = BigInt;
  mapToDriverValue = String;
  getSQLType() {
    return "numeric";
  }
};
function numeric(a, b) {
  const { name, config: config2 } = getColumnNameAndConfig(a, b);
  const mode = config2?.mode;
  return mode === "number" ? new SQLiteNumericNumberBuilder(name) : mode === "bigint" ? new SQLiteNumericBigIntBuilder(name) : new SQLiteNumericBuilder(name);
}

// ../../node_modules/.pnpm/drizzle-orm@0.44.7_@electri_170ce7fb4153736f6f8b6fe6a8fee8b5/node_modules/drizzle-orm/sqlite-core/columns/real.js
var SQLiteRealBuilder = class extends SQLiteColumnBuilder {
  static [entityKind] = "SQLiteRealBuilder";
  constructor(name) {
    super(name, "number", "SQLiteReal");
  }
  /** @internal */
  build(table) {
    return new SQLiteReal(table, this.config);
  }
};
var SQLiteReal = class extends SQLiteColumn {
  static [entityKind] = "SQLiteReal";
  getSQLType() {
    return "real";
  }
};
function real(name) {
  return new SQLiteRealBuilder(name ?? "");
}

// ../../node_modules/.pnpm/drizzle-orm@0.44.7_@electri_170ce7fb4153736f6f8b6fe6a8fee8b5/node_modules/drizzle-orm/sqlite-core/columns/text.js
var SQLiteTextBuilder = class extends SQLiteColumnBuilder {
  static [entityKind] = "SQLiteTextBuilder";
  constructor(name, config2) {
    super(name, "string", "SQLiteText");
    this.config.enumValues = config2.enum;
    this.config.length = config2.length;
  }
  /** @internal */
  build(table) {
    return new SQLiteText(
      table,
      this.config
    );
  }
};
var SQLiteText = class extends SQLiteColumn {
  static [entityKind] = "SQLiteText";
  enumValues = this.config.enumValues;
  length = this.config.length;
  constructor(table, config2) {
    super(table, config2);
  }
  getSQLType() {
    return `text${this.config.length ? `(${this.config.length})` : ""}`;
  }
};
var SQLiteTextJsonBuilder = class extends SQLiteColumnBuilder {
  static [entityKind] = "SQLiteTextJsonBuilder";
  constructor(name) {
    super(name, "json", "SQLiteTextJson");
  }
  /** @internal */
  build(table) {
    return new SQLiteTextJson(
      table,
      this.config
    );
  }
};
var SQLiteTextJson = class extends SQLiteColumn {
  static [entityKind] = "SQLiteTextJson";
  getSQLType() {
    return "text";
  }
  mapFromDriverValue(value) {
    return JSON.parse(value);
  }
  mapToDriverValue(value) {
    return JSON.stringify(value);
  }
};
function text(a, b = {}) {
  const { name, config: config2 } = getColumnNameAndConfig(a, b);
  if (config2.mode === "json") {
    return new SQLiteTextJsonBuilder(name);
  }
  return new SQLiteTextBuilder(name, config2);
}

// ../../node_modules/.pnpm/drizzle-orm@0.44.7_@electri_170ce7fb4153736f6f8b6fe6a8fee8b5/node_modules/drizzle-orm/sqlite-core/columns/all.js
function getSQLiteColumnBuilders() {
  return {
    blob,
    customType,
    integer,
    numeric,
    real,
    text
  };
}

// ../../node_modules/.pnpm/drizzle-orm@0.44.7_@electri_170ce7fb4153736f6f8b6fe6a8fee8b5/node_modules/drizzle-orm/sqlite-core/table.js
var InlineForeignKeys2 = Symbol.for("drizzle:SQLiteInlineForeignKeys");
var SQLiteTable = class extends Table {
  static [entityKind] = "SQLiteTable";
  /** @internal */
  static Symbol = Object.assign({}, Table.Symbol, {
    InlineForeignKeys: InlineForeignKeys2
  });
  /** @internal */
  [Table.Symbol.Columns];
  /** @internal */
  [InlineForeignKeys2] = [];
  /** @internal */
  [Table.Symbol.ExtraConfigBuilder] = void 0;
};
function sqliteTableBase(name, columns, extraConfig, schema, baseName = name) {
  const rawTable = new SQLiteTable(name, schema, baseName);
  const parsedColumns = typeof columns === "function" ? columns(getSQLiteColumnBuilders()) : columns;
  const builtColumns = Object.fromEntries(
    Object.entries(parsedColumns).map(([name2, colBuilderBase]) => {
      const colBuilder = colBuilderBase;
      colBuilder.setName(name2);
      const column = colBuilder.build(rawTable);
      rawTable[InlineForeignKeys2].push(...colBuilder.buildForeignKeys(column, rawTable));
      return [name2, column];
    })
  );
  const table = Object.assign(rawTable, builtColumns);
  table[Table.Symbol.Columns] = builtColumns;
  table[Table.Symbol.ExtraConfigColumns] = builtColumns;
  if (extraConfig) {
    table[SQLiteTable.Symbol.ExtraConfigBuilder] = extraConfig;
  }
  return table;
}
var sqliteTable = (name, columns, extraConfig) => {
  return sqliteTableBase(name, columns, extraConfig);
};

// ../../node_modules/.pnpm/drizzle-orm@0.44.7_@electri_170ce7fb4153736f6f8b6fe6a8fee8b5/node_modules/drizzle-orm/sqlite-core/indexes.js
var IndexBuilderOn = class {
  constructor(name, unique) {
    this.name = name;
    this.unique = unique;
  }
  static [entityKind] = "SQLiteIndexBuilderOn";
  on(...columns) {
    return new IndexBuilder(this.name, columns, this.unique);
  }
};
var IndexBuilder = class {
  static [entityKind] = "SQLiteIndexBuilder";
  /** @internal */
  config;
  constructor(name, columns, unique) {
    this.config = {
      name,
      columns,
      unique,
      where: void 0
    };
  }
  /**
   * Condition for partial index.
   */
  where(condition) {
    this.config.where = condition;
    return this;
  }
  /** @internal */
  build(table) {
    return new Index(this.config, table);
  }
};
var Index = class {
  static [entityKind] = "SQLiteIndex";
  config;
  constructor(config2, table) {
    this.config = { ...config2, table };
  }
};
function index(name) {
  return new IndexBuilderOn(name, false);
}
function uniqueIndex(name) {
  return new IndexBuilderOn(name, true);
}

// ../../node_modules/.pnpm/drizzle-orm@0.44.7_@electri_170ce7fb4153736f6f8b6fe6a8fee8b5/node_modules/drizzle-orm/sqlite-core/utils.js
function extractUsedTable(table) {
  if (is(table, SQLiteTable)) {
    return [`${table[Table.Symbol.BaseName]}`];
  }
  if (is(table, Subquery)) {
    return table._.usedTables ?? [];
  }
  if (is(table, SQL)) {
    return table.usedTables ?? [];
  }
  return [];
}

// ../../node_modules/.pnpm/drizzle-orm@0.44.7_@electri_170ce7fb4153736f6f8b6fe6a8fee8b5/node_modules/drizzle-orm/sqlite-core/query-builders/delete.js
var SQLiteDeleteBase = class extends QueryPromise {
  constructor(table, session, dialect, withList) {
    super();
    this.table = table;
    this.session = session;
    this.dialect = dialect;
    this.config = { table, withList };
  }
  static [entityKind] = "SQLiteDelete";
  /** @internal */
  config;
  /**
   * Adds a `where` clause to the query.
   *
   * Calling this method will delete only those rows that fulfill a specified condition.
   *
   * See docs: {@link https://orm.drizzle.team/docs/delete}
   *
   * @param where the `where` clause.
   *
   * @example
   * You can use conditional operators and `sql function` to filter the rows to be deleted.
   *
   * ```ts
   * // Delete all cars with green color
   * db.delete(cars).where(eq(cars.color, 'green'));
   * // or
   * db.delete(cars).where(sql`${cars.color} = 'green'`)
   * ```
   *
   * You can logically combine conditional operators with `and()` and `or()` operators:
   *
   * ```ts
   * // Delete all BMW cars with a green color
   * db.delete(cars).where(and(eq(cars.color, 'green'), eq(cars.brand, 'BMW')));
   *
   * // Delete all cars with the green or blue color
   * db.delete(cars).where(or(eq(cars.color, 'green'), eq(cars.color, 'blue')));
   * ```
   */
  where(where) {
    this.config.where = where;
    return this;
  }
  orderBy(...columns) {
    if (typeof columns[0] === "function") {
      const orderBy = columns[0](
        new Proxy(
          this.config.table[Table.Symbol.Columns],
          new SelectionProxyHandler({ sqlAliasedBehavior: "alias", sqlBehavior: "sql" })
        )
      );
      const orderByArray = Array.isArray(orderBy) ? orderBy : [orderBy];
      this.config.orderBy = orderByArray;
    } else {
      const orderByArray = columns;
      this.config.orderBy = orderByArray;
    }
    return this;
  }
  limit(limit) {
    this.config.limit = limit;
    return this;
  }
  returning(fields = this.table[SQLiteTable.Symbol.Columns]) {
    this.config.returning = orderSelectedFields(fields);
    return this;
  }
  /** @internal */
  getSQL() {
    return this.dialect.buildDeleteQuery(this.config);
  }
  toSQL() {
    const { typings: _typings, ...rest } = this.dialect.sqlToQuery(this.getSQL());
    return rest;
  }
  /** @internal */
  _prepare(isOneTimeQuery = true) {
    return this.session[isOneTimeQuery ? "prepareOneTimeQuery" : "prepareQuery"](
      this.dialect.sqlToQuery(this.getSQL()),
      this.config.returning,
      this.config.returning ? "all" : "run",
      true,
      void 0,
      {
        type: "delete",
        tables: extractUsedTable(this.config.table)
      }
    );
  }
  prepare() {
    return this._prepare(false);
  }
  run = (placeholderValues) => {
    return this._prepare().run(placeholderValues);
  };
  all = (placeholderValues) => {
    return this._prepare().all(placeholderValues);
  };
  get = (placeholderValues) => {
    return this._prepare().get(placeholderValues);
  };
  values = (placeholderValues) => {
    return this._prepare().values(placeholderValues);
  };
  async execute(placeholderValues) {
    return this._prepare().execute(placeholderValues);
  }
  $dynamic() {
    return this;
  }
};

// ../../node_modules/.pnpm/drizzle-orm@0.44.7_@electri_170ce7fb4153736f6f8b6fe6a8fee8b5/node_modules/drizzle-orm/casing.js
function toSnakeCase(input) {
  const words = input.replace(/['\u2019]/g, "").match(/[\da-z]+|[A-Z]+(?![a-z])|[A-Z][\da-z]+/g) ?? [];
  return words.map((word) => word.toLowerCase()).join("_");
}
function toCamelCase(input) {
  const words = input.replace(/['\u2019]/g, "").match(/[\da-z]+|[A-Z]+(?![a-z])|[A-Z][\da-z]+/g) ?? [];
  return words.reduce((acc, word, i) => {
    const formattedWord = i === 0 ? word.toLowerCase() : `${word[0].toUpperCase()}${word.slice(1)}`;
    return acc + formattedWord;
  }, "");
}
function noopCase(input) {
  return input;
}
var CasingCache = class {
  static [entityKind] = "CasingCache";
  /** @internal */
  cache = {};
  cachedTables = {};
  convert;
  constructor(casing) {
    this.convert = casing === "snake_case" ? toSnakeCase : casing === "camelCase" ? toCamelCase : noopCase;
  }
  getColumnCasing(column) {
    if (!column.keyAsName) return column.name;
    const schema = column.table[Table.Symbol.Schema] ?? "public";
    const tableName = column.table[Table.Symbol.OriginalName];
    const key = `${schema}.${tableName}.${column.name}`;
    if (!this.cache[key]) {
      this.cacheTable(column.table);
    }
    return this.cache[key];
  }
  cacheTable(table) {
    const schema = table[Table.Symbol.Schema] ?? "public";
    const tableName = table[Table.Symbol.OriginalName];
    const tableKey = `${schema}.${tableName}`;
    if (!this.cachedTables[tableKey]) {
      for (const column of Object.values(table[Table.Symbol.Columns])) {
        const columnKey = `${tableKey}.${column.name}`;
        this.cache[columnKey] = this.convert(column.name);
      }
      this.cachedTables[tableKey] = true;
    }
  }
  clearCache() {
    this.cache = {};
    this.cachedTables = {};
  }
};

// ../../node_modules/.pnpm/drizzle-orm@0.44.7_@electri_170ce7fb4153736f6f8b6fe6a8fee8b5/node_modules/drizzle-orm/sqlite-core/view-base.js
var SQLiteViewBase = class extends View {
  static [entityKind] = "SQLiteViewBase";
};

// ../../node_modules/.pnpm/drizzle-orm@0.44.7_@electri_170ce7fb4153736f6f8b6fe6a8fee8b5/node_modules/drizzle-orm/sqlite-core/dialect.js
var SQLiteDialect = class {
  static [entityKind] = "SQLiteDialect";
  /** @internal */
  casing;
  constructor(config2) {
    this.casing = new CasingCache(config2?.casing);
  }
  escapeName(name) {
    return `"${name}"`;
  }
  escapeParam(_num) {
    return "?";
  }
  escapeString(str) {
    return `'${str.replace(/'/g, "''")}'`;
  }
  buildWithCTE(queries) {
    if (!queries?.length) return void 0;
    const withSqlChunks = [sql`with `];
    for (const [i, w] of queries.entries()) {
      withSqlChunks.push(sql`${sql.identifier(w._.alias)} as (${w._.sql})`);
      if (i < queries.length - 1) {
        withSqlChunks.push(sql`, `);
      }
    }
    withSqlChunks.push(sql` `);
    return sql.join(withSqlChunks);
  }
  buildDeleteQuery({ table, where, returning, withList, limit, orderBy }) {
    const withSql = this.buildWithCTE(withList);
    const returningSql = returning ? sql` returning ${this.buildSelection(returning, { isSingleTable: true })}` : void 0;
    const whereSql = where ? sql` where ${where}` : void 0;
    const orderBySql = this.buildOrderBy(orderBy);
    const limitSql = this.buildLimit(limit);
    return sql`${withSql}delete from ${table}${whereSql}${returningSql}${orderBySql}${limitSql}`;
  }
  buildUpdateSet(table, set) {
    const tableColumns = table[Table.Symbol.Columns];
    const columnNames = Object.keys(tableColumns).filter(
      (colName) => set[colName] !== void 0 || tableColumns[colName]?.onUpdateFn !== void 0
    );
    const setSize = columnNames.length;
    return sql.join(columnNames.flatMap((colName, i) => {
      const col = tableColumns[colName];
      const value = set[colName] ?? sql.param(col.onUpdateFn(), col);
      const res = sql`${sql.identifier(this.casing.getColumnCasing(col))} = ${value}`;
      if (i < setSize - 1) {
        return [res, sql.raw(", ")];
      }
      return [res];
    }));
  }
  buildUpdateQuery({ table, set, where, returning, withList, joins, from, limit, orderBy }) {
    const withSql = this.buildWithCTE(withList);
    const setSql = this.buildUpdateSet(table, set);
    const fromSql = from && sql.join([sql.raw(" from "), this.buildFromTable(from)]);
    const joinsSql = this.buildJoins(joins);
    const returningSql = returning ? sql` returning ${this.buildSelection(returning, { isSingleTable: true })}` : void 0;
    const whereSql = where ? sql` where ${where}` : void 0;
    const orderBySql = this.buildOrderBy(orderBy);
    const limitSql = this.buildLimit(limit);
    return sql`${withSql}update ${table} set ${setSql}${fromSql}${joinsSql}${whereSql}${returningSql}${orderBySql}${limitSql}`;
  }
  /**
   * Builds selection SQL with provided fields/expressions
   *
   * Examples:
   *
   * `select <selection> from`
   *
   * `insert ... returning <selection>`
   *
   * If `isSingleTable` is true, then columns won't be prefixed with table name
   */
  buildSelection(fields, { isSingleTable = false } = {}) {
    const columnsLen = fields.length;
    const chunks = fields.flatMap(({ field }, i) => {
      const chunk = [];
      if (is(field, SQL.Aliased) && field.isSelectionField) {
        chunk.push(sql.identifier(field.fieldAlias));
      } else if (is(field, SQL.Aliased) || is(field, SQL)) {
        const query = is(field, SQL.Aliased) ? field.sql : field;
        if (isSingleTable) {
          chunk.push(
            new SQL(
              query.queryChunks.map((c) => {
                if (is(c, Column)) {
                  return sql.identifier(this.casing.getColumnCasing(c));
                }
                return c;
              })
            )
          );
        } else {
          chunk.push(query);
        }
        if (is(field, SQL.Aliased)) {
          chunk.push(sql` as ${sql.identifier(field.fieldAlias)}`);
        }
      } else if (is(field, Column)) {
        const tableName = field.table[Table.Symbol.Name];
        if (field.columnType === "SQLiteNumericBigInt") {
          if (isSingleTable) {
            chunk.push(sql`cast(${sql.identifier(this.casing.getColumnCasing(field))} as text)`);
          } else {
            chunk.push(
              sql`cast(${sql.identifier(tableName)}.${sql.identifier(this.casing.getColumnCasing(field))} as text)`
            );
          }
        } else {
          if (isSingleTable) {
            chunk.push(sql.identifier(this.casing.getColumnCasing(field)));
          } else {
            chunk.push(sql`${sql.identifier(tableName)}.${sql.identifier(this.casing.getColumnCasing(field))}`);
          }
        }
      }
      if (i < columnsLen - 1) {
        chunk.push(sql`, `);
      }
      return chunk;
    });
    return sql.join(chunks);
  }
  buildJoins(joins) {
    if (!joins || joins.length === 0) {
      return void 0;
    }
    const joinsArray = [];
    if (joins) {
      for (const [index2, joinMeta] of joins.entries()) {
        if (index2 === 0) {
          joinsArray.push(sql` `);
        }
        const table = joinMeta.table;
        const onSql = joinMeta.on ? sql` on ${joinMeta.on}` : void 0;
        if (is(table, SQLiteTable)) {
          const tableName = table[SQLiteTable.Symbol.Name];
          const tableSchema = table[SQLiteTable.Symbol.Schema];
          const origTableName = table[SQLiteTable.Symbol.OriginalName];
          const alias = tableName === origTableName ? void 0 : joinMeta.alias;
          joinsArray.push(
            sql`${sql.raw(joinMeta.joinType)} join ${tableSchema ? sql`${sql.identifier(tableSchema)}.` : void 0}${sql.identifier(origTableName)}${alias && sql` ${sql.identifier(alias)}`}${onSql}`
          );
        } else {
          joinsArray.push(
            sql`${sql.raw(joinMeta.joinType)} join ${table}${onSql}`
          );
        }
        if (index2 < joins.length - 1) {
          joinsArray.push(sql` `);
        }
      }
    }
    return sql.join(joinsArray);
  }
  buildLimit(limit) {
    return typeof limit === "object" || typeof limit === "number" && limit >= 0 ? sql` limit ${limit}` : void 0;
  }
  buildOrderBy(orderBy) {
    const orderByList = [];
    if (orderBy) {
      for (const [index2, orderByValue] of orderBy.entries()) {
        orderByList.push(orderByValue);
        if (index2 < orderBy.length - 1) {
          orderByList.push(sql`, `);
        }
      }
    }
    return orderByList.length > 0 ? sql` order by ${sql.join(orderByList)}` : void 0;
  }
  buildFromTable(table) {
    if (is(table, Table) && table[Table.Symbol.IsAlias]) {
      return sql`${sql`${sql.identifier(table[Table.Symbol.Schema] ?? "")}.`.if(table[Table.Symbol.Schema])}${sql.identifier(table[Table.Symbol.OriginalName])} ${sql.identifier(table[Table.Symbol.Name])}`;
    }
    return table;
  }
  buildSelectQuery({
    withList,
    fields,
    fieldsFlat,
    where,
    having,
    table,
    joins,
    orderBy,
    groupBy,
    limit,
    offset,
    distinct,
    setOperators
  }) {
    const fieldsList = fieldsFlat ?? orderSelectedFields(fields);
    for (const f of fieldsList) {
      if (is(f.field, Column) && getTableName(f.field.table) !== (is(table, Subquery) ? table._.alias : is(table, SQLiteViewBase) ? table[ViewBaseConfig].name : is(table, SQL) ? void 0 : getTableName(table)) && !((table2) => joins?.some(
        ({ alias }) => alias === (table2[Table.Symbol.IsAlias] ? getTableName(table2) : table2[Table.Symbol.BaseName])
      ))(f.field.table)) {
        const tableName = getTableName(f.field.table);
        throw new Error(
          `Your "${f.path.join("->")}" field references a column "${tableName}"."${f.field.name}", but the table "${tableName}" is not part of the query! Did you forget to join it?`
        );
      }
    }
    const isSingleTable = !joins || joins.length === 0;
    const withSql = this.buildWithCTE(withList);
    const distinctSql = distinct ? sql` distinct` : void 0;
    const selection = this.buildSelection(fieldsList, { isSingleTable });
    const tableSql = this.buildFromTable(table);
    const joinsSql = this.buildJoins(joins);
    const whereSql = where ? sql` where ${where}` : void 0;
    const havingSql = having ? sql` having ${having}` : void 0;
    const groupByList = [];
    if (groupBy) {
      for (const [index2, groupByValue] of groupBy.entries()) {
        groupByList.push(groupByValue);
        if (index2 < groupBy.length - 1) {
          groupByList.push(sql`, `);
        }
      }
    }
    const groupBySql = groupByList.length > 0 ? sql` group by ${sql.join(groupByList)}` : void 0;
    const orderBySql = this.buildOrderBy(orderBy);
    const limitSql = this.buildLimit(limit);
    const offsetSql = offset ? sql` offset ${offset}` : void 0;
    const finalQuery = sql`${withSql}select${distinctSql} ${selection} from ${tableSql}${joinsSql}${whereSql}${groupBySql}${havingSql}${orderBySql}${limitSql}${offsetSql}`;
    if (setOperators.length > 0) {
      return this.buildSetOperations(finalQuery, setOperators);
    }
    return finalQuery;
  }
  buildSetOperations(leftSelect, setOperators) {
    const [setOperator, ...rest] = setOperators;
    if (!setOperator) {
      throw new Error("Cannot pass undefined values to any set operator");
    }
    if (rest.length === 0) {
      return this.buildSetOperationQuery({ leftSelect, setOperator });
    }
    return this.buildSetOperations(
      this.buildSetOperationQuery({ leftSelect, setOperator }),
      rest
    );
  }
  buildSetOperationQuery({
    leftSelect,
    setOperator: { type, isAll, rightSelect, limit, orderBy, offset }
  }) {
    const leftChunk = sql`${leftSelect.getSQL()} `;
    const rightChunk = sql`${rightSelect.getSQL()}`;
    let orderBySql;
    if (orderBy && orderBy.length > 0) {
      const orderByValues = [];
      for (const singleOrderBy of orderBy) {
        if (is(singleOrderBy, SQLiteColumn)) {
          orderByValues.push(sql.identifier(singleOrderBy.name));
        } else if (is(singleOrderBy, SQL)) {
          for (let i = 0; i < singleOrderBy.queryChunks.length; i++) {
            const chunk = singleOrderBy.queryChunks[i];
            if (is(chunk, SQLiteColumn)) {
              singleOrderBy.queryChunks[i] = sql.identifier(this.casing.getColumnCasing(chunk));
            }
          }
          orderByValues.push(sql`${singleOrderBy}`);
        } else {
          orderByValues.push(sql`${singleOrderBy}`);
        }
      }
      orderBySql = sql` order by ${sql.join(orderByValues, sql`, `)}`;
    }
    const limitSql = typeof limit === "object" || typeof limit === "number" && limit >= 0 ? sql` limit ${limit}` : void 0;
    const operatorChunk = sql.raw(`${type} ${isAll ? "all " : ""}`);
    const offsetSql = offset ? sql` offset ${offset}` : void 0;
    return sql`${leftChunk}${operatorChunk}${rightChunk}${orderBySql}${limitSql}${offsetSql}`;
  }
  buildInsertQuery({ table, values: valuesOrSelect, onConflict, returning, withList, select }) {
    const valuesSqlList = [];
    const columns = table[Table.Symbol.Columns];
    const colEntries = Object.entries(columns).filter(
      ([_, col]) => !col.shouldDisableInsert()
    );
    const insertOrder = colEntries.map(([, column]) => sql.identifier(this.casing.getColumnCasing(column)));
    if (select) {
      const select2 = valuesOrSelect;
      if (is(select2, SQL)) {
        valuesSqlList.push(select2);
      } else {
        valuesSqlList.push(select2.getSQL());
      }
    } else {
      const values = valuesOrSelect;
      valuesSqlList.push(sql.raw("values "));
      for (const [valueIndex, value] of values.entries()) {
        const valueList = [];
        for (const [fieldName, col] of colEntries) {
          const colValue = value[fieldName];
          if (colValue === void 0 || is(colValue, Param) && colValue.value === void 0) {
            let defaultValue;
            if (col.default !== null && col.default !== void 0) {
              defaultValue = is(col.default, SQL) ? col.default : sql.param(col.default, col);
            } else if (col.defaultFn !== void 0) {
              const defaultFnResult = col.defaultFn();
              defaultValue = is(defaultFnResult, SQL) ? defaultFnResult : sql.param(defaultFnResult, col);
            } else if (!col.default && col.onUpdateFn !== void 0) {
              const onUpdateFnResult = col.onUpdateFn();
              defaultValue = is(onUpdateFnResult, SQL) ? onUpdateFnResult : sql.param(onUpdateFnResult, col);
            } else {
              defaultValue = sql`null`;
            }
            valueList.push(defaultValue);
          } else {
            valueList.push(colValue);
          }
        }
        valuesSqlList.push(valueList);
        if (valueIndex < values.length - 1) {
          valuesSqlList.push(sql`, `);
        }
      }
    }
    const withSql = this.buildWithCTE(withList);
    const valuesSql = sql.join(valuesSqlList);
    const returningSql = returning ? sql` returning ${this.buildSelection(returning, { isSingleTable: true })}` : void 0;
    const onConflictSql = onConflict?.length ? sql.join(onConflict) : void 0;
    return sql`${withSql}insert into ${table} ${insertOrder} ${valuesSql}${onConflictSql}${returningSql}`;
  }
  sqlToQuery(sql2, invokeSource) {
    return sql2.toQuery({
      casing: this.casing,
      escapeName: this.escapeName,
      escapeParam: this.escapeParam,
      escapeString: this.escapeString,
      invokeSource
    });
  }
  buildRelationalQuery({
    fullSchema,
    schema,
    tableNamesMap,
    table,
    tableConfig,
    queryConfig: config2,
    tableAlias,
    nestedQueryRelation,
    joinOn
  }) {
    let selection = [];
    let limit, offset, orderBy = [], where;
    const joins = [];
    if (config2 === true) {
      const selectionEntries = Object.entries(tableConfig.columns);
      selection = selectionEntries.map(([key, value]) => ({
        dbKey: value.name,
        tsKey: key,
        field: aliasedTableColumn(value, tableAlias),
        relationTableTsKey: void 0,
        isJson: false,
        selection: []
      }));
    } else {
      const aliasedColumns = Object.fromEntries(
        Object.entries(tableConfig.columns).map(([key, value]) => [key, aliasedTableColumn(value, tableAlias)])
      );
      if (config2.where) {
        const whereSql = typeof config2.where === "function" ? config2.where(aliasedColumns, getOperators()) : config2.where;
        where = whereSql && mapColumnsInSQLToAlias(whereSql, tableAlias);
      }
      const fieldsSelection = [];
      let selectedColumns = [];
      if (config2.columns) {
        let isIncludeMode = false;
        for (const [field, value] of Object.entries(config2.columns)) {
          if (value === void 0) {
            continue;
          }
          if (field in tableConfig.columns) {
            if (!isIncludeMode && value === true) {
              isIncludeMode = true;
            }
            selectedColumns.push(field);
          }
        }
        if (selectedColumns.length > 0) {
          selectedColumns = isIncludeMode ? selectedColumns.filter((c) => config2.columns?.[c] === true) : Object.keys(tableConfig.columns).filter((key) => !selectedColumns.includes(key));
        }
      } else {
        selectedColumns = Object.keys(tableConfig.columns);
      }
      for (const field of selectedColumns) {
        const column = tableConfig.columns[field];
        fieldsSelection.push({ tsKey: field, value: column });
      }
      let selectedRelations = [];
      if (config2.with) {
        selectedRelations = Object.entries(config2.with).filter((entry) => !!entry[1]).map(([tsKey, queryConfig]) => ({ tsKey, queryConfig, relation: tableConfig.relations[tsKey] }));
      }
      let extras;
      if (config2.extras) {
        extras = typeof config2.extras === "function" ? config2.extras(aliasedColumns, { sql }) : config2.extras;
        for (const [tsKey, value] of Object.entries(extras)) {
          fieldsSelection.push({
            tsKey,
            value: mapColumnsInAliasedSQLToAlias(value, tableAlias)
          });
        }
      }
      for (const { tsKey, value } of fieldsSelection) {
        selection.push({
          dbKey: is(value, SQL.Aliased) ? value.fieldAlias : tableConfig.columns[tsKey].name,
          tsKey,
          field: is(value, Column) ? aliasedTableColumn(value, tableAlias) : value,
          relationTableTsKey: void 0,
          isJson: false,
          selection: []
        });
      }
      let orderByOrig = typeof config2.orderBy === "function" ? config2.orderBy(aliasedColumns, getOrderByOperators()) : config2.orderBy ?? [];
      if (!Array.isArray(orderByOrig)) {
        orderByOrig = [orderByOrig];
      }
      orderBy = orderByOrig.map((orderByValue) => {
        if (is(orderByValue, Column)) {
          return aliasedTableColumn(orderByValue, tableAlias);
        }
        return mapColumnsInSQLToAlias(orderByValue, tableAlias);
      });
      limit = config2.limit;
      offset = config2.offset;
      for (const {
        tsKey: selectedRelationTsKey,
        queryConfig: selectedRelationConfigValue,
        relation
      } of selectedRelations) {
        const normalizedRelation = normalizeRelation(schema, tableNamesMap, relation);
        const relationTableName = getTableUniqueName(relation.referencedTable);
        const relationTableTsName = tableNamesMap[relationTableName];
        const relationTableAlias = `${tableAlias}_${selectedRelationTsKey}`;
        const joinOn2 = and(
          ...normalizedRelation.fields.map(
            (field2, i) => eq(
              aliasedTableColumn(normalizedRelation.references[i], relationTableAlias),
              aliasedTableColumn(field2, tableAlias)
            )
          )
        );
        const builtRelation = this.buildRelationalQuery({
          fullSchema,
          schema,
          tableNamesMap,
          table: fullSchema[relationTableTsName],
          tableConfig: schema[relationTableTsName],
          queryConfig: is(relation, One) ? selectedRelationConfigValue === true ? { limit: 1 } : { ...selectedRelationConfigValue, limit: 1 } : selectedRelationConfigValue,
          tableAlias: relationTableAlias,
          joinOn: joinOn2,
          nestedQueryRelation: relation
        });
        const field = sql`(${builtRelation.sql})`.as(selectedRelationTsKey);
        selection.push({
          dbKey: selectedRelationTsKey,
          tsKey: selectedRelationTsKey,
          field,
          relationTableTsKey: relationTableTsName,
          isJson: true,
          selection: builtRelation.selection
        });
      }
    }
    if (selection.length === 0) {
      throw new DrizzleError({
        message: `No fields selected for table "${tableConfig.tsName}" ("${tableAlias}"). You need to have at least one item in "columns", "with" or "extras". If you need to select all columns, omit the "columns" key or set it to undefined.`
      });
    }
    let result;
    where = and(joinOn, where);
    if (nestedQueryRelation) {
      let field = sql`json_array(${sql.join(
        selection.map(
          ({ field: field2 }) => is(field2, SQLiteColumn) ? sql.identifier(this.casing.getColumnCasing(field2)) : is(field2, SQL.Aliased) ? field2.sql : field2
        ),
        sql`, `
      )})`;
      if (is(nestedQueryRelation, Many)) {
        field = sql`coalesce(json_group_array(${field}), json_array())`;
      }
      const nestedSelection = [{
        dbKey: "data",
        tsKey: "data",
        field: field.as("data"),
        isJson: true,
        relationTableTsKey: tableConfig.tsName,
        selection
      }];
      const needsSubquery = limit !== void 0 || offset !== void 0 || orderBy.length > 0;
      if (needsSubquery) {
        result = this.buildSelectQuery({
          table: aliasedTable(table, tableAlias),
          fields: {},
          fieldsFlat: [
            {
              path: [],
              field: sql.raw("*")
            }
          ],
          where,
          limit,
          offset,
          orderBy,
          setOperators: []
        });
        where = void 0;
        limit = void 0;
        offset = void 0;
        orderBy = void 0;
      } else {
        result = aliasedTable(table, tableAlias);
      }
      result = this.buildSelectQuery({
        table: is(result, SQLiteTable) ? result : new Subquery(result, {}, tableAlias),
        fields: {},
        fieldsFlat: nestedSelection.map(({ field: field2 }) => ({
          path: [],
          field: is(field2, Column) ? aliasedTableColumn(field2, tableAlias) : field2
        })),
        joins,
        where,
        limit,
        offset,
        orderBy,
        setOperators: []
      });
    } else {
      result = this.buildSelectQuery({
        table: aliasedTable(table, tableAlias),
        fields: {},
        fieldsFlat: selection.map(({ field }) => ({
          path: [],
          field: is(field, Column) ? aliasedTableColumn(field, tableAlias) : field
        })),
        joins,
        where,
        limit,
        offset,
        orderBy,
        setOperators: []
      });
    }
    return {
      tableTsKey: tableConfig.tsName,
      sql: result,
      selection
    };
  }
};
var SQLiteSyncDialect = class extends SQLiteDialect {
  static [entityKind] = "SQLiteSyncDialect";
  migrate(migrations, session, config2) {
    const migrationsTable = config2 === void 0 ? "__drizzle_migrations" : typeof config2 === "string" ? "__drizzle_migrations" : config2.migrationsTable ?? "__drizzle_migrations";
    const migrationTableCreate = sql`
			CREATE TABLE IF NOT EXISTS ${sql.identifier(migrationsTable)} (
				id SERIAL PRIMARY KEY,
				hash text NOT NULL,
				created_at numeric
			)
		`;
    session.run(migrationTableCreate);
    const dbMigrations = session.values(
      sql`SELECT id, hash, created_at FROM ${sql.identifier(migrationsTable)} ORDER BY created_at DESC LIMIT 1`
    );
    const lastDbMigration = dbMigrations[0] ?? void 0;
    session.run(sql`BEGIN`);
    try {
      for (const migration of migrations) {
        if (!lastDbMigration || Number(lastDbMigration[2]) < migration.folderMillis) {
          for (const stmt of migration.sql) {
            session.run(sql.raw(stmt));
          }
          session.run(
            sql`INSERT INTO ${sql.identifier(migrationsTable)} ("hash", "created_at") VALUES(${migration.hash}, ${migration.folderMillis})`
          );
        }
      }
      session.run(sql`COMMIT`);
    } catch (e) {
      session.run(sql`ROLLBACK`);
      throw e;
    }
  }
};
var SQLiteAsyncDialect = class extends SQLiteDialect {
  static [entityKind] = "SQLiteAsyncDialect";
  async migrate(migrations, session, config2) {
    const migrationsTable = config2 === void 0 ? "__drizzle_migrations" : typeof config2 === "string" ? "__drizzle_migrations" : config2.migrationsTable ?? "__drizzle_migrations";
    const migrationTableCreate = sql`
			CREATE TABLE IF NOT EXISTS ${sql.identifier(migrationsTable)} (
				id SERIAL PRIMARY KEY,
				hash text NOT NULL,
				created_at numeric
			)
		`;
    await session.run(migrationTableCreate);
    const dbMigrations = await session.values(
      sql`SELECT id, hash, created_at FROM ${sql.identifier(migrationsTable)} ORDER BY created_at DESC LIMIT 1`
    );
    const lastDbMigration = dbMigrations[0] ?? void 0;
    await session.transaction(async (tx) => {
      for (const migration of migrations) {
        if (!lastDbMigration || Number(lastDbMigration[2]) < migration.folderMillis) {
          for (const stmt of migration.sql) {
            await tx.run(sql.raw(stmt));
          }
          await tx.run(
            sql`INSERT INTO ${sql.identifier(migrationsTable)} ("hash", "created_at") VALUES(${migration.hash}, ${migration.folderMillis})`
          );
        }
      }
    });
  }
};

// ../../node_modules/.pnpm/drizzle-orm@0.44.7_@electri_170ce7fb4153736f6f8b6fe6a8fee8b5/node_modules/drizzle-orm/query-builders/query-builder.js
var TypedQueryBuilder = class {
  static [entityKind] = "TypedQueryBuilder";
  /** @internal */
  getSelectedFields() {
    return this._.selectedFields;
  }
};

// ../../node_modules/.pnpm/drizzle-orm@0.44.7_@electri_170ce7fb4153736f6f8b6fe6a8fee8b5/node_modules/drizzle-orm/sqlite-core/query-builders/select.js
var SQLiteSelectBuilder = class {
  static [entityKind] = "SQLiteSelectBuilder";
  fields;
  session;
  dialect;
  withList;
  distinct;
  constructor(config2) {
    this.fields = config2.fields;
    this.session = config2.session;
    this.dialect = config2.dialect;
    this.withList = config2.withList;
    this.distinct = config2.distinct;
  }
  from(source) {
    const isPartialSelect = !!this.fields;
    let fields;
    if (this.fields) {
      fields = this.fields;
    } else if (is(source, Subquery)) {
      fields = Object.fromEntries(
        Object.keys(source._.selectedFields).map((key) => [key, source[key]])
      );
    } else if (is(source, SQLiteViewBase)) {
      fields = source[ViewBaseConfig].selectedFields;
    } else if (is(source, SQL)) {
      fields = {};
    } else {
      fields = getTableColumns(source);
    }
    return new SQLiteSelectBase({
      table: source,
      fields,
      isPartialSelect,
      session: this.session,
      dialect: this.dialect,
      withList: this.withList,
      distinct: this.distinct
    });
  }
};
var SQLiteSelectQueryBuilderBase = class extends TypedQueryBuilder {
  static [entityKind] = "SQLiteSelectQueryBuilder";
  _;
  /** @internal */
  config;
  joinsNotNullableMap;
  tableName;
  isPartialSelect;
  session;
  dialect;
  cacheConfig = void 0;
  usedTables = /* @__PURE__ */ new Set();
  constructor({ table, fields, isPartialSelect, session, dialect, withList, distinct }) {
    super();
    this.config = {
      withList,
      table,
      fields: { ...fields },
      distinct,
      setOperators: []
    };
    this.isPartialSelect = isPartialSelect;
    this.session = session;
    this.dialect = dialect;
    this._ = {
      selectedFields: fields,
      config: this.config
    };
    this.tableName = getTableLikeName(table);
    this.joinsNotNullableMap = typeof this.tableName === "string" ? { [this.tableName]: true } : {};
    for (const item of extractUsedTable(table)) this.usedTables.add(item);
  }
  /** @internal */
  getUsedTables() {
    return [...this.usedTables];
  }
  createJoin(joinType) {
    return (table, on) => {
      const baseTableName = this.tableName;
      const tableName = getTableLikeName(table);
      for (const item of extractUsedTable(table)) this.usedTables.add(item);
      if (typeof tableName === "string" && this.config.joins?.some((join3) => join3.alias === tableName)) {
        throw new Error(`Alias "${tableName}" is already used in this query`);
      }
      if (!this.isPartialSelect) {
        if (Object.keys(this.joinsNotNullableMap).length === 1 && typeof baseTableName === "string") {
          this.config.fields = {
            [baseTableName]: this.config.fields
          };
        }
        if (typeof tableName === "string" && !is(table, SQL)) {
          const selection = is(table, Subquery) ? table._.selectedFields : is(table, View) ? table[ViewBaseConfig].selectedFields : table[Table.Symbol.Columns];
          this.config.fields[tableName] = selection;
        }
      }
      if (typeof on === "function") {
        on = on(
          new Proxy(
            this.config.fields,
            new SelectionProxyHandler({ sqlAliasedBehavior: "sql", sqlBehavior: "sql" })
          )
        );
      }
      if (!this.config.joins) {
        this.config.joins = [];
      }
      this.config.joins.push({ on, table, joinType, alias: tableName });
      if (typeof tableName === "string") {
        switch (joinType) {
          case "left": {
            this.joinsNotNullableMap[tableName] = false;
            break;
          }
          case "right": {
            this.joinsNotNullableMap = Object.fromEntries(
              Object.entries(this.joinsNotNullableMap).map(([key]) => [key, false])
            );
            this.joinsNotNullableMap[tableName] = true;
            break;
          }
          case "cross":
          case "inner": {
            this.joinsNotNullableMap[tableName] = true;
            break;
          }
          case "full": {
            this.joinsNotNullableMap = Object.fromEntries(
              Object.entries(this.joinsNotNullableMap).map(([key]) => [key, false])
            );
            this.joinsNotNullableMap[tableName] = false;
            break;
          }
        }
      }
      return this;
    };
  }
  /**
   * Executes a `left join` operation by adding another table to the current query.
   *
   * Calling this method associates each row of the table with the corresponding row from the joined table, if a match is found. If no matching row exists, it sets all columns of the joined table to null.
   *
   * See docs: {@link https://orm.drizzle.team/docs/joins#left-join}
   *
   * @param table the table to join.
   * @param on the `on` clause.
   *
   * @example
   *
   * ```ts
   * // Select all users and their pets
   * const usersWithPets: { user: User; pets: Pet | null; }[] = await db.select()
   *   .from(users)
   *   .leftJoin(pets, eq(users.id, pets.ownerId))
   *
   * // Select userId and petId
   * const usersIdsAndPetIds: { userId: number; petId: number | null; }[] = await db.select({
   *   userId: users.id,
   *   petId: pets.id,
   * })
   *   .from(users)
   *   .leftJoin(pets, eq(users.id, pets.ownerId))
   * ```
   */
  leftJoin = this.createJoin("left");
  /**
   * Executes a `right join` operation by adding another table to the current query.
   *
   * Calling this method associates each row of the joined table with the corresponding row from the main table, if a match is found. If no matching row exists, it sets all columns of the main table to null.
   *
   * See docs: {@link https://orm.drizzle.team/docs/joins#right-join}
   *
   * @param table the table to join.
   * @param on the `on` clause.
   *
   * @example
   *
   * ```ts
   * // Select all users and their pets
   * const usersWithPets: { user: User | null; pets: Pet; }[] = await db.select()
   *   .from(users)
   *   .rightJoin(pets, eq(users.id, pets.ownerId))
   *
   * // Select userId and petId
   * const usersIdsAndPetIds: { userId: number | null; petId: number; }[] = await db.select({
   *   userId: users.id,
   *   petId: pets.id,
   * })
   *   .from(users)
   *   .rightJoin(pets, eq(users.id, pets.ownerId))
   * ```
   */
  rightJoin = this.createJoin("right");
  /**
   * Executes an `inner join` operation, creating a new table by combining rows from two tables that have matching values.
   *
   * Calling this method retrieves rows that have corresponding entries in both joined tables. Rows without matching entries in either table are excluded, resulting in a table that includes only matching pairs.
   *
   * See docs: {@link https://orm.drizzle.team/docs/joins#inner-join}
   *
   * @param table the table to join.
   * @param on the `on` clause.
   *
   * @example
   *
   * ```ts
   * // Select all users and their pets
   * const usersWithPets: { user: User; pets: Pet; }[] = await db.select()
   *   .from(users)
   *   .innerJoin(pets, eq(users.id, pets.ownerId))
   *
   * // Select userId and petId
   * const usersIdsAndPetIds: { userId: number; petId: number; }[] = await db.select({
   *   userId: users.id,
   *   petId: pets.id,
   * })
   *   .from(users)
   *   .innerJoin(pets, eq(users.id, pets.ownerId))
   * ```
   */
  innerJoin = this.createJoin("inner");
  /**
   * Executes a `full join` operation by combining rows from two tables into a new table.
   *
   * Calling this method retrieves all rows from both main and joined tables, merging rows with matching values and filling in `null` for non-matching columns.
   *
   * See docs: {@link https://orm.drizzle.team/docs/joins#full-join}
   *
   * @param table the table to join.
   * @param on the `on` clause.
   *
   * @example
   *
   * ```ts
   * // Select all users and their pets
   * const usersWithPets: { user: User | null; pets: Pet | null; }[] = await db.select()
   *   .from(users)
   *   .fullJoin(pets, eq(users.id, pets.ownerId))
   *
   * // Select userId and petId
   * const usersIdsAndPetIds: { userId: number | null; petId: number | null; }[] = await db.select({
   *   userId: users.id,
   *   petId: pets.id,
   * })
   *   .from(users)
   *   .fullJoin(pets, eq(users.id, pets.ownerId))
   * ```
   */
  fullJoin = this.createJoin("full");
  /**
   * Executes a `cross join` operation by combining rows from two tables into a new table.
   *
   * Calling this method retrieves all rows from both main and joined tables, merging all rows from each table.
   *
   * See docs: {@link https://orm.drizzle.team/docs/joins#cross-join}
   *
   * @param table the table to join.
   *
   * @example
   *
   * ```ts
   * // Select all users, each user with every pet
   * const usersWithPets: { user: User; pets: Pet; }[] = await db.select()
   *   .from(users)
   *   .crossJoin(pets)
   *
   * // Select userId and petId
   * const usersIdsAndPetIds: { userId: number; petId: number; }[] = await db.select({
   *   userId: users.id,
   *   petId: pets.id,
   * })
   *   .from(users)
   *   .crossJoin(pets)
   * ```
   */
  crossJoin = this.createJoin("cross");
  createSetOperator(type, isAll) {
    return (rightSelection) => {
      const rightSelect = typeof rightSelection === "function" ? rightSelection(getSQLiteSetOperators()) : rightSelection;
      if (!haveSameKeys(this.getSelectedFields(), rightSelect.getSelectedFields())) {
        throw new Error(
          "Set operator error (union / intersect / except): selected fields are not the same or are in a different order"
        );
      }
      this.config.setOperators.push({ type, isAll, rightSelect });
      return this;
    };
  }
  /**
   * Adds `union` set operator to the query.
   *
   * Calling this method will combine the result sets of the `select` statements and remove any duplicate rows that appear across them.
   *
   * See docs: {@link https://orm.drizzle.team/docs/set-operations#union}
   *
   * @example
   *
   * ```ts
   * // Select all unique names from customers and users tables
   * await db.select({ name: users.name })
   *   .from(users)
   *   .union(
   *     db.select({ name: customers.name }).from(customers)
   *   );
   * // or
   * import { union } from 'drizzle-orm/sqlite-core'
   *
   * await union(
   *   db.select({ name: users.name }).from(users),
   *   db.select({ name: customers.name }).from(customers)
   * );
   * ```
   */
  union = this.createSetOperator("union", false);
  /**
   * Adds `union all` set operator to the query.
   *
   * Calling this method will combine the result-set of the `select` statements and keep all duplicate rows that appear across them.
   *
   * See docs: {@link https://orm.drizzle.team/docs/set-operations#union-all}
   *
   * @example
   *
   * ```ts
   * // Select all transaction ids from both online and in-store sales
   * await db.select({ transaction: onlineSales.transactionId })
   *   .from(onlineSales)
   *   .unionAll(
   *     db.select({ transaction: inStoreSales.transactionId }).from(inStoreSales)
   *   );
   * // or
   * import { unionAll } from 'drizzle-orm/sqlite-core'
   *
   * await unionAll(
   *   db.select({ transaction: onlineSales.transactionId }).from(onlineSales),
   *   db.select({ transaction: inStoreSales.transactionId }).from(inStoreSales)
   * );
   * ```
   */
  unionAll = this.createSetOperator("union", true);
  /**
   * Adds `intersect` set operator to the query.
   *
   * Calling this method will retain only the rows that are present in both result sets and eliminate duplicates.
   *
   * See docs: {@link https://orm.drizzle.team/docs/set-operations#intersect}
   *
   * @example
   *
   * ```ts
   * // Select course names that are offered in both departments A and B
   * await db.select({ courseName: depA.courseName })
   *   .from(depA)
   *   .intersect(
   *     db.select({ courseName: depB.courseName }).from(depB)
   *   );
   * // or
   * import { intersect } from 'drizzle-orm/sqlite-core'
   *
   * await intersect(
   *   db.select({ courseName: depA.courseName }).from(depA),
   *   db.select({ courseName: depB.courseName }).from(depB)
   * );
   * ```
   */
  intersect = this.createSetOperator("intersect", false);
  /**
   * Adds `except` set operator to the query.
   *
   * Calling this method will retrieve all unique rows from the left query, except for the rows that are present in the result set of the right query.
   *
   * See docs: {@link https://orm.drizzle.team/docs/set-operations#except}
   *
   * @example
   *
   * ```ts
   * // Select all courses offered in department A but not in department B
   * await db.select({ courseName: depA.courseName })
   *   .from(depA)
   *   .except(
   *     db.select({ courseName: depB.courseName }).from(depB)
   *   );
   * // or
   * import { except } from 'drizzle-orm/sqlite-core'
   *
   * await except(
   *   db.select({ courseName: depA.courseName }).from(depA),
   *   db.select({ courseName: depB.courseName }).from(depB)
   * );
   * ```
   */
  except = this.createSetOperator("except", false);
  /** @internal */
  addSetOperators(setOperators) {
    this.config.setOperators.push(...setOperators);
    return this;
  }
  /**
   * Adds a `where` clause to the query.
   *
   * Calling this method will select only those rows that fulfill a specified condition.
   *
   * See docs: {@link https://orm.drizzle.team/docs/select#filtering}
   *
   * @param where the `where` clause.
   *
   * @example
   * You can use conditional operators and `sql function` to filter the rows to be selected.
   *
   * ```ts
   * // Select all cars with green color
   * await db.select().from(cars).where(eq(cars.color, 'green'));
   * // or
   * await db.select().from(cars).where(sql`${cars.color} = 'green'`)
   * ```
   *
   * You can logically combine conditional operators with `and()` and `or()` operators:
   *
   * ```ts
   * // Select all BMW cars with a green color
   * await db.select().from(cars).where(and(eq(cars.color, 'green'), eq(cars.brand, 'BMW')));
   *
   * // Select all cars with the green or blue color
   * await db.select().from(cars).where(or(eq(cars.color, 'green'), eq(cars.color, 'blue')));
   * ```
   */
  where(where) {
    if (typeof where === "function") {
      where = where(
        new Proxy(
          this.config.fields,
          new SelectionProxyHandler({ sqlAliasedBehavior: "sql", sqlBehavior: "sql" })
        )
      );
    }
    this.config.where = where;
    return this;
  }
  /**
   * Adds a `having` clause to the query.
   *
   * Calling this method will select only those rows that fulfill a specified condition. It is typically used with aggregate functions to filter the aggregated data based on a specified condition.
   *
   * See docs: {@link https://orm.drizzle.team/docs/select#aggregations}
   *
   * @param having the `having` clause.
   *
   * @example
   *
   * ```ts
   * // Select all brands with more than one car
   * await db.select({
   * 	brand: cars.brand,
   * 	count: sql<number>`cast(count(${cars.id}) as int)`,
   * })
   *   .from(cars)
   *   .groupBy(cars.brand)
   *   .having(({ count }) => gt(count, 1));
   * ```
   */
  having(having) {
    if (typeof having === "function") {
      having = having(
        new Proxy(
          this.config.fields,
          new SelectionProxyHandler({ sqlAliasedBehavior: "sql", sqlBehavior: "sql" })
        )
      );
    }
    this.config.having = having;
    return this;
  }
  groupBy(...columns) {
    if (typeof columns[0] === "function") {
      const groupBy = columns[0](
        new Proxy(
          this.config.fields,
          new SelectionProxyHandler({ sqlAliasedBehavior: "alias", sqlBehavior: "sql" })
        )
      );
      this.config.groupBy = Array.isArray(groupBy) ? groupBy : [groupBy];
    } else {
      this.config.groupBy = columns;
    }
    return this;
  }
  orderBy(...columns) {
    if (typeof columns[0] === "function") {
      const orderBy = columns[0](
        new Proxy(
          this.config.fields,
          new SelectionProxyHandler({ sqlAliasedBehavior: "alias", sqlBehavior: "sql" })
        )
      );
      const orderByArray = Array.isArray(orderBy) ? orderBy : [orderBy];
      if (this.config.setOperators.length > 0) {
        this.config.setOperators.at(-1).orderBy = orderByArray;
      } else {
        this.config.orderBy = orderByArray;
      }
    } else {
      const orderByArray = columns;
      if (this.config.setOperators.length > 0) {
        this.config.setOperators.at(-1).orderBy = orderByArray;
      } else {
        this.config.orderBy = orderByArray;
      }
    }
    return this;
  }
  /**
   * Adds a `limit` clause to the query.
   *
   * Calling this method will set the maximum number of rows that will be returned by this query.
   *
   * See docs: {@link https://orm.drizzle.team/docs/select#limit--offset}
   *
   * @param limit the `limit` clause.
   *
   * @example
   *
   * ```ts
   * // Get the first 10 people from this query.
   * await db.select().from(people).limit(10);
   * ```
   */
  limit(limit) {
    if (this.config.setOperators.length > 0) {
      this.config.setOperators.at(-1).limit = limit;
    } else {
      this.config.limit = limit;
    }
    return this;
  }
  /**
   * Adds an `offset` clause to the query.
   *
   * Calling this method will skip a number of rows when returning results from this query.
   *
   * See docs: {@link https://orm.drizzle.team/docs/select#limit--offset}
   *
   * @param offset the `offset` clause.
   *
   * @example
   *
   * ```ts
   * // Get the 10th-20th people from this query.
   * await db.select().from(people).offset(10).limit(10);
   * ```
   */
  offset(offset) {
    if (this.config.setOperators.length > 0) {
      this.config.setOperators.at(-1).offset = offset;
    } else {
      this.config.offset = offset;
    }
    return this;
  }
  /** @internal */
  getSQL() {
    return this.dialect.buildSelectQuery(this.config);
  }
  toSQL() {
    const { typings: _typings, ...rest } = this.dialect.sqlToQuery(this.getSQL());
    return rest;
  }
  as(alias) {
    const usedTables = [];
    usedTables.push(...extractUsedTable(this.config.table));
    if (this.config.joins) {
      for (const it of this.config.joins) usedTables.push(...extractUsedTable(it.table));
    }
    return new Proxy(
      new Subquery(this.getSQL(), this.config.fields, alias, false, [...new Set(usedTables)]),
      new SelectionProxyHandler({ alias, sqlAliasedBehavior: "alias", sqlBehavior: "error" })
    );
  }
  /** @internal */
  getSelectedFields() {
    return new Proxy(
      this.config.fields,
      new SelectionProxyHandler({ alias: this.tableName, sqlAliasedBehavior: "alias", sqlBehavior: "error" })
    );
  }
  $dynamic() {
    return this;
  }
};
var SQLiteSelectBase = class extends SQLiteSelectQueryBuilderBase {
  static [entityKind] = "SQLiteSelect";
  /** @internal */
  _prepare(isOneTimeQuery = true) {
    if (!this.session) {
      throw new Error("Cannot execute a query on a query builder. Please use a database instance instead.");
    }
    const fieldsList = orderSelectedFields(this.config.fields);
    const query = this.session[isOneTimeQuery ? "prepareOneTimeQuery" : "prepareQuery"](
      this.dialect.sqlToQuery(this.getSQL()),
      fieldsList,
      "all",
      true,
      void 0,
      {
        type: "select",
        tables: [...this.usedTables]
      },
      this.cacheConfig
    );
    query.joinsNotNullableMap = this.joinsNotNullableMap;
    return query;
  }
  $withCache(config2) {
    this.cacheConfig = config2 === void 0 ? { config: {}, enable: true, autoInvalidate: true } : config2 === false ? { enable: false } : { enable: true, autoInvalidate: true, ...config2 };
    return this;
  }
  prepare() {
    return this._prepare(false);
  }
  run = (placeholderValues) => {
    return this._prepare().run(placeholderValues);
  };
  all = (placeholderValues) => {
    return this._prepare().all(placeholderValues);
  };
  get = (placeholderValues) => {
    return this._prepare().get(placeholderValues);
  };
  values = (placeholderValues) => {
    return this._prepare().values(placeholderValues);
  };
  async execute() {
    return this.all();
  }
};
applyMixins(SQLiteSelectBase, [QueryPromise]);
function createSetOperator(type, isAll) {
  return (leftSelect, rightSelect, ...restSelects) => {
    const setOperators = [rightSelect, ...restSelects].map((select) => ({
      type,
      isAll,
      rightSelect: select
    }));
    for (const setOperator of setOperators) {
      if (!haveSameKeys(leftSelect.getSelectedFields(), setOperator.rightSelect.getSelectedFields())) {
        throw new Error(
          "Set operator error (union / intersect / except): selected fields are not the same or are in a different order"
        );
      }
    }
    return leftSelect.addSetOperators(setOperators);
  };
}
var getSQLiteSetOperators = () => ({
  union,
  unionAll,
  intersect,
  except
});
var union = createSetOperator("union", false);
var unionAll = createSetOperator("union", true);
var intersect = createSetOperator("intersect", false);
var except = createSetOperator("except", false);

// ../../node_modules/.pnpm/drizzle-orm@0.44.7_@electri_170ce7fb4153736f6f8b6fe6a8fee8b5/node_modules/drizzle-orm/sqlite-core/query-builders/query-builder.js
var QueryBuilder = class {
  static [entityKind] = "SQLiteQueryBuilder";
  dialect;
  dialectConfig;
  constructor(dialect) {
    this.dialect = is(dialect, SQLiteDialect) ? dialect : void 0;
    this.dialectConfig = is(dialect, SQLiteDialect) ? void 0 : dialect;
  }
  $with = (alias, selection) => {
    const queryBuilder = this;
    const as = (qb) => {
      if (typeof qb === "function") {
        qb = qb(queryBuilder);
      }
      return new Proxy(
        new WithSubquery(
          qb.getSQL(),
          selection ?? ("getSelectedFields" in qb ? qb.getSelectedFields() ?? {} : {}),
          alias,
          true
        ),
        new SelectionProxyHandler({ alias, sqlAliasedBehavior: "alias", sqlBehavior: "error" })
      );
    };
    return { as };
  };
  with(...queries) {
    const self = this;
    function select(fields) {
      return new SQLiteSelectBuilder({
        fields: fields ?? void 0,
        session: void 0,
        dialect: self.getDialect(),
        withList: queries
      });
    }
    function selectDistinct(fields) {
      return new SQLiteSelectBuilder({
        fields: fields ?? void 0,
        session: void 0,
        dialect: self.getDialect(),
        withList: queries,
        distinct: true
      });
    }
    return { select, selectDistinct };
  }
  select(fields) {
    return new SQLiteSelectBuilder({ fields: fields ?? void 0, session: void 0, dialect: this.getDialect() });
  }
  selectDistinct(fields) {
    return new SQLiteSelectBuilder({
      fields: fields ?? void 0,
      session: void 0,
      dialect: this.getDialect(),
      distinct: true
    });
  }
  // Lazy load dialect to avoid circular dependency
  getDialect() {
    if (!this.dialect) {
      this.dialect = new SQLiteSyncDialect(this.dialectConfig);
    }
    return this.dialect;
  }
};

// ../../node_modules/.pnpm/drizzle-orm@0.44.7_@electri_170ce7fb4153736f6f8b6fe6a8fee8b5/node_modules/drizzle-orm/sqlite-core/query-builders/insert.js
var SQLiteInsertBuilder = class {
  constructor(table, session, dialect, withList) {
    this.table = table;
    this.session = session;
    this.dialect = dialect;
    this.withList = withList;
  }
  static [entityKind] = "SQLiteInsertBuilder";
  values(values) {
    values = Array.isArray(values) ? values : [values];
    if (values.length === 0) {
      throw new Error("values() must be called with at least one value");
    }
    const mappedValues = values.map((entry) => {
      const result = {};
      const cols = this.table[Table.Symbol.Columns];
      for (const colKey of Object.keys(entry)) {
        const colValue = entry[colKey];
        result[colKey] = is(colValue, SQL) ? colValue : new Param(colValue, cols[colKey]);
      }
      return result;
    });
    return new SQLiteInsertBase(this.table, mappedValues, this.session, this.dialect, this.withList);
  }
  select(selectQuery) {
    const select = typeof selectQuery === "function" ? selectQuery(new QueryBuilder()) : selectQuery;
    if (!is(select, SQL) && !haveSameKeys(this.table[Columns], select._.selectedFields)) {
      throw new Error(
        "Insert select error: selected fields are not the same or are in a different order compared to the table definition"
      );
    }
    return new SQLiteInsertBase(this.table, select, this.session, this.dialect, this.withList, true);
  }
};
var SQLiteInsertBase = class extends QueryPromise {
  constructor(table, values, session, dialect, withList, select) {
    super();
    this.session = session;
    this.dialect = dialect;
    this.config = { table, values, withList, select };
  }
  static [entityKind] = "SQLiteInsert";
  /** @internal */
  config;
  returning(fields = this.config.table[SQLiteTable.Symbol.Columns]) {
    this.config.returning = orderSelectedFields(fields);
    return this;
  }
  /**
   * Adds an `on conflict do nothing` clause to the query.
   *
   * Calling this method simply avoids inserting a row as its alternative action.
   *
   * See docs: {@link https://orm.drizzle.team/docs/insert#on-conflict-do-nothing}
   *
   * @param config The `target` and `where` clauses.
   *
   * @example
   * ```ts
   * // Insert one row and cancel the insert if there's a conflict
   * await db.insert(cars)
   *   .values({ id: 1, brand: 'BMW' })
   *   .onConflictDoNothing();
   *
   * // Explicitly specify conflict target
   * await db.insert(cars)
   *   .values({ id: 1, brand: 'BMW' })
   *   .onConflictDoNothing({ target: cars.id });
   * ```
   */
  onConflictDoNothing(config2 = {}) {
    if (!this.config.onConflict) this.config.onConflict = [];
    if (config2.target === void 0) {
      this.config.onConflict.push(sql` on conflict do nothing`);
    } else {
      const targetSql = Array.isArray(config2.target) ? sql`${config2.target}` : sql`${[config2.target]}`;
      const whereSql = config2.where ? sql` where ${config2.where}` : sql``;
      this.config.onConflict.push(sql` on conflict ${targetSql} do nothing${whereSql}`);
    }
    return this;
  }
  /**
   * Adds an `on conflict do update` clause to the query.
   *
   * Calling this method will update the existing row that conflicts with the row proposed for insertion as its alternative action.
   *
   * See docs: {@link https://orm.drizzle.team/docs/insert#upserts-and-conflicts}
   *
   * @param config The `target`, `set` and `where` clauses.
   *
   * @example
   * ```ts
   * // Update the row if there's a conflict
   * await db.insert(cars)
   *   .values({ id: 1, brand: 'BMW' })
   *   .onConflictDoUpdate({
   *     target: cars.id,
   *     set: { brand: 'Porsche' }
   *   });
   *
   * // Upsert with 'where' clause
   * await db.insert(cars)
   *   .values({ id: 1, brand: 'BMW' })
   *   .onConflictDoUpdate({
   *     target: cars.id,
   *     set: { brand: 'newBMW' },
   *     where: sql`${cars.createdAt} > '2023-01-01'::date`,
   *   });
   * ```
   */
  onConflictDoUpdate(config2) {
    if (config2.where && (config2.targetWhere || config2.setWhere)) {
      throw new Error(
        'You cannot use both "where" and "targetWhere"/"setWhere" at the same time - "where" is deprecated, use "targetWhere" or "setWhere" instead.'
      );
    }
    if (!this.config.onConflict) this.config.onConflict = [];
    const whereSql = config2.where ? sql` where ${config2.where}` : void 0;
    const targetWhereSql = config2.targetWhere ? sql` where ${config2.targetWhere}` : void 0;
    const setWhereSql = config2.setWhere ? sql` where ${config2.setWhere}` : void 0;
    const targetSql = Array.isArray(config2.target) ? sql`${config2.target}` : sql`${[config2.target]}`;
    const setSql = this.dialect.buildUpdateSet(this.config.table, mapUpdateSet(this.config.table, config2.set));
    this.config.onConflict.push(
      sql` on conflict ${targetSql}${targetWhereSql} do update set ${setSql}${whereSql}${setWhereSql}`
    );
    return this;
  }
  /** @internal */
  getSQL() {
    return this.dialect.buildInsertQuery(this.config);
  }
  toSQL() {
    const { typings: _typings, ...rest } = this.dialect.sqlToQuery(this.getSQL());
    return rest;
  }
  /** @internal */
  _prepare(isOneTimeQuery = true) {
    return this.session[isOneTimeQuery ? "prepareOneTimeQuery" : "prepareQuery"](
      this.dialect.sqlToQuery(this.getSQL()),
      this.config.returning,
      this.config.returning ? "all" : "run",
      true,
      void 0,
      {
        type: "insert",
        tables: extractUsedTable(this.config.table)
      }
    );
  }
  prepare() {
    return this._prepare(false);
  }
  run = (placeholderValues) => {
    return this._prepare().run(placeholderValues);
  };
  all = (placeholderValues) => {
    return this._prepare().all(placeholderValues);
  };
  get = (placeholderValues) => {
    return this._prepare().get(placeholderValues);
  };
  values = (placeholderValues) => {
    return this._prepare().values(placeholderValues);
  };
  async execute() {
    return this.config.returning ? this.all() : this.run();
  }
  $dynamic() {
    return this;
  }
};

// ../../node_modules/.pnpm/drizzle-orm@0.44.7_@electri_170ce7fb4153736f6f8b6fe6a8fee8b5/node_modules/drizzle-orm/sqlite-core/query-builders/update.js
var SQLiteUpdateBuilder = class {
  constructor(table, session, dialect, withList) {
    this.table = table;
    this.session = session;
    this.dialect = dialect;
    this.withList = withList;
  }
  static [entityKind] = "SQLiteUpdateBuilder";
  set(values) {
    return new SQLiteUpdateBase(
      this.table,
      mapUpdateSet(this.table, values),
      this.session,
      this.dialect,
      this.withList
    );
  }
};
var SQLiteUpdateBase = class extends QueryPromise {
  constructor(table, set, session, dialect, withList) {
    super();
    this.session = session;
    this.dialect = dialect;
    this.config = { set, table, withList, joins: [] };
  }
  static [entityKind] = "SQLiteUpdate";
  /** @internal */
  config;
  from(source) {
    this.config.from = source;
    return this;
  }
  createJoin(joinType) {
    return (table, on) => {
      const tableName = getTableLikeName(table);
      if (typeof tableName === "string" && this.config.joins.some((join3) => join3.alias === tableName)) {
        throw new Error(`Alias "${tableName}" is already used in this query`);
      }
      if (typeof on === "function") {
        const from = this.config.from ? is(table, SQLiteTable) ? table[Table.Symbol.Columns] : is(table, Subquery) ? table._.selectedFields : is(table, SQLiteViewBase) ? table[ViewBaseConfig].selectedFields : void 0 : void 0;
        on = on(
          new Proxy(
            this.config.table[Table.Symbol.Columns],
            new SelectionProxyHandler({ sqlAliasedBehavior: "sql", sqlBehavior: "sql" })
          ),
          from && new Proxy(
            from,
            new SelectionProxyHandler({ sqlAliasedBehavior: "sql", sqlBehavior: "sql" })
          )
        );
      }
      this.config.joins.push({ on, table, joinType, alias: tableName });
      return this;
    };
  }
  leftJoin = this.createJoin("left");
  rightJoin = this.createJoin("right");
  innerJoin = this.createJoin("inner");
  fullJoin = this.createJoin("full");
  /**
   * Adds a 'where' clause to the query.
   *
   * Calling this method will update only those rows that fulfill a specified condition.
   *
   * See docs: {@link https://orm.drizzle.team/docs/update}
   *
   * @param where the 'where' clause.
   *
   * @example
   * You can use conditional operators and `sql function` to filter the rows to be updated.
   *
   * ```ts
   * // Update all cars with green color
   * db.update(cars).set({ color: 'red' })
   *   .where(eq(cars.color, 'green'));
   * // or
   * db.update(cars).set({ color: 'red' })
   *   .where(sql`${cars.color} = 'green'`)
   * ```
   *
   * You can logically combine conditional operators with `and()` and `or()` operators:
   *
   * ```ts
   * // Update all BMW cars with a green color
   * db.update(cars).set({ color: 'red' })
   *   .where(and(eq(cars.color, 'green'), eq(cars.brand, 'BMW')));
   *
   * // Update all cars with the green or blue color
   * db.update(cars).set({ color: 'red' })
   *   .where(or(eq(cars.color, 'green'), eq(cars.color, 'blue')));
   * ```
   */
  where(where) {
    this.config.where = where;
    return this;
  }
  orderBy(...columns) {
    if (typeof columns[0] === "function") {
      const orderBy = columns[0](
        new Proxy(
          this.config.table[Table.Symbol.Columns],
          new SelectionProxyHandler({ sqlAliasedBehavior: "alias", sqlBehavior: "sql" })
        )
      );
      const orderByArray = Array.isArray(orderBy) ? orderBy : [orderBy];
      this.config.orderBy = orderByArray;
    } else {
      const orderByArray = columns;
      this.config.orderBy = orderByArray;
    }
    return this;
  }
  limit(limit) {
    this.config.limit = limit;
    return this;
  }
  returning(fields = this.config.table[SQLiteTable.Symbol.Columns]) {
    this.config.returning = orderSelectedFields(fields);
    return this;
  }
  /** @internal */
  getSQL() {
    return this.dialect.buildUpdateQuery(this.config);
  }
  toSQL() {
    const { typings: _typings, ...rest } = this.dialect.sqlToQuery(this.getSQL());
    return rest;
  }
  /** @internal */
  _prepare(isOneTimeQuery = true) {
    return this.session[isOneTimeQuery ? "prepareOneTimeQuery" : "prepareQuery"](
      this.dialect.sqlToQuery(this.getSQL()),
      this.config.returning,
      this.config.returning ? "all" : "run",
      true,
      void 0,
      {
        type: "insert",
        tables: extractUsedTable(this.config.table)
      }
    );
  }
  prepare() {
    return this._prepare(false);
  }
  run = (placeholderValues) => {
    return this._prepare().run(placeholderValues);
  };
  all = (placeholderValues) => {
    return this._prepare().all(placeholderValues);
  };
  get = (placeholderValues) => {
    return this._prepare().get(placeholderValues);
  };
  values = (placeholderValues) => {
    return this._prepare().values(placeholderValues);
  };
  async execute() {
    return this.config.returning ? this.all() : this.run();
  }
  $dynamic() {
    return this;
  }
};

// ../../node_modules/.pnpm/drizzle-orm@0.44.7_@electri_170ce7fb4153736f6f8b6fe6a8fee8b5/node_modules/drizzle-orm/sqlite-core/query-builders/count.js
var SQLiteCountBuilder = class _SQLiteCountBuilder extends SQL {
  constructor(params) {
    super(_SQLiteCountBuilder.buildEmbeddedCount(params.source, params.filters).queryChunks);
    this.params = params;
    this.session = params.session;
    this.sql = _SQLiteCountBuilder.buildCount(
      params.source,
      params.filters
    );
  }
  sql;
  static [entityKind] = "SQLiteCountBuilderAsync";
  [Symbol.toStringTag] = "SQLiteCountBuilderAsync";
  session;
  static buildEmbeddedCount(source, filters) {
    return sql`(select count(*) from ${source}${sql.raw(" where ").if(filters)}${filters})`;
  }
  static buildCount(source, filters) {
    return sql`select count(*) from ${source}${sql.raw(" where ").if(filters)}${filters}`;
  }
  then(onfulfilled, onrejected) {
    return Promise.resolve(this.session.count(this.sql)).then(
      onfulfilled,
      onrejected
    );
  }
  catch(onRejected) {
    return this.then(void 0, onRejected);
  }
  finally(onFinally) {
    return this.then(
      (value) => {
        onFinally?.();
        return value;
      },
      (reason) => {
        onFinally?.();
        throw reason;
      }
    );
  }
};

// ../../node_modules/.pnpm/drizzle-orm@0.44.7_@electri_170ce7fb4153736f6f8b6fe6a8fee8b5/node_modules/drizzle-orm/sqlite-core/query-builders/query.js
var RelationalQueryBuilder = class {
  constructor(mode, fullSchema, schema, tableNamesMap, table, tableConfig, dialect, session) {
    this.mode = mode;
    this.fullSchema = fullSchema;
    this.schema = schema;
    this.tableNamesMap = tableNamesMap;
    this.table = table;
    this.tableConfig = tableConfig;
    this.dialect = dialect;
    this.session = session;
  }
  static [entityKind] = "SQLiteAsyncRelationalQueryBuilder";
  findMany(config2) {
    return this.mode === "sync" ? new SQLiteSyncRelationalQuery(
      this.fullSchema,
      this.schema,
      this.tableNamesMap,
      this.table,
      this.tableConfig,
      this.dialect,
      this.session,
      config2 ? config2 : {},
      "many"
    ) : new SQLiteRelationalQuery(
      this.fullSchema,
      this.schema,
      this.tableNamesMap,
      this.table,
      this.tableConfig,
      this.dialect,
      this.session,
      config2 ? config2 : {},
      "many"
    );
  }
  findFirst(config2) {
    return this.mode === "sync" ? new SQLiteSyncRelationalQuery(
      this.fullSchema,
      this.schema,
      this.tableNamesMap,
      this.table,
      this.tableConfig,
      this.dialect,
      this.session,
      config2 ? { ...config2, limit: 1 } : { limit: 1 },
      "first"
    ) : new SQLiteRelationalQuery(
      this.fullSchema,
      this.schema,
      this.tableNamesMap,
      this.table,
      this.tableConfig,
      this.dialect,
      this.session,
      config2 ? { ...config2, limit: 1 } : { limit: 1 },
      "first"
    );
  }
};
var SQLiteRelationalQuery = class extends QueryPromise {
  constructor(fullSchema, schema, tableNamesMap, table, tableConfig, dialect, session, config2, mode) {
    super();
    this.fullSchema = fullSchema;
    this.schema = schema;
    this.tableNamesMap = tableNamesMap;
    this.table = table;
    this.tableConfig = tableConfig;
    this.dialect = dialect;
    this.session = session;
    this.config = config2;
    this.mode = mode;
  }
  static [entityKind] = "SQLiteAsyncRelationalQuery";
  /** @internal */
  mode;
  /** @internal */
  getSQL() {
    return this.dialect.buildRelationalQuery({
      fullSchema: this.fullSchema,
      schema: this.schema,
      tableNamesMap: this.tableNamesMap,
      table: this.table,
      tableConfig: this.tableConfig,
      queryConfig: this.config,
      tableAlias: this.tableConfig.tsName
    }).sql;
  }
  /** @internal */
  _prepare(isOneTimeQuery = false) {
    const { query, builtQuery } = this._toSQL();
    return this.session[isOneTimeQuery ? "prepareOneTimeQuery" : "prepareQuery"](
      builtQuery,
      void 0,
      this.mode === "first" ? "get" : "all",
      true,
      (rawRows, mapColumnValue) => {
        const rows = rawRows.map(
          (row) => mapRelationalRow(this.schema, this.tableConfig, row, query.selection, mapColumnValue)
        );
        if (this.mode === "first") {
          return rows[0];
        }
        return rows;
      }
    );
  }
  prepare() {
    return this._prepare(false);
  }
  _toSQL() {
    const query = this.dialect.buildRelationalQuery({
      fullSchema: this.fullSchema,
      schema: this.schema,
      tableNamesMap: this.tableNamesMap,
      table: this.table,
      tableConfig: this.tableConfig,
      queryConfig: this.config,
      tableAlias: this.tableConfig.tsName
    });
    const builtQuery = this.dialect.sqlToQuery(query.sql);
    return { query, builtQuery };
  }
  toSQL() {
    return this._toSQL().builtQuery;
  }
  /** @internal */
  executeRaw() {
    if (this.mode === "first") {
      return this._prepare(false).get();
    }
    return this._prepare(false).all();
  }
  async execute() {
    return this.executeRaw();
  }
};
var SQLiteSyncRelationalQuery = class extends SQLiteRelationalQuery {
  static [entityKind] = "SQLiteSyncRelationalQuery";
  sync() {
    return this.executeRaw();
  }
};

// ../../node_modules/.pnpm/drizzle-orm@0.44.7_@electri_170ce7fb4153736f6f8b6fe6a8fee8b5/node_modules/drizzle-orm/sqlite-core/query-builders/raw.js
var SQLiteRaw = class extends QueryPromise {
  constructor(execute, getSQL, action, dialect, mapBatchResult) {
    super();
    this.execute = execute;
    this.getSQL = getSQL;
    this.dialect = dialect;
    this.mapBatchResult = mapBatchResult;
    this.config = { action };
  }
  static [entityKind] = "SQLiteRaw";
  /** @internal */
  config;
  getQuery() {
    return { ...this.dialect.sqlToQuery(this.getSQL()), method: this.config.action };
  }
  mapResult(result, isFromBatch) {
    return isFromBatch ? this.mapBatchResult(result) : result;
  }
  _prepare() {
    return this;
  }
  /** @internal */
  isResponseInArrayMode() {
    return false;
  }
};

// ../../node_modules/.pnpm/drizzle-orm@0.44.7_@electri_170ce7fb4153736f6f8b6fe6a8fee8b5/node_modules/drizzle-orm/sqlite-core/db.js
var BaseSQLiteDatabase = class {
  constructor(resultKind, dialect, session, schema) {
    this.resultKind = resultKind;
    this.dialect = dialect;
    this.session = session;
    this._ = schema ? {
      schema: schema.schema,
      fullSchema: schema.fullSchema,
      tableNamesMap: schema.tableNamesMap
    } : {
      schema: void 0,
      fullSchema: {},
      tableNamesMap: {}
    };
    this.query = {};
    const query = this.query;
    if (this._.schema) {
      for (const [tableName, columns] of Object.entries(this._.schema)) {
        query[tableName] = new RelationalQueryBuilder(
          resultKind,
          schema.fullSchema,
          this._.schema,
          this._.tableNamesMap,
          schema.fullSchema[tableName],
          columns,
          dialect,
          session
        );
      }
    }
    this.$cache = { invalidate: async (_params) => {
    } };
  }
  static [entityKind] = "BaseSQLiteDatabase";
  query;
  /**
   * Creates a subquery that defines a temporary named result set as a CTE.
   *
   * It is useful for breaking down complex queries into simpler parts and for reusing the result set in subsequent parts of the query.
   *
   * See docs: {@link https://orm.drizzle.team/docs/select#with-clause}
   *
   * @param alias The alias for the subquery.
   *
   * Failure to provide an alias will result in a DrizzleTypeError, preventing the subquery from being referenced in other queries.
   *
   * @example
   *
   * ```ts
   * // Create a subquery with alias 'sq' and use it in the select query
   * const sq = db.$with('sq').as(db.select().from(users).where(eq(users.id, 42)));
   *
   * const result = await db.with(sq).select().from(sq);
   * ```
   *
   * To select arbitrary SQL values as fields in a CTE and reference them in other CTEs or in the main query, you need to add aliases to them:
   *
   * ```ts
   * // Select an arbitrary SQL value as a field in a CTE and reference it in the main query
   * const sq = db.$with('sq').as(db.select({
   *   name: sql<string>`upper(${users.name})`.as('name'),
   * })
   * .from(users));
   *
   * const result = await db.with(sq).select({ name: sq.name }).from(sq);
   * ```
   */
  $with = (alias, selection) => {
    const self = this;
    const as = (qb) => {
      if (typeof qb === "function") {
        qb = qb(new QueryBuilder(self.dialect));
      }
      return new Proxy(
        new WithSubquery(
          qb.getSQL(),
          selection ?? ("getSelectedFields" in qb ? qb.getSelectedFields() ?? {} : {}),
          alias,
          true
        ),
        new SelectionProxyHandler({ alias, sqlAliasedBehavior: "alias", sqlBehavior: "error" })
      );
    };
    return { as };
  };
  $count(source, filters) {
    return new SQLiteCountBuilder({ source, filters, session: this.session });
  }
  /**
   * Incorporates a previously defined CTE (using `$with`) into the main query.
   *
   * This method allows the main query to reference a temporary named result set.
   *
   * See docs: {@link https://orm.drizzle.team/docs/select#with-clause}
   *
   * @param queries The CTEs to incorporate into the main query.
   *
   * @example
   *
   * ```ts
   * // Define a subquery 'sq' as a CTE using $with
   * const sq = db.$with('sq').as(db.select().from(users).where(eq(users.id, 42)));
   *
   * // Incorporate the CTE 'sq' into the main query and select from it
   * const result = await db.with(sq).select().from(sq);
   * ```
   */
  with(...queries) {
    const self = this;
    function select(fields) {
      return new SQLiteSelectBuilder({
        fields: fields ?? void 0,
        session: self.session,
        dialect: self.dialect,
        withList: queries
      });
    }
    function selectDistinct(fields) {
      return new SQLiteSelectBuilder({
        fields: fields ?? void 0,
        session: self.session,
        dialect: self.dialect,
        withList: queries,
        distinct: true
      });
    }
    function update(table) {
      return new SQLiteUpdateBuilder(table, self.session, self.dialect, queries);
    }
    function insert(into) {
      return new SQLiteInsertBuilder(into, self.session, self.dialect, queries);
    }
    function delete_(from) {
      return new SQLiteDeleteBase(from, self.session, self.dialect, queries);
    }
    return { select, selectDistinct, update, insert, delete: delete_ };
  }
  select(fields) {
    return new SQLiteSelectBuilder({ fields: fields ?? void 0, session: this.session, dialect: this.dialect });
  }
  selectDistinct(fields) {
    return new SQLiteSelectBuilder({
      fields: fields ?? void 0,
      session: this.session,
      dialect: this.dialect,
      distinct: true
    });
  }
  /**
   * Creates an update query.
   *
   * Calling this method without `.where()` clause will update all rows in a table. The `.where()` clause specifies which rows should be updated.
   *
   * Use `.set()` method to specify which values to update.
   *
   * See docs: {@link https://orm.drizzle.team/docs/update}
   *
   * @param table The table to update.
   *
   * @example
   *
   * ```ts
   * // Update all rows in the 'cars' table
   * await db.update(cars).set({ color: 'red' });
   *
   * // Update rows with filters and conditions
   * await db.update(cars).set({ color: 'red' }).where(eq(cars.brand, 'BMW'));
   *
   * // Update with returning clause
   * const updatedCar: Car[] = await db.update(cars)
   *   .set({ color: 'red' })
   *   .where(eq(cars.id, 1))
   *   .returning();
   * ```
   */
  update(table) {
    return new SQLiteUpdateBuilder(table, this.session, this.dialect);
  }
  $cache;
  /**
   * Creates an insert query.
   *
   * Calling this method will create new rows in a table. Use `.values()` method to specify which values to insert.
   *
   * See docs: {@link https://orm.drizzle.team/docs/insert}
   *
   * @param table The table to insert into.
   *
   * @example
   *
   * ```ts
   * // Insert one row
   * await db.insert(cars).values({ brand: 'BMW' });
   *
   * // Insert multiple rows
   * await db.insert(cars).values([{ brand: 'BMW' }, { brand: 'Porsche' }]);
   *
   * // Insert with returning clause
   * const insertedCar: Car[] = await db.insert(cars)
   *   .values({ brand: 'BMW' })
   *   .returning();
   * ```
   */
  insert(into) {
    return new SQLiteInsertBuilder(into, this.session, this.dialect);
  }
  /**
   * Creates a delete query.
   *
   * Calling this method without `.where()` clause will delete all rows in a table. The `.where()` clause specifies which rows should be deleted.
   *
   * See docs: {@link https://orm.drizzle.team/docs/delete}
   *
   * @param table The table to delete from.
   *
   * @example
   *
   * ```ts
   * // Delete all rows in the 'cars' table
   * await db.delete(cars);
   *
   * // Delete rows with filters and conditions
   * await db.delete(cars).where(eq(cars.color, 'green'));
   *
   * // Delete with returning clause
   * const deletedCar: Car[] = await db.delete(cars)
   *   .where(eq(cars.id, 1))
   *   .returning();
   * ```
   */
  delete(from) {
    return new SQLiteDeleteBase(from, this.session, this.dialect);
  }
  run(query) {
    const sequel = typeof query === "string" ? sql.raw(query) : query.getSQL();
    if (this.resultKind === "async") {
      return new SQLiteRaw(
        async () => this.session.run(sequel),
        () => sequel,
        "run",
        this.dialect,
        this.session.extractRawRunValueFromBatchResult.bind(this.session)
      );
    }
    return this.session.run(sequel);
  }
  all(query) {
    const sequel = typeof query === "string" ? sql.raw(query) : query.getSQL();
    if (this.resultKind === "async") {
      return new SQLiteRaw(
        async () => this.session.all(sequel),
        () => sequel,
        "all",
        this.dialect,
        this.session.extractRawAllValueFromBatchResult.bind(this.session)
      );
    }
    return this.session.all(sequel);
  }
  get(query) {
    const sequel = typeof query === "string" ? sql.raw(query) : query.getSQL();
    if (this.resultKind === "async") {
      return new SQLiteRaw(
        async () => this.session.get(sequel),
        () => sequel,
        "get",
        this.dialect,
        this.session.extractRawGetValueFromBatchResult.bind(this.session)
      );
    }
    return this.session.get(sequel);
  }
  values(query) {
    const sequel = typeof query === "string" ? sql.raw(query) : query.getSQL();
    if (this.resultKind === "async") {
      return new SQLiteRaw(
        async () => this.session.values(sequel),
        () => sequel,
        "values",
        this.dialect,
        this.session.extractRawValuesValueFromBatchResult.bind(this.session)
      );
    }
    return this.session.values(sequel);
  }
  transaction(transaction, config2) {
    return this.session.transaction(transaction, config2);
  }
};

// ../../node_modules/.pnpm/drizzle-orm@0.44.7_@electri_170ce7fb4153736f6f8b6fe6a8fee8b5/node_modules/drizzle-orm/cache/core/cache.js
var Cache = class {
  static [entityKind] = "Cache";
};
var NoopCache = class extends Cache {
  strategy() {
    return "all";
  }
  static [entityKind] = "NoopCache";
  async get(_key) {
    return void 0;
  }
  async put(_hashedQuery, _response, _tables, _config) {
  }
  async onMutate(_params) {
  }
};
async function hashQuery(sql2, params) {
  const dataToHash = `${sql2}-${JSON.stringify(params)}`;
  const encoder = new TextEncoder();
  const data = encoder.encode(dataToHash);
  const hashBuffer = await crypto.subtle.digest("SHA-256", data);
  const hashArray = [...new Uint8Array(hashBuffer)];
  const hashHex = hashArray.map((b) => b.toString(16).padStart(2, "0")).join("");
  return hashHex;
}

// ../../node_modules/.pnpm/drizzle-orm@0.44.7_@electri_170ce7fb4153736f6f8b6fe6a8fee8b5/node_modules/drizzle-orm/sqlite-core/session.js
var ExecuteResultSync = class extends QueryPromise {
  constructor(resultCb) {
    super();
    this.resultCb = resultCb;
  }
  static [entityKind] = "ExecuteResultSync";
  async execute() {
    return this.resultCb();
  }
  sync() {
    return this.resultCb();
  }
};
var SQLitePreparedQuery = class {
  constructor(mode, executeMethod, query, cache, queryMetadata, cacheConfig) {
    this.mode = mode;
    this.executeMethod = executeMethod;
    this.query = query;
    this.cache = cache;
    this.queryMetadata = queryMetadata;
    this.cacheConfig = cacheConfig;
    if (cache && cache.strategy() === "all" && cacheConfig === void 0) {
      this.cacheConfig = { enable: true, autoInvalidate: true };
    }
    if (!this.cacheConfig?.enable) {
      this.cacheConfig = void 0;
    }
  }
  static [entityKind] = "PreparedQuery";
  /** @internal */
  joinsNotNullableMap;
  /** @internal */
  async queryWithCache(queryString, params, query) {
    if (this.cache === void 0 || is(this.cache, NoopCache) || this.queryMetadata === void 0) {
      try {
        return await query();
      } catch (e) {
        throw new DrizzleQueryError(queryString, params, e);
      }
    }
    if (this.cacheConfig && !this.cacheConfig.enable) {
      try {
        return await query();
      } catch (e) {
        throw new DrizzleQueryError(queryString, params, e);
      }
    }
    if ((this.queryMetadata.type === "insert" || this.queryMetadata.type === "update" || this.queryMetadata.type === "delete") && this.queryMetadata.tables.length > 0) {
      try {
        const [res] = await Promise.all([
          query(),
          this.cache.onMutate({ tables: this.queryMetadata.tables })
        ]);
        return res;
      } catch (e) {
        throw new DrizzleQueryError(queryString, params, e);
      }
    }
    if (!this.cacheConfig) {
      try {
        return await query();
      } catch (e) {
        throw new DrizzleQueryError(queryString, params, e);
      }
    }
    if (this.queryMetadata.type === "select") {
      const fromCache = await this.cache.get(
        this.cacheConfig.tag ?? await hashQuery(queryString, params),
        this.queryMetadata.tables,
        this.cacheConfig.tag !== void 0,
        this.cacheConfig.autoInvalidate
      );
      if (fromCache === void 0) {
        let result;
        try {
          result = await query();
        } catch (e) {
          throw new DrizzleQueryError(queryString, params, e);
        }
        await this.cache.put(
          this.cacheConfig.tag ?? await hashQuery(queryString, params),
          result,
          // make sure we send tables that were used in a query only if user wants to invalidate it on each write
          this.cacheConfig.autoInvalidate ? this.queryMetadata.tables : [],
          this.cacheConfig.tag !== void 0,
          this.cacheConfig.config
        );
        return result;
      }
      return fromCache;
    }
    try {
      return await query();
    } catch (e) {
      throw new DrizzleQueryError(queryString, params, e);
    }
  }
  getQuery() {
    return this.query;
  }
  mapRunResult(result, _isFromBatch) {
    return result;
  }
  mapAllResult(_result, _isFromBatch) {
    throw new Error("Not implemented");
  }
  mapGetResult(_result, _isFromBatch) {
    throw new Error("Not implemented");
  }
  execute(placeholderValues) {
    if (this.mode === "async") {
      return this[this.executeMethod](placeholderValues);
    }
    return new ExecuteResultSync(() => this[this.executeMethod](placeholderValues));
  }
  mapResult(response, isFromBatch) {
    switch (this.executeMethod) {
      case "run": {
        return this.mapRunResult(response, isFromBatch);
      }
      case "all": {
        return this.mapAllResult(response, isFromBatch);
      }
      case "get": {
        return this.mapGetResult(response, isFromBatch);
      }
    }
  }
};
var SQLiteSession = class {
  constructor(dialect) {
    this.dialect = dialect;
  }
  static [entityKind] = "SQLiteSession";
  prepareOneTimeQuery(query, fields, executeMethod, isResponseInArrayMode, customResultMapper, queryMetadata, cacheConfig) {
    return this.prepareQuery(
      query,
      fields,
      executeMethod,
      isResponseInArrayMode,
      customResultMapper,
      queryMetadata,
      cacheConfig
    );
  }
  run(query) {
    const staticQuery = this.dialect.sqlToQuery(query);
    try {
      return this.prepareOneTimeQuery(staticQuery, void 0, "run", false).run();
    } catch (err) {
      throw new DrizzleError({ cause: err, message: `Failed to run the query '${staticQuery.sql}'` });
    }
  }
  /** @internal */
  extractRawRunValueFromBatchResult(result) {
    return result;
  }
  all(query) {
    return this.prepareOneTimeQuery(this.dialect.sqlToQuery(query), void 0, "run", false).all();
  }
  /** @internal */
  extractRawAllValueFromBatchResult(_result) {
    throw new Error("Not implemented");
  }
  get(query) {
    return this.prepareOneTimeQuery(this.dialect.sqlToQuery(query), void 0, "run", false).get();
  }
  /** @internal */
  extractRawGetValueFromBatchResult(_result) {
    throw new Error("Not implemented");
  }
  values(query) {
    return this.prepareOneTimeQuery(this.dialect.sqlToQuery(query), void 0, "run", false).values();
  }
  async count(sql2) {
    const result = await this.values(sql2);
    return result[0][0];
  }
  /** @internal */
  extractRawValuesValueFromBatchResult(_result) {
    throw new Error("Not implemented");
  }
};
var SQLiteTransaction = class extends BaseSQLiteDatabase {
  constructor(resultType, dialect, session, schema, nestedIndex = 0) {
    super(resultType, dialect, session, schema);
    this.schema = schema;
    this.nestedIndex = nestedIndex;
  }
  static [entityKind] = "SQLiteTransaction";
  rollback() {
    throw new TransactionRollbackError();
  }
};

// ../../node_modules/.pnpm/drizzle-orm@0.44.7_@electri_170ce7fb4153736f6f8b6fe6a8fee8b5/node_modules/drizzle-orm/better-sqlite3/session.js
var BetterSQLiteSession = class extends SQLiteSession {
  constructor(client, dialect, schema, options = {}) {
    super(dialect);
    this.client = client;
    this.schema = schema;
    this.logger = options.logger ?? new NoopLogger();
    this.cache = options.cache ?? new NoopCache();
  }
  static [entityKind] = "BetterSQLiteSession";
  logger;
  cache;
  prepareQuery(query, fields, executeMethod, isResponseInArrayMode, customResultMapper, queryMetadata, cacheConfig) {
    const stmt = this.client.prepare(query.sql);
    return new PreparedQuery(
      stmt,
      query,
      this.logger,
      this.cache,
      queryMetadata,
      cacheConfig,
      fields,
      executeMethod,
      isResponseInArrayMode,
      customResultMapper
    );
  }
  transaction(transaction, config2 = {}) {
    const tx = new BetterSQLiteTransaction("sync", this.dialect, this, this.schema);
    const nativeTx = this.client.transaction(transaction);
    return nativeTx[config2.behavior ?? "deferred"](tx);
  }
};
var BetterSQLiteTransaction = class _BetterSQLiteTransaction extends SQLiteTransaction {
  static [entityKind] = "BetterSQLiteTransaction";
  transaction(transaction) {
    const savepointName = `sp${this.nestedIndex}`;
    const tx = new _BetterSQLiteTransaction("sync", this.dialect, this.session, this.schema, this.nestedIndex + 1);
    this.session.run(sql.raw(`savepoint ${savepointName}`));
    try {
      const result = transaction(tx);
      this.session.run(sql.raw(`release savepoint ${savepointName}`));
      return result;
    } catch (err) {
      this.session.run(sql.raw(`rollback to savepoint ${savepointName}`));
      throw err;
    }
  }
};
var PreparedQuery = class extends SQLitePreparedQuery {
  constructor(stmt, query, logger, cache, queryMetadata, cacheConfig, fields, executeMethod, _isResponseInArrayMode, customResultMapper) {
    super("sync", executeMethod, query, cache, queryMetadata, cacheConfig);
    this.stmt = stmt;
    this.logger = logger;
    this.fields = fields;
    this._isResponseInArrayMode = _isResponseInArrayMode;
    this.customResultMapper = customResultMapper;
  }
  static [entityKind] = "BetterSQLitePreparedQuery";
  run(placeholderValues) {
    const params = fillPlaceholders(this.query.params, placeholderValues ?? {});
    this.logger.logQuery(this.query.sql, params);
    return this.stmt.run(...params);
  }
  all(placeholderValues) {
    const { fields, joinsNotNullableMap, query, logger, stmt, customResultMapper } = this;
    if (!fields && !customResultMapper) {
      const params = fillPlaceholders(query.params, placeholderValues ?? {});
      logger.logQuery(query.sql, params);
      return stmt.all(...params);
    }
    const rows = this.values(placeholderValues);
    if (customResultMapper) {
      return customResultMapper(rows);
    }
    return rows.map((row) => mapResultRow(fields, row, joinsNotNullableMap));
  }
  get(placeholderValues) {
    const params = fillPlaceholders(this.query.params, placeholderValues ?? {});
    this.logger.logQuery(this.query.sql, params);
    const { fields, stmt, joinsNotNullableMap, customResultMapper } = this;
    if (!fields && !customResultMapper) {
      return stmt.get(...params);
    }
    const row = stmt.raw().get(...params);
    if (!row) {
      return void 0;
    }
    if (customResultMapper) {
      return customResultMapper([row]);
    }
    return mapResultRow(fields, row, joinsNotNullableMap);
  }
  values(placeholderValues) {
    const params = fillPlaceholders(this.query.params, placeholderValues ?? {});
    this.logger.logQuery(this.query.sql, params);
    return this.stmt.raw().all(...params);
  }
  /** @internal */
  isResponseInArrayMode() {
    return this._isResponseInArrayMode;
  }
};

// ../../node_modules/.pnpm/drizzle-orm@0.44.7_@electri_170ce7fb4153736f6f8b6fe6a8fee8b5/node_modules/drizzle-orm/better-sqlite3/driver.js
var BetterSQLite3Database = class extends BaseSQLiteDatabase {
  static [entityKind] = "BetterSQLite3Database";
};
function construct(client, config2 = {}) {
  const dialect = new SQLiteSyncDialect({ casing: config2.casing });
  let logger;
  if (config2.logger === true) {
    logger = new DefaultLogger();
  } else if (config2.logger !== false) {
    logger = config2.logger;
  }
  let schema;
  if (config2.schema) {
    const tablesConfig = extractTablesRelationalConfig(
      config2.schema,
      createTableRelationsHelpers
    );
    schema = {
      fullSchema: config2.schema,
      schema: tablesConfig.tables,
      tableNamesMap: tablesConfig.tableNamesMap
    };
  }
  const session = new BetterSQLiteSession(client, dialect, schema, { logger });
  const db2 = new BetterSQLite3Database("sync", dialect, session, schema);
  db2.$client = client;
  return db2;
}
function drizzle(...params) {
  if (params[0] === void 0 || typeof params[0] === "string") {
    const instance = params[0] === void 0 ? new Client() : new Client(params[0]);
    return construct(instance, params[1]);
  }
  if (isConfig(params[0])) {
    const { connection, client, ...drizzleConfig } = params[0];
    if (client) return construct(client, drizzleConfig);
    if (typeof connection === "object") {
      const { source, ...options } = connection;
      const instance2 = new Client(source, options);
      return construct(instance2, drizzleConfig);
    }
    const instance = new Client(connection);
    return construct(instance, drizzleConfig);
  }
  return construct(params[0], params[1]);
}
((drizzle2) => {
  function mock(config2) {
    return construct({}, config2);
  }
  drizzle2.mock = mock;
})(drizzle || (drizzle = {}));

// ../../node_modules/.pnpm/drizzle-orm@0.44.7_@electri_170ce7fb4153736f6f8b6fe6a8fee8b5/node_modules/drizzle-orm/migrator.js
import crypto3 from "node:crypto";
import fs from "node:fs";
function readMigrationFiles(config2) {
  const migrationFolderTo = config2.migrationsFolder;
  const migrationQueries = [];
  const journalPath = `${migrationFolderTo}/meta/_journal.json`;
  if (!fs.existsSync(journalPath)) {
    throw new Error(`Can't find meta/_journal.json file`);
  }
  const journalAsString = fs.readFileSync(`${migrationFolderTo}/meta/_journal.json`).toString();
  const journal = JSON.parse(journalAsString);
  for (const journalEntry of journal.entries) {
    const migrationPath = `${migrationFolderTo}/${journalEntry.tag}.sql`;
    try {
      const query = fs.readFileSync(`${migrationFolderTo}/${journalEntry.tag}.sql`).toString();
      const result = query.split("--> statement-breakpoint").map((it) => {
        return it;
      });
      migrationQueries.push({
        sql: result,
        bps: journalEntry.breakpoints,
        folderMillis: journalEntry.when,
        hash: crypto3.createHash("sha256").update(query).digest("hex")
      });
    } catch {
      throw new Error(`No file ${migrationPath} found in ${migrationFolderTo} folder`);
    }
  }
  return migrationQueries;
}

// ../../node_modules/.pnpm/drizzle-orm@0.44.7_@electri_170ce7fb4153736f6f8b6fe6a8fee8b5/node_modules/drizzle-orm/better-sqlite3/migrator.js
function migrate(db2, config2) {
  const migrations = readMigrationFiles(config2);
  db2.dialect.migrate(migrations, db2.session, config2);
}

// ../../packages/db-local/dist/index.js
var dist_exports = {};
__export(dist_exports, {
  LEDGER_PROTECTION_SQL: () => LEDGER_PROTECTION_SQL,
  auditLog: () => auditLog,
  branches: () => branches,
  cashMovements: () => cashMovements,
  customerAliases: () => customerAliases,
  customers: () => customers,
  devices: () => devices,
  dynamicPricingRules: () => dynamicPricingRules,
  gamePlayEvents: () => gamePlayEvents,
  games: () => games,
  orderItems: () => orderItems,
  orders: () => orders,
  pairingCodes: () => pairingCodes,
  pcs: () => pcs,
  pointsLedger: () => pointsLedger,
  pricingRateCards: () => pricingRateCards,
  products: () => products,
  sessionSegments: () => sessionSegments,
  sessions: () => sessions,
  settings: () => settings,
  shifts: () => shifts,
  staff: () => staff,
  stationPasses: () => stationPasses,
  syncApplied: () => syncApplied,
  syncCursors: () => syncCursors,
  syncOutbox: () => syncOutbox,
  tabs: () => tabs,
  walletLedger: () => walletLedger,
  zones: () => zones
});

// ../../packages/db-local/dist/schema.js
var branches = sqliteTable("branches", {
  id: text("id").primaryKey(),
  name: text("name").notNull(),
  address: text("address"),
  timezone: text("timezone").notNull().default("Asia/Tehran"),
  status: text("status", { enum: ["active", "inactive"] }).notNull().default("active"),
  createdAt: integer("created_at").notNull(),
  updatedAt: integer("updated_at").notNull()
});
var staff = sqliteTable("staff", {
  id: text("id").primaryKey(),
  branchId: text("branch_id").notNull().references(() => branches.id),
  name: text("name").notNull(),
  phone: text("phone"),
  username: text("username").notNull(),
  passwordHash: text("password_hash").notNull(),
  // Argon2id
  role: text("role", { enum: ["owner", "manager", "operator"] }).notNull(),
  active: integer("active", { mode: "boolean" }).notNull().default(true),
  createdAt: integer("created_at").notNull(),
  updatedAt: integer("updated_at").notNull()
}, (t) => [uniqueIndex("staff_username_uq").on(t.username)]);
var zones = sqliteTable("zones", {
  id: text("id").primaryKey(),
  branchId: text("branch_id").notNull().references(() => branches.id),
  name: text("name").notNull(),
  sort: integer("sort").notNull().default(0)
});
var pcs = sqliteTable("pcs", {
  id: text("id").primaryKey(),
  branchId: text("branch_id").notNull().references(() => branches.id),
  zoneId: text("zone_id").notNull().references(() => zones.id),
  name: text("name").notNull(),
  // "PC-07"
  /** Station kind — consoles (PS5…) are admin-driven: no launcher, no pairing. */
  kind: text("kind", { enum: ["pc", "console"] }).notNull().default("pc"),
  /** Console add-on: Toman/hour per EXTRA controller beyond the first. */
  extraControllerRate: integer("extra_controller_rate"),
  mac: text("mac"),
  staticIp: text("static_ip"),
  deviceId: text("device_id"),
  status: text("status", {
    enum: ["idle", "in_session", "locked", "offline", "maintenance"]
  }).notNull().default("offline"),
  specs: text("specs", { mode: "json" }).$type(),
  enabled: integer("enabled", { mode: "boolean" }).notNull().default(true),
  createdAt: integer("created_at").notNull(),
  updatedAt: integer("updated_at").notNull()
}, (t) => [index("pcs_zone_idx").on(t.zoneId)]);
var devices = sqliteTable("devices", {
  id: text("id").primaryKey(),
  branchId: text("branch_id").notNull().references(() => branches.id),
  type: text("type", { enum: ["client", "admin_station", "watchdog"] }).notNull(),
  tokenHash: text("token_hash").notNull(),
  // sha256 of 256-bit device token
  pcId: text("pc_id").references(() => pcs.id),
  pairedAt: integer("paired_at").notNull(),
  revokedAt: integer("revoked_at"),
  lastSeen: integer("last_seen")
});
var pairingCodes = sqliteTable("pairing_codes", {
  code: text("code").primaryKey(),
  // 6-digit
  branchId: text("branch_id").notNull(),
  deviceType: text("device_type", { enum: ["client", "admin_station", "watchdog"] }).notNull(),
  /** The seat this code pairs; the resulting device is bound to it. */
  pcId: text("pc_id"),
  createdBy: text("created_by").notNull(),
  expiresAt: integer("expires_at").notNull(),
  usedAt: integer("used_at")
});
var customers = sqliteTable("customers", {
  id: text("id").primaryKey(),
  phone: text("phone").notNull(),
  // normalized 989xxxxxxxxx
  name: text("name").notNull(),
  /** Discount tier — null = no tier assigned, quotes at the zone base rate. */
  tier: text("tier", { enum: ["bronze", "silver", "gold"] }),
  /** کد ملی — optional, unique when present (NULLs are distinct in SQLite). */
  nationalId: text("national_id"),
  /** Scanned national-card image filename under data/cards (PII — authed GET only). */
  nationalCardFile: text("national_card_file"),
  /**
   * Argon2id hash for launcher self-login (phone+password at the seat).
   * Null = member has not set a password yet. Synced through customer.*
   * events so login verifies fully offline at every branch.
   */
  passwordHash: text("password_hash"),
  birthDate: text("birth_date"),
  // ISO date, optional
  createdBranchId: text("created_branch_id").notNull(),
  status: text("status", { enum: ["active", "blocked", "negative_balance"] }).notNull().default("active"),
  /** True until the cloud confirms/dedupes this locally-created customer. */
  provisional: integer("provisional", { mode: "boolean" }).notNull().default(false),
  createdAt: integer("created_at").notNull(),
  updatedAt: integer("updated_at").notNull()
}, (t) => [
  uniqueIndex("customers_phone_uq").on(t.phone),
  uniqueIndex("customers_national_id_uq").on(t.nationalId)
]);
var customerAliases = sqliteTable("customer_aliases", {
  provisionalId: text("provisional_id").primaryKey(),
  canonicalId: text("canonical_id").notNull(),
  createdAt: integer("created_at").notNull()
});
var games = sqliteTable("games", {
  id: text("id").primaryKey(),
  branchId: text("branch_id").notNull().references(() => branches.id),
  title: text("title").notNull(),
  /** Launcher shelf: games live on the بازی‌ها tab, apps (Steam, Discord…) on برنامه‌ها. */
  kind: text("kind", { enum: ["game", "app"] }).notNull().default("game"),
  launchType: text("launch_type", { enum: ["exe", "steam_uri", "shortcut"] }).notNull(),
  exePath: text("exe_path"),
  launchUri: text("launch_uri"),
  // steam://run/<appid>
  args: text("args"),
  processNames: text("process_names", { mode: "json" }).$type().notNull(),
  coverUrl: text("cover_url"),
  category: text("category"),
  /** Minimum age (years) from the member's birthDate — null = no restriction. */
  minAge: integer("min_age"),
  enabled: integer("enabled", { mode: "boolean" }).notNull().default(true),
  sort: integer("sort").notNull().default(0)
});
var gamePlayEvents = sqliteTable("game_play_events", {
  id: text("id").primaryKey(),
  branchId: text("branch_id").notNull(),
  sessionId: text("session_id").notNull(),
  customerId: text("customer_id"),
  gameId: text("game_id").notNull(),
  pcId: text("pc_id").notNull(),
  processName: text("process_name").notNull(),
  startedAt: integer("started_at").notNull(),
  endedAt: integer("ended_at"),
  seconds: integer("seconds")
}, (t) => [
  index("gpe_session_idx").on(t.sessionId),
  index("gpe_customer_idx").on(t.customerId),
  index("gpe_game_idx").on(t.gameId)
]);
var sessions = sqliteTable("sessions", {
  id: text("id").primaryKey(),
  branchId: text("branch_id").notNull(),
  customerId: text("customer_id"),
  // nullable: walk-in guest
  mode: text("mode", { enum: ["prepaid", "open"] }).notNull(),
  status: text("status", { enum: ["active", "paused", "finished", "cancelled"] }).notNull(),
  startedAt: integer("started_at").notNull(),
  endedAt: integer("ended_at"),
  prepaidMinutes: integer("prepaid_minutes"),
  totalCost: integer("total_cost").notNull().default(0),
  // Toman; = SUM(segments.cost)
  /** Extra controllers beyond the first (consoles) — surcharge baked into segment rates. */
  extraControllers: integer("extra_controllers").notNull().default(0),
  /** Prepaid ran out but the session kept accruing (console/guest) — alarm shown, not auto-stopped. */
  expiredAt: integer("expired_at"),
  /** Null for self-service sessions (member logged in at the seat). */
  openedByStaff: text("opened_by_staff"),
  /** staff = counter; member = phone+password at the seat; qr = mobile-app QR at the seat. */
  openedVia: text("opened_via", { enum: ["staff", "member", "qr"] }).notNull().default("staff"),
  notes: text("notes")
}, (t) => [
  index("sessions_status_idx").on(t.status),
  index("sessions_customer_idx").on(t.customerId)
]);
var sessionSegments = sqliteTable("session_segments", {
  id: text("id").primaryKey(),
  sessionId: text("session_id").notNull().references(() => sessions.id),
  pcId: text("pc_id").notNull(),
  zoneId: text("zone_id").notNull(),
  ratePerHour: integer("rate_per_hour").notNull(),
  // Toman snapshot
  appliedRuleIds: text("applied_rule_ids", { mode: "json" }).$type().notNull(),
  startedAt: integer("started_at").notNull(),
  endedAt: integer("ended_at"),
  cost: integer("cost").notNull().default(0)
  // Toman
}, (t) => [index("segments_session_idx").on(t.sessionId)]);
var walletLedger = sqliteTable("wallet_ledger", {
  id: text("id").primaryKey(),
  customerId: text("customer_id").notNull(),
  branchId: text("branch_id"),
  type: text("type", {
    enum: [
      "topup_cash",
      "topup_card",
      "topup_online",
      "session_charge",
      "order_charge",
      "refund",
      "adjustment",
      "points_redemption",
      "tournament_fee",
      // cloud-originated only (club tournaments); arrives via pull
      "tab_settle",
      // parked console bill settled from the wallet
      "station_pass"
      // per-station monthly pass bought at the counter
    ]
  }).notNull(),
  amount: integer("amount").notNull(),
  // signed Toman
  refType: text("ref_type"),
  // "session" | "order" | "payment_intent" | ...
  refId: text("ref_id"),
  reason: text("reason"),
  // required for adjustments (enforced in service layer)
  idempotencyKey: text("idempotency_key").notNull(),
  createdBy: text("created_by").notNull(),
  // staff id | "customer" | "system"
  deviceId: text("device_id"),
  prevHash: text("prev_hash").notNull(),
  rowHash: text("row_hash").notNull(),
  createdAt: integer("created_at").notNull()
}, (t) => [
  uniqueIndex("wallet_idem_uq").on(t.idempotencyKey),
  index("wallet_customer_idx").on(t.customerId)
]);
var pricingRateCards = sqliteTable("pricing_rate_cards", {
  id: text("id").primaryKey(),
  branchId: text("branch_id").notNull(),
  zoneId: text("zone_id").notNull(),
  tier: text("tier", { enum: ["bronze", "silver", "gold"] }),
  // null = base rate
  pricePerHour: integer("price_per_hour").notNull(),
  // Toman
  effectiveFrom: integer("effective_from").notNull()
}, (t) => [index("rate_cards_zone_idx").on(t.zoneId)]);
var dynamicPricingRules = sqliteTable("dynamic_pricing_rules", {
  id: text("id").primaryKey(),
  branchId: text("branch_id").notNull(),
  name: text("name").notNull(),
  priority: integer("priority").notNull().default(100),
  // lower wins
  enabled: integer("enabled", { mode: "boolean" }).notNull().default(false),
  conditions: text("conditions", { mode: "json" }).$type().notNull(),
  action: text("action", { mode: "json" }).$type().notNull(),
  floorRate: integer("floor_rate")
  // Toman
});
var shifts = sqliteTable("shifts", {
  id: text("id").primaryKey(),
  branchId: text("branch_id").notNull(),
  staffId: text("staff_id").notNull(),
  openedAt: integer("opened_at").notNull(),
  closedAt: integer("closed_at"),
  openingCash: integer("opening_cash").notNull(),
  // Toman
  countedCash: integer("counted_cash"),
  expectedCash: integer("expected_cash"),
  zReport: text("z_report", { mode: "json" }).$type()
});
var cashMovements = sqliteTable("cash_movements", {
  id: text("id").primaryKey(),
  shiftId: text("shift_id").notNull().references(() => shifts.id),
  type: text("type", { enum: ["in", "out", "payout"] }).notNull(),
  amount: integer("amount").notNull(),
  // Toman
  reason: text("reason").notNull(),
  staffId: text("staff_id").notNull(),
  createdAt: integer("created_at").notNull()
});
var products = sqliteTable("products", {
  id: text("id").primaryKey(),
  branchId: text("branch_id").notNull(),
  name: text("name").notNull(),
  price: integer("price").notNull(),
  // Toman
  category: text("category"),
  stockQty: integer("stock_qty"),
  /** Product photo filename under data/products (public GET — not PII). */
  imageFile: text("image_file"),
  active: integer("active", { mode: "boolean" }).notNull().default(true)
});
var tabs = sqliteTable("tabs", {
  id: text("id").primaryKey(),
  branchId: text("branch_id").notNull(),
  pcId: text("pc_id").notNull(),
  sessionId: text("session_id").notNull(),
  customerId: text("customer_id"),
  label: text("label"),
  amount: integer("amount").notNull(),
  // Toman
  status: text("status", { enum: ["open", "settled"] }).notNull().default("open"),
  settledVia: text("settled_via", { enum: ["cash", "wallet"] }),
  /** The shift whose drawer received the cash (cash settlement only). */
  shiftId: text("shift_id"),
  createdAt: integer("created_at").notNull(),
  settledAt: integer("settled_at")
}, (t) => [uniqueIndex("tabs_session_uq").on(t.sessionId), index("tabs_status_idx").on(t.status)]);
var stationPasses = sqliteTable("station_passes", {
  id: text("id").primaryKey(),
  branchId: text("branch_id").notNull(),
  pcId: text("pc_id").notNull(),
  customerId: text("customer_id").notNull(),
  price: integer("price").notNull(),
  // Toman actually paid (snapshot)
  days: integer("days").notNull(),
  startsAt: integer("starts_at").notNull(),
  expiresAt: integer("expires_at").notNull(),
  soldBy: text("sold_by").notNull(),
  // staff id
  createdAt: integer("created_at").notNull()
}, (t) => [
  index("passes_pc_idx").on(t.pcId),
  index("passes_customer_idx").on(t.customerId),
  index("passes_expires_idx").on(t.expiresAt)
]);
var orders = sqliteTable("orders", {
  id: text("id").primaryKey(),
  branchId: text("branch_id").notNull(),
  sessionId: text("session_id"),
  customerId: text("customer_id"),
  status: text("status", { enum: ["placed", "delivered", "cancelled"] }).notNull(),
  total: integer("total").notNull(),
  // Toman
  paidVia: text("paid_via", { enum: ["wallet", "cash"] }).notNull(),
  staffId: text("staff_id"),
  source: text("source", { enum: ["seat", "counter"] }).notNull(),
  createdAt: integer("created_at").notNull()
}, (t) => [index("orders_session_idx").on(t.sessionId)]);
var orderItems = sqliteTable("order_items", {
  id: text("id").primaryKey(),
  orderId: text("order_id").notNull().references(() => orders.id),
  productId: text("product_id").notNull(),
  qty: integer("qty").notNull(),
  unitPrice: integer("unit_price").notNull()
  // Toman snapshot
});
var auditLog = sqliteTable("audit_log", {
  id: text("id").primaryKey(),
  branchId: text("branch_id").notNull(),
  staffId: text("staff_id"),
  action: text("action").notNull(),
  entity: text("entity").notNull(),
  entityId: text("entity_id"),
  before: text("before", { mode: "json" }).$type(),
  after: text("after", { mode: "json" }).$type(),
  deviceId: text("device_id"),
  createdAt: integer("created_at").notNull()
}, (t) => [index("audit_entity_idx").on(t.entity, t.entityId)]);
var pointsLedger = sqliteTable("points_ledger", {
  id: text("id").primaryKey(),
  customerId: text("customer_id").notNull(),
  branchId: text("branch_id"),
  type: text("type", {
    enum: ["earn_playtime", "earn_spend", "redeem", "badge_bonus", "adjust"]
  }).notNull(),
  points: integer("points").notNull(),
  // signed
  refType: text("ref_type"),
  refId: text("ref_id"),
  idempotencyKey: text("idempotency_key").notNull(),
  createdAt: integer("created_at").notNull()
}, (t) => [
  uniqueIndex("points_idem_uq").on(t.idempotencyKey),
  index("points_customer_idx").on(t.customerId)
]);
var settings = sqliteTable("settings", {
  key: text("key").primaryKey(),
  value: text("value", { mode: "json" }).$type().notNull(),
  updatedAt: integer("updated_at").notNull()
});
var syncOutbox = sqliteTable("sync_outbox", {
  eventId: text("event_id").primaryKey(),
  // uuidv7
  aggregateType: text("aggregate_type").notNull(),
  aggregateId: text("aggregate_id").notNull(),
  eventType: text("event_type").notNull(),
  payload: text("payload", { mode: "json" }).$type().notNull(),
  createdAt: integer("created_at").notNull(),
  ackedAt: integer("acked_at")
}, (t) => [index("outbox_unacked_idx").on(t.ackedAt, t.eventId)]);
var syncApplied = sqliteTable("sync_applied", {
  eventId: text("event_id").primaryKey(),
  appliedAt: integer("applied_at").notNull()
});
var syncCursors = sqliteTable("sync_cursors", {
  streamName: text("stream_name").primaryKey(),
  lastEventId: text("last_event_id"),
  updatedAt: integer("updated_at").notNull()
});

// ../../packages/db-local/dist/protection.js
var LEDGER_PROTECTION_SQL = `
CREATE TRIGGER IF NOT EXISTS wallet_ledger_no_update
BEFORE UPDATE ON wallet_ledger
BEGIN SELECT RAISE(ABORT, 'wallet_ledger is append-only'); END;

CREATE TRIGGER IF NOT EXISTS wallet_ledger_no_delete
BEFORE DELETE ON wallet_ledger
BEGIN SELECT RAISE(ABORT, 'wallet_ledger is append-only'); END;

CREATE TRIGGER IF NOT EXISTS points_ledger_no_update
BEFORE UPDATE ON points_ledger
BEGIN SELECT RAISE(ABORT, 'points_ledger is append-only'); END;

CREATE TRIGGER IF NOT EXISTS points_ledger_no_delete
BEFORE DELETE ON points_ledger
BEGIN SELECT RAISE(ABORT, 'points_ledger is append-only'); END;

CREATE TRIGGER IF NOT EXISTS audit_log_no_update
BEFORE UPDATE ON audit_log
BEGIN SELECT RAISE(ABORT, 'audit_log is append-only'); END;

CREATE TRIGGER IF NOT EXISTS audit_log_no_delete
BEFORE DELETE ON audit_log
BEGIN SELECT RAISE(ABORT, 'audit_log is append-only'); END;
`;

// ../../packages/domain/dist/ids.js
function uuidv7(now = Date.now()) {
  const bytes = new Uint8Array(16);
  crypto.getRandomValues(bytes);
  bytes[0] = now / 2 ** 40 & 255;
  bytes[1] = now / 2 ** 32 & 255;
  bytes[2] = now / 2 ** 24 & 255;
  bytes[3] = now / 2 ** 16 & 255;
  bytes[4] = now / 2 ** 8 & 255;
  bytes[5] = now & 255;
  bytes[6] = bytes[6] & 15 | 112;
  bytes[8] = bytes[8] & 63 | 128;
  const hex = Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("");
  return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
}

// ../../packages/domain/dist/money.js
function assertToman(value) {
  if (!Number.isSafeInteger(value)) {
    throw new Error(`Invalid Toman amount (must be integer): ${value}`);
  }
  return value;
}
function minuteCost(ratePerHour, minutes) {
  return Math.round(ratePerHour * minutes / 60);
}

// ../../packages/domain/dist/phone.js
var PERSIAN_DIGITS = "\u06F0\u06F1\u06F2\u06F3\u06F4\u06F5\u06F6\u06F7\u06F8\u06F9";
var ARABIC_DIGITS = "\u0660\u0661\u0662\u0663\u0664\u0665\u0666\u0667\u0668\u0669";
function toLatinDigits(s) {
  return s.replace(/[۰-۹٠-٩]/g, (ch) => {
    const p = PERSIAN_DIGITS.indexOf(ch);
    return String(p !== -1 ? p : ARABIC_DIGITS.indexOf(ch));
  });
}
function normalizePhone(raw2) {
  let d = toLatinDigits(raw2).replace(/[^0-9+]/g, "");
  if (d.startsWith("+"))
    d = d.slice(1);
  if (d.startsWith("00"))
    d = d.slice(2);
  if (d.startsWith("98"))
    d = d.slice(2);
  else if (d.startsWith("0"))
    d = d.slice(1);
  if (!/^9\d{9}$/.test(d))
    throw new Error(`Invalid Iranian mobile number: ${raw2}`);
  return `98${d}`;
}

// ../../packages/domain/dist/layout.js
function parseLayout(s) {
  if (!s)
    return null;
  const parts = s.split(",").map(Number);
  if (parts.length !== 3 || !parts.every(Number.isFinite))
    return null;
  return { x: parts[0], y: parts[1], r: parts[2] };
}

// dist/config.js
import { fileURLToPath } from "node:url";
var config = {
  port: Number(process.env.GAMENET_PORT ?? 4700),
  dbPath: process.env.GAMENET_DB ?? "./data/gamenet.db",
  migrationsFolder: process.env.GAMENET_MIGRATIONS ?? fileURLToPath(new URL("../../../packages/db-local/migrations", import.meta.url)),
  /** Both set → the outbox push worker runs. Unset = fully offline (default). */
  cloudUrl: (process.env.GAMENET_CLOUD_URL ?? "").replace(/\/+$/, ""),
  cloudToken: process.env.GAMENET_CLOUD_TOKEN ?? ""
};

// dist/db.js
function openDb() {
  mkdirSync(dirname(config.dbPath), { recursive: true });
  const sqlite2 = new Database(config.dbPath);
  sqlite2.pragma("journal_mode = WAL");
  const db2 = drizzle(sqlite2, { schema: dist_exports });
  if (existsSync(config.migrationsFolder)) {
    sqlite2.pragma("foreign_keys = OFF");
    migrate(db2, { migrationsFolder: config.migrationsFolder });
    sqlite2.exec(LEDGER_PROTECTION_SQL);
  } else {
    console.warn(`[db] migrations folder not found at ${config.migrationsFolder} \u2014 run 'pnpm --filter @gamenet/db-local generate' first`);
  }
  sqlite2.pragma("foreign_keys = ON");
  return { db: db2, sqlite: sqlite2 };
}
function ensureBranch(db2) {
  const existing = db2.select().from(settings).where(eq(settings.key, "branch_id")).get();
  if (existing)
    return existing.value;
  const now = Date.now();
  const id = uuidv7(now);
  db2.insert(branches).values({ id, name: "\u0634\u0639\u0628\u0647 \u06F1", createdAt: now, updatedAt: now }).run();
  db2.insert(settings).values({ key: "branch_id", value: id, updatedAt: now }).run();
  console.log(`[db] initialized branch ${id}`);
  return id;
}

// dist/routes.js
import { createHash, randomBytes } from "node:crypto";
import { mkdirSync as mkdirSync2, readFileSync, rmSync, writeFileSync } from "node:fs";
import { dirname as dirname2, join } from "node:path";
import { hash as hashPassword, verify as verifyPassword } from "@node-rs/argon2";

// ../../node_modules/.pnpm/hono@4.12.27/node_modules/hono/dist/compose.js
var compose = (middleware, onError, onNotFound) => {
  return (context, next) => {
    let index2 = -1;
    return dispatch(0);
    async function dispatch(i) {
      if (i <= index2) {
        throw new Error("next() called multiple times");
      }
      index2 = i;
      let res;
      let isError = false;
      let handler;
      if (middleware[i]) {
        handler = middleware[i][0][0];
        context.req.routeIndex = i;
      } else {
        handler = i === middleware.length && next || void 0;
      }
      if (handler) {
        try {
          res = await handler(context, () => dispatch(i + 1));
        } catch (err) {
          if (err instanceof Error && onError) {
            context.error = err;
            res = await onError(err, context);
            isError = true;
          } else {
            throw err;
          }
        }
      } else {
        if (context.finalized === false && onNotFound) {
          res = await onNotFound(context);
        }
      }
      if (res && (context.finalized === false || isError)) {
        context.res = res;
      }
      return context;
    }
  };
};

// ../../node_modules/.pnpm/hono@4.12.27/node_modules/hono/dist/request/constants.js
var GET_MATCH_RESULT = /* @__PURE__ */ Symbol();

// ../../node_modules/.pnpm/hono@4.12.27/node_modules/hono/dist/utils/body.js
var parseBody = async (request, options = /* @__PURE__ */ Object.create(null)) => {
  const { all = false, dot = false } = options;
  const headers = request instanceof HonoRequest ? request.raw.headers : request.headers;
  const contentType = headers.get("Content-Type");
  if (contentType?.startsWith("multipart/form-data") || contentType?.startsWith("application/x-www-form-urlencoded")) {
    return parseFormData(request, { all, dot });
  }
  return {};
};
async function parseFormData(request, options) {
  const formData = await request.formData();
  if (formData) {
    return convertFormDataToBodyData(formData, options);
  }
  return {};
}
function convertFormDataToBodyData(formData, options) {
  const form = /* @__PURE__ */ Object.create(null);
  formData.forEach((value, key) => {
    const shouldParseAllValues = options.all || key.endsWith("[]");
    if (!shouldParseAllValues) {
      form[key] = value;
    } else {
      handleParsingAllValues(form, key, value);
    }
  });
  if (options.dot) {
    Object.entries(form).forEach(([key, value]) => {
      const shouldParseDotValues = key.includes(".");
      if (shouldParseDotValues) {
        handleParsingNestedValues(form, key, value);
        delete form[key];
      }
    });
  }
  return form;
}
var handleParsingAllValues = (form, key, value) => {
  if (form[key] !== void 0) {
    if (Array.isArray(form[key])) {
      ;
      form[key].push(value);
    } else {
      form[key] = [form[key], value];
    }
  } else {
    if (!key.endsWith("[]")) {
      form[key] = value;
    } else {
      form[key] = [value];
    }
  }
};
var handleParsingNestedValues = (form, key, value) => {
  if (/(?:^|\.)__proto__\./.test(key)) {
    return;
  }
  let nestedForm = form;
  const keys = key.split(".");
  keys.forEach((key2, index2) => {
    if (index2 === keys.length - 1) {
      nestedForm[key2] = value;
    } else {
      if (!nestedForm[key2] || typeof nestedForm[key2] !== "object" || Array.isArray(nestedForm[key2]) || nestedForm[key2] instanceof File) {
        nestedForm[key2] = /* @__PURE__ */ Object.create(null);
      }
      nestedForm = nestedForm[key2];
    }
  });
};

// ../../node_modules/.pnpm/hono@4.12.27/node_modules/hono/dist/utils/url.js
var splitPath = (path) => {
  const paths = path.split("/");
  if (paths[0] === "") {
    paths.shift();
  }
  return paths;
};
var splitRoutingPath = (routePath) => {
  const { groups, path } = extractGroupsFromPath(routePath);
  const paths = splitPath(path);
  return replaceGroupMarks(paths, groups);
};
var extractGroupsFromPath = (path) => {
  const groups = [];
  path = path.replace(/\{[^}]+\}/g, (match2, index2) => {
    const mark = `@${index2}`;
    groups.push([mark, match2]);
    return mark;
  });
  return { groups, path };
};
var replaceGroupMarks = (paths, groups) => {
  for (let i = groups.length - 1; i >= 0; i--) {
    const [mark] = groups[i];
    for (let j = paths.length - 1; j >= 0; j--) {
      if (paths[j].includes(mark)) {
        paths[j] = paths[j].replace(mark, groups[i][1]);
        break;
      }
    }
  }
  return paths;
};
var patternCache = {};
var getPattern = (label, next) => {
  if (label === "*") {
    return "*";
  }
  const match2 = label.match(/^\:([^\{\}]+)(?:\{(.+)\})?$/);
  if (match2) {
    const cacheKey2 = `${label}#${next}`;
    if (!patternCache[cacheKey2]) {
      if (match2[2]) {
        patternCache[cacheKey2] = next && next[0] !== ":" && next[0] !== "*" ? [cacheKey2, match2[1], new RegExp(`^${match2[2]}(?=/${next})`)] : [label, match2[1], new RegExp(`^${match2[2]}$`)];
      } else {
        patternCache[cacheKey2] = [label, match2[1], true];
      }
    }
    return patternCache[cacheKey2];
  }
  return null;
};
var tryDecode = (str, decoder) => {
  try {
    return decoder(str);
  } catch {
    return str.replace(/(?:%[0-9A-Fa-f]{2})+/g, (match2) => {
      try {
        return decoder(match2);
      } catch {
        return match2;
      }
    });
  }
};
var tryDecodeURI = (str) => tryDecode(str, decodeURI);
var getPath = (request) => {
  const url = request.url;
  const start = url.indexOf("/", url.indexOf(":") + 4);
  let i = start;
  for (; i < url.length; i++) {
    const charCode = url.charCodeAt(i);
    if (charCode === 37) {
      const queryIndex = url.indexOf("?", i);
      const hashIndex = url.indexOf("#", i);
      const end = queryIndex === -1 ? hashIndex === -1 ? void 0 : hashIndex : hashIndex === -1 ? queryIndex : Math.min(queryIndex, hashIndex);
      const path = url.slice(start, end);
      return tryDecodeURI(path.includes("%25") ? path.replace(/%25/g, "%2525") : path);
    } else if (charCode === 63 || charCode === 35) {
      break;
    }
  }
  return url.slice(start, i);
};
var getPathNoStrict = (request) => {
  const result = getPath(request);
  return result.length > 1 && result.at(-1) === "/" ? result.slice(0, -1) : result;
};
var mergePath = (base, sub, ...rest) => {
  if (rest.length) {
    sub = mergePath(sub, ...rest);
  }
  return `${base?.[0] === "/" ? "" : "/"}${base}${sub === "/" ? "" : `${base?.at(-1) === "/" ? "" : "/"}${sub?.[0] === "/" ? sub.slice(1) : sub}`}`;
};
var checkOptionalParameter = (path) => {
  if (path.charCodeAt(path.length - 1) !== 63 || !path.includes(":")) {
    return null;
  }
  const segments = path.split("/");
  const results = [];
  let basePath = "";
  segments.forEach((segment) => {
    if (segment !== "" && !/\:/.test(segment)) {
      basePath += "/" + segment;
    } else if (/\:/.test(segment)) {
      if (/\?/.test(segment)) {
        if (results.length === 0 && basePath === "") {
          results.push("/");
        } else {
          results.push(basePath);
        }
        const optionalSegment = segment.replace("?", "");
        basePath += "/" + optionalSegment;
        results.push(basePath);
      } else {
        basePath += "/" + segment;
      }
    }
  });
  return results.filter((v, i, a) => a.indexOf(v) === i);
};
var _decodeURI = (value) => {
  if (!/[%+]/.test(value)) {
    return value;
  }
  if (value.indexOf("+") !== -1) {
    value = value.replace(/\+/g, " ");
  }
  return value.indexOf("%") !== -1 ? tryDecode(value, decodeURIComponent_) : value;
};
var _getQueryParam = (url, key, multiple) => {
  let encoded;
  if (!multiple && key && !/[%+]/.test(key)) {
    let keyIndex2 = url.indexOf("?", 8);
    if (keyIndex2 === -1) {
      return void 0;
    }
    if (!url.startsWith(key, keyIndex2 + 1)) {
      keyIndex2 = url.indexOf(`&${key}`, keyIndex2 + 1);
    }
    while (keyIndex2 !== -1) {
      const trailingKeyCode = url.charCodeAt(keyIndex2 + key.length + 1);
      if (trailingKeyCode === 61) {
        const valueIndex = keyIndex2 + key.length + 2;
        const endIndex = url.indexOf("&", valueIndex);
        return _decodeURI(url.slice(valueIndex, endIndex === -1 ? void 0 : endIndex));
      } else if (trailingKeyCode == 38 || isNaN(trailingKeyCode)) {
        return "";
      }
      keyIndex2 = url.indexOf(`&${key}`, keyIndex2 + 1);
    }
    encoded = /[%+]/.test(url);
    if (!encoded) {
      return void 0;
    }
  }
  const results = {};
  encoded ??= /[%+]/.test(url);
  let keyIndex = url.indexOf("?", 8);
  while (keyIndex !== -1) {
    const nextKeyIndex = url.indexOf("&", keyIndex + 1);
    let valueIndex = url.indexOf("=", keyIndex);
    if (valueIndex > nextKeyIndex && nextKeyIndex !== -1) {
      valueIndex = -1;
    }
    let name = url.slice(
      keyIndex + 1,
      valueIndex === -1 ? nextKeyIndex === -1 ? void 0 : nextKeyIndex : valueIndex
    );
    if (encoded) {
      name = _decodeURI(name);
    }
    keyIndex = nextKeyIndex;
    if (name === "") {
      continue;
    }
    let value;
    if (valueIndex === -1) {
      value = "";
    } else {
      value = url.slice(valueIndex + 1, nextKeyIndex === -1 ? void 0 : nextKeyIndex);
      if (encoded) {
        value = _decodeURI(value);
      }
    }
    if (multiple) {
      if (!(results[name] && Array.isArray(results[name]))) {
        results[name] = [];
      }
      ;
      results[name].push(value);
    } else {
      results[name] ??= value;
    }
  }
  return key ? results[key] : results;
};
var getQueryParam = _getQueryParam;
var getQueryParams = (url, key) => {
  return _getQueryParam(url, key, true);
};
var decodeURIComponent_ = decodeURIComponent;

// ../../node_modules/.pnpm/hono@4.12.27/node_modules/hono/dist/request.js
var tryDecodeURIComponent = (str) => tryDecode(str, decodeURIComponent_);
var HonoRequest = class {
  /**
   * `.raw` can get the raw Request object.
   *
   * @see {@link https://hono.dev/docs/api/request#raw}
   *
   * @example
   * ```ts
   * // For Cloudflare Workers
   * app.post('/', async (c) => {
   *   const metadata = c.req.raw.cf?.hostMetadata?
   *   ...
   * })
   * ```
   */
  raw;
  #validatedData;
  // Short name of validatedData
  #matchResult;
  routeIndex = 0;
  /**
   * `.path` can get the pathname of the request.
   *
   * @see {@link https://hono.dev/docs/api/request#path}
   *
   * @example
   * ```ts
   * app.get('/about/me', (c) => {
   *   const pathname = c.req.path // `/about/me`
   * })
   * ```
   */
  path;
  bodyCache = {};
  constructor(request, path = "/", matchResult = [[]]) {
    this.raw = request;
    this.path = path;
    this.#matchResult = matchResult;
    this.#validatedData = {};
  }
  param(key) {
    return key ? this.#getDecodedParam(key) : this.#getAllDecodedParams();
  }
  #getDecodedParam(key) {
    const paramKey = this.#matchResult[0][this.routeIndex][1][key];
    const param = this.#getParamValue(paramKey);
    return param && /\%/.test(param) ? tryDecodeURIComponent(param) : param;
  }
  #getAllDecodedParams() {
    const decoded = {};
    const keys = Object.keys(this.#matchResult[0][this.routeIndex][1]);
    for (const key of keys) {
      const value = this.#getParamValue(this.#matchResult[0][this.routeIndex][1][key]);
      if (value !== void 0) {
        decoded[key] = /\%/.test(value) ? tryDecodeURIComponent(value) : value;
      }
    }
    return decoded;
  }
  #getParamValue(paramKey) {
    return this.#matchResult[1] ? this.#matchResult[1][paramKey] : paramKey;
  }
  query(key) {
    return getQueryParam(this.url, key);
  }
  queries(key) {
    return getQueryParams(this.url, key);
  }
  header(name) {
    if (name) {
      return this.raw.headers.get(name) ?? void 0;
    }
    const headerData = {};
    this.raw.headers.forEach((value, key) => {
      headerData[key] = value;
    });
    return headerData;
  }
  async parseBody(options) {
    return parseBody(this, options);
  }
  #cachedBody = (key) => {
    const { bodyCache, raw: raw2 } = this;
    const cachedBody = bodyCache[key];
    if (cachedBody) {
      return cachedBody;
    }
    const anyCachedKey = Object.keys(bodyCache)[0];
    if (anyCachedKey) {
      return bodyCache[anyCachedKey].then((body) => {
        if (anyCachedKey === "json") {
          body = JSON.stringify(body);
        }
        return new Response(body)[key]();
      });
    }
    return bodyCache[key] = raw2[key]();
  };
  /**
   * `.json()` can parse Request body of type `application/json`
   *
   * @see {@link https://hono.dev/docs/api/request#json}
   *
   * @example
   * ```ts
   * app.post('/entry', async (c) => {
   *   const body = await c.req.json()
   * })
   * ```
   */
  json() {
    return this.#cachedBody("text").then((text2) => JSON.parse(text2));
  }
  /**
   * `.text()` can parse Request body of type `text/plain`
   *
   * @see {@link https://hono.dev/docs/api/request#text}
   *
   * @example
   * ```ts
   * app.post('/entry', async (c) => {
   *   const body = await c.req.text()
   * })
   * ```
   */
  text() {
    return this.#cachedBody("text");
  }
  /**
   * `.arrayBuffer()` parse Request body as an `ArrayBuffer`
   *
   * @see {@link https://hono.dev/docs/api/request#arraybuffer}
   *
   * @example
   * ```ts
   * app.post('/entry', async (c) => {
   *   const body = await c.req.arrayBuffer()
   * })
   * ```
   */
  arrayBuffer() {
    return this.#cachedBody("arrayBuffer");
  }
  /**
   * `.bytes()` parses the request body as a `Uint8Array`.
   *
   * @see {@link https://hono.dev/docs/api/request#bytes}
   *
   * @example
   * ```ts
   * app.post('/entry', async (c) => {
   *   const body = await c.req.bytes()
   * })
   * ```
   */
  bytes() {
    return this.#cachedBody("arrayBuffer").then((buffer) => new Uint8Array(buffer));
  }
  /**
   * Parses the request body as a `Blob`.
   * @example
   * ```ts
   * app.post('/entry', async (c) => {
   *   const body = await c.req.blob();
   * });
   * ```
   * @see https://hono.dev/docs/api/request#blob
   */
  blob() {
    return this.#cachedBody("blob");
  }
  /**
   * Parses the request body as `FormData`.
   * @example
   * ```ts
   * app.post('/entry', async (c) => {
   *   const body = await c.req.formData();
   * });
   * ```
   * @see https://hono.dev/docs/api/request#formdata
   */
  formData() {
    return this.#cachedBody("formData");
  }
  /**
   * Adds validated data to the request.
   *
   * @param target - The target of the validation.
   * @param data - The validated data to add.
   */
  addValidatedData(target, data) {
    this.#validatedData[target] = data;
  }
  valid(target) {
    return this.#validatedData[target];
  }
  /**
   * `.url()` can get the request url strings.
   *
   * @see {@link https://hono.dev/docs/api/request#url}
   *
   * @example
   * ```ts
   * app.get('/about/me', (c) => {
   *   const url = c.req.url // `http://localhost:8787/about/me`
   *   ...
   * })
   * ```
   */
  get url() {
    return this.raw.url;
  }
  /**
   * `.method()` can get the method name of the request.
   *
   * @see {@link https://hono.dev/docs/api/request#method}
   *
   * @example
   * ```ts
   * app.get('/about/me', (c) => {
   *   const method = c.req.method // `GET`
   * })
   * ```
   */
  get method() {
    return this.raw.method;
  }
  get [GET_MATCH_RESULT]() {
    return this.#matchResult;
  }
  /**
   * `.matchedRoutes()` can return a matched route in the handler
   *
   * @deprecated
   *
   * Use matchedRoutes helper defined in "hono/route" instead.
   *
   * @see {@link https://hono.dev/docs/api/request#matchedroutes}
   *
   * @example
   * ```ts
   * app.use('*', async function logger(c, next) {
   *   await next()
   *   c.req.matchedRoutes.forEach(({ handler, method, path }, i) => {
   *     const name = handler.name || (handler.length < 2 ? '[handler]' : '[middleware]')
   *     console.log(
   *       method,
   *       ' ',
   *       path,
   *       ' '.repeat(Math.max(10 - path.length, 0)),
   *       name,
   *       i === c.req.routeIndex ? '<- respond from here' : ''
   *     )
   *   })
   * })
   * ```
   */
  get matchedRoutes() {
    return this.#matchResult[0].map(([[, route]]) => route);
  }
  /**
   * `routePath()` can retrieve the path registered within the handler
   *
   * @deprecated
   *
   * Use routePath helper defined in "hono/route" instead.
   *
   * @see {@link https://hono.dev/docs/api/request#routepath}
   *
   * @example
   * ```ts
   * app.get('/posts/:id', (c) => {
   *   return c.json({ path: c.req.routePath })
   * })
   * ```
   */
  get routePath() {
    return this.#matchResult[0].map(([[, route]]) => route)[this.routeIndex].path;
  }
};

// ../../node_modules/.pnpm/hono@4.12.27/node_modules/hono/dist/utils/html.js
var HtmlEscapedCallbackPhase = {
  Stringify: 1,
  BeforeStream: 2,
  Stream: 3
};
var raw = (value, callbacks) => {
  const escapedString = new String(value);
  escapedString.isEscaped = true;
  escapedString.callbacks = callbacks;
  return escapedString;
};
var resolveCallback = async (str, phase, preserveCallbacks, context, buffer) => {
  if (typeof str === "object" && !(str instanceof String)) {
    if (!(str instanceof Promise)) {
      str = str.toString();
    }
    if (str instanceof Promise) {
      str = await str;
    }
  }
  const callbacks = str.callbacks;
  if (!callbacks?.length) {
    return Promise.resolve(str);
  }
  if (buffer) {
    buffer[0] += str;
  } else {
    buffer = [str];
  }
  const resStr = Promise.all(callbacks.map((c) => c({ phase, buffer, context }))).then(
    (res) => Promise.all(
      res.filter(Boolean).map((str2) => resolveCallback(str2, phase, false, context, buffer))
    ).then(() => buffer[0])
  );
  if (preserveCallbacks) {
    return raw(await resStr, callbacks);
  } else {
    return resStr;
  }
};

// ../../node_modules/.pnpm/hono@4.12.27/node_modules/hono/dist/context.js
var TEXT_PLAIN = "text/plain; charset=UTF-8";
var setDefaultContentType = (contentType, headers) => {
  return {
    "Content-Type": contentType,
    ...headers
  };
};
var createResponseInstance = (body, init) => new Response(body, init);
var Context = class {
  #rawRequest;
  #req;
  /**
   * `.env` can get bindings (environment variables, secrets, KV namespaces, D1 database, R2 bucket etc.) in Cloudflare Workers.
   *
   * @see {@link https://hono.dev/docs/api/context#env}
   *
   * @example
   * ```ts
   * // Environment object for Cloudflare Workers
   * app.get('*', async c => {
   *   const counter = c.env.COUNTER
   * })
   * ```
   */
  env = {};
  #var;
  finalized = false;
  /**
   * `.error` can get the error object from the middleware if the Handler throws an error.
   *
   * @see {@link https://hono.dev/docs/api/context#error}
   *
   * @example
   * ```ts
   * app.use('*', async (c, next) => {
   *   await next()
   *   if (c.error) {
   *     // do something...
   *   }
   * })
   * ```
   */
  error;
  #status;
  #executionCtx;
  #res;
  #layout;
  #renderer;
  #notFoundHandler;
  #preparedHeaders;
  #matchResult;
  #path;
  /**
   * Creates an instance of the Context class.
   *
   * @param req - The Request object.
   * @param options - Optional configuration options for the context.
   */
  constructor(req, options) {
    this.#rawRequest = req;
    if (options) {
      this.#executionCtx = options.executionCtx;
      this.env = options.env;
      this.#notFoundHandler = options.notFoundHandler;
      this.#path = options.path;
      this.#matchResult = options.matchResult;
    }
  }
  /**
   * `.req` is the instance of {@link HonoRequest}.
   */
  get req() {
    this.#req ??= new HonoRequest(this.#rawRequest, this.#path, this.#matchResult);
    return this.#req;
  }
  /**
   * @see {@link https://hono.dev/docs/api/context#event}
   * The FetchEvent associated with the current request.
   *
   * @throws Will throw an error if the context does not have a FetchEvent.
   */
  get event() {
    if (this.#executionCtx && "respondWith" in this.#executionCtx) {
      return this.#executionCtx;
    } else {
      throw Error("This context has no FetchEvent");
    }
  }
  /**
   * @see {@link https://hono.dev/docs/api/context#executionctx}
   * The ExecutionContext associated with the current request.
   *
   * @throws Will throw an error if the context does not have an ExecutionContext.
   */
  get executionCtx() {
    if (this.#executionCtx) {
      return this.#executionCtx;
    } else {
      throw Error("This context has no ExecutionContext");
    }
  }
  /**
   * @see {@link https://hono.dev/docs/api/context#res}
   * The Response object for the current request.
   */
  get res() {
    return this.#res ||= createResponseInstance(null, {
      headers: this.#preparedHeaders ??= new Headers()
    });
  }
  /**
   * Sets the Response object for the current request.
   *
   * @param _res - The Response object to set.
   */
  set res(_res) {
    if (this.#res && _res) {
      _res = createResponseInstance(_res.body, _res);
      for (const [k, v] of this.#res.headers.entries()) {
        if (k === "content-type") {
          continue;
        }
        if (k === "set-cookie") {
          const cookies = this.#res.headers.getSetCookie();
          _res.headers.delete("set-cookie");
          for (const cookie of cookies) {
            _res.headers.append("set-cookie", cookie);
          }
        } else {
          _res.headers.set(k, v);
        }
      }
    }
    this.#res = _res;
    this.finalized = true;
  }
  /**
   * `.render()` can create a response within a layout.
   *
   * @see {@link https://hono.dev/docs/api/context#render-setrenderer}
   *
   * @example
   * ```ts
   * app.get('/', (c) => {
   *   return c.render('Hello!')
   * })
   * ```
   */
  render = (...args) => {
    this.#renderer ??= (content) => this.html(content);
    return this.#renderer(...args);
  };
  /**
   * Sets the layout for the response.
   *
   * @param layout - The layout to set.
   * @returns The layout function.
   */
  setLayout = (layout) => this.#layout = layout;
  /**
   * Gets the current layout for the response.
   *
   * @returns The current layout function.
   */
  getLayout = () => this.#layout;
  /**
   * `.setRenderer()` can set the layout in the custom middleware.
   *
   * @see {@link https://hono.dev/docs/api/context#render-setrenderer}
   *
   * @example
   * ```tsx
   * app.use('*', async (c, next) => {
   *   c.setRenderer((content) => {
   *     return c.html(
   *       <html>
   *         <body>
   *           <p>{content}</p>
   *         </body>
   *       </html>
   *     )
   *   })
   *   await next()
   * })
   * ```
   */
  setRenderer = (renderer) => {
    this.#renderer = renderer;
  };
  /**
   * `.header()` can set headers.
   *
   * @see {@link https://hono.dev/docs/api/context#header}
   *
   * @example
   * ```ts
   * app.get('/welcome', (c) => {
   *   // Set headers
   *   c.header('X-Message', 'Hello!')
   *   c.header('Content-Type', 'text/plain')
   *
   *   return c.body('Thank you for coming')
   * })
   * ```
   */
  header = (name, value, options) => {
    if (this.finalized) {
      this.#res = createResponseInstance(this.#res.body, this.#res);
    }
    const headers = this.#res ? this.#res.headers : this.#preparedHeaders ??= new Headers();
    if (value === void 0) {
      headers.delete(name);
    } else if (options?.append) {
      headers.append(name, value);
    } else {
      headers.set(name, value);
    }
  };
  status = (status) => {
    this.#status = status;
  };
  /**
   * `.set()` can set the value specified by the key.
   *
   * @see {@link https://hono.dev/docs/api/context#set-get}
   *
   * @example
   * ```ts
   * app.use('*', async (c, next) => {
   *   c.set('message', 'Hono is hot!!')
   *   await next()
   * })
   * ```
   */
  set = (key, value) => {
    this.#var ??= /* @__PURE__ */ new Map();
    this.#var.set(key, value);
  };
  /**
   * `.get()` can use the value specified by the key.
   *
   * @see {@link https://hono.dev/docs/api/context#set-get}
   *
   * @example
   * ```ts
   * app.get('/', (c) => {
   *   const message = c.get('message')
   *   return c.text(`The message is "${message}"`)
   * })
   * ```
   */
  get = (key) => {
    return this.#var ? this.#var.get(key) : void 0;
  };
  /**
   * `.var` can access the value of a variable.
   *
   * @see {@link https://hono.dev/docs/api/context#var}
   *
   * @example
   * ```ts
   * const result = c.var.client.oneMethod()
   * ```
   */
  // c.var.propName is a read-only
  get var() {
    if (!this.#var) {
      return {};
    }
    return Object.fromEntries(this.#var);
  }
  #newResponse(data, arg, headers) {
    const responseHeaders = this.#res ? new Headers(this.#res.headers) : this.#preparedHeaders ?? new Headers();
    if (typeof arg === "object" && "headers" in arg) {
      const argHeaders = arg.headers instanceof Headers ? arg.headers : new Headers(arg.headers);
      for (const [key, value] of argHeaders) {
        if (key.toLowerCase() === "set-cookie") {
          responseHeaders.append(key, value);
        } else {
          responseHeaders.set(key, value);
        }
      }
    }
    if (headers) {
      for (const [k, v] of Object.entries(headers)) {
        if (typeof v === "string") {
          responseHeaders.set(k, v);
        } else {
          responseHeaders.delete(k);
          for (const v2 of v) {
            responseHeaders.append(k, v2);
          }
        }
      }
    }
    const status = typeof arg === "number" ? arg : arg?.status ?? this.#status;
    return createResponseInstance(data, { status, headers: responseHeaders });
  }
  newResponse = (...args) => this.#newResponse(...args);
  /**
   * `.body()` can return the HTTP response.
   * You can set headers with `.header()` and set HTTP status code with `.status`.
   * This can also be set in `.text()`, `.json()` and so on.
   *
   * @see {@link https://hono.dev/docs/api/context#body}
   *
   * @example
   * ```ts
   * app.get('/welcome', (c) => {
   *   // Set headers
   *   c.header('X-Message', 'Hello!')
   *   c.header('Content-Type', 'text/plain')
   *   // Set HTTP status code
   *   c.status(201)
   *
   *   // Return the response body
   *   return c.body('Thank you for coming')
   * })
   * ```
   */
  body = (data, arg, headers) => this.#newResponse(data, arg, headers);
  /**
   * `.text()` can render text as `Content-Type:text/plain`.
   *
   * @see {@link https://hono.dev/docs/api/context#text}
   *
   * @example
   * ```ts
   * app.get('/say', (c) => {
   *   return c.text('Hello!')
   * })
   * ```
   */
  text = (text2, arg, headers) => {
    return !this.#preparedHeaders && !this.#status && !arg && !headers && !this.finalized ? new Response(text2) : this.#newResponse(
      text2,
      arg,
      setDefaultContentType(TEXT_PLAIN, headers)
    );
  };
  /**
   * `.json()` can render JSON as `Content-Type:application/json`.
   *
   * @see {@link https://hono.dev/docs/api/context#json}
   *
   * @example
   * ```ts
   * app.get('/api', (c) => {
   *   return c.json({ message: 'Hello!' })
   * })
   * ```
   */
  json = (object, arg, headers) => {
    return this.#newResponse(
      JSON.stringify(object),
      arg,
      setDefaultContentType("application/json", headers)
    );
  };
  html = (html, arg, headers) => {
    const res = (html2) => this.#newResponse(html2, arg, setDefaultContentType("text/html; charset=UTF-8", headers));
    return typeof html === "object" ? resolveCallback(html, HtmlEscapedCallbackPhase.Stringify, false, {}).then(res) : res(html);
  };
  /**
   * `.redirect()` can Redirect, default status code is 302.
   *
   * @see {@link https://hono.dev/docs/api/context#redirect}
   *
   * @example
   * ```ts
   * app.get('/redirect', (c) => {
   *   return c.redirect('/')
   * })
   * app.get('/redirect-permanently', (c) => {
   *   return c.redirect('/', 301)
   * })
   * ```
   */
  redirect = (location, status) => {
    const locationString = String(location);
    this.header(
      "Location",
      // Multibyes should be encoded
      // eslint-disable-next-line no-control-regex
      !/[^\x00-\xFF]/.test(locationString) ? locationString : encodeURI(locationString)
    );
    return this.newResponse(null, status ?? 302);
  };
  /**
   * `.notFound()` can return the Not Found Response.
   *
   * @see {@link https://hono.dev/docs/api/context#notfound}
   *
   * @example
   * ```ts
   * app.get('/notfound', (c) => {
   *   return c.notFound()
   * })
   * ```
   */
  notFound = () => {
    this.#notFoundHandler ??= () => createResponseInstance();
    return this.#notFoundHandler(this);
  };
};

// ../../node_modules/.pnpm/hono@4.12.27/node_modules/hono/dist/router.js
var METHOD_NAME_ALL = "ALL";
var METHOD_NAME_ALL_LOWERCASE = "all";
var METHODS = ["get", "post", "put", "delete", "options", "patch"];
var MESSAGE_MATCHER_IS_ALREADY_BUILT = "Can not add a route since the matcher is already built.";
var UnsupportedPathError = class extends Error {
};

// ../../node_modules/.pnpm/hono@4.12.27/node_modules/hono/dist/utils/constants.js
var COMPOSED_HANDLER = "__COMPOSED_HANDLER";

// ../../node_modules/.pnpm/hono@4.12.27/node_modules/hono/dist/hono-base.js
var notFoundHandler = (c) => {
  return c.text("404 Not Found", 404);
};
var errorHandler = (err, c) => {
  if ("getResponse" in err) {
    const res = err.getResponse();
    return c.newResponse(res.body, res);
  }
  console.error(err);
  return c.text("Internal Server Error", 500);
};
var Hono = class _Hono {
  get;
  post;
  put;
  delete;
  options;
  patch;
  all;
  on;
  use;
  /*
    This class is like an abstract class and does not have a router.
    To use it, inherit the class and implement router in the constructor.
  */
  router;
  getPath;
  // Cannot use `#` because it requires visibility at JavaScript runtime.
  _basePath = "/";
  #path = "/";
  routes = [];
  constructor(options = {}) {
    const allMethods = [...METHODS, METHOD_NAME_ALL_LOWERCASE];
    allMethods.forEach((method) => {
      this[method] = (args1, ...args) => {
        if (typeof args1 === "string") {
          this.#path = args1;
        } else {
          this.#addRoute(method, this.#path, args1);
        }
        args.forEach((handler) => {
          this.#addRoute(method, this.#path, handler);
        });
        return this;
      };
    });
    this.on = (method, path, ...handlers) => {
      for (const p of [path].flat()) {
        this.#path = p;
        for (const m of [method].flat()) {
          handlers.map((handler) => {
            this.#addRoute(m.toUpperCase(), this.#path, handler);
          });
        }
      }
      return this;
    };
    this.use = (arg1, ...handlers) => {
      if (typeof arg1 === "string") {
        this.#path = arg1;
      } else {
        this.#path = "*";
        handlers.unshift(arg1);
      }
      handlers.forEach((handler) => {
        this.#addRoute(METHOD_NAME_ALL, this.#path, handler);
      });
      return this;
    };
    const { strict, ...optionsWithoutStrict } = options;
    Object.assign(this, optionsWithoutStrict);
    this.getPath = strict ?? true ? options.getPath ?? getPath : getPathNoStrict;
  }
  #clone() {
    const clone = new _Hono({
      router: this.router,
      getPath: this.getPath
    });
    clone.errorHandler = this.errorHandler;
    clone.#notFoundHandler = this.#notFoundHandler;
    clone.routes = this.routes;
    return clone;
  }
  #notFoundHandler = notFoundHandler;
  // Cannot use `#` because it requires visibility at JavaScript runtime.
  errorHandler = errorHandler;
  /**
   * `.route()` allows grouping other Hono instance in routes.
   *
   * @see {@link https://hono.dev/docs/api/routing#grouping}
   *
   * @param {string} path - base Path
   * @param {Hono} app - other Hono instance
   * @returns {Hono} routed Hono instance
   *
   * @example
   * ```ts
   * const app = new Hono()
   * const app2 = new Hono()
   *
   * app2.get("/user", (c) => c.text("user"))
   * app.route("/api", app2) // GET /api/user
   * ```
   */
  route(path, app2) {
    const subApp = this.basePath(path);
    app2.routes.map((r) => {
      let handler;
      if (app2.errorHandler === errorHandler) {
        handler = r.handler;
      } else {
        handler = async (c, next) => (await compose([], app2.errorHandler)(c, () => r.handler(c, next))).res;
        handler[COMPOSED_HANDLER] = r.handler;
      }
      subApp.#addRoute(r.method, r.path, handler, r.basePath);
    });
    return this;
  }
  /**
   * `.basePath()` allows base paths to be specified.
   *
   * @see {@link https://hono.dev/docs/api/routing#base-path}
   *
   * @param {string} path - base Path
   * @returns {Hono} changed Hono instance
   *
   * @example
   * ```ts
   * const api = new Hono().basePath('/api')
   * ```
   */
  basePath(path) {
    const subApp = this.#clone();
    subApp._basePath = mergePath(this._basePath, path);
    return subApp;
  }
  /**
   * `.onError()` handles an error and returns a customized Response.
   *
   * @see {@link https://hono.dev/docs/api/hono#error-handling}
   *
   * @param {ErrorHandler} handler - request Handler for error
   * @returns {Hono} changed Hono instance
   *
   * @example
   * ```ts
   * app.onError((err, c) => {
   *   console.error(`${err}`)
   *   return c.text('Custom Error Message', 500)
   * })
   * ```
   */
  onError = (handler) => {
    this.errorHandler = handler;
    return this;
  };
  /**
   * `.notFound()` allows you to customize a Not Found Response.
   *
   * @see {@link https://hono.dev/docs/api/hono#not-found}
   *
   * @param {NotFoundHandler} handler - request handler for not-found
   * @returns {Hono} changed Hono instance
   *
   * @example
   * ```ts
   * app.notFound((c) => {
   *   return c.text('Custom 404 Message', 404)
   * })
   * ```
   */
  notFound = (handler) => {
    this.#notFoundHandler = handler;
    return this;
  };
  /**
   * `.mount()` allows you to mount applications built with other frameworks into your Hono application.
   *
   * @see {@link https://hono.dev/docs/api/hono#mount}
   *
   * @param {string} path - base Path
   * @param {Function} applicationHandler - other Request Handler
   * @param {MountOptions} [options] - options of `.mount()`
   * @returns {Hono} mounted Hono instance
   *
   * @example
   * ```ts
   * import { Router as IttyRouter } from 'itty-router'
   * import { Hono } from 'hono'
   * // Create itty-router application
   * const ittyRouter = IttyRouter()
   * // GET /itty-router/hello
   * ittyRouter.get('/hello', () => new Response('Hello from itty-router'))
   *
   * const app = new Hono()
   * app.mount('/itty-router', ittyRouter.handle)
   * ```
   *
   * @example
   * ```ts
   * const app = new Hono()
   * // Send the request to another application without modification.
   * app.mount('/app', anotherApp, {
   *   replaceRequest: (req) => req,
   * })
   * ```
   */
  mount(path, applicationHandler, options) {
    let replaceRequest;
    let optionHandler;
    if (options) {
      if (typeof options === "function") {
        optionHandler = options;
      } else {
        optionHandler = options.optionHandler;
        if (options.replaceRequest === false) {
          replaceRequest = (request) => request;
        } else {
          replaceRequest = options.replaceRequest;
        }
      }
    }
    const getOptions = optionHandler ? (c) => {
      const options2 = optionHandler(c);
      return Array.isArray(options2) ? options2 : [options2];
    } : (c) => {
      let executionContext = void 0;
      try {
        executionContext = c.executionCtx;
      } catch {
      }
      return [c.env, executionContext];
    };
    replaceRequest ||= (() => {
      const mergedPath = mergePath(this._basePath, path);
      const pathPrefixLength = mergedPath === "/" ? 0 : mergedPath.length;
      return (request) => {
        const url = new URL(request.url);
        url.pathname = this.getPath(request).slice(pathPrefixLength) || "/";
        return new Request(url, request);
      };
    })();
    const handler = async (c, next) => {
      const res = await applicationHandler(replaceRequest(c.req.raw), ...getOptions(c));
      if (res) {
        return res;
      }
      await next();
    };
    this.#addRoute(METHOD_NAME_ALL, mergePath(path, "*"), handler);
    return this;
  }
  #addRoute(method, path, handler, baseRoutePath) {
    method = method.toUpperCase();
    path = mergePath(this._basePath, path);
    const r = {
      basePath: baseRoutePath !== void 0 ? mergePath(this._basePath, baseRoutePath) : this._basePath,
      path,
      method,
      handler
    };
    this.router.add(method, path, [handler, r]);
    this.routes.push(r);
  }
  #handleError(err, c) {
    if (err instanceof Error) {
      return this.errorHandler(err, c);
    }
    throw err;
  }
  #dispatch(request, executionCtx, env, method) {
    if (method === "HEAD") {
      return (async () => new Response(null, await this.#dispatch(request, executionCtx, env, "GET")))();
    }
    const path = this.getPath(request, { env });
    const matchResult = this.router.match(method, path);
    const c = new Context(request, {
      path,
      matchResult,
      env,
      executionCtx,
      notFoundHandler: this.#notFoundHandler
    });
    if (matchResult[0].length === 1) {
      let res;
      try {
        res = matchResult[0][0][0][0](c, async () => {
          c.res = await this.#notFoundHandler(c);
        });
      } catch (err) {
        return this.#handleError(err, c);
      }
      return res instanceof Promise ? res.then(
        (resolved) => resolved || (c.finalized ? c.res : this.#notFoundHandler(c))
      ).catch((err) => this.#handleError(err, c)) : res ?? this.#notFoundHandler(c);
    }
    const composed = compose(matchResult[0], this.errorHandler, this.#notFoundHandler);
    return (async () => {
      try {
        const context = await composed(c);
        if (!context.finalized) {
          throw new Error(
            "Context is not finalized. Did you forget to return a Response object or `await next()`?"
          );
        }
        return context.res;
      } catch (err) {
        return this.#handleError(err, c);
      }
    })();
  }
  /**
   * `.fetch()` will be entry point of your app.
   *
   * @see {@link https://hono.dev/docs/api/hono#fetch}
   *
   * @param {Request} request - request Object of request
   * @param {Env} Env - env Object
   * @param {ExecutionContext} - context of execution
   * @returns {Response | Promise<Response>} response of request
   *
   */
  fetch = (request, ...rest) => {
    return this.#dispatch(request, rest[1], rest[0], request.method);
  };
  /**
   * `.request()` is a useful method for testing.
   * You can pass a URL or pathname to send a GET request.
   * app will return a Response object.
   * ```ts
   * test('GET /hello is ok', async () => {
   *   const res = await app.request('/hello')
   *   expect(res.status).toBe(200)
   * })
   * ```
   * @see https://hono.dev/docs/api/hono#request
   */
  request = (input, requestInit, Env, executionCtx) => {
    if (input instanceof Request) {
      return this.fetch(requestInit ? new Request(input, requestInit) : input, Env, executionCtx);
    }
    input = input.toString();
    return this.fetch(
      new Request(
        /^https?:\/\//.test(input) ? input : `http://localhost${mergePath("/", input)}`,
        requestInit
      ),
      Env,
      executionCtx
    );
  };
  /**
   * `.fire()` automatically adds a global fetch event listener.
   * This can be useful for environments that adhere to the Service Worker API, such as non-ES module Cloudflare Workers.
   * @deprecated
   * Use `fire` from `hono/service-worker` instead.
   * ```ts
   * import { Hono } from 'hono'
   * import { fire } from 'hono/service-worker'
   *
   * const app = new Hono()
   * // ...
   * fire(app)
   * ```
   * @see https://hono.dev/docs/api/hono#fire
   * @see https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API
   * @see https://developers.cloudflare.com/workers/reference/migrate-to-module-workers/
   */
  fire = () => {
    addEventListener("fetch", (event) => {
      event.respondWith(this.#dispatch(event.request, event, void 0, event.request.method));
    });
  };
};

// ../../node_modules/.pnpm/hono@4.12.27/node_modules/hono/dist/router/reg-exp-router/matcher.js
var emptyParam = [];
function match(method, path) {
  const matchers = this.buildAllMatchers();
  const match2 = ((method2, path2) => {
    const matcher = matchers[method2] || matchers[METHOD_NAME_ALL];
    const staticMatch = matcher[2][path2];
    if (staticMatch) {
      return staticMatch;
    }
    const match3 = path2.match(matcher[0]);
    if (!match3) {
      return [[], emptyParam];
    }
    const index2 = match3.indexOf("", 1);
    return [matcher[1][index2], match3];
  });
  this.match = match2;
  return match2(method, path);
}

// ../../node_modules/.pnpm/hono@4.12.27/node_modules/hono/dist/router/reg-exp-router/node.js
var LABEL_REG_EXP_STR = "[^/]+";
var ONLY_WILDCARD_REG_EXP_STR = ".*";
var TAIL_WILDCARD_REG_EXP_STR = "(?:|/.*)";
var PATH_ERROR = /* @__PURE__ */ Symbol();
var regExpMetaChars = new Set(".\\+*[^]$()");
function compareKey(a, b) {
  if (a.length === 1) {
    return b.length === 1 ? a < b ? -1 : 1 : -1;
  }
  if (b.length === 1) {
    return 1;
  }
  if (a === ONLY_WILDCARD_REG_EXP_STR || a === TAIL_WILDCARD_REG_EXP_STR) {
    return 1;
  } else if (b === ONLY_WILDCARD_REG_EXP_STR || b === TAIL_WILDCARD_REG_EXP_STR) {
    return -1;
  }
  if (a === LABEL_REG_EXP_STR) {
    return 1;
  } else if (b === LABEL_REG_EXP_STR) {
    return -1;
  }
  return a.length === b.length ? a < b ? -1 : 1 : b.length - a.length;
}
var Node = class _Node {
  #index;
  #varIndex;
  #children = /* @__PURE__ */ Object.create(null);
  insert(tokens, index2, paramMap, context, pathErrorCheckOnly) {
    if (tokens.length === 0) {
      if (this.#index !== void 0) {
        throw PATH_ERROR;
      }
      if (pathErrorCheckOnly) {
        return;
      }
      this.#index = index2;
      return;
    }
    const [token, ...restTokens] = tokens;
    const pattern = token === "*" ? restTokens.length === 0 ? ["", "", ONLY_WILDCARD_REG_EXP_STR] : ["", "", LABEL_REG_EXP_STR] : token === "/*" ? ["", "", TAIL_WILDCARD_REG_EXP_STR] : token.match(/^\:([^\{\}]+)(?:\{(.+)\})?$/);
    let node;
    if (pattern) {
      const name = pattern[1];
      let regexpStr = pattern[2] || LABEL_REG_EXP_STR;
      if (name && pattern[2]) {
        if (regexpStr === ".*") {
          throw PATH_ERROR;
        }
        regexpStr = regexpStr.replace(/^\((?!\?:)(?=[^)]+\)$)/, "(?:");
        if (/\((?!\?:)/.test(regexpStr)) {
          throw PATH_ERROR;
        }
      }
      node = this.#children[regexpStr];
      if (!node) {
        if (Object.keys(this.#children).some(
          (k) => k !== ONLY_WILDCARD_REG_EXP_STR && k !== TAIL_WILDCARD_REG_EXP_STR
        )) {
          throw PATH_ERROR;
        }
        if (pathErrorCheckOnly) {
          return;
        }
        node = this.#children[regexpStr] = new _Node();
        if (name !== "") {
          node.#varIndex = context.varIndex++;
        }
      }
      if (!pathErrorCheckOnly && name !== "") {
        paramMap.push([name, node.#varIndex]);
      }
    } else {
      node = this.#children[token];
      if (!node) {
        if (Object.keys(this.#children).some(
          (k) => k.length > 1 && k !== ONLY_WILDCARD_REG_EXP_STR && k !== TAIL_WILDCARD_REG_EXP_STR
        )) {
          throw PATH_ERROR;
        }
        if (pathErrorCheckOnly) {
          return;
        }
        node = this.#children[token] = new _Node();
      }
    }
    node.insert(restTokens, index2, paramMap, context, pathErrorCheckOnly);
  }
  buildRegExpStr() {
    const childKeys = Object.keys(this.#children).sort(compareKey);
    const strList = childKeys.map((k) => {
      const c = this.#children[k];
      return (typeof c.#varIndex === "number" ? `(${k})@${c.#varIndex}` : regExpMetaChars.has(k) ? `\\${k}` : k) + c.buildRegExpStr();
    });
    if (typeof this.#index === "number") {
      strList.unshift(`#${this.#index}`);
    }
    if (strList.length === 0) {
      return "";
    }
    if (strList.length === 1) {
      return strList[0];
    }
    return "(?:" + strList.join("|") + ")";
  }
};

// ../../node_modules/.pnpm/hono@4.12.27/node_modules/hono/dist/router/reg-exp-router/trie.js
var Trie = class {
  #context = { varIndex: 0 };
  #root = new Node();
  insert(path, index2, pathErrorCheckOnly) {
    const paramAssoc = [];
    const groups = [];
    for (let i = 0; ; ) {
      let replaced = false;
      path = path.replace(/\{[^}]+\}/g, (m) => {
        const mark = `@\\${i}`;
        groups[i] = [mark, m];
        i++;
        replaced = true;
        return mark;
      });
      if (!replaced) {
        break;
      }
    }
    const tokens = path.match(/(?::[^\/]+)|(?:\/\*$)|./g) || [];
    for (let i = groups.length - 1; i >= 0; i--) {
      const [mark] = groups[i];
      for (let j = tokens.length - 1; j >= 0; j--) {
        if (tokens[j].indexOf(mark) !== -1) {
          tokens[j] = tokens[j].replace(mark, groups[i][1]);
          break;
        }
      }
    }
    this.#root.insert(tokens, index2, paramAssoc, this.#context, pathErrorCheckOnly);
    return paramAssoc;
  }
  buildRegExp() {
    let regexp = this.#root.buildRegExpStr();
    if (regexp === "") {
      return [/^$/, [], []];
    }
    let captureIndex = 0;
    const indexReplacementMap = [];
    const paramReplacementMap = [];
    regexp = regexp.replace(/#(\d+)|@(\d+)|\.\*\$/g, (_, handlerIndex, paramIndex) => {
      if (handlerIndex !== void 0) {
        indexReplacementMap[++captureIndex] = Number(handlerIndex);
        return "$()";
      }
      if (paramIndex !== void 0) {
        paramReplacementMap[Number(paramIndex)] = ++captureIndex;
        return "";
      }
      return "";
    });
    return [new RegExp(`^${regexp}`), indexReplacementMap, paramReplacementMap];
  }
};

// ../../node_modules/.pnpm/hono@4.12.27/node_modules/hono/dist/router/reg-exp-router/router.js
var nullMatcher = [/^$/, [], /* @__PURE__ */ Object.create(null)];
var wildcardRegExpCache = /* @__PURE__ */ Object.create(null);
function buildWildcardRegExp(path) {
  return wildcardRegExpCache[path] ??= new RegExp(
    path === "*" ? "" : `^${path.replace(
      /\/\*$|([.\\+*[^\]$()])/g,
      (_, metaChar) => metaChar ? `\\${metaChar}` : "(?:|/.*)"
    )}$`
  );
}
function clearWildcardRegExpCache() {
  wildcardRegExpCache = /* @__PURE__ */ Object.create(null);
}
function buildMatcherFromPreprocessedRoutes(routes) {
  const trie = new Trie();
  const handlerData = [];
  if (routes.length === 0) {
    return nullMatcher;
  }
  const routesWithStaticPathFlag = routes.map(
    (route) => [!/\*|\/:/.test(route[0]), ...route]
  ).sort(
    ([isStaticA, pathA], [isStaticB, pathB]) => isStaticA ? 1 : isStaticB ? -1 : pathA.length - pathB.length
  );
  const staticMap = /* @__PURE__ */ Object.create(null);
  for (let i = 0, j = -1, len = routesWithStaticPathFlag.length; i < len; i++) {
    const [pathErrorCheckOnly, path, handlers] = routesWithStaticPathFlag[i];
    if (pathErrorCheckOnly) {
      staticMap[path] = [handlers.map(([h]) => [h, /* @__PURE__ */ Object.create(null)]), emptyParam];
    } else {
      j++;
    }
    let paramAssoc;
    try {
      paramAssoc = trie.insert(path, j, pathErrorCheckOnly);
    } catch (e) {
      throw e === PATH_ERROR ? new UnsupportedPathError(path) : e;
    }
    if (pathErrorCheckOnly) {
      continue;
    }
    handlerData[j] = handlers.map(([h, paramCount]) => {
      const paramIndexMap = /* @__PURE__ */ Object.create(null);
      paramCount -= 1;
      for (; paramCount >= 0; paramCount--) {
        const [key, value] = paramAssoc[paramCount];
        paramIndexMap[key] = value;
      }
      return [h, paramIndexMap];
    });
  }
  const [regexp, indexReplacementMap, paramReplacementMap] = trie.buildRegExp();
  for (let i = 0, len = handlerData.length; i < len; i++) {
    for (let j = 0, len2 = handlerData[i].length; j < len2; j++) {
      const map = handlerData[i][j]?.[1];
      if (!map) {
        continue;
      }
      const keys = Object.keys(map);
      for (let k = 0, len3 = keys.length; k < len3; k++) {
        map[keys[k]] = paramReplacementMap[map[keys[k]]];
      }
    }
  }
  const handlerMap = [];
  for (const i in indexReplacementMap) {
    handlerMap[i] = handlerData[indexReplacementMap[i]];
  }
  return [regexp, handlerMap, staticMap];
}
function findMiddleware(middleware, path) {
  if (!middleware) {
    return void 0;
  }
  for (const k of Object.keys(middleware).sort((a, b) => b.length - a.length)) {
    if (buildWildcardRegExp(k).test(path)) {
      return [...middleware[k]];
    }
  }
  return void 0;
}
var RegExpRouter = class {
  name = "RegExpRouter";
  #middleware;
  #routes;
  constructor() {
    this.#middleware = { [METHOD_NAME_ALL]: /* @__PURE__ */ Object.create(null) };
    this.#routes = { [METHOD_NAME_ALL]: /* @__PURE__ */ Object.create(null) };
  }
  add(method, path, handler) {
    const middleware = this.#middleware;
    const routes = this.#routes;
    if (!middleware || !routes) {
      throw new Error(MESSAGE_MATCHER_IS_ALREADY_BUILT);
    }
    if (!middleware[method]) {
      ;
      [middleware, routes].forEach((handlerMap) => {
        handlerMap[method] = /* @__PURE__ */ Object.create(null);
        Object.keys(handlerMap[METHOD_NAME_ALL]).forEach((p) => {
          handlerMap[method][p] = [...handlerMap[METHOD_NAME_ALL][p]];
        });
      });
    }
    if (path === "/*") {
      path = "*";
    }
    const paramCount = (path.match(/\/:/g) || []).length;
    if (/\*$/.test(path)) {
      const re = buildWildcardRegExp(path);
      if (method === METHOD_NAME_ALL) {
        Object.keys(middleware).forEach((m) => {
          middleware[m][path] ||= findMiddleware(middleware[m], path) || findMiddleware(middleware[METHOD_NAME_ALL], path) || [];
        });
      } else {
        middleware[method][path] ||= findMiddleware(middleware[method], path) || findMiddleware(middleware[METHOD_NAME_ALL], path) || [];
      }
      Object.keys(middleware).forEach((m) => {
        if (method === METHOD_NAME_ALL || method === m) {
          Object.keys(middleware[m]).forEach((p) => {
            re.test(p) && middleware[m][p].push([handler, paramCount]);
          });
        }
      });
      Object.keys(routes).forEach((m) => {
        if (method === METHOD_NAME_ALL || method === m) {
          Object.keys(routes[m]).forEach(
            (p) => re.test(p) && routes[m][p].push([handler, paramCount])
          );
        }
      });
      return;
    }
    const paths = checkOptionalParameter(path) || [path];
    for (let i = 0, len = paths.length; i < len; i++) {
      const path2 = paths[i];
      Object.keys(routes).forEach((m) => {
        if (method === METHOD_NAME_ALL || method === m) {
          routes[m][path2] ||= [
            ...findMiddleware(middleware[m], path2) || findMiddleware(middleware[METHOD_NAME_ALL], path2) || []
          ];
          routes[m][path2].push([handler, paramCount - len + i + 1]);
        }
      });
    }
  }
  match = match;
  buildAllMatchers() {
    const matchers = /* @__PURE__ */ Object.create(null);
    Object.keys(this.#routes).concat(Object.keys(this.#middleware)).forEach((method) => {
      matchers[method] ||= this.#buildMatcher(method);
    });
    this.#middleware = this.#routes = void 0;
    clearWildcardRegExpCache();
    return matchers;
  }
  #buildMatcher(method) {
    const routes = [];
    let hasOwnRoute = method === METHOD_NAME_ALL;
    [this.#middleware, this.#routes].forEach((r) => {
      const ownRoute = r[method] ? Object.keys(r[method]).map((path) => [path, r[method][path]]) : [];
      if (ownRoute.length !== 0) {
        hasOwnRoute ||= true;
        routes.push(...ownRoute);
      } else if (method !== METHOD_NAME_ALL) {
        routes.push(
          ...Object.keys(r[METHOD_NAME_ALL]).map((path) => [path, r[METHOD_NAME_ALL][path]])
        );
      }
    });
    if (!hasOwnRoute) {
      return null;
    } else {
      return buildMatcherFromPreprocessedRoutes(routes);
    }
  }
};

// ../../node_modules/.pnpm/hono@4.12.27/node_modules/hono/dist/router/smart-router/router.js
var SmartRouter = class {
  name = "SmartRouter";
  #routers = [];
  #routes = [];
  constructor(init) {
    this.#routers = init.routers;
  }
  add(method, path, handler) {
    if (!this.#routes) {
      throw new Error(MESSAGE_MATCHER_IS_ALREADY_BUILT);
    }
    this.#routes.push([method, path, handler]);
  }
  match(method, path) {
    if (!this.#routes) {
      throw new Error("Fatal error");
    }
    const routers = this.#routers;
    const routes = this.#routes;
    const len = routers.length;
    let i = 0;
    let res;
    for (; i < len; i++) {
      const router = routers[i];
      try {
        for (let i2 = 0, len2 = routes.length; i2 < len2; i2++) {
          router.add(...routes[i2]);
        }
        res = router.match(method, path);
      } catch (e) {
        if (e instanceof UnsupportedPathError) {
          continue;
        }
        throw e;
      }
      this.match = router.match.bind(router);
      this.#routers = [router];
      this.#routes = void 0;
      break;
    }
    if (i === len) {
      throw new Error("Fatal error");
    }
    this.name = `SmartRouter + ${this.activeRouter.name}`;
    return res;
  }
  get activeRouter() {
    if (this.#routes || this.#routers.length !== 1) {
      throw new Error("No active router has been determined yet.");
    }
    return this.#routers[0];
  }
};

// ../../node_modules/.pnpm/hono@4.12.27/node_modules/hono/dist/router/trie-router/node.js
var emptyParams = /* @__PURE__ */ Object.create(null);
var hasChildren = (children) => {
  for (const _ in children) {
    return true;
  }
  return false;
};
var Node2 = class _Node2 {
  #methods;
  #children;
  #patterns;
  #order = 0;
  #params = emptyParams;
  constructor(method, handler, children) {
    this.#children = children || /* @__PURE__ */ Object.create(null);
    this.#methods = [];
    if (method && handler) {
      const m = /* @__PURE__ */ Object.create(null);
      m[method] = { handler, possibleKeys: [], score: 0 };
      this.#methods = [m];
    }
    this.#patterns = [];
  }
  insert(method, path, handler) {
    this.#order = ++this.#order;
    let curNode = this;
    const parts = splitRoutingPath(path);
    const possibleKeys = [];
    for (let i = 0, len = parts.length; i < len; i++) {
      const p = parts[i];
      const nextP = parts[i + 1];
      const pattern = getPattern(p, nextP);
      const key = Array.isArray(pattern) ? pattern[0] : p;
      if (key in curNode.#children) {
        curNode = curNode.#children[key];
        if (pattern) {
          possibleKeys.push(pattern[1]);
        }
        continue;
      }
      curNode.#children[key] = new _Node2();
      if (pattern) {
        curNode.#patterns.push(pattern);
        possibleKeys.push(pattern[1]);
      }
      curNode = curNode.#children[key];
    }
    curNode.#methods.push({
      [method]: {
        handler,
        possibleKeys: possibleKeys.filter((v, i, a) => a.indexOf(v) === i),
        score: this.#order
      }
    });
    return curNode;
  }
  #pushHandlerSets(handlerSets, node, method, nodeParams, params) {
    for (let i = 0, len = node.#methods.length; i < len; i++) {
      const m = node.#methods[i];
      const handlerSet = m[method] || m[METHOD_NAME_ALL];
      const processedSet = {};
      if (handlerSet !== void 0) {
        handlerSet.params = /* @__PURE__ */ Object.create(null);
        handlerSets.push(handlerSet);
        if (nodeParams !== emptyParams || params && params !== emptyParams) {
          for (let i2 = 0, len2 = handlerSet.possibleKeys.length; i2 < len2; i2++) {
            const key = handlerSet.possibleKeys[i2];
            const processed = processedSet[handlerSet.score];
            handlerSet.params[key] = params?.[key] && !processed ? params[key] : nodeParams[key] ?? params?.[key];
            processedSet[handlerSet.score] = true;
          }
        }
      }
    }
  }
  search(method, path) {
    const handlerSets = [];
    this.#params = emptyParams;
    const curNode = this;
    let curNodes = [curNode];
    const parts = splitPath(path);
    const curNodesQueue = [];
    const len = parts.length;
    let partOffsets = null;
    for (let i = 0; i < len; i++) {
      const part = parts[i];
      const isLast = i === len - 1;
      const tempNodes = [];
      for (let j = 0, len2 = curNodes.length; j < len2; j++) {
        const node = curNodes[j];
        const nextNode = node.#children[part];
        if (nextNode) {
          nextNode.#params = node.#params;
          if (isLast) {
            if (nextNode.#children["*"]) {
              this.#pushHandlerSets(handlerSets, nextNode.#children["*"], method, node.#params);
            }
            this.#pushHandlerSets(handlerSets, nextNode, method, node.#params);
          } else {
            tempNodes.push(nextNode);
          }
        }
        for (let k = 0, len3 = node.#patterns.length; k < len3; k++) {
          const pattern = node.#patterns[k];
          const params = node.#params === emptyParams ? {} : { ...node.#params };
          if (pattern === "*") {
            const astNode = node.#children["*"];
            if (astNode) {
              this.#pushHandlerSets(handlerSets, astNode, method, node.#params);
              astNode.#params = params;
              tempNodes.push(astNode);
            }
            continue;
          }
          const [key, name, matcher] = pattern;
          if (!part && !(matcher instanceof RegExp)) {
            continue;
          }
          const child = node.#children[key];
          if (matcher instanceof RegExp) {
            if (partOffsets === null) {
              partOffsets = new Array(len);
              let offset = path[0] === "/" ? 1 : 0;
              for (let p = 0; p < len; p++) {
                partOffsets[p] = offset;
                offset += parts[p].length + 1;
              }
            }
            const restPathString = path.substring(partOffsets[i]);
            const m = matcher.exec(restPathString);
            if (m) {
              params[name] = m[0];
              this.#pushHandlerSets(handlerSets, child, method, node.#params, params);
              if (hasChildren(child.#children)) {
                child.#params = params;
                const componentCount = m[0].match(/\//)?.length ?? 0;
                const targetCurNodes = curNodesQueue[componentCount] ||= [];
                targetCurNodes.push(child);
              }
              continue;
            }
          }
          if (matcher === true || matcher.test(part)) {
            params[name] = part;
            if (isLast) {
              this.#pushHandlerSets(handlerSets, child, method, params, node.#params);
              if (child.#children["*"]) {
                this.#pushHandlerSets(
                  handlerSets,
                  child.#children["*"],
                  method,
                  params,
                  node.#params
                );
              }
            } else {
              child.#params = params;
              tempNodes.push(child);
            }
          }
        }
      }
      const shifted = curNodesQueue.shift();
      curNodes = shifted ? tempNodes.concat(shifted) : tempNodes;
    }
    if (handlerSets.length > 1) {
      handlerSets.sort((a, b) => {
        return a.score - b.score;
      });
    }
    return [handlerSets.map(({ handler, params }) => [handler, params])];
  }
};

// ../../node_modules/.pnpm/hono@4.12.27/node_modules/hono/dist/router/trie-router/router.js
var TrieRouter = class {
  name = "TrieRouter";
  #node;
  constructor() {
    this.#node = new Node2();
  }
  add(method, path, handler) {
    const results = checkOptionalParameter(path);
    if (results) {
      for (let i = 0, len = results.length; i < len; i++) {
        this.#node.insert(method, results[i], handler);
      }
      return;
    }
    this.#node.insert(method, path, handler);
  }
  match(method, path) {
    return this.#node.search(method, path);
  }
};

// ../../node_modules/.pnpm/hono@4.12.27/node_modules/hono/dist/hono.js
var Hono2 = class extends Hono {
  /**
   * Creates an instance of the Hono class.
   *
   * @param options - Optional configuration options for the Hono instance.
   */
  constructor(options = {}) {
    super(options);
    this.router = options.router ?? new SmartRouter({
      routers: [new RegExpRouter(), new TrieRouter()]
    });
  }
};

// ../../node_modules/.pnpm/hono@4.12.27/node_modules/hono/dist/middleware/cors/index.js
var cors = (options) => {
  const opts = {
    origin: "*",
    allowMethods: ["GET", "HEAD", "PUT", "POST", "DELETE", "PATCH"],
    allowHeaders: [],
    exposeHeaders: [],
    ...options
  };
  const findAllowOrigin = ((optsOrigin) => {
    if (typeof optsOrigin === "string") {
      if (optsOrigin === "*") {
        return () => optsOrigin;
      } else {
        return (origin) => optsOrigin === origin ? origin : null;
      }
    } else if (typeof optsOrigin === "function") {
      return optsOrigin;
    } else {
      return (origin) => optsOrigin.includes(origin) ? origin : null;
    }
  })(opts.origin);
  const findAllowMethods = ((optsAllowMethods) => {
    if (typeof optsAllowMethods === "function") {
      return optsAllowMethods;
    } else if (Array.isArray(optsAllowMethods)) {
      return () => optsAllowMethods;
    } else {
      return () => [];
    }
  })(opts.allowMethods);
  return async function cors2(c, next) {
    function set(key, value) {
      c.res.headers.set(key, value);
    }
    const allowOrigin = await findAllowOrigin(c.req.header("origin") || "", c);
    if (allowOrigin) {
      set("Access-Control-Allow-Origin", allowOrigin);
    }
    if (opts.credentials) {
      set("Access-Control-Allow-Credentials", "true");
    }
    if (opts.exposeHeaders?.length) {
      set("Access-Control-Expose-Headers", opts.exposeHeaders.join(","));
    }
    if (c.req.method === "OPTIONS") {
      if (opts.origin !== "*") {
        set("Vary", "Origin");
      }
      if (opts.maxAge != null) {
        set("Access-Control-Max-Age", opts.maxAge.toString());
      }
      const allowMethods = await findAllowMethods(c.req.header("origin") || "", c);
      if (allowMethods.length) {
        set("Access-Control-Allow-Methods", allowMethods.join(","));
      }
      let headers = opts.allowHeaders;
      if (!headers?.length) {
        const requestHeaders = c.req.header("Access-Control-Request-Headers");
        if (requestHeaders) {
          headers = requestHeaders.split(/\s*,\s*/);
        }
      }
      if (headers?.length) {
        set("Access-Control-Allow-Headers", headers.join(","));
        c.res.headers.append("Vary", "Access-Control-Request-Headers");
      }
      c.res.headers.delete("Content-Length");
      c.res.headers.delete("Content-Type");
      return new Response(null, {
        headers: c.res.headers,
        status: 204,
        statusText: "No Content"
      });
    }
    await next();
    if (opts.origin !== "*") {
      c.header("Vary", "Origin", { append: true });
    }
  };
};

// ../../node_modules/.pnpm/hono@4.12.27/node_modules/hono/dist/helper/factory/index.js
var createMiddleware = (middleware) => middleware;

// ../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/external.js
var external_exports = {};
__export(external_exports, {
  BRAND: () => BRAND,
  DIRTY: () => DIRTY,
  EMPTY_PATH: () => EMPTY_PATH,
  INVALID: () => INVALID,
  NEVER: () => NEVER,
  OK: () => OK,
  ParseStatus: () => ParseStatus,
  Schema: () => ZodType,
  ZodAny: () => ZodAny,
  ZodArray: () => ZodArray,
  ZodBigInt: () => ZodBigInt,
  ZodBoolean: () => ZodBoolean,
  ZodBranded: () => ZodBranded,
  ZodCatch: () => ZodCatch,
  ZodDate: () => ZodDate,
  ZodDefault: () => ZodDefault,
  ZodDiscriminatedUnion: () => ZodDiscriminatedUnion,
  ZodEffects: () => ZodEffects,
  ZodEnum: () => ZodEnum,
  ZodError: () => ZodError,
  ZodFirstPartyTypeKind: () => ZodFirstPartyTypeKind,
  ZodFunction: () => ZodFunction,
  ZodIntersection: () => ZodIntersection,
  ZodIssueCode: () => ZodIssueCode,
  ZodLazy: () => ZodLazy,
  ZodLiteral: () => ZodLiteral,
  ZodMap: () => ZodMap,
  ZodNaN: () => ZodNaN,
  ZodNativeEnum: () => ZodNativeEnum,
  ZodNever: () => ZodNever,
  ZodNull: () => ZodNull,
  ZodNullable: () => ZodNullable,
  ZodNumber: () => ZodNumber,
  ZodObject: () => ZodObject,
  ZodOptional: () => ZodOptional,
  ZodParsedType: () => ZodParsedType,
  ZodPipeline: () => ZodPipeline,
  ZodPromise: () => ZodPromise,
  ZodReadonly: () => ZodReadonly,
  ZodRecord: () => ZodRecord,
  ZodSchema: () => ZodType,
  ZodSet: () => ZodSet,
  ZodString: () => ZodString,
  ZodSymbol: () => ZodSymbol,
  ZodTransformer: () => ZodEffects,
  ZodTuple: () => ZodTuple,
  ZodType: () => ZodType,
  ZodUndefined: () => ZodUndefined,
  ZodUnion: () => ZodUnion,
  ZodUnknown: () => ZodUnknown,
  ZodVoid: () => ZodVoid,
  addIssueToContext: () => addIssueToContext,
  any: () => anyType,
  array: () => arrayType,
  bigint: () => bigIntType,
  boolean: () => booleanType,
  coerce: () => coerce,
  custom: () => custom,
  date: () => dateType,
  datetimeRegex: () => datetimeRegex,
  defaultErrorMap: () => en_default,
  discriminatedUnion: () => discriminatedUnionType,
  effect: () => effectsType,
  enum: () => enumType,
  function: () => functionType,
  getErrorMap: () => getErrorMap,
  getParsedType: () => getParsedType,
  instanceof: () => instanceOfType,
  intersection: () => intersectionType,
  isAborted: () => isAborted,
  isAsync: () => isAsync,
  isDirty: () => isDirty,
  isValid: () => isValid,
  late: () => late,
  lazy: () => lazyType,
  literal: () => literalType,
  makeIssue: () => makeIssue,
  map: () => mapType,
  nan: () => nanType,
  nativeEnum: () => nativeEnumType,
  never: () => neverType,
  null: () => nullType,
  nullable: () => nullableType,
  number: () => numberType,
  object: () => objectType,
  objectUtil: () => objectUtil,
  oboolean: () => oboolean,
  onumber: () => onumber,
  optional: () => optionalType,
  ostring: () => ostring,
  pipeline: () => pipelineType,
  preprocess: () => preprocessType,
  promise: () => promiseType,
  quotelessJson: () => quotelessJson,
  record: () => recordType,
  set: () => setType,
  setErrorMap: () => setErrorMap,
  strictObject: () => strictObjectType,
  string: () => stringType,
  symbol: () => symbolType,
  transformer: () => effectsType,
  tuple: () => tupleType,
  undefined: () => undefinedType,
  union: () => unionType,
  unknown: () => unknownType,
  util: () => util,
  void: () => voidType
});

// ../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/helpers/util.js
var util;
(function(util2) {
  util2.assertEqual = (_) => {
  };
  function assertIs(_arg) {
  }
  util2.assertIs = assertIs;
  function assertNever(_x) {
    throw new Error();
  }
  util2.assertNever = assertNever;
  util2.arrayToEnum = (items) => {
    const obj = {};
    for (const item of items) {
      obj[item] = item;
    }
    return obj;
  };
  util2.getValidEnumValues = (obj) => {
    const validKeys = util2.objectKeys(obj).filter((k) => typeof obj[obj[k]] !== "number");
    const filtered = {};
    for (const k of validKeys) {
      filtered[k] = obj[k];
    }
    return util2.objectValues(filtered);
  };
  util2.objectValues = (obj) => {
    return util2.objectKeys(obj).map(function(e) {
      return obj[e];
    });
  };
  util2.objectKeys = typeof Object.keys === "function" ? (obj) => Object.keys(obj) : (object) => {
    const keys = [];
    for (const key in object) {
      if (Object.prototype.hasOwnProperty.call(object, key)) {
        keys.push(key);
      }
    }
    return keys;
  };
  util2.find = (arr, checker) => {
    for (const item of arr) {
      if (checker(item))
        return item;
    }
    return void 0;
  };
  util2.isInteger = typeof Number.isInteger === "function" ? (val) => Number.isInteger(val) : (val) => typeof val === "number" && Number.isFinite(val) && Math.floor(val) === val;
  function joinValues(array, separator = " | ") {
    return array.map((val) => typeof val === "string" ? `'${val}'` : val).join(separator);
  }
  util2.joinValues = joinValues;
  util2.jsonStringifyReplacer = (_, value) => {
    if (typeof value === "bigint") {
      return value.toString();
    }
    return value;
  };
})(util || (util = {}));
var objectUtil;
(function(objectUtil2) {
  objectUtil2.mergeShapes = (first, second) => {
    return {
      ...first,
      ...second
      // second overwrites first
    };
  };
})(objectUtil || (objectUtil = {}));
var ZodParsedType = util.arrayToEnum([
  "string",
  "nan",
  "number",
  "integer",
  "float",
  "boolean",
  "date",
  "bigint",
  "symbol",
  "function",
  "undefined",
  "null",
  "array",
  "object",
  "unknown",
  "promise",
  "void",
  "never",
  "map",
  "set"
]);
var getParsedType = (data) => {
  const t = typeof data;
  switch (t) {
    case "undefined":
      return ZodParsedType.undefined;
    case "string":
      return ZodParsedType.string;
    case "number":
      return Number.isNaN(data) ? ZodParsedType.nan : ZodParsedType.number;
    case "boolean":
      return ZodParsedType.boolean;
    case "function":
      return ZodParsedType.function;
    case "bigint":
      return ZodParsedType.bigint;
    case "symbol":
      return ZodParsedType.symbol;
    case "object":
      if (Array.isArray(data)) {
        return ZodParsedType.array;
      }
      if (data === null) {
        return ZodParsedType.null;
      }
      if (data.then && typeof data.then === "function" && data.catch && typeof data.catch === "function") {
        return ZodParsedType.promise;
      }
      if (typeof Map !== "undefined" && data instanceof Map) {
        return ZodParsedType.map;
      }
      if (typeof Set !== "undefined" && data instanceof Set) {
        return ZodParsedType.set;
      }
      if (typeof Date !== "undefined" && data instanceof Date) {
        return ZodParsedType.date;
      }
      return ZodParsedType.object;
    default:
      return ZodParsedType.unknown;
  }
};

// ../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/ZodError.js
var ZodIssueCode = util.arrayToEnum([
  "invalid_type",
  "invalid_literal",
  "custom",
  "invalid_union",
  "invalid_union_discriminator",
  "invalid_enum_value",
  "unrecognized_keys",
  "invalid_arguments",
  "invalid_return_type",
  "invalid_date",
  "invalid_string",
  "too_small",
  "too_big",
  "invalid_intersection_types",
  "not_multiple_of",
  "not_finite"
]);
var quotelessJson = (obj) => {
  const json = JSON.stringify(obj, null, 2);
  return json.replace(/"([^"]+)":/g, "$1:");
};
var ZodError = class _ZodError extends Error {
  get errors() {
    return this.issues;
  }
  constructor(issues) {
    super();
    this.issues = [];
    this.addIssue = (sub) => {
      this.issues = [...this.issues, sub];
    };
    this.addIssues = (subs = []) => {
      this.issues = [...this.issues, ...subs];
    };
    const actualProto = new.target.prototype;
    if (Object.setPrototypeOf) {
      Object.setPrototypeOf(this, actualProto);
    } else {
      this.__proto__ = actualProto;
    }
    this.name = "ZodError";
    this.issues = issues;
  }
  format(_mapper) {
    const mapper = _mapper || function(issue) {
      return issue.message;
    };
    const fieldErrors = { _errors: [] };
    const processError = (error) => {
      for (const issue of error.issues) {
        if (issue.code === "invalid_union") {
          issue.unionErrors.map(processError);
        } else if (issue.code === "invalid_return_type") {
          processError(issue.returnTypeError);
        } else if (issue.code === "invalid_arguments") {
          processError(issue.argumentsError);
        } else if (issue.path.length === 0) {
          fieldErrors._errors.push(mapper(issue));
        } else {
          let curr = fieldErrors;
          let i = 0;
          while (i < issue.path.length) {
            const el = issue.path[i];
            const terminal = i === issue.path.length - 1;
            if (!terminal) {
              curr[el] = curr[el] || { _errors: [] };
            } else {
              curr[el] = curr[el] || { _errors: [] };
              curr[el]._errors.push(mapper(issue));
            }
            curr = curr[el];
            i++;
          }
        }
      }
    };
    processError(this);
    return fieldErrors;
  }
  static assert(value) {
    if (!(value instanceof _ZodError)) {
      throw new Error(`Not a ZodError: ${value}`);
    }
  }
  toString() {
    return this.message;
  }
  get message() {
    return JSON.stringify(this.issues, util.jsonStringifyReplacer, 2);
  }
  get isEmpty() {
    return this.issues.length === 0;
  }
  flatten(mapper = (issue) => issue.message) {
    const fieldErrors = {};
    const formErrors = [];
    for (const sub of this.issues) {
      if (sub.path.length > 0) {
        const firstEl = sub.path[0];
        fieldErrors[firstEl] = fieldErrors[firstEl] || [];
        fieldErrors[firstEl].push(mapper(sub));
      } else {
        formErrors.push(mapper(sub));
      }
    }
    return { formErrors, fieldErrors };
  }
  get formErrors() {
    return this.flatten();
  }
};
ZodError.create = (issues) => {
  const error = new ZodError(issues);
  return error;
};

// ../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/locales/en.js
var errorMap = (issue, _ctx) => {
  let message;
  switch (issue.code) {
    case ZodIssueCode.invalid_type:
      if (issue.received === ZodParsedType.undefined) {
        message = "Required";
      } else {
        message = `Expected ${issue.expected}, received ${issue.received}`;
      }
      break;
    case ZodIssueCode.invalid_literal:
      message = `Invalid literal value, expected ${JSON.stringify(issue.expected, util.jsonStringifyReplacer)}`;
      break;
    case ZodIssueCode.unrecognized_keys:
      message = `Unrecognized key(s) in object: ${util.joinValues(issue.keys, ", ")}`;
      break;
    case ZodIssueCode.invalid_union:
      message = `Invalid input`;
      break;
    case ZodIssueCode.invalid_union_discriminator:
      message = `Invalid discriminator value. Expected ${util.joinValues(issue.options)}`;
      break;
    case ZodIssueCode.invalid_enum_value:
      message = `Invalid enum value. Expected ${util.joinValues(issue.options)}, received '${issue.received}'`;
      break;
    case ZodIssueCode.invalid_arguments:
      message = `Invalid function arguments`;
      break;
    case ZodIssueCode.invalid_return_type:
      message = `Invalid function return type`;
      break;
    case ZodIssueCode.invalid_date:
      message = `Invalid date`;
      break;
    case ZodIssueCode.invalid_string:
      if (typeof issue.validation === "object") {
        if ("includes" in issue.validation) {
          message = `Invalid input: must include "${issue.validation.includes}"`;
          if (typeof issue.validation.position === "number") {
            message = `${message} at one or more positions greater than or equal to ${issue.validation.position}`;
          }
        } else if ("startsWith" in issue.validation) {
          message = `Invalid input: must start with "${issue.validation.startsWith}"`;
        } else if ("endsWith" in issue.validation) {
          message = `Invalid input: must end with "${issue.validation.endsWith}"`;
        } else {
          util.assertNever(issue.validation);
        }
      } else if (issue.validation !== "regex") {
        message = `Invalid ${issue.validation}`;
      } else {
        message = "Invalid";
      }
      break;
    case ZodIssueCode.too_small:
      if (issue.type === "array")
        message = `Array must contain ${issue.exact ? "exactly" : issue.inclusive ? `at least` : `more than`} ${issue.minimum} element(s)`;
      else if (issue.type === "string")
        message = `String must contain ${issue.exact ? "exactly" : issue.inclusive ? `at least` : `over`} ${issue.minimum} character(s)`;
      else if (issue.type === "number")
        message = `Number must be ${issue.exact ? `exactly equal to ` : issue.inclusive ? `greater than or equal to ` : `greater than `}${issue.minimum}`;
      else if (issue.type === "bigint")
        message = `Number must be ${issue.exact ? `exactly equal to ` : issue.inclusive ? `greater than or equal to ` : `greater than `}${issue.minimum}`;
      else if (issue.type === "date")
        message = `Date must be ${issue.exact ? `exactly equal to ` : issue.inclusive ? `greater than or equal to ` : `greater than `}${new Date(Number(issue.minimum))}`;
      else
        message = "Invalid input";
      break;
    case ZodIssueCode.too_big:
      if (issue.type === "array")
        message = `Array must contain ${issue.exact ? `exactly` : issue.inclusive ? `at most` : `less than`} ${issue.maximum} element(s)`;
      else if (issue.type === "string")
        message = `String must contain ${issue.exact ? `exactly` : issue.inclusive ? `at most` : `under`} ${issue.maximum} character(s)`;
      else if (issue.type === "number")
        message = `Number must be ${issue.exact ? `exactly` : issue.inclusive ? `less than or equal to` : `less than`} ${issue.maximum}`;
      else if (issue.type === "bigint")
        message = `BigInt must be ${issue.exact ? `exactly` : issue.inclusive ? `less than or equal to` : `less than`} ${issue.maximum}`;
      else if (issue.type === "date")
        message = `Date must be ${issue.exact ? `exactly` : issue.inclusive ? `smaller than or equal to` : `smaller than`} ${new Date(Number(issue.maximum))}`;
      else
        message = "Invalid input";
      break;
    case ZodIssueCode.custom:
      message = `Invalid input`;
      break;
    case ZodIssueCode.invalid_intersection_types:
      message = `Intersection results could not be merged`;
      break;
    case ZodIssueCode.not_multiple_of:
      message = `Number must be a multiple of ${issue.multipleOf}`;
      break;
    case ZodIssueCode.not_finite:
      message = "Number must be finite";
      break;
    default:
      message = _ctx.defaultError;
      util.assertNever(issue);
  }
  return { message };
};
var en_default = errorMap;

// ../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/errors.js
var overrideErrorMap = en_default;
function setErrorMap(map) {
  overrideErrorMap = map;
}
function getErrorMap() {
  return overrideErrorMap;
}

// ../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/helpers/parseUtil.js
var makeIssue = (params) => {
  const { data, path, errorMaps, issueData } = params;
  const fullPath = [...path, ...issueData.path || []];
  const fullIssue = {
    ...issueData,
    path: fullPath
  };
  if (issueData.message !== void 0) {
    return {
      ...issueData,
      path: fullPath,
      message: issueData.message
    };
  }
  let errorMessage = "";
  const maps = errorMaps.filter((m) => !!m).slice().reverse();
  for (const map of maps) {
    errorMessage = map(fullIssue, { data, defaultError: errorMessage }).message;
  }
  return {
    ...issueData,
    path: fullPath,
    message: errorMessage
  };
};
var EMPTY_PATH = [];
function addIssueToContext(ctx2, issueData) {
  const overrideMap = getErrorMap();
  const issue = makeIssue({
    issueData,
    data: ctx2.data,
    path: ctx2.path,
    errorMaps: [
      ctx2.common.contextualErrorMap,
      // contextual error map is first priority
      ctx2.schemaErrorMap,
      // then schema-bound map if available
      overrideMap,
      // then global override map
      overrideMap === en_default ? void 0 : en_default
      // then global default map
    ].filter((x) => !!x)
  });
  ctx2.common.issues.push(issue);
}
var ParseStatus = class _ParseStatus {
  constructor() {
    this.value = "valid";
  }
  dirty() {
    if (this.value === "valid")
      this.value = "dirty";
  }
  abort() {
    if (this.value !== "aborted")
      this.value = "aborted";
  }
  static mergeArray(status, results) {
    const arrayValue = [];
    for (const s of results) {
      if (s.status === "aborted")
        return INVALID;
      if (s.status === "dirty")
        status.dirty();
      arrayValue.push(s.value);
    }
    return { status: status.value, value: arrayValue };
  }
  static async mergeObjectAsync(status, pairs) {
    const syncPairs = [];
    for (const pair of pairs) {
      const key = await pair.key;
      const value = await pair.value;
      syncPairs.push({
        key,
        value
      });
    }
    return _ParseStatus.mergeObjectSync(status, syncPairs);
  }
  static mergeObjectSync(status, pairs) {
    const finalObject = {};
    for (const pair of pairs) {
      const { key, value } = pair;
      if (key.status === "aborted")
        return INVALID;
      if (value.status === "aborted")
        return INVALID;
      if (key.status === "dirty")
        status.dirty();
      if (value.status === "dirty")
        status.dirty();
      if (key.value !== "__proto__" && (typeof value.value !== "undefined" || pair.alwaysSet)) {
        finalObject[key.value] = value.value;
      }
    }
    return { status: status.value, value: finalObject };
  }
};
var INVALID = Object.freeze({
  status: "aborted"
});
var DIRTY = (value) => ({ status: "dirty", value });
var OK = (value) => ({ status: "valid", value });
var isAborted = (x) => x.status === "aborted";
var isDirty = (x) => x.status === "dirty";
var isValid = (x) => x.status === "valid";
var isAsync = (x) => typeof Promise !== "undefined" && x instanceof Promise;

// ../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/helpers/errorUtil.js
var errorUtil;
(function(errorUtil2) {
  errorUtil2.errToObj = (message) => typeof message === "string" ? { message } : message || {};
  errorUtil2.toString = (message) => typeof message === "string" ? message : message?.message;
})(errorUtil || (errorUtil = {}));

// ../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/types.js
var ParseInputLazyPath = class {
  constructor(parent, value, path, key) {
    this._cachedPath = [];
    this.parent = parent;
    this.data = value;
    this._path = path;
    this._key = key;
  }
  get path() {
    if (!this._cachedPath.length) {
      if (Array.isArray(this._key)) {
        this._cachedPath.push(...this._path, ...this._key);
      } else {
        this._cachedPath.push(...this._path, this._key);
      }
    }
    return this._cachedPath;
  }
};
var handleResult = (ctx2, result) => {
  if (isValid(result)) {
    return { success: true, data: result.value };
  } else {
    if (!ctx2.common.issues.length) {
      throw new Error("Validation failed but no issues detected.");
    }
    return {
      success: false,
      get error() {
        if (this._error)
          return this._error;
        const error = new ZodError(ctx2.common.issues);
        this._error = error;
        return this._error;
      }
    };
  }
};
function processCreateParams(params) {
  if (!params)
    return {};
  const { errorMap: errorMap2, invalid_type_error, required_error, description } = params;
  if (errorMap2 && (invalid_type_error || required_error)) {
    throw new Error(`Can't use "invalid_type_error" or "required_error" in conjunction with custom error map.`);
  }
  if (errorMap2)
    return { errorMap: errorMap2, description };
  const customMap = (iss, ctx2) => {
    const { message } = params;
    if (iss.code === "invalid_enum_value") {
      return { message: message ?? ctx2.defaultError };
    }
    if (typeof ctx2.data === "undefined") {
      return { message: message ?? required_error ?? ctx2.defaultError };
    }
    if (iss.code !== "invalid_type")
      return { message: ctx2.defaultError };
    return { message: message ?? invalid_type_error ?? ctx2.defaultError };
  };
  return { errorMap: customMap, description };
}
var ZodType = class {
  get description() {
    return this._def.description;
  }
  _getType(input) {
    return getParsedType(input.data);
  }
  _getOrReturnCtx(input, ctx2) {
    return ctx2 || {
      common: input.parent.common,
      data: input.data,
      parsedType: getParsedType(input.data),
      schemaErrorMap: this._def.errorMap,
      path: input.path,
      parent: input.parent
    };
  }
  _processInputParams(input) {
    return {
      status: new ParseStatus(),
      ctx: {
        common: input.parent.common,
        data: input.data,
        parsedType: getParsedType(input.data),
        schemaErrorMap: this._def.errorMap,
        path: input.path,
        parent: input.parent
      }
    };
  }
  _parseSync(input) {
    const result = this._parse(input);
    if (isAsync(result)) {
      throw new Error("Synchronous parse encountered promise.");
    }
    return result;
  }
  _parseAsync(input) {
    const result = this._parse(input);
    return Promise.resolve(result);
  }
  parse(data, params) {
    const result = this.safeParse(data, params);
    if (result.success)
      return result.data;
    throw result.error;
  }
  safeParse(data, params) {
    const ctx2 = {
      common: {
        issues: [],
        async: params?.async ?? false,
        contextualErrorMap: params?.errorMap
      },
      path: params?.path || [],
      schemaErrorMap: this._def.errorMap,
      parent: null,
      data,
      parsedType: getParsedType(data)
    };
    const result = this._parseSync({ data, path: ctx2.path, parent: ctx2 });
    return handleResult(ctx2, result);
  }
  "~validate"(data) {
    const ctx2 = {
      common: {
        issues: [],
        async: !!this["~standard"].async
      },
      path: [],
      schemaErrorMap: this._def.errorMap,
      parent: null,
      data,
      parsedType: getParsedType(data)
    };
    if (!this["~standard"].async) {
      try {
        const result = this._parseSync({ data, path: [], parent: ctx2 });
        return isValid(result) ? {
          value: result.value
        } : {
          issues: ctx2.common.issues
        };
      } catch (err) {
        if (err?.message?.toLowerCase()?.includes("encountered")) {
          this["~standard"].async = true;
        }
        ctx2.common = {
          issues: [],
          async: true
        };
      }
    }
    return this._parseAsync({ data, path: [], parent: ctx2 }).then((result) => isValid(result) ? {
      value: result.value
    } : {
      issues: ctx2.common.issues
    });
  }
  async parseAsync(data, params) {
    const result = await this.safeParseAsync(data, params);
    if (result.success)
      return result.data;
    throw result.error;
  }
  async safeParseAsync(data, params) {
    const ctx2 = {
      common: {
        issues: [],
        contextualErrorMap: params?.errorMap,
        async: true
      },
      path: params?.path || [],
      schemaErrorMap: this._def.errorMap,
      parent: null,
      data,
      parsedType: getParsedType(data)
    };
    const maybeAsyncResult = this._parse({ data, path: ctx2.path, parent: ctx2 });
    const result = await (isAsync(maybeAsyncResult) ? maybeAsyncResult : Promise.resolve(maybeAsyncResult));
    return handleResult(ctx2, result);
  }
  refine(check, message) {
    const getIssueProperties = (val) => {
      if (typeof message === "string" || typeof message === "undefined") {
        return { message };
      } else if (typeof message === "function") {
        return message(val);
      } else {
        return message;
      }
    };
    return this._refinement((val, ctx2) => {
      const result = check(val);
      const setError = () => ctx2.addIssue({
        code: ZodIssueCode.custom,
        ...getIssueProperties(val)
      });
      if (typeof Promise !== "undefined" && result instanceof Promise) {
        return result.then((data) => {
          if (!data) {
            setError();
            return false;
          } else {
            return true;
          }
        });
      }
      if (!result) {
        setError();
        return false;
      } else {
        return true;
      }
    });
  }
  refinement(check, refinementData) {
    return this._refinement((val, ctx2) => {
      if (!check(val)) {
        ctx2.addIssue(typeof refinementData === "function" ? refinementData(val, ctx2) : refinementData);
        return false;
      } else {
        return true;
      }
    });
  }
  _refinement(refinement) {
    return new ZodEffects({
      schema: this,
      typeName: ZodFirstPartyTypeKind.ZodEffects,
      effect: { type: "refinement", refinement }
    });
  }
  superRefine(refinement) {
    return this._refinement(refinement);
  }
  constructor(def) {
    this.spa = this.safeParseAsync;
    this._def = def;
    this.parse = this.parse.bind(this);
    this.safeParse = this.safeParse.bind(this);
    this.parseAsync = this.parseAsync.bind(this);
    this.safeParseAsync = this.safeParseAsync.bind(this);
    this.spa = this.spa.bind(this);
    this.refine = this.refine.bind(this);
    this.refinement = this.refinement.bind(this);
    this.superRefine = this.superRefine.bind(this);
    this.optional = this.optional.bind(this);
    this.nullable = this.nullable.bind(this);
    this.nullish = this.nullish.bind(this);
    this.array = this.array.bind(this);
    this.promise = this.promise.bind(this);
    this.or = this.or.bind(this);
    this.and = this.and.bind(this);
    this.transform = this.transform.bind(this);
    this.brand = this.brand.bind(this);
    this.default = this.default.bind(this);
    this.catch = this.catch.bind(this);
    this.describe = this.describe.bind(this);
    this.pipe = this.pipe.bind(this);
    this.readonly = this.readonly.bind(this);
    this.isNullable = this.isNullable.bind(this);
    this.isOptional = this.isOptional.bind(this);
    this["~standard"] = {
      version: 1,
      vendor: "zod",
      validate: (data) => this["~validate"](data)
    };
  }
  optional() {
    return ZodOptional.create(this, this._def);
  }
  nullable() {
    return ZodNullable.create(this, this._def);
  }
  nullish() {
    return this.nullable().optional();
  }
  array() {
    return ZodArray.create(this);
  }
  promise() {
    return ZodPromise.create(this, this._def);
  }
  or(option) {
    return ZodUnion.create([this, option], this._def);
  }
  and(incoming) {
    return ZodIntersection.create(this, incoming, this._def);
  }
  transform(transform) {
    return new ZodEffects({
      ...processCreateParams(this._def),
      schema: this,
      typeName: ZodFirstPartyTypeKind.ZodEffects,
      effect: { type: "transform", transform }
    });
  }
  default(def) {
    const defaultValueFunc = typeof def === "function" ? def : () => def;
    return new ZodDefault({
      ...processCreateParams(this._def),
      innerType: this,
      defaultValue: defaultValueFunc,
      typeName: ZodFirstPartyTypeKind.ZodDefault
    });
  }
  brand() {
    return new ZodBranded({
      typeName: ZodFirstPartyTypeKind.ZodBranded,
      type: this,
      ...processCreateParams(this._def)
    });
  }
  catch(def) {
    const catchValueFunc = typeof def === "function" ? def : () => def;
    return new ZodCatch({
      ...processCreateParams(this._def),
      innerType: this,
      catchValue: catchValueFunc,
      typeName: ZodFirstPartyTypeKind.ZodCatch
    });
  }
  describe(description) {
    const This = this.constructor;
    return new This({
      ...this._def,
      description
    });
  }
  pipe(target) {
    return ZodPipeline.create(this, target);
  }
  readonly() {
    return ZodReadonly.create(this);
  }
  isOptional() {
    return this.safeParse(void 0).success;
  }
  isNullable() {
    return this.safeParse(null).success;
  }
};
var cuidRegex = /^c[^\s-]{8,}$/i;
var cuid2Regex = /^[0-9a-z]+$/;
var ulidRegex = /^[0-9A-HJKMNP-TV-Z]{26}$/i;
var uuidRegex = /^[0-9a-fA-F]{8}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{12}$/i;
var nanoidRegex = /^[a-z0-9_-]{21}$/i;
var jwtRegex = /^[A-Za-z0-9-_]+\.[A-Za-z0-9-_]+\.[A-Za-z0-9-_]*$/;
var durationRegex = /^[-+]?P(?!$)(?:(?:[-+]?\d+Y)|(?:[-+]?\d+[.,]\d+Y$))?(?:(?:[-+]?\d+M)|(?:[-+]?\d+[.,]\d+M$))?(?:(?:[-+]?\d+W)|(?:[-+]?\d+[.,]\d+W$))?(?:(?:[-+]?\d+D)|(?:[-+]?\d+[.,]\d+D$))?(?:T(?=[\d+-])(?:(?:[-+]?\d+H)|(?:[-+]?\d+[.,]\d+H$))?(?:(?:[-+]?\d+M)|(?:[-+]?\d+[.,]\d+M$))?(?:[-+]?\d+(?:[.,]\d+)?S)?)??$/;
var emailRegex = /^(?!\.)(?!.*\.\.)([A-Z0-9_'+\-\.]*)[A-Z0-9_+-]@([A-Z0-9][A-Z0-9\-]*\.)+[A-Z]{2,}$/i;
var _emojiRegex = `^(\\p{Extended_Pictographic}|\\p{Emoji_Component})+$`;
var emojiRegex;
var ipv4Regex = /^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])$/;
var ipv4CidrRegex = /^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\/(3[0-2]|[12]?[0-9])$/;
var ipv6Regex = /^(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))$/;
var ipv6CidrRegex = /^(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))\/(12[0-8]|1[01][0-9]|[1-9]?[0-9])$/;
var base64Regex = /^([0-9a-zA-Z+/]{4})*(([0-9a-zA-Z+/]{2}==)|([0-9a-zA-Z+/]{3}=))?$/;
var base64urlRegex = /^([0-9a-zA-Z-_]{4})*(([0-9a-zA-Z-_]{2}(==)?)|([0-9a-zA-Z-_]{3}(=)?))?$/;
var dateRegexSource = `((\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-((0[13578]|1[02])-(0[1-9]|[12]\\d|3[01])|(0[469]|11)-(0[1-9]|[12]\\d|30)|(02)-(0[1-9]|1\\d|2[0-8])))`;
var dateRegex = new RegExp(`^${dateRegexSource}$`);
function timeRegexSource(args) {
  let secondsRegexSource = `[0-5]\\d`;
  if (args.precision) {
    secondsRegexSource = `${secondsRegexSource}\\.\\d{${args.precision}}`;
  } else if (args.precision == null) {
    secondsRegexSource = `${secondsRegexSource}(\\.\\d+)?`;
  }
  const secondsQuantifier = args.precision ? "+" : "?";
  return `([01]\\d|2[0-3]):[0-5]\\d(:${secondsRegexSource})${secondsQuantifier}`;
}
function timeRegex(args) {
  return new RegExp(`^${timeRegexSource(args)}$`);
}
function datetimeRegex(args) {
  let regex = `${dateRegexSource}T${timeRegexSource(args)}`;
  const opts = [];
  opts.push(args.local ? `Z?` : `Z`);
  if (args.offset)
    opts.push(`([+-]\\d{2}:?\\d{2})`);
  regex = `${regex}(${opts.join("|")})`;
  return new RegExp(`^${regex}$`);
}
function isValidIP(ip, version2) {
  if ((version2 === "v4" || !version2) && ipv4Regex.test(ip)) {
    return true;
  }
  if ((version2 === "v6" || !version2) && ipv6Regex.test(ip)) {
    return true;
  }
  return false;
}
function isValidJWT(jwt, alg) {
  if (!jwtRegex.test(jwt))
    return false;
  try {
    const [header] = jwt.split(".");
    if (!header)
      return false;
    const base64 = header.replace(/-/g, "+").replace(/_/g, "/").padEnd(header.length + (4 - header.length % 4) % 4, "=");
    const decoded = JSON.parse(atob(base64));
    if (typeof decoded !== "object" || decoded === null)
      return false;
    if ("typ" in decoded && decoded?.typ !== "JWT")
      return false;
    if (!decoded.alg)
      return false;
    if (alg && decoded.alg !== alg)
      return false;
    return true;
  } catch {
    return false;
  }
}
function isValidCidr(ip, version2) {
  if ((version2 === "v4" || !version2) && ipv4CidrRegex.test(ip)) {
    return true;
  }
  if ((version2 === "v6" || !version2) && ipv6CidrRegex.test(ip)) {
    return true;
  }
  return false;
}
var ZodString = class _ZodString extends ZodType {
  _parse(input) {
    if (this._def.coerce) {
      input.data = String(input.data);
    }
    const parsedType = this._getType(input);
    if (parsedType !== ZodParsedType.string) {
      const ctx3 = this._getOrReturnCtx(input);
      addIssueToContext(ctx3, {
        code: ZodIssueCode.invalid_type,
        expected: ZodParsedType.string,
        received: ctx3.parsedType
      });
      return INVALID;
    }
    const status = new ParseStatus();
    let ctx2 = void 0;
    for (const check of this._def.checks) {
      if (check.kind === "min") {
        if (input.data.length < check.value) {
          ctx2 = this._getOrReturnCtx(input, ctx2);
          addIssueToContext(ctx2, {
            code: ZodIssueCode.too_small,
            minimum: check.value,
            type: "string",
            inclusive: true,
            exact: false,
            message: check.message
          });
          status.dirty();
        }
      } else if (check.kind === "max") {
        if (input.data.length > check.value) {
          ctx2 = this._getOrReturnCtx(input, ctx2);
          addIssueToContext(ctx2, {
            code: ZodIssueCode.too_big,
            maximum: check.value,
            type: "string",
            inclusive: true,
            exact: false,
            message: check.message
          });
          status.dirty();
        }
      } else if (check.kind === "length") {
        const tooBig = input.data.length > check.value;
        const tooSmall = input.data.length < check.value;
        if (tooBig || tooSmall) {
          ctx2 = this._getOrReturnCtx(input, ctx2);
          if (tooBig) {
            addIssueToContext(ctx2, {
              code: ZodIssueCode.too_big,
              maximum: check.value,
              type: "string",
              inclusive: true,
              exact: true,
              message: check.message
            });
          } else if (tooSmall) {
            addIssueToContext(ctx2, {
              code: ZodIssueCode.too_small,
              minimum: check.value,
              type: "string",
              inclusive: true,
              exact: true,
              message: check.message
            });
          }
          status.dirty();
        }
      } else if (check.kind === "email") {
        if (!emailRegex.test(input.data)) {
          ctx2 = this._getOrReturnCtx(input, ctx2);
          addIssueToContext(ctx2, {
            validation: "email",
            code: ZodIssueCode.invalid_string,
            message: check.message
          });
          status.dirty();
        }
      } else if (check.kind === "emoji") {
        if (!emojiRegex) {
          emojiRegex = new RegExp(_emojiRegex, "u");
        }
        if (!emojiRegex.test(input.data)) {
          ctx2 = this._getOrReturnCtx(input, ctx2);
          addIssueToContext(ctx2, {
            validation: "emoji",
            code: ZodIssueCode.invalid_string,
            message: check.message
          });
          status.dirty();
        }
      } else if (check.kind === "uuid") {
        if (!uuidRegex.test(input.data)) {
          ctx2 = this._getOrReturnCtx(input, ctx2);
          addIssueToContext(ctx2, {
            validation: "uuid",
            code: ZodIssueCode.invalid_string,
            message: check.message
          });
          status.dirty();
        }
      } else if (check.kind === "nanoid") {
        if (!nanoidRegex.test(input.data)) {
          ctx2 = this._getOrReturnCtx(input, ctx2);
          addIssueToContext(ctx2, {
            validation: "nanoid",
            code: ZodIssueCode.invalid_string,
            message: check.message
          });
          status.dirty();
        }
      } else if (check.kind === "cuid") {
        if (!cuidRegex.test(input.data)) {
          ctx2 = this._getOrReturnCtx(input, ctx2);
          addIssueToContext(ctx2, {
            validation: "cuid",
            code: ZodIssueCode.invalid_string,
            message: check.message
          });
          status.dirty();
        }
      } else if (check.kind === "cuid2") {
        if (!cuid2Regex.test(input.data)) {
          ctx2 = this._getOrReturnCtx(input, ctx2);
          addIssueToContext(ctx2, {
            validation: "cuid2",
            code: ZodIssueCode.invalid_string,
            message: check.message
          });
          status.dirty();
        }
      } else if (check.kind === "ulid") {
        if (!ulidRegex.test(input.data)) {
          ctx2 = this._getOrReturnCtx(input, ctx2);
          addIssueToContext(ctx2, {
            validation: "ulid",
            code: ZodIssueCode.invalid_string,
            message: check.message
          });
          status.dirty();
        }
      } else if (check.kind === "url") {
        try {
          new URL(input.data);
        } catch {
          ctx2 = this._getOrReturnCtx(input, ctx2);
          addIssueToContext(ctx2, {
            validation: "url",
            code: ZodIssueCode.invalid_string,
            message: check.message
          });
          status.dirty();
        }
      } else if (check.kind === "regex") {
        check.regex.lastIndex = 0;
        const testResult = check.regex.test(input.data);
        if (!testResult) {
          ctx2 = this._getOrReturnCtx(input, ctx2);
          addIssueToContext(ctx2, {
            validation: "regex",
            code: ZodIssueCode.invalid_string,
            message: check.message
          });
          status.dirty();
        }
      } else if (check.kind === "trim") {
        input.data = input.data.trim();
      } else if (check.kind === "includes") {
        if (!input.data.includes(check.value, check.position)) {
          ctx2 = this._getOrReturnCtx(input, ctx2);
          addIssueToContext(ctx2, {
            code: ZodIssueCode.invalid_string,
            validation: { includes: check.value, position: check.position },
            message: check.message
          });
          status.dirty();
        }
      } else if (check.kind === "toLowerCase") {
        input.data = input.data.toLowerCase();
      } else if (check.kind === "toUpperCase") {
        input.data = input.data.toUpperCase();
      } else if (check.kind === "startsWith") {
        if (!input.data.startsWith(check.value)) {
          ctx2 = this._getOrReturnCtx(input, ctx2);
          addIssueToContext(ctx2, {
            code: ZodIssueCode.invalid_string,
            validation: { startsWith: check.value },
            message: check.message
          });
          status.dirty();
        }
      } else if (check.kind === "endsWith") {
        if (!input.data.endsWith(check.value)) {
          ctx2 = this._getOrReturnCtx(input, ctx2);
          addIssueToContext(ctx2, {
            code: ZodIssueCode.invalid_string,
            validation: { endsWith: check.value },
            message: check.message
          });
          status.dirty();
        }
      } else if (check.kind === "datetime") {
        const regex = datetimeRegex(check);
        if (!regex.test(input.data)) {
          ctx2 = this._getOrReturnCtx(input, ctx2);
          addIssueToContext(ctx2, {
            code: ZodIssueCode.invalid_string,
            validation: "datetime",
            message: check.message
          });
          status.dirty();
        }
      } else if (check.kind === "date") {
        const regex = dateRegex;
        if (!regex.test(input.data)) {
          ctx2 = this._getOrReturnCtx(input, ctx2);
          addIssueToContext(ctx2, {
            code: ZodIssueCode.invalid_string,
            validation: "date",
            message: check.message
          });
          status.dirty();
        }
      } else if (check.kind === "time") {
        const regex = timeRegex(check);
        if (!regex.test(input.data)) {
          ctx2 = this._getOrReturnCtx(input, ctx2);
          addIssueToContext(ctx2, {
            code: ZodIssueCode.invalid_string,
            validation: "time",
            message: check.message
          });
          status.dirty();
        }
      } else if (check.kind === "duration") {
        if (!durationRegex.test(input.data)) {
          ctx2 = this._getOrReturnCtx(input, ctx2);
          addIssueToContext(ctx2, {
            validation: "duration",
            code: ZodIssueCode.invalid_string,
            message: check.message
          });
          status.dirty();
        }
      } else if (check.kind === "ip") {
        if (!isValidIP(input.data, check.version)) {
          ctx2 = this._getOrReturnCtx(input, ctx2);
          addIssueToContext(ctx2, {
            validation: "ip",
            code: ZodIssueCode.invalid_string,
            message: check.message
          });
          status.dirty();
        }
      } else if (check.kind === "jwt") {
        if (!isValidJWT(input.data, check.alg)) {
          ctx2 = this._getOrReturnCtx(input, ctx2);
          addIssueToContext(ctx2, {
            validation: "jwt",
            code: ZodIssueCode.invalid_string,
            message: check.message
          });
          status.dirty();
        }
      } else if (check.kind === "cidr") {
        if (!isValidCidr(input.data, check.version)) {
          ctx2 = this._getOrReturnCtx(input, ctx2);
          addIssueToContext(ctx2, {
            validation: "cidr",
            code: ZodIssueCode.invalid_string,
            message: check.message
          });
          status.dirty();
        }
      } else if (check.kind === "base64") {
        if (!base64Regex.test(input.data)) {
          ctx2 = this._getOrReturnCtx(input, ctx2);
          addIssueToContext(ctx2, {
            validation: "base64",
            code: ZodIssueCode.invalid_string,
            message: check.message
          });
          status.dirty();
        }
      } else if (check.kind === "base64url") {
        if (!base64urlRegex.test(input.data)) {
          ctx2 = this._getOrReturnCtx(input, ctx2);
          addIssueToContext(ctx2, {
            validation: "base64url",
            code: ZodIssueCode.invalid_string,
            message: check.message
          });
          status.dirty();
        }
      } else {
        util.assertNever(check);
      }
    }
    return { status: status.value, value: input.data };
  }
  _regex(regex, validation, message) {
    return this.refinement((data) => regex.test(data), {
      validation,
      code: ZodIssueCode.invalid_string,
      ...errorUtil.errToObj(message)
    });
  }
  _addCheck(check) {
    return new _ZodString({
      ...this._def,
      checks: [...this._def.checks, check]
    });
  }
  email(message) {
    return this._addCheck({ kind: "email", ...errorUtil.errToObj(message) });
  }
  url(message) {
    return this._addCheck({ kind: "url", ...errorUtil.errToObj(message) });
  }
  emoji(message) {
    return this._addCheck({ kind: "emoji", ...errorUtil.errToObj(message) });
  }
  uuid(message) {
    return this._addCheck({ kind: "uuid", ...errorUtil.errToObj(message) });
  }
  nanoid(message) {
    return this._addCheck({ kind: "nanoid", ...errorUtil.errToObj(message) });
  }
  cuid(message) {
    return this._addCheck({ kind: "cuid", ...errorUtil.errToObj(message) });
  }
  cuid2(message) {
    return this._addCheck({ kind: "cuid2", ...errorUtil.errToObj(message) });
  }
  ulid(message) {
    return this._addCheck({ kind: "ulid", ...errorUtil.errToObj(message) });
  }
  base64(message) {
    return this._addCheck({ kind: "base64", ...errorUtil.errToObj(message) });
  }
  base64url(message) {
    return this._addCheck({
      kind: "base64url",
      ...errorUtil.errToObj(message)
    });
  }
  jwt(options) {
    return this._addCheck({ kind: "jwt", ...errorUtil.errToObj(options) });
  }
  ip(options) {
    return this._addCheck({ kind: "ip", ...errorUtil.errToObj(options) });
  }
  cidr(options) {
    return this._addCheck({ kind: "cidr", ...errorUtil.errToObj(options) });
  }
  datetime(options) {
    if (typeof options === "string") {
      return this._addCheck({
        kind: "datetime",
        precision: null,
        offset: false,
        local: false,
        message: options
      });
    }
    return this._addCheck({
      kind: "datetime",
      precision: typeof options?.precision === "undefined" ? null : options?.precision,
      offset: options?.offset ?? false,
      local: options?.local ?? false,
      ...errorUtil.errToObj(options?.message)
    });
  }
  date(message) {
    return this._addCheck({ kind: "date", message });
  }
  time(options) {
    if (typeof options === "string") {
      return this._addCheck({
        kind: "time",
        precision: null,
        message: options
      });
    }
    return this._addCheck({
      kind: "time",
      precision: typeof options?.precision === "undefined" ? null : options?.precision,
      ...errorUtil.errToObj(options?.message)
    });
  }
  duration(message) {
    return this._addCheck({ kind: "duration", ...errorUtil.errToObj(message) });
  }
  regex(regex, message) {
    return this._addCheck({
      kind: "regex",
      regex,
      ...errorUtil.errToObj(message)
    });
  }
  includes(value, options) {
    return this._addCheck({
      kind: "includes",
      value,
      position: options?.position,
      ...errorUtil.errToObj(options?.message)
    });
  }
  startsWith(value, message) {
    return this._addCheck({
      kind: "startsWith",
      value,
      ...errorUtil.errToObj(message)
    });
  }
  endsWith(value, message) {
    return this._addCheck({
      kind: "endsWith",
      value,
      ...errorUtil.errToObj(message)
    });
  }
  min(minLength, message) {
    return this._addCheck({
      kind: "min",
      value: minLength,
      ...errorUtil.errToObj(message)
    });
  }
  max(maxLength, message) {
    return this._addCheck({
      kind: "max",
      value: maxLength,
      ...errorUtil.errToObj(message)
    });
  }
  length(len, message) {
    return this._addCheck({
      kind: "length",
      value: len,
      ...errorUtil.errToObj(message)
    });
  }
  /**
   * Equivalent to `.min(1)`
   */
  nonempty(message) {
    return this.min(1, errorUtil.errToObj(message));
  }
  trim() {
    return new _ZodString({
      ...this._def,
      checks: [...this._def.checks, { kind: "trim" }]
    });
  }
  toLowerCase() {
    return new _ZodString({
      ...this._def,
      checks: [...this._def.checks, { kind: "toLowerCase" }]
    });
  }
  toUpperCase() {
    return new _ZodString({
      ...this._def,
      checks: [...this._def.checks, { kind: "toUpperCase" }]
    });
  }
  get isDatetime() {
    return !!this._def.checks.find((ch) => ch.kind === "datetime");
  }
  get isDate() {
    return !!this._def.checks.find((ch) => ch.kind === "date");
  }
  get isTime() {
    return !!this._def.checks.find((ch) => ch.kind === "time");
  }
  get isDuration() {
    return !!this._def.checks.find((ch) => ch.kind === "duration");
  }
  get isEmail() {
    return !!this._def.checks.find((ch) => ch.kind === "email");
  }
  get isURL() {
    return !!this._def.checks.find((ch) => ch.kind === "url");
  }
  get isEmoji() {
    return !!this._def.checks.find((ch) => ch.kind === "emoji");
  }
  get isUUID() {
    return !!this._def.checks.find((ch) => ch.kind === "uuid");
  }
  get isNANOID() {
    return !!this._def.checks.find((ch) => ch.kind === "nanoid");
  }
  get isCUID() {
    return !!this._def.checks.find((ch) => ch.kind === "cuid");
  }
  get isCUID2() {
    return !!this._def.checks.find((ch) => ch.kind === "cuid2");
  }
  get isULID() {
    return !!this._def.checks.find((ch) => ch.kind === "ulid");
  }
  get isIP() {
    return !!this._def.checks.find((ch) => ch.kind === "ip");
  }
  get isCIDR() {
    return !!this._def.checks.find((ch) => ch.kind === "cidr");
  }
  get isBase64() {
    return !!this._def.checks.find((ch) => ch.kind === "base64");
  }
  get isBase64url() {
    return !!this._def.checks.find((ch) => ch.kind === "base64url");
  }
  get minLength() {
    let min = null;
    for (const ch of this._def.checks) {
      if (ch.kind === "min") {
        if (min === null || ch.value > min)
          min = ch.value;
      }
    }
    return min;
  }
  get maxLength() {
    let max = null;
    for (const ch of this._def.checks) {
      if (ch.kind === "max") {
        if (max === null || ch.value < max)
          max = ch.value;
      }
    }
    return max;
  }
};
ZodString.create = (params) => {
  return new ZodString({
    checks: [],
    typeName: ZodFirstPartyTypeKind.ZodString,
    coerce: params?.coerce ?? false,
    ...processCreateParams(params)
  });
};
function floatSafeRemainder(val, step) {
  const valDecCount = (val.toString().split(".")[1] || "").length;
  const stepDecCount = (step.toString().split(".")[1] || "").length;
  const decCount = valDecCount > stepDecCount ? valDecCount : stepDecCount;
  const valInt = Number.parseInt(val.toFixed(decCount).replace(".", ""));
  const stepInt = Number.parseInt(step.toFixed(decCount).replace(".", ""));
  return valInt % stepInt / 10 ** decCount;
}
var ZodNumber = class _ZodNumber extends ZodType {
  constructor() {
    super(...arguments);
    this.min = this.gte;
    this.max = this.lte;
    this.step = this.multipleOf;
  }
  _parse(input) {
    if (this._def.coerce) {
      input.data = Number(input.data);
    }
    const parsedType = this._getType(input);
    if (parsedType !== ZodParsedType.number) {
      const ctx3 = this._getOrReturnCtx(input);
      addIssueToContext(ctx3, {
        code: ZodIssueCode.invalid_type,
        expected: ZodParsedType.number,
        received: ctx3.parsedType
      });
      return INVALID;
    }
    let ctx2 = void 0;
    const status = new ParseStatus();
    for (const check of this._def.checks) {
      if (check.kind === "int") {
        if (!util.isInteger(input.data)) {
          ctx2 = this._getOrReturnCtx(input, ctx2);
          addIssueToContext(ctx2, {
            code: ZodIssueCode.invalid_type,
            expected: "integer",
            received: "float",
            message: check.message
          });
          status.dirty();
        }
      } else if (check.kind === "min") {
        const tooSmall = check.inclusive ? input.data < check.value : input.data <= check.value;
        if (tooSmall) {
          ctx2 = this._getOrReturnCtx(input, ctx2);
          addIssueToContext(ctx2, {
            code: ZodIssueCode.too_small,
            minimum: check.value,
            type: "number",
            inclusive: check.inclusive,
            exact: false,
            message: check.message
          });
          status.dirty();
        }
      } else if (check.kind === "max") {
        const tooBig = check.inclusive ? input.data > check.value : input.data >= check.value;
        if (tooBig) {
          ctx2 = this._getOrReturnCtx(input, ctx2);
          addIssueToContext(ctx2, {
            code: ZodIssueCode.too_big,
            maximum: check.value,
            type: "number",
            inclusive: check.inclusive,
            exact: false,
            message: check.message
          });
          status.dirty();
        }
      } else if (check.kind === "multipleOf") {
        if (floatSafeRemainder(input.data, check.value) !== 0) {
          ctx2 = this._getOrReturnCtx(input, ctx2);
          addIssueToContext(ctx2, {
            code: ZodIssueCode.not_multiple_of,
            multipleOf: check.value,
            message: check.message
          });
          status.dirty();
        }
      } else if (check.kind === "finite") {
        if (!Number.isFinite(input.data)) {
          ctx2 = this._getOrReturnCtx(input, ctx2);
          addIssueToContext(ctx2, {
            code: ZodIssueCode.not_finite,
            message: check.message
          });
          status.dirty();
        }
      } else {
        util.assertNever(check);
      }
    }
    return { status: status.value, value: input.data };
  }
  gte(value, message) {
    return this.setLimit("min", value, true, errorUtil.toString(message));
  }
  gt(value, message) {
    return this.setLimit("min", value, false, errorUtil.toString(message));
  }
  lte(value, message) {
    return this.setLimit("max", value, true, errorUtil.toString(message));
  }
  lt(value, message) {
    return this.setLimit("max", value, false, errorUtil.toString(message));
  }
  setLimit(kind, value, inclusive, message) {
    return new _ZodNumber({
      ...this._def,
      checks: [
        ...this._def.checks,
        {
          kind,
          value,
          inclusive,
          message: errorUtil.toString(message)
        }
      ]
    });
  }
  _addCheck(check) {
    return new _ZodNumber({
      ...this._def,
      checks: [...this._def.checks, check]
    });
  }
  int(message) {
    return this._addCheck({
      kind: "int",
      message: errorUtil.toString(message)
    });
  }
  positive(message) {
    return this._addCheck({
      kind: "min",
      value: 0,
      inclusive: false,
      message: errorUtil.toString(message)
    });
  }
  negative(message) {
    return this._addCheck({
      kind: "max",
      value: 0,
      inclusive: false,
      message: errorUtil.toString(message)
    });
  }
  nonpositive(message) {
    return this._addCheck({
      kind: "max",
      value: 0,
      inclusive: true,
      message: errorUtil.toString(message)
    });
  }
  nonnegative(message) {
    return this._addCheck({
      kind: "min",
      value: 0,
      inclusive: true,
      message: errorUtil.toString(message)
    });
  }
  multipleOf(value, message) {
    return this._addCheck({
      kind: "multipleOf",
      value,
      message: errorUtil.toString(message)
    });
  }
  finite(message) {
    return this._addCheck({
      kind: "finite",
      message: errorUtil.toString(message)
    });
  }
  safe(message) {
    return this._addCheck({
      kind: "min",
      inclusive: true,
      value: Number.MIN_SAFE_INTEGER,
      message: errorUtil.toString(message)
    })._addCheck({
      kind: "max",
      inclusive: true,
      value: Number.MAX_SAFE_INTEGER,
      message: errorUtil.toString(message)
    });
  }
  get minValue() {
    let min = null;
    for (const ch of this._def.checks) {
      if (ch.kind === "min") {
        if (min === null || ch.value > min)
          min = ch.value;
      }
    }
    return min;
  }
  get maxValue() {
    let max = null;
    for (const ch of this._def.checks) {
      if (ch.kind === "max") {
        if (max === null || ch.value < max)
          max = ch.value;
      }
    }
    return max;
  }
  get isInt() {
    return !!this._def.checks.find((ch) => ch.kind === "int" || ch.kind === "multipleOf" && util.isInteger(ch.value));
  }
  get isFinite() {
    let max = null;
    let min = null;
    for (const ch of this._def.checks) {
      if (ch.kind === "finite" || ch.kind === "int" || ch.kind === "multipleOf") {
        return true;
      } else if (ch.kind === "min") {
        if (min === null || ch.value > min)
          min = ch.value;
      } else if (ch.kind === "max") {
        if (max === null || ch.value < max)
          max = ch.value;
      }
    }
    return Number.isFinite(min) && Number.isFinite(max);
  }
};
ZodNumber.create = (params) => {
  return new ZodNumber({
    checks: [],
    typeName: ZodFirstPartyTypeKind.ZodNumber,
    coerce: params?.coerce || false,
    ...processCreateParams(params)
  });
};
var ZodBigInt = class _ZodBigInt extends ZodType {
  constructor() {
    super(...arguments);
    this.min = this.gte;
    this.max = this.lte;
  }
  _parse(input) {
    if (this._def.coerce) {
      try {
        input.data = BigInt(input.data);
      } catch {
        return this._getInvalidInput(input);
      }
    }
    const parsedType = this._getType(input);
    if (parsedType !== ZodParsedType.bigint) {
      return this._getInvalidInput(input);
    }
    let ctx2 = void 0;
    const status = new ParseStatus();
    for (const check of this._def.checks) {
      if (check.kind === "min") {
        const tooSmall = check.inclusive ? input.data < check.value : input.data <= check.value;
        if (tooSmall) {
          ctx2 = this._getOrReturnCtx(input, ctx2);
          addIssueToContext(ctx2, {
            code: ZodIssueCode.too_small,
            type: "bigint",
            minimum: check.value,
            inclusive: check.inclusive,
            message: check.message
          });
          status.dirty();
        }
      } else if (check.kind === "max") {
        const tooBig = check.inclusive ? input.data > check.value : input.data >= check.value;
        if (tooBig) {
          ctx2 = this._getOrReturnCtx(input, ctx2);
          addIssueToContext(ctx2, {
            code: ZodIssueCode.too_big,
            type: "bigint",
            maximum: check.value,
            inclusive: check.inclusive,
            message: check.message
          });
          status.dirty();
        }
      } else if (check.kind === "multipleOf") {
        if (input.data % check.value !== BigInt(0)) {
          ctx2 = this._getOrReturnCtx(input, ctx2);
          addIssueToContext(ctx2, {
            code: ZodIssueCode.not_multiple_of,
            multipleOf: check.value,
            message: check.message
          });
          status.dirty();
        }
      } else {
        util.assertNever(check);
      }
    }
    return { status: status.value, value: input.data };
  }
  _getInvalidInput(input) {
    const ctx2 = this._getOrReturnCtx(input);
    addIssueToContext(ctx2, {
      code: ZodIssueCode.invalid_type,
      expected: ZodParsedType.bigint,
      received: ctx2.parsedType
    });
    return INVALID;
  }
  gte(value, message) {
    return this.setLimit("min", value, true, errorUtil.toString(message));
  }
  gt(value, message) {
    return this.setLimit("min", value, false, errorUtil.toString(message));
  }
  lte(value, message) {
    return this.setLimit("max", value, true, errorUtil.toString(message));
  }
  lt(value, message) {
    return this.setLimit("max", value, false, errorUtil.toString(message));
  }
  setLimit(kind, value, inclusive, message) {
    return new _ZodBigInt({
      ...this._def,
      checks: [
        ...this._def.checks,
        {
          kind,
          value,
          inclusive,
          message: errorUtil.toString(message)
        }
      ]
    });
  }
  _addCheck(check) {
    return new _ZodBigInt({
      ...this._def,
      checks: [...this._def.checks, check]
    });
  }
  positive(message) {
    return this._addCheck({
      kind: "min",
      value: BigInt(0),
      inclusive: false,
      message: errorUtil.toString(message)
    });
  }
  negative(message) {
    return this._addCheck({
      kind: "max",
      value: BigInt(0),
      inclusive: false,
      message: errorUtil.toString(message)
    });
  }
  nonpositive(message) {
    return this._addCheck({
      kind: "max",
      value: BigInt(0),
      inclusive: true,
      message: errorUtil.toString(message)
    });
  }
  nonnegative(message) {
    return this._addCheck({
      kind: "min",
      value: BigInt(0),
      inclusive: true,
      message: errorUtil.toString(message)
    });
  }
  multipleOf(value, message) {
    return this._addCheck({
      kind: "multipleOf",
      value,
      message: errorUtil.toString(message)
    });
  }
  get minValue() {
    let min = null;
    for (const ch of this._def.checks) {
      if (ch.kind === "min") {
        if (min === null || ch.value > min)
          min = ch.value;
      }
    }
    return min;
  }
  get maxValue() {
    let max = null;
    for (const ch of this._def.checks) {
      if (ch.kind === "max") {
        if (max === null || ch.value < max)
          max = ch.value;
      }
    }
    return max;
  }
};
ZodBigInt.create = (params) => {
  return new ZodBigInt({
    checks: [],
    typeName: ZodFirstPartyTypeKind.ZodBigInt,
    coerce: params?.coerce ?? false,
    ...processCreateParams(params)
  });
};
var ZodBoolean = class extends ZodType {
  _parse(input) {
    if (this._def.coerce) {
      input.data = Boolean(input.data);
    }
    const parsedType = this._getType(input);
    if (parsedType !== ZodParsedType.boolean) {
      const ctx2 = this._getOrReturnCtx(input);
      addIssueToContext(ctx2, {
        code: ZodIssueCode.invalid_type,
        expected: ZodParsedType.boolean,
        received: ctx2.parsedType
      });
      return INVALID;
    }
    return OK(input.data);
  }
};
ZodBoolean.create = (params) => {
  return new ZodBoolean({
    typeName: ZodFirstPartyTypeKind.ZodBoolean,
    coerce: params?.coerce || false,
    ...processCreateParams(params)
  });
};
var ZodDate = class _ZodDate extends ZodType {
  _parse(input) {
    if (this._def.coerce) {
      input.data = new Date(input.data);
    }
    const parsedType = this._getType(input);
    if (parsedType !== ZodParsedType.date) {
      const ctx3 = this._getOrReturnCtx(input);
      addIssueToContext(ctx3, {
        code: ZodIssueCode.invalid_type,
        expected: ZodParsedType.date,
        received: ctx3.parsedType
      });
      return INVALID;
    }
    if (Number.isNaN(input.data.getTime())) {
      const ctx3 = this._getOrReturnCtx(input);
      addIssueToContext(ctx3, {
        code: ZodIssueCode.invalid_date
      });
      return INVALID;
    }
    const status = new ParseStatus();
    let ctx2 = void 0;
    for (const check of this._def.checks) {
      if (check.kind === "min") {
        if (input.data.getTime() < check.value) {
          ctx2 = this._getOrReturnCtx(input, ctx2);
          addIssueToContext(ctx2, {
            code: ZodIssueCode.too_small,
            message: check.message,
            inclusive: true,
            exact: false,
            minimum: check.value,
            type: "date"
          });
          status.dirty();
        }
      } else if (check.kind === "max") {
        if (input.data.getTime() > check.value) {
          ctx2 = this._getOrReturnCtx(input, ctx2);
          addIssueToContext(ctx2, {
            code: ZodIssueCode.too_big,
            message: check.message,
            inclusive: true,
            exact: false,
            maximum: check.value,
            type: "date"
          });
          status.dirty();
        }
      } else {
        util.assertNever(check);
      }
    }
    return {
      status: status.value,
      value: new Date(input.data.getTime())
    };
  }
  _addCheck(check) {
    return new _ZodDate({
      ...this._def,
      checks: [...this._def.checks, check]
    });
  }
  min(minDate, message) {
    return this._addCheck({
      kind: "min",
      value: minDate.getTime(),
      message: errorUtil.toString(message)
    });
  }
  max(maxDate, message) {
    return this._addCheck({
      kind: "max",
      value: maxDate.getTime(),
      message: errorUtil.toString(message)
    });
  }
  get minDate() {
    let min = null;
    for (const ch of this._def.checks) {
      if (ch.kind === "min") {
        if (min === null || ch.value > min)
          min = ch.value;
      }
    }
    return min != null ? new Date(min) : null;
  }
  get maxDate() {
    let max = null;
    for (const ch of this._def.checks) {
      if (ch.kind === "max") {
        if (max === null || ch.value < max)
          max = ch.value;
      }
    }
    return max != null ? new Date(max) : null;
  }
};
ZodDate.create = (params) => {
  return new ZodDate({
    checks: [],
    coerce: params?.coerce || false,
    typeName: ZodFirstPartyTypeKind.ZodDate,
    ...processCreateParams(params)
  });
};
var ZodSymbol = class extends ZodType {
  _parse(input) {
    const parsedType = this._getType(input);
    if (parsedType !== ZodParsedType.symbol) {
      const ctx2 = this._getOrReturnCtx(input);
      addIssueToContext(ctx2, {
        code: ZodIssueCode.invalid_type,
        expected: ZodParsedType.symbol,
        received: ctx2.parsedType
      });
      return INVALID;
    }
    return OK(input.data);
  }
};
ZodSymbol.create = (params) => {
  return new ZodSymbol({
    typeName: ZodFirstPartyTypeKind.ZodSymbol,
    ...processCreateParams(params)
  });
};
var ZodUndefined = class extends ZodType {
  _parse(input) {
    const parsedType = this._getType(input);
    if (parsedType !== ZodParsedType.undefined) {
      const ctx2 = this._getOrReturnCtx(input);
      addIssueToContext(ctx2, {
        code: ZodIssueCode.invalid_type,
        expected: ZodParsedType.undefined,
        received: ctx2.parsedType
      });
      return INVALID;
    }
    return OK(input.data);
  }
};
ZodUndefined.create = (params) => {
  return new ZodUndefined({
    typeName: ZodFirstPartyTypeKind.ZodUndefined,
    ...processCreateParams(params)
  });
};
var ZodNull = class extends ZodType {
  _parse(input) {
    const parsedType = this._getType(input);
    if (parsedType !== ZodParsedType.null) {
      const ctx2 = this._getOrReturnCtx(input);
      addIssueToContext(ctx2, {
        code: ZodIssueCode.invalid_type,
        expected: ZodParsedType.null,
        received: ctx2.parsedType
      });
      return INVALID;
    }
    return OK(input.data);
  }
};
ZodNull.create = (params) => {
  return new ZodNull({
    typeName: ZodFirstPartyTypeKind.ZodNull,
    ...processCreateParams(params)
  });
};
var ZodAny = class extends ZodType {
  constructor() {
    super(...arguments);
    this._any = true;
  }
  _parse(input) {
    return OK(input.data);
  }
};
ZodAny.create = (params) => {
  return new ZodAny({
    typeName: ZodFirstPartyTypeKind.ZodAny,
    ...processCreateParams(params)
  });
};
var ZodUnknown = class extends ZodType {
  constructor() {
    super(...arguments);
    this._unknown = true;
  }
  _parse(input) {
    return OK(input.data);
  }
};
ZodUnknown.create = (params) => {
  return new ZodUnknown({
    typeName: ZodFirstPartyTypeKind.ZodUnknown,
    ...processCreateParams(params)
  });
};
var ZodNever = class extends ZodType {
  _parse(input) {
    const ctx2 = this._getOrReturnCtx(input);
    addIssueToContext(ctx2, {
      code: ZodIssueCode.invalid_type,
      expected: ZodParsedType.never,
      received: ctx2.parsedType
    });
    return INVALID;
  }
};
ZodNever.create = (params) => {
  return new ZodNever({
    typeName: ZodFirstPartyTypeKind.ZodNever,
    ...processCreateParams(params)
  });
};
var ZodVoid = class extends ZodType {
  _parse(input) {
    const parsedType = this._getType(input);
    if (parsedType !== ZodParsedType.undefined) {
      const ctx2 = this._getOrReturnCtx(input);
      addIssueToContext(ctx2, {
        code: ZodIssueCode.invalid_type,
        expected: ZodParsedType.void,
        received: ctx2.parsedType
      });
      return INVALID;
    }
    return OK(input.data);
  }
};
ZodVoid.create = (params) => {
  return new ZodVoid({
    typeName: ZodFirstPartyTypeKind.ZodVoid,
    ...processCreateParams(params)
  });
};
var ZodArray = class _ZodArray extends ZodType {
  _parse(input) {
    const { ctx: ctx2, status } = this._processInputParams(input);
    const def = this._def;
    if (ctx2.parsedType !== ZodParsedType.array) {
      addIssueToContext(ctx2, {
        code: ZodIssueCode.invalid_type,
        expected: ZodParsedType.array,
        received: ctx2.parsedType
      });
      return INVALID;
    }
    if (def.exactLength !== null) {
      const tooBig = ctx2.data.length > def.exactLength.value;
      const tooSmall = ctx2.data.length < def.exactLength.value;
      if (tooBig || tooSmall) {
        addIssueToContext(ctx2, {
          code: tooBig ? ZodIssueCode.too_big : ZodIssueCode.too_small,
          minimum: tooSmall ? def.exactLength.value : void 0,
          maximum: tooBig ? def.exactLength.value : void 0,
          type: "array",
          inclusive: true,
          exact: true,
          message: def.exactLength.message
        });
        status.dirty();
      }
    }
    if (def.minLength !== null) {
      if (ctx2.data.length < def.minLength.value) {
        addIssueToContext(ctx2, {
          code: ZodIssueCode.too_small,
          minimum: def.minLength.value,
          type: "array",
          inclusive: true,
          exact: false,
          message: def.minLength.message
        });
        status.dirty();
      }
    }
    if (def.maxLength !== null) {
      if (ctx2.data.length > def.maxLength.value) {
        addIssueToContext(ctx2, {
          code: ZodIssueCode.too_big,
          maximum: def.maxLength.value,
          type: "array",
          inclusive: true,
          exact: false,
          message: def.maxLength.message
        });
        status.dirty();
      }
    }
    if (ctx2.common.async) {
      return Promise.all([...ctx2.data].map((item, i) => {
        return def.type._parseAsync(new ParseInputLazyPath(ctx2, item, ctx2.path, i));
      })).then((result2) => {
        return ParseStatus.mergeArray(status, result2);
      });
    }
    const result = [...ctx2.data].map((item, i) => {
      return def.type._parseSync(new ParseInputLazyPath(ctx2, item, ctx2.path, i));
    });
    return ParseStatus.mergeArray(status, result);
  }
  get element() {
    return this._def.type;
  }
  min(minLength, message) {
    return new _ZodArray({
      ...this._def,
      minLength: { value: minLength, message: errorUtil.toString(message) }
    });
  }
  max(maxLength, message) {
    return new _ZodArray({
      ...this._def,
      maxLength: { value: maxLength, message: errorUtil.toString(message) }
    });
  }
  length(len, message) {
    return new _ZodArray({
      ...this._def,
      exactLength: { value: len, message: errorUtil.toString(message) }
    });
  }
  nonempty(message) {
    return this.min(1, message);
  }
};
ZodArray.create = (schema, params) => {
  return new ZodArray({
    type: schema,
    minLength: null,
    maxLength: null,
    exactLength: null,
    typeName: ZodFirstPartyTypeKind.ZodArray,
    ...processCreateParams(params)
  });
};
function deepPartialify(schema) {
  if (schema instanceof ZodObject) {
    const newShape = {};
    for (const key in schema.shape) {
      const fieldSchema = schema.shape[key];
      newShape[key] = ZodOptional.create(deepPartialify(fieldSchema));
    }
    return new ZodObject({
      ...schema._def,
      shape: () => newShape
    });
  } else if (schema instanceof ZodArray) {
    return new ZodArray({
      ...schema._def,
      type: deepPartialify(schema.element)
    });
  } else if (schema instanceof ZodOptional) {
    return ZodOptional.create(deepPartialify(schema.unwrap()));
  } else if (schema instanceof ZodNullable) {
    return ZodNullable.create(deepPartialify(schema.unwrap()));
  } else if (schema instanceof ZodTuple) {
    return ZodTuple.create(schema.items.map((item) => deepPartialify(item)));
  } else {
    return schema;
  }
}
var ZodObject = class _ZodObject extends ZodType {
  constructor() {
    super(...arguments);
    this._cached = null;
    this.nonstrict = this.passthrough;
    this.augment = this.extend;
  }
  _getCached() {
    if (this._cached !== null)
      return this._cached;
    const shape = this._def.shape();
    const keys = util.objectKeys(shape);
    this._cached = { shape, keys };
    return this._cached;
  }
  _parse(input) {
    const parsedType = this._getType(input);
    if (parsedType !== ZodParsedType.object) {
      const ctx3 = this._getOrReturnCtx(input);
      addIssueToContext(ctx3, {
        code: ZodIssueCode.invalid_type,
        expected: ZodParsedType.object,
        received: ctx3.parsedType
      });
      return INVALID;
    }
    const { status, ctx: ctx2 } = this._processInputParams(input);
    const { shape, keys: shapeKeys } = this._getCached();
    const extraKeys = [];
    if (!(this._def.catchall instanceof ZodNever && this._def.unknownKeys === "strip")) {
      for (const key in ctx2.data) {
        if (!shapeKeys.includes(key)) {
          extraKeys.push(key);
        }
      }
    }
    const pairs = [];
    for (const key of shapeKeys) {
      const keyValidator = shape[key];
      const value = ctx2.data[key];
      pairs.push({
        key: { status: "valid", value: key },
        value: keyValidator._parse(new ParseInputLazyPath(ctx2, value, ctx2.path, key)),
        alwaysSet: key in ctx2.data
      });
    }
    if (this._def.catchall instanceof ZodNever) {
      const unknownKeys = this._def.unknownKeys;
      if (unknownKeys === "passthrough") {
        for (const key of extraKeys) {
          pairs.push({
            key: { status: "valid", value: key },
            value: { status: "valid", value: ctx2.data[key] }
          });
        }
      } else if (unknownKeys === "strict") {
        if (extraKeys.length > 0) {
          addIssueToContext(ctx2, {
            code: ZodIssueCode.unrecognized_keys,
            keys: extraKeys
          });
          status.dirty();
        }
      } else if (unknownKeys === "strip") {
      } else {
        throw new Error(`Internal ZodObject error: invalid unknownKeys value.`);
      }
    } else {
      const catchall = this._def.catchall;
      for (const key of extraKeys) {
        const value = ctx2.data[key];
        pairs.push({
          key: { status: "valid", value: key },
          value: catchall._parse(
            new ParseInputLazyPath(ctx2, value, ctx2.path, key)
            //, ctx.child(key), value, getParsedType(value)
          ),
          alwaysSet: key in ctx2.data
        });
      }
    }
    if (ctx2.common.async) {
      return Promise.resolve().then(async () => {
        const syncPairs = [];
        for (const pair of pairs) {
          const key = await pair.key;
          const value = await pair.value;
          syncPairs.push({
            key,
            value,
            alwaysSet: pair.alwaysSet
          });
        }
        return syncPairs;
      }).then((syncPairs) => {
        return ParseStatus.mergeObjectSync(status, syncPairs);
      });
    } else {
      return ParseStatus.mergeObjectSync(status, pairs);
    }
  }
  get shape() {
    return this._def.shape();
  }
  strict(message) {
    errorUtil.errToObj;
    return new _ZodObject({
      ...this._def,
      unknownKeys: "strict",
      ...message !== void 0 ? {
        errorMap: (issue, ctx2) => {
          const defaultError = this._def.errorMap?.(issue, ctx2).message ?? ctx2.defaultError;
          if (issue.code === "unrecognized_keys")
            return {
              message: errorUtil.errToObj(message).message ?? defaultError
            };
          return {
            message: defaultError
          };
        }
      } : {}
    });
  }
  strip() {
    return new _ZodObject({
      ...this._def,
      unknownKeys: "strip"
    });
  }
  passthrough() {
    return new _ZodObject({
      ...this._def,
      unknownKeys: "passthrough"
    });
  }
  // const AugmentFactory =
  //   <Def extends ZodObjectDef>(def: Def) =>
  //   <Augmentation extends ZodRawShape>(
  //     augmentation: Augmentation
  //   ): ZodObject<
  //     extendShape<ReturnType<Def["shape"]>, Augmentation>,
  //     Def["unknownKeys"],
  //     Def["catchall"]
  //   > => {
  //     return new ZodObject({
  //       ...def,
  //       shape: () => ({
  //         ...def.shape(),
  //         ...augmentation,
  //       }),
  //     }) as any;
  //   };
  extend(augmentation) {
    return new _ZodObject({
      ...this._def,
      shape: () => ({
        ...this._def.shape(),
        ...augmentation
      })
    });
  }
  /**
   * Prior to zod@1.0.12 there was a bug in the
   * inferred type of merged objects. Please
   * upgrade if you are experiencing issues.
   */
  merge(merging) {
    const merged = new _ZodObject({
      unknownKeys: merging._def.unknownKeys,
      catchall: merging._def.catchall,
      shape: () => ({
        ...this._def.shape(),
        ...merging._def.shape()
      }),
      typeName: ZodFirstPartyTypeKind.ZodObject
    });
    return merged;
  }
  // merge<
  //   Incoming extends AnyZodObject,
  //   Augmentation extends Incoming["shape"],
  //   NewOutput extends {
  //     [k in keyof Augmentation | keyof Output]: k extends keyof Augmentation
  //       ? Augmentation[k]["_output"]
  //       : k extends keyof Output
  //       ? Output[k]
  //       : never;
  //   },
  //   NewInput extends {
  //     [k in keyof Augmentation | keyof Input]: k extends keyof Augmentation
  //       ? Augmentation[k]["_input"]
  //       : k extends keyof Input
  //       ? Input[k]
  //       : never;
  //   }
  // >(
  //   merging: Incoming
  // ): ZodObject<
  //   extendShape<T, ReturnType<Incoming["_def"]["shape"]>>,
  //   Incoming["_def"]["unknownKeys"],
  //   Incoming["_def"]["catchall"],
  //   NewOutput,
  //   NewInput
  // > {
  //   const merged: any = new ZodObject({
  //     unknownKeys: merging._def.unknownKeys,
  //     catchall: merging._def.catchall,
  //     shape: () =>
  //       objectUtil.mergeShapes(this._def.shape(), merging._def.shape()),
  //     typeName: ZodFirstPartyTypeKind.ZodObject,
  //   }) as any;
  //   return merged;
  // }
  setKey(key, schema) {
    return this.augment({ [key]: schema });
  }
  // merge<Incoming extends AnyZodObject>(
  //   merging: Incoming
  // ): //ZodObject<T & Incoming["_shape"], UnknownKeys, Catchall> = (merging) => {
  // ZodObject<
  //   extendShape<T, ReturnType<Incoming["_def"]["shape"]>>,
  //   Incoming["_def"]["unknownKeys"],
  //   Incoming["_def"]["catchall"]
  // > {
  //   // const mergedShape = objectUtil.mergeShapes(
  //   //   this._def.shape(),
  //   //   merging._def.shape()
  //   // );
  //   const merged: any = new ZodObject({
  //     unknownKeys: merging._def.unknownKeys,
  //     catchall: merging._def.catchall,
  //     shape: () =>
  //       objectUtil.mergeShapes(this._def.shape(), merging._def.shape()),
  //     typeName: ZodFirstPartyTypeKind.ZodObject,
  //   }) as any;
  //   return merged;
  // }
  catchall(index2) {
    return new _ZodObject({
      ...this._def,
      catchall: index2
    });
  }
  pick(mask) {
    const shape = {};
    for (const key of util.objectKeys(mask)) {
      if (mask[key] && this.shape[key]) {
        shape[key] = this.shape[key];
      }
    }
    return new _ZodObject({
      ...this._def,
      shape: () => shape
    });
  }
  omit(mask) {
    const shape = {};
    for (const key of util.objectKeys(this.shape)) {
      if (!mask[key]) {
        shape[key] = this.shape[key];
      }
    }
    return new _ZodObject({
      ...this._def,
      shape: () => shape
    });
  }
  /**
   * @deprecated
   */
  deepPartial() {
    return deepPartialify(this);
  }
  partial(mask) {
    const newShape = {};
    for (const key of util.objectKeys(this.shape)) {
      const fieldSchema = this.shape[key];
      if (mask && !mask[key]) {
        newShape[key] = fieldSchema;
      } else {
        newShape[key] = fieldSchema.optional();
      }
    }
    return new _ZodObject({
      ...this._def,
      shape: () => newShape
    });
  }
  required(mask) {
    const newShape = {};
    for (const key of util.objectKeys(this.shape)) {
      if (mask && !mask[key]) {
        newShape[key] = this.shape[key];
      } else {
        const fieldSchema = this.shape[key];
        let newField = fieldSchema;
        while (newField instanceof ZodOptional) {
          newField = newField._def.innerType;
        }
        newShape[key] = newField;
      }
    }
    return new _ZodObject({
      ...this._def,
      shape: () => newShape
    });
  }
  keyof() {
    return createZodEnum(util.objectKeys(this.shape));
  }
};
ZodObject.create = (shape, params) => {
  return new ZodObject({
    shape: () => shape,
    unknownKeys: "strip",
    catchall: ZodNever.create(),
    typeName: ZodFirstPartyTypeKind.ZodObject,
    ...processCreateParams(params)
  });
};
ZodObject.strictCreate = (shape, params) => {
  return new ZodObject({
    shape: () => shape,
    unknownKeys: "strict",
    catchall: ZodNever.create(),
    typeName: ZodFirstPartyTypeKind.ZodObject,
    ...processCreateParams(params)
  });
};
ZodObject.lazycreate = (shape, params) => {
  return new ZodObject({
    shape,
    unknownKeys: "strip",
    catchall: ZodNever.create(),
    typeName: ZodFirstPartyTypeKind.ZodObject,
    ...processCreateParams(params)
  });
};
var ZodUnion = class extends ZodType {
  _parse(input) {
    const { ctx: ctx2 } = this._processInputParams(input);
    const options = this._def.options;
    function handleResults(results) {
      for (const result of results) {
        if (result.result.status === "valid") {
          return result.result;
        }
      }
      for (const result of results) {
        if (result.result.status === "dirty") {
          ctx2.common.issues.push(...result.ctx.common.issues);
          return result.result;
        }
      }
      const unionErrors = results.map((result) => new ZodError(result.ctx.common.issues));
      addIssueToContext(ctx2, {
        code: ZodIssueCode.invalid_union,
        unionErrors
      });
      return INVALID;
    }
    if (ctx2.common.async) {
      return Promise.all(options.map(async (option) => {
        const childCtx = {
          ...ctx2,
          common: {
            ...ctx2.common,
            issues: []
          },
          parent: null
        };
        return {
          result: await option._parseAsync({
            data: ctx2.data,
            path: ctx2.path,
            parent: childCtx
          }),
          ctx: childCtx
        };
      })).then(handleResults);
    } else {
      let dirty = void 0;
      const issues = [];
      for (const option of options) {
        const childCtx = {
          ...ctx2,
          common: {
            ...ctx2.common,
            issues: []
          },
          parent: null
        };
        const result = option._parseSync({
          data: ctx2.data,
          path: ctx2.path,
          parent: childCtx
        });
        if (result.status === "valid") {
          return result;
        } else if (result.status === "dirty" && !dirty) {
          dirty = { result, ctx: childCtx };
        }
        if (childCtx.common.issues.length) {
          issues.push(childCtx.common.issues);
        }
      }
      if (dirty) {
        ctx2.common.issues.push(...dirty.ctx.common.issues);
        return dirty.result;
      }
      const unionErrors = issues.map((issues2) => new ZodError(issues2));
      addIssueToContext(ctx2, {
        code: ZodIssueCode.invalid_union,
        unionErrors
      });
      return INVALID;
    }
  }
  get options() {
    return this._def.options;
  }
};
ZodUnion.create = (types, params) => {
  return new ZodUnion({
    options: types,
    typeName: ZodFirstPartyTypeKind.ZodUnion,
    ...processCreateParams(params)
  });
};
var getDiscriminator = (type) => {
  if (type instanceof ZodLazy) {
    return getDiscriminator(type.schema);
  } else if (type instanceof ZodEffects) {
    return getDiscriminator(type.innerType());
  } else if (type instanceof ZodLiteral) {
    return [type.value];
  } else if (type instanceof ZodEnum) {
    return type.options;
  } else if (type instanceof ZodNativeEnum) {
    return util.objectValues(type.enum);
  } else if (type instanceof ZodDefault) {
    return getDiscriminator(type._def.innerType);
  } else if (type instanceof ZodUndefined) {
    return [void 0];
  } else if (type instanceof ZodNull) {
    return [null];
  } else if (type instanceof ZodOptional) {
    return [void 0, ...getDiscriminator(type.unwrap())];
  } else if (type instanceof ZodNullable) {
    return [null, ...getDiscriminator(type.unwrap())];
  } else if (type instanceof ZodBranded) {
    return getDiscriminator(type.unwrap());
  } else if (type instanceof ZodReadonly) {
    return getDiscriminator(type.unwrap());
  } else if (type instanceof ZodCatch) {
    return getDiscriminator(type._def.innerType);
  } else {
    return [];
  }
};
var ZodDiscriminatedUnion = class _ZodDiscriminatedUnion extends ZodType {
  _parse(input) {
    const { ctx: ctx2 } = this._processInputParams(input);
    if (ctx2.parsedType !== ZodParsedType.object) {
      addIssueToContext(ctx2, {
        code: ZodIssueCode.invalid_type,
        expected: ZodParsedType.object,
        received: ctx2.parsedType
      });
      return INVALID;
    }
    const discriminator = this.discriminator;
    const discriminatorValue = ctx2.data[discriminator];
    const option = this.optionsMap.get(discriminatorValue);
    if (!option) {
      addIssueToContext(ctx2, {
        code: ZodIssueCode.invalid_union_discriminator,
        options: Array.from(this.optionsMap.keys()),
        path: [discriminator]
      });
      return INVALID;
    }
    if (ctx2.common.async) {
      return option._parseAsync({
        data: ctx2.data,
        path: ctx2.path,
        parent: ctx2
      });
    } else {
      return option._parseSync({
        data: ctx2.data,
        path: ctx2.path,
        parent: ctx2
      });
    }
  }
  get discriminator() {
    return this._def.discriminator;
  }
  get options() {
    return this._def.options;
  }
  get optionsMap() {
    return this._def.optionsMap;
  }
  /**
   * The constructor of the discriminated union schema. Its behaviour is very similar to that of the normal z.union() constructor.
   * However, it only allows a union of objects, all of which need to share a discriminator property. This property must
   * have a different value for each object in the union.
   * @param discriminator the name of the discriminator property
   * @param types an array of object schemas
   * @param params
   */
  static create(discriminator, options, params) {
    const optionsMap = /* @__PURE__ */ new Map();
    for (const type of options) {
      const discriminatorValues = getDiscriminator(type.shape[discriminator]);
      if (!discriminatorValues.length) {
        throw new Error(`A discriminator value for key \`${discriminator}\` could not be extracted from all schema options`);
      }
      for (const value of discriminatorValues) {
        if (optionsMap.has(value)) {
          throw new Error(`Discriminator property ${String(discriminator)} has duplicate value ${String(value)}`);
        }
        optionsMap.set(value, type);
      }
    }
    return new _ZodDiscriminatedUnion({
      typeName: ZodFirstPartyTypeKind.ZodDiscriminatedUnion,
      discriminator,
      options,
      optionsMap,
      ...processCreateParams(params)
    });
  }
};
function mergeValues(a, b) {
  const aType = getParsedType(a);
  const bType = getParsedType(b);
  if (a === b) {
    return { valid: true, data: a };
  } else if (aType === ZodParsedType.object && bType === ZodParsedType.object) {
    const bKeys = util.objectKeys(b);
    const sharedKeys = util.objectKeys(a).filter((key) => bKeys.indexOf(key) !== -1);
    const newObj = { ...a, ...b };
    for (const key of sharedKeys) {
      const sharedValue = mergeValues(a[key], b[key]);
      if (!sharedValue.valid) {
        return { valid: false };
      }
      newObj[key] = sharedValue.data;
    }
    return { valid: true, data: newObj };
  } else if (aType === ZodParsedType.array && bType === ZodParsedType.array) {
    if (a.length !== b.length) {
      return { valid: false };
    }
    const newArray = [];
    for (let index2 = 0; index2 < a.length; index2++) {
      const itemA = a[index2];
      const itemB = b[index2];
      const sharedValue = mergeValues(itemA, itemB);
      if (!sharedValue.valid) {
        return { valid: false };
      }
      newArray.push(sharedValue.data);
    }
    return { valid: true, data: newArray };
  } else if (aType === ZodParsedType.date && bType === ZodParsedType.date && +a === +b) {
    return { valid: true, data: a };
  } else {
    return { valid: false };
  }
}
var ZodIntersection = class extends ZodType {
  _parse(input) {
    const { status, ctx: ctx2 } = this._processInputParams(input);
    const handleParsed = (parsedLeft, parsedRight) => {
      if (isAborted(parsedLeft) || isAborted(parsedRight)) {
        return INVALID;
      }
      const merged = mergeValues(parsedLeft.value, parsedRight.value);
      if (!merged.valid) {
        addIssueToContext(ctx2, {
          code: ZodIssueCode.invalid_intersection_types
        });
        return INVALID;
      }
      if (isDirty(parsedLeft) || isDirty(parsedRight)) {
        status.dirty();
      }
      return { status: status.value, value: merged.data };
    };
    if (ctx2.common.async) {
      return Promise.all([
        this._def.left._parseAsync({
          data: ctx2.data,
          path: ctx2.path,
          parent: ctx2
        }),
        this._def.right._parseAsync({
          data: ctx2.data,
          path: ctx2.path,
          parent: ctx2
        })
      ]).then(([left, right]) => handleParsed(left, right));
    } else {
      return handleParsed(this._def.left._parseSync({
        data: ctx2.data,
        path: ctx2.path,
        parent: ctx2
      }), this._def.right._parseSync({
        data: ctx2.data,
        path: ctx2.path,
        parent: ctx2
      }));
    }
  }
};
ZodIntersection.create = (left, right, params) => {
  return new ZodIntersection({
    left,
    right,
    typeName: ZodFirstPartyTypeKind.ZodIntersection,
    ...processCreateParams(params)
  });
};
var ZodTuple = class _ZodTuple extends ZodType {
  _parse(input) {
    const { status, ctx: ctx2 } = this._processInputParams(input);
    if (ctx2.parsedType !== ZodParsedType.array) {
      addIssueToContext(ctx2, {
        code: ZodIssueCode.invalid_type,
        expected: ZodParsedType.array,
        received: ctx2.parsedType
      });
      return INVALID;
    }
    if (ctx2.data.length < this._def.items.length) {
      addIssueToContext(ctx2, {
        code: ZodIssueCode.too_small,
        minimum: this._def.items.length,
        inclusive: true,
        exact: false,
        type: "array"
      });
      return INVALID;
    }
    const rest = this._def.rest;
    if (!rest && ctx2.data.length > this._def.items.length) {
      addIssueToContext(ctx2, {
        code: ZodIssueCode.too_big,
        maximum: this._def.items.length,
        inclusive: true,
        exact: false,
        type: "array"
      });
      status.dirty();
    }
    const items = [...ctx2.data].map((item, itemIndex) => {
      const schema = this._def.items[itemIndex] || this._def.rest;
      if (!schema)
        return null;
      return schema._parse(new ParseInputLazyPath(ctx2, item, ctx2.path, itemIndex));
    }).filter((x) => !!x);
    if (ctx2.common.async) {
      return Promise.all(items).then((results) => {
        return ParseStatus.mergeArray(status, results);
      });
    } else {
      return ParseStatus.mergeArray(status, items);
    }
  }
  get items() {
    return this._def.items;
  }
  rest(rest) {
    return new _ZodTuple({
      ...this._def,
      rest
    });
  }
};
ZodTuple.create = (schemas, params) => {
  if (!Array.isArray(schemas)) {
    throw new Error("You must pass an array of schemas to z.tuple([ ... ])");
  }
  return new ZodTuple({
    items: schemas,
    typeName: ZodFirstPartyTypeKind.ZodTuple,
    rest: null,
    ...processCreateParams(params)
  });
};
var ZodRecord = class _ZodRecord extends ZodType {
  get keySchema() {
    return this._def.keyType;
  }
  get valueSchema() {
    return this._def.valueType;
  }
  _parse(input) {
    const { status, ctx: ctx2 } = this._processInputParams(input);
    if (ctx2.parsedType !== ZodParsedType.object) {
      addIssueToContext(ctx2, {
        code: ZodIssueCode.invalid_type,
        expected: ZodParsedType.object,
        received: ctx2.parsedType
      });
      return INVALID;
    }
    const pairs = [];
    const keyType = this._def.keyType;
    const valueType = this._def.valueType;
    for (const key in ctx2.data) {
      pairs.push({
        key: keyType._parse(new ParseInputLazyPath(ctx2, key, ctx2.path, key)),
        value: valueType._parse(new ParseInputLazyPath(ctx2, ctx2.data[key], ctx2.path, key)),
        alwaysSet: key in ctx2.data
      });
    }
    if (ctx2.common.async) {
      return ParseStatus.mergeObjectAsync(status, pairs);
    } else {
      return ParseStatus.mergeObjectSync(status, pairs);
    }
  }
  get element() {
    return this._def.valueType;
  }
  static create(first, second, third) {
    if (second instanceof ZodType) {
      return new _ZodRecord({
        keyType: first,
        valueType: second,
        typeName: ZodFirstPartyTypeKind.ZodRecord,
        ...processCreateParams(third)
      });
    }
    return new _ZodRecord({
      keyType: ZodString.create(),
      valueType: first,
      typeName: ZodFirstPartyTypeKind.ZodRecord,
      ...processCreateParams(second)
    });
  }
};
var ZodMap = class extends ZodType {
  get keySchema() {
    return this._def.keyType;
  }
  get valueSchema() {
    return this._def.valueType;
  }
  _parse(input) {
    const { status, ctx: ctx2 } = this._processInputParams(input);
    if (ctx2.parsedType !== ZodParsedType.map) {
      addIssueToContext(ctx2, {
        code: ZodIssueCode.invalid_type,
        expected: ZodParsedType.map,
        received: ctx2.parsedType
      });
      return INVALID;
    }
    const keyType = this._def.keyType;
    const valueType = this._def.valueType;
    const pairs = [...ctx2.data.entries()].map(([key, value], index2) => {
      return {
        key: keyType._parse(new ParseInputLazyPath(ctx2, key, ctx2.path, [index2, "key"])),
        value: valueType._parse(new ParseInputLazyPath(ctx2, value, ctx2.path, [index2, "value"]))
      };
    });
    if (ctx2.common.async) {
      const finalMap = /* @__PURE__ */ new Map();
      return Promise.resolve().then(async () => {
        for (const pair of pairs) {
          const key = await pair.key;
          const value = await pair.value;
          if (key.status === "aborted" || value.status === "aborted") {
            return INVALID;
          }
          if (key.status === "dirty" || value.status === "dirty") {
            status.dirty();
          }
          finalMap.set(key.value, value.value);
        }
        return { status: status.value, value: finalMap };
      });
    } else {
      const finalMap = /* @__PURE__ */ new Map();
      for (const pair of pairs) {
        const key = pair.key;
        const value = pair.value;
        if (key.status === "aborted" || value.status === "aborted") {
          return INVALID;
        }
        if (key.status === "dirty" || value.status === "dirty") {
          status.dirty();
        }
        finalMap.set(key.value, value.value);
      }
      return { status: status.value, value: finalMap };
    }
  }
};
ZodMap.create = (keyType, valueType, params) => {
  return new ZodMap({
    valueType,
    keyType,
    typeName: ZodFirstPartyTypeKind.ZodMap,
    ...processCreateParams(params)
  });
};
var ZodSet = class _ZodSet extends ZodType {
  _parse(input) {
    const { status, ctx: ctx2 } = this._processInputParams(input);
    if (ctx2.parsedType !== ZodParsedType.set) {
      addIssueToContext(ctx2, {
        code: ZodIssueCode.invalid_type,
        expected: ZodParsedType.set,
        received: ctx2.parsedType
      });
      return INVALID;
    }
    const def = this._def;
    if (def.minSize !== null) {
      if (ctx2.data.size < def.minSize.value) {
        addIssueToContext(ctx2, {
          code: ZodIssueCode.too_small,
          minimum: def.minSize.value,
          type: "set",
          inclusive: true,
          exact: false,
          message: def.minSize.message
        });
        status.dirty();
      }
    }
    if (def.maxSize !== null) {
      if (ctx2.data.size > def.maxSize.value) {
        addIssueToContext(ctx2, {
          code: ZodIssueCode.too_big,
          maximum: def.maxSize.value,
          type: "set",
          inclusive: true,
          exact: false,
          message: def.maxSize.message
        });
        status.dirty();
      }
    }
    const valueType = this._def.valueType;
    function finalizeSet(elements2) {
      const parsedSet = /* @__PURE__ */ new Set();
      for (const element of elements2) {
        if (element.status === "aborted")
          return INVALID;
        if (element.status === "dirty")
          status.dirty();
        parsedSet.add(element.value);
      }
      return { status: status.value, value: parsedSet };
    }
    const elements = [...ctx2.data.values()].map((item, i) => valueType._parse(new ParseInputLazyPath(ctx2, item, ctx2.path, i)));
    if (ctx2.common.async) {
      return Promise.all(elements).then((elements2) => finalizeSet(elements2));
    } else {
      return finalizeSet(elements);
    }
  }
  min(minSize, message) {
    return new _ZodSet({
      ...this._def,
      minSize: { value: minSize, message: errorUtil.toString(message) }
    });
  }
  max(maxSize, message) {
    return new _ZodSet({
      ...this._def,
      maxSize: { value: maxSize, message: errorUtil.toString(message) }
    });
  }
  size(size, message) {
    return this.min(size, message).max(size, message);
  }
  nonempty(message) {
    return this.min(1, message);
  }
};
ZodSet.create = (valueType, params) => {
  return new ZodSet({
    valueType,
    minSize: null,
    maxSize: null,
    typeName: ZodFirstPartyTypeKind.ZodSet,
    ...processCreateParams(params)
  });
};
var ZodFunction = class _ZodFunction extends ZodType {
  constructor() {
    super(...arguments);
    this.validate = this.implement;
  }
  _parse(input) {
    const { ctx: ctx2 } = this._processInputParams(input);
    if (ctx2.parsedType !== ZodParsedType.function) {
      addIssueToContext(ctx2, {
        code: ZodIssueCode.invalid_type,
        expected: ZodParsedType.function,
        received: ctx2.parsedType
      });
      return INVALID;
    }
    function makeArgsIssue(args, error) {
      return makeIssue({
        data: args,
        path: ctx2.path,
        errorMaps: [ctx2.common.contextualErrorMap, ctx2.schemaErrorMap, getErrorMap(), en_default].filter((x) => !!x),
        issueData: {
          code: ZodIssueCode.invalid_arguments,
          argumentsError: error
        }
      });
    }
    function makeReturnsIssue(returns, error) {
      return makeIssue({
        data: returns,
        path: ctx2.path,
        errorMaps: [ctx2.common.contextualErrorMap, ctx2.schemaErrorMap, getErrorMap(), en_default].filter((x) => !!x),
        issueData: {
          code: ZodIssueCode.invalid_return_type,
          returnTypeError: error
        }
      });
    }
    const params = { errorMap: ctx2.common.contextualErrorMap };
    const fn = ctx2.data;
    if (this._def.returns instanceof ZodPromise) {
      const me = this;
      return OK(async function(...args) {
        const error = new ZodError([]);
        const parsedArgs = await me._def.args.parseAsync(args, params).catch((e) => {
          error.addIssue(makeArgsIssue(args, e));
          throw error;
        });
        const result = await Reflect.apply(fn, this, parsedArgs);
        const parsedReturns = await me._def.returns._def.type.parseAsync(result, params).catch((e) => {
          error.addIssue(makeReturnsIssue(result, e));
          throw error;
        });
        return parsedReturns;
      });
    } else {
      const me = this;
      return OK(function(...args) {
        const parsedArgs = me._def.args.safeParse(args, params);
        if (!parsedArgs.success) {
          throw new ZodError([makeArgsIssue(args, parsedArgs.error)]);
        }
        const result = Reflect.apply(fn, this, parsedArgs.data);
        const parsedReturns = me._def.returns.safeParse(result, params);
        if (!parsedReturns.success) {
          throw new ZodError([makeReturnsIssue(result, parsedReturns.error)]);
        }
        return parsedReturns.data;
      });
    }
  }
  parameters() {
    return this._def.args;
  }
  returnType() {
    return this._def.returns;
  }
  args(...items) {
    return new _ZodFunction({
      ...this._def,
      args: ZodTuple.create(items).rest(ZodUnknown.create())
    });
  }
  returns(returnType) {
    return new _ZodFunction({
      ...this._def,
      returns: returnType
    });
  }
  implement(func) {
    const validatedFunc = this.parse(func);
    return validatedFunc;
  }
  strictImplement(func) {
    const validatedFunc = this.parse(func);
    return validatedFunc;
  }
  static create(args, returns, params) {
    return new _ZodFunction({
      args: args ? args : ZodTuple.create([]).rest(ZodUnknown.create()),
      returns: returns || ZodUnknown.create(),
      typeName: ZodFirstPartyTypeKind.ZodFunction,
      ...processCreateParams(params)
    });
  }
};
var ZodLazy = class extends ZodType {
  get schema() {
    return this._def.getter();
  }
  _parse(input) {
    const { ctx: ctx2 } = this._processInputParams(input);
    const lazySchema = this._def.getter();
    return lazySchema._parse({ data: ctx2.data, path: ctx2.path, parent: ctx2 });
  }
};
ZodLazy.create = (getter, params) => {
  return new ZodLazy({
    getter,
    typeName: ZodFirstPartyTypeKind.ZodLazy,
    ...processCreateParams(params)
  });
};
var ZodLiteral = class extends ZodType {
  _parse(input) {
    if (input.data !== this._def.value) {
      const ctx2 = this._getOrReturnCtx(input);
      addIssueToContext(ctx2, {
        received: ctx2.data,
        code: ZodIssueCode.invalid_literal,
        expected: this._def.value
      });
      return INVALID;
    }
    return { status: "valid", value: input.data };
  }
  get value() {
    return this._def.value;
  }
};
ZodLiteral.create = (value, params) => {
  return new ZodLiteral({
    value,
    typeName: ZodFirstPartyTypeKind.ZodLiteral,
    ...processCreateParams(params)
  });
};
function createZodEnum(values, params) {
  return new ZodEnum({
    values,
    typeName: ZodFirstPartyTypeKind.ZodEnum,
    ...processCreateParams(params)
  });
}
var ZodEnum = class _ZodEnum extends ZodType {
  _parse(input) {
    if (typeof input.data !== "string") {
      const ctx2 = this._getOrReturnCtx(input);
      const expectedValues = this._def.values;
      addIssueToContext(ctx2, {
        expected: util.joinValues(expectedValues),
        received: ctx2.parsedType,
        code: ZodIssueCode.invalid_type
      });
      return INVALID;
    }
    if (!this._cache) {
      this._cache = new Set(this._def.values);
    }
    if (!this._cache.has(input.data)) {
      const ctx2 = this._getOrReturnCtx(input);
      const expectedValues = this._def.values;
      addIssueToContext(ctx2, {
        received: ctx2.data,
        code: ZodIssueCode.invalid_enum_value,
        options: expectedValues
      });
      return INVALID;
    }
    return OK(input.data);
  }
  get options() {
    return this._def.values;
  }
  get enum() {
    const enumValues = {};
    for (const val of this._def.values) {
      enumValues[val] = val;
    }
    return enumValues;
  }
  get Values() {
    const enumValues = {};
    for (const val of this._def.values) {
      enumValues[val] = val;
    }
    return enumValues;
  }
  get Enum() {
    const enumValues = {};
    for (const val of this._def.values) {
      enumValues[val] = val;
    }
    return enumValues;
  }
  extract(values, newDef = this._def) {
    return _ZodEnum.create(values, {
      ...this._def,
      ...newDef
    });
  }
  exclude(values, newDef = this._def) {
    return _ZodEnum.create(this.options.filter((opt) => !values.includes(opt)), {
      ...this._def,
      ...newDef
    });
  }
};
ZodEnum.create = createZodEnum;
var ZodNativeEnum = class extends ZodType {
  _parse(input) {
    const nativeEnumValues = util.getValidEnumValues(this._def.values);
    const ctx2 = this._getOrReturnCtx(input);
    if (ctx2.parsedType !== ZodParsedType.string && ctx2.parsedType !== ZodParsedType.number) {
      const expectedValues = util.objectValues(nativeEnumValues);
      addIssueToContext(ctx2, {
        expected: util.joinValues(expectedValues),
        received: ctx2.parsedType,
        code: ZodIssueCode.invalid_type
      });
      return INVALID;
    }
    if (!this._cache) {
      this._cache = new Set(util.getValidEnumValues(this._def.values));
    }
    if (!this._cache.has(input.data)) {
      const expectedValues = util.objectValues(nativeEnumValues);
      addIssueToContext(ctx2, {
        received: ctx2.data,
        code: ZodIssueCode.invalid_enum_value,
        options: expectedValues
      });
      return INVALID;
    }
    return OK(input.data);
  }
  get enum() {
    return this._def.values;
  }
};
ZodNativeEnum.create = (values, params) => {
  return new ZodNativeEnum({
    values,
    typeName: ZodFirstPartyTypeKind.ZodNativeEnum,
    ...processCreateParams(params)
  });
};
var ZodPromise = class extends ZodType {
  unwrap() {
    return this._def.type;
  }
  _parse(input) {
    const { ctx: ctx2 } = this._processInputParams(input);
    if (ctx2.parsedType !== ZodParsedType.promise && ctx2.common.async === false) {
      addIssueToContext(ctx2, {
        code: ZodIssueCode.invalid_type,
        expected: ZodParsedType.promise,
        received: ctx2.parsedType
      });
      return INVALID;
    }
    const promisified = ctx2.parsedType === ZodParsedType.promise ? ctx2.data : Promise.resolve(ctx2.data);
    return OK(promisified.then((data) => {
      return this._def.type.parseAsync(data, {
        path: ctx2.path,
        errorMap: ctx2.common.contextualErrorMap
      });
    }));
  }
};
ZodPromise.create = (schema, params) => {
  return new ZodPromise({
    type: schema,
    typeName: ZodFirstPartyTypeKind.ZodPromise,
    ...processCreateParams(params)
  });
};
var ZodEffects = class extends ZodType {
  innerType() {
    return this._def.schema;
  }
  sourceType() {
    return this._def.schema._def.typeName === ZodFirstPartyTypeKind.ZodEffects ? this._def.schema.sourceType() : this._def.schema;
  }
  _parse(input) {
    const { status, ctx: ctx2 } = this._processInputParams(input);
    const effect = this._def.effect || null;
    const checkCtx = {
      addIssue: (arg) => {
        addIssueToContext(ctx2, arg);
        if (arg.fatal) {
          status.abort();
        } else {
          status.dirty();
        }
      },
      get path() {
        return ctx2.path;
      }
    };
    checkCtx.addIssue = checkCtx.addIssue.bind(checkCtx);
    if (effect.type === "preprocess") {
      const processed = effect.transform(ctx2.data, checkCtx);
      if (ctx2.common.async) {
        return Promise.resolve(processed).then(async (processed2) => {
          if (status.value === "aborted")
            return INVALID;
          const result = await this._def.schema._parseAsync({
            data: processed2,
            path: ctx2.path,
            parent: ctx2
          });
          if (result.status === "aborted")
            return INVALID;
          if (result.status === "dirty")
            return DIRTY(result.value);
          if (status.value === "dirty")
            return DIRTY(result.value);
          return result;
        });
      } else {
        if (status.value === "aborted")
          return INVALID;
        const result = this._def.schema._parseSync({
          data: processed,
          path: ctx2.path,
          parent: ctx2
        });
        if (result.status === "aborted")
          return INVALID;
        if (result.status === "dirty")
          return DIRTY(result.value);
        if (status.value === "dirty")
          return DIRTY(result.value);
        return result;
      }
    }
    if (effect.type === "refinement") {
      const executeRefinement = (acc) => {
        const result = effect.refinement(acc, checkCtx);
        if (ctx2.common.async) {
          return Promise.resolve(result);
        }
        if (result instanceof Promise) {
          throw new Error("Async refinement encountered during synchronous parse operation. Use .parseAsync instead.");
        }
        return acc;
      };
      if (ctx2.common.async === false) {
        const inner = this._def.schema._parseSync({
          data: ctx2.data,
          path: ctx2.path,
          parent: ctx2
        });
        if (inner.status === "aborted")
          return INVALID;
        if (inner.status === "dirty")
          status.dirty();
        executeRefinement(inner.value);
        return { status: status.value, value: inner.value };
      } else {
        return this._def.schema._parseAsync({ data: ctx2.data, path: ctx2.path, parent: ctx2 }).then((inner) => {
          if (inner.status === "aborted")
            return INVALID;
          if (inner.status === "dirty")
            status.dirty();
          return executeRefinement(inner.value).then(() => {
            return { status: status.value, value: inner.value };
          });
        });
      }
    }
    if (effect.type === "transform") {
      if (ctx2.common.async === false) {
        const base = this._def.schema._parseSync({
          data: ctx2.data,
          path: ctx2.path,
          parent: ctx2
        });
        if (!isValid(base))
          return INVALID;
        const result = effect.transform(base.value, checkCtx);
        if (result instanceof Promise) {
          throw new Error(`Asynchronous transform encountered during synchronous parse operation. Use .parseAsync instead.`);
        }
        return { status: status.value, value: result };
      } else {
        return this._def.schema._parseAsync({ data: ctx2.data, path: ctx2.path, parent: ctx2 }).then((base) => {
          if (!isValid(base))
            return INVALID;
          return Promise.resolve(effect.transform(base.value, checkCtx)).then((result) => ({
            status: status.value,
            value: result
          }));
        });
      }
    }
    util.assertNever(effect);
  }
};
ZodEffects.create = (schema, effect, params) => {
  return new ZodEffects({
    schema,
    typeName: ZodFirstPartyTypeKind.ZodEffects,
    effect,
    ...processCreateParams(params)
  });
};
ZodEffects.createWithPreprocess = (preprocess, schema, params) => {
  return new ZodEffects({
    schema,
    effect: { type: "preprocess", transform: preprocess },
    typeName: ZodFirstPartyTypeKind.ZodEffects,
    ...processCreateParams(params)
  });
};
var ZodOptional = class extends ZodType {
  _parse(input) {
    const parsedType = this._getType(input);
    if (parsedType === ZodParsedType.undefined) {
      return OK(void 0);
    }
    return this._def.innerType._parse(input);
  }
  unwrap() {
    return this._def.innerType;
  }
};
ZodOptional.create = (type, params) => {
  return new ZodOptional({
    innerType: type,
    typeName: ZodFirstPartyTypeKind.ZodOptional,
    ...processCreateParams(params)
  });
};
var ZodNullable = class extends ZodType {
  _parse(input) {
    const parsedType = this._getType(input);
    if (parsedType === ZodParsedType.null) {
      return OK(null);
    }
    return this._def.innerType._parse(input);
  }
  unwrap() {
    return this._def.innerType;
  }
};
ZodNullable.create = (type, params) => {
  return new ZodNullable({
    innerType: type,
    typeName: ZodFirstPartyTypeKind.ZodNullable,
    ...processCreateParams(params)
  });
};
var ZodDefault = class extends ZodType {
  _parse(input) {
    const { ctx: ctx2 } = this._processInputParams(input);
    let data = ctx2.data;
    if (ctx2.parsedType === ZodParsedType.undefined) {
      data = this._def.defaultValue();
    }
    return this._def.innerType._parse({
      data,
      path: ctx2.path,
      parent: ctx2
    });
  }
  removeDefault() {
    return this._def.innerType;
  }
};
ZodDefault.create = (type, params) => {
  return new ZodDefault({
    innerType: type,
    typeName: ZodFirstPartyTypeKind.ZodDefault,
    defaultValue: typeof params.default === "function" ? params.default : () => params.default,
    ...processCreateParams(params)
  });
};
var ZodCatch = class extends ZodType {
  _parse(input) {
    const { ctx: ctx2 } = this._processInputParams(input);
    const newCtx = {
      ...ctx2,
      common: {
        ...ctx2.common,
        issues: []
      }
    };
    const result = this._def.innerType._parse({
      data: newCtx.data,
      path: newCtx.path,
      parent: {
        ...newCtx
      }
    });
    if (isAsync(result)) {
      return result.then((result2) => {
        return {
          status: "valid",
          value: result2.status === "valid" ? result2.value : this._def.catchValue({
            get error() {
              return new ZodError(newCtx.common.issues);
            },
            input: newCtx.data
          })
        };
      });
    } else {
      return {
        status: "valid",
        value: result.status === "valid" ? result.value : this._def.catchValue({
          get error() {
            return new ZodError(newCtx.common.issues);
          },
          input: newCtx.data
        })
      };
    }
  }
  removeCatch() {
    return this._def.innerType;
  }
};
ZodCatch.create = (type, params) => {
  return new ZodCatch({
    innerType: type,
    typeName: ZodFirstPartyTypeKind.ZodCatch,
    catchValue: typeof params.catch === "function" ? params.catch : () => params.catch,
    ...processCreateParams(params)
  });
};
var ZodNaN = class extends ZodType {
  _parse(input) {
    const parsedType = this._getType(input);
    if (parsedType !== ZodParsedType.nan) {
      const ctx2 = this._getOrReturnCtx(input);
      addIssueToContext(ctx2, {
        code: ZodIssueCode.invalid_type,
        expected: ZodParsedType.nan,
        received: ctx2.parsedType
      });
      return INVALID;
    }
    return { status: "valid", value: input.data };
  }
};
ZodNaN.create = (params) => {
  return new ZodNaN({
    typeName: ZodFirstPartyTypeKind.ZodNaN,
    ...processCreateParams(params)
  });
};
var BRAND = Symbol("zod_brand");
var ZodBranded = class extends ZodType {
  _parse(input) {
    const { ctx: ctx2 } = this._processInputParams(input);
    const data = ctx2.data;
    return this._def.type._parse({
      data,
      path: ctx2.path,
      parent: ctx2
    });
  }
  unwrap() {
    return this._def.type;
  }
};
var ZodPipeline = class _ZodPipeline extends ZodType {
  _parse(input) {
    const { status, ctx: ctx2 } = this._processInputParams(input);
    if (ctx2.common.async) {
      const handleAsync = async () => {
        const inResult = await this._def.in._parseAsync({
          data: ctx2.data,
          path: ctx2.path,
          parent: ctx2
        });
        if (inResult.status === "aborted")
          return INVALID;
        if (inResult.status === "dirty") {
          status.dirty();
          return DIRTY(inResult.value);
        } else {
          return this._def.out._parseAsync({
            data: inResult.value,
            path: ctx2.path,
            parent: ctx2
          });
        }
      };
      return handleAsync();
    } else {
      const inResult = this._def.in._parseSync({
        data: ctx2.data,
        path: ctx2.path,
        parent: ctx2
      });
      if (inResult.status === "aborted")
        return INVALID;
      if (inResult.status === "dirty") {
        status.dirty();
        return {
          status: "dirty",
          value: inResult.value
        };
      } else {
        return this._def.out._parseSync({
          data: inResult.value,
          path: ctx2.path,
          parent: ctx2
        });
      }
    }
  }
  static create(a, b) {
    return new _ZodPipeline({
      in: a,
      out: b,
      typeName: ZodFirstPartyTypeKind.ZodPipeline
    });
  }
};
var ZodReadonly = class extends ZodType {
  _parse(input) {
    const result = this._def.innerType._parse(input);
    const freeze = (data) => {
      if (isValid(data)) {
        data.value = Object.freeze(data.value);
      }
      return data;
    };
    return isAsync(result) ? result.then((data) => freeze(data)) : freeze(result);
  }
  unwrap() {
    return this._def.innerType;
  }
};
ZodReadonly.create = (type, params) => {
  return new ZodReadonly({
    innerType: type,
    typeName: ZodFirstPartyTypeKind.ZodReadonly,
    ...processCreateParams(params)
  });
};
function cleanParams(params, data) {
  const p = typeof params === "function" ? params(data) : typeof params === "string" ? { message: params } : params;
  const p2 = typeof p === "string" ? { message: p } : p;
  return p2;
}
function custom(check, _params = {}, fatal) {
  if (check)
    return ZodAny.create().superRefine((data, ctx2) => {
      const r = check(data);
      if (r instanceof Promise) {
        return r.then((r2) => {
          if (!r2) {
            const params = cleanParams(_params, data);
            const _fatal = params.fatal ?? fatal ?? true;
            ctx2.addIssue({ code: "custom", ...params, fatal: _fatal });
          }
        });
      }
      if (!r) {
        const params = cleanParams(_params, data);
        const _fatal = params.fatal ?? fatal ?? true;
        ctx2.addIssue({ code: "custom", ...params, fatal: _fatal });
      }
      return;
    });
  return ZodAny.create();
}
var late = {
  object: ZodObject.lazycreate
};
var ZodFirstPartyTypeKind;
(function(ZodFirstPartyTypeKind2) {
  ZodFirstPartyTypeKind2["ZodString"] = "ZodString";
  ZodFirstPartyTypeKind2["ZodNumber"] = "ZodNumber";
  ZodFirstPartyTypeKind2["ZodNaN"] = "ZodNaN";
  ZodFirstPartyTypeKind2["ZodBigInt"] = "ZodBigInt";
  ZodFirstPartyTypeKind2["ZodBoolean"] = "ZodBoolean";
  ZodFirstPartyTypeKind2["ZodDate"] = "ZodDate";
  ZodFirstPartyTypeKind2["ZodSymbol"] = "ZodSymbol";
  ZodFirstPartyTypeKind2["ZodUndefined"] = "ZodUndefined";
  ZodFirstPartyTypeKind2["ZodNull"] = "ZodNull";
  ZodFirstPartyTypeKind2["ZodAny"] = "ZodAny";
  ZodFirstPartyTypeKind2["ZodUnknown"] = "ZodUnknown";
  ZodFirstPartyTypeKind2["ZodNever"] = "ZodNever";
  ZodFirstPartyTypeKind2["ZodVoid"] = "ZodVoid";
  ZodFirstPartyTypeKind2["ZodArray"] = "ZodArray";
  ZodFirstPartyTypeKind2["ZodObject"] = "ZodObject";
  ZodFirstPartyTypeKind2["ZodUnion"] = "ZodUnion";
  ZodFirstPartyTypeKind2["ZodDiscriminatedUnion"] = "ZodDiscriminatedUnion";
  ZodFirstPartyTypeKind2["ZodIntersection"] = "ZodIntersection";
  ZodFirstPartyTypeKind2["ZodTuple"] = "ZodTuple";
  ZodFirstPartyTypeKind2["ZodRecord"] = "ZodRecord";
  ZodFirstPartyTypeKind2["ZodMap"] = "ZodMap";
  ZodFirstPartyTypeKind2["ZodSet"] = "ZodSet";
  ZodFirstPartyTypeKind2["ZodFunction"] = "ZodFunction";
  ZodFirstPartyTypeKind2["ZodLazy"] = "ZodLazy";
  ZodFirstPartyTypeKind2["ZodLiteral"] = "ZodLiteral";
  ZodFirstPartyTypeKind2["ZodEnum"] = "ZodEnum";
  ZodFirstPartyTypeKind2["ZodEffects"] = "ZodEffects";
  ZodFirstPartyTypeKind2["ZodNativeEnum"] = "ZodNativeEnum";
  ZodFirstPartyTypeKind2["ZodOptional"] = "ZodOptional";
  ZodFirstPartyTypeKind2["ZodNullable"] = "ZodNullable";
  ZodFirstPartyTypeKind2["ZodDefault"] = "ZodDefault";
  ZodFirstPartyTypeKind2["ZodCatch"] = "ZodCatch";
  ZodFirstPartyTypeKind2["ZodPromise"] = "ZodPromise";
  ZodFirstPartyTypeKind2["ZodBranded"] = "ZodBranded";
  ZodFirstPartyTypeKind2["ZodPipeline"] = "ZodPipeline";
  ZodFirstPartyTypeKind2["ZodReadonly"] = "ZodReadonly";
})(ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {}));
var instanceOfType = (cls, params = {
  message: `Input not instance of ${cls.name}`
}) => custom((data) => data instanceof cls, params);
var stringType = ZodString.create;
var numberType = ZodNumber.create;
var nanType = ZodNaN.create;
var bigIntType = ZodBigInt.create;
var booleanType = ZodBoolean.create;
var dateType = ZodDate.create;
var symbolType = ZodSymbol.create;
var undefinedType = ZodUndefined.create;
var nullType = ZodNull.create;
var anyType = ZodAny.create;
var unknownType = ZodUnknown.create;
var neverType = ZodNever.create;
var voidType = ZodVoid.create;
var arrayType = ZodArray.create;
var objectType = ZodObject.create;
var strictObjectType = ZodObject.strictCreate;
var unionType = ZodUnion.create;
var discriminatedUnionType = ZodDiscriminatedUnion.create;
var intersectionType = ZodIntersection.create;
var tupleType = ZodTuple.create;
var recordType = ZodRecord.create;
var mapType = ZodMap.create;
var setType = ZodSet.create;
var functionType = ZodFunction.create;
var lazyType = ZodLazy.create;
var literalType = ZodLiteral.create;
var enumType = ZodEnum.create;
var nativeEnumType = ZodNativeEnum.create;
var promiseType = ZodPromise.create;
var effectsType = ZodEffects.create;
var optionalType = ZodOptional.create;
var nullableType = ZodNullable.create;
var preprocessType = ZodEffects.createWithPreprocess;
var pipelineType = ZodPipeline.create;
var ostring = () => stringType().optional();
var onumber = () => numberType().optional();
var oboolean = () => booleanType().optional();
var coerce = {
  string: ((arg) => ZodString.create({ ...arg, coerce: true })),
  number: ((arg) => ZodNumber.create({ ...arg, coerce: true })),
  boolean: ((arg) => ZodBoolean.create({
    ...arg,
    coerce: true
  })),
  bigint: ((arg) => ZodBigInt.create({ ...arg, coerce: true })),
  date: ((arg) => ZodDate.create({ ...arg, coerce: true }))
};
var NEVER = INVALID;

// dist/services/analytics.js
var HOUR = 36e5;
var DAY = 24 * HOUR;
var grid = () => Array.from({ length: 7 }, () => Array(24).fill(0));
var iranDay = (d) => (d.getDay() + 1) % 7;
function walkHours(startMs, endMs, add) {
  let t = startMs;
  while (t < endMs) {
    const d = new Date(t);
    const hourEnd = new Date(d.getFullYear(), d.getMonth(), d.getDate(), d.getHours() + 1).getTime();
    const chunk = Math.min(hourEnd, endMs) - t;
    add(iranDay(d), d.getHours(), chunk);
    t += chunk;
  }
}
function heatmap(ctx2, weeks = 8) {
  const to = ctx2.clock();
  const from = to - weeks * 7 * DAY;
  const zoneList = ctx2.db.select().from(zones).orderBy(zones.sort).all();
  const pcCounts = new Map(ctx2.db.select({ zoneId: pcs.zoneId, n: sql`count(*)` }).from(pcs).where(eq(pcs.enabled, true)).groupBy(pcs.zoneId).all().map((r) => [r.zoneId, r.n]));
  const busy = new Map(zoneList.map((z) => [z.id, grid()]));
  const segs = ctx2.db.select({
    zoneId: sessionSegments.zoneId,
    startedAt: sessionSegments.startedAt,
    endedAt: sessionSegments.endedAt
  }).from(sessionSegments).where(and(lte(sessionSegments.startedAt, to), or(isNull(sessionSegments.endedAt), gte(sessionSegments.endedAt, from)))).all();
  for (const seg of segs) {
    const g = busy.get(seg.zoneId);
    if (!g)
      continue;
    walkHours(Math.max(seg.startedAt, from), Math.min(seg.endedAt ?? to, to), (day, hour, ms) => {
      g[day][hour] += ms;
    });
  }
  const total = grid();
  let totalPcs = 0;
  const zonesOut = zoneList.map((z) => {
    const pcCount = pcCounts.get(z.id) ?? 0;
    totalPcs += pcCount;
    const b = busy.get(z.id);
    const cells = b.map((row, day) => row.map((ms, hour) => {
      total[day][hour] += ms;
      return pcCount > 0 ? Math.min(1, ms / (weeks * HOUR * pcCount)) : 0;
    }));
    return { zoneId: z.id, pcCount, cells };
  });
  const totalCells = total.map((row) => row.map((ms) => totalPcs > 0 ? Math.min(1, ms / (weeks * HOUR * totalPcs)) : 0));
  return { from, to, weeks, zones: zonesOut, total: totalCells };
}
function revenue(ctx2, days = 30) {
  const to = ctx2.clock();
  const d0 = new Date(to);
  const from = new Date(d0.getFullYear(), d0.getMonth(), d0.getDate() - (days - 1)).getTime();
  const finished = ctx2.db.select().from(sessions).where(and(eq(sessions.status, "finished"), gte(sessions.endedAt, from), lte(sessions.endedAt, to))).all();
  const dayBuckets = /* @__PURE__ */ new Map();
  for (let i = 0; i < days; i++) {
    dayBuckets.set(new Date(d0.getFullYear(), d0.getMonth(), d0.getDate() - i).getTime(), {
      revenue: 0,
      orderRevenue: 0,
      sessions: 0
    });
  }
  const opBuckets = /* @__PURE__ */ new Map();
  let sessionRevenue = 0;
  for (const s of finished) {
    sessionRevenue += s.totalCost;
    const e = new Date(s.endedAt);
    const key = new Date(e.getFullYear(), e.getMonth(), e.getDate()).getTime();
    const day = dayBuckets.get(key);
    if (day) {
      day.revenue += s.totalCost;
      day.sessions += 1;
    }
    const opKey = s.openedByStaff ?? "self";
    const op = opBuckets.get(opKey) ?? { revenue: 0, sessions: 0 };
    op.revenue += s.totalCost;
    op.sessions += 1;
    opBuckets.set(opKey, op);
  }
  const placed = ctx2.db.select({ total: orders.total, createdAt: orders.createdAt }).from(orders).where(and(eq(orders.branchId, ctx2.branchId), ne(orders.status, "cancelled"), gte(orders.createdAt, from), lte(orders.createdAt, to))).all();
  let orderRevenue = 0;
  for (const o of placed) {
    orderRevenue += o.total;
    const d = new Date(o.createdAt);
    const day = dayBuckets.get(new Date(d.getFullYear(), d.getMonth(), d.getDate()).getTime());
    if (day)
      day.orderRevenue += o.total;
  }
  const byZone = ctx2.db.select({
    zoneId: sessionSegments.zoneId,
    revenue: sql`coalesce(sum(${sessionSegments.cost}), 0)`
  }).from(sessionSegments).innerJoin(sessions, eq(sessionSegments.sessionId, sessions.id)).where(and(eq(sessions.status, "finished"), gte(sessions.endedAt, from), lte(sessions.endedAt, to))).groupBy(sessionSegments.zoneId).orderBy(desc(sql`sum(${sessionSegments.cost})`)).all();
  const staffNames = new Map(ctx2.db.select({ id: staff.id, name: staff.name }).from(staff).all().map((r) => [r.id, r.name]));
  const byOperator = [...opBuckets.entries()].map(([staffId, agg]) => ({
    staffId,
    name: staffId === "self" ? "\u0648\u0631\u0648\u062F \u062E\u0648\u062F \u0645\u0634\u062A\u0631\u06CC" : staffNames.get(staffId) ?? null,
    ...agg
  })).sort((a, b) => b.revenue - a.revenue);
  return {
    from,
    to,
    totalRevenue: sessionRevenue + orderRevenue,
    sessionRevenue,
    orderRevenue,
    sessionCount: finished.length,
    orderCount: placed.length,
    byDay: [...dayBuckets.entries()].map(([day, agg]) => ({ day, ...agg })).sort((a, b) => a.day - b.day),
    byZone,
    byOperator
  };
}
function topGames(ctx2, days = 30, limit = 10) {
  const from = ctx2.clock() - days * DAY;
  return ctx2.db.select({
    gameId: gamePlayEvents.gameId,
    title: games.title,
    seconds: sql`sum(coalesce(${gamePlayEvents.seconds}, 0))`,
    plays: sql`count(*)`,
    sessions: sql`count(distinct ${gamePlayEvents.sessionId})`
  }).from(gamePlayEvents).leftJoin(games, eq(gamePlayEvents.gameId, games.id)).where(gte(gamePlayEvents.startedAt, from)).groupBy(gamePlayEvents.gameId).orderBy(desc(sql`sum(coalesce(${gamePlayEvents.seconds}, 0))`)).limit(limit).all();
}
var hm = (h) => `${String(h % 24).padStart(2, "0")}:00`;
var condKey = (c) => JSON.stringify({
  z: c.zoneIds ?? null,
  d: c.days ?? null,
  s: c.timeStart ?? null,
  e: c.timeEnd ?? null
});
function suggestRules(ctx2, opts = {}) {
  const { weeks = 8, occupancyLt = 0.35, minRunHours = 2, multiplier = 0.8 } = opts;
  const h = heatmap(ctx2, weeks);
  const now = ctx2.clock();
  const envelope = /* @__PURE__ */ new Set();
  for (let hr = 0; hr < 24; hr++) {
    if (h.zones.some((z) => z.cells.some((row) => row[hr] > 0)))
      envelope.add(hr);
  }
  const existing = new Set(ctx2.db.select().from(dynamicPricingRules).all().map((r) => condKey(r.conditions)));
  const zoneNames = new Map(ctx2.db.select().from(zones).all().map((z) => [z.id, z.name]));
  const created = [];
  let skippedExisting = 0;
  for (const z of h.zones) {
    if (z.pcCount === 0)
      continue;
    const runs = /* @__PURE__ */ new Map();
    for (let day = 0; day < 7; day++) {
      let start = -1;
      for (let hr = 0; hr <= 24; hr++) {
        const idle = hr < 24 && envelope.has(hr) && z.cells[day][hr] < occupancyLt;
        if (idle && start === -1)
          start = hr;
        if (!idle && start !== -1) {
          if (hr - start >= minRunHours) {
            const key = `${start}-${hr}`;
            const run = runs.get(key) ?? { start, end: hr, days: [] };
            run.days.push(day);
            runs.set(key, run);
          }
          start = -1;
        }
      }
    }
    for (const run of runs.values()) {
      const days = run.days.length === 7 ? void 0 : run.days;
      const conditions = {
        zoneIds: [z.zoneId],
        ...days ? { days } : {},
        timeStart: hm(run.start),
        timeEnd: hm(run.end),
        occupancyLt
      };
      if (existing.has(condKey(conditions))) {
        skippedExisting++;
        continue;
      }
      const rule = {
        id: uuidv7(now),
        branchId: ctx2.branchId,
        name: `\u067E\u06CC\u0634\u0646\u0647\u0627\u062F: ${zoneNames.get(z.zoneId) ?? z.zoneId} ${hm(run.start)}\u2013${hm(run.end)}${days ? ` (${days.length} \u0631\u0648\u0632)` : ""}`,
        priority: 100,
        enabled: false,
        conditions,
        action: { multiplier },
        floorRate: null
      };
      ctx2.db.insert(dynamicPricingRules).values(rule).run();
      existing.add(condKey(conditions));
      created.push(rule);
    }
  }
  return { created, skippedExisting };
}

// ../../packages/pricing-engine/dist/quote.js
function parseHm(hm2) {
  const [h = 0, m = 0] = hm2.split(":").map(Number);
  return h * 60 + m;
}
function inTimeWindow(minutes, start, end) {
  if (start === void 0 && end === void 0)
    return true;
  const s = start !== void 0 ? parseHm(start) : 0;
  const e = end !== void 0 ? parseHm(end) : 24 * 60;
  return s <= e ? minutes >= s && minutes < e : minutes >= s || minutes < e;
}
function pickCard(cards, zoneId, tier, now) {
  return cards.filter((c) => c.zoneId === zoneId && c.tier === tier && c.effectiveFrom <= now).sort((a, b) => b.effectiveFrom - a.effectiveFrom)[0];
}
function ruleMatches(rule, ctx2) {
  const c = rule.conditions;
  if (!rule.enabled)
    return false;
  if (c.zoneIds && !c.zoneIds.includes(ctx2.zoneId))
    return false;
  if (c.tiers && (ctx2.tier === null || !c.tiers.includes(ctx2.tier)))
    return false;
  if (c.days && !c.days.includes(ctx2.dayOfWeek))
    return false;
  if (!inTimeWindow(ctx2.minutesOfDay, c.timeStart, c.timeEnd))
    return false;
  const occupancy = c.zoneIds ? ctx2.occupancyByZone[ctx2.zoneId] ?? 0 : ctx2.occupancyTotal;
  if (c.occupancyLt !== void 0 && !(occupancy < c.occupancyLt))
    return false;
  if (c.occupancyGte !== void 0 && !(occupancy >= c.occupancyGte))
    return false;
  return true;
}
function quoteRate(ctx2) {
  const baseCard = pickCard(ctx2.rateCards, ctx2.zoneId, null, ctx2.now);
  if (!baseCard) {
    throw new Error(`No base rate card for zone ${ctx2.zoneId}`);
  }
  const base = baseCard.pricePerHour;
  const tierCard = ctx2.tier !== null ? pickCard(ctx2.rateCards, ctx2.zoneId, ctx2.tier, ctx2.now) : void 0;
  const tierAdjusted = tierCard?.pricePerHour ?? base;
  const matched = ctx2.rules.filter((r) => ruleMatches(r, ctx2)).sort((a, b) => a.priority - b.priority)[0];
  let dynamicAdjusted = tierAdjusted;
  const appliedRuleIds = [baseCard.id];
  if (tierCard)
    appliedRuleIds.push(tierCard.id);
  if (matched) {
    const { setRate, multiplier, discount } = matched.action;
    if (setRate !== void 0)
      dynamicAdjusted = setRate;
    else if (multiplier !== void 0)
      dynamicAdjusted = Math.round(tierAdjusted * multiplier);
    else if (discount !== void 0)
      dynamicAdjusted = tierAdjusted - discount;
    const floor = matched.floorRate ?? 0;
    dynamicAdjusted = Math.max(dynamicAdjusted, floor, 0);
    appliedRuleIds.push(matched.id);
  }
  return { ratePerHour: dynamicAdjusted, base, tierAdjusted, dynamicAdjusted, appliedRuleIds };
}

// dist/services/pricing.js
function loadPricingState(ctx2) {
  const rateCards = ctx2.db.select().from(pricingRateCards).all();
  const rules = ctx2.db.select().from(dynamicPricingRules).where(eq(dynamicPricingRules.enabled, true)).all();
  const zoneRows = ctx2.db.select({
    zoneId: pcs.zoneId,
    total: sql`count(*)`,
    busy: sql`sum(case when ${pcs.status} = 'in_session' then 1 else 0 end)`
  }).from(pcs).where(eq(pcs.enabled, true)).groupBy(pcs.zoneId).all();
  const occupancyByZone = {};
  let total = 0;
  let busy = 0;
  for (const z of zoneRows) {
    occupancyByZone[z.zoneId] = z.total > 0 ? z.busy / z.total : 0;
    total += z.total;
    busy += z.busy;
  }
  return {
    rateCards,
    rules: rules.map((r) => ({
      id: r.id,
      priority: r.priority,
      enabled: r.enabled,
      conditions: r.conditions,
      action: r.action,
      floorRate: r.floorRate
    })),
    occupancyByZone,
    occupancyTotal: total > 0 ? busy / total : 0
  };
}
function quoteFor(state, zoneId, tier, now) {
  const d = new Date(now);
  return quoteRate({
    zoneId,
    tier,
    now,
    dayOfWeek: (d.getDay() + 1) % 7,
    minutesOfDay: d.getHours() * 60 + d.getMinutes(),
    occupancyByZone: state.occupancyByZone,
    occupancyTotal: state.occupancyTotal,
    rateCards: state.rateCards,
    rules: state.rules
  });
}

// dist/services/ctx.js
var EngineError = class extends Error {
  code;
  status;
  constructor(code, message, status = 400) {
    super(message);
    this.code = code;
    this.status = status;
    this.name = "EngineError";
  }
};
function writeAudit(ctx2, entry, now = ctx2.clock()) {
  ctx2.db.insert(auditLog).values({
    id: uuidv7(now),
    branchId: ctx2.branchId,
    staffId: entry.staffId,
    action: entry.action,
    entity: entry.entity,
    entityId: entry.entityId ?? null,
    before: entry.before ?? null,
    after: entry.after ?? null,
    createdAt: now
  }).run();
}
function aliasEquivalents(db2, customerId) {
  const alias = db2.select().from(customerAliases).where(eq(customerAliases.provisionalId, customerId)).get();
  const canonical = alias?.canonicalId ?? customerId;
  const provisionals = db2.select({ id: customerAliases.provisionalId }).from(customerAliases).where(eq(customerAliases.canonicalId, canonical)).all().map((r) => r.id);
  return [canonical, ...provisionals];
}
function getSetting(db2, key) {
  const row = db2.select().from(settings).where(eq(settings.key, key)).get();
  return row?.value;
}
function setSetting(db2, key, value, now) {
  db2.insert(settings).values({ key, value, updatedAt: now }).onConflictDoUpdate({ target: settings.key, set: { value, updatedAt: now } }).run();
}

// dist/services/points.js
var POINTS_PER_PLAYED_HOUR_SETTING = "points_per_played_hour";
var POINTS_PER_100K_SPENT_SETTING = "points_per_100k_spent";
var SPEND_BUCKET_TOMAN = 1e5;
var TOMAN_PER_POINT_SETTING = "points_toman_per_point";
var DEFAULT_PER_PLAYED_HOUR = 10;
var DEFAULT_PER_100K_SPENT = 1;
var DEFAULT_TOMAN_PER_POINT = 50;
var PointsService = class {
  ctx;
  constructor(ctx2) {
    this.ctx = ctx2;
  }
  perPlayedHour() {
    return getSetting(this.ctx.db, POINTS_PER_PLAYED_HOUR_SETTING) ?? DEFAULT_PER_PLAYED_HOUR;
  }
  per100kSpent() {
    return getSetting(this.ctx.db, POINTS_PER_100K_SPENT_SETTING) ?? DEFAULT_PER_100K_SPENT;
  }
  tomanPerPoint() {
    return getSetting(this.ctx.db, TOMAN_PER_POINT_SETTING) ?? DEFAULT_TOMAN_PER_POINT;
  }
  /** Union balance: SUM over the customer's alias-equivalence set (cross-branch rows included). */
  balance(customerId) {
    const row = this.ctx.db.select({ sum: sql`coalesce(sum(${pointsLedger.points}), 0)` }).from(pointsLedger).where(inArray(pointsLedger.customerId, aliasEquivalents(this.ctx.db, customerId))).get();
    return row?.sum ?? 0;
  }
  ledger(customerId, limit = 50) {
    return this.ctx.db.select().from(pointsLedger).where(inArray(pointsLedger.customerId, aliasEquivalents(this.ctx.db, customerId))).orderBy(desc(sql`rowid`)).limit(limit).all();
  }
  append(input) {
    if (!Number.isSafeInteger(input.points) || input.points === 0) {
      throw new EngineError("bad_points", "Points entries must have a non-zero integer amount");
    }
    return this.ctx.sqlite.transaction(() => {
      const existing = this.ctx.db.select().from(pointsLedger).where(eq(pointsLedger.idempotencyKey, input.idempotencyKey)).get();
      if (existing) {
        if (existing.customerId !== input.customerId || existing.type !== input.type || existing.points !== input.points) {
          throw new EngineError("idempotency_conflict", "This idempotency key was already used for a different points entry", 409);
        }
        return { entry: existing, deduped: true };
      }
      const now = this.ctx.clock();
      const entry = {
        id: uuidv7(now),
        customerId: input.customerId,
        branchId: this.ctx.branchId,
        type: input.type,
        points: input.points,
        refType: input.refType ?? null,
        refId: input.refId ?? null,
        idempotencyKey: input.idempotencyKey,
        createdAt: now
      };
      this.ctx.db.insert(pointsLedger).values(entry).run();
      this.ctx.db.insert(syncOutbox).values({
        eventId: uuidv7(now),
        aggregateType: "points_ledger",
        aggregateId: entry.id,
        eventType: "points.appended",
        payload: entry,
        createdAt: now
      }).run();
      return { entry, deduped: false };
    })();
  }
  /**
   * Earn (or reverse) spend points for one wallet row. spentToman is signed:
   * positive = money spent, negative = money refunded. floor() both ways — a
   * ±1 point drift on partial refunds is acceptable for loyalty points, as is
   * a briefly negative points balance after a refund.
   */
  earnSpend(customerId, spentToman, walletEntryId, refType, refId) {
    const pts = Math.sign(spentToman) * Math.floor(Math.abs(spentToman) * this.per100kSpent() / SPEND_BUCKET_TOMAN);
    if (pts === 0)
      return;
    this.append({
      customerId,
      type: "earn_spend",
      points: pts,
      refType: refType ?? void 0,
      refId: refId ?? void 0,
      // 1:1 with the wallet row; wallet dedupe short-circuits before this runs again.
      idempotencyKey: `pts:${walletEntryId}`
    });
  }
};

// dist/services/ratelimit.js
var FailureLimiter = class {
  windowMs;
  clock;
  hits = /* @__PURE__ */ new Map();
  constructor(windowMs, clock) {
    this.windowMs = windowMs;
    this.clock = clock;
  }
  /** Throw 429 while `key` is locked out (≥ max failures inside the window). */
  check(key, max) {
    const h = this.hits.get(key);
    if (!h)
      return;
    if (h.resetAt <= this.clock()) {
      this.hits.delete(key);
      return;
    }
    if (h.count >= max) {
      throw new EngineError("rate_limited", "Too many failed attempts \u2014 try again later", 429);
    }
  }
  fail(key) {
    const now = this.clock();
    if (this.hits.size > 1e4) {
      for (const [k, h2] of this.hits)
        if (h2.resetAt <= now)
          this.hits.delete(k);
    }
    const h = this.hits.get(key);
    if (!h || h.resetAt <= now)
      this.hits.set(key, { count: 1, resetAt: now + this.windowMs });
    else
      h.count += 1;
  }
  /** A success clears the key — a legit user who mistyped is not an attacker. */
  clear(key) {
    this.hits.delete(key);
  }
};

// dist/services/passes.js
var PASS_PRICE_SETTING = "station_pass_price";
var PASS_DAYS_SETTING = "station_pass_days";
var DEFAULT_DAYS = 30;
var DAY_MS = 864e5;
function activePass(ctx2, customerId, pcId, now) {
  if (!customerId)
    return void 0;
  return ctx2.db.select().from(stationPasses).where(and(eq(stationPasses.pcId, pcId), inArray(stationPasses.customerId, aliasEquivalents(ctx2.db, customerId)), gt(stationPasses.expiresAt, now))).orderBy(desc(stationPasses.expiresAt)).get();
}
var PassService = class {
  ctx;
  wallet;
  constructor(ctx2, wallet2) {
    this.ctx = ctx2;
    this.wallet = wallet2;
  }
  price() {
    return getSetting(this.ctx.db, PASS_PRICE_SETTING) ?? 0;
  }
  days() {
    return getSetting(this.ctx.db, PASS_DAYS_SETTING) ?? DEFAULT_DAYS;
  }
  /** Every pass that has not expired yet, soonest to expire first. */
  active() {
    return this.ctx.db.select({ pass: stationPasses, pcName: pcs.name, customerName: customers.name }).from(stationPasses).leftJoin(pcs, eq(stationPasses.pcId, pcs.id)).leftJoin(customers, eq(stationPasses.customerId, customers.id)).where(gt(stationPasses.expiresAt, this.ctx.clock())).orderBy(stationPasses.expiresAt).all().map((r) => ({ ...r.pass, pcName: r.pcName, customerName: r.customerName }));
  }
  sell(input) {
    return this.ctx.sqlite.transaction(() => {
      const price = this.price();
      if (price <= 0) {
        throw new EngineError("pass_disabled", "Station passes are not priced on this branch", 409);
      }
      const days = this.days();
      const pc = this.ctx.db.select().from(pcs).where(eq(pcs.id, input.pcId)).get();
      if (!pc)
        throw new EngineError("not_found", `PC ${input.pcId} not found`, 404);
      if (!pc.enabled)
        throw new EngineError("pc_disabled", `${pc.name} is disabled`);
      const customer = this.ctx.db.select().from(customers).where(eq(customers.id, input.customerId)).get();
      if (!customer)
        throw new EngineError("not_found", "Customer not found", 404);
      if (customer.status !== "active") {
        throw new EngineError("customer_blocked", `Customer is ${customer.status}`, 409);
      }
      if (this.wallet.balance(customer.id) < price) {
        throw new EngineError("insufficient_balance", "Wallet balance below the pass price", 409);
      }
      const now = this.ctx.clock();
      const live = activePass(this.ctx, customer.id, pc.id, now);
      const startsAt = live?.expiresAt ?? now;
      const pass = {
        id: uuidv7(now),
        branchId: this.ctx.branchId,
        pcId: pc.id,
        customerId: customer.id,
        price,
        days,
        startsAt,
        expiresAt: startsAt + days * DAY_MS,
        soldBy: input.staffId,
        createdAt: now
      };
      this.ctx.db.insert(stationPasses).values(pass).run();
      this.wallet.append({
        customerId: customer.id,
        type: "station_pass",
        amount: -price,
        refType: "station_pass",
        refId: pass.id,
        idempotencyKey: `pass:${pass.id}`,
        createdBy: input.staffId
      });
      writeAudit(this.ctx, {
        staffId: input.staffId,
        action: "pass.sell",
        entity: "station_pass",
        entityId: pass.id,
        after: { pcId: pass.pcId, customerId: pass.customerId, price, days, expiresAt: pass.expiresAt }
      }, now);
      return pass;
    })();
  }
};

// dist/services/shifts.js
var SHIFT_MODE_SETTING = "shift_mode";
function currentShift(ctx2) {
  return ctx2.db.select().from(shifts).where(and(eq(shifts.branchId, ctx2.branchId), isNull(shifts.closedAt))).get() ?? null;
}
function requireOpenShift(ctx2, what) {
  const shift = currentShift(ctx2);
  if (!shift && getSetting(ctx2.db, SHIFT_MODE_SETTING) !== "free") {
    throw new EngineError("no_open_shift", `Open a shift before ${what}`, 409);
  }
  return shift;
}
var ShiftService = class {
  ctx;
  constructor(ctx2) {
    this.ctx = ctx2;
  }
  current() {
    return currentShift(this.ctx);
  }
  /** Closed shifts, newest first, for the admin history screen. */
  history(limit = 30) {
    const n = Math.trunc(Number.isFinite(limit) ? Math.min(Math.max(limit, 1), 100) : 30);
    return this.ctx.db.select().from(shifts).where(and(eq(shifts.branchId, this.ctx.branchId), isNotNull(shifts.closedAt))).orderBy(desc(shifts.closedAt)).limit(n).all();
  }
  open(input) {
    if (input.openingCash < 0 || !Number.isSafeInteger(input.openingCash)) {
      throw new EngineError("bad_amount", "openingCash must be a non-negative integer");
    }
    if (this.current()) {
      throw new EngineError("shift_open", "A shift is already open \u2014 close it first", 409);
    }
    const lastClosed = this.ctx.db.select({ t: sql`coalesce(max(${shifts.closedAt}), 0)` }).from(shifts).where(eq(shifts.branchId, this.ctx.branchId)).get()?.t ?? 0;
    const now = Math.max(this.ctx.clock(), lastClosed + 1);
    const shift = {
      id: uuidv7(now),
      branchId: this.ctx.branchId,
      staffId: input.staffId,
      openedAt: now,
      closedAt: null,
      openingCash: input.openingCash,
      countedCash: null,
      expectedCash: null,
      zReport: null
    };
    this.ctx.db.insert(shifts).values(shift).run();
    return shift;
  }
  cashMovement(input) {
    if (input.amount <= 0 || !Number.isSafeInteger(input.amount)) {
      throw new EngineError("bad_amount", "Amount must be a positive integer");
    }
    const shift = this.ctx.db.select().from(shifts).where(eq(shifts.id, input.shiftId)).get();
    if (!shift)
      throw new EngineError("not_found", "Shift not found", 404);
    if (shift.closedAt)
      throw new EngineError("shift_closed", "Shift is closed", 409);
    const now = this.ctx.clock();
    const movement = {
      id: uuidv7(now),
      shiftId: input.shiftId,
      type: input.type,
      amount: input.amount,
      reason: input.reason,
      staffId: input.staffId,
      createdAt: now
    };
    this.ctx.db.insert(cashMovements).values(movement).run();
    return movement;
  }
  close(input) {
    if (input.countedCash < 0 || !Number.isSafeInteger(input.countedCash)) {
      throw new EngineError("bad_amount", "countedCash must be a non-negative integer");
    }
    return this.ctx.sqlite.transaction(() => {
      const shift = this.ctx.db.select().from(shifts).where(eq(shifts.id, input.shiftId)).get();
      if (!shift)
        throw new EngineError("not_found", "Shift not found", 404);
      if (shift.closedAt)
        throw new EngineError("shift_closed", "Shift is already closed", 409);
      const now = Math.max(this.ctx.clock(), shift.openedAt);
      const sumWallet = (type) => this.ctx.db.select({ sum: sql`coalesce(sum(${walletLedger.amount}), 0)` }).from(walletLedger).where(and(eq(walletLedger.branchId, this.ctx.branchId), eq(walletLedger.type, type), gte(walletLedger.createdAt, shift.openedAt), lte(walletLedger.createdAt, now))).get()?.sum ?? 0;
      const guestCash = this.ctx.db.select({ sum: sql`coalesce(sum(${sessions.totalCost}), 0)` }).from(sessions).where(and(eq(sessions.branchId, this.ctx.branchId), isNull(sessions.customerId), eq(sessions.status, "finished"), gte(sessions.endedAt, shift.openedAt), lte(sessions.endedAt, now), sql`${sessions.id} not in (select session_id from ${tabs})`)).get()?.sum ?? 0;
      const tabsCash = this.ctx.db.select({ sum: sql`coalesce(sum(${tabs.amount}), 0)` }).from(tabs).where(and(eq(tabs.settledVia, "cash"), eq(tabs.shiftId, shift.id))).get()?.sum ?? 0;
      const orderCash = this.ctx.db.select({ sum: sql`coalesce(sum(${orders.total}), 0)` }).from(orders).where(and(eq(orders.branchId, this.ctx.branchId), eq(orders.paidVia, "cash"), ne(orders.status, "cancelled"), gte(orders.createdAt, shift.openedAt), lte(orders.createdAt, now))).get()?.sum ?? 0;
      const cash = { in: 0, out: 0, payout: 0 };
      for (const m of this.ctx.db.select({ type: cashMovements.type, sum: sql`sum(${cashMovements.amount})` }).from(cashMovements).where(eq(cashMovements.shiftId, shift.id)).groupBy(cashMovements.type).all()) {
        cash[m.type] = m.sum;
      }
      const walletTopups = {
        cash: sumWallet("topup_cash"),
        card: sumWallet("topup_card"),
        online: sumWallet("topup_online")
      };
      const expectedCash = shift.openingCash + walletTopups.cash + guestCash + tabsCash + orderCash + cash.in - cash.out - cash.payout;
      const zReport = {
        openedAt: shift.openedAt,
        closedAt: now,
        walletTopups,
        walletSessionCharges: -sumWallet("session_charge"),
        walletOrderCharges: -sumWallet("order_charge"),
        walletRefunds: sumWallet("refund"),
        guestSessionCash: guestCash,
        tabsCash,
        orderCash,
        cash,
        openingCash: shift.openingCash,
        expectedCash,
        countedCash: input.countedCash,
        delta: input.countedCash - expectedCash
      };
      this.ctx.db.update(shifts).set({
        closedAt: now,
        countedCash: input.countedCash,
        expectedCash,
        zReport
      }).where(eq(shifts.id, shift.id)).run();
      return {
        ...shift,
        closedAt: now,
        countedCash: input.countedCash,
        expectedCash,
        zReport
      };
    })();
  }
};

// dist/routes.js
function detectMedia(buf) {
  if (buf.length < 12)
    return null;
  if (buf[0] === 255 && buf[1] === 216 && buf[2] === 255)
    return { ext: "jpg", kind: "image" };
  if (buf.readUInt32BE(0) === 2303741511)
    return { ext: "png", kind: "image" };
  if (buf.toString("ascii", 0, 4) === "RIFF" && buf.toString("ascii", 8, 12) === "WEBP")
    return { ext: "webp", kind: "image" };
  if (buf.toString("ascii", 4, 8) === "ftyp")
    return { ext: "mp4", kind: "video" };
  if (buf.readUInt32BE(0) === 440786851)
    return { ext: "webm", kind: "video" };
  return null;
}
function parse(schema, data) {
  const r = schema.safeParse(data);
  if (!r.success) {
    const msg = r.error.issues.map((i) => `${i.path.join(".") || "body"}: ${i.message}`).join("; ");
    throw new EngineError("invalid", msg);
  }
  return r.data;
}
var money = external_exports.number().int();
var tierSchema = external_exports.enum(["bronze", "silver", "gold"]);
function pub(row) {
  const { passwordHash: _ph, ...rest } = row;
  return rest;
}
async function cloudIntegrations(s, method, body) {
  if (!s.cloud)
    throw new EngineError("cloud_disabled", "Cloud sync is not configured", 503);
  const f = s.cloud.fetchImpl ?? fetch;
  let res;
  try {
    res = await f(`${s.cloud.url}/api/sync/integrations`, {
      method,
      headers: {
        authorization: `Bearer ${s.cloud.token}`,
        ...body !== void 0 ? { "content-type": "application/json" } : {}
      },
      ...body !== void 0 ? { body: JSON.stringify(body) } : {},
      signal: AbortSignal.timeout(8e3)
    });
  } catch {
    throw new EngineError("cloud_unreachable", "Cloud did not respond", 502);
  }
  if (!res.ok)
    throw new EngineError("cloud_error", `Cloud settings failed (${res.status})`, 502);
  return await res.json().catch(() => null) ?? {};
}
function createApp(s) {
  const limiter = new FailureLimiter(15 * 6e4, s.ctx.clock);
  const clientIp = (c) => c.env?.incoming?.socket?.remoteAddress ?? "local";
  const emitRuleUpsert = (rule) => {
    const now = s.ctx.clock();
    s.ctx.db.insert(syncOutbox).values({
      eventId: uuidv7(now),
      aggregateType: "pricing_rule",
      aggregateId: rule.id,
      eventType: "pricing.rule.upserted",
      payload: rule,
      createdAt: now
    }).run();
  };
  const withStaffNames = (rows) => {
    const names = new Map(s.ctx.db.select({ id: staff.id, name: staff.name }).from(staff).all().map((r) => [r.id, r.name]));
    return rows.map((r) => ({ ...r, staffName: names.get(r.staffId) ?? null }));
  };
  const requireStaff = (min = "operator") => createMiddleware(async (c, next) => {
    const token = c.req.header("authorization")?.replace(/^Bearer\s+/i, "");
    const session = s.auth.authenticate(token);
    if (!session)
      throw new EngineError("unauthorized", "Login required", 401);
    if (!s.auth.hasRole(session, min)) {
      throw new EngineError("forbidden", `Requires ${min} role`, 403);
    }
    c.set("staff", session);
    await next();
  });
  const json = (c) => c.req.json().catch(() => ({}));
  const intQuery = (v, def, min, max) => {
    const n = Math.floor(Number(v));
    return Number.isFinite(n) ? Math.min(max, Math.max(min, n)) : def;
  };
  return new Hono2().use("*", cors({
    origin: (origin) => !origin || /^(https?:\/\/localhost(:\d+)?|https?:\/\/tauri\.localhost|tauri:\/\/localhost)$/.test(origin) ? origin : null
  })).onError((err, c) => {
    if (err instanceof EngineError) {
      return c.json({ error: err.message, code: err.code }, err.status);
    }
    console.error("[api]", err);
    return c.json({ error: "internal error", code: "internal" }, 500);
  }).get("/health", (c) => c.json({
    ok: true,
    connectedPcs: s.hub.connectedPcIds().length,
    // ids too: lets tooling (smoke) avoid pairing over a live seat — two
    // launchers on one PC evict each other in an endless reconnect war.
    connectedPcIds: s.hub.connectedPcIds(),
    ts: s.ctx.clock()
  })).post("/api/auth/login", async (c) => {
    const body = parse(external_exports.object({ username: external_exports.string().min(1), password: external_exports.string().min(1) }), await json(c));
    const userKey = `login:u:${body.username}`;
    const ipKey = `login:ip:${clientIp(c)}`;
    limiter.check(userKey, 5);
    limiter.check(ipKey, 20);
    let session;
    try {
      session = await s.auth.login(body.username, body.password);
    } catch (err) {
      if (err instanceof EngineError && err.code === "bad_credentials") {
        limiter.fail(userKey);
        limiter.fail(ipKey);
      }
      throw err;
    }
    limiter.clear(userKey);
    limiter.clear(ipKey);
    return c.json({
      token: session.token,
      staffId: session.staffId,
      name: session.name,
      role: session.role
    });
  }).post("/api/auth/logout", requireStaff(), (c) => {
    s.auth.logout(c.get("staff").token);
    return c.json({ ok: true });
  }).get("/api/floor", requireStaff(), (c) => {
    const rows = s.ctx.db.select().from(pcs).all();
    return c.json(rows.map((pc) => ({
      pcId: pc.id,
      name: pc.name,
      zoneId: pc.zoneId,
      status: pc.status,
      enabled: pc.enabled,
      session: s.engine.sessionInfoForPc(pc.id)
    })));
  }).post("/api/sessions", requireStaff(), async (c) => {
    const body = parse(external_exports.object({
      pcId: external_exports.string(),
      customerId: external_exports.string().nullish(),
      mode: external_exports.enum(["prepaid", "open"]),
      prepaidMinutes: external_exports.number().int().positive().nullish(),
      extraControllers: external_exports.number().int().min(0).max(4).optional(),
      notes: external_exports.string().optional()
    }), await json(c));
    const result = s.engine.start({
      pcId: body.pcId,
      customerId: body.customerId ?? null,
      mode: body.mode,
      prepaidMinutes: body.prepaidMinutes ?? null,
      extraControllers: body.extraControllers ?? 0,
      staffId: c.get("staff").staffId,
      notes: body.notes
    });
    return c.json(result, 201);
  }).post("/api/sessions/:id/extend", requireStaff(), async (c) => {
    const body = parse(external_exports.object({ minutes: external_exports.number().int().positive() }), await json(c));
    return c.json(s.engine.extend(c.req.param("id"), body.minutes, c.get("staff").staffId));
  }).post("/api/sessions/:id/park", requireStaff(), async (c) => {
    const body = parse(external_exports.object({ label: external_exports.string().max(64).optional(), customerId: external_exports.string().nullish() }), await json(c));
    const tab = s.tabs.park(c.req.param("id"), { label: body.label, customerId: body.customerId ?? null }, c.get("staff").staffId);
    s.hub.broadcastFloor(tab.pcId);
    return c.json(tab, 201);
  }).get("/api/tabs", requireStaff(), (c) => c.json(s.tabs.open())).post("/api/tabs/:id/settle", requireStaff(), async (c) => {
    const body = parse(external_exports.object({ via: external_exports.enum(["cash", "wallet"]), customerId: external_exports.string().nullish() }), await json(c));
    const tab = s.tabs.settle(c.req.param("id"), { via: body.via, customerId: body.customerId ?? null }, c.get("staff").staffId);
    s.hub.broadcastFloor(tab.pcId);
    return c.json(tab);
  }).get("/api/passes", requireStaff(), (c) => c.json({ price: s.passes.price(), days: s.passes.days(), passes: s.passes.active() })).post("/api/passes", requireStaff(), async (c) => {
    const body = parse(external_exports.object({ pcId: external_exports.string().min(1), customerId: external_exports.string().min(1) }), await json(c));
    return c.json(s.passes.sell({ ...body, staffId: c.get("staff").staffId }), 201);
  }).get("/api/sessions/active", requireStaff(), (c) => c.json(s.engine.activeSessions())).post("/api/sessions/:id/stop", requireStaff(), async (c) => {
    const body = parse(external_exports.object({ reason: external_exports.string().optional() }), await json(c));
    return c.json(s.engine.stop(c.req.param("id"), { by: c.get("staff").staffId, reason: body.reason }));
  }).post("/api/sessions/:id/pause", requireStaff(), (c) => c.json(s.engine.pause(c.req.param("id")))).post("/api/sessions/:id/resume", requireStaff(), (c) => c.json(s.engine.resume(c.req.param("id")))).post("/api/sessions/:id/transfer", requireStaff(), async (c) => {
    const body = parse(external_exports.object({ toPcId: external_exports.string() }), await json(c));
    return c.json(s.engine.transfer(c.req.param("id"), body.toPcId));
  }).get("/api/customers", requireStaff(), (c) => c.json(s.customers.search(c.req.query("q") ?? "").map(pub))).post("/api/customers", requireStaff(), async (c) => {
    const body = parse(external_exports.object({
      phone: external_exports.string().min(4),
      name: external_exports.string().min(1),
      tier: tierSchema.optional(),
      // Mandatory: game age limits derive from it (Gregorian ISO; UI shows Jalali).
      birthDate: external_exports.string().regex(/^\d{4}-\d{2}-\d{2}$/, "birthDate must be YYYY-MM-DD"),
      // Mandatory alongside birthDate: counter registration requires full identity.
      nationalId: external_exports.string().regex(/^\d{10}$/, "\u06A9\u062F \u0645\u0644\u06CC must be 10 digits")
    }), await json(c));
    return c.json(pub(s.customers.create({ ...body, staffId: c.get("staff").staffId })), 201);
  }).get("/api/customers/:id", requireStaff(), (c) => c.json(pub(s.customers.withBalance(c.req.param("id"))))).patch("/api/customers/:id", requireStaff(), async (c) => {
    const body = parse(external_exports.object({
      name: external_exports.string().min(1).optional(),
      tier: tierSchema.nullish(),
      // explicit null clears the tier → base rate
      birthDate: external_exports.string().regex(/^\d{4}-\d{2}-\d{2}$/).nullish(),
      status: external_exports.enum(["active", "blocked"]).optional(),
      nationalId: external_exports.string().regex(/^\d{10}$/, "\u06A9\u062F \u0645\u0644\u06CC must be 10 digits").nullish()
    }), await json(c));
    if ((body.tier !== void 0 || body.status) && !s.auth.hasRole(c.get("staff"), "manager")) {
      throw new EngineError("forbidden", "Changing tier/status requires manager role", 403);
    }
    return c.json(pub(s.customers.update(c.req.param("id"), { ...body, birthDate: body.birthDate ?? void 0 }, c.get("staff").staffId)));
  }).post("/api/customers/:id/password", requireStaff(), async (c) => {
    const body = parse(external_exports.object({ password: external_exports.string().min(4).max(128) }), await json(c));
    const passwordHash = await hashPassword(body.password);
    return c.json(pub(s.customers.setPassword(c.req.param("id"), passwordHash, c.get("staff").staffId)));
  }).post("/api/customers/:id/card", requireStaff(), async (c) => {
    const id = c.req.param("id");
    const customer = s.customers.get(id);
    const form = await c.req.parseBody();
    const file = form["file"];
    if (!(file instanceof File))
      throw new EngineError("invalid", "multipart field 'file' required", 400);
    const buf = Buffer.from(await file.arrayBuffer());
    const sig = detectMedia(buf);
    if (!sig || sig.kind !== "image") {
      throw new EngineError("invalid", "Only JPEG/PNG/WebP images", 400);
    }
    if (buf.length > 1e7)
      throw new EngineError("too_large", "File exceeds 10MB limit", 413);
    const dir = s.cardsDir ?? "./data/cards";
    mkdirSync2(dir, { recursive: true });
    const cardFile = `${id}-${s.ctx.clock()}.${sig.ext}`;
    writeFileSync(join(dir, cardFile), buf);
    if (customer.nationalCardFile)
      rmSync(join(dir, customer.nationalCardFile), { force: true });
    s.ctx.db.update(customers).set({ nationalCardFile: cardFile, updatedAt: s.ctx.clock() }).where(eq(customers.id, id)).run();
    writeAudit(s.ctx, {
      staffId: c.get("staff").staffId,
      action: "customer.card_upload",
      entity: "customer",
      entityId: id
    });
    return c.json({ nationalCardFile: cardFile }, 201);
  }).delete("/api/customers/:id/card", requireStaff(), (c) => {
    const id = c.req.param("id");
    const customer = s.customers.get(id);
    if (customer.nationalCardFile) {
      rmSync(join(s.cardsDir ?? "./data/cards", customer.nationalCardFile), { force: true });
      s.ctx.db.update(customers).set({ nationalCardFile: null, updatedAt: s.ctx.clock() }).where(eq(customers.id, id)).run();
    }
    return c.json({ ok: true });
  }).get("/api/customers/:id/card", requireStaff(), (c) => {
    const customer = s.customers.get(c.req.param("id"));
    if (!customer.nationalCardFile)
      throw new EngineError("not_found", "No card image", 404);
    let body;
    try {
      body = readFileSync(join(s.cardsDir ?? "./data/cards", customer.nationalCardFile));
    } catch {
      throw new EngineError("not_found", "No card image", 404);
    }
    const ext = customer.nationalCardFile.split(".").pop();
    const type = { jpg: "image/jpeg", png: "image/png", webp: "image/webp" }[ext] ?? "application/octet-stream";
    return c.body(new Uint8Array(body), 200, { "content-type": type, "cache-control": "private, no-store" });
  }).get("/api/customers/:id/ledger", requireStaff(), (c) => c.json({
    balance: s.wallet.balance(c.req.param("id")),
    entries: s.wallet.ledger(c.req.param("id")),
    points: s.wallet.points.balance(c.req.param("id")),
    // Redeem rate for the admin preview (Toman per point; 0 = disabled).
    pointsRate: s.wallet.points.tomanPerPoint()
  })).post("/api/customers/:id/redeem", requireStaff(), async (c) => {
    const body = parse(external_exports.object({ points: external_exports.number().int().positive(), idempotencyKey: external_exports.string().min(8) }), await json(c));
    const result = s.wallet.redeemPoints({
      customerId: c.req.param("id"),
      points: body.points,
      idempotencyKey: body.idempotencyKey,
      staffId: c.get("staff").staffId
    });
    return c.json({
      ...result,
      balance: s.wallet.balance(c.req.param("id")),
      points: s.wallet.points.balance(c.req.param("id"))
    }, 201);
  }).post("/api/customers/:id/topup", requireStaff(), async (c) => {
    const body = parse(external_exports.object({
      amount: money.positive(),
      method: external_exports.enum(["cash", "card"]),
      idempotencyKey: external_exports.string().min(8)
    }), await json(c));
    const result = s.wallet.topUp({
      customerId: c.req.param("id"),
      amount: body.amount,
      method: body.method,
      idempotencyKey: body.idempotencyKey,
      staffId: c.get("staff").staffId
    });
    return c.json({ ...result, balance: s.wallet.balance(c.req.param("id")) }, 201);
  }).post("/api/customers/:id/adjust", requireStaff("manager"), async (c) => {
    const body = parse(external_exports.object({
      amount: money.refine((n) => n !== 0, "amount must be non-zero"),
      reason: external_exports.string().min(3),
      idempotencyKey: external_exports.string().min(8)
    }), await json(c));
    const result = s.wallet.adjust({
      customerId: c.req.param("id"),
      amount: body.amount,
      reason: body.reason,
      idempotencyKey: body.idempotencyKey,
      staffId: c.get("staff").staffId
    });
    return c.json({ ...result, balance: s.wallet.balance(c.req.param("id")) }, 201);
  }).post("/api/qr/resolve", requireStaff(), async (c) => {
    if (!s.cloud)
      throw new EngineError("cloud_disabled", "Cloud sync is not configured", 503);
    const body = parse(external_exports.object({ token: external_exports.string().min(8).max(128) }), await json(c));
    const f = s.cloud.fetchImpl ?? fetch;
    let res;
    try {
      res = await f(`${s.cloud.url}/api/sync/qr/verify`, {
        method: "POST",
        headers: {
          "content-type": "application/json",
          authorization: `Bearer ${s.cloud.token}`
        },
        body: JSON.stringify({ token: body.token }),
        signal: AbortSignal.timeout(8e3)
      });
    } catch {
      throw new EngineError("cloud_unreachable", "Cloud did not respond", 502);
    }
    if (res.status === 404)
      throw new EngineError("qr_invalid", "QR code is invalid or expired", 404);
    if (!res.ok)
      throw new EngineError("cloud_error", `Cloud verify failed (${res.status})`, 502);
    const cust = external_exports.object({
      id: external_exports.string().min(1),
      phone: external_exports.string().min(1),
      name: external_exports.string().min(1),
      tier: tierSchema.nullish(),
      status: external_exports.enum(["active", "blocked", "negative_balance"]),
      passwordHash: external_exports.string().nullish(),
      birthDate: external_exports.string().nullish(),
      createdAt: external_exports.number().int(),
      updatedAt: external_exports.number().int()
    }).safeParse((await res.json().catch(() => null))?.customer);
    if (!cust.success)
      throw new EngineError("cloud_error", "Cloud returned an unexpected shape", 502);
    return c.json(pub(s.customers.withBalance(s.customers.adoptCloud(cust.data).id)));
  }).get("/api/rate-cards", requireStaff(), (c) => c.json(s.ctx.db.select().from(pricingRateCards).all())).post("/api/rate-cards", requireStaff("manager"), async (c) => {
    const body = parse(external_exports.object({
      zoneId: external_exports.string(),
      tier: tierSchema.nullish(),
      pricePerHour: money.positive(),
      effectiveFrom: external_exports.number().int().optional()
    }), await json(c));
    const now = s.ctx.clock();
    const card = {
      id: uuidv7(now),
      branchId: s.ctx.branchId,
      zoneId: body.zoneId,
      tier: body.tier ?? null,
      pricePerHour: body.pricePerHour,
      effectiveFrom: body.effectiveFrom ?? now
    };
    s.ctx.db.insert(pricingRateCards).values(card).run();
    writeAudit(s.ctx, {
      staffId: c.get("staff").staffId,
      action: "ratecard.create",
      entity: "rate_card",
      entityId: card.id,
      after: { zoneId: card.zoneId, tier: card.tier, pricePerHour: card.pricePerHour }
    });
    return c.json(card, 201);
  }).get("/api/quote", requireStaff(), (c) => {
    const pcId = c.req.query("pcId") ?? "";
    const customerId = c.req.query("customerId");
    const minutes = Math.floor(Number(c.req.query("minutes") ?? 0));
    const controllers = intQuery(c.req.query("controllers"), 0, 0, 4);
    const pc = s.ctx.db.select().from(pcs).where(eq(pcs.id, pcId)).get();
    if (!pc)
      throw new EngineError("not_found", "PC not found", 404);
    const tier = customerId ? s.ctx.db.select({ tier: customers.tier }).from(customers).where(eq(customers.id, customerId)).get()?.tier ?? null : null;
    const now = s.ctx.clock();
    const q = quoteFor(loadPricingState(s.ctx), pc.zoneId, tier, now);
    const ratePerHour = activePass(s.ctx, customerId ?? null, pc.id, now) ? 0 : q.ratePerHour + controllers * (pc.extraControllerRate ?? 0);
    return c.json({
      ratePerHour,
      cost: minutes > 0 ? minuteCost(ratePerHour, minutes) : null
    });
  }).get("/api/pricing-rules", requireStaff(), (c) => c.json(s.ctx.db.select().from(dynamicPricingRules).all())).post("/api/pricing-rules", requireStaff("manager"), async (c) => {
    const body = parse(external_exports.object({
      name: external_exports.string().min(1),
      priority: external_exports.number().int().default(100),
      enabled: external_exports.boolean().default(false),
      conditions: external_exports.record(external_exports.unknown()).default({}),
      action: external_exports.record(external_exports.unknown()),
      floorRate: money.nonnegative().nullish()
    }), await json(c));
    const rule = {
      id: uuidv7(s.ctx.clock()),
      branchId: s.ctx.branchId,
      name: body.name,
      priority: body.priority,
      enabled: body.enabled,
      conditions: body.conditions,
      action: body.action,
      floorRate: body.floorRate ?? null
    };
    s.ctx.sqlite.transaction(() => {
      s.ctx.db.insert(dynamicPricingRules).values(rule).run();
      emitRuleUpsert(rule);
    })();
    writeAudit(s.ctx, {
      staffId: c.get("staff").staffId,
      action: "rule.create",
      entity: "pricing_rule",
      entityId: rule.id,
      after: { name: rule.name, enabled: rule.enabled, action: rule.action }
    });
    return c.json(rule, 201);
  }).patch("/api/pricing-rules/:id", requireStaff("manager"), async (c) => {
    const body = parse(external_exports.object({
      name: external_exports.string().min(1).optional(),
      priority: external_exports.number().int().optional(),
      enabled: external_exports.boolean().optional(),
      conditions: external_exports.record(external_exports.unknown()).optional(),
      action: external_exports.record(external_exports.unknown()).optional(),
      floorRate: money.nonnegative().nullish()
    }), await json(c));
    const id = c.req.param("id");
    const existing = s.ctx.db.select().from(dynamicPricingRules).where(eq(dynamicPricingRules.id, id)).get();
    if (!existing)
      throw new EngineError("not_found", "Rule not found", 404);
    const updated = s.ctx.sqlite.transaction(() => {
      s.ctx.db.update(dynamicPricingRules).set({
        ...body.name !== void 0 && { name: body.name },
        ...body.priority !== void 0 && { priority: body.priority },
        ...body.enabled !== void 0 && { enabled: body.enabled },
        ...body.conditions !== void 0 && {
          conditions: body.conditions
        },
        ...body.action !== void 0 && {
          action: body.action
        },
        ...body.floorRate !== void 0 && { floorRate: body.floorRate }
      }).where(eq(dynamicPricingRules.id, id)).run();
      const u = s.ctx.db.select().from(dynamicPricingRules).where(eq(dynamicPricingRules.id, id)).get();
      emitRuleUpsert(u);
      return u;
    })();
    const snap = (r) => ({
      name: r.name,
      priority: r.priority,
      enabled: r.enabled,
      conditions: r.conditions,
      action: r.action,
      floorRate: r.floorRate
    });
    writeAudit(s.ctx, {
      staffId: c.get("staff").staffId,
      action: "rule.update",
      entity: "pricing_rule",
      entityId: id,
      before: snap(existing),
      after: snap(updated)
    });
    return c.json(updated);
  }).get("/api/analytics/heatmap", requireStaff("manager"), (c) => c.json(heatmap(s.ctx, intQuery(c.req.query("weeks"), 8, 1, 26)))).get("/api/analytics/revenue", requireStaff("manager"), (c) => c.json(revenue(s.ctx, intQuery(c.req.query("days"), 30, 1, 365)))).get("/api/analytics/top-games", requireStaff("manager"), (c) => c.json(topGames(s.ctx, intQuery(c.req.query("days"), 30, 1, 365), intQuery(c.req.query("limit"), 10, 1, 50)))).post("/api/analytics/suggest-rules", requireStaff("manager"), async (c) => {
    const body = parse(external_exports.object({
      weeks: external_exports.number().int().min(1).max(26).default(8),
      occupancyLt: external_exports.number().gt(0).lt(1).default(0.35),
      minRunHours: external_exports.number().int().min(1).max(12).default(2),
      multiplier: external_exports.number().gt(0).lt(1).default(0.8)
    }), await json(c));
    return c.json(suggestRules(s.ctx, body), 201);
  }).get("/api/audit", requireStaff("manager"), (c) => {
    const before = c.req.query("before");
    const limit = intQuery(c.req.query("limit"), 50, 1, 200);
    const entries = s.ctx.db.select({
      id: auditLog.id,
      staffId: auditLog.staffId,
      staffName: staff.name,
      action: auditLog.action,
      entity: auditLog.entity,
      entityId: auditLog.entityId,
      before: auditLog.before,
      after: auditLog.after,
      createdAt: auditLog.createdAt
    }).from(auditLog).leftJoin(staff, eq(staff.id, auditLog.staffId)).where(before ? lt(auditLog.id, before) : void 0).orderBy(desc(auditLog.id)).limit(limit).all();
    const customerIds = [
      ...new Set(entries.flatMap((e) => {
        if (e.entity === "customer" && e.entityId)
          return [e.entityId];
        const cid = e.after?.customerId;
        return cid ? [cid] : [];
      }))
    ];
    const names = Object.fromEntries(customerIds.length ? s.ctx.db.select({ id: customers.id, name: customers.name }).from(customers).where(inArray(customers.id, customerIds)).all().map((r) => [r.id, r.name]) : []);
    return c.json({ entries, names });
  }).get("/api/shifts", requireStaff(), (c) => {
    const limit = Number(c.req.query("limit") ?? 30);
    return c.json(withStaffNames(s.shifts.history(Number.isFinite(limit) ? limit : 30)));
  }).get("/api/shifts/current", requireStaff(), (c) => {
    const cur = s.shifts.current();
    return c.json(cur ? withStaffNames([cur])[0] : null);
  }).post("/api/shifts", requireStaff(), async (c) => {
    const body = parse(external_exports.object({ openingCash: money.nonnegative() }), await json(c));
    return c.json(withStaffNames([
      s.shifts.open({ staffId: c.get("staff").staffId, openingCash: body.openingCash })
    ])[0], 201);
  }).post("/api/shifts/:id/close", requireStaff(), async (c) => {
    const body = parse(external_exports.object({ countedCash: money.nonnegative() }), await json(c));
    return c.json(s.shifts.close({
      shiftId: c.req.param("id"),
      countedCash: body.countedCash,
      staffId: c.get("staff").staffId
    }));
  }).post("/api/shifts/:id/cash", requireStaff(), async (c) => {
    const body = parse(external_exports.object({
      type: external_exports.enum(["in", "out", "payout"]),
      amount: money.positive(),
      reason: external_exports.string().min(2)
    }), await json(c));
    return c.json(s.shifts.cashMovement({
      shiftId: c.req.param("id"),
      ...body,
      staffId: c.get("staff").staffId
    }), 201);
  }).get("/api/settings", requireStaff(), (c) => c.json({
    cafeName: getSetting(s.ctx.db, "cafe_name") ?? null,
    logo: getSetting(s.ctx.db, "cafe_logo") ?? null,
    pointsPerPlayedHour: getSetting(s.ctx.db, POINTS_PER_PLAYED_HOUR_SETTING) ?? null,
    pointsPer100kSpent: getSetting(s.ctx.db, POINTS_PER_100K_SPENT_SETTING) ?? null,
    tomanPerPoint: getSetting(s.ctx.db, TOMAN_PER_POINT_SETTING) ?? null,
    shiftMode: getSetting(s.ctx.db, SHIFT_MODE_SETTING) ?? "shift",
    stationPassPrice: getSetting(s.ctx.db, PASS_PRICE_SETTING) ?? null,
    stationPassDays: getSetting(s.ctx.db, PASS_DAYS_SETTING) ?? null
  })).patch("/api/settings", requireStaff("manager"), async (c) => {
    const body = parse(external_exports.object({
      cafeName: external_exports.string().min(1).max(64).nullish(),
      // data:image/… only; ~512KB image ≈ 700k chars base64.
      logo: external_exports.string().regex(/^data:image\/(png|jpeg|webp);base64,/, "logo must be a data:image URL").max(7e5).nullish(),
      pointsPerPlayedHour: external_exports.number().int().min(0).max(1e5).nullish(),
      pointsPer100kSpent: external_exports.number().int().min(0).max(1e5).nullish(),
      tomanPerPoint: external_exports.number().int().min(0).max(1e6).nullish(),
      shiftMode: external_exports.enum(["shift", "free"]).nullish(),
      // 0/unset = this café does not sell station passes.
      stationPassPrice: external_exports.number().int().min(0).max(1e8).nullish(),
      stationPassDays: external_exports.number().int().min(1).max(365).nullish()
    }), await json(c));
    if (body.shiftMode === "free" && s.shifts.current()) {
      throw new EngineError("shift_open", "Close the open shift (count the drawer) before switching to free mode", 409);
    }
    const now = s.ctx.clock();
    const KEYS = {
      cafeName: "cafe_name",
      logo: "cafe_logo",
      pointsPerPlayedHour: POINTS_PER_PLAYED_HOUR_SETTING,
      pointsPer100kSpent: POINTS_PER_100K_SPENT_SETTING,
      tomanPerPoint: TOMAN_PER_POINT_SETTING,
      shiftMode: SHIFT_MODE_SETTING,
      stationPassPrice: PASS_PRICE_SETTING,
      stationPassDays: PASS_DAYS_SETTING
    };
    const changed = {};
    for (const [field, key] of Object.entries(KEYS)) {
      const v = body[field];
      if (v === void 0)
        continue;
      if (v === null)
        s.ctx.db.delete(settings).where(eq(settings.key, key)).run();
      else
        setSetting(s.ctx.db, key, v, now);
      changed[field] = field === "logo" && v ? "(image)" : v;
    }
    if (Object.keys(changed).length > 0) {
      writeAudit(s.ctx, {
        staffId: c.get("staff").staffId,
        action: "settings.update",
        entity: "settings",
        after: changed
      });
    }
    return c.json({ ok: true });
  }).get("/api/settings/integrations", requireStaff("manager"), async (c) => c.json(await cloudIntegrations(s, "GET"))).put("/api/settings/integrations", requireStaff("manager"), async (c) => {
    const body = parse(external_exports.object({
      smsProvider: external_exports.enum(["kavenegar"]).nullable(),
      smsTemplate: external_exports.string().trim().min(1).max(64).nullable(),
      // Omitted = keep the stored key; null = clear it.
      smsApiKey: external_exports.string().trim().min(8).max(256).nullable().optional()
    }), await json(c));
    await cloudIntegrations(s, "PUT", body);
    writeAudit(s.ctx, {
      staffId: c.get("staff").staffId,
      action: "settings.integrations",
      entity: "settings",
      // Never the key itself — audit rows are readable in the panel.
      after: {
        smsProvider: body.smsProvider,
        smsTemplate: body.smsTemplate,
        smsApiKey: body.smsApiKey === void 0 ? "(unchanged)" : body.smsApiKey ? "(set)" : null
      }
    });
    return c.json({ ok: true });
  }).post("/api/me/password", requireStaff(), async (c) => {
    const body = parse(external_exports.object({
      currentPassword: external_exports.string().min(1),
      newPassword: external_exports.string().min(6).max(128)
    }), await json(c));
    const me = c.get("staff");
    const row = s.ctx.db.select().from(staff).where(eq(staff.id, me.staffId)).get();
    if (!row)
      throw new EngineError("not_found", "Staff member not found", 404);
    const ok = await verifyPassword(row.passwordHash, body.currentPassword).catch(() => false);
    if (!ok)
      throw new EngineError("bad_credentials", "Current password is incorrect", 401);
    s.ctx.db.update(staff).set({ passwordHash: await hashPassword(body.newPassword), updatedAt: s.ctx.clock() }).where(eq(staff.id, me.staffId)).run();
    writeAudit(s.ctx, {
      staffId: me.staffId,
      action: "staff.password_change",
      entity: "staff",
      entityId: me.staffId
    });
    return c.json({ ok: true });
  }).get("/api/staff", requireStaff("manager"), (c) => c.json(s.ctx.db.select().from(staff).orderBy(staff.createdAt).all().map(pub))).post("/api/staff", requireStaff("manager"), async (c) => {
    const body = parse(external_exports.object({
      name: external_exports.string().min(1),
      username: external_exports.string().min(3).max(64),
      password: external_exports.string().min(6).max(128),
      role: external_exports.enum(["owner", "manager", "operator"]),
      phone: external_exports.string().optional()
    }), await json(c));
    if (!s.auth.hasRole(c.get("staff"), body.role)) {
      throw new EngineError("forbidden", `Creating a ${body.role} requires that role or higher`, 403);
    }
    if (s.ctx.db.select({ id: staff.id }).from(staff).where(eq(staff.username, body.username)).get()) {
      throw new EngineError("username_taken", "Username is already in use", 409);
    }
    const now = s.ctx.clock();
    const row = {
      id: uuidv7(now),
      branchId: s.ctx.branchId,
      name: body.name,
      phone: body.phone ?? null,
      username: body.username,
      passwordHash: await hashPassword(body.password),
      role: body.role,
      active: true,
      createdAt: now,
      updatedAt: now
    };
    s.ctx.db.insert(staff).values(row).run();
    writeAudit(s.ctx, {
      staffId: c.get("staff").staffId,
      action: "staff.create",
      entity: "staff",
      entityId: row.id,
      after: { username: row.username, role: row.role }
    });
    return c.json(pub(row), 201);
  }).patch("/api/staff/:id", requireStaff("manager"), async (c) => {
    const body = parse(external_exports.object({
      name: external_exports.string().min(1).optional(),
      phone: external_exports.string().nullish(),
      role: external_exports.enum(["owner", "manager", "operator"]).optional(),
      active: external_exports.boolean().optional(),
      password: external_exports.string().min(6).max(128).optional()
    }), await json(c));
    const actor = c.get("staff");
    const target = s.ctx.db.select().from(staff).where(eq(staff.id, c.req.param("id"))).get();
    if (!target)
      throw new EngineError("not_found", "Staff member not found", 404);
    if (!s.auth.hasRole(actor, target.role) || body.role && !s.auth.hasRole(actor, body.role)) {
      throw new EngineError("forbidden", "Insufficient role for this staff member", 403);
    }
    if (body.active === false && target.id === actor.staffId) {
      throw new EngineError("self_deactivate", "You cannot deactivate your own account", 400);
    }
    const losesOwner = target.role === "owner" && target.active && (body.active === false || body.role !== void 0 && body.role !== "owner");
    if (losesOwner) {
      const other = s.ctx.db.select({ id: staff.id }).from(staff).where(and(eq(staff.role, "owner"), eq(staff.active, true), ne(staff.id, target.id))).get();
      if (!other) {
        throw new EngineError("last_owner", "Cannot demote or deactivate the last active owner", 409);
      }
    }
    const patch = { updatedAt: s.ctx.clock() };
    if (body.name !== void 0)
      patch.name = body.name;
    if (body.phone !== void 0)
      patch.phone = body.phone ?? null;
    if (body.role !== void 0)
      patch.role = body.role;
    if (body.active !== void 0)
      patch.active = body.active;
    if (body.password !== void 0)
      patch.passwordHash = await hashPassword(body.password);
    s.ctx.db.update(staff).set(patch).where(eq(staff.id, target.id)).run();
    if (body.active === false || body.role !== void 0 && body.role !== target.role) {
      s.auth.revokeStaff(target.id);
    }
    writeAudit(s.ctx, {
      staffId: actor.staffId,
      action: "staff.update",
      entity: "staff",
      entityId: target.id,
      before: { role: target.role, active: target.active },
      after: { role: body.role ?? target.role, active: body.active ?? target.active }
    });
    return c.json(pub({ ...target, ...patch }));
  }).get("/api/zones", requireStaff(), (c) => c.json(s.ctx.db.select().from(zones).all())).post("/api/zones", requireStaff("manager"), async (c) => {
    const body = parse(external_exports.object({ name: external_exports.string().min(1), sort: external_exports.number().int().default(0) }), await json(c));
    const zone = { id: uuidv7(s.ctx.clock()), branchId: s.ctx.branchId, ...body };
    s.ctx.db.insert(zones).values(zone).run();
    return c.json(zone, 201);
  }).get("/api/pcs", requireStaff(), (c) => c.json(s.ctx.db.select().from(pcs).all())).post("/api/pcs", requireStaff("manager"), async (c) => {
    const body = parse(external_exports.object({
      zoneId: external_exports.string(),
      name: external_exports.string().min(1),
      kind: external_exports.enum(["pc", "console"]).optional(),
      extraControllerRate: money.nonnegative().nullish(),
      mac: external_exports.string().optional(),
      staticIp: external_exports.string().optional()
    }), await json(c));
    const now = s.ctx.clock();
    const kind = body.kind ?? "pc";
    const pc = {
      id: uuidv7(now),
      branchId: s.ctx.branchId,
      zoneId: body.zoneId,
      name: body.name,
      kind,
      extraControllerRate: kind === "console" ? body.extraControllerRate ?? null : null,
      mac: body.mac ?? null,
      staticIp: body.staticIp ?? null,
      // A console never gets a launcher heartbeat — it is "idle" from birth.
      status: kind === "console" ? "idle" : "offline",
      enabled: true,
      createdAt: now,
      updatedAt: now
    };
    s.ctx.db.insert(pcs).values(pc).run();
    s.hub.broadcastFloor(pc.id);
    return c.json(pc, 201);
  }).patch("/api/pcs/:id", requireStaff("manager"), async (c) => {
    const body = parse(external_exports.object({
      name: external_exports.string().min(1).optional(),
      zoneId: external_exports.string().optional(),
      enabled: external_exports.boolean().optional(),
      extraControllerRate: money.nonnegative().nullish(),
      // Manual overrides only between non-session states; the engine owns in_session.
      status: external_exports.enum(["idle", "maintenance"]).optional(),
      // Cosmetic seat identity — stored in specs, null clears.
      callsign: external_exports.string().trim().max(24).nullable().optional(),
      emblem: external_exports.string().max(32).nullable().optional(),
      bgTheme: external_exports.string().max(32).nullable().optional(),
      deckSkin: external_exports.string().max(32).nullable().optional(),
      // Floor-plan placement "x,y,r" (percent, percent, degrees) — null clears.
      layout: external_exports.string().regex(/^-?\d+(\.\d+)?,-?\d+(\.\d+)?,-?\d+(\.\d+)?$/).nullable().optional()
    }), await json(c));
    const id = c.req.param("id");
    const pc = s.ctx.db.select().from(pcs).where(eq(pcs.id, id)).get();
    if (!pc)
      throw new EngineError("not_found", "PC not found", 404);
    if (pc.status === "in_session" && (body.status || body.enabled === false)) {
      throw new EngineError("pc_busy", "Stop the session before changing this PC", 409);
    }
    const { callsign, emblem, bgTheme, deckSkin, layout, ...cols } = body;
    const set = { ...cols, updatedAt: s.ctx.clock() };
    if (callsign !== void 0 || emblem !== void 0 || bgTheme !== void 0 || deckSkin !== void 0 || layout !== void 0) {
      const specs = { ...pc.specs ?? {} };
      for (const [k, v] of [
        ["callsign", callsign],
        ["emblem", emblem],
        ["bgTheme", bgTheme],
        ["deckSkin", deckSkin],
        ["layout", layout]
      ]) {
        if (v === void 0)
          continue;
        if (v === null || v === "")
          delete specs[k];
        else
          specs[k] = v;
      }
      set.specs = specs;
    }
    s.ctx.db.update(pcs).set(set).where(eq(pcs.id, id)).run();
    s.hub.identityChanged(id);
    return c.json(s.ctx.db.select().from(pcs).where(eq(pcs.id, id)).get());
  }).post("/api/pcs/:id/lock", requireStaff(), (c) => {
    const id = c.req.param("id");
    const pc = s.ctx.db.select().from(pcs).where(eq(pcs.id, id)).get();
    if (!pc)
      throw new EngineError("not_found", "PC not found", 404);
    if (pc.status !== "idle" && pc.status !== "offline") {
      throw new EngineError("pc_busy", `Cannot lock a ${pc.status} PC`, 409);
    }
    s.ctx.db.update(pcs).set({ status: "locked", updatedAt: s.ctx.clock() }).where(eq(pcs.id, id)).run();
    s.hub.sendToPc(id, "pc.lock", {});
    s.hub.broadcastFloor(id);
    return c.json(s.ctx.db.select().from(pcs).where(eq(pcs.id, id)).get());
  }).post("/api/pcs/:id/unlock", requireStaff(), (c) => {
    const id = c.req.param("id");
    const pc = s.ctx.db.select().from(pcs).where(eq(pcs.id, id)).get();
    if (!pc)
      throw new EngineError("not_found", "PC not found", 404);
    if (pc.status !== "locked") {
      throw new EngineError("invalid", "PC is not locked", 409);
    }
    s.ctx.db.update(pcs).set({ status: "idle", updatedAt: s.ctx.clock() }).where(eq(pcs.id, id)).run();
    s.hub.sendToPc(id, "pc.unlock", {});
    s.hub.broadcastFloor(id);
    return c.json(s.ctx.db.select().from(pcs).where(eq(pcs.id, id)).get());
  }).post("/api/pcs/:id/background", requireStaff("manager"), async (c) => {
    const id = c.req.param("id");
    const pc = s.ctx.db.select().from(pcs).where(eq(pcs.id, id)).get();
    if (!pc)
      throw new EngineError("not_found", "PC not found", 404);
    const form = await c.req.parseBody();
    const file = form["file"];
    if (!(file instanceof File))
      throw new EngineError("invalid", "multipart field 'file' required", 400);
    const buf = Buffer.from(await file.arrayBuffer());
    const sig = detectMedia(buf);
    if (!sig)
      throw new EngineError("invalid", "Only JPEG/PNG/WebP images or MP4/WebM video", 400);
    const cap = sig.kind === "video" ? 6e7 : 1e7;
    if (buf.length > cap) {
      throw new EngineError("too_large", `File exceeds ${Math.round(cap / 1e6)}MB limit`, 413);
    }
    const dir = s.bgDir ?? "./data/backgrounds";
    mkdirSync2(dir, { recursive: true });
    const bgFile = `${id}-${s.ctx.clock()}.${sig.ext}`;
    writeFileSync(join(dir, bgFile), buf);
    const old = pc.specs?.bgFile;
    if (old)
      rmSync(join(dir, old), { force: true });
    s.ctx.db.update(pcs).set({ specs: { ...pc.specs ?? {}, bgFile }, updatedAt: s.ctx.clock() }).where(eq(pcs.id, id)).run();
    s.hub.identityChanged(id);
    return c.json({ bgFile }, 201);
  }).delete("/api/pcs/:id/background", requireStaff("manager"), (c) => {
    const id = c.req.param("id");
    const pc = s.ctx.db.select().from(pcs).where(eq(pcs.id, id)).get();
    if (!pc)
      throw new EngineError("not_found", "PC not found", 404);
    const { bgFile, ...rest } = pc.specs ?? {};
    if (bgFile) {
      rmSync(join(s.bgDir ?? "./data/backgrounds", bgFile), { force: true });
      s.ctx.db.update(pcs).set({ specs: rest, updatedAt: s.ctx.clock() }).where(eq(pcs.id, id)).run();
      s.hub.identityChanged(id);
    }
    return c.json({ ok: true });
  }).get("/api/pcs/:id/background", (c) => {
    const id = c.req.param("id");
    const pc = s.ctx.db.select().from(pcs).where(eq(pcs.id, id)).get();
    const bgFile = pc?.specs?.bgFile;
    if (!bgFile)
      throw new EngineError("not_found", "No background", 404);
    let body;
    try {
      body = readFileSync(join(s.bgDir ?? "./data/backgrounds", bgFile));
    } catch {
      throw new EngineError("not_found", "No background", 404);
    }
    const ext = bgFile.split(".").pop();
    const type = { jpg: "image/jpeg", png: "image/png", webp: "image/webp", mp4: "video/mp4", webm: "video/webm" }[ext] ?? "application/octet-stream";
    return c.body(new Uint8Array(body), 200, {
      "content-type": type,
      "cache-control": "public, max-age=31536000, immutable"
    });
  }).get("/covers/:file", (c) => {
    const file = c.req.param("file");
    if (file.includes("..") || file.includes("/") || file.includes("\\")) {
      throw new EngineError("not_found", "No cover", 404);
    }
    let body;
    try {
      body = readFileSync(join(s.coversDir ?? "./data/covers", file));
    } catch {
      throw new EngineError("not_found", "No cover", 404);
    }
    const type = {
      jpg: "image/jpeg",
      jpeg: "image/jpeg",
      png: "image/png",
      webp: "image/webp",
      svg: "image/svg+xml"
    }[file.split(".").pop()] ?? "application/octet-stream";
    return c.body(new Uint8Array(body), 200, {
      "content-type": type,
      "cache-control": "public, max-age=86400"
    });
  }).get("/api/games", requireStaff(), (c) => c.json(s.ctx.db.select().from(games).all())).post("/api/games", requireStaff("manager"), async (c) => {
    const body = parse(external_exports.object({
      title: external_exports.string().min(1),
      kind: external_exports.enum(["game", "app"]).default("game"),
      launchType: external_exports.enum(["exe", "steam_uri", "shortcut"]),
      exePath: external_exports.string().nullish(),
      launchUri: external_exports.string().nullish(),
      args: external_exports.string().nullish(),
      processNames: external_exports.array(external_exports.string().min(1)).min(1),
      coverUrl: external_exports.string().nullish(),
      category: external_exports.string().nullish(),
      minAge: external_exports.number().int().min(1).max(99).nullish(),
      sort: external_exports.number().int().default(0)
    }), await json(c));
    const game = {
      id: uuidv7(s.ctx.clock()),
      branchId: s.ctx.branchId,
      title: body.title,
      kind: body.kind,
      launchType: body.launchType,
      exePath: body.exePath ?? null,
      launchUri: body.launchUri ?? null,
      args: body.args ?? null,
      processNames: body.processNames,
      coverUrl: body.coverUrl ?? null,
      category: body.category ?? null,
      minAge: body.minAge ?? null,
      enabled: true,
      sort: body.sort
    };
    s.ctx.db.insert(games).values(game).run();
    return c.json(game, 201);
  }).patch("/api/games/:id", requireStaff("manager"), async (c) => {
    const body = parse(external_exports.object({
      title: external_exports.string().min(1).optional(),
      kind: external_exports.enum(["game", "app"]).optional(),
      enabled: external_exports.boolean().optional(),
      sort: external_exports.number().int().optional(),
      coverUrl: external_exports.string().nullish(),
      category: external_exports.string().nullish(),
      minAge: external_exports.number().int().min(1).max(99).nullish()
    }), await json(c));
    const id = c.req.param("id");
    const game = s.ctx.db.select().from(games).where(eq(games.id, id)).get();
    if (!game)
      throw new EngineError("not_found", "Game not found", 404);
    s.ctx.db.update(games).set({
      ...body.title !== void 0 && { title: body.title },
      ...body.kind !== void 0 && { kind: body.kind },
      ...body.enabled !== void 0 && { enabled: body.enabled },
      ...body.sort !== void 0 && { sort: body.sort },
      ...body.coverUrl !== void 0 && { coverUrl: body.coverUrl },
      ...body.category !== void 0 && { category: body.category },
      ...body.minAge !== void 0 && { minAge: body.minAge }
    }).where(eq(games.id, id)).run();
    return c.json(s.ctx.db.select().from(games).where(eq(games.id, id)).get());
  }).get("/api/products", requireStaff(), (c) => c.json(s.orders.products())).post("/api/products", requireStaff("manager"), async (c) => {
    const body = parse(external_exports.object({
      name: external_exports.string().min(1),
      price: money.positive(),
      category: external_exports.string().nullish(),
      stockQty: external_exports.number().int().nonnegative().nullish()
    }), await json(c));
    const product = {
      id: uuidv7(s.ctx.clock()),
      branchId: s.ctx.branchId,
      name: body.name,
      price: body.price,
      category: body.category ?? null,
      stockQty: body.stockQty ?? null,
      imageFile: null,
      active: true
    };
    s.ctx.db.insert(products).values(product).run();
    return c.json(product, 201);
  }).post("/api/products/:id/image", requireStaff("manager"), async (c) => {
    const id = c.req.param("id");
    const product = s.ctx.db.select().from(products).where(eq(products.id, id)).get();
    if (!product)
      throw new EngineError("not_found", "Product not found", 404);
    const form = await c.req.parseBody();
    const file = form["file"];
    if (!(file instanceof File))
      throw new EngineError("invalid", "multipart field 'file' required", 400);
    const buf = Buffer.from(await file.arrayBuffer());
    const sig = detectMedia(buf);
    if (!sig || sig.kind !== "image")
      throw new EngineError("invalid", "Only JPEG/PNG/WebP images", 400);
    if (buf.length > 1e7)
      throw new EngineError("too_large", "File exceeds 10MB limit", 413);
    const dir = s.productsDir ?? "./data/products";
    mkdirSync2(dir, { recursive: true });
    const imageFile = `${id}-${s.ctx.clock()}.${sig.ext}`;
    writeFileSync(join(dir, imageFile), buf);
    if (product.imageFile)
      rmSync(join(dir, product.imageFile), { force: true });
    s.ctx.db.update(products).set({ imageFile }).where(eq(products.id, id)).run();
    return c.json({ imageFile }, 201);
  }).delete("/api/products/:id/image", requireStaff("manager"), (c) => {
    const id = c.req.param("id");
    const product = s.ctx.db.select().from(products).where(eq(products.id, id)).get();
    if (!product)
      throw new EngineError("not_found", "Product not found", 404);
    if (product.imageFile) {
      rmSync(join(s.productsDir ?? "./data/products", product.imageFile), { force: true });
      s.ctx.db.update(products).set({ imageFile: null }).where(eq(products.id, id)).run();
    }
    return c.json({ ok: true });
  }).get("/api/products/:id/image", (c) => {
    const product = s.ctx.db.select().from(products).where(eq(products.id, c.req.param("id"))).get();
    if (!product?.imageFile)
      throw new EngineError("not_found", "No image", 404);
    let body;
    try {
      body = readFileSync(join(s.productsDir ?? "./data/products", product.imageFile));
    } catch {
      throw new EngineError("not_found", "No image", 404);
    }
    const ext = product.imageFile.split(".").pop();
    const type = { jpg: "image/jpeg", png: "image/png", webp: "image/webp" }[ext] ?? "application/octet-stream";
    return c.body(new Uint8Array(body), 200, {
      "content-type": type,
      "cache-control": "public, max-age=31536000, immutable"
    });
  }).patch("/api/products/:id", requireStaff("manager"), async (c) => {
    const body = parse(external_exports.object({
      name: external_exports.string().min(1).optional(),
      price: money.positive().optional(),
      category: external_exports.string().nullish(),
      stockQty: external_exports.number().int().nonnegative().nullish(),
      active: external_exports.boolean().optional()
    }), await json(c));
    const id = c.req.param("id");
    const product = s.ctx.db.select().from(products).where(eq(products.id, id)).get();
    if (!product)
      throw new EngineError("not_found", "Product not found", 404);
    s.ctx.db.update(products).set({
      ...body.name !== void 0 && { name: body.name },
      ...body.price !== void 0 && { price: body.price },
      ...body.category !== void 0 && { category: body.category },
      ...body.stockQty !== void 0 && { stockQty: body.stockQty },
      ...body.active !== void 0 && { active: body.active }
    }).where(eq(products.id, id)).run();
    return c.json(s.ctx.db.select().from(products).where(eq(products.id, id)).get());
  }).get("/api/orders", requireStaff(), (c) => {
    const status = c.req.query("status");
    if (status && !["placed", "delivered", "cancelled"].includes(status)) {
      throw new EngineError("invalid", "Bad status filter");
    }
    return c.json(s.orders.list({ status, limit: intQuery(c.req.query("limit"), 50, 1, 200) }));
  }).post("/api/orders", requireStaff(), async (c) => {
    const body = parse(external_exports.object({
      items: external_exports.array(external_exports.object({ productId: external_exports.string(), qty: external_exports.number().int().positive() })).min(1),
      paidVia: external_exports.enum(["wallet", "cash"]),
      customerId: external_exports.string().nullish(),
      idempotencyKey: external_exports.string().min(8)
    }), await json(c));
    return c.json(s.orders.create({
      items: body.items,
      paidVia: body.paidVia,
      customerId: body.customerId ?? null,
      source: "counter",
      staffId: c.get("staff").staffId,
      idempotencyKey: body.idempotencyKey
    }), 201);
  }).post("/api/orders/:id/deliver", requireStaff(), (c) => c.json(s.orders.deliver(c.req.param("id"), c.get("staff").staffId))).post("/api/orders/:id/cancel", requireStaff(), (c) => c.json(s.orders.cancel(c.req.param("id"), c.get("staff").staffId))).get("/api/devices", requireStaff(), (c) => c.json(s.ctx.db.select({
    id: devices.id,
    type: devices.type,
    pcId: devices.pcId,
    pairedAt: devices.pairedAt,
    revokedAt: devices.revokedAt,
    lastSeen: devices.lastSeen
  }).from(devices).all())).post("/api/devices/:id/revoke", requireStaff("manager"), (c) => {
    const id = c.req.param("id");
    const device = s.ctx.db.select().from(devices).where(eq(devices.id, id)).get();
    if (!device)
      throw new EngineError("not_found", "Device not found", 404);
    if (device.revokedAt)
      throw new EngineError("invalid", "Device already revoked", 409);
    const now = s.ctx.clock();
    s.ctx.db.update(devices).set({ revokedAt: now }).where(eq(devices.id, id)).run();
    writeAudit(s.ctx, {
      staffId: c.get("staff").staffId,
      action: "device.revoke",
      entity: "device",
      entityId: id,
      after: { type: device.type, pcId: device.pcId }
    });
    s.hub.dropDevice(id);
    const { tokenHash: _th, ...pub2 } = device;
    return c.json({ ...pub2, revokedAt: now });
  }).post("/api/devices/pairing-code", requireStaff("manager"), async (c) => {
    const body = parse(external_exports.object({ pcId: external_exports.string(), deviceType: external_exports.enum(["client", "watchdog"]).optional() }), await json(c));
    const deviceType = body.deviceType ?? "client";
    const pc = s.ctx.db.select().from(pcs).where(eq(pcs.id, body.pcId)).get();
    if (!pc)
      throw new EngineError("not_found", "PC not found", 404);
    if (pc.kind === "console") {
      throw new EngineError("bad_input", "Console stations do not pair devices", 400);
    }
    const now = s.ctx.clock();
    s.ctx.db.delete(pairingCodes).where(or(isNotNull(pairingCodes.usedAt), lt(pairingCodes.expiresAt, now))).run();
    let code;
    do {
      code = String(Math.floor(1e5 + Math.random() * 9e5));
    } while (s.ctx.db.select({ code: pairingCodes.code }).from(pairingCodes).where(eq(pairingCodes.code, code)).get());
    s.ctx.db.insert(pairingCodes).values({
      code,
      branchId: s.ctx.branchId,
      deviceType,
      pcId: body.pcId,
      createdBy: c.get("staff").staffId,
      expiresAt: now + 10 * 6e4
    }).run();
    return c.json({ code, pcId: body.pcId, expiresAt: now + 10 * 6e4 }, 201);
  }).post("/api/devices/pair", async (c) => {
    const body = parse(external_exports.object({ code: external_exports.string().length(6) }), await json(c));
    const ipKey = `pair:ip:${clientIp(c)}`;
    limiter.check(ipKey, 10);
    limiter.check("pair:global", 100);
    const now = s.ctx.clock();
    const result = s.ctx.sqlite.transaction(() => {
      const pairing = s.ctx.db.select().from(pairingCodes).where(and(eq(pairingCodes.code, body.code), isNull(pairingCodes.usedAt))).get();
      if (!pairing || pairing.expiresAt < now) {
        limiter.fail(ipKey);
        limiter.fail("pair:global");
        throw new EngineError("bad_code", "Invalid or expired pairing code", 401);
      }
      const pcId = pairing.pcId;
      if (!pcId)
        throw new EngineError("bad_code", "Pairing code is not bound to a PC", 500);
      const token = randomBytes(32).toString("hex");
      const device = {
        id: uuidv7(now),
        branchId: pairing.branchId,
        type: pairing.deviceType,
        tokenHash: createHash("sha256").update(token).digest("hex"),
        pcId,
        pairedAt: now
      };
      s.ctx.db.insert(devices).values(device).run();
      s.ctx.db.update(pairingCodes).set({ usedAt: now }).where(eq(pairingCodes.code, body.code)).run();
      if (pairing.deviceType === "client") {
        s.ctx.db.update(pcs).set({ deviceId: device.id, updatedAt: now }).where(eq(pcs.id, pcId)).run();
      }
      return { deviceToken: token, deviceId: device.id, pcId };
    })();
    limiter.clear(ipKey);
    return c.json(result, 201);
  }).post("/api/watchdog/heartbeat", async (c) => {
    const token = c.req.header("authorization")?.replace(/^Bearer\s+/i, "");
    if (!token)
      throw new EngineError("unauthorized", "Device token required", 401);
    const device = s.ctx.db.select().from(devices).where(and(eq(devices.tokenHash, createHash("sha256").update(token).digest("hex")), eq(devices.type, "watchdog"), isNull(devices.revokedAt))).get();
    if (!device?.pcId)
      throw new EngineError("unauthorized", "Unknown watchdog device", 401);
    const body = parse(external_exports.object({ launcherRunning: external_exports.boolean() }), await json(c));
    s.ctx.db.update(devices).set({ lastSeen: s.ctx.clock() }).where(eq(devices.id, device.id)).run();
    s.hub.watchdogBeat(device.pcId, body.launcherRunning);
    return c.json({ ok: true });
  });
}

// dist/services/auth.js
import { randomBytes as randomBytes2 } from "node:crypto";
import { verify } from "@node-rs/argon2";
var RANK = { operator: 0, manager: 1, owner: 2 };
var DUMMY_ARGON2_HASH = "$argon2id$v=19$m=19456,t=2,p=1$AAAAAAAAAAAAAAAAAAAAAA$AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
var TTL_MS = 12 * 36e5;
var ABSOLUTE_TTL_MS = 24 * 36e5;
var AuthService = class {
  ctx;
  sessions = /* @__PURE__ */ new Map();
  constructor(ctx2) {
    this.ctx = ctx2;
  }
  async login(username, password) {
    const row = this.ctx.db.select().from(staff).where(and(eq(staff.username, username), eq(staff.active, true))).get();
    const ok = row ? await verify(row.passwordHash, password).catch(() => false) : await verify(DUMMY_ARGON2_HASH, password).catch(() => false) && false;
    if (!row || !ok)
      throw new EngineError("bad_credentials", "Invalid username or password", 401);
    const now = this.ctx.clock();
    const session = {
      token: randomBytes2(32).toString("hex"),
      staffId: row.id,
      name: row.name,
      role: row.role,
      issuedAt: now,
      expiresAt: now + TTL_MS
    };
    this.sessions.set(session.token, session);
    return session;
  }
  authenticate(token) {
    if (!token)
      return null;
    const s = this.sessions.get(token);
    if (!s)
      return null;
    const now = this.ctx.clock();
    if (s.expiresAt <= now || now - s.issuedAt >= ABSOLUTE_TTL_MS) {
      this.sessions.delete(token);
      return null;
    }
    s.expiresAt = now + TTL_MS;
    return s;
  }
  logout(token) {
    this.sessions.delete(token);
  }
  /** Kill every live token for a staff member — deactivation or a role change
   *  must not leave an old-role session usable until its TTL. */
  revokeStaff(staffId) {
    for (const [token, sess] of this.sessions) {
      if (sess.staffId === staffId)
        this.sessions.delete(token);
    }
  }
  hasRole(s, min) {
    return RANK[s.role] >= RANK[min];
  }
};

// dist/services/customers.js
var CustomerService = class {
  ctx;
  wallet;
  constructor(ctx2, wallet2) {
    this.ctx = ctx2;
    this.wallet = wallet2;
  }
  get(id) {
    const c = this.ctx.db.select().from(customers).where(eq(customers.id, id)).get();
    if (!c)
      throw new EngineError("not_found", "Customer not found", 404);
    return c;
  }
  withBalance(id) {
    const c = this.get(id);
    return { ...c, balance: this.wallet.balance(id) };
  }
  byPhone(rawPhone) {
    const phone = this.normalize(rawPhone);
    return this.ctx.db.select().from(customers).where(eq(customers.phone, phone)).get() ?? null;
  }
  search(q, limit = 30) {
    const needle = `%${q}%`;
    return this.ctx.db.select().from(customers).where(or(like(customers.name, needle), like(customers.phone, needle))).orderBy(desc(sql`rowid`)).limit(limit).all();
  }
  create(input) {
    const phone = this.normalize(input.phone);
    if (!input.name.trim())
      throw new EngineError("bad_input", "Name is required");
    return this.ctx.sqlite.transaction(() => {
      const dup = this.ctx.db.select().from(customers).where(eq(customers.phone, phone)).get();
      if (dup)
        throw new EngineError("phone_exists", "A customer with this phone already exists", 409);
      if (input.nationalId) {
        const nidDup = this.ctx.db.select({ id: customers.id }).from(customers).where(eq(customers.nationalId, input.nationalId)).get();
        if (nidDup)
          throw new EngineError("national_id_exists", "A customer with this \u06A9\u062F \u0645\u0644\u06CC already exists", 409);
      }
      const now = this.ctx.clock();
      const customer = {
        id: uuidv7(now),
        phone,
        name: input.name.trim(),
        tier: input.tier ?? null,
        // no tier until staff assigns one — base rate applies
        nationalId: input.nationalId ?? null,
        nationalCardFile: null,
        passwordHash: null,
        // set later from the counter or the mobile app
        birthDate: input.birthDate ?? null,
        createdBranchId: this.ctx.branchId,
        status: "active",
        provisional: true,
        createdAt: now,
        updatedAt: now
      };
      this.ctx.db.insert(customers).values(customer).run();
      this.outbox("customer.created", customer, now);
      return customer;
    })();
  }
  update(id, patch, staffId) {
    return this.ctx.sqlite.transaction(() => {
      const before = this.get(id);
      if (patch.nationalId) {
        const nidDup = this.ctx.db.select({ id: customers.id }).from(customers).where(eq(customers.nationalId, patch.nationalId)).get();
        if (nidDup && nidDup.id !== id) {
          throw new EngineError("national_id_exists", "A customer with this \u06A9\u062F \u0645\u0644\u06CC already exists", 409);
        }
      }
      const now = this.ctx.clock();
      this.ctx.db.update(customers).set({ ...patch, updatedAt: now }).where(eq(customers.id, id)).run();
      const after = this.get(id);
      if (patch.tier !== void 0 && patch.tier !== before.tier || patch.status && patch.status !== before.status) {
        writeAudit(this.ctx, {
          staffId,
          action: "customer.update",
          entity: "customer",
          entityId: id,
          before: { tier: before.tier, status: before.status },
          after: { tier: after.tier, status: after.status }
        }, now);
      }
      this.outbox("customer.updated", after, now);
      return after;
    })();
  }
  /**
   * Adopt a cloud-verified identity (QR login): resolve through the alias set,
   * then phone, else insert cloud-confirmed — same rules as the sync pull
   * worker. NO outbox: the cloud already owns this identity, an echo would
   * re-register it as branch-created.
   */
  adoptCloud(cust) {
    return this.ctx.sqlite.transaction(() => {
      const local = this.ctx.db.select().from(customers).where(inArray(customers.id, aliasEquivalents(this.ctx.db, cust.id))).get();
      if (local)
        return local;
      const byPhone = this.ctx.db.select().from(customers).where(eq(customers.phone, cust.phone)).get();
      if (byPhone)
        return byPhone;
      const row = {
        id: cust.id,
        phone: cust.phone,
        name: cust.name,
        tier: cust.tier ?? null,
        nationalId: null,
        // branch-local identity fields — not part of cloud adoption
        nationalCardFile: null,
        status: cust.status,
        passwordHash: cust.passwordHash ?? null,
        birthDate: cust.birthDate ?? null,
        createdBranchId: "cloud",
        provisional: false,
        // cloud-confirmed identity
        createdAt: cust.createdAt,
        updatedAt: cust.updatedAt
      };
      this.ctx.db.insert(customers).values(row).run();
      return row;
    })();
  }
  /**
   * Set/replace the member's launcher password (hash computed by the caller —
   * this layer stays sync). Rides customer.updated so every branch can verify
   * the login offline; the audit row records who, never the hash.
   */
  setPassword(id, passwordHash, staffId) {
    return this.ctx.sqlite.transaction(() => {
      this.get(id);
      const now = this.ctx.clock();
      this.ctx.db.update(customers).set({ passwordHash, updatedAt: now }).where(eq(customers.id, id)).run();
      const after = this.get(id);
      writeAudit(this.ctx, { staffId, action: "customer.password_set", entity: "customer", entityId: id }, now);
      this.outbox("customer.updated", after, now, true);
      return after;
    })();
  }
  normalize(phone) {
    try {
      return normalizePhone(phone);
    } catch {
      throw new EngineError("bad_phone", `Invalid Iranian mobile number: ${phone}`);
    }
  }
  /**
   * passwordHash is OMITTED unless the event exists to change it (`setPassword`).
   * Absent means "don't touch" on every apply site, so a counter edit made from
   * a branch holding a stale row can never wipe — or roll back — a password set
   * from the mobile app or another branch.
   */
  outbox(eventType, customer, now, withHash = false) {
    const { passwordHash: _omit, ...withoutHash } = customer;
    this.ctx.db.insert(syncOutbox).values({
      eventId: uuidv7(now),
      aggregateType: "customer",
      aggregateId: customer.id,
      eventType,
      payload: withHash ? customer : withoutHash,
      createdAt: now
    }).run();
  }
};

// dist/services/member-auth.js
import { verify as verify2 } from "@node-rs/argon2";
var MSG = {
  badCredentials: "\u0634\u0645\u0627\u0631\u0647 \u0645\u0648\u0628\u0627\u06CC\u0644 \u06CC\u0627 \u0631\u0645\u0632 \u0639\u0628\u0648\u0631 \u0646\u0627\u062F\u0631\u0633\u062A \u0627\u0633\u062A",
  noPassword: "\u0628\u0631\u0627\u06CC \u0627\u06CC\u0646 \u062D\u0633\u0627\u0628 \u0631\u0645\u0632\u06CC \u062A\u0646\u0638\u06CC\u0645 \u0646\u0634\u062F\u0647 \u2014 \u0627\u0632 \u0627\u067E\u0644\u06CC\u06A9\u06CC\u0634\u0646 \u06CC\u0627 \u067E\u06CC\u0634\u062E\u0648\u0627\u0646 \u0631\u0645\u0632 \u0628\u06AF\u0630\u0627\u0631\u06CC\u062F",
  rateLimited: "\u062A\u0644\u0627\u0634 \u0646\u0627\u0645\u0648\u0641\u0642 \u0632\u06CC\u0627\u062F \u0628\u0648\u062F \u2014 \u0686\u0646\u062F \u062F\u0642\u06CC\u0642\u0647 \u062F\u06CC\u06AF\u0631 \u062F\u0648\u0628\u0627\u0631\u0647 \u0627\u0645\u062A\u062D\u0627\u0646 \u06A9\u0646\u06CC\u062F",
  blocked: "\u062D\u0633\u0627\u0628 \u0634\u0645\u0627 \u0645\u0633\u062F\u0648\u062F \u0627\u0633\u062A \u2014 \u0628\u0647 \u067E\u06CC\u0634\u062E\u0648\u0627\u0646 \u0645\u0631\u0627\u062C\u0639\u0647 \u06A9\u0646\u06CC\u062F",
  debt: "\u062D\u0633\u0627\u0628 \u0634\u0645\u0627 \u0628\u062F\u0647\u06CC \u062F\u0627\u0631\u062F \u2014 \u0628\u0631\u0627\u06CC \u062A\u0633\u0648\u06CC\u0647 \u0628\u0647 \u067E\u06CC\u0634\u062E\u0648\u0627\u0646 \u0645\u0631\u0627\u062C\u0639\u0647 \u06A9\u0646\u06CC\u062F",
  emptyWallet: "\u0645\u0648\u062C\u0648\u062F\u06CC \u06A9\u06CC\u0641 \u067E\u0648\u0644 \u06A9\u0627\u0641\u06CC \u0646\u06CC\u0633\u062A \u2014 \u0627\u0628\u062A\u062F\u0627 \u062D\u0633\u0627\u0628 \u062E\u0648\u062F \u0631\u0627 \u0634\u0627\u0631\u0698 \u06A9\u0646\u06CC\u062F"
};
function engineErrorMessage(err) {
  switch (err.code) {
    case "customer_in_session":
      return "\u06CC\u06A9 \u0646\u0634\u0633\u062A \u0641\u0639\u0627\u0644 \u0628\u0631\u0627\u06CC \u0634\u0645\u0627 \u062B\u0628\u062A \u0627\u0633\u062A \u2014 \u0627\u0632 \u067E\u06CC\u0634\u062E\u0648\u0627\u0646 \u067E\u06CC\u06AF\u06CC\u0631\u06CC \u06A9\u0646\u06CC\u062F";
    case "insufficient_balance":
      return "\u0645\u0648\u062C\u0648\u062F\u06CC \u06A9\u06CC\u0641 \u067E\u0648\u0644 \u06A9\u0627\u0641\u06CC \u0646\u06CC\u0633\u062A \u2014 \u0627\u0628\u062A\u062F\u0627 \u062D\u0633\u0627\u0628 \u062E\u0648\u062F \u0631\u0627 \u0634\u0627\u0631\u0698 \u06A9\u0646\u06CC\u062F";
    case "pc_busy":
    case "pc_disabled":
      return "\u0627\u06CC\u0646 \u062F\u0633\u062A\u06AF\u0627\u0647 \u062F\u0631 \u062F\u0633\u062A\u0631\u0633 \u0646\u06CC\u0633\u062A \u2014 \u0628\u0647 \u067E\u06CC\u0634\u062E\u0648\u0627\u0646 \u0645\u0631\u0627\u062C\u0639\u0647 \u06A9\u0646\u06CC\u062F";
    default:
      return "\u0634\u0631\u0648\u0639 \u0646\u0634\u0633\u062A \u0645\u0645\u06A9\u0646 \u0646\u0634\u062F \u2014 \u0628\u0647 \u067E\u06CC\u0634\u062E\u0648\u0627\u0646 \u0645\u0631\u0627\u062C\u0639\u0647 \u06A9\u0646\u06CC\u062F";
  }
}
var MemberAuthService = class {
  customers;
  engine;
  limiter;
  constructor(customers3, engine2, limiter) {
    this.customers = customers3;
    this.engine = engine2;
    this.limiter = limiter;
  }
  /**
   * Verify credentials and start the session in one step. `via` records how
   * the seat was opened; the QR path skips password verify (the phone already
   * proved identity to the cloud) and calls startSession directly.
   */
  async login(input) {
    let phone;
    try {
      phone = normalizePhone(input.phone);
    } catch {
      return { ok: false, error: MSG.badCredentials };
    }
    const phoneKey = `mlogin:p:${phone}`;
    const deviceKey = `mlogin:d:${input.deviceId}`;
    try {
      this.limiter.check(phoneKey, 5);
      this.limiter.check(deviceKey, 15);
    } catch {
      return { ok: false, error: MSG.rateLimited };
    }
    this.limiter.fail(phoneKey);
    this.limiter.fail(deviceKey);
    const customer = this.customers.byPhone(phone);
    const ok = await verify2(customer?.passwordHash ?? DUMMY_ARGON2_HASH, input.password).catch(() => false);
    if (!customer || !customer.passwordHash || !ok) {
      if (customer && !customer.passwordHash)
        return { ok: false, error: MSG.noPassword };
      return { ok: false, error: MSG.badCredentials };
    }
    this.limiter.clear(phoneKey);
    return this.startSession(customer.id, customer.status, input.pcId, "member");
  }
  /** Start the self-service open session for an already-authenticated member. */
  startSession(customerId, status, pcId, via) {
    if (status === "blocked")
      return { ok: false, error: MSG.blocked };
    if (status === "negative_balance")
      return { ok: false, error: MSG.debt };
    if (this.customers.withBalance(customerId).balance <= 0) {
      return { ok: false, error: MSG.emptyWallet };
    }
    try {
      this.engine.start({ pcId, customerId, mode: "open", openedVia: via });
    } catch (err) {
      if (err instanceof EngineError)
        return { ok: false, error: engineErrorMessage(err) };
      throw err;
    }
    return { ok: true };
  }
};

// dist/services/orders.js
var OrderService = class {
  ctx;
  wallet;
  constructor(ctx2, wallet2) {
    this.ctx = ctx2;
    this.wallet = wallet2;
  }
  products() {
    return this.ctx.db.select().from(products).where(eq(products.branchId, this.ctx.branchId)).orderBy(products.category, products.name).all();
  }
  create(input) {
    if (input.items.length === 0)
      throw new EngineError("empty_order", "Order has no items");
    for (const l of input.items) {
      if (!Number.isSafeInteger(l.qty) || l.qty <= 0) {
        throw new EngineError("bad_qty", "Item qty must be a positive integer");
      }
    }
    if (input.source === "seat" && input.paidVia === "cash" && input.customerId) {
      throw new EngineError("invalid", "Member seat orders are wallet-paid");
    }
    if (input.source === "counter" && input.paidVia === "cash" && !input.staffId) {
      throw new EngineError("invalid", "Cash orders require an operator");
    }
    return this.ctx.sqlite.transaction(() => {
      const now = this.ctx.clock();
      let staffId = input.staffId ?? null;
      const wanted = /* @__PURE__ */ new Map();
      for (const l of input.items)
        wanted.set(l.productId, (wanted.get(l.productId) ?? 0) + l.qty);
      const rows = this.ctx.db.select().from(products).where(and(eq(products.branchId, this.ctx.branchId), inArray(products.id, [...wanted.keys()]))).all();
      const byId = new Map(rows.map((p) => [p.id, p]));
      let total = 0;
      const lines = [];
      for (const [productId, qty] of wanted) {
        const p = byId.get(productId);
        if (!p || !p.active)
          throw new EngineError("not_found", "Product not available", 404);
        if (p.stockQty !== null && p.stockQty < qty) {
          throw new EngineError("out_of_stock", `\xAB${p.name}\xBB \u0645\u0648\u062C\u0648\u062F\u06CC \u06A9\u0627\u0641\u06CC \u0646\u062F\u0627\u0631\u062F`, 409);
        }
        total += p.price * qty;
        lines.push({ product: p, qty });
      }
      if (total <= 0)
        throw new EngineError("bad_amount", "Order total must be positive");
      const orderId = uuidv7(now);
      if (input.paidVia === "wallet") {
        if (!input.customerId) {
          throw new EngineError("invalid", "Wallet payment requires a customer");
        }
        const customer = this.ctx.db.select().from(customers).where(eq(customers.id, input.customerId)).get();
        if (!customer)
          throw new EngineError("not_found", "Customer not found", 404);
        if (customer.status === "blocked") {
          throw new EngineError("customer_blocked", "Customer is blocked", 409);
        }
        const balance = this.wallet.balance(customer.id);
        if (balance < total) {
          throw new EngineError("insufficient_balance", "\u0645\u0648\u062C\u0648\u062F\u06CC \u06A9\u06CC\u0641 \u067E\u0648\u0644 \u06A9\u0627\u0641\u06CC \u0646\u06CC\u0633\u062A", 409);
        }
        const { entry, deduped } = this.wallet.append({
          customerId: customer.id,
          type: "order_charge",
          amount: -total,
          refType: "order",
          refId: orderId,
          idempotencyKey: input.idempotencyKey,
          createdBy: input.staffId ?? customer.id
        });
        if (deduped) {
          const existing = entry.refId ? this.byId(entry.refId) : null;
          if (!existing)
            throw new EngineError("not_found", "Replayed order not found", 404);
          return { order: existing, balance: this.wallet.balance(customer.id) };
        }
      } else {
        const shift = requireOpenShift(this.ctx, "taking a cash order");
        staffId ??= shift?.staffId ?? null;
      }
      this.ctx.db.insert(orders).values({
        id: orderId,
        branchId: this.ctx.branchId,
        sessionId: input.sessionId ?? null,
        customerId: input.customerId ?? null,
        status: "placed",
        total,
        paidVia: input.paidVia,
        staffId,
        source: input.source,
        createdAt: now
      }).run();
      const itemRows = lines.map((l) => ({
        id: uuidv7(now),
        orderId,
        productId: l.product.id,
        qty: l.qty,
        unitPrice: l.product.price
      }));
      this.ctx.db.insert(orderItems).values(itemRows).run();
      for (const l of lines) {
        if (l.product.stockQty !== null) {
          this.ctx.db.update(products).set({ stockQty: l.product.stockQty - l.qty }).where(eq(products.id, l.product.id)).run();
        }
      }
      const order = this.byId(orderId);
      if (!order)
        throw new EngineError("internal", "Order vanished", 500);
      const { items: _items, ...orderRow } = order;
      this.ctx.db.insert(syncOutbox).values({
        eventId: uuidv7(now),
        aggregateType: "order",
        aggregateId: orderId,
        eventType: "order.created",
        payload: orderRow,
        createdAt: now
      }).run();
      return {
        order,
        balance: input.customerId ? this.wallet.balance(input.customerId) : null
      };
    })();
  }
  deliver(orderId, staffId) {
    return this.transition(orderId, "delivered", staffId);
  }
  /** Cancel a placed order: wallet refund (ledger "refund") + tracked stock back.
   *  Cash refunds are drawer-physical: the Z-report only counts non-cancelled
   *  cash orders, so a same-shift cancel reconciles; a cross-shift cancel of a
   *  cash order is the operator's manual drawer problem (delivered orders can't
   *  cancel, so the window is minutes, not days). */
  cancel(orderId, staffId) {
    return this.transition(orderId, "cancelled", staffId);
  }
  transition(orderId, to, staffId) {
    return this.ctx.sqlite.transaction(() => {
      const now = this.ctx.clock();
      const order = this.ctx.db.select().from(orders).where(eq(orders.id, orderId)).get();
      if (!order)
        throw new EngineError("not_found", "Order not found", 404);
      if (order.status !== "placed") {
        throw new EngineError("invalid", `Order is already ${order.status}`, 409);
      }
      if (to === "cancelled") {
        if (order.paidVia === "wallet" && order.customerId) {
          this.wallet.append({
            customerId: order.customerId,
            type: "refund",
            amount: order.total,
            refType: "order",
            refId: order.id,
            reason: "order cancelled",
            idempotencyKey: `order-cancel:${order.id}`,
            createdBy: staffId
          });
        }
        const items = this.ctx.db.select().from(orderItems).where(eq(orderItems.orderId, order.id)).all();
        for (const it of items) {
          this.ctx.db.update(products).set({ stockQty: sql`${products.stockQty} + ${it.qty}` }).where(and(eq(products.id, it.productId), sql`${products.stockQty} is not null`)).run();
        }
      }
      this.ctx.db.update(orders).set({ status: to }).where(eq(orders.id, order.id)).run();
      if (to === "cancelled") {
        this.ctx.db.insert(syncOutbox).values({
          eventId: uuidv7(now),
          aggregateType: "order",
          aggregateId: order.id,
          eventType: "order.cancelled",
          payload: { id: order.id, total: order.total, paidVia: order.paidVia, staffId },
          createdAt: now
        }).run();
      }
      return { ...order, status: to };
    })();
  }
  byId(orderId) {
    const order = this.ctx.db.select().from(orders).where(eq(orders.id, orderId)).get();
    if (!order)
      return null;
    return { ...order, items: this.itemsFor([orderId]).get(orderId) ?? [] };
  }
  list(opts = {}) {
    const n = Math.trunc(Number.isFinite(opts.limit ?? 50) ? Math.min(Math.max(opts.limit ?? 50, 1), 200) : 50);
    const rows = this.ctx.db.select().from(orders).where(and(eq(orders.branchId, this.ctx.branchId), ...opts.status ? [eq(orders.status, opts.status)] : [])).orderBy(desc(orders.createdAt)).limit(n).all();
    const items = this.itemsFor(rows.map((o) => o.id));
    const customerIds = [...new Set(rows.map((o) => o.customerId).filter((v) => !!v))];
    const names = new Map(customerIds.length ? this.ctx.db.select({ id: customers.id, name: customers.name }).from(customers).where(inArray(customers.id, customerIds)).all().map((r) => [r.id, r.name]) : []);
    return rows.map((o) => ({
      ...o,
      items: items.get(o.id) ?? [],
      customerName: o.customerId ? names.get(o.customerId) ?? null : null
    }));
  }
  itemsFor(orderIds) {
    const out = /* @__PURE__ */ new Map();
    if (orderIds.length === 0)
      return out;
    const rows = this.ctx.db.select({
      orderId: orderItems.orderId,
      productId: orderItems.productId,
      qty: orderItems.qty,
      unitPrice: orderItems.unitPrice,
      name: products.name
    }).from(orderItems).leftJoin(products, eq(orderItems.productId, products.id)).where(inArray(orderItems.orderId, orderIds)).all();
    for (const r of rows) {
      const list = out.get(r.orderId) ?? [];
      list.push({ productId: r.productId, name: r.name ?? "?", qty: r.qty, unitPrice: r.unitPrice });
      out.set(r.orderId, list);
    }
    return out;
  }
};

// dist/services/qr-login.js
var POLL_MS = 2500;
var REUSE_MIN_MS = 3e4;
var mintResponse = external_exports.object({ token: external_exports.string().min(8).max(128), expiresAt: external_exports.number().int() });
var claimedCustomer = external_exports.object({
  id: external_exports.string().min(1),
  phone: external_exports.string().min(1),
  name: external_exports.string().min(1),
  tier: external_exports.enum(["bronze", "silver", "gold"]).nullish(),
  status: external_exports.enum(["active", "blocked", "negative_balance"]),
  passwordHash: external_exports.string().nullish(),
  birthDate: external_exports.string().nullish(),
  createdAt: external_exports.number().int(),
  updatedAt: external_exports.number().int()
});
var QrLoginService = class {
  ctx;
  cloud;
  customers;
  memberAuth;
  push;
  watches = /* @__PURE__ */ new Map();
  // pcId → live challenge
  timer = null;
  sweeping = false;
  constructor(ctx2, cloud2, customers3, memberAuth2, push) {
    this.ctx = ctx2;
    this.cloud = cloud2;
    this.customers = customers3;
    this.memberAuth = memberAuth2;
    this.push = push;
  }
  /** Launcher asked for a challenge (lock screen mount / previous one expired). */
  async begin(pcId) {
    if (!this.cloud) {
      this.pushChallenge(pcId, null);
      return;
    }
    const existing = this.watches.get(pcId);
    if (existing && existing.expiresAt - this.ctx.clock() > REUSE_MIN_MS) {
      this.pushChallenge(pcId, existing);
      return;
    }
    const pc = this.ctx.db.select().from(pcs).where(eq(pcs.id, pcId)).get();
    if (!pc)
      return;
    try {
      const res = await this.post("/api/sync/qr/challenge", { pcId, pcName: pc.name });
      if (!res.ok)
        throw new Error(`mint failed (${res.status})`);
      const parsed = mintResponse.safeParse(await res.json());
      if (!parsed.success)
        throw new Error("mint returned an unexpected shape");
      this.watches.set(pcId, parsed.data);
      this.ensureTimer();
      this.pushChallenge(pcId, parsed.data);
    } catch {
      this.pushChallenge(pcId, null);
    }
  }
  /**
   * The seat gets a lifetime relative to receipt, never the absolute epoch:
   * `expiresAt` is minted on the CLOUD clock, and a kiosk comparing it to its
   * own would dim a perfectly good QR (or keep a dead one on screen) whenever
   * the two disagree.
   */
  pushChallenge(pcId, live) {
    this.push(pcId, "qr.challenge", {
      token: live?.token ?? null,
      ttlMs: live ? Math.max(0, live.expiresAt - this.ctx.clock()) : null
    });
  }
  /** Seat went into a session or disconnected — stop polling for it. */
  cancel(pcId) {
    this.watches.delete(pcId);
    this.maybeStopTimer();
  }
  /**
   * A challenge can rotate or be cancelled while its claim is in flight, so
   * every watch mutation — and the session start itself — must prove the seat
   * still owns the token that round-trip started with. Without this, a stale
   * 404 deletes the freshly minted watch, and a claim that resolves after
   * `cancel()` starts a billed session on a seat nobody is at.
   */
  owns(pcId, token) {
    return this.watches.get(pcId)?.token === token;
  }
  /** Shutdown/test hook. */
  stop() {
    this.watches.clear();
    this.maybeStopTimer();
  }
  ensureTimer() {
    if (this.timer)
      return;
    this.timer = setInterval(() => void this.sweep(), POLL_MS);
    this.timer.unref?.();
  }
  maybeStopTimer() {
    if (this.watches.size === 0 && this.timer) {
      clearInterval(this.timer);
      this.timer = null;
    }
  }
  async sweep() {
    if (this.sweeping)
      return;
    this.sweeping = true;
    try {
      for (const [pcId, w] of [...this.watches]) {
        if (!this.owns(pcId, w.token))
          continue;
        if (w.expiresAt <= this.ctx.clock()) {
          this.watches.delete(pcId);
          continue;
        }
        await this.claim(pcId, w.token);
      }
    } finally {
      this.sweeping = false;
      this.maybeStopTimer();
    }
  }
  /** `token` is only the ownership receipt — the cloud claims by seat. */
  async claim(pcId, token) {
    let res;
    try {
      res = await this.post("/api/sync/qr/claim", { pcId });
    } catch {
      return;
    }
    if (res.status === 404) {
      if (!this.owns(pcId, token))
        return;
      this.watches.delete(pcId);
      await this.begin(pcId);
      return;
    }
    if (!res.ok)
      return;
    const body = await res.json().catch(() => null);
    if (body?.status === "pending")
      return;
    const cust = claimedCustomer.safeParse(body?.customer);
    if (!this.owns(pcId, token))
      return;
    this.watches.delete(pcId);
    if (!cust.success)
      return;
    const local = this.customers.adoptCloud(cust.data);
    const result = this.memberAuth.startSession(local.id, local.status, pcId, "qr");
    if (!result.ok) {
      this.push(pcId, "message.show", { text: result.error, durationSec: 8 });
      this.pushChallenge(pcId, null);
    }
  }
  post(path, body) {
    const cloud2 = this.cloud;
    const f = cloud2.fetchImpl ?? fetch;
    return f(`${cloud2.url}${path}`, {
      method: "POST",
      headers: { "content-type": "application/json", authorization: `Bearer ${cloud2.token}` },
      body: JSON.stringify(body),
      signal: AbortSignal.timeout(8e3)
    });
  }
};

// dist/services/sessions.js
import { EventEmitter } from "node:events";
var LOCK_RATE_SETTING = "lock_rate_at_session_start";
function segCost(ratePerHour, startMs, endMs) {
  return minuteCost(ratePerHour, (endMs - startMs) / 6e4);
}
function effectiveRate(base, extraControllers, pc) {
  if (!extraControllers || !pc?.extraControllerRate)
    return base;
  return base + extraControllers * pc.extraControllerRate;
}
var SessionEngine = class {
  ctx;
  wallet;
  events = new EventEmitter();
  constructor(ctx2, wallet2) {
    this.ctx = ctx2;
    this.wallet = wallet2;
  }
  // -------------------------------------------------------------- queries
  session(id) {
    const s = this.ctx.db.select().from(sessions).where(eq(sessions.id, id)).get();
    if (!s)
      throw new EngineError("not_found", `Session ${id} not found`, 404);
    return s;
  }
  segments(sessionId) {
    return this.ctx.db.select().from(sessionSegments).where(eq(sessionSegments.sessionId, sessionId)).orderBy(sql`rowid`).all();
  }
  openSegment(sessionId) {
    return this.ctx.db.select().from(sessionSegments).where(and(eq(sessionSegments.sessionId, sessionId), isNull(sessionSegments.endedAt))).get();
  }
  lastSegment(sessionId) {
    return this.ctx.db.select().from(sessionSegments).where(eq(sessionSegments.sessionId, sessionId)).orderBy(desc(sql`rowid`)).limit(1).get();
  }
  activeSessions() {
    return this.ctx.db.select().from(sessions).where(inArray(sessions.status, ["active", "paused"])).all();
  }
  /** Total already charged to the wallet for this session (positive Toman). */
  chargedFor(sessionId) {
    const row = this.ctx.db.select({ sum: sql`coalesce(sum(${walletLedger.amount}), 0)` }).from(walletLedger).where(and(eq(walletLedger.refType, "session"), eq(walletLedger.refId, sessionId), eq(walletLedger.type, "session_charge"))).get();
    return -(row?.sum ?? 0);
  }
  /** Prepaid budget in Toman: what was actually charged (customer) or quoted (guest). */
  prepaidBudget(s, segs) {
    if (s.customerId)
      return this.chargedFor(s.id);
    const first = segs[0];
    if (!first || s.prepaidMinutes == null)
      return 0;
    return minuteCost(first.ratePerHour, s.prepaidMinutes);
  }
  elapsedMinutes(segs, now) {
    let ms = 0;
    for (const seg of segs)
      ms += (seg.endedAt ?? now) - seg.startedAt;
    return ms / 6e4;
  }
  accrued(segs, now) {
    let total = 0;
    for (const seg of segs) {
      total += seg.endedAt !== null ? seg.cost : segCost(seg.ratePerHour, seg.startedAt, now);
    }
    return total;
  }
  // ------------------------------------------------------------ lifecycle
  start(input) {
    const openedVia = input.openedVia ?? "staff";
    if (openedVia === "staff" && !input.staffId) {
      throw new EngineError("bad_input", "staffId required for counter session starts");
    }
    if (openedVia !== "staff" && !input.customerId) {
      throw new EngineError("bad_input", "Self-service sessions require a customer");
    }
    const events = [];
    const result = this.ctx.sqlite.transaction(() => {
      const now = this.ctx.clock();
      const pc = this.ctx.db.select().from(pcs).where(eq(pcs.id, input.pcId)).get();
      if (!pc)
        throw new EngineError("not_found", `PC ${input.pcId} not found`, 404);
      if (!pc.enabled)
        throw new EngineError("pc_disabled", `${pc.name} is disabled`);
      if (pc.status === "in_session" || pc.status === "maintenance" || pc.status === "locked") {
        throw new EngineError("pc_busy", `${pc.name} is not free (${pc.status})`, 409);
      }
      let customer = null;
      if (input.customerId) {
        customer = this.ctx.db.select().from(customers).where(eq(customers.id, input.customerId)).get() ?? null;
        if (!customer)
          throw new EngineError("not_found", "Customer not found", 404);
        if (customer.status !== "active") {
          throw new EngineError("customer_blocked", `Customer is ${customer.status}`, 409);
        }
        const live = this.ctx.db.select({ id: sessions.id }).from(sessions).where(and(eq(sessions.customerId, customer.id), inArray(sessions.status, ["active", "paused"]))).get();
        if (live) {
          throw new EngineError("customer_in_session", `${customer.name} already has an active session`, 409);
        }
      }
      const extraControllers = input.extraControllers ?? 0;
      if (extraControllers < 0 || !Number.isSafeInteger(extraControllers)) {
        throw new EngineError("bad_input", "extraControllers must be a non-negative integer");
      }
      if (extraControllers > 0 && pc.kind !== "console") {
        throw new EngineError("bad_input", "Extra controllers only apply to console stations");
      }
      const state = loadPricingState(this.ctx);
      const quote = quoteFor(state, pc.zoneId, customer?.tier ?? null, now);
      const pass = activePass(this.ctx, customer?.id ?? null, pc.id, now);
      const rate = pass ? 0 : effectiveRate(quote.ratePerHour, extraControllers, pc);
      const appliedRuleIds = pass ? [`pass:${pass.id}`] : quote.appliedRuleIds;
      const sessionId = uuidv7(now);
      let prepaidCost = null;
      if (input.mode === "prepaid") {
        if (!input.prepaidMinutes || input.prepaidMinutes <= 0) {
          throw new EngineError("bad_input", "prepaidMinutes required for prepaid sessions");
        }
        prepaidCost = minuteCost(rate, input.prepaidMinutes);
        if (customer && prepaidCost > 0) {
          if (this.wallet.balance(customer.id) < prepaidCost) {
            throw new EngineError("insufficient_balance", "Wallet balance below prepaid cost", 409);
          }
          this.wallet.append({
            customerId: customer.id,
            type: "session_charge",
            amount: -prepaidCost,
            refType: "session",
            refId: sessionId,
            idempotencyKey: `prepaid:${sessionId}`,
            createdBy: input.staffId ?? "customer"
          });
        }
      }
      const session = {
        id: sessionId,
        branchId: this.ctx.branchId,
        customerId: customer?.id ?? null,
        mode: input.mode,
        status: "active",
        startedAt: now,
        endedAt: null,
        prepaidMinutes: input.mode === "prepaid" ? input.prepaidMinutes ?? null : null,
        totalCost: 0,
        extraControllers,
        expiredAt: null,
        openedByStaff: input.staffId ?? null,
        openedVia,
        notes: input.notes ?? null
      };
      this.ctx.db.insert(sessions).values(session).run();
      const segment = {
        id: uuidv7(now),
        sessionId,
        pcId: pc.id,
        zoneId: pc.zoneId,
        ratePerHour: rate,
        appliedRuleIds,
        startedAt: now,
        endedAt: null,
        cost: 0
      };
      this.ctx.db.insert(sessionSegments).values(segment).run();
      this.setPcStatus(pc.id, "in_session", now);
      if (customer) {
        this.ctx.db.insert(syncOutbox).values({
          eventId: uuidv7(now),
          aggregateType: "session",
          aggregateId: sessionId,
          eventType: "session.started",
          payload: { sessionId, customerId: customer.id, pcName: pc.name, startedAt: now },
          createdAt: now
        }).run();
      }
      events.push({
        type: "session.start",
        pcId: pc.id,
        payload: this.sessionInfo(session, segment.ratePerHour)
      });
      return { session, segment, prepaidCost };
    })();
    this.flush(events);
    return result;
  }
  stop(sessionId, opts) {
    const events = [];
    const result = this.ctx.sqlite.transaction(() => {
      const s = this.session(sessionId);
      if (s.status !== "active" && s.status !== "paused") {
        throw new EngineError("bad_state", `Session is already ${s.status}`, 409);
      }
      const now = this.ctx.clock();
      const open = this.openSegment(sessionId);
      if (open)
        this.closeSegment(open, now);
      const segs = this.segments(sessionId);
      const rawTotal = segs.reduce((sum, seg) => sum + seg.cost, 0);
      let totalCost = rawTotal;
      if (s.mode === "prepaid" && s.expiredAt == null) {
        const budget = this.prepaidBudget(s, segs);
        totalCost = Math.min(rawTotal, budget);
        if (s.customerId && budget - totalCost > 0) {
          this.wallet.append({
            customerId: s.customerId,
            type: "refund",
            amount: budget - totalCost,
            refType: "session",
            refId: sessionId,
            idempotencyKey: `refund:${sessionId}`,
            createdBy: opts.by
          });
        }
      } else if (s.customerId) {
        const remaining = rawTotal - this.chargedFor(sessionId);
        if (remaining > 0) {
          this.wallet.append({
            customerId: s.customerId,
            type: "session_charge",
            amount: -remaining,
            refType: "session",
            refId: sessionId,
            idempotencyKey: `final:${sessionId}`,
            createdBy: opts.by
          });
        }
      }
      if (!opts.park && !s.customerId && totalCost > 0) {
        requireOpenShift(this.ctx, "settling guest cash");
      }
      if (s.customerId) {
        const playedPts = Math.floor(this.elapsedMinutes(segs, now) / 60 * this.wallet.points.perPlayedHour());
        if (playedPts > 0) {
          this.wallet.points.append({
            customerId: s.customerId,
            type: "earn_playtime",
            points: playedPts,
            refType: "session",
            refId: sessionId,
            idempotencyKey: `pts-play:${sessionId}`
          });
        }
      }
      const notes = opts.reason ? s.notes ? `${s.notes} | ${opts.reason}` : opts.reason : s.notes;
      this.ctx.db.update(sessions).set({ status: "finished", endedAt: now, totalCost, notes }).where(eq(sessions.id, sessionId)).run();
      const pcId = (open ?? this.lastSegment(sessionId))?.pcId;
      if (pcId)
        this.setPcStatus(pcId, "idle", now);
      const finished = { ...s, status: "finished", endedAt: now, totalCost, notes };
      this.ctx.db.insert(syncOutbox).values({
        eventId: uuidv7(now),
        aggregateType: "session",
        aggregateId: sessionId,
        eventType: "session.finished",
        payload: { session: finished, segments: this.segments(sessionId) },
        createdAt: now
      }).run();
      if (pcId) {
        events.push({
          type: "session.stop",
          pcId,
          payload: { sessionId, reason: opts.reason ?? "stopped" }
        });
      }
      return finished;
    })();
    this.flush(events);
    return result;
  }
  pause(sessionId) {
    const events = [];
    const result = this.ctx.sqlite.transaction(() => {
      const s = this.session(sessionId);
      if (s.status !== "active")
        throw new EngineError("bad_state", `Session is ${s.status}`, 409);
      const now = this.ctx.clock();
      const open = this.openSegment(sessionId);
      if (open)
        this.closeSegment(open, now);
      this.ctx.db.update(sessions).set({ status: "paused" }).where(eq(sessions.id, sessionId)).run();
      if (open)
        events.push({ type: "session.pause", pcId: open.pcId, payload: { sessionId } });
      return { ...s, status: "paused" };
    })();
    this.flush(events);
    return result;
  }
  resume(sessionId) {
    const events = [];
    const result = this.ctx.sqlite.transaction(() => {
      const s = this.session(sessionId);
      if (s.status !== "paused")
        throw new EngineError("bad_state", `Session is ${s.status}`, 409);
      const now = this.ctx.clock();
      const last = this.lastSegment(sessionId);
      if (!last)
        throw new EngineError("bad_state", "Session has no segments", 500);
      const pc = this.ctx.db.select().from(pcs).where(eq(pcs.id, last.pcId)).get();
      const rate = this.currentRateFor(s, last.zoneId, pc, now);
      this.ctx.db.insert(sessionSegments).values({
        id: uuidv7(now),
        sessionId,
        pcId: last.pcId,
        zoneId: last.zoneId,
        ratePerHour: rate.ratePerHour,
        appliedRuleIds: rate.appliedRuleIds,
        startedAt: now,
        endedAt: null,
        cost: 0
      }).run();
      this.ctx.db.update(sessions).set({ status: "active" }).where(eq(sessions.id, sessionId)).run();
      events.push({ type: "session.resume", pcId: last.pcId, payload: { sessionId } });
      return { ...s, status: "active" };
    })();
    this.flush(events);
    return result;
  }
  /**
   * Add prepaid minutes mid-session (console alarm response or proactive
   * top-up). Members pay the extension NOW at the current open-segment rate
   * (surcharge included); guests settle cash at stop. Clears the expiry alarm
   * so the tick can re-arm it when the new budget runs out too.
   */
  extend(sessionId, minutes, by) {
    if (!Number.isSafeInteger(minutes) || minutes <= 0) {
      throw new EngineError("bad_input", "minutes must be a positive integer");
    }
    const events = [];
    const result = this.ctx.sqlite.transaction(() => {
      const s = this.session(sessionId);
      if (s.status !== "active" && s.status !== "paused") {
        throw new EngineError("bad_state", `Session is already ${s.status}`, 409);
      }
      if (s.mode !== "prepaid" || s.prepaidMinutes == null) {
        throw new EngineError("bad_state", "Only prepaid sessions can be extended", 409);
      }
      const seg = this.openSegment(sessionId) ?? this.lastSegment(sessionId);
      if (!seg)
        throw new EngineError("bad_state", "Session has no segments", 500);
      const cost = minuteCost(seg.ratePerHour, minutes);
      if (s.customerId && cost > 0) {
        if (this.wallet.balance(s.customerId) < cost) {
          throw new EngineError("insufficient_balance", "Wallet balance below extension cost", 409);
        }
        this.wallet.append({
          customerId: s.customerId,
          type: "session_charge",
          amount: -cost,
          refType: "session",
          refId: sessionId,
          // prepaidMinutes-before-increment is unique per successful extend,
          // so a duplicate submit of the same step charges once.
          idempotencyKey: `extend:${sessionId}:${s.prepaidMinutes}`,
          createdBy: by
        });
      }
      const prepaidMinutes = s.prepaidMinutes + minutes;
      this.ctx.db.update(sessions).set({ prepaidMinutes, expiredAt: null }).where(eq(sessions.id, sessionId)).run();
      const updated = { ...s, prepaidMinutes, expiredAt: null };
      events.push({
        type: "session.extend",
        pcId: seg.pcId,
        payload: this.sessionInfo(updated, seg.ratePerHour)
      });
      return updated;
    })();
    this.flush(events);
    return result;
  }
  transfer(sessionId, toPcId) {
    const events = [];
    const result = this.ctx.sqlite.transaction(() => {
      const s = this.session(sessionId);
      if (s.status !== "active") {
        throw new EngineError("bad_state", `Only active sessions transfer (session is ${s.status})`, 409);
      }
      const now = this.ctx.clock();
      const open = this.openSegment(sessionId);
      if (!open)
        throw new EngineError("bad_state", "Active session has no open segment", 500);
      if (open.pcId === toPcId)
        throw new EngineError("bad_input", "Session is already on that PC");
      const target = this.ctx.db.select().from(pcs).where(eq(pcs.id, toPcId)).get();
      if (!target)
        throw new EngineError("not_found", `PC ${toPcId} not found`, 404);
      if (!target.enabled)
        throw new EngineError("pc_disabled", `${target.name} is disabled`);
      if (target.status === "in_session" || target.status === "maintenance" || target.status === "locked") {
        throw new EngineError("pc_busy", `${target.name} is not free (${target.status})`, 409);
      }
      this.closeSegment(open, now);
      this.setPcStatus(open.pcId, "idle", now);
      const rate = this.currentRateFor(s, target.zoneId, target, now);
      const segment = {
        id: uuidv7(now),
        sessionId,
        pcId: target.id,
        zoneId: target.zoneId,
        ratePerHour: rate.ratePerHour,
        appliedRuleIds: rate.appliedRuleIds,
        startedAt: now,
        endedAt: null,
        cost: 0
      };
      this.ctx.db.insert(sessionSegments).values(segment).run();
      this.setPcStatus(target.id, "in_session", now);
      events.push({ type: "session.stop", pcId: open.pcId, payload: { sessionId, reason: "transferred" } });
      events.push({ type: "session.start", pcId: target.id, payload: this.sessionInfo(s, segment.ratePerHour) });
      return { session: s, segment };
    })();
    this.flush(events);
    return result;
  }
  // ----------------------------------------------------------------- tick
  /**
   * The 60s billing tick. Deliberately NOT one big transaction: each
   * sub-operation (rate flip, checkpoint, auto-stop) is atomic on its own, and
   * a crash between them just leaves work for the next tick.
   */
  tick() {
    const now = this.ctx.clock();
    const lockRate = getSetting(this.ctx.db, LOCK_RATE_SETTING) === true;
    const active = this.ctx.db.select().from(sessions).where(eq(sessions.status, "active")).all();
    if (active.length === 0)
      return;
    const state = loadPricingState(this.ctx);
    for (const s of active) {
      try {
        this.tickSession(s, state, lockRate, now);
      } catch (err) {
        console.error(`[engine] tick failed for session ${s.id}:`, err);
      }
    }
  }
  tickSession(s, state, lockRate, now) {
    let seg = this.openSegment(s.id);
    if (!seg)
      return;
    const pc = this.ctx.db.select().from(pcs).where(eq(pcs.id, seg.pcId)).get();
    const locked = s.mode === "prepaid" && lockRate;
    if (!locked) {
      const tier = s.customerId ? this.ctx.db.select().from(customers).where(eq(customers.id, s.customerId)).get()?.tier ?? null : null;
      const q = quoteFor(state, seg.zoneId, tier, now);
      const pass = activePass(this.ctx, s.customerId, seg.pcId, now);
      const rate = pass ? 0 : effectiveRate(q.ratePerHour, s.extraControllers, pc);
      if (rate !== seg.ratePerHour) {
        seg = this.ctx.sqlite.transaction(() => {
          this.closeSegment(seg, now);
          const next = {
            id: uuidv7(now),
            sessionId: s.id,
            pcId: seg.pcId,
            zoneId: seg.zoneId,
            ratePerHour: rate,
            appliedRuleIds: pass ? [`pass:${pass.id}`] : q.appliedRuleIds,
            startedAt: now,
            endedAt: null,
            cost: 0
          };
          this.ctx.db.insert(sessionSegments).values(next).run();
          return next;
        })();
      }
    }
    const segs = this.segments(s.id);
    const accrued = this.accrued(segs, now);
    const elapsed = this.elapsedMinutes(segs, now);
    let balance = null;
    if (s.mode === "prepaid" && s.prepaidMinutes != null) {
      const budget = this.prepaidBudget(s, segs);
      const exhausted = locked ? elapsed >= s.prepaidMinutes : budget > 0 ? accrued >= budget : elapsed >= s.prepaidMinutes;
      if (exhausted) {
        if (pc?.kind !== "console") {
          this.stop(s.id, { by: "system", reason: "prepaid_exhausted" });
          return;
        }
        if (s.expiredAt == null) {
          this.ctx.db.update(sessions).set({ expiredAt: now }).where(eq(sessions.id, s.id)).run();
          s.expiredAt = now;
          this.events.emit("session.expired", {
            type: "session.expired",
            pcId: seg.pcId,
            payload: {
              sessionId: s.id,
              pcId: seg.pcId,
              pcName: pc?.name ?? seg.pcId,
              elapsedMinutes: Math.floor(elapsed),
              accruedCost: accrued
            }
          });
        }
      }
      const remaining = locked ? s.prepaidMinutes - elapsed : seg.ratePerHour > 0 ? (budget - accrued) / seg.ratePerHour * 60 : s.prepaidMinutes - elapsed;
      if (s.customerId)
        balance = this.wallet.balance(s.customerId);
      this.emitTick(s, seg.pcId, elapsed, remaining, accrued, balance, seg.ratePerHour);
      return;
    }
    if (s.customerId) {
      const uncharged = accrued - this.chargedFor(s.id);
      balance = this.wallet.balance(s.customerId);
      if (uncharged >= seg.ratePerHour && seg.ratePerHour > 0) {
        const priorCharges = this.ctx.db.select({ n: sql`count(*)` }).from(walletLedger).where(and(eq(walletLedger.refType, "session"), eq(walletLedger.refId, s.id), eq(walletLedger.type, "session_charge"))).get();
        this.wallet.append({
          customerId: s.customerId,
          type: "session_charge",
          amount: -uncharged,
          refType: "session",
          refId: s.id,
          idempotencyKey: `ckpt:${s.id}:${priorCharges?.n ?? 0}`,
          createdBy: "system"
        });
        balance -= uncharged;
      }
    }
    this.emitTick(s, seg.pcId, elapsed, null, accrued, balance, seg.ratePerHour);
  }
  // -------------------------------------------------------------- helpers
  /** Locked prepaid sessions keep their original (first-segment) rate everywhere.
   *  `pc` supplies the controller surcharge of the station the session sits on. */
  currentRateFor(s, zoneId, pc, now) {
    const pass = pc ? activePass(this.ctx, s.customerId, pc.id, now) : void 0;
    if (pass)
      return { ratePerHour: 0, appliedRuleIds: [`pass:${pass.id}`] };
    const lockRate = getSetting(this.ctx.db, LOCK_RATE_SETTING) === true;
    if (s.mode === "prepaid" && lockRate) {
      const first = this.segments(s.id)[0];
      if (first)
        return { ratePerHour: first.ratePerHour, appliedRuleIds: first.appliedRuleIds };
    }
    const tier = s.customerId ? this.ctx.db.select().from(customers).where(eq(customers.id, s.customerId)).get()?.tier ?? null : null;
    const q = quoteFor(loadPricingState(this.ctx), zoneId, tier, now);
    return {
      ratePerHour: effectiveRate(q.ratePerHour, s.extraControllers, pc),
      appliedRuleIds: q.appliedRuleIds
    };
  }
  closeSegment(seg, at) {
    const cost = segCost(seg.ratePerHour, seg.startedAt, at);
    this.ctx.db.update(sessionSegments).set({ endedAt: at, cost }).where(eq(sessionSegments.id, seg.id)).run();
    seg.endedAt = at;
    seg.cost = cost;
  }
  setPcStatus(pcId, status, now) {
    this.ctx.db.update(pcs).set({ status, updatedAt: now }).where(eq(pcs.id, pcId)).run();
  }
  emitTick(s, pcId, elapsed, remaining, accrued, balance, ratePerHour) {
    this.events.emit("session.tick", {
      type: "session.tick",
      pcId,
      payload: {
        sessionId: s.id,
        elapsedMinutes: Math.floor(elapsed),
        remainingMinutes: remaining !== null ? Math.ceil(remaining) : null,
        accruedCost: accrued,
        balance,
        ratePerHour
      }
    });
  }
  flush(events) {
    for (const e of events)
      this.events.emit(e.type, e);
  }
  sessionInfo(s, ratePerHour) {
    let customer = null;
    if (s.customerId) {
      const c = this.ctx.db.select().from(customers).where(eq(customers.id, s.customerId)).get();
      if (c) {
        customer = {
          id: c.id,
          name: c.name,
          tier: c.tier,
          birthDate: c.birthDate,
          balance: this.wallet.balance(c.id)
        };
      }
    }
    const now = this.ctx.clock();
    const segs = this.segments(s.id);
    return {
      sessionId: s.id,
      mode: s.mode,
      status: s.status === "paused" ? "paused" : "active",
      startedAt: s.startedAt,
      openedVia: s.openedVia,
      prepaidMinutes: s.prepaidMinutes,
      customer,
      ratePerHour,
      elapsedMinutes: Math.floor(this.elapsedMinutes(segs, now)),
      accruedCost: this.accrued(segs, now),
      expired: s.expiredAt != null,
      extraControllers: s.extraControllers
    };
  }
  /** Snapshot for the launcher on (re)connect: the live session on this PC, if any. */
  sessionInfoForPc(pcId) {
    for (const s of this.activeSessions()) {
      const last = this.lastSegment(s.id);
      if (last?.pcId === pcId)
        return this.sessionInfo(s, last.ratePerHour);
    }
    return null;
  }
};

// dist/services/tabs.js
var TabService = class {
  ctx;
  engine;
  wallet;
  constructor(ctx2, engine2, wallet2) {
    this.ctx = ctx2;
    this.engine = engine2;
    this.wallet = wallet2;
  }
  /** Open tabs, newest first, with display names for the settle panel. */
  open() {
    return this.ctx.db.select({
      tab: tabs,
      pcName: pcs.name,
      customerName: customers.name
    }).from(tabs).leftJoin(pcs, eq(tabs.pcId, pcs.id)).leftJoin(customers, eq(tabs.customerId, customers.id)).where(eq(tabs.status, "open")).orderBy(desc(tabs.createdAt)).all().map((r) => ({ ...r.tab, pcName: r.pcName, customerName: r.customerName }));
  }
  /** Open tab sitting on a station, if any (floor chip). */
  openForPc(pcId) {
    return this.ctx.db.select().from(tabs).where(eq(tabs.pcId, pcId)).orderBy(desc(tabs.createdAt)).all().find((t) => t.status === "open") ?? null;
  }
  park(sessionId, input, staffId) {
    return this.ctx.sqlite.transaction(() => {
      const s = this.ctx.db.select().from(sessions).where(eq(sessions.id, sessionId)).get();
      if (!s)
        throw new EngineError("not_found", "Session not found", 404);
      if (s.customerId) {
        throw new EngineError("bad_state", "Member sessions settle through the wallet \u2014 only guest rounds park", 409);
      }
      const lastSeg = this.ctx.db.select().from(sessionSegments).where(eq(sessionSegments.sessionId, sessionId)).orderBy(desc(sessionSegments.startedAt)).limit(1).get();
      if (!lastSeg)
        throw new EngineError("bad_state", "Session has no segments", 500);
      const finished = this.engine.stop(sessionId, { by: staffId, reason: "parked", park: true });
      const now = this.ctx.clock();
      const tab = {
        id: uuidv7(now),
        branchId: this.ctx.branchId,
        pcId: lastSeg.pcId,
        sessionId,
        customerId: input.customerId ?? null,
        label: input.label?.trim() || null,
        amount: finished.totalCost,
        status: "open",
        settledVia: null,
        shiftId: null,
        createdAt: now,
        settledAt: null
      };
      this.ctx.db.insert(tabs).values(tab).run();
      writeAudit(this.ctx, {
        staffId,
        action: "tab.park",
        entity: "tab",
        entityId: tab.id,
        after: { amount: tab.amount, label: tab.label, sessionId }
      });
      return tab;
    })();
  }
  settle(tabId, input, staffId) {
    return this.ctx.sqlite.transaction(() => {
      const tab = this.ctx.db.select().from(tabs).where(eq(tabs.id, tabId)).get();
      if (!tab)
        throw new EngineError("not_found", "Tab not found", 404);
      if (tab.status !== "open")
        throw new EngineError("bad_state", "Tab is already settled", 409);
      const now = this.ctx.clock();
      const customerId = input.customerId ?? tab.customerId;
      let shiftId = null;
      if (input.via === "cash") {
        shiftId = requireOpenShift(this.ctx, "settling tab cash")?.id ?? null;
      } else {
        if (!customerId)
          throw new EngineError("bad_input", "Wallet settlement needs a customer");
        const cust = this.ctx.db.select().from(customers).where(eq(customers.id, customerId)).get();
        if (!cust)
          throw new EngineError("not_found", "Customer not found", 404);
        if (this.wallet.balance(customerId) < tab.amount) {
          throw new EngineError("insufficient_balance", "Wallet balance below the tab amount", 409);
        }
        if (tab.amount > 0) {
          this.wallet.append({
            customerId,
            type: "tab_settle",
            amount: -tab.amount,
            refType: "tab",
            refId: tab.id,
            idempotencyKey: `tab:${tab.id}`,
            createdBy: staffId
          });
        }
      }
      this.ctx.db.update(tabs).set({ status: "settled", settledVia: input.via, customerId, shiftId, settledAt: now }).where(eq(tabs.id, tabId)).run();
      writeAudit(this.ctx, {
        staffId,
        action: "tab.settle",
        entity: "tab",
        entityId: tabId,
        after: { via: input.via, amount: tab.amount, customerId }
      });
      return { ...tab, status: "settled", settledVia: input.via, customerId, shiftId, settledAt: now };
    })();
  }
};

// ../../packages/sync/dist/hash-chain.js
import { createHash as createHash2 } from "node:crypto";
var GENESIS_HASH = "0".repeat(64);
function computeRowHash(entry) {
  return createHash2("sha256").update(`${entry.prevHash}|${entry.id}|${entry.customerId}|${entry.type}|${entry.amount}|${entry.createdAt}`).digest("hex");
}
function chainEntry(entry, prev) {
  const prevHash = prev?.rowHash ?? GENESIS_HASH;
  const withPrev = { ...entry, prevHash };
  return { ...withPrev, rowHash: computeRowHash(withPrev) };
}
function verifyChain(entries, startPrevHash = GENESIS_HASH) {
  let prevHash = startPrevHash;
  for (const entry of entries) {
    if (entry.prevHash !== prevHash)
      return entry.id;
    if (computeRowHash(entry) !== entry.rowHash)
      return entry.id;
    prevHash = entry.rowHash;
  }
  return null;
}

// dist/services/wallet.js
var WalletService = class {
  ctx;
  points;
  constructor(ctx2, points = new PointsService(ctx2)) {
    this.ctx = ctx2;
    this.points = points;
  }
  /** Union balance: SUM over the customer's alias-equivalence set (cross-branch rows included). */
  balance(customerId) {
    const row = this.ctx.db.select({ sum: sql`coalesce(sum(${walletLedger.amount}), 0)` }).from(walletLedger).where(inArray(walletLedger.customerId, aliasEquivalents(this.ctx.db, customerId))).get();
    return row?.sum ?? 0;
  }
  ledger(customerId, limit = 50) {
    return this.ctx.db.select().from(walletLedger).where(inArray(walletLedger.customerId, aliasEquivalents(this.ctx.db, customerId))).orderBy(desc(sql`rowid`)).limit(limit).all();
  }
  append(input) {
    assertToman(input.amount);
    if (input.amount === 0) {
      throw new EngineError("zero_amount", "Ledger entries must have a non-zero amount");
    }
    if (input.type === "adjustment" && !input.reason) {
      throw new EngineError("reason_required", "Adjustments require a reason");
    }
    return this.ctx.sqlite.transaction(() => {
      const existing = this.ctx.db.select().from(walletLedger).where(eq(walletLedger.idempotencyKey, input.idempotencyKey)).get();
      if (existing) {
        if (existing.customerId !== input.customerId || existing.type !== input.type || existing.amount !== input.amount) {
          throw new EngineError("idempotency_conflict", "This idempotency key was already used for a different transaction", 409);
        }
        return { entry: existing, deduped: true };
      }
      const now = this.ctx.clock();
      const prev = this.ctx.db.select().from(walletLedger).where(eq(walletLedger.branchId, this.ctx.branchId)).orderBy(desc(sql`rowid`)).limit(1).get();
      const chained = chainEntry({
        id: uuidv7(now),
        customerId: input.customerId,
        type: input.type,
        amount: input.amount,
        createdAt: now
      }, prev ?? null);
      const entry = {
        ...chained,
        type: input.type,
        branchId: this.ctx.branchId,
        refType: input.refType ?? null,
        refId: input.refId ?? null,
        reason: input.reason ?? null,
        idempotencyKey: input.idempotencyKey,
        createdBy: input.createdBy,
        deviceId: input.deviceId ?? null
      };
      this.ctx.db.insert(walletLedger).values(entry).run();
      this.ctx.db.insert(syncOutbox).values({
        eventId: uuidv7(now),
        aggregateType: "wallet_ledger",
        aggregateId: entry.id,
        eventType: "wallet.appended",
        payload: entry,
        createdAt: now
      }).run();
      if (input.type === "session_charge" || input.type === "order_charge" || input.type === "refund" && (input.refType === "session" || input.refType === "order")) {
        this.points.earnSpend(input.customerId, -input.amount, entry.id, entry.refType, entry.refId);
      }
      if (input.type === "adjustment") {
        writeAudit(this.ctx, {
          staffId: input.createdBy,
          action: "wallet.adjust",
          entity: "wallet_ledger",
          entityId: entry.id,
          after: { customerId: input.customerId, amount: input.amount, reason: input.reason }
        }, now);
      }
      return { entry, deduped: false };
    })();
  }
  topUp(input) {
    if (input.amount <= 0)
      throw new EngineError("bad_amount", "Top-up amount must be positive");
    requireOpenShift(this.ctx, "taking a counter top-up");
    return this.append({
      customerId: input.customerId,
      type: input.method === "cash" ? "topup_cash" : "topup_card",
      amount: input.amount,
      idempotencyKey: input.idempotencyKey,
      createdBy: input.staffId
    });
  }
  /**
   * Redeem points for wallet credit: one transaction writes the negative
   * `redeem` points row and the positive `points_redemption` wallet row
   * (which the earn hook ignores — redemption credit never earns points).
   * Replay-safe: the points row keys on `redeem:<key>`, and both rows are
   * atomic, so an existing points row means the wallet row exists too.
   */
  redeemPoints(input) {
    if (!Number.isSafeInteger(input.points) || input.points <= 0) {
      throw new EngineError("bad_points", "Redeem points must be a positive integer");
    }
    const rate = this.points.tomanPerPoint();
    if (rate <= 0) {
      throw new EngineError("redeem_disabled", "Point redemption is disabled on this branch", 409);
    }
    const amount = input.points * rate;
    assertToman(amount);
    return this.ctx.sqlite.transaction(() => {
      const replay = !!this.ctx.db.select().from(walletLedger).where(eq(walletLedger.idempotencyKey, input.idempotencyKey)).get();
      if (!replay && this.points.balance(input.customerId) < input.points) {
        throw new EngineError("insufficient_points", "Not enough points to redeem", 409);
      }
      const pts = this.points.append({
        customerId: input.customerId,
        type: "redeem",
        points: -input.points,
        refType: "wallet",
        idempotencyKey: `redeem:${input.idempotencyKey}`
      });
      const wallet2 = this.append({
        customerId: input.customerId,
        type: "points_redemption",
        amount,
        refType: "points",
        refId: pts.entry.id,
        idempotencyKey: input.idempotencyKey,
        createdBy: input.staffId
      });
      return { entry: wallet2.entry, amount, deduped: wallet2.deduped };
    })();
  }
  adjust(input) {
    return this.append({
      customerId: input.customerId,
      type: "adjustment",
      amount: input.amount,
      reason: input.reason,
      idempotencyKey: input.idempotencyKey,
      createdBy: input.staffId
    });
  }
  /**
   * Walk this branch's own chain in insertion order; returns the first bad row
   * id or null. Rows pulled from other branches are excluded — their chains
   * are verified by the cloud against their own branch.
   */
  verify() {
    const rows = this.ctx.db.select().from(walletLedger).where(eq(walletLedger.branchId, this.ctx.branchId)).orderBy(sql`rowid`).all();
    return verifyChain(rows);
  }
};

// dist/sync/pull.js
var BATCH = 200;
var CURSOR_STREAM = "cloud-pull";
var pullResponse = external_exports.object({
  events: external_exports.array(external_exports.object({
    seq: external_exports.number().int().positive(),
    eventId: external_exports.string(),
    branchId: external_exports.string().nullable(),
    eventType: external_exports.string(),
    payload: external_exports.unknown(),
    createdAt: external_exports.number().int()
  })),
  next: external_exports.number().int().nonnegative()
});
var walletRow = external_exports.object({
  id: external_exports.string(),
  customerId: external_exports.string(),
  branchId: external_exports.string().nullable(),
  // Derived from the schema enum — a hand-copied list here silently dropped
  // tab_settle events (found live 2026-08-01); the column is the one source.
  type: external_exports.enum(walletLedger.type.enumValues),
  amount: external_exports.number().int(),
  refType: external_exports.string().nullish(),
  refId: external_exports.string().nullish(),
  reason: external_exports.string().nullish(),
  idempotencyKey: external_exports.string(),
  createdBy: external_exports.string(),
  deviceId: external_exports.string().nullish(),
  prevHash: external_exports.string(),
  rowHash: external_exports.string(),
  createdAt: external_exports.number().int()
});
var pointsRow = external_exports.object({
  id: external_exports.string(),
  customerId: external_exports.string(),
  branchId: external_exports.string().nullable(),
  type: external_exports.enum(["earn_playtime", "earn_spend", "redeem", "badge_bonus", "adjust"]),
  points: external_exports.number().int(),
  refType: external_exports.string().nullish(),
  refId: external_exports.string().nullish(),
  idempotencyKey: external_exports.string(),
  createdAt: external_exports.number().int()
});
var customerRow = external_exports.object({
  id: external_exports.string(),
  phone: external_exports.string(),
  name: external_exports.string(),
  // Absent (old-version peer) coalesces to null = no tier.
  tier: external_exports.enum(["bronze", "silver", "gold"]).nullish(),
  status: external_exports.enum(["active", "blocked", "negative_balance"]),
  // Absent (old-version peer) ≠ null: absent means "don't touch the hash",
  // so a stale branch can never wipe a password set elsewhere.
  passwordHash: external_exports.string().nullish(),
  birthDate: external_exports.string().nullish(),
  createdBranchId: external_exports.string().nullish(),
  createdAt: external_exports.number().int(),
  updatedAt: external_exports.number().int()
});
var aliasPayload = external_exports.object({ provisionalId: external_exports.string(), canonicalId: external_exports.string() });
async function pullEvents(ctx2, target) {
  const f = target.fetchImpl ?? fetch;
  const wallet2 = new WalletService(ctx2);
  let applied = 0;
  for (; ; ) {
    const after = Number(ctx2.db.select().from(syncCursors).where(eq(syncCursors.streamName, CURSOR_STREAM)).get()?.lastEventId ?? 0);
    let body;
    try {
      const res = await f(`${target.url}/api/sync/pull?after=${after}&limit=${BATCH}`, {
        headers: { authorization: `Bearer ${target.token}` },
        signal: AbortSignal.timeout(15e3)
      });
      if (!res.ok)
        return null;
      const parsed = pullResponse.safeParse(await res.json());
      if (!parsed.success)
        return null;
      body = parsed.data;
    } catch {
      return null;
    }
    if (body.events.length === 0)
      return applied;
    ctx2.sqlite.transaction(() => {
      const now = ctx2.clock();
      const known = new Set(ctx2.db.select({ id: syncApplied.eventId }).from(syncApplied).where(inArray(syncApplied.eventId, body.events.map((e) => e.eventId))).all().map((r) => r.id));
      const touched = /* @__PURE__ */ new Set();
      for (const event of body.events) {
        if (!known.has(event.eventId)) {
          applyEvent(ctx2, event, touched);
          ctx2.db.insert(syncApplied).values({ eventId: event.eventId, appliedAt: now }).run();
          applied++;
        }
      }
      for (const customerId of touched) {
        const row = ctx2.db.select().from(customers).where(inArray(customers.id, aliasEquivalents(ctx2.db, customerId))).get();
        if (!row || row.status !== "active")
          continue;
        const balance = wallet2.balance(row.id);
        if (balance < 0) {
          ctx2.db.update(customers).set({ status: "negative_balance", updatedAt: now }).where(eq(customers.id, row.id)).run();
          writeAudit(ctx2, {
            staffId: null,
            action: "customer.negative_balance",
            entity: "customer",
            entityId: row.id,
            before: { status: row.status },
            after: { status: "negative_balance", balance }
          }, now);
        }
      }
      ctx2.db.insert(syncCursors).values({ streamName: CURSOR_STREAM, lastEventId: String(body.next), updatedAt: now }).onConflictDoUpdate({
        target: syncCursors.streamName,
        set: { lastEventId: String(body.next), updatedAt: now }
      }).run();
    })();
    if (body.events.length < BATCH)
      return applied;
  }
}
function applyEvent(ctx2, event, touched) {
  switch (event.eventType) {
    case "wallet.appended": {
      const p = walletRow.safeParse(event.payload);
      if (!p.success)
        return void console.error(`[sync] unparseable wallet event ${event.eventId} \u2014 skipped`);
      const entry = p.data;
      if (entry.branchId === ctx2.branchId)
        return;
      ctx2.db.insert(walletLedger).values({
        ...entry,
        refType: entry.refType ?? null,
        refId: entry.refId ?? null,
        reason: entry.reason ?? null,
        deviceId: entry.deviceId ?? null
      }).onConflictDoNothing().run();
      touched.add(entry.customerId);
      return;
    }
    case "points.appended": {
      const p = pointsRow.safeParse(event.payload);
      if (!p.success)
        return void console.error(`[sync] unparseable points event ${event.eventId} \u2014 skipped`);
      if (p.data.branchId === ctx2.branchId)
        return;
      ctx2.db.insert(pointsLedger).values({ ...p.data, refType: p.data.refType ?? null, refId: p.data.refId ?? null }).onConflictDoNothing().run();
      return;
    }
    case "customer.created":
    case "customer.updated": {
      const p = customerRow.safeParse(event.payload);
      if (!p.success)
        return void console.error(`[sync] unparseable customer event ${event.eventId} \u2014 skipped`);
      const cust = p.data;
      const local = ctx2.db.select().from(customers).where(inArray(customers.id, aliasEquivalents(ctx2.db, cust.id))).get();
      if (local) {
        if (cust.updatedAt > local.updatedAt) {
          ctx2.db.update(customers).set({
            name: cust.name,
            tier: cust.tier,
            status: cust.status,
            ...cust.passwordHash !== void 0 && { passwordHash: cust.passwordHash },
            birthDate: cust.birthDate ?? null,
            updatedAt: cust.updatedAt
          }).where(eq(customers.id, local.id)).run();
        }
        return;
      }
      const phoneTaken = ctx2.db.select().from(customers).where(eq(customers.phone, cust.phone)).get();
      if (phoneTaken)
        return;
      ctx2.db.insert(customers).values({
        id: cust.id,
        phone: cust.phone,
        name: cust.name,
        tier: cust.tier,
        status: cust.status,
        passwordHash: cust.passwordHash ?? null,
        birthDate: cust.birthDate ?? null,
        createdBranchId: cust.createdBranchId ?? "cloud",
        provisional: false,
        // cloud-confirmed identity
        createdAt: cust.createdAt,
        updatedAt: cust.updatedAt
      }).run();
      return;
    }
    case "customer.alias": {
      const p = aliasPayload.safeParse(event.payload);
      if (!p.success)
        return void console.error(`[sync] unparseable alias event ${event.eventId} \u2014 skipped`);
      ctx2.db.insert(customerAliases).values({ provisionalId: p.data.provisionalId, canonicalId: p.data.canonicalId, createdAt: event.createdAt }).onConflictDoNothing().run();
      ctx2.db.update(customers).set({ provisional: false }).where(eq(customers.id, p.data.provisionalId)).run();
      touched.add(p.data.canonicalId);
      return;
    }
    default:
      return;
  }
}

// dist/sync/push.js
var BATCH2 = 200;
async function pushOutbox(ctx2, target) {
  const f = target.fetchImpl ?? fetch;
  let pushed = 0;
  for (; ; ) {
    const rows = ctx2.db.select().from(syncOutbox).where(isNull(syncOutbox.ackedAt)).orderBy(sql`rowid`).limit(BATCH2).all();
    if (rows.length === 0)
      return pushed;
    let body;
    try {
      const res = await f(`${target.url}/api/sync/push`, {
        method: "POST",
        headers: { authorization: `Bearer ${target.token}`, "content-type": "application/json" },
        body: JSON.stringify({ events: rows.map(({ ackedAt: _, ...e }) => e) }),
        signal: AbortSignal.timeout(15e3)
      });
      if (!res.ok)
        return null;
      body = await res.json();
    } catch {
      return null;
    }
    if (!body.chainOk) {
      console.error("[sync] cloud reports WALLET CHAIN BROKEN for this branch \u2014 investigate before trusting the local ledger");
    }
    if (!Array.isArray(body.acked) || body.acked.length === 0)
      return null;
    ctx2.db.update(syncOutbox).set({ ackedAt: ctx2.clock() }).where(inArray(syncOutbox.eventId, body.acked)).run();
    pushed += rows.length;
    if (rows.length < BATCH2)
      return pushed;
  }
}

// dist/ws/hub.js
import { createHash as createHash3 } from "node:crypto";

// ../../node_modules/.pnpm/ws@8.21.0/node_modules/ws/wrapper.mjs
var import_stream2 = __toESM(require_stream(), 1);
var import_extension = __toESM(require_extension(), 1);
var import_permessage_deflate = __toESM(require_permessage_deflate(), 1);
var import_receiver = __toESM(require_receiver(), 1);
var import_sender = __toESM(require_sender(), 1);
var import_subprotocol = __toESM(require_subprotocol(), 1);
var import_websocket = __toESM(require_websocket(), 1);
var import_websocket_server = __toESM(require_websocket_server(), 1);

// ../../packages/protocol/dist/messages.js
var envelopeSchema = external_exports.object({
  id: external_exports.string().uuid(),
  type: external_exports.string(),
  ts: external_exports.number(),
  replyTo: external_exports.string().uuid().optional(),
  payload: external_exports.unknown()
});
var ackSchema = external_exports.object({
  ok: external_exports.boolean(),
  error: external_exports.string().optional()
});
var sessionInfoSchema = external_exports.object({
  sessionId: external_exports.string(),
  mode: external_exports.enum(["prepaid", "open"]),
  status: external_exports.enum(["active", "paused"]),
  startedAt: external_exports.number(),
  // Who opened the seat: staff from the counter, or the member themself
  // (phone+password / QR at the seat). The launcher only offers "logout &
  // end session" for self-opened sessions — counter-opened ones end at the
  // counter. Default keeps old servers/messages parseable.
  openedVia: external_exports.enum(["staff", "member", "qr"]).default("staff"),
  prepaidMinutes: external_exports.number().nullable(),
  customer: external_exports.object({
    id: external_exports.string(),
    name: external_exports.string(),
    /** null = no tier assigned (base rate). Default keeps old servers parseable. */
    tier: external_exports.enum(["bronze", "silver", "gold"]).nullable().default(null),
    /** Gregorian ISO date — the launcher derives age for game minAge gating. */
    birthDate: external_exports.string().nullable().default(null),
    balance: external_exports.number()
    // Toman
  }).nullable(),
  ratePerHour: external_exports.number(),
  // Toman
  // Authoritative billing snapshot so a (re)connecting client seeds an accurate
  // HUD without waiting for the first tick — startedAt alone can't express
  // pause-adjusted elapsed. Both are pause-aware (sum over session segments).
  elapsedMinutes: external_exports.number(),
  // active minutes played so far
  accruedCost: external_exports.number(),
  // Toman accrued so far
  /** Prepaid ran out but the session is still accruing (console/guest overtime). */
  expired: external_exports.boolean().default(false),
  /** Extra controllers beyond the first (consoles) — surcharge already in ratePerHour. */
  extraControllers: external_exports.number().default(0)
});
var gameEntrySchema = external_exports.object({
  id: external_exports.string(),
  title: external_exports.string(),
  // Default keeps older servers compatible: entries without kind are games.
  kind: external_exports.enum(["game", "app"]).default("game"),
  launchType: external_exports.enum(["exe", "steam_uri", "shortcut"]),
  exePath: external_exports.string().nullable(),
  launchUri: external_exports.string().nullable(),
  args: external_exports.string().nullable(),
  processNames: external_exports.array(external_exports.string()),
  coverUrl: external_exports.string().nullable(),
  category: external_exports.string().nullable(),
  /** Minimum age in years — null/absent = unrestricted (old servers parse fine). */
  minAge: external_exports.number().nullable().default(null),
  sort: external_exports.number()
});
var productEntrySchema = external_exports.object({
  id: external_exports.string(),
  name: external_exports.string(),
  price: external_exports.number(),
  // Toman
  category: external_exports.string().nullable(),
  stockQty: external_exports.number().nullable()
  // null = untracked
});
var pcIdentitySchema = external_exports.object({
  callsign: external_exports.string().nullable(),
  // "VIPER" — display handle for the seat
  emblem: external_exports.string().nullable(),
  // emblem id from @gamenet/ui EMBLEMS
  /** Built-in animated theme id (@gamenet/ui BG_THEMES) — open string like
   *  emblem. An uploaded background takes precedence over the theme. */
  theme: external_exports.string().nullable(),
  /** Session-screen skin id (@gamenet/ui DECK_SKINS) — open string like
   *  emblem. null = the default command deck. */
  skin: external_exports.string().nullable(),
  /** Owner-uploaded seat background. url is SERVER-RELATIVE ("/api/pcs/…") —
   *  each client prefixes its own SERVER_URL. kind gates rendering: the floor
   *  never autoplays video, the launcher plays it muted+looped. */
  background: external_exports.object({ url: external_exports.string(), kind: external_exports.enum(["image", "video"]) }).nullable()
});
var clientSnapshotSchema = external_exports.object({
  pcId: external_exports.string(),
  pcName: external_exports.string(),
  identity: pcIdentitySchema,
  session: sessionInfoSchema.nullable(),
  games: external_exports.array(gameEntrySchema),
  products: external_exports.array(productEntrySchema),
  configVersion: external_exports.number(),
  // Staff lock survives a launcher restart/reconnect — without this a killed
  // launcher process would come back unlocked.
  locked: external_exports.boolean()
});
var clientToServer = {
  "auth": external_exports.object({
    deviceToken: external_exports.string(),
    appVersion: external_exports.string()
  }),
  "heartbeat": external_exports.object({
    cpu: external_exports.number(),
    ram: external_exports.number(),
    foregroundApp: external_exports.string().nullable(),
    runningGameProcesses: external_exports.array(external_exports.string())
  }),
  "game.started": external_exports.object({
    gameId: external_exports.string(),
    processName: external_exports.string(),
    at: external_exports.number()
  }),
  "game.stopped": external_exports.object({
    gameId: external_exports.string(),
    processName: external_exports.string(),
    at: external_exports.number()
  }),
  "order.create": external_exports.object({
    sessionId: external_exports.string(),
    items: external_exports.array(external_exports.object({ productId: external_exports.string(), qty: external_exports.number().int().positive() }))
  }),
  // Member self-login at the seat. Server verifies against the locally-synced
  // Argon2id hash (works fully offline) and starts an open wallet-billed
  // session; the reply is member.login.result (replyTo = this envelope id),
  // the session itself arrives as the usual session.start push.
  "member.login": external_exports.object({
    phone: external_exports.string().min(4).max(32),
    password: external_exports.string().min(1).max(128)
  }),
  // End a SELF-opened session from the seat (server refuses for staff-opened).
  "member.logout": external_exports.object({}),
  // Ask for a fresh QR login challenge (lock screen mount / previous expired).
  "qr.refresh": external_exports.object({})
};
var serverToClient = {
  "auth.ok": clientSnapshotSchema,
  "auth.fail": external_exports.object({ reason: external_exports.string() }),
  "session.start": sessionInfoSchema,
  "session.tick": external_exports.object({
    sessionId: external_exports.string(),
    elapsedMinutes: external_exports.number(),
    remainingMinutes: external_exports.number().nullable(),
    // prepaid only
    accruedCost: external_exports.number(),
    // Toman
    balance: external_exports.number().nullable(),
    // Toman
    ratePerHour: external_exports.number()
  }),
  "session.stop": external_exports.object({ sessionId: external_exports.string(), reason: external_exports.string() }),
  "session.pause": external_exports.object({ sessionId: external_exports.string() }),
  "session.resume": external_exports.object({ sessionId: external_exports.string() }),
  // Reply to order.create (envelope.replyTo = the request id). ok:false carries
  // the human-readable reason (insufficient balance, out of stock, …).
  "order.result": external_exports.object({
    ok: external_exports.boolean(),
    orderId: external_exports.string().optional(),
    total: external_exports.number().optional(),
    // Toman
    balance: external_exports.number().optional(),
    // Toman, post-charge
    error: external_exports.string().optional()
  }),
  // Reply to member.login (envelope.replyTo = the request id). ok:false carries
  // the human-readable Persian reason (bad credentials, blocked, empty wallet …).
  "member.login.result": external_exports.object({
    ok: external_exports.boolean(),
    error: external_exports.string().optional()
  }),
  // A QR login challenge for the lock screen to render. token is the full QR
  // payload ("gnq1:<hex>"); null = QR login unavailable right now (offline
  // branch or cloud unreachable) — the launcher hides the QR block.
  // Lifetime is RELATIVE (ms from receipt), never an absolute epoch: a kiosk
  // clock that drifts from the server's would otherwise show a live QR as dead
  // (or vice versa), and a stuck kiosk clock would spin re-requesting it.
  "qr.challenge": external_exports.object({
    token: external_exports.string().nullable(),
    ttlMs: external_exports.number().nullable()
  }),
  // Cosmetic identity changed while connected (Devices edit / wallpaper upload) —
  // repaints the seat live instead of waiting for the next reconnect snapshot.
  "pc.identity": pcIdentitySchema,
  "pc.lock": external_exports.object({}),
  "pc.unlock": external_exports.object({}),
  "pc.shutdown": external_exports.object({}),
  "pc.reboot": external_exports.object({}),
  "message.show": external_exports.object({ text: external_exports.string(), durationSec: external_exports.number() }),
  "config.update": external_exports.object({
    games: external_exports.array(gameEntrySchema),
    configVersion: external_exports.number()
  })
};
var pcFloorStateSchema = external_exports.object({
  pcId: external_exports.string(),
  name: external_exports.string(),
  identity: pcIdentitySchema,
  zoneId: external_exports.string(),
  /** Consoles are admin-driven stations — no launcher/heartbeat. Default keeps old servers parseable. */
  kind: external_exports.enum(["pc", "console"]).default("pc"),
  /** Floor-plan placement (percent coords + rotation); null = not placed yet. */
  layout: external_exports.object({ x: external_exports.number(), y: external_exports.number(), r: external_exports.number() }).nullable().default(null),
  status: external_exports.enum(["idle", "in_session", "locked", "offline", "maintenance"]),
  session: sessionInfoSchema.nullable(),
  lastHeartbeat: external_exports.number().nullable(),
  foregroundApp: external_exports.string().nullable(),
  // Title of the tracked game the seat is running (from game.started/stopped
  // telemetry) — advisory display, never billing input.
  runningGame: external_exports.string().nullable(),
  /** Unsettled parked bill sitting on this station (console loser-pays flow). */
  openTab: external_exports.object({ id: external_exports.string(), label: external_exports.string().nullable(), amount: external_exports.number() }).nullable().default(null),
  // Last watchdog-service heartbeat (independent tamper channel, PLAN §Kiosk 3).
  // null = never seen since server start. `stale` is judged on the SERVER clock
  // (billing authority) — an admin box with a skewed clock must not false-alarm.
  watchdog: external_exports.object({ lastSeen: external_exports.number(), launcherRunning: external_exports.boolean(), stale: external_exports.boolean() }).nullable()
});
var adminToServer = {
  "auth": external_exports.object({ staffToken: external_exports.string() }),
  "subscribe.floor": external_exports.object({}),
  "cmd.session.start": external_exports.object({
    pcId: external_exports.string(),
    customerId: external_exports.string().nullable(),
    mode: external_exports.enum(["prepaid", "open"]),
    prepaidMinutes: external_exports.number().int().positive().nullable()
  }),
  "cmd.session.stop": external_exports.object({ sessionId: external_exports.string() }),
  "cmd.session.pause": external_exports.object({ sessionId: external_exports.string() }),
  "cmd.session.resume": external_exports.object({ sessionId: external_exports.string() }),
  "cmd.session.transfer": external_exports.object({ sessionId: external_exports.string(), toPcId: external_exports.string() }),
  "cmd.pc.lock": external_exports.object({ pcId: external_exports.string() }),
  "cmd.pc.unlock": external_exports.object({ pcId: external_exports.string() }),
  "cmd.pc.shutdown": external_exports.object({ pcId: external_exports.string() }),
  "cmd.pc.reboot": external_exports.object({ pcId: external_exports.string() }),
  "cmd.message.broadcast": external_exports.object({
    pcIds: external_exports.array(external_exports.string()).nullable(),
    // null = all
    text: external_exports.string(),
    durationSec: external_exports.number()
  })
};
var serverToAdmin = {
  "auth.ok": external_exports.object({ staffId: external_exports.string(), role: external_exports.enum(["owner", "manager", "operator"]) }),
  "auth.fail": external_exports.object({ reason: external_exports.string() }),
  "floor.snapshot": external_exports.object({ pcs: external_exports.array(pcFloorStateSchema) }),
  "floor.delta": external_exports.object({ pc: pcFloorStateSchema }),
  "order.alert": external_exports.object({
    orderId: external_exports.string(),
    pcName: external_exports.string(),
    items: external_exports.array(external_exports.object({ name: external_exports.string(), qty: external_exports.number() })),
    total: external_exports.number(),
    // Toman
    // Guest seats pay cash on delivery — the runner must know to collect.
    paidVia: external_exports.enum(["wallet", "cash"])
  }),
  // Prepaid time ran out on a console/guest seat — the session keeps accruing
  // overtime until an admin extends, stops, or parks it.
  "session.expired": external_exports.object({
    sessionId: external_exports.string(),
    pcId: external_exports.string(),
    pcName: external_exports.string(),
    elapsedMinutes: external_exports.number(),
    accruedCost: external_exports.number()
    // Toman
  })
};
function parseMessage(schemas, raw2) {
  const env = envelopeSchema.safeParse(raw2);
  if (!env.success)
    return { error: `bad envelope: ${env.error.message}` };
  const schema = schemas[env.data.type];
  if (!schema)
    return { error: `unknown message type: ${env.data.type}` };
  const payload = schema.safeParse(env.data.payload);
  if (!payload.success)
    return { error: `bad payload for ${env.data.type}: ${payload.error.message}` };
  return { type: env.data.type, envelope: env.data, payload: payload.data };
}

// dist/ws/hub.js
function identityOf(pc) {
  const bgFile = pc.specs?.bgFile ?? null;
  return {
    callsign: pc.specs?.callsign ?? null,
    emblem: pc.specs?.emblem ?? null,
    theme: pc.specs?.bgTheme ?? null,
    skin: pc.specs?.deckSkin ?? null,
    background: bgFile ? {
      url: `/api/pcs/${pc.id}/background?v=${bgFile}`,
      kind: /\.(mp4|webm)$/.test(bgFile) ? "video" : "image"
    } : null
  };
}
var WATCHDOG_STALE_MS = 9e4;
var MSG_BUDGET_PER_MIN = 120;
var Hub = class {
  db;
  clients = /* @__PURE__ */ new Map();
  // pcId → conn
  admins = /* @__PURE__ */ new Set();
  // pcId → last watchdog REST heartbeat (independent tamper channel). Memory-held
  // like connection state: a server restart just waits one beat (~30s) to repopulate.
  // `stale` is judged here on the server clock (see sweep) — never on the admin's.
  watchdogs = /* @__PURE__ */ new Map();
  sessionForPc;
  authStaff;
  placeOrder;
  memberLogin;
  memberLogout;
  qrBegin;
  qrCancel;
  constructor(db2, deps = {}) {
    this.db = db2;
    this.sessionForPc = deps.sessionForPc ?? (() => null);
    this.authStaff = deps.authStaff ?? (() => null);
    this.placeOrder = deps.placeOrder;
    this.memberLogin = deps.memberLogin;
    this.memberLogout = deps.memberLogout;
    this.qrBegin = deps.qrBegin;
    this.qrCancel = deps.qrCancel;
  }
  attach(server2) {
    const clientWss = new import_websocket_server.default({ noServer: true });
    const adminWss = new import_websocket_server.default({ noServer: true });
    server2.on("upgrade", (req, socket, head) => {
      const path = (req.url ?? "").split("?")[0];
      if (path === "/ws") {
        clientWss.handleUpgrade(req, socket, head, (ws) => clientWss.emit("connection", ws, req));
      } else if (path === "/admin/ws") {
        adminWss.handleUpgrade(req, socket, head, (ws) => adminWss.emit("connection", ws, req));
      } else {
        socket.destroy();
      }
    });
    clientWss.on("connection", (socket) => this.onClient(socket));
    adminWss.on("connection", (socket) => this.onAdmin(socket));
  }
  // -------------------------------------------------------------- launchers
  /** Returns a gate that is false once the connection exceeds its 60s budget. */
  makeBudget(socket, isAuthed) {
    let left = MSG_BUDGET_PER_MIN;
    let resetAt = Date.now() + 6e4;
    return () => {
      const now = Date.now();
      if (now >= resetAt) {
        left = MSG_BUDGET_PER_MIN;
        resetAt = now + 6e4;
      }
      if (--left >= 0)
        return true;
      if (!isAuthed())
        socket.close();
      return false;
    };
  }
  onClient(socket) {
    let conn;
    const withinBudget = this.makeBudget(socket, () => conn !== void 0);
    socket.on("message", (raw2) => {
      if (!withinBudget())
        return;
      let json;
      try {
        json = JSON.parse(String(raw2));
      } catch {
        return;
      }
      const msg = parseMessage(clientToServer, json);
      if ("error" in msg) {
        if (!conn)
          this.send(socket, "auth.fail", { reason: msg.error });
        return;
      }
      if (msg.type === "auth") {
        conn = this.authenticate(socket, msg.payload);
        return;
      }
      if (!conn)
        return;
      if (msg.type === "heartbeat") {
        conn.lastHeartbeat = Date.now();
        const fg = msg.payload.foregroundApp;
        if (fg !== conn.foregroundApp) {
          conn.foregroundApp = fg;
          this.broadcastFloor(conn.pcId);
        }
      } else if (msg.type === "game.started" || msg.type === "game.stopped") {
        const p = msg.payload;
        this.onGameActivity(conn, msg.type, p.gameId, p.processName);
      } else if (msg.type === "order.create") {
        this.onOrderCreate(conn, msg.envelope.id, msg.payload);
      } else if (msg.type === "member.login") {
        void this.onMemberLogin(conn, msg.envelope.id, msg.payload);
      } else if (msg.type === "member.logout") {
        this.onMemberLogout(conn);
      } else if (msg.type === "qr.refresh") {
        this.qrBegin?.(conn.pcId);
      }
    });
    socket.on("close", () => {
      if (!conn)
        return;
      const now = Date.now();
      for (const g of conn.runningGames.values())
        this.closePlayEvent(g, now);
      conn.runningGames.clear();
      if (this.clients.get(conn.pcId) === conn) {
        this.clients.delete(conn.pcId);
        this.qrCancel?.(conn.pcId);
        this.broadcastFloor(conn.pcId);
      }
    });
  }
  authenticate(socket, payload) {
    const tokenHash = createHash3("sha256").update(payload.deviceToken).digest("hex");
    const device = this.db.select().from(devices).where(and(eq(devices.tokenHash, tokenHash), isNull(devices.revokedAt))).get();
    if (!device?.pcId) {
      this.send(socket, "auth.fail", { reason: "unknown or revoked device" });
      socket.close();
      return void 0;
    }
    const pc = this.db.select().from(pcs).where(eq(pcs.id, device.pcId)).get();
    if (!pc) {
      this.send(socket, "auth.fail", { reason: "device not bound to a PC" });
      socket.close();
      return void 0;
    }
    const conn = {
      socket,
      deviceId: device.id,
      pcId: pc.id,
      isAlive: true,
      lastHeartbeat: Date.now(),
      foregroundApp: null,
      runningGames: /* @__PURE__ */ new Map()
    };
    socket.on("pong", () => {
      conn.isAlive = true;
      conn.lastHeartbeat = Date.now();
    });
    this.clients.get(pc.id)?.socket.terminate();
    this.clients.set(pc.id, conn);
    if (pc.status === "offline") {
      this.db.update(pcs).set({ status: "idle", updatedAt: Date.now() }).where(eq(pcs.id, pc.id)).run();
    }
    this.db.update(devices).set({ lastSeen: Date.now() }).where(eq(devices.id, device.id)).run();
    const gameList = this.db.select().from(games).where(and(eq(games.branchId, pc.branchId), eq(games.enabled, true))).all();
    const menu = this.db.select().from(products).where(and(eq(products.branchId, pc.branchId), eq(products.active, true))).all();
    const snapshot = {
      pcId: pc.id,
      pcName: pc.name,
      identity: identityOf(pc),
      session: this.sessionForPc(pc.id),
      products: menu.map((p) => ({
        id: p.id,
        name: p.name,
        price: p.price,
        category: p.category,
        stockQty: p.stockQty
      })),
      games: gameList.map((g) => ({
        id: g.id,
        title: g.title,
        kind: g.kind,
        launchType: g.launchType,
        exePath: g.exePath,
        launchUri: g.launchUri,
        args: g.args,
        processNames: g.processNames,
        coverUrl: g.coverUrl,
        category: g.category,
        minAge: g.minAge,
        sort: g.sort
      })),
      configVersion: 1,
      locked: pc.status === "locked"
    };
    this.send(socket, "auth.ok", snapshot);
    this.broadcastFloor(pc.id);
    return conn;
  }
  /**
   * Advisory game telemetry from proc-watch → floor display. The gameId is
   * client-supplied, so it is resolved against this branch's library and a
   * miss is dropped — a tampered client can at worst mislabel its own seat.
   * Keyed by processName so a game with several tracked processes only clears
   * the floor once its LAST process stops.
   */
  onGameActivity(conn, type, gameId, processName) {
    if (type === "game.stopped") {
      const entry = conn.runningGames.get(processName);
      if (!entry)
        return;
      conn.runningGames.delete(processName);
      this.closePlayEvent(entry, Date.now());
    } else {
      if (conn.runningGames.has(processName))
        return;
      const pc = this.db.select().from(pcs).where(eq(pcs.id, conn.pcId)).get();
      const game = this.db.select().from(games).where(eq(games.id, gameId)).get();
      if (!pc || !game || game.branchId !== pc.branchId)
        return;
      const now = Date.now();
      let playEventId = null;
      const session = this.sessionForPc(pc.id);
      if (session) {
        playEventId = uuidv7(now);
        this.db.insert(gamePlayEvents).values({
          id: playEventId,
          branchId: pc.branchId,
          sessionId: session.sessionId,
          customerId: session.customer?.id ?? null,
          gameId,
          pcId: pc.id,
          processName,
          startedAt: now,
          endedAt: null,
          seconds: null
        }).run();
      }
      conn.runningGames.set(processName, { gameId, title: game.title, playEventId, startedAt: now });
    }
    this.broadcastFloor(conn.pcId);
  }
  /**
   * In-seat snack order. Trust boundary: the client only picks products and
   * quantities — the customer/wallet comes from the seat's LIVE session on the
   * server, and the claimed sessionId must match it (a stale HUD ordering
   * against a finished session gets a refusal, not a charge). The envelope id
   * (uuid, one per tap) is the wallet idempotency key, so a reconnect-replay
   * returns the same order instead of double-charging.
   */
  onOrderCreate(conn, envelopeId, payload) {
    const reply = (p) => this.send(conn.socket, "order.result", p, envelopeId);
    if (!this.placeOrder)
      return reply({ ok: false, error: "\u0633\u0641\u0627\u0631\u0634 \u0627\u0632 \u0635\u0646\u062F\u0644\u06CC \u0641\u0639\u0627\u0644 \u0646\u06CC\u0633\u062A" });
    const session = this.sessionForPc(conn.pcId);
    if (!session || session.sessionId !== payload.sessionId) {
      return reply({ ok: false, error: "\u062C\u0644\u0633\u0647 \u0641\u0639\u0627\u0644\u06CC \u0631\u0648\u06CC \u0627\u06CC\u0646 \u062F\u0633\u062A\u06AF\u0627\u0647 \u0646\u06CC\u0633\u062A" });
    }
    try {
      const { order, balance } = this.placeOrder({
        items: payload.items,
        // Guest seat: no wallet to charge, the operator collects cash on delivery.
        customerId: session.customer?.id ?? null,
        sessionId: session.sessionId,
        idempotencyKey: envelopeId
      });
      reply({ ok: true, orderId: order.id, total: order.total, balance: balance ?? void 0 });
      const pc = this.db.select().from(pcs).where(eq(pcs.id, conn.pcId)).get();
      const alert = {
        orderId: order.id,
        pcName: pc?.name ?? conn.pcId,
        items: order.items.map((i) => ({ name: i.name, qty: i.qty })),
        total: order.total,
        paidVia: session.customer ? "wallet" : "cash"
      };
      for (const a of this.admins) {
        if (a.subscribed && a.socket.readyState === import_websocket.default.OPEN) {
          this.send(a.socket, "order.alert", alert);
        }
      }
    } catch (err) {
      reply({ ok: false, error: err instanceof Error ? err.message : "\u062E\u0637\u0627\u06CC \u0633\u0641\u0627\u0631\u0634" });
    }
  }
  /**
   * Member self-login from the lock screen. All policy (rate limits, hash
   * verify, wallet/status guards, session start) lives in MemberAuthService —
   * the hub only correlates the reply envelope. The session itself reaches the
   * launcher as the usual session.start engine push.
   */
  async onMemberLogin(conn, envelopeId, payload) {
    const reply = (ok, error) => this.send(conn.socket, "member.login.result", { ok, ...error ? { error } : {} }, envelopeId);
    if (!this.memberLogin)
      return reply(false, "\u0648\u0631\u0648\u062F \u0627\u0632 \u0635\u0646\u062F\u0644\u06CC \u0641\u0639\u0627\u0644 \u0646\u06CC\u0633\u062A");
    try {
      const result = await this.memberLogin({ ...payload, pcId: conn.pcId, deviceId: conn.deviceId });
      if (result.ok) {
        this.qrCancel?.(conn.pcId);
        reply(true);
      } else {
        reply(false, result.error);
      }
    } catch (err) {
      console.error("[hub] member.login failed:", err);
      reply(false, "\u062E\u0637\u0627\u06CC \u062F\u0627\u062E\u0644\u06CC \u2014 \u062F\u0648\u0628\u0627\u0631\u0647 \u062A\u0644\u0627\u0634 \u06A9\u0646\u06CC\u062F");
    }
  }
  /**
   * End the seat's session from the seat (خروج button, two-tap confirmed).
   * Owner decision 2026-07-26: allowed for ALL sessions, including
   * counter-opened — ending stops billing; settlement stays at the counter.
   */
  onMemberLogout(conn) {
    const session = this.sessionForPc(conn.pcId);
    if (!session)
      return;
    try {
      this.memberLogout?.(session.sessionId);
    } catch (err) {
      console.error("[hub] member.logout failed:", err);
    }
  }
  /** Close the play-event row a tracked process opened. Rows orphaned open by a
   *  server crash are never closed; analytics counts them as 0s (advisory data). */
  closePlayEvent(entry, now) {
    if (!entry.playEventId)
      return;
    const row = this.db.update(gamePlayEvents).set({ endedAt: now, seconds: Math.round((now - entry.startedAt) / 1e3) }).where(eq(gamePlayEvents.id, entry.playEventId)).returning().get();
    if (!row?.customerId)
      return;
    this.db.insert(syncOutbox).values({
      eventId: uuidv7(now),
      aggregateType: "gameplay",
      aggregateId: row.id,
      eventType: "gameplay.finished",
      payload: {
        gameId: entry.gameId,
        title: entry.title,
        customerId: row.customerId,
        sessionId: row.sessionId,
        seconds: row.seconds
      },
      createdAt: now
    }).run();
  }
  // ------------------------------------------------------------ admin floor
  onAdmin(socket) {
    let conn;
    const withinBudget = this.makeBudget(socket, () => conn !== void 0);
    socket.on("message", (raw2) => {
      if (!withinBudget())
        return;
      let json;
      try {
        json = JSON.parse(String(raw2));
      } catch {
        return;
      }
      const msg = parseMessage(adminToServer, json);
      if ("error" in msg) {
        if (!conn)
          this.send(socket, "auth.fail", { reason: msg.error });
        return;
      }
      if (msg.type === "auth") {
        if (conn)
          return;
        const staff2 = this.authStaff(msg.payload.staffToken);
        if (!staff2) {
          this.send(socket, "auth.fail", { reason: "invalid or expired staff token" });
          socket.close();
          return;
        }
        conn = { socket, staffId: staff2.staffId, role: staff2.role, subscribed: false };
        this.admins.add(conn);
        this.send(socket, "auth.ok", { staffId: staff2.staffId, role: staff2.role });
        return;
      }
      if (!conn)
        return;
      if (msg.type === "subscribe.floor") {
        conn.subscribed = true;
        this.send(socket, "floor.snapshot", { pcs: this.floorSnapshot() });
      }
    });
    socket.on("close", () => {
      if (conn)
        this.admins.delete(conn);
    });
  }
  floorStateFor(pc) {
    const conn = this.clients.get(pc.id);
    let runningGame = null;
    if (conn)
      for (const g of conn.runningGames.values())
        runningGame = g.title;
    const openTab = this.db.select({ id: tabs.id, label: tabs.label, amount: tabs.amount }).from(tabs).where(and(eq(tabs.pcId, pc.id), eq(tabs.status, "open"))).orderBy(desc(tabs.createdAt)).limit(1).get();
    return {
      pcId: pc.id,
      name: pc.name,
      identity: identityOf(pc),
      zoneId: pc.zoneId,
      kind: pc.kind,
      layout: parseLayout(pc.specs?.layout),
      status: pc.status,
      session: this.sessionForPc(pc.id),
      lastHeartbeat: conn?.lastHeartbeat ?? null,
      foregroundApp: conn?.foregroundApp ?? null,
      runningGame,
      openTab: openTab ?? null,
      watchdog: this.watchdogs.get(pc.id) ?? null
    };
  }
  /** Watchdog REST heartbeat → floor. Every beat broadcasts so admins see a live
   *  lastSeen; a beat also clears staleness immediately (sweep flips it back on). */
  watchdogBeat(pcId, launcherRunning) {
    this.watchdogs.set(pcId, { lastSeen: Date.now(), launcherRunning, stale: false });
    this.broadcastFloor(pcId);
  }
  floorSnapshot() {
    return this.db.select().from(pcs).all().map((pc) => this.floorStateFor(pc));
  }
  /** Generic admin fan-out (alarms like session.expired — same path as order.alert). */
  adminBroadcast(type, payload) {
    for (const a of this.admins) {
      if (a.subscribed && a.socket.readyState === import_websocket.default.OPEN) {
        this.send(a.socket, type, payload);
      }
    }
  }
  /** Push one seat's fresh state to every subscribed admin. Cheap no-op with no admins. */
  broadcastFloor(pcId) {
    if (this.admins.size === 0)
      return;
    const pc = this.db.select().from(pcs).where(eq(pcs.id, pcId)).get();
    if (!pc)
      return;
    const payload = { pc: this.floorStateFor(pc) };
    for (const a of this.admins) {
      if (a.subscribed && a.socket.readyState === import_websocket.default.OPEN) {
        this.send(a.socket, "floor.delta", payload);
      }
    }
  }
  // ---------------------------------------------------------------- shared
  send(socket, type, payload, replyTo) {
    const envelope = { id: uuidv7(), type, ts: Date.now(), payload };
    if (replyTo !== void 0)
      envelope.replyTo = replyTo;
    socket.send(JSON.stringify(envelope));
  }
  /** Best-effort push to one PC's launcher; false when it is not connected. */
  /** Cosmetic identity changed (Devices edit / wallpaper upload) — repaint the
   *  connected launcher live + refresh the floor. Offline seats miss the push
   *  harmlessly: the auth snapshot re-delivers identity on the next connect. */
  identityChanged(pcId) {
    const pc = this.db.select().from(pcs).where(eq(pcs.id, pcId)).get();
    if (pc)
      this.sendToPc(pcId, "pc.identity", identityOf(pc));
    this.broadcastFloor(pcId);
  }
  sendToPc(pcId, type, payload) {
    const conn = this.clients.get(pcId);
    if (!conn || conn.socket.readyState !== import_websocket.default.OPEN)
      return false;
    this.send(conn.socket, type, payload);
    return true;
  }
  /** Device revocation: drop the live socket holding this device's token NOW.
   *  auth.fail is terminal for the launcher (deviceSocket stops reconnecting,
   *  device.tsx clears storage) — the seat falls back to the pairing screen;
   *  the socket close handler does the registry/floor cleanup. */
  dropDevice(deviceId) {
    for (const conn of this.clients.values()) {
      if (conn.deviceId !== deviceId)
        continue;
      this.send(conn.socket, "auth.fail", { reason: "device revoked" });
      conn.socket.close();
    }
  }
  /**
   * Connectivity sweep: idle seats without a fresh heartbeat go offline, offline
   * seats with one come back. in_session/locked/maintenance are never touched —
   * billing runs on the server clock regardless of launcher connectivity. Each
   * actual transition emits a floor.delta so the admin floor stays live.
   */
  sweep(now = Date.now()) {
    const fresh = /* @__PURE__ */ new Set();
    for (const [pcId, conn] of this.clients) {
      if (!conn.isAlive) {
        conn.socket.terminate();
        this.clients.delete(pcId);
      } else {
        fresh.add(pcId);
        conn.isAlive = false;
        conn.socket.ping();
      }
    }
    const seats = this.db.select().from(pcs).where(and(inArray(pcs.status, ["idle", "offline"]), eq(pcs.kind, "pc"))).all();
    for (const pc of seats) {
      const shouldBe = fresh.has(pc.id) ? "idle" : "offline";
      if (pc.status !== shouldBe) {
        this.db.update(pcs).set({ status: shouldBe, updatedAt: now }).where(eq(pcs.id, pc.id)).run();
        this.broadcastFloor(pc.id);
      }
    }
    for (const [pcId, wd] of this.watchdogs) {
      const stale = now - wd.lastSeen > WATCHDOG_STALE_MS;
      if (stale !== wd.stale) {
        wd.stale = stale;
        this.broadcastFloor(pcId);
      }
    }
  }
  connectedPcIds() {
    return [...this.clients.keys()];
  }
};

// dist/index.js
var { db, sqlite } = openDb();
var ctx = { db, sqlite, branchId: ensureBranch(db), clock: Date.now };
var cloud = config.cloudUrl && config.cloudToken ? { url: config.cloudUrl, token: config.cloudToken } : void 0;
var wallet = new WalletService(ctx);
var engine = new SessionEngine(ctx, wallet);
var shifts2 = new ShiftService(ctx);
var customers2 = new CustomerService(ctx, wallet);
var orders2 = new OrderService(ctx, wallet);
var tabsService = new TabService(ctx, engine, wallet);
var passes = new PassService(ctx, wallet);
var auth = new AuthService(ctx);
var memberAuth = new MemberAuthService(customers2, engine, new FailureLimiter(15 * 6e4, ctx.clock));
var qrLogin;
var hub = new Hub(db, {
  sessionForPc: (pcId) => engine.sessionInfoForPc(pcId),
  authStaff: (token) => {
    const s = auth.authenticate(token);
    return s ? { staffId: s.staffId, role: s.role } : null;
  },
  // Member seat → wallet charge; guest seat → cash collected on delivery.
  placeOrder: (input) => orders2.create({ ...input, paidVia: input.customerId ? "wallet" : "cash", source: "seat" }),
  memberLogin: (input) => memberAuth.login(input),
  memberLogout: (sessionId) => void engine.stop(sessionId, { by: "customer", reason: "member_logout" }),
  qrBegin: (pcId) => void qrLogin.begin(pcId),
  qrCancel: (pcId) => qrLogin.cancel(pcId)
});
qrLogin = new QrLoginService(ctx, cloud, customers2, memberAuth, (pcId, type, payload) => hub.sendToPc(pcId, type, payload));
engine.events.on("session.start", (e) => qrLogin.cancel(e.pcId));
for (const type of ["session.start", "session.stop", "session.pause", "session.resume", "session.tick"]) {
  engine.events.on(type, (e) => hub.sendToPc(e.pcId, e.type, e.payload));
}
for (const type of ["session.start", "session.stop", "session.pause", "session.resume", "session.extend"]) {
  engine.events.on(type, (e) => hub.broadcastFloor(e.pcId));
}
engine.events.on("session.expired", (e) => {
  hub.adminBroadcast("session.expired", e.payload);
  hub.broadcastFloor(e.pcId);
});
engine.events.on("session.extend", (e) => hub.sendToPc(e.pcId, "session.start", e.payload));
var app = createApp({
  ctx,
  wallet,
  engine,
  shifts: shifts2,
  customers: customers2,
  orders: orders2,
  tabs: tabsService,
  passes,
  auth,
  hub,
  bgDir: join2(dirname3(config.dbPath), "backgrounds"),
  coversDir: join2(dirname3(config.dbPath), "covers"),
  cardsDir: join2(dirname3(config.dbPath), "cards"),
  productsDir: join2(dirname3(config.dbPath), "products"),
  ...cloud ? { cloud } : {}
});
var server = serve({ fetch: app.fetch, port: config.port }, (info) => {
  console.log(`[gamenet] local server on http://localhost:${info.port} (WS /ws)`);
});
hub.attach(server);
setInterval(() => engine.tick(), 6e4);
setInterval(() => hub.sweep(), 5e3);
if (cloud) {
  let syncing = false;
  const syncTick = async () => {
    if (syncing)
      return;
    syncing = true;
    try {
      const pushed = await pushOutbox(ctx, cloud);
      if (pushed)
        console.log(`[sync] pushed ${pushed} events to cloud`);
      const pulled = await pullEvents(ctx, cloud);
      if (pulled)
        console.log(`[sync] applied ${pulled} events from cloud`);
    } finally {
      syncing = false;
    }
  };
  void syncTick();
  setInterval(() => void syncTick(), 6e4);
  console.log(`[gamenet] cloud sync enabled \u2192 ${config.cloudUrl}`);
}
var startupChain = wallet.verify();
if (startupChain) {
  console.error(`[gamenet] WALLET LEDGER CHAIN BROKEN at entry ${startupChain} \u2014 investigate before operating`);
}
