# All files / src/server pubsub.js

93.18% Statements 41/44
62.5% Branches 5/8
92.86% Functions 13/14
94.44% Lines 34/36

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    971x
    1x
    1x
    1x

    23x

    23x

    11014x

    3081x
    1027x

    1027x
    3081x
    1027x
    1027x

    1027x
    1027x

    1027x

    1027x

    1027x

    1027x

    1027x

    2054x
    1027x

    1027x
    1027x
    1027x
    1027x

    1027x

    2054x
    1027x
    1027x

    8x

    18x

    9x

    23x

     import { expose, caller } from 'postmsg-rpc'
    import { pre } from 'prepost'
    import { isFunctionJson } from '../serialization/function'
    import { preBufferFromJson } from '../serialization/buffer'

    export default function (getIpfs, opts) {
      const subs = [
      /*
        {
          topic,    // name of the topic subscribed to
          rpc: {    // details of the RPC stub created to send updates
            fnName, // the RPC function name the stub calls
            stubFn  // the RPC stub function created by postmsg-rpc
          }
        }
      */
      ]

      const api = {
        publish: expose('ipfs.pubsub.publish', pre(
          preBufferFromJson(1),
          opts.pre('pubsub.publish'),
          (...args) => getIpfs().pubsub.publish(...args)
        ), opts),
        subscribe: expose('ipfs.pubsub.subscribe', function (...args) {
          let sub

          return pre(
            (...args) => {
              const topic = args[0]
              const handlerIndex = args.length === 3 ? 2 : 1

              Eif (isFunctionJson(args[handlerIndex])) {
                const stubFn = caller(args[handlerIndex].name, opts)

                sub = {
                  topic,
                  rpc: {
                    fnName: args[handlerIndex].name,
                    stubFn
                  }
                }

                subs.push(sub)

                args[handlerIndex] = stubFn
              }

              return args
            },
            opts.pre('pubsub.subscribe'),
            (...args) => {
              return getIpfs().pubsub.subscribe(...args)
                .catch((err) => {
                  subs.splice(subs.indexOf(sub), 1)
                  throw err
                })
            }
          )(...args)
        }, opts),
        unsubscribe: expose('ipfs.pubsub.unsubscribe', pre(
          (...args) => {
            const topic = args[0]

            Eif (isFunctionJson(args[1])) {
              const sub = subs.find((s) => s.topic === topic && s.rpc.fnName === args[1].name)
              args[1] = sub.rpc.stubFn
              subs.splice(subs.indexOf(sub), 1)
            }

            return args
          },
          opts.pre('pubsub.unsubscribe'),
          (...args) => new Promise((resolve) => {
            getIpfs().pubsub.unsubscribe(...args)
            resolve()
          })
        ), opts),
        peers: expose('ipfs.pubsub.peers', pre(
          opts.pre('pubsub.peers'),
          (...args) => getIpfs().pubsub.peers(...args)
        ), opts),
        ls: expose('ipfs.pubsub.ls', pre(
          // FIXME: The interface-ipfs-core tests call ls straight after unsubscribe.
          //
          // Unsubscribe in js-ipfs is synchronous but it HAS to be async in the
          // proxy partly because of the way it is coded but mostly because
          // window.postMessage is asynchronous.
          (...args) => new Promise((resolve) => setTimeout(() => resolve(args))),
          opts.pre('pubsub.ls'),
          (...args) => getIpfs().pubsub.ls(...args)
        ), opts)
      }

      return api
    }