mirror of
https://github.com/jetkvm/kvm.git
synced 2026-05-21 05:20:35 +00:00
chore(ui): migrate to Vite 8, oxlint, and oxfmt (#1362)
* chore(ui): migrate to Vite 8, oxlint, and oxfmt Replace esbuild+Rollup with Oxc+Rolldown (Vite 8), ESLint with oxlint (with type-aware linting), and Prettier with oxfmt. No source code changes — formatting and lint fixes will roll out incrementally via lint-staged as files are touched. * fix(ui): resolve oxlint errors in existing code Fix errors caught by oxlint: useless rename, redundant undefined on optional params, duplicate union type constituent, and unsafe toString on union type.
This commit is contained in:
@@ -5,9 +5,9 @@
|
||||
"useTabs": false,
|
||||
"arrowParens": "avoid",
|
||||
"singleQuote": false,
|
||||
"plugins": ["prettier-plugin-tailwindcss"],
|
||||
"tailwindFunctions": ["clsx", "cx"],
|
||||
"printWidth": 100,
|
||||
"max_line_length": 100,
|
||||
"tailwindStylesheet": "./src/index.css"
|
||||
"sortTailwindcss": {
|
||||
"functions": ["clsx", "cx"],
|
||||
"stylesheet": "./src/index.css",
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
{
|
||||
"$schema": "https://raw.githubusercontent.com/oxc-project/oxc/main/npm/oxlint/configuration_schema.json",
|
||||
"plugins": ["react", "typescript", "import"],
|
||||
"options": {
|
||||
"typeAware": true
|
||||
},
|
||||
"categories": {
|
||||
"correctness": "error"
|
||||
},
|
||||
"rules": {
|
||||
"typescript/no-unused-vars": ["warn", { "argsIgnorePattern": "^_", "varsIgnorePattern": "^_" }],
|
||||
"typescript/no-floating-promises": "warn",
|
||||
"typescript/restrict-template-expressions": "warn",
|
||||
"typescript/no-base-to-string": "warn",
|
||||
"import/order": [
|
||||
"error",
|
||||
{
|
||||
"groups": ["builtin", "external", "internal", "parent", "sibling"],
|
||||
"newlines-between": "ignore"
|
||||
}
|
||||
]
|
||||
},
|
||||
"settings": {
|
||||
"react": {
|
||||
"version": "19"
|
||||
}
|
||||
},
|
||||
"ignorePatterns": ["dist", "tailwind.config.js", "postcss.config.js"]
|
||||
}
|
||||
@@ -1,90 +0,0 @@
|
||||
import globals from "globals";
|
||||
import { defineConfig, globalIgnores } from "eslint/config";
|
||||
import { fixupConfigRules } from "@eslint/compat";
|
||||
import js from "@eslint/js";
|
||||
import { FlatCompat } from "@eslint/eslintrc";
|
||||
import path from "path";
|
||||
import { fileURLToPath } from "url";
|
||||
|
||||
import tsParser from "@typescript-eslint/parser";
|
||||
import reactRefresh from "eslint-plugin-react-refresh";
|
||||
|
||||
// mimic CommonJS variables
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = path.dirname(__filename);
|
||||
|
||||
const compat = new FlatCompat({
|
||||
baseDirectory: __dirname,
|
||||
recommendedConfig: js.configs.recommended,
|
||||
allConfig: js.configs.all
|
||||
});
|
||||
|
||||
export default defineConfig([
|
||||
{
|
||||
languageOptions: {
|
||||
globals: globals.browser,
|
||||
parser: tsParser,
|
||||
ecmaVersion: "latest",
|
||||
sourceType: "module",
|
||||
parserOptions: {
|
||||
project: ["./tsconfig.app.json", "./tsconfig.node.json"],
|
||||
tsconfigRootDir: __dirname,
|
||||
ecmaFeatures: {
|
||||
jsx: true
|
||||
}
|
||||
},
|
||||
},
|
||||
extends: fixupConfigRules(compat.extends(
|
||||
"eslint:recommended",
|
||||
"plugin:@typescript-eslint/recommended",
|
||||
"plugin:@typescript-eslint/stylistic",
|
||||
"plugin:react/recommended",
|
||||
"plugin:react-hooks/recommended",
|
||||
"plugin:react/jsx-runtime",
|
||||
"plugin:import/recommended",
|
||||
"plugin:prettier/recommended",
|
||||
"prettier",
|
||||
)),
|
||||
plugins: {
|
||||
"react-refresh": reactRefresh,
|
||||
},
|
||||
rules: {
|
||||
"react-refresh/only-export-components": ["warn", {
|
||||
allowConstantExport: true,
|
||||
}],
|
||||
|
||||
"import/order": ["error", {
|
||||
groups: ["builtin", "external", "internal", "parent", "sibling"],
|
||||
"newlines-between": "ignore",
|
||||
}],
|
||||
|
||||
"@typescript-eslint/no-unused-vars": ["warn", {
|
||||
"argsIgnorePattern": "^_", "varsIgnorePattern": "^_"
|
||||
}],
|
||||
},
|
||||
settings: {
|
||||
"react": {
|
||||
"version": "detect"
|
||||
},
|
||||
"import/resolver": {
|
||||
alias: {
|
||||
map: [
|
||||
["@components", "./src/components"],
|
||||
["@routes", "./src/routes"],
|
||||
["@hooks", "./src/hooks"],
|
||||
["@providers", "./src/providers"],
|
||||
["@assets", "./src/assets"],
|
||||
["@localizations", "./localization/paraglide"],
|
||||
["@", "./src"],
|
||||
],
|
||||
|
||||
extensions: [".ts", ".tsx", ".js", ".jsx", ".json"],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
globalIgnores([
|
||||
"**/dist",
|
||||
"**/tailwind.config.js",
|
||||
"**/postcss.config.js",
|
||||
])]);
|
||||
Generated
+1942
-4899
File diff suppressed because it is too large
Load Diff
+16
-30
@@ -1,11 +1,8 @@
|
||||
{
|
||||
"name": "kvm-ui",
|
||||
"private": true,
|
||||
"version": "2025.12.11.1200",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"engines": {
|
||||
"node": "^22.21.1"
|
||||
},
|
||||
"scripts": {
|
||||
"dev": "./dev_device.sh",
|
||||
"dev:ssl": "USE_SSL=true ./dev_device.sh",
|
||||
@@ -15,9 +12,9 @@
|
||||
"build:staging": "npm run i18n:compile && tsc && vite build --mode=cloud-staging",
|
||||
"build:prod": "npm run i18n:compile && tsc && vite build --mode=cloud-production",
|
||||
"lint": "npm run i18n:compile && npm run lint:only",
|
||||
"lint:only": "eslint './src/**/*.{ts,tsx}'",
|
||||
"lint:only": "oxlint ./src",
|
||||
"lint:fix": "npm run i18n:compile && npm run lint:fixonly",
|
||||
"lint:fixonly": "eslint './src/**/*.{ts,tsx}' --fix",
|
||||
"lint:fixonly": "oxlint ./src --fix",
|
||||
"i18n": "npm run i18n:resort && npm run i18n:validate && npm run i18n:compile",
|
||||
"i18n:resort": "python3 tools/resort_messages.py",
|
||||
"i18n:validate": "inlang validate --project ./localization/jetKVM.UI.inlang",
|
||||
@@ -34,7 +31,7 @@
|
||||
"@headlessui/react": "^2.2.9",
|
||||
"@headlessui/tailwindcss": "^0.2.2",
|
||||
"@heroicons/react": "^2.2.0",
|
||||
"@vitejs/plugin-basic-ssl": "^2.1.0",
|
||||
"@vitejs/plugin-basic-ssl": "^2.3.0",
|
||||
"@xterm/addon-clipboard": "^0.1.0",
|
||||
"@xterm/addon-fit": "^0.10.0",
|
||||
"@xterm/addon-unicode11": "^0.8.0",
|
||||
@@ -66,9 +63,6 @@
|
||||
"zustand": "^4.5.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/compat": "^2.0.0",
|
||||
"@eslint/eslintrc": "^3.3.3",
|
||||
"@eslint/js": "^9.39.2",
|
||||
"@inlang/cli": "^3.0.12",
|
||||
"@inlang/paraglide-js": "^2.6.0",
|
||||
"@inlang/plugin-m-function-matcher": "^2.1.0",
|
||||
@@ -78,38 +72,30 @@
|
||||
"@tailwindcss/forms": "^0.5.10",
|
||||
"@tailwindcss/postcss": "^4.1.18",
|
||||
"@tailwindcss/typography": "^0.5.19",
|
||||
"@tailwindcss/vite": "^4.1.18",
|
||||
"@tailwindcss/vite": "^4.2.2",
|
||||
"@types/node": "^24.10.1",
|
||||
"@types/react": "^19.2.7",
|
||||
"@types/react-dom": "^19.2.3",
|
||||
"@types/semver": "^7.7.1",
|
||||
"@types/validator": "^13.15.10",
|
||||
"@typescript-eslint/eslint-plugin": "^8.49.0",
|
||||
"@typescript-eslint/parser": "^8.49.0",
|
||||
"@vitejs/plugin-react-swc": "^4.2.2",
|
||||
"@vitejs/plugin-react-swc": "^4.3.0",
|
||||
"autoprefixer": "^10.4.23",
|
||||
"eslint": "^9.39.2",
|
||||
"eslint-config-prettier": "^10.1.8",
|
||||
"eslint-import-resolver-alias": "^1.1.2",
|
||||
"eslint-plugin-import": "^2.32.0",
|
||||
"eslint-plugin-prettier": "^5.5.4",
|
||||
"eslint-plugin-react": "^7.37.5",
|
||||
"eslint-plugin-react-hooks": "^7.0.1",
|
||||
"eslint-plugin-react-refresh": "^0.4.25",
|
||||
"globals": "^16.5.0",
|
||||
"husky": "^9.1.7",
|
||||
"lint-staged": "^16.4.0",
|
||||
"oxfmt": "^0.42.0",
|
||||
"oxlint": "^1.57.0",
|
||||
"oxlint-tsgolint": "^0.18.1",
|
||||
"postcss": "^8.5.6",
|
||||
"prettier": "^3.7.4",
|
||||
"prettier-plugin-tailwindcss": "^0.7.2",
|
||||
"tailwindcss": "^4.1.18",
|
||||
"typescript": "^5.9.3",
|
||||
"typescript-eslint": "^8.49.0",
|
||||
"vite": "^7.2.7",
|
||||
"vite-tsconfig-paths": "^5.1.4"
|
||||
"vite": "^8.0.3",
|
||||
"vite-tsconfig-paths": "^6.1.1"
|
||||
},
|
||||
"lint-staged": {
|
||||
"*.{ts,tsx}": "eslint --fix",
|
||||
"*.{ts,tsx,js,jsx,json,css,md}": "prettier --write"
|
||||
"*.{ts,tsx}": "oxlint --fix --deny-warnings",
|
||||
"*.{ts,tsx,js,jsx,json,css,md}": "oxfmt"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^22.21.1"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -161,7 +161,6 @@ type ButtonPropsType = Pick<
|
||||
| "onMouseLeave"
|
||||
| "onMouseDown"
|
||||
| "onMouseUp"
|
||||
| "onMouseLeave"
|
||||
| "data-testid"
|
||||
> &
|
||||
React.ComponentProps<typeof ButtonContent> & {
|
||||
@@ -220,9 +219,9 @@ export const LinkButton = ({ to, ...props }: LinkPropsType) => {
|
||||
props.className,
|
||||
);
|
||||
|
||||
if (to.toString().startsWith("http")) {
|
||||
if (typeof to === "string" && to.startsWith("http")) {
|
||||
return (
|
||||
<ExtLink href={to.toString()} className={classes} target={props.target}>
|
||||
<ExtLink href={to} className={classes} target={props.target}>
|
||||
<ButtonContent {...props} />
|
||||
</ExtLink>
|
||||
);
|
||||
|
||||
+2
-10
@@ -899,18 +899,10 @@ export interface MacrosState {
|
||||
loadMacros: () => Promise<void>;
|
||||
saveMacros: (macros: KeySequence[]) => Promise<void>;
|
||||
sendFn:
|
||||
| ((
|
||||
method: string,
|
||||
params: unknown,
|
||||
callback?: ((resp: JsonRpcResponse) => void) | undefined,
|
||||
) => void)
|
||||
| ((method: string, params: unknown, callback?: (resp: JsonRpcResponse) => void) => void)
|
||||
| null;
|
||||
setSendFn: (
|
||||
sendFn: (
|
||||
method: string,
|
||||
params: unknown,
|
||||
callback?: ((resp: JsonRpcResponse) => void) | undefined,
|
||||
) => void,
|
||||
sendFn: (method: string, params: unknown, callback?: (resp: JsonRpcResponse) => void) => void,
|
||||
) => void;
|
||||
}
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ export default function SettingsRoute() {
|
||||
const { width = 0 } = useResizeObserver({
|
||||
ref: scrollContainerRef as React.RefObject<HTMLDivElement>,
|
||||
});
|
||||
const { isFailsafeMode: isFailsafeMode, reason: failsafeReason } = useFailsafeModeStore();
|
||||
const { isFailsafeMode, reason: failsafeReason } = useFailsafeModeStore();
|
||||
const isVideoDisabled = isFailsafeMode && failsafeReason === "video";
|
||||
|
||||
// Handle scroll position to show/hide gradients
|
||||
|
||||
+23
-25
@@ -18,37 +18,35 @@ export default defineConfig(({ mode, command }) => {
|
||||
const { JETKVM_PROXY_URL, USE_SSL } = process.env;
|
||||
const useSSL = USE_SSL === "true";
|
||||
|
||||
const plugins = [
|
||||
tailwindcss(),
|
||||
tsconfigPaths(),
|
||||
react()
|
||||
];
|
||||
const plugins = [tailwindcss(), tsconfigPaths(), react()];
|
||||
|
||||
if (useSSL) {
|
||||
plugins.push(basicSsl());
|
||||
}
|
||||
|
||||
plugins.push(paraglideVitePlugin({
|
||||
project: "./localization/jetKVM.UI.inlang",
|
||||
outdir: "./localization/paraglide",
|
||||
outputStructure: 'message-modules',
|
||||
cookieName: 'JETKVM_LOCALE',
|
||||
strategy: ['cookie', 'baseLocale'],
|
||||
}))
|
||||
plugins.push(
|
||||
paraglideVitePlugin({
|
||||
project: "./localization/jetKVM.UI.inlang",
|
||||
outdir: "./localization/paraglide",
|
||||
outputStructure: "message-modules",
|
||||
cookieName: "JETKVM_LOCALE",
|
||||
strategy: ["cookie", "baseLocale"],
|
||||
}),
|
||||
);
|
||||
|
||||
return {
|
||||
plugins,
|
||||
esbuild: {
|
||||
pure: command === "build" ? ["console.debug"]: [],
|
||||
oxc: {
|
||||
pure: command === "build" ? ["console.debug"] : [],
|
||||
},
|
||||
assetsInclude: ["**/*.woff2"],
|
||||
build: {
|
||||
outDir: isCloud ? "dist" : "../static",
|
||||
rollupOptions: {
|
||||
rolldownOptions: {
|
||||
output: {
|
||||
manualChunks: (id) => {
|
||||
manualChunks: id => {
|
||||
if (id.includes("node_modules")) {
|
||||
// Let Rollup handle tesseract.js naturally via dynamic import
|
||||
// Let Rolldown handle tesseract.js naturally via dynamic import
|
||||
// to avoid CommonJS/ESM interop issues across chunks
|
||||
if (id.includes("tesseract")) return;
|
||||
return "vendor";
|
||||
@@ -66,14 +64,14 @@ export default defineConfig(({ mode, command }) => {
|
||||
https: useSSL,
|
||||
proxy: JETKVM_PROXY_URL
|
||||
? {
|
||||
"/me": JETKVM_PROXY_URL,
|
||||
"/device": JETKVM_PROXY_URL,
|
||||
"/webrtc": JETKVM_PROXY_URL,
|
||||
"/auth": JETKVM_PROXY_URL,
|
||||
"/storage": JETKVM_PROXY_URL,
|
||||
"/cloud": JETKVM_PROXY_URL,
|
||||
"/developer": JETKVM_PROXY_URL,
|
||||
}
|
||||
"/me": JETKVM_PROXY_URL,
|
||||
"/device": JETKVM_PROXY_URL,
|
||||
"/webrtc": JETKVM_PROXY_URL,
|
||||
"/auth": JETKVM_PROXY_URL,
|
||||
"/storage": JETKVM_PROXY_URL,
|
||||
"/cloud": JETKVM_PROXY_URL,
|
||||
"/developer": JETKVM_PROXY_URL,
|
||||
}
|
||||
: undefined,
|
||||
},
|
||||
base: onDevice && command === "build" ? "/static" : "/",
|
||||
|
||||
Reference in New Issue
Block a user