Skip to content

Commit 8373173

Browse files
committed
Revert "feat: upgrade zod to v4"
This reverts commit 417d7bd.
1 parent 417d7bd commit 8373173

14 files changed

Lines changed: 90 additions & 88 deletions

File tree

package-lock.json

Lines changed: 14 additions & 14 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/backend/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,6 @@
3434
"@trpc/server": "10.45.2",
3535
"@tsndr/cloudflare-worker-jwt": "^3.2.0",
3636
"toucan-js": "^4.1.1",
37-
"zod": "^4.1.5"
37+
"zod": "^3.25.76"
3838
}
3939
}
Lines changed: 22 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1+
import { infer as zodInfer, SafeParseReturnType, ZodTypeAny } from "zod";
12
import { TRPCError } from "@trpc/server";
2-
import type { output, infer as zodInfer, ZodSafeParseResult, ZodTypeAny } from "zod";
33

44
export class KvWrapper {
5-
constructor(private readonly kv: KVNamespace) {}
5+
constructor(private kv: KVNamespace) {}
66

77
async get<T extends ZodTypeAny>(parser: T, key: string): Promise<zodInfer<T>> {
8-
const json = await this.kv.get<zodInfer<T>>(key, "json");
9-
if (json == null) {
8+
const json = await this.kv.get(key, "json");
9+
if (!json) {
1010
throw new TRPCError({ code: "NOT_FOUND" });
1111
}
1212
return parser.parse(json);
@@ -15,56 +15,50 @@ export class KvWrapper {
1515
async safeGet<T extends ZodTypeAny>(
1616
parser: T,
1717
key: string,
18-
): Promise<ZodSafeParseResult<output<T>>> {
19-
const json = await this.kv.get<zodInfer<T>>(key, "json");
18+
): Promise<SafeParseReturnType<T, zodInfer<T>>> {
19+
const json = await this.kv.get(key, "json");
2020
return parser.safeParse(json);
2121
}
2222

2323
async getOptional<T extends ZodTypeAny>(
2424
parser: T,
2525
key: string,
2626
): Promise<zodInfer<T> | undefined> {
27-
const value = await this.safeGet<T>(parser, key);
28-
return value.success ? value.data : undefined;
27+
try {
28+
const value = await this.get(parser, key);
29+
return value;
30+
} catch (_) {
31+
return undefined;
32+
}
2933
}
3034

31-
async getUnsafe<T>(key: string) {
32-
return this.kv.get<T>(key, "json");
35+
getUnsafe(key: string) {
36+
return this.kv.get(key, "json");
3337
}
3438

35-
async getAll<T extends ZodTypeAny>(parser: T): Promise<Array<zodInfer<T>>> {
39+
async getAll<T extends ZodTypeAny>(parser: T): Promise<zodInfer<T>[]> {
3640
const list = await this.kv.list();
3741
const possiblyNullJson = await Promise.all(
38-
list.keys.map(async (key) => {
39-
const value = await this.safeGet<T>(parser, key.name);
40-
return value.success ? value.data : null;
41-
}),
42+
list.keys.map((key) => this.kv.get(key.name, "json")),
4243
);
43-
return possiblyNullJson.filter((json) => json != null);
44-
}
45-
46-
async safeGetAll<T extends ZodTypeAny>(
47-
parser: T,
48-
): Promise<Array<ZodSafeParseResult<output<T>>>> {
49-
const list = await this.kv.list();
50-
return Promise.all(list.keys.map(async (key) => this.safeGet<T>(parser, key.name)));
44+
return possiblyNullJson.filter((exists) => exists).map((json) => parser.parse(json));
5145
}
5246

53-
async put<T extends ZodTypeAny, U extends zodInfer<T>>(
47+
put<T extends ZodTypeAny, U extends zodInfer<T>>(
5448
parser: T,
5549
key: string,
5650
data: U,
5751
options?: KVNamespacePutOptions,
5852
) {
5953
const parsed = parser.parse(data);
60-
await this.kv.put(key, JSON.stringify(parsed), options);
54+
return this.kv.put(key, JSON.stringify(parsed), options);
6155
}
6256

63-
async delete(key: string) {
64-
await this.kv.delete(key);
57+
delete(key: string) {
58+
return this.kv.delete(key);
6559
}
6660

67-
async list(options?: KVNamespaceListOptions) {
61+
list(options?: KVNamespaceListOptions) {
6862
return this.kv.list(options);
6963
}
7064
}

packages/backend/src/dao/rating-analyzer-dao.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ interface PerspectiveRequestedAttribute {
102102
}
103103

104104
const analyzeCommentResponseParser = z.object({
105-
attributeScores: z.record(z.string(), perspectiveAttributeScoreParser),
105+
attributeScores: z.record(perspectiveAttributeScoreParser),
106106
languages: z.string().array(),
107107
clientToken: z.string(),
108108
});

packages/backend/src/routers/admin.ts

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,19 @@ import { addRating } from "@backend/types/schemaHelpers";
44
import { bulkKeys, DEPARTMENT_LIST } from "@backend/utils/const";
55

66
const changeDepartmentParser = z.object({
7-
professorId: z.uuid(),
7+
professorId: z.string().uuid(),
88
department: z.enum(DEPARTMENT_LIST),
99
});
1010

1111
const changeNameParser = z.object({
12-
professorId: z.uuid(),
12+
professorId: z.string().uuid(),
1313
firstName: z.string().trim(),
1414
lastName: z.string().trim(),
1515
});
1616

1717
const fixEscapedCharsParser = z.object({
1818
professors: z
19-
.array(z.uuid())
19+
.array(z.string().uuid())
2020
.min(1)
2121
.max(250, "Separate your request into batches of 250 professors."),
2222
});
@@ -30,22 +30,28 @@ export const adminRouter = t.router({
3030
getPendingProfessors: protectedProcedure.query(({ ctx }) =>
3131
ctx.env.kvDao.getAllPendingProfessors(),
3232
),
33-
approvePendingProfessor: protectedProcedure.input(z.uuid()).mutation(async ({ ctx, input }) => {
34-
const pendingProfessor = await ctx.env.kvDao.getPendingProfessor(input);
33+
approvePendingProfessor: protectedProcedure
34+
.input(z.string().uuid())
35+
.mutation(async ({ ctx, input }) => {
36+
const pendingProfessor = await ctx.env.kvDao.getPendingProfessor(input);
3537

36-
await ctx.env.kvDao.putProfessor(pendingProfessor);
37-
await ctx.env.kvDao.removePendingProfessor(input);
38-
}),
39-
rejectPendingProfessor: protectedProcedure.input(z.uuid()).mutation(async ({ input, ctx }) => {
40-
await ctx.env.kvDao.removePendingProfessor(input);
41-
}),
42-
removeProfessor: protectedProcedure.input(z.uuid()).mutation(async ({ input, ctx }) => {
43-
await ctx.env.kvDao.removeProfessor(input);
44-
}),
38+
await ctx.env.kvDao.putProfessor(pendingProfessor);
39+
await ctx.env.kvDao.removePendingProfessor(input);
40+
}),
41+
rejectPendingProfessor: protectedProcedure
42+
.input(z.string().uuid())
43+
.mutation(async ({ input, ctx }) => {
44+
await ctx.env.kvDao.removePendingProfessor(input);
45+
}),
46+
removeProfessor: protectedProcedure
47+
.input(z.string().uuid())
48+
.mutation(async ({ input, ctx }) => {
49+
await ctx.env.kvDao.removeProfessor(input);
50+
}),
4551

4652
// Takes reviews of target professor and applies them to dest and then removes the target professor
4753
mergeProfessor: protectedProcedure
48-
.input(z.object({ destId: z.uuid(), sourceId: z.uuid() }))
54+
.input(z.object({ destId: z.string().uuid(), sourceId: z.string().uuid() }))
4955
.mutation(async ({ ctx, input: { destId, sourceId } }) => {
5056
const destProfessor = await ctx.env.kvDao.getProfessor(destId);
5157
const sourceProfessor = await ctx.env.kvDao.getProfessor(sourceId);
@@ -96,10 +102,10 @@ export const adminRouter = t.router({
96102
.mutation(async ({ ctx, input: { bulkKey, keys } }) =>
97103
ctx.env.kvDao.getBulkValues(bulkKey, keys),
98104
),
99-
removeReport: protectedProcedure.input(z.uuid()).mutation(async ({ ctx, input }) => {
105+
removeReport: protectedProcedure.input(z.string().uuid()).mutation(async ({ ctx, input }) => {
100106
await ctx.env.kvDao.removeReport(input);
101107
}),
102-
actOnReport: protectedProcedure.input(z.uuid()).mutation(async ({ ctx, input }) => {
108+
actOnReport: protectedProcedure.input(z.string().uuid()).mutation(async ({ ctx, input }) => {
103109
const report = await ctx.env.kvDao.getReport(input);
104110
await ctx.env.kvDao.removeRating(report.professorId, report.ratingId);
105111
await ctx.env.kvDao.removeReport(input);

packages/backend/src/routers/professor.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,10 @@ import { addRating } from "./rating";
88
export const professorRouter = t.router({
99
all: t.procedure.query(({ ctx }) => ctx.env.kvDao.getAllProfessors()),
1010
get: t.procedure
11-
.input(z.object({ id: z.uuid() }))
11+
.input(z.object({ id: z.string().uuid() }))
1212
.query(({ input, ctx }) => ctx.env.kvDao.getProfessor(input.id)),
1313
getMany: t.procedure
14-
.input(z.object({ ids: z.array(z.uuid()) }))
14+
.input(z.object({ ids: z.array(z.string().uuid()) }))
1515
.query(({ input, ctx }) =>
1616
Promise.all(input.ids.map((id) => ctx.env.kvDao.getProfessor(id))),
1717
),
@@ -60,8 +60,7 @@ export const professorRouter = t.router({
6060
overallRating: input.rating.overallRating,
6161
materialClear: input.rating.presentsMaterialClearly,
6262
studentDifficulties: input.rating.recognizesStudentDifficulties,
63-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
64-
tags: tags as any,
63+
tags,
6564
reviews: {
6665
[`${input.rating.department} ${input.rating.courseNum}`]: [
6766
{

packages/backend/src/routers/rating.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { Env } from "@backend/env";
77

88
const addRatingParser = ratingBaseParser.merge(
99
z.object({
10-
professor: z.uuid(),
10+
professor: z.string().uuid(),
1111
department: z.enum(DEPARTMENT_LIST),
1212
courseNum: z.number().min(100).max(599),
1313
}),
@@ -80,7 +80,11 @@ export const ratingsRouter = t.router({
8080
.input(addRatingParser)
8181
.mutation(async ({ ctx, input }) => addRating(input, ctx)),
8282
report: t.procedure
83-
.input(reportParser.merge(z.object({ ratingId: z.uuid(), professorId: z.uuid() })))
83+
.input(
84+
reportParser.merge(
85+
z.object({ ratingId: z.string().uuid(), professorId: z.string().uuid() }),
86+
),
87+
)
8488
.mutation(async ({ ctx, input }) => {
8589
const anonymousIdentifier = await ctx.env.anonymousIdDao.getIdentifier();
8690
const ratingReport: RatingReport = {

packages/backend/src/types/schema.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@ export type RatingBase = z.infer<typeof ratingBaseParser>;
2424

2525
export const ratingParser = ratingBaseParser.merge(
2626
z.object({
27-
id: z.uuid(),
28-
professor: z.uuid(),
27+
id: z.string().uuid(),
28+
professor: z.string().uuid(),
2929
postDate: z.string(),
3030
}),
3131
);
@@ -55,15 +55,15 @@ export const pendingRatingParser = ratingParser.merge(
5555
z.object({
5656
status: z.enum(PENDING_RATING_STATUSES),
5757
error: z.nullable(z.string()),
58-
analyzedScores: z.nullable(z.record(z.string(), z.number())),
58+
analyzedScores: z.nullable(z.record(z.number())),
5959
courseNum: z.number().min(100).max(599),
6060
department: z.enum(DEPARTMENT_LIST),
6161
}),
6262
);
6363
export type PendingRating = z.infer<typeof pendingRatingParser>;
6464

6565
export const truncatedProfessorParser = z.object({
66-
id: z.uuid(),
66+
id: z.string().uuid(),
6767
department: z.enum(DEPARTMENT_LIST),
6868
firstName: z.string().trim(),
6969
lastName: z.string().trim(),
@@ -78,7 +78,7 @@ export type TruncatedProfessor = z.infer<typeof truncatedProfessorParser>;
7878

7979
export const professorParser = truncatedProfessorParser.merge(
8080
z.object({
81-
reviews: z.record(z.string(), z.array(ratingParser)),
81+
reviews: z.record(z.array(ratingParser)),
8282
}),
8383
);
8484
export type Professor = z.infer<typeof professorParser>;
@@ -95,8 +95,8 @@ export const reportParser = z.object({
9595
anonymousIdentifier: z.optional(z.string()),
9696
});
9797
export const ratingReportParser = z.object({
98-
ratingId: z.uuid(),
99-
professorId: z.uuid(),
98+
ratingId: z.string().uuid(),
99+
professorId: z.string().uuid(),
100100
reports: z.array(reportParser),
101101
});
102102

packages/backend/src/types/schemaHelpers.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,12 @@ export function addRating(professor: Professor, reviewUnparsed: Rating, courseNa
99
review.professor = professor.id;
1010

1111
// For migration purposes from old schema
12-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
13-
professor.tags ??= {} as any;
12+
professor.tags ??= {};
1413

1514
// Add tags to the professor
1615
for (const tag of review.tags ?? []) {
17-
const current = professor.tags![tag] ?? 0;
18-
professor.tags![tag] = current + 1;
16+
const current = professor.tags[tag] ?? 0;
17+
professor.tags[tag] = current + 1;
1918
}
2019

2120
const ratings = professor.reviews[courseName];

packages/frontend/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@
4141
"react-toastify": "^11.0.5",
4242
"tailwind-scrollbar-hide": "^1.3.1",
4343
"type-fest": "^4.41.0",
44-
"zod": "^4.1.5"
44+
"zod": "^3.25.76"
4545
},
4646
"devDependencies": {
4747
"@cloudflare/workers-types": "^4.20250906.0",

0 commit comments

Comments
 (0)