web: Upgrade to Zod 4.

Signed-off-by: Anders Kaseorg <anders@zulip.com>
This commit is contained in:
Anders Kaseorg
2025-06-13 14:42:45 -07:00
committed by Tim Abbott
parent 73bf77b972
commit c431785d3f
9 changed files with 22 additions and 21 deletions

View File

@@ -91,7 +91,7 @@
"webpack-bundle-tracker": "^3.0.1",
"webpack-cli": "^6.0.1",
"winchan": "^0.2.1",
"zod": "^3.21.4"
"zod": "^4.0.5"
},
"devDependencies": {
"@babel/plugin-transform-modules-commonjs": "^7.19.6",

9
pnpm-lock.yaml generated
View File

@@ -299,8 +299,8 @@ importers:
specifier: ^0.2.1
version: 0.2.2
zod:
specifier: ^3.21.4
version: 3.25.67
specifier: ^4.0.5
version: 4.0.5
devDependencies:
'@babel/plugin-transform-modules-commonjs':
specifier: ^7.19.6
@@ -10082,6 +10082,9 @@ packages:
zod@3.25.67:
resolution: {integrity: sha512-idA2YXwpCdqUSKRCACDE6ItZD9TZzy3OZMtpfLoh6oPR47lipysRrJfjzMqFxQ3uJuUPyUeWe1r9vLH33xO/Qw==}
zod@4.0.5:
resolution: {integrity: sha512-/5UuuRPStvHXu7RS+gmvRf4NXrNxpSllGwDnCBcJZtQsKrviYXm54yDGV2KYNLT5kq0lHGcl7lqWJLgSaG+tgA==}
zulip-js@2.1.0:
resolution: {integrity: sha512-kLdxzJZ/FvWHBotUJl7LXCHIkShTjy1FUk5HAWfsal1TM+hw0atCZwgasCpvFDBj01y+39ZEZXgjePaie74Xhg==}
@@ -21889,6 +21892,8 @@ snapshots:
zod@3.25.67: {}
zod@4.0.5: {}
zulip-js@2.1.0(encoding@0.1.13):
dependencies:
'@babel/runtime': 7.27.6

View File

@@ -49,4 +49,4 @@ API_FEATURE_LEVEL = 408
# historical commits sharing the same major version, in which case a
# minor version bump suffices.
PROVISION_VERSION = (334, 2) # bumped 2025-07-17 to add mdx linting libraries
PROVISION_VERSION = (335, 0) # bumped 2025-07-19 to upgrade Zod

View File

@@ -48,9 +48,9 @@ const home_params_schema = default_params_schema
state_data: state_data_schema.nullable(),
translation_data: z.record(z.string(), z.string()),
})
// TODO/typescript: Remove .passthrough() when all consumers have been
// TODO/typescript: Remove .loose() when all consumers have been
// converted to TypeScript and the schema is complete.
.passthrough();
.loose();
// Sync this with analytics.views.stats.render_stats.
const stats_params_schema = default_params_schema.extend({

View File

@@ -2,14 +2,10 @@ import {z} from "zod";
import * as blueslip from "./blueslip.ts";
const formDataSchema = z
.object({
data: z.unknown(),
__valid: z.literal(true),
})
// z.unknown by default marks the field as optional.
// Use zod transform to make optional data field non-optional.
.transform((o) => ({data: o.data, ...o}));
const formDataSchema = z.object({
data: z.unknown(),
__valid: z.literal(true),
});
type FormData = z.infer<typeof formDataSchema>;

View File

@@ -49,7 +49,7 @@ export const update_message_event_schema = z.object({
export type UpdateMessageEvent = z.output<typeof update_message_event_schema>;
export const message_details_schema = z.record(
z.coerce.number(),
z.coerce.number<string>(),
z.object({mentioned: z.optional(z.boolean())}).and(
z.discriminatedUnion("type", [
z.object({type: z.literal("private"), user_ids: z.array(z.number())}),

View File

@@ -97,7 +97,7 @@ export const user_schema = z
timezone: z.string().optional(),
avatar_url: z.string().nullish(),
avatar_version: z.number(),
profile_data: z.record(z.coerce.number(), profile_datum_schema).optional(),
profile_data: z.record(z.coerce.number<string>(), profile_datum_schema).optional(),
// used for fake user objects.
is_missing_server_data: z.optional(z.boolean()),
// used for inaccessible user objects.
@@ -501,7 +501,7 @@ export const state_data_schema = z
.and(
z
.object({
presences: z.record(z.coerce.number(), presence_schema),
presences: z.record(z.coerce.number<string>(), presence_schema),
server_timestamp: z.number(),
presence_last_update_id: z.number().optional(),
})

View File

@@ -55,7 +55,7 @@ type DataByTime<T> = {
const datum_schema: z.ZodType<Plotly.Datum> = z.any();
// Define a schema factory function for the utility generic type
function instantiate_type_DataByEveryoneUser<T extends z.ZodTypeAny>(
function instantiate_type_DataByEveryoneUser<T extends z.ZodType>(
schema: T,
): z.ZodObject<{everyone: T; user: T}> {
return z.object({
@@ -120,8 +120,8 @@ const font_12pt = {
let last_full_update = Number.POSITIVE_INFINITY;
function handle_parse_server_stats_result<_, T>(
result: z.SafeParseReturnType<_, T>,
function handle_parse_server_stats_result<T>(
result: z.core.util.SafeParseResult<T>,
): T | undefined {
if (!result.success) {
blueslip.warn(

View File

@@ -59,7 +59,7 @@ export const stream_schema = z.object({
name: z.string(),
rendered_description: z.string(),
stream_id: z.number(),
stream_post_policy: z.nativeEnum(StreamPostPolicy),
stream_post_policy: z.enum(StreamPostPolicy),
// Generally, this should not be accessed directly, since it can
// have small inaccuracies in the event of rare races. See
// the comments on peer_data.get_subscriber_count.