Skip to content

Commit 5bb48f0

Browse files
committed
Enhance error handling in all package readme routes
1 parent cd40580 commit 5bb48f0

File tree

4 files changed

+181
-158
lines changed

4 files changed

+181
-158
lines changed
Lines changed: 59 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,85 +1,89 @@
11
import { Await, type LoaderFunctionArgs } from "react-router";
22
import { useLoaderData } from "react-router";
3-
import { DapperTs } from "@thunderstore/dapper-ts";
4-
import {
5-
getPublicEnvVariables,
6-
getSessionTools,
7-
} from "cyberstorm/security/publicEnvVariables";
83
import { Suspense } from "react";
94
import { SkeletonBox } from "@thunderstore/cyberstorm";
105
import "./Readme.css";
6+
import { handleLoaderError } from "cyberstorm/utils/errors/handleLoaderError";
7+
import { createNotFoundMapping } from "cyberstorm/utils/errors/loaderMappings";
8+
import { throwUserFacingPayloadResponse } from "cyberstorm/utils/errors/userFacingErrorResponse";
9+
import {
10+
NimbusAwaitErrorElement,
11+
NimbusDefaultRouteErrorBoundary,
12+
} from "cyberstorm/utils/errors/NimbusErrorBoundary";
13+
import { getLoaderTools } from "cyberstorm/utils/getLoaderTools";
1114

1215
export async function loader({ params }: LoaderFunctionArgs) {
1316
if (params.namespaceId && params.packageId && params.packageVersion) {
14-
const publicEnvVariables = getPublicEnvVariables(["VITE_API_URL"]);
15-
const dapper = new DapperTs(() => {
16-
return {
17-
apiHost: publicEnvVariables.VITE_API_URL,
18-
sessionId: undefined,
19-
};
20-
});
21-
return {
22-
readme: await dapper.getPackageReadme(
17+
const { dapper } = getLoaderTools();
18+
try {
19+
const readme = await dapper.getPackageReadme(
2320
params.namespaceId,
2421
params.packageId,
2522
params.packageVersion
26-
),
27-
};
23+
);
24+
25+
return {
26+
readme,
27+
};
28+
} catch (error) {
29+
handleLoaderError(error, {
30+
mappings: [
31+
createNotFoundMapping(
32+
"Readme not available.",
33+
"We could not find a readme for this package version."
34+
),
35+
],
36+
});
37+
}
2838
}
29-
return {
30-
status: "error",
31-
message: "Failed to load readme",
32-
readme: { html: "" },
33-
};
39+
throwUserFacingPayloadResponse({
40+
headline: "Readme not available.",
41+
description: "We could not find a readme for this package version.",
42+
category: "not_found",
43+
status: 404,
44+
});
3445
}
3546

