jsに書き直して。

import { api, app } from "../../scripts/app.js";

class FileGroupsMuter {
    static title = "FileGroupsMuter";
    static desc = "Reads group states from JSON file";
    static category = "test";
    static input = false;
    static output = false;
    static outputs = [];

    properties = {
        filePath: { value: "", type: "string" },
        refreshInterval: { value: 5000, type: "number" },
    };

    widgets: any[] = [];
    tempSize: number[] | null = null;

    static setUp() {
        // ノードタイプを登録
        api.registerNodeType({
            title: this.title,
            desc: this.desc,
            input: this.input,
            output: this.output,
            outputs: this.outputs,
            category: this.category,
            functions: {
                loadFromFile: this.prototype.loadFromFile,
            },
        });
    }

    async loadFromFile() {
        try {
            const response = await fetch(this.properties.filePath.value);
            if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`);

            const json = await response.json();
            const enableGroups = json.enable || [];
            const muteGroups = json.mute || [];
            this.updateGroupsFromState(enableGroups, muteGroups);
        } catch (error) {
            console.error("Error loading JSON file:", error);
        }
    }

    updateGroupsFromState(enableGroups: string[], muteGroups: string[]) {
        const groups = app.graph._groups;

        // 全てのグループを一旦ミュート解除
        groups.forEach((group: any) => {
            this.setGroupMode(group, true);
        });

        // JSONで指定されたグループをミュート
        groups.forEach((group: any) => {
            if (muteGroups.includes(group.title)) {
                this.setGroupMode(group, false);
            }
        });

        this.refreshWidgets(enableGroups, muteGroups);
    }

    setGroupMode(group: any, enabled: boolean) {
        if (group.recomputeInsideNodes) group.recomputeInsideNodes();
        group._nodes.forEach((node: any) => {
            node.mode = enabled ? 0 : 2;
        });

        // 状態をlocalStorageに保存
        const storedState = JSON.parse(localStorage.getItem("groupStates") || "{}");
        storedState[group.title] = enabled;
        localStorage.setItem("groupStates", JSON.stringify(storedState));

        app.graph.setDirtyCanvas(true, false);
    }

    refreshWidgets(enableGroups: string[], muteGroups: string[]) {
        // 既存のウィジェットをクリア
        this.widgets = [];

        // 有効グループセクション
        this.widgets.push({ type: "text", text: "Enabled Groups" });
        enableGroups.forEach((title: string) => {
            this.widgets.push({
                type: "button",
                text: `Enable ${title}`,
                callback: () => this.toggleGroup(title, true)
            });
        });

        // ミュートグループセクション
        this.widgets.push({ type: "text", text: "Muted Groups" });
        muteGroups.forEach((title: string) => {
            this.widgets.push({
                type: "button",
                text: `Mute ${title}`,
                callback: () => this.toggleGroup(title, false)
            });
        });
    }

    toggleGroup(title: string, enabled: boolean) {
        const group = app.graph._groups.find((g: any) => g.title === title);
        if (group) this.setGroupMode(group, enabled);
    }

    computeSize(out?: number[]): number[] {
        return [200, 100];
    }
}

// ComfyUI拡張機能として登録
app.registerExtension({
    name: "custom.FileGroupsMuter",
    registerCustomNodes() {
        LiteGraph.registerNodeType({
            title: FileGroupsMuter.title,
            desc: FileGroupsMuter.desc,
            input: FileGroupsMuter.input,
            output: FileGroupsMuter.output,
            outputs: FileGroupsMuter.outputs,
            category: FileGroupsMuter.category,
            functions: {
                loadFromFile: FileGroupsMuter.prototype.loadFromFile,
            },
        });
    },
    loadedGraphNode(node: any) {
        if (node.type === FileGroupsMuter.title) {
            (node as any).tempSize = [...node.size];
        }
    },
});
        }
    },
});