Add entity-level deletion guards to QueryFolder and ConnectionFolder:
if a folder still has queries/connections, .remove() throws a
descriptive error before touching the database. This mirrors the
cloud API behaviour where non-empty folders cannot be deleted.
Unit tests (18 total, 9 per model) cover:
- Basic save/retrieve
- Deletion blocked when folder contains items (checks error message,
count wording, singular vs plural)
- Deletion succeeds when folder is empty
- Deletion succeeds after items are moved out (items survive)
- Parent folder relationship is persisted correctly
- Deleting a parent folder (no direct items) succeeds and sets
child folder parentId to NULL via DB-level SET NULL
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add @ManyToOne/@JoinColumn FK relationships for parentId in
QueryFolder and ConnectionFolder (self-referential)
- Add @OneToMany queries/connections to QueryFolder/ConnectionFolder
- Add @ManyToOne/@JoinColumn to FavoriteQuery.queryFolder and
SavedConnection.connectionFolder
- Add explicit FK constraints (REFERENCES ... ON DELETE SET NULL)
to both migration files for parentId and the folder FK columns
- LocalQueryFolderModule/LocalConnectionFolderModule: remove
isUltimate gate from load() — folders always load; check emptiness
before remove() and throw a descriptive error if non-empty
- New Folder button always visible; clicking it shows upgrade modal
for Community users (isUltimate check moved to UI)
- Fix modal input focus: use @opened event instead of $nextTick so
it fires after animation completes
- deleteFolder now catches store errors and shows them via $noty
- Remove foldersUnsupported/foldersSupported in favour of isUltimate
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds the ability to organize saved connections and saved queries into
folders. For local workspaces this is an Ultimate-only feature; cloud
workspaces use the existing cloud API with Personal/Team root folders.
- TypeORM entities: ConnectionFolder, QueryFolder (mirrors cloud schema
including parentId for hierarchy)
- SQLite migrations: create connection_folder/query_folder tables and
add connectionFolderId/queryFolderId FK columns
- IPC handlers via appdb/connectionFolder/* and appdb/queryFolder/*
- LocalConnectionFolderModule and LocalQueryFolderModule: full CRUD,
license-gated (unsupported=true for Community users)
- UI: New Folder button, create/rename/delete folder modals with parent
folder picker (cloud), right-click context menus on folders
- ConnectionListItem and FavoriteListItem: show Move to Folder options
for local Ultimate users as well as cloud
- Subfolder nesting: child folders render inside their parent folder
with correct visual indentation (margin-left: 0.8rem)
- Fix: ClientHelpers.res() now accepts any 2xx status (was rejecting
201 Created from POST endpoints)
- Fix: SearchModule was using f.queryFolderId instead of
f.connectionFolderId when looking up connection folders
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The guard check in checkForUpdates() is redundant since manageUpdates()
already performs the same check before calling checkForUpdates().
Co-authored-by: Day Matchullis <not-night-but@users.noreply.github.com>