36-
export async function clientLoader({ params }: LoaderFunctionArgs) {
47+
export function clientLoader({ params }: LoaderFunctionArgs) {
3748
if (params.namespaceId && params.packageId && params.packageVersion) {
38-
const tools = getSessionTools();
39-
const dapper = new DapperTs(() => {
40-
return {
41-
apiHost: tools?.getConfig().apiHost,
42-
sessionId: tools?.getConfig().sessionId,
43-
};
44-
});
49+
const { dapper } = getLoaderTools();
50+
const readme = dapper.getPackageReadme(
51+
params.namespaceId,
52+
params.packageId,
53+
params.packageVersion
54+
);
55+
4556
return {
46-
readme: dapper.getPackageReadme(
47-
params.namespaceId,
48-
params.packageId,
49-
params.packageVersion
50-
),
57+
readme,
5158
};
5259
}
53-
return {
54-
status: "error",
55-
message: "Failed to load readme",
56-
readme: { html: "" },
57-
};
60+
throwUserFacingPayloadResponse({
61+
headline: "Readme not available.",
62+
description: "We could not find a readme for this package version.",
63+
category: "not_found",
64+
status: 404,
65+
});
5866
}
5967

6068
export default function PackageVersionReadme() {
61-
const { status, message, readme } = useLoaderData<
62-
typeof loader | typeof clientLoader
63-
>();
69+
const { readme } = useLoaderData<typeof loader | typeof clientLoader>();
6470

65-
if (status === "error") return <div>{message}</div>;
6671
return (
6772
<Suspense fallback={<SkeletonBox className="package-readme__skeleton" />}>
68-
<Await
69-
resolve={readme}
70-
errorElement={<div>Error occurred while loading description</div>}
71-
>
73+
<Await resolve={readme} errorElement={<NimbusAwaitErrorElement />}>
7274
{(resolvedValue) => (
73-
<>
74-
<div className="markdown-wrapper">
75-
<div
76-
dangerouslySetInnerHTML={{ __html: resolvedValue.html }}
77-
className="markdown"
78-
/>
79-
</div>
80-
</>
75+
<div className="markdown-wrapper">
76+
<div
77+
dangerouslySetInnerHTML={{ __html: resolvedValue.html }}
78+
className="markdown"
79+
/>
80+
</div>
8181
)}
8282
</Await>
8383
</Suspense>
8484
);
8585
}
86+
87+
export function ErrorBoundary() {
88+
return <NimbusDefaultRouteErrorBoundary />;
89+
}
Lines changed: 51 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,85 +1,81 @@
11
import { Await, type LoaderFunctionArgs } from "react-router";
22
import { useLoaderData } from "react-router";
3-
import { DapperTs } from "@thunderstore/dapper-ts";
4-
import {
5-
getPublicEnvVariables,
6-
getSessionTools,
7-
} from "cyberstorm/security/publicEnvVariables";
83
import { Suspense } from "react";
94
import { SkeletonBox } from "@thunderstore/cyberstorm";
105
import "./Readme.css";
6+
import { handleLoaderError } from "cyberstorm/utils/errors/handleLoaderError";
7+
import { throwUserFacingPayloadResponse } from "cyberstorm/utils/errors/userFacingErrorResponse";
8+
import {
9+
NimbusAwaitErrorElement,
10+
NimbusDefaultRouteErrorBoundary,
11+
} from "cyberstorm/utils/errors/NimbusErrorBoundary";
12+
import { getLoaderTools } from "cyberstorm/utils/getLoaderTools";
1113

1214
export async function loader({ params }: LoaderFunctionArgs) {
1315
if (params.namespaceId && params.packageId && params.packageVersion) {
14-
const publicEnvVariables = getPublicEnvVariables(["VITE_API_URL"]);
15-
const dapper = new DapperTs(() => {
16-
return {
17-
apiHost: publicEnvVariables.VITE_API_URL,
18-
sessionId: undefined,
19-
};
20-
});
21-
return {
22-
readme: await dapper.getPackageReadme(
16+
const { dapper } = getLoaderTools();
17+
try {
18+
const readme = await dapper.getPackageReadme(
2319
params.namespaceId,
2420
params.packageId,
2521
params.packageVersion
26-
),
27-
};
22+
);
23+
24+
return {
25+
readme,
26+
};
27+
} catch (error) {
28+
handleLoaderError(error);
29+
}
2830
}
29-
return {
30-
status: "error",
31-
message: "Failed to load readme",
32-
readme: { html: "" },
33-
};
31+
throwUserFacingPayloadResponse({
32+
headline: "Readme not available.",
33+
description: "We could not find a readme for this package version.",
34+
category: "not_found",
35+
status: 404,
36+
});
3437
}
3538

36-
export async function clientLoader({ params }: LoaderFunctionArgs) {
39+
export function clientLoader({ params }: LoaderFunctionArgs) {
3740
if (params.namespaceId && params.packageId && params.packageVersion) {
38-
const tools = getSessionTools();
39-
const dapper = new DapperTs(() => {
40-
return {
41-
apiHost: tools?.getConfig().apiHost,
42-
sessionId: tools?.getConfig().sessionId,
43-
};
44-
});
41+
const { dapper } = getLoaderTools();
42+
const readme = dapper.getPackageReadme(
43+
params.namespaceId,
44+
params.packageId,
45+
params.packageVersion
46+
);
47+
4548
return {
46-
readme: dapper.getPackageReadme(
47-
params.namespaceId,
48-
params.packageId,
49-
params.packageVersion
50-
),
49+
readme,
5150
};
5251
}
53-
return {
54-
status: "error",
55-
message: "Failed to load readme",
56-
readme: { html: "" },
57-
};
52+
throwUserFacingPayloadResponse({
53+
headline: "Readme not available.",
54+
description: "We could not find a readme for this package version.",
55+
category: "not_found",
56+
status: 404,
57+
});
5858
}
5959

6060
export default function PackageVersionReadme() {
61-
const { status, message, readme } = useLoaderData<
62-
typeof loader | typeof clientLoader
63-
>();
61+
const { readme } = useLoaderData<typeof loader | typeof clientLoader>();
6462

65-
if (status === "error") return <div>{message}</div>;
6663
return (
6764
<Suspense fallback={<SkeletonBox className="package-readme__skeleton" />}>
68-
<Await
69-
resolve={readme}
70-
errorElement={<div>Error occurred while loading description</div>}
71-
>
65+
<Await resolve={readme} errorElement={<NimbusAwaitErrorElement />}>
7266
{(resolvedValue) => (
73-
<>
74-
<div className="markdown-wrapper">
75-
<div
76-
dangerouslySetInnerHTML={{ __html: resolvedValue.html }}
77-
className="markdown"
78-
/>
79-
</div>
80-
</>
67+
<div className="markdown-wrapper">
68+
<div
69+
dangerouslySetInnerHTML={{ __html: resolvedValue.html }}
70+
className="markdown"
71+
/>
72+
</div>
8173
)}
8274
</Await>
8375
</Suspense>
8476
);
8577
}
78+
79+
export function ErrorBoundary() {
80+
return <NimbusDefaultRouteErrorBoundary />;
81+
}

apps/cyberstorm-remix/app/p/tabs/Readme/Readme.css

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,17 @@
22
.package-readme__skeleton {
33
height: 500px;
44
}
5+
6+
.package-readme__error {
7+
display: flex;
8+
flex-direction: column;
9+
gap: 1rem;
10+
align-items: flex-start;
11+
padding: 3rem 0;
12+
}
13+
14+
.package-readme__error-description {
15+
max-width: 40rem;
16+
color: var(--Color-text-muted, rgb(180 189 255 / 0.8));
17+
}
518
}

0 commit comments

Comments
 (0)