Skip to content

Commit c432dc4

Browse files
committed
Refactor API methods and enhance type safety
- Updated community and package-related API methods to utilize structured parameters, improving clarity and maintainability. - Enhanced error handling in upload processes and API fetch functions to provide clearer feedback on validation errors. - Removed deprecated schemas and cleaned up imports for better organization and readability. - Introduced new request and response schemas for improved type safety and validation using Zod. - Streamlined the codebase by removing legacy components and comments, enhancing overall maintainability.
1 parent fcbc8b6 commit c432dc4

36 files changed

+818
-604
lines changed

apps/cyberstorm-remix/app/communities/communities.tsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ const selectOptions = [
6363

6464
export async function loader({ request }: LoaderFunctionArgs) {
6565
const searchParams = new URL(request.url).searchParams;
66-
const order = searchParams.get("order") ?? SortOptions.Popular;
66+
const order = searchParams.get("order");
6767
const search = searchParams.get("search");
6868
const page = undefined;
6969
const dapper = new DapperTs(() => {
@@ -72,7 +72,11 @@ export async function loader({ request }: LoaderFunctionArgs) {
7272
sessionId: undefined,
7373
};
7474
});
75-
return await dapper.getCommunities(page, order ?? "", search ?? "");
75+
return await dapper.getCommunities(
76+
page,
77+
order === null ? undefined : order,
78+
search === null ? undefined : search
79+
);
7680
}
7781

7882
export async function clientLoader({ request }: LoaderFunctionArgs) {

apps/cyberstorm-remix/app/settings/user/Account/Account.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import {
66
FormTextInput,
77
useFormToaster,
88
} from "@thunderstore/cyberstorm-forms";
9-
import { currentUserSchema } from "@thunderstore/dapper-ts";
109
import { faTrashCan } from "@fortawesome/pro-solid-svg-icons";
1110
import {
1211
ApiForm,
@@ -40,7 +39,7 @@ export async function clientLoader() {
4039
} else {
4140
return {
4241
config: getConfig(_storage),
43-
currentUser: currentUser as typeof currentUserSchema._type,
42+
currentUser: currentUser,
4443
};
4544
}
4645
}

apps/cyberstorm-remix/app/upload/upload.tsx

Lines changed: 83 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -33,17 +33,22 @@ import {
3333
faArrowUpRight,
3434
} from "@fortawesome/pro-solid-svg-icons";
3535
import { UserMedia } from "@thunderstore/ts-uploader/src/client/types";
36-
import { DapperTs, PackageSubmissionResponse } from "@thunderstore/dapper-ts";
36+
import { DapperTs } from "@thunderstore/dapper-ts";
3737
import { MetaFunction } from "@remix-run/node";
3838
import { useLoaderData } from "@remix-run/react";
39-
import {
40-
packageSubmissionErrorSchema,
41-
packageSubmissionStatusSchema,
42-
} from "@thunderstore/dapper-ts/src/methods/package";
39+
// import {
40+
// packageSubmissionErrorSchema,
41+
// packageSubmissionStatusSchema,
42+
// } from "@thunderstore/dapper-ts/src/methods/package";
4343
import {
4444
PackageSubmissionResult,
4545
PackageSubmissionStatus,
4646
} from "@thunderstore/dapper/types";
47+
import {
48+
PackageSubmissionError,
49+
packageSubmissionErrorSchema,
50+
packageSubmissionStatusSchema,
51+
} from "@thunderstore/thunderstore-api";
4752

4853
interface CommunityOption {
4954
value: string;
@@ -107,7 +112,7 @@ export default function Upload() {
107112

108113
// Teams do not have a separate identifier, the team name is the identifier
109114
useEffect(() => {
110-
setAvailableTeams(session.getSessionCurrentUser()?.teams ?? []);
115+
setAvailableTeams(session.getSessionCurrentUser()?.teams_full ?? []);
111116
}, [session]);
112117

113118
const [NSFW, setNSFW] = useState<boolean>(false);
@@ -146,8 +151,9 @@ export default function Upload() {
146151

147152
const [submissionStatus, setSubmissionStatus] =
148153
useState<PackageSubmissionStatus>();
149-
const [submissionError, setSubmissionError] =
150-
useState<PackageSubmissionResponse>({});
154+
const [submissionError, setSubmissionError] = useState<
155+
PackageSubmissionError | undefined
156+
>();
151157

152158
const startUpload = useCallback(async () => {
153159
// console.log("Starting upload");
@@ -187,12 +193,20 @@ export default function Upload() {
187193
const submit = useCallback(async () => {
188194
if (!usermedia?.uuid) {
189195
setSubmissionError({
196+
upload_uuid: null,
197+
author_name: null,
198+
categories: null,
199+
communities: null,
200+
has_nsfw_content: null,
201+
detail: null,
202+
file: null,
203+
team: null,
190204
__all__: ["Upload not completed"],
191205
});
192206
return;
193207
}
194208

195-
setSubmissionError({});
209+
setSubmissionError(undefined);
196210
const config = session.getConfig();
197211
const dapper = new DapperTs(() => config);
198212
const result = await dapper.postPackageSubmissionMetadata(
@@ -215,15 +229,24 @@ export default function Upload() {
215229
} else {
216230
// Check if the submission request had an error
217231
// console.log("Submission error:", result);
218-
if (packageSubmissionErrorSchema.safeParse(result).success) {
219-
setSubmissionError(result);
232+
const errorParsed = packageSubmissionErrorSchema.safeParse(result);
233+
if (errorParsed.success) {
234+
setSubmissionError(errorParsed.data);
220235
return;
221236
}
222237
}
223238

224239
// Handle successful submission
225240
if ("task_error" in result && result.task_error) {
226241
setSubmissionError({
242+
upload_uuid: null,
243+
author_name: null,
244+
categories: null,
245+
communities: null,
246+
has_nsfw_content: null,
247+
detail: null,
248+
file: null,
249+
team: null,
227250
__all__: [`Submission failed: ${result.result}`],
228251
});
229252
return;
@@ -255,16 +278,44 @@ export default function Upload() {
255278
}
256279
}, [selectedCommunities]);
257280

258-
const pollSubmission = async (submissionId: string) => {
281+
const pollSubmission = async (
282+
submissionId: string
283+
): Promise<
284+
| { success: true; data: PackageSubmissionStatus }
285+
| { success: false; data: PackageSubmissionError }
286+
> => {
259287
console.log("Polling submission status");
260288
// Wait 5 seconds before polling again
261289
await new Promise((resolve) => setTimeout(resolve, 5000));
262290
const result = await window.Dapper.getPackageSubmissionStatus(submissionId);
263291
const parsedResult = packageSubmissionStatusSchema.safeParse(result);
264292
if (parsedResult.success) {
265-
return { success: true, data: parsedResult.data };
293+
return {
294+
success: true,
295+
data: parsedResult.data as PackageSubmissionStatus,
296+
};
266297
} else {
267-
return { success: false, data: parsedResult.data };
298+
const errorParsed = packageSubmissionErrorSchema.safeParse(result);
299+
if (errorParsed.success) {
300+
return {
301+
success: false,
302+
data: errorParsed.data as PackageSubmissionError,
303+
};
304+
}
305+
return {
306+
success: false,
307+
data: {
308+
upload_uuid: null,
309+
author_name: null,
310+
categories: null,
311+
communities: null,
312+
has_nsfw_content: null,
313+
detail: null,
314+
file: null,
315+
team: null,
316+
__all__: ["Error while polling submission status"],
317+
},
318+
};
268319
}
269320
};
270321

@@ -294,18 +345,20 @@ export default function Upload() {
294345
submissionStatusRef.current = data.data;
295346
setSubmissionStatus(data.data);
296347
} else {
297-
if (data.data) {
298-
setSubmissionError(data.data);
299-
} else {
300-
setSubmissionError({
301-
__all__: ["Unable to check submission status"],
302-
});
303-
}
348+
setSubmissionError(data.data);
304349
}
305350
},
306351
// eslint-disable-next-line @typescript-eslint/no-unused-vars
307352
(_error) => {
308353
setSubmissionError({
354+
upload_uuid: null,
355+
author_name: null,
356+
categories: null,
357+
communities: null,
358+
has_nsfw_content: null,
359+
detail: null,
360+
file: null,
361+
team: null,
309362
__all__: ["Unable to check submission status"],
310363
});
311364
}
@@ -361,6 +414,14 @@ export default function Upload() {
361414
// eslint-disable-next-line @typescript-eslint/no-unused-vars
362415
(_error) => {
363416
setSubmissionError({
417+
upload_uuid: null,
418+
author_name: null,
419+
categories: null,
420+
communities: null,
421+
has_nsfw_content: null,
422+
detail: null,
423+
file: null,
424+
team: null,
364425
__all__: ["Unable to check submission status"],
365426
});
366427
}
@@ -663,7 +724,7 @@ export default function Upload() {
663724
<p>Please select at least one community.</p>
664725
</div>
665726
)}
666-
{Object.keys(submissionError).length > 0 && (
727+
{submissionError && Object.keys(submissionError).length > 0 && (
667728
<div className="upload__error">
668729
{Object.entries(submissionError).map(([field, errors]) => (
669730
<div key={field}>

packages/cyberstorm-forms/package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,9 @@
2222
"@radix-ui/react-select": "^2.1.1",
2323
"@thunderstore/cyberstorm": "*",
2424
"@thunderstore/dapper": "^0.1.0",
25-
"@thunderstore/thunderstore-api": "*",
26-
"@thunderstore/ts-api-react-actions": "*",
27-
"@thunderstore/ts-api-react-forms": "*",
25+
"@thunderstore/thunderstore-api": "^0.1.0",
26+
"@thunderstore/ts-api-react-actions": "^0.1.0",
27+
"@thunderstore/ts-api-react-forms": "^0.1.0",
2828
"@thunderstore/use-promise": "^0.1.0",
2929
"@types/react": "^18.3.8",
3030
"react": "^18.3.1",

packages/cyberstorm-forms/src/forms/DisbandTeamForm.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import {
1515
} from "@thunderstore/cyberstorm-forms";
1616

1717
import { CyberstormLink } from "@thunderstore/cyberstorm";
18-
import { teamDisbandRequestParamsSchema } from "@thunderstore/thunderstore-api/src/schemas/requestSchemas";
18+
import { teamDisbandRequestParamsSchema } from "@thunderstore/thunderstore-api";
1919

2020
export function DisbandTeamForm(props: {
2121
teamName: string;

packages/dapper-ts/src/index.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@ import { getDynamicHTML } from "./methods/dynamicHTML";
55
import { getCommunities, getCommunity } from "./methods/communities";
66
import { getCommunityFilters } from "./methods/communityFilters";
77
import { getRatedPackages } from "./methods/ratedPackages";
8-
export { ratedPackagesSchema } from "./methods/ratedPackages";
9-
import { getCurrentUser, emptyUser } from "./methods/currentUser";
10-
export const getEmptyUser = emptyUser;
11-
export { dependencyShema } from "./methods/packageListings";
12-
export { currentUserSchema } from "./methods/currentUser";
8+
// export { ratedPackagesSchema } from "./methods/ratedPackages";
9+
import { getCurrentUser } from "./methods/currentUser";
10+
// export const getEmptyUser = emptyUser;
11+
// export { dependencyShema } from "./methods/packageListings";
12+
// export { currentUserSchema } from "./methods/currentUser";
1313
import {
1414
getPackageChangelog,
1515
getPackageReadme,
@@ -26,7 +26,7 @@ import {
2626
getTeamMembers,
2727
getTeamServiceAccounts,
2828
} from "./methods/team";
29-
export type { PackageSubmissionResponse } from "./methods/package";
29+
// export type { PackageSubmissionResponse } from "./methods/package";
3030

3131
export interface DapperTsInterface extends DapperInterface {
3232
config: () => RequestConfig;
Lines changed: 31 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,54 @@
11
import {
2+
CommunityListOrderingEnum,
23
fetchCommunity,
34
fetchCommunityList,
45
} from "@thunderstore/thunderstore-api";
56

67
import { DapperTsInterface } from "../index";
7-
import { formatErrorMessage } from "../utils";
88

99
export async function getCommunities(
1010
this: DapperTsInterface,
11-
page = 1,
12-
ordering = "name",
11+
page?: number,
12+
ordering?: string,
1313
search?: string
1414
) {
15-
const data = await fetchCommunityList(this.config, page, ordering, search);
16-
const parsed = communitiesSchema.safeParse(data);
17-
18-
if (!parsed.success) {
19-
throw new Error(formatErrorMessage(parsed.error));
15+
let supportedOrdering = undefined;
16+
// As dapper accepts more options, than the TS api at this time, we'll need to check if the given ordering is supported.
17+
if (ordering && ordering in CommunityListOrderingEnum) {
18+
supportedOrdering = ordering as CommunityListOrderingEnum;
2019
}
20+
const data = await fetchCommunityList({
21+
config: this.config,
22+
queryParams: [
23+
{ key: "page", value: page, impotent: 1 },
24+
{
25+
key: "ordering",
26+
value: supportedOrdering,
27+
impotent: CommunityListOrderingEnum.Popular,
28+
},
29+
{ key: "search", value: search },
30+
],
31+
params: {},
32+
data: {},
33+
});
2134

2235
return {
23-
count: parsed.data.count,
24-
hasMore: Boolean(parsed.data.next),
25-
results: parsed.data.results,
36+
count: data.count,
37+
hasMore: Boolean(data.next),
38+
results: data.results,
2639
};
2740
}
2841

2942
export async function getCommunity(
3043
this: DapperTsInterface,
3144
communityId: string
3245
) {
33-
const data = await fetchCommunity(this.config, communityId);
34-
const parsed = communitySchema.safeParse(data);
35-
36-
if (!parsed.success) {
37-
throw new Error(formatErrorMessage(parsed.error));
38-
}
46+
const data = await fetchCommunity({
47+
config: this.config,
48+
params: { community_id: communityId },
49+
data: {},
50+
queryParams: {},
51+
});
3952

40-
return parsed.data;
53+
return data;
4154
}
Lines changed: 7 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,17 @@
1-
import { z } from "zod";
21
import { fetchCommunityFilters } from "@thunderstore/thunderstore-api";
32

43
import { DapperTsInterface } from "../index";
5-
import { PackageCategory } from "../sharedSchemas";
6-
import { formatErrorMessage } from "../utils";
7-
8-
const Section = z.object({
9-
uuid: z.string().uuid(),
10-
name: z.string().nonempty(),
11-
slug: z.string().nonempty(),
12-
priority: z.number().int(),
13-
});
14-
15-
const schema = z.object({
16-
package_categories: PackageCategory.array(),
17-
sections: Section.array(),
18-
});
194

205
export async function getCommunityFilters(
216
this: DapperTsInterface,
227
communityId: string
238
) {
24-
const data = await fetchCommunityFilters(this.config, communityId);
25-
const parsed = schema.safeParse(data);
26-
27-
if (!parsed.success) {
28-
throw new Error(formatErrorMessage(parsed.error));
29-
}
9+
const data = await fetchCommunityFilters({
10+
config: this.config,
11+
params: { community_id: communityId },
12+
data: {},
13+
queryParams: {},
14+
});
3015

31-
return parsed.data;
16+
return data;
3217
}

0 commit comments

Comments
 (0)