UNPKG

@pgxsinkit/pgwasm

Version:
6,672 lines • 242 kB
// @bun
import {
  createPgwasm2
} from "../chunk-gjf102c9.js";
import {
  UnsupportedFeatureError2
} from "../chunk-cpsnmzrf.js";
import {
  BaseFilesystem2
} from "../chunk-z0c40tja.js";
import {
  registerStrictSync,
  strictSyncOf
} from "../chunk-74gcrk47.js";

// packages/pgwasm/src/opfs/core/errors.ts
var FS_ERRNO = {
  EBADF: 8,
  EEXIST: 20,
  EINVAL: 28,
  EIO: 29,
  EISDIR: 31,
  ELOOP: 32,
  ENOENT: 44,
  ENOTDIR: 54,
  ENOTEMPTY: 55,
  EXDEV: 75
};

class FsError extends Error {
  code;
  operation;
  path;
  constructor(name, message, options = {}) {
    super(message, { cause: options.cause });
    this.name = "FsError";
    this.code = FS_ERRNO[name];
    this.operation = options.operation;
    this.path = options.path;
  }
}

class StoreLimitError extends Error {
  storeCode = "STORE_LIMIT";
  constructor(message, options) {
    super(message, options);
    this.name = "StoreLimitError";
  }
}

class CorruptStoreError extends Error {
  storeCode = "CORRUPT_STORE";
  constructor(message, options) {
    super(message, options);
    this.name = "CorruptStoreError";
  }
}

class StoreRecreationRequiredError extends Error {
  storeCode = "STORE_RECREATION_REQUIRED";
  constructor(message, options) {
    super(message, options);
    this.name = "StoreRecreationRequiredError";
  }
}

class ExtentSizeMismatchError extends Error {
  storeCode = "EXTENT_SIZE_MISMATCH";
  constructor(expected, actual) {
    super(`configured extent size ${expected} does not match persisted extent size ${actual}`);
    this.name = "ExtentSizeMismatchError";
  }
}

class StoreOwnedError extends Error {
  storeCode = "STORE_OWNED";
  constructor(options) {
    super("the OPFS repacked store is already exclusively owned by another live instance", options);
    this.name = "StoreOwnedError";
  }
}

class UnexpectedStoreEntryError extends Error {
  storeCode = "UNEXPECTED_STORE_ENTRY";
  constructor(entryName) {
    super(`the OPFS repacked store contains an unexpected entry: ${entryName}`);
    this.name = "UnexpectedStoreEntryError";
  }
}

class DurabilityModeMismatchError extends Error {
  storeCode = "DURABILITY_MODE_MISMATCH";
  constructor() {
    super("the pgwasm host attempted a non-awaited OPFS repacked sync");
    this.name = "DurabilityModeMismatchError";
  }
}

class StoreClosedError extends Error {
  storeCode = "STORE_CLOSED";
  constructor() {
    super("the OPFS repacked store is closed");
    this.name = "StoreClosedError";
  }
}

class StoreFailedError extends Error {
  storeCode = "STORE_FAILED";
  code = FS_ERRNO.EIO;
  cause;
  constructor(cause) {
    super(`the OPFS repacked store is poisoned and must be reopened: ${String(cause)}`, { cause });
    this.name = "StoreFailedError";
    this.cause = cause;
  }
}
// packages/pgwasm/src/opfs/opfs-port.ts
class OpfsRepackedPort {
  #directory;
  constructor(directory) {
    this.#directory = directory;
  }
  async enumerate(_label) {
    const entries = [];
    for await (const entry of this.#directory.values()) {
      entries.push({ name: entry.name, kind: entry.kind });
    }
    return entries;
  }
  async acquire(name, _label) {
    const file = await this.#directory.getFileHandle(name, { create: true });
    try {
      return new OpfsRepackedFileHandle(name, await file.createSyncAccessHandle());
    } catch (cause) {
      if (isOwnershipFailure(cause))
        throw new StoreOwnedError({ cause });
      throw cause;
    }
  }
}

class OpfsRepackedFileHandle {
  name;
  #handle;
  constructor(name, handle) {
    this.name = name;
    this.#handle = handle;
  }
  getSize(_label) {
    return this.#handle.getSize();
  }
  read(target, at, _label) {
    return this.#handle.read(target, { at });
  }
  write(source, at, _label) {
    return this.#handle.write(source, { at });
  }
  truncate(size, _label) {
    this.#handle.truncate(size);
  }
  flush(_label) {
    this.#handle.flush();
  }
  close() {
    this.#handle.close();
  }
}
function isOwnershipFailure(cause) {
  if (typeof cause !== "object" || cause === null || !("name" in cause))
    return false;
  return cause.name === "NoModificationAllowedError" || cause.name === "InvalidStateError";
}

// packages/pgwasm/src/opfs/core/checksum.ts
var CRC32_TABLE = new Uint32Array(256);
for (let value = 0;value < CRC32_TABLE.length; value += 1) {
  let remainder = value;
  for (let bit = 0;bit < 8; bit += 1) {
    remainder = (remainder & 1) === 1 ? 3988292384 ^ remainder >>> 1 : remainder >>> 1;
  }
  CRC32_TABLE[value] = remainder >>> 0;
}
var CRC32_SLICES = [CRC32_TABLE];
for (let slice = 1;slice < 8; slice += 1) {
  const previous = CRC32_SLICES[slice - 1];
  const current = new Uint32Array(256);
  for (let value = 0;value < current.length; value += 1) {
    const remainder = previous[value];
    current[value] = (CRC32_TABLE[remainder & 255] ^ remainder >>> 8) >>> 0;
  }
  CRC32_SLICES.push(current);
}
var CRC32_SLICE_1 = CRC32_SLICES[1];
var CRC32_SLICE_2 = CRC32_SLICES[2];
var CRC32_SLICE_3 = CRC32_SLICES[3];
var CRC32_SLICE_4 = CRC32_SLICES[4];
var CRC32_SLICE_5 = CRC32_SLICES[5];
var CRC32_SLICE_6 = CRC32_SLICES[6];
var CRC32_SLICE_7 = CRC32_SLICES[7];
function updateCrc32(remainder, bytes, start, end) {
  let index = start;
  while (index + 8 <= end) {
    const word = remainder ^ (bytes[index] | bytes[index + 1] << 8 | bytes[index + 2] << 16 | bytes[index + 3] << 24);
    remainder = CRC32_SLICE_7[word & 255] ^ CRC32_SLICE_6[word >>> 8 & 255] ^ CRC32_SLICE_5[word >>> 16 & 255] ^ CRC32_SLICE_4[word >>> 24] ^ CRC32_SLICE_3[bytes[index + 4]] ^ CRC32_SLICE_2[bytes[index + 5]] ^ CRC32_SLICE_1[bytes[index + 6]] ^ CRC32_TABLE[bytes[index + 7]];
    index += 8;
  }
  for (;index < end; index += 1) {
    remainder = CRC32_TABLE[(remainder ^ bytes[index]) & 255] ^ remainder >>> 8;
  }
  return remainder;
}
function updateCrc32WithZeros(remainder, length) {
  while (length >= 8) {
    remainder = CRC32_SLICE_7[remainder & 255] ^ CRC32_SLICE_6[remainder >>> 8 & 255] ^ CRC32_SLICE_5[remainder >>> 16 & 255] ^ CRC32_SLICE_4[remainder >>> 24];
    length -= 8;
  }
  while (length > 0) {
    remainder = CRC32_TABLE[remainder & 255] ^ remainder >>> 8;
    length -= 1;
  }
  return remainder;
}
function crc32(bytes) {
  const remainder = updateCrc32(4294967295, bytes, 0, bytes.byteLength);
  return (remainder ^ 4294967295) >>> 0;
}
function crc32WithZeroedRange(bytes, offset, length) {
  if (!Number.isSafeInteger(offset) || !Number.isSafeInteger(length) || offset < 0 || length < 0) {
    throw new TypeError("checksum range must use non-negative safe integers");
  }
  if (offset + length > bytes.byteLength) {
    throw new RangeError("checksum range exceeds the input");
  }
  const zeroEnd = offset + length;
  let remainder = updateCrc32(4294967295, bytes, 0, offset);
  remainder = updateCrc32WithZeros(remainder, length);
  remainder = updateCrc32(remainder, bytes, zeroEnd, bytes.byteLength);
  return (remainder ^ 4294967295) >>> 0;
}

// packages/pgwasm/src/opfs/core/limits.ts
var FORMAT_VERSION = 2;
var LIMITS_PROFILE_VERSION = 1;
var ARENA_HEADER_BYTES = 8192;
var MIN_EXTENT_BYTES = 8192;
var MAX_EXTENT_BYTES = 16 * 1024 * 1024;
var DEFAULT_EXTENT_BYTES = 64 * 1024;
var MAX_COMPONENT_BYTES = 255;
var MAX_PATH_BYTES = 1024;
var MAX_PATH_DEPTH = 32;
var MAX_SYMLINK_HOPS = 32;
var MAX_INODES = 65536;
var MAX_EXTENTS_PER_INODE = 2 ** 20;
var MAX_TOTAL_EXTENTS = 2 ** 22;
var MAX_METADATA_BASE_READER_BYTES = 64 * 1024 * 1024;
var MAX_METADATA_BASE_WRITER_BYTES = 32 * 1024 * 1024;
var MAX_FRAME_PAYLOAD_BYTES = 1024 * 1024;
var MAX_ACTIVE_LOG_BYTES = 16 * 1024 * 1024;
var SOFT_ACTIVE_LOG_BYTES = 8 * 1024 * 1024;
var MAX_ACTIVE_LOG_FRAMES = 32768;
var SOFT_ACTIVE_LOG_FRAMES = 16384;
var MAX_U64 = (1n << 64n) - 1n;
function validateExtentSize(value) {
  if (!Number.isSafeInteger(value) || value < MIN_EXTENT_BYTES || value > MAX_EXTENT_BYTES || value % ARENA_HEADER_BYTES !== 0) {
    throw new TypeError(`extentSize must be an ${ARENA_HEADER_BYTES}-byte multiple between ${MIN_EXTENT_BYTES} and ${MAX_EXTENT_BYTES}`);
  }
  return value;
}
function checkedU64(value, label) {
  if (value < 0n || value > MAX_U64) {
    throw new StoreLimitError(`${label} is outside the unsigned 64-bit range`);
  }
  return value;
}
function checkedSafeNumber(value, label) {
  checkedU64(value, label);
  if (value > BigInt(Number.MAX_SAFE_INTEGER)) {
    throw new StoreLimitError(`${label} exceeds JavaScript's safe integer range`);
  }
  return Number(value);
}
function checkedAdd(left, right, label) {
  return checkedU64(left + right, label);
}
function checkedMultiply(left, right, label) {
  return checkedU64(left * right, label);
}

// packages/pgwasm/src/opfs/core/path.ts
function utf8Length(value, label) {
  let bytes = 0;
  for (let index = 0;index < value.length; index += 1) {
    const codeUnit = value.charCodeAt(index);
    if (codeUnit <= 127) {
      bytes += 1;
    } else if (codeUnit <= 2047) {
      bytes += 2;
    } else if (codeUnit >= 55296 && codeUnit <= 56319) {
      const next = value.charCodeAt(index + 1);
      if (index + 1 >= value.length || next < 56320 || next > 57343) {
        throw new FsError("EINVAL", `${label} is not canonically representable as UTF-8`);
      }
      bytes += 4;
      index += 1;
    } else if (codeUnit >= 56320 && codeUnit <= 57343) {
      throw new FsError("EINVAL", `${label} is not canonically representable as UTF-8`);
    } else {
      bytes += 3;
    }
  }
  return bytes;
}
function encodedUtf8Length(value) {
  return utf8Length(value, "string");
}
function validatePathComponent(component) {
  if (component.length === 0 || component === "." || component === "..") {
    throw new FsError("EINVAL", "path contains an empty or reserved component");
  }
  if (component.includes("/") || component.includes("\x00")) {
    throw new FsError("EINVAL", "path component contains a forbidden character");
  }
  const bytes = utf8Length(component, "path component");
  if (bytes > MAX_COMPONENT_BYTES) {
    throw new FsError("EINVAL", `path component exceeds ${MAX_COMPONENT_BYTES} UTF-8 bytes`);
  }
  return bytes;
}
function validateSymlinkTarget(target) {
  const bytes = utf8Length(target, "symlink target");
  if (bytes === 0 || bytes > MAX_PATH_BYTES) {
    throw new FsError("EINVAL", `symlink target must be 1 to ${MAX_PATH_BYTES} UTF-8 bytes`);
  }
  parsePath(target);
  return bytes;
}
function parsePath(path) {
  if (path === "/") {
    return [];
  }
  if (!path.startsWith("/") || path.endsWith("/") || path.includes("//")) {
    throw new FsError("EINVAL", "path must be absolute and canonical", { path });
  }
  if (utf8Length(path, "path") > MAX_PATH_BYTES) {
    throw new FsError("EINVAL", `path exceeds ${MAX_PATH_BYTES} UTF-8 bytes`, { path });
  }
  const components = path.slice(1).split("/");
  if (components.length > MAX_PATH_DEPTH) {
    throw new FsError("EINVAL", `path exceeds ${MAX_PATH_DEPTH} components`, { path });
  }
  for (const component of components) {
    validatePathComponent(component);
  }
  return components;
}

// packages/pgwasm/src/opfs/core/state-machine.ts
function otherMetadataFile(file) {
  return file === "a" ? "b" : "a";
}
function makeOrphanRecord(inode) {
  return {
    inodeId: inode.id,
    mode: inode.mode,
    atimeMs: inode.atimeMs,
    mtimeMs: inode.mtimeMs,
    ctimeMs: inode.ctimeMs,
    size: inode.size,
    extents: [...inode.extents]
  };
}

