File: /var/www/zaklada/html/node_modules/gulp-cache/lib/TaskProxy.js
'use strict';
var crypto = require('crypto');
var objectAssign = require('object-assign');
var objectOmit = require('object.omit');
var Bluebird = require('bluebird');
var tryJsonParse = require('try-json-parse');
var TaskProxy = function(opts) {
  objectAssign(this, {
    task: opts.task,
    file: opts.file,
    opts: opts.opts,
    originalPath: opts.file.path
  });
};
function makeHash(key) {
  return crypto.createHash('md5').update(key).digest('hex');
}
objectAssign(TaskProxy.prototype, {
  processFile: function() {
    var self = this;
    return this._checkForCachedValue().then(function(cached) {
      // If we found a cached value
      // The path of the cache key should also be identical to the original one when the file path changed inside the task
      if (cached.value && (!cached.value.filePathChangedInsideTask || cached.value.originalPath === self.file.path)) {
        // Extend the cached value onto the file, but don't overwrite original path info
        var file = objectAssign(
          self.file,
          objectOmit(cached.value, ['cwd', 'path', 'base', 'stat', 'history'])
        );
        // Restore the file path if it was set
        if (cached.value.path && cached.value.filePathChangedInsideTask) {
          file.path = cached.value.path;
        }
        return file;
      }
      // Otherwise, run the proxied task
      return self._runProxiedTaskAndCache(cached.key);
    });
  },
  removeCachedResult: function() {
    var self = this;
    return this._getFileKey().then(function(cachedKey) {
      var removeCached = Bluebird.promisify(self.opts.fileCache.removeCached, {
        context: self.opts.fileCache
      });
      return removeCached(self.opts.name, cachedKey);
    });
  },
  _getFileKey: function() {
    var getKey = this.opts.key;
    if (typeof getKey === 'function' && getKey.length === 2) {
      getKey = Bluebird.promisify(getKey.bind(this.opts));
    }
    return Bluebird.resolve(getKey(this.file)).then(function(key) {
      if (!key) {
        return key;
      }
      return makeHash(key);
    });
  },
  _checkForCachedValue: function() {
    var self = this;
    return this._getFileKey().then(function(key) {
      // If no key returned, bug out early
      if (!key) {
        return {
          key: key,
          value: null
        };
      }
      var getCached = Bluebird.promisify(self.opts.fileCache.getCached.bind(self.opts.fileCache));
      return getCached(self.opts.name, key).then(function(cached) {
        if (!cached) {
          return {
            key: key,
            value: null
          };
        }
        var parsedContents = tryJsonParse(cached.contents);
        if (parsedContents === undefined) {
          parsedContents = {cached: cached.contents};
        }
        if (self.opts.restore) {
          parsedContents = self.opts.restore(parsedContents);
        }
        return {
          key: key,
          value: parsedContents
        };
      });
    });
  },
  _runProxiedTaskAndCache: function(cachedKey) {
    var self = this;
    return self._runProxiedTask().then(function(result) {
      // If this wasn't a success, continue to next task
      // TODO: Should this also offer an async option?
      if (self.opts.success !== true && !self.opts.success(result)) {
        return result;
      }
      return self._storeCachedResult(cachedKey, result).then(function() {
        return result;
      });
    });
  },
  _runProxiedTask: function() {
    var self = this;
    return new Bluebird(function(resolve, reject) {
      function handleError(err) {
        // TODO: Errors will step on each other here
        // Reduce the maxListeners back down
        self.task.setMaxListeners(self.task._maxListeners - 1);
        reject(err);
      }
      function handleData(datum) {
        // Wait for data (can be out of order, so check for matching file we wrote)
        if (self.file !== datum) {
          return;
        }
        // Be good citizens and remove our listeners
        self.task.removeListener('error', handleError);
        self.task.removeListener('data', handleData);
        // Reduce the maxListeners back down
        self.task.setMaxListeners(self.task._maxListeners - 2);
        resolve(datum);
      }
      // Bump up max listeners to prevent memory leak warnings
      var currMaxListeners = self.task._maxListeners || 0;
      self.task.setMaxListeners(currMaxListeners + 2);
      self.task.on('data', handleData);
      self.task.once('error', handleError);
      // Run through the other task and grab output (or error)
      // Not sure if a _.defer is necessary here
      self.task.write(self.file);
    });
  },
  _getValueFromResult: function(result) {
    var getValue;
    if (typeof this.opts.value !== 'function') {
      if (typeof this.opts.value === 'string') {
        getValue = {};
        getValue[this.opts.value] = result[this.opts.value];
      }
      return Bluebird.resolve(getValue);
    } else if (this.opts.value.length === 2) {
      // Promisify if passed a node style function
      getValue = Bluebird.promisify(this.opts.value.bind(this.opts));
    } else {
      getValue = this.opts.value;
    }
    return Bluebird.resolve(getValue(result));
  },
  _storeCachedResult: function(key, result) {
    var self = this;
    // If we didn't have a cachedKey, skip caching result
    if (!key) {
      return Bluebird.resolve(result);
    }
    return this._getValueFromResult(result).then(function(value) {
      var val;
      var addCached = Bluebird.promisify(self.opts.fileCache.addCached.bind(self.opts.fileCache));
      if (typeof value !== 'string') {
        if (value && typeof value === 'object' && Buffer.isBuffer(value.contents)) {
          // Shallow copy so "contents" can be safely modified
          val = objectAssign({}, value);
          val.contents = val.contents.toString('utf8');
        }
        // Check if the task changed the file path
        if (value.path !== self.originalPath) {
          value.filePathChangedInsideTask = true;
        }
        // Keep track of the original path
        value.originalPath = self.originalPath;
        val = JSON.stringify(value, null, 2);
      } else {
        val = value;
      }
      return addCached(self.opts.name, key, val);
    });
  }
});
module.exports = TaskProxy;