Skip to content

Commit ed67b8c

Browse files
committed
Enhance error handling across package Wiki routes with user-facing error mapping and improved loader functions
1 parent 5ac0d36 commit ed67b8c

File tree

6 files changed

+434
-376
lines changed

6 files changed

+434
-376
lines changed

apps/cyberstorm-remix/app/p/tabs/Wiki/Wiki.tsx

Lines changed: 67 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import {
99
Await,
1010
type LoaderFunctionArgs,
1111
Outlet,
12+
useLoaderData,
1213
useOutletContext,
1314
} from "react-router";
1415
import { useLoaderData } from "react-router";
@@ -17,79 +18,96 @@ import { type OutletContextShape } from "~/root";
1718
import { NewButton, NewIcon, SkeletonBox } from "@thunderstore/cyberstorm";
1819
import { DapperTs } from "@thunderstore/dapper-ts";
1920
import { getPackageWiki } from "@thunderstore/dapper-ts/src/methods/package";
21+
import { NewButton, NewIcon, SkeletonBox } from "@thunderstore/cyberstorm";
22+
import { faPlus } from "@fortawesome/pro-solid-svg-icons";
23+
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
24+
import { type OutletContextShape } from "~/root";
25+
import { Suspense } from "react";
26+
import { handleLoaderError } from "cyberstorm/utils/errors/handleLoaderError";
27+
import { createNotFoundMapping } from "cyberstorm/utils/errors/loaderMappings";
28+
import {
29+
NimbusAwaitErrorElement,
30+
NimbusDefaultRouteErrorBoundary,
31+
} from "cyberstorm/utils/errors/NimbusErrorBoundary";
32+
import { throwUserFacingPayloadResponse } from "cyberstorm/utils/errors/userFacingErrorResponse";
33+
import { getLoaderTools } from "cyberstorm/utils/getLoaderTools";
34+
35+
export const wikiErrorMappings = [
36+
createNotFoundMapping(
37+
"Wiki not available.",
38+
"We could not find the requested wiki."
39+
),
40+
];
2041

2142
import { ApiError } from "../../../../../../packages/thunderstore-api/src";
2243
import "./Wiki.css";
2344