class IndexedExtentSet {
  #items = [];
  #indexes = new Map;
  get size() {
    return this.#items.length;
  }
  has(extentId) {
    return this.#indexes.has(extentId);
  }
  add(extentId) {
    if (this.#indexes.has(extentId)) {
      return;
    }
    this.#indexes.set(extentId, this.#items.length);
    this.#items.push(extentId);
  }
  delete(extentId) {
    const index = this.#indexes.get(extentId);
    if (index === undefined) {
      return false;
    }
    const last = this.#items.pop();
    this.#indexes.delete(extentId);
    if (last !== undefined && index < this.#items.length) {
      this.#items[index] = last;
      this.#indexes.set(last, index);
    }
    return true;
  }
  values() {
    return this.#items;
  }
  peekLast(count) {
    if (!Number.isSafeInteger(count) || count < 0 || count > this.#items.length) {
      throw new StoreLimitError("invalid available-extent selection count");
    }
    return this.#items.slice(this.#items.length - count).reverse();
  }
  clone() {
    const copy = new IndexedExtentSet;
    for (const extentId of this.#items) {
      copy.add(extentId);
    }
    return copy;
  }
}
var BASE_STATE_FIXED_BYTES = 20;
var DIRECTORY_INODE_FIXED_BYTES = 41;
var FILE_INODE_FIXED_BYTES = 49;
var SYMLINK_INODE_FIXED_BYTES = 39;
var CHILD_FIXED_BYTES = 10;
var SYMLINK_MODE = 41471;
function childBaseBytes(name) {
  return CHILD_FIXED_BYTES + encodedUtf8Length(name);
}
function inodeBaseBytes(inode) {
  if (inode.kind === "file") {
    return FILE_INODE_FIXED_BYTES + inode.extents.length * 8;
  }
  if (inode.kind === "symlink") {
    return SYMLINK_INODE_FIXED_BYTES + encodedUtf8Length(inode.target);
  }
  let bytes = DIRECTORY_INODE_FIXED_BYTES;
  for (const name of inode.children.keys()) {
    bytes += childBaseBytes(name);
  }
  return bytes;
}
function extentRunsPayloadBytes(runs) {
  return 4 + runs.length * 12;
}
function estimateTxnPayloadBytes(record) {
  switch (record.kind) {
    case "createDirectories":
      return 5 + record.entries.reduce((bytes, entry) => bytes + 8 + 2 + encodedUtf8Length(entry.name) + 8 + 4 + 24, 0);
    case "createFile":
      return 1 + 8 + 2 + encodedUtf8Length(record.name) + 8 + 4 + 24 + 8 + extentRunsPayloadBytes(record.extents);
    case "removeFile":
    case "removeDirectory":
      return 1 + 8 + 2 + encodedUtf8Length(record.name) + 16;
    case "changeMode":
      return 1 + 8 + 4 + 8;
    case "changeTimes":
      return 1 + 8 + 24;
    case "resizeFile":
      return 1 + 1 + 8 + 8 + extentRunsPayloadBytes(record.allocated) + 16;
    case "rename":
      return 1 + 8 + 2 + encodedUtf8Length(record.sourceName) + 8 + 2 + encodedUtf8Length(record.destinationName) + 8;
    case "createSymlink":
      return 1 + 8 + 2 + encodedUtf8Length(record.name) + 8 + 4 + 24 + 2 + encodedUtf8Length(record.target);
    case "reserveQuarantine":
      return 1 + extentRunsPayloadBytes(record.extents);
  }
}
function selectedExtentsAlreadyAvailable(state, runs) {
  let count = 0;
  for (const extentId of expandExtentRuns(runs, MAX_EXTENTS_PER_INODE)) {
    if (extentId < state.allocator.totalExtents) {
      count += 1;
    }
  }
  return count;
}
function projectedBaseDelta(state, record) {
  switch (record.kind) {
    case "createDirectories":
      return record.entries.reduce((bytes, entry) => bytes + DIRECTORY_INODE_FIXED_BYTES + childBaseBytes(entry.name), 0);
    case "createFile": {
      const extentCount = expandExtentRuns(record.extents, MAX_EXTENTS_PER_INODE).length;
      const reused = selectedExtentsAlreadyAvailable(state, record.extents);
      return FILE_INODE_FIXED_BYTES + extentCount * 8 + childBaseBytes(record.name) - reused * 8;
    }
    case "removeFile": {
      const parent = directoryById(state, record.parentId);
      const inodeId = parent.children.get(record.name);
      const inode = inodeId === undefined ? undefined : state.inodes.get(inodeId);
      if (inode === undefined || inode.kind === "directory") {
        throw new FsError("ENOENT", "file does not exist");
      }
      const quarantined = inode.kind === "file" ? inode.extents.length * 16 : 0;
      return -inodeBaseBytes(inode) - childBaseBytes(record.name) + quarantined;
    }
    case "changeMode":
    case "changeTimes":
      return 0;
    case "resizeFile": {
      const inode = fileById(state, record.inodeId);
      const required = extentCountForSize(record.size, state.extentSize);
      const allocatedCount = Math.max(0, required - inode.extents.length);
      const releasedCount = Math.max(0, inode.extents.length - required);
      const reused = selectedExtentsAlreadyAvailable(state, record.allocated);
      return (allocatedCount - releasedCount) * 8 - reused * 8 + releasedCount * 16;
    }
    case "removeDirectory": {
      const parent = directoryById(state, record.parentId);
      const inodeId = parent.children.get(record.name);
      const inode = inodeId === undefined ? undefined : state.inodes.get(inodeId);
      if (inode?.kind !== "directory") {
        throw new FsError("ENOENT", "directory does not exist");
      }
      return -inodeBaseBytes(inode) - childBaseBytes(record.name);
    }
    case "rename": {
      const sourceParent = directoryById(state, record.sourceParentId);
      const destinationParent = directoryById(state, record.destinationParentId);
      const destinationId = destinationParent.children.get(record.destinationName);
      const destination = destinationId === undefined ? undefined : state.inodes.get(destinationId);
      let delta = -childBaseBytes(record.sourceName);
      if (destination === undefined) {
        delta += childBaseBytes(record.destinationName);
      } else {
        delta -= inodeBaseBytes(destination);
        if (destination.kind === "file") {
          delta += destination.extents.length * 16;
        }
      }
      const sourceId = sourceParent.children.get(record.sourceName);
      if (sourceId === undefined) {
        throw new FsError("ENOENT", "rename source does not exist");
      }
      return delta;
    }
    case "createSymlink":
      return SYMLINK_INODE_FIXED_BYTES + encodedUtf8Length(record.target) + childBaseBytes(record.name);
    case "reserveQuarantine": {
      const count = expandExtentRuns(record.extents, MAX_EXTENTS_PER_INODE).length;
      const reused = selectedExtentsAlreadyAvailable(state, record.extents);
      return count * 16 - reused * 8;
    }
  }
}
function preflightTxn(state, record, limits = {
  maxFramePayloadBytes: MAX_FRAME_PAYLOAD_BYTES,
  maxBasePayloadBytes: MAX_METADATA_BASE_WRITER_BYTES
}) {
  const payloadBytes = estimateTxnPayloadBytes(record);
  if (payloadBytes > limits.maxFramePayloadBytes) {
    throw new StoreLimitError(`transaction payload would exceed ${limits.maxFramePayloadBytes} bytes`);
  }
  const projected = state.basePayloadBytes + projectedBaseDelta(state, record);
  if (!Number.isSafeInteger(projected) || projected < 0 || projected > limits.maxBasePayloadBytes) {
    throw new StoreLimitError(`metadata base would exceed ${limits.maxBasePayloadBytes} bytes`);
  }
  return projected;
}
var PREPARED_TXN_PROJECTION = Symbol("prepared transaction projection");
function prepareTxnProjection(state, record) {
  return {
    projectedBasePayloadBytes: preflightTxn(state, record),
    state,
    record,
    [PREPARED_TXN_PROJECTION]: true
  };
}
function checkedPlan(state, record) {
  preflightTxn(state, record);
  return { record };
}
function createInitialState(extentSize) {
  validateExtentSize(extentSize);
  const root = {
    id: 1n,
    kind: "directory",
    mode: 16895,
    atimeMs: 0n,
    mtimeMs: 0n,
    ctimeMs: 0n,
    children: new Map
  };
  return {
    generation: 1n,
    nextInodeId: 2n,
    rootInodeId: root.id,
    extentSize,
    activeMetadataFile: "a",
    retainedGenerations: { a: 1n, b: null },
    basePayloadBytes: BASE_STATE_FIXED_BYTES + DIRECTORY_INODE_FIXED_BYTES,
    inodes: new Map([[root.id, root]]),
    parentByInode: new Map,
    allocator: {
      totalExtents: 0n,
      ownedBy: new Map,
      available: new IndexedExtentSet,
      quarantine: new Map
    }
  };
}
function validateMode(mode) {
  if (!Number.isSafeInteger(mode) || mode < 0 || mode > 4294967295) {
    throw new FsError("EINVAL", "mode must be an unsigned 32-bit integer");
  }
  return mode;
}
function validateTimestamp(timestamp) {
  return checkedU64(timestamp, "timestamp");
}
function advanceNextInodeId(inodeId) {
  if (inodeId === MAX_U64) {
    throw new StoreLimitError("next inode ID is exhausted; the store must be recreated");
  }
  return checkedAdd(inodeId, 1n, "next inode ID");
}
function directoryById(state, inodeId) {
  const inode = state.inodes.get(inodeId);
  if (inode === undefined) {
    throw new FsError("ENOENT", "directory does not exist");
  }
  if (inode.kind !== "directory") {
    throw new FsError("ENOTDIR", "path component is not a directory");
  }
  return inode;
}
function inodeById(state, inodeId) {
  const inode = state.inodes.get(inodeId);
  if (inode === undefined) {
    throw new FsError("ENOENT", "inode does not exist");
  }
  return inode;
}
function fileById(state, inodeId) {
  const inode = inodeById(state, inodeId);
  if (inode.kind !== "file") {
    throw new FsError("EISDIR", "inode is not a file");
  }
  return inode;
}
function joinPath(base, rest) {
  if (rest.length === 0)
    return base;
  return base === "/" ? `/${rest.join("/")}` : `${base}/${rest.join("/")}`;
}
function parentAndName(state, path) {
  const components = parsePath(path);
  const name = components.pop();
  if (name === undefined) {
    throw new FsError("EINVAL", "operation is not permitted on root", { path });
  }
  let parent = directoryById(state, state.rootInodeId);
  for (const component of components) {
    const childId = parent.children.get(component);
    if (childId === undefined) {
      throw new FsError("ENOENT", "parent directory does not exist", { path });
    }
    parent = directoryById(state, childId);
  }
  return { parent, name };
}
function extentCountForSize(size, extentSize) {
  checkedU64(size, "file size");
  if (size === 0n) {
    return 0;
  }
  const count = (size + BigInt(extentSize) - 1n) / BigInt(extentSize);
  if (count > BigInt(MAX_EXTENTS_PER_INODE)) {
    throw new StoreLimitError(`file would exceed ${MAX_EXTENTS_PER_INODE} extents`);
  }
  return Number(count);
}
function toExtentRuns(extents) {
  const runs = [];
  for (const extentId of extents) {
    checkedU64(extentId, "extent ID");
    const last = runs.at(-1);
    if (last !== undefined && last.start + BigInt(last.count) === extentId && last.count < 4294967295) {
      last.count += 1;
    } else {
      runs.push({ start: extentId, count: 1 });
    }
  }
  return runs;
}
function expandExtentRuns(runs, maximum) {
  const extents = [];
  for (const run of runs) {
    checkedU64(run.start, "extent run start");
    if (!Number.isSafeInteger(run.count) || run.count <= 0) {
      throw new FsError("EINVAL", "extent run count must be a positive safe integer");
    }
    if (extents.length + run.count > maximum) {
      throw new StoreLimitError(`extent list exceeds ${maximum} entries`);
    }
    for (let offset = 0;offset < run.count; offset += 1) {
      extents.push(checkedAdd(run.start, BigInt(offset), "extent ID"));
    }
  }
  return extents;
}
function chooseExtents(state, count) {
  if (count > MAX_EXTENTS_PER_INODE) {
    throw new StoreLimitError(`allocation exceeds ${MAX_EXTENTS_PER_INODE} extents`);
  }
  const availableCount = Math.min(count, state.allocator.available.size);
  const chosen = state.allocator.available.peekLast(availableCount);
  const freshCount = count - availableCount;
  if (state.allocator.totalExtents + BigInt(freshCount) > BigInt(MAX_TOTAL_EXTENTS)) {
    throw new StoreLimitError(`total extent count would exceed ${MAX_TOTAL_EXTENTS}`);
  }
  for (let offset = 0;offset < freshCount; offset += 1) {
    chosen.push(state.allocator.totalExtents + BigInt(offset));
  }
  return chosen;
}
function getInodeAtPath(state, path) {
  const components = parsePath(path);
  let inode = state.inodes.get(state.rootInodeId);
  if (inode === undefined) {
    throw new StoreLimitError("root inode is missing");
  }
  for (const component of components) {
    if (inode.kind !== "directory") {
      throw new FsError("ENOTDIR", "path component is not a directory", { path });
    }
    const childId = inode.children.get(component);
    if (childId === undefined) {
      throw new FsError("ENOENT", "path does not exist", { path });
    }
    const child = state.inodes.get(childId);
    if (child === undefined) {
      throw new StoreLimitError("directory entry references a missing inode");
    }
    inode = child;
  }
  return inode;
}
function resolveLinks(state, path, follow) {
  const root = state.inodes.get(state.rootInodeId);
  if (root === undefined) {
    throw new StoreLimitError("root inode is missing");
  }
  let pending = parsePath(path);
  let index = 0;
  let current = root;
  const resolved = [];
  let hops = 0;
  while (index < pending.length) {
    const name = pending[index];
    if (current.kind !== "directory")
      break;
    const childId = current.children.get(name);
    if (childId === undefined)
      break;
    const child = state.inodes.get(childId);
    if (child === undefined) {
      throw new StoreLimitError("directory entry references a missing inode");
    }
    if (child.kind === "symlink" && (follow || index < pending.length - 1)) {
      hops += 1;
      if (hops > MAX_SYMLINK_HOPS) {
        throw new FsError("ELOOP", `path traverses more than ${MAX_SYMLINK_HOPS} symbolic links`, { path });
      }
      pending = parsePath(joinPath(child.target, pending.slice(index + 1)));
      index = 0;
      current = root;
      resolved.length = 0;
      continue;
    }
    resolved.push(name);
    current = child;
    index += 1;
  }
  return joinPath(`/${resolved.join("/")}`, pending.slice(index));
}
function planMkdir(state, path, options) {
  const components = parsePath(path);
  if (components.length === 0) {
    throw new FsError("EEXIST", "root directory already exists", { operation: "mkdir", path });
  }
  const mode = validateMode(options.mode ?? 16895);
  const nowMs = validateTimestamp(options.nowMs);
  const entries = [];
  let parent = directoryById(state, state.rootInodeId);
  let nextInodeId = state.nextInodeId;
  for (let index = 0;index < components.length; index += 1) {
    const name = components[index];
    const existingId = parent.children.get(name);
    if (existingId !== undefined) {
      const existing = state.inodes.get(existingId);
      if (existing?.kind !== "directory") {
        throw new FsError("ENOTDIR", "path component is not a directory", { operation: "mkdir", path });
      }
      if (index === components.length - 1) {
        throw new FsError("EEXIST", "path already exists", { operation: "mkdir", path });
      }
      parent = existing;
      continue;
    }
    if (!options.recursive && index !== components.length - 1) {
      throw new FsError("ENOENT", "parent directory does not exist", { operation: "mkdir", path });
    }
    if (state.inodes.size + entries.length >= MAX_INODES) {
      throw new StoreLimitError(`inode count would exceed ${MAX_INODES}`);
    }
    checkedU64(nextInodeId, "next inode ID");
    const followingInodeId = advanceNextInodeId(nextInodeId);
    const entry = {
      parentId: parent.id,
      name,
      inodeId: nextInodeId,
      mode,
      atimeMs: nowMs,
      mtimeMs: nowMs,
      ctimeMs: nowMs
    };
    entries.push(entry);
    parent = { ...entry, kind: "directory", id: entry.inodeId, children: new Map };
    nextInodeId = followingInodeId;
  }
  if (entries.length === 0) {
    throw new FsError("EEXIST", "path already exists", { operation: "mkdir", path });
  }
  return checkedPlan(state, { kind: "createDirectories", entries });
}
function planCreateFile(state, path, options) {
  const { parent, name } = parentAndName(state, path);
  if (parent.children.has(name)) {
    throw new FsError("EEXIST", "path already exists", { operation: "writeFile", path });
  }
  if (state.inodes.size >= MAX_INODES) {
    throw new StoreLimitError(`inode count would exceed ${MAX_INODES}`);
  }
  const inodeId = checkedU64(state.nextInodeId, "next inode ID");
  advanceNextInodeId(inodeId);
  const mode = validateMode(options.mode ?? 33206);
  const nowMs = validateTimestamp(options.nowMs);
  const size = checkedU64(options.size ?? 0n, "file size");
  const extents = toExtentRuns(chooseExtents(state, extentCountForSize(size, state.extentSize)));
  return checkedPlan(state, {
    kind: "createFile",
    parentId: parent.id,
    name,
    inodeId,
    mode,
    atimeMs: nowMs,
    mtimeMs: nowMs,
    ctimeMs: nowMs,
    size,
    extents
  });
}
function planSymlink(state, path, target, options) {
  const { parent, name } = parentAndName(state, path);
  if (parent.children.has(name)) {
    throw new FsError("EEXIST", "path already exists", { operation: "symlink", path });
  }
  if (state.inodes.size >= MAX_INODES) {
    throw new StoreLimitError(`inode count would exceed ${MAX_INODES}`);
  }
  validateSymlinkTarget(target);
  const inodeId = checkedU64(state.nextInodeId, "next inode ID");
  advanceNextInodeId(inodeId);
  const nowMs = validateTimestamp(options.nowMs);
  return checkedPlan(state, {
    kind: "createSymlink",
    parentId: parent.id,
    name,
    inodeId,
    mode: validateMode(options.mode ?? SYMLINK_MODE),
    atimeMs: nowMs,
    mtimeMs: nowMs,
    ctimeMs: nowMs,
    target
  });
}
function planUnlink(state, path, nowMs) {
  const { parent, name } = parentAndName(state, path);
  const inodeId = parent.children.get(name);
  const inode = inodeId === undefined ? undefined : state.inodes.get(inodeId);
  if (inode === undefined) {
    throw new FsError("ENOENT", "path does not exist", { operation: "unlink", path });
  }
  if (inode.kind === "directory") {
    throw new FsError("EISDIR", "path is a directory", { operation: "unlink", path });
  }
  const timestamp = validateTimestamp(nowMs);
  return checkedPlan(state, {
    kind: "removeFile",
    parentId: parent.id,
    name,
    parentMtimeMs: timestamp,
    parentCtimeMs: timestamp
  });
}
function planChmod(state, path, mode, nowMs) {
  const inode = getInodeAtPath(state, path);
  return checkedPlan(state, {
    kind: "changeMode",
    inodeId: inode.id,
    mode: validateMode(mode),
    ctimeMs: validateTimestamp(nowMs)
  });
}
function planUtimes(state, path, atimeMs, mtimeMs, ctimeMs) {
  const inode = getInodeAtPath(state, path);
  return checkedPlan(state, {
    kind: "changeTimes",
    inodeId: inode.id,
    atimeMs: validateTimestamp(atimeMs),
    mtimeMs: validateTimestamp(mtimeMs),
    ctimeMs: validateTimestamp(ctimeMs)
  });
}
function planResizeFile(state, path, size, nowMs, operation) {
  const inode = getInodeAtPath(state, path);
  if (inode.kind !== "file") {
    throw new FsError("EISDIR", "path is a directory", { operation, path });
  }
  return planResizeFileForInode(state, inode, size, nowMs, operation);
}
function planResizeFileForInode(state, inode, size, nowMs, operation) {
  if (state.inodes.get(inode.id) !== inode) {
    throw new StoreLimitError("resize planner requires the current file inode");
  }
  const checkedSize = checkedU64(size, "file size");
  const required = extentCountForSize(checkedSize, state.extentSize);
  const additional = Math.max(0, required - inode.extents.length);
  const timestamp = validateTimestamp(nowMs);
  return checkedPlan(state, {
    kind: "resizeFile",
    operation,
    inodeId: inode.id,
    size: checkedSize,
    allocated: toExtentRuns(chooseExtents(state, additional)),
    mtimeMs: timestamp,
    ctimeMs: timestamp
  });
}
function planRmdir(state, path, nowMs) {
  const { parent, name } = parentAndName(state, path);
  const inodeId = parent.children.get(name);
  const inode = inodeId === undefined ? undefined : state.inodes.get(inodeId);
  if (inode === undefined) {
    throw new FsError("ENOENT", "directory does not exist", { operation: "rmdir", path });
  }
  if (inode.kind !== "directory") {
    throw new FsError("ENOTDIR", "path is not a directory", { operation: "rmdir", path });
  }
  if (inode.children.size !== 0) {
    throw new FsError("ENOTEMPTY", "directory is not empty", { operation: "rmdir", path });
  }
  const timestamp = validateTimestamp(nowMs);
  return checkedPlan(state, {
    kind: "removeDirectory",
    parentId: parent.id,
    name,
    parentMtimeMs: timestamp,
    parentCtimeMs: timestamp
  });
}
function directoryContains(state, directory, candidateId) {
  if (directory.id === candidateId) {
    return true;
  }
  for (const childId of directory.children.values()) {
    const child = inodeById(state, childId);
    if (child.kind === "directory" && directoryContains(state, child, candidateId)) {
      return true;
    }
  }
  return false;
}
function childPathMetrics(parent, name) {
  return {
    depth: parent.depth + 1,
    bytes: parent.bytes + (parent.depth === 0 ? 0 : 1) + encodedUtf8Length(name)
  };
}
function findPathMetrics(state, targetId) {
  let currentId = targetId;
  let depth = 0;
  let componentBytes = 0;
  const visited = new Set;
  while (currentId !== state.rootInodeId) {
    if (visited.has(currentId)) {
      throw new StoreLimitError("inode parent index contains a cycle");
    }
    visited.add(currentId);
    const entry = state.parentByInode.get(currentId);
    if (entry === undefined) {
      throw new StoreLimitError("inode parent index does not reach root");
    }
    depth += 1;
    componentBytes += encodedUtf8Length(entry.name);
    currentId = entry.parentId;
  }
  return { depth, bytes: 1 + componentBytes + Math.max(0, depth - 1) };
}
function validateRenamedSubtreeBounds(state, source, destinationParent, destinationName) {
  const visit = (inode, metrics) => {
    if (metrics.depth > MAX_PATH_DEPTH) {
      throw new FsError("EINVAL", `rename would exceed ${MAX_PATH_DEPTH} path components`);
    }
    if (metrics.bytes > MAX_PATH_BYTES) {
      throw new FsError("EINVAL", `rename would exceed ${MAX_PATH_BYTES} UTF-8 path bytes`);
    }
    if (inode.kind === "directory") {
      for (const [name, childId] of inode.children) {
        visit(inodeById(state, childId), childPathMetrics(metrics, name));
      }
    }
  };
  const destinationMetrics = findPathMetrics(state, destinationParent.id);
  visit(source, childPathMetrics(destinationMetrics, destinationName));
}
function validateRenameTypes(source, destination) {
  if (destination === undefined) {
    return;
  }
  if (source.kind !== "directory" && destination.kind === "directory") {
    throw new FsError("EISDIR", "cannot replace a directory with a file");
  }
  if (source.kind === "directory" && destination.kind !== "directory") {
    throw new FsError("ENOTDIR", "cannot replace a file with a directory");
  }
  if (destination.kind === "directory" && destination.children.size !== 0) {
    throw new FsError("ENOTEMPTY", "destination directory is not empty");
  }
}
function planRename(state, oldPath, newPath, nowMs) {
  if (oldPath === newPath) {
    throw new FsError("EINVAL", "source and destination are identical", { operation: "rename", path: oldPath });
  }
  const sourceLocation = parentAndName(state, oldPath);
  const destinationLocation = parentAndName(state, newPath);
  const sourceId = sourceLocation.parent.children.get(sourceLocation.name);
  if (sourceId === undefined) {
    throw new FsError("ENOENT", "rename source does not exist", { operation: "rename", path: oldPath });
  }
  const source = inodeById(state, sourceId);
  const destinationId = destinationLocation.parent.children.get(destinationLocation.name);
  const destination = destinationId === undefined ? undefined : inodeById(state, destinationId);
  validateRenameTypes(source, destination);
  if (source.kind === "directory" && directoryContains(state, source, destinationLocation.parent.id)) {
    throw new FsError("EINVAL", "cannot move a directory into itself", { operation: "rename", path: newPath });
  }
  validateRenamedSubtreeBounds(state, source, destinationLocation.parent, destinationLocation.name);
  return checkedPlan(state, {
    kind: "rename",
    sourceParentId: sourceLocation.parent.id,
    sourceName: sourceLocation.name,
    destinationParentId: destinationLocation.parent.id,
    destinationName: destinationLocation.name,
    timestampMs: validateTimestamp(nowMs)
  });
}
function planReserveQuarantine(state, count) {
  if (!Number.isSafeInteger(count) || count <= 0 || count > MAX_EXTENTS_PER_INODE) {
    throw new StoreLimitError(`orphan reservation must contain 1 to ${MAX_EXTENTS_PER_INODE} extents`);
  }
  return checkedPlan(state, {
    kind: "reserveQuarantine",
    extents: toExtentRuns(chooseExtents(state, count))
  });
}
function validateCreateDirectories(state, entries) {
  if (entries.length === 0) {
    throw new FsError("EINVAL", "createDirectories record is empty");
  }
  const staged = new Map;
  const stagedDirectory = (inodeId) => {
    const alreadyStaged = staged.get(inodeId);
    if (alreadyStaged !== undefined) {
      return alreadyStaged;
    }
    const existing = directoryById(state, inodeId);
    const copy = { ...existing, children: new Map(existing.children) };
    staged.set(inodeId, copy);
    return copy;
  };
  let expectedInodeId = state.nextInodeId;
  for (const entry of entries) {
    validatePathComponent(entry.name);
    validateMode(entry.mode);
    validateTimestamp(entry.atimeMs);
    validateTimestamp(entry.mtimeMs);
    validateTimestamp(entry.ctimeMs);
    if (entry.inodeId !== expectedInodeId || entry.inodeId > MAX_U64) {
      throw new FsError("EINVAL", "createDirectories record has a non-canonical inode sequence");
    }
    const parent = stagedDirectory(entry.parentId);
    if (parent.children.has(entry.name)) {
      throw new FsError("EEXIST", "directory entry already exists");
    }
    const created = {
      id: entry.inodeId,
      kind: "directory",
      mode: entry.mode,
      atimeMs: entry.atimeMs,
      mtimeMs: entry.mtimeMs,
      ctimeMs: entry.ctimeMs,
      children: new Map
    };
    parent.children.set(entry.name, entry.inodeId);
    staged.set(entry.inodeId, created);
    expectedInodeId = advanceNextInodeId(expectedInodeId);
  }
  if (state.inodes.size + entries.length > MAX_INODES) {
    throw new StoreLimitError(`inode count would exceed ${MAX_INODES}`);
  }
}
function validateExtentAssignment(state, runs, expectedCount) {
  const extents = expandExtentRuns(runs, MAX_EXTENTS_PER_INODE);
  if (extents.length !== expectedCount) {
    throw new FsError("EINVAL", "extent choices do not cover the file size exactly");
  }
  const unique = new Set(extents);
  if (unique.size !== extents.length) {
    throw new FsError("EINVAL", "extent choices contain a duplicate");
  }
  let nextFresh = state.allocator.totalExtents;
  for (const extentId of extents) {
    if (extentId < state.allocator.totalExtents) {
      if (!state.allocator.available.has(extentId)) {
        throw new FsError("EINVAL", "extent choice is not safely available");
      }
      continue;
    }
    if (extentId !== nextFresh) {
      throw new FsError("EINVAL", "fresh extent choices must grow the arena contiguously");
    }
    nextFresh += 1n;
  }
  if (nextFresh > BigInt(MAX_TOTAL_EXTENTS)) {
    throw new StoreLimitError(`total extent count would exceed ${MAX_TOTAL_EXTENTS}`);
  }
  return extents;
}
function applyCreateFile(state, record) {
  validatePathComponent(record.name);
  const parent = directoryById(state, record.parentId);
  if (parent.children.has(record.name)) {
    throw new FsError("EEXIST", "directory entry already exists");
  }
  if (record.inodeId !== state.nextInodeId || state.inodes.has(record.inodeId)) {
    throw new FsError("EINVAL", "createFile record has a non-canonical inode ID");
  }
  const nextInodeId = advanceNextInodeId(record.inodeId);
  validateMode(record.mode);
  validateTimestamp(record.atimeMs);
  validateTimestamp(record.mtimeMs);
  validateTimestamp(record.ctimeMs);
  const size = checkedU64(record.size, "file size");
  const extents = validateExtentAssignment(state, record.extents, extentCountForSize(size, state.extentSize));
  if (state.inodes.size >= MAX_INODES) {
    throw new StoreLimitError(`inode count would exceed ${MAX_INODES}`);
  }
  const inode = {
    id: record.inodeId,
    kind: "file",
    mode: record.mode,
    atimeMs: record.atimeMs,
    mtimeMs: record.mtimeMs,
    ctimeMs: record.ctimeMs,
    size,
    extents
  };
  for (const extentId of extents) {
    if (extentId < state.allocator.totalExtents) {
      state.allocator.available.delete(extentId);
    } else {
      state.allocator.totalExtents += 1n;
    }
    state.allocator.ownedBy.set(extentId, inode.id);
  }
  parent.children.set(record.name, inode.id);
  state.inodes.set(inode.id, inode);
  state.parentByInode.set(inode.id, { parentId: parent.id, name: record.name });
  state.nextInodeId = nextInodeId;
}
function applyRemoveFile(state, record) {
  validatePathComponent(record.name);
  validateTimestamp(record.parentMtimeMs);
  validateTimestamp(record.parentCtimeMs);
  const parent = directoryById(state, record.parentId);
  const inodeId = parent.children.get(record.name);
  const inode = inodeId === undefined ? undefined : state.inodes.get(inodeId);
  if (inode === undefined) {
    throw new FsError("ENOENT", "file does not exist");
  }
  if (inode.kind === "directory") {
    throw new FsError("EISDIR", "path is a directory");
  }
  const extents = inode.kind === "file" ? inode.extents : [];
  for (const extentId of extents) {
    if (state.allocator.ownedBy.get(extentId) !== inode.id || state.allocator.quarantine.has(extentId)) {
      throw new StoreLimitError("file extent ownership is inconsistent");
    }
  }
  parent.children.delete(record.name);
  parent.mtimeMs = record.parentMtimeMs;
  parent.ctimeMs = record.parentCtimeMs;
  state.inodes.delete(inode.id);
  state.parentByInode.delete(inode.id);
  for (const extentId of extents) {
    state.allocator.ownedBy.delete(extentId);
    state.allocator.quarantine.set(extentId, null);
  }
}
function applyCreateSymlink(state, record) {
  validatePathComponent(record.name);
  const parent = directoryById(state, record.parentId);
  if (parent.children.has(record.name)) {
    throw new FsError("EEXIST", "directory entry already exists");
  }
  if (record.inodeId !== state.nextInodeId || state.inodes.has(record.inodeId)) {
    throw new FsError("EINVAL", "createSymlink record has a non-canonical inode ID");
  }
  const nextInodeId = advanceNextInodeId(record.inodeId);
  validateMode(record.mode);
  validateTimestamp(record.atimeMs);
  validateTimestamp(record.mtimeMs);
  validateTimestamp(record.ctimeMs);
  validateSymlinkTarget(record.target);
  if (state.inodes.size >= MAX_INODES) {
    throw new StoreLimitError(`inode count would exceed ${MAX_INODES}`);
  }
  const inode = {
    id: record.inodeId,
    kind: "symlink",
    mode: record.mode,
    atimeMs: record.atimeMs,
    mtimeMs: record.mtimeMs,
    ctimeMs: record.ctimeMs,
    target: record.target
  };
  parent.children.set(record.name, inode.id);
  state.inodes.set(inode.id, inode);
  state.parentByInode.set(inode.id, { parentId: parent.id, name: record.name });
  state.nextInodeId = nextInodeId;
}
function applyChangeMode(state, record) {
  const inode = inodeById(state, record.inodeId);
  const mode = validateMode(record.mode);
  const ctimeMs = validateTimestamp(record.ctimeMs);
  inode.mode = mode;
  inode.ctimeMs = ctimeMs;
}
function applyChangeTimes(state, record) {
  const inode = inodeById(state, record.inodeId);
  const atimeMs = validateTimestamp(record.atimeMs);
  const mtimeMs = validateTimestamp(record.mtimeMs);
  const ctimeMs = validateTimestamp(record.ctimeMs);
  inode.atimeMs = atimeMs;
  inode.mtimeMs = mtimeMs;
  inode.ctimeMs = ctimeMs;
}
function applyResizeFile(state, record) {
  const inode = fileById(state, record.inodeId);
  const size = checkedU64(record.size, "file size");
  const required = extentCountForSize(size, state.extentSize);
  const additionalCount = Math.max(0, required - inode.extents.length);
  const allocated = validateExtentAssignment(state, record.allocated, additionalCount);
  const retained = required >= inode.extents.length ? inode.extents : inode.extents.slice(0, required);
  const released = inode.extents.slice(required);
  for (const extentId of released) {
    if (state.allocator.ownedBy.get(extentId) !== inode.id || state.allocator.quarantine.has(extentId)) {
      throw new StoreLimitError("file extent ownership is inconsistent");
    }
  }
  const mtimeMs = validateTimestamp(record.mtimeMs);
  const ctimeMs = validateTimestamp(record.ctimeMs);
  for (const extentId of allocated) {
    if (extentId < state.allocator.totalExtents) {
      state.allocator.available.delete(extentId);
    } else {
      state.allocator.totalExtents += 1n;
    }
    state.allocator.ownedBy.set(extentId, inode.id);
    retained.push(extentId);
  }
  for (const extentId of released) {
    state.allocator.ownedBy.delete(extentId);
    state.allocator.quarantine.set(extentId, null);
  }
  inode.size = size;
  inode.extents = retained;
  inode.mtimeMs = mtimeMs;
  inode.ctimeMs = ctimeMs;
}
function applyRemoveDirectory(state, record) {
  validatePathComponent(record.name);
  const parent = directoryById(state, record.parentId);
  const inodeId = parent.children.get(record.name);
  const inode = inodeId === undefined ? undefined : state.inodes.get(inodeId);
  if (inode === undefined) {
    throw new FsError("ENOENT", "directory does not exist");
  }
  if (inode.kind !== "directory") {
    throw new FsError("ENOTDIR", "path is not a directory");
  }
  if (inode.children.size !== 0) {
    throw new FsError("ENOTEMPTY", "directory is not empty");
  }
  const mtimeMs = validateTimestamp(record.parentMtimeMs);
  const ctimeMs = validateTimestamp(record.parentCtimeMs);
  parent.children.delete(record.name);
  parent.mtimeMs = mtimeMs;
  parent.ctimeMs = ctimeMs;
  state.inodes.delete(inode.id);
  state.parentByInode.delete(inode.id);
}
function applyRename(state, record) {
  validatePathComponent(record.sourceName);
  validatePathComponent(record.destinationName);
  if (record.sourceParentId === record.destinationParentId && record.sourceName === record.destinationName) {
    throw new FsError("EINVAL", "rename source and destination are identical");
  }
  const timestampMs = validateTimestamp(record.timestampMs);
  const sourceParent = directoryById(state, record.sourceParentId);
  const destinationParent = directoryById(state, record.destinationParentId);
  const sourceId = sourceParent.children.get(record.sourceName);
  if (sourceId === undefined) {
    throw new FsError("ENOENT", "rename source does not exist");
  }
  const source = inodeById(state, sourceId);
  const destinationId = destinationParent.children.get(record.destinationName);
  const destination = destinationId === undefined ? undefined : inodeById(state, destinationId);
  validateRenameTypes(source, destination);
  if (source.kind === "directory" && directoryContains(state, source, destinationParent.id)) {
    throw new FsError("EINVAL", "cannot move a directory into itself");
  }
  validateRenamedSubtreeBounds(state, source, destinationParent, record.destinationName);
  if (destination?.kind === "file") {
    for (const extentId of destination.extents) {
      if (state.allocator.ownedBy.get(extentId) !== destination.id || state.allocator.quarantine.has(extentId)) {
        throw new StoreLimitError("replacement extent ownership is inconsistent");
      }
    }
  }
  sourceParent.children.delete(record.sourceName);
  if (destination !== undefined) {
    destinationParent.children.delete(record.destinationName);
    state.inodes.delete(destination.id);
    state.parentByInode.delete(destination.id);
    if (destination.kind === "file") {
      for (const extentId of destination.extents) {
        state.allocator.ownedBy.delete(extentId);
        state.allocator.quarantine.set(extentId, null);
      }
    }
  }
  destinationParent.children.set(record.destinationName, source.id);
  state.parentByInode.set(source.id, {
    parentId: destinationParent.id,
    name: record.destinationName
  });
  source.ctimeMs = timestampMs;
  sourceParent.mtimeMs = timestampMs;
  sourceParent.ctimeMs = timestampMs;
  destinationParent.mtimeMs = timestampMs;
  destinationParent.ctimeMs = timestampMs;
}
function applyReserveQuarantine(state, record) {
  const declaredCount = record.extents.reduce((sum, run) => sum + run.count, 0);
  if (declaredCount <= 0 || declaredCount > MAX_EXTENTS_PER_INODE) {
    throw new StoreLimitError("orphan reservation extent count is outside limits");
  }
  const extents = validateExtentAssignment(state, record.extents, declaredCount);
  for (const extentId of extents) {
    if (extentId < state.allocator.totalExtents) {
      state.allocator.available.delete(extentId);
    } else {
      state.allocator.totalExtents += 1n;
    }
    state.allocator.quarantine.set(extentId, null);
  }
}
function applyTxn(state, record, prepared) {
  if (prepared !== undefined && (prepared[PREPARED_TXN_PROJECTION] !== true || prepared.state !== state || prepared.record !== record)) {
    throw new StoreLimitError("prepared transaction projection does not match the live transition");
  }
  const projectedBasePayloadBytes = prepared?.projectedBasePayloadBytes ?? preflightTxn(state, record);
  switch (record.kind) {
    case "createDirectories":
      validateCreateDirectories(state, record.entries);
      for (const entry of record.entries) {
        const parent = directoryById(state, entry.parentId);
        const created = {
          id: entry.inodeId,
          kind: "directory",
          mode: entry.mode,
          atimeMs: entry.atimeMs,
          mtimeMs: entry.mtimeMs,
          ctimeMs: entry.ctimeMs,
          children: new Map
        };
        parent.children.set(entry.name, created.id);
        state.inodes.set(created.id, created);
        state.parentByInode.set(created.id, { parentId: parent.id, name: entry.name });
        state.nextInodeId = advanceNextInodeId(created.id);
      }
      break;
    case "createFile":
      applyCreateFile(state, record);
      break;
    case "removeFile":
      applyRemoveFile(state, record);
      break;
    case "changeMode":
      applyChangeMode(state, record);
      break;
    case "changeTimes":
      applyChangeTimes(state, record);
      break;
    case "resizeFile":
      applyResizeFile(state, record);
      break;
    case "removeDirectory":
      applyRemoveDirectory(state, record);
      break;
    case "rename":
      applyRename(state, record);
      break;
    case "createSymlink":
      applyCreateSymlink(state, record);
      break;
    case "reserveQuarantine":
      applyReserveQuarantine(state, record);
      break;
  }
  state.basePayloadBytes = projectedBasePayloadBytes;
}
function projectRepackFromCopy(state, projected, pinnedQuarantine) {
  if (state.generation === MAX_U64) {
    throw new StoreLimitError("generation is exhausted; the store must be recreated");
  }
  let projectedBasePayloadBytes = state.basePayloadBytes;
  const nextGeneration = state.generation + 1n;
  const target = otherMetadataFile(state.activeMetadataFile);
  const targetPreviousGeneration = state.retainedGenerations[target];
  for (const [extentId, firstExcludedGeneration] of projected.allocator.quarantine) {
    if (pinnedQuarantine.has(extentId)) {
      projected.allocator.quarantine.set(extentId, null);
    } else if (firstExcludedGeneration === null) {
      projected.allocator.quarantine.set(extentId, nextGeneration);
    } else if (targetPreviousGeneration === null || targetPreviousGeneration < firstExcludedGeneration) {
      projected.allocator.quarantine.delete(extentId);
      projected.allocator.available.add(extentId);
      projectedBasePayloadBytes -= 8;
    }
  }
  while (projected.allocator.totalExtents > 0n) {
    const tail = projected.allocator.totalExtents - 1n;
    if (!projected.allocator.available.delete(tail))
      break;
    projected.allocator.totalExtents = tail;
    projectedBasePayloadBytes -= 8;
  }
  projected.generation = nextGeneration;
  projected.activeMetadataFile = target;
  projected.retainedGenerations[target] = nextGeneration;
  projected.basePayloadBytes = projectedBasePayloadBytes;
  validateState(projected);
  return projected;
}
function projectRepackForActivation(state, pinnedQuarantine = new Set) {
  const projected = {
    ...state,
    retainedGenerations: { ...state.retainedGenerations },
    inodes: state.inodes,
    parentByInode: state.parentByInode,
    allocator: {
      totalExtents: state.allocator.totalExtents,
      ownedBy: state.allocator.ownedBy,
      available: state.allocator.available.clone(),
      quarantine: new Map(state.allocator.quarantine)
    }
  };
  return projectRepackFromCopy(state, projected, pinnedQuarantine);
}
function validateState(state) {
  validateExtentSize(state.extentSize);
  checkedU64(state.generation, "generation");
  if (state.generation === 0n) {
    throw new StoreLimitError("generation must be positive");
  }
  checkedU64(state.nextInodeId, "next inode ID");
  const root = state.inodes.get(state.rootInodeId);
  if (root?.kind !== "directory") {
    throw new StoreLimitError("root inode is missing or is not a directory");
  }
  if (state.parentByInode.has(state.rootInodeId)) {
    throw new StoreLimitError("root inode must not have a parent entry");
  }
  if (state.inodes.size > MAX_INODES) {
    throw new StoreLimitError(`inode count exceeds ${MAX_INODES}`);
  }
  checkedU64(state.allocator.totalExtents, "total extent count");
  if (state.allocator.totalExtents > BigInt(MAX_TOTAL_EXTENTS)) {
    throw new StoreLimitError(`total extent count exceeds ${MAX_TOTAL_EXTENTS}`);
  }
  const classified = new Uint8Array(Number(state.allocator.totalExtents));
  let classifiedCount = 0;
  const classify = (extentId, label) => {
    if (extentId < 0n || extentId >= state.allocator.totalExtents) {
      throw new StoreLimitError(`${label} extent is out of range or multiply classified`);
    }
    const index = Number(extentId);
    if (classified[index] !== 0) {
      throw new StoreLimitError(`${label} extent is out of range or multiply classified`);
    }
    classified[index] = 1;
    classifiedCount += 1;
  };
  const reached = new Set;
  let calculatedBasePayloadBytes = BASE_STATE_FIXED_BYTES;
  const visit = (inodeKey, inode, metrics) => {
    checkedU64(inodeKey, "inode map key");
    checkedU64(inode.id, "inode ID");
    if (inodeKey !== inode.id) {
      throw new StoreLimitError("inode map key does not match the inode ID");
    }
    if (inode.id >= state.nextInodeId) {
      throw new StoreLimitError("inode ID is not below the unused next inode ID");
    }
    if (reached.has(inode.id)) {
      throw new StoreLimitError("inode has more than one directory owner");
    }
    reached.add(inode.id);
    validateMode(inode.mode);
    validateTimestamp(inode.atimeMs);
    validateTimestamp(inode.mtimeMs);
    validateTimestamp(inode.ctimeMs);
    if (inode.kind === "directory") {
      calculatedBasePayloadBytes += DIRECTORY_INODE_FIXED_BYTES;
      for (const [name, childId] of inode.children) {
        const nameBytes = validatePathComponent(name);
        calculatedBasePayloadBytes += CHILD_FIXED_BYTES + nameBytes;
        const parentEntry = state.parentByInode.get(childId);
        if (parentEntry?.parentId !== inode.id || parentEntry.name !== name) {
          throw new StoreLimitError("inode parent index does not match its directory entry");
        }
        const childMetrics = {
          depth: metrics.depth + 1,
          bytes: metrics.bytes + (metrics.depth === 0 ? 0 : 1) + nameBytes
        };
        if (childMetrics.depth > MAX_PATH_DEPTH) {
          throw new StoreLimitError(`inode path exceeds ${MAX_PATH_DEPTH} components`);
        }
        if (childMetrics.bytes > MAX_PATH_BYTES) {
          throw new StoreLimitError(`inode path exceeds ${MAX_PATH_BYTES} UTF-8 bytes`);
        }
        const child = state.inodes.get(childId);
        if (child === undefined) {
          throw new StoreLimitError("directory entry references a missing inode");
        }
        visit(childId, child, childMetrics);
      }
    } else if (inode.kind === "symlink") {
      let targetBytes;
      try {
        targetBytes = validateSymlinkTarget(inode.target);
      } catch (cause) {
        throw new StoreLimitError(`symlink target is invalid: ${String(cause)}`, { cause });
      }
      calculatedBasePayloadBytes += SYMLINK_INODE_FIXED_BYTES + targetBytes;
    } else {
      calculatedBasePayloadBytes += FILE_INODE_FIXED_BYTES + inode.extents.length * 8;
      if (inode.extents.length !== extentCountForSize(inode.size, state.extentSize)) {
        throw new StoreLimitError("file extent count does not cover its size exactly");
      }
      for (const extentId of inode.extents) {
        classify(extentId, "owned");
        if (state.allocator.ownedBy.get(extentId) !== inode.id) {
          throw new StoreLimitError("owned extent does not map back to its inode");
        }
      }
    }
  };
  visit(state.rootInodeId, root, { depth: 0, bytes: 1 });
  if (reached.size !== state.inodes.size) {
    throw new StoreLimitError("inode graph contains unreachable inodes");
  }
  if (state.parentByInode.size !== state.inodes.size - 1) {
    throw new StoreLimitError("inode parent index does not cover every non-root inode");
  }
  if (classifiedCount !== state.allocator.ownedBy.size) {
    throw new StoreLimitError("allocator contains an owner not referenced by a file");
  }
  calculatedBasePayloadBytes += state.allocator.available.size * 8 + state.allocator.quarantine.size * 16;
  if (state.basePayloadBytes !== calculatedBasePayloadBytes) {
    throw new StoreLimitError("tracked metadata-base size does not match canonical state size");
  }
  if (state.basePayloadBytes > MAX_METADATA_BASE_WRITER_BYTES) {
    throw new StoreLimitError(`metadata base exceeds ${MAX_METADATA_BASE_WRITER_BYTES} bytes`);
  }
  if (state.retainedGenerations[state.activeMetadataFile] !== state.generation) {
    throw new StoreLimitError("active metadata identity does not match the state generation");
  }
  const inactiveMetadataFile = otherMetadataFile(state.activeMetadataFile);
  const inactiveGeneration = state.retainedGenerations[inactiveMetadataFile];
  if (inactiveGeneration !== null) {
    checkedU64(inactiveGeneration, "inactive retained generation");
    if (inactiveGeneration === 0n || inactiveGeneration + 1n !== state.generation) {
      throw new StoreLimitError("inactive retained generation is not the immediate predecessor");
    }
  }
  for (const extentId of state.allocator.available.values()) {
    classify(extentId, "available");
  }
  for (const [extentId, firstExcludedGeneration] of state.allocator.quarantine) {
    classify(extentId, "quarantined");
    if (firstExcludedGeneration !== null && firstExcludedGeneration !== state.generation) {
      throw new StoreLimitError("quarantine generation is inconsistent with retained metadata");
    }
  }
  if (BigInt(classifiedCount) !== state.allocator.totalExtents) {
    throw new StoreLimitError("allocator partition does not cover every extent");
  }
}

// packages/pgwasm/src/opfs/core/codec.ts
var textEncoder = new TextEncoder;
var textDecoder = new TextDecoder("utf-8", { fatal: true });
var ARENA_MAGIC = textEncoder.encode("PGXRPA01");
var METADATA_MAGIC = textEncoder.encode("PGXRPM01");
var FRAME_MAGIC = textEncoder.encode("PGXRPF01");
var ACTIVATION_MAGIC = textEncoder.encode("PGXRPK01");
var ARENA_HEADER_CHECKSUM_OFFSET = 24;
var METADATA_HEADER_BYTES = 80;
var TXN_FRAME_HEADER_BYTES = 48;
var ACTIVATION_SLOT_BYTES = 128;
var METADATA_HEADER_CHECKSUM_OFFSET = 64;
var FRAME_CHECKSUM_OFFSET = 40;
var ACTIVATION_CHECKSUM_OFFSET = 52;

