text: // Generated by CoffeeScript 1.10.0
  (function() {
    var JSONStorage, KEY_FOR_EMPTY_STRING, LocalStorage, MetaKey, QUOTA_EXCEEDED_ERR, StorageEvent, _emptyDirectory, _escapeKey, _rm, createMap, events, fs, path, writeSync,
      extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
      hasProp = {}.hasOwnProperty;
  
    path = require('path');
  
    fs = require('fs');
  
    events = require('events');
  
    writeSync = require('write-file-atomic').sync;
  
    KEY_FOR_EMPTY_STRING = '---.EMPTY_STRING.---';
  
    _emptyDirectory = function(target) {
      var i, len, p, ref, results;
      ref = fs.readdirSync(target);
      results = [];
      for (i = 0, len = ref.length; i < len; i++) {
        p = ref[i];
        results.push(_rm(path.join(target, p)));
      }
      return results;
    };
  
    _rm = function(target) {
      if (fs.statSync(target).isDirectory()) {
        _emptyDirectory(target);
        return fs.rmdirSync(target);
      } else {
        return fs.unlinkSync(target);
      }
    };
  
    _escapeKey = function(key) {
      var newKey;
      if (key === '') {
        newKey = KEY_FOR_EMPTY_STRING;
      } else {
        newKey = key.toString();
      }
      return newKey;
    };
  
    QUOTA_EXCEEDED_ERR = (function(superClass) {
      extend(QUOTA_EXCEEDED_ERR, superClass);
  
      function QUOTA_EXCEEDED_ERR(message) {
        this.message = message != null ? message : 'Unknown error.';
        if (Error.captureStackTrace != null) {
          Error.captureStackTrace(this, this.constructor);
        }
        this.name = this.constructor.name;
      }
  
      QUOTA_EXCEEDED_ERR.prototype.toString = function() {
        return this.name + ": " + this.message;
      };
  
      return QUOTA_EXCEEDED_ERR;
  
    })(Error);
  
    StorageEvent = (function() {
      function StorageEvent(key1, oldValue1, newValue1, url, storageArea) {
        this.key = key1;
        this.oldValue = oldValue1;
        this.newValue = newValue1;
        this.url = url;
        this.storageArea = storageArea != null ? storageArea : 'localStorage';
      }
  
      return StorageEvent;
  
    })();
  
    MetaKey = (function() {
      function MetaKey(key1, index1) {
        this.key = key1;
        this.index = index1;
        if (!(this instanceof MetaKey)) {
          return new MetaKey(this.key, this.index);
        }
      }
  
      return MetaKey;
  
    })();
  
    createMap = function() {
      var Map;
      Map = function() {};
      Map.prototype = Object.create(null);
      return new Map();
    };
  
    LocalStorage = (function(superClass) {
      var instanceMap;
  
      extend(LocalStorage, superClass);
  
      instanceMap = {};
  
      function LocalStorage(_location, quota) {
        this._location = _location;
        this.quota = quota != null ? quota : 5 * 1024 * 1024;
        if (!(this instanceof LocalStorage)) {
          return new LocalStorage(this._location, this.quota);
        }
        this._location = path.resolve(this._location);
        if (instanceMap[this._location] != null) {
          return instanceMap[this._location];
        }
        this.length = 0;
        this._bytesInUse = 0;
        this._keys = [];
        this._metaKeyMap = createMap();
        this._eventUrl = "pid:" + process.pid;
        this._init();
        this._QUOTA_EXCEEDED_ERR = QUOTA_EXCEEDED_ERR;
        instanceMap[this._location] = this;
        return instanceMap[this._location];
      }
  
      LocalStorage.prototype._init = function() {
        var _MetaKey, _decodedKey, _keys, error, i, index, k, len, stat;
        try {
          stat = fs.statSync(this._location);
          if ((stat != null) && !stat.isDirectory()) {
            throw new Error("A file exists at the location '" + this._location + "' when trying to create/open localStorage");
          }
          this._bytesInUse = 0;
          this.length = 0;
          _keys = fs.readdirSync(this._location);
          for (index = i = 0, len = _keys.length; i < len; index = ++i) {
            k = _keys[index];
            _decodedKey = decodeURIComponent(k);
            this._keys.push(_decodedKey);
            _MetaKey = new MetaKey(k, index);
            this._metaKeyMap[_decodedKey] = _MetaKey;
            stat = this._getStat(k);
            if ((stat != null ? stat.size : void 0) != null) {
              _MetaKey.size = stat.size;
              this._bytesInUse += stat.size;
            }
          }
          this.length = _keys.length;
        } catch (error) {
          fs.mkdirSync(this._location);
        }
      };
  
      LocalStorage.prototype.setItem = function(key, value) {
        var encodedKey, evnt, existsBeforeSet, filename, hasListeners, metaKey, oldLength, oldValue, valueString, valueStringLength;
        hasListeners = events.EventEmitter.listenerCount(this, 'storage');
        oldValue = null;
        if (hasListeners) {
          oldValue = this.getItem(key);
        }
        key = _escapeKey(key);
        encodedKey = encodeURIComponent(key);
        filename = path.join(this._location, encodedKey);
        valueString = value.toString();
        valueStringLength = valueString.length;
        metaKey = this._metaKeyMap[key];
        existsBeforeSet = !!metaKey;
        if (existsBeforeSet) {
          oldLength = metaKey.size;
        } else {
          oldLength = 0;
        }
        if (this._bytesInUse - oldLength + valueStringLength > this.quota) {
          throw new QUOTA_EXCEEDED_ERR();
        }
        writeSync(filename, valueString, 'utf8');
        if (!existsBeforeSet) {
          metaKey = new MetaKey(encodedKey, (this._keys.push(key)) - 1);
          metaKey.size = valueStringLength;
          this._metaKeyMap[key] = metaKey;
          this.length += 1;
          this._bytesInUse += valueStringLength;
        }
        if (hasListeners) {
          evnt = new StorageEvent(key, oldValue, value, this._eventUrl);
          return this.emit('storage', evnt);
        }
      };
  
      LocalStorage.prototype.getItem = function(key) {
        var filename, metaKey;
        key = _escapeKey(key);
        metaKey = this._metaKeyMap[key];
        if (!!metaKey) {
          filename = path.join(this._location, metaKey.key);
          return fs.readFileSync(filename, 'utf8');
        } else {
          return null;
        }
      };
  
      LocalStorage.prototype._getStat = function(key) {
        var error, filename;
        key = _escapeKey(key);
        filename = path.join(this._location, encodeURIComponent(key));
        try {
          return fs.statSync(filename);
        } catch (error) {
          return null;
        }
      };
  
      LocalStorage.prototype.removeItem = function(key) {
        var evnt, filename, hasListeners, k, meta, metaKey, oldValue, ref, v;
        key = _escapeKey(key);
        metaKey = this._metaKeyMap[key];
        if (!!metaKey) {
          hasListeners = events.EventEmitter.listenerCount(this, 'storage');
          oldValue = null;
          if (hasListeners) {
            oldValue = this.getItem(key);
          }
          delete this._metaKeyMap[key];
          this.length -= 1;
          this._bytesInUse -= metaKey.size;
          filename = path.join(this._location, metaKey.key);
          this._keys.splice(metaKey.index, 1);
          ref = this._metaKeyMap;
          for (k in ref) {
            v = ref[k];
            meta = this._metaKeyMap[k];
            if (meta.index > metaKey.index) {
              meta.index -= 1;
            }
          }
          _rm(filename);
          if (hasListeners) {
            evnt = new StorageEvent(key, oldValue, null, this._eventUrl);
            return this.emit('storage', evnt);
          }
        }
      };
  
      LocalStorage.prototype.key = function(n) {
        return this._keys[n];
      };
  
      LocalStorage.prototype.clear = function() {
        var evnt;
        _emptyDirectory(this._location);
        this._metaKeyMap = createMap();
        this._keys = [];
        this.length = 0;
        this._bytesInUse = 0;
        if (events.EventEmitter.listenerCount(this, 'storage')) {
          evnt = new StorageEvent(null, null, null, this._eventUrl);
          return this.emit('storage', evnt);
        }
      };
  
      LocalStorage.prototype._getBytesInUse = function() {
        return this._bytesInUse;
      };
  
      LocalStorage.prototype._deleteLocation = function() {
        delete instanceMap[this._location];
        _rm(this._location);
        this._metaKeyMap = {};
        this._keys = [];
        this.length = 0;
        return this._bytesInUse = 0;
      };
  
      return LocalStorage;
  
    })(events.EventEmitter);
  
    JSONStorage = (function(superClass) {
      extend(JSONStorage, superClass);
  
      function JSONStorage() {
        return JSONStorage.__super__.constructor.apply(this, arguments);
      }
  
      JSONStorage.prototype.setItem = function(key, value) {
        var newValue;
        newValue = JSON.stringify(value);
        return JSONStorage.__super__.setItem.call(this, key, newValue);
      };
  
      JSONStorage.prototype.getItem = function(key) {
        return JSON.parse(JSONStorage.__super__.getItem.call(this, key));
      };
  
      return JSONStorage;
  
    })(LocalStorage);
  
    exports.LocalStorage = LocalStorage;
  
    exports.JSONStorage = JSONStorage;
  
    exports.QUOTA_EXCEEDED_ERR = QUOTA_EXCEEDED_ERR;
  
  }).call(this);
  