0d056a45e9
Vue 3 + Vuetify 4 + TypeScript + Vue Router 4 + Pinia frontend, replacing the old Tailwind+Alpine.js static pages. Infrastructure (8 new files): - composables/useSnackbar.ts — centralized notifications - composables/useServerList.ts — server dropdown data - composables/useServerPagination.ts — paginated server table - types/api.ts — 14 typed API response interfaces - types/global.d.ts — Window augmentation - utils/status.ts — server status display helpers - utils/validation.ts — 8 form validation rules - components/MonacoEditor.vue — fullscreen code editor 14 pages rebuilt: - LoginPage, DashboardPage, ServersPage, TerminalPage - FilesPage, PushPage, ScriptsPage, CredentialsPage - SchedulesPage, RetriesPage, CommandsPage - AlertsPage, AuditPage, SettingsPage Critical fixes (from audit): - Files upload JWT auth (was missing Authorization header) - API Key reveal password verification dialog - 6 silent catch blocks → snackbar error feedback - 33 as any → 0 (typed interfaces + global.d.ts) - Dashboard: alerts/summary/categories/audit data loading - WebSocket reconnect timer cleanup + auth failure handling - Terminal ResizeObserver leak fix - PushPage timer cleanup on unmount - FilesPage path double-slash fix (joinPath helper) - Filter changes reset pagination to page 1 Features added: - Servers: batch operations, CSV export/import, detail panel - Push: sync modes, ZIP upload, WebSocket real-time progress, cancel - Scripts: quick execute panel, execution status tracking - Files: Monaco editor, context menu, batch delete, rename, chmod - Terminal: right-click menu, server sidebar, tab persistence - Settings: batch save, TOTP manual key, password TOTP verification - Dashboard: category distribution, recent audit, WS refresh Quality: - vue-tsc --noEmit zero errors - vite build passes (1613 modules) - Formal 8-step security audit passed (0 FINDING) - .gitignore: dist/ → **/dist/ to cover web/app/dist/ Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
70 lines
1.5 KiB
TypeScript
70 lines
1.5 KiB
TypeScript
import { fileURLToPath, URL } from 'node:url'
|
|
import Vue from '@vitejs/plugin-vue'
|
|
import Fonts from 'unplugin-fonts/vite'
|
|
import { defineConfig } from 'vite'
|
|
import Vuetify, { transformAssetUrls } from 'vite-plugin-vuetify'
|
|
|
|
// https://vitejs.dev/config/
|
|
export default defineConfig({
|
|
plugins: [
|
|
Vue({
|
|
template: { transformAssetUrls },
|
|
}),
|
|
Vuetify({
|
|
autoImport: true,
|
|
styles: {
|
|
configFile: 'src/styles/settings.scss',
|
|
},
|
|
}),
|
|
Fonts({
|
|
fontsource: {
|
|
families: [
|
|
{
|
|
name: 'Roboto',
|
|
weights: [100, 300, 400, 500, 700, 900],
|
|
styles: ['normal', 'italic'],
|
|
},
|
|
],
|
|
},
|
|
}),
|
|
],
|
|
define: { 'process.env': {} },
|
|
resolve: {
|
|
alias: {
|
|
'@': fileURLToPath(new URL('src', import.meta.url)),
|
|
},
|
|
extensions: [
|
|
'.js',
|
|
'.json',
|
|
'.jsx',
|
|
'.mjs',
|
|
'.ts',
|
|
'.tsx',
|
|
'.vue',
|
|
],
|
|
},
|
|
// Production build: output to web/app/dist/ so the backend can serve it
|
|
// alongside the existing HTML pages. Base path matches the backend's /app/ route.
|
|
base: '/app/',
|
|
build: {
|
|
outDir: fileURLToPath(new URL('../web/app/dist', import.meta.url)),
|
|
emptyOutDir: true,
|
|
},
|
|
server: {
|
|
port: 3000,
|
|
proxy: {
|
|
'/api': {
|
|
target: 'https://api.synaglobal.vip',
|
|
changeOrigin: true,
|
|
secure: true,
|
|
},
|
|
'/ws': {
|
|
target: 'wss://api.synaglobal.vip',
|
|
ws: true,
|
|
changeOrigin: true,
|
|
secure: true,
|
|
},
|
|
},
|
|
},
|
|
})
|