Files
olivv-cs-ComfyUI-FunPack/tools/devserver.py
T
digital-garbage 835fab7864 core+shell: the bridge, and the first module through it
One declaration does three jobs: renders the panel, carries the defaults, names
the values that come back. A module writes no DOM and reads no DOM.

Validation refuses rather than repairs -- unknown type, a renderer its type does
not have, a label that is not text, a default outside its own bounds, a when
naming a key the module never declared. A module that is wrong does not get a
best-effort panel; it does not load, and says why once.

Ordering is by declared relation and stage, never priority numbers, and a cycle
drops only the modules in it. Compatibility is by trait, never model name.

The shell hands a module { composer, values, on, shell } and nothing else: no
node, no document, no kit internals. It cannot style anything because it is
never given anything that could.

catalogue/hide.html puts one good module and five broken ones through the real
shell and shows the result: one panel, five absent, no placeholders. The lint
fixtures make the scanner prove it catches each rule, so a clean scan means
something.

First slice: modules/system/appearance. Two settings, an optional ui.js, and
clicking Light actually turns the app light.
2026-08-28 19:58:06 +03:00

64 lines
2.3 KiB
Python

"""Dev server: serves the app exactly as ComfyUI will, without ComfyUI.
Routes through core.serve, so the extension allowlist and the traversal guard are
exercised every time you look at the catalogue.
python tools/devserver.py [port]
"""
import json
import sys
from http.server import BaseHTTPRequestHandler, HTTPServer
from pathlib import Path
from urllib.parse import parse_qs, unquote, urlparse
sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
from core import config, routes, serve as static # noqa: E402
P = config.UI_PREFIX
class Handler(BaseHTTPRequestHandler):
def do_GET(self):
parsed = urlparse(self.path)
path = unquote(parsed.path)
# The same manifest the aiohttp route serves, so what you see in the
# browser here is what ComfyUI would send.
if path == P + "/api/modules":
raw = parse_qs(parsed.query).get("traits")
traits = [t for t in raw[0].split(",") if t] if raw else None
body = json.dumps(routes.manifest(traits)).encode()
served = static.Served(200, body, "application/json")
elif path in (P, P + "/"):
served = static.serve(config.APP_DIR, "index.html", config.APP_EXTS)
elif path.startswith(P + "/app/"):
served = static.serve(config.APP_DIR, path[len(P) + 5:], config.APP_EXTS)
elif path.startswith(P + "/modules/"):
served = static.serve(config.MODULES_DIR, path[len(P) + 9:], config.MODULE_EXTS)
elif path == "/":
self.send_response(302)
self.send_header("Location", P + "/")
self.end_headers()
return
else:
served = static.Served(404)
self.send_response(served.status)
self.send_header("Content-Type", served.content_type)
self.send_header("Content-Length", str(len(served.body)))
for k, v in served.headers.items():
self.send_header(k, v)
self.end_headers()
self.wfile.write(served.body)
def log_message(self, fmt, *args):
sys.stderr.write("%s %s\n" % (self.address_string(), fmt % args))
if __name__ == "__main__":
port = int(sys.argv[1]) if len(sys.argv) > 1 else 8188
print(f"FunPack v5 dev server: http://127.0.0.1:{port}{P}/")
HTTPServer(("127.0.0.1", port), Handler).serve_forever()