import crypto from "node:crypto";
import fs from "node:fs/promises";
import path from "pathe";
import { getDefaultPersistPath } from "./paths.js";
const BINDING_TYPE_KEY = {
    d1: "miniflare-D1DatabaseObject",
    kv: "miniflare-KVNamespaceObject",
    r2: "miniflare-R2BucketObject",
};
/**
 * Delete a binding from the miniflare directory.
 */
export async function deleteMiniflareBinding(scope, type, id) {
    const persistRoot = path.resolve(getDefaultPersistPath(scope.rootDir));
    const bindingPath = path.join(persistRoot, type, BINDING_TYPE_KEY[type]);
    // delete durable object/sqlite files
    const namespaceId = durableObjectNamespaceIdFromName(BINDING_TYPE_KEY[type], id);
    const files = await fs
        .readdir(bindingPath)
        .then((files) => files.filter((file) => file.startsWith(namespaceId)))
        .catch(() => []);
    await Promise.all(files.map((file) => fs.rm(path.join(bindingPath, file))));
    // if running E2E tests, do not delete the data directory to prevent race conditions in smoke tests
    if (process.env.ALCHEMY_E2E)
        return;
    // delete data directory, if present
    await removeDirectory(path.join(persistRoot, type, id), {
        recursive: true,
    });
    // delete the miniflare directory if it is empty
    await cleanMiniflareDirectory(scope.dotAlchemy);
}
/**
 * Delete local durable object and workflow data for a given Worker script.
 */
export async function deleteMiniflareWorkerData(scope, scriptName, input) {
    const persistRoot = path.resolve(getDefaultPersistPath(scope.rootDir));
    await Promise.all(input.durableObjects.map((durableObject) => removeDirectory(path.join(persistRoot, "do", `${scriptName}-${durableObject.className}`), {
        recursive: true,
    })));
    await Promise.all(input.workflows.map((workflow) => removeDirectory(path.join(persistRoot, "workflows", `miniflare-workflows-${workflow.workflowName}`), {
        recursive: true,
    })));
    await cleanMiniflareDirectory(persistRoot);
}
/**
 * Delete the miniflare directory iff it is empty.
 */
async function cleanMiniflareDirectory(dotAlchemy) {
    const directory = path.resolve(dotAlchemy, "miniflare");
    const files = await fs
        .readdir(directory, {
        recursive: true,
        withFileTypes: true,
    })
        .catch((error) => {
        if (!isENOENT(error)) {
            throw error;
        }
        return [];
    });
    if (!files.some((file) => !file.isDirectory())) {
        await removeDirectory(directory, { recursive: true });
    }
}
const removeDirectory = async (path, options) => {
    try {
        await fs.rm(path, options);
    }
    catch (error) {
        if (!isENOENT(error)) {
            throw error;
        }
    }
};
const isENOENT = (error) => !!error &&
    typeof error === "object" &&
    "code" in error &&
    error.code === "ENOENT";
// copied from https://github.com/cloudflare/workers-sdk/blob/a5892915e173ca8666c04fb394e70711e87b46d8/packages/miniflare/src/plugins/shared/index.ts#L236
const durableObjectNamespaceIdFromName = (uniqueKey, name) => {
    const key = crypto.createHash("sha256").update(uniqueKey).digest();
    const nameHmac = crypto
        .createHmac("sha256", key)
        .update(name)
        .digest()
        .subarray(0, 16);
    const hmac = crypto
        .createHmac("sha256", key)
        .update(nameHmac)
        .digest()
        .subarray(0, 16);
    return Buffer.concat([nameHmac, hmac]).toString("hex");
};
//# sourceMappingURL=delete.js.map