提交学习笔记专用
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

59 lines
1.6 KiB

  1. import { createBirpcGroup, cachedMap, createBirpc } from 'birpc';
  2. function createRPCServer(name, ws, functions, options = {}) {
  3. const event = `${name}:rpc`;
  4. const group = createBirpcGroup(
  5. functions,
  6. () => cachedMap(
  7. Array.from(ws?.clients || []),
  8. (channel) => {
  9. if (channel.socket.readyState === channel.socket.CLOSED)
  10. return void 0;
  11. return {
  12. on: (fn) => {
  13. function handler(data, source) {
  14. if (!source.socket)
  15. throw new Error("source.socket is undefined");
  16. if (channel.socket === source.socket)
  17. fn(data, source);
  18. }
  19. ws.on(event, handler);
  20. channel.socket.on("close", () => {
  21. ws.off(event, handler);
  22. });
  23. },
  24. post: (data) => {
  25. channel.send(event, data);
  26. }
  27. };
  28. }
  29. ).filter((c) => !!c),
  30. options
  31. );
  32. ws.on("connection", () => {
  33. group.updateChannels();
  34. });
  35. return group.broadcast;
  36. }
  37. function createRPCClient(name, hot, functions = {}, options = {}) {
  38. const event = `${name}:rpc`;
  39. const promise = Promise.resolve(hot).then((r) => {
  40. if (!r)
  41. console.warn("[vite-hot-client] Received undefined hot context, RPC calls are ignored");
  42. return r;
  43. });
  44. return createBirpc(
  45. functions,
  46. {
  47. ...options,
  48. on: async (fn) => {
  49. (await promise)?.on(event, fn);
  50. },
  51. post: async (data) => {
  52. (await promise)?.send(event, data);
  53. }
  54. }
  55. );
  56. }
  57. export { createRPCClient, createRPCServer };