diff --git a/.github/workflows/python-tests.yml b/.github/workflows/python-tests.yml index 3a0244fc..33f2e00c 100644 --- a/.github/workflows/python-tests.yml +++ b/.github/workflows/python-tests.yml @@ -109,6 +109,15 @@ jobs: - name: Install JS dependencies run: npm ci --ignore-scripts + - name: Typecheck frontend + run: npx tsc -p tsconfig.json --noEmit --pretty false + + - name: Build frontend bundle + run: npm run build + + - name: Verify committed frontend bundle is current + run: git diff --exit-code -- js_dist + - name: Run JS tests (vitest) run: npm run test:js diff --git a/.gitignore b/.gitignore index a4089cb2..77c235f2 100644 --- a/.gitignore +++ b/.gitignore @@ -221,3 +221,5 @@ docs/TAGS_NORMALIZATION_REMAINING_WORK.md docs/PLAN_COMFY_FRONTEND_ALIGNMENT.md .github/agents/comfyui-dev.agent.md AGENTS.md +ts_errors*.txt +test-results/ diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 26a1b7f2..637baa61 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -2,6 +2,8 @@ default_install_hook_types: [pre-commit, pre-push] minimum_pre_commit_version: "3.6.0" +exclude: ^js_dist/ + repos: - repo: https://github.com/pre-commit/pre-commit-hooks rev: v5.0.0 @@ -32,13 +34,13 @@ repos: name: ESLint autofix entry: npm exec eslint --fix language: system - files: ^js/.*\.(js|mjs)$ + files: ^js/.*\.(ts|js|mjs)$ - id: prettier-write name: Prettier write entry: npm exec prettier --write language: system - files: ^js/.*\.(js|mjs|vue)$ + files: ^js/.*\.(ts|js|mjs|vue)$ - id: mypy name: Mypy (manual) diff --git a/__init__.py b/__init__.py index 2e345895..2b88b19d 100644 --- a/__init__.py +++ b/__init__.py @@ -71,11 +71,16 @@ __branch__ = _detect_branch_from_env() root = Path(__file__).resolve().parent if WEB_DIRECTORY is None: - # js_dist/ contains the Vite-built bundle (npm run build). - # Fall back to js/ (raw source) when the dist directory has not been built yet - # so development without a build step still works. + # ComfyUI only auto-loads browser-ready .js files from WEB_DIRECTORY. + # The TypeScript/Vue source under js/ must be bundled first with `npm run build`. _js_dist = root / "js_dist" - WEB_DIRECTORY = str(_js_dist if _js_dist.is_dir() else root / "js") + WEB_DIRECTORY = str(_js_dist) + if not (_js_dist / "entry.js").is_file(): + _logger.warning( + "Majoor Assets Manager frontend bundle is missing at %s. " + "Run `npm run build` before loading the custom node.", + _js_dist / "entry.js", + ) # Ensure extension-local packages (e.g. `mjr_am_backend`) are importable even when # ComfyUI loads this module by file path without adding custom node root to sys.path. diff --git a/js_dist/assets/comfyui-majoor-assetsmanager.css b/js_dist/assets/comfyui-majoor-assetsmanager.css index e73558f5..67925d87 100644 --- a/js_dist/assets/comfyui-majoor-assetsmanager.css +++ b/js_dist/assets/comfyui-majoor-assetsmanager.css @@ -1,2 +1,2 @@ .mjr-rating-badge[data-v-821bf1b1]{letter-spacing:1px;pointer-events:none;z-index:10;text-shadow:0 2px 6px #0009;background:#0000008c;border:1px solid #ffffff1f;border-radius:6px;justify-content:center;align-items:center;padding:2px 6px;font-size:13px;animation:.2s ease-out mjr-fade-in-821bf1b1;display:inline-flex;position:absolute;top:6px;right:6px;box-shadow:0 6px 18px #00000040}@keyframes mjr-fade-in-821bf1b1{0%{opacity:0;transform:scale(.9)}to{opacity:1;transform:scale(1)}}.mjr-tags-badge[data-v-15044260]{text-overflow:ellipsis;white-space:nowrap;pointer-events:none;z-index:10;background:#000c;border-radius:4px;max-width:calc(100% - 56px);padding:3px 6px;font-size:9px;animation:.2s ease-out mjr-fade-in-15044260;position:absolute;bottom:6px;left:6px;overflow:hidden;box-shadow:0 2px 4px #0000004d}@keyframes mjr-fade-in-15044260{0%{opacity:0;transform:scale(.95)}to{opacity:1;transform:scale(1)}}.mjr-gentime-badge[data-v-60fe3677]{letter-spacing:.015em;pointer-events:none;z-index:10;text-shadow:0 1px 2px #000000e6, 0 0 10px color-mix(in srgb, currentColor 35%, transparent);-webkit-backdrop-filter:blur(2px);background:#0000008c;border:1px solid #ffffff1f;border-radius:4px;padding:2px 6px;font-size:10px;font-weight:800;line-height:1.1;position:absolute;bottom:6px;right:6px;box-shadow:0 2px 4px #0000004d}.mjr-grid-skeleton-layout[data-v-ce411986]{grid-template-columns:repeat(auto-fill,minmax(132px,1fr));gap:12px;display:grid}.mjr-grid-skeleton-card[data-v-ce411986]{background:#c0c6ce33;border:1px solid #ffffff38;border-radius:12px;min-height:146px;overflow:hidden;box-shadow:0 6px 18px #0000003d}.mjr-grid-skeleton-thumb[data-v-ce411986]{aspect-ratio:1;background:linear-gradient(90deg,#9ca2ab85 0%,#dce1e8b8 45%,#9ca2ab85 100%) 0 0/240% 100%;width:100%;animation:1.2s linear infinite mjr-grid-skeleton-shimmer-ce411986}.mjr-grid-skeleton-line[data-v-ce411986]{background:linear-gradient(90deg,#a4aab37a 0%,#d6dbe2b3 45%,#a4aab37a 100%) 0 0/240% 100%;border-radius:8px;height:10px;margin:8px 10px;animation:1.2s linear infinite mjr-grid-skeleton-shimmer-ce411986}.mjr-grid-skeleton-line--title[data-v-ce411986]{width:72%}.mjr-grid-skeleton-line--meta[data-v-ce411986]{width:48%;margin-top:2px;margin-bottom:10px}@keyframes mjr-grid-skeleton-shimmer-ce411986{0%{background-position:100% 0}to{background-position:-100% 0}}.mjr-popover-row[data-v-3c2601ee]{grid-template-columns:110px 1fr;align-items:center;gap:8px;margin-bottom:8px;display:grid}.mjr-popover-row--3col[data-v-3c2601ee]{grid-template-columns:110px 1fr 1fr}.mjr-popover-label[data-v-3c2601ee]{color:var(--mjr-muted,var(--descrip-text,#ffffffa6));white-space:nowrap;font-size:12px}.mjr-popover-toggle[data-v-3c2601ee]{cursor:pointer;color:var(--fg-color,#e6edf7);align-items:center;gap:6px;font-size:12px;display:flex}.mjr-filter-group-toggle[data-v-3c2601ee]{width:100%;color:inherit;cursor:pointer;text-align:left;background:0 0;border:0;justify-content:space-between;align-items:center;gap:10px;margin:0 0 10px;padding:0;display:flex}.mjr-filter-group-title[data-v-3c2601ee]{letter-spacing:.08em;text-transform:uppercase;font-size:11px;font-weight:700}.mjr-filter-group-chevron[data-v-3c2601ee]{color:var(--mjr-muted,var(--descrip-text,#ffffffa6));font-size:12px;line-height:1}.mjr-filter-group-body[data-v-3c2601ee]{padding-top:2px}.mjr-filter-group[data-v-3c2601ee]:not(.is-open){padding-bottom:8px}.mjr-filter-group:not(.is-open) .mjr-filter-group-toggle[data-v-3c2601ee]{margin-bottom:0}.mjr-pinned-folders-menu[data-v-bdae920e]{gap:6px;display:grid}.mjr-pinned-folders-empty[data-v-bdae920e]{opacity:.75;padding:10px 12px}.mjr-pinned-folder-row[data-v-bdae920e]{align-items:stretch;width:100%;display:flex}.mjr-pinned-folder-open[data-v-bdae920e]{background:linear-gradient(135deg,#ffffff08,#ffffff03);border:1px solid #78beff2e;border-radius:9px;flex:1;justify-content:space-between;align-items:center;gap:10px;width:100%;padding:9px 10px;transition:border-color .12s,background .12s;display:flex}.mjr-pinned-folder-open[data-v-bdae920e]:hover,.mjr-pinned-folder-open[data-v-bdae920e]:focus-visible{background:linear-gradient(135deg,#508cff2e,#2064c824);border-color:#91cdff66}.mjr-pinned-folder-label[data-v-bdae920e]{text-overflow:ellipsis;white-space:nowrap;min-width:0;color:var(--fg-color,#e6edf7);font-weight:600;overflow:hidden}.mjr-pinned-folder-path[data-v-bdae920e]{text-overflow:ellipsis;white-space:nowrap;opacity:.68;flex:0 auto;min-width:0;max-width:220px;font-size:11px;overflow:hidden}.mjr-pinned-folder-unpin[data-v-bdae920e]{background:linear-gradient(135deg,#ff464629,#a014141f);border:1px solid #ff5f5f59;border-radius:9px;justify-content:center;width:42px;margin-left:6px;padding:0}.mjr-pinned-folder-unpin .pi[data-v-bdae920e]{opacity:.88;color:#ff8282f5}.mjr-folder-breadcrumb[data-v-d38c4371]{opacity:.78;white-space:nowrap;background:color-mix(in srgb, var(--mjr-surface-2,#ffffff0d) 42%, transparent);border-radius:8px;align-items:center;gap:4px;margin:1px 0 3px;padding:3px 6px;font-size:11px;display:none;overflow:auto}.mjr-folder-breadcrumb.is-visible[data-v-d38c4371]{display:flex}.mjr-folder-breadcrumb-action[data-v-d38c4371]{color:var(--mjr-accent,#7aa2ff);font:inherit;background:#7aa2ff1f;border:1px solid #7aa2ff59;border-radius:6px;padding:2px 8px}.mjr-folder-breadcrumb-segment[data-v-d38c4371]{min-width:0;max-width:220px;color:var(--mjr-accent,#7aa2ff);font:inherit;text-overflow:ellipsis;background:0 0;border:none;padding:0;overflow:hidden}.mjr-folder-breadcrumb-segment.is-current[data-v-d38c4371],.mjr-folder-breadcrumb-segment[data-v-d38c4371]:disabled{color:var(--mjr-text,inherit);cursor:default}.mjr-folder-breadcrumb-separator[data-v-d38c4371]{opacity:.6}.mjr-rating-star[data-v-e285b3be]{outline:none}.mjr-rating-star[data-v-e285b3be]:hover:not(:disabled){transform:scale(1.2)}.mjr-rating-star[data-v-e285b3be]:focus-visible{outline:2px solid var(--focus-outline-color,#4dabf7);outline-offset:2px;border-radius:2px} -/*$vite$:1*/ +/*$vite$:1*/ \ No newline at end of file diff --git a/package.json b/package.json index 39b05575..2a3f5a5a 100644 --- a/package.json +++ b/package.json @@ -22,8 +22,8 @@ "lint:dead": "knip --config knip.json || node -e \"process.exit(0)\"", "typecheck:js": "tsc -p tsconfig.json --noEmit || node -e \"process.exit(0)\"", "lint:js:fix": "eslint js/ --fix", - "format": "prettier --write \"js/**/*.{js,mjs,vue}\"", - "format:check": "prettier --check \"js/**/*.{js,mjs,vue}\"" + "format": "prettier --write \"js/**/*.{ts,js,mjs,vue}\"", + "format:check": "prettier --check \"js/**/*.{ts,js,mjs,vue}\"" }, "devDependencies": { "@comfyorg/litegraph": "^0.17.2",