mirror of
https://github.com/hoppscotch/hoppscotch.git
synced 2026-04-26 01:06:00 +03:00
[PR #5421] [MERGED] feat(desktop): portable phase-3: instance manager #5199
Labels
No labels
CodeDay
a11y
browser limited
bug
bug fix
cli
core
critical
design
desktop
discussion
docker
documentation
duplicate
enterprise
feature
feature
fosshack
future
good first issue
hacktoberfest
help wanted
i18n
invalid
major
minor
need information
need testing
not applicable to hoppscotch
not reproducible
pull-request
question
refactor
resolved
sandbox
self-host
spam
stale
testmu
wip
wont fix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
starred/hoppscotch#5199
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
📋 Pull Request Information
Original PR: https://github.com/hoppscotch/hoppscotch/pull/5421
Author: @CuriousCorrelation
Created: 10/1/2025
Status: ✅ Merged
Merged: 11/25/2025
Merged by: @jamesgeorge007
Base:
next← Head:desktop-feat-portable-app-phase-3📝 Commits (10+)
bee32ddfeat(desktop): portable phase-3: instance managerd1be901fix: unused vars and lint from merge conflicts1d7c1d4chore: updatedevenvce42336chore: safely deprecateselfhost-desktopb7687c0chore: fix merge artifactsd05f884fix: rebase artifacts6318f5cfix(desktop): missingawaita581103fix: rebase artifact292019afix: rebase artifact93fec9cchore: minor formatting update📊 Changes
218 files changed (+5112 additions, -16795 deletions)
View changed files
📝
devenv.lock(+33 -13)📝
devenv.nix(+5 -6)📝
devenv.yaml(+7 -16)📝
packages/hoppscotch-common/.eslintrc.js(+7 -1)📝
packages/hoppscotch-common/locales/en.json(+22 -1)📝
packages/hoppscotch-common/src/components/app/Header.vue(+12 -41)📝
packages/hoppscotch-common/src/components/instance/Switcher.vue(+578 -176)📝
packages/hoppscotch-common/src/kernel/store.ts(+50 -9)📝
packages/hoppscotch-common/src/platform/index.ts(+1 -0)📝
packages/hoppscotch-common/src/platform/instance.ts(+219 -7)➖
packages/hoppscotch-common/src/services/instance-switcher.service.ts(+0 -508)📝
packages/hoppscotch-desktop/.gitignore(+4 -0)📝
packages/hoppscotch-desktop/plugin-workspace/tauri-plugin-appload/dist-js/index.js(+8 -5)📝
packages/hoppscotch-desktop/plugin-workspace/tauri-plugin-appload/examples/tauri-app/src/main.js(+4 -4)📝
packages/hoppscotch-desktop/plugin-workspace/tauri-plugin-appload/examples/tauri-app/vite.config.js(+10 -8)📝
packages/hoppscotch-desktop/plugin-workspace/tauri-plugin-appload/guest-js/index.ts(+9 -7)📝
packages/hoppscotch-desktop/plugin-workspace/tauri-plugin-appload/permissions/schemas/schema.json(+10 -0)📝
packages/hoppscotch-desktop/plugin-workspace/tauri-plugin-appload/rollup.config.js(+13 -13)📝
packages/hoppscotch-desktop/plugin-workspace/tauri-plugin-appload/src/kernel.js(+4 -4)📝
packages/hoppscotch-desktop/plugin-workspace/tauri-plugin-relay/dist-js/index.js(+18 -18)...and 80 more files
📄 Description
This is an experimental first look at the portable version for the
desktop app.
This implementation activates the FE integration, finalizing the
instance switching architecture, plus portable functionality with
better compliance and security capabilities.
Closes FE-758
Closes FE-829
Closes FE-849
Closes FE-857
Closes FE-861
Closes FE-862
Closes FE-866
Closes FE-868
Closes FE-888
Closes FE-899
Closes FE-910
Closes FE-912
Closes FE-919
Closes FE-921
Closes FE-931
Closes FE-932
Closes FE-933
Closes FE-934
Closes FE-935
Closes FE-937
Closes FE-938
Closes FE-939
Closes FE-961
Closes FE-963
Closes FE-964
Closes FE-965
Closes FE-966
Closes FE-1053
Closes https://github.com/hoppscotch/hoppscotch/issues/4978 (Portable version now has disable updates toggle) [caveat: just for Windows]
Closes https://github.com/hoppscotch/hoppscotch/issues/4119 (Portable version can choose the current directory as the default storage location) [requested just for Windows]
Closes https://github.com/hoppscotch/hoppscotch/issues/3526 (Portable version in general) [requested for Windows]
Closes https://github.com/hoppscotch/hoppscotch/issues/4828 (Bug fix + Feature) [applies to all platforms]
The desktop app infrastructure established in phase-1 and phase-2
provided path management, data migration, and service architecture.
This phase completes the implementation by connecting frontend
components to the backend systems and enabling those managers and
paths.
Instance Switching
Desktop Instance Service
The
DesktopInstanceServiceis now fully integrated with the frontendinstance switcher component. The service provides instance management
with the persistent storage layer introduced in phase-1.
NOTE: Implementation uses the appload plugin for bundle loading
and window management. See those files in file view for
better context.
The service manages connection state through observables (so it's
reactive enough, the idea is to rely solely on store, since it's
the main source of truth but because there are ways to bypass it when
switching, see more details below, this approach works better), handles
bundle loading via the appload plugin, maintains recent instances via
the persistence layer (see phase-1). Window management during instance
switching prevents the multiple window issue identified in earlier
development (see https://github.com/hoppscotch/hoppscotch/pull/5381).
NOTE: Instance switching functionality is desktop-only. Web platform
continues using the no-op
WebInstanceServiceimplementation.Switcher Component
The instance switcher component in
hoppscotch-commonnow adapts toplatform:
The component subscribes to platform-provided observables for
connection state, recent instances, and current instance updates.
Notice the difference between the prior service-in-common to
platform-from-web change.
It also now includes better error handling with some new toasts
for notifications since instance closing is now handled client-side.
In this case
client-sidemeans the hosted web-app,host-sidemeansthe underlying machinery run by
plugin-appload.Web platform sees no instance switching UI.
Desktop platform gets full functionality with fallback to default
implementation if custom components are unavailable.
Route Resolution
Updated router configuration detects portable mode at runtime and loads
appropriate home view:
In contrast to what we had prior, a consolidated
Home.vuefilewhich would actually prevent updater because the Rust updater part that
handles portable version would setup before it gets called in the FE
causing a perpetual
nullvalue return bycheck()function.Basically dynamic imports prevent race conditions (not exactly
but close enough) with the updater while ensuring correct component
loading based on build configuration.
Standard mode loads
StandardHome.vuewith all the existingfunctionality. Portable mode loads
PortableHome.vuewithportable-specific stuff.
Portable Mode Welcome Flow
Implemented first-launch experience for portable mode with information
related to what to expect with this version:
The welcome screen explains portable mode behavior including data
isolation from installed versions, manual update requirements, and
enterprise deployment constraints. Users can configure update
notification preferences and opt to skip the welcome screen in future
launches.
Welcome screen only appears in portable mode and only on first launch
unless re-enabled by user preferences.
Update Flow Differentiation
Standard and portable modes now have distinct update handling:
StandardHome.vuePortableHome.vueEssentially:
Standard mode: provides automatic download and installation with
progress tracking.
Portable mode: shows native dialogs for manual download from releases
page, respecting enterprise requirements for controlled versioning.
Standard mode update behavior remains (mostly) identical.
Portable mode adds new manual update workflow without affecting
existing installations.
Backend
Updater
Extended the updater system with commands for different scenarios:
The updater emits progress events that frontend components can
subscribe to. It also handles both portable and standard mode update
flows. It also has some error handling with the same event emission
mechanics for UI feedback as well.
App Initialization
Initialization Composable
Created
useAppInitialization()composable that handles all startupscenarios, the idea is basically this:
Initialization flow maintains identical behavior for existing
functionality, this is mainly a portable mode extension.
Migration System Activation
The
InstanceStoreMigrationServicenow actively migrates data fromlegacy stores to the new kernel-based system:
The migration system automatically detects existing data from legacy
LazyStore files, transfers connection state and recent instances to
kernel store, moves
.hoppscotch.storefiles to organized directorystructure, and cleans up old files after successful migration.
Migration system preserves all existing user data and settings.
Users should experience no disruption during the upgrade process.
ESLint Infra
Added ESLint setup matching patterns from
hoppscotch-commonandhoppscotch-selfhost-web:Kernel Integration
Multi-Store Path Resolution
Completed kernel store integration with dynamic path resolution:
This is overall a better approach than the isolated calls to
LazyStoresince the kernel store can manage multiple concurrent storeinstances with different paths for different data types while
maintaining all the namespace isolation guarantees we need when
switching between contexts.
Portable Mode Isolation
This also implemented complete data boundary isolation between portable
and installed versions:
That data isolation makes sure portable versions never access system
directories or data from installed versions, to meet the enterprise
security requirements for locked-down environments.
Instance Platform Definition
Extended the instance platform definition with operations for
instance management:
The definition includes lifecycle hooks (
beforeConnect,afterConnect, etc.) and error handlers for platform-specificbehavior customization.
Localization Updates
Added instance switcher translations to
en.json:Shared View Components
Created shared view components in
src/views/shared/:AppHeader.vue: Displays app branding with optional mode indicatorLoadingState.vue: Shows loading spinner with status messageUpdateFlow.vue: Handles update UI with progress trackingErrorState.vue: Displays error messages with retry optionVersionInfo.vue: Shows version and data directory informationThese components are used by both
StandardHome.vueandPortableHome.vuefor consistent UI across modes.Header Integration
Updated
Header.vueto use platform-provided instance information:Removed the service-in-common pattern in favor of platform-provided
observables for cleaner separation of concerns.
Plugin Type Updates
Updated
plugin-apploadguest-js types to includecloseoperationwith proper TypeScript definitions. The close operation allows
controlled window management during instance switching.
Path Import Reorganization
Restructured imports in
hoppscotch-selfhost-webwith new aliasstructure:
This creates clear boundaries between application-specific code
(
@app/*) and shared common code (@hoppscotch/commonand legacy@composables,@helpersaliases).NOTE: Prior to this the loading path difference between portable
and standard would prevent either from building.
All platform implementation files now use
@app/platform/*instead of@platform/*for consistency. API files moved from@api/*to@app/api/*. Library utilities moved from@lib/*to@app/lib/*.Main Entry Point Updates
Updated
main.tsto initialize kernel on startup:The kernel initialization sets up the store system and IO operations
before the app mounts.
NOTE: This is important to make sure the plugin initializers in
the
host-sideare initialized before the kernel components users.Also consolidated platform configuration into a single
PLATFORM_CONFIGobject that defines all platform-specific settings (interceptors,
default values, menu items) for both web and desktop modes.
🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.