Skip to content

Commit 7f95d37

Browse files
committed
Enhance error handling across package Wiki routes with user-facing error mapping and improved loader functions
1 parent cd40580 commit 7f95d37

File tree

6 files changed

+443
-435
lines changed

6 files changed

+443
-435
lines changed

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

Lines changed: 62 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -4,91 +4,96 @@ import {
44
Await,
55
type LoaderFunctionArgs,
66
Outlet,
7+
useLoaderData,
78
useOutletContext,
89
} from "react-router";
9-
import { useLoaderData } from "react-router";
10-
import { DapperTs } from "@thunderstore/dapper-ts";
11-
import {
12-
getPublicEnvVariables,
13-
getSessionTools,
14-
} from "cyberstorm/security/publicEnvVariables";
1510
import { NewButton, NewIcon, SkeletonBox } from "@thunderstore/cyberstorm";
1611
import { faPlus } from "@fortawesome/pro-solid-svg-icons";
1712
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
1813
import { type OutletContextShape } from "~/root";
1914
import { Suspense } from "react";
20-
import { ApiError } from "../../../../../../packages/thunderstore-api/src";
21-
import { getPackageWiki } from "@thunderstore/dapper-ts/src/methods/package";
15+
import { handleLoaderError } from "cyberstorm/utils/errors/handleLoaderError";
16+
import { createNotFoundMapping } from "cyberstorm/utils/errors/loaderMappings";
17+
import {
18+
NimbusAwaitErrorElement,
19+
NimbusDefaultRouteErrorBoundary,
20+
} from "cyberstorm/utils/errors/NimbusErrorBoundary";
21+
import { throwUserFacingPayloadResponse } from "cyberstorm/utils/errors/userFacingErrorResponse";
22+
import { getLoaderTools } from "cyberstorm/utils/getLoaderTools";
23+
24+
export const wikiErrorMappings = [
25+
createNotFoundMapping(
26+
"Wiki not available.",
27+
"We could not find the requested wiki."
28+
),
29+
];
2230

2331
export async function loader({ params }: LoaderFunctionArgs) {
2432
if (params.communityId && params.namespaceId && params.packageId) {
25-
const publicEnvVariables = getPublicEnvVariables(["VITE_API_URL"]);
26-
const dapper = new DapperTs(() => {
33+
const { dapper } = getLoaderTools();
34+
try {
35+
const wiki = await dapper.getPackageWiki(
36+
params.namespaceId,
37+
params.packageId
38+
);
39+
2740
return {
28-
apiHost: publicEnvVariables.VITE_API_URL,
29-
sessionId: undefined,
41+
wiki,
42+
communityId: params.communityId,
43+
namespaceId: params.namespaceId,
44+
packageId: params.packageId,
45+
slug: params.slug,
46+
permissions: undefined,
3047
};
31-
});
32-
33-
let wiki: Awaited<ReturnType<typeof getPackageWiki>> | undefined;
34-
35-
try {
36-
wiki = await dapper.getPackageWiki(params.namespaceId, params.packageId);
3748
} catch (error) {
38-
if (error instanceof ApiError) {
39-
if (error.response.status === 404) {
40-
wiki = undefined;
41-
} else {
42-
wiki = undefined;
43-
console.error("Error fetching package wiki:", error);
44-
}
45-
}
49+
handleLoaderError(error, { mappings: wikiErrorMappings });
4650
}
47-
48-
return {
49-
wiki: wiki,
50-
communityId: params.communityId,
51-
namespaceId: params.namespaceId,
52-
packageId: params.packageId,
53-
slug: params.slug,
54-
permissions: undefined,
55-
};
5651
} else {
57-
throw new Error("Namespace ID or Package ID is missing");
52+
throwUserFacingPayloadResponse({
53+
headline: "Wiki not available.",
54+
description: "We could not find the requested wiki.",
55+
category: "not_found",
56+
status: 404,
57+
});
5858
}
5959
}
6060

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

71-
const wiki = dapper.getPackageWiki(params.namespaceId, params.packageId);
65+
const wikiPromise = dapper.getPackageWiki(
66+
params.namespaceId,
67+
params.packageId
68+
);
7269

73-
const permissions = dapper.getPackagePermissions(
70+
const permissionsPromise = dapper.getPackagePermissions(
7471
params.communityId,
7572
params.namespaceId,
7673
params.packageId
7774
);
7875

7976
return {
80-
wiki: wiki,
77+
wiki: wikiPromise,
8178
communityId: params.communityId,
8279
namespaceId: params.namespaceId,
8380
packageId: params.packageId,
8481
slug: params.slug,
85-
permissions: permissions,
82+
permissions: permissionsPromise,
8683
};
8784
} else {
88-
throw new Error("Namespace ID or Package ID is missing");
85+
throwUserFacingPayloadResponse({
86+
headline: "Wiki not available.",
87+
description: "We could not find the requested wiki.",
88+
category: "not_found",
89+
status: 404,
90+
});
8991
}
9092
}
9193

94+
/**
95+
* Displays the package wiki navigation and nested routes, relying on Suspense for data.
96+
*/
9297
export default function Wiki() {
9398
const { wiki, communityId, namespaceId, packageId, slug, permissions } =
9499
useLoaderData<typeof loader | typeof clientLoader>();
@@ -99,7 +104,10 @@ export default function Wiki() {
99104
<div className="package-wiki">
100105
<div className="package-wiki-nav">
101106
<Suspense>
102-
<Await resolve={permissions}>
107+
<Await
108+
resolve={permissions}
109+
errorElement={<NimbusAwaitErrorElement />}
110+
>
103111
{(resolvedValue) =>
104112
resolvedValue?.permissions.can_manage ? (
105113
<div className="package-wiki-nav__header">
@@ -125,7 +133,7 @@ export default function Wiki() {
125133
<Suspense
126134
fallback={<SkeletonBox className="package-wiki-nav__skeleton" />}
127135
>
128-
<Await resolve={wiki} errorElement={<></>}>
136+
<Await resolve={wiki} errorElement={<NimbusAwaitErrorElement />}>
129137
{(resolvedValue) =>
130138
resolvedValue &&
131139
resolvedValue.pages.map((page, index) => {
@@ -193,3 +201,7 @@ export default function Wiki() {
193201
</div>
194202
);
195203
}
204+
205+
export function ErrorBoundary() {
206+
return <NimbusDefaultRouteErrorBoundary />;
207+
}

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
1212
import { memo, Suspense } from "react";
1313
import { Markdown } from "~/commonComponents/Markdown/Markdown";
1414
import { Await } from "react-router";
15+
import { NimbusAwaitErrorElement } from "cyberstorm/utils/errors/NimbusErrorBoundary";
1516

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

0 commit comments

Comments
 (0)