# All files / server pubsub.js

15.91% Statements 7/44
0% Branches 0/8
0% Functions 0/14
19.44% Lines 7/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

    1x

    1x

    1x

     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

              if (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]

            if (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
    }