From 7957ed06e404542859714e18994f266addd69f68 Mon Sep 17 00:00:00 2001 From: LukeGus Date: Thu, 21 Aug 2025 22:47:38 -0500 Subject: [PATCH 01/12] Fix localhost connection issues --- src/ui/Homepage/HomepageAuth.tsx | 118 +++++++------ src/ui/main-axios.ts | 284 ++++++++++++++++++++++--------- 2 files changed, 265 insertions(+), 137 deletions(-) diff --git a/src/ui/Homepage/HomepageAuth.tsx b/src/ui/Homepage/HomepageAuth.tsx index 43241e55..8cb5a221 100644 --- a/src/ui/Homepage/HomepageAuth.tsx +++ b/src/ui/Homepage/HomepageAuth.tsx @@ -1,10 +1,21 @@ import React, {useState, useEffect} from "react"; -import {cn} from "@/lib/utils.ts"; -import {Button} from "@/components/ui/button.tsx"; -import {Input} from "@/components/ui/input.tsx"; -import {Label} from "@/components/ui/label.tsx"; -import {Alert, AlertTitle, AlertDescription} from "@/components/ui/alert.tsx"; -import axios from "axios"; +import {cn} from "../../lib/utils.ts"; +import {Button} from "../../components/ui/button.tsx"; +import {Input} from "../../components/ui/input.tsx"; +import {Label} from "../../components/ui/label.tsx"; +import {Alert, AlertTitle, AlertDescription} from "../../components/ui/alert.tsx"; +import { + registerUser, + loginUser, + getUserInfo, + getRegistrationAllowed, + getOIDCConfig, + getUserCount, + initiatePasswordReset, + verifyPasswordResetCode, + completePasswordReset, + getOIDCAuthorizeUrl +} from "../main-axios.ts"; function setCookie(name: string, value: string, days = 7) { const expires = new Date(Date.now() + days * 864e5).toUTCString(); @@ -18,11 +29,7 @@ function getCookie(name: string) { }, ""); } -const apiBase = import.meta.env.DEV ? "http://localhost:8081/users" : "/users"; -const API = axios.create({ - baseURL: apiBase, -}); interface HomepageAuthProps extends React.ComponentProps<"div"> { setLoggedIn: (loggedIn: boolean) => void; @@ -74,14 +81,14 @@ export function HomepageAuth({ }, [loggedIn]); useEffect(() => { - API.get("/registration-allowed").then(res => { - setRegistrationAllowed(res.data.allowed); + getRegistrationAllowed().then(res => { + setRegistrationAllowed(res.allowed); }); }, []); useEffect(() => { - API.get("/oidc-config").then((response) => { - if (response.data) { + getOIDCConfig().then((response) => { + if (response) { setOidcConfigured(true); } else { setOidcConfigured(false); @@ -96,8 +103,8 @@ export function HomepageAuth({ }, []); useEffect(() => { - API.get("/count").then(res => { - if (res.data.count === 0) { + getUserCount().then(res => { + if (res.count === 0) { setFirstUser(true); setTab("signup"); } else { @@ -123,7 +130,7 @@ export function HomepageAuth({ try { let res, meRes; if (tab === "login") { - res = await API.post("/login", {username: localUsername, password}); + res = await loginUser(localUsername, password); } else { if (password !== signupConfirmPassword) { setError("Passwords do not match"); @@ -135,31 +142,37 @@ export function HomepageAuth({ setLoading(false); return; } - await API.post("/create", {username: localUsername, password}); - res = await API.post("/login", {username: localUsername, password}); + + await registerUser(localUsername, password); + res = await loginUser(localUsername, password); } - setCookie("jwt", res.data.token); + + if (!res || !res.token) { + throw new Error('No token received from login'); + } + + setCookie("jwt", res.token); [meRes] = await Promise.all([ - API.get("/me", {headers: {Authorization: `Bearer ${res.data.token}`}}), - API.get("/db-health") + getUserInfo(), ]); + setInternalLoggedIn(true); setLoggedIn(true); - setIsAdmin(!!meRes.data.is_admin); - setUsername(meRes.data.username || null); - setUserId(meRes.data.id || null); + setIsAdmin(!!meRes.is_admin); + setUsername(meRes.username || null); + setUserId(meRes.userId || null); setDbError(null); onAuthSuccess({ - isAdmin: !!meRes.data.is_admin, - username: meRes.data.username || null, - userId: meRes.data.id || null + isAdmin: !!meRes.is_admin, + username: meRes.username || null, + userId: meRes.userId || null }); setInternalLoggedIn(true); if (tab === "signup") { setSignupConfirmPassword(""); } } catch (err: any) { - setError(err?.response?.data?.error || "Unknown error"); + setError(err?.response?.data?.error || err?.message || "Unknown error"); setInternalLoggedIn(false); setLoggedIn(false); setIsAdmin(false); @@ -176,29 +189,26 @@ export function HomepageAuth({ } } - async function initiatePasswordReset() { + async function handleInitiatePasswordReset() { setError(null); setResetLoading(true); try { - await API.post("/initiate-reset", {username: localUsername}); + const result = await initiatePasswordReset(localUsername); setResetStep("verify"); setError(null); } catch (err: any) { - setError(err?.response?.data?.error || "Failed to initiate password reset"); + setError(err?.response?.data?.error || err?.message || "Failed to initiate password reset"); } finally { setResetLoading(false); } } - async function verifyResetCode() { + async function handleVerifyResetCode() { setError(null); setResetLoading(true); try { - const response = await API.post("/verify-reset-code", { - username: localUsername, - resetCode: resetCode - }); - setTempToken(response.data.tempToken); + const response = await verifyPasswordResetCode(localUsername, resetCode); + setTempToken(response.tempToken); setResetStep("newPassword"); setError(null); } catch (err: any) { @@ -208,7 +218,7 @@ export function HomepageAuth({ } } - async function completePasswordReset() { + async function handleCompletePasswordReset() { setError(null); setResetLoading(true); @@ -225,11 +235,7 @@ export function HomepageAuth({ } try { - await API.post("/complete-reset", { - username: localUsername, - tempToken: tempToken, - newPassword: newPassword - }); + await completePasswordReset(localUsername, tempToken, newPassword); setResetStep("initiate"); setResetCode(""); @@ -267,8 +273,8 @@ export function HomepageAuth({ setError(null); setOidcLoading(true); try { - const authResponse = await API.get("/oidc/authorize"); - const {auth_url: authUrl} = authResponse.data; + const authResponse = await getOIDCAuthorizeUrl(); + const {auth_url: authUrl} = authResponse; if (!authUrl || authUrl === 'undefined') { throw new Error('Invalid authorization URL received from backend'); @@ -299,18 +305,18 @@ export function HomepageAuth({ setError(null); setCookie("jwt", token); - API.get("/me", {headers: {Authorization: `Bearer ${token}`}}) + getUserInfo() .then(meRes => { setInternalLoggedIn(true); setLoggedIn(true); - setIsAdmin(!!meRes.data.is_admin); - setUsername(meRes.data.username || null); - setUserId(meRes.data.id || null); + setIsAdmin(!!meRes.is_admin); + setUsername(meRes.username || null); + setUserId(meRes.id || null); setDbError(null); onAuthSuccess({ - isAdmin: !!meRes.data.is_admin, - username: meRes.data.username || null, - userId: meRes.data.id || null + isAdmin: !!meRes.is_admin, + username: meRes.username || null, + userId: meRes.id || null }); setInternalLoggedIn(true); window.history.replaceState({}, document.title, window.location.pathname); @@ -486,7 +492,7 @@ export function HomepageAuth({ type="button" className="w-full h-11 text-base font-semibold" disabled={resetLoading || !localUsername.trim()} - onClick={initiatePasswordReset} + onClick={handleInitiatePasswordReset} > {resetLoading ? Spinner : "Send Reset Code"} @@ -519,7 +525,7 @@ export function HomepageAuth({ type="button" className="w-full h-11 text-base font-semibold" disabled={resetLoading || resetCode.length !== 6} - onClick={verifyResetCode} + onClick={handleVerifyResetCode} > {resetLoading ? Spinner : "Verify Code"} @@ -598,7 +604,7 @@ export function HomepageAuth({ type="button" className="w-full h-11 text-base font-semibold" disabled={resetLoading || !newPassword || !confirmPassword} - onClick={completePasswordReset} + onClick={handleCompletePasswordReset} > {resetLoading ? Spinner : "Reset Password"} diff --git a/src/ui/main-axios.ts b/src/ui/main-axios.ts index c1192d85..771cb493 100644 --- a/src/ui/main-axios.ts +++ b/src/ui/main-axios.ts @@ -105,35 +105,51 @@ export type ServerMetrics = { lastChecked: string; }; -const isLocalhost = window.location.hostname === 'localhost' || window.location.hostname === '127.0.0.1'; +interface AuthResponse { + token: string; +} -const sshHostApi = axios.create({ - baseURL: isLocalhost ? 'http://localhost:8081' : '', - headers: { - 'Content-Type': 'application/json', - }, -}); +interface UserInfo { + id: string; + username: string; + is_admin: boolean; +} -const tunnelApi = axios.create({ - baseURL: isLocalhost ? 'http://localhost:8083' : '', - headers: { - 'Content-Type': 'application/json', - }, -}); +interface RegistrationResponse { + allowed: boolean; +} -const fileManagerApi = axios.create({ - baseURL: isLocalhost ? 'http://localhost:8084' : '', - headers: { - 'Content-Type': 'application/json', - } -}) +interface OIDCConfig { + configured: boolean; +} -const statsApi = axios.create({ - baseURL: isLocalhost ? 'http://localhost:8085' : '', - headers: { - 'Content-Type': 'application/json', - } -}) +interface UserCount { + count: number; +} + +interface PasswordResetInitiate { + username: string; +} + +interface PasswordResetVerify { + username: string; + resetCode: string; +} + +interface PasswordResetComplete { + username: string; + tempToken: string; + newPassword: string; +} + +interface OIDCAuthorize { + auth_url: string; +} + +function setCookie(name: string, value: string, days = 7) { + const expires = new Date(Date.now() + days * 864e5).toUTCString(); + document.cookie = `${name}=${encodeURIComponent(value)}; expires=${expires}; path=/`; +} function getCookie(name: string): string | undefined { const value = `; ${document.cookie}`; @@ -141,41 +157,54 @@ function getCookie(name: string): string | undefined { if (parts.length === 2) return parts.pop()?.split(';').shift(); } -sshHostApi.interceptors.request.use((config) => { - const token = getCookie('jwt'); - if (token) { - config.headers.Authorization = `Bearer ${token}`; - } - return config; +const sshHostApi = axios.create({ + baseURL: import.meta.env.DEV ? 'http://localhost:8081/ssh' : '/ssh', + headers: { + 'Content-Type': 'application/json', + }, }); -statsApi.interceptors.request.use((config) => { - const token = getCookie('jwt'); - if (token) { - config.headers.Authorization = `Bearer ${token}`; - } - return config; +const tunnelApi = axios.create({ + baseURL: import.meta.env.DEV ? 'http://localhost:8083/ssh' : '/ssh', + headers: { + 'Content-Type': 'application/json', + }, }); -tunnelApi.interceptors.request.use((config) => { - const token = getCookie('jwt'); - if (token) { - config.headers.Authorization = `Bearer ${token}`; +const fileManagerApi = axios.create({ + baseURL: import.meta.env.DEV ? 'http://localhost:8084/ssh' : '/ssh', + headers: { + 'Content-Type': 'application/json', } - return config; }); -fileManagerApi.interceptors.request.use((config) => { - const token = getCookie('jwt'); - if (token) { - config.headers.Authorization = `Bearer ${token}`; +const statsApi = axios.create({ + baseURL: import.meta.env.DEV ? 'http://localhost:8085' : '', + headers: { + 'Content-Type': 'application/json', } - return config; +}); + +const authApi = axios.create({ + baseURL: import.meta.env.DEV ? 'http://localhost:8081/users' : '/users', + headers: { + 'Content-Type': 'application/json', + } +}); + +[sshHostApi, tunnelApi, fileManagerApi, statsApi, authApi].forEach(api => { + api.interceptors.request.use((config) => { + const token = getCookie('jwt'); + if (token) { + config.headers.Authorization = `Bearer ${token}`; + } + return config; + }); }); export async function getSSHHosts(): Promise { try { - const response = await sshHostApi.get('/ssh/db/host'); + const response = await sshHostApi.get('/db/host'); return response.data; } catch (error) { throw error; @@ -220,7 +249,7 @@ export async function createSSHHost(hostData: SSHHostData): Promise { delete dataWithoutFile.key; formData.append('data', JSON.stringify(dataWithoutFile)); - const response = await sshHostApi.post('/ssh/db/host', formData, { + const response = await sshHostApi.post('/db/host', formData, { headers: { 'Content-Type': 'multipart/form-data', }, @@ -228,7 +257,7 @@ export async function createSSHHost(hostData: SSHHostData): Promise { return response.data; } else { - const response = await sshHostApi.post('/ssh/db/host', submitData); + const response = await sshHostApi.post('/db/host', submitData); return response.data; } } catch (error) { @@ -273,7 +302,7 @@ export async function updateSSHHost(hostId: number, hostData: SSHHostData): Prom delete dataWithoutFile.key; formData.append('data', JSON.stringify(dataWithoutFile)); - const response = await sshHostApi.put(`/ssh/db/host/${hostId}`, formData, { + const response = await sshHostApi.put(`/db/host/${hostId}`, formData, { headers: { 'Content-Type': 'multipart/form-data', }, @@ -281,7 +310,7 @@ export async function updateSSHHost(hostId: number, hostData: SSHHostData): Prom return response.data; } else { - const response = await sshHostApi.put(`/ssh/db/host/${hostId}`, submitData); + const response = await sshHostApi.put(`/db/host/${hostId}`, submitData); return response.data; } } catch (error) { @@ -296,7 +325,7 @@ export async function bulkImportSSHHosts(hosts: SSHHostData[]): Promise<{ errors: string[]; }> { try { - const response = await sshHostApi.post('/ssh/bulk-import', {hosts}); + const response = await sshHostApi.post('/bulk-import', {hosts}); return response.data; } catch (error) { throw error; @@ -305,7 +334,7 @@ export async function bulkImportSSHHosts(hosts: SSHHostData[]): Promise<{ export async function deleteSSHHost(hostId: number): Promise { try { - const response = await sshHostApi.delete(`/ssh/db/host/${hostId}`); + const response = await sshHostApi.delete(`/db/host/${hostId}`); return response.data; } catch (error) { throw error; @@ -314,7 +343,7 @@ export async function deleteSSHHost(hostId: number): Promise { export async function getSSHHostById(hostId: number): Promise { try { - const response = await sshHostApi.get(`/ssh/db/host/${hostId}`); + const response = await sshHostApi.get(`/db/host/${hostId}`); return response.data; } catch (error) { throw error; @@ -323,7 +352,7 @@ export async function getSSHHostById(hostId: number): Promise { export async function getTunnelStatuses(): Promise> { try { - const response = await tunnelApi.get('/ssh/tunnel/status'); + const response = await tunnelApi.get('/tunnel/status'); return response.data || {}; } catch (error) { throw error; @@ -337,7 +366,7 @@ export async function getTunnelStatusByName(tunnelName: string): Promise { try { - const response = await tunnelApi.post('/ssh/tunnel/connect', tunnelConfig); + const response = await tunnelApi.post('/tunnel/connect', tunnelConfig); return response.data; } catch (error) { throw error; @@ -346,7 +375,7 @@ export async function connectTunnel(tunnelConfig: TunnelConfig): Promise { export async function disconnectTunnel(tunnelName: string): Promise { try { - const response = await tunnelApi.post('/ssh/tunnel/disconnect', {tunnelName}); + const response = await tunnelApi.post('/tunnel/disconnect', {tunnelName}); return response.data; } catch (error) { throw error; @@ -355,7 +384,7 @@ export async function disconnectTunnel(tunnelName: string): Promise { export async function cancelTunnel(tunnelName: string): Promise { try { - const response = await tunnelApi.post('/ssh/tunnel/cancel', {tunnelName}); + const response = await tunnelApi.post('/tunnel/cancel', {tunnelName}); return response.data; } catch (error) { throw error; @@ -364,7 +393,7 @@ export async function cancelTunnel(tunnelName: string): Promise { export async function getFileManagerRecent(hostId: number): Promise { try { - const response = await sshHostApi.get(`/ssh/file_manager/recent?hostId=${hostId}`); + const response = await sshHostApi.get(`/file_manager/recent?hostId=${hostId}`); return response.data || []; } catch (error) { return []; @@ -379,7 +408,7 @@ export async function addFileManagerRecent(file: { hostId: number }): Promise { try { - const response = await sshHostApi.post('/ssh/file_manager/recent', file); + const response = await sshHostApi.post('/file_manager/recent', file); return response.data; } catch (error) { throw error; @@ -394,7 +423,7 @@ export async function removeFileManagerRecent(file: { hostId: number }): Promise { try { - const response = await sshHostApi.delete('/ssh/file_manager/recent', {data: file}); + const response = await sshHostApi.delete('/file_manager/recent', {data: file}); return response.data; } catch (error) { throw error; @@ -403,7 +432,7 @@ export async function removeFileManagerRecent(file: { export async function getFileManagerPinned(hostId: number): Promise { try { - const response = await sshHostApi.get(`/ssh/file_manager/pinned?hostId=${hostId}`); + const response = await sshHostApi.get(`/file_manager/pinned?hostId=${hostId}`); return response.data || []; } catch (error) { return []; @@ -418,7 +447,7 @@ export async function addFileManagerPinned(file: { hostId: number }): Promise { try { - const response = await sshHostApi.post('/ssh/file_manager/pinned', file); + const response = await sshHostApi.post('/file_manager/pinned', file); return response.data; } catch (error) { throw error; @@ -433,7 +462,7 @@ export async function removeFileManagerPinned(file: { hostId: number }): Promise { try { - const response = await sshHostApi.delete('/ssh/file_manager/pinned', {data: file}); + const response = await sshHostApi.delete('/file_manager/pinned', {data: file}); return response.data; } catch (error) { throw error; @@ -442,7 +471,7 @@ export async function removeFileManagerPinned(file: { export async function getFileManagerShortcuts(hostId: number): Promise { try { - const response = await sshHostApi.get(`/ssh/file_manager/shortcuts?hostId=${hostId}`); + const response = await sshHostApi.get(`/file_manager/shortcuts?hostId=${hostId}`); return response.data || []; } catch (error) { return []; @@ -457,7 +486,7 @@ export async function addFileManagerShortcut(shortcut: { hostId: number }): Promise { try { - const response = await sshHostApi.post('/ssh/file_manager/shortcuts', shortcut); + const response = await sshHostApi.post('/file_manager/shortcuts', shortcut); return response.data; } catch (error) { throw error; @@ -472,7 +501,7 @@ export async function removeFileManagerShortcut(shortcut: { hostId: number }): Promise { try { - const response = await sshHostApi.delete('/ssh/file_manager/shortcuts', {data: shortcut}); + const response = await sshHostApi.delete('/file_manager/shortcuts', {data: shortcut}); return response.data; } catch (error) { throw error; @@ -488,7 +517,7 @@ export async function connectSSH(sessionId: string, config: { keyPassword?: string; }): Promise { try { - const response = await fileManagerApi.post('/ssh/file_manager/ssh/connect', { + const response = await fileManagerApi.post('/ssh/connect', { sessionId, ...config }); @@ -500,7 +529,7 @@ export async function connectSSH(sessionId: string, config: { export async function disconnectSSH(sessionId: string): Promise { try { - const response = await fileManagerApi.post('/ssh/file_manager/ssh/disconnect', {sessionId}); + const response = await fileManagerApi.post('/ssh/disconnect', {sessionId}); return response.data; } catch (error) { throw error; @@ -509,7 +538,7 @@ export async function disconnectSSH(sessionId: string): Promise { export async function getSSHStatus(sessionId: string): Promise<{ connected: boolean }> { try { - const response = await fileManagerApi.get('/ssh/file_manager/ssh/status', { + const response = await fileManagerApi.get('/ssh/status', { params: {sessionId} }); return response.data; @@ -520,7 +549,7 @@ export async function getSSHStatus(sessionId: string): Promise<{ connected: bool export async function listSSHFiles(sessionId: string, path: string): Promise { try { - const response = await fileManagerApi.get('/ssh/file_manager/ssh/listFiles', { + const response = await fileManagerApi.get('/ssh/listFiles', { params: {sessionId, path} }); return response.data || []; @@ -531,7 +560,7 @@ export async function listSSHFiles(sessionId: string, path: string): Promise { try { - const response = await fileManagerApi.get('/ssh/file_manager/ssh/readFile', { + const response = await fileManagerApi.get('/ssh/readFile', { params: {sessionId, path} }); return response.data; @@ -542,7 +571,7 @@ export async function readSSHFile(sessionId: string, path: string): Promise<{ co export async function writeSSHFile(sessionId: string, path: string, content: string): Promise { try { - const response = await fileManagerApi.post('/ssh/file_manager/ssh/writeFile', { + const response = await fileManagerApi.post('/ssh/writeFile', { sessionId, path, content @@ -560,7 +589,7 @@ export async function writeSSHFile(sessionId: string, path: string, content: str export async function uploadSSHFile(sessionId: string, path: string, fileName: string, content: string): Promise { try { - const response = await fileManagerApi.post('/ssh/file_manager/ssh/uploadFile', { + const response = await fileManagerApi.post('/ssh/uploadFile', { sessionId, path, fileName, @@ -574,7 +603,7 @@ export async function uploadSSHFile(sessionId: string, path: string, fileName: s export async function createSSHFile(sessionId: string, path: string, fileName: string, content: string = ''): Promise { try { - const response = await fileManagerApi.post('/ssh/file_manager/ssh/createFile', { + const response = await fileManagerApi.post('/ssh/createFile', { sessionId, path, fileName, @@ -588,7 +617,7 @@ export async function createSSHFile(sessionId: string, path: string, fileName: s export async function createSSHFolder(sessionId: string, path: string, folderName: string): Promise { try { - const response = await fileManagerApi.post('/ssh/file_manager/ssh/createFolder', { + const response = await fileManagerApi.post('/ssh/createFolder', { sessionId, path, folderName @@ -601,7 +630,7 @@ export async function createSSHFolder(sessionId: string, path: string, folderNam export async function deleteSSHItem(sessionId: string, path: string, isDirectory: boolean): Promise { try { - const response = await fileManagerApi.delete('/ssh/file_manager/ssh/deleteItem', { + const response = await fileManagerApi.delete('/ssh/deleteItem', { data: { sessionId, path, @@ -616,7 +645,7 @@ export async function deleteSSHItem(sessionId: string, path: string, isDirectory export async function renameSSHItem(sessionId: string, oldPath: string, newName: string): Promise { try { - const response = await fileManagerApi.put('/ssh/file_manager/ssh/renameItem', { + const response = await fileManagerApi.put('/ssh/renameItem', { sessionId, oldPath, newName @@ -627,7 +656,7 @@ export async function renameSSHItem(sessionId: string, oldPath: string, newName: } } -export {sshHostApi, tunnelApi, fileManagerApi}; + export async function getAllServerStatuses(): Promise> { try { @@ -654,4 +683,97 @@ export async function getServerMetricsById(id: number): Promise { } catch (error) { throw error; } -} \ No newline at end of file +} + +// Auth-related functions +export async function registerUser(username: string, password: string): Promise { + try { + const response = await authApi.post('/create', { username, password }); + return response.data; + } catch (error) { + throw error; + } +} + +export async function loginUser(username: string, password: string): Promise { + try { + const response = await authApi.post('/login', { username, password }); + return response.data; + } catch (error) { + throw error; + } +} + +export async function getUserInfo(): Promise { + try { + const response = await authApi.get('/me'); + return response.data; + } catch (error) { + throw error; + } +} + +export async function getRegistrationAllowed(): Promise<{ allowed: boolean }> { + try { + const response = await authApi.get('/registration-allowed'); + return response.data; + } catch (error) { + throw error; + } +} + +export async function getOIDCConfig(): Promise { + try { + const response = await authApi.get('/oidc-config'); + return response.data; + } catch (error) { + throw error; + } +} + +export async function getUserCount(): Promise { + try { + const response = await authApi.get('/count'); + return response.data; + } catch (error) { + throw error; + } +} + +export async function initiatePasswordReset(username: string): Promise { + try { + const response = await authApi.post('/initiate-reset', { username }); + return response.data; + } catch (error) { + throw error; + } +} + +export async function verifyPasswordResetCode(username: string, resetCode: string): Promise { + try { + const response = await authApi.post('/verify-reset-code', { username, resetCode }); + return response.data; + } catch (error) { + throw error; + } +} + +export async function completePasswordReset(username: string, tempToken: string, newPassword: string): Promise { + try { + const response = await authApi.post('/complete-reset', { username, tempToken, newPassword }); + return response.data; + } catch (error) { + throw error; + } +} + +export async function getOIDCAuthorizeUrl(): Promise { + try { + const response = await authApi.get('/oidc/authorize'); + return response.data; + } catch (error) { + throw error; + } +} + +export {sshHostApi, tunnelApi, fileManagerApi, authApi}; \ No newline at end of file From 23e72aedfd6b81a795ee835793482d337a202dbd Mon Sep 17 00:00:00 2001 From: LukeGus Date: Sun, 24 Aug 2025 00:59:39 -0500 Subject: [PATCH 02/12] Migrate to new websocket link for locahlost --- src/ui/apps/Terminal/TerminalComponent.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/ui/apps/Terminal/TerminalComponent.tsx b/src/ui/apps/Terminal/TerminalComponent.tsx index d77ac606..322afa41 100644 --- a/src/ui/apps/Terminal/TerminalComponent.tsx +++ b/src/ui/apps/Terminal/TerminalComponent.tsx @@ -226,7 +226,9 @@ export const TerminalComponent = forwardRef(function SSHT const cols = terminal.cols; const rows = terminal.rows; - const wsUrl = window.location.hostname === 'localhost' ? 'ws://localhost:8082' : `${window.location.protocol === 'https:' ? 'wss' : 'ws'}://${window.location.host}/ssh/websocket/`; + const wsUrl = import.meta.env.DEV + ? 'ws://localhost:8082' + : `${window.location.protocol === 'https:' ? 'wss' : 'ws'}://${window.location.host}/ssh/websocket/`; const ws = new WebSocket(wsUrl); webSocketRef.current = ws; From 94f69cee3f1f001f6ea091a5c4a860c1a193a0ef Mon Sep 17 00:00:00 2001 From: LukeGus Date: Sun, 24 Aug 2025 01:10:59 -0500 Subject: [PATCH 03/12] Migrate to new websocket link for locahlost --- src/backend/database/routes/users.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/backend/database/routes/users.ts b/src/backend/database/routes/users.ts index 790ac7be..aca004ab 100644 --- a/src/backend/database/routes/users.ts +++ b/src/backend/database/routes/users.ts @@ -79,7 +79,7 @@ async function verifyOIDCToken(idToken: string, issuerUrl: string, clientId: str const key = await importJWK(publicKey); const {payload} = await jwtVerify(idToken, key, { - issuer: issuerUrl, + issuer: [issuerUrl, issuerUrl.replace(/\/application\/o\/[^\/]+$/, '')], audience: clientId, }); From cef420d1d8d7c74595f2f48db370cf753b0d7fd0 Mon Sep 17 00:00:00 2001 From: LukeGus Date: Sun, 24 Aug 2025 01:27:41 -0500 Subject: [PATCH 04/12] Clean up main-axios.ts --- src/ui/main-axios.ts | 390 ++++++++++++++++++++++++------------------- 1 file changed, 218 insertions(+), 172 deletions(-) diff --git a/src/ui/main-axios.ts b/src/ui/main-axios.ts index 771cb493..4c3a5c99 100644 --- a/src/ui/main-axios.ts +++ b/src/ui/main-axios.ts @@ -1,4 +1,8 @@ -import axios from 'axios'; +import axios, { AxiosError, AxiosInstance } from 'axios'; + +// ============================================================================ +// TYPES & INTERFACES +// ============================================================================ interface SSHHostData { name?: string; @@ -93,15 +97,41 @@ interface FileManagerShortcut { path: string; } +interface FileManagerOperation { + name: string; + path: string; + isSSH: boolean; + sshSessionId?: string; + hostId: number; +} + export type ServerStatus = { status: 'online' | 'offline'; lastChecked: string; }; +interface CpuMetrics { + percent: number | null; + cores: number | null; + load: [number, number, number] | null; +} + +interface MemoryMetrics { + percent: number | null; + usedGiB: number | null; + totalGiB: number | null; +} + +interface DiskMetrics { + percent: number | null; + usedHuman: string | null; + totalHuman: string | null; +} + export type ServerMetrics = { - cpu: { percent: number | null; cores: number | null; load: [number, number, number] | null }; - memory: { percent: number | null; usedGiB: number | null; totalGiB: number | null }; - disk: { percent: number | null; usedHuman: string | null; totalHuman: string | null }; + cpu: CpuMetrics; + memory: MemoryMetrics; + disk: DiskMetrics; lastChecked: string; }; @@ -115,38 +145,19 @@ interface UserInfo { is_admin: boolean; } -interface RegistrationResponse { - allowed: boolean; -} - -interface OIDCConfig { - configured: boolean; -} - interface UserCount { count: number; } -interface PasswordResetInitiate { - username: string; -} - -interface PasswordResetVerify { - username: string; - resetCode: string; -} - -interface PasswordResetComplete { - username: string; - tempToken: string; - newPassword: string; -} - interface OIDCAuthorize { auth_url: string; } -function setCookie(name: string, value: string, days = 7) { +// ============================================================================ +// UTILITY FUNCTIONS +// ============================================================================ + +function setCookie(name: string, value: string, days = 7): void { const expires = new Date(Date.now() + days * 864e5).toUTCString(); document.cookie = `${name}=${encodeURIComponent(value)}; expires=${expires}; path=/`; } @@ -157,57 +168,118 @@ function getCookie(name: string): string | undefined { if (parts.length === 2) return parts.pop()?.split(';').shift(); } -const sshHostApi = axios.create({ - baseURL: import.meta.env.DEV ? 'http://localhost:8081/ssh' : '/ssh', - headers: { - 'Content-Type': 'application/json', - }, -}); +function createApiInstance(baseURL: string): AxiosInstance { + const instance = axios.create({ + baseURL, + headers: { 'Content-Type': 'application/json' }, + timeout: 30000, + }); -const tunnelApi = axios.create({ - baseURL: import.meta.env.DEV ? 'http://localhost:8083/ssh' : '/ssh', - headers: { - 'Content-Type': 'application/json', - }, -}); - -const fileManagerApi = axios.create({ - baseURL: import.meta.env.DEV ? 'http://localhost:8084/ssh' : '/ssh', - headers: { - 'Content-Type': 'application/json', - } -}); - -const statsApi = axios.create({ - baseURL: import.meta.env.DEV ? 'http://localhost:8085' : '', - headers: { - 'Content-Type': 'application/json', - } -}); - -const authApi = axios.create({ - baseURL: import.meta.env.DEV ? 'http://localhost:8081/users' : '/users', - headers: { - 'Content-Type': 'application/json', - } -}); - -[sshHostApi, tunnelApi, fileManagerApi, statsApi, authApi].forEach(api => { - api.interceptors.request.use((config) => { + // Add JWT token to all requests + instance.interceptors.request.use((config) => { const token = getCookie('jwt'); if (token) { config.headers.Authorization = `Bearer ${token}`; } return config; }); -}); + + // Global error handling + instance.interceptors.response.use( + (response) => response, + (error: AxiosError) => { + if (error.response?.status === 401) { + // Token expired or invalid - clear cookie + document.cookie = 'jwt=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;'; + } + return Promise.reject(error); + } + ); + + return instance; +} + +// ============================================================================ +// API INSTANCES +// ============================================================================ + +const isDev = process.env.NODE_ENV === 'development' || window.location.hostname === 'localhost'; + +// SSH Host Management API (port 8081) +export const sshHostApi = createApiInstance( + isDev ? 'http://localhost:8081/ssh' : '/ssh' +); + +// Tunnel Management API (port 8083) +export const tunnelApi = createApiInstance( + isDev ? 'http://localhost:8083/ssh' : '/ssh' +); + +// File Manager Operations API (port 8084) - SSH file operations +export const fileManagerApi = createApiInstance( + isDev ? 'http://localhost:8084/ssh/file_manager' : '/ssh/file_manager' +); + +// Server Statistics API (port 8085) +export const statsApi = createApiInstance( + isDev ? 'http://localhost:8085' : '' +); + +// Authentication API (port 8081) +export const authApi = createApiInstance( + isDev ? 'http://localhost:8081/users' : '/users' +); + +// ============================================================================ +// ERROR HANDLING +// ============================================================================ + +class ApiError extends Error { + constructor( + message: string, + public status?: number, + public code?: string + ) { + super(message); + this.name = 'ApiError'; + } +} + +function handleApiError(error: unknown, operation: string): never { + if (axios.isAxiosError(error)) { + const status = error.response?.status; + const message = error.response?.data?.error || error.message; + + if (status === 401) { + throw new ApiError('Authentication required', 401); + } else if (status === 403) { + throw new ApiError('Access denied', 403); + } else if (status === 404) { + throw new ApiError('Resource not found', 404); + } else if (status && status >= 500) { + throw new ApiError('Server error occurred', status); + } else { + throw new ApiError(message || `Failed to ${operation}`, status); + } + } + + if (error instanceof ApiError) { + throw error; + } + + throw new ApiError(`Unexpected error during ${operation}: ${error instanceof Error ? error.message : 'Unknown error'}`); +} + +// ============================================================================ +// SSH HOST MANAGEMENT +// ============================================================================ export async function getSSHHosts(): Promise { try { const response = await sshHostApi.get('/db/host'); return response.data; } catch (error) { - throw error; + handleApiError(error, 'fetch SSH hosts'); } } @@ -245,23 +317,20 @@ export async function createSSHHost(hostData: SSHHostData): Promise { const formData = new FormData(); formData.append('key', hostData.key); - const dataWithoutFile = {...submitData}; + const dataWithoutFile = { ...submitData }; delete dataWithoutFile.key; formData.append('data', JSON.stringify(dataWithoutFile)); const response = await sshHostApi.post('/db/host', formData, { - headers: { - 'Content-Type': 'multipart/form-data', - }, + headers: { 'Content-Type': 'multipart/form-data' }, }); - return response.data; } else { const response = await sshHostApi.post('/db/host', submitData); return response.data; } } catch (error) { - throw error; + handleApiError(error, 'create SSH host'); } } @@ -298,23 +367,20 @@ export async function updateSSHHost(hostId: number, hostData: SSHHostData): Prom const formData = new FormData(); formData.append('key', hostData.key); - const dataWithoutFile = {...submitData}; + const dataWithoutFile = { ...submitData }; delete dataWithoutFile.key; formData.append('data', JSON.stringify(dataWithoutFile)); const response = await sshHostApi.put(`/db/host/${hostId}`, formData, { - headers: { - 'Content-Type': 'multipart/form-data', - }, + headers: { 'Content-Type': 'multipart/form-data' }, }); - return response.data; } else { const response = await sshHostApi.put(`/db/host/${hostId}`, submitData); return response.data; } } catch (error) { - throw error; + handleApiError(error, 'update SSH host'); } } @@ -325,10 +391,10 @@ export async function bulkImportSSHHosts(hosts: SSHHostData[]): Promise<{ errors: string[]; }> { try { - const response = await sshHostApi.post('/bulk-import', {hosts}); + const response = await sshHostApi.post('/bulk-import', { hosts }); return response.data; } catch (error) { - throw error; + handleApiError(error, 'bulk import SSH hosts'); } } @@ -337,7 +403,7 @@ export async function deleteSSHHost(hostId: number): Promise { const response = await sshHostApi.delete(`/db/host/${hostId}`); return response.data; } catch (error) { - throw error; + handleApiError(error, 'delete SSH host'); } } @@ -346,16 +412,20 @@ export async function getSSHHostById(hostId: number): Promise { const response = await sshHostApi.get(`/db/host/${hostId}`); return response.data; } catch (error) { - throw error; + handleApiError(error, 'fetch SSH host'); } } +// ============================================================================ +// TUNNEL MANAGEMENT +// ============================================================================ + export async function getTunnelStatuses(): Promise> { try { const response = await tunnelApi.get('/tunnel/status'); return response.data || {}; } catch (error) { - throw error; + handleApiError(error, 'fetch tunnel statuses'); } } @@ -369,64 +439,57 @@ export async function connectTunnel(tunnelConfig: TunnelConfig): Promise { const response = await tunnelApi.post('/tunnel/connect', tunnelConfig); return response.data; } catch (error) { - throw error; + handleApiError(error, 'connect tunnel'); } } export async function disconnectTunnel(tunnelName: string): Promise { try { - const response = await tunnelApi.post('/tunnel/disconnect', {tunnelName}); + const response = await tunnelApi.post('/tunnel/disconnect', { tunnelName }); return response.data; } catch (error) { - throw error; + handleApiError(error, 'disconnect tunnel'); } } export async function cancelTunnel(tunnelName: string): Promise { try { - const response = await tunnelApi.post('/tunnel/cancel', {tunnelName}); + const response = await tunnelApi.post('/tunnel/cancel', { tunnelName }); return response.data; } catch (error) { - throw error; + handleApiError(error, 'cancel tunnel'); } } +// ============================================================================ +// FILE MANAGER METADATA (Recent, Pinned, Shortcuts) +// ============================================================================ + export async function getFileManagerRecent(hostId: number): Promise { try { const response = await sshHostApi.get(`/file_manager/recent?hostId=${hostId}`); return response.data || []; } catch (error) { + // Don't throw for file manager metadata - return empty array return []; } } -export async function addFileManagerRecent(file: { - name: string; - path: string; - isSSH: boolean; - sshSessionId?: string; - hostId: number -}): Promise { +export async function addFileManagerRecent(file: FileManagerOperation): Promise { try { const response = await sshHostApi.post('/file_manager/recent', file); return response.data; } catch (error) { - throw error; + handleApiError(error, 'add recent file'); } } -export async function removeFileManagerRecent(file: { - name: string; - path: string; - isSSH: boolean; - sshSessionId?: string; - hostId: number -}): Promise { +export async function removeFileManagerRecent(file: FileManagerOperation): Promise { try { - const response = await sshHostApi.delete('/file_manager/recent', {data: file}); + const response = await sshHostApi.delete('/file_manager/recent', { data: file }); return response.data; } catch (error) { - throw error; + handleApiError(error, 'remove recent file'); } } @@ -439,33 +502,21 @@ export async function getFileManagerPinned(hostId: number): Promise { +export async function addFileManagerPinned(file: FileManagerOperation): Promise { try { const response = await sshHostApi.post('/file_manager/pinned', file); return response.data; } catch (error) { - throw error; + handleApiError(error, 'add pinned file'); } } -export async function removeFileManagerPinned(file: { - name: string; - path: string; - isSSH: boolean; - sshSessionId?: string; - hostId: number -}): Promise { +export async function removeFileManagerPinned(file: FileManagerOperation): Promise { try { - const response = await sshHostApi.delete('/file_manager/pinned', {data: file}); + const response = await sshHostApi.delete('/file_manager/pinned', { data: file }); return response.data; } catch (error) { - throw error; + handleApiError(error, 'remove pinned file'); } } @@ -478,36 +529,28 @@ export async function getFileManagerShortcuts(hostId: number): Promise { +export async function addFileManagerShortcut(shortcut: FileManagerOperation): Promise { try { const response = await sshHostApi.post('/file_manager/shortcuts', shortcut); return response.data; } catch (error) { - throw error; + handleApiError(error, 'add shortcut'); } } -export async function removeFileManagerShortcut(shortcut: { - name: string; - path: string; - isSSH: boolean; - sshSessionId?: string; - hostId: number -}): Promise { +export async function removeFileManagerShortcut(shortcut: FileManagerOperation): Promise { try { - const response = await sshHostApi.delete('/file_manager/shortcuts', {data: shortcut}); + const response = await sshHostApi.delete('/file_manager/shortcuts', { data: shortcut }); return response.data; } catch (error) { - throw error; + handleApiError(error, 'remove shortcut'); } } +// ============================================================================ +// SSH FILE OPERATIONS +// ============================================================================ + export async function connectSSH(sessionId: string, config: { ip: string; port: number; @@ -523,49 +566,49 @@ export async function connectSSH(sessionId: string, config: { }); return response.data; } catch (error) { - throw error; + handleApiError(error, 'connect SSH'); } } export async function disconnectSSH(sessionId: string): Promise { try { - const response = await fileManagerApi.post('/ssh/disconnect', {sessionId}); + const response = await fileManagerApi.post('/ssh/disconnect', { sessionId }); return response.data; } catch (error) { - throw error; + handleApiError(error, 'disconnect SSH'); } } export async function getSSHStatus(sessionId: string): Promise<{ connected: boolean }> { try { const response = await fileManagerApi.get('/ssh/status', { - params: {sessionId} + params: { sessionId } }); return response.data; } catch (error) { - throw error; + handleApiError(error, 'get SSH status'); } } export async function listSSHFiles(sessionId: string, path: string): Promise { try { const response = await fileManagerApi.get('/ssh/listFiles', { - params: {sessionId, path} + params: { sessionId, path } }); return response.data || []; } catch (error) { - throw error; + handleApiError(error, 'list SSH files'); } } export async function readSSHFile(sessionId: string, path: string): Promise<{ content: string; path: string }> { try { const response = await fileManagerApi.get('/ssh/readFile', { - params: {sessionId, path} + params: { sessionId, path } }); return response.data; } catch (error) { - throw error; + handleApiError(error, 'read SSH file'); } } @@ -583,7 +626,7 @@ export async function writeSSHFile(sessionId: string, path: string, content: str throw new Error('File write operation did not return success status'); } } catch (error) { - throw error; + handleApiError(error, 'write SSH file'); } } @@ -597,7 +640,7 @@ export async function uploadSSHFile(sessionId: string, path: string, fileName: s }); return response.data; } catch (error) { - throw error; + handleApiError(error, 'upload SSH file'); } } @@ -611,7 +654,7 @@ export async function createSSHFile(sessionId: string, path: string, fileName: s }); return response.data; } catch (error) { - throw error; + handleApiError(error, 'create SSH file'); } } @@ -624,7 +667,7 @@ export async function createSSHFolder(sessionId: string, path: string, folderNam }); return response.data; } catch (error) { - throw error; + handleApiError(error, 'create SSH folder'); } } @@ -639,7 +682,7 @@ export async function deleteSSHItem(sessionId: string, path: string, isDirectory }); return response.data; } catch (error) { - throw error; + handleApiError(error, 'delete SSH item'); } } @@ -652,18 +695,20 @@ export async function renameSSHItem(sessionId: string, oldPath: string, newName: }); return response.data; } catch (error) { - throw error; + handleApiError(error, 'rename SSH item'); } } - +// ============================================================================ +// SERVER STATISTICS +// ============================================================================ export async function getAllServerStatuses(): Promise> { try { const response = await statsApi.get('/status'); return response.data || {}; } catch (error) { - throw error; + handleApiError(error, 'fetch server statuses'); } } @@ -672,7 +717,7 @@ export async function getServerStatusById(id: number): Promise { const response = await statsApi.get(`/status/${id}`); return response.data; } catch (error) { - throw error; + handleApiError(error, 'fetch server status'); } } @@ -681,17 +726,20 @@ export async function getServerMetricsById(id: number): Promise { const response = await statsApi.get(`/metrics/${id}`); return response.data; } catch (error) { - throw error; + handleApiError(error, 'fetch server metrics'); } } -// Auth-related functions +// ============================================================================ +// AUTHENTICATION +// ============================================================================ + export async function registerUser(username: string, password: string): Promise { try { const response = await authApi.post('/create', { username, password }); return response.data; } catch (error) { - throw error; + handleApiError(error, 'register user'); } } @@ -700,7 +748,7 @@ export async function loginUser(username: string, password: string): Promise { const response = await authApi.get('/me'); return response.data; } catch (error) { - throw error; + handleApiError(error, 'fetch user info'); } } @@ -718,7 +766,7 @@ export async function getRegistrationAllowed(): Promise<{ allowed: boolean }> { const response = await authApi.get('/registration-allowed'); return response.data; } catch (error) { - throw error; + handleApiError(error, 'check registration status'); } } @@ -727,7 +775,7 @@ export async function getOIDCConfig(): Promise { const response = await authApi.get('/oidc-config'); return response.data; } catch (error) { - throw error; + handleApiError(error, 'fetch OIDC config'); } } @@ -736,7 +784,7 @@ export async function getUserCount(): Promise { const response = await authApi.get('/count'); return response.data; } catch (error) { - throw error; + handleApiError(error, 'fetch user count'); } } @@ -745,7 +793,7 @@ export async function initiatePasswordReset(username: string): Promise { const response = await authApi.post('/initiate-reset', { username }); return response.data; } catch (error) { - throw error; + handleApiError(error, 'initiate password reset'); } } @@ -754,7 +802,7 @@ export async function verifyPasswordResetCode(username: string, resetCode: strin const response = await authApi.post('/verify-reset-code', { username, resetCode }); return response.data; } catch (error) { - throw error; + handleApiError(error, 'verify reset code'); } } @@ -763,7 +811,7 @@ export async function completePasswordReset(username: string, tempToken: string, const response = await authApi.post('/complete-reset', { username, tempToken, newPassword }); return response.data; } catch (error) { - throw error; + handleApiError(error, 'complete password reset'); } } @@ -772,8 +820,6 @@ export async function getOIDCAuthorizeUrl(): Promise { const response = await authApi.get('/oidc/authorize'); return response.data; } catch (error) { - throw error; + handleApiError(error, 'get OIDC authorize URL'); } -} - -export {sshHostApi, tunnelApi, fileManagerApi, authApi}; \ No newline at end of file +} \ No newline at end of file From f2fb938e5f3781c1bed3723837c36ddedb197b83 Mon Sep 17 00:00:00 2001 From: LukeGus Date: Sun, 24 Aug 2025 01:28:18 -0500 Subject: [PATCH 05/12] Clean up main-axios.ts --- src/ui/main-axios.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/ui/main-axios.ts b/src/ui/main-axios.ts index 4c3a5c99..85766006 100644 --- a/src/ui/main-axios.ts +++ b/src/ui/main-axios.ts @@ -175,7 +175,6 @@ function createApiInstance(baseURL: string): AxiosInstance { timeout: 30000, }); - // Add JWT token to all requests instance.interceptors.request.use((config) => { const token = getCookie('jwt'); if (token) { @@ -184,7 +183,6 @@ function createApiInstance(baseURL: string): AxiosInstance { return config; }); - // Global error handling instance.interceptors.response.use( (response) => response, (error: AxiosError) => { From 5ac25e2a2676b4b750a9328d3e77895c7303066f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 24 Aug 2025 21:08:49 +0000 Subject: [PATCH 06/12] Bump docker/build-push-action from 5 to 6 Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 5 to 6. - [Release notes](https://github.com/docker/build-push-action/releases) - [Commits](https://github.com/docker/build-push-action/compare/v5...v6) --- updated-dependencies: - dependency-name: docker/build-push-action dependency-version: '6' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/docker-image.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docker-image.yml b/.github/workflows/docker-image.yml index 2d473e10..f88215d6 100644 --- a/.github/workflows/docker-image.yml +++ b/.github/workflows/docker-image.yml @@ -78,7 +78,7 @@ jobs: echo "IMAGE_TAG=$IMAGE_TAG" >> $GITHUB_ENV - name: Build and Push Multi-Arch Docker Image - uses: docker/build-push-action@v5 + uses: docker/build-push-action@v6 with: context: . file: ./docker/Dockerfile From 402f9fa909b298037c4d2ab026aa1b236c3d33cc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 24 Aug 2025 21:08:51 +0000 Subject: [PATCH 07/12] Bump actions/checkout from 4 to 5 Bumps [actions/checkout](https://github.com/actions/checkout) from 4 to 5. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v4...v5) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: '5' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/docker-image.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docker-image.yml b/.github/workflows/docker-image.yml index 2d473e10..897fe7de 100644 --- a/.github/workflows/docker-image.yml +++ b/.github/workflows/docker-image.yml @@ -19,7 +19,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: fetch-depth: 1 From e364e9b38eb9842be3a116f4848759647f826ccd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 24 Aug 2025 21:08:53 +0000 Subject: [PATCH 08/12] Bump actions/cache from 3 to 4 Bumps [actions/cache](https://github.com/actions/cache) from 3 to 4. - [Release notes](https://github.com/actions/cache/releases) - [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md) - [Commits](https://github.com/actions/cache/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/cache dependency-version: '4' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/docker-image.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/docker-image.yml b/.github/workflows/docker-image.yml index 2d473e10..1e583af5 100644 --- a/.github/workflows/docker-image.yml +++ b/.github/workflows/docker-image.yml @@ -37,7 +37,7 @@ jobs: network=host - name: Cache npm dependencies - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: | ~/.npm @@ -48,7 +48,7 @@ jobs: ${{ runner.os }}-node- - name: Cache Docker layers - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: /tmp/.buildx-cache key: ${{ runner.os }}-buildx-${{ github.ref_name }}-${{ hashFiles('docker/Dockerfile') }} From 12418eb5b29b8faf3c3c5e7b814100b9dab1fa27 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 24 Aug 2025 21:08:59 +0000 Subject: [PATCH 09/12] Bump node from 22-alpine to 24-alpine in /docker Bumps node from 22-alpine to 24-alpine. --- updated-dependencies: - dependency-name: node dependency-version: 24-alpine dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- docker/Dockerfile | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index c82aa3e6..15f3d81f 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -1,5 +1,5 @@ # Stage 1: Install dependencies and build frontend -FROM node:22-alpine AS deps +FROM node:24-alpine AS deps WORKDIR /app RUN apk add --no-cache python3 make g++ @@ -26,7 +26,7 @@ COPY . . RUN npm run build:backend # Stage 4: Production dependencies -FROM node:22-alpine AS production-deps +FROM node:24-alpine AS production-deps WORKDIR /app COPY package*.json ./ @@ -35,7 +35,7 @@ RUN npm ci --only=production --ignore-scripts --force && \ npm cache clean --force # Stage 5: Build native modules -FROM node:22-alpine AS native-builder +FROM node:24-alpine AS native-builder WORKDIR /app RUN apk add --no-cache python3 make g++ @@ -46,7 +46,7 @@ RUN npm ci --only=production bcryptjs better-sqlite3 --force && \ npm cache clean --force # Stage 6: Final image -FROM node:22-alpine +FROM node:24-alpine ENV DATA_DIR=/app/data \ PORT=8080 \ NODE_ENV=production From 6ac536ebad44ab8b70fd7059982256c96c63cda3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 24 Aug 2025 21:09:29 +0000 Subject: [PATCH 10/12] Bump tw-animate-css from 1.3.5 to 1.3.7 in the dev-patch-updates group Bumps the dev-patch-updates group with 1 update: [tw-animate-css](https://github.com/Wombosvideo/tw-animate-css). Updates `tw-animate-css` from 1.3.5 to 1.3.7 - [Release notes](https://github.com/Wombosvideo/tw-animate-css/releases) - [Commits](https://github.com/Wombosvideo/tw-animate-css/compare/v1.3.5...v1.3.7) --- updated-dependencies: - dependency-name: tw-animate-css dependency-version: 1.3.7 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: dev-patch-updates ... Signed-off-by: dependabot[bot] --- package-lock.json | 62 ++++++++++++++++++++++++++++++++++++++++++++--- package.json | 2 +- 2 files changed, 59 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index dc2db2ae..b12d4f42 100644 --- a/package-lock.json +++ b/package-lock.json @@ -89,7 +89,7 @@ "eslint-plugin-react-refresh": "^0.4.20", "globals": "^16.3.0", "ts-node": "^10.9.2", - "tw-animate-css": "^1.3.5", + "tw-animate-css": "^1.3.7", "typescript": "~5.8.3", "typescript-eslint": "^8.35.1", "vite": "^7.0.4" @@ -3525,6 +3525,60 @@ "node": ">=14.0.0" } }, + "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/core": { + "version": "1.4.3", + "inBundle": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/wasi-threads": "1.0.2", + "tslib": "^2.4.0" + } + }, + "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/runtime": { + "version": "1.4.3", + "inBundle": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/wasi-threads": { + "version": "1.0.2", + "inBundle": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@napi-rs/wasm-runtime": { + "version": "0.2.11", + "inBundle": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "^1.4.3", + "@emnapi/runtime": "^1.4.3", + "@tybys/wasm-util": "^0.9.0" + } + }, + "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@tybys/wasm-util": { + "version": "0.9.0", + "inBundle": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/tslib": { + "version": "2.8.0", + "inBundle": true, + "license": "0BSD", + "optional": true + }, "node_modules/@tailwindcss/oxide-win32-arm64-msvc": { "version": "4.1.11", "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.11.tgz", @@ -8198,9 +8252,9 @@ } }, "node_modules/tw-animate-css": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/tw-animate-css/-/tw-animate-css-1.3.5.tgz", - "integrity": "sha512-t3u+0YNoloIhj1mMXs779P6MO9q3p3mvGn4k1n3nJPqJw/glZcuijG2qTSN4z4mgNRfW5ZC3aXJFLwDtiipZXA==", + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/tw-animate-css/-/tw-animate-css-1.3.7.tgz", + "integrity": "sha512-lvLb3hTIpB5oGsk8JmLoAjeCHV58nKa2zHYn8yWOoG5JJusH3bhJlF2DLAZ/5NmJ+jyH3ssiAx/2KmbhavJy/A==", "dev": true, "license": "MIT", "funding": { diff --git a/package.json b/package.json index e53653c2..d602d11b 100644 --- a/package.json +++ b/package.json @@ -93,7 +93,7 @@ "eslint-plugin-react-refresh": "^0.4.20", "globals": "^16.3.0", "ts-node": "^10.9.2", - "tw-animate-css": "^1.3.5", + "tw-animate-css": "^1.3.7", "typescript": "~5.8.3", "typescript-eslint": "^8.35.1", "vite": "^7.0.4" From c7fba8dbb18044b91afb8c2dd77d51430cecf456 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 24 Aug 2025 21:14:46 +0000 Subject: [PATCH 11/12] Bump the prod-minor-updates group with 10 updates Bumps the prod-minor-updates group with 10 updates: | Package | From | To | | --- | --- | --- | | [@hookform/resolvers](https://github.com/react-hook-form/resolvers) | `5.1.1` | `5.2.1` | | [@uiw/codemirror-extensions-hyper-link](https://github.com/uiwjs/react-codemirror) | `4.24.1` | `4.25.1` | | [@uiw/codemirror-extensions-langs](https://github.com/uiwjs/react-codemirror) | `4.24.1` | `4.25.1` | | [@uiw/codemirror-themes](https://github.com/uiwjs/react-codemirror) | `4.24.1` | `4.25.1` | | [@uiw/react-codemirror](https://github.com/uiwjs/react-codemirror) | `4.24.1` | `4.25.1` | | [axios](https://github.com/axios/axios) | `1.10.0` | `1.11.0` | | [lucide-react](https://github.com/lucide-icons/lucide/tree/HEAD/packages/lucide-react) | `0.525.0` | `0.541.0` | | [react-hook-form](https://github.com/react-hook-form/react-hook-form) | `7.60.0` | `7.62.0` | | [ssh2](https://github.com/mscdex/ssh2) | `1.16.0` | `1.17.0` | | [zod](https://github.com/colinhacks/zod) | `4.0.5` | `4.1.1` | Updates `@hookform/resolvers` from 5.1.1 to 5.2.1 - [Release notes](https://github.com/react-hook-form/resolvers/releases) - [Commits](https://github.com/react-hook-form/resolvers/compare/v5.1.1...v5.2.1) Updates `@uiw/codemirror-extensions-hyper-link` from 4.24.1 to 4.25.1 - [Release notes](https://github.com/uiwjs/react-codemirror/releases) - [Commits](https://github.com/uiwjs/react-codemirror/compare/v4.24.1...v4.25.1) Updates `@uiw/codemirror-extensions-langs` from 4.24.1 to 4.25.1 - [Release notes](https://github.com/uiwjs/react-codemirror/releases) - [Commits](https://github.com/uiwjs/react-codemirror/compare/v4.24.1...v4.25.1) Updates `@uiw/codemirror-themes` from 4.24.1 to 4.25.1 - [Release notes](https://github.com/uiwjs/react-codemirror/releases) - [Commits](https://github.com/uiwjs/react-codemirror/compare/v4.24.1...v4.25.1) Updates `@uiw/react-codemirror` from 4.24.1 to 4.25.1 - [Release notes](https://github.com/uiwjs/react-codemirror/releases) - [Commits](https://github.com/uiwjs/react-codemirror/compare/v4.24.1...v4.25.1) Updates `axios` from 1.10.0 to 1.11.0 - [Release notes](https://github.com/axios/axios/releases) - [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md) - [Commits](https://github.com/axios/axios/compare/v1.10.0...v1.11.0) Updates `lucide-react` from 0.525.0 to 0.541.0 - [Release notes](https://github.com/lucide-icons/lucide/releases) - [Commits](https://github.com/lucide-icons/lucide/commits/0.541.0/packages/lucide-react) Updates `react-hook-form` from 7.60.0 to 7.62.0 - [Release notes](https://github.com/react-hook-form/react-hook-form/releases) - [Changelog](https://github.com/react-hook-form/react-hook-form/blob/master/CHANGELOG.md) - [Commits](https://github.com/react-hook-form/react-hook-form/compare/v7.60.0...v7.62.0) Updates `ssh2` from 1.16.0 to 1.17.0 - [Commits](https://github.com/mscdex/ssh2/compare/v1.16.0...v1.17.0) Updates `zod` from 4.0.5 to 4.1.1 - [Release notes](https://github.com/colinhacks/zod/releases) - [Commits](https://github.com/colinhacks/zod/compare/v4.0.5...v4.1.1) --- updated-dependencies: - dependency-name: "@hookform/resolvers" dependency-version: 5.2.1 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: prod-minor-updates - dependency-name: "@uiw/codemirror-extensions-hyper-link" dependency-version: 4.25.1 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: prod-minor-updates - dependency-name: "@uiw/codemirror-extensions-langs" dependency-version: 4.25.1 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: prod-minor-updates - dependency-name: "@uiw/codemirror-themes" dependency-version: 4.25.1 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: prod-minor-updates - dependency-name: "@uiw/react-codemirror" dependency-version: 4.25.1 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: prod-minor-updates - dependency-name: axios dependency-version: 1.11.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: prod-minor-updates - dependency-name: lucide-react dependency-version: 0.541.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: prod-minor-updates - dependency-name: react-hook-form dependency-version: 7.62.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: prod-minor-updates - dependency-name: ssh2 dependency-version: 1.17.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: prod-minor-updates - dependency-name: zod dependency-version: 4.1.1 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: prod-minor-updates ... Signed-off-by: dependabot[bot] --- package-lock.json | 235 +++++++++++++++++++++------------------------- package.json | 20 ++-- 2 files changed, 116 insertions(+), 139 deletions(-) diff --git a/package-lock.json b/package-lock.json index dc2db2ae..ce31b6ba 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,7 +8,7 @@ "name": "termix", "version": "0.0.0", "dependencies": { - "@hookform/resolvers": "^5.1.1", + "@hookform/resolvers": "^5.2.1", "@radix-ui/react-accordion": "^1.2.11", "@radix-ui/react-avatar": "^1.1.10", "@radix-ui/react-checkbox": "^1.3.2", @@ -29,10 +29,10 @@ "@tailwindcss/vite": "^4.1.11", "@types/bcryptjs": "^2.4.6", "@types/multer": "^2.0.0", - "@uiw/codemirror-extensions-hyper-link": "^4.24.1", - "@uiw/codemirror-extensions-langs": "^4.24.1", - "@uiw/codemirror-themes": "^4.24.1", - "@uiw/react-codemirror": "^4.24.1", + "@uiw/codemirror-extensions-hyper-link": "^4.25.1", + "@uiw/codemirror-extensions-langs": "^4.25.1", + "@uiw/codemirror-themes": "^4.25.1", + "@uiw/react-codemirror": "^4.25.1", "@xterm/addon-attach": "^0.11.0", "@xterm/addon-clipboard": "^0.1.0", "@xterm/addon-fit": "^0.10.0", @@ -40,7 +40,7 @@ "@xterm/addon-unicode11": "^0.8.0", "@xterm/addon-web-links": "^0.11.0", "@xterm/xterm": "^5.5.0", - "axios": "^1.10.0", + "axios": "^1.11.0", "bcryptjs": "^3.0.2", "better-sqlite3": "^12.2.0", "chalk": "^4.1.2", @@ -53,23 +53,23 @@ "express": "^5.1.0", "jose": "^5.2.3", "jsonwebtoken": "^9.0.2", - "lucide-react": "^0.525.0", + "lucide-react": "^0.541.0", "multer": "^2.0.2", "nanoid": "^5.1.5", "next-themes": "^0.4.6", "node-fetch": "^3.3.2", "react": "^19.1.0", "react-dom": "^19.1.0", - "react-hook-form": "^7.60.0", + "react-hook-form": "^7.62.0", "react-resizable-panels": "^3.0.3", "react-xtermjs": "^1.0.10", "sonner": "^2.0.7", - "ssh2": "^1.16.0", + "ssh2": "^1.17.0", "tailwind-merge": "^3.3.1", "tailwindcss": "^4.1.11", "validator": "^13.15.15", "ws": "^8.18.3", - "zod": "^4.0.5" + "zod": "^4.1.1" }, "devDependencies": { "@eslint/js": "^9.30.1", @@ -256,18 +256,6 @@ "@lezer/lr": "^1.0.0" } }, - "node_modules/@codemirror/lang-lezer": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/@codemirror/lang-lezer/-/lang-lezer-6.0.2.tgz", - "integrity": "sha512-mcVAf8lw+sCfSlr2ivMqV8JtNmOQjSXdA1vHKRtoW0OZsz1k6qhF+DX0K2TbWlAThqiGgRkRSZyYzIoEtKB2uQ==", - "license": "MIT", - "dependencies": { - "@codemirror/language": "^6.0.0", - "@codemirror/state": "^6.0.0", - "@lezer/common": "^1.0.0", - "@lezer/lezer": "^1.0.0" - } - }, "node_modules/@codemirror/lang-liquid": { "version": "6.2.3", "resolved": "https://registry.npmjs.org/@codemirror/lang-liquid/-/lang-liquid-6.2.3.tgz", @@ -1158,9 +1146,9 @@ "license": "MIT" }, "node_modules/@hookform/resolvers": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/@hookform/resolvers/-/resolvers-5.1.1.tgz", - "integrity": "sha512-J/NVING3LMAEvexJkyTLjruSm7aOFx7QX21pzkiJfMoNG0wl5aFEjLTl7ay7IQb9EWY6AkrBy7tHL2Alijpdcg==", + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/@hookform/resolvers/-/resolvers-5.2.1.tgz", + "integrity": "sha512-u0+6X58gkjMcxur1wRWokA7XsiiBJ6aK17aPZxhkoYiK5J+HcTx0Vhu9ovXe6H+dVpO6cjrn2FkJTryXEMlryQ==", "license": "MIT", "dependencies": { "@standard-schema/utils": "^0.3.0" @@ -1374,16 +1362,6 @@ "@lezer/lr": "^1.0.0" } }, - "node_modules/@lezer/lezer": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@lezer/lezer/-/lezer-1.1.2.tgz", - "integrity": "sha512-O8yw3CxPhzYHB1hvwbdozjnAslhhR8A5BH7vfEMof0xk3p+/DFDfZkA9Tde6J+88WgtwaHy4Sy6ThZSkaI0Evw==", - "license": "MIT", - "dependencies": { - "@lezer/highlight": "^1.0.0", - "@lezer/lr": "^1.0.0" - } - }, "node_modules/@lezer/lr": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-1.4.2.tgz", @@ -1475,25 +1453,6 @@ "integrity": "sha512-l0h88YhZFyKdXIFNfSWpyjStDjGHwZ/U7iobcK1cQQD8sejsONdQtTVU+1wVN1PBw40PiiHB1vA5S7VTfQiP9g==", "license": "MIT" }, - "node_modules/@nextjournal/lang-clojure": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@nextjournal/lang-clojure/-/lang-clojure-1.0.0.tgz", - "integrity": "sha512-gOCV71XrYD0DhwGoPMWZmZ0r92/lIHsqQu9QWdpZYYBwiChNwMO4sbVMP7eTuAqffFB2BTtCSC+1skSH9d3bNg==", - "license": "ISC", - "dependencies": { - "@codemirror/language": "^6.0.0", - "@nextjournal/lezer-clojure": "1.0.0" - } - }, - "node_modules/@nextjournal/lezer-clojure": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@nextjournal/lezer-clojure/-/lezer-clojure-1.0.0.tgz", - "integrity": "sha512-VZyuGu4zw5mkTOwQBTaGVNWmsOZAPw5ZRxu1/Knk/Xfs7EDBIogwIs5UXTYkuECX5ZQB8eOB+wKA2pc7VyqaZQ==", - "license": "ISC", - "dependencies": { - "@lezer/lr": "^1.0.0" - } - }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -2749,21 +2708,6 @@ "integrity": "sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw==", "license": "MIT" }, - "node_modules/@replit/codemirror-lang-csharp": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/@replit/codemirror-lang-csharp/-/codemirror-lang-csharp-6.2.0.tgz", - "integrity": "sha512-6utbaWkoymhoAXj051mkRp+VIJlpwUgCX9Toevz3YatiZsz512fw3OVCedXQx+WcR0wb6zVHjChnuxqfCLtFVQ==", - "license": "MIT", - "peerDependencies": { - "@codemirror/autocomplete": "^6.0.0", - "@codemirror/language": "^6.0.0", - "@codemirror/state": "^6.0.0", - "@codemirror/view": "^6.0.0", - "@lezer/common": "^1.0.0", - "@lezer/highlight": "^1.0.0", - "@lezer/lr": "^1.0.0" - } - }, "node_modules/@replit/codemirror-lang-nix": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/@replit/codemirror-lang-nix/-/codemirror-lang-nix-6.0.1.tgz", @@ -3525,6 +3469,60 @@ "node": ">=14.0.0" } }, + "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/core": { + "version": "1.4.3", + "inBundle": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/wasi-threads": "1.0.2", + "tslib": "^2.4.0" + } + }, + "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/runtime": { + "version": "1.4.3", + "inBundle": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/wasi-threads": { + "version": "1.0.2", + "inBundle": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@napi-rs/wasm-runtime": { + "version": "0.2.11", + "inBundle": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "^1.4.3", + "@emnapi/runtime": "^1.4.3", + "@tybys/wasm-util": "^0.9.0" + } + }, + "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@tybys/wasm-util": { + "version": "0.9.0", + "inBundle": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/tslib": { + "version": "2.8.0", + "inBundle": true, + "license": "0BSD", + "optional": true + }, "node_modules/@tailwindcss/oxide-win32-arm64-msvc": { "version": "4.1.11", "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.11.tgz", @@ -4077,9 +4075,9 @@ } }, "node_modules/@uiw/codemirror-extensions-basic-setup": { - "version": "4.24.1", - "resolved": "https://registry.npmjs.org/@uiw/codemirror-extensions-basic-setup/-/codemirror-extensions-basic-setup-4.24.1.tgz", - "integrity": "sha512-o1m1a8eUS3fWERMbDFvN8t8sZUFPgDKNemmlQ5Ot2vKm+Ax84lKP1dhEFgkiOaZ1bDHk4T5h6SjHuTghrJHKww==", + "version": "4.25.1", + "resolved": "https://registry.npmjs.org/@uiw/codemirror-extensions-basic-setup/-/codemirror-extensions-basic-setup-4.25.1.tgz", + "integrity": "sha512-zxgA2QkvP3ZDKxTBc9UltNFTrSeFezGXcZtZj6qcsBxiMzowoEMP5mVwXcKjpzldpZVRuY+JCC+RsekEgid4vg==", "license": "MIT", "dependencies": { "@codemirror/autocomplete": "^6.0.0", @@ -4104,9 +4102,9 @@ } }, "node_modules/@uiw/codemirror-extensions-hyper-link": { - "version": "4.24.1", - "resolved": "https://registry.npmjs.org/@uiw/codemirror-extensions-hyper-link/-/codemirror-extensions-hyper-link-4.24.1.tgz", - "integrity": "sha512-qf3docpmsHHM0OKLO5m2Fc8t4G+pr1+k9QwrhlM2iolku/INbz+B1JzbRcSU0ow1EcxKtHRtCFE4Lnu6DwP7CQ==", + "version": "4.25.1", + "resolved": "https://registry.npmjs.org/@uiw/codemirror-extensions-hyper-link/-/codemirror-extensions-hyper-link-4.25.1.tgz", + "integrity": "sha512-BVp+bnPI0LtqYXAPFWBqpLLLICoD8QsTAC/KQVRf7l+MO8FXCP0F/4WoM724eU4/2bcLefBkK1gBgCB1+Ug1CQ==", "license": "MIT", "funding": { "url": "https://jaywcjlove.github.io/#/sponsor" @@ -4117,34 +4115,13 @@ } }, "node_modules/@uiw/codemirror-extensions-langs": { - "version": "4.24.1", - "resolved": "https://registry.npmjs.org/@uiw/codemirror-extensions-langs/-/codemirror-extensions-langs-4.24.1.tgz", - "integrity": "sha512-8Q33k/UhNni2u5VvAHD+2mxe4hNIqZTNySSUcnJ7urV2lXXau+0fimsQlI+GQLF7gy5F1BUzIi+yvOMrEPK9Ig==", + "version": "4.25.1", + "resolved": "https://registry.npmjs.org/@uiw/codemirror-extensions-langs/-/codemirror-extensions-langs-4.25.1.tgz", + "integrity": "sha512-P9Sxk0w8WgxxoOK4hC2yNV2f3shE0CH8gmk8lG5rDrAYYyuUrTsTmJANXh30TuQWCPCkEXwXZZVy+dbTYAgvMQ==", "license": "MIT", "dependencies": { - "@codemirror/lang-angular": "^0.1.0", - "@codemirror/lang-cpp": "^6.0.0", - "@codemirror/lang-css": "^6.2.0", - "@codemirror/lang-html": "^6.4.0", - "@codemirror/lang-java": "^6.0.0", - "@codemirror/lang-javascript": "^6.1.0", - "@codemirror/lang-json": "^6.0.0", - "@codemirror/lang-less": "^6.0.1", - "@codemirror/lang-lezer": "^6.0.0", - "@codemirror/lang-liquid": "^6.0.1", - "@codemirror/lang-markdown": "^6.1.0", - "@codemirror/lang-php": "^6.0.0", - "@codemirror/lang-python": "^6.1.0", - "@codemirror/lang-rust": "^6.0.0", - "@codemirror/lang-sass": "^6.0.1", - "@codemirror/lang-sql": "^6.4.0", - "@codemirror/lang-vue": "^0.1.1", - "@codemirror/lang-wast": "^6.0.0", - "@codemirror/lang-xml": "^6.0.0", - "@codemirror/language-data": ">=6.0.0", - "@codemirror/legacy-modes": ">=6.0.0", - "@nextjournal/lang-clojure": "^1.0.0", - "@replit/codemirror-lang-csharp": "^6.1.0", + "@codemirror/language": "^6.0.0", + "@codemirror/language-data": "^6.5.1", "@replit/codemirror-lang-nix": "^6.0.1", "@replit/codemirror-lang-solidity": "^6.0.1", "@replit/codemirror-lang-svelte": "^6.0.0", @@ -4154,14 +4131,14 @@ "url": "https://jaywcjlove.github.io/#/sponsor" }, "peerDependencies": { - "@codemirror/language-data": ">=6.0.0", - "@codemirror/legacy-modes": ">=6.0.0" + "@codemirror/language": ">=6.0.0", + "@codemirror/language-data": ">=6.0.0" } }, "node_modules/@uiw/codemirror-themes": { - "version": "4.24.1", - "resolved": "https://registry.npmjs.org/@uiw/codemirror-themes/-/codemirror-themes-4.24.1.tgz", - "integrity": "sha512-hduBbFNiWNW6nYa2/giKQ9YpzhWNw87BGpCjC+cXYMZ7bCD6q5DC6Hw+7z7ZwSzEaOQvV91lmirOjJ8hn9+pkg==", + "version": "4.25.1", + "resolved": "https://registry.npmjs.org/@uiw/codemirror-themes/-/codemirror-themes-4.25.1.tgz", + "integrity": "sha512-6o8tQ8bdq14RuVFpZ7l9u8KnuPq824uG3U1VV933Uhv8mfaxaoaOQSjv6T2bQUPhjH6ZlEu5+tAMkOfIL21eIQ==", "license": "MIT", "dependencies": { "@codemirror/language": "^6.0.0", @@ -4178,16 +4155,16 @@ } }, "node_modules/@uiw/react-codemirror": { - "version": "4.24.1", - "resolved": "https://registry.npmjs.org/@uiw/react-codemirror/-/react-codemirror-4.24.1.tgz", - "integrity": "sha512-BivF4NLqbuBQK5gPVhSkOARi9nPXw8X5r25EnInPeY+I9l1dfEX8O9V6+0xHTlGHyUo0cNfGEF9t1KHEicUfJw==", + "version": "4.25.1", + "resolved": "https://registry.npmjs.org/@uiw/react-codemirror/-/react-codemirror-4.25.1.tgz", + "integrity": "sha512-eESBKHndoYkaEGlKCwRO4KrnTw1HkWBxVpEeqntoWTpoFEUYxdLWUYmkPBVk4/u8YzVy9g91nFfIRpqe5LjApg==", "license": "MIT", "dependencies": { "@babel/runtime": "^7.18.6", "@codemirror/commands": "^6.1.0", "@codemirror/state": "^6.1.1", "@codemirror/theme-one-dark": "^6.0.0", - "@uiw/codemirror-extensions-basic-setup": "4.24.1", + "@uiw/codemirror-extensions-basic-setup": "4.25.1", "codemirror": "^6.0.0" }, "funding": { @@ -4199,8 +4176,8 @@ "@codemirror/theme-one-dark": ">=6.0.0", "@codemirror/view": ">=6.0.0", "codemirror": ">=6.0.0", - "react": ">=16.8.0", - "react-dom": ">=16.8.0" + "react": ">=17.0.0", + "react-dom": ">=17.0.0" } }, "node_modules/@vitejs/plugin-react-swc": { @@ -4447,13 +4424,13 @@ } }, "node_modules/axios": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.10.0.tgz", - "integrity": "sha512-/1xYAC4MP/HEG+3duIhFr4ZQXR4sQXOIe+o6sdqzeykGLx6Upp/1p8MHqhINOvGeP7xyNHe7tsiJByc4SSVUxw==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.11.0.tgz", + "integrity": "sha512-1Lx3WLFQWm3ooKDYZD1eXmoGO9fxYQjrycfHFC8P0sCfQVXyROp0p9PFWBehewBOdCwHc+f/b8I0fMto5eSfwA==", "license": "MIT", "dependencies": { "follow-redirects": "^1.15.6", - "form-data": "^4.0.0", + "form-data": "^4.0.4", "proxy-from-env": "^1.1.0" } }, @@ -6671,9 +6648,9 @@ "license": "MIT" }, "node_modules/lucide-react": { - "version": "0.525.0", - "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.525.0.tgz", - "integrity": "sha512-Tm1txJ2OkymCGkvwoHt33Y2JpN5xucVq1slHcgE6Lk0WjDfjgKWor5CdVER8U6DvcfMwh4M8XxmpTiyzfmfDYQ==", + "version": "0.541.0", + "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.541.0.tgz", + "integrity": "sha512-s0Vircsu5WaGv2KoJZ5+SoxiAJ3UXV5KqEM3eIFDHaHkcLIFdIWgXtZ412+Gh02UsdS7Was+jvEpBvPCWQISlg==", "license": "ISC", "peerDependencies": { "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" @@ -7445,9 +7422,9 @@ } }, "node_modules/react-hook-form": { - "version": "7.60.0", - "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.60.0.tgz", - "integrity": "sha512-SBrYOvMbDB7cV8ZfNpaiLcgjH/a1c7aK0lK+aNigpf4xWLO8q+o4tcvVurv3c4EOyzn/3dCsYt4GKD42VvJ/+A==", + "version": "7.62.0", + "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.62.0.tgz", + "integrity": "sha512-7KWFejc98xqG/F4bAxpL41NB3o1nnvQO1RWZT3TqRZYL8RryQETGfEdVnJN2fy1crCiBLLjkRBVK05j24FxJGA==", "license": "MIT", "engines": { "node": ">=18.0.0" @@ -7909,9 +7886,9 @@ } }, "node_modules/ssh2": { - "version": "1.16.0", - "resolved": "https://registry.npmjs.org/ssh2/-/ssh2-1.16.0.tgz", - "integrity": "sha512-r1X4KsBGedJqo7h8F5c4Ybpcr5RjyP+aWIG007uBPRjmdQWfEiVLzSK71Zji1B9sKxwaCvD8y8cwSkYrlLiRRg==", + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/ssh2/-/ssh2-1.17.0.tgz", + "integrity": "sha512-wPldCk3asibAjQ/kziWQQt1Wh3PgDFpC0XpwclzKcdT1vql6KeYxf5LIt4nlFkUeR8WuphYMKqUA56X4rjbfgQ==", "hasInstallScript": true, "dependencies": { "asn1": "^0.2.6", @@ -7922,7 +7899,7 @@ }, "optionalDependencies": { "cpu-features": "~0.0.10", - "nan": "^2.20.0" + "nan": "^2.23.0" } }, "node_modules/statuses": { @@ -8633,9 +8610,9 @@ } }, "node_modules/zod": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/zod/-/zod-4.0.5.tgz", - "integrity": "sha512-/5UuuRPStvHXu7RS+gmvRf4NXrNxpSllGwDnCBcJZtQsKrviYXm54yDGV2KYNLT5kq0lHGcl7lqWJLgSaG+tgA==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.1.1.tgz", + "integrity": "sha512-SgMZK/h8Tigt9nnKkfJMvB/mKjiJXaX26xegP4sa+0wHIFVFWVlsQGdhklDmuargBD3Hsi3rsQRIzwJIhTPJHA==", "license": "MIT", "funding": { "url": "https://github.com/sponsors/colinhacks" diff --git a/package.json b/package.json index e53653c2..352a3e49 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ "preview": "vite preview" }, "dependencies": { - "@hookform/resolvers": "^5.1.1", + "@hookform/resolvers": "^5.2.1", "@radix-ui/react-accordion": "^1.2.11", "@radix-ui/react-avatar": "^1.1.10", "@radix-ui/react-checkbox": "^1.3.2", @@ -33,10 +33,10 @@ "@tailwindcss/vite": "^4.1.11", "@types/bcryptjs": "^2.4.6", "@types/multer": "^2.0.0", - "@uiw/codemirror-extensions-hyper-link": "^4.24.1", - "@uiw/codemirror-extensions-langs": "^4.24.1", - "@uiw/codemirror-themes": "^4.24.1", - "@uiw/react-codemirror": "^4.24.1", + "@uiw/codemirror-extensions-hyper-link": "^4.25.1", + "@uiw/codemirror-extensions-langs": "^4.25.1", + "@uiw/codemirror-themes": "^4.25.1", + "@uiw/react-codemirror": "^4.25.1", "@xterm/addon-attach": "^0.11.0", "@xterm/addon-clipboard": "^0.1.0", "@xterm/addon-fit": "^0.10.0", @@ -44,7 +44,7 @@ "@xterm/addon-unicode11": "^0.8.0", "@xterm/addon-web-links": "^0.11.0", "@xterm/xterm": "^5.5.0", - "axios": "^1.10.0", + "axios": "^1.11.0", "bcryptjs": "^3.0.2", "better-sqlite3": "^12.2.0", "chalk": "^4.1.2", @@ -57,23 +57,23 @@ "express": "^5.1.0", "jose": "^5.2.3", "jsonwebtoken": "^9.0.2", - "lucide-react": "^0.525.0", + "lucide-react": "^0.541.0", "multer": "^2.0.2", "nanoid": "^5.1.5", "next-themes": "^0.4.6", "node-fetch": "^3.3.2", "react": "^19.1.0", "react-dom": "^19.1.0", - "react-hook-form": "^7.60.0", + "react-hook-form": "^7.62.0", "react-resizable-panels": "^3.0.3", "react-xtermjs": "^1.0.10", "sonner": "^2.0.7", - "ssh2": "^1.16.0", + "ssh2": "^1.17.0", "tailwind-merge": "^3.3.1", "tailwindcss": "^4.1.11", "validator": "^13.15.15", "ws": "^8.18.3", - "zod": "^4.0.5" + "zod": "^4.1.1" }, "devDependencies": { "@eslint/js": "^9.30.1", From 6e175e2b3615a033830445558f3d32ab2faafb90 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 24 Aug 2025 21:14:55 +0000 Subject: [PATCH 12/12] Bump @vitejs/plugin-react-swc from 3.10.2 to 4.0.1 Bumps [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react/tree/HEAD/packages/plugin-react-swc) from 3.10.2 to 4.0.1. - [Release notes](https://github.com/vitejs/vite-plugin-react/releases) - [Changelog](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react-swc/CHANGELOG.md) - [Commits](https://github.com/vitejs/vite-plugin-react/commits/plugin-react@4.0.1/packages/plugin-react-swc) --- updated-dependencies: - dependency-name: "@vitejs/plugin-react-swc" dependency-version: 4.0.1 dependency-type: direct:development update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- package-lock.json | 171 ++++++++++++++++++++++++++++++---------------- package.json | 2 +- 2 files changed, 115 insertions(+), 58 deletions(-) diff --git a/package-lock.json b/package-lock.json index dc2db2ae..5ea143ff 100644 --- a/package-lock.json +++ b/package-lock.json @@ -82,7 +82,7 @@ "@types/react-dom": "^19.1.6", "@types/ssh2": "^1.15.5", "@types/ws": "^8.18.1", - "@vitejs/plugin-react-swc": "^3.10.2", + "@vitejs/plugin-react-swc": "^4.0.1", "autoprefixer": "^10.4.21", "eslint": "^9.30.1", "eslint-plugin-react-hooks": "^5.2.0", @@ -2811,9 +2811,9 @@ } }, "node_modules/@rolldown/pluginutils": { - "version": "1.0.0-beta.11", - "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.11.tgz", - "integrity": "sha512-L/gAA/hyCSuzTF1ftlzUSI/IKr2POHsv1Dd78GfqkR83KMNuswWD61JxGV2L7nRwBBBSDr6R1gCkdTmoN7W4ag==", + "version": "1.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.32.tgz", + "integrity": "sha512-QReCdvxiUZAPkvp1xpAg62IeNzykOFA6syH2CnClif4YmALN1XKpB39XneL80008UbtMShthSVDKmrx05N1q/g==", "dev": true, "license": "MIT" }, @@ -3084,15 +3084,15 @@ "license": "MIT" }, "node_modules/@swc/core": { - "version": "1.12.14", - "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.12.14.tgz", - "integrity": "sha512-CJSn2vstd17ddWIHBsjuD4OQnn9krQfaq6EO+w9YfId5DKznyPmzxAARlOXG99cC8/3Kli8ysKy6phL43bSr0w==", + "version": "1.13.5", + "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.13.5.tgz", + "integrity": "sha512-WezcBo8a0Dg2rnR82zhwoR6aRNxeTGfK5QCD6TQ+kg3xx/zNT02s/0o+81h/3zhvFSB24NtqEr8FTw88O5W/JQ==", "dev": true, "hasInstallScript": true, "license": "Apache-2.0", "dependencies": { "@swc/counter": "^0.1.3", - "@swc/types": "^0.1.23" + "@swc/types": "^0.1.24" }, "engines": { "node": ">=10" @@ -3102,16 +3102,16 @@ "url": "https://opencollective.com/swc" }, "optionalDependencies": { - "@swc/core-darwin-arm64": "1.12.14", - "@swc/core-darwin-x64": "1.12.14", - "@swc/core-linux-arm-gnueabihf": "1.12.14", - "@swc/core-linux-arm64-gnu": "1.12.14", - "@swc/core-linux-arm64-musl": "1.12.14", - "@swc/core-linux-x64-gnu": "1.12.14", - "@swc/core-linux-x64-musl": "1.12.14", - "@swc/core-win32-arm64-msvc": "1.12.14", - "@swc/core-win32-ia32-msvc": "1.12.14", - "@swc/core-win32-x64-msvc": "1.12.14" + "@swc/core-darwin-arm64": "1.13.5", + "@swc/core-darwin-x64": "1.13.5", + "@swc/core-linux-arm-gnueabihf": "1.13.5", + "@swc/core-linux-arm64-gnu": "1.13.5", + "@swc/core-linux-arm64-musl": "1.13.5", + "@swc/core-linux-x64-gnu": "1.13.5", + "@swc/core-linux-x64-musl": "1.13.5", + "@swc/core-win32-arm64-msvc": "1.13.5", + "@swc/core-win32-ia32-msvc": "1.13.5", + "@swc/core-win32-x64-msvc": "1.13.5" }, "peerDependencies": { "@swc/helpers": ">=0.5.17" @@ -3123,9 +3123,9 @@ } }, "node_modules/@swc/core-darwin-arm64": { - "version": "1.12.14", - "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.12.14.tgz", - "integrity": "sha512-HNukQoOKgMsHSETj8vgGGKK3SEcH7Cz6k4bpntCxBKNkO3sH7RcBTDulWGGHJfZaDNix7Rw2ExUVWtLZlzkzXg==", + "version": "1.13.5", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.13.5.tgz", + "integrity": "sha512-lKNv7SujeXvKn16gvQqUQI5DdyY8v7xcoO3k06/FJbHJS90zEwZdQiMNRiqpYw/orU543tPaWgz7cIYWhbopiQ==", "cpu": [ "arm64" ], @@ -3140,9 +3140,9 @@ } }, "node_modules/@swc/core-darwin-x64": { - "version": "1.12.14", - "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.12.14.tgz", - "integrity": "sha512-4Ttf3Obtk3MvFrR0e04qr6HfXh4L1Z+K3dRej63TAFuYpo+cPXeOZdPUddAW73lSUGkj+61IHnGPoXD3OQYy4Q==", + "version": "1.13.5", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.13.5.tgz", + "integrity": "sha512-ILd38Fg/w23vHb0yVjlWvQBoE37ZJTdlLHa8LRCFDdX4WKfnVBiblsCU9ar4QTMNdeTBEX9iUF4IrbNWhaF1Ng==", "cpu": [ "x64" ], @@ -3157,9 +3157,9 @@ } }, "node_modules/@swc/core-linux-arm-gnueabihf": { - "version": "1.12.14", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.12.14.tgz", - "integrity": "sha512-zhJOH2KWjtQpzJ27Xjw/RKLVOa1aiEJC2b70xbCwEX6ZTVAl8tKbhkZ3GMphhfVmLJ9gf/2UQR58oxVnsXqX5Q==", + "version": "1.13.5", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.13.5.tgz", + "integrity": "sha512-Q6eS3Pt8GLkXxqz9TAw+AUk9HpVJt8Uzm54MvPsqp2yuGmY0/sNaPPNVqctCX9fu/Nu8eaWUen0si6iEiCsazQ==", "cpu": [ "arm" ], @@ -3174,9 +3174,9 @@ } }, "node_modules/@swc/core-linux-arm64-gnu": { - "version": "1.12.14", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.12.14.tgz", - "integrity": "sha512-akUAe1YrBqZf1EDdUxahQ8QZnJi8Ts6Ya0jf6GBIMvnXL4Y6QIuvKTRwfNxy7rJ+x9zpzP1Vlh14ZZkSKZ1EGA==", + "version": "1.13.5", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.13.5.tgz", + "integrity": "sha512-aNDfeN+9af+y+M2MYfxCzCy/VDq7Z5YIbMqRI739o8Ganz6ST+27kjQFd8Y/57JN/hcnUEa9xqdS3XY7WaVtSw==", "cpu": [ "arm64" ], @@ -3191,9 +3191,9 @@ } }, "node_modules/@swc/core-linux-arm64-musl": { - "version": "1.12.14", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.12.14.tgz", - "integrity": "sha512-ZkOOIpSMXuPAjfOXEIAEQcrPOgLi6CaXvA5W+GYnpIpFG21Nd0qb0WbwFRv4K8BRtl993Q21v0gPpOaFHU+wdA==", + "version": "1.13.5", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.13.5.tgz", + "integrity": "sha512-9+ZxFN5GJag4CnYnq6apKTnnezpfJhCumyz0504/JbHLo+Ue+ZtJnf3RhyA9W9TINtLE0bC4hKpWi8ZKoETyOQ==", "cpu": [ "arm64" ], @@ -3208,9 +3208,9 @@ } }, "node_modules/@swc/core-linux-x64-gnu": { - "version": "1.12.14", - "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.12.14.tgz", - "integrity": "sha512-71EPPccwJiJUxd2aMwNlTfom2mqWEWYGdbeTju01tzSHsEuD7E6ePlgC3P3ngBqB3urj41qKs87z7zPOswT5Iw==", + "version": "1.13.5", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.13.5.tgz", + "integrity": "sha512-WD530qvHrki8Ywt/PloKUjaRKgstQqNGvmZl54g06kA+hqtSE2FTG9gngXr3UJxYu/cNAjJYiBifm7+w4nbHbA==", "cpu": [ "x64" ], @@ -3225,9 +3225,9 @@ } }, "node_modules/@swc/core-linux-x64-musl": { - "version": "1.12.14", - "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.12.14.tgz", - "integrity": "sha512-nImF1hZJqKTcl0WWjHqlelOhvuB9rU9kHIw/CmISBUZXogjLIvGyop1TtJNz0ULcz2Oxr3Q2YpwfrzsgvgbGkA==", + "version": "1.13.5", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.13.5.tgz", + "integrity": "sha512-Luj8y4OFYx4DHNQTWjdIuKTq2f5k6uSXICqx+FSabnXptaOBAbJHNbHT/06JZh6NRUouaf0mYXN0mcsqvkhd7Q==", "cpu": [ "x64" ], @@ -3242,9 +3242,9 @@ } }, "node_modules/@swc/core-win32-arm64-msvc": { - "version": "1.12.14", - "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.12.14.tgz", - "integrity": "sha512-sABFQFxSuStFoxvEWZUHWYldtB1B4A9eDNFd4Ty50q7cemxp7uoscFoaCqfXSGNBwwBwpS5EiPB6YN4y6hqmLQ==", + "version": "1.13.5", + "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.13.5.tgz", + "integrity": "sha512-cZ6UpumhF9SDJvv4DA2fo9WIzlNFuKSkZpZmPG1c+4PFSEMy5DFOjBSllCvnqihCabzXzpn6ykCwBmHpy31vQw==", "cpu": [ "arm64" ], @@ -3259,9 +3259,9 @@ } }, "node_modules/@swc/core-win32-ia32-msvc": { - "version": "1.12.14", - "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.12.14.tgz", - "integrity": "sha512-KBznRB02NASkpepRdWIK4f1AvmaJCDipKWdW1M1xV9QL2tE4aySJFojVuG1+t0tVDkjRfwcZjycQfRoJ4RjD7Q==", + "version": "1.13.5", + "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.13.5.tgz", + "integrity": "sha512-C5Yi/xIikrFUzZcyGj9L3RpKljFvKiDMtyDzPKzlsDrKIw2EYY+bF88gB6oGY5RGmv4DAX8dbnpRAqgFD0FMEw==", "cpu": [ "ia32" ], @@ -3276,9 +3276,9 @@ } }, "node_modules/@swc/core-win32-x64-msvc": { - "version": "1.12.14", - "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.12.14.tgz", - "integrity": "sha512-SymoP2CJHzrYaFKjWvuQljcF7BkTpzaS1vpywv7K9EzdTb5N8qPDvNd+PhWUqBz9JHBhbJxpaeTDQBXF/WWPmw==", + "version": "1.13.5", + "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.13.5.tgz", + "integrity": "sha512-YrKdMVxbYmlfybCSbRtrilc6UA8GF5aPmGKBdPvjrarvsmf4i7ZHGCEnLtfOMd3Lwbs2WUZq3WdMbozYeLU93Q==", "cpu": [ "x64" ], @@ -3300,9 +3300,9 @@ "license": "Apache-2.0" }, "node_modules/@swc/types": { - "version": "0.1.23", - "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.23.tgz", - "integrity": "sha512-u1iIVZV9Q0jxY+yM2vw/hZGDNudsN85bBpTqzAQ9rzkxW9D+e3aEM4Han+ow518gSewkXgjmEK0BD79ZcNVgPw==", + "version": "0.1.24", + "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.24.tgz", + "integrity": "sha512-tjTMh3V4vAORHtdTprLlfoMptu1WfTZG9Rsca6yOKyNYsRr+MUXutKmliB17orgSZk5DpnDxs8GUdd/qwYxOng==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -3525,6 +3525,60 @@ "node": ">=14.0.0" } }, + "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/core": { + "version": "1.4.3", + "inBundle": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/wasi-threads": "1.0.2", + "tslib": "^2.4.0" + } + }, + "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/runtime": { + "version": "1.4.3", + "inBundle": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/wasi-threads": { + "version": "1.0.2", + "inBundle": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@napi-rs/wasm-runtime": { + "version": "0.2.11", + "inBundle": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "^1.4.3", + "@emnapi/runtime": "^1.4.3", + "@tybys/wasm-util": "^0.9.0" + } + }, + "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@tybys/wasm-util": { + "version": "0.9.0", + "inBundle": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/tslib": { + "version": "2.8.0", + "inBundle": true, + "license": "0BSD", + "optional": true + }, "node_modules/@tailwindcss/oxide-win32-arm64-msvc": { "version": "4.1.11", "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.11.tgz", @@ -4204,17 +4258,20 @@ } }, "node_modules/@vitejs/plugin-react-swc": { - "version": "3.10.2", - "resolved": "https://registry.npmjs.org/@vitejs/plugin-react-swc/-/plugin-react-swc-3.10.2.tgz", - "integrity": "sha512-xD3Rdvrt5LgANug7WekBn1KhcvLn1H3jNBfJRL3reeOIua/WnZOEV5qi5qIBq5T8R0jUDmRtxuvk4bPhzGHDWw==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react-swc/-/plugin-react-swc-4.0.1.tgz", + "integrity": "sha512-NQhPjysi5duItyrMd5JWZFf2vNOuSMyw+EoZyTBDzk+DkfYD8WNrsUs09sELV2cr1P15nufsN25hsUBt4CKF9Q==", "dev": true, "license": "MIT", "dependencies": { - "@rolldown/pluginutils": "1.0.0-beta.11", - "@swc/core": "^1.11.31" + "@rolldown/pluginutils": "1.0.0-beta.32", + "@swc/core": "^1.13.2" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" }, "peerDependencies": { - "vite": "^4 || ^5 || ^6 || ^7.0.0-beta.0" + "vite": "^4 || ^5 || ^6 || ^7" } }, "node_modules/@xterm/addon-attach": { diff --git a/package.json b/package.json index e53653c2..eec23c0c 100644 --- a/package.json +++ b/package.json @@ -86,7 +86,7 @@ "@types/react-dom": "^19.1.6", "@types/ssh2": "^1.15.5", "@types/ws": "^8.18.1", - "@vitejs/plugin-react-swc": "^3.10.2", + "@vitejs/plugin-react-swc": "^4.0.1", "autoprefixer": "^10.4.21", "eslint": "^9.30.1", "eslint-plugin-react-hooks": "^5.2.0",