From 0fd594002ed5d3700b8a0a2012604d2c380c618e Mon Sep 17 00:00:00 2001 From: Oksamies Date: Wed, 19 Nov 2025 14:27:49 +0200 Subject: [PATCH] Enhance error handling in all package required routes --- .../tabs/Required/PackageVersionRequired.tsx | 96 +++++++----- ...PackageVersionWithoutCommunityRequired.tsx | 96 +++++++----- .../app/p/tabs/Required/Required.tsx | 146 +++++++++++------- 3 files changed, 209 insertions(+), 129 deletions(-) diff --git a/apps/cyberstorm-remix/app/p/tabs/Required/PackageVersionRequired.tsx b/apps/cyberstorm-remix/app/p/tabs/Required/PackageVersionRequired.tsx index 396df1595..aee87cba4 100644 --- a/apps/cyberstorm-remix/app/p/tabs/Required/PackageVersionRequired.tsx +++ b/apps/cyberstorm-remix/app/p/tabs/Required/PackageVersionRequired.tsx @@ -1,71 +1,89 @@ -import { - getPublicEnvVariables, - getSessionTools, -} from "cyberstorm/security/publicEnvVariables"; +import { NimbusDefaultRouteErrorBoundary } from "cyberstorm/utils/errors/NimbusErrorBoundary"; +import { handleLoaderError } from "cyberstorm/utils/errors/handleLoaderError"; +import { throwUserFacingPayloadResponse } from "cyberstorm/utils/errors/userFacingErrorResponse"; +import { getLoaderTools } from "cyberstorm/utils/getLoaderTools"; +import { parseIntegerSearchParam } from "cyberstorm/utils/searchParamsUtils"; import { Suspense } from "react"; import { type LoaderFunctionArgs } from "react-router"; import { Await, useLoaderData } from "react-router"; import { PaginatedDependencies } from "~/commonComponents/PaginatedDependencies/PaginatedDependencies"; import { SkeletonBox } from "@thunderstore/cyberstorm"; -import { DapperTs } from "@thunderstore/dapper-ts"; + +import { packageDependenciesErrorMappings } from "./Required"; export async function loader({ params, request }: LoaderFunctionArgs) { if (params.namespaceId && params.packageId && params.packageVersion) { - const publicEnvVariables = getPublicEnvVariables(["VITE_API_URL"]); - const dapper = new DapperTs(() => { - return { - apiHost: publicEnvVariables.VITE_API_URL, - sessionId: undefined, - }; - }); + const { dapper } = getLoaderTools(); const searchParams = new URL(request.url).searchParams; - const page = searchParams.get("page"); + const page = parseIntegerSearchParam(searchParams.get("page")); - return { - version: await dapper.getPackageVersionDetails( + try { + const version = await dapper.getPackageVersionDetails( params.namespaceId, params.packageId, params.packageVersion - ), - dependencies: await dapper.getPackageVersionDependencies( + ); + const dependencies = await dapper.getPackageVersionDependencies( params.namespaceId, params.packageId, params.packageVersion, - page === null ? undefined : Number(page) - ), - }; + page + ); + + return { + version, + dependencies, + }; + } catch (error) { + handleLoaderError(error, { mappings: packageDependenciesErrorMappings }); + } } - throw new Response("Package version dependencies not found", { status: 404 }); + throwUserFacingPayloadResponse({ + headline: "Dependencies not found.", + description: "We could not find the requested version dependencies.", + category: "not_found", + status: 404, + }); } -export async function clientLoader({ params, request }: LoaderFunctionArgs) { +export function clientLoader({ params, request }: LoaderFunctionArgs) { if (params.namespaceId && params.packageId && params.packageVersion) { - const tools = getSessionTools(); - const dapper = new DapperTs(() => { - return { - apiHost: tools?.getConfig().apiHost, - sessionId: tools?.getConfig().sessionId, - }; - }); + const { dapper } = getLoaderTools(); const searchParams = new URL(request.url).searchParams; - const page = searchParams.get("page"); + const page = parseIntegerSearchParam(searchParams.get("page")); - return { - version: dapper.getPackageVersionDetails( + const version = dapper + .getPackageVersionDetails( params.namespaceId, params.packageId, params.packageVersion - ), - dependencies: dapper.getPackageVersionDependencies( + ) + .catch((error) => + handleLoaderError(error, { mappings: packageDependenciesErrorMappings }) + ); + const dependencies = dapper + .getPackageVersionDependencies( params.namespaceId, params.packageId, params.packageVersion, - page === null ? undefined : Number(page) - ), + page + ) + .catch((error) => + handleLoaderError(error, { mappings: packageDependenciesErrorMappings }) + ); + + return { + version, + dependencies, }; } - throw new Response("Package version dependencies not found", { status: 404 }); + throwUserFacingPayloadResponse({ + headline: "Dependencies not found.", + description: "We could not find the requested version dependencies.", + category: "not_found", + status: 404, + }); } export default function PackageVersionRequired() { @@ -88,3 +106,7 @@ export default function PackageVersionRequired() { ); } + +export function ErrorBoundary() { + return ; +} diff --git a/apps/cyberstorm-remix/app/p/tabs/Required/PackageVersionWithoutCommunityRequired.tsx b/apps/cyberstorm-remix/app/p/tabs/Required/PackageVersionWithoutCommunityRequired.tsx index b7c50ce3a..c14cdb2b1 100644 --- a/apps/cyberstorm-remix/app/p/tabs/Required/PackageVersionWithoutCommunityRequired.tsx +++ b/apps/cyberstorm-remix/app/p/tabs/Required/PackageVersionWithoutCommunityRequired.tsx @@ -1,71 +1,89 @@ -import { - getPublicEnvVariables, - getSessionTools, -} from "cyberstorm/security/publicEnvVariables"; +import { NimbusDefaultRouteErrorBoundary } from "cyberstorm/utils/errors/NimbusErrorBoundary"; +import { handleLoaderError } from "cyberstorm/utils/errors/handleLoaderError"; +import { throwUserFacingPayloadResponse } from "cyberstorm/utils/errors/userFacingErrorResponse"; +import { getLoaderTools } from "cyberstorm/utils/getLoaderTools"; +import { parseIntegerSearchParam } from "cyberstorm/utils/searchParamsUtils"; import { Suspense } from "react"; import { type LoaderFunctionArgs } from "react-router"; import { Await, useLoaderData } from "react-router"; import { PaginatedDependencies } from "~/commonComponents/PaginatedDependencies/PaginatedDependencies"; import { SkeletonBox } from "@thunderstore/cyberstorm"; -import { DapperTs } from "@thunderstore/dapper-ts"; + +import { packageDependenciesErrorMappings } from "./Required"; export async function loader({ params, request }: LoaderFunctionArgs) { if (params.namespaceId && params.packageId && params.packageVersion) { - const publicEnvVariables = getPublicEnvVariables(["VITE_API_URL"]); - const dapper = new DapperTs(() => { - return { - apiHost: publicEnvVariables.VITE_API_URL, - sessionId: undefined, - }; - }); + const { dapper } = getLoaderTools(); const searchParams = new URL(request.url).searchParams; - const page = searchParams.get("page"); + const page = parseIntegerSearchParam(searchParams.get("page")); - return { - version: await dapper.getPackageVersionDetails( + try { + const version = await dapper.getPackageVersionDetails( params.namespaceId, params.packageId, params.packageVersion - ), - dependencies: await dapper.getPackageVersionDependencies( + ); + const dependencies = await dapper.getPackageVersionDependencies( params.namespaceId, params.packageId, params.packageVersion, - page === null ? undefined : Number(page) - ), - }; + page + ); + + return { + version, + dependencies, + }; + } catch (error) { + handleLoaderError(error, { mappings: packageDependenciesErrorMappings }); + } } - throw new Response("Package version dependencies not found", { status: 404 }); + throwUserFacingPayloadResponse({ + headline: "Dependencies not found.", + description: "We could not find the requested version dependencies.", + category: "not_found", + status: 404, + }); } -export async function clientLoader({ params, request }: LoaderFunctionArgs) { +export function clientLoader({ params, request }: LoaderFunctionArgs) { if (params.namespaceId && params.packageId && params.packageVersion) { - const tools = getSessionTools(); - const dapper = new DapperTs(() => { - return { - apiHost: tools?.getConfig().apiHost, - sessionId: tools?.getConfig().sessionId, - }; - }); + const { dapper } = getLoaderTools(); const searchParams = new URL(request.url).searchParams; - const page = searchParams.get("page"); + const page = parseIntegerSearchParam(searchParams.get("page")); - return { - version: dapper.getPackageVersionDetails( + const version = dapper + .getPackageVersionDetails( params.namespaceId, params.packageId, params.packageVersion - ), - dependencies: dapper.getPackageVersionDependencies( + ) + .catch((error) => + handleLoaderError(error, { mappings: packageDependenciesErrorMappings }) + ); + const dependencies = dapper + .getPackageVersionDependencies( params.namespaceId, params.packageId, params.packageVersion, - page === null ? undefined : Number(page) - ), + page + ) + .catch((error) => + handleLoaderError(error, { mappings: packageDependenciesErrorMappings }) + ); + + return { + version, + dependencies, }; } - throw new Response("Package version dependencies not found", { status: 404 }); + throwUserFacingPayloadResponse({ + headline: "Dependencies not found.", + description: "We could not find the requested version dependencies.", + category: "not_found", + status: 404, + }); } export default function PackageVersionWithoutCommunityRequired() { @@ -88,3 +106,7 @@ export default function PackageVersionWithoutCommunityRequired() { ); } + +export function ErrorBoundary() { + return ; +} diff --git a/apps/cyberstorm-remix/app/p/tabs/Required/Required.tsx b/apps/cyberstorm-remix/app/p/tabs/Required/Required.tsx index 2ab6b9bc3..6a0e57762 100644 --- a/apps/cyberstorm-remix/app/p/tabs/Required/Required.tsx +++ b/apps/cyberstorm-remix/app/p/tabs/Required/Required.tsx @@ -1,81 +1,113 @@ -import { - getPublicEnvVariables, - getSessionTools, -} from "cyberstorm/security/publicEnvVariables"; import { Suspense } from "react"; -import { type LoaderFunctionArgs } from "react-router"; -import { Await, useLoaderData } from "react-router"; +import { Await, type LoaderFunctionArgs } from "react-router"; +import { useLoaderData } from "react-router"; import { PaginatedDependencies } from "~/commonComponents/PaginatedDependencies/PaginatedDependencies"; - +import { throwUserFacingPayloadResponse } from "cyberstorm/utils/errors/userFacingErrorResponse"; +import { handleLoaderError } from "cyberstorm/utils/errors/handleLoaderError"; +import { createNotFoundMapping } from "cyberstorm/utils/errors/loaderMappings"; +import { NimbusDefaultRouteErrorBoundary } from "cyberstorm/utils/errors/NimbusErrorBoundary"; +import { getLoaderTools } from "cyberstorm/utils/getLoaderTools"; import { SkeletonBox } from "@thunderstore/cyberstorm"; -import { DapperTs } from "@thunderstore/dapper-ts"; +import { parseIntegerSearchParam } from "cyberstorm/utils/searchParamsUtils"; + +export const packageDependenciesErrorMappings = [ + createNotFoundMapping( + "Dependencies not found.", + "We could not find the requested version dependencies." + ), +]; export async function loader({ params, request }: LoaderFunctionArgs) { if (params.communityId && params.namespaceId && params.packageId) { - const publicEnvVariables = getPublicEnvVariables(["VITE_API_URL"]); - const dapper = new DapperTs(() => { - return { - apiHost: publicEnvVariables.VITE_API_URL, - sessionId: undefined, - }; - }); + const { dapper } = getLoaderTools(); const searchParams = new URL(request.url).searchParams; - const page = searchParams.get("page"); - const listing = await dapper.getPackageListingDetails( - params.communityId, - params.namespaceId, - params.packageId - ); + const page = parseIntegerSearchParam(searchParams.get("page")); + try { + const listing = await dapper.getPackageListingDetails( + params.communityId, + params.namespaceId, + params.packageId + ); - return { - version: await dapper.getPackageVersionDetails( + const version = await dapper.getPackageVersionDetails( params.namespaceId, params.packageId, listing.latest_version_number - ), - dependencies: await dapper.getPackageVersionDependencies( + ); + const dependencies = await dapper.getPackageVersionDependencies( params.namespaceId, params.packageId, listing.latest_version_number, - page === null ? undefined : Number(page) - ), - }; + page + ); + + return { + version, + dependencies, + }; + } catch (error) { + handleLoaderError(error, { mappings: packageDependenciesErrorMappings }); + } } - throw new Response("Package version dependencies not found", { status: 404 }); + throwUserFacingPayloadResponse({ + headline: "Dependencies not found.", + description: "We could not find the requested version dependencies.", + category: "not_found", + status: 404, + }); } -export async function clientLoader({ params, request }: LoaderFunctionArgs) { +export function clientLoader({ params, request }: LoaderFunctionArgs) { if (params.communityId && params.namespaceId && params.packageId) { - const tools = getSessionTools(); - const dapper = new DapperTs(() => { - return { - apiHost: tools?.getConfig().apiHost, - sessionId: tools?.getConfig().sessionId, - }; - }); + const { dapper } = getLoaderTools(); const searchParams = new URL(request.url).searchParams; - const page = searchParams.get("page"); - const listing = await dapper.getPackageListingDetails( - params.communityId, - params.namespaceId, - params.packageId - ); + const page = parseIntegerSearchParam(searchParams.get("page")); + const listingPromise = dapper + .getPackageListingDetails( + params.communityId, + params.namespaceId, + params.packageId + ) + .catch((error) => + handleLoaderError(error, { mappings: packageDependenciesErrorMappings }) + ); + + const version = listingPromise + .then((listing) => + dapper.getPackageVersionDetails( + listing.namespace, + listing.name, + listing.latest_version_number + ) + ) + .catch((error) => + handleLoaderError(error, { mappings: packageDependenciesErrorMappings }) + ); + + const dependencies = listingPromise + .then((listing) => + dapper.getPackageVersionDependencies( + listing.namespace, + listing.name, + listing.latest_version_number, + page + ) + ) + .catch((error) => + handleLoaderError(error, { mappings: packageDependenciesErrorMappings }) + ); return { - version: dapper.getPackageVersionDetails( - params.namespaceId, - params.packageId, - listing.latest_version_number - ), - dependencies: dapper.getPackageVersionDependencies( - params.namespaceId, - params.packageId, - listing.latest_version_number, - page === null ? undefined : Number(page) - ), + version, + dependencies, }; } - throw new Response("Package version dependencies not found", { status: 404 }); + throwUserFacingPayloadResponse({ + headline: "Dependencies not found.", + description: "We could not find the requested version dependencies.", + category: "not_found", + status: 404, + }); } export default function PackageVersionRequired() { @@ -98,3 +130,7 @@ export default function PackageVersionRequired() { ); } + +export function ErrorBoundary() { + return ; +}