Skip to content

Commit e5151e2

Browse files
committed
Enhance error handling in all package version routes
1 parent cd40580 commit e5151e2

File tree

2 files changed

+308
-187
lines changed

2 files changed

+308
-187
lines changed

apps/cyberstorm-remix/app/p/packageVersion.tsx

Lines changed: 147 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -39,23 +39,34 @@ import {
3939
} from "react";
4040
import { useHydrated } from "remix-utils/use-hydrated";
4141
import { PageHeader } from "~/commonComponents/PageHeader/PageHeader";
42+
import {
43+
NimbusAwaitErrorElement,
44+
NimbusDefaultRouteErrorBoundary,
45+
} from "cyberstorm/utils/errors/NimbusErrorBoundary";
4246
import { faArrowUpRight } from "@fortawesome/pro-solid-svg-icons";
4347
import { RelativeTime } from "@thunderstore/cyberstorm/src/components/RelativeTime/RelativeTime";
4448
import {
4549
formatFileSize,
4650
formatInteger,
4751
formatToDisplayName,
4852
} from "@thunderstore/cyberstorm/src/utils/utils";
49-
import { DapperTs } from "@thunderstore/dapper-ts";
5053
import { type OutletContextShape } from "~/root";
5154
import { CopyButton } from "~/commonComponents/CopyButton/CopyButton";
52-
import {
53-
getPublicEnvVariables,
54-
getSessionTools,
55-
} from "cyberstorm/security/publicEnvVariables";
55+
import { getPublicEnvVariables } from "cyberstorm/security/publicEnvVariables";
5656
import { getTeamDetails } from "@thunderstore/dapper-ts/src/methods/team";
5757
import { isPromise } from "cyberstorm/utils/typeChecks";
5858
import { getPackageVersionDetails } from "@thunderstore/dapper-ts/src/methods/packageVersion";
59+
import { throwUserFacingPayloadResponse } from "cyberstorm/utils/errors/userFacingErrorResponse";
60+
import { handleLoaderError } from "cyberstorm/utils/errors/handleLoaderError";
61+
import { createNotFoundMapping } from "cyberstorm/utils/errors/loaderMappings";
62+
import { getLoaderTools } from "cyberstorm/utils/getLoaderTools";
63+
64+
const packageVersionNotFoundMappings = [
65+
createNotFoundMapping(
66+
"Package version not found.",
67+
"We could not find the requested package version."
68+
),
69+
];
5970