2445
export async function loader({ params }: LoaderFunctionArgs) {
2546
if (params.communityId && params.namespaceId && params.packageId) {
26-
const publicEnvVariables = getPublicEnvVariables(["VITE_API_URL"]);
27-
const dapper = new DapperTs(() => {
47+
const { dapper } = getLoaderTools();
48+
try {
49+
const wiki = await dapper.getPackageWiki(
50+
params.namespaceId,
51+
params.packageId
52+
);
53+
2854
return {
29-
apiHost: publicEnvVariables.VITE_API_URL,
30-
sessionId: undefined,
55+
wiki,
56+
communityId: params.communityId,
57+
namespaceId: params.namespaceId,
58+
packageId: params.packageId,
59+
slug: params.slug,
60+
permissions: undefined,
3161
};
32-
});
33-
34-
let wiki: Awaited<ReturnType<typeof getPackageWiki>> | undefined;
35-
36-
try {
37-
wiki = await dapper.getPackageWiki(params.namespaceId, params.packageId);
3862
} catch (error) {
39-
if (error instanceof ApiError) {
40-
if (error.response.status === 404) {
41-
wiki = undefined;
42-
} else {
43-
wiki = undefined;
44-
console.error("Error fetching package wiki:", error);
45-
}
46-
}
63+
handleLoaderError(error, { mappings: wikiErrorMappings });
4764
}
48-
49-
return {
50-
wiki: wiki,
51-
communityId: params.communityId,
52-
namespaceId: params.namespaceId,
53-
packageId: params.packageId,
54-
slug: params.slug,
55-
permissions: undefined,
56-
};
5765
} else {
58-
throw new Error("Namespace ID or Package ID is missing");
66+
throwUserFacingPayloadResponse({
67+
headline: "Wiki not available.",
68+
description: "We could not find the requested wiki.",
69+
category: "not_found",
70+
status: 404,
71+
});
5972
}
6073
}
6174

6275
export async function clientLoader({ params }: LoaderFunctionArgs) {
6376
if (params.communityId && params.namespaceId && params.packageId) {
64-
const tools = getSessionTools();
65-
const dapper = new DapperTs(() => {
66-
return {
67-
apiHost: tools?.getConfig().apiHost,
68-
sessionId: tools?.getConfig().sessionId,
69-
};
70-
});
77+
const { dapper } = getLoaderTools();
7178

72-
const wiki = dapper.getPackageWiki(params.namespaceId, params.packageId);
79+
const wikiPromise = dapper.getPackageWiki(
80+
params.namespaceId,
81+
params.packageId
82+
);
7383

74-
const permissions = dapper.getPackagePermissions(
84+
const permissionsPromise = dapper.getPackagePermissions(
7585
params.communityId,
7686
params.namespaceId,
7787
params.packageId
7888
);
7989

8090
return {
81-
wiki: wiki,
91+
wiki: wikiPromise,
8292
communityId: params.communityId,
8393
namespaceId: params.namespaceId,
8494
packageId: params.packageId,
8595
slug: params.slug,
86-
permissions: permissions,
96+
permissions: permissionsPromise,
8797
};
8898
} else {
89-
throw new Error("Namespace ID or Package ID is missing");
99+
throwUserFacingPayloadResponse({
100+
headline: "Wiki not available.",
101+
description: "We could not find the requested wiki.",
102+
category: "not_found",
103+
status: 404,
104+
});
90105
}
91106
}
92107

108+
/**
109+
* Displays the package wiki navigation and nested routes, relying on Suspense for data.
110+
*/
93111
export default function Wiki() {
94112
const { wiki, communityId, namespaceId, packageId, slug, permissions } =
95113
useLoaderData<typeof loader | typeof clientLoader>();
@@ -100,7 +118,10 @@ export default function Wiki() {
100118
<div className="package-wiki">
101119
<div className="package-wiki-nav">
102120
<Suspense>
103-
<Await resolve={permissions}>
121+
<Await
122+
resolve={permissions}
123+
errorElement={<NimbusAwaitErrorElement />}
124+
>
104125
{(resolvedValue) =>
105126
resolvedValue?.permissions.can_manage ? (
106127
<div className="package-wiki-nav__header">
@@ -126,7 +147,7 @@ export default function Wiki() {
126147
<Suspense
127148
fallback={<SkeletonBox className="package-wiki-nav__skeleton" />}
128149
>
129-
<Await resolve={wiki} errorElement={<></>}>
150+
<Await resolve={wiki} errorElement={<NimbusAwaitErrorElement />}>
130151
{(resolvedValue) =>
131152
resolvedValue &&
132153
resolvedValue.pages.map((page, index) => {
@@ -194,3 +215,7 @@ export default function Wiki() {
194215
</div>
195216
);
196217
}
218+
219+
export function ErrorBoundary() {
220+
return <NimbusDefaultRouteErrorBoundary />;
221+
}

apps/cyberstorm-remix/app/p/tabs/Wiki/WikiContent.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import { Heading, NewButton, NewIcon } from "@thunderstore/cyberstorm";
1313
import { type PackageWikiPageResponseData } from "@thunderstore/thunderstore-api";
1414

1515
import "./Wiki.css";
16+
import { NimbusAwaitErrorElement } from "cyberstorm/utils/errors/NimbusErrorBoundary";
1617

1718
interface WikiContentProps {
1819
page: PackageWikiPageResponseData;
@@ -51,7 +52,7 @@ export const WikiContent = memo(function WikiContent({
5152
</div>
5253
</div>
5354
<Suspense>
54-
<Await resolve={canManage}>
55+
<Await resolve={canManage} errorElement={<NimbusAwaitErrorElement />}>
5556
{(resolvedValue) =>
5657
resolvedValue ? (
5758
<div className="package-wiki-content__actions">

0 commit comments

Comments
 (0)