Skip to content

Commit 85a1a0e

Browse files
committed
Enhance error handling in all package versions routes
1 parent cd40580 commit 85a1a0e

File tree

3 files changed

+154
-126
lines changed

3 files changed

+154
-126
lines changed

apps/cyberstorm-remix/app/p/tabs/Versions/PackageVersionVersions.tsx

Lines changed: 50 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -8,73 +8,76 @@ import {
88
} from "@thunderstore/cyberstorm";
99
import { Await, type LoaderFunctionArgs } from "react-router";
1010
import { useLoaderData } from "react-router";
11-
import { DapperTs } from "@thunderstore/dapper-ts";
12-
import {
13-
getPublicEnvVariables,
14-
getSessionTools,
15-
} from "cyberstorm/security/publicEnvVariables";
1611
import { Suspense } from "react";
1712
import { DownloadLink, InstallLink, ModManagerBanner } from "./common";
1813
import { rowSemverCompare } from "cyberstorm/utils/semverCompare";
19-
import { columns } from "./Versions";
14+
import { columns, packageVersionsErrorMappings } from "./Versions";
15+
import { handleLoaderError } from "cyberstorm/utils/errors/handleLoaderError";
16+
import { throwUserFacingPayloadResponse } from "cyberstorm/utils/errors/userFacingErrorResponse";
17+
import {
18+
NimbusAwaitErrorElement,
19+
NimbusDefaultRouteErrorBoundary,
20+
} from "cyberstorm/utils/errors/NimbusErrorBoundary";
21+
import { getLoaderTools } from "cyberstorm/utils/getLoaderTools";
2022

2123
export async function loader({ params }: LoaderFunctionArgs) {
2224
if (params.communityId && params.namespaceId && params.packageId) {
23-
const publicEnvVariables = getPublicEnvVariables(["VITE_API_URL"]);
24-
const dapper = new DapperTs(() => {
25+
const { dapper } = getLoaderTools();
26+
try {
27+
const versions = await dapper.getPackageVersions(
28+
params.namespaceId,
29+
params.packageId
30+
);
31+
2532
return {
26-
apiHost: publicEnvVariables.VITE_API_URL,
27-
sessionId: undefined,
33+
communityId: params.communityId,
34+
namespaceId: params.namespaceId,
35+
packageId: params.packageId,
36+
versions,
2837
};
29-
});
30-
return {
31-
communityId: params.communityId,
32-
namespaceId: params.namespaceId,
33-
packageId: params.packageId,
34-
versions: dapper.getPackageVersions(params.namespaceId, params.packageId),
35-
};
38+
} catch (error) {
39+
handleLoaderError(error, { mappings: packageVersionsErrorMappings });
40+
}
3641
}
37-
return {
38-
status: "error",
39-
message: "Failed to load versions",
40-
versions: [],
41-
};
42+
throwUserFacingPayloadResponse({
43+
headline: "Package not found.",
44+
description: "We could not find the requested package.",
45+
category: "not_found",
46+
status: 404,
47+
});
4248
}
4349