6071
export async function loader({ params }: LoaderFunctionArgs) {
6172
if (
@@ -64,55 +75,81 @@ export async function loader({ params }: LoaderFunctionArgs) {
6475
params.packageId &&
6576
params.packageVersion
6677
) {
67-
const publicEnvVariables = getPublicEnvVariables(["VITE_API_URL"]);
68-
const dapper = new DapperTs(() => {
78+
const { dapper } = getLoaderTools();
79+
try {
80+
const [community, version, team] = await Promise.all([
81+
dapper.getCommunity(params.communityId),
82+
dapper.getPackageVersionDetails(
83+
params.namespaceId,
84+
params.packageId,
85+
params.packageVersion
86+
),
87+
dapper.getTeamDetails(params.namespaceId),
88+
]);
89+
6990
return {
70-
apiHost: publicEnvVariables.VITE_API_URL,
71-
sessionId: undefined,
91+
communityId: params.communityId,
92+
community,
93+
version,
94+
team,
7295
};
73-
});
74-
75-
return {
76-
communityId: params.communityId,
77-
community: await dapper.getCommunity(params.communityId),
78-
version: await dapper.getPackageVersionDetails(
79-
params.namespaceId,
80-
params.packageId,
81-
params.packageVersion
82-
),
83-
team: await dapper.getTeamDetails(params.namespaceId),
84-
};
96+
} catch (error) {
97+
handleLoaderError(error, { mappings: packageVersionNotFoundMappings });
98+
}
8599
}
86-
throw new Response("Package not found", { status: 404 });
100+
throwUserFacingPayloadResponse({
101+
headline: "Package not found.",
102+
description: "We could not find the requested package.",
103+
category: "not_found",
104+
status: 404,
105+
});
87106
}
88107

89-
export async function clientLoader({ params }: LoaderFunctionArgs) {
108+
export function clientLoader({ params }: LoaderFunctionArgs) {
90109
if (
91110
params.communityId &&
92111
params.namespaceId &&
93112
params.packageId &&
94113
params.packageVersion
95114
) {
96-
const tools = getSessionTools();
97-
const dapper = new DapperTs(() => {
98-
return {
99-
apiHost: tools?.getConfig().apiHost,
100-
sessionId: tools?.getConfig().sessionId,
101-
};
102-
});
103-
104-
return {
105-
communityId: params.communityId,
106-
community: dapper.getCommunity(params.communityId),
107-
version: dapper.getPackageVersionDetails(
115+
const { dapper } = getLoaderTools();
116+
const community = dapper
117+
.getCommunity(params.communityId)
118+
.catch((error) =>
119+
handleLoaderError(error, { mappings: packageVersionNotFoundMappings })
120+
);
121+
const version = dapper
122+
.getPackageVersionDetails(
108123
params.namespaceId,
109124
params.packageId,
110125
params.packageVersion
111-
),
112-
team: dapper.getTeamDetails(params.namespaceId),
126+
)
127+
.catch((error) =>
128+
handleLoaderError(error, { mappings: packageVersionNotFoundMappings })
129+
);
130+
const team = dapper
131+
.getTeamDetails(params.namespaceId)
132+
.catch((error) =>
133+
handleLoaderError(error, { mappings: packageVersionNotFoundMappings })
134+
);
135+
136+
return {
137+
communityId: params.communityId,
138+
community,
139+
version,
140+
team,
113141
};
114142
}
115-
throw new Response("Package not found", { status: 404 });
143+
throwUserFacingPayloadResponse({
144+
headline: "Package not found.",
145+
description: "We could not find the requested package.",
146+
category: "not_found",
147+
status: 404,
148+
});
149+
}
150+
151+
export function ErrorBoundary() {
152+
return <NimbusDefaultRouteErrorBoundary />;
116153
}
117154

118155
export function shouldRevalidate(arg: ShouldRevalidateFunctionArgs) {
@@ -152,39 +189,65 @@ export default function PackageVersion() {
152189
// If strict mode is removed from the entry.client.tsx, this should only run once
153190
useEffect(() => {
154191
if (!startsHydrated.current && isHydrated) return;
155-
if (isPromise(version)) {
156-
version.then((versionData) => {
157-
setFirstUploaded(
158-
<RelativeTime
159-
time={versionData.datetime_created}
160-
suppressHydrationWarning
161-
/>
162-
);
163-
});
164-
} else {
192+
if (!isPromise(version)) {
165193
setFirstUploaded(
166194
<RelativeTime
167195
time={version.datetime_created}
168196
suppressHydrationWarning
169197
/>
170198
);
199+
return;
171200
}
172-
}, []);
201+
202+
let isCancelled = false;
203+
204+
const resolveVersionTimes = async () => {
205+
try {
206+
const versionData = await version;
207+
if (isCancelled) {
208+
return;
209+
}
210+
211+
setFirstUploaded(
212+
<RelativeTime
213+
time={versionData.datetime_created}
214+
suppressHydrationWarning
215+
/>
216+
);
217+
} catch (error) {
218+
if (!isCancelled) {
219+
console.error("Failed to resolve version metadata", error);
220+
}
221+
}
222+
};
223+
224+
resolveVersionTimes();
225+
226+
return () => {
227+
isCancelled = true;
228+
};
229+
}, [isHydrated, version]);
173230
// END: For sidebar meta dates
174231

175232
const currentTab = location.pathname.split("/")[8] || "details";
176233

177234
const versionAndCommunityPromise = useMemo(
178235
() => Promise.all([version, community]),
179-
[]
236+
[version, community]
180237
);
181238

182-
const versionAndTeamPromise = useMemo(() => Promise.all([version, team]), []);
239+
const versionAndTeamPromise = useMemo(
240+
() => Promise.all([version, team]),
241+
[version, team]
242+
);
183243

184244
return (
185245
<>
186246
<Suspense>
187-
<Await resolve={versionAndCommunityPromise}>
247+
<Await
248+
resolve={versionAndCommunityPromise}
249+
errorElement={<NimbusAwaitErrorElement />}
250+
>
188251
{(resolvedValue) => (
189252
<>
190253
<meta
@@ -233,7 +296,10 @@ export default function PackageVersion() {
233296
</NewAlert>
234297
}
235298
>
236-
<Await resolve={version}>
299+
<Await
300+
resolve={version}
301+
errorElement={<NimbusAwaitErrorElement />}
302+
>
237303
{(resolvedValue) => (
238304
<NewAlert csVariant="warning">
239305
You are viewing a potentially older version of this
@@ -257,7 +323,10 @@ export default function PackageVersion() {
257323
<SkeletonBox className="package-listing__page-header-skeleton" />
258324
}
259325
>
260-
<Await resolve={version}>
326+
<Await
327+
resolve={version}
328+
errorElement={<NimbusAwaitErrorElement />}
329+
>
261330
{(resolvedValue) => (
262331
<PageHeader
263332
headingLevel="1"
@@ -323,15 +392,21 @@ export default function PackageVersion() {
323392
rootClasses="package-listing__drawer"
324393
>
325394
<Suspense fallback={<p>Loading...</p>}>
326-
<Await resolve={version}>
395+
<Await
396+
resolve={version}
397+
errorElement={<NimbusAwaitErrorElement />}
398+
>
327399
{(resolvedValue) => (
328400
<>{packageMeta(firstUploaded, resolvedValue)}</>
329401
)}
330402
</Await>
331403
</Suspense>
332404
</Drawer>
333405
<Suspense fallback={<p>Loading...</p>}>
334-
<Await resolve={versionAndTeamPromise}>
406+
<Await
407+
resolve={versionAndTeamPromise}
408+
errorElement={<NimbusAwaitErrorElement />}
409+
>
335410
{(resolvedValue) => (
336411
<Actions
337412
team={resolvedValue[1]}
@@ -346,7 +421,10 @@ export default function PackageVersion() {
346421
<SkeletonBox className="package-listing__nav-skeleton" />
347422
}
348423
>
349-
<Await resolve={version}>
424+
<Await
425+
resolve={version}
426+
errorElement={<NimbusAwaitErrorElement />}
427+
>
350428
{(resolvedValue) => (
351429
<>
352430
<Tabs>
@@ -416,7 +494,10 @@ export default function PackageVersion() {
416494
<SkeletonBox className="package-listing-sidebar__install-skeleton" />
417495
}
418496
>
419-
<Await resolve={version}>
497+
<Await
498+
resolve={version}
499+
errorElement={<NimbusAwaitErrorElement />}
500+
>
420501
{(resolvedValue) => (
421502
<NewButton
422503
csVariant="accent"
@@ -440,7 +521,10 @@ export default function PackageVersion() {
440521
<SkeletonBox className="package-listing-sidebar__actions-skeleton" />
441522
}
442523
>
443-
<Await resolve={versionAndTeamPromise}>
524+
<Await
525+
resolve={versionAndTeamPromise}
526+
errorElement={<NimbusAwaitErrorElement />}
527+
>
444528
{(resolvedValue) => (
445529
<Actions
446530
team={resolvedValue[1]}
@@ -454,7 +538,10 @@ export default function PackageVersion() {
454538
<SkeletonBox className="package-listing-sidebar__skeleton" />
455539
}
456540
>
457-
<Await resolve={version}>
541+
<Await
542+
resolve={version}
543+
errorElement={<NimbusAwaitErrorElement />}
544+
>
458545
{(resolvedValue) => (
459546
<>{packageMeta(firstUploaded, resolvedValue)}</>
460547
)}

0 commit comments

Comments
 (0)