class BinaryWriter {
  bytes;
  #view;
  #offset = 0;
  constructor(length, initialOffset = 0) {
    if (!Number.isSafeInteger(length) || length < 0 || !Number.isSafeInteger(initialOffset) || initialOffset < 0 || initialOffset > length) {
      throw new StoreLimitError("binary output length is invalid");
    }
    this.bytes = new Uint8Array(length);
    this.#view = new DataView(this.bytes.buffer);
    this.#offset = initialOffset;
  }
  u8(value) {
    this.#require(1);
    if (!Number.isSafeInteger(value) || value < 0 || value > 255) {
      throw new StoreLimitError("unsigned 8-bit value is out of range");
    }
    this.#view.setUint8(this.#offset, value);
    this.#offset += 1;
  }
  u16(value) {
    this.#require(2);
    if (!Number.isSafeInteger(value) || value < 0 || value > 65535) {
      throw new StoreLimitError("unsigned 16-bit value is out of range");
    }
    this.#view.setUint16(this.#offset, value, true);
    this.#offset += 2;
  }
  u32(value) {
    this.#require(4);
    if (!Number.isSafeInteger(value) || value < 0 || value > 4294967295) {
      throw new StoreLimitError("unsigned 32-bit value is out of range");
    }
    this.#view.setUint32(this.#offset, value, true);
    this.#offset += 4;
  }
  u64(value) {
    this.#require(8);
    this.#view.setBigUint64(this.#offset, checkedU64(value, "encoded integer"), true);
    this.#offset += 8;
  }
  validatedU64(value) {
    this.#require(8);
    this.#view.setBigUint64(this.#offset, value, true);
    this.#offset += 8;
  }
  raw(value) {
    this.#require(value.byteLength);
    this.bytes.set(value, this.#offset);
    this.#offset += value.byteLength;
  }
  string(value) {
    validatePathComponent(value);
    this.validatedString(textEncoder.encode(value));
  }
  symlinkTarget(value) {
    validateSymlinkTarget(value);
    this.validatedString(textEncoder.encode(value));
  }
  validatedString(encoded) {
    this.u16(encoded.byteLength);
    this.raw(encoded);
  }
  finish() {
    if (this.#offset !== this.bytes.byteLength) {
      throw new StoreLimitError(`binary encoder wrote ${this.#offset} bytes into a ${this.bytes.byteLength}-byte output`);
    }
    return this.bytes;
  }
  #require(length) {
    if (this.#offset + length > this.bytes.byteLength) {
      throw new StoreLimitError("binary encoder exceeded its preflighted size");
    }
  }
}

class BinaryReader {
  #bytes;
  #view;
  #offset = 0;
  constructor(bytes) {
    this.#bytes = bytes;
    this.#view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
  }
  get remaining() {
    return this.#bytes.byteLength - this.#offset;
  }
  u8() {
    this.#require(1);
    const value = this.#view.getUint8(this.#offset);
    this.#offset += 1;
    return value;
  }
  u16() {
    this.#require(2);
    const value = this.#view.getUint16(this.#offset, true);
    this.#offset += 2;
    return value;
  }
  u32() {
    this.#require(4);
    const value = this.#view.getUint32(this.#offset, true);
    this.#offset += 4;
    return value;
  }
  u64() {
    this.#require(8);
    const value = this.#view.getBigUint64(this.#offset, true);
    this.#offset += 8;
    return value;
  }
  raw(length) {
    this.#require(length);
    const value = this.#bytes.subarray(this.#offset, this.#offset + length);
    this.#offset += length;
    return value;
  }
  string() {
    const length = this.u16();
    if (length === 0 || length > MAX_COMPONENT_BYTES) {
      throw new CorruptStoreError("encoded path component length is invalid");
    }
    let value;
    try {
      value = textDecoder.decode(this.raw(length));
    } catch (cause) {
      throw new CorruptStoreError("encoded path component is not valid UTF-8", { cause });
    }
    if (textEncoder.encode(value).byteLength !== length) {
      throw new CorruptStoreError("encoded path component is not canonical UTF-8");
    }
    try {
      validatePathComponent(value);
    } catch (cause) {
      throw new CorruptStoreError(`encoded path component is invalid: ${String(cause)}`, { cause });
    }
    return value;
  }
  symlinkTarget() {
    const length = this.u16();
    if (length === 0 || length > MAX_PATH_BYTES) {
      throw new CorruptStoreError("encoded symlink target length is invalid");
    }
    let value;
    try {
      value = textDecoder.decode(this.raw(length));
    } catch (cause) {
      throw new CorruptStoreError("encoded symlink target is not valid UTF-8", { cause });
    }
    if (textEncoder.encode(value).byteLength !== length) {
      throw new CorruptStoreError("encoded symlink target is not canonical UTF-8");
    }
    try {
      validateSymlinkTarget(value);
    } catch (cause) {
      throw new CorruptStoreError(`encoded symlink target is invalid: ${String(cause)}`, { cause });
    }
    return value;
  }
  end() {
    if (this.remaining !== 0) {
      throw new CorruptStoreError("binary value has trailing bytes");
    }
  }
  #require(length) {
    if (!Number.isSafeInteger(length) || length < 0 || length > this.remaining) {
      throw new CorruptStoreError("binary value is truncated");
    }
  }
}
function bytesEqual(left, right) {
  if (left.byteLength !== right.byteLength) {
    return false;
  }
  for (let index = 0;index < left.byteLength; index += 1) {
    if (left[index] !== right[index]) {
      return false;
    }
  }
  return true;
}
function requireMagic(bytes, magic, label) {
  if (!bytesEqual(bytes.subarray(0, magic.byteLength), magic)) {
    throw new CorruptStoreError(`${label} magic is invalid`);
  }
}
function requireZero(bytes, start, end, label) {
  for (let offset = start;offset < end; offset += 1) {
    if (bytes[offset] !== 0) {
      throw new CorruptStoreError(`${label} padding is not canonical`);
    }
  }
}
function requireChecksum(bytes, offset, label) {
  const stored = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength).getUint32(offset, true);
  const calculated = crc32WithZeroedRange(bytes, offset, 4);
  if (stored !== calculated) {
    throw new CorruptStoreError(`${label} checksum is invalid`);
  }
}
function requireCurrentIdentity(version, profile) {
  if (version !== FORMAT_VERSION || profile !== LIMITS_PROFILE_VERSION) {
    throw new StoreRecreationRequiredError(`store format ${version}/limits profile ${profile} is unsupported; delete the store and create it fresh`);
  }
}
function encodeArenaHeader(options) {
  const extentSize = validateExtentSize(options.extentSize);
  const bytes = new Uint8Array(ARENA_HEADER_BYTES);
  const view = new DataView(bytes.buffer);
  bytes.set(ARENA_MAGIC, 0);
  view.setUint32(8, FORMAT_VERSION, true);
  view.setUint32(12, LIMITS_PROFILE_VERSION, true);
  view.setUint32(16, extentSize, true);
  view.setUint32(ARENA_HEADER_CHECKSUM_OFFSET, crc32WithZeroedRange(bytes, ARENA_HEADER_CHECKSUM_OFFSET, 4), true);
  return bytes;
}
function decodeArenaHeader(bytes, configuredExtentSize) {
  if (configuredExtentSize !== undefined) {
    validateExtentSize(configuredExtentSize);
  }
  if (bytes.byteLength !== ARENA_HEADER_BYTES) {
    throw new CorruptStoreError("arena header has the wrong length");
  }
  requireMagic(bytes, ARENA_MAGIC, "arena header");
  requireZero(bytes, 20, 24, "arena header");
  requireZero(bytes, 28, bytes.byteLength, "arena header");
  requireChecksum(bytes, ARENA_HEADER_CHECKSUM_OFFSET, "arena header");
  const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
  const formatVersion = view.getUint32(8, true);
  const limitsProfileVersion = view.getUint32(12, true);
  requireCurrentIdentity(formatVersion, limitsProfileVersion);
  const extentSize = view.getUint32(16, true);
  try {
    validateExtentSize(extentSize);
  } catch (cause) {
    throw new CorruptStoreError("arena header extent size is invalid", { cause });
  }
  if (configuredExtentSize !== undefined && configuredExtentSize !== extentSize) {
    throw new ExtentSizeMismatchError(configuredExtentSize, extentSize);
  }
  return { extentSize, limitsProfileVersion, formatVersion };
}
function metadataFileCode(file) {
  return file === "a" ? 0 : 1;
}
function decodeMetadataFile(value) {
  if (value === 0)
    return "a";
  if (value === 1)
    return "b";
  throw new CorruptStoreError("metadata file selector is invalid");
}
function compareBigint(left, right) {
  return left < right ? -1 : left > right ? 1 : 0;
}
function compareUtf8Names(left, right) {
  let leftIndex = 0;
  let rightIndex = 0;
  while (leftIndex < left.length && rightIndex < right.length) {
    const leftPoint = left.codePointAt(leftIndex);
    const rightPoint = right.codePointAt(rightIndex);
    if (leftPoint !== rightPoint)
      return leftPoint - rightPoint;
    leftIndex += leftPoint > 65535 ? 2 : 1;
    rightIndex += rightPoint > 65535 ? 2 : 1;
  }
  return left.length - right.length;
}
function sortIfNeeded(values, compare) {
  for (let index = 1;index < values.length; index += 1) {
    if (compare(values[index - 1], values[index]) > 0) {
      values.sort(compare);
      break;
    }
  }
  return values;
}
var INODE_KIND_DIRECTORY = 0;
var INODE_KIND_FILE = 1;
var INODE_KIND_SYMLINK = 2;
function writeInode(writer, inode) {
  writer.validatedU64(inode.id);
  writer.u8(inode.kind === "directory" ? INODE_KIND_DIRECTORY : inode.kind === "file" ? INODE_KIND_FILE : INODE_KIND_SYMLINK);
  writer.u32(inode.mode);
  writer.validatedU64(inode.atimeMs);
  writer.validatedU64(inode.mtimeMs);
  writer.validatedU64(inode.ctimeMs);
  if (inode.kind === "directory") {
    const children = sortIfNeeded([...inode.children], ([left], [right]) => compareUtf8Names(left, right));
    writer.u32(children.length);
    for (const [name, inodeId] of children) {
      writer.validatedString(textEncoder.encode(name));
      writer.validatedU64(inodeId);
    }
  } else if (inode.kind === "symlink") {
    writer.symlinkTarget(inode.target);
  } else {
    writer.validatedU64(inode.size);
    writer.u32(inode.extents.length);
    for (const extentId of inode.extents)
      writer.validatedU64(extentId);
  }
}
function encodeMetadataPayload(state, length, prefixBytes = 0) {
  if (length > MAX_METADATA_BASE_WRITER_BYTES) {
    throw new StoreLimitError(`metadata base payload exceeds ${MAX_METADATA_BASE_WRITER_BYTES} bytes`);
  }
  const writer = new BinaryWriter(prefixBytes + length, prefixBytes);
  writer.validatedU64(state.allocator.totalExtents);
  writer.validatedU64(state.nextInodeId);
  writer.u32(state.inodes.size);
  const inodes = sortIfNeeded([...state.inodes.values()], (left, right) => compareBigint(left.id, right.id));
  for (const inode of inodes) {
    writeInode(writer, inode);
  }
  const available = sortIfNeeded([...state.allocator.available.values()], compareBigint);
  for (const extentId of available)
    writer.validatedU64(extentId);
  const quarantine = sortIfNeeded([...state.allocator.quarantine], ([left], [right]) => compareBigint(left, right));
  for (const [extentId, generation] of quarantine) {
    writer.validatedU64(extentId);
    writer.validatedU64(generation ?? 0n);
  }
  return writer.finish();
}
function inspectMetadataBaseHeader(header) {
  if (header.byteLength !== METADATA_HEADER_BYTES) {
    throw new CorruptStoreError("metadata base header has the wrong length");
  }
  requireMagic(header, METADATA_MAGIC, "metadata base");
  requireZero(header, 29, 32, "metadata base");
  requireZero(header, 52, 56, "metadata base");
  requireZero(header, 68, 80, "metadata base");
  const view = new DataView(header.buffer, header.byteOffset, header.byteLength);
  const payloadLength = view.getUint32(40, true);
  if (payloadLength > MAX_METADATA_BASE_READER_BYTES) {
    throw new CorruptStoreError("metadata base payload declaration exceeds the reader limit");
  }
  const baseEnd = view.getBigUint64(56, true);
  if (baseEnd !== BigInt(METADATA_HEADER_BYTES + payloadLength)) {
    throw new CorruptStoreError("metadata base end offset is inconsistent");
  }
  const availableCount = view.getUint32(44, true);
  const quarantineCount = view.getUint32(48, true);
  return {
    formatVersion: view.getUint32(8, true),
    limitsProfileVersion: view.getUint32(12, true),
    generation: view.getBigUint64(16, true),
    extentSize: view.getUint32(24, true),
    metadataFileCode: view.getUint8(28),
    rootInodeId: view.getBigUint64(32, true),
    payloadLength,
    availableCount,
    quarantineCount,
    baseEnd
  };
}
function encodeMetadataBase(state) {
  validateState(state);
  return encodeValidatedMetadataBase(state);
}
function encodeValidatedMetadataBase(state) {
  const baseEnd = METADATA_HEADER_BYTES + state.basePayloadBytes;
  const bytes = encodeMetadataPayload(state, state.basePayloadBytes, METADATA_HEADER_BYTES);
  const view = new DataView(bytes.buffer);
  bytes.set(METADATA_MAGIC, 0);
  view.setUint32(8, FORMAT_VERSION, true);
  view.setUint32(12, LIMITS_PROFILE_VERSION, true);
  view.setBigUint64(16, state.generation, true);
  view.setUint32(24, state.extentSize, true);
  view.setUint8(28, metadataFileCode(state.activeMetadataFile));
  view.setBigUint64(32, state.rootInodeId, true);
  view.setUint32(40, state.basePayloadBytes, true);
  view.setUint32(44, state.allocator.available.size, true);
  view.setUint32(48, state.allocator.quarantine.size, true);
  view.setBigUint64(56, BigInt(baseEnd), true);
  view.setUint32(METADATA_HEADER_CHECKSUM_OFFSET, crc32WithZeroedRange(bytes, METADATA_HEADER_CHECKSUM_OFFSET, 4), true);
  return bytes;
}
function readBoundedCount(reader, maximum, label) {
  const count = reader.u32();
  if (count > maximum) {
    throw new CorruptStoreError(`${label} count exceeds ${maximum}`);
  }
  return count;
}
function readInode(reader) {
  const id = reader.u64();
  const kind = reader.u8();
  const mode = reader.u32();
  const atimeMs = reader.u64();
  const mtimeMs = reader.u64();
  const ctimeMs = reader.u64();
  if (kind === INODE_KIND_DIRECTORY) {
    const childCount = readBoundedCount(reader, MAX_INODES, "directory child");
    const children = new Map;
    let previousName;
    for (let index = 0;index < childCount; index += 1) {
      const name = reader.string();
      if (previousName !== undefined && compareUtf8Names(previousName, name) >= 0) {
        throw new CorruptStoreError("directory children are not in canonical order");
      }
      children.set(name, reader.u64());
      previousName = name;
    }
    const inode = { id, kind: "directory", mode, atimeMs, mtimeMs, ctimeMs, children };
    return inode;
  }
  if (kind === INODE_KIND_FILE) {
    const size = reader.u64();
    const extentCount = readBoundedCount(reader, MAX_EXTENTS_PER_INODE, "file extent");
    const extents = [];
    for (let index = 0;index < extentCount; index += 1)
      extents.push(reader.u64());
    const inode = { id, kind: "file", mode, atimeMs, mtimeMs, ctimeMs, size, extents };
    return inode;
  }
  if (kind === INODE_KIND_SYMLINK) {
    const inode = {
      id,
      kind: "symlink",
      mode,
      atimeMs,
      mtimeMs,
      ctimeMs,
      target: reader.symlinkTarget()
    };
    return inode;
  }
  throw new CorruptStoreError("inode type is invalid");
}
function decodeMetadataBase(bytes) {
  if (bytes.byteLength < METADATA_HEADER_BYTES) {
    throw new CorruptStoreError("metadata base header is truncated");
  }
  const inspected = inspectMetadataBaseHeader(bytes.subarray(0, METADATA_HEADER_BYTES));
  const { payloadLength, baseEnd } = inspected;
  if (bytes.byteLength !== Number(baseEnd)) {
    throw new CorruptStoreError("metadata base end offset is inconsistent");
  }
  requireChecksum(bytes, METADATA_HEADER_CHECKSUM_OFFSET, "metadata base");
  const payload = bytes.subarray(METADATA_HEADER_BYTES);
  requireCurrentIdentity(inspected.formatVersion, inspected.limitsProfileVersion);
  const { generation, extentSize, rootInodeId, availableCount, quarantineCount } = inspected;
  if (generation === 0n)
    throw new CorruptStoreError("metadata generation must be positive");
  try {
    validateExtentSize(extentSize);
  } catch (cause) {
    throw new CorruptStoreError("metadata base extent size is invalid", { cause });
  }
  const activeMetadataFile = decodeMetadataFile(inspected.metadataFileCode);
  if (availableCount > MAX_TOTAL_EXTENTS || quarantineCount > MAX_TOTAL_EXTENTS) {
    throw new CorruptStoreError("metadata allocator count exceeds the extent limit");
  }
  try {
    const reader = new BinaryReader(payload);
    const totalExtents = reader.u64();
    if (totalExtents > BigInt(MAX_TOTAL_EXTENTS)) {
      throw new CorruptStoreError("metadata total extent count exceeds the extent limit");
    }
    const nextInodeId = reader.u64();
    const inodeCount = readBoundedCount(reader, MAX_INODES, "inode");
    const inodes = new Map;
    const ownedBy = new Map;
    let previousInodeId;
    for (let index = 0;index < inodeCount; index += 1) {
      const inode = readInode(reader);
      if (previousInodeId !== undefined && inode.id <= previousInodeId) {
        throw new CorruptStoreError("inodes are not in canonical order");
      }
      inodes.set(inode.id, inode);
      previousInodeId = inode.id;
      if (inode.kind === "file") {
        for (const extentId of inode.extents) {
          if (ownedBy.has(extentId))
            throw new CorruptStoreError("metadata contains duplicate extent ownership");
          ownedBy.set(extentId, inode.id);
        }
      }
    }
    const available = new IndexedExtentSet;
    let previousAvailable;
    for (let index = 0;index < availableCount; index += 1) {
      const extentId = reader.u64();
      if (previousAvailable !== undefined && extentId <= previousAvailable) {
        throw new CorruptStoreError("available extents are not in canonical order");
      }
      available.add(extentId);
      previousAvailable = extentId;
    }
    const quarantine = new Map;
    let previousQuarantine;
    for (let index = 0;index < quarantineCount; index += 1) {
      const extentId = reader.u64();
      const encodedGeneration = reader.u64();
      if (previousQuarantine !== undefined && extentId <= previousQuarantine) {
        throw new CorruptStoreError("quarantine extents are not in canonical order");
      }
      quarantine.set(extentId, encodedGeneration === 0n ? null : encodedGeneration);
      previousQuarantine = extentId;
    }
    reader.end();
    const parentByInode = new Map;
    for (const inode of inodes.values()) {
      if (inode.kind !== "directory")
        continue;
      for (const [name, childId] of inode.children) {
        if (parentByInode.has(childId)) {
          throw new CorruptStoreError("metadata inode has multiple directory owners");
        }
        parentByInode.set(childId, { parentId: inode.id, name });
      }
    }
    const retainedGenerations = { a: null, b: null };
    retainedGenerations[activeMetadataFile] = generation;
    const state = {
      generation,
      nextInodeId,
      rootInodeId,
      extentSize,
      activeMetadataFile,
      retainedGenerations,
      basePayloadBytes: payloadLength,
      inodes,
      parentByInode,
      allocator: { totalExtents, ownedBy, available, quarantine }
    };
    validateState(state);
    return { state, payloadBytes: payloadLength, baseEnd, baseDigest: crc32(bytes) };
  } catch (cause) {
    if (cause instanceof CorruptStoreError)
      throw cause;
    throw new CorruptStoreError(`metadata base is semantically invalid: ${String(cause)}`, { cause });
  }
}
function writeExtentRuns(writer, runs) {
  writer.u32(runs.length);
  for (const run of runs) {
    writer.u64(run.start);
    writer.u32(run.count);
  }
}
function readExtentRuns(reader) {
  const runCount = readBoundedCount(reader, MAX_EXTENTS_PER_INODE, "extent run");
  const runs = [];
  let extentCount = 0;
  for (let index = 0;index < runCount; index += 1) {
    const start = reader.u64();
    const count = reader.u32();
    if (count === 0 || extentCount + count > MAX_EXTENTS_PER_INODE) {
      throw new CorruptStoreError("extent run count is invalid");
    }
    extentCount += count;
    runs.push({ start, count });
  }
  return runs;
}
var RECORD_CODES = {
  createDirectories: 1,
  createFile: 2,
  removeFile: 3,
  changeMode: 4,
  changeTimes: 5,
  resizeFile: 6,
  removeDirectory: 7,
  rename: 8,
  reserveQuarantine: 9,
  createSymlink: 10
};
function encodeTxnRecord(record) {
  const writer = new BinaryWriter(estimateTxnPayloadBytes(record));
  writer.u8(RECORD_CODES[record.kind]);
  switch (record.kind) {
    case "createDirectories":
      writer.u32(record.entries.length);
      for (const entry of record.entries) {
        writer.u64(entry.parentId);
        writer.string(entry.name);
        writer.u64(entry.inodeId);
        writer.u32(entry.mode);
        writer.u64(entry.atimeMs);
        writer.u64(entry.mtimeMs);
        writer.u64(entry.ctimeMs);
      }
      break;
    case "createFile":
      writer.u64(record.parentId);
      writer.string(record.name);
      writer.u64(record.inodeId);
      writer.u32(record.mode);
      writer.u64(record.atimeMs);
      writer.u64(record.mtimeMs);
      writer.u64(record.ctimeMs);
      writer.u64(record.size);
      writeExtentRuns(writer, record.extents);
      break;
    case "removeFile":
    case "removeDirectory":
      writer.u64(record.parentId);
      writer.string(record.name);
      writer.u64(record.parentMtimeMs);
      writer.u64(record.parentCtimeMs);
      break;
    case "changeMode":
      writer.u64(record.inodeId);
      writer.u32(record.mode);
      writer.u64(record.ctimeMs);
      break;
    case "changeTimes":
      writer.u64(record.inodeId);
      writer.u64(record.atimeMs);
      writer.u64(record.mtimeMs);
      writer.u64(record.ctimeMs);
      break;
    case "resizeFile":
      writer.u8(record.operation === "truncate" ? 0 : 1);
      writer.u64(record.inodeId);
      writer.u64(record.size);
      writeExtentRuns(writer, record.allocated);
      writer.u64(record.mtimeMs);
      writer.u64(record.ctimeMs);
      break;
    case "rename":
      writer.u64(record.sourceParentId);
      writer.string(record.sourceName);
      writer.u64(record.destinationParentId);
      writer.string(record.destinationName);
      writer.u64(record.timestampMs);
      break;
    case "createSymlink":
      writer.u64(record.parentId);
      writer.string(record.name);
      writer.u64(record.inodeId);
      writer.u32(record.mode);
      writer.u64(record.atimeMs);
      writer.u64(record.mtimeMs);
      writer.u64(record.ctimeMs);
      writer.symlinkTarget(record.target);
      break;
    case "reserveQuarantine":
      writeExtentRuns(writer, record.extents);
      break;
  }
  return writer.finish();
}
function decodeTxnRecord(bytes) {
  const reader = new BinaryReader(bytes);
  const type = reader.u8();
  let record;
  switch (type) {
    case 1: {
      const count = readBoundedCount(reader, MAX_INODES, "created directory");
      if (count === 0)
        throw new CorruptStoreError("directory transaction must not be empty");
      const entries = [];
      for (let index = 0;index < count; index += 1) {
        entries.push({
          parentId: reader.u64(),
          name: reader.string(),
          inodeId: reader.u64(),
          mode: reader.u32(),
          atimeMs: reader.u64(),
          mtimeMs: reader.u64(),
          ctimeMs: reader.u64()
        });
      }
      record = { kind: "createDirectories", entries };
      break;
    }
    case 2:
      record = {
        kind: "createFile",
        parentId: reader.u64(),
        name: reader.string(),
        inodeId: reader.u64(),
        mode: reader.u32(),
        atimeMs: reader.u64(),
        mtimeMs: reader.u64(),
        ctimeMs: reader.u64(),
        size: reader.u64(),
        extents: readExtentRuns(reader)
      };
      break;
    case 3:
    case 7:
      record = {
        kind: type === 3 ? "removeFile" : "removeDirectory",
        parentId: reader.u64(),
        name: reader.string(),
        parentMtimeMs: reader.u64(),
        parentCtimeMs: reader.u64()
      };
      break;
    case 4:
      record = { kind: "changeMode", inodeId: reader.u64(), mode: reader.u32(), ctimeMs: reader.u64() };
      break;
    case 5:
      record = {
        kind: "changeTimes",
        inodeId: reader.u64(),
        atimeMs: reader.u64(),
        mtimeMs: reader.u64(),
        ctimeMs: reader.u64()
      };
      break;
    case 6: {
      const operation = reader.u8();
      if (operation !== 0 && operation !== 1)
        throw new CorruptStoreError("resize operation is invalid");
      record = {
        kind: "resizeFile",
        operation: operation === 0 ? "truncate" : "write",
        inodeId: reader.u64(),
        size: reader.u64(),
        allocated: readExtentRuns(reader),
        mtimeMs: reader.u64(),
        ctimeMs: reader.u64()
      };
      break;
    }
    case 8:
      record = {
        kind: "rename",
        sourceParentId: reader.u64(),
        sourceName: reader.string(),
        destinationParentId: reader.u64(),
        destinationName: reader.string(),
        timestampMs: reader.u64()
      };
      break;
    case 9:
      record = { kind: "reserveQuarantine", extents: readExtentRuns(reader) };
      break;
    case 10:
      record = {
        kind: "createSymlink",
        parentId: reader.u64(),
        name: reader.string(),
        inodeId: reader.u64(),
        mode: reader.u32(),
        atimeMs: reader.u64(),
        mtimeMs: reader.u64(),
        ctimeMs: reader.u64(),
        target: reader.symlinkTarget()
      };
      break;
    default:
      throw new CorruptStoreError("transaction record type is invalid");
  }
  reader.end();
  return record;
}
function txnFrameBytes(record) {
  const payloadBytes = estimateTxnPayloadBytes(record);
  if (payloadBytes > MAX_FRAME_PAYLOAD_BYTES) {
    throw new StoreLimitError(`transaction payload exceeds ${MAX_FRAME_PAYLOAD_BYTES} bytes`);
  }
  return TXN_FRAME_HEADER_BYTES + payloadBytes;
}
function inspectTxnFrameHeader(header) {
  if (header.byteLength !== TXN_FRAME_HEADER_BYTES) {
    throw new CorruptStoreError("transaction frame header has the wrong length");
  }
  const view = new DataView(header.buffer, header.byteOffset, header.byteLength);
  requireMagic(header, FRAME_MAGIC, "transaction frame");
  requireZero(header, 36, 40, "transaction frame");
  requireZero(header, 44, 48, "transaction frame");
  const payloadLength = view.getUint32(32, true);
  if (payloadLength > MAX_FRAME_PAYLOAD_BYTES) {
    throw new CorruptStoreError("transaction payload declaration exceeds the frame limit");
  }
  if (view.getUint32(8, true) !== FORMAT_VERSION || view.getUint32(12, true) !== LIMITS_PROFILE_VERSION) {
    throw new CorruptStoreError("transaction frame format is invalid");
  }
  return {
    generation: view.getBigUint64(16, true),
    sequence: view.getBigUint64(24, true),
    payloadLength,
    frameBytes: TXN_FRAME_HEADER_BYTES + payloadLength
  };
}
function encodeTxnFrame(frame) {
  const payload = encodeTxnRecord(frame.record);
  if (payload.byteLength > MAX_FRAME_PAYLOAD_BYTES) {
    throw new StoreLimitError(`transaction payload exceeds ${MAX_FRAME_PAYLOAD_BYTES} bytes`);
  }
  const bytes = new Uint8Array(TXN_FRAME_HEADER_BYTES + payload.byteLength);
  const view = new DataView(bytes.buffer);
  bytes.set(FRAME_MAGIC, 0);
  view.setUint32(8, FORMAT_VERSION, true);
  view.setUint32(12, LIMITS_PROFILE_VERSION, true);
  view.setBigUint64(16, checkedU64(frame.generation, "frame generation"), true);
  view.setBigUint64(24, checkedU64(frame.sequence, "frame sequence"), true);
  view.setUint32(32, payload.byteLength, true);
  bytes.set(payload, TXN_FRAME_HEADER_BYTES);
  view.setUint32(FRAME_CHECKSUM_OFFSET, crc32WithZeroedRange(bytes, FRAME_CHECKSUM_OFFSET, 4), true);
  return bytes;
}
function decodeTxnFrame(bytes) {
  if (bytes.byteLength < TXN_FRAME_HEADER_BYTES)
    throw new CorruptStoreError("transaction frame is truncated");
  const inspected = inspectTxnFrameHeader(bytes.subarray(0, TXN_FRAME_HEADER_BYTES));
  if (bytes.byteLength !== inspected.frameBytes) {
    throw new CorruptStoreError("transaction frame length is inconsistent");
  }
  requireChecksum(bytes, FRAME_CHECKSUM_OFFSET, "transaction frame");
  return {
    generation: inspected.generation,
    sequence: inspected.sequence,
    record: decodeTxnRecord(bytes.subarray(TXN_FRAME_HEADER_BYTES))
  };
}
function encodeActivationSlot(record) {
  if (record.sequence === 0n || record.generation === 0n || record.baseEnd < BigInt(METADATA_HEADER_BYTES)) {
    throw new StoreLimitError("activation identity values are outside the encodable domain");
  }
  const bytes = new Uint8Array(ACTIVATION_SLOT_BYTES);
  const view = new DataView(bytes.buffer);
  bytes.set(ACTIVATION_MAGIC, 0);
  view.setUint32(8, FORMAT_VERSION, true);
  view.setUint32(12, LIMITS_PROFILE_VERSION, true);
  view.setBigUint64(16, checkedU64(record.sequence, "activation sequence"), true);
  view.setUint8(24, metadataFileCode(record.metadataFile));
  view.setBigUint64(32, checkedU64(record.generation, "activation generation"), true);
  view.setBigUint64(40, checkedU64(record.baseEnd, "activation base end"), true);
  if (!Number.isSafeInteger(record.baseDigest) || record.baseDigest < 0 || record.baseDigest > 4294967295) {
    throw new StoreLimitError("activation base digest is outside the unsigned 32-bit range");
  }
  view.setUint32(48, record.baseDigest, true);
  view.setUint32(ACTIVATION_CHECKSUM_OFFSET, crc32WithZeroedRange(bytes, ACTIVATION_CHECKSUM_OFFSET, 4), true);
  return bytes;
}
function decodeActivationSlot(bytes) {
  if (bytes.byteLength !== ACTIVATION_SLOT_BYTES) {
    throw new CorruptStoreError("activation slot has the wrong length");
  }
  requireMagic(bytes, ACTIVATION_MAGIC, "activation slot");
  requireZero(bytes, 25, 32, "activation slot");
  requireZero(bytes, 56, bytes.byteLength, "activation slot");
  requireChecksum(bytes, ACTIVATION_CHECKSUM_OFFSET, "activation slot");
  const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
  requireCurrentIdentity(view.getUint32(8, true), view.getUint32(12, true));
  const sequence = view.getBigUint64(16, true);
  const generation = view.getBigUint64(32, true);
  const baseEnd = view.getBigUint64(40, true);
  if (sequence === 0n || generation === 0n || baseEnd < BigInt(METADATA_HEADER_BYTES)) {
    throw new CorruptStoreError("activation slot contains invalid identity values");
  }
  return {
    sequence,
    metadataFile: decodeMetadataFile(view.getUint8(24)),
    generation,
    baseEnd,
    baseDigest: view.getUint32(48, true)
  };
}
function tryDecodeActivationSlot(bytes) {
  try {
    return decodeActivationSlot(bytes);
  } catch (cause) {
    if (cause instanceof CorruptStoreError)
      return null;
    throw cause;
  }
}
function selectActivationPair(leftBytes, rightBytes) {
  const left = tryDecodeActivationSlot(leftBytes);
  const right = tryDecodeActivationSlot(rightBytes);
  if (left === null && right === null) {
    throw new CorruptStoreError("both activation slots are invalid");
  }
  if (left === null)
    return { selected: right, other: null };
  if (right === null)
    return { selected: left, other: null };
  const older = left.sequence < right.sequence ? left : right;
  const newer = older === left ? right : left;
  if (newer.sequence !== older.sequence + 1n || newer.metadataFile === older.metadataFile) {
    throw new CorruptStoreError("activation slots do not form one exact alternating progression");
  }
  return { selected: newer, other: older };
}
function metadataBaseDigest(bytes) {
  return crc32(bytes);
}

