Name Picker Malfunction

    redux-awesome-socket-middleware
    TypeScript icon, indicating that this package has built-in type declarations

    1.1.7 • Public • Published

    Redux Awesome Socket Middleware

    This package makes web socket management much easier with redux.
    The package is built over the WebSocket constructor from browser API.

    npm version size npm downloads

    Structure


    Installation

    # using npm
    npm install redux-awesome-socket-middleware
    
    # using yarn
    yarn add redux-awesome-socket-middleware
    

    Options

    Name Required Type Default
    url Yes string -
    actionTypes Yes Array<string OR RegExp> -
    completedActionTypes Yes Array<string> -
    onMessage Yes (res: Res, dispatch: Dispatch<AnyAction>) => void -
    autoConnect No boolean true
    protocols No string OR string[] -
    shouldReconnect No ((event: CloseEvent) => boolean) OR boolean true
    reconnectionIntervals No number OR number[] 1000
    serialize No (req: Req) => SReq -
    deserialize No (res: Res) => DRes -
    debug No boolean -

    url (required)

    string

    Url for the WebSocket constructor.

    url: 'ws://localhost:3000'
    url: 'wss://example.com'

    actionTypes (required)

    [RegExp | string, RegExp | string, RegExp | string]

    WARNING: Sequence is important!

    Types that you are able to manage the socket with.
    You can manage socket be dispatching any of them.

    The first element should be the SEND action type.
    Second - CONNECT type.
    Third - DISCONNECT type.

    actionTypes: ['SEND', 'CONNECT', 'DISCONNECT']
    actionTypes: [new RegExp(/_REQUEST/g), 'CONNECT', 'DISCONNECT']

    If you don't need these: CONNECT, DISCONNECT so just don't send them.

    actionTypes: ['SEND', 'CONNECT']
    actionTypes: ['SEND']
    actionTypes: [new RegExp(/_REQUEST/g)]

    completedActionTypes (required)

    [string, string]

    WARNING: Sequence is important!

    Types that you receive back on actions.

    completedActionTypes: ['CONNECTED', 'DISCONNECTED']

    onMessage (required)

    (res: Res, dispatch: Dispatch<AnyAction>) => void

    The 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.

    *(this is just an example of the onMessage handler)

    onMessage: (data, dispatch) => {
      switch (data.method) {
        case 'posts':
          if (data.error) {
            dispatch(postsActions.getPostsRejected(data.error));
          } else {
            dispatch(postsActions.getPostsFulfilled(data.result));
          }
          break;
          
        ...
          
        default:
          break;
      }
    }

    autoConnect

    boolean - (true by default)

    When true you don't need to send anything else to connect it.
    When false you need to dispatch the connect action with a type actionTypes[1].

    autoConnect: false

    shouldReconnect

    ((event: CloseEvent) => boolean) | boolean - (true by default)

    When true the socket tries to reconnect if event.code !== 1005.
    When predicate is passed you are able to decide if the sockets needs to be reconnected.

    shouldReconnect: false

    debug

    boolean

    When true the package shows additional logs.

    debug: ture

    protocols

    boolean

    Protocols for the WebSocket constructor.

    protocols: 'some protocol'
    protocols: ['some protocol']

    reconnectionInterval

    number | number[] - (1000 by default)

    In milliseconds.
    When array each new connection uses the next number from the array for a timeout to avoid DDOSing a server.

    reconnectionInterval: 1000

    When reconnection count reaches the last array element it uses it each the next time.
    When the socket connects back the next reconnection loop will start from the 0 index.

    reconnectionInterval: [0, 1000, 2000, 3000, 4000, 5000, 10000]

    serialize

    (req: Req) => SReq
    Req and SReq are templates of the generic MiddlewareOptions type

    The format function gets called to prepare the data to get submitted to the server. For example, camelCase to snake_case conversion.

    serialize: req => {
      return {
        ...req,
        time: Date.now()
      }
    }

    deserialize

    (res: Res) => DRes
    Res and DRes are templates of the generic MiddlewareOptions type

    The format function gets called to prepare the message to get submitted to the onMessage callback. For example, snake_case to camelCase conversion.

    deserialize: res => {
      return res.data
    }

    Usage

    Connecting

    const SOCKET_SEND = 'SCOKET_SEND';
    const SOCKET_CONNECT = 'SOCKET_CONNECT';
    const SOCKET_DISCONNECT = 'SOCKET_DISCONNECT';
    
    const otpions = {
      ...
      actionTypes: [SOCKET_SEND, SOCKET_CONNECT, SOCKET_DISCONNECT],
      ...
    };
    
    const connectAction = () => ({ type: SOCKET_CONNECT });
    
    dispatch(connectAction());

    Disconnecting

    import { CloseAction } from 'redux-awesome-socket-middleware';
    
    const SOCKET_SEND = 'SCOKET_SEND';
    const SOCKET_CONNECT = 'SOCKET_CONNECT';
    const SOCKET_DISCONNECT = 'SOCKET_DISCONNECT';
    
    const otpions = {
      ...
      actionTypes: [SOCKET_SEND, SOCKET_CONNECT, SOCKET_DISCONNECT],
      ...
    };
    
    const disconnectAction = (code?: number): CloseAction<typeof SOCKET_DISCONNECT> => ({
      type: SOCKET_DISCONNECT,
      payload: { code }
    });
    
    OR
    
    dispatch(disconnectAction(1000));

    The disconnectAction can return:

    {
      type: SOCKET_DISCONNECT,
      code
    }
    {
      type: SOCKET_DISCONNECT,
      payload: { code }
    }
    {
      type: SOCKET_DISCONNECT,
      data: { code }
    }

    (all these are supported by CloseAction<typeof SOCKET_DISCONNECT> type)

    Sending data

    The data can be sent in payload OR in data key.

    import { SendAction } from 'redux-awesome-socket-middleware';
    
    const GET_POSTS = 'GET_POSTS_REQUEST';
    
    const otpions = {
      ...
      actionTypes: [new RegExp(/_REQUEST/g)],
      ...
    }
    
    const getPostsAction = (offset: number, limit: number): SendAction<typeof GET_POSTS> => ({
      type: GET_POSTS,
      payload: { offset, limit }
    });
    
    dispatch(getPostsAction(0, 20));

    The getPostsAction can return:

    {
      type: GET_POSTS,
      payload: { code }
    }
    {
      type: GET_POSTS,
      data: { code }
    }

    (all these are supported by SendAction<typeof GET_POSTS> type)


    MiddlewareOptions declaration

    import { createSocketMiddleware, MiddlewareOptions } from 'redux-awesome-socket-middleware';
    
    type ScoketReq = {
      method: string
      data: Record<string, unknown>
    };
    
    type SocketRes = {
      [method: string]: Record<string, unknown>
    };
    
    type ScoketSerializedReq = {
      [method: string]: Record<string, unknown>
    };
    
    type SocketDeserializedRes = Record<string, unknown>;
    
    const options: MiddlewareOptions<ScoketReq, SocketRes, ScoketSerializedReq, SocketDeserializedRes> = {
      url: 'ws://localhost:3000',
      actionTypes: ['SEND', 'CONNECT', 'DISCONNECT'],
      completedActionTypes: ['CONNECTED', 'DISCONNECTED'],
    
      // serialize: (req: ScoketReq) => ScoketSerializedReq
      serialize: ({ method, data }) => ({ [method]: data }),
    
      // deserialize: (res: SocketRes) => SocketDeserializedRes
      deserialize: (res: SocketRes) => res[Object.keys(res)[0]]
    };
    
    const socketMiddleware = createSocketMiddleware(options);

    Passing own types to MiddlewareOptions type

    MiddlewareOptions is a generic type.

    MiddlewareOptions<Req, Res, SReq = Req, DRes = Res>

    Req - type of the socket request (required).

    Res - type of the socket response (required).

    SReq (default is Req) - type of serialized socket request which will be sent to the API (not required).
    This type should be returned from the MiddlewareOptions.serialize function.

    DRes (default is Res) - type of deserialized socket response which is reachable by using hooks as data (not required).
    This type should be returned from the MiddlewareOptions.deserialize function.

    Install

    npm i redux-awesome-socket-middleware

    DownloadsWeekly Downloads

    35

    Version

    1.1.7

    License

    MIT

    Unpacked Size

    125 kB

    Total Files

    50

    Last publish

    Collaborators

    • maxzinchenko