Remove unused dependencies and symbols using knip

This commit is contained in:
Quentin Gliech
2025-01-06 10:05:00 +01:00
parent ff7500ec57
commit 6bd0fc6457
14 changed files with 297 additions and 424 deletions

View File

@@ -98,6 +98,31 @@ jobs:
run: npm test
frontend-knip:
name: Check the frontend for unused dependencies
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- name: Checkout the code
uses: actions/checkout@v4.2.2
- name: Install Node
uses: actions/setup-node@v4.1.0
with:
node-version: 20
- name: Install Node dependencies
working-directory: ./frontend
run: npm ci
- name: Check for unused dependencies
working-directory: ./frontend
run: npm run knip
rustfmt:
name: Check Rust style
runs-on: ubuntu-latest
@@ -362,6 +387,7 @@ jobs:
- opa-lint
- frontend-lint
- frontend-test
- frontend-knip
- rustfmt
- cargo-deny
- clippy

View File

@@ -6,7 +6,7 @@
import type { UserConfig } from "i18next-parser";
const config: UserConfig = {
export default {
keySeparator: ".",
pluralSeparator: ":",
defaultNamespace: "frontend",
@@ -30,6 +30,4 @@ const config: UserConfig = {
output: "locales/$LOCALE.json",
input: ["src/**/*.{ts,tsx}"],
sort: true,
};
export default config;
} satisfies UserConfig;

22
frontend/knip.config.ts Normal file
View File

@@ -0,0 +1,22 @@
// Copyright 2024 New Vector Ltd.
//
// SPDX-License-Identifier: AGPL-3.0-only
// Please see LICENSE in the repository root for full details.
import type { KnipConfig } from "knip";
export default {
entry: [
"src/main.tsx",
"src/swagger.tsx",
"src/routes/*",
"i18next-parser.config.ts",
],
ignore: ["src/gql/*", "src/routeTree.gen.ts", ".storybook/locales.ts"],
ignoreDependencies: [
// This is used by the tailwind PostCSS plugin, but not detected by knip
"postcss-nesting",
// We're using @storybook/addon-essentials to simplify upgrades, but knip doesn't detect them
"@storybook/addon-*",
],
} satisfies KnipConfig;

View File

@@ -96,7 +96,6 @@
"settings": "Settings"
},
"not_found_alert_title": "Not found.",
"not_logged_in_alert": "You're not logged in.",
"oauth2_client_detail": {
"details_title": "Client info",
"name": "Name",

View File

@@ -15,10 +15,6 @@
"@tanstack/react-query": "^5.62.15",
"@tanstack/react-router": "^1.95.1",
"@tanstack/router-zod-adapter": "^1.81.5",
"@urql/core": "^5.0.8",
"@urql/devtools": "^2.0.3",
"@urql/exchange-refocus": "^1.1.0",
"@urql/exchange-request-policy": "^1.2.0",
"@vector-im/compound-design-tokens": "2.1.3",
"@vector-im/compound-web": "^7.3.0",
"@zxcvbn-ts/core": "^3.0.4",
@@ -39,11 +35,9 @@
"@browser-logos/firefox": "^3.0.10",
"@browser-logos/safari": "^2.1.0",
"@codecov/vite-plugin": "^1.4.0",
"@graphql-codegen/add": "^5.0.3",
"@graphql-codegen/cli": "^5.0.3",
"@graphql-codegen/client-preset": "^4.5.1",
"@graphql-codegen/typescript-msw": "^3.0.0",
"@graphql-codegen/urql-introspection": "^3.0.0",
"@storybook/addon-essentials": "^8.4.7",
"@storybook/addon-interactions": "^8.4.7",
"@storybook/react": "^8.4.7",
@@ -54,10 +48,10 @@
"@tanstack/router-vite-plugin": "^1.95.1",
"@testing-library/jest-dom": "^6.6.3",
"@testing-library/react": "^16.0.1",
"@testing-library/user-event": "^14.5.2",
"@types/node": "^22.10.5",
"@types/react": "^18.3.12",
"@types/react-dom": "^18.3.1",
"@types/react-test-renderer": "^19.0.0",
"@types/swagger-ui-react": "^4.18.3",
"@vitejs/plugin-react": "^4.3.3",
"@vitest/coverage-v8": "^2.1.8",
@@ -66,16 +60,17 @@
"graphql": "^16.9.0",
"happy-dom": "^15.11.4",
"i18next-parser": "^9.1.0",
"knip": "^5.41.1",
"msw": "^2.6.5",
"msw-storybook-addon": "^2.0.4",
"postcss": "^8.4.49",
"postcss-modules": "^6.0.1",
"postcss-import": "^16.1.0",
"postcss-nesting": "^13.0.1",
"rimraf": "^6.0.1",
"storybook": "^8.4.4",
"storybook-react-i18next": "^3.1.8",
"tailwindcss": "^3.4.17",
"typescript": "5.7.2",
"typescript": "^5.7.2",
"vite": "5.4.11",
"vite-plugin-compression": "^0.5.1",
"vite-plugin-graphql-codegen": "^3.3.8",
@@ -83,20 +78,6 @@
"vitest": "^2.1.2"
}
},
"node_modules/@0no-co/graphql.web": {
"version": "1.0.11",
"resolved": "https://registry.npmjs.org/@0no-co/graphql.web/-/graphql.web-1.0.11.tgz",
"integrity": "sha512-xuSJ9WXwTmtngWkbdEoopMo6F8NLtjy84UNAMsAr5C3/2SgAL/dEU10TMqTIsipqPQ8HA/7WzeqQ9DEQxSvPPA==",
"license": "MIT",
"peerDependencies": {
"graphql": "^14.0.0 || ^15.0.0 || ^16.0.0"
},
"peerDependenciesMeta": {
"graphql": {
"optional": true
}
}
},
"node_modules/@actions/core": {
"version": "1.11.1",
"resolved": "https://registry.npmjs.org/@actions/core/-/core-1.11.1.tgz",
@@ -2436,63 +2417,6 @@
"graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0"
}
},
"node_modules/@graphql-codegen/urql-introspection": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/@graphql-codegen/urql-introspection/-/urql-introspection-3.0.0.tgz",
"integrity": "sha512-DBYfG3CO3G6MTzp+/FaXuxYS6cFSkpDMwxXKoJVqKR0jIGd/ev3Gh1pTgqxndcBu8oV9xjiaBQglKCge0EqLpQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@graphql-codegen/plugin-helpers": "^3.0.0",
"@urql/introspection": "^0.3.2",
"tslib": "~2.6.0"
},
"engines": {
"node": ">= 16.0.0"
},
"peerDependencies": {
"graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0"
}
},
"node_modules/@graphql-codegen/urql-introspection/node_modules/@graphql-codegen/plugin-helpers": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/@graphql-codegen/plugin-helpers/-/plugin-helpers-3.1.2.tgz",
"integrity": "sha512-emOQiHyIliVOIjKVKdsI5MXj312zmRDwmHpyUTZMjfpvxq/UVAHUJIVdVf+lnjjrI+LXBTgMlTWTgHQfmICxjg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@graphql-tools/utils": "^9.0.0",
"change-case-all": "1.0.15",
"common-tags": "1.8.2",
"import-from": "4.0.0",
"lodash": "~4.17.0",
"tslib": "~2.4.0"
},
"peerDependencies": {
"graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0"
}
},
"node_modules/@graphql-codegen/urql-introspection/node_modules/@graphql-codegen/plugin-helpers/node_modules/tslib": {
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz",
"integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==",
"dev": true,
"license": "0BSD"
},
"node_modules/@graphql-codegen/urql-introspection/node_modules/@graphql-tools/utils": {
"version": "9.2.1",
"resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-9.2.1.tgz",
"integrity": "sha512-WUw506Ql6xzmOORlriNrD6Ugx+HjVgYxt9KCXD9mHAak+eaXSwuGGPyE60hy9xaDEoXKBsG7SkG69ybitaVl6A==",
"dev": true,
"license": "MIT",
"dependencies": {
"@graphql-typed-document-node/core": "^3.1.1",
"tslib": "^2.4.0"
},
"peerDependencies": {
"graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0"
}
},
"node_modules/@graphql-codegen/visitor-plugin-common": {
"version": "5.6.0",
"resolved": "https://registry.npmjs.org/@graphql-codegen/visitor-plugin-common/-/visitor-plugin-common-5.6.0.tgz",
@@ -4801,6 +4725,34 @@
"hasInstallScript": true,
"license": "Apache-2.0"
},
"node_modules/@snyk/github-codeowners": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@snyk/github-codeowners/-/github-codeowners-1.1.0.tgz",
"integrity": "sha512-lGFf08pbkEac0NYgVf4hdANpAgApRjNByLXB+WBip3qj1iendOIyAwP2GKkKbQMNVy2r1xxDf0ssfWscoiC+Vw==",
"dev": true,
"license": "MIT",
"dependencies": {
"commander": "^4.1.1",
"ignore": "^5.1.8",
"p-map": "^4.0.0"
},
"bin": {
"github-codeowners": "dist/cli.js"
},
"engines": {
"node": ">=8.10"
}
},
"node_modules/@snyk/github-codeowners/node_modules/commander": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz",
"integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">= 6"
}
},
"node_modules/@storybook/addon-actions": {
"version": "8.4.7",
"resolved": "https://registry.npmjs.org/@storybook/addon-actions/-/addon-actions-8.4.7.tgz",
@@ -6323,6 +6275,7 @@
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.5.tgz",
"integrity": "sha512-F8Q+SeGimwOo86fiovQh8qiXfFEh2/ocYv7tU5pJ3EXMSSxk1Joj5wefpFK2fHTf/N6HKGSxIDBT9f3gCxXPkQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"undici-types": "~6.20.0"
}
@@ -6364,16 +6317,6 @@
"@types/react": "*"
}
},
"node_modules/@types/react-test-renderer": {
"version": "19.0.0",
"resolved": "https://registry.npmjs.org/@types/react-test-renderer/-/react-test-renderer-19.0.0.tgz",
"integrity": "sha512-qDVnNybqFm2eZKJ4jD34EvRd6VHD67KjgnWaEMM0Id9L22EpWe3nOSVKHWL1XWRCxUWe3lhXwlEeCKD1BlJCQA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@types/react": "*"
}
},
"node_modules/@types/resolve": {
"version": "1.20.6",
"resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.6.tgz",
@@ -6441,65 +6384,6 @@
"@types/node": "*"
}
},
"node_modules/@urql/core": {
"version": "5.0.8",
"resolved": "https://registry.npmjs.org/@urql/core/-/core-5.0.8.tgz",
"integrity": "sha512-1GOnUw7/a9bzkcM0+U8U5MmxW2A7FE5YquuEmcJzTtW5tIs2EoS4F2ITpuKBjRBbyRjZgO860nWFPo1m4JImGA==",
"license": "MIT",
"dependencies": {
"@0no-co/graphql.web": "^1.0.5",
"wonka": "^6.3.2"
}
},
"node_modules/@urql/devtools": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/@urql/devtools/-/devtools-2.0.3.tgz",
"integrity": "sha512-TktPLiBS9LcBPHD6qcnb8wqOVcg3Bx0iCtvQ80uPpfofwwBGJmqnQTjUdEFU6kwaLOFZULQ9+Uo4831G823mQw==",
"license": "MIT",
"dependencies": {
"wonka": ">= 4.0.9"
},
"peerDependencies": {
"@urql/core": ">= 1.14.0",
"graphql": ">= 0.11.0"
}
},
"node_modules/@urql/exchange-refocus": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@urql/exchange-refocus/-/exchange-refocus-1.1.0.tgz",
"integrity": "sha512-tMgIqXUGIuNBeEoXDNOZ48Kut2m85etNIorwBG89tQZHDLxJM52N6A0eLm0Mv9BJFb0U94i3drwlD55He+9Uvw==",
"license": "MIT",
"dependencies": {
"@urql/core": "^5.0.0",
"wonka": "^6.3.2"
},
"peerDependencies": {
"@urql/core": "^5.0.0"
}
},
"node_modules/@urql/exchange-request-policy": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/@urql/exchange-request-policy/-/exchange-request-policy-1.2.0.tgz",
"integrity": "sha512-30CwS5/YzX0YWVATg19rrDhruDCRIu96xUz6HGlhJPUw22M7njRldl44fmoU11ZbIemg01t8ysq6+0rdktYBgg==",
"license": "MIT",
"dependencies": {
"@urql/core": "^5.0.0",
"wonka": "^6.3.2"
},
"peerDependencies": {
"@urql/core": "^5.0.0"
}
},
"node_modules/@urql/introspection": {
"version": "0.3.3",
"resolved": "https://registry.npmjs.org/@urql/introspection/-/introspection-0.3.3.tgz",
"integrity": "sha512-tekSLLqWnusfV6V7xaEnLJQSdXOD/lWy7f8JYQwrX+88Md+voGSCSx5WJXI7KLBN3Tat2OV08tAr8UROykls4Q==",
"dev": true,
"license": "MIT",
"peerDependencies": {
"graphql": "^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0"
}
},
"node_modules/@vector-im/compound-design-tokens": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/@vector-im/compound-design-tokens/-/compound-design-tokens-2.1.3.tgz",
@@ -8608,6 +8492,19 @@
"dev": true,
"license": "MIT"
},
"node_modules/easy-table": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/easy-table/-/easy-table-1.2.0.tgz",
"integrity": "sha512-OFzVOv03YpvtcWGe5AayU5G2hgybsg3iqA6drU8UaoZyB9jLGMTrz9+asnLp/E+6qPh88yEI1gvyZFZ41dmgww==",
"dev": true,
"license": "MIT",
"dependencies": {
"ansi-regex": "^5.0.1"
},
"optionalDependencies": {
"wcwidth": "^1.0.1"
}
},
"node_modules/electron-to-chromium": {
"version": "1.5.58",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.58.tgz",
@@ -8646,6 +8543,20 @@
"once": "^1.4.0"
}
},
"node_modules/enhanced-resolve": {
"version": "5.18.0",
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.0.tgz",
"integrity": "sha512-0/r0MySGYG8YqlayBZ6MuCfECmHFdJ5qyPh8s8wa5Hnm6SaFLSK1VYCbj+NKp090Nm1caZhD+QTnmxO7esYGyQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"graceful-fs": "^4.2.4",
"tapable": "^2.2.0"
},
"engines": {
"node": ">=10.13.0"
}
},
"node_modules/ensure-posix-path": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/ensure-posix-path/-/ensure-posix-path-1.1.1.tgz",
@@ -9249,16 +9160,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/generic-names": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/generic-names/-/generic-names-4.0.0.tgz",
"integrity": "sha512-ySFolZQfw9FoDb3ed9d80Cm9f0+r7qj+HJkWjeD9RBfpxEVTlVhol+gvaQB/78WbwYfbnNh8nWHHBSlg072y6A==",
"dev": true,
"license": "MIT",
"dependencies": {
"loader-utils": "^3.2.0"
}
},
"node_modules/gensync": {
"version": "1.0.0-beta.2",
"resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
@@ -9463,6 +9364,7 @@
"version": "16.9.0",
"resolved": "https://registry.npmjs.org/graphql/-/graphql-16.9.0.tgz",
"integrity": "sha512-GGTKBX4SD7Wdb8mqeDLni2oaRGYQWjWHGKPQ24ZMnUtKfcsVoiv4uX8+LJr1K6U5VW2Lu1BwJnj7uiori0YtRw==",
"dev": true,
"license": "MIT",
"engines": {
"node": "^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0"
@@ -10374,19 +10276,6 @@
"node": ">=0.10.0"
}
},
"node_modules/icss-utils": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz",
"integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==",
"dev": true,
"license": "ISC",
"engines": {
"node": "^10 || ^12 || >= 14"
},
"peerDependencies": {
"postcss": "^8.1.0"
}
},
"node_modules/ieee754": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
@@ -11091,6 +10980,79 @@
"graceful-fs": "^4.1.6"
}
},
"node_modules/knip": {
"version": "5.41.1",
"resolved": "https://registry.npmjs.org/knip/-/knip-5.41.1.tgz",
"integrity": "sha512-yNpCCe2REU7U3VRvMASnXSEtfEC2HmOoDW9Vp9teQ9FktJYnuagvSZD3xWq8Ru7sPABkmvbC5TVWuMzIaeADNA==",
"dev": true,
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/webpro"
},
{
"type": "opencollective",
"url": "https://opencollective.com/knip"
},
{
"type": "polar",
"url": "https://polar.sh/webpro-nl"
}
],
"license": "ISC",
"dependencies": {
"@nodelib/fs.walk": "1.2.8",
"@snyk/github-codeowners": "1.1.0",
"easy-table": "1.2.0",
"enhanced-resolve": "^5.17.1",
"fast-glob": "^3.3.2",
"jiti": "^2.4.0",
"js-yaml": "^4.1.0",
"minimist": "^1.2.8",
"picocolors": "^1.1.0",
"picomatch": "^4.0.1",
"pretty-ms": "^9.0.0",
"smol-toml": "^1.3.1",
"strip-json-comments": "5.0.1",
"summary": "2.1.0",
"zod": "^3.22.4",
"zod-validation-error": "^3.0.3"
},
"bin": {
"knip": "bin/knip.js",
"knip-bun": "bin/knip-bun.js"
},
"engines": {
"node": ">=18.6.0"
},
"peerDependencies": {
"@types/node": ">=18",
"typescript": ">=5.0.4"
}
},
"node_modules/knip/node_modules/jiti": {
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/jiti/-/jiti-2.4.2.tgz",
"integrity": "sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==",
"dev": true,
"license": "MIT",
"bin": {
"jiti": "lib/jiti-cli.mjs"
}
},
"node_modules/knip/node_modules/strip-json-comments": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-5.0.1.tgz",
"integrity": "sha512-0fk9zBqO67Nq5M/m45qHCJxylV/DhBlIOVExqgOMiCCrzrhU6tCibRXNqE3jwJLftzE9SNuZtYbpzcO+i9FiKw==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=14.16"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/lead": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/lead/-/lead-4.0.0.tgz",
@@ -11166,16 +11128,6 @@
"url": "https://github.com/chalk/wrap-ansi?sponsor=1"
}
},
"node_modules/loader-utils": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-3.3.1.tgz",
"integrity": "sha512-FMJTLMXfCLMLfJxcX9PFqX5qD88Z5MRGaZCVzfuqeZSPsyiBzs+pahDQjbIWz2QIzPZz0NX9Zy4FX3lmK6YHIg==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">= 12.13.0"
}
},
"node_modules/locate-path": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
@@ -11198,13 +11150,6 @@
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
"license": "MIT"
},
"node_modules/lodash.camelcase": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz",
"integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==",
"dev": true,
"license": "MIT"
},
"node_modules/lodash.debounce": {
"version": "4.0.8",
"resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz",
@@ -12175,6 +12120,19 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/parse-ms": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/parse-ms/-/parse-ms-4.0.0.tgz",
"integrity": "sha512-TXfryirbmq34y8QBwgqCVLi+8oA3oWx2eAnSn62ITyEhEYaWRlVZ2DvMM9eZbMs/RfxPu/PK/aBLyGj4IrqMHw==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=18"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/parse5": {
"version": "7.2.1",
"resolved": "https://registry.npmjs.org/parse5/-/parse5-7.2.1.tgz",
@@ -12457,9 +12415,9 @@
}
},
"node_modules/postcss-import": {
"version": "15.1.0",
"resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz",
"integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==",
"version": "16.1.0",
"resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-16.1.0.tgz",
"integrity": "sha512-7hsAZ4xGXl4MW+OKEWCnF6T5jqBw80/EE9aXg1r2yyn1RsVEU8EtKXbijEODa+rg7iih4bKf7vlvTGYR4CnPNg==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -12468,7 +12426,7 @@
"resolve": "^1.1.7"
},
"engines": {
"node": ">=14.0.0"
"node": ">=18.0.0"
},
"peerDependencies": {
"postcss": "^8.0.0"
@@ -12530,89 +12488,6 @@
}
}
},
"node_modules/postcss-modules": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/postcss-modules/-/postcss-modules-6.0.1.tgz",
"integrity": "sha512-zyo2sAkVvuZFFy0gc2+4O+xar5dYlaVy/ebO24KT0ftk/iJevSNyPyQellsBLlnccwh7f6V6Y4GvuKRYToNgpQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"generic-names": "^4.0.0",
"icss-utils": "^5.1.0",
"lodash.camelcase": "^4.3.0",
"postcss-modules-extract-imports": "^3.1.0",
"postcss-modules-local-by-default": "^4.0.5",
"postcss-modules-scope": "^3.2.0",
"postcss-modules-values": "^4.0.0",
"string-hash": "^1.1.3"
},
"peerDependencies": {
"postcss": "^8.0.0"
}
},
"node_modules/postcss-modules-extract-imports": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.1.0.tgz",
"integrity": "sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q==",
"dev": true,
"license": "ISC",
"engines": {
"node": "^10 || ^12 || >= 14"
},
"peerDependencies": {
"postcss": "^8.1.0"
}
},
"node_modules/postcss-modules-local-by-default": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.1.0.tgz",
"integrity": "sha512-rm0bdSv4jC3BDma3s9H19ZddW0aHX6EoqwDYU2IfZhRN+53QrufTRo2IdkAbRqLx4R2IYbZnbjKKxg4VN5oU9Q==",
"dev": true,
"license": "MIT",
"dependencies": {
"icss-utils": "^5.0.0",
"postcss-selector-parser": "^7.0.0",
"postcss-value-parser": "^4.1.0"
},
"engines": {
"node": "^10 || ^12 || >= 14"
},
"peerDependencies": {
"postcss": "^8.1.0"
}
},
"node_modules/postcss-modules-scope": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.2.1.tgz",
"integrity": "sha512-m9jZstCVaqGjTAuny8MdgE88scJnCiQSlSrOWcTQgM2t32UBe+MUmFSO5t7VMSfAf/FJKImAxBav8ooCHJXCJA==",
"dev": true,
"license": "ISC",
"dependencies": {
"postcss-selector-parser": "^7.0.0"
},
"engines": {
"node": "^10 || ^12 || >= 14"
},
"peerDependencies": {
"postcss": "^8.1.0"
}
},
"node_modules/postcss-modules-values": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz",
"integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==",
"dev": true,
"license": "ISC",
"dependencies": {
"icss-utils": "^5.0.0"
},
"engines": {
"node": "^10 || ^12 || >= 14"
},
"peerDependencies": {
"postcss": "^8.1.0"
}
},
"node_modules/postcss-nested": {
"version": "6.2.0",
"resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz",
@@ -12772,6 +12647,22 @@
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
}
},
"node_modules/pretty-ms": {
"version": "9.2.0",
"resolved": "https://registry.npmjs.org/pretty-ms/-/pretty-ms-9.2.0.tgz",
"integrity": "sha512-4yf0QO/sllf/1zbZWYnvWw3NxCQwLXKzIj0G849LSufP15BXKM0rbD2Z3wVnkMfjdn/CB0Dpp444gYAACdsplg==",
"dev": true,
"license": "MIT",
"dependencies": {
"parse-ms": "^4.0.0"
},
"engines": {
"node": ">=18"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/prismjs": {
"version": "1.29.0",
"resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.29.0.tgz",
@@ -14059,6 +13950,19 @@
"node": ">=8"
}
},
"node_modules/smol-toml": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/smol-toml/-/smol-toml-1.3.1.tgz",
"integrity": "sha512-tEYNll18pPKHroYSmLLrksq233j021G0giwW7P3D24jC54pQ5W5BXMsQ/Mvw1OJCmEYDgY+lrzT+3nNUtoNfXQ==",
"dev": true,
"license": "BSD-3-Clause",
"engines": {
"node": ">= 18"
},
"funding": {
"url": "https://github.com/sponsors/cyyynthia"
}
},
"node_modules/snake-case": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/snake-case/-/snake-case-3.0.4.tgz",
@@ -14264,13 +14168,6 @@
"dev": true,
"license": "MIT"
},
"node_modules/string-hash": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/string-hash/-/string-hash-1.1.3.tgz",
"integrity": "sha512-kJUvRUFK49aub+a7T1nNE66EJbZBMnBgoC1UbCZ5n6bsZKBRga4KgBRTMn/pFkeCZSYtNeSyMxPDM0AXWELk2A==",
"dev": true,
"license": "CC0-1.0"
},
"node_modules/string-width": {
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
@@ -14485,6 +14382,13 @@
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/summary": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/summary/-/summary-2.1.0.tgz",
"integrity": "sha512-nMIjMrd5Z2nuB2RZCKJfFMjgS3fygbeyGk9PxPPaJR1RIcyN9yn4A63Isovzm3ZtQuEkLBVgMdPup8UeLH7aQw==",
"dev": true,
"license": "MIT"
},
"node_modules/supports-color": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
@@ -14674,6 +14578,24 @@
"node": ">=10.13.0"
}
},
"node_modules/tailwindcss/node_modules/postcss-import": {
"version": "15.1.0",
"resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz",
"integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==",
"dev": true,
"license": "MIT",
"dependencies": {
"postcss-value-parser": "^4.0.0",
"read-cache": "^1.0.0",
"resolve": "^1.1.7"
},
"engines": {
"node": ">=14.0.0"
},
"peerDependencies": {
"postcss": "^8.0.0"
}
},
"node_modules/tailwindcss/node_modules/postcss-selector-parser": {
"version": "6.1.2",
"resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz",
@@ -14688,6 +14610,16 @@
"node": ">=4"
}
},
"node_modules/tapable": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz",
"integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=6"
}
},
"node_modules/tar-fs": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz",
@@ -15220,6 +15152,7 @@
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.2.tgz",
"integrity": "sha512-i5t66RHxDvVN40HfDd1PsEThGNnlMCMT3jMUuoh9/0TaqWevNontacunWyN02LA9/fIbEWlcHZcgTKb9QoaLfg==",
"devOptional": true,
"license": "Apache-2.0",
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
@@ -16493,12 +16426,6 @@
"node": ">=8"
}
},
"node_modules/wonka": {
"version": "6.3.4",
"resolved": "https://registry.npmjs.org/wonka/-/wonka-6.3.4.tgz",
"integrity": "sha512-CjpbqNtBGNAeyNS/9W6q3kSkKE52+FjIj7AkFlLr11s/VWGUu6a2CdYSdGxocIhIVjaW/zchesBQUKPVU69Cqg==",
"license": "MIT"
},
"node_modules/wrap-ansi": {
"version": "6.2.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz",
@@ -16692,6 +16619,19 @@
"funding": {
"url": "https://github.com/sponsors/colinhacks"
}
},
"node_modules/zod-validation-error": {
"version": "3.4.0",
"resolved": "https://registry.npmjs.org/zod-validation-error/-/zod-validation-error-3.4.0.tgz",
"integrity": "sha512-ZOPR9SVY6Pb2qqO5XHt+MkkTRxGXb4EVtnjc9JpXUOtUB1T9Ru7mZOT361AN3MsetVe7R0a1KZshJDZdgp9miQ==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=18.0.0"
},
"peerDependencies": {
"zod": "^3.18.0"
}
}
}
}

