From a101e161dc1a7de2c07815f69d4cccc07210b370 Mon Sep 17 00:00:00 2001 From: Varun Singh Date: Thu, 28 Mar 2024 20:23:32 +0530 Subject: [PATCH] submessage: Parse 'events' array data with zod. The 'events' array in 'get_message_events' is made of objects. Each object has 'data' field which is of type 'any' because 'JSON.parse' returns 'any'. We need to parse it using zod to add type-safety. The reason I am parsing the entire array at once is because, 'events' array is made of objects of two different schema; and the order matters. The first element is of different schema than the rest.(.tuple().rest() used is for that purpose). This validates the entire submessage content before it is passed to 'widgetize.ts'. --- web/src/submessage.js | 33 +++++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/web/src/submessage.js b/web/src/submessage.js index 977640d9a9..93014a535e 100644 --- a/web/src/submessage.js +++ b/web/src/submessage.js @@ -18,6 +18,35 @@ export const zform_widget_extra_data_schema = z.object({ type: z.literal("choices"), }); +const poll_widget_extra_data_schema = z.object({ + question: z.string().optional(), + options: z.array(z.string()).optional(), +}); + +const widget_data_event_schema = z.object({ + sender_id: z.number(), + data: z.object({ + widget_type: z.string().optional(), + extra_data: z + .union([zform_widget_extra_data_schema, poll_widget_extra_data_schema]) + .nullable(), + }), +}); + +const inbound_data_event_schema = z.object({ + sender_id: z.number(), + data: z.intersection( + z.object({ + type: z.string(), + }), + z.record(z.string(), z.unknown()), + ), +}); + +const submessages_event_schema = z + .tuple([widget_data_event_schema]) + .rest(inbound_data_event_schema); + export function get_message_events(message) { if (message.locally_echoed) { return undefined; @@ -37,8 +66,8 @@ export function get_message_events(message) { sender_id: obj.sender_id, data: JSON.parse(obj.content), })); - - return events; + const clean_events = submessages_event_schema.parse(events); + return clean_events; } export function process_submessages(in_opts) {