44-
export async function clientLoader({ params }: LoaderFunctionArgs) {
50+
export function clientLoader({ params }: LoaderFunctionArgs) {
4551
if (params.communityId && params.namespaceId && params.packageId) {
46-
const tools = getSessionTools();
47-
const dapper = new DapperTs(() => {
48-
return {
49-
apiHost: tools?.getConfig().apiHost,
50-
sessionId: tools?.getConfig().sessionId,
51-
};
52-
});
52+
const { dapper } = getLoaderTools();
53+
const versions = dapper.getPackageVersions(
54+
params.namespaceId,
55+
params.packageId
56+
);
57+
5358
return {
5459
communityId: params.communityId,
5560
namespaceId: params.namespaceId,
5661
packageId: params.packageId,
57-
versions: dapper.getPackageVersions(params.namespaceId, params.packageId),
62+
versions,
5863
};
5964
}
60-
return {
61-
status: "error",
62-
message: "Failed to load versions",
63-
versions: [],
64-
};
65+
throwUserFacingPayloadResponse({
66+
headline: "Package not found.",
67+
description: "We could not find the requested package.",
68+
category: "not_found",
69+
status: 404,
70+
});
6571
}
6672

6773
export default function Versions() {
68-
const { communityId, namespaceId, packageId, status, message, versions } =
69-
useLoaderData<typeof loader | typeof clientLoader>();
70-
71-
if (status === "error") {
72-
return <div>{message}</div>;
73-
}
74+
const { communityId, namespaceId, packageId, versions } = useLoaderData<
75+
typeof loader | typeof clientLoader
76+
>();
7477

7578
return (
7679
<Suspense fallback={<SkeletonBox className="package-versions__skeleton" />}>
77-
<Await resolve={versions}>
80+
<Await resolve={versions} errorElement={<NimbusAwaitErrorElement />}>
7881
{(resolvedValue) => (
7982
<div className="package-versions">
8083
<ModManagerBanner />
@@ -132,3 +135,7 @@ export default function Versions() {
132135
</Suspense>
133136
);
134137
}
138+
139+
export function ErrorBoundary() {
140+
return <NimbusDefaultRouteErrorBoundary />;
141+
}

apps/cyberstorm-remix/app/p/tabs/Versions/PackageVersionWithoutCommunityVersions.tsx

Lines changed: 47 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -8,72 +8,74 @@ import {
88
} from "@thunderstore/cyberstorm";
99
import { Await, type LoaderFunctionArgs } from "react-router";
1010
import { useLoaderData } from "react-router";
11-
import { DapperTs } from "@thunderstore/dapper-ts";
12-
import {
13-
getPublicEnvVariables,
14-
getSessionTools,
15-
} from "cyberstorm/security/publicEnvVariables";
1611
import { Suspense } from "react";
1712
import { DownloadLink, InstallLink, ModManagerBanner } from "./common";
1813
import { rowSemverCompare } from "cyberstorm/utils/semverCompare";
19-
import { columns } from "./Versions";
14+
import { columns, packageVersionsErrorMappings } from "./Versions";
15+
import { handleLoaderError } from "cyberstorm/utils/errors/handleLoaderError";
16+
import { throwUserFacingPayloadResponse } from "cyberstorm/utils/errors/userFacingErrorResponse";
17+
import {
18+
NimbusAwaitErrorElement,
19+
NimbusDefaultRouteErrorBoundary,
20+
} from "cyberstorm/utils/errors/NimbusErrorBoundary";
21+
import { getLoaderTools } from "cyberstorm/utils/getLoaderTools";
2022

2123
export async function loader({ params }: LoaderFunctionArgs) {
2224
if (params.namespaceId && params.packageId) {
23-
const publicEnvVariables = getPublicEnvVariables(["VITE_API_URL"]);
24-
const dapper = new DapperTs(() => {
25+
const { dapper } = getLoaderTools();
26+
try {
27+
const versions = await dapper.getPackageVersions(
28+
params.namespaceId,
29+
params.packageId
30+
);
31+
2532
return {
26-
apiHost: publicEnvVariables.VITE_API_URL,
27-
sessionId: undefined,
33+
namespaceId: params.namespaceId,
34+
packageId: params.packageId,
35+
versions,
2836
};
29-
});
30-
return {
31-
namespaceId: params.namespaceId,
32-
packageId: params.packageId,
33-
versions: dapper.getPackageVersions(params.namespaceId, params.packageId),
34-
};
37+
} catch (error) {
38+
handleLoaderError(error, { mappings: packageVersionsErrorMappings });
39+
}
3540
}
36-
return {
37-
status: "error",
38-
message: "Failed to load versions",
39-
versions: [],
40-
};
41+
throwUserFacingPayloadResponse({
42+
headline: "Package not found.",
43+
description: "We could not find the requested package.",
44+
category: "not_found",
45+
status: 404,
46+
});
4147
}
4248

43-
export async function clientLoader({ params }: LoaderFunctionArgs) {
49+
export function clientLoader({ params }: LoaderFunctionArgs) {
4450
if (params.namespaceId && params.packageId) {
45-
const tools = getSessionTools();
46-
const dapper = new DapperTs(() => {
47-
return {
48-
apiHost: tools?.getConfig().apiHost,
49-
sessionId: tools?.getConfig().sessionId,
50-
};
51-
});
51+
const { dapper } = getLoaderTools();
52+
const versions = dapper.getPackageVersions(
53+
params.namespaceId,
54+
params.packageId
55+
);
56+
5257
return {
5358
namespaceId: params.namespaceId,
5459
packageId: params.packageId,
55-
versions: dapper.getPackageVersions(params.namespaceId, params.packageId),
60+
versions,
5661
};
5762
}
58-
return {
59-
status: "error",
60-
message: "Failed to load versions",
61-
versions: [],
62-
};
63+
throwUserFacingPayloadResponse({
64+
headline: "Package not found.",
65+
description: "We could not find the requested package.",
66+
category: "not_found",
67+
status: 404,
68+
});
6369
}
6470

6571
export default function Versions() {
66-
const { namespaceId, packageId, status, message, versions } = useLoaderData<
72+
const { namespaceId, packageId, versions } = useLoaderData<
6773
typeof loader | typeof clientLoader
6874
>();
6975

70-
if (status === "error") {
71-
return <div>{message}</div>;
72-
}
73-
7476
return (
7577
<Suspense fallback={<SkeletonBox className="package-versions__skeleton" />}>
76-
<Await resolve={versions}>
78+
<Await resolve={versions} errorElement={<NimbusAwaitErrorElement />}>
7779
{(resolvedValue) => (
7880
<div className="package-versions">
7981
<ModManagerBanner />
@@ -130,3 +132,7 @@ export default function Versions() {
130132
</Suspense>
131133
);
132134
}
135+
136+
export function ErrorBoundary() {
137+
return <NimbusDefaultRouteErrorBoundary />;
138+
}

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

Lines changed: 57 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -9,72 +9,83 @@ import {
99
} from "@thunderstore/cyberstorm";
1010
import { Await, type LoaderFunctionArgs } from "react-router";
1111
import { useLoaderData } from "react-router";
12-
import { DapperTs } from "@thunderstore/dapper-ts";
13-
import {
14-
getPublicEnvVariables,
15-
getSessionTools,
16-
} from "cyberstorm/security/publicEnvVariables";
1712
import { Suspense } from "react";
1813
import { DownloadLink, InstallLink, ModManagerBanner } from "./common";
1914
import { rowSemverCompare } from "cyberstorm/utils/semverCompare";
15+
import { handleLoaderError } from "cyberstorm/utils/errors/handleLoaderError";
16+
import { createNotFoundMapping } from "cyberstorm/utils/errors/loaderMappings";
17+
import { throwUserFacingPayloadResponse } from "cyberstorm/utils/errors/userFacingErrorResponse";
18+
import {
19+
NimbusAwaitErrorElement,
20+
NimbusDefaultRouteErrorBoundary,
21+
} from "cyberstorm/utils/errors/NimbusErrorBoundary";
22+
import { getLoaderTools } from "cyberstorm/utils/getLoaderTools";
23+
24+
export const packageVersionsErrorMappings = [
25+
createNotFoundMapping(
26+
"Package not found.",
27+
"We could not find the requested package."
28+
),
29+
];
2030

2131
export async function loader({ params }: LoaderFunctionArgs) {
2232
if (params.communityId && params.namespaceId && params.packageId) {
23-
const publicEnvVariables = getPublicEnvVariables(["VITE_API_URL"]);
24-
const dapper = new DapperTs(() => {
33+
const { dapper } = getLoaderTools();
34+
try {
35+
const versions = await dapper.getPackageVersions(
36+
params.namespaceId,
37+
params.packageId
38+
);
39+
2540
return {
26-
apiHost: publicEnvVariables.VITE_API_URL,
27-
sessionId: undefined,
41+
communityId: params.communityId,
42+
namespaceId: params.namespaceId,
43+
packageId: params.packageId,
44+
versions,
2845
};
29-
});
30-
return {
31-
communityId: params.communityId,
32-
namespaceId: params.namespaceId,
33-
packageId: params.packageId,
34-
versions: dapper.getPackageVersions(params.namespaceId, params.packageId),
35-
};
46+
} catch (error) {
47+
handleLoaderError(error, { mappings: packageVersionsErrorMappings });
48+
}
3649
}
37-
return {
38-
status: "error",
39-
message: "Failed to load versions",
40-
versions: [],
41-
};
50+
throwUserFacingPayloadResponse({
51+
headline: "Package not found.",
52+
description: "We could not find the requested package.",
53+
category: "not_found",
54+
status: 404,
55+
});
4256
}
4357

44-
export async function clientLoader({ params }: LoaderFunctionArgs) {
58+
export function clientLoader({ params }: LoaderFunctionArgs) {
4559
if (params.communityId && params.namespaceId && params.packageId) {
46-
const tools = getSessionTools();
47-
const dapper = new DapperTs(() => {
48-
return {
49-
apiHost: tools?.getConfig().apiHost,
50-
sessionId: tools?.getConfig().sessionId,
51-
};
52-
});
60+
const { dapper } = getLoaderTools();
61+
const versions = dapper.getPackageVersions(
62+
params.namespaceId,
63+
params.packageId
64+
);
65+
5366
return {
5467
communityId: params.communityId,
5568
namespaceId: params.namespaceId,
5669
packageId: params.packageId,
57-
versions: dapper.getPackageVersions(params.namespaceId, params.packageId),
70+
versions,
5871
};
5972
}
60-
return {
61-
status: "error",
62-
message: "Failed to load versions",
63-
versions: [],
64-
};
73+
throwUserFacingPayloadResponse({
74+
headline: "Package not found.",
75+
description: "We could not find the requested package.",
76+
category: "not_found",
77+
status: 404,
78+
});
6579
}
6680

6781
export default function Versions() {
68-
const { communityId, namespaceId, packageId, status, message, versions } =
69-
useLoaderData<typeof loader | typeof clientLoader>();
70-
71-
if (status === "error") {
72-
return <div>{message}</div>;
73-
}
82+
const { communityId, namespaceId, packageId, versions } = useLoaderData<
83+
typeof loader | typeof clientLoader
84+
>();
7485

7586
return (
7687
<Suspense fallback={<SkeletonBox className="package-versions__skeleton" />}>
77-
<Await resolve={versions}>
88+
<Await resolve={versions} errorElement={<NimbusAwaitErrorElement />}>
7889
{(resolvedValue) => (
7990
<div className="package-versions">
8091
<ModManagerBanner />
@@ -133,6 +144,10 @@ export default function Versions() {
133144
);
134145
}
135146

147+
export function ErrorBoundary() {
148+
return <NimbusDefaultRouteErrorBoundary />;
149+
}
150+
136151
export const columns: NewTableLabels = [
137152
{
138153
value: "Version",

0 commit comments

Comments
 (0)