View File

@@ -14,7 +14,8 @@
"coverage": "vitest run --coverage",
"storybook": "storybook dev -p 6006",
"build-storybook": "storybook build",
"i18n": "i18next"
"i18n": "i18next",
"knip": "knip"
},
"dependencies": {
"@fontsource/inconsolata": "^5.1.1",
@@ -24,10 +25,6 @@
"@tanstack/react-query": "^5.62.15",
"@tanstack/react-router": "^1.95.1",
"@tanstack/router-zod-adapter": "^1.81.5",
"@urql/core": "^5.0.8",
"@urql/devtools": "^2.0.3",
"@urql/exchange-refocus": "^1.1.0",
"@urql/exchange-request-policy": "^1.2.0",
"@vector-im/compound-design-tokens": "2.1.3",
"@vector-im/compound-web": "^7.3.0",
"@zxcvbn-ts/core": "^3.0.4",
@@ -48,11 +45,9 @@
"@browser-logos/firefox": "^3.0.10",
"@browser-logos/safari": "^2.1.0",
"@codecov/vite-plugin": "^1.4.0",
"@graphql-codegen/add": "^5.0.3",
"@graphql-codegen/cli": "^5.0.3",
"@graphql-codegen/client-preset": "^4.5.1",
"@graphql-codegen/typescript-msw": "^3.0.0",
"@graphql-codegen/urql-introspection": "^3.0.0",
"@storybook/addon-essentials": "^8.4.7",
"@storybook/addon-interactions": "^8.4.7",
"@storybook/react": "^8.4.7",
@@ -63,10 +58,10 @@
"@tanstack/router-vite-plugin": "^1.95.1",
"@testing-library/jest-dom": "^6.6.3",
"@testing-library/react": "^16.0.1",
"@testing-library/user-event": "^14.5.2",
"@types/node": "^22.10.5",
"@types/react": "^18.3.12",
"@types/react-dom": "^18.3.1",
"@types/react-test-renderer": "^19.0.0",
"@types/swagger-ui-react": "^4.18.3",
"@vitejs/plugin-react": "^4.3.3",
"@vitest/coverage-v8": "^2.1.8",
@@ -75,16 +70,17 @@
"graphql": "^16.9.0",
"happy-dom": "^15.11.4",
"i18next-parser": "^9.1.0",
"knip": "^5.41.1",
"msw": "^2.6.5",
"msw-storybook-addon": "^2.0.4",
"postcss": "^8.4.49",
"postcss-modules": "^6.0.1",
"postcss-import": "^16.1.0",
"postcss-nesting": "^13.0.1",
"rimraf": "^6.0.1",
"storybook": "^8.4.4",
"storybook-react-i18next": "^3.1.8",
"tailwindcss": "^3.4.17",
"typescript": "5.7.2",
"typescript": "^5.7.2",
"vite": "5.4.11",
"vite-plugin-compression": "^0.5.1",
"vite-plugin-graphql-codegen": "^3.3.8",

View File

@@ -1,19 +0,0 @@
// Copyright 2024 New Vector Ltd.
// Copyright 2023, 2024 The Matrix.org Foundation C.I.C.
//
// SPDX-License-Identifier: AGPL-3.0-only
// Please see LICENSE in the repository root for full details.
import { Alert } from "@vector-im/compound-web";
import type { ReactNode } from "react";
import { Translation } from "react-i18next";
const NotLoggedIn: React.FC = () => (
<Translation>
{(t): ReactNode => (
<Alert type="critical" title={t("frontend.not_logged_in_alert")} />
)}
</Translation>
);
export default NotLoggedIn;

View File

@@ -20,7 +20,9 @@ const CONFIG_FRAGMENT = graphql(/* GraphQL */ `
// This will load the password complexity module lazily,
// so that it doesn't block the initial render and can be code-split
const loadPromise = import("../utils/password_complexity");
const loadPromise = import("../utils/password_complexity").then(
({ estimatePasswordComplexity }) => estimatePasswordComplexity,
);
const usePasswordComplexity = (password: string): PasswordComplexity => {
const { t } = useTranslation();
@@ -40,7 +42,7 @@ const usePasswordComplexity = (password: string): PasswordComplexity => {
});
} else {
loadPromise
.then(({ estimatePasswordComplexity }) =>
.then((estimatePasswordComplexity) =>
estimatePasswordComplexity(deferredPassword, t),
)
.then((response) => setResult(response));

View File

@@ -21,7 +21,7 @@ import { VisualList, VisualListItem } from "../VisualList/VisualList";
import styles from "./SessionDetails.module.css";
export type Detail = { label: string; value: ReactNode };
type Detail = { label: string; value: ReactNode };
type Props = {
title: string | ReactNode;
lastActive?: Date;

View File

@@ -48,31 +48,4 @@ const Typography: React.FC<Props> = ({
return createElement(element, { className }, ...Children.toArray(children));
};
type SimpleProps = { children: React.ReactNode };
export const Bold: React.FC<SimpleProps> = ({ children }) => (
<strong className="font-semibold">{children}</strong>
);
export const Code: React.FC<SimpleProps> = ({ children }) => (
<code className="font-mono text-sm">{children}</code>
);
export const Title: React.FC<SimpleProps> = ({ children }) => (
<Typography variant="title">{children}</Typography>
);
export const Subtitle: React.FC<SimpleProps> = ({ children }) => (
<Typography variant="subtitle">{children}</Typography>
);
export const Body: React.FC<{
children: React.ReactNode;
justified?: boolean;
}> = ({ children, justified }) => (
<Typography variant="body" justified={justified}>
{children}
</Typography>
);
export default Typography;

View File

@@ -49,7 +49,7 @@ const QUERY = graphql(/* GraphQL */ `
}
`);
export const FRAGMENT = graphql(/* GraphQL */ `
const FRAGMENT = graphql(/* GraphQL */ `
fragment UserEmailList_user on User {
id
primaryEmail {

View File

@@ -4,7 +4,7 @@
// SPDX-License-Identifier: AGPL-3.0-only
// Please see LICENSE in the repository root for full details.
export type AppConfig = {
type AppConfig = {
root: string;
graphqlEndpoint: string;
};

View File

@@ -16,7 +16,7 @@ type PageInfo = {
};
export const FIRST_PAGE = Symbol("FIRST_PAGE");
export const LAST_PAGE = Symbol("LAST_PAGE");
const LAST_PAGE = Symbol("LAST_PAGE");
export const anyPaginationSchema = z.object({
first: z.number().nullish(),
@@ -25,7 +25,7 @@ export const anyPaginationSchema = z.object({
before: z.string().nullish(),
});
export const forwardPaginationSchema = z.object({
const forwardPaginationSchema = z.object({
first: z.number(),
after: z.string().nullish(),
});
@@ -46,20 +46,20 @@ export type Pagination = z.infer<typeof paginationSchema>;
export type AnyPagination = z.infer<typeof anyPaginationSchema>;
// Check if the pagination is a valid pagination
export const isValidPagination = (
const isValidPagination = (
pagination: AnyPagination,
): pagination is Pagination =>
typeof pagination.first === "number" || typeof pagination.last === "number";
// Check if the pagination is forward pagination.
export const isForwardPagination = (
const isForwardPagination = (
pagination: Pagination,
): pagination is ForwardPagination => {
return Object.hasOwn(pagination, "first");
};
// Check if the pagination is backward pagination.
export const isBackwardPagination = (
const isBackwardPagination = (
pagination: Pagination,
): pagination is BackwardPagination => {
return Object.hasOwn(pagination, "last");

View File

@@ -1,64 +0,0 @@
// Copyright 2024 New Vector Ltd.
// Copyright 2023, 2024 The Matrix.org Foundation C.I.C.
//
// SPDX-License-Identifier: AGPL-3.0-only
// Please see LICENSE in the repository root for full details.
const RESULT = Symbol("Result");
const ERR = Symbol("Err");
const OK = Symbol("Ok");
/**
* An `Ok` is a type that represents a successful result.
*/
export type Ok<T> = {
[RESULT]: typeof OK;
[OK]: T;
};
/**
* An `Err` is a type that represents an error.
*/
export type Err<E> = {
[RESULT]: typeof ERR;
[ERR]: E;
};
/**
* A `Result` is a type that represents either an `Ok` or an `Err`.
*/
export type Result<T, E> = Ok<T> | Err<E>;
// Construct an `Ok`
export const ok = <T>(data: T): Ok<T> => ({ [RESULT]: OK, [OK]: data });
// Construct an `Err`
export const err = <E>(error: E): Err<E> => ({
[RESULT]: ERR,
[ERR]: error,
});
// Check if a `Result` is an `Ok`
export const isOk = <T, E>(result: Result<T, E>): result is Ok<T> =>
result[RESULT] === OK;
// Check if a `Result` is an `Err`
export const isErr = <T, E>(result: Result<T, E>): result is Err<E> =>
result[RESULT] === ERR;
// Extract the data from an `Ok`
export const unwrapOk = <T>(result: Ok<T>): T => result[OK];
// Extract the error from an `Err`
export const unwrapErr = <E>(result: Err<E>): E => result[ERR];
/**
* Check result for error and throw unwrapped error
* Otherwise return unwrapped Ok result
*/
export const unwrap = <T, E>(result: Result<T, E>): T => {
if (isErr(result)) {
throw unwrapErr(result);
}
return unwrapOk(result);
};