import { DurableObject, RpcTarget, WorkerEntrypoint } from "cloudflare:workers";
import { timingSafeEqual } from "node:crypto";

//#region ../node_modules/.bun/dofs@0.1.0+0530043001070a11/node_modules/dofs/dist/index.js
var Fs = class extends RpcTarget {
	ctx;
	env;
	chunkSize;
	constructor(ctx, env, options) {
		super();
		this.env = env;
		this.ctx = ctx;
		this.chunkSize = options?.chunkSize ?? 64 * 1024;
		this.ctx.blockConcurrencyWhile(async () => {
			this.ensureSchema();
		});
	}
	readFile(path, options) {
		const ino = this.resolvePathToInode(path);
		const statRow = this.ctx.storage.sql.exec("SELECT attr FROM dofs_files WHERE ino = ?", ino).next().value;
		if (!statRow || !statRow.attr) throw new Error("ENOENT");
		const fileSize = (typeof statRow.attr === "string" ? JSON.parse(statRow.attr) : statRow.attr).size || 0;
		let currentOffset = 0;
		const self = this;
		return new ReadableStream({ pull(controller) {
			console.log("pull", {
				currentOffset,
				fileSize
			});
			if (currentOffset >= fileSize) {
				controller.close();
				return;
			}
			const readLength = Math.min(self.chunkSize, fileSize - currentOffset);
			const chunkRow = self.ctx.storage.sql.exec("SELECT data FROM dofs_chunks WHERE ino = ? AND offset = ? LIMIT 1", ino, currentOffset).next().value;
			let chunk;
			if (chunkRow && chunkRow.data) if (chunkRow.data instanceof ArrayBuffer) chunk = new Uint8Array(chunkRow.data);
			else if (ArrayBuffer.isView(chunkRow.data)) chunk = new Uint8Array(chunkRow.data.buffer);
			else if (typeof chunkRow.data === "string") chunk = Uint8Array.from(chunkRow.data);
			else chunk = new Uint8Array(0);
			else chunk = new Uint8Array(0);
			console.log("chunk", { chunk });
			controller.enqueue(chunk);
			currentOffset += readLength;
		} });
	}
	async writeFile(path, data, options) {
		try {
			this.unlink(path);
		} catch (e) {
			if (!(e instanceof Error && e.message === "ENOENT")) throw e;
		}
		const deviceSize = this.getDeviceSize();
		const spaceUsed = this.getSpaceUsed();
		this.create(path);
		if (typeof data === "object" && data !== null && typeof data.getReader === "function") {
			let offset = 0;
			let total = 0;
			const reader = data.getReader();
			while (true) {
				const { value, done } = await reader.read();
				if (done) break;
				if (!value) continue;
				if (spaceUsed + total + value.length > deviceSize) throw Object.assign(/* @__PURE__ */ new Error("ENOSPC"), { code: "ENOSPC" });
				this.write(path, value, {
					offset,
					encoding: options?.encoding
				});
				offset += value.length;
				total += value.length;
			}
			return;
		}
		if (typeof data === "string") {
			const buf = new TextEncoder().encode(data);
			if (spaceUsed + buf.length > deviceSize) throw Object.assign(/* @__PURE__ */ new Error("ENOSPC"), { code: "ENOSPC" });
			this.write(path, buf, {
				offset: 0,
				encoding: options?.encoding
			});
			return;
		}
		if (data instanceof ArrayBuffer) {
			const buf = new Uint8Array(data);
			if (spaceUsed + buf.length > deviceSize) throw Object.assign(/* @__PURE__ */ new Error("ENOSPC"), { code: "ENOSPC" });
			this.write(path, buf, {
				offset: 0,
				encoding: options?.encoding
			});
			return;
		}
		if (ArrayBuffer.isView(data)) {
			const buf = new Uint8Array(data.buffer);
			if (spaceUsed + buf.length > deviceSize) throw Object.assign(/* @__PURE__ */ new Error("ENOSPC"), { code: "ENOSPC" });
			this.write(path, buf, {
				offset: 0,
				encoding: options?.encoding
			});
			return;
		}
		throw new Error("Unsupported data type for writeFile");
	}
	read(path, options) {
		const ino = this.resolvePathToInode(path);
		const offset = options?.offset ?? 0;
		const length = options?.length ?? void 0;
		const cursor = this.ctx.storage.sql.exec("SELECT offset, data, length FROM dofs_chunks WHERE ino = ? ORDER BY offset ASC", ino);
		let chunks = [];
		let fileEnd = 0;
		for (let row of cursor) if (row.data && (row.data instanceof ArrayBuffer || ArrayBuffer.isView(row.data))) {
			const arr = row.data instanceof ArrayBuffer ? new Uint8Array(row.data) : new Uint8Array(row.data.buffer);
			chunks.push({
				offset: Number(row.offset),
				data: arr
			});
			fileEnd = Math.max(fileEnd, Number(row.offset) + arr.length);
		}
		const end = length !== void 0 ? offset + length : fileEnd;
		const result = new Uint8Array(end - offset);
		for (const chunk of chunks) {
			const chunkStart = chunk.offset;
			const chunkEnd = chunk.offset + chunk.data.length;
			const readStart = Math.max(offset, chunkStart);
			const readEnd = Math.min(end, chunkEnd);
			if (readStart < readEnd) {
				const destStart = readStart - offset;
				const srcStart = readStart - chunkStart;
				const len = readEnd - readStart;
				result.set(chunk.data.subarray(srcStart, srcStart + len), destStart);
			}
		}
		return result.buffer;
	}
	write(path, data, options) {
		let ino;
		try {
			ino = this.resolvePathToInode(path);
		} catch (e) {
			if (e instanceof Error && e.message === "ENOENT") {
				this.create(path);
				ino = this.resolvePathToInode(path);
			} else throw e;
		}
		const offset = options?.offset ?? 0;
		const buf = typeof data === "string" ? new TextEncoder().encode(data) : new Uint8Array(data);
		const deviceSize = this.getDeviceSize();
		const spaceUsed = this.getSpaceUsed();
		const fileRow = this.ctx.storage.sql.exec("SELECT attr FROM dofs_files WHERE ino = ?", ino).next().value;
		let fileSize = 0;
		if (fileRow && fileRow.attr) fileSize = (typeof fileRow.attr === "string" ? JSON.parse(fileRow.attr) : fileRow.attr).size || 0;
		const endOffset = offset + buf.length;
		if (spaceUsed + (endOffset > fileSize ? endOffset - fileSize : 0) > deviceSize) throw Object.assign(/* @__PURE__ */ new Error("ENOSPC"), { code: "ENOSPC" });
		const CHUNK_SIZE = this.chunkSize;
		let written = 0;
		let maxEnd = 0;
		while (written < buf.length) {
			const absOffset = offset + written;
			const chunkOffset = Math.floor(absOffset / CHUNK_SIZE) * CHUNK_SIZE;
			const chunkOffInChunk = absOffset % CHUNK_SIZE;
			const writeLen = Math.min(CHUNK_SIZE - chunkOffInChunk, buf.length - written);
			let chunkData = this.loadChunk(ino, chunkOffset, CHUNK_SIZE);
			chunkData.set(buf.subarray(written, written + writeLen), chunkOffInChunk);
			let chunkLength = CHUNK_SIZE;
			const thisEnd = chunkOffInChunk + writeLen;
			if (thisEnd < CHUNK_SIZE) chunkLength = thisEnd;
			this.ctx.storage.sql.exec("INSERT INTO dofs_chunks (ino, offset, data, length) VALUES (?, ?, ?, ?) ON CONFLICT(ino, offset) DO UPDATE SET data=excluded.data, length=excluded.length", ino, chunkOffset, chunkData.subarray(0, chunkLength), chunkLength);
			written += writeLen;
			maxEnd = Math.max(maxEnd, absOffset + writeLen);
		}
		this.updateFileSizeAndSpaceUsed(ino);
	}
	mkdir(path, options) {
		const parts = path.split("/").filter(Boolean);
		if (parts.length === 0) throw Object.assign(/* @__PURE__ */ new Error("EEXIST"), { code: "EEXIST" });
		const name = parts[parts.length - 1];
		const parentPath = "/" + parts.slice(0, -1).join("/");
		let parent;
		try {
			parent = this.resolvePathToInode(parentPath);
		} catch (e) {
			if (e.message === "ENOENT" && options?.recursive) {
				this.mkdir(parentPath, options);
				parent = this.resolvePathToInode(parentPath);
			} else throw e;
		}
		if (this.ctx.storage.sql.exec("SELECT ino FROM dofs_files WHERE parent = ? AND name = ?", parent, name).next().value) {
			if (options?.recursive) return;
			throw Object.assign(/* @__PURE__ */ new Error("EEXIST"), { code: "EEXIST" });
		}
		const ino = this.allocInode();
		const now = Date.now();
		const attr = {
			ino,
			size: 0,
			blocks: 0,
			atime: now,
			mtime: now,
			ctime: now,
			crtime: now,
			kind: "Directory",
			perm: (options?.mode ?? 493) & ~(options?.umask ?? 0) & 4095,
			nlink: 2,
			uid: 0,
			gid: 0,
			rdev: 0,
			flags: 0,
			blksize: 512
		};
		this.ctx.storage.sql.exec("INSERT INTO dofs_files (ino, name, parent, is_dir, attr, data) VALUES (?, ?, ?, ?, ?, NULL)", ino, name, parent, 1, JSON.stringify(attr));
	}
	rmdir(path, options) {
		let ino;
		try {
			ino = this.resolvePathToInode(path);
		} catch (e) {
			if (e.message === "ENOENT" && options?.recursive) return;
			throw e;
		}
		if (options?.recursive) {
			const cursor = this.ctx.storage.sql.exec("SELECT name, is_dir FROM dofs_files WHERE parent = ?", ino);
			for (let row of cursor) {
				const childPath = path === "/" ? `/${row.name}` : `${path}/${row.name}`;
				if (row.is_dir) this.rmdir(childPath, options);
				else this.unlink(childPath);
			}
		} else {
			const row = this.ctx.storage.sql.exec("SELECT COUNT(*) as count FROM dofs_files WHERE parent = ?", ino).next().value;
			if (!row) throw new Error("ENOENT");
			if (Number(row.count) > 0) throw new Error("ENOTEMPTY");
		}
		this.ctx.storage.sql.exec("DELETE FROM dofs_files WHERE ino = ?", ino);
	}
	listDir(path, options) {
		const ino = this.resolvePathToInode(path);
		const cursor = this.ctx.storage.sql.exec("SELECT name, is_dir FROM dofs_files WHERE parent = ?", ino);
		const names = [".", ".."];
		for (let row of cursor) if (typeof row.name === "string") {
			names.push(row.name);
			if (options?.recursive && row.is_dir) {
				const childPath = path === "/" ? `/${row.name}` : `${path}/${row.name}`;
				const childNames = this.listDir(childPath, options);
				for (const childName of childNames) if (childName !== "." && childName !== "..") names.push(`${row.name}/${childName}`);
			}
		}
		return names;
	}
	stat(path) {
		const ino = this.resolvePathToInode(path);
		const row = this.ctx.storage.sql.exec("SELECT attr, is_dir FROM dofs_files WHERE ino = ?", ino).next().value;
		if (!row) throw new Error("ENOENT");
		const attr = typeof row.attr === "string" ? JSON.parse(row.attr) : row.attr;
		return {
			isFile: !row.is_dir,
			isDirectory: !!row.is_dir,
			size: attr.size,
			mode: attr.perm,
			uid: attr.uid,
			gid: attr.gid,
			mtime: attr.mtime,
			ctime: attr.ctime,
			atime: attr.atime,
			crtime: attr.crtime,
			blocks: attr.blocks,
			nlink: attr.nlink,
			rdev: attr.rdev,
			flags: attr.flags,
			blksize: attr.blksize,
			kind: attr.kind
		};
	}
	setattr(path, options) {
		const ino = this.resolvePathToInode(path);
		const row = this.ctx.storage.sql.exec("SELECT attr FROM dofs_files WHERE ino = ?", ino).next().value;
		if (!row) throw new Error("ENOENT");
		const attr = typeof row.attr === "string" ? JSON.parse(row.attr) : row.attr;
		if (options.mode !== void 0) attr.perm = options.mode;
		if (options.uid !== void 0) attr.uid = options.uid;
		if (options.gid !== void 0) attr.gid = options.gid;
		this.ctx.storage.sql.exec("UPDATE dofs_files SET attr = ? WHERE ino = ?", JSON.stringify(attr), ino);
	}
	symlink(target, path) {
		const parts = path.split("/").filter(Boolean);
		if (parts.length === 0) throw new Error("EEXIST");
		const name = parts[parts.length - 1];
		const parentPath = "/" + parts.slice(0, -1).join("/");
		const parent = this.resolvePathToInode(parentPath);
		if (this.ctx.storage.sql.exec("SELECT ino FROM dofs_files WHERE parent = ? AND name = ?", parent, name).next().value) throw new Error("EEXIST");
		const ino = this.allocInode();
		const now = Date.now();
		const attr = {
			ino,
			size: target.length,
			blocks: 0,
			atime: now,
			mtime: now,
			ctime: now,
			crtime: now,
			kind: "Symlink",
			perm: 511,
			nlink: 1,
			uid: 0,
			gid: 0,
			rdev: 0,
			flags: 0,
			blksize: 512
		};
		const data = new TextEncoder().encode(target);
		this.ctx.storage.sql.exec("INSERT INTO dofs_files (ino, name, parent, is_dir, attr, data) VALUES (?, ?, ?, ?, ?, ?)", ino, name, parent, 0, JSON.stringify(attr), data);
	}
	readlink(path) {
		const ino = this.resolvePathToInode(path);
		const row = this.ctx.storage.sql.exec("SELECT data FROM dofs_files WHERE ino = ?", ino).next().value;
		if (!row || !row.data) throw new Error("ENOENT");
		let arr;
		if (row.data instanceof ArrayBuffer) arr = new Uint8Array(row.data);
		else if (ArrayBuffer.isView(row.data)) arr = new Uint8Array(row.data.buffer);
		else throw new Error("ENOENT");
		return new TextDecoder().decode(arr);
	}
	rename(oldPath, newPath) {
		const oldParts = oldPath.split("/").filter(Boolean);
		const newParts = newPath.split("/").filter(Boolean);
		if (oldParts.length === 0 || newParts.length === 0) throw Object.assign(/* @__PURE__ */ new Error("ENOENT"), { code: "ENOENT" });
		const oldName = oldParts[oldParts.length - 1];
		const oldParentPath = "/" + oldParts.slice(0, -1).join("/");
		const newName = newParts[newParts.length - 1];
		const newParentPath = "/" + newParts.slice(0, -1).join("/");
		const oldParent = this.resolvePathToInode(oldParentPath);
		const newParent = this.resolvePathToInode(newParentPath);
		const oldRow = this.ctx.storage.sql.exec("SELECT ino FROM dofs_files WHERE parent = ? AND name = ?", oldParent, oldName).next().value;
		if (!oldRow) throw Object.assign(/* @__PURE__ */ new Error("ENOENT"), { code: "ENOENT" });
		const ino = oldRow.ino;
		const newRow = this.ctx.storage.sql.exec("SELECT ino, is_dir FROM dofs_files WHERE parent = ? AND name = ?", newParent, newName).next().value;
		if (newRow) {
			if (newRow.is_dir) {
				const childRow = this.ctx.storage.sql.exec("SELECT COUNT(*) as count FROM dofs_files WHERE parent = ?", newRow.ino).next().value;
				if (childRow && Number(childRow.count) > 0) throw Object.assign(/* @__PURE__ */ new Error("ENOTEMPTY"), { code: "ENOTEMPTY" });
			}
			this.ctx.storage.sql.exec("DELETE FROM dofs_files WHERE ino = ?", newRow.ino);
			this.ctx.storage.sql.exec("DELETE FROM dofs_chunks WHERE ino = ?", newRow.ino);
		}
		this.ctx.storage.sql.exec("UPDATE dofs_files SET parent = ?, name = ? WHERE ino = ?", newParent, newName, ino);
	}
	unlink(path) {
		const ino = this.resolvePathToInode(path);
		const row = this.ctx.storage.sql.exec("SELECT is_dir FROM dofs_files WHERE ino = ?", ino).next().value;
		if (!row) throw Object.assign(/* @__PURE__ */ new Error("ENOENT"), { code: "ENOENT" });
		if (row.is_dir) throw Object.assign(/* @__PURE__ */ new Error("EISDIR"), { code: "EISDIR" });
		this.ctx.storage.sql.exec("DELETE FROM dofs_files WHERE ino = ?", ino);
		this.ctx.storage.sql.exec("DELETE FROM dofs_chunks WHERE ino = ?", ino);
		this.updateFileSizeAndSpaceUsed(ino);
	}
	create(path, options) {
		const parts = path.split("/").filter(Boolean);
		if (parts.length === 0) throw Object.assign(/* @__PURE__ */ new Error("EEXIST"), { code: "EEXIST" });
		const name = parts[parts.length - 1];
		const parentPath = "/" + parts.slice(0, -1).join("/");
		const parent = this.resolvePathToInode(parentPath);
		if (this.ctx.storage.sql.exec("SELECT ino FROM dofs_files WHERE parent = ? AND name = ?", parent, name).next().value) throw Object.assign(/* @__PURE__ */ new Error("EEXIST"), { code: "EEXIST" });
		const ino = this.allocInode();
		const now = Date.now();
		const attr = {
			ino,
			size: 0,
			blocks: 0,
			atime: now,
			mtime: now,
			ctime: now,
			crtime: now,
			kind: "File",
			perm: (options?.mode ?? 420) & ~(options?.umask ?? 0) & 4095,
			nlink: 1,
			uid: 0,
			gid: 0,
			rdev: 0,
			flags: 0,
			blksize: 512
		};
		this.ctx.storage.sql.exec("INSERT INTO dofs_files (ino, name, parent, is_dir, attr, data) VALUES (?, ?, ?, ?, ?, NULL)", ino, name, parent, 0, JSON.stringify(attr));
	}
	truncate(path, size) {
		const ino = this.resolvePathToInode(path);
		const CHUNK_SIZE = this.chunkSize;
		const firstExcessChunk = Math.floor(size / CHUNK_SIZE) * CHUNK_SIZE;
		this.ctx.storage.sql.exec("DELETE FROM dofs_chunks WHERE ino = ? AND offset >= ?", ino, firstExcessChunk);
		if (size % CHUNK_SIZE !== 0) {
			const lastChunkOffset = Math.floor(size / CHUNK_SIZE) * CHUNK_SIZE;
			const lastLen = size % CHUNK_SIZE;
			let chunkData = this.loadChunk(ino, lastChunkOffset, CHUNK_SIZE);
			chunkData = chunkData.subarray(0, lastLen);
			this.ctx.storage.sql.exec("UPDATE dofs_chunks SET data = ?, length = ? WHERE ino = ? AND offset = ?", chunkData, lastLen, ino, lastChunkOffset);
		}
		this.updateFileSizeAndSpaceUsed(ino);
	}
	getDeviceStats() {
		const size = this.getDeviceSize();
		const used = this.getSpaceUsed();
		return {
			deviceSize: size,
			spaceUsed: used,
			spaceAvailable: size - used
		};
	}
	setDeviceSize(newSize) {
		if (newSize < this.getSpaceUsed()) throw Object.assign(/* @__PURE__ */ new Error("ENOSPC"), { code: "ENOSPC" });
		this.ctx.storage.sql.exec("UPDATE dofs_meta SET value = ? WHERE key = ?", newSize.toString(), "device_size");
	}
	rootDirAttr() {
		const now = Date.now();
		return {
			ino: 1,
			size: 0,
			blocks: 0,
			atime: now,
			mtime: now,
			ctime: now,
			crtime: now,
			kind: "Directory",
			perm: 493,
			nlink: 2,
			uid: 0,
			gid: 0,
			rdev: 0,
			flags: 0,
			blksize: 512
		};
	}
	ensureSchema() {
		this.ctx.storage.sql.exec(`
      CREATE TABLE IF NOT EXISTS dofs_meta (
        key TEXT PRIMARY KEY,
        value TEXT
      );
      CREATE TABLE IF NOT EXISTS dofs_files (
        ino INTEGER PRIMARY KEY,
        name TEXT NOT NULL,
        parent INTEGER,
        is_dir INTEGER NOT NULL,
        attr BLOB,
        data BLOB
      );
      CREATE TABLE IF NOT EXISTS dofs_chunks (
        ino INTEGER NOT NULL,
        offset INTEGER NOT NULL,
        data BLOB NOT NULL,
        length INTEGER NOT NULL,
        PRIMARY KEY (ino, offset)
      );
      CREATE INDEX IF NOT EXISTS idx_dofs_files_parent_name ON dofs_files(parent, name);
      CREATE INDEX IF NOT EXISTS idx_dofs_files_parent ON dofs_files(parent);
      CREATE INDEX IF NOT EXISTS idx_dofs_files_name ON dofs_files(name);
      CREATE INDEX IF NOT EXISTS idx_dofs_chunks_ino ON dofs_chunks(ino);
      CREATE INDEX IF NOT EXISTS idx_dofs_chunks_ino_offset ON dofs_chunks(ino, offset);
    `);
		if (!this.ctx.storage.sql.exec("SELECT value FROM dofs_meta WHERE key = ?", "device_size").next().value) this.ctx.storage.sql.exec("INSERT INTO dofs_meta (key, value) VALUES (?, ?)", "device_size", (1024 * 1024 * 1024).toString());
		if (!this.ctx.storage.sql.exec("SELECT value FROM dofs_meta WHERE key = ?", "space_used").next().value) this.ctx.storage.sql.exec("INSERT INTO dofs_meta (key, value) VALUES (?, ?)", "space_used", "0");
		const row = this.ctx.storage.sql.exec("SELECT COUNT(*) as count FROM dofs_files WHERE ino = ?", 1).next().value;
		if (!row || row.count === 0) {
			const attr = this.rootDirAttr();
			this.ctx.storage.sql.exec("INSERT INTO dofs_files (ino, name, parent, is_dir, attr, data) VALUES (?, ?, ?, ?, ?, NULL)", 1, "/", void 0, 1, JSON.stringify(attr));
		}
	}
	resolvePathToInode(path) {
		if (path === "/" || path === "") return 1;
		const parts = path.split("/").filter(Boolean);
		let parent = 1;
		for (const name of parts) {
			const row = this.ctx.storage.sql.exec("SELECT ino FROM dofs_files WHERE parent = ? AND name = ?", parent, name).next().value;
			if (!row || row.ino == null) throw new Error("ENOENT");
			parent = Number(row.ino);
		}
		return parent;
	}
	allocInode() {
		const row = this.ctx.storage.sql.exec("SELECT MAX(ino) as max FROM dofs_files").next().value;
		return row && row.max != null ? Number(row.max) + 1 : 2;
	}
	loadChunk(ino, chunkOffset, chunkSize) {
		const chunkRow = this.ctx.storage.sql.exec("SELECT data FROM dofs_chunks WHERE ino = ? AND offset = ?", ino, chunkOffset).next().value;
		if (chunkRow && chunkRow.data) {
			if (chunkRow.data instanceof ArrayBuffer) return new Uint8Array(chunkRow.data);
			else if (ArrayBuffer.isView(chunkRow.data)) return new Uint8Array(chunkRow.data.buffer);
		}
		return new Uint8Array(chunkSize);
	}
	getDeviceSize() {
		const row = this.ctx.storage.sql.exec("SELECT value FROM dofs_meta WHERE key = ?", "device_size").next().value;
		return row ? Number(row.value) : 1024 * 1024 * 1024;
	}
	getSpaceUsed() {
		const row = this.ctx.storage.sql.exec("SELECT value FROM dofs_meta WHERE key = ?", "space_used").next().value;
		return row ? Number(row.value) : 0;
	}
	setSpaceUsed(val) {
		this.ctx.storage.sql.exec("UPDATE dofs_meta SET value = ? WHERE key = ?", val.toString(), "space_used");
	}
	updateFileSizeAndSpaceUsed(ino) {
		const row = this.ctx.storage.sql.exec("SELECT SUM(length) as total FROM dofs_chunks WHERE ino = ?", ino).next().value;
		const size = row && row.total ? Number(row.total) : 0;
		this.ctx.storage.sql.exec("UPDATE dofs_files SET attr = json_set(attr, \"$.size\", ?) WHERE ino = ?", size, ino);
		const usedRow = this.ctx.storage.sql.exec("SELECT SUM(length) as total FROM dofs_chunks").next().value;
		const used = usedRow && usedRow.total ? Number(usedRow.total) : 0;
		this.setSpaceUsed(used);
	}
};

