Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

✅ feature suggestion: websocket support #991

ben-xD started this conversation in Ideas
May 21, 2023 · 6 comments · 1 reply
Discussion options

It would be nice if we could define WebSocket endpoints that clients can call, which establishes a connection. The handler would give developers a subscription, which they can store to send messages to the client later, or close the websocket.

Example

  • Multiple users call the subscribeEndpoint, which sets up a websocket between them and the server.
  • Whenever a user calls the sendMessageEndpoint, messages are broadcast to all subscribers.
  • Clients can unsubscribe (client side code not shown)
// In practice, subscriptions might be scoped to a specific chat room, not globally for all users.
const subscriptions: Subscription[] = [];

const subscribeEndpoint = defaultEndpointsFactory.build({
    method: "subscribe",
    input: z.object({
      userId: z.string(),
    }),
    message: z.object({ // defines the message type on the websocket
      message: z.string(),
      userId: z.string(),
    }),
    output: z.void({}),
    handler: async ({ input: { name }, options, logger, subscription }) => {
      subscriptions.push(subscription);
        logger.debug(`Subscribed by ${input.userId}`, options); 
      return {};
    },
  });

const sendMessageEndpoint = defaultEndpointsFactory.build({
    method: "post",
    input: z.object({
        userId: z.string(),
        message: z.string()
      }),
    output: z.void(),
    handler: async ({ input: { name }, options, logger, subscription }) => {
        for (const sub of subscriptions) {
            // send message to all subscribers
            sub.sendMessage({ message: input.message, userId: input.userId });
        };
      },
});
You must be logged in to vote

Replies: 6 comments · 1 reply

Comment options

Hello @ben-xD ,

I'm not sure I understand what "WebSocket endpoints" are.
As far as I know websockets are event-based entities operating own protocol, but maybe something changed since last time I worked with websockets.

From your code samples, if I understand correctly, you meant that there are similarities between Request method and Event type, and that the Event payload could be validated against the schema.

My experience with Websockets is limited to this library:
https://socket.io/get-started/chat#integrating-socketio

And as you may see from the example there, it has a slightly separated workflow (dedicated event-based server).

So... I'm not sure that the existing entities (like EndpointsFactory) could be reused in any suitable way for integrating websockets.

However, since zod is a peer dependency now, and following attachRouting() approach with a custom app, it could be actually not a difficult task to add websockets with IO validation by consumer, I presume.

On the other side, making websockets entry easier seems interesting.

Please let me know if you have any recommendations or visions on how this idea could be implemented.
I'll take a time to think on it as well. Thank you.

You must be logged in to vote
0 replies
Comment options

Dear @ben-xD ,

would you be interested in testing this feature:
#1545

Could it help you to achieve the desired functionality?

Your feedback is appreciated — please let me know.

You must be logged in to vote
1 reply
@ben-xD
Comment options

Hey @RobinTail

Sorry for not replying earlier. I've been using trpc over websockets which has been quite nice. I could play around with your PR/feature though :)

Comment options

Hello @ben-xD ,

I actually decided to move that feature to a separate project, which is basically attachable to any HTTP server, including the one returned by createServer() of express-zod-api.

Check this out: https://www.npmjs.com/package/zod-sockets

Would you try to install version 0.2.0 or higher for your sample project and let me know if it's usable, understandable, make sense, etc.
Basically, I need some feedback.

So far, this thing is capable to listen for incoming events, acknowledge them, emit and broadcast events and handle their acknowledgements. All that is validated and you can connect the logger from express-zod-api to it.
There is an example folder in the repo where I managed to demonstrate such samples as ping-pong with echo, subscriptions and a basic chat.

Rooms and namespaces are not yet supported.
I've been using Postman for playing with it.
Please let me know what you think about it.

You must be logged in to vote
0 replies
Comment options

Latest news on that matter for those who interested, CC @ben-xD :

https://github.com/RobinTail/zod-sockets

  • I significantly improved a lot of things there;
  • Made a very simple example of subscription service;
  • It has all the basic features including rooms and namespaces;
  • It can generate documentation according to AsyncAPI standard;
  • It can export types for client constraints;
  • It's awesome!

Check it out.

You must be logged in to vote
0 replies
Comment options

Dear @ben-xD ,

did you have a chance to look at or try zod-sockets ?
I need some feedback.

You must be logged in to vote
0 replies
Comment options

I made a lightweight alternative using Server-sent Events.
Client can subscribe to event stream. No extra package needed.
Available in v21.5.0, CC @ben-xD
https://ez.robintail.cz/v21.5.0/subscriptions

You must be logged in to vote
0 replies
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Category
💡
Ideas
Labels
None yet
2 participants
Morty Proxy This is a proxified and sanitized view of the page, visit original site.