From 6ba2132cfe56a3bb781912a5ba133608cfc57ed1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89mile=20R=C3=A9?= Date: Thu, 22 Jan 2026 14:40:12 +0400 Subject: [PATCH] Fix apps/trust lint issues MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Émile Ré --- apps/console/src/routes.tsx | 1 - apps/trust/eslint.config.mjs | 21 +++- apps/trust/src/components/AuditRow.tsx | 76 ++++++------- apps/trust/src/components/DocumentRow.tsx | 76 ++++++------- apps/trust/src/components/NDADialog.tsx | 10 +- .../src/components/OrganizationSidebar.tsx | 68 ++++++------ apps/trust/src/components/PDFPreview.tsx | 11 +- apps/trust/src/components/PageError.tsx | 20 ++-- .../src/components/TrustCenterFileRow.tsx | 76 ++++++------- apps/trust/src/components/VendorRow.tsx | 50 +++++---- apps/trust/src/hooks/useMutationWithToast.ts | 14 +-- apps/trust/src/layouts/MainLayout.tsx | 12 ++- apps/trust/src/main.tsx | 2 +- apps/trust/src/pages/DocumentsPage.tsx | 20 ++-- apps/trust/src/pages/OverviewPage.tsx | 24 ++--- apps/trust/src/pages/SubprocessorsPage.tsx | 8 +- apps/trust/src/pages/auth/ConnectPage.tsx | 5 +- .../src/pages/auth/ConnectPageLoader.tsx | 4 +- .../src/pages/auth/VerifyMagicLinkPage.tsx | 6 +- apps/trust/src/providers/RelayProviders.tsx | 102 +----------------- apps/trust/src/routes.tsx | 5 +- apps/trust/src/types.ts | 8 +- apps/trust/tsconfig.node.json | 3 +- 23 files changed, 283 insertions(+), 339 deletions(-) diff --git a/apps/console/src/routes.tsx b/apps/console/src/routes.tsx index 24e505402..a011e1d88 100644 --- a/apps/console/src/routes.tsx +++ b/apps/console/src/routes.tsx @@ -153,7 +153,6 @@ const routes = [ children: [ { index: true, - // Component: () => "hello world", Component: lazy( () => import("./pages/organizations/employee/EmployeeDocumentsPageLoader"), diff --git a/apps/trust/eslint.config.mjs b/apps/trust/eslint.config.mjs index a6d6cf395..8e6a879b2 100644 --- a/apps/trust/eslint.config.mjs +++ b/apps/trust/eslint.config.mjs @@ -1,6 +1,17 @@ -import { browser } from "@probo/eslint-config"; +import { defineConfig } from "eslint/config"; +import { configs } from "@probo/eslint-config"; -export default [ - { ignores: ["dist", "eslint.config.mjs", "*.config.{js,mjs,ts}"] }, - ...browser(["./tsconfig.app.json", "./tsconfig.node.json"], import.meta.dirname), -]; +export default defineConfig([ + ...configs.base, + ...configs.ts, + ...configs.react, + configs.languageOptions.browser, + ...configs.stylistic, + { + languageOptions: { + parserOptions: { + tsConfigRootDir: import.meta.dirname, + }, + }, + }, +]); diff --git a/apps/trust/src/components/AuditRow.tsx b/apps/trust/src/components/AuditRow.tsx index 4e436cae6..8e61572ec 100644 --- a/apps/trust/src/components/AuditRow.tsx +++ b/apps/trust/src/components/AuditRow.tsx @@ -68,10 +68,10 @@ export function AuditRow(props: { audit: AuditRowFragment$key }) { audit.report?.hasUserRequestedAccess, ); - const [requestAccess, isRequestingAccess] = - useMutation(requestAccessMutation); - const [commitDownload, downloading] = - useMutationWithToasts(downloadMutation); + const [requestAccess, isRequestingAccess] + = useMutation(requestAccessMutation); + const [commitDownload, downloading] + = useMutationWithToasts(downloadMutation); const handleRequestAccess = () => { requestAccess({ @@ -106,11 +106,11 @@ export function AuditRow(props: { audit: AuditRowFragment$key }) { }); }; - const handleDownload = () => { + const handleDownload = async () => { if (!audit.report?.id) { return; } - commitDownload({ + await commitDownload({ variables: { input: { reportId: audit.report.id, @@ -128,36 +128,40 @@ export function AuditRow(props: { audit: AuditRowFragment$key }) { {audit.framework.name} - {audit.report && audit.report.isUserAuthorized ? ( - - ) : viewer ? ( - - ) : ( - - )} + {audit.report && audit.report.isUserAuthorized + ? ( + + ) + : viewer + ? ( + + ) + : ( + + )} ); } diff --git a/apps/trust/src/components/DocumentRow.tsx b/apps/trust/src/components/DocumentRow.tsx index a4d69ccda..b35448d7e 100644 --- a/apps/trust/src/components/DocumentRow.tsx +++ b/apps/trust/src/components/DocumentRow.tsx @@ -56,10 +56,10 @@ export function DocumentRow(props: { document: DocumentRowFragment$key }) { document.hasUserRequestedAccess, ); - const [requestAccess, isRequestingAccess] = - useMutation(requestAccessMutation); - const [commitDownload, downloading] = - useMutationWithToasts(downloadMutation); + const [requestAccess, isRequestingAccess] + = useMutation(requestAccessMutation); + const [commitDownload, downloading] + = useMutationWithToasts(downloadMutation); const handleRequestAccess = () => { requestAccess({ @@ -94,8 +94,8 @@ export function DocumentRow(props: { document: DocumentRowFragment$key }) { }); }; - const handleDownload = () => { - commitDownload({ + const handleDownload = async () => { + await commitDownload({ variables: { input: { documentId: document.id, @@ -113,36 +113,40 @@ export function DocumentRow(props: { document: DocumentRowFragment$key }) { {document.title} - {document.isUserAuthorized ? ( - - ) : viewer ? ( - - ) : ( - - )} + {document.isUserAuthorized + ? ( + + ) + : viewer + ? ( + + ) + : ( + + )} ); } diff --git a/apps/trust/src/components/NDADialog.tsx b/apps/trust/src/components/NDADialog.tsx index d6259cf46..2d3cfff76 100644 --- a/apps/trust/src/components/NDADialog.tsx +++ b/apps/trust/src/components/NDADialog.tsx @@ -60,8 +60,8 @@ export function NDADialog({ }, }); - const handleSubmit = handleSubmitWrapper(({ fullName }) => { - commitSigning({ + const handleSubmit = handleSubmitWrapper(async ({ fullName }) => { + await commitSigning({ variables: { input: { fullName, @@ -98,7 +98,7 @@ export function NDADialog({ )} -
+ void handleSubmit(e)}>
- Powered by + Powered by + {" "} +
{isDesktop && ( diff --git a/apps/trust/src/components/OrganizationSidebar.tsx b/apps/trust/src/components/OrganizationSidebar.tsx index 0bedfa684..11da95967 100644 --- a/apps/trust/src/components/OrganizationSidebar.tsx +++ b/apps/trust/src/components/OrganizationSidebar.tsx @@ -35,8 +35,8 @@ export function OrganizationSidebar({ const isAuthenticated = !!use(Viewer); const { toast } = useToast(); - const [requestAllAccesses, isRequestingAccess] = - useMutation( + const [requestAllAccesses, isRequestingAccess] + = useMutation( requestAllAccessesMutation, ); @@ -75,15 +75,17 @@ export function OrganizationSidebar({ return (
- {trustCenter.organization.logoUrl ? ( - - ) : ( -
- )} + {trustCenter.organization.logoUrl + ? ( + + ) + : ( +
+ )}

{trustCenter.organization.name}

{trustCenter.organization.description} @@ -137,7 +139,7 @@ export function OrganizationSidebar({ gridTemplateColumns: "repeat(auto-fit, 75px", }} > - {trustCenter.audits.edges.map((audit) => ( + {trustCenter.audits.edges.map(audit => ( ))}

@@ -148,26 +150,28 @@ export function OrganizationSidebar({ )} {/* Actions */} - {isAuthenticated ? ( - - ) : ( - - )} + {isAuthenticated + ? ( + + ) + : ( + + )}
); diff --git a/apps/trust/src/components/PDFPreview.tsx b/apps/trust/src/components/PDFPreview.tsx index 572bb2995..ad2ff688c 100644 --- a/apps/trust/src/components/PDFPreview.tsx +++ b/apps/trust/src/components/PDFPreview.tsx @@ -15,8 +15,8 @@ import { IconMinusLarge } from "@probo/ui/src/Atoms/Icons/IconMinusLarge.tsx"; // Worker for PDF.js pdfjs.GlobalWorkerOptions.workerSrc = `//unpkg.com/pdfjs-dist@${pdfjs.version}/build/pdf.worker.min.mjs`; -const btnClass = - "size-8 grid place-items-center hover:bg-secondary-hover cursor-pointer rounded-sm disabled:opacity-30 transition-all"; +const btnClass + = "size-8 grid place-items-center hover:bg-secondary-hover cursor-pointer rounded-sm disabled:opacity-30 transition-all"; export function PDFPreview({ src, name }: { src: string; name?: string }) { const [numPages, setNumPages] = useState(0); @@ -92,7 +92,10 @@ export function PDFPreview({ src, name }: { src: string; name?: string }) {
- {currentPage} / {numPages} + {currentPage} + {" "} + / + {numPages}
- ) : viewer ? ( - - ) : ( - - )} + {file.isUserAuthorized + ? ( + + ) + : viewer + ? ( + + ) + : ( + + )} ); } diff --git a/apps/trust/src/components/VendorRow.tsx b/apps/trust/src/components/VendorRow.tsx index 6598b02c1..adb8a143d 100644 --- a/apps/trust/src/components/VendorRow.tsx +++ b/apps/trust/src/components/VendorRow.tsx @@ -25,35 +25,39 @@ export function VendorRow(props: { vendor: VendorRowFragment$key; hasAnyCountrie return (
- {logo ? ( - - ) : ( -
- )} + {logo + ? ( + + ) + : ( +
+ )}
{vendor.name}
- {vendor.privacyPolicyUrl ? ( - - - {__("Privacy")} - - ) : ( -
- )} + {vendor.privacyPolicyUrl + ? ( + + + {__("Privacy")} + + ) + : ( +
+ )} {vendor.countries.length > 0 && ( -
+
{vendor.countries - .map((country) => getCountryName(__, country)) + .map(country => getCountryName(__, country)) .join(", ")}
diff --git a/apps/trust/src/hooks/useMutationWithToast.ts b/apps/trust/src/hooks/useMutationWithToast.ts index f047a9ad4..6001ae473 100644 --- a/apps/trust/src/hooks/useMutationWithToast.ts +++ b/apps/trust/src/hooks/useMutationWithToast.ts @@ -12,7 +12,7 @@ export function useMutationWithToasts( baseOptions?: { onSuccess?: (response: T["response"]) => void; errorMessage?: string; - } + }, ) { const [mutate, isLoading] = useMutation(query); const { toast } = useToast(); @@ -22,7 +22,7 @@ export function useMutationWithToasts( queryOptions: UseMutationConfig & { onSuccess?: (response: T["response"]) => void; errorMessage?: string; - } + }, ) => { const options = { ...baseOptions, ...queryOptions }; return new Promise((resolve, reject) => @@ -34,11 +34,11 @@ export function useMutationWithToasts( toast({ title: __("Error"), description: - options.errorMessage ?? - __("Failed to commit this operation."), + options.errorMessage + ?? __("Failed to commit this operation."), variant: "error", }); - reject(error); + reject(error instanceof Error ? error : new Error(__("Failed to commit this operation."))); return; } options.onSuccess?.(response); @@ -53,10 +53,10 @@ export function useMutationWithToasts( }); reject(error); }, - }) + }), ); }, - [mutate, toast, __, baseOptions] + [mutate, toast, __, baseOptions], ); return [mutateWithToast, isLoading] as const; diff --git a/apps/trust/src/layouts/MainLayout.tsx b/apps/trust/src/layouts/MainLayout.tsx index 9b73cea64..a35715ca3 100644 --- a/apps/trust/src/layouts/MainLayout.tsx +++ b/apps/trust/src/layouts/MainLayout.tsx @@ -21,10 +21,10 @@ export function MainLayout(props: Props) { if (!trustCenter) { return null; } - const showNDADialog = - trustCenter.isViewerMember && - !trustCenter.hasAcceptedNonDisclosureAgreement && - trustCenter.ndaFileUrl; + const showNDADialog + = trustCenter.isViewerMember + && !trustCenter.hasAcceptedNonDisclosureAgreement + && trustCenter.ndaFileUrl; return ( @@ -51,7 +51,9 @@ export function MainLayout(props: Props) { href="https://www.getprobo.com/" className="flex gap-2 text-sm font-medium text-txt-tertiary items-center w-max mx-auto my-10" > - {__("Powered by")} + {__("Powered by")} + {" "} + diff --git a/apps/trust/src/main.tsx b/apps/trust/src/main.tsx index 099511216..021e50da2 100644 --- a/apps/trust/src/main.tsx +++ b/apps/trust/src/main.tsx @@ -23,5 +23,5 @@ createRoot(document.getElementById("root")!).render( - + , ); diff --git a/apps/trust/src/pages/DocumentsPage.tsx b/apps/trust/src/pages/DocumentsPage.tsx index 719a02d83..357c225df 100644 --- a/apps/trust/src/pages/DocumentsPage.tsx +++ b/apps/trust/src/pages/DocumentsPage.tsx @@ -18,16 +18,16 @@ export function DocumentsPage({ queryRef }: Props) { const { __ } = useTranslate(); const data = usePreloadedQuery( currentTrustDocumentsQuery, - queryRef + queryRef, ); - const documents = - data.currentTrustCenter?.documents.edges.map((edge) => edge.node) ?? []; - const files = - data.currentTrustCenter?.trustCenterFiles.edges.map((edge) => edge.node) ?? []; - const documentsPerType = groupBy(documents, (document) => - documentTypeLabel(document.documentType, __) + const documents + = data.currentTrustCenter?.documents.edges.map(edge => edge.node) ?? []; + const files + = data.currentTrustCenter?.trustCenterFiles.edges.map(edge => edge.node) ?? []; + const documentsPerType = groupBy(documents, document => + documentTypeLabel(document.documentType, __), ); - const filesPerCategory = groupBy(files, (file) => file.category); + const filesPerCategory = groupBy(files, file => file.category); return (

{__("Documents")}

@@ -38,7 +38,7 @@ export function DocumentsPage({ queryRef }: Props) { {objectEntries(documentsPerType).map(([label, documents]) => ( {label} - {documents.map((document) => ( + {documents.map(document => ( ))} @@ -46,7 +46,7 @@ export function DocumentsPage({ queryRef }: Props) { {objectEntries(filesPerCategory).map(([category, files]) => ( {category} - {files.map((file) => ( + {files.map(file => ( ))} diff --git a/apps/trust/src/pages/OverviewPage.tsx b/apps/trust/src/pages/OverviewPage.tsx index 2c1095e79..66941e14e 100644 --- a/apps/trust/src/pages/OverviewPage.tsx +++ b/apps/trust/src/pages/OverviewPage.tsx @@ -67,14 +67,14 @@ const overviewFragment = graphql` export function OverviewPage() { const { trustCenter } = useOutletContext<{ - trustCenter: OverviewPageFragment$key & - TrustGraphCurrentQuery$data["currentTrustCenter"]; + trustCenter: OverviewPageFragment$key + & TrustGraphCurrentQuery$data["currentTrustCenter"]; }>(); const fragment = useFragment(overviewFragment, trustCenter); return (
edge.node)} + references={fragment.references.edges.map(edge => edge.node)} /> edge.node), - (node) => documentTypeLabel(node.documentType, __), + documents.map(edge => edge.node), + node => documentTypeLabel(node.documentType, __), ); const filesPerCategory = groupBy( - files.map((edge) => edge.node), - (node) => node.category, + files.map(edge => edge.node), + node => node.category, ); const hasAudits = audits.length > 0; const hasDocuments = hasAudits || documents.length > 0 || files.length > 0; @@ -130,7 +130,7 @@ function Documents({ {audits.length > 0 && ( <> {__("Compliance")} - {audits.map((audit) => ( + {audits.map(audit => ( ))} @@ -138,7 +138,7 @@ function Documents({ {objectEntries(documentsPerType).map(([label, documents]) => ( {label} - {documents.map((document) => ( + {documents.map(document => ( ))} @@ -146,7 +146,7 @@ function Documents({ {objectEntries(filesPerCategory).map(([category, files]) => ( {category} - {files.map((file) => ( + {files.map(file => ( ))} @@ -189,7 +189,7 @@ function Subprocessors({ )}

- {vendors.map((vendor) => ( + {vendors.map(vendor => (

{__("Trusted by")}

- {references.map((reference) => ( + {references.map(reference => ( edge.node) ?? []; + const vendors + = data.currentTrustCenter?.vendors.edges.map(edge => edge.node) ?? []; const hasAnyCountries = vendors.some(vendor => vendor.countries.length > 0); @@ -24,11 +24,11 @@ export function SubprocessorsPage({ queryRef }: Props) {

{sprintf( __("Third-party subprocessors %s work with:"), - data.currentTrustCenter?.organization.name ?? "" + data.currentTrustCenter?.organization.name ?? "", )}

- {vendors.map((vendor) => ( + {vendors.map(vendor => ( ))} diff --git a/apps/trust/src/pages/auth/ConnectPage.tsx b/apps/trust/src/pages/auth/ConnectPage.tsx index 46b361789..1c06f4b5a 100644 --- a/apps/trust/src/pages/auth/ConnectPage.tsx +++ b/apps/trust/src/pages/auth/ConnectPage.tsx @@ -59,12 +59,11 @@ export function ConnectPage(props: { if (!magicLinkSent && interval.current) { clearInterval(interval.current); interval.current = undefined; - setTimer(timerDurationSeconds); } if (magicLinkSent) { clearInterval(interval.current); interval.current = setInterval(() => { - setTimer((timer) => Math.max(timer - 1, 0)); + setTimer(timer => Math.max(timer - 1, 0)); }, 1000); } @@ -138,7 +137,7 @@ export function ConnectPage(props: {

- + void handleSubmit(e)} className="space-y-4"> (connectPageQuery); + const [queryRef, loadQuery] + = useQueryLoader(connectPageQuery); useEffect(() => { if (!queryRef) { diff --git a/apps/trust/src/pages/auth/VerifyMagicLinkPage.tsx b/apps/trust/src/pages/auth/VerifyMagicLinkPage.tsx index 5646686df..5a86cef5f 100644 --- a/apps/trust/src/pages/auth/VerifyMagicLinkPage.tsx +++ b/apps/trust/src/pages/auth/VerifyMagicLinkPage.tsx @@ -42,7 +42,7 @@ export default function VerifyMagicLinkPagePageMutation() { verifyMagicLinkMutation, ); - const handleSubmit = form.handleSubmit(async (data) => { + const handleSubmit = form.handleSubmit((data) => { verifyMagicLink({ variables: { input: { @@ -79,7 +79,7 @@ export default function VerifyMagicLinkPagePageMutation() { useEffect(() => { if (!submittedRef.current && searchParams.get("token")) { - handleSubmit(); + void handleSubmit(); submittedRef.current = true; } }); @@ -94,7 +94,7 @@ export default function VerifyMagicLinkPagePageMutation() {

- + void handleSubmit(e)} className="space-y-4"> - error.extensions?.code == "UNAUTHENTICATED"; - -const hasInvalidError = (error: GraphQLError) => - error.extensions?.code == "INVALID_REQUEST"; - -const fetchRelay: FetchFunction = async ( - request, - variables, - _, - uploadables, -) => { - const requestInit: RequestInit = { - method: "POST", - credentials: "include", - headers: {}, - }; - - if (uploadables) { - const formData = new FormData(); - formData.append( - "operations", - JSON.stringify({ - operationName: request.name, - query: request.text, - variables: variables, - }), - ); - - const uploadableMap: { - [key: string]: string[]; - } = {}; - - Object.keys(uploadables).forEach((key, index) => { - uploadableMap[index] = [`variables.${key}`]; - }); - - formData.append("map", JSON.stringify(uploadableMap)); - - Object.keys(uploadables).forEach((key, index) => { - formData.append(index.toString(), uploadables[key]); - }); - - requestInit.body = formData; - } else { - // Extract slug from URL if present for slug-based routing - const slugMatch = window.location.pathname.match(/^\/trust\/([^/]+)/); - const slug = slugMatch ? slugMatch[1] : null; - - requestInit.headers = { - Accept: - "application/graphql-response+json; charset=utf-8, application/json; charset=utf-8", - "Content-Type": "application/json", - ...(slug ? { "X-Trust-Slug": slug } : {}), - }; - - requestInit.body = JSON.stringify({ - operationName: request.name, - query: request.text, - variables, - }); - } - - const response = await fetch(buildEndpoint(), requestInit); - - if (response.status === 500) { - throw new InternalServerError(); - } - - const json = await response.json(); - - if (json.errors) { - const errors = json.errors as GraphQLError[]; - - if (errors.find(hasUnauthenticatedError)) { - throw new UnAuthenticatedError(); - } - - const invalidError = errors.find(hasInvalidError); - if (invalidError) { - throw new InvalidError( - invalidError.message, - (invalidError.extensions.field as string) ?? "", - (invalidError.extensions.cause as string) ?? "", - ); - } - - throw new Error(`Error fetching GraphQL query '${request.name}'`); - } - - return json; -}; - const source = new RecordSource(); const store = new Store(source, { queryCacheExpirationTime: 1 * 60 * 1000, @@ -164,7 +70,7 @@ const store = new Store(source, { export const consoleEnvironment = new Environment({ configName: "trust", - network: Network.create(fetchRelay), + network: Network.create(makeFetchQuery(buildEndpoint())), store, }); diff --git a/apps/trust/src/routes.tsx b/apps/trust/src/routes.tsx index 0603b9b99..388986aad 100644 --- a/apps/trust/src/routes.tsx +++ b/apps/trust/src/routes.tsx @@ -27,7 +27,7 @@ import { function ErrorBoundary({ error: propsError }: { error?: string }) { const error = useRouteError() ?? propsError; - return ; + return ; } const routes = [ @@ -41,7 +41,8 @@ const routes = [ }, { path: "/", - loader: async () => { + loader: () => { + // eslint-disable-next-line throw redirect("/overview"); }, Component: Fragment, diff --git a/apps/trust/src/types.ts b/apps/trust/src/types.ts index 583413b93..a6ff58670 100644 --- a/apps/trust/src/types.ts +++ b/apps/trust/src/types.ts @@ -1,7 +1,7 @@ -export type NodeOf = - NonNullable extends - | { readonly edges: ReadonlyArray<{ readonly node: infer U }> } - | undefined +export type NodeOf + = NonNullable extends + | { readonly edges: ReadonlyArray<{ readonly node: infer U }> } + | undefined ? U : never; diff --git a/apps/trust/tsconfig.node.json b/apps/trust/tsconfig.node.json index 9728af2d8..fad570de9 100644 --- a/apps/trust/tsconfig.node.json +++ b/apps/trust/tsconfig.node.json @@ -1,6 +1,7 @@ { "compilerOptions": { "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + "allowJs": true, "target": "ES2022", "lib": ["ES2023"], "module": "ESNext", @@ -21,5 +22,5 @@ "noFallthroughCasesInSwitch": true, "noUncheckedSideEffectImports": true }, - "include": ["vite.config.ts"] + "include": ["vite.config.ts", "eslint.config.mjs"] }