Format everything (#211)

This commit is contained in:
Chenlei Hu
2024-07-23 15:40:54 -04:00
committed by GitHub
parent 648e52e39c
commit 1b7db43f8a
25 changed files with 1014 additions and 526 deletions

View File

@@ -20,7 +20,10 @@ export class EzConnection {
link;
get originNode() {
return new EzNode(this.app, this.app.graph.getNodeById(this.link.origin_id));
return new EzNode(
this.app,
this.app.graph.getNodeById(this.link.origin_id)
);
}
get originOutput() {
@@ -28,7 +31,10 @@ export class EzConnection {
}
get targetNode() {
return new EzNode(this.app, this.app.graph.getNodeById(this.link.target_id));
return new EzNode(
this.app,
this.app.graph.getNodeById(this.link.target_id)
);
}
get targetInput() {
@@ -121,7 +127,11 @@ export class EzOutput extends EzSlot {
/**
* @type { LG["LLink"] | null }
*/
const link = this.node.node.connect(this.index, input.node.node, input.index);
const link = this.node.node.connect(
this.index,
input.node.node,
input.index
);
if (!link) {
const inp = input.input;
const inName = inp.name || inp.label || inp.type;
@@ -155,11 +165,21 @@ export class EzNodeMenuItem {
}
call(selectNode = true) {
if (!this.item?.callback) throw new Error(`Menu Item ${this.item?.content ?? "[null]"} has no callback.`);
if (!this.item?.callback)
throw new Error(
`Menu Item ${this.item?.content ?? "[null]"} has no callback.`
);
if (selectNode) {
this.node.select();
}
return this.item.callback.call(this.node.node, undefined, undefined, undefined, undefined, this.node.node);
return this.item.callback.call(
this.node.node,
undefined,
undefined,
undefined,
undefined,
this.node.node
);
}
}
@@ -188,7 +208,7 @@ export class EzWidget {
set value(v) {
this.widget.value = v;
this.widget.callback?.call?.(this.widget, v)
this.widget.callback?.call?.(this.widget, v);
}
get isConvertedToInput() {
@@ -197,24 +217,35 @@ export class EzWidget {
}
getConvertedInput() {
if (!this.isConvertedToInput) throw new Error(`Widget ${this.widget.name} is not converted to input.`);
if (!this.isConvertedToInput)
throw new Error(`Widget ${this.widget.name} is not converted to input.`);
return this.node.inputs.find((inp) => inp.input["widget"]?.name === this.widget.name);
return this.node.inputs.find(
(inp) => inp.input["widget"]?.name === this.widget.name
);
}
convertToWidget() {
if (!this.isConvertedToInput)
throw new Error(`Widget ${this.widget.name} cannot be converted as it is already a widget.`);
throw new Error(
`Widget ${this.widget.name} cannot be converted as it is already a widget.`
);
var menu = this.node.menu["Convert Input to Widget"].item.submenu.options;
var index = menu.findIndex(a => a.content == `Convert ${this.widget.name} to widget`);
var index = menu.findIndex(
(a) => a.content == `Convert ${this.widget.name} to widget`
);
menu[index].callback.call();
}
convertToInput() {
if (this.isConvertedToInput)
throw new Error(`Widget ${this.widget.name} cannot be converted as it is already an input.`);
throw new Error(
`Widget ${this.widget.name} cannot be converted as it is already an input.`
);
var menu = this.node.menu["Convert Widget to Input"].item.submenu.options;
var index = menu.findIndex(a => a.content == `Convert ${this.widget.name} to input`);
var index = menu.findIndex(
(a) => a.content == `Convert ${this.widget.name} to input`
);
menu[index].callback.call();
}
}
@@ -251,7 +282,11 @@ export class EzNode {
}
get menu() {
return this.#makeLookupArray(() => this.app.canvas.getNodeMenuOptions(this.node), "content", EzNodeMenuItem);
return this.#makeLookupArray(
() => this.app.canvas.getNodeMenuOptions(this.node),
"content",
EzNodeMenuItem
);
}
get isRemoved() {
@@ -287,25 +322,33 @@ export class EzNode {
* @returns { Record<string, InstanceType<T>> & Array<InstanceType<T>> }
*/
#makeLookupArray(nodeProperty, nameProperty, ctor) {
const items = typeof nodeProperty === "function" ? nodeProperty() : this.node[nodeProperty];
const items =
typeof nodeProperty === "function"
? nodeProperty()
: this.node[nodeProperty];
// @ts-ignore
return (items ?? []).reduce((p, s, i) => {
if (!s) return p;
return (items ?? []).reduce(
(p, s, i) => {
if (!s) return p;
const name = s[nameProperty];
const item = new ctor(this, i, s);
// @ts-ignore
p.push(item);
if (name) {
const name = s[nameProperty];
const item = new ctor(this, i, s);
// @ts-ignore
if (name in p) {
throw new Error(`Unable to store ${nodeProperty} ${name} on array as name conflicts.`);
p.push(item);
if (name) {
// @ts-ignore
if (name in p) {
throw new Error(
`Unable to store ${nodeProperty} ${name} on array as name conflicts.`
);
}
}
}
// @ts-ignore
p[name] = item;
return p;
}, Object.assign([], { $: this }));
// @ts-ignore
p[name] = item;
return p;
},
Object.assign([], { $: this })
);
}
}
@@ -388,28 +431,28 @@ export class EzGraph {
}
export const Ez = {
/**
* Quickly build and interact with a ComfyUI graph
* @example
* const { ez, graph } = Ez.graph(app);
* graph.clear();
* const [model, clip, vae] = ez.CheckpointLoaderSimple().outputs;
* const [pos] = ez.CLIPTextEncode(clip, { text: "positive" }).outputs;
* const [neg] = ez.CLIPTextEncode(clip, { text: "negative" }).outputs;
* const [latent] = ez.KSampler(model, pos, neg, ...ez.EmptyLatentImage().outputs).outputs;
* const [image] = ez.VAEDecode(latent, vae).outputs;
* const saveNode = ez.SaveImage(image);
* console.log(saveNode);
* graph.arrange();
* @param { app } app
* @param { boolean } clearGraph
* @param { LG["LiteGraph"] } LiteGraph
* @param { LG["LGraphCanvas"] } LGraphCanvas
* @returns { { graph: EzGraph, ez: Record<string, EzNodeFactory> } }
*/
graph(app, LiteGraph, LGraphCanvas, clearGraph = true) {
// Always set the active canvas so things work
LGraphCanvas.active_canvas = app.canvas;
/**
* Quickly build and interact with a ComfyUI graph
* @example
* const { ez, graph } = Ez.graph(app);
* graph.clear();
* const [model, clip, vae] = ez.CheckpointLoaderSimple().outputs;
* const [pos] = ez.CLIPTextEncode(clip, { text: "positive" }).outputs;
* const [neg] = ez.CLIPTextEncode(clip, { text: "negative" }).outputs;
* const [latent] = ez.KSampler(model, pos, neg, ...ez.EmptyLatentImage().outputs).outputs;
* const [image] = ez.VAEDecode(latent, vae).outputs;
* const saveNode = ez.SaveImage(image);
* console.log(saveNode);
* graph.arrange();
* @param { app } app
* @param { boolean } clearGraph
* @param { LG["LiteGraph"] } LiteGraph
* @param { LG["LGraphCanvas"] } LGraphCanvas
* @returns { { graph: EzGraph, ez: Record<string, EzNodeFactory> } }
*/
graph(app, LiteGraph, LGraphCanvas, clearGraph = true) {
// Always set the active canvas so things work
LGraphCanvas.active_canvas = app.canvas;
if (clearGraph) {
app.graph.clear();

View File

@@ -4,7 +4,7 @@ import lg from "./litegraph";
import fs from "fs";
import path from "path";
const html = fs.readFileSync(path.resolve(__dirname, "../../index.html"))
const html = fs.readFileSync(path.resolve(__dirname, "../../index.html"));
interface StartConfig extends APIConfig {
resetEnv?: boolean;
@@ -20,18 +20,18 @@ interface StartResult {
/**
*
* @param { Parameters<typeof mockApi>[0] & {
* resetEnv?: boolean,
* @param { Parameters<typeof mockApi>[0] & {
* resetEnv?: boolean,
* preSetup?(app): Promise<void>,
* localStorage?: Record<string, string>
* localStorage?: Record<string, string>
* } } config
* @returns
*/
export async function start(config: StartConfig = {}): Promise<StartResult> {
if(config.resetEnv) {
if (config.resetEnv) {
jest.resetModules();
jest.resetAllMocks();
lg.setup(global);
lg.setup(global);
localStorage.clear();
sessionStorage.clear();
}
@@ -39,14 +39,14 @@ export async function start(config: StartConfig = {}): Promise<StartResult> {
Object.assign(localStorage, config.localStorage ?? {});
document.body.innerHTML = html.toString();
mockApi(config);
const { app } = await import("../../src/scripts/app");
const { LiteGraph, LGraphCanvas } = await import("@comfyorg/litegraph");
config.preSetup?.(app);
await app.setup();
mockApi(config);
const { app } = await import("../../src/scripts/app");
const { LiteGraph, LGraphCanvas } = await import("@comfyorg/litegraph");
config.preSetup?.(app);
await app.setup();
// @ts-ignore
return { ...Ez.graph(app, LiteGraph, LGraphCanvas), app };
// @ts-ignore
return { ...Ez.graph(app, LiteGraph, LGraphCanvas), app };
}
/**
@@ -77,7 +77,8 @@ export function makeNodeDef(name, input, output = {}) {
},
};
for (const k in input) {
nodeDef.input.required[k] = typeof input[k] === "string" ? [input[k], {}] : [...input[k]];
nodeDef.input.required[k] =
typeof input[k] === "string" ? [input[k], {}] : [...input[k]];
}
if (output instanceof Array) {
output = output.reduce((p, c) => {
@@ -143,4 +144,4 @@ export async function getNodeDefs() {
export async function getNodeDef(nodeId) {
return (await getNodeDefs())[nodeId];
}
}

View File

@@ -18,14 +18,12 @@ function forEachKey(cb) {
}
export default {
setup(ctx) {
setup(ctx) {},
},
teardown(ctx) {
// forEachKey((k) => delete ctx[k]);
teardown(ctx) {
// forEachKey((k) => delete ctx[k]);
// Clear document after each run
document.getElementsByTagName("html")[0].innerHTML = "";
}
};
},
};

View File

@@ -17,7 +17,11 @@ export interface APIConfig {
mockExtensions?: string[];
mockNodeDefs?: Record<string, any>;
settings?: Record<string, string>;
userConfig?: { storage: "server" | "browser"; users?: Record<string, any>; migrated?: boolean };
userConfig?: {
storage: "server" | "browser";
users?: Record<string, any>;
migrated?: boolean;
};
userData?: Record<string, any>;
}
@@ -29,9 +33,9 @@ export interface APIConfig {
* @param {{
* mockExtensions?: string[],
* mockNodeDefs?: Record<string, ComfyObjectInfo>,
* settings?: Record<string, string>
* userConfig?: {storage: "server" | "browser", users?: Record<string, any>, migrated?: boolean },
* userData?: Record<string, any>
* settings?: Record<string, string>
* userConfig?: {storage: "server" | "browser", users?: Record<string, any>, migrated?: boolean },
* userData?: Record<string, any>
* }} config
*/
export function mockApi(config: APIConfig = {}) {
@@ -46,7 +50,9 @@ export function mockApi(config: APIConfig = {}) {
.map((x) => path.relative(path.resolve("./src/"), x).replace(/\\/g, "/"));
}
if (!mockNodeDefs) {
mockNodeDefs = JSON.parse(fs.readFileSync(path.resolve("./tests-ui/data/object_info.json")));
mockNodeDefs = JSON.parse(
fs.readFileSync(path.resolve("./tests-ui/data/object_info.json"))
);
}
const events = new EventTarget();
@@ -62,14 +68,16 @@ export function mockApi(config: APIConfig = {}) {
fileURL: jest.fn((x) => "src/" + x),
createUser: jest.fn((username) => {
// @ts-ignore
if(username in userConfig.users) {
return { status: 400, json: () => "Duplicate" }
if (username in userConfig.users) {
return { status: 400, json: () => "Duplicate" };
}
// @ts-ignore
userConfig.users[username + "!"] = username;
return { status: 200, json: () => username + "!" }
return { status: 200, json: () => username + "!" };
}),
getUserConfig: jest.fn(() => userConfig ?? { storage: "browser", migrated: false }),
getUserConfig: jest.fn(
() => userConfig ?? { storage: "browser", migrated: false }
),
getSettings: jest.fn(() => settings),
storeSettings: jest.fn((v) => Object.assign(settings, v)),
getUserData: jest.fn((f) => {