chore: bump version to 2025.5.2

This commit is contained in:
jamesgeorge007 2025-06-10 14:11:35 +05:30
parent b63c707624
commit 9493b30a84
12 changed files with 199 additions and 148 deletions

View file

@ -1,6 +1,6 @@
{
"name": "hoppscotch-backend",
"version": "2025.5.1",
"version": "2025.5.2",
"description": "",
"author": "",
"private": true,

View file

@ -1,7 +1,7 @@
{
"name": "@hoppscotch/common",
"private": true,
"version": "2025.5.1",
"version": "2025.5.2",
"scripts": {
"dev": "pnpm exec npm-run-all -p -l dev:*",
"test": "vitest --run",

View file

@ -1,7 +1,7 @@
{
"name": "hoppscotch-desktop",
"private": true,
"version": "25.5.1",
"version": "25.5.2",
"type": "module",
"scripts": {
"dev": "vite",

View file

@ -2054,7 +2054,7 @@ dependencies = [
[[package]]
name = "hoppscotch-desktop"
version = "25.5.1"
version = "25.5.2"
dependencies = [
"axum",
"dirs 6.0.0",

View file

@ -1,6 +1,6 @@
[package]
name = "hoppscotch-desktop"
version = "25.5.1"
version = "25.5.2"
description = "Desktop App for hoppscotch.io"
authors = ["CuriousCorrelation"]
edition = "2021"

View file

@ -1,7 +1,7 @@
{
"$schema": "https://schema.tauri.app/config/2",
"productName": "Hoppscotch",
"version": "25.5.1",
"version": "25.5.2",
"identifier": "io.hoppscotch.desktop",
"build": {
"beforeDevCommand": "pnpm dev",

View file

@ -1,5 +1,7 @@
<template>
<div class="flex flex-col items-center justify-center w-full h-screen bg-primary">
<div
class="flex flex-col items-center justify-center w-full h-screen bg-primary"
>
<div class="flex flex-col items-center space-y-6 max-w-md text-center">
<div class="flex items-center space-x-4">
<img src="/logo.svg" alt="Hoppscotch" class="h-7 w-7" />
@ -9,39 +11,70 @@
</div>
</div>
<div v-if="appState === AppState.LOADING" class="flex flex-col items-center space-y-4">
<div
v-if="appState === AppState.LOADING"
class="flex flex-col items-center space-y-4"
>
<HoppSmartSpinner />
<p class="text-secondaryDark">{{ statusMessage }}</p>
</div>
<div
v-else-if="appState === AppState.UPDATE_AVAILABLE || appState === AppState.UPDATE_IN_PROGRESS || appState === AppState.UPDATE_READY"
v-else-if="
appState === AppState.UPDATE_AVAILABLE ||
appState === AppState.UPDATE_IN_PROGRESS ||
appState === AppState.UPDATE_READY
"
class="flex flex-col items-center space-y-4"
>
<IconLucideDownload class="h-16 w-16 text-accent" />
<div class="text-center">
<h2 class="text-xl font-semibold text-secondaryDark">Update Available</h2>
<p class="text-secondary mt-1">{{ updateMessage || 'A new version of Hoppscotch is available, downloading...' }}</p>
<h2 class="text-xl font-semibold text-secondaryDark">
Update Available
</h2>
<p class="text-secondary mt-1">
{{
updateMessage ||
"A new version of Hoppscotch is available, downloading..."
}}
</p>
</div>
<div v-if="downloadProgress.total && downloadProgress.downloaded" class="w-full">
<div
v-if="downloadProgress.total && downloadProgress.downloaded"
class="w-full"
>
<div class="w-full bg-primaryLight rounded-full h-2.5">
<div
class="bg-accent h-2.5 rounded-full"
:style="{ width: `${(downloadProgress.downloaded / downloadProgress.total) * 100}%` }"
:style="{
width: `${
(downloadProgress.downloaded / downloadProgress.total) * 100
}%`,
}"
></div>
</div>
<div class="flex justify-between text-sm text-secondaryLight mt-1">
<span>{{ Math.round((downloadProgress.downloaded / downloadProgress.total) * 100) }}%</span>
<span
>{{
Math.round(
(downloadProgress.downloaded / downloadProgress.total) * 100
)
}}%</span
>
<span class="text-xs">
{{ formatBytes(downloadProgress.downloaded) }} / {{ formatBytes(downloadProgress.total) }}
{{ formatBytes(downloadProgress.downloaded) }} /
{{ formatBytes(downloadProgress.total) }}
</span>
</div>
</div>
<div v-else-if="downloadProgress.downloaded > 0" class="w-full">
<div class="w-full bg-primaryLight rounded-full h-2.5">
<div class="bg-accent h-2.5 rounded-full animate-pulse" style="width: 100%"></div>
<div
class="bg-accent h-2.5 rounded-full animate-pulse"
style="width: 100%"
></div>
</div>
<p class="text-sm text-secondaryLight text-center mt-1">
Downloaded {{ formatBytes(downloadProgress.downloaded) }}
@ -70,10 +103,15 @@
</div>
</div>
<div v-else-if="appState === AppState.ERROR" class="flex flex-col items-center space-y-4">
<div
v-else-if="appState === AppState.ERROR"
class="flex flex-col items-center space-y-4"
>
<IconLucideAlertCircle class="h-16 w-16 text-red-500" />
<div class="text-center">
<h2 class="text-xl font-semibold text-secondaryDark">Something went wrong</h2>
<h2 class="text-xl font-semibold text-secondaryDark">
Something went wrong
</h2>
<p class="text-red-500 mt-2">{{ error }}</p>
</div>
<HoppButtonPrimary
@ -91,24 +129,24 @@
</template>
<script setup lang="ts">
import { ref, onMounted } from "vue";
import { LazyStore } from '@tauri-apps/plugin-store';
import { load } from "@hoppscotch/plugin-appload";
import { getVersion } from '@tauri-apps/api/app';
import { ref, onMounted } from "vue"
import { LazyStore } from "@tauri-apps/plugin-store"
import { load } from "@hoppscotch/plugin-appload"
import { getVersion } from "@tauri-apps/api/app"
import { UpdateStatus, CheckResult, UpdateState } from "~/types";
import { UpdaterService } from "~/utils/updater";
import { UpdateStatus, CheckResult, UpdateState } from "~/types"
import { UpdaterService } from "~/utils/updater"
import IconLucideAlertCircle from "~icons/lucide/alert-circle";
import IconLucideRefreshCw from "~icons/lucide/refresh-cw";
import IconLucideDownload from "~icons/lucide/download";
import IconLucideAlertCircle from "~icons/lucide/alert-circle"
import IconLucideRefreshCw from "~icons/lucide/refresh-cw"
import IconLucideDownload from "~icons/lucide/download"
const APP_STORE_PATH = "hoppscotch-desktop.store";
const APP_STORE_PATH = "hoppscotch-desktop.store"
// `InstanceSwitcherService` store path.
// NOTE: This should be removed eventually,
// right now this is part 1/5 of HFE-864
const INSTANCE_STORE_PATH = "hopp.store.json";
const INSTANCE_STORE_PATH = "hopp.store.json"
enum AppState {
LOADING = "loading",
@ -116,108 +154,116 @@ enum AppState {
UPDATE_IN_PROGRESS = "update_in_progress",
UPDATE_READY = "update_ready",
ERROR = "error",
LOADED = "loaded"
LOADED = "loaded",
}
interface VendoredInstance {
type: "vendored";
displayName: string;
version: string;
type: "vendored"
displayName: string
version: string
}
interface ConnectionState {
status: "idle" | "connecting" | "connected" | "error";
instance?: VendoredInstance;
target?: string;
message?: string;
status: "idle" | "connecting" | "connected" | "error"
instance?: VendoredInstance
target?: string
message?: string
}
const appStore = new LazyStore(APP_STORE_PATH);
const appState = ref<AppState>(AppState.LOADING);
const updateStatus = ref("");
const updateMessage = ref("");
const downloadProgress = ref<{ downloaded: number; total?: number }>({ downloaded: 0 });
const error = ref("");
const statusMessage = ref("Initializing...");
const appVersion = ref("...");
const appStore = new LazyStore(APP_STORE_PATH)
const appState = ref<AppState>(AppState.LOADING)
const updateStatus = ref("")
const updateMessage = ref("")
const downloadProgress = ref<{ downloaded: number; total?: number }>({
downloaded: 0,
})
const error = ref("")
const statusMessage = ref("Initializing...")
const appVersion = ref("...")
const updaterService = new UpdaterService(appStore);
const updaterService = new UpdaterService(appStore)
const formatBytes = (bytes: number): string => {
if (bytes === 0) return '0 Bytes';
if (bytes === 0) return "0 Bytes"
const k = 1024;
const sizes = ['Bytes', 'KB', 'MB', 'GB'];
const i = Math.floor(Math.log(bytes) / Math.log(k));
const k = 1024
const sizes = ["Bytes", "KB", "MB", "GB"]
const i = Math.floor(Math.log(bytes) / Math.log(k))
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
};
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + " " + sizes[i]
}
const saveConnectionState = async (state: ConnectionState) => {
try {
await appStore.set("connectionState", state);
await appStore.save();
await appStore.set("connectionState", state)
await appStore.save()
} catch (err) {
console.error("Failed to save connection state:", err);
console.error("Failed to save connection state:", err)
}
};
}
const setupUpdateStateWatcher = async () => {
const unsubscribe = await appStore.onKeyChange<UpdateState>("updateState", (newValue) => {
if (!newValue) return;
const unsubscribe = await appStore.onKeyChange<UpdateState>(
"updateState",
(newValue) => {
if (!newValue) return
updateStatus.value = newValue.status;
updateMessage.value = newValue.message || "";
updateStatus.value = newValue.status
updateMessage.value = newValue.message || ""
if (newValue.progress) {
downloadProgress.value = newValue.progress;
if (newValue.progress) {
downloadProgress.value = newValue.progress
}
if (newValue.status === UpdateStatus.AVAILABLE) {
appState.value = AppState.UPDATE_AVAILABLE
} else if (newValue.status === UpdateStatus.ERROR) {
error.value = newValue.message || "Unknown error"
appState.value = AppState.ERROR
} else if (
newValue.status === UpdateStatus.DOWNLOADING ||
newValue.status === UpdateStatus.INSTALLING
) {
appState.value = AppState.UPDATE_IN_PROGRESS
} else if (newValue.status === UpdateStatus.READY_TO_RESTART) {
appState.value = AppState.UPDATE_READY
}
}
)
if (newValue.status === UpdateStatus.AVAILABLE) {
appState.value = AppState.UPDATE_AVAILABLE;
} else if (newValue.status === UpdateStatus.ERROR) {
error.value = newValue.message || "Unknown error";
appState.value = AppState.ERROR;
} else if (newValue.status === UpdateStatus.DOWNLOADING || newValue.status === UpdateStatus.INSTALLING) {
appState.value = AppState.UPDATE_IN_PROGRESS;
} else if (newValue.status === UpdateStatus.READY_TO_RESTART) {
appState.value = AppState.UPDATE_READY;
}
});
return unsubscribe;
};
return unsubscribe
}
const installUpdate = async () => {
try {
appState.value = AppState.UPDATE_IN_PROGRESS;
await updaterService.downloadAndInstall();
appState.value = AppState.UPDATE_IN_PROGRESS
await updaterService.downloadAndInstall()
// In a rare occurrence where we reach here but automatic restart didn't happen,
// we'll just show a restart button instead
} catch (err) {
const errorMessage = err instanceof Error ? err.message : String(err);
error.value = `Failed to install update: ${errorMessage}`;
appState.value = AppState.ERROR;
const errorMessage = err instanceof Error ? err.message : String(err)
error.value = `Failed to install update: ${errorMessage}`
appState.value = AppState.ERROR
}
};
}
const skipUpdate = async () => {
await loadVendored();
};
await loadVendored()
}
const restartApp = async () => {
try {
await updaterService.restartApp();
await updaterService.restartApp()
} catch (err) {
const errorMessage = err instanceof Error ? err.message : String(err);
error.value = `Failed to restart app: ${errorMessage}`;
appState.value = AppState.ERROR;
const errorMessage = err instanceof Error ? err.message : String(err)
error.value = `Failed to restart app: ${errorMessage}`
appState.value = AppState.ERROR
}
};
}
const loadVendored = async () => {
try {
statusMessage.value = "Loading application...";
statusMessage.value = "Loading application..."
// Standardized vendored instance data.
// NOTE: This should be removed eventually,
@ -225,96 +271,101 @@ const loadVendored = async () => {
const vendoredInstance: VendoredInstance = {
type: "vendored",
displayName: "Hoppscotch",
version: "25.5.1"
};
version: "25.5.2",
}
const connectionState: ConnectionState = {
status: "connected",
instance: vendoredInstance
};
instance: vendoredInstance,
}
// Save to current app store.
// NOTE: This is existing behavior
await saveConnectionState(connectionState);
await saveConnectionState(connectionState)
// ALSO save to `InstanceSwitcherService` store,
// NOTE: This should be removed eventually,
// right now this is part 1/5 of HFE-864
try {
const instanceStore = new LazyStore(INSTANCE_STORE_PATH);
await instanceStore.init();
await instanceStore.set("connectionState", connectionState);
await instanceStore.save();
console.log("Successfully saved vendored state to `InstanceSwitcherService` store");
const instanceStore = new LazyStore(INSTANCE_STORE_PATH)
await instanceStore.init()
await instanceStore.set("connectionState", connectionState)
await instanceStore.save()
console.log(
"Successfully saved vendored state to `InstanceSwitcherService` store"
)
} catch (instanceStoreError) {
console.error("Failed to save to `InstanceSwitcherService` store:", instanceStoreError);
console.error(
"Failed to save to `InstanceSwitcherService` store:",
instanceStoreError
)
// Don't need to fail the flow if this fails.
}
console.log("Loading vendored app...");
console.log("Loading vendored app...")
const loadResp = await load({
bundleName: "Hoppscotch",
window: { title: "Hoppscotch" }
});
window: { title: "Hoppscotch" },
})
if (!loadResp.success) {
throw new Error("Failed to load Hoppscotch Vendored");
throw new Error("Failed to load Hoppscotch Vendored")
}
console.log("Vendored app loaded successfully");
console.log("Vendored app loaded successfully")
} catch (err) {
const errorMessage = err instanceof Error ? err.message : String(err);
console.error("Error loading vendored app:", errorMessage);
error.value = errorMessage;
const errorMessage = err instanceof Error ? err.message : String(err)
console.error("Error loading vendored app:", errorMessage)
error.value = errorMessage
await saveConnectionState({
status: "error",
target: "Vendored",
message: errorMessage
});
message: errorMessage,
})
appState.value = AppState.ERROR;
appState.value = AppState.ERROR
}
};
}
const initialize = async () => {
appState.value = AppState.LOADING;
error.value = "";
downloadProgress.value = { downloaded: 0 };
appState.value = AppState.LOADING
error.value = ""
downloadProgress.value = { downloaded: 0 }
try {
try {
appVersion.value = await getVersion();
appVersion.value = await getVersion()
} catch (error) {
console.error("Failed to get app version:", error);
appVersion.value = "unknown";
console.error("Failed to get app version:", error)
appVersion.value = "unknown"
}
statusMessage.value = "Initializing stores...";
await appStore.init();
await updaterService.initialize();
statusMessage.value = "Initializing stores..."
await appStore.init()
await updaterService.initialize()
await setupUpdateStateWatcher();
await setupUpdateStateWatcher()
statusMessage.value = "Checking for updates...";
const checkResult = await updaterService.checkForUpdates();
statusMessage.value = "Checking for updates..."
const checkResult = await updaterService.checkForUpdates()
if (checkResult === CheckResult.AVAILABLE) {
console.log("Updates available, prompting for install");
appState.value = AppState.UPDATE_AVAILABLE;
return;
console.log("Updates available, prompting for install")
appState.value = AppState.UPDATE_AVAILABLE
return
}
await loadVendored();
await loadVendored()
} catch (err) {
const errorMessage = err instanceof Error ? err.message : String(err);
console.error("Initialization error:", errorMessage);
error.value = errorMessage;
appState.value = AppState.ERROR;
const errorMessage = err instanceof Error ? err.message : String(err)
console.error("Initialization error:", errorMessage)
error.value = errorMessage
appState.value = AppState.ERROR
}
};
}
onMounted(() => {
initialize();
});
initialize()
})
</script>

