{"id":26882969,"url":"https://github.com/maxzinchenko/redux-ws-middleware","last_synced_at":"2025-05-08T03:50:55.177Z","repository":{"id":44656906,"uuid":"444554085","full_name":"maxzinchenko/redux-ws-middleware","owner":"maxzinchenko","description":"This package makes web socket management much easier with redux.","archived":false,"fork":false,"pushed_at":"2023-06-30T09:45:07.000Z","size":578,"stargazers_count":4,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-05-01T04:37:05.131Z","etag":null,"topics":["middleware","redux","redux-middleware","redux-ws-middleware","websocket"],"latest_commit_sha":null,"homepage":"https://www.npmjs.com/package/redux-ws-middleware","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/maxzinchenko.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-01-04T20:28:01.000Z","updated_at":"2025-02-06T03:43:03.000Z","dependencies_parsed_at":"2025-03-31T16:57:40.985Z","dependency_job_id":"57280276-d394-4d48-94df-859d9f38ace7","html_url":"https://github.com/maxzinchenko/redux-ws-middleware","commit_stats":null,"previous_names":["maxzinchenko/redux-awesome-socket-middleware"],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maxzinchenko%2Fredux-ws-middleware","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maxzinchenko%2Fredux-ws-middleware/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maxzinchenko%2Fredux-ws-middleware/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maxzinchenko%2Fredux-ws-middleware/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/maxzinchenko","download_url":"https://codeload.github.com/maxzinchenko/redux-ws-middleware/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252996228,"owners_count":21837617,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["middleware","redux","redux-middleware","redux-ws-middleware","websocket"],"created_at":"2025-03-31T16:55:58.707Z","updated_at":"2025-05-08T03:50:55.160Z","avatar_url":"https://github.com/maxzinchenko.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Redux WebSocket Middleware\n\nThis package makes web socket management much easier with redux.\u003cbr\u003e\nThe package is built over the \u003ca href=\"https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/WebSocket\"\u003eWebSocket\u003c/a\u003e constructor from browser API.\n\n\u003ca href=\"https://npmjs.com/package/redux-ws-middleware\" target=\"\\_blank\"\u003e\n  \u003cimg alt=\"npm version\" src=\"https://img.shields.io/npm/v/redux-ws-middleware.svg\" /\u003e\n\u003c/a\u003e\n\u003ca href=\"https://bundlephobia.com/result?p=redux-ws-middleware@latest\" target=\"\\_blank\"\u003e\n  \u003cimg alt=\"size\" src=\"https://flat-badgen.vercel.app/bundlephobia/minzip/redux-ws-middleware@latest\" /\u003e\n\u003c/a\u003e\n\u003ca href=\"https://bundlephobia.com/result?p=redux-ws-middleware@latest\" target=\"\\_blank\"\u003e\n  \u003cimg alt=\"size\" src=\"https://flat-badgen.vercel.app/bundlephobia/min/redux-ws-middleware@latest\" /\u003e\n\u003c/a\u003e\n\u003ca href=\"https://npmjs.com/package/redux-ws-middleware\" target=\"\\_blank\"\u003e\n  \u003cimg alt=\"npm downloads\" src=\"https://img.shields.io/npm/dm/redux-ws-middleware.svg\" /\u003e\n\u003c/a\u003e\n\n---\n\n# Examples\n\n- [Single socket](https://github.com/maxzinchenko/redux-ws-middleware/tree/master/examples/single-socket)\n\n\n---\n\n# Structure\n\n- [Installation](#installation)\n- [Options](#options)\n  - [url](#url)\n  - [actionTypes](#actionTypes)\n  - [completedActionTypes](#completedActionTypes)\n  - [onMessage](#onMessage)\n  - [autoConnect](#autoConnect)\n  - [protocols](#protocols)\n  - [shouldReconnect](#shouldReconnect)\n  - [shouldOpen](#shouldOpen)\n  - [shouldClose](#shouldClose)\n  - [reconnectionIntervals](#reconnectionInterval)\n  - [serialize](#serialize)\n  - [deserialize](#deserialize)\n  - [debug](#debug)\n- [Usage](#usage)\n  - [Connecting](#connecting)\n  - [Disconnecting](#disconnecting)\n  - [Sending data](#sending-data)\n- [MiddlewareOptions declaration](#middlewareoptions-declaration)\n  - [Passing own types to MiddlewareOptions type](#passing-own-types-to-middlewareoptions-type)\n\n\n---\n\n\n## Installation\n\n```\n# using npm\nnpm install redux-ws-middleware\n\n# using yarn\nyarn add redux-ws-middleware\n```\n\n---\n\n\n## Options\n\n| Name                                           | Required | Type                                                | Default     |\n| ---------------------------------------------- | -------- | --------------------------------------------------- | ----------- |\n| [url](#url)                                    | Yes      | `string`                                            | -           |\n| [actionTypes](#actionTypes)                    | Yes      | `Array\u003cstring OR RegExp\u003e`                           | -           |\n| [completedActionTypes](#completedActionTypes)  | Yes      | `Array\u003cstring\u003e`                                     | -           |\n| [onMessage](#onMessage)                        | Yes      | `(res: Res, dispatch: Dispatch\u003cAnyAction\u003e) =\u003e void` | -           |\n| [autoConnect](#autoConnect)                    | No       | `boolean`                                           | `true`      |\n| [protocols](#protocols)                        | No       | `string OR string[]`                                | -           |\n| [shouldReconnect](#shouldReconnect)            | No       | `((event: CloseEvent) =\u003e boolean) OR boolean`       | `true`      |\n| [reconnectionIntervals](#reconnectionInterval) | No       | `number OR number[]`                                | `1000`      |\n| [shouldOpen](#shouldReconnect)                 | No       | `((req: Req) =\u003e boolean) OR boolean`                | `false`     |\n| [shouldClose](#shouldReconnect)                | No       | `((res: DRes) =\u003e boolean) OR boolean`               | `false`     |\n| [serialize](#serialize)                        | No       | `(req: Req) =\u003e SReq`                                | -           | \n| [deserialize](#deserialize)                    | No       | `(res: Res) =\u003e DRes`                                | -           |\n| [debug](#debug)                                | No       | `boolean`                                           | -           |\n\n--------\n\n## url\n\n\u003cb\u003eRequired*\u003c/b\u003e\n\nType: `string`\n\nUrl for the \u003ca href=\"https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/WebSocket\"\u003eWebSocket\u003c/a\u003e constructor.\n\n```ts\nurl: 'ws://localhost:3000'\n```\n\n```ts\nurl: 'wss://example.com'\n```\n\n## actionTypes\n\n\u003cb\u003eRequired*\u003c/b\u003e\n\nType: `[RegExp | string, RegExp | string, RegExp | string]`\n\n\u003cb\u003eWARNING: Sequence is important!\u003c/b\u003e\u003cbr\u003e\n\nTypes that you are able to manage the socket with.\u003cbr\u003e\nYou can have socket dispatching any of them.\n\nThe first element should be the `SEND` action type.\u003cbr\u003e\nSecond - `CONNECT` type. \u003cbr\u003e\nThird - `DISCONNECT` type.\n\n\u003cb\u003eIMPORTANT: Do not use `/g` at the end of RegExp!\u003c/b\u003e\n\n```ts\nactionTypes: ['SEND', 'CONNECT', 'DISCONNECT']\n```\n\n```ts\nactionTypes: [new RegExp(/_REQUEST$/), 'CONNECT', 'DISCONNECT']\n```\n\nIf you don't need these: `CONNECT`, `DISCONNECT` so just don't send them.\n\n```ts\nactionTypes: ['SEND', 'CONNECT']\n```\n\n```ts\nactionTypes: ['SEND']\n```\n\n```ts\nactionTypes: [new RegExp(/_REQUEST$/)]\n```\n\n## completedActionTypes\n\n\u003cb\u003eRequired*\u003c/b\u003e\n\nType: `[string, string]`\n\n\u003cb\u003eWARNING: Sequence is important!\u003c/b\u003e\n\nTypes that you receive back on actions.\n\n```ts\ncompletedActionTypes: ['CONNECTED', 'DISCONNECTED']\n```\n\n## onMessage\n\n\u003cb\u003eRequired*\u003c/b\u003e\n\nType: `(res: Res, dispatch: Dispatch\u003cAnyAction\u003e) =\u003e void`\n\nThe callback gets called with deserialized data already, if you put deserialize function into options, or with a normal data if you don't. And with a `dispatch` so you can manage your store.\n\n*(this is just an example of the `onMessage` handler)\n\n```ts\nonMessage: (data, dispatch) =\u003e {\n  switch (data.method) {\n    case 'posts':\n      if (data.error) {\n        dispatch(postsActions.getPostsRejected(data.error));\n      } else {\n        dispatch(postsActions.getPostsFulfilled(data.result));\n      }\n      break;\n      \n    ...\n      \n    default:\n      break;\n  }\n}\n```\n\n## autoConnect\n\nType: `boolean` - (`true` by default)\n\nWhen `true` you don't need to send anything else to connect it.\u003cbr\u003e\nWhen `false` you need to dispatch the connect action with a type  `actionTypes[1]`.\n\n```ts\nautoConnect: false\n```\n\n## debug\n\nType: `boolean`\n\nWhen `true` the package shows additional logs.\n\n```ts\ndebug: ture\n```\n\n## protocols\n\nType: `string | string[]`\n\nProtocols for the \u003ca href=\"https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/WebSocket\"\u003eWebSocket\u003c/a\u003e constructor.\n\n```ts\nprotocols: 'some protocol'\n```\n\n```ts\nprotocols: ['some protocol']\n```\n\n\n## shouldReconnect\n\nType: `((event: CloseEvent) =\u003e boolean) | boolean` - (`true` by default)\n\nWhen `true` the socket tries to reconnect if `event.code !== 1005`.\u003cbr\u003e\nWhen predicate is passed you are able to decide if the socket needs to be reconnected.\n\n```ts\nshouldReconnect: false\n```\n\n## reconnectionInterval\n\nType: `number | number[]` - (`1000` by default)\n\n\u003cb\u003eIn milliseconds.\u003c/b\u003e\u003cbr\u003e\nWhen array each new connection uses the next number from the array for a timeout to avoid DDOSing a server.\n\n```ts\nreconnectionInterval: 1000\n```\n\nWhen reconnection count reaches the last array element it uses it each the next time.\u003cbr\u003e\nWhen the socket connects back the next reconnection loop will start from the `0` index.\n\n```ts\nreconnectionInterval: [0, 1000, 2000, 3000, 4000, 5000, 10000]\n```\n\n## shouldOpen\n\nType: `((req: Req) =\u003e boolean) | boolean` - (`false` by default)\nReq is a template of the generic MiddlewareOptions type\n\nWhen `true` the socket opens on any `send` action if connection is closed`.\u003cbr\u003e\nWhen predicate is passed you are able to decide if socket needs to be open.\n\n```ts\nshouldOpen: true\n```\n\nWhen predicate is passed you are able to decide when socket needs to be open.\n\n```ts\nshouldOpen: (req: SomeReq) =\u003e req.method === 'load_session'\n```\n\n## shouldClose\n\nType: `((res: DRes) =\u003e boolean) | boolean` - (`false` by default)\n\n`DRes` is a templates of the generic `MiddlewareOptions` type\n\nWhen `true` the socket closes connection after each response from the server.\u003cbr\u003e\nWhen predicate is passed you are able to decide when the socket needs to be closed.\n\n```ts\nshouldClose: true\n```\n\n```ts\nshouldClose: (res: SomeDeserializedRes) =\u003e res.method === 'logout'\n```\n\n## serialize\n\nType: `(req: Req) =\u003e SReq`\u003cbr\u003e\n\n`Req` and `SReq` are templates of the generic `MiddlewareOptions` type\n\nThe format function gets called to prepare the data to get submitted to the server. For example, `camelCase` to `snake_case` conversion.\n\n```ts\nserialize: req =\u003e {\n  return {\n    ...req,\n    time: Date.now()\n  }\n}\n```\n\n## deserialize\n\nType: `(res: Res) =\u003e DRes`\u003cbr\u003e\n\n`Res` and `DRes` are templates of the generic `MiddlewareOptions` type\n\nThe format function gets called to prepare the message to get submitted to the `onMessage` callback. For example, `snake_case` to `camelCase` conversion.\n\n```ts\ndeserialize: res =\u003e {\n  return res.data\n}\n```\n\n\n---\n\n\n## Usage\n\n### Connecting\n```ts\nconst SOCKET_SEND = 'SCOKET_SEND';\nconst SOCKET_CONNECT = 'SOCKET_CONNECT';\nconst SOCKET_DISCONNECT = 'SOCKET_DISCONNECT';\n\nconst otpions = {\n  ...\n  actionTypes: [SOCKET_SEND, SOCKET_CONNECT, SOCKET_DISCONNECT],\n  ...\n};\n\nconst connectAction = () =\u003e ({ type: SOCKET_CONNECT });\n\ndispatch(connectAction());\n```\n\n### Disconnecting\n\n```ts\nimport { CloseAction } from 'redux-ws-middleware';\n\nconst SOCKET_SEND = 'SCOKET_SEND';\nconst SOCKET_CONNECT = 'SOCKET_CONNECT';\nconst SOCKET_DISCONNECT = 'SOCKET_DISCONNECT';\n\nconst otpions = {\n  ...\n  actionTypes: [SOCKET_SEND, SOCKET_CONNECT, SOCKET_DISCONNECT],\n  ...\n};\n\nconst disconnectAction = (code?: number): CloseAction\u003ctypeof SOCKET_DISCONNECT\u003e =\u003e ({\n  type: SOCKET_DISCONNECT,\n  payload: { code }\n});\n\nOR\n\ndispatch(disconnectAction(1000));\n```\n\nThe `disconnectAction` can return:\u003cbr\u003e\n\n```ts\n{\n  type: SOCKET_DISCONNECT,\n  code\n}\n```\n\n```ts\n{\n  type: SOCKET_DISCONNECT,\n  payload: { code }\n}\n```\n\n```ts\n{\n  type: SOCKET_DISCONNECT,\n  data: { code }\n}\n```\n\n(all these are supported by `CloseAction\u003ctypeof SOCKET_DISCONNECT\u003e` type)\n\n### Sending data\n\nThe data can be sent in `payload` OR in `data` key.\n\n```ts\nimport { SendAction } from 'redux-ws-middleware';\n\nconst GET_POSTS = 'GET_POSTS_REQUEST';\n\nconst otpions = {\n  ...\n  actionTypes: [new RegExp(/_REQUEST$/)],\n  ...\n}\n\nconst getPostsAction = (offset: number, limit: number): SendAction\u003ctypeof GET_POSTS\u003e =\u003e ({\n  type: GET_POSTS,\n  payload: { offset, limit }\n});\n\ndispatch(getPostsAction(0, 20));\n```\n\nThe `getPostsAction` can return:\u003cbr\u003e\n\n```ts\n{\n  type: GET_POSTS,\n  payload: { code }\n}\n```\n\n```ts\n{\n  type: GET_POSTS,\n  data: { code }\n}\n```\n\n(all these are supported by `SendAction\u003ctypeof GET_POSTS\u003e` type)\n\n\n---\n\n## MiddlewareOptions declaration\n\n```ts\nimport { createSocketMiddleware, MiddlewareOptions } from 'redux-ws-middleware';\n\ntype ScoketReq = {\n  method: string\n  data: Record\u003cstring, unknown\u003e\n};\n\ntype SocketRes = {\n  [method: string]: Record\u003cstring, unknown\u003e\n};\n\ntype ScoketSerializedReq = {\n  [method: string]: Record\u003cstring, unknown\u003e\n};\n\ntype SocketDeserializedRes = Record\u003cstring, unknown\u003e;\n\nconst options: MiddlewareOptions\u003cScoketReq, SocketRes, ScoketSerializedReq, SocketDeserializedRes\u003e = {\n  url: 'ws://localhost:3000',\n  actionTypes: ['SEND', 'CONNECT', 'DISCONNECT'],\n  completedActionTypes: ['CONNECTED', 'DISCONNECTED'],\n\n  // serialize: (req: ScoketReq) =\u003e ScoketSerializedReq\n  serialize: ({ method, data }) =\u003e ({ [method]: data }),\n\n  // deserialize: (res: SocketRes) =\u003e SocketDeserializedRes\n  deserialize: (res: SocketRes) =\u003e res[Object.keys(res)[0]]\n};\n\nconst socketMiddleware = createSocketMiddleware(options);\n```\n\n### Passing own types to MiddlewareOptions type\n\n`MiddlewareOptions` is a generic type.\n\n```ts\nMiddlewareOptions\u003cReq, Res, SReq = Req, DRes = Res\u003e\n```\n\n`Req` - type of the socket request (required).\n\n`Res` - type of the socket response (required).\n\n`SReq` (default is `Req`) - type of serialized socket request which will be sent to the API (not required).\u003cbr\u003e\n**This type should be returned from the MiddlewareOptions.serialize function.**\n\n`DRes` (default is `Res`) - type of deserialized socket response which is reachable by using hooks as `data` (not required).\u003cbr\u003e\n**This type should be returned from the MiddlewareOptions.deserialize function.**\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmaxzinchenko%2Fredux-ws-middleware","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmaxzinchenko%2Fredux-ws-middleware","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmaxzinchenko%2Fredux-ws-middleware/lists"}