Files
DumiFlex-ComfyUI-Wildcard-P…/engine/db/migrations_sql/013_community_origin.py
T
DumiFlex 9957702099 feat(community): track install origin + update-available indicator
Library rows installed from the community embed now carry the source
post slug + installed version_number in the engine sqlite. The SPA
uses both surfaces: a "community" pill next to the row name (so users
can tell at a glance which entries were authored locally vs pulled
from the embed), and a warn-coloured "v{N}" pill when the post has
shipped a newer version since install.

Engine:
- Migration 013 adds community_post_slug + community_version_number
  to modules + bundles. Both nullable; locally-authored rows stay
  NULL forever. Implemented as a .py migration with PRAGMA
  table_info guards so rerunning against an already-migrated DB
  (test fixtures rewind migrations to exercise older paths) is a
  clean no-op rather than "duplicate column name".
- _insert_module / _insert_bundle (importer.py) persist the fields
  when the entity dict carries them.
- _row_to_module / _row_to_bundle (repositories.py) surface them on
  every read path. Try/except guard for pre-013 DB shape so a
  connection opened mid-rollout does not crash.

Manager:
- installEnvelope grows optional `origin: { post_slug, version_number }`
  in InstallOptions. When set, stamps every module + bundle in the
  selection before the commit roundtrip.
- Host bridge in main.ts threads origin from `install(envelope, opts)`
  through to installEnvelope. ABI stays at 1 (additive).
- New communityUpdateStore walks the library snapshot, batch-fetches
  each unique community post (deduped, 8-wide concurrency), surfaces
  rows whose installed version is behind the post's
  latest_version_number. Network failures clear the store silently
  so an offline session does not render misleading "v2 available"
  pills.
- AppLayout kicks one check after the initial library fetch
  resolves. No background polling.
- ModuleListView renders two distinct pills per row: a static
  "community" indicator on origin-stamped rows, and a separate
  warn-coloured "v{N}" pill when the update store has an entry.

Migration tests updated for the new schema head + bundle/module
column sets.
2026-06-04 17:21:04 +03:00

50 lines
2.2 KiB
Python

"""Migration 013 — community install origin columns.
Adds ``community_post_slug`` and ``community_version_number`` to both
``modules`` and ``bundles``. Stamped at install time by the host-bridge
``install()`` path (via the embed's ``origin`` opt) so the SPA can:
- Render an "installed from community" pill on origin-stamped rows.
- Run an update-availability check that compares
``community_version_number`` against the post's
``latest_version_number`` in the community API.
Both columns are nullable on purpose — locally-authored rows (Create
flow, Import-from-file, starter set) leave them NULL forever.
Idempotent: each ALTER is gated on ``PRAGMA table_info`` so re-running
the migration against a DB that already has the columns is a no-op.
The migration runner's existing version table guards against re-runs
in production; this guard exists for tests that explicitly rewind the
``migrations`` table to exercise the migration on a populated DB
(see ``tests/engine/db/test_migration_010.py``).
"""
from __future__ import annotations
import sqlite3
def _has_column(conn: sqlite3.Connection, table: str, column: str) -> bool:
cur = conn.execute(f"PRAGMA table_info({table});")
return any(row[1] == column for row in cur.fetchall())
def up(conn: sqlite3.Connection) -> None:
with conn:
if not _has_column(conn, "modules", "community_post_slug"):
conn.execute("ALTER TABLE modules ADD COLUMN community_post_slug TEXT;")
if not _has_column(conn, "modules", "community_version_number"):
conn.execute("ALTER TABLE modules ADD COLUMN community_version_number INTEGER;")
if not _has_column(conn, "bundles", "community_post_slug"):
conn.execute("ALTER TABLE bundles ADD COLUMN community_post_slug TEXT;")
if not _has_column(conn, "bundles", "community_version_number"):
conn.execute("ALTER TABLE bundles ADD COLUMN community_version_number INTEGER;")
conn.execute(
"CREATE INDEX IF NOT EXISTS idx_modules_community_slug "
"ON modules(community_post_slug);"
)
conn.execute(
"CREATE INDEX IF NOT EXISTS idx_bundles_community_slug "
"ON bundles(community_post_slug);"
)