// packages/pgwasm/src/opfs/core/port.ts
var OWNED_FILE_NAMES = ["arena.bin", "metadata-a.bin", "metadata-b.bin", "activation.bin"];
function metadataFileName(file) {
  return file === "a" ? "metadata-a.bin" : "metadata-b.bin";
}

class PortWriteError extends Error {
  constructor(label) {
    super(`${label} made no valid write progress`);
    this.name = "PortWriteError";
  }
}
function checkedRange(offset, length, label) {
  checkedU64(offset, `${label} offset`);
  if (!Number.isSafeInteger(length) || length < 0) {
    throw new StoreLimitError(`${label} length is invalid`);
  }
  checkedSafeNumber(checkedAdd(offset, BigInt(length), `${label} end`), `${label} end`);
  return checkedSafeNumber(offset, `${label} offset`);
}
function readExact(handle, offset, length, maximumLength, label) {
  if (!Number.isSafeInteger(maximumLength) || maximumLength < 0 || length > maximumLength) {
    throw new StoreLimitError(`${label} length exceeds the bounded read limit`);
  }
  const start = checkedRange(offset, length, label);
  const output = new Uint8Array(length);
  let completed = 0;
  while (completed < output.byteLength) {
    const count = handle.read(output.subarray(completed), start + completed, label);
    if (!Number.isSafeInteger(count) || count <= 0 || count > output.byteLength - completed) {
      throw new CorruptStoreError(`${label} ended before the declared byte length`);
    }
    completed += count;
  }
  return output;
}
function writeExact(handle, offset, bytes, label) {
  const start = checkedRange(offset, bytes.byteLength, label);
  let completed = 0;
  while (completed < bytes.byteLength) {
    const count = handle.write(bytes.subarray(completed), start + completed, label);
    if (!Number.isSafeInteger(count) || count <= 0 || count > bytes.byteLength - completed) {
      throw new PortWriteError(label);
    }
    completed += count;
  }
}
function truncateChecked(handle, size, label) {
  handle.truncate(checkedSafeNumber(size, `${label} size`), label);
}
function arenaByteOffset(extentId, extentSize, withinExtent = 0) {
  validateExtentSize(extentSize);
  checkedU64(extentId, "extent ID");
  if (extentId >= BigInt(MAX_TOTAL_EXTENTS)) {
    throw new StoreLimitError(`extent ID exceeds ${MAX_TOTAL_EXTENTS - 1}`);
  }
  if (!Number.isSafeInteger(withinExtent) || withinExtent < 0 || withinExtent >= extentSize) {
    throw new StoreLimitError("within-extent offset is outside the extent");
  }
  return checkedAdd(checkedAdd(BigInt(ARENA_HEADER_BYTES), checkedMultiply(extentId, BigInt(extentSize), "arena offset"), "arena offset"), BigInt(withinExtent), "arena offset");
}

// packages/pgwasm/src/opfs/core/metadata-store.ts
function validateEntries(entries) {
  for (const entry of entries) {
    if (!OWNED_FILE_NAMES.includes(entry.name) || entry.kind !== "file") {
      throw new UnexpectedStoreEntryError(entry.name);
    }
  }
}
function closeHandles(handles) {
  for (let index = handles.length - 1;index >= 0; index -= 1) {
    try {
      handles[index].close();
    } catch {}
  }
}
async function acquireHandles(port) {
  validateEntries(await port.enumerate("store.enumerate.initial"));
  const acquired = [];
  try {
    const activation = await port.acquire("activation.bin", "store.acquire.activation");
    acquired.push(activation);
    validateEntries(await port.enumerate("store.enumerate.locked"));
    for (const name of ["arena.bin", "metadata-a.bin", "metadata-b.bin"]) {
      acquired.push(await port.acquire(name, `store.acquire.${name}`));
    }
    return Object.fromEntries(acquired.map((handle) => [handle.name, handle]));
  } catch (cause) {
    closeHandles(acquired);
    throw cause;
  }
}
function getSizes(handles) {
  return Object.fromEntries(OWNED_FILE_NAMES.map((name) => [name, handles[name].getSize(`store.size.${name}`)]));
}
function readSlot(handle, size, index) {
  const offset = index * ACTIVATION_SLOT_BYTES;
  if (offset >= size)
    return new Uint8Array;
  const length = Math.min(ACTIVATION_SLOT_BYTES, size - offset);
  return readExact(handle, BigInt(offset), length, ACTIVATION_SLOT_BYTES, `activation.read.slot-${index}`);
}
function isPrefix(bytes, canonical) {
  if (bytes.byteLength > canonical.byteLength)
    return false;
  for (let index = 0;index < bytes.byteLength; index += 1) {
    if (bytes[index] !== canonical[index])
      return false;
  }
  return true;
}
function readWhole(handle, size, maximum, label) {
  return readExact(handle, 0n, size, maximum, label);
}
function bootstrapExtentSize(arena, arenaSize, configuredExtentSize) {
  if (arenaSize === 0)
    return configuredExtentSize ?? DEFAULT_EXTENT_BYTES;
  if (arenaSize >= ARENA_HEADER_BYTES) {
    const header = readExact(arena, 0n, ARENA_HEADER_BYTES, ARENA_HEADER_BYTES, "arena.read.bootstrap");
    const extentSize = decodeArenaHeader(header).extentSize;
    if (arenaSize > ARENA_HEADER_BYTES) {
      throw new CorruptStoreError("unactivated arena contains extent payload");
    }
    return extentSize;
  }
  const bytes = readWhole(arena, arenaSize, ARENA_HEADER_BYTES, "arena.read.bootstrap");
  let partialExtentSize;
  if (arenaSize >= 20) {
    const declared = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength).getUint32(16, true);
    try {
      partialExtentSize = validateExtentSize(declared);
    } catch (cause) {
      if (!(cause instanceof TypeError))
        throw cause;
      partialExtentSize = undefined;
    }
  }
  const candidates = new Set;
  if (configuredExtentSize !== undefined)
    candidates.add(configuredExtentSize);
  if (partialExtentSize !== undefined)
    candidates.add(partialExtentSize);
  candidates.add(DEFAULT_EXTENT_BYTES);
  if (arenaSize < 20) {
    for (let candidate = MIN_EXTENT_BYTES;candidate <= MAX_EXTENT_BYTES; candidate += ARENA_HEADER_BYTES) {
      candidates.add(candidate);
    }
  }
  const matchingExtentSize = [...candidates].find((candidate) => isPrefix(bytes, encodeArenaHeader({ extentSize: candidate })));
  if (matchingExtentSize === undefined) {
    throw new CorruptStoreError("unactivated arena is not canonical bootstrap residue");
  }
  return partialExtentSize ?? matchingExtentSize;
}
function detectArenaVersion(handle, size) {
  if (size < ARENA_HEADER_BYTES)
    return;
  const bytes = readExact(handle, 0n, ARENA_HEADER_BYTES, ARENA_HEADER_BYTES, "arena.inspect.identity");
  try {
    decodeArenaHeader(bytes);
  } catch (cause) {
    if (cause instanceof StoreRecreationRequiredError)
      throw cause;
    if (!(cause instanceof CorruptStoreError))
      throw cause;
  }
}
function detectCompleteMetadataVersion(handle, size, label) {
  if (size < METADATA_HEADER_BYTES)
    return;
  let header;
  try {
    header = inspectMetadataBaseHeader(readExact(handle, 0n, METADATA_HEADER_BYTES, METADATA_HEADER_BYTES, label));
  } catch (cause) {
    if (cause instanceof CorruptStoreError)
      return;
    throw cause;
  }
  if (header.baseEnd > BigInt(size))
    return;
  const base = readExact(handle, 0n, Number(header.baseEnd), METADATA_HEADER_BYTES + MAX_METADATA_BASE_READER_BYTES, `${label}.base`);
  try {
    decodeMetadataBase(base);
  } catch (cause) {
    if (cause instanceof StoreRecreationRequiredError)
      throw cause;
    if (!(cause instanceof CorruptStoreError))
      throw cause;
  }
}
function classifyBootstrapResidue(handles, sizes, configuredExtentSize) {
  const extentSize = bootstrapExtentSize(handles["arena.bin"], sizes["arena.bin"], configuredExtentSize);
  const initialA = createInitialState(extentSize);
  const baseA = encodeMetadataBase(initialA);
  const initialB = createInitialState(extentSize);
  initialB.activeMetadataFile = "b";
  initialB.retainedGenerations = { a: null, b: 1n };
  const baseB = encodeMetadataBase(initialB);
  for (const [name, canonical] of [
    ["metadata-a.bin", baseA],
    ["metadata-b.bin", baseB]
  ]) {
    const size = sizes[name];
    detectCompleteMetadataVersion(handles[name], size, `${name}.inspect.bootstrap`);
    if (size > canonical.byteLength) {
      throw new CorruptStoreError(`${name} exceeds the empty-root bootstrap envelope`);
    }
    const bytes = readWhole(handles[name], size, canonical.byteLength, `${name}.read.bootstrap`);
    if (!isPrefix(bytes, canonical)) {
      throw new CorruptStoreError(`${name} is not canonical bootstrap residue`);
    }
  }
  if (sizes["activation.bin"] > ACTIVATION_SLOT_BYTES * 2) {
    throw new CorruptStoreError("unactivated manifest exceeds its fixed envelope");
  }
  const initialSlot = encodeActivationSlot({
    sequence: 1n,
    metadataFile: "a",
    generation: 1n,
    baseEnd: BigInt(baseA.byteLength),
    baseDigest: metadataBaseDigest(baseA)
  });
  const canonicalManifest = new Uint8Array(ACTIVATION_SLOT_BYTES * 2);
  canonicalManifest.set(initialSlot);
  const manifest = readWhole(handles["activation.bin"], sizes["activation.bin"], canonicalManifest.byteLength, "activation.read.bootstrap");
  if (!isPrefix(manifest, canonicalManifest)) {
    throw new CorruptStoreError("manifest is not canonical bootstrap residue");
  }
  if (sizes["arena.bin"] === ARENA_HEADER_BYTES && configuredExtentSize !== undefined && configuredExtentSize !== extentSize) {
    throw new ExtentSizeMismatchError(configuredExtentSize, extentSize);
  }
  return sizes["arena.bin"] < ARENA_HEADER_BYTES && configuredExtentSize !== undefined ? configuredExtentSize : extentSize;
}
function bootstrap(handles, extentSize) {
  const state = createInitialState(extentSize);
  const arenaBytes = encodeArenaHeader({ extentSize });
  const baseBytes = encodeMetadataBase(state);
  const activationBytes = encodeActivationSlot({
    sequence: 1n,
    metadataFile: "a",
    generation: 1n,
    baseEnd: BigInt(baseBytes.byteLength),
    baseDigest: metadataBaseDigest(baseBytes)
  });
  const arena = handles["arena.bin"];
  arena.truncate(0, "bootstrap.arena.reset");
  writeExact(arena, 0n, arenaBytes, "bootstrap.arena.write");
  arena.flush("bootstrap.arena.flush");
  const metadataA = handles["metadata-a.bin"];
  metadataA.truncate(0, "bootstrap.metadata-a.reset");
  writeExact(metadataA, 0n, baseBytes, "bootstrap.metadata-a.write");
  metadataA.flush("bootstrap.metadata-a.flush");
  handles["metadata-b.bin"].truncate(0, "bootstrap.metadata-b.reset");
  const activation = handles["activation.bin"];
  activation.truncate(0, "bootstrap.activation.reset");
  writeExact(activation, 0n, activationBytes, "bootstrap.activation.write");
  activation.flush("bootstrap.activation.flush");
  const decoded = decodeMetadataBase(baseBytes);
  return {
    handles,
    state: decoded.state,
    activeLogEnd: decoded.baseEnd,
    nextSequence: 1n,
    activeLogBytes: 0,
    activeLogFrames: 0,
    activationSequence: 1n,
    arenaHighWaterExtents: 0n,
    arenaSize: arenaBytes.byteLength,
    arenaDirty: false,
    activeMetadataDirty: false
  };
}
function metadataHandle(handles, file) {
  return handles[metadataFileName(file)];
}
function verifyInactiveVersion(handles, sizes, selectedFile) {
  const inactiveName = metadataFileName(otherMetadataFile(selectedFile));
  detectCompleteMetadataVersion(handles[inactiveName], sizes[inactiveName], `${inactiveName}.inspect.inactive`);
}
function readSelectedBase(handle, fileSize, selected) {
  if (fileSize < METADATA_HEADER_BYTES)
    throw new CorruptStoreError("selected metadata base is missing or short");
  const headerBytes = readExact(handle, 0n, METADATA_HEADER_BYTES, METADATA_HEADER_BYTES, "metadata.read.header");
  const header = inspectMetadataBaseHeader(headerBytes);
  if (header.baseEnd !== selected.baseEnd || header.baseEnd > BigInt(fileSize)) {
    throw new CorruptStoreError("selected metadata base end does not match activation");
  }
  const baseBytes = readExact(handle, 0n, Number(header.baseEnd), METADATA_HEADER_BYTES + MAX_METADATA_BASE_READER_BYTES, "metadata.read.base");
  const decoded = decodeMetadataBase(baseBytes);
  if (decoded.state.activeMetadataFile !== selected.metadataFile || decoded.state.generation !== selected.generation || decoded.baseEnd !== selected.baseEnd || decoded.baseDigest !== selected.baseDigest) {
    throw new CorruptStoreError("selected metadata base identity does not match activation");
  }
  return { ...decoded, header };
}
function requiredArenaEnd(state) {
  return checkedAdd(BigInt(ARENA_HEADER_BYTES), checkedMultiply(state.allocator.totalExtents, BigInt(state.extentSize), "required arena bytes"), "required arena end");
}
function replayLog(handle, fileSize, state, baseEnd) {
  let cursor = checkedSafeNumber(baseEnd, "active log start");
  let sequence = 1n;
  let frameCount = 0;
  while (cursor < fileSize && frameCount < MAX_ACTIVE_LOG_FRAMES) {
    const logBytes = cursor - Number(baseEnd);
    const remaining = fileSize - cursor;
    if (remaining < TXN_FRAME_HEADER_BYTES || logBytes + TXN_FRAME_HEADER_BYTES > MAX_ACTIVE_LOG_BYTES)
      break;
    const headerBytes = readExact(handle, BigInt(cursor), TXN_FRAME_HEADER_BYTES, TXN_FRAME_HEADER_BYTES, "metadata.log.read-header");
    let inspected;
    try {
      inspected = inspectTxnFrameHeader(headerBytes);
    } catch (cause) {
      if (cause instanceof CorruptStoreError)
        break;
      throw cause;
    }
    if (inspected.frameBytes > remaining || logBytes + inspected.frameBytes > MAX_ACTIVE_LOG_BYTES)
      break;
    const frameBytes = readExact(handle, BigInt(cursor), inspected.frameBytes, TXN_FRAME_HEADER_BYTES + inspected.payloadLength, "metadata.log.read-frame");
    try {
      const frame = decodeTxnFrame(frameBytes);
      if (frame.generation !== state.generation || frame.sequence !== sequence)
        break;
      applyTxn(state, frame.record);
    } catch (cause) {
      if (cause instanceof CorruptStoreError || cause instanceof FsError || cause instanceof StoreLimitError) {
        break;
      }
      throw cause;
    }
    cursor += inspected.frameBytes;
    sequence += 1n;
    frameCount += 1;
  }
  validateState(state);
  return { validEnd: BigInt(cursor), nextSequence: sequence, requiredArenaEnd: requiredArenaEnd(state) };
}
function recoverActivated(handles, sizes, leftBytes, rightBytes, configuredExtentSize) {
  if (sizes["arena.bin"] < ARENA_HEADER_BYTES) {
    throw new CorruptStoreError("activated arena header is missing or short");
  }
  const arenaHeader = decodeArenaHeader(readExact(handles["arena.bin"], 0n, ARENA_HEADER_BYTES, ARENA_HEADER_BYTES, "arena.read.header"));
  const selection = selectActivationPair(leftBytes, rightBytes);
  verifyInactiveVersion(handles, sizes, selection.selected.metadataFile);
  const selectedHandle = metadataHandle(handles, selection.selected.metadataFile);
  const selectedName = selectedHandle.name;
  const decoded = readSelectedBase(selectedHandle, sizes[selectedName], selection.selected);
  if (decoded.state.extentSize !== arenaHeader.extentSize || decoded.header.limitsProfileVersion !== arenaHeader.limitsProfileVersion) {
    throw new CorruptStoreError("arena and metadata identities disagree");
  }
  if (selection.other !== null) {
    decoded.state.retainedGenerations[selection.other.metadataFile] = selection.other.generation;
  }
  try {
    validateState(decoded.state);
  } catch (cause) {
    if (cause instanceof StoreLimitError) {
      throw new CorruptStoreError(`activation retained-generation facts are invalid: ${cause.message}`, { cause });
    }
    throw cause;
  }
  const replayed = replayLog(selectedHandle, sizes[selectedName], decoded.state, decoded.baseEnd);
  if (configuredExtentSize !== undefined && configuredExtentSize !== arenaHeader.extentSize) {
    throw new ExtentSizeMismatchError(configuredExtentSize, arenaHeader.extentSize);
  }
  const requiredEnd = checkedSafeNumber(replayed.requiredArenaEnd, "required arena end");
  const arenaDirty = sizes["arena.bin"] < requiredEnd;
  if (arenaDirty) {
    truncateChecked(handles["arena.bin"], replayed.requiredArenaEnd, "recovery.arena.grow");
  }
  const activeMetadataDirty = replayed.validEnd < BigInt(sizes[selectedName]);
  if (activeMetadataDirty) {
    truncateChecked(selectedHandle, replayed.validEnd, "recovery.metadata.discard-suffix");
  }
  const physicalArenaExtents = (BigInt(Math.max(0, sizes["arena.bin"] - ARENA_HEADER_BYTES)) + BigInt(arenaHeader.extentSize) - 1n) / BigInt(arenaHeader.extentSize);
  return {
    handles,
    state: decoded.state,
    activeLogEnd: replayed.validEnd,
    nextSequence: replayed.nextSequence,
    activeLogBytes: Number(replayed.validEnd - decoded.baseEnd),
    activeLogFrames: Number(replayed.nextSequence - 1n),
    activationSequence: selection.selected.sequence,
    arenaHighWaterExtents: physicalArenaExtents > decoded.state.allocator.totalExtents ? physicalArenaExtents : decoded.state.allocator.totalExtents,
    arenaSize: arenaDirty ? requiredEnd : sizes["arena.bin"],
    arenaDirty,
    activeMetadataDirty
  };
}
async function openMetadataStore(port, options) {
  const configuredExtentSize = options.extentSize;
  if (configuredExtentSize !== undefined)
    validateExtentSize(configuredExtentSize);
  const handles = await acquireHandles(port);
  try {
    const sizes = getSizes(handles);
    const leftBytes = readSlot(handles["activation.bin"], sizes["activation.bin"], 0);
    const rightBytes = readSlot(handles["activation.bin"], sizes["activation.bin"], 1);
    detectArenaVersion(handles["arena.bin"], sizes["arena.bin"]);
    detectCompleteMetadataVersion(handles["metadata-a.bin"], sizes["metadata-a.bin"], "metadata-a.bin.inspect.identity");
    detectCompleteMetadataVersion(handles["metadata-b.bin"], sizes["metadata-b.bin"], "metadata-b.bin.inspect.identity");
    const left = tryDecodeActivationSlot(leftBytes);
    const right = tryDecodeActivationSlot(rightBytes);
    if (sizes["activation.bin"] > ACTIVATION_SLOT_BYTES * 2) {
      throw new CorruptStoreError("manifest exceeds its fixed envelope");
    }
    if (left !== null || right !== null) {
      return recoverActivated(handles, sizes, leftBytes, rightBytes, configuredExtentSize);
    }
    const extentSize = classifyBootstrapResidue(handles, sizes, configuredExtentSize);
    return bootstrap(handles, extentSize);
  } catch (cause) {
    closeHandles(Object.values(handles));
    throw cause;
  }
}

// packages/pgwasm/src/opfs/core/repacked-vfs.ts
var REPACK_INTERVAL_MS = 30000;
var AMORTIZED_ARENA_FLUSH_BYTES = 4 * 1024 * 1024;
var BASE_REPACK_PRESSURE_BYTES = Math.floor(MAX_METADATA_BASE_WRITER_BYTES * 0.75);
var QUARANTINE_PRESSURE_EXTENTS = 64;

class ArenaGrowthQuotaError extends Error {
  cause;
  constructor(cause) {
    super("arena growth exhausted the storage quota");
    this.name = "ArenaGrowthQuotaError";
    this.cause = cause;
  }
}
function isQuotaExceeded(cause) {
  return typeof cause === "object" && cause !== null && "name" in cause && cause.name === "QuotaExceededError";
}
function mergeExtentRuns(left, right) {
  const merged = left.map((run) => ({ ...run }));
  for (const run of right) {
    const last = merged.at(-1);
    if (last !== undefined && last.start + BigInt(last.count) === run.start && last.count + run.count <= 4294967295) {
      last.count += run.count;
    } else {
      merged.push({ ...run });
    }
  }
  return merged;
}

