- Field registry (services/filter_registry.go): ~55 typed fields — every book column, file/lifecycle facts, the three HOLDING STRUCTURES (library, collections with excluded-aware membership, series with FULL primary+alternate_info membership), and the whole user-relative class (status, progress, last read, my rating, review, notes/highlights presence, note/highlight text, time spent, pages read, collections, added by) reading the VIEWER's rows. Operators are typed constants; negation is an operator. - Composed engines (services/filter_query.go): one Go clause builder over raw pgx feeds the search (identical SearchMediaItemsUnifiedRow shape), the field-aware suggestions, and a true-COUNT live count. Mandatory WHERE head everywhere (family lens + integrity facts). Values are always bound parameters — no user string reaches a field/operator position, ever. - Wire: the qf JSON param (validated strictly — unknown fields/operators/malformed values are 400); qf wins over flat params on hand-crafted URLs; flat deep links keep working unchanged. - Endpoints: GET /api/media-items/filter-count (live count); field-values autocomplete upgraded in place — any registry field key, qf binds the OTHER rules (symmetric under-filter suggestions, zero-match values never offered); classic six without a tree keep their static pinned contract. - UI: the drawer becomes the rule builder — the ONLY filter UI (templ markup, Alpine tree state, sanctioned island; grouped field menus, operator menus with red negations, field-aware value menus, live count, chips per rule with red negations, URL rehydration, smart serialization flat-when-simple else qf). - Tests: composed semantics (AND/OR/negation/nesting/enums/bools/ numbers/dates/empty), every user-relative field class with the my-data weld (two readers, different worlds), note-text substring pin (catharsis ≠ Carthage), family lens (hidden libraries nowhere, 403s), suggestion-under-rules exactness, qf validation + precedence, flat-vs-tree equivalence; registry completeness unit test.
45 lines
942 B
TypeScript
45 lines
942 B
TypeScript
import "./alpine";
|
|
import { Alpine } from "./alpine";
|
|
|
|
import "./admin";
|
|
import "./audio";
|
|
import "./api";
|
|
import "./api-explorer";
|
|
import "./api-explorer-docs";
|
|
import "./bookPicker";
|
|
import "./bookshelf";
|
|
import "./filter_builder";
|
|
import "./book-detail";
|
|
import "./collection-rules";
|
|
import "./collections";
|
|
import "./conflicts";
|
|
import "./custom-section-builder";
|
|
import "./dashboard";
|
|
import "./device-management";
|
|
import "./docs";
|
|
import "./dom";
|
|
import "./events";
|
|
import "./header";
|
|
import "./index";
|
|
import "./library-switcher";
|
|
import "./linking";
|
|
import "./login";
|
|
import "./password_validation";
|
|
import "./profile";
|
|
import "./profile-modal";
|
|
import "./queue";
|
|
import "./register";
|
|
import "./search";
|
|
import "./series";
|
|
import "./setup";
|
|
import "./stats";
|
|
import "./storage";
|
|
import "./theme";
|
|
import "./toast";
|
|
import "./toast-error";
|
|
import "./unlinked_books";
|
|
import "./websocket";
|
|
import "./woodPanelingInit";
|
|
|
|
Alpine.start();
|