//#endregion
//#region workers/dofs-state-store.ts
var dofs_state_store_default = class extends WorkerEntrypoint {
	async fetch(request) {
		if (new URL(request.url).pathname === "/health-check") return new Response("OK", { status: 200 });
		try {
			const body = {
				success: true,
				status: 200,
				result: await this.handle(request) ?? void 0
			};
			return Response.json(body, { status: body.status });
		} catch (error) {
			return APIError.fromUnknown(error).toResponse();
		}
	}
	async handle(request) {
		if (!this.authorize(request)) throw new APIError("Unauthorized", 401);
		const stub = this.getStub(request);
		const body = await this.parseBody(request);
		switch (body.method) {
			case "validate": return null;
			case "all": return await stub.all(body.params.prefix);
			case "count": return await stub.count(body.params.prefix);
			case "delete": return await stub.delete(body.params.key);
			case "get": return await stub.get(body.params.key);
			case "getBatch": return await stub.getBatch(body.params.keys);
			case "list": return await stub.list(body.params.prefix);
			case "set": return await stub.set(body.params.key, body.params.value);
			default: throw new APIError("Method not found", 404);
		}
	}
	authorize(request) {
		const token = request.headers.get("Authorization")?.split(" ")[1];
		if (!token) return false;
		const expectedBuffer = Buffer.from(this.env.DOFS_TOKEN, "utf8");
		const providedBuffer = Buffer.alloc(expectedBuffer.length);
		Buffer.from(token, "utf8").copy(providedBuffer, 0, 0, expectedBuffer.length);
		return timingSafeEqual(expectedBuffer, providedBuffer);
	}
	getStub(request) {
		const url = new URL(request.url);
		const app = url.searchParams.get("app");
		const stage = url.searchParams.get("stage");
		if (!app || !stage) throw new APIError("Missing app or stage", 400);
		return this.env.DOFS_STATE_STORE.get(this.env.DOFS_STATE_STORE.idFromName(`${app}/${stage}`));
	}
	async parseBody(request) {
		try {
			return await request.json();
		} catch {
			throw new APIError("Invalid JSON", 400);
		}
	}
};
var APIError = class APIError extends Error {
	constructor(message, status) {
		super(message);
		this.status = status;
	}
	toResponse() {
		return Response.json({
			success: false,
			status: this.status,
			error: this.message
		}, { status: this.status });
	}
	static fromUnknown(error) {
		if (error instanceof APIError) return error;
		if (error instanceof Error) return new APIError(error.message, 500);
		return new APIError("An unknown error occurred.", 500);
	}
};
var DOFSStateStore = class extends DurableObject {
	fs = new Fs(this.ctx, this.env, { chunkSize: 256 * 1024 });
	async all(prefix) {
		const keys = this.list(prefix);
		const result = {};
		await Promise.all(keys.map(async (key) => {
			const value = await this.get(`${prefix}/${key}`);
			if (value) result[key] = value;
		}));
		return result;
	}
	count(prefix) {
		return this.list(prefix).length;
	}
	delete(key) {
		if (this.isFile(`${key}.json`)) this.fs.unlink(`${key}.json`);
		if (this.isDirectory(key)) this.fs.rmdir(key);
	}
	async get(key) {
		try {
			const file = this.fs.readFile(`${key}.json`);
			return new Response(file).text();
		} catch (error) {
			if (isErrorCode(error, "ENOENT")) return;
			throw error;
		}
	}
	async getBatch(keys) {
		const result = {};
		await Promise.all(keys.map(async (key) => {
			const value = await this.get(key);
			if (value) result[key] = value;
		}));
		return result;
	}
	list(prefix) {
		const path = prefix.endsWith("/") ? prefix.slice(0, -1) : prefix;
		if (!this.isDirectory(path)) return [];
		return this.fs.listDir(path).filter((item) => item.endsWith(".json")).map((item) => item.slice(0, -5));
	}
	async set(key, value) {
		this.ensureDir(key);
		await this.fs.writeFile(`${key}.json`, JSON.stringify(value));
	}
	ensureDir(path) {
		const dir = path.split("/").slice(0, -1).join("/");
		try {
			this.fs.mkdir(dir, { recursive: true });
		} catch (error) {
			if (isErrorCode(error, "EEXIST")) return;
			throw error;
		}
	}
	stat(path) {
		try {
			const stat = this.fs.stat(path);
			if (stat.isDirectory) return "directory";
			if (stat.isFile) return "file";
			throw new APIError(`Invalid file type for ${path}`, 500);
		} catch (error) {
			if (isErrorCode(error, "ENOENT")) return "not-found";
			throw error;
		}
	}
	isFile(path) {
		return this.stat(path) === "file";
	}
	isDirectory(path) {
		return this.stat(path) === "directory";
	}
};
const isErrorCode = (error, code) => {
	return error instanceof Error && "message" in error && error.message === code;
};

//#endregion
export { DOFSStateStore, dofs_state_store_default as default };