class RepackedVfs {
  #store;
  #status = "open";
  #failure;
  #descriptors = new Map;
  #nextDescriptor = 3;
  #pendingResizeCommit;
  #arenaSize;
  #arenaDirty;
  #arenaDirtyBytesSinceFlush = 0;
  #metadataDirtySinceFlush;
  #repacking = false;
  #lastRepackReason = null;
  #lastRepackDurationMs = null;
  #pendingRepackReason = null;
  #repackCount = 0;
  #lastRepackAtMs = Date.now();
  #flushes = { amortized: 0, arena: 0, metadata: 0, zeroBarrier: 0, manifest: 0 };
  constructor(store) {
    this.#store = store;
    this.#arenaSize = store.arenaSize;
    this.#arenaDirty = store.arenaDirty;
    this.#metadataDirtySinceFlush = store.activeMetadataDirty;
  }
  static async open(port, options = {}) {
    return new RepackedVfs(await openMetadataStore(port, options));
  }
  strictSync() {
    this.#assertOpen();
    try {
      if (this.#arenaDirty)
        this.#flush(this.#store.handles["arena.bin"], "sync.arena.flush", "arena");
      this.#materializePendingResize();
      if (this.#metadataDirtySinceFlush) {
        const activeName = metadataFileName(this.#store.state.activeMetadataFile);
        this.#flush(this.#store.handles[activeName], "sync.metadata.flush", "metadata");
      }
      this.#arenaDirty = false;
      this.#arenaDirtyBytesSinceFlush = 0;
      this.#metadataDirtySinceFlush = false;
    } catch (cause) {
      this.#poison(cause);
      throw cause;
    }
  }
  assertHealthy() {
    this.#assertOpen();
  }
  fail(cause) {
    this.#assertOpen();
    this.#poison(cause);
    throw cause;
  }
  cleanupFailedInit() {
    if (this.#status === "closed")
      return;
    this.#status = "closed";
    this.#descriptors.clear();
    const closeError = this.#closeHandles();
    if (closeError !== undefined)
      throw closeError;
  }
  metrics() {
    this.#assertOpen();
    return {
      generation: this.#store.state.generation,
      totalExtents: this.#store.state.allocator.totalExtents,
      availableExtents: this.#store.state.allocator.available.size,
      quarantineExtents: this.#store.state.allocator.quarantine.size,
      quarantineBytes: BigInt(this.#store.state.allocator.quarantine.size) * BigInt(this.#store.state.extentSize),
      activeLogBytes: this.#store.activeLogBytes,
      activeLogFrames: this.#store.activeLogFrames,
      lastRepackReason: this.#lastRepackReason,
      lastRepackDurationMs: this.#lastRepackDurationMs,
      repackCount: this.#repackCount,
      pendingRepackReason: this.#pendingRepackReason,
      flushes: { ...this.#flushes }
    };
  }
  repack(reason = "manual") {
    this.#assertOpen();
    if (this.#repacking)
      throw new Error("OPFS repacked VFS repack is already running");
    checkedAdd(this.#store.state.generation, 1n, "generation");
    const activationSequence = checkedAdd(this.#store.activationSequence, 1n, "activation sequence");
    this.#repacking = true;
    const startedAt = performance.now();
    try {
      this.#materializePendingResize();
      const pinned = new Set;
      for (const descriptor of this.#descriptors.values()) {
        if (descriptor.orphan === undefined)
          continue;
        for (const extentId of descriptor.orphan.extents)
          pinned.add(extentId);
      }
      const projected = projectRepackForActivation(this.#store.state, pinned);
      const base = encodeValidatedMetadataBase(projected);
      const activation = encodeActivationSlot({
        sequence: activationSequence,
        metadataFile: projected.activeMetadataFile,
        generation: projected.generation,
        baseEnd: BigInt(base.byteLength),
        baseDigest: metadataBaseDigest(base)
      });
      this.#flush(this.#store.handles["arena.bin"], "repack.arena.flush", "arena");
      this.#arenaDirty = false;
      this.#arenaDirtyBytesSinceFlush = 0;
      const inactiveName = metadataFileName(projected.activeMetadataFile);
      const inactive = this.#store.handles[inactiveName];
      inactive.truncate(0, "repack.metadata.reset");
      writeExact(inactive, 0n, base, "repack.metadata.write");
      this.#flush(inactive, "repack.metadata.flush", "metadata");
      const activationOffset = (activationSequence - 1n) % 2n * BigInt(ACTIVATION_SLOT_BYTES);
      try {
        writeExact(this.#store.handles["activation.bin"], activationOffset, activation, "repack.activation.write");
        this.#flush(this.#store.handles["activation.bin"], "repack.activation.flush", "manifest");
      } catch (cause) {
        this.#poison(cause);
        throw cause;
      }
      try {
        this.#store.state = projected;
        this.#store.activeLogEnd = BigInt(base.byteLength);
        this.#store.nextSequence = 1n;
        this.#store.activeLogBytes = 0;
        this.#store.activeLogFrames = 0;
        this.#store.activationSequence = activationSequence;
        this.#metadataDirtySinceFlush = false;
        this.#lastRepackReason = reason;
        this.#pendingRepackReason = null;
        this.#repackCount += 1;
        this.#lastRepackAtMs = Date.now();
        this.#scheduleRepack();
      } catch (cause) {
        this.#poison(cause);
        throw cause;
      }
      const requiredArenaEnd = checkedAdd(BigInt(ARENA_HEADER_BYTES), checkedMultiply(projected.allocator.totalExtents, BigInt(projected.extentSize), "arena byte length"), "arena byte length");
      try {
        if (BigInt(this.#arenaSizeChecked("repack.arena.size-before-trim")) > requiredArenaEnd) {
          this.#arenaDirty = true;
          this.#truncateArena(requiredArenaEnd, "repack.arena.trim");
        }
      } catch {}
      this.#lastRepackDurationMs = performance.now() - startedAt;
    } finally {
      this.#repacking = false;
    }
  }
  runScheduledRepack(nowMs = Date.now()) {
    this.#assertOpen();
    if (!Number.isSafeInteger(nowMs) || nowMs < 0)
      throw new TypeError("repack scheduler time is invalid");
    this.#materializePendingResize();
    if (this.#arenaDirtyBytesSinceFlush >= AMORTIZED_ARENA_FLUSH_BYTES) {
      try {
        this.#flush(this.#store.handles["arena.bin"], "sync.arena.amortized.flush", "amortized");
        this.#arenaDirty = false;
        this.#arenaDirtyBytesSinceFlush = 0;
      } catch (cause) {
        this.#poison(cause);
        throw cause;
      }
    }
    const reason = this.#dueRepackReason(nowMs);
    if (reason === null)
      return false;
    this.repack(reason);
    this.#lastRepackAtMs = nowMs;
    return true;
  }
  resolvePath(path, follow = true) {
    this.#assertOpen();
    return this.#resolve(path, follow);
  }
  stat(requestPath) {
    this.#assertOpen();
    return this.#statValue(getInodeAtPath(this.#store.state, this.#resolve(requestPath, true)));
  }
  lstat(requestPath) {
    this.#assertOpen();
    return this.#statValue(getInodeAtPath(this.#store.state, this.#resolve(requestPath, false)));
  }
  symlink(target, requestPath, nowMs) {
    this.#assertOpen();
    const path = this.#resolve(requestPath, false);
    this.#commit(planSymlink(this.#store.state, path, target, { nowMs }).record);
  }
  readlink(requestPath) {
    this.#assertOpen();
    const path = this.#resolve(requestPath, false);
    const inode = getInodeAtPath(this.#store.state, path);
    if (inode.kind !== "symlink")
      throw new FsError("EINVAL", "path is not a symbolic link", { path });
    return inode.target;
  }
  readdir(requestPath) {
    this.#assertOpen();
    const path = this.#resolve(requestPath, true);
    const inode = getInodeAtPath(this.#store.state, path);
    if (inode.kind !== "directory")
      throw new FsError("ENOTDIR", "path is not a directory", { path });
    return [...inode.children.keys()].sort();
  }
  mkdir(requestPath, options) {
    this.#assertOpen();
    this.#commit(planMkdir(this.#store.state, this.#resolve(requestPath, false), options).record);
  }
  writeFile(requestPath, data, options) {
    this.#assertOpen();
    const path = this.#resolve(requestPath, true);
    const flags = this.#parseFlags(options.flag ?? "w");
    if (!flags.writable)
      throw new FsError("EBADF", "writeFile flags are not writable", { operation: "writeFile", path });
    let bytes;
    if (typeof data === "string") {
      this.#validateEncoding(options.encoding ?? "utf8", path);
      bytes = new TextEncoder().encode(data);
    } else {
      bytes = data;
    }
    checkedU64(options.nowMs, "timestamp");
    let existing;
    try {
      const inode = getInodeAtPath(this.#store.state, path);
      if (inode.kind !== "file")
        throw new FsError("EISDIR", "path is a directory", { path });
      existing = inode;
    } catch (cause) {
      if (!(cause instanceof FsError) || cause.code !== FS_ERRNO.ENOENT)
        throw cause;
    }
    if (existing !== undefined && flags.create && flags.exclusive) {
      throw new FsError("EEXIST", "path already exists", { operation: "writeFile", path });
    }
    if (existing === undefined && !flags.create) {
      throw new FsError("ENOENT", "path does not exist", { operation: "writeFile", path });
    }
    const wasExisting = existing !== undefined;
    if (bytes.byteLength === 0 && existing !== undefined && !flags.truncate)
      return;
    const buildPlan = () => {
      let current;
      if (wasExisting) {
        const inode = getInodeAtPath(this.#store.state, path);
        if (inode.kind !== "file")
          throw new FsError("EISDIR", "path is a directory", { path });
        current = inode;
      }
      const currentStart = current !== undefined && flags.append ? current.size : 0n;
      const targetSize = current === undefined ? BigInt(bytes.byteLength) : flags.append ? checkedAdd(current.size, BigInt(bytes.byteLength), "writeFile size") : flags.truncate ? BigInt(bytes.byteLength) : current.size > BigInt(bytes.byteLength) ? current.size : BigInt(bytes.byteLength);
      const currentPlan = current === undefined ? planCreateFile(this.#store.state, path, {
        ...options.mode === undefined ? {} : { mode: options.mode },
        nowMs: options.nowMs,
        size: targetSize
      }) : planResizeFile(this.#store.state, path, targetSize, options.nowMs, "write");
      return {
        existing: current,
        start: currentStart,
        plan: currentPlan,
        preparedCommit: this.#preflightCommit(currentPlan.record),
        allocated: expandExtentRuns(currentPlan.record.kind === "createFile" ? currentPlan.record.extents : currentPlan.record.allocated, MAX_EXTENTS_PER_INODE)
      };
    };
    const prepared = this.#prepareAllocationWithQuotaRetry(buildPlan(), buildPlan);
    existing = prepared.existing;
    const { start, plan, preparedCommit, allocated } = prepared;
    if (bytes.byteLength === 0) {
      this.#commit(plan.record, preparedCommit);
      return;
    }
    const progress = this.#writeLogical(existing?.extents ?? [], start, bytes, "arena.write-file", allocated);
    if (progress.bytes === 0)
      this.#failStore(progress.error);
    const partialSize = existing !== undefined && !flags.truncate ? existing.size > checkedAdd(start, BigInt(progress.bytes), "partial writeFile size") ? existing.size : checkedAdd(start, BigInt(progress.bytes), "partial writeFile size") : BigInt(progress.bytes);
    const committedPlan = progress.bytes === bytes.byteLength ? plan : existing === undefined ? planCreateFile(this.#store.state, path, {
      ...options.mode === undefined ? {} : { mode: options.mode },
      nowMs: options.nowMs,
      size: partialSize
    }) : planResizeFile(this.#store.state, path, partialSize, options.nowMs, "write");
    if (progress.error === undefined || partialSize !== existing?.size) {
      this.#commit(committedPlan.record, committedPlan === plan ? preparedCommit : undefined);
    }
    if (progress.error !== undefined)
      throw progress.error;
  }
  readFile(requestPath) {
    this.#assertOpen();
    const path = this.#resolve(requestPath, true);
    const inode = getInodeAtPath(this.#store.state, path);
    if (inode.kind !== "file")
      throw new FsError("EISDIR", "path is a directory", { path });
    const output = new Uint8Array(checkedSafeNumber(inode.size, "file read size"));
    this.#readLogical(inode.extents, 0n, output);
    return output;
  }
  truncate(requestPath, size, nowMs) {
    this.#assertOpen();
    const path = this.#resolve(requestPath, true);
    let inode = getInodeAtPath(this.#store.state, path);
    if (inode.kind !== "file")
      throw new FsError("EISDIR", "path is a directory", { path });
    if (size === inode.size)
      return;
    let plan = planResizeFile(this.#store.state, path, size, nowMs, "truncate");
    let preparedCommit = this.#preflightCommit(plan.record);
    if (size > inode.size) {
      const buildPlan = () => {
        const current = getInodeAtPath(this.#store.state, path);
        if (current.kind !== "file")
          throw new FsError("EISDIR", "path is a directory", { path });
        const currentPlan = planResizeFile(this.#store.state, path, size, nowMs, "truncate");
        return {
          inode: current,
          plan: currentPlan,
          preparedCommit: this.#preflightCommit(currentPlan.record),
          allocated: expandExtentRuns(currentPlan.record.allocated, MAX_EXTENTS_PER_INODE),
          arenaSizeBefore: this.#arenaSizeChecked("arena.size.before-extension")
        };
      };
      const prepared = this.#prepareAllocationWithQuotaRetry({
        inode,
        plan,
        preparedCommit,
        allocated: expandExtentRuns(plan.record.allocated, MAX_EXTENTS_PER_INODE),
        arenaSizeBefore: this.#arenaSizeChecked("arena.size.before-extension")
      }, buildPlan);
      inode = prepared.inode;
      plan = prepared.plan;
      preparedCommit = prepared.preparedCommit;
      const touchedExisting = this.#zeroLogical(inode.extents, inode.size, size - inode.size, prepared.arenaSizeBefore, prepared.allocated);
      if (touchedExisting)
        this.#flushPreparedArena("arena.gap-zero.flush");
    }
    this.#commit(plan.record, preparedCommit);
  }
  open(requestPath, flags = "r", mode = 33206, nowMs = 0n) {
    this.#assertOpen();
    const path = this.#resolve(requestPath, true);
    const parsed = this.#parseFlags(flags);
    let inode;
    try {
      const found = getInodeAtPath(this.#store.state, path);
      if (found.kind !== "file")
        throw new FsError("EISDIR", "path is a directory", { path });
      if (parsed.exclusive && parsed.create)
        throw new FsError("EEXIST", "path already exists", { path });
      inode = found;
      if (parsed.truncate) {
        this.truncate(path, 0n, nowMs);
        inode = getInodeAtPath(this.#store.state, path);
      }
    } catch (cause) {
      if (!(cause instanceof FsError) || cause.code !== FS_ERRNO.ENOENT || !parsed.create)
        throw cause;
      this.#commit(planCreateFile(this.#store.state, path, { mode, nowMs, size: 0n }).record);
      inode = getInodeAtPath(this.#store.state, path);
    }
    const fd = this.#nextDescriptor++;
    this.#descriptors.set(fd, {
      inodeId: inode.id,
      offset: parsed.append ? inode.size : 0n,
      readable: parsed.readable,
      writable: parsed.writable,
      append: parsed.append
    });
    return fd;
  }
  fstat(fd) {
    this.#assertOpen();
    const descriptor = this.#descriptor(fd);
    const inode = descriptor.orphan ?? this.#linkedFile(descriptor.inodeId);
    return this.#statValue(inode);
  }
  read(fd, buffer, offset, length, position) {
    this.#assertOpen();
    this.#validateBufferRange(buffer, offset, length);
    const descriptor = this.#descriptor(fd);
    if (!descriptor.readable)
      throw new FsError("EBADF", "descriptor is not readable");
    const inode = descriptor.orphan ?? this.#linkedFile(descriptor.inodeId);
    const start = position ?? descriptor.offset;
    if (start < 0n)
      throw new FsError("EINVAL", "read position is negative");
    const available = start >= inode.size ? 0 : Math.min(length, checkedSafeNumber(inode.size - start, "read length"));
    if (available > 0)
      this.#readLogical(inode.extents, start, buffer.subarray(offset, offset + available));
    if (position === undefined)
      descriptor.offset = start + BigInt(available);
    return available;
  }
  write(fd, buffer, offset, length, position, nowMs) {
    this.#assertOpen();
    this.#validateBufferRange(buffer, offset, length);
    checkedU64(nowMs, "timestamp");
    const descriptor = this.#descriptor(fd);
    if (!descriptor.writable)
      throw new FsError("EBADF", "descriptor is not writable");
    if (descriptor.orphan !== undefined) {
      return this.#writeOrphan(descriptor, buffer.subarray(offset, offset + length), position, nowMs);
    }
    let inode = this.#linkedFile(descriptor.inodeId);
    const start = descriptor.append ? inode.size : position ?? descriptor.offset;
    if (start < 0n)
      throw new FsError("EINVAL", "write position is negative");
    if (length === 0)
      return 0;
    const requestedEnd = checkedAdd(start, BigInt(length), "write end");
    let admittedLength = length;
    let allocated = [];
    let plan;
    let preparedCommit;
    if (requestedEnd > inode.size) {
      const buildPlan = () => {
        const current = this.#linkedFile(descriptor.inodeId);
        const admitted = this.#planLinkedWrite(current, start, length, nowMs);
        return {
          inode: current,
          admitted,
          allocated: admitted.plan === undefined ? [] : expandExtentRuns(admitted.plan.record.allocated, MAX_EXTENTS_PER_INODE),
          arenaSizeBefore: start > current.size ? this.#arenaSizeChecked("arena.size.before-write-extension") : 0
        };
      };
      const prepared = this.#prepareAllocationWithQuotaRetry(buildPlan(), buildPlan);
      inode = prepared.inode;
      plan = prepared.admitted.plan;
      preparedCommit = prepared.admitted.preparedCommit;
      admittedLength = prepared.admitted.length;
      if (plan !== undefined) {
        allocated = prepared.allocated;
        if (start > inode.size) {
          const touchedExisting = this.#zeroLogical(inode.extents, inode.size, start - inode.size, prepared.arenaSizeBefore, allocated);
          if (touchedExisting)
            this.#flushPreparedArena("arena.gap-zero.flush");
        }
      }
    }
    const source = buffer.subarray(offset, offset + admittedLength);
    const progress = this.#writeLogical(inode.extents, start, source, "arena.write", allocated);
    if (progress.bytes === 0)
      this.#failStore(progress.error);
    const completedEnd = checkedAdd(start, BigInt(progress.bytes), "completed write end");
    if (completedEnd > inode.size) {
      const committedPlan = plan !== undefined && completedEnd === plan.record.size ? plan : planResizeFileForInode(this.#store.state, inode, completedEnd, nowMs, "write");
      this.#commit(committedPlan.record, committedPlan === plan ? preparedCommit : undefined);
    }
    if (position === undefined)
      descriptor.offset = completedEnd;
    return progress.bytes;
  }
  chmod(requestPath, mode, nowMs) {
    this.#assertOpen();
    this.#commit(planChmod(this.#store.state, this.#resolve(requestPath, true), mode, nowMs).record);
  }
  utimes(requestPath, atimeMs, mtimeMs, ctimeMs) {
    this.#assertOpen();
    const path = this.#resolve(requestPath, true);
    this.#commit(planUtimes(this.#store.state, path, atimeMs, mtimeMs, ctimeMs).record);
  }
  unlink(requestPath, nowMs) {
    this.#assertOpen();
    const path = this.#resolve(requestPath, false);
    const inode = getInodeAtPath(this.#store.state, path);
    if (inode.kind === "directory")
      throw new FsError("EISDIR", "path is a directory", { path });
    const affected = inode.kind === "file" ? [...this.#descriptors.values()].filter((descriptor) => descriptor.orphan === undefined && descriptor.inodeId === inode.id) : [];
    const orphan = inode.kind === "file" && affected.length > 0 ? makeOrphanRecord(inode) : undefined;
    this.#commit(planUnlink(this.#store.state, path, nowMs).record);
    if (orphan !== undefined)
      for (const descriptor of affected)
        descriptor.orphan = orphan;
  }
  rmdir(requestPath, nowMs) {
    this.#assertOpen();
    this.#commit(planRmdir(this.#store.state, this.#resolve(requestPath, false), nowMs).record);
  }
  rename(oldRequestPath, newRequestPath, nowMs) {
    this.#assertOpen();
    const oldPath = this.#resolve(oldRequestPath, false);
    const newPath = this.#resolve(newRequestPath, false);
    let destination;
    try {
      const inode = getInodeAtPath(this.#store.state, newPath);
      if (inode.kind === "file")
        destination = inode;
    } catch (cause) {
      if (!(cause instanceof FsError) || cause.code !== FS_ERRNO.ENOENT)
        throw cause;
    }
    const affected = destination === undefined ? [] : [...this.#descriptors.values()].filter((descriptor) => descriptor.orphan === undefined && descriptor.inodeId === destination.id);
    const orphan = destination !== undefined && affected.length > 0 ? makeOrphanRecord(destination) : undefined;
    this.#commit(planRename(this.#store.state, oldPath, newPath, nowMs).record);
    if (orphan !== undefined)
      for (const descriptor of affected)
        descriptor.orphan = orphan;
  }
  close(fd) {
    if (fd !== undefined) {
      this.#assertOpen();
      if (!this.#descriptors.delete(fd))
        throw new FsError("EBADF", "descriptor is invalid");
      return;
    }
    if (this.#status === "closed")
      return;
    let firstError;
    if (this.#status === "open") {
      try {
        this.strictSync();
      } catch (cause) {
        firstError = cause;
      }
    } else {
      firstError = new StoreFailedError(this.#failure);
    }
    this.#status = "closed";
    this.#descriptors.clear();
    const closeError = this.#closeHandles();
    firstError ??= closeError;
    if (firstError !== undefined)
      throw firstError;
  }
  #closeHandles() {
    let firstError;
    for (const name of ["metadata-b.bin", "metadata-a.bin", "arena.bin", "activation.bin"]) {
      try {
        this.#store.handles[name].close();
      } catch (cause) {
        firstError ??= cause;
      }
    }
    return firstError;
  }
  #prepareAllocated(extents) {
    if (extents.length === 0)
      return;
    const totalBefore = this.#store.state.allocator.totalExtents;
    const highWaterBefore = this.#store.arenaHighWaterExtents;
    const fresh = extents.filter((extentId) => extentId >= totalBefore);
    const arenaSizeBefore = this.#arenaSizeChecked("arena.size.before-allocation");
    if (fresh.length > 0) {
      const last = fresh[fresh.length - 1];
      const requiredExtents = checkedAdd(last, 1n, "arena extent count");
      const requiredEnd = checkedAdd(BigInt(ARENA_HEADER_BYTES), checkedMultiply(requiredExtents, BigInt(this.#store.state.extentSize), "arena byte length"), "arena byte length");
      if (requiredEnd > BigInt(arenaSizeBefore)) {
        this.#arenaDirty = true;
        if (requiredExtents > this.#store.arenaHighWaterExtents) {
          this.#store.arenaHighWaterExtents = requiredExtents;
        }
        try {
          this.#truncateArena(requiredEnd, "arena.grow");
        } catch (cause) {
          if (isQuotaExceeded(cause))
            throw new ArenaGrowthQuotaError(cause);
          throw cause;
        }
      }
    }
    const reused = extents.filter((extentId) => extentId < totalBefore || extentId < highWaterBefore);
    if (reused.length === 0)
      return;
    const zeros = new Uint8Array(Math.min(this.#store.state.extentSize, 64 * 1024));
    for (const extentId of reused) {
      let within = 0;
      while (within < this.#store.state.extentSize) {
        const count = Math.min(zeros.byteLength, this.#store.state.extentSize - within);
        this.#arenaDirty = true;
        this.#writeArenaExact(arenaByteOffset(extentId, this.#store.state.extentSize, within), zeros.subarray(0, count), "arena.allocation.zero");
        this.#recordArenaWrite(count);
        within += count;
      }
    }
    this.#flushPreparedArena("arena.allocation.flush");
  }
  #readLogical(extents, position, target) {
    checkedU64(position, "read position");
    let completed = 0;
    while (completed < target.byteLength) {
      const logical = checkedAdd(position, BigInt(completed), "read position");
      const extentIndex = checkedSafeNumber(logical / BigInt(this.#store.state.extentSize), "extent index");
      const extentId = this.#extentAt(extents, [], extentIndex);
      if (extentId === undefined)
        throw new CorruptStoreError("file metadata does not cover its visible data");
      const within = Number(logical % BigInt(this.#store.state.extentSize));
      const count = Math.min(target.byteLength - completed, this.#store.state.extentSize - within);
      let extentCompleted = 0;
      while (extentCompleted < count) {
        const read = this.#store.handles["arena.bin"].read(target.subarray(completed + extentCompleted, completed + count), checkedSafeNumber(arenaByteOffset(extentId, this.#store.state.extentSize, within + extentCompleted), "arena read offset"), "arena.read");
        if (!Number.isSafeInteger(read) || read <= 0 || read > count - extentCompleted) {
          throw new CorruptStoreError("arena data ended before the visible file range");
        }
        extentCompleted += read;
      }
      completed += count;
    }
  }
  #writeLogical(extents, position, source, label, allocated = []) {
    checkedU64(position, "write position");
    let completed = 0;
    while (completed < source.byteLength) {
      const logical = checkedAdd(position, BigInt(completed), "write position");
      const extentIndex = checkedSafeNumber(logical / BigInt(this.#store.state.extentSize), "extent index");
      const extentId = this.#extentAt(extents, allocated, extentIndex);
      if (extentId === undefined)
        throw new StoreLimitError("planned extents do not cover the write range");
      const within = Number(logical % BigInt(this.#store.state.extentSize));
      const requested = Math.min(source.byteLength - completed, this.#store.state.extentSize - within);
      try {
        this.#arenaDirty = true;
        const written = this.#writeArena(source.subarray(completed, completed + requested), checkedSafeNumber(arenaByteOffset(extentId, this.#store.state.extentSize, within), "arena write offset"), label);
        if (!Number.isSafeInteger(written) || written <= 0 || written > requested) {
          throw new PortWriteError(label);
        }
        this.#recordArenaWrite(written);
        completed += written;
      } catch (error) {
        return { bytes: completed, error };
      }
    }
    return { bytes: completed };
  }
  #zeroLogical(extents, position, length, arenaSizeBefore, allocated = []) {
    checkedU64(position, "zero position");
    checkedU64(length, "zero length");
    const zeros = new Uint8Array(64 * 1024);
    const previousEnd = BigInt(arenaSizeBefore);
    let completed = 0n;
    let touchedExisting = false;
    while (completed < length) {
      const logical = checkedAdd(position, completed, "zero position");
      const extentIndex = checkedSafeNumber(logical / BigInt(this.#store.state.extentSize), "extent index");
      const extentId = this.#extentAt(extents, allocated, extentIndex);
      if (extentId === undefined)
        throw new StoreLimitError("planned extents do not cover the zero range");
      const within = Number(logical % BigInt(this.#store.state.extentSize));
      const remainingInExtent = this.#store.state.extentSize - within;
      const count = Math.min(zeros.byteLength, remainingInExtent, checkedSafeNumber(length - completed, "remaining zero length"));
      const physical = arenaByteOffset(extentId, this.#store.state.extentSize, within);
      if (physical < previousEnd) {
        const existingCount = Math.min(count, checkedSafeNumber(previousEnd - physical, "existing zero length"));
        this.#arenaDirty = true;
        this.#writeArenaExact(physical, zeros.subarray(0, existingCount), "arena.gap-zero.write");
        this.#recordArenaWrite(existingCount);
        touchedExisting = true;
      }
      completed += BigInt(count);
    }
    return touchedExisting;
  }
  #extentAt(head, tail, index) {
    return index < head.length ? head[index] : tail[index - head.length];
  }
  #planLinkedWrite(inode, start, requestedLength, nowMs) {
    const attempt = (length) => {
      const end = checkedAdd(start, BigInt(length), "write end");
      if (end <= inode.size)
        return;
      const plan = planResizeFileForInode(this.#store.state, inode, end, nowMs, "write");
      return { plan, preparedCommit: this.#preflightCommit(plan.record) };
    };
    try {
      const admitted = attempt(requestedLength);
      return {
        length: requestedLength,
        plan: admitted?.plan,
        preparedCommit: admitted?.preparedCommit
      };
    } catch (cause) {
      if (!(cause instanceof StoreLimitError))
        throw cause;
      let low = 0;
      let high = requestedLength - 1;
      let admitted = 0;
      let admittedPlan;
      let admittedCommit;
      while (low <= high) {
        const candidate = low + Math.floor((high - low) / 2);
        try {
          const candidatePlan = attempt(candidate);
          admitted = candidate;
          admittedPlan = candidatePlan?.plan;
          admittedCommit = candidatePlan?.preparedCommit;
          low = candidate + 1;
        } catch (candidateCause) {
          if (!(candidateCause instanceof StoreLimitError))
            throw candidateCause;
          high = candidate - 1;
        }
      }
      if (admitted === 0)
        throw cause;
      return { length: admitted, plan: admittedPlan, preparedCommit: admittedCommit };
    }
  }
  #writeOrphan(descriptor, source, position, nowMs) {
    const orphan = descriptor.orphan;
    const start = descriptor.append ? orphan.size : position ?? descriptor.offset;
    if (start < 0n)
      throw new FsError("EINVAL", "write position is negative");
    if (source.byteLength === 0)
      return 0;
    const buildPlan = () => {
      const admitted = this.#planOrphanWrite(orphan, start, source.byteLength);
      return {
        admitted,
        allocated: admitted.reservation === undefined ? [] : expandExtentRuns(admitted.reservation.record.extents, MAX_EXTENTS_PER_INODE),
        arenaSizeBefore: this.#arenaSizeChecked("arena.size.before-orphan-extension")
      };
    };
    const prepared = this.#prepareAllocationWithQuotaRetry(buildPlan(), buildPlan);
    const { admitted, allocated, arenaSizeBefore } = prepared;
    if (admitted.reservation !== undefined) {
      this.#commit(admitted.reservation.record);
      orphan.extents.push(...allocated);
    }
    if (start > orphan.size) {
      const touchedExisting = this.#zeroLogical(orphan.extents, orphan.size, start - orphan.size, arenaSizeBefore);
      if (touchedExisting)
        this.#flushPreparedArena("arena.gap-zero.flush");
    }
    const progress = this.#writeLogical(orphan.extents, start, source.subarray(0, admitted.length), "arena.write");
    if (progress.bytes === 0)
      this.#failStore(progress.error);
    const completedEnd = checkedAdd(start, BigInt(progress.bytes), "completed orphan write end");
    if (completedEnd > orphan.size)
      orphan.size = completedEnd;
    orphan.mtimeMs = nowMs;
    orphan.ctimeMs = nowMs;
    if (position === undefined)
      descriptor.offset = completedEnd;
    return progress.bytes;
  }
  #planOrphanWrite(orphan, start, requestedLength) {
    const attempt = (length) => {
      const end = checkedAdd(start, BigInt(length), "orphan write end");
      const required = this.#extentCount(end);
      const additional = Math.max(0, required - orphan.extents.length);
      if (additional === 0)
        return;
      const reservation = planReserveQuarantine(this.#store.state, additional);
      this.#preflightCommit(reservation.record);
      return reservation;
    };
    try {
      return { length: requestedLength, reservation: attempt(requestedLength) };
    } catch (cause) {
      if (!(cause instanceof StoreLimitError))
        throw cause;
      let low = 0;
      let high = requestedLength - 1;
      let admitted = 0;
      let reservation;
      while (low <= high) {
        const candidate = low + Math.floor((high - low) / 2);
        try {
          const candidateReservation = attempt(candidate);
          admitted = candidate;
          reservation = candidateReservation;
          low = candidate + 1;
        } catch (candidateCause) {
          if (!(candidateCause instanceof StoreLimitError))
            throw candidateCause;
          high = candidate - 1;
        }
      }
      if (admitted === 0)
        throw cause;
      return { length: admitted, reservation };
    }
  }
  #extentCount(size) {
    checkedU64(size, "file size");
    if (size === 0n)
      return 0;
    const count = (size + BigInt(this.#store.state.extentSize) - 1n) / BigInt(this.#store.state.extentSize);
    const result = checkedSafeNumber(count, "file extent count");
    if (result > MAX_EXTENTS_PER_INODE) {
      throw new StoreLimitError(`file extent count exceeds ${MAX_EXTENTS_PER_INODE}`);
    }
    return result;
  }
  #parseFlags(flags) {
    const parsed = {
      r: { readable: true, writable: false, create: false, exclusive: false, truncate: false, append: false },
      "r+": { readable: true, writable: true, create: false, exclusive: false, truncate: false, append: false },
      w: { readable: false, writable: true, create: true, exclusive: false, truncate: true, append: false },
      "w+": { readable: true, writable: true, create: true, exclusive: false, truncate: true, append: false },
      wx: { readable: false, writable: true, create: true, exclusive: true, truncate: true, append: false },
      "wx+": { readable: true, writable: true, create: true, exclusive: true, truncate: true, append: false },
      a: { readable: false, writable: true, create: true, exclusive: false, truncate: false, append: true },
      "a+": { readable: true, writable: true, create: true, exclusive: false, truncate: false, append: true },
      ax: { readable: false, writable: true, create: true, exclusive: true, truncate: false, append: true },
      "ax+": { readable: true, writable: true, create: true, exclusive: true, truncate: false, append: true }
    };
    const result = parsed[flags];
    if (result === undefined)
      throw new FsError("EINVAL", `unsupported open flags: ${flags}`);
    return result;
  }
  #validateEncoding(encoding, path) {
    if (encoding !== "utf8" && encoding !== "utf-8") {
      throw new FsError("EINVAL", `unsupported writeFile encoding: ${encoding}`, { operation: "writeFile", path });
    }
    return "utf8";
  }
  #flushPreparedArena(label) {
    this.#flush(this.#store.handles["arena.bin"], label, "zeroBarrier");
    this.#arenaDirty = false;
    this.#arenaDirtyBytesSinceFlush = 0;
  }
  #recordArenaWrite(bytes) {
    if (!Number.isSafeInteger(bytes) || bytes < 0)
      throw new TypeError("arena dirty byte count is invalid");
    this.#arenaDirtyBytesSinceFlush = Math.min(Number.MAX_SAFE_INTEGER, this.#arenaDirtyBytesSinceFlush + bytes);
  }
  #arenaSizeChecked(label) {
    if (this.#arenaSize !== undefined)
      return this.#arenaSize;
    const size = this.#store.handles["arena.bin"].getSize(label);
    if (!Number.isSafeInteger(size) || size < 0)
      throw new Error(`${label} returned an invalid arena size`);
    this.#arenaSize = size;
    return size;
  }
  #writeArena(source, at, label) {
    const sizeBefore = this.#arenaSize;
    this.#arenaSize = undefined;
    const written = this.#store.handles["arena.bin"].write(source, at, label);
    if (sizeBefore !== undefined && Number.isSafeInteger(written) && written >= 0 && written <= source.byteLength) {
      const end = at + written;
      if (!Number.isSafeInteger(end))
        return written;
      this.#arenaSize = Math.max(sizeBefore, end);
    }
    return written;
  }
  #writeArenaExact(at, source, label) {
    const sizeBefore = this.#arenaSize;
    this.#arenaSize = undefined;
    writeExact(this.#store.handles["arena.bin"], at, source, label);
    if (sizeBefore !== undefined) {
      this.#arenaSize = Math.max(sizeBefore, checkedSafeNumber(checkedAdd(at, BigInt(source.byteLength), "arena write end"), "arena write end"));
    }
  }
  #truncateArena(size, label) {
    this.#arenaSize = undefined;
    truncateChecked(this.#store.handles["arena.bin"], size, label);
    this.#arenaSize = checkedSafeNumber(size, "arena truncate size");
  }
  #flush(handle, label, kind) {
    this.#flushes[kind] += 1;
    handle.flush(label);
  }
  #prepareAllocationWithQuotaRetry(initial, retry) {
    try {
      this.#prepareAllocated(initial.allocated);
      return initial;
    } catch (cause) {
      if (!(cause instanceof ArenaGrowthQuotaError))
        throw cause;
      this.repack("quota");
      this.repack("quota");
      const retried = retry();
      try {
        this.#prepareAllocated(retried.allocated);
      } catch (retryCause) {
        if (retryCause instanceof ArenaGrowthQuotaError)
          throw retryCause.cause;
        throw retryCause;
      }
      return retried;
    }
  }
  #descriptor(fd) {
    if (!Number.isSafeInteger(fd))
      throw new FsError("EBADF", "descriptor is invalid");
    const descriptor = this.#descriptors.get(fd);
    if (descriptor === undefined)
      throw new FsError("EBADF", "descriptor is invalid");
    return descriptor;
  }
  #resolve(path, follow) {
    return resolveLinks(this.#store.state, path, follow);
  }
  #linkedFile(inodeId) {
    const inode = this.#store.state.inodes.get(inodeId);
    if (inode?.kind !== "file")
      throw new FsError("EBADF", "descriptor no longer references a file");
    return inode;
  }
  #statValue(inode) {
    const kind = "kind" in inode ? inode.kind : "file";
    return {
      kind,
      mode: inode.mode,
      size: kind === "file" ? inode.size : kind === "symlink" ? BigInt(encodedUtf8Length(inode.target)) : 0n,
      atimeMs: inode.atimeMs,
      mtimeMs: inode.mtimeMs,
      ctimeMs: inode.ctimeMs
    };
  }
  #validateBufferRange(buffer, offset, length) {
    if (!Number.isSafeInteger(offset) || !Number.isSafeInteger(length) || offset < 0 || length < 0 || offset + length > buffer.byteLength) {
      throw new FsError("EINVAL", "buffer range is invalid");
    }
  }
  #preflightCommit(record) {
    this.#assertOpen();
    const projection = prepareTxnProjection(this.#store.state, record);
    const deferResize = this.#isDeferrableResize(record);
    const pending = this.#pendingResizeCommit;
    const replacesPendingResize = deferResize && pending !== undefined && record.kind === "resizeFile" && pending.record.inodeId === record.inodeId;
    const materializedRecord = replacesPendingResize ? {
      ...record,
      allocated: mergeExtentRuns(pending.record.allocated, record.allocated)
    } : record;
    const sequence = replacesPendingResize ? pending.sequence : this.#store.nextSequence;
    const frameBytes = txnFrameBytes(materializedRecord);
    const frame = deferResize ? undefined : encodeTxnFrame({
      generation: this.#store.state.generation,
      sequence,
      record: materializedRecord
    });
    const projectedLogBytes = replacesPendingResize ? this.#store.activeLogBytes - pending.frameBytes + frameBytes : this.#store.activeLogBytes + frameBytes;
    if (!replacesPendingResize && this.#store.activeLogFrames >= MAX_ACTIVE_LOG_FRAMES || projectedLogBytes > MAX_ACTIVE_LOG_BYTES) {
      throw new StoreLimitError("active metadata log reached its hard limit");
    }
    return {
      frame,
      frameBytes,
      projection,
      materializedRecord,
      deferResize,
      replacesPendingResize
    };
  }
  #commit(record, preparedCommit) {
    this.#assertOpen();
    const prepared = preparedCommit ?? this.#preflightCommit(record);
    if (prepared.replacesPendingResize) {
      const pending = this.#pendingResizeCommit;
      if (pending === undefined || prepared.materializedRecord.kind !== "resizeFile") {
        const cause = new Error("pending resize preflight no longer matches live state");
        this.#poison(cause);
        throw cause;
      }
      try {
        applyTxn(this.#store.state, record, prepared.projection);
      } catch (cause) {
        this.#poison(cause);
        throw cause;
      }
      this.#store.activeLogBytes += prepared.frameBytes - pending.frameBytes;
      this.#pendingResizeCommit = {
        record: prepared.materializedRecord,
        frameBytes: prepared.frameBytes,
        sequence: pending.sequence
      };
      this.#scheduleRepack();
      return;
    }
    this.#materializePendingResize();
    if (prepared.deferResize && prepared.materializedRecord.kind === "resizeFile") {
      try {
        applyTxn(this.#store.state, record, prepared.projection);
      } catch (cause) {
        this.#poison(cause);
        throw cause;
      }
      this.#pendingResizeCommit = {
        record: prepared.materializedRecord,
        frameBytes: prepared.frameBytes,
        sequence: this.#store.nextSequence
      };
      this.#store.activeLogBytes += prepared.frameBytes;
      this.#store.activeLogFrames += 1;
      this.#store.nextSequence += 1n;
      this.#scheduleRepack();
      return;
    }
    if (prepared.frame === undefined) {
      const cause = new Error("immediate commit has no encoded transaction frame");
      this.#poison(cause);
      throw cause;
    }
    this.#appendFrame(prepared.frame);
    try {
      applyTxn(this.#store.state, record, prepared.projection);
    } catch (cause) {
      this.#poison(cause);
      throw cause;
    }
    this.#store.activeLogBytes += prepared.frameBytes;
    this.#store.activeLogFrames += 1;
    this.#store.nextSequence += 1n;
    this.#scheduleRepack();
  }
  #isDeferrableResize(record) {
    if (record.kind !== "resizeFile" || record.operation !== "write")
      return false;
    const inode = this.#store.state.inodes.get(record.inodeId);
    return inode?.kind === "file" && record.size > inode.size;
  }
  #appendFrame(frame) {
    const activeName = metadataFileName(this.#store.state.activeMetadataFile);
    try {
      writeExact(this.#store.handles[activeName], this.#store.activeLogEnd, frame, "metadata.log.append");
      this.#metadataDirtySinceFlush = true;
      this.#store.activeLogEnd += BigInt(frame.byteLength);
    } catch (cause) {
      this.#failStore(cause);
    }
  }
  #materializePendingResize() {
    const pending = this.#pendingResizeCommit;
    if (pending === undefined)
      return;
    let frame;
    try {
      frame = encodeTxnFrame({
        generation: this.#store.state.generation,
        sequence: pending.sequence,
        record: pending.record
      });
      if (frame.byteLength !== pending.frameBytes) {
        throw new Error("pending resize frame length changed after preflight");
      }
    } catch (cause) {
      this.#poison(cause);
      throw cause;
    }
    this.#appendFrame(frame);
    this.#pendingResizeCommit = undefined;
  }
  #scheduleRepack() {
    if (this.#store.activeLogBytes >= SOFT_ACTIVE_LOG_BYTES) {
      this.#pendingRepackReason = "log-bytes";
    } else if (this.#store.activeLogFrames >= SOFT_ACTIVE_LOG_FRAMES) {
      this.#pendingRepackReason = "log-frames";
    } else if (this.#store.state.basePayloadBytes >= BASE_REPACK_PRESSURE_BYTES) {
      this.#pendingRepackReason = "writer-limit";
    } else if (this.#store.state.allocator.quarantine.size >= QUARANTINE_PRESSURE_EXTENTS || this.#store.state.allocator.quarantine.size > 0 && this.#store.state.allocator.available.size === 0) {
      this.#pendingRepackReason ??= "quarantine-pressure";
    }
  }
  #dueRepackReason(nowMs) {
    if (this.#pendingRepackReason !== null)
      return this.#pendingRepackReason;
    if (this.#store.activeLogBytes >= SOFT_ACTIVE_LOG_BYTES)
      return "log-bytes";
    if (this.#store.activeLogFrames >= SOFT_ACTIVE_LOG_FRAMES)
      return "log-frames";
    if (this.#store.state.basePayloadBytes >= BASE_REPACK_PRESSURE_BYTES) {
      return "writer-limit";
    }
    return this.#store.activeLogFrames > 0 && nowMs - this.#lastRepackAtMs >= REPACK_INTERVAL_MS ? "time" : null;
  }
  #assertOpen() {
    if (this.#status === "failed")
      throw new StoreFailedError(this.#failure);
    if (this.#status === "closed")
      throw new StoreClosedError;
  }
  #poison(cause) {
    if (this.#status === "open") {
      this.#status = "failed";
      this.#failure = cause;
    }
  }
  #failStore(cause) {
    this.#poison(cause);
    throw new StoreFailedError(this.#failure);
  }
}

// packages/pgwasm/src/opfs/opfs-repacked-fs.ts
var DESCRIPTION = Object.freeze({ name: "opfs-repacked", persistent: true });

class OpfsRepackedFS extends BaseFilesystem2 {
  #vfs;
  #durability;
  constructor(vfs, durability) {
    super();
    this.#vfs = vfs;
    this.#durability = durability;
  }
  get description() {
    return DESCRIPTION;
  }
  async initialSyncFs() {
    this.#vfs.assertHealthy();
  }
  async syncToFs(relaxedDurability = false) {
    this.#vfs.assertHealthy();
    if (relaxedDurability)
      this.#vfs.fail(new DurabilityModeMismatchError);
    this.#vfs.runScheduledRepack();
    if (this.#durability === "strict")
      this.#vfs.strictSync();
  }
  strictSync() {
    this.#vfs.strictSync();
  }
  async cleanupFailedInit() {
    this.#vfs.cleanupFailedInit();
  }
  async closeFs() {
    this.#vfs.close();
  }
  chmod(path, mode) {
    this.#vfs.chmod(hostPath(path), mode, nowMs());
  }
  close(fd) {
    this.#vfs.close(fd);
  }
  fstat(fd) {
    return toFsStats(this.#vfs.fstat(fd));
  }
  lstat(path) {
    return toFsStats(this.#vfs.lstat(hostPath(path)));
  }
  mkdir(path, options) {
    this.#vfs.mkdir(hostPath(path), {
      ...options?.recursive === undefined ? {} : { recursive: options.recursive },
      ...options?.mode === undefined ? {} : { mode: options.mode },
      nowMs: nowMs()
    });
  }
  open(path, flags = "r+", mode = 33206) {
    return this.#vfs.open(hostPath(path), flags, mode, nowMs());
  }
  readdir(path) {
    return this.#vfs.readdir(hostPath(path));
  }
  read(fd, buffer, offset, length, position) {
    return this.#vfs.read(fd, buffer, offset, length, toFileOffset(position));
  }
  rename(oldPath, newPath) {
    this.#vfs.rename(hostPath(oldPath), hostPath(newPath), nowMs());
  }
  rmdir(path) {
    this.#vfs.rmdir(hostPath(path), nowMs());
  }
  truncate(path, length) {
    this.#vfs.truncate(hostPath(path), toFileOffset(length), nowMs());
  }
  unlink(path) {
    this.#vfs.unlink(hostPath(path), nowMs());
  }
  utimes(path, atime, mtime) {
    this.#vfs.utimes(hostPath(path), toTimestamp(atime), toTimestamp(mtime), nowMs());
  }
  writeFile(path, data, options) {
    this.#vfs.writeFile(hostPath(path), data, {
      ...options?.encoding === undefined ? {} : { encoding: options.encoding },
      ...options?.mode === undefined ? {} : { mode: options.mode },
      ...options?.flag === undefined ? {} : { flag: options.flag },
      nowMs: nowMs()
    });
  }
  write(fd, buffer, offset, length, position) {
    if (buffer instanceof Uint8Array) {
      return this.#vfs.write(fd, buffer, offset, length, toFileOffset(position), nowMs());
    }
    const source = new Uint8Array(buffer, offset, length);
    return this.#vfs.write(fd, source, 0, source.byteLength, toFileOffset(position), nowMs());
  }
}

class ConcreteOpfsRepackedFS extends OpfsRepackedFS {
  constructor(vfs, durability) {
    super(vfs, durability);
  }
}
async function openOpfsRepackedFsForPort(port, options = {}) {
  const durability = options.durability ?? "relaxed";
  if (durability !== "relaxed" && durability !== "strict") {
    throw new TypeError(`unsupported OPFS repacked durability: ${String(durability)}`);
  }
  const vfs = await RepackedVfs.open(port, {
    ...options.extentSize === undefined ? {} : { extentSize: options.extentSize }
  });
  return new ConcreteOpfsRepackedFS(vfs, durability);
}
function nowMs() {
  return BigInt(Date.now());
}
function hostPath(path) {
  return path === "" ? "/" : path;
}
function toFileOffset(value) {
  if (!Number.isSafeInteger(value) || value < 0)
    throw new TypeError("file offset is not a non-negative safe integer");
  return BigInt(value);
}
function toTimestamp(value) {
  const floored = Math.floor(value);
  if (!Number.isSafeInteger(floored) || floored < 0) {
    throw new TypeError("timestamp is not a non-negative finite millisecond value");
  }
  return BigInt(floored);
}
function toFsStats(stat) {
  const size = toSafeNumber(stat.size, "file size");
  const blksize = 4096;
  return {
    dev: 0,
    ino: 0,
    mode: stat.mode,
    nlink: 1,
    uid: 0,
    gid: 0,
    rdev: 0,
    size,
    blksize,
    blocks: Math.ceil(size / blksize),
    atime: toSafeNumber(stat.atimeMs, "access time"),
    mtime: toSafeNumber(stat.mtimeMs, "modification time"),
    ctime: toSafeNumber(stat.ctimeMs, "change time")
  };
}
function toSafeNumber(value, label) {
  if (value > BigInt(Number.MAX_SAFE_INTEGER))
    throw new StoreLimitError(`${label} exceeds safe integer range`);
  return Number(value);
}

// packages/pgwasm/src/opfs/create.ts
async function createOpfsPgwasm(options) {
  assertHostOptions(options.pgwasm);
  const store = await openOpfsRepackedFsForPort(new OpfsRepackedPort(options.directory), filesystemOptions(options));
  options.onPhase?.("store-opened");
  let pg;
  try {
    pg = await createPgwasm2({
      ...options.pgwasm,
      build: options.build,
      fs: store,
      relaxedDurability: false
    });
    registerStrictSync(pg, () => store.strictSync());
    options.onPhase?.("pgwasm-ready");
    store.strictSync();
    return pg;
  } catch (cause) {
    try {
      await pg?.close();
    } catch {}
    try {
      await store.cleanupFailedInit();
    } catch {}
    throw cause;
  }
}
async function strictSync(pg) {
  const sync = strictSyncOf(pg);
  if (sync === undefined) {
    throw new UnsupportedFeatureError2("strictSync needs a database on an OPFS-repacked store (created by createOpfsPgwasm).");
  }
  await pg.runExclusive(async () => {
    sync();
  });
}
function filesystemOptions(options) {
  return {
    ...options.extentSize === undefined ? {} : { extentSize: options.extentSize },
    ...options.durability === undefined ? {} : { durability: options.durability }
  };
}
function assertHostOptions(options) {
  if (options === undefined)
    return;
  for (const reserved of ["build", "dataDir", "fs", "relaxedDurability"]) {
    if (reserved in options) {
      throw new TypeError(`pgwasm.${reserved} is owned by createOpfsPgwasm`);
    }
  }
}
// packages/pgwasm/src/opfs/core/memory-port.ts
function clone(bytes) {
  return bytes.slice();
}
function applyWrite(current, at, source) {
  const required = at + source.byteLength;
  const next = required <= current.byteLength ? clone(current) : new Uint8Array(required);
  if (next.byteLength > current.byteLength)
    next.set(current);
  next.set(source, at);
  return next;
}
function applyTruncate(current, size) {
  if (size === current.byteLength)
    return clone(current);
  const next = new Uint8Array(size);
  next.set(current.subarray(0, Math.min(size, current.byteLength)));
  return next;
}
function resizeImage(current, size) {
  if (size <= current.byteLength)
    return new Uint8Array(current.buffer, 0, size);
  if (size <= current.buffer.byteLength) {
    const grown = new Uint8Array(current.buffer, 0, size);
    grown.fill(0, current.byteLength, size);
    return grown;
  }
  const capacity = Math.max(size, current.buffer.byteLength * 2, 64);
  const grown = new Uint8Array(new ArrayBuffer(capacity), 0, size);
  grown.set(current);
  return grown;
}
function isOwnedFileName(name) {
  return OWNED_FILE_NAMES.includes(name);
}

class MemoryHandle {
  name;
  #port;
  #epoch;
  #closed = false;
  constructor(port, name, epoch) {
    this.#port = port;
    this.name = name;
    this.#epoch = epoch;
  }
  getSize(label) {
    this.#assertOpen();
    return this.#port.handleGetSize(this.name, label);
  }
  read(target, at, label) {
    this.#assertOpen();
    return this.#port.handleRead(this.name, target, at, label);
  }
  write(source, at, label) {
    this.#assertOpen();
    return this.#port.handleWrite(this.name, source, at, label);
  }
  truncate(size, label) {
    this.#assertOpen();
    this.#port.handleTruncate(this.name, size, label);
  }
  flush(label) {
    this.#assertOpen();
    this.#port.handleFlush(this.name, label);
  }
  close() {
    if (this.#closed)
      return;
    this.#closed = true;
    if (this.#epoch === this.#port.epoch)
      this.#port.handleClose(this.name);
  }
  #assertOpen() {
    if (this.#closed || this.#epoch !== this.#port.epoch) {
      throw new Error(`memory handle ${this.name} is closed`);
    }
  }
}

class MemoryRepackedPort {
  #durable = new Map;
  #volatile = new Map;
  #entryKinds = new Map;
  #open = new Set;
  #faults = [];
  #operations = [];
  #effects = [];
  #nextEffectId = 1;
  #epoch = 1;
  get epoch() {
    return this.#epoch;
  }
  async enumerate(label) {
    this.#recordOperation("enumerate", undefined, label);
    const fault = this.#takeFault("enumerate", undefined, label);
    if (fault !== undefined)
      throw new Error(`injected enumerate failure ${fault.outcome}`);
    return [...this.#entryKinds].sort(([left], [right]) => left.localeCompare(right)).map(([name, kind]) => ({
      name,
      kind
    }));
  }
  async acquire(name, label) {
    this.#recordOperation("acquire", name, label);
    const fault = this.#takeFault("acquire", name, label);
    if (fault?.outcome === "throw-before")
      throw new Error("injected acquire failure before effect");
    if (this.#open.has(name))
      throw new StoreOwnedError;
    if (this.#entryKinds.get(name) === "directory")
      throw new Error(`memory entry ${name} is not a file`);
    if (!this.#volatile.has(name)) {
      this.#volatile.set(name, new Uint8Array);
      this.#durable.set(name, new Uint8Array);
      this.#entryKinds.set(name, "file");
    }
    if (fault !== undefined)
      throw new Error(`injected acquire failure ${fault.outcome}`);
    this.#open.add(name);
    return new MemoryHandle(this, name, this.#epoch);
  }
  injectEntry(name, kind) {
    if (isOwnedFileName(name) && this.#open.has(name)) {
      throw new Error(`cannot replace acquired memory entry ${name}`);
    }
    this.#entryKinds.set(name, kind);
    if (isOwnedFileName(name)) {
      this.#effects = this.#effects.filter((effect) => effect.file !== name);
      if (kind === "file") {
        this.#volatile.set(name, new Uint8Array);
        this.#durable.set(name, new Uint8Array);
      } else {
        this.#volatile.delete(name);
        this.#durable.delete(name);
      }
    }
  }
  injectFault(fault) {
    if (fault.outcome === "quota" && fault.operation !== "truncate") {
      throw new TypeError("quota faults are supported only for arena growth truncates");
    }
    if (fault.bytes !== undefined && (!Number.isSafeInteger(fault.bytes) || fault.bytes < 0)) {
      throw new TypeError("fault byte count must be a non-negative safe integer");
    }
    if (fault.occurrence !== undefined && (!Number.isSafeInteger(fault.occurrence) || fault.occurrence < 0)) {
      throw new TypeError("fault occurrence must be a non-negative safe integer");
    }
    this.#faults.push({ ...fault });
  }
  pendingEffects() {
    return this.#effects.map((effect) => ({
      id: effect.id,
      file: effect.file,
      operation: effect.kind,
      bytes: effect.kind === "write" ? effect.data.byteLength : effect.size
    }));
  }
  openHandleCount() {
    return this.#open.size;
  }
  observedOperations() {
    return Object.freeze(this.#operations.map((operation) => Object.freeze({ ...operation })));
  }
  clearObservedOperations() {
    this.#operations.length = 0;
  }
  durableBytes(name) {
    return clone(this.#durable.get(name) ?? new Uint8Array);
  }
  terminate(decisions = {}) {
    const materialized = new Map;
    for (const [name, bytes] of this.#durable)
      materialized.set(name, clone(bytes));
    for (const effect of this.#effects) {
      const decision = decisions[effect.id] ?? "absent";
      if (decision === "absent")
        continue;
      const current = materialized.get(effect.file) ?? new Uint8Array;
      if (effect.kind === "truncate") {
        if (decision !== "full") {
          throw new TypeError("truncate termination decisions must be absent or full");
        }
        materialized.set(effect.file, applyTruncate(current, effect.size));
      } else {
        const bytes = decision === "full" ? effect.data.byteLength : decision;
        if (!Number.isSafeInteger(bytes) || bytes < 0 || bytes > effect.data.byteLength) {
          throw new TypeError("write termination prefix is outside the effect");
        }
        if (bytes > 0)
          materialized.set(effect.file, applyWrite(current, effect.at, effect.data.subarray(0, bytes)));
      }
    }
    this.#durable.clear();
    this.#volatile.clear();
    for (const [name, bytes] of materialized) {
      this.#durable.set(name, clone(bytes));
      this.#volatile.set(name, clone(bytes));
    }
    this.#effects = [];
    this.#faults.length = 0;
    this.#open.clear();
    this.#epoch += 1;
  }
  handleGetSize(name, label) {
    this.#recordOperation("getSize", name, label);
    const fault = this.#takeFault("getSize", name, label);
    if (fault !== undefined)
      throw new Error(`injected getSize failure ${fault.outcome}`);
    return this.#file(name).byteLength;
  }
  handleRead(name, target, at, label) {
    this.#validateRange(at, target.byteLength);
    this.#recordOperation("read", name, label);
    const fault = this.#takeFault("read", name, label);
    if (fault?.outcome === "throw-before" || fault?.outcome === "throw-after") {
      throw new Error(`injected read failure ${fault.outcome === "throw-before" ? "before" : "after"} effect`);
    }
    const source = this.#file(name);
    const available = Math.max(0, Math.min(target.byteLength, source.byteLength - at));
    const count = fault?.outcome === "short" ? Math.min(available, fault.bytes ?? 0) : available;
    target.set(source.subarray(at, at + count));
    return count;
  }
  handleWrite(name, source, at, label) {
    this.#validateRange(at, source.byteLength);
    this.#recordOperation("write", name, label);
    const fault = this.#takeFault("write", name, label);
    if (fault?.outcome === "throw-before")
      throw new Error("injected write failure before effect");
    const count = fault?.outcome === "short" || fault?.outcome === "throw-after" ? Math.min(source.byteLength, fault.bytes ?? source.byteLength) : source.byteLength;
    if (count > 0)
      this.#recordWrite(name, at, source.subarray(0, count));
    if (fault?.outcome === "throw-after")
      throw new Error("injected write failure after effect");
    return count;
  }
  handleTruncate(name, size, label) {
    this.#validateRange(size, 0);
    this.#recordOperation("truncate", name, label);
    const fault = this.#takeFault("truncate", name, label);
    if (fault?.outcome === "quota")
      throw new DOMException("injected arena quota exhaustion", "QuotaExceededError");
    if (fault?.outcome === "throw-before")
      throw new Error("injected truncate failure before effect");
    this.#volatile.set(name, resizeImage(this.#file(name), size));
    this.#effects.push({ id: this.#nextEffectId++, file: name, kind: "truncate", size });
    if (fault?.outcome === "throw-after")
      throw new Error("injected truncate failure after effect");
  }
  handleFlush(name, label) {
    const record = this.#recordOperation("flush", name, label);
    record.copiedBytes = 0;
    const fault = this.#takeFault("flush", name, label);
    if (fault?.outcome === "throw-before")
      throw new Error("injected flush failure before effect");
    record.copiedBytes = this.#makeDurable(name);
    if (fault?.outcome === "throw-after")
      throw new Error("injected flush failure after effect");
  }
  handleClose(name) {
    this.#open.delete(name);
  }
  #file(name) {
    const bytes = this.#volatile.get(name);
    if (bytes === undefined)
      throw new Error(`memory file ${name} was not acquired`);
    return bytes;
  }
  #recordWrite(name, at, source) {
    const data = clone(source);
    const current = this.#file(name);
    const required = at + data.byteLength;
    const target = required > current.byteLength ? resizeImage(current, required) : current;
    target.set(data, at);
    this.#volatile.set(name, target);
    this.#effects.push({ id: this.#nextEffectId++, file: name, kind: "write", at, data });
  }
  #makeDurable(name) {
    let image = this.#durable.get(name) ?? new Uint8Array;
    const remaining = [];
    let copied = 0;
    for (const effect of this.#effects) {
      if (effect.file !== name) {
        remaining.push(effect);
        continue;
      }
      if (effect.kind === "truncate") {
        const resized = resizeImage(image, effect.size);
        if (resized.buffer !== image.buffer)
          copied += image.byteLength;
        image = resized;
        continue;
      }
      const required = effect.at + effect.data.byteLength;
      if (required > image.byteLength) {
        const grown = resizeImage(image, required);
        if (grown.buffer !== image.buffer)
          copied += image.byteLength;
        image = grown;
      }
      image.set(effect.data, effect.at);
      copied += effect.data.byteLength;
    }
    this.#durable.set(name, image);
    this.#effects = remaining;
    return copied;
  }
  #takeFault(operation, file, label) {
    const index = this.#faults.findIndex((fault) => fault.operation === operation && (fault.file === undefined || fault.file === file) && (fault.label === undefined || fault.label === label));
    if (index < 0)
      return;
    const fault = this.#faults[index];
    if ((fault.occurrence ?? 0) > 0) {
      this.#faults[index] = { ...fault, occurrence: fault.occurrence - 1 };
      return;
    }
    return this.#faults.splice(index, 1)[0];
  }
  #recordOperation(operation, file, label) {
    const record = { operation, file, label };
    this.#operations.push(record);
    return record;
  }
  #validateRange(at, length) {
    if (!Number.isSafeInteger(at) || !Number.isSafeInteger(length) || at < 0 || length < 0) {
      throw new RangeError("memory port range is invalid");
    }
    if (!Number.isSafeInteger(at + length))
      throw new RangeError("memory port range exceeds safe integers");
  }
}
// packages/pgwasm/src/opfs/core/mounted-vfs.ts
function joinPath2(base, rest) {
  if (rest.length === 0)
    return base;
  return base === "/" ? `/${rest.join("/")}` : `${base}/${rest.join("/")}`;
}
function isMissing(cause) {
  return cause instanceof FsError && (cause.code === FS_ERRNO.ENOENT || cause.code === FS_ERRNO.ENOTDIR);
}

class MountedRepackedVfs {
  #root;
  #mounts;
  #descriptors = new Map;
  #nextDescriptor = 3;
  constructor(options) {
    this.#root = options.root;
    const nowMs = (options.nowMs ?? (() => BigInt(Date.now())))();
    const mounts = [];
    for (const mount of options.mounts) {
      if (parsePath(mount.prefix).length === 0) {
        throw new FsError("EINVAL", "a mount prefix must be an absolute path below the root", {
          path: mount.prefix
        });
      }
      for (const existing of mounts) {
        if (existing.prefix === mount.prefix || mount.prefix.startsWith(existing.boundary) || existing.prefix.startsWith(`${mount.prefix}/`)) {
          throw new FsError("EINVAL", `mount prefix ${mount.prefix} overlaps ${existing.prefix}`, {
            path: mount.prefix
          });
        }
      }
      mounts.push({
        prefix: mount.prefix,
        boundary: `${mount.prefix}/`,
        vfs: mount.vfs,
        durable: mount.durable ?? true
      });
    }
    this.#mounts = mounts;
    for (const mount of mounts) {
      try {
        this.#root.mkdir(mount.prefix, { recursive: true, nowMs });
      } catch (cause) {
        if (!(cause instanceof FsError) || cause.code !== FS_ERRNO.EEXIST)
          throw cause;
      }
    }
  }
  get mounts() {
    return this.#mounts.map((mount) => ({ prefix: mount.prefix, vfs: mount.vfs, durable: mount.durable }));
  }
  get root() {
    return this.#root;
  }
  #route(path) {
    parsePath(path);
    for (const mount of this.#mounts) {
      if (path === mount.prefix)
        return { fs: mount.vfs, path: "/", mount };
      if (path.startsWith(mount.boundary)) {
        return { fs: mount.vfs, path: path.slice(mount.prefix.length), mount };
      }
    }
    return { fs: this.#root, path, mount: undefined };
  }
  resolvePath(path, follow = true) {
    const route = this.#route(path);
    if (route.fs.resolvePath(route.path, follow) === route.path)
      return path;
    return this.#walk(path, follow);
  }
  #walk(path, follow) {
    let pending = parsePath(path);
    let index = 0;
    const resolved = [];
    let hops = 0;
    while (index < pending.length) {
      const candidate = joinPath2(`/${resolved.join("/")}`, [pending[index]]);
      const route = this.#route(candidate);
      let stat;
      try {
        stat = route.fs.lstat(route.path);
      } catch (cause) {
        if (isMissing(cause))
          break;
        throw cause;
      }
      if (stat.kind === "symlink" && (follow || index < pending.length - 1)) {
        hops += 1;
        if (hops > MAX_SYMLINK_HOPS) {
          throw new FsError("ELOOP", `path traverses more than ${MAX_SYMLINK_HOPS} symbolic links`, { path });
        }
        pending = parsePath(joinPath2(route.fs.readlink(route.path), pending.slice(index + 1)));
        index = 0;
        resolved.length = 0;
        continue;
      }
      resolved.push(pending[index]);
      index += 1;
    }
    return joinPath2(`/${resolved.join("/")}`, pending.slice(index));
  }
  #at(path, follow) {
    return this.#route(this.resolvePath(path, follow));
  }
  #descriptor(fd) {
    const entry = this.#descriptors.get(fd);
    if (entry === undefined)
      throw new FsError("EBADF", "descriptor is invalid");
    return entry;
  }
  strictSync() {
    this.#root.strictSync();
    for (const mount of this.#mounts) {
      if (mount.durable)
        mount.vfs.strictSync();
    }
  }
  assertHealthy() {
    this.#root.assertHealthy();
    for (const mount of this.#mounts)
      mount.vfs.assertHealthy();
  }
  fail(cause) {
    for (const mount of this.#mounts) {
      try {
        mount.vfs.fail(cause);
      } catch {}
    }
    return this.#root.fail(cause);
  }
  metrics() {
    return this.#root.metrics();
  }
  repack(reason) {
    this.#root.repack(reason);
    for (const mount of this.#mounts)
      mount.vfs.repack(reason);
  }
  runScheduledRepack(nowMs) {
    let repacked = this.#root.runScheduledRepack(nowMs);
    for (const mount of this.#mounts) {
      if (mount.vfs.runScheduledRepack(nowMs))
        repacked = true;
    }
    return repacked;
  }
  close(fd) {
    if (fd !== undefined) {
      const entry = this.#descriptor(fd);
      this.#descriptors.delete(fd);
      entry.fs.close(entry.fd);
      return;
    }
    this.#descriptors.clear();
    let firstError;
    for (const mount of this.#mounts) {
      try {
        mount.vfs.close();
      } catch (cause) {
        firstError ??= cause;
      }
    }
    try {
      this.#root.close();
    } catch (cause) {
      firstError ??= cause;
    }
    if (firstError !== undefined)
      throw firstError;
  }
  stat(path) {
    const route = this.#at(path, true);
    return route.fs.stat(route.path);
  }
  lstat(path) {
    const route = this.#at(path, false);
    return route.fs.lstat(route.path);
  }
  symlink(target, path, nowMs) {
    const route = this.#at(path, false);
    route.fs.symlink(target, route.path, nowMs);
  }
  readlink(path) {
    const route = this.#at(path, false);
    return route.fs.readlink(route.path);
  }
  readdir(path) {
    const route = this.#at(path, true);
    return route.fs.readdir(route.path);
  }
  mkdir(path, options) {
    const route = this.#at(path, false);
    route.fs.mkdir(route.path, options);
  }
  writeFile(path, data, options) {
    const route = this.#at(path, true);
    route.fs.writeFile(route.path, data, options);
  }
  readFile(path) {
    const route = this.#at(path, true);
    return route.fs.readFile(route.path);
  }
  truncate(path, size, nowMs) {
    const route = this.#at(path, true);
    route.fs.truncate(route.path, size, nowMs);
  }
  chmod(path, mode, nowMs) {
    const route = this.#at(path, true);
    route.fs.chmod(route.path, mode, nowMs);
  }
  utimes(path, atimeMs, mtimeMs, ctimeMs) {
    const route = this.#at(path, true);
    route.fs.utimes(route.path, atimeMs, mtimeMs, ctimeMs);
  }
  unlink(path, nowMs) {
    const route = this.#at(path, false);
    route.fs.unlink(route.path, nowMs);
  }
  rmdir(path, nowMs) {
    const route = this.#at(path, false);
    route.fs.rmdir(route.path, nowMs);
  }
  rename(oldPath, newPath, nowMs) {
    const source = this.#at(oldPath, false);
    const destination = this.#at(newPath, false);
    if (source.mount !== destination.mount) {
      throw new FsError("EXDEV", "rename crosses a mount boundary", { operation: "rename", path: newPath });
    }
    source.fs.rename(source.path, destination.path, nowMs);
  }
  open(path, flags = "r", mode = 33206, nowMs = 0n) {
    const route = this.#at(path, true);
    const inner = route.fs.open(route.path, flags, mode, nowMs);
    const fd = this.#nextDescriptor++;
    this.#descriptors.set(fd, { fs: route.fs, fd: inner });
    return fd;
  }
  fstat(fd) {
    const entry = this.#descriptor(fd);
    return entry.fs.fstat(entry.fd);
  }
  read(fd, buffer, offset, length, position) {
    const entry = this.#descriptor(fd);
    return entry.fs.read(entry.fd, buffer, offset, length, position);
  }
  write(fd, buffer, offset, length, position, nowMs) {
    const entry = this.#descriptor(fd);
    return entry.fs.write(entry.fd, buffer, offset, length, position, nowMs);
  }
}
// packages/pgwasm/src/opfs/file-port.ts
var CREATED_FILE_MODE = 438;
async function loadNodeFileSystem() {
  const runtime = globalThis;
  if (runtime.process?.versions?.["node"] === undefined) {
    throw new Error("FileRepackedPort needs node:fs and this scope has none (no process.versions.node); " + "a browser store belongs on OpfsRepackedPort");
  }
  return await import("fs");
}
function joinPath3(directory, name) {
  return `${directory.replace(/\/+$/, "")}/${name}`;
}

class FileRepackedPort {
  #directory;
  #open = new Set;
  #fs;
  constructor(directory) {
    if (directory.trim() === "")
      throw new TypeError("FileRepackedPort needs a directory path");
    this.#directory = directory;
  }
  get directory() {
    return this.#directory;
  }
  async enumerate(_label) {
    const fs = await this.#ready();
    return fs.readdirSync(this.#directory, { withFileTypes: true }).map((entry) => ({
      name: entry.name,
      kind: entry.isDirectory() ? "directory" : "file"
    }));
  }
  async acquire(name, _label) {
    const fs = await this.#ready();
    if (this.#open.has(name))
      throw new StoreOwnedError;
    const fd = fs.openSync(joinPath3(this.#directory, name), fs.constants.O_RDWR | fs.constants.O_CREAT, CREATED_FILE_MODE);
    this.#open.add(name);
    return new FileRepackedFileHandle(fs, name, fd, () => this.#open.delete(name));
  }
  async#ready() {
    if (this.#fs === undefined) {
      const fs = await loadNodeFileSystem();
      fs.mkdirSync(this.#directory, { recursive: true });
      this.#fs = fs;
    }
    return this.#fs;
  }
}

class FileRepackedFileHandle {
  name;
  #fs;
  #fd;
  #released;
  #closed = false;
  constructor(fs, name, fd, released) {
    this.#fs = fs;
    this.name = name;
    this.#fd = fd;
    this.#released = released;
  }
  getSize(_label) {
    this.#assertOpen();
    return this.#fs.fstatSync(this.#fd).size;
  }
  read(target, at, _label) {
    this.#assertOpen();
    return this.#fs.readSync(this.#fd, target, 0, target.byteLength, at);
  }
  write(source, at, _label) {
    this.#assertOpen();
    return this.#fs.writeSync(this.#fd, source, 0, source.byteLength, at);
  }
  truncate(size, _label) {
    this.#assertOpen();
    this.#fs.ftruncateSync(this.#fd, size);
  }
  flush(_label) {
    this.#assertOpen();
    this.#fs.fsyncSync(this.#fd);
  }
  close() {
    if (this.#closed)
      return;
    this.#closed = true;
    this.#released();
    this.#fs.closeSync(this.#fd);
  }
  #assertOpen() {
    if (this.#closed)
      throw new Error(`file handle ${this.name} is closed`);
  }
}
// packages/pgwasm/src/opfs/broker/protocol.ts
var HEADER_STATE = 0;
var HEADER_OPCODE = 1;
var HEADER_REQUEST = 2;
var HEADER_RESPONSE = 3;
var HEADER_ERRNO = 4;
var HEADER_RESULT_LO = 5;
var HEADER_RESULT_HI = 6;
var HEADER_SEQUENCE = 7;
var HEADER_FAULT = 8;
var HEADER_PAYLOAD = 9;
var CHANNEL_HEADER_SLOTS = 16;
var CHANNEL_HEADER_BYTES = CHANNEL_HEADER_SLOTS * 4;
var STATE_IDLE = 0;
var STATE_REQUEST = 1;
var STATE_RESPONSE = 2;
var STATE_DETACHED = 3;
var DOORBELL_TICKET = 0;
var DOORBELL_RUNNING = 1;
var DOORBELL_SLOTS = 4;
var DOORBELL_BYTES = DOORBELL_SLOTS * 4;
var DEFAULT_PAYLOAD_BYTES = 64 * 1024;
var MIN_PAYLOAD_BYTES = 1024;
var FAULT_NONE = 0;
var FAULT_PROTOCOL = 1;
var FAULT_STORE = 2;
var FAULT_DETACHED = 3;
var OPCODE_OPEN = 1;
var OPCODE_CLOSE = 2;
var OPCODE_READ = 3;
var OPCODE_WRITE = 4;
var OPCODE_FSYNC = 5;
var OPCODE_FSTAT = 6;
var OPCODE_STAT = 7;
var OPCODE_LSTAT = 8;
var OPCODE_READDIR = 9;
var OPCODE_MKDIR = 10;
var OPCODE_RMDIR = 11;
var OPCODE_UNLINK = 12;
var OPCODE_RENAME = 13;
var OPCODE_TRUNCATE = 14;
var OPCODE_SIZE = 15;
var OPCODE_SYMLINK = 16;
var OPCODE_READLINK = 17;
var MIN_OPCODE = OPCODE_OPEN;
var MAX_OPCODE = OPCODE_READLINK;
function isKnownOpcode(opcode) {
  return Number.isInteger(opcode) && opcode >= MIN_OPCODE && opcode <= MAX_OPCODE;
}
var O_RDONLY = 0;
var O_WRONLY = 1;
var O_RDWR = 2;
var O_ACCMODE = 3;
var O_CREAT = 64;
var O_EXCL = 128;
var O_TRUNC = 512;
var O_APPEND = 1024;
var O_NOFOLLOW = 131072;
var O_KNOWN = O_ACCMODE | O_CREAT | O_EXCL | O_TRUNC | O_APPEND | O_NOFOLLOW;
var STAT_KIND_FILE = 0;
var STAT_KIND_DIRECTORY = 1;
var STAT_KIND_SYMLINK = 2;
var STAT_BYTES = 1 + 4 + 8 * 4;
var READDIR_DONE = -1;
function planOpen(flags) {
  if (!Number.isInteger(flags) || flags < 0 || (flags & ~O_KNOWN) !== 0) {
    throw new FsError("EINVAL", `unsupported open flags: ${flags}`);
  }
  const access = flags & O_ACCMODE;
  if (access === O_ACCMODE)
    throw new FsError("EINVAL", "open access mode is invalid");
  const readable = access === O_RDONLY || access === O_RDWR;
  const writable = access === O_WRONLY || access === O_RDWR;
  const create = (flags & O_CREAT) !== 0;
  const exclusive = (flags & O_EXCL) !== 0;
  const truncate = (flags & O_TRUNC) !== 0;
  const append = (flags & O_APPEND) !== 0;
  if (exclusive && !create)
    throw new FsError("EINVAL", "O_EXCL requires O_CREAT");
  if (truncate && append)
    throw new FsError("EINVAL", "O_TRUNC and O_APPEND are contradictory");
  if (!writable && (create || truncate || append)) {
    throw new FsError("EINVAL", "O_CREAT, O_TRUNC and O_APPEND require write access");
  }
  const plan = (coreFlags, extra = {}) => ({
    coreFlags,
    fallbackFlags: undefined,
    truncateFirst: false,
    requireExisting: false,
    readable,
    writable,
    follow: (flags & O_NOFOLLOW) === 0,
    ...extra
  });
  if (exclusive)
    return plan(append ? readable ? "ax+" : "ax" : readable ? "wx+" : "wx");
  if (append && create)
    return plan(readable ? "a+" : "a");
  if (truncate && create)
    return plan(readable ? "w+" : "w");
  if (append)
    return plan(readable ? "a+" : "a", { requireExisting: true });
  if (truncate)
    return plan("r+", { truncateFirst: true });
  if (create)
    return plan("r+", { fallbackFlags: "w+" });
  return plan(readable && !writable ? "r" : "r+");
}
var textEncoder2 = new TextEncoder;
var textDecoder2 = new TextDecoder("utf-8", { fatal: true });

class PayloadOverflowError extends Error {
  constructor(needed, capacity) {
    super(`broker payload needs ${needed} bytes but the channel region holds ${capacity}`);
    this.name = "PayloadOverflowError";
  }
}

class PayloadDecodeError extends Error {
  constructor(message) {
    super(`broker payload is malformed: ${message}`);
    this.name = "PayloadDecodeError";
  }
}

class PayloadWriter {
  #view;
  #bytes;
  #cursor = 0;
  constructor(payload) {
    this.#bytes = payload;
    this.#view = new DataView(payload.buffer, payload.byteOffset, payload.byteLength);
  }
  get length() {
    return this.#cursor;
  }
  get remaining() {
    return this.#bytes.byteLength - this.#cursor;
  }
  u8(value) {
    this.#view.setUint8(this.#reserve(1), value);
  }
  u32(value) {
    this.#view.setUint32(this.#reserve(4), value, true);
  }
  i32(value) {
    this.#view.setInt32(this.#reserve(4), value, true);
  }
  u64(value) {
    this.#view.setBigUint64(this.#reserve(8), value, true);
  }
  bytes(source) {
    this.#bytes.set(source, this.#reserve(source.byteLength));
  }
  string(value) {
    const encoded = textEncoder2.encode(value);
    this.u32(encoded.byteLength);
    this.bytes(encoded);
  }
  rewind(to) {
    if (!Number.isSafeInteger(to) || to < 0 || to > this.#cursor) {
      throw new RangeError("the payload rewind target is outside what has been written");
    }
    this.#cursor = to;
  }
  patch(at, count) {
    if (!Number.isSafeInteger(at) || !Number.isSafeInteger(count) || at < 0 || count < 0 || at + count > this.#cursor) {
      throw new RangeError("the payload patch range is outside what has been written");
    }
    return new DataView(this.#bytes.buffer, this.#bytes.byteOffset + at, count);
  }
  #reserve(count) {
    if (count > this.remaining)
      throw new PayloadOverflowError(this.#cursor + count, this.#bytes.byteLength);
    const at = this.#cursor;
    this.#cursor += count;
    return at;
  }
}

class PayloadReader {
  #view;
  #bytes;
  #cursor = 0;
  constructor(payload, length) {
    if (!Number.isSafeInteger(length) || length < 0 || length > payload.byteLength) {
      throw new PayloadDecodeError(`declared length ${length} is outside the payload region`);
    }
    this.#bytes = payload.subarray(0, length);
    this.#view = new DataView(payload.buffer, payload.byteOffset, length);
  }
  get remaining() {
    return this.#bytes.byteLength - this.#cursor;
  }
  u8() {
    return this.#view.getUint8(this.#take(1));
  }
  u32() {
    return this.#view.getUint32(this.#take(4), true);
  }
  i32() {
    return this.#view.getInt32(this.#take(4), true);
  }
  u64() {
    return this.#view.getBigUint64(this.#take(8), true);
  }
  bytes(count) {
    return this.#bytes.subarray(this.#take(count), this.#cursor);
  }
  string() {
    const length = this.u32();
    const raw = this.bytes(length);
    try {
      return textDecoder2.decode(raw.slice());
    } catch (cause) {
      throw new PayloadDecodeError(`a string is not valid UTF-8: ${String(cause)}`);
    }
  }
  #take(count) {
    if (!Number.isSafeInteger(count) || count < 0)
      throw new PayloadDecodeError(`length ${count} is invalid`);
    if (count > this.remaining)
      throw new PayloadDecodeError("the payload ended mid-field");
    const at = this.#cursor;
    this.#cursor += count;
    return at;
  }
}
function splitResult(value) {
  if (value < 0n || value > 0xffffffffffffffffn) {
    throw new RangeError(`broker result ${value} is outside the unsigned 64-bit range`);
  }
  return { lo: Number(value & 0xffffffffn) | 0, hi: Number(value >> 32n) | 0 };
}
function joinResult(lo, hi) {
  return BigInt(hi >>> 0) << 32n | BigInt(lo >>> 0);
}
function writeStat(writer, stat) {
  writer.u8(stat.kind === "directory" ? STAT_KIND_DIRECTORY : stat.kind === "symlink" ? STAT_KIND_SYMLINK : STAT_KIND_FILE);
  writer.u32(stat.mode);
  writer.u64(stat.size);
  writer.u64(stat.atimeMs);
  writer.u64(stat.mtimeMs);
  writer.u64(stat.ctimeMs);
}
function readStat(reader) {
  const code = reader.u8();
  const kind = code === STAT_KIND_DIRECTORY ? "directory" : code === STAT_KIND_SYMLINK ? "symlink" : "file";
  return {
    kind,
    mode: reader.u32(),
    size: reader.u64(),
    atimeMs: reader.u64(),
    mtimeMs: reader.u64(),
    ctimeMs: reader.u64()
  };
}

class RepackedDoorbell {
  buffer;
  #slots;
  constructor(buffer) {
    if (buffer.byteLength < DOORBELL_BYTES) {
      throw new RangeError(`a broker doorbell needs at least ${DOORBELL_BYTES} bytes`);
    }
    this.buffer = buffer;
    this.#slots = new Int32Array(buffer, 0, DOORBELL_SLOTS);
  }
  static create() {
    const doorbell = new RepackedDoorbell(new SharedArrayBuffer(DOORBELL_BYTES));
    Atomics.store(doorbell.#slots, DOORBELL_RUNNING, 1);
    return doorbell;
  }
  static attach(buffer) {
    return new RepackedDoorbell(buffer);
  }
  ticket() {
    return Atomics.load(this.#slots, DOORBELL_TICKET);
  }
  ring() {
    Atomics.add(this.#slots, DOORBELL_TICKET, 1);
    Atomics.notify(this.#slots, DOORBELL_TICKET);
  }
  running() {
    return Atomics.load(this.#slots, DOORBELL_RUNNING) === 1;
  }
  requestStop() {
    Atomics.store(this.#slots, DOORBELL_RUNNING, 0);
    this.ring();
  }
  resume() {
    Atomics.store(this.#slots, DOORBELL_RUNNING, 1);
  }
  wait(observed, timeoutMs) {
    return Atomics.wait(this.#slots, DOORBELL_TICKET, observed, timeoutMs);
  }
  waitAsync(observed, timeoutMs) {
    const result = Atomics.waitAsync(this.#slots, DOORBELL_TICKET, observed, timeoutMs);
    return result.async ? result.value : Promise.resolve(result.value);
  }
}

class RepackedChannel {
  id;
  buffer;
  doorbell;
  header;
  payload;
  constructor(id, buffer, doorbell) {
    this.id = id;
    this.buffer = buffer;
    this.doorbell = doorbell;
    this.header = new Int32Array(buffer, 0, CHANNEL_HEADER_SLOTS);
    this.payload = new Uint8Array(buffer, CHANNEL_HEADER_BYTES);
  }
  static create(options) {
    const payloadBytes = options.payloadBytes ?? DEFAULT_PAYLOAD_BYTES;
    if (!Number.isSafeInteger(payloadBytes) || payloadBytes < MIN_PAYLOAD_BYTES) {
      throw new RangeError(`a broker channel payload must be at least ${MIN_PAYLOAD_BYTES} bytes`);
    }
    if (!Number.isSafeInteger(options.id) || options.id < 0) {
      throw new RangeError("a broker channel id must be a non-negative safe integer");
    }
    const channel = new RepackedChannel(options.id, new SharedArrayBuffer(CHANNEL_HEADER_BYTES + payloadBytes), options.doorbell);
    Atomics.store(channel.header, HEADER_PAYLOAD, payloadBytes);
    Atomics.store(channel.header, HEADER_STATE, STATE_IDLE);
    return channel;
  }
  static attach(transfer) {
    const doorbell = RepackedDoorbell.attach(transfer.doorbell);
    if (transfer.channel.byteLength < CHANNEL_HEADER_BYTES + MIN_PAYLOAD_BYTES) {
      throw new RangeError("the broker channel buffer is too small to be a channel");
    }
    const channel = new RepackedChannel(transfer.id, transfer.channel, doorbell);
    const declared = Atomics.load(channel.header, HEADER_PAYLOAD);
    if (declared !== channel.payload.byteLength) {
      throw new RangeError(`the broker channel declares ${declared} payload bytes but carries a different region`);
    }
    return channel;
  }
  transfer() {
    return { id: this.id, channel: this.buffer, doorbell: this.doorbell.buffer };
  }
  get payloadBytes() {
    return this.payload.byteLength;
  }
  state() {
    return Atomics.load(this.header, HEADER_STATE);
  }
}
function fsErrorNameOf(code) {
  for (const name of Object.keys(FS_ERRNO)) {
    if (FS_ERRNO[name] === code)
      return name;
  }
  return;
}
function errnoName(code) {
  return fsErrorNameOf(code) ?? `errno ${code}`;
}

// packages/pgwasm/src/opfs/broker/server.ts
var OK = { errno: 0, result: 0n, responseBytes: 0 };
function ok(result = 0n, responseBytes = 0) {
  return { errno: 0, result: typeof result === "bigint" ? result : BigInt(result), responseBytes };
}

class ProtocolViolation extends Error {
  constructor(message) {
    super(message);
    this.name = "ProtocolViolation";
  }
}

class RepackedSyncBroker {
  doorbell;
  #vfs;
  #now;
  #log;
  #pollIntervalMs;
  #clients = new Map;
  #serving = false;
  constructor(options) {
    this.#vfs = options.vfs;
    this.doorbell = options.doorbell;
    this.#now = options.now ?? (() => BigInt(Date.now()));
    this.#log = options.log ?? ((message) => console.warn(message));
    this.#pollIntervalMs = options.pollIntervalMs ?? 250;
  }
  attachedIds() {
    return [...this.#clients.keys()].sort((left, right) => left - right);
  }
  openFdCount(channelId) {
    if (channelId === undefined) {
      let total = 0;
      for (const client of this.#clients.values())
        total += client.fds.size;
      return total;
    }
    return this.#clients.get(channelId)?.fds.size ?? 0;
  }
  attach(channel) {
    if (this.#clients.has(channel.id))
      throw new Error(`broker channel ${channel.id} is already attached`);
    if (channel.doorbell.buffer !== this.doorbell.buffer) {
      throw new Error(`broker channel ${channel.id} rings a different doorbell`);
    }
    this.#clients.set(channel.id, { channel, fds: new Map });
  }
  detach(channel, reason = "detached by the host") {
    this.#detach(typeof channel === "number" ? channel : channel.id, reason, FAULT_DETACHED);
  }
  #detach(id, reason, fault) {
    const client = this.#clients.get(id);
    if (client === undefined)
      return;
    this.#clients.delete(id);
    this.#releaseFds(client);
    const header = client.channel.header;
    Atomics.store(header, HEADER_FAULT, fault);
    Atomics.store(header, HEADER_ERRNO, 0);
    Atomics.store(header, HEADER_RESPONSE, 0);
    Atomics.store(header, HEADER_STATE, STATE_DETACHED);
    Atomics.notify(header, HEADER_STATE);
    this.#log(`repacked broker detached channel ${id}: ${reason}`);
  }
  detachAll(reason = "broker shutting down") {
    for (const id of this.attachedIds())
      this.detach(id, reason);
  }
  serveOnce() {
    let served = 0;
    for (const client of [...this.#clients.values()]) {
      if (Atomics.load(client.channel.header, HEADER_STATE) !== STATE_REQUEST)
        continue;
      this.#answer(client);
      served += 1;
    }
    return served;
  }
  serveForever() {
    this.#enterLoop();
    try {
      while (this.doorbell.running()) {
        const observed = this.doorbell.ticket();
        if (this.serveOnce() > 0)
          continue;
        this.doorbell.wait(observed, this.#pollIntervalMs);
      }
    } finally {
      this.#serving = false;
    }
  }
  async serve() {
    this.#enterLoop();
    try {
      while (this.doorbell.running()) {
        const observed = this.doorbell.ticket();
        if (this.serveOnce() > 0)
          continue;
        await this.doorbell.waitAsync(observed, this.#pollIntervalMs);
      }
    } finally {
      this.#serving = false;
    }
  }
  #enterLoop() {
    if (this.#serving)
      throw new Error("the repacked broker is already serving");
    this.#serving = true;
  }
  #releaseFds(client) {
    for (const entry of client.fds.values()) {
      try {
        this.#vfs.close(entry.fd);
      } catch {}
    }
    client.fds.clear();
  }
  #answer(client) {
    const header = client.channel.header;
    const opcode = Atomics.load(header, HEADER_OPCODE);
    const requestBytes = Atomics.load(header, HEADER_REQUEST);
    let fault = FAULT_NONE;
    let answer = OK;
    try {
      if (!isKnownOpcode(opcode))
        throw new ProtocolViolation(`unknown opcode ${opcode}`);
      if (requestBytes < 0 || requestBytes > client.channel.payloadBytes) {
        throw new ProtocolViolation(`request length ${requestBytes} is outside the payload region`);
      }
      const reader = new PayloadReader(client.channel.payload, requestBytes);
      const writer = new PayloadWriter(client.channel.payload);
      answer = this.#dispatch(client, opcode, reader, writer);
    } catch (cause) {
      if (cause instanceof ProtocolViolation || cause instanceof PayloadDecodeError) {
        this.#detach(client.channel.id, cause.message, FAULT_PROTOCOL);
        return;
      }
      if (cause instanceof FsError) {
        answer = { errno: cause.code, result: 0n, responseBytes: 0 };
      } else {
        fault = FAULT_STORE;
        answer = this.#faultAnswer(client, cause);
      }
    }
    const { lo, hi } = splitResult(answer.result);
    Atomics.store(header, HEADER_ERRNO, answer.errno);
    Atomics.store(header, HEADER_RESULT_LO, lo);
    Atomics.store(header, HEADER_RESULT_HI, hi);
    Atomics.store(header, HEADER_RESPONSE, answer.responseBytes);
    Atomics.store(header, HEADER_FAULT, fault);
    Atomics.store(header, HEADER_STATE, STATE_RESPONSE);
    Atomics.notify(header, HEADER_STATE);
  }
  #faultAnswer(client, cause) {
    const message = cause instanceof Error ? `${cause.name}: ${cause.message}` : String(cause);
    const writer = new PayloadWriter(client.channel.payload);
    const room = client.channel.payloadBytes - 4;
    try {
      writer.string(message.length > room ? message.slice(0, Math.max(0, room)) : message);
    } catch {
      return { errno: 0, result: 0n, responseBytes: 0 };
    }
    return { errno: 0, result: 0n, responseBytes: writer.length };
  }
  #dispatch(client, opcode, reader, writer) {
    switch (opcode) {
      case OPCODE_OPEN:
        return this.#open(client, reader);
      case OPCODE_CLOSE:
        return this.#close(client, reader);
      case OPCODE_READ:
        return this.#read(client, reader);
      case OPCODE_WRITE:
        return this.#write(client, reader);
      case OPCODE_FSYNC:
        return this.#fsync(client, reader);
      case OPCODE_FSTAT:
        return this.#stat(writer, this.#vfs.fstat(this.#fd(client, reader.u32()).fd));
      case OPCODE_STAT:
        return this.#stat(writer, this.#vfs.stat(reader.string()));
      case OPCODE_LSTAT:
        return this.#stat(writer, this.#vfs.lstat(reader.string()));
      case OPCODE_READDIR:
        return this.#readdir(reader, writer);
      case OPCODE_MKDIR:
        return this.#mkdir(reader);
      case OPCODE_RMDIR:
        this.#vfs.rmdir(reader.string(), this.#now());
        return OK;
      case OPCODE_UNLINK:
        this.#vfs.unlink(reader.string(), this.#now());
        return OK;
      case OPCODE_RENAME: {
        const oldPath = reader.string();
        this.#vfs.rename(oldPath, reader.string(), this.#now());
        return OK;
      }
      case OPCODE_TRUNCATE: {
        const path = reader.string();
        this.#vfs.truncate(path, reader.u64(), this.#now());
        return OK;
      }
      case OPCODE_SIZE:
        return this.#size(reader);
      case OPCODE_SYMLINK: {
        const target = reader.string();
        this.#vfs.symlink(target, reader.string(), this.#now());
        return OK;
      }
      case OPCODE_READLINK:
        return this.#readlink(reader, writer);
      default:
        throw new ProtocolViolation(`unhandled opcode ${opcode}`);
    }
  }
  #open(client, reader) {
    const path = reader.string();
    const flags = reader.u32();
    const mode = reader.u32();
    const plan = planOpen(flags);
    const nowMs = this.#now();
    if (!plan.follow) {
      try {
        if (this.#vfs.lstat(path).kind === "symlink") {
          throw new FsError("ELOOP", "path is a symbolic link and O_NOFOLLOW was requested", { path });
        }
      } catch (cause) {
        if (!(cause instanceof FsError) || cause.code !== FS_ERRNO.ENOENT)
          throw cause;
      }
    }
    if (plan.requireExisting)
      this.#vfs.lstat(path);
    if (plan.truncateFirst)
      this.#vfs.truncate(path, 0n, nowMs);
    let fd;
    try {
      fd = this.#vfs.open(path, plan.coreFlags, mode, nowMs);
    } catch (cause) {
      if (plan.fallbackFlags === undefined || !(cause instanceof FsError) || cause.code !== FS_ERRNO.ENOENT) {
        throw cause;
      }
      fd = this.#vfs.open(path, plan.fallbackFlags, mode, nowMs);
    }
    client.fds.set(fd, { fd, readable: plan.readable, writable: plan.writable });
    return ok(fd);
  }
  #close(client, reader) {
    const entry = this.#fd(client, reader.u32());
    this.#vfs.close(entry.fd);
    client.fds.delete(entry.fd);
    return OK;
  }
  #read(client, reader) {
    const entry = this.#fd(client, reader.u32());
    if (!entry.readable)
      throw new FsError("EBADF", "descriptor was not opened for reading");
    const hasPosition = reader.u8() === 1;
    const position = reader.u64();
    const length = reader.u32();
    if (length > client.channel.payloadBytes) {
      throw new ProtocolViolation(`read length ${length} exceeds the payload region`);
    }
    const target = client.channel.payload.subarray(0, length);
    const count = hasPosition ? this.#vfs.read(entry.fd, target, 0, length, position) : this.#vfs.read(entry.fd, target, 0, length);
    return ok(count, count);
  }
  #write(client, reader) {
    const entry = this.#fd(client, reader.u32());
    if (!entry.writable)
      throw new FsError("EBADF", "descriptor was not opened for writing");
    const hasPosition = reader.u8() === 1;
    const position = reader.u64();
    const length = reader.u32();
    const source = reader.bytes(length);
    const count = this.#vfs.write(entry.fd, source, 0, length, hasPosition ? position : undefined, this.#now());
    return ok(count);
  }
  #fsync(client, reader) {
    if (reader.u8() === 1)
      this.#fd(client, reader.u32());
    this.#vfs.strictSync();
    return OK;
  }
  #stat(writer, stat) {
    writeStat(writer, stat);
    return ok(stat.size, writer.length);
  }
  #readdir(reader, writer) {
    const path = reader.string();
    const cursor = reader.u32();
    const names = this.#vfs.readdir(path);
    if (cursor > names.length)
      throw new ProtocolViolation(`readdir cursor ${cursor} is past the listing`);
    const countAt = writer.length;
    writer.u32(0);
    writer.i32(READDIR_DONE);
    let emitted = 0;
    let next = READDIR_DONE;
    for (let index = cursor;index < names.length; index += 1) {
      const before = writer.length;
      try {
        writer.string(names[index]);
      } catch (cause) {
        if (!(cause instanceof PayloadOverflowError))
          throw cause;
        writer.rewind(before);
        if (emitted === 0)
          throw cause;
        next = index;
        break;
      }
      emitted += 1;
    }
    const counters = writer.patch(countAt, 8);
    counters.setUint32(0, emitted, true);
    counters.setInt32(4, next, true);
    return ok(emitted, writer.length);
  }
  #mkdir(reader) {
    const path = reader.string();
    const recursive = reader.u8() === 1;
    const mode = reader.u32();
    this.#vfs.mkdir(path, { recursive, mode, nowMs: this.#now() });
    return OK;
  }
  #readlink(reader, writer) {
    writer.string(this.#vfs.readlink(reader.string()));
    return ok(writer.length, writer.length);
  }
  #size(reader) {
    const stat = this.#vfs.stat(reader.string());
    if (stat.kind !== "file")
      throw new FsError("EISDIR", "size is a file query");
    return ok(stat.size);
  }
  #fd(client, fd) {
    const entry = client.fds.get(fd);
    if (entry === undefined)
      throw new FsError("EBADF", `descriptor ${fd} is not owned by this client`);
    return entry;
  }
}
// packages/pgwasm/src/opfs/broker/client.ts
class RepackedBrokerTransportError extends Error {
  brokerCode;
  constructor(brokerCode, message) {
    super(message);
    this.name = "RepackedBrokerTransportError";
    this.brokerCode = brokerCode;
  }
}

class RepackedBrokerStoreError extends Error {
  brokerCode = "store";
  constructor(message) {
    super(`the repacked store behind the broker failed: ${message}`);
    this.name = "RepackedBrokerStoreError";
  }
}
var DEFAULT_REQUEST_TIMEOUT_MS = 30000;
var TRANSFER_OVERHEAD_BYTES = 4 + 1 + 8 + 4;

class RepackedSyncClient {
  channel;
  #timeoutMs;
  #reply;
  #sequence = 0;
  constructor(channel, options = {}) {
    this.channel = channel;
    this.#timeoutMs = options.requestTimeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS;
    this.#reply = new Uint8Array(channel.payloadBytes);
  }
  get maxTransferBytes() {
    return this.channel.payloadBytes - TRANSFER_OVERHEAD_BYTES;
  }
  open(path, flags, mode = 33206) {
    const reply = this.#call(OPCODE_OPEN, (writer) => {
      writer.string(path);
      writer.u32(flags);
      writer.u32(mode);
    });
    return { errno: reply.errno, fd: reply.errno === 0 ? Number(reply.result) : -1 };
  }
  close(fd) {
    return { errno: this.#call(OPCODE_CLOSE, (writer) => writer.u32(fd)).errno };
  }
  read(fd, length, position) {
    if (!Number.isSafeInteger(length) || length < 0) {
      throw new RangeError("a broker read length must be a non-negative safe integer");
    }
    const output = new Uint8Array(length);
    let filled = 0;
    let errno = 0;
    while (filled < length) {
      const want = Math.min(length - filled, this.maxTransferBytes);
      const at = position === undefined ? undefined : position + BigInt(filled);
      const reply = this.#call(OPCODE_READ, (writer) => {
        writer.u32(fd);
        writer.u8(at === undefined ? 0 : 1);
        writer.u64(at ?? 0n);
        writer.u32(want);
      });
      if (reply.errno !== 0) {
        errno = reply.errno;
        break;
      }
      output.set(reply.bytes, filled);
      filled += reply.bytes.byteLength;
      if (reply.bytes.byteLength < want)
        break;
    }
    return { errno, count: filled, bytes: output.subarray(0, filled) };
  }
  write(fd, bytes, position) {
    let written = 0;
    let errno = 0;
    while (written < bytes.byteLength) {
      const chunk = bytes.subarray(written, written + Math.min(bytes.byteLength - written, this.maxTransferBytes));
      const at = position === undefined ? undefined : position + BigInt(written);
      const reply = this.#call(OPCODE_WRITE, (writer) => {
        writer.u32(fd);
        writer.u8(at === undefined ? 0 : 1);
        writer.u64(at ?? 0n);
        writer.u32(chunk.byteLength);
        writer.bytes(chunk);
      });
      if (reply.errno !== 0) {
        errno = reply.errno;
        break;
      }
      const count = Number(reply.result);
      written += count;
      if (count < chunk.byteLength)
        break;
    }
    return { errno, count: written };
  }
  fsync(fd) {
    return {
      errno: this.#call(OPCODE_FSYNC, (writer) => {
        writer.u8(fd === undefined ? 0 : 1);
        writer.u32(fd ?? 0);
      }).errno
    };
  }
  fstat(fd) {
    return this.#statCall(OPCODE_FSTAT, (writer) => writer.u32(fd));
  }
  stat(path) {
    return this.#statCall(OPCODE_STAT, (writer) => writer.string(path));
  }
  lstat(path) {
    return this.#statCall(OPCODE_LSTAT, (writer) => writer.string(path));
  }
  symlink(target, path) {
    return {
      errno: this.#call(OPCODE_SYMLINK, (writer) => {
        writer.string(target);
        writer.string(path);
      }).errno
    };
  }
  readlink(path) {
    const reply = this.#call(OPCODE_READLINK, (writer) => writer.string(path));
    if (reply.errno !== 0)
      return { errno: reply.errno, target: undefined };
    return { errno: 0, target: new PayloadReader(reply.bytes, reply.bytes.byteLength).string() };
  }
  readdir(path) {
    const entries = [];
    let cursor = 0;
    while (cursor !== undefined) {
      const page = this.readdirPage(path, cursor);
      if (page.errno !== 0)
        return { errno: page.errno, entries: [] };
      entries.push(...page.entries);
      cursor = page.nextCursor;
    }
    return { errno: 0, entries };
  }
  readdirPage(path, cursor = 0) {
    const reply = this.#call(OPCODE_READDIR, (writer) => {
      writer.string(path);
      writer.u32(cursor);
    });
    if (reply.errno !== 0)
      return { errno: reply.errno, entries: [], nextCursor: undefined };
    const reader = new PayloadReader(reply.bytes, reply.bytes.byteLength);
    const count = reader.u32();
    const next = reader.i32();
    const entries = [];
    for (let index = 0;index < count; index += 1)
      entries.push(reader.string());
    return { errno: 0, entries, nextCursor: next === READDIR_DONE ? undefined : next };
  }
  mkdir(path, options = {}) {
    return {
      errno: this.#call(OPCODE_MKDIR, (writer) => {
        writer.string(path);
        writer.u8(options.recursive === true ? 1 : 0);
        writer.u32(options.mode ?? 16895);
      }).errno
    };
  }
  rmdir(path) {
    return { errno: this.#call(OPCODE_RMDIR, (writer) => writer.string(path)).errno };
  }
  unlink(path) {
    return { errno: this.#call(OPCODE_UNLINK, (writer) => writer.string(path)).errno };
  }
  rename(oldPath, newPath) {
    return {
      errno: this.#call(OPCODE_RENAME, (writer) => {
        writer.string(oldPath);
        writer.string(newPath);
      }).errno
    };
  }
  truncate(path, size) {
    return {
      errno: this.#call(OPCODE_TRUNCATE, (writer) => {
        writer.string(path);
        writer.u64(size);
      }).errno
    };
  }
  size(path) {
    const reply = this.#call(OPCODE_SIZE, (writer) => writer.string(path));
    return { errno: reply.errno, size: reply.errno === 0 ? reply.result : 0n };
  }
  #statCall(opcode, encode) {
    const reply = this.#call(opcode, encode);
    if (reply.errno !== 0)
      return { errno: reply.errno, stat: undefined };
    return { errno: 0, stat: readStat(new PayloadReader(reply.bytes, reply.bytes.byteLength)) };
  }
  #call(opcode, encode) {
    const header = this.channel.header;
    const state = Atomics.load(header, HEADER_STATE);
    if (state === STATE_DETACHED) {
      throw new RepackedBrokerTransportError("detached", "the repacked broker detached this client");
    }
    if (state === STATE_REQUEST) {
      throw new RepackedBrokerTransportError("protocol", "a repacked broker request is already in flight");
    }
    const writer = new PayloadWriter(this.channel.payload);
    encode(writer);
    this.#sequence = this.#sequence + 1 | 0;
    Atomics.store(header, HEADER_SEQUENCE, this.#sequence);
    Atomics.store(header, HEADER_OPCODE, opcode);
    Atomics.store(header, HEADER_REQUEST, writer.length);
    Atomics.store(header, HEADER_RESPONSE, 0);
    Atomics.store(header, HEADER_ERRNO, 0);
    Atomics.store(header, HEADER_FAULT, FAULT_NONE);
    Atomics.store(header, HEADER_STATE, STATE_REQUEST);
    this.channel.doorbell.ring();
    while (Atomics.load(header, HEADER_STATE) === STATE_REQUEST) {
      const outcome = Atomics.wait(header, HEADER_STATE, STATE_REQUEST, this.#timeoutMs);
      if (outcome === "timed-out" && Atomics.load(header, HEADER_STATE) === STATE_REQUEST) {
        throw new RepackedBrokerTransportError("timeout", `the repacked broker did not answer opcode ${opcode} within ${this.#timeoutMs} ms`);
      }
    }
    const responseBytes = Atomics.load(header, HEADER_RESPONSE);
    const fault = Atomics.load(header, HEADER_FAULT);
    const errno = Atomics.load(header, HEADER_ERRNO);
    const result = joinResult(Atomics.load(header, HEADER_RESULT_LO), Atomics.load(header, HEADER_RESULT_HI));
    let bytes = new Uint8Array;
    if (responseBytes > 0 && responseBytes <= this.channel.payloadBytes) {
      this.#reply.set(this.channel.payload.subarray(0, responseBytes));
      bytes = this.#reply.subarray(0, responseBytes);
    }
    if (Atomics.load(header, HEADER_STATE) === STATE_DETACHED) {
      throw new RepackedBrokerTransportError(fault === FAULT_PROTOCOL ? "protocol" : "detached", fault === FAULT_PROTOCOL ? `the repacked broker rejected opcode ${opcode} as a protocol violation and detached this client` : "the repacked broker detached this client");
    }
    if (Atomics.load(header, HEADER_STATE) !== STATE_RESPONSE) {
      throw new RepackedBrokerTransportError("protocol", "the repacked broker left the channel in an unknown state");
    }
    Atomics.store(header, HEADER_STATE, STATE_IDLE);
    if (fault === FAULT_STORE)
      throw new RepackedBrokerStoreError(this.#faultMessage(bytes));
    if (fault !== FAULT_NONE) {
      throw new RepackedBrokerTransportError("protocol", `the repacked broker reported fault ${fault}`);
    }
    return { errno, result, bytes };
  }
  #faultMessage(bytes) {
    if (bytes.byteLength === 0)
      return "no detail was reported";
    try {
      return new PayloadReader(bytes, bytes.byteLength).string();
    } catch {
      return "the fault detail was malformed";
    }
  }
}
function throwOnErrno(result, operation, path) {
  if (result.errno === 0)
    return;
  const name = fsErrorNameOf(result.errno);
  const detail = `${operation} failed with ${errnoName(result.errno)}`;
  if (name === undefined)
    throw new RepackedBrokerTransportError("protocol", `${detail} (unknown to the core)`);
  throw new FsError(name, detail, path === undefined ? { operation } : { operation, path });
}
// packages/pgwasm/src/opfs/wasi/preview1.ts
var WASI_ERRNO = {
  SUCCESS: 0,
  ACCES: 2,
  BADF: 8,
  EXIST: 20,
  INVAL: 28,
  IO: 29,
  ISDIR: 31,
  LOOP: 32,
  NOENT: 44,
  NOSYS: 52,
  NOTDIR: 54,
  NOTEMPTY: 55,
  NOTSUP: 58,
  OVERFLOW: 61,
  PERM: 63,
  SPIPE: 70,
  NOTCAPABLE: 76
};
var WASI_FILETYPE = {
  UNKNOWN: 0,
  BLOCK_DEVICE: 1,
  CHARACTER_DEVICE: 2,
  DIRECTORY: 3,
  REGULAR_FILE: 4,
  SOCKET_DGRAM: 5,
  SOCKET_STREAM: 6,
  SYMBOLIC_LINK: 7
};
var OFLAGS_CREAT = 1;
var OFLAGS_DIRECTORY = 2;
var OFLAGS_EXCL = 4;
var OFLAGS_TRUNC = 8;
var FDFLAGS_APPEND = 1;
var FDFLAGS_DSYNC = 2;
var FDFLAGS_NONBLOCK = 4;
var FDFLAGS_RSYNC = 8;
var FDFLAGS_SYNC = 16;
var LOOKUPFLAGS_SYMLINK_FOLLOW = 1;
var RIGHTS_FD_READ = 1n << 1n;
var RIGHTS_FD_WRITE = 1n << 6n;
var RIGHTS_ALL = 0xffffffffffffffffn;
var WHENCE_SET = 0;
var WHENCE_CUR = 1;
var WHENCE_END = 2;
var FILESTAT_BYTES = 64;
var DIRENT_HEADER_BYTES = 24;
var DIRECTORY_SIZE = 4096n;
var NS_PER_MS = 1000000n;
var FD_ARGUMENT_INDEX = {
  fd_prestat_get: 0,
  fd_prestat_dir_name: 0,
  fd_close: 0,
  fd_read: 0,
  fd_pread: 0,
  fd_write: 0,
  fd_pwrite: 0,
  fd_seek: 0,
  fd_tell: 0,
  fd_fdstat_get: 0,
  fd_fdstat_set_flags: 0,
  fd_fdstat_set_rights: 0,
  fd_filestat_get: 0,
  fd_filestat_set_size: 0,
  fd_filestat_set_times: 0,
  fd_readdir: 0,
  fd_sync: 0,
  fd_datasync: 0,
  fd_allocate: 0,
  fd_advise: 0,
  path_open: 0,
  path_filestat_get: 0,
  path_filestat_set_times: 0,
  path_create_directory: 0,
  path_remove_directory: 0,
  path_unlink_file: 0,
  path_rename: 0,
  path_readlink: 0,
  path_symlink: 2,
  path_link: 0
};
var textEncoder3 = new TextEncoder;
var textDecoder3 = new TextDecoder("utf-8", { fatal: false });
function normalizeWasiPath(path) {
  let value = path.replace(/\0+$/u, "");
  if (value === "" || value === ".")
    return "/";
  if (!value.startsWith("/"))
    value = `/${value}`;
  const parts = [];
  for (const segment of value.split("/")) {
    if (segment === "" || segment === ".")
      continue;
    if (segment === "..") {
      parts.pop();
      continue;
    }
    parts.push(segment);
  }
  return `/${parts.join("/")}`;
}
function inodeOf(path) {
  let hash = 0xcbf29ce484222325n;
  const bytes = textEncoder3.encode(path);
  for (const byte of bytes) {
    hash = BigInt.asUintN(64, (hash ^ BigInt(byte)) * 0x1000000001b3n);
  }
  return hash === 0n ? 1n : hash;
}
function toBigInt(value) {
  return typeof value === "bigint" ? value : BigInt(Math.trunc(value));
}
function createWasiPreview1Fs(options) {
  const client = options.client;
  const preopenFd = options.preopenFd ?? 3;
  const preopenPath = normalizeWasiPath(options.preopenPath ?? "/");
  const fdBase = options.fdBase ?? preopenFd + 1;
  const now = options.now ?? (() => BigInt(Date.now()));
  const onError = options.onError ?? ((call, cause) => {
    const detail = cause instanceof Error ? cause.stack ?? `${cause.name}: ${cause.message}` : String(cause);
    console.error(`[wasi-preview1 ${call} @${now()}] ${detail}`);
  });
  if (!Number.isSafeInteger(preopenFd) || preopenFd < 3) {
    throw new RangeError("a WASI preopen fd must be a safe integer of at least 3 (0-2 are stdio)");
  }
  if (!Number.isSafeInteger(fdBase) || fdBase <= preopenFd) {
    throw new RangeError("the WASI adapter fd base must be a safe integer above the preopen fd");
  }
  const table = new Map;
  let nextFd = fdBase;
  const preopenEntry = () => ({
    fd: preopenFd,
    path: preopenPath,
    isDir: true,
    clientFd: undefined,
    offset: 0n,
    fdflags: 0,
    rightsBase: RIGHTS_ALL,
    rightsInheriting: RIGHTS_ALL,
    readable: true,
    writable: false,
    listing: undefined
  });
  table.set(preopenFd, preopenEntry());
  const bytes = () => new Uint8Array(options.memory());
  const view = () => new DataView(options.memory());
  function readGuestString(ptr, length) {
    return textDecoder3.decode(bytes().slice(ptr, ptr + length));
  }
  function* iovecs(ptr, count) {
    const data = view();
    for (let index = 0;index < count; index += 1) {
      const base = ptr + index * 8;
      yield { ptr: data.getUint32(base, true), len: data.getUint32(base + 4, true) };
    }
  }
  function owns(fd) {
    return fd === preopenFd || Number.isSafeInteger(fd) && fd >= fdBase;
  }
  function entryOf(fd) {
    return table.get(fd);
  }
  function allocate(entry) {
    const fd = nextFd;
    nextFd += 1;
    table.set(fd, { ...entry, fd });
    return fd;
  }
  function resolve(dirfd, ptr, length) {
    const dir = entryOf(dirfd);
    if (dir === undefined || !dir.isDir)
      return;
    const relative = readGuestString(ptr, length);
    if (relative.startsWith("/"))
      return normalizeWasiPath(relative);
    return normalizeWasiPath(dir.path === "/" ? `/${relative}` : `${dir.path}/${relative}`);
  }
  function filetypeOf(kind) {
    if (kind === "directory")
      return WASI_FILETYPE.DIRECTORY;
    return kind === "symlink" ? WASI_FILETYPE.SYMBOLIC_LINK : WASI_FILETYPE.REGULAR_FILE;
  }
  function writeFilestat(ptr, path, stat) {
    bytes().fill(0, ptr, ptr + FILESTAT_BYTES);
    const data = view();
    const isDirectory = stat.kind === "directory";
    const times = [stat.atimeMs, stat.mtimeMs, stat.ctimeMs].map((ms) => ms * NS_PER_MS);
    data.setBigUint64(ptr + 0, 1n, true);
    data.setBigUint64(ptr + 8, inodeOf(path), true);
    data.setUint8(ptr + 16, filetypeOf(stat.kind));
    data.setBigUint64(ptr + 24, 1n, true);
    data.setBigUint64(ptr + 32, isDirectory ? DIRECTORY_SIZE : stat.size, true);
    data.setBigUint64(ptr + 40, times[0], true);
    data.setBigUint64(ptr + 48, times[1], true);
    data.setBigUint64(ptr + 56, times[2], true);
  }
  function sizeOf(entry) {
    if (entry.clientFd === undefined)
      return { errno: 0, size: DIRECTORY_SIZE };
    const stat = client.fstat(entry.clientFd);
    if (stat.errno !== 0 || stat.stat === undefined)
      return { errno: stat.errno || WASI_ERRNO.IO, size: 0n };
    return { errno: 0, size: stat.stat.size };
  }
  const fs = {
    fd_prestat_get(fd, resultPtr) {
      if (fd !== preopenFd)
        return WASI_ERRNO.BADF;
      const data = view();
      data.setUint8(resultPtr, 0);
      data.setUint32(resultPtr + 4, textEncoder3.encode(preopenPath).byteLength, true);
      return WASI_ERRNO.SUCCESS;
    },
    fd_prestat_dir_name(fd, pathPtr, pathLen) {
      if (fd !== preopenFd)
        return WASI_ERRNO.BADF;
      const encoded = textEncoder3.encode(preopenPath);
      if (pathLen < encoded.byteLength)
        return WASI_ERRNO.INVAL;
      bytes().set(encoded, pathPtr);
      return WASI_ERRNO.SUCCESS;
    },
    fd_close(fd) {
      if (fd === preopenFd)
        return WASI_ERRNO.SUCCESS;
      const entry = entryOf(fd);
      if (entry === undefined)
        return WASI_ERRNO.BADF;
      table.delete(fd);
      if (entry.clientFd === undefined)
        return WASI_ERRNO.SUCCESS;
      return client.close(entry.clientFd).errno;
    },
    fd_read(fd, iovsPtr, iovsLen, nreadPtr) {
      const entry = entryOf(fd);
      if (entry === undefined)
        return WASI_ERRNO.BADF;
      if (entry.clientFd === undefined)
        return WASI_ERRNO.ISDIR;
      if (!entry.readable)
        return WASI_ERRNO.NOTCAPABLE;
      let total = 0;
      let errno = WASI_ERRNO.SUCCESS;
      for (const { ptr, len } of iovecs(iovsPtr, iovsLen)) {
        if (len === 0)
          continue;
        const chunk = client.read(entry.clientFd, len, entry.offset + BigInt(total));
        if (chunk.count > 0)
          bytes().set(chunk.bytes, ptr);
        total += chunk.count;
        if (chunk.errno !== 0) {
          errno = chunk.errno;
          break;
        }
        if (chunk.count < len)
          break;
      }
      entry.offset += BigInt(total);
      view().setUint32(nreadPtr, total, true);
      return total > 0 ? WASI_ERRNO.SUCCESS : errno;
    },
    fd_pread(fd, iovsPtr, iovsLen, offset, nreadPtr) {
      const entry = entryOf(fd);
      if (entry === undefined)
        return WASI_ERRNO.BADF;
      if (entry.clientFd === undefined)
        return WASI_ERRNO.ISDIR;
      if (!entry.readable)
        return WASI_ERRNO.NOTCAPABLE;
      let at = toBigInt(offset);
      let total = 0;
      let errno = WASI_ERRNO.SUCCESS;
      for (const { ptr, len } of iovecs(iovsPtr, iovsLen)) {
        if (len === 0)
          continue;
        const chunk = client.read(entry.clientFd, len, at);
        if (chunk.count > 0)
          bytes().set(chunk.bytes, ptr);
        at += BigInt(chunk.count);
        total += chunk.count;
        if (chunk.errno !== 0) {
          errno = chunk.errno;
          break;
        }
        if (chunk.count < len)
          break;
      }
      view().setUint32(nreadPtr, total, true);
      return total > 0 ? WASI_ERRNO.SUCCESS : errno;
    },
    fd_write(fd, iovsPtr, iovsLen, nwrittenPtr) {
      const entry = entryOf(fd);
      if (entry === undefined)
        return WASI_ERRNO.BADF;
      if (entry.clientFd === undefined)
        return WASI_ERRNO.ISDIR;
      if (!entry.writable)
        return WASI_ERRNO.NOTCAPABLE;
      if ((entry.fdflags & FDFLAGS_APPEND) !== 0) {
        const end = sizeOf(entry);
        if (end.errno !== 0)
          return end.errno;
        entry.offset = end.size;
      }
      let total = 0;
      let errno = WASI_ERRNO.SUCCESS;
      for (const { ptr, len } of iovecs(iovsPtr, iovsLen)) {
        if (len === 0)
          continue;
        const source = bytes().subarray(ptr, ptr + len);
        const written = client.write(entry.clientFd, source, entry.offset + BigInt(total));
        total += written.count;
        if (written.errno !== 0) {
          errno = written.errno;
          break;
        }
        if (written.count < len)
          break;
      }
      entry.offset += BigInt(total);
      view().setUint32(nwrittenPtr, total, true);
      return total > 0 ? WASI_ERRNO.SUCCESS : errno;
    },
    fd_pwrite(fd, iovsPtr, iovsLen, offset, nwrittenPtr) {
      const entry = entryOf(fd);
      if (entry === undefined)
        return WASI_ERRNO.BADF;
      if (entry.clientFd === undefined)
        return WASI_ERRNO.ISDIR;
      if (!entry.writable)
        return WASI_ERRNO.NOTCAPABLE;
      let at = toBigInt(offset);
      let total = 0;
      let errno = WASI_ERRNO.SUCCESS;
      for (const { ptr, len } of iovecs(iovsPtr, iovsLen)) {
        if (len === 0)
          continue;
        const written = client.write(entry.clientFd, bytes().subarray(ptr, ptr + len), at);
        at += BigInt(written.count);
        total += written.count;
        if (written.errno !== 0) {
          errno = written.errno;
          break;
        }
        if (written.count < len)
          break;
      }
      view().setUint32(nwrittenPtr, total, true);
      return total > 0 ? WASI_ERRNO.SUCCESS : errno;
    },
    fd_seek(fd, offset, whence, resultPtr) {
      const entry = entryOf(fd);
      if (entry === undefined)
        return WASI_ERRNO.BADF;
      if (entry.clientFd === undefined)
        return WASI_ERRNO.BADF;
      const delta = toBigInt(offset);
      let target;
      if (whence === WHENCE_SET)
        target = delta;
      else if (whence === WHENCE_CUR)
        target = entry.offset + delta;
      else if (whence === WHENCE_END) {
        const end = sizeOf(entry);
        if (end.errno !== 0)
          return end.errno;
        target = end.size + delta;
      } else
        return WASI_ERRNO.INVAL;
      if (target < 0n)
        return WASI_ERRNO.INVAL;
      entry.offset = target;
      view().setBigUint64(resultPtr, target, true);
      return WASI_ERRNO.SUCCESS;
    },
    fd_tell(fd, resultPtr) {
      const entry = entryOf(fd);
      if (entry === undefined)
        return WASI_ERRNO.BADF;
      if (entry.clientFd === undefined)
        return WASI_ERRNO.BADF;
      view().setBigUint64(resultPtr, entry.offset, true);
      return WASI_ERRNO.SUCCESS;
    },
    fd_fdstat_get(fd, resultPtr) {
      const entry = entryOf(fd);
      if (entry === undefined)
        return WASI_ERRNO.BADF;
      const data = view();
      data.setUint8(resultPtr, entry.isDir ? WASI_FILETYPE.DIRECTORY : WASI_FILETYPE.REGULAR_FILE);
      data.setUint8(resultPtr + 1, 0);
      data.setUint16(resultPtr + 2, entry.fdflags, true);
      data.setUint32(resultPtr + 4, 0, true);
      data.setBigUint64(resultPtr + 8, entry.rightsBase, true);
      data.setBigUint64(resultPtr + 16, entry.rightsInheriting, true);
      return WASI_ERRNO.SUCCESS;
    },
    fd_fdstat_set_flags(fd, fdflags) {
      const entry = entryOf(fd);
      if (entry === undefined)
        return WASI_ERRNO.BADF;
      entry.fdflags = fdflags & (FDFLAGS_APPEND | FDFLAGS_DSYNC | FDFLAGS_NONBLOCK | FDFLAGS_RSYNC | FDFLAGS_SYNC);
      return WASI_ERRNO.SUCCESS;
    },
    fd_fdstat_set_rights(fd, rightsBase, rightsInheriting) {
      const entry = entryOf(fd);
      if (entry === undefined)
        return WASI_ERRNO.BADF;
      const base = toBigInt(rightsBase);
      const inheriting = toBigInt(rightsInheriting);
      if ((base & ~entry.rightsBase) !== 0n || (inheriting & ~entry.rightsInheriting) !== 0n) {
        return WASI_ERRNO.NOTCAPABLE;
      }
      entry.rightsBase = base;
      entry.rightsInheriting = inheriting;
      return WASI_ERRNO.SUCCESS;
    },
    fd_filestat_get(fd, resultPtr) {
      const entry = entryOf(fd);
      if (entry === undefined)
        return WASI_ERRNO.BADF;
      const stat = entry.clientFd === undefined ? client.stat(entry.path) : client.fstat(entry.clientFd);
      if (stat.errno !== 0 || stat.stat === undefined)
        return stat.errno || WASI_ERRNO.IO;
      writeFilestat(resultPtr, entry.path, stat.stat);
      return WASI_ERRNO.SUCCESS;
    },
    fd_filestat_set_size(fd, size) {
      const entry = entryOf(fd);
      if (entry === undefined)
        return WASI_ERRNO.BADF;
      if (entry.clientFd === undefined)
        return WASI_ERRNO.ISDIR;
      if (!entry.writable)
        return WASI_ERRNO.NOTCAPABLE;
      return client.truncate(entry.path, toBigInt(size)).errno;
    },
    fd_filestat_set_times(fd, _atim, _mtim, fstflags) {
      const entry = entryOf(fd);
      if (entry === undefined)
        return WASI_ERRNO.BADF;
      if ((fstflags & ~15) !== 0)
        return WASI_ERRNO.INVAL;
      if (fstflags === 0)
        return WASI_ERRNO.SUCCESS;
      return WASI_ERRNO.NOTSUP;
    },
    fd_readdir(fd, bufPtr, bufLen, cookie, bufusedPtr) {
      const entry = entryOf(fd);
      if (entry === undefined)
        return WASI_ERRNO.BADF;
      if (!entry.isDir)
        return WASI_ERRNO.NOTDIR;
      const start = Number(toBigInt(cookie));
      if (!Number.isSafeInteger(start) || start < 0)
        return WASI_ERRNO.INVAL;
      if (start === 0 || entry.listing === undefined) {
        const listed = client.readdir(entry.path);
        if (listed.errno !== 0)
          return listed.errno;
        entry.listing = { names: listed.entries, filetypes: new Map };
      }
      const listing = entry.listing;
      const data = view();
      const memory = bytes();
      let used = 0;
      for (let index = start;index < listing.names.length; index += 1) {
        const name = listing.names[index];
        const nameBytes = textEncoder3.encode(name);
        if (used + DIRENT_HEADER_BYTES >= bufLen) {
          used = bufLen;
          break;
        }
        let filetype = listing.filetypes.get(name);
        if (filetype === undefined) {
          const child = client.lstat(entry.path === "/" ? `/${name}` : `${entry.path}/${name}`);
          filetype = child.errno !== 0 || child.stat === undefined ? WASI_FILETYPE.UNKNOWN : filetypeOf(child.stat.kind);
          listing.filetypes.set(name, filetype);
        }
        const at = bufPtr + used;
        data.setBigUint64(at, BigInt(index + 1), true);
        data.setBigUint64(at + 8, inodeOf(entry.path === "/" ? `/${name}` : `${entry.path}/${name}`), true);
        data.setUint32(at + 16, nameBytes.byteLength, true);
        data.setUint8(at + 20, filetype);
        data.setUint8(at + 21, 0);
        data.setUint16(at + 22, 0, true);
        const room = bufLen - used - DIRENT_HEADER_BYTES;
        const copied = Math.min(nameBytes.byteLength, room);
        memory.set(nameBytes.subarray(0, copied), at + DIRENT_HEADER_BYTES);
        used += DIRENT_HEADER_BYTES + copied;
        if (copied < nameBytes.byteLength)
          break;
      }
      data.setUint32(bufusedPtr, used, true);
      return WASI_ERRNO.SUCCESS;
    },
    fd_sync(fd) {
      const entry = entryOf(fd);
      if (entry === undefined)
        return WASI_ERRNO.BADF;
      return entry.clientFd === undefined ? client.fsync().errno : client.fsync(entry.clientFd).errno;
    },
    fd_datasync(fd) {
      return fs.fd_sync(fd);
    },
    fd_allocate(fd, offset, length) {
      const entry = entryOf(fd);
      if (entry === undefined)
        return WASI_ERRNO.BADF;
      if (entry.clientFd === undefined)
        return WASI_ERRNO.ISDIR;
      if (!entry.writable)
        return WASI_ERRNO.NOTCAPABLE;
      const end = toBigInt(offset) + toBigInt(length);
      if (end < 0n)
        return WASI_ERRNO.INVAL;
      const current = sizeOf(entry);
      if (current.errno !== 0)
        return current.errno;
      if (end <= current.size)
        return WASI_ERRNO.SUCCESS;
      return client.truncate(entry.path, end).errno;
    },
    fd_advise(fd, _offset, _length, _advice) {
      return entryOf(fd) === undefined ? WASI_ERRNO.BADF : WASI_ERRNO.SUCCESS;
    },
    path_open(dirfd, dirflags, pathPtr, pathLen, oflags, rightsBase, rightsInheriting, fdflags, resultPtr) {
      const path = resolve(dirfd, pathPtr, pathLen);
      if (path === undefined)
        return WASI_ERRNO.BADF;
      const followLinks = (dirflags & LOOKUPFLAGS_SYMLINK_FOLLOW) !== 0;
      const base = toBigInt(rightsBase);
      const inheriting = toBigInt(rightsInheriting);
      const wantsRead = (base & RIGHTS_FD_READ) !== 0n;
      const wantsWrite = (base & RIGHTS_FD_WRITE) !== 0n;
      const create = (oflags & OFLAGS_CREAT) !== 0;
      const exclusive = (oflags & OFLAGS_EXCL) !== 0;
      const truncate = (oflags & OFLAGS_TRUNC) !== 0;
      const directory = (oflags & OFLAGS_DIRECTORY) !== 0;
      const readable = wantsRead || !wantsWrite;
      const writable = wantsWrite;
      const openDirectory = () => {
        const stat = followLinks ? client.stat(path) : client.lstat(path);
        if (stat.errno !== 0 || stat.stat === undefined)
          return stat.errno || WASI_ERRNO.IO;
        if (stat.stat.kind === "symlink")
          return WASI_ERRNO.LOOP;
        if (stat.stat.kind !== "directory")
          return WASI_ERRNO.NOTDIR;
        if (create && exclusive)
          return WASI_ERRNO.EXIST;
        const fd = allocate({
          path,
          isDir: true,
          clientFd: undefined,
          offset: 0n,
          fdflags: 0,
          rightsBase: base === 0n ? RIGHTS_ALL : base,
          rightsInheriting: inheriting === 0n ? RIGHTS_ALL : inheriting,
          readable: true,
          writable: false,
          listing: undefined
        });
        view().setUint32(resultPtr, fd, true);
        return WASI_ERRNO.SUCCESS;
      };
      if (directory)
        return openDirectory();
      const posixWrite = writable || create || truncate;
      const posixRead = readable || !posixWrite;
      let flags = posixRead && posixWrite ? O_RDWR : posixWrite ? O_WRONLY : O_RDONLY;
      if (create)
        flags |= O_CREAT;
      if (exclusive)
        flags |= O_EXCL;
      if (truncate)
        flags |= O_TRUNC;
      if (!followLinks)
        flags |= O_NOFOLLOW;
      const opened = client.open(path, flags);
      if (opened.errno !== 0) {
        if (opened.errno === WASI_ERRNO.ISDIR)
          return create && exclusive ? WASI_ERRNO.EXIST : openDirectory();
        return opened.errno;
      }
      const fd = allocate({
        path,
        isDir: false,
        clientFd: opened.fd,
        offset: 0n,
        fdflags: fdflags & (FDFLAGS_APPEND | FDFLAGS_DSYNC | FDFLAGS_NONBLOCK | FDFLAGS_RSYNC | FDFLAGS_SYNC),
        rightsBase: base === 0n ? RIGHTS_ALL : base,
        rightsInheriting: inheriting === 0n ? RIGHTS_ALL : inheriting,
        readable,
        writable,
        listing: undefined
      });
      view().setUint32(resultPtr, fd, true);
      return WASI_ERRNO.SUCCESS;
    },
    path_filestat_get(dirfd, flags, pathPtr, pathLen, resultPtr) {
      const path = resolve(dirfd, pathPtr, pathLen);
      if (path === undefined)
        return WASI_ERRNO.BADF;
      const follow = (flags & LOOKUPFLAGS_SYMLINK_FOLLOW) !== 0;
      const stat = follow ? client.stat(path) : client.lstat(path);
      if (stat.errno !== 0 || stat.stat === undefined)
        return stat.errno || WASI_ERRNO.IO;
      writeFilestat(resultPtr, path, stat.stat);
      return WASI_ERRNO.SUCCESS;
    },
    path_filestat_set_times(dirfd, _flags, pathPtr, pathLen, _atim, _mtim, fstflags) {
      const path = resolve(dirfd, pathPtr, pathLen);
      if (path === undefined)
        return WASI_ERRNO.BADF;
      if ((fstflags & ~15) !== 0)
        return WASI_ERRNO.INVAL;
      const stat = client.lstat(path);
      if (stat.errno !== 0)
        return stat.errno;
      if (fstflags === 0)
        return WASI_ERRNO.SUCCESS;
      return WASI_ERRNO.NOTSUP;
    },
    path_create_directory(dirfd, pathPtr, pathLen) {
      const path = resolve(dirfd, pathPtr, pathLen);
      if (path === undefined)
        return WASI_ERRNO.BADF;
      return client.mkdir(path).errno;
    },
    path_remove_directory(dirfd, pathPtr, pathLen) {
      const path = resolve(dirfd, pathPtr, pathLen);
      if (path === undefined)
        return WASI_ERRNO.BADF;
      return client.rmdir(path).errno;
    },
    path_unlink_file(dirfd, pathPtr, pathLen) {
      const path = resolve(dirfd, pathPtr, pathLen);
      if (path === undefined)
        return WASI_ERRNO.BADF;
      return client.unlink(path).errno;
    },
    path_rename(dirfd, oldPtr, oldLen, newDirfd, newPtr, newLen) {
      const oldPath = resolve(dirfd, oldPtr, oldLen);
      const newPath = resolve(newDirfd, newPtr, newLen);
      if (oldPath === undefined || newPath === undefined)
        return WASI_ERRNO.BADF;
      const result = client.rename(oldPath, newPath);
      if (result.errno !== 0)
        return result.errno;
      const prefix = oldPath === "/" ? "/" : `${oldPath}/`;
      for (const entry of table.values()) {
        if (entry.path === oldPath)
          entry.path = newPath;
        else if (entry.path.startsWith(prefix))
          entry.path = newPath + entry.path.slice(oldPath.length);
      }
      return WASI_ERRNO.SUCCESS;
    },
    path_readlink(dirfd, pathPtr, pathLen, bufPtr, bufLen, bufusedPtr) {
      const path = resolve(dirfd, pathPtr, pathLen);
      if (path === undefined)
        return WASI_ERRNO.BADF;
      const link = client.readlink(path);
      if (link.errno !== 0 || link.target === undefined)
        return link.errno || WASI_ERRNO.IO;
      const encoded = textEncoder3.encode(link.target);
      const copied = Math.min(encoded.byteLength, bufLen);
      if (copied > 0)
        bytes().set(encoded.subarray(0, copied), bufPtr);
      view().setUint32(bufusedPtr, copied, true);
      return WASI_ERRNO.SUCCESS;
    },
    path_symlink(oldPtr, oldLen, dirfd, newPtr, newLen) {
      const path = resolve(dirfd, newPtr, newLen);
      if (path === undefined)
        return WASI_ERRNO.BADF;
      const target = readGuestString(oldPtr, oldLen).replace(/\0+$/u, "");
      return client.symlink(target, path).errno;
    },
    path_link(oldDirfd, _oldFlags, _oldPtr, _oldLen, newDirfd, _newPtr, _newLen) {
      if (entryOf(oldDirfd)?.isDir !== true || entryOf(newDirfd)?.isDir !== true)
        return WASI_ERRNO.BADF;
      return WASI_ERRNO.NOTSUP;
    }
  };
  const guarded = {};
  for (const name of Object.keys(fs)) {
    const inner = fs[name];
    guarded[name] = (...args) => {
      try {
        return inner(...args);
      } catch (cause) {
        onError(name, cause);
        return WASI_ERRNO.IO;
      }
    };
  }
  const adapter = guarded;
  adapter.owns = owns;
  adapter.openFdCount = () => table.size - (table.has(preopenFd) ? 1 : 0);
  adapter.closeAll = () => {
    let released = 0;
    for (const entry of table.values()) {
      if (entry.clientFd === undefined)
        continue;
      client.close(entry.clientFd);
      released += 1;
    }
    table.clear();
    table.set(preopenFd, preopenEntry());
    nextFd = fdBase;
    return released;
  };
  adapter.compose = (base) => {
    const merged = { ...base };
    for (const [name, index] of Object.entries(FD_ARGUMENT_INDEX)) {
      const mine = guarded[name];
      const theirs = base[name];
      if (typeof theirs !== "function") {
        merged[name] = (...args) => owns(Number(args[index])) ? mine(...args) : WASI_ERRNO.BADF;
        continue;
      }
      const fallback = theirs;
      merged[name] = (...args) => owns(Number(args[index])) ? mine(...args) : fallback(...args);
    }
    return merged;
  };
  return adapter;
}
export {
  CorruptStoreError,
  DEFAULT_PAYLOAD_BYTES,
  DurabilityModeMismatchError,
  ExtentSizeMismatchError,
  FileRepackedPort,
  FsError,
  MemoryRepackedPort,
  MountedRepackedVfs,
  O_APPEND,
  O_CREAT,
  O_EXCL,
  O_NOFOLLOW,
  O_RDONLY,
  O_RDWR,
  O_TRUNC,
  O_WRONLY,
  OpfsRepackedFS,
  OpfsRepackedPort,
  RepackedBrokerStoreError,
  RepackedBrokerTransportError,
  RepackedChannel,
  RepackedDoorbell,
  RepackedSyncBroker,
  RepackedSyncClient,
  RepackedVfs,
  StoreClosedError,
  StoreFailedError,
  StoreLimitError,
  StoreOwnedError,
  StoreRecreationRequiredError,
  UnexpectedStoreEntryError,
  WASI_ERRNO,
  WASI_FILETYPE,
  createOpfsPgwasm,
  createWasiPreview1Fs,
  errnoName,
  fsErrorNameOf,
  normalizeWasiPath,
  planOpen,
  strictSync,
  throwOnErrno
};

//# debugId=C6DDC6F2B59C0DC864756E2164756E21