diff --git a/.github/workflows/lint-web.yml b/.github/workflows/lint-web.yml index 12a74e2dd..b58b73c4c 100644 --- a/.github/workflows/lint-web.yml +++ b/.github/workflows/lint-web.yml @@ -33,6 +33,9 @@ jobs: run: | npm i -g npm pnpm pnpm i --frozen-lockfile + - name: Build + working-directory: ./web + run: pnpm build - name: Lint working-directory: ./web run: pnpm run lint diff --git a/.gitmodules b/.gitmodules index a5df1c851..561704131 100644 --- a/.gitmodules +++ b/.gitmodules @@ -3,4 +3,4 @@ url = ../proto.git [submodule "web/src/shared/defguard-ui"] path = web/src/shared/defguard-ui - url = ../ui.git + url = git@github.com:DefGuard/ui.git diff --git a/Dockerfile b/Dockerfile index 8939f2b52..100ea408a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,11 +1,10 @@ FROM public.ecr.aws/docker/library/node:24 AS web WORKDIR /app -COPY web/package.json web/pnpm-lock.yaml web/.npmrc ./ +COPY web/package.json web/pnpm-lock.yaml ./ RUN npm i -g pnpm RUN pnpm install --ignore-scripts --frozen-lockfile COPY web/ . -RUN pnpm run generate-translation-types RUN pnpm build FROM public.ecr.aws/docker/library/rust:1 AS chef @@ -31,7 +30,6 @@ RUN cargo chef cook --release --recipe-path recipe.json # build project COPY --from=web /app/dist ./web/dist -COPY web/src/shared/images/svg ./web/src/shared/images/svg RUN apt-get update && apt-get -y install protobuf-compiler libprotobuf-dev COPY Cargo.toml Cargo.lock ./ # for vergen diff --git a/web/.biomeignore b/web/.biomeignore deleted file mode 100644 index 8260f01a7..000000000 --- a/web/.biomeignore +++ /dev/null @@ -1,2 +0,0 @@ -src/i18n/*.ts -src/i18n/*.tsx diff --git a/web/.browserslistrc b/web/.browserslistrc new file mode 100644 index 000000000..549f14c02 --- /dev/null +++ b/web/.browserslistrc @@ -0,0 +1 @@ +>0.3%, last 2 versions, since 2025, not op_mini all, not dead diff --git a/web/.editorconfig b/web/.editorconfig index 57516b7ac..73f410322 100644 --- a/web/.editorconfig +++ b/web/.editorconfig @@ -7,23 +7,5 @@ insert_final_newline = true indent_style = space indent_size = 2 -[*.{ts,tsx}] -indent_style = space -indent_size = 2 -rulers = 90 - -[*.{scss}] -indent_style = space -indent_size = 2 -rulers = 90 - -[*.{html}] -indent_style = space -indent_size = 2 +[*.{ts,tsx,js,jsx,scss,html,json,yaml}] rulers = 90 - -[*.{json,yaml}] -insert_final_newline = true -indent_style = space -indent_size = 2 -rulers = 80 diff --git a/web/.gitattributes b/web/.gitattributes new file mode 100644 index 000000000..ee7f45a36 --- /dev/null +++ b/web/.gitattributes @@ -0,0 +1,36 @@ +* text=auto eol=lf + +*.js text eol=lf +*.jsx text eol=lf +*.ts text eol=lf +*.tsx text eol=lf +*.css text eol=lf +*.scss text eol=lf +*.json text eol=lf +*.html text eol=lf +*.md text eol=lf +*.yml text eol=lf +*.yaml text eol=lf +*.lock text eol=lf + +*.woff binary +*.woff2 binary +*.ttf binary +*.otf binary +*.eot binary +*.png binary +*.jpg binary +*.jpeg binary +*.gif binary +*.webp binary +*.avif binary +*.ico binary +*.mp4 binary +*.webm binary +*.ogg binary +*.mp3 binary +*.wav binary +*.pdf binary +*.zip binary +*.tar binary +*.gz binary diff --git a/web/.gitignore b/web/.gitignore index 88e111584..175f4eee7 100644 --- a/web/.gitignore +++ b/web/.gitignore @@ -1,2 +1,29 @@ -*.local* -./*.env +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +dist +dist-ssr +*.local +project.inlang/cache +.env.development + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? +.tanstack +.cfft* +blueprint-templates diff --git a/web/.npmrc b/web/.npmrc deleted file mode 100644 index 319e41e69..000000000 --- a/web/.npmrc +++ /dev/null @@ -1 +0,0 @@ -strict-peer-dependencies=false diff --git a/web/.nvmrc b/web/.nvmrc deleted file mode 100644 index 53a256a2e..000000000 --- a/web/.nvmrc +++ /dev/null @@ -1 +0,0 @@ -v24.7 diff --git a/web/.prettierignore b/web/.prettierignore index 74dbecd59..402ea0086 100644 --- a/web/.prettierignore +++ b/web/.prettierignore @@ -1,4 +1,3 @@ -/src/i18n/*.ts -/src/i18n/*.tsx /src/**/*.tsx /src/**/*.ts +/src/**/*.js diff --git a/web/.stylelintrc.json b/web/.stylelintrc.json new file mode 100644 index 000000000..6a4e21333 --- /dev/null +++ b/web/.stylelintrc.json @@ -0,0 +1,10 @@ +{ + "extends": ["stylelint-config-standard-scss"], + "plugins": ["stylelint-scss"], + "rules": { + "at-rule-no-unknown": null, + "scss/at-rule-no-unknown": true, + "custom-property-empty-line-before": null, + "value-keyword-case": null + } +} diff --git a/web/.typesafe-i18n.json b/web/.typesafe-i18n.json deleted file mode 100644 index 28148cbaf..000000000 --- a/web/.typesafe-i18n.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "adapter": "react", - "$schema": "https://unpkg.com/typesafe-i18n@5.26.2/schema/typesafe-i18n.json", - "baseLocale": "en" -} diff --git a/web/README.md b/web/README.md index c88e39e5b..4dcad1f91 100644 --- a/web/README.md +++ b/web/README.md @@ -1,73 +1,73 @@ -# Defguard frontend +# React + TypeScript + Vite -React.js based, web user interface for Defguard project. +This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules. -## Run development server +Currently, two official plugins are available: -Install dependencies +- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react) uses [Babel](https://babeljs.io/) (or [oxc](https://oxc.rs) when used in [rolldown-vite](https://vite.dev/guide/rolldown)) for Fast Refresh +- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh -```bash - pnpm install -``` - -Start the dev server - -```bash - pnpm run dev -``` - -You can configure API proxy by changing `target` key value under `/api` path within `vite.config.ts` file. - -## Build docker image +## React Compiler -```bash -docker build . -``` - -## Linting - -For linting this project uses [prettier](https://www.npmjs.com/package/prettier), [eslint](https://www.npmjs.com/package/eslint) and [stylelint](https://stylelint.io/) +The React Compiler is currently not compatible with SWC. See [this issue](https://github.com/vitejs/vite-plugin-react/issues/428) for tracking the progress. -#### Available commands +## Expanding the ESLint configuration -Check linting in all supported files ( both prettier and eslint ) +If you are developing a production application, we recommend updating the configuration to enable type-aware lint rules: -```bash -pnpm run lint -``` +```js +export default defineConfig([ + globalIgnores(['dist']), + { + files: ['**/*.{ts,tsx}'], + extends: [ + // Other configs... -Fix all autofixable problems with eslint + // Remove tseslint.configs.recommended and replace with this + tseslint.configs.recommendedTypeChecked, + // Alternatively, use this for stricter rules + tseslint.configs.strictTypeChecked, + // Optionally, add this for stylistic rules + tseslint.configs.stylisticTypeChecked, -```bash -pnpm run eslint-fix + // Other configs... + ], + languageOptions: { + parserOptions: { + project: ['./tsconfig.node.json', './tsconfig.app.json'], + tsconfigRootDir: import.meta.dirname, + }, + // other options... + }, + }, +]) ``` -Fix all autofixable probles with prettier - -```bash -pnpm run prettier-fix +You can also install [eslint-plugin-react-x](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-x) and [eslint-plugin-react-dom](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-dom) for React-specific lint rules: + +```js +// eslint.config.js +import reactX from 'eslint-plugin-react-x' +import reactDom from 'eslint-plugin-react-dom' + +export default defineConfig([ + globalIgnores(['dist']), + { + files: ['**/*.{ts,tsx}'], + extends: [ + // Other configs... + // Enable lint rules for React + reactX.configs['recommended-typescript'], + // Enable lint rules for React DOM + reactDom.configs.recommended, + ], + languageOptions: { + parserOptions: { + project: ['./tsconfig.node.json', './tsconfig.app.json'], + tsconfigRootDir: import.meta.dirname, + }, + // other options... + }, + }, +]) ``` - -Fix all autofixable problems with pretter and eslint - -```bash -pnpm fix-lint -``` - -#### Adding new SVG components - -Move .svg files into `src/shared/images/svg` then use command: - -```bash -pnpm parse-svgs -``` - -This will generate new components within `src/shared/components/svg`, they can be used as a regular components. Also this command doesn't replace or modify already existing files. - -## Conventional Commits - -Using [commitlint](https://commitlint.js.org/#/) with this [config](https://github.com/conventional-changelog/commitlint/tree/master/%40commitlint/config-conventional). - -## Versioning - -Using [standard-version](https://github.com/conventional-changelog/standard-version) diff --git a/web/biome.json b/web/biome.json index 2bcbfd1d7..bfaf40f57 100644 --- a/web/biome.json +++ b/web/biome.json @@ -1,21 +1,29 @@ { - "$schema": "https://biomejs.dev/schemas/2.2.2/schema.json", - "vcs": { "enabled": false, "clientKind": "git", "useIgnoreFile": false }, + "$schema": "https://biomejs.dev/schemas/2.3.3/schema.json", + "vcs": { + "enabled": false, + "clientKind": "git", + "useIgnoreFile": false + }, "files": { "ignoreUnknown": false, - "includes": ["src/**", "!src/i18n", "!**/svg"] + "includes": [ + "src/**", + "!src/messages", + "!src/paraglide/**/*.js", + "!src/routeTree.gen.ts" + ] }, "formatter": { "enabled": true, "formatWithErrors": false, - "indentStyle": "space", - "indentWidth": 2, - "lineEnding": "lf", - "lineWidth": 90, "attributePosition": "auto", "bracketSameLine": false, "bracketSpacing": true, "expand": "auto", + "lineEnding": "lf", + "lineWidth": 90, + "indentStyle": "space", "useEditorconfig": true }, "linter": { @@ -23,47 +31,26 @@ "rules": { "recommended": true, "a11y": "off", - "complexity": { - "noBannedTypes": "error", - "noUselessTypeConstraint": "error" - }, "correctness": { - "noChildrenProp": "error", - "noPrecisionLoss": "error", - "noUnusedVariables": "error", - "useExhaustiveDependencies": "error", - "useHookAtTopLevel": "error", - "useJsxKeyInIterable": "error", "useUniqueElementIds": "off" }, - "security": { "noDangerouslySetInnerHtmlWithChildren": "error" }, "style": { - "noNamespace": "error", - "noNonNullAssertion": "error", - "useArrayLiterals": "error", - "useAsConstAssertion": "error", - "useBlockStatements": "off", - "useLiteralEnumMembers": "off" + "useLiteralEnumMembers": "off", + "useBlockStatements": "off" }, "suspicious": { - "noCommentText": "error", - "noDuplicateJsxProps": "error", - "noExplicitAny": "error", - "noExtraNonNullAssertion": "error", - "noMisleadingInstantiator": "error", - "noUnsafeDeclarationMerging": "error", "noArrayIndexKey": "off" } } }, "javascript": { "formatter": { + "quoteStyle": "single", "jsxQuoteStyle": "double", "quoteProperties": "asNeeded", "trailingCommas": "all", "semicolons": "always", "arrowParentheses": "always", - "quoteStyle": "single", "attributePosition": "auto", "bracketSameLine": false, "bracketSpacing": true @@ -71,14 +58,10 @@ }, "assist": { "enabled": true, - "actions": { "source": { "organizeImports": "on" } } - }, - "overrides": [ - { - "includes": ["src/shared/links.ts"], - "formatter": { - "enabled": false + "actions": { + "source": { + "organizeImports": "on" } } - ] + } } diff --git a/web/index.html b/web/index.html index 33c26718f..5917d0880 100644 --- a/web/index.html +++ b/web/index.html @@ -4,36 +4,34 @@
- - - - + + +