@@ -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" ;
1510import { NewButton , NewIcon , SkeletonBox } from "@thunderstore/cyberstorm" ;
1611import { faPlus } from "@fortawesome/pro-solid-svg-icons" ;
1712import { FontAwesomeIcon } from "@fortawesome/react-fontawesome" ;
1813import { type OutletContextShape } from "~/root" ;
1914import { 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
2331export 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
6161export 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+ */
9297export 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+ }
0 commit comments