View file

@ -1,7 +1,7 @@
{
"name": "@hoppscotch/selfhost-web",
"private": true,
"version": "2025.5.1",
"version": "2025.5.2",
"type": "module",
"scripts": {
"dev:vite": "vite",

View file

@ -79,14 +79,14 @@ async function initApp() {
auth: platformDefs.auth.get(kernelMode),
kernelIO,
instance: {
instanceType: 'vendored',
instanceType: "vendored",
displayConfig: {
displayName: 'Hoppscotch',
description: 'On-Prem',
version: '25.5.1',
connectingMessage: 'Connecting to On-prem',
connectedMessage: 'Connected to On-prem'
}
displayName: "Hoppscotch",
description: "On-Prem",
version: "25.5.2",
connectingMessage: "Connecting to On-prem",
connectedMessage: "Connected to On-prem",
},
},
sync: {
environments: platformDefs.environments.get(kernelMode),

View file

@ -47,7 +47,7 @@ pub struct Bundle {
impl Bundle {
pub fn new(bundle_version: Option<String>, content: Vec<u8>, signature: Signature, files: Vec<FileEntry>) -> Self {
let metadata = BundleMetadata {
version: "2025.5.1".to_string(),
version: "2025.5.2".to_string(),
created_at: Utc::now(),
signature,
manifest: Manifest { files },

View file

@ -54,7 +54,7 @@ impl Default for ServerConfig {
Self {
port: default_port(),
max_bundle_size: default_max_bundle_size(),
bundle_version: Some("2025.5.1".to_string()),
bundle_version: Some("2025.5.2".to_string()),
csp_directives: None,
signing_key: None,
verifying_key: None,
@ -75,7 +75,7 @@ impl ServerConfig {
Self {
signing_key: Some(key_pair.signing_key),
verifying_key: Some(key_pair.verifying_key),
bundle_version: Some("2025.5.1".to_string()),
bundle_version: Some("2025.5.2".to_string()),
frontend_path,
is_dev: cfg!(debug_assertions),
..Default::default()

View file

@ -1,7 +1,7 @@
{
"name": "hoppscotch-sh-admin",
"private": true,
"version": "2025.5.1",
"version": "2025.5.2",
"type": "module",
"scripts": {
"dev": "pnpm exec npm-run-all -p -l dev:*",