All files / src/channels mixins.ts

100% Statements 32/32
100% Branches 5/5
100% Functions 6/6
100% Lines 31/31

Press n or j to go to the next uncovered block, b, p or k for the previous block.

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 962x 2x 2x     2x 2x 2x 2x   2x                     2x         69x     1x       61x     1x       38x   38x 4x 4x     38x     60x     14x   7x       37x               2x         14x     2x 2x         1x     13x     13x   13x       54x    
import Debug from 'debug';
import { Channel } from './channel/base';
import { CombinedChannel } from './channel/combined';
import { HookContext } from '@feathersjs/feathers';
 
const debug = Debug('@feathersjs/transport-commons:channels/mixins');
const PUBLISHERS = Symbol('@feathersjs/transport-commons/publishers');
const CHANNELS = Symbol('@feathersjs/transport-commons/channels');
const ALL_EVENTS = Symbol('@feathersjs/transport-commons/all-events');
 
export const keys = {
  PUBLISHERS,
  CHANNELS,
  ALL_EVENTS
};
 
export interface ChannelMixin {
  [CHANNELS]: { [key: string]: Channel };
  channel(...names: string[]): Channel;
}
 
export function channelMixin() {
  const mixin: ChannelMixin = {
    [CHANNELS]: {},
 
    channel(...names: string[]): Channel {
      debug('Returning channels', names);
 
      if (names.length === 0) {
        throw new Error('app.channel needs at least one channel name');
      }
 
      if (names.length === 1) {
        const [ name ] = names;
 
        if (Array.isArray(name)) {
          return this.channel(...name);
        }
 
        if (!this[CHANNELS][name]) {
          const channel = new Channel();
 
          channel.once('empty', () => {
            channel.removeAllListeners();
            delete this[CHANNELS][name];
          });
 
          this[CHANNELS][name] = channel;
        }
 
        return this[CHANNELS][name];
      }
 
      const channels = names.map(name => this.channel(name));
 
      return new CombinedChannel(channels);
    }
  };
 
  return mixin;
}
 
export interface PublishMixin {
  [PUBLISHERS]: { [key: string]: Channel };
  publish(event: string|symbol, callback: (data: any, hook: HookContext) => Channel): any;
}
 
export function publishMixin() {
  const result: PublishMixin = {
    [PUBLISHERS]: {},
 
    publish(event, callback) {
      debug('Registering publisher', event);
 
      if (!callback && typeof event === 'function') {
        callback = event;
        event = ALL_EVENTS;
      }
 
      // @ts-ignore
      if (this._serviceEvents && event !== ALL_EVENTS && this._serviceEvents.indexOf(event) === -1) {
        throw new Error(`'${event.toString()}' is not a valid service event`);
      }
 
      const publishers = this[PUBLISHERS];
 
      // @ts-ignore
      publishers[event] = callback;
 
      return this;
    }
  };
 
  return result;
}