Source: cached-dns/index.js

/**
 * @author Vivek Kumar <vivek.kumar26@live.com>
 * @overview DNS Cache Memoized.
 * @copyright Vivek Kumar 2018
 * @license MIT
 */
import EventEmitter from 'events';
import createCacheStore from '../cache';
import { getAllDnsMethods, memoizeDnsMethods } from './memoize-dns';

/* eslint-disable class-methods-use-this */
/* eslint-disable arrow-parens */

/** Cached DNS Class - Override DNS Methods */
export class CachedDNS extends EventEmitter {
  /**
   * Creates an instance of CachedDNS.
   * @param {number} [ttl] TTL value for cache items in minutes.
   * @param {object} [config] Config / Options object.
   * @param {number} [config.maxSize] Maximum number of items to be stored in cache.
   * @memberof CachedDNS
   */
  constructor(ttl, config) {
    super();
    /* Allow only one instance of CachedDNS class */
    if (CachedDNS.$instance) {
      throw new Error('CachedDNS Class already has an instance!');
    }

    CachedDNS.$instance = this;

    this.methods = null;

    /* Create Cache Store Object (Static) */
    CachedDNS.cacheObj = createCacheStore(ttl, config);

    /**
     * Flush Complete Event Listener.
     * @listens CacheStore#flush-complete
     */
    CachedDNS.cacheObj.on('flush-complete', (stats) => {
      /**
       * Flush Cache Event.
       * @event CachedDNS#flush-cache
       * @type {object}
       * @property {boolean} status Indicates status.
       * @property {number} nTimeouts Number of timeouts cleared.
       * @property {number} nKeys Number of cache items cleared.
       */
      this.emit('flush-cache', stats);
    });
  }

  /**
   * Override all DNS Methods.
   * @returns {boolean}
   * @memberof CachedDNS
   */
  overrideMethods(options) {
    const allDnsMethods = getAllDnsMethods();

    if (!options) {
      this.methods = allDnsMethods;
    } else if (typeof options === 'string') {
      if (allDnsMethods.includes(options)) {
        this.methods = [options];
      } else {
        throw new Error(`Invalid DNS Method - '${options}'`);
      }
    } else if (Array.isArray(options)) {
      if (options.every((m) => allDnsMethods.includes(m))) {
        this.methods = options;
      } else {
        throw new Error('An invalid dns method was passed');
      }
    } else {
      throw new TypeError('Expected a string or an array of strings');
    }

    memoizeDnsMethods(this.methods, CachedDNS.cacheObj);
    return true;
  }

  /**
   * Flushes the cache and clears all timers.
   * Once flushing is complete, emits `flush-cache` event with stats object.
   * @memberof CachedDNS
   */
  flush() {
    CachedDNS.cacheObj.flush = true;
    CachedDNS.cacheObj.flushCache();
  }
}

/**
 * Function to create a new instance of CachedDNS class.
 * @param {number} ttl TTL value for cache items in minutes.
 * @param {object} config Config / Options object.
 * @param {number} config.maxSize Maximum number of items to be stored in cache.
 * @returns {object} Instance of CachedDNS class.
 */
const dnsCached = (ttl, config) => new CachedDNS(ttl, config);

export default dnsCached;