File
Blob: worker/src/shared/contracts/channels.ts
| 1 | import { z } from 'zod'; |
| 2 | |
| 3 | export const CHANNEL_PROFILES = [ |
| 4 | { dataChannelName: 'robot', ordered: true }, |
| 5 | { dataChannelName: 'spectrum', ordered: false, maxRetransmits: 0 }, |
| 6 | ] as const; |
| 7 | // The SFU may return only id/name. Reliability is our requested configuration, |
| 8 | // not a mandatory echo in its response. Reject an explicit conflicting setting. |
| 9 | export const channelSchema = z |
| 10 | .object({ |
| 11 | id: z.number().int().min(0).max(65534), |
| 12 | dataChannelName: z.enum(['robot', 'spectrum']), |
| 13 | ordered: z.boolean().optional(), |
| 14 | maxRetransmits: z.number().int().nonnegative().optional(), |
| 15 | }) |
| 16 | .refine( |
| 17 | (channel) => |
| 18 | channel.ordered === undefined || channel.ordered === (channel.dataChannelName === 'robot'), |
| 19 | ) |
| 20 | .refine( |
| 21 | (channel) => |
| 22 | channel.maxRetransmits === undefined || |
| 23 | (channel.dataChannelName === 'spectrum' && channel.maxRetransmits === 0), |
| 24 | ) |
| 25 | .transform((channel) => ({ |
| 26 | id: channel.id, |
| 27 | ...CHANNEL_PROFILES.find((profile) => profile.dataChannelName === channel.dataChannelName)!, |
| 28 | })); |
| 29 | export const channelListSchema = z |
| 30 | .array(channelSchema) |
| 31 | .length(2) |
| 32 | .refine( |
| 33 | (channels) => |
| 34 | new Set(channels.map((channel) => channel.id)).size === 2 && |
| 35 | new Set(channels.map((channel) => channel.dataChannelName)).size === 2, |
| 36 | ); |
| 37 | export const channelsSchema = z.object({ channels: channelListSchema }); |
| 38 | |
| 39 | export type Channel = z.infer<typeof channelSchema>; |