diff --git a/apps/cyberstorm-remix/app/p/packageListing.tsx b/apps/cyberstorm-remix/app/p/packageListing.tsx
index a28757665..e04e61be6 100644
--- a/apps/cyberstorm-remix/app/p/packageListing.tsx
+++ b/apps/cyberstorm-remix/app/p/packageListing.tsx
@@ -55,6 +55,7 @@ import {
import { PackageLikeAction } from "@thunderstore/cyberstorm-forms";
import type { CurrentUser } from "@thunderstore/dapper/types";
import { DapperTs, type DapperTsInterface } from "@thunderstore/dapper-ts";
+import { getDapperForRequest } from "cyberstorm/utils/dapperSingleton";
import { getPublicListing, getPrivateListing } from "./listingUtils";
import { ManagementTools } from "./components/PackageListing/ManagementTools";
@@ -132,7 +133,7 @@ async function getPackageListingStatus(
return undefined;
}
-export async function clientLoader({ params }: LoaderFunctionArgs) {
+export async function clientLoader({ params, request }: LoaderFunctionArgs) {
const { communityId, namespaceId, packageId } = params;
if (!communityId || !namespaceId || !packageId) {
@@ -140,11 +141,7 @@ export async function clientLoader({ params }: LoaderFunctionArgs) {
}
const tools = getSessionTools();
- const config = tools.getConfig();
- const dapper = new DapperTs(() => ({
- apiHost: config.apiHost,
- sessionId: config.sessionId,
- }));
+ const dapper = getDapperForRequest(request);
const listing = await getPrivateListing(dapper, {
communityId,
diff --git a/apps/cyberstorm-remix/app/p/packageListingVersion.tsx b/apps/cyberstorm-remix/app/p/packageListingVersion.tsx
index 26a070927..ef9418478 100644
--- a/apps/cyberstorm-remix/app/p/packageListingVersion.tsx
+++ b/apps/cyberstorm-remix/app/p/packageListingVersion.tsx
@@ -40,10 +40,8 @@ import {
import { DapperTs } from "@thunderstore/dapper-ts";
import { type OutletContextShape } from "~/root";
import { CopyButton } from "~/commonComponents/CopyButton/CopyButton";
-import {
- getPublicEnvVariables,
- getSessionTools,
-} from "cyberstorm/security/publicEnvVariables";
+import { getPublicEnvVariables } from "cyberstorm/security/publicEnvVariables";
+import { getDapperForRequest } from "cyberstorm/utils/dapperSingleton";
import { getPrivateListing, getPublicListing } from "./listingUtils";
import {
type PackageListingDetails,
@@ -77,19 +75,14 @@ export async function loader({ params }: LoaderFunctionArgs) {
};
}
-export async function clientLoader({ params }: LoaderFunctionArgs) {
+export async function clientLoader({ params, request }: LoaderFunctionArgs) {
const { communityId, namespaceId, packageId, packageVersion } = params;
if (!communityId || !namespaceId || !packageId || !packageVersion) {
throw new Response("Package not found", { status: 404 });
}
- const tools = getSessionTools();
- const config = tools.getConfig();
- const dapper = new DapperTs(() => ({
- apiHost: config.apiHost,
- sessionId: config.sessionId,
- }));
+ const dapper = getDapperForRequest(request);
const listing = await getPrivateListing(dapper, {
communityId,
diff --git a/apps/cyberstorm-remix/app/p/tabs/Required/PackageVersionRequired.tsx b/apps/cyberstorm-remix/app/p/tabs/Required/PackageVersionRequired.tsx
deleted file mode 100644
index bd8d99c21..000000000
--- a/apps/cyberstorm-remix/app/p/tabs/Required/PackageVersionRequired.tsx
+++ /dev/null
@@ -1,89 +0,0 @@
-import { Suspense } from "react";
-import { type LoaderFunctionArgs } from "react-router";
-import { useLoaderData, Await } from "react-router";
-import { DapperTs } from "@thunderstore/dapper-ts";
-import { SkeletonBox } from "@thunderstore/cyberstorm";
-import { PaginatedDependencies } from "~/commonComponents/PaginatedDependencies/PaginatedDependencies";
-import {
- getPublicEnvVariables,
- getSessionTools,
-} from "cyberstorm/security/publicEnvVariables";
-
-export async function loader({ params, request }: LoaderFunctionArgs) {
- if (params.namespaceId && params.packageId && params.packageVersion) {
- const publicEnvVariables = getPublicEnvVariables(["VITE_API_URL"]);
- const dapper = new DapperTs(() => {
- return {
- apiHost: publicEnvVariables.VITE_API_URL,
- sessionId: undefined,
- };
- });
- const searchParams = new URL(request.url).searchParams;
- const page = searchParams.get("page");
-
- return {
- version: await dapper.getPackageVersionDetails(
- params.namespaceId,
- params.packageId,
- params.packageVersion
- ),
- dependencies: await dapper.getPackageVersionDependencies(
- params.namespaceId,
- params.packageId,
- params.packageVersion,
- page === null ? undefined : Number(page)
- ),
- };
- }
- throw new Response("Package version dependencies not found", { status: 404 });
-}
-
-export async function clientLoader({ params, request }: LoaderFunctionArgs) {
- if (params.namespaceId && params.packageId && params.packageVersion) {
- const tools = getSessionTools();
- const dapper = new DapperTs(() => {
- return {
- apiHost: tools?.getConfig().apiHost,
- sessionId: tools?.getConfig().sessionId,
- };
- });
- const searchParams = new URL(request.url).searchParams;
- const page = searchParams.get("page");
-
- return {
- version: dapper.getPackageVersionDetails(
- params.namespaceId,
- params.packageId,
- params.packageVersion
- ),
- dependencies: dapper.getPackageVersionDependencies(
- params.namespaceId,
- params.packageId,
- params.packageVersion,
- page === null ? undefined : Number(page)
- ),
- };
- }
- throw new Response("Package version dependencies not found", { status: 404 });
-}
-
-export default function PackageVersionRequired() {
- const { dependencies } = useLoaderData();
-
- return (
- }
- >
- Error occurred while loading required dependencies
- }
- >
- {(resolvedDependencies) => (
-
- )}
-
-
- );
-}
diff --git a/apps/cyberstorm-remix/app/p/tabs/Required/PackageVersionWithoutCommunityRequired.tsx b/apps/cyberstorm-remix/app/p/tabs/Required/PackageVersionWithoutCommunityRequired.tsx
deleted file mode 100644
index af6cdd0ac..000000000
--- a/apps/cyberstorm-remix/app/p/tabs/Required/PackageVersionWithoutCommunityRequired.tsx
+++ /dev/null
@@ -1,89 +0,0 @@
-import { Suspense } from "react";
-import { type LoaderFunctionArgs } from "react-router";
-import { useLoaderData, Await } from "react-router";
-import { DapperTs } from "@thunderstore/dapper-ts";
-import { SkeletonBox } from "@thunderstore/cyberstorm";
-import { PaginatedDependencies } from "~/commonComponents/PaginatedDependencies/PaginatedDependencies";
-import {
- getPublicEnvVariables,
- getSessionTools,
-} from "cyberstorm/security/publicEnvVariables";
-
-export async function loader({ params, request }: LoaderFunctionArgs) {
- if (params.namespaceId && params.packageId && params.packageVersion) {
- const publicEnvVariables = getPublicEnvVariables(["VITE_API_URL"]);
- const dapper = new DapperTs(() => {
- return {
- apiHost: publicEnvVariables.VITE_API_URL,
- sessionId: undefined,
- };
- });
- const searchParams = new URL(request.url).searchParams;
- const page = searchParams.get("page");
-
- return {
- version: await dapper.getPackageVersionDetails(
- params.namespaceId,
- params.packageId,
- params.packageVersion
- ),
- dependencies: await dapper.getPackageVersionDependencies(
- params.namespaceId,
- params.packageId,
- params.packageVersion,
- page === null ? undefined : Number(page)
- ),
- };
- }
- throw new Response("Package version dependencies not found", { status: 404 });
-}
-
-export async function clientLoader({ params, request }: LoaderFunctionArgs) {
- if (params.namespaceId && params.packageId && params.packageVersion) {
- const tools = getSessionTools();
- const dapper = new DapperTs(() => {
- return {
- apiHost: tools?.getConfig().apiHost,
- sessionId: tools?.getConfig().sessionId,
- };
- });
- const searchParams = new URL(request.url).searchParams;
- const page = searchParams.get("page");
-
- return {
- version: dapper.getPackageVersionDetails(
- params.namespaceId,
- params.packageId,
- params.packageVersion
- ),
- dependencies: dapper.getPackageVersionDependencies(
- params.namespaceId,
- params.packageId,
- params.packageVersion,
- page === null ? undefined : Number(page)
- ),
- };
- }
- throw new Response("Package version dependencies not found", { status: 404 });
-}
-
-export default function PackageVersionWithoutCommunityRequired() {
- const { dependencies } = useLoaderData();
-
- return (
- }
- >
- Error occurred while loading required dependencies
- }
- >
- {(resolvedDependencies) => (
-
- )}
-
-
- );
-}
diff --git a/apps/cyberstorm-remix/app/p/tabs/Required/Required.tsx b/apps/cyberstorm-remix/app/p/tabs/Required/Required.tsx
index 64d76108c..d2fcace55 100644
--- a/apps/cyberstorm-remix/app/p/tabs/Required/Required.tsx
+++ b/apps/cyberstorm-remix/app/p/tabs/Required/Required.tsx
@@ -1,84 +1,108 @@
import { Suspense } from "react";
-import { type LoaderFunctionArgs } from "react-router";
-import { useLoaderData, Await } from "react-router";
-import { DapperTs } from "@thunderstore/dapper-ts";
+import { Await, type LoaderFunctionArgs, useLoaderData } from "react-router";
+
import { SkeletonBox } from "@thunderstore/cyberstorm";
-import { PaginatedDependencies } from "~/commonComponents/PaginatedDependencies/PaginatedDependencies";
-import {
- getPublicEnvVariables,
- getSessionTools,
-} from "cyberstorm/security/publicEnvVariables";
+import { DapperTs } from "@thunderstore/dapper-ts";
+
+import { PaginatedDependencies } from "app/commonComponents/PaginatedDependencies/PaginatedDependencies";
+import { getPrivateListing, getPublicListing } from "app/p/listingUtils";
+import { getPublicEnvVariables } from "cyberstorm/security/publicEnvVariables";
+import { getDapperForRequest } from "cyberstorm/utils/dapperSingleton";
+
+const Dependency404 = new Response("Package dependencies not found", {
+ status: 404,
+});
+
+const getPageFromUrl = (url: string): number | undefined => {
+ const searchParams = new URL(url).searchParams;
+ const maybePage = searchParams.get("page");
+ return maybePage ? Number(maybePage) : undefined;
+};
export async function loader({ params, request }: LoaderFunctionArgs) {
- if (params.communityId && params.namespaceId && params.packageId) {
- const publicEnvVariables = getPublicEnvVariables(["VITE_API_URL"]);
- const dapper = new DapperTs(() => {
- return {
- apiHost: publicEnvVariables.VITE_API_URL,
- sessionId: undefined,
- };
- });
- const searchParams = new URL(request.url).searchParams;
- const page = searchParams.get("page");
- const listing = await dapper.getPackageListingDetails(
- params.communityId,
- params.namespaceId,
- params.packageId
- );
-
- return {
- version: await dapper.getPackageVersionDetails(
- params.namespaceId,
- params.packageId,
- listing.latest_version_number
- ),
- dependencies: await dapper.getPackageVersionDependencies(
- params.namespaceId,
- params.packageId,
- listing.latest_version_number,
- page === null ? undefined : Number(page)
- ),
- };
+ const { communityId, namespaceId, packageId, packageVersion } = params;
+
+ // Either communityId or packageVersion is required depending on route.
+ if (!namespaceId || !packageId || (!communityId && !packageVersion)) {
+ throw Dependency404;
+ }
+
+ const publicEnvVariables = getPublicEnvVariables(["VITE_API_URL"]);
+ const dapper = new DapperTs(() => ({
+ apiHost: publicEnvVariables.VITE_API_URL,
+ sessionId: undefined,
+ }));
+
+ let version: string;
+
+ if (packageVersion) {
+ version = packageVersion;
+ } else if (communityId) {
+ const listingArgs = { communityId, namespaceId, packageId };
+ const listing = await getPublicListing(dapper, listingArgs);
+
+ // Listing that's not available on unauthenticated SSR request
+ // might be available for authenticated user on client. Return
+ // undefined rather than throw error to allow refetch on client.
+ if (!listing) {
+ return { dependencies: undefined };
+ }
+
+ version = listing.latest_version_number;
+ } else {
+ throw Dependency404; // Can't happen, satisfies TypeScript
}
- throw new Response("Package version dependencies not found", { status: 404 });
+
+ return {
+ dependencies: await dapper.getPackageVersionDependencies(
+ namespaceId,
+ packageId,
+ version,
+ getPageFromUrl(request.url)
+ ),
+ };
}
export async function clientLoader({ params, request }: LoaderFunctionArgs) {
- if (params.communityId && params.namespaceId && params.packageId) {
- const tools = getSessionTools();
- const dapper = new DapperTs(() => {
- return {
- apiHost: tools?.getConfig().apiHost,
- sessionId: tools?.getConfig().sessionId,
- };
- });
- const searchParams = new URL(request.url).searchParams;
- const page = searchParams.get("page");
- const listing = await dapper.getPackageListingDetails(
- params.communityId,
- params.namespaceId,
- params.packageId
- );
-
- return {
- version: dapper.getPackageVersionDetails(
- params.namespaceId,
- params.packageId,
- listing.latest_version_number
- ),
- dependencies: dapper.getPackageVersionDependencies(
- params.namespaceId,
- params.packageId,
- listing.latest_version_number,
- page === null ? undefined : Number(page)
- ),
- };
+ const { communityId, namespaceId, packageId, packageVersion } = params;
+
+ // Either communityId or packageVersion is required depending on route.
+ if (!namespaceId || !packageId || (!communityId && !packageVersion)) {
+ throw Dependency404;
}
- throw new Response("Package version dependencies not found", { status: 404 });
+
+ const dapper = getDapperForRequest(request);
+ let version: string;
+
+ if (packageVersion) {
+ version = packageVersion;
+ } else if (communityId) {
+ const listingArgs = { communityId, namespaceId, packageId };
+ const listing = await getPrivateListing(dapper, listingArgs);
+ version = listing.latest_version_number;
+ } else {
+ throw Dependency404; // Can't happen, satisfies TypeScript
+ }
+
+ return {
+ dependencies: dapper.getPackageVersionDependencies(
+ namespaceId,
+ packageId,
+ version,
+ getPageFromUrl(request.url)
+ ),
+ };
}
+clientLoader.hydrate = true;
+
export default function PackageVersionRequired() {
- const { dependencies } = useLoaderData();
+ const { dependencies } = useLoaderData();
+
+ // SSR failed to fetch, retry as authenticated user on client.
+ if (dependencies === undefined) {
+ return ;
+ }
return (