Skip to content

Commit 84ebf1d

Browse files
committed
Enhance error handling across package Wiki routes with user-facing error mapping and improved loader functions
1 parent de2572f commit 84ebf1d

File tree

6 files changed

+435
-429
lines changed

6 files changed

+435
-429
lines changed

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

Lines changed: 61 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,95 +1,100 @@
11
import { faPlus } from "@fortawesome/pro-solid-svg-icons";
22
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
33
import {
4-
getPublicEnvVariables,
5-
getSessionTools,
6-
} from "cyberstorm/security/publicEnvVariables";
4+
NimbusAwaitErrorElement,
5+
NimbusDefaultRouteErrorBoundary,
6+
} from "cyberstorm/utils/errors/NimbusErrorBoundary";
7+
import { handleLoaderError } from "cyberstorm/utils/errors/handleLoaderError";
8+
import { createNotFoundMapping } from "cyberstorm/utils/errors/loaderMappings";
9+
import { throwUserFacingPayloadResponse } from "cyberstorm/utils/errors/userFacingErrorResponse";
10+
import { getLoaderTools } from "cyberstorm/utils/getLoaderTools";
711
import { Suspense } from "react";
812
import {
913
Await,
1014
type LoaderFunctionArgs,
1115
Outlet,
16+
useLoaderData,
1217
useOutletContext,
1318
} from "react-router";
14-
import { useLoaderData } from "react-router";
1519
import { type OutletContextShape } from "~/root";
1620

1721
import { NewButton, NewIcon, SkeletonBox } from "@thunderstore/cyberstorm";
18-
import { DapperTs } from "@thunderstore/dapper-ts";
19-
import { getPackageWiki } from "@thunderstore/dapper-ts";
20-
import { ApiError } from "@thunderstore/thunderstore-api";
2122

2223
import "./Wiki.css";
2324

25+
export const wikiErrorMappings = [
26+
createNotFoundMapping(
27+
"Wiki not available.",
28+
"We could not find the requested wiki."
29+
),
30+
];
31+
2432
export async function loader({ params }: LoaderFunctionArgs) {
2533
if (params.communityId && params.namespaceId && params.packageId) {
26-
const publicEnvVariables = getPublicEnvVariables(["VITE_API_URL"]);
27-
const dapper = new DapperTs(() => {
34+
const { dapper } = getLoaderTools();
35+
try {
36+
const wiki = await dapper.getPackageWiki(
37+
params.namespaceId,
38+
params.packageId
39+
);
40+
2841
return {
29-
apiHost: publicEnvVariables.VITE_API_URL,
30-
sessionId: undefined,
42+
wiki,
43+
communityId: params.communityId,
44+
namespaceId: params.namespaceId,
45+
packageId: params.packageId,
46+
slug: params.slug,
47+
permissions: undefined,
3148
};
32-
});
33-
34-
let wiki: Awaited<ReturnType<typeof getPackageWiki>> | undefined;
35-
36-
try {
37-
wiki = await dapper.getPackageWiki(params.namespaceId, params.packageId);
3849
} 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-
}
50+
handleLoaderError(error, { mappings: wikiErrorMappings });
4751
}
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-
};
5752
} else {
58-
throw new Error("Namespace ID or Package ID is missing");
53+
throwUserFacingPayloadResponse({
54+
headline: "Wiki not available.",
55+
description: "We could not find the requested wiki.",
56+
category: "not_found",
57+
status: 404,
58+
});
5959
}
6060
}
6161

6262
export async function clientLoader({ params }: LoaderFunctionArgs) {
6363
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-
});
64+
const { dapper } = getLoaderTools();
7165

72-
const wiki = dapper.getPackageWiki(params.namespaceId, params.packageId);
66+
const wikiPromise = dapper.getPackageWiki(
67+
params.namespaceId,
68+
params.packageId
69+
);
7370

74-
const permissions = dapper.getPackagePermissions(
71+
const permissionsPromise = dapper.getPackagePermissions(
7572
params.communityId,
7673
params.namespaceId,
7774
params.packageId
7875
);
7976

8077
return {
81-
wiki: wiki,
78+
wiki: wikiPromise,
8279
communityId: params.communityId,
8380
namespaceId: params.namespaceId,
8481
packageId: params.packageId,
8582
slug: params.slug,
86-
permissions: permissions,
83+
permissions: permissionsPromise,
8784
};
8885
} else {
89-
throw new Error("Namespace ID or Package ID is missing");
86+
throwUserFacingPayloadResponse({
87+
headline: "Wiki not available.",
88+
description: "We could not find the requested wiki.",
89+
category: "not_found",
90+
status: 404,
91+
});
9092
}
9193
}
9294

95+
/**
96+
* Displays the package wiki navigation and nested routes, relying on Suspense for data.
97+
*/
9398
export default function Wiki() {
9499
const { wiki, communityId, namespaceId, packageId, slug, permissions } =
95100
useLoaderData<typeof loader | typeof clientLoader>();
@@ -100,7 +105,10 @@ export default function Wiki() {
100105
<div className="package-wiki">
101106
<div className="package-wiki-nav">
102107
<Suspense>
103-
<Await resolve={permissions}>
108+
<Await
109+
resolve={permissions}
110+
errorElement={<NimbusAwaitErrorElement />}
111+
>
104112
{(resolvedValue) =>
105113
resolvedValue?.permissions.can_manage ? (
106114
<div className="package-wiki-nav__header">
@@ -126,7 +134,7 @@ export default function Wiki() {
126134
<Suspense
127135
fallback={<SkeletonBox className="package-wiki-nav__skeleton" />}
128136
>
129-
<Await resolve={wiki} errorElement={<></>}>
137+
<Await resolve={wiki} errorElement={<NimbusAwaitErrorElement />}>
130138
{(resolvedValue) =>
131139
resolvedValue &&
132140
resolvedValue.pages.map((page, index) => {
@@ -194,3 +202,7 @@ export default function Wiki() {
194202
</div>
195203
);
196204
}
205+
206+
export function ErrorBoundary() {
207+
return <NimbusDefaultRouteErrorBoundary />;
208+
}

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)