Creates an in-memory kad storage adapter
@constructor
549914
function MemoryBackend(options) {
    this._options = options || {};
    assert(this._options.interval, 'options.interval is required');
    if (!this._options.minValue) {
        this._options.minValue = 0.1;
    }

    this._counters = {};
    // Exponential decay with factor 2, thrice per interval for better
    // smoothness, using the cubic root of 2).
    this._decayFactor = Math.pow(2, 1/3);

    // Start the periodic decay process.
    var self = this;
    this._decayCountersInterval = setInterval(function() {
        self._decayCounters();
    }, self._options.interval / 3);
}
379726
function initAdapters(container) {

        var calls = [];

        if (container === 'webserver') {
            _.each(adapters, function (adapter) {
                if (adapter.webInit) {
                    calls.push(adapter.webInit);
                }
            });
        }
        else {
            _.each(adapters, function (adapter) {
                if (adapter.init) {
                    calls.push(adapter.init);
                }
            });
        }

        return chainPromises(calls, config)
            .then(function (returnConfig) {
                if (returnConfig) {
                    return returnConfig;
                }
                else {
                    throw new Error('An adapter in the chain is not returning the config.');
                }
            });
    }
192615
function Adapter(params) {
	this.params = params || {};

	if (!this.params.dir) {
		throw new Error('`dir` parameter required');
	}

	this.migrationsFilePath = (
		this.params.migrationsFile ||
		pathUtils.join(this.params.dir, '.migrations')
	);

	this.dir = __dirname;
}
348380
function WebTreeStore(storageObject, storageId, dataChanged) {
            this.storage = storageObject;
            this.id = storageId;
            this._setItem(this.id + "-tree", true);
            this.dataChanged = dataChanged;
        }
1076613
function(storage) {

		this._data_uids = storage.uids;
		this._data_values = storage.values;
		this._data_names = storage.names;

	}
880681
function mkfile(path, options, realCallback) {
        var meta = {};
        var called;
        var callback = function (err) {
            if (called) {
                if (err) {
                    if (meta.stream) meta.stream.emit("error", err);
                    else console.error(err.stack);
                }
                else if (meta.stream) meta.stream.emit("saved");
                return;
            }
            called = true;
            return realCallback(err, meta);
        };

        if (options.stream && !options.stream.readable) {
            return callback(new TypeError("options.stream must be readable."));
        }

        // Pause the input for now since we're not ready to write quite yet
        var readable = options.stream;
        if (readable) {
            if (readable.pause) readable.pause();
            var buffer = [];
            readable.on("data", onData);
            readable.on("end", onEnd);
        }

        function onData(chunk) {
            buffer.push(["data", chunk]);
        }
        function onEnd() {
            buffer.push(["end"]);
        }
        function error(err) {
            resume();
            if (tempPath) {
                fs.unlink(tempPath, callback.bind(null, err));
            }
            else
                return callback(err);
        }
        
        function resume() {
            if (readable) {
                // Stop buffering events and playback anything that happened.
                readable.removeListener("data", onData);
                readable.removeListener("end", onEnd);

                buffer.forEach(function (event) {
                    readable.emit.apply(readable, event);
                });
                // Resume the input stream if possible
                if (readable.resume) readable.resume();
            }
        }
        
        var tempPath;
        var resolvedPath = "";

        mkdir();

        function mkdir() {
            if (options.parents) {
                mkdirP(dirname(path), {}, function(err) {
                    if (err) return error(err);
                    resolve();
                });
            }
            else {
                resolve();
            }
        }

        // Make sure the user has access to the directory and get the real path.
        function resolve() {
            resolvePath(path, function (err, _resolvedPath) {
                if (err) {
                    if (err.code !== "ENOENT") {
                        return error(err);
                    }
                    // If checkSymlinks is on we'll get an ENOENT when creating a new file.
                    // In that case, just resolve the parent path and go from there.
                    resolvePath(dirname(path), function (err, dir) {
                        if (err) return error(err);
                        resolvedPath = join(dir, basename(path));
                        createTempFile();
                    });
                    return;
                }
                
                resolvedPath = _resolvedPath;
                createTempFile();
            });
        }
        
        
        function createTempFile() {
            tempPath = tmpFile(dirname(resolvedPath), "." + basename(resolvedPath) + "-", "~");
            
            var mode = options.mode || umask & 0666;
            fs.stat(resolvedPath, function(err, stat) {
                if (err && err.code !== "ENOENT") return error(err);
                
                var uid = process.getuid ? process.getuid() : 0;
                var gid = process.getgid ? process.getgid() : 0;
                
                if (stat) {
                    mode = stat.mode & 0777;
                    uid = stat.uid;
                    gid = stat.gid;
                }

                // node 0.8.x adds a "wx" shortcut, but since it's not in 0.6.x we use the
                // longhand here.
                var flags = constants.O_CREAT | constants.O_WRONLY | constants.O_EXCL;
                fs.open(tempPath, flags, mode, function (err, fd) {
                    if (err) return error(err);
                    
                    fs.fchown(fd, uid, gid, function(err) {
                        fs.close(fd);
                        if (err) return error(err);
                        
                        pipe(fs.WriteStream(tempPath, {
                            encoding: options.encoding || null,
                            mode: mode
                        }));
                    });
                });
            });
        }

        function pipe(writable) {
            var hadError;
            
            if (readable) {
                readable.pipe(writable);
            }
            else {
                writable.on('open', function () {
                    if (hadError) return;
                    meta.stream = writable;
                    callback();
                });
            }
            writable.on('error', function (err) {
                hadError = true;
                error(err);
            });
            writable.on('close', function () {
                if (hadError) return;
                swap();
            });

            resume();
        }
        
        function swap() {
            fs.rename(tempPath, resolvedPath, function (err) {
                if (err) return error(err);
                callback();
            });
        }
    }
762530
function initializeKVPersistent (config) {
	/* NB Makes FS syscalls each time in case config changes during lifetime.
	 * Could cache the set of initialized dirs if this is a performance issue. */

	/* First try a mkdir. Dir might exist already. */
	try {
		fs.mkdirSync(config.cache.persistentDir);
	} catch (e) {
	}

	/* If we have a dir now, we're happy.
	 * This also works if persistentDir is a symlink. */
	try {
		const stats = fs.lstatSync(config.cache.persistentDir);
		if (stats.isDirectory()) {
			return true;
		} else {
			return false;
		}
	} catch (e) {
		/* Hmm. */
		return false;
	}
}
303313
function(k, v) {
    // remember every item in an object individually
    if (typeof arguments[0] == 'object')
      for (var v in k)
        this.remember(v, k[v])

    // retrieve memory
    else if (arguments.length == 1)
      return this.memory()[k]

    // store memory
    else
      this.memory()[k] = v

    return this
  }
1112901
function asDataMap(files, mapping, callback) {
  try {
    const out = files.reduce((obj, file) => {
      let key;
      switch (mapping) {
        case Mapping.DIR:
          key = path.dirname(file.path);
          break;
        case Mapping.MODULE:
          key = trimExtension(file.path).replace(PATH_SEP_RE, '.');
          break;
        default:
          key = file.path;
          break;
      }

      return Object.assign(obj, { [key]: file.data });
    }, {});
    async.nextTick(callback, null, out);
  } catch (error) {
    async.nextTick(callback, error);
  }
}
688945
function init(configuration){
    var self = {
        config : configuration,
        adapters : [],
        getWhenCurrentWritesDone : getWhenCurrentWritesDone
    };

    _.each(self.config.adapters, function(adapter){
        var adapterInstance;

        try {
            adapterInstance = require('./adapters/' + adapter.type).init(adapter);
        } catch (e) {
            console.log(chalk.red('Initialization Error: '), e);
            throw e;
        }

        adapterInstance.writeQueue = BB.resolve();

        self.adapters.push(adapterInstance);
    });

    [
        'error',
        'info',
        'debug',
        'warn',
        'trace',
        'critical'
    ].forEach(function (type) {
        /**
         * Create a TYPE log entry
         * @param category Categorize your error with a user defined label
         * @param args Include your customized messages. This should be a comma separated list just like `console.log`
         */
        self[type] = function () {
            // If we are still logging and there are messages to write
            if(arguments.length > 0){
                var category = (arguments.length > 1 && _.isString(arguments[0])) ? arguments[0] : '',
                    startIdx = (arguments.length > 1) ? 1 : 0;

                _write.call(self, type, category, Array.prototype.slice.call(arguments, startIdx));
            }
        };
    });

    return self;
}
708736
function (callback) {
            var idx = this.indexer.all()
            ,   r   = []
            ,   o
            ,   k
            for (var i = 0, l = idx.length; i < l; i++) {
                k     = idx[i] //v
                o     = JSON.parse(storage.getItem(k))
                o.key = k.replace(this.name + '.', '')
                r.push(o)
            }
            if (callback) this.fn(this.name, callback).call(this, r)
            return this
        }
269474
def create(self, key, value=None, dir=False, ttl=None, timeout=None):
        """"""
        return self.adapter.set(key, value, dir=dir, ttl=ttl,
                                prev_exist=False, timeout=timeout)
104675
function (key, callbackId) {
    const sender = this.sender
    if (!supportLocalStorage) {
      return callNotSupportFail(sender, callbackId)
    }
    if (!key) {
      sender.performCallback(callbackId, {
        result: FAILED,
        data: INVALID_PARAM
      })
      return
    }
    try {
      const val = localStorage.getItem(key)
      sender.performCallback(callbackId, {
        result: val ? SUCCESS : FAILED,
        data: val || UNDEFINED
      })
    }
    catch (e) {
      // accept any exception thrown during a storage attempt as a quota error
      callFail(sender, callbackId)
    }
  }
408850
function create() {
  var defaultState = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};

  var state = clone(defaultState);
  var watchers = [];

  /**
   * Get a store value by path/key
   *
   * @param {String} path
   * @throws Error when specified store key is not found
   * @return value
   */
  function get(path) {
    var value = _get(state, path);

    if (value === undefined) {
      throw new Error('[toystore] Requested store key "' + path + '" was not found in store.');
    }

    return clone(value);
  }

  /**
   * Get multiple path values from store
   *
   * @param {String[]} paths
   * @return {Object} key/value pair of path => value
   */
  function getAll(paths) {
    if (paths === undefined) {
      return clone(state);
    }

    if (!paths instanceof Array) {
      throw new Error('[toystore] getAll() argument "paths" must be an array.');
    }

    var values = paths.map(get);

    return zipObject(paths, values);
  }

  /**
   * Get a store value by path/key
   *
   * @param {String} path
   * @return value
   */
  function getSilent(path) {
    return _get(state, path);
  }

  /**
   * Run all watchers with new/current values
   */
  function notifyAllWatchers() {
    watchers.map(function _notifyWatcher(watcher) {
      var watchedKeyValues = {};
      try {
        watchedKeyValues = getAll(watcher.paths);
      } catch (e) {}

      watcher.callback(watchedKeyValues);
    });
  }

  /**
   * Notify/update watcher functions for given paths
   *
   * @param {String[]} paths
   */
  function notifyWatchersOnPaths(paths) {
    var expandedPaths = _expandNestedPaths(paths);

    watchers.map(function _notifyWatcher(watcher) {
      var hasPath = intersect(expandedPaths, watcher.paths).length > 0;

      if (hasPath) {
        var watchedKeyValues = {};
        try {
          watchedKeyValues = getAll(paths);
        } catch (e) {}

        if (watcher.options.async !== false) {
          setTimeout(function () {
            watcher.callback(watchedKeyValues);
          }, watcher.options.async || 0);
        } else {
          watcher.callback(watchedKeyValues);
        }
      }
    });

    if (paths !== '*') {
      notifyGlobalWatchers();
    }
  }

  /**
   * Notify/update global watchers
   */
  function notifyGlobalWatchers() {
    notifyWatchersOnPaths('*');
  }

  /**
   * Set a store value at path/key to given value
   *
   * @param {String} path
   * @param {mixed} value
   * @param {Boolean} value
   * @return null
   */
  function set(path, value) {
    var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};

    var paths = _pathsArray(path);
    var existingValue = void 0;

    // If using options.compare = true.  JSON.strigify compare the two sets of data.
    // If they are exactly the same, abort the update.
    if (options.compare) {
      existingValue = getSilent(path);

      if (JSON.stringify(value) === JSON.stringify(existingValue)) {
        return;
      }
    }

    // Get all paths to notify for updates if given an object
    if (_isObject(value) === true) {
      existingValue = existingValue || getSilent(path);

      // If previous value was also an object, we need to see which keys have
      // changed to notify watchers on those keys
      if (_isObject(existingValue)) {

        var oldKeys = _deepKeys(existingValue, path);
        var removedKeys = void 0;

        paths = _deepKeys(value, path);
        removedKeys = difference(oldKeys, paths);

        // If keys were removed in set, we need to notify those watchers
        if (removedKeys.length > 0) {
          paths = paths.concat(removedKeys);
        }
      }
    }

    setSilent(path, value);
    notifyWatchersOnPaths(paths);
  }

  /**
   * Set a store value at path/key to given value WITHOUT notifying watchers
   *
   * @param {String} path
   * @param {mixed} value
   * @return null
   */
  function setSilent(path, value) {
    // Cannot set things that can't be serialized
    var valueType = typeof value === 'undefined' ? 'undefined' : _typeof(value);

    if (valueType === 'function') {
      throw new Error('[toystore] Cannot set "' + path + '" with value type "' + valueType + '". All store values must be serializable.');
    }

    // Setting 'undefined' on an object key here will remove it from the store,
    // so we switch it to null. Removing keys should only be done with 'unset'.
    if (value === undefined) {
      value = null;
    }

    _set(state, path, value);
  }

  /**
   * Set multiple paths with given values to the store
   *
   * @param {Object} key/value pair of path => value
   * @return null
   */
  function setAll(obj) {
    var paths = Object.keys(obj);

    paths.map(function (path) {
      return setSilent(path, obj[path]);
    });
    notifyWatchersOnPaths(paths);
  }

  /**
   * Reset the whole state object to provided one
   *
   * @param {Object} newState (optional) - Will reset to first provided state if none provided
   * @return null
   */
  function reset(newState) {
    state = clone(newState || defaultState);

    notifyAllWatchers();
  }

  /**
   * Watch for changes on a given key, and execute the provided callback when there are changes
   *
   * @param {String[]|String} String path or array of paths to watch
   * @param {Function} callback to execute when there are changes
   * @param {Object} options Options
   * @param {Boolean} options.async Callback execution is async (in next cycle) or sync (as soon as the key changes)
   * @param {Number} options.priority Controls the order the provided callback is called when multiple watches exist on the same key.
   * @return {String} id of watcher (useful for unwatch())
   */
  function watch(paths, callback) {
    var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};

    paths = paths === '*' ? paths : _pathsArray(paths);
    var id = randomString();
    var defaultOptions = { async: false, priority: 0 };

    options = Object.assign({}, defaultOptions, options);

    watchers.push({
      callback: callback,
      id: id,
      options: options,
      paths: paths
    });

    watchers = watchers.sort(_sortByPriority);

    return id;
  }

  /**
   * Watch ALL keys, and execute the provided callback on any and every key change
   */
  function watchAll(callback, options) {
    return watch('*', callback, options);
  }

  /**
   * Watch for changes on a given key once, and execute the provided callback
   * when there are changes. Callback removes itself after the first call so
   * that it is never called again.
   *
   * @param {String[]|String} String path or array of paths to watch
   * @param {Function} callback to execute when there are changes
   * @param {Object} options Options
   * @param {Number} options.priority Controls the order the provided callback is called when multiple watches exist on the same key.
   */
  function watchOnce(paths, callback) {
    var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : { priority: 0 };

    var id = void 0;
    var onceCallback = function _watchOnceCallback() {
      unwatch(id);
      callback.apply(undefined, arguments);
    };

    id = watch(paths, onceCallback, options);
  }

  /**
   * Remove key
   */
  function unset(path) {
    _set(state, path, undefined);
  }

  /**
   * Clear/remove specific watcher by id or callback function
   *
   * @param {String|Function} id - String id (returned from watch() or callback function)
   */
  function unwatch(id) {
    var type = typeof id === 'undefined' ? 'undefined' : _typeof(id);
    var index = watchers.findIndex(function _matchWatcher(watcher) {
      return watcher && (type === 'string' ? watcher.id === id : watcher.callback === id);
    });

    if (index !== -1) {
      // We can't delete the last watcher...
      if (watchers.length === 1) {
        unwatchAll();
      } else {
        delete watchers[index];
      }
    }
  }

  /**
   * Clear/remove all watchers
   */
  function unwatchAll() {
    watchers = [];
  }

  // Public API
  return {
    get: get,
    getAll: getAll,
    reset: reset,
    set: set,
    setAll: setAll,
    setSilent: setSilent,
    watch: watch,
    watchAll: watchAll,
    watchOnce: watchOnce,
    unset: unset,
    unwatch: unwatch,
    unwatchAll: unwatchAll
  };
}
663393
function _initStorage(options) {
	        var self = this;
	        var dbInfo = {};
	        if (options) {
	            for (var i in options) {
	                dbInfo[i] = options[i];
	            }
	        }

	        dbInfo.keyPrefix = dbInfo.name + '/';

	        if (dbInfo.storeName !== self._defaultConfig.storeName) {
	            dbInfo.keyPrefix += dbInfo.storeName + '/';
	        }

	        self._dbInfo = dbInfo;

	        return new Promise(function (resolve, reject) {
	            resolve(__webpack_require__(3));
	        }).then(function (lib) {
	            dbInfo.serializer = lib;
	            return Promise.resolve();
	        });
	    }
1118126
function StoragePlugin(options) {

    var merge       = merge || require('utils/merge');
    var Collection  = Collection || require('utils/collection');
    var uuid        = uuid || require('vendor/uuid');


    var self = {
        'options' : {
            'bucket': 'default'
        }
    };

    var bucketInstance = {};
    var storage     = null;

    var entities    = {}, collections = {}; // entities & collections (data) objects
    var keywords    = ['not null']; // TODO - null, exists


    var proto = {
        'bucket'    : undefined,
        'drop'      : bucketDrop,
        'Collection': Collection
    };

    var entityProto = {
        'insert'    : collectionInsert,
        'find'      : collectionFind,
        'findOne'   : collectionFindOne,
        'update'    : null,
        'delete'    : collectionDelete,
        'drop'      : collectionDrop
    };

    var init = function(options) {

        // detect if cookies are enabled
        if ( !window.localStorage || window.localStorage && ! typeof(window.localStorage.setItem) == 'undefined' ) {
            throw new Error('Make sure your browser supports `window.localStorage` to use Gina Storage. See: `https://developer.mozilla.org/en-US/docs/Web/API/Web_Storage_API#Browser_compatibility`');
        }

        if ( typeof(options) != 'object' && typeof(options) != 'undefined' ) {
            throw new Error('`options` must be an object')
        } else if ( typeof(options) == 'undefined' ) {
            var options = {}
        }

        self.options    = merge(options, self.options);
        storage         = window.localStorage;

        var bucketName  = self.options['bucket'];
        var bucket      = storage.getItem(bucketName);

        if (!bucket && bucketName != undefined) {
            //console.log('creating new bucket !');
            bucketCreate(bucketName);
        } else if (bucketName == undefined) {
            throw new Error('`bucket` name cannot be undefined')
        }

        bucketInstance['bucket'] = bucketName;
        bucketInstance = merge(bucketInstance, proto);
    }



    /**
     * Create bucket
     *
     * @param {string} bucketName
     * */
    var bucketCreate = function(bucketName) {
        storage.setItem(bucketName, JSON.stringify(collections));
    }

    /**
     * Drop bucket
     *
     * */
    function bucketDrop() {
        storage.removeItem(self.options['bucket']);
        bucketInstance = null;

        for (var prop in this) {
            delete this[prop]
        }

        return bucketInstance;
    }

    /**
     * Create or Get Collection by name
     *
     * @param {string} name - Collection name
     * */
    function Collection(name) {
        // retrieve collections state
        collections = JSON.parse(storage.getItem(this['bucket']));
        //console.log('collections ', (collections || null) );
        if ( typeof(collections[name]) == 'undefined' ) {
            collections[name] = [];
            storage.setItem(this['bucket'], JSON.stringify(collections));
            collections = JSON.parse(storage.getItem(this['bucket']));
        }

        entities[name]      = { '_collection': name, '_bucket': this['bucket'] };
        entities[name]      = merge(entities[name], entityProto);

        return entities[name]
    }

    /**
     * Drop collection
     *
     * @param {string} name
     * */
    function collectionDrop(name) {
        if ( typeof(collections[ this['_collection'] ]) == 'undefined' ) {
            throw new Error('Collection `'+name+'` not found')
        }

        delete entities[ this['_collection'] ]; // delete entity
        delete collections[ this['_collection'] ]; // delete data

        storage.setItem(this['_bucket'], JSON.stringify(collections));
    }

    /**
     * Insert into collection
     *
     * @param {object} content
     * */
    function collectionInsert(content) {

        // TODO - add uuid
        content['_id']         = uuid.v1();
        content['_createdAt']  = new Date().format("isoDateTime");
        content['_updatedAt']  = new Date().format("isoDateTime");

        collections[ this['_collection'] ][ collections[ this['_collection'] ].length ] = content;

        storage.setItem(this['_bucket'], JSON.stringify(collections));
    }

    /**
     * Find from collection
     *
     * // TODO - add options
     *
     * @param {object} filter
     * @param {object} [options] - e.g.: limit
     *
     * @return {array} result
     * */
    function collectionFind(filter, options) {
        if (!filter) {
            // TODO - limit of ten by
            return collections[ this['_collection'] ]
        }

        if ( typeof(filter) !== 'object' ) { // == findAll
            throw new Error('filter must be an object');
        } else {
            //console.log('search into ', this['_collection'], collections[ this['_collection'] ], collections);
            var content             = collections[ this['_collection'] ]
                , condition         = filter.count()
                , i                 = 0
                , found             = []
                , localeLowerCase   = '';

            for (var o in content) {
                for (var f in filter) {
                    localeLowerCase = ( typeof(filter[f]) != 'boolean' ) ? filter[f].toLocaleLowerCase() : filter[f];
                    if ( filter[f] && keywords.indexOf(localeLowerCase) > -1 && localeLowerCase == 'not null' && typeof(content[o][f]) != 'undefined' && typeof(content[o][f]) !== 'object' && content[o][f] != 'null' && content[o][f] != 'undefined' ) {
                        if (found.indexOf(content[o][f]) < 0 ) {
                            found[i] = content[o][f];
                            ++i
                        }

                    } else if ( typeof(content[o][f]) != 'undefined' && typeof(content[o][f]) !== 'object' && content[o][f] === filter[f] ) {
                        found[i] = content[o];
                        ++i
                    }
                }
            }
        }

        return found
    }

    //function collectionLimit(limit) {}

    /**
     * Find a single result from collection
     *
     * e.g:
     *  // getting a record
     *  > var objectRecord = <bucket>.Collection('myBucket').findOne({_name: "someName"});
     *
     *  // updating record by adding or updating an existing property
     *  > objectRecord.myProperty = 'some value';
     *  > objectRecord.save();
     *
     *  // deleting record
     *  > objectRecord.myProperty.delete()
     *
     * @param {object} filter
     *
     * @returns {object|array|string} result
     *
     * */
    function collectionFindOne(filter) {

        if ( typeof(filter) !== 'object' ) {
            throw new Error('filter must be an object');
        } else {
            var content             = collections[ this['_collection'] ]
                , condition         = filter.count()
                , i                 = 0
                , result            = null
                , localeLowerCase   = '';


            //console.log('condition ', condition, '\nfitler', filter, '\ncontent', content);
            if (condition == 0) return null;

            for (var o in content) {
                for (var f in filter) {
                    localeLowerCase = ( typeof(filter[f]) != 'boolean' ) ? filter[f].toLocaleLowerCase() : filter[f];
                    if ( filter[f] && keywords.indexOf(localeLowerCase) > -1 && localeLowerCase == 'not null' && typeof(content[o][f]) != 'undefined' && typeof(content[o][f]) !== 'object' && content[o][f] === filter[f] && content[o][f] != 'null' && content[o][f] != 'undefined' ) {
                        if (result.indexOf(content[o][f]) < 0 ) {
                            ++i;
                            if (i === condition) {
                                result                   = content[o];
                                result['_index']         = o;
                                result['_collection']    = this['_collection'];
                                result['_bucket']        = this['_bucket'];
                            }

                        }

                    } else if ( typeof(content[o][f]) != 'undefined' && typeof(content[o][f]) !== 'object' && content[o][f] === filter[f] ) {
                        ++i;
                        if (i === condition) {
                            result                   = content[o];
                            result['_index']         = o;
                            result['_collection']    = this['_collection'];
                            result['_bucket']        = this['_bucket'];
                            result['_filter']        = filter;
                        }
                    }
                }
            }
        }

        if (result) {
            /**
             * save
             *  e.g.:
             *      // updating property
             *      <obj>.property = 'value';
             *      <obj>.save();
             *
             *      // deleting property
             *      delete <obj>.property;
             *      <obj>.save(true);
             *
             * @param {boolean} enforceDeleted
             * */
            result['save'] = function(enforceDeleted) {

                var enforceDeleted = enforceDeleted || false;

                try {
                    //backing up collections
                    var tmpCollections  = JSON.parse(JSON.stringify(collections));
                    var index           = this['_index'];
                    var collection      = this['_collection'];
                    var bucket          = this['_bucket'];
                    var filter          = this['_filter'];
                    this['_updatedAt']  = new Date().format("isoDateTime");

                    merge(tmpCollections[ collection ][ index ], this, true);

                    // cleaning
                    delete tmpCollections[ collection ][ index ]['_index'];
                    delete tmpCollections[ collection ][ index ]['_collection'];
                    delete tmpCollections[ collection ][ index ]['_bucket'];
                    delete tmpCollections[ collection ][ index ]['save'];
                    delete tmpCollections[ collection ][ index ]['_filter'];

                    if (enforceDeleted && typeof(tmpCollections[ collection ][ index ]) == 'object' ) {

                        var parseEnforcedCollection = function (arr, target) {
                            for (var i = 0, len = arr.length; i < len; ++i) {
                                if ( typeof (target[i]) == 'object' && typeof(arr[i]) != 'undefined' && !Array.isArray(arr[i]) ) {
                                    parseEnforced(arr[i], target[i])
                                } else if ( !Array.isArray(arr[i]) ){
                                    if (typeof(arr[i]) == 'undefined') {
                                        delete target[i]
                                    }
                                } else { // is collection type
                                    parseEnforcedCollection(arr[i], target[i])
                                }
                            }

                            return target
                        }

                        var parseEnforced = function (obj, target) {
                            for (var prop in target) {
                                if ( typeof (target[prop]) == 'object' && typeof(obj[prop]) != 'undefined' && !Array.isArray(obj[prop]) ) {
                                    parseEnforced(obj[prop], target[prop])
                                } else if ( !Array.isArray(obj[prop]) ){
                                    if (typeof(obj[prop]) == 'undefined') {
                                        delete target[ prop ]
                                    }
                                } else { // is collection type
                                    parseEnforcedCollection(obj[prop], target[prop])
                                }
                            }

                            return target
                        };

                        if ( Array.isArray(tmpCollections[ collection ][ index ]) ) {
                            tmpCollections[ collection ][ index ] = parseEnforcedCollection(this, tmpCollections[ collection ][ index ])
                        } else if ( typeof(tmpCollections[ collection ][ index ] ) == 'object' ) {
                            tmpCollections[ collection ][ index ] = parseEnforced(this, tmpCollections[ collection ][ index ])
                        } else {
                            if (typeof(this[prop]) == 'undefined') {
                                delete tmpCollections[ collection ][ index ]
                            }
                        }
                    }

                    collections[ collection ][ index ] = tmpCollections[ collection ][ index ];

                    // saving
                    storage.setItem(bucket, JSON.stringify(collections));

                    return collectionFindOne(filter)

                } catch (err) {
                    throw err
                }
            }
        }


        return result
    }

    /**
     * Delete from collection
     *
     * @param {object} filter
     *
     * @return {array} result
     * */
    function collectionDelete(filter) {

        if ( typeof(filter) !== 'object' ) {
            throw new Error('filter must be an object');
        } else {
            var content     = JSON.parse(JSON.stringify( collections[ this['_collection'] ] ))
                //, condition = filter.count()
                , i         = 0
                , found     = [];

            for (var o in content) {
                for (var f in filter) {
                    if ( filter[f] && keywords.indexOf(filter[f].toLocaleLowerCase()) > -1 && filter[f].toLowerCase() == 'not null' && typeof(content[o][f]) != 'undefined' && typeof(content[o][f]) !== 'object' && content[o][f] != 'null' && content[o][f] != 'undefined' ) {
                        if (found.indexOf(content[o][f]) < 0 ) {
                            found[i] = content[o][f];
                            delete collections[ this['_collection'] ][o][f];
                            ++i
                        }

                    } else if ( typeof(content[o][f]) != 'undefined' && typeof(content[o][f]) !== 'object' && content[o][f] === filter[f] ) {
                        found[i] = content[o];
                        collections[ this['_collection'] ].splice(o, 1);
                        ++i
                    }
                }
            }
        }

        if (found.length > 0 ) {
            storage.setItem(this['_bucket'], JSON.stringify(collections));
            return true
        }

        return false
    }

    init(options);


    return bucketInstance
}
983510
function load() {
      var key, data, value, pos = 0;

      items = {};

      // localStorage can be disabled on WebKit/Gecko so make a dummy storage
      if (!hasOldIEDataSupport) {
        return;
      }

      function next(end) {
        var value, nextPos;

        nextPos = end !== undefined ? pos + end : data.indexOf(',', pos);
        if (nextPos === -1 || nextPos > data.length) {
          return null;
        }

        value = data.substring(pos, nextPos);
        pos = nextPos + 1;

        return value;
      }

      storageElm.load(userDataKey);
      data = storageElm.getAttribute(userDataKey) || '';

      do {
        var offset = next();
        if (offset === null) {
          break;
        }

        key = next(parseInt(offset, 32) || 0);
        if (key !== null) {
          offset = next();
          if (offset === null) {
            break;
          }

          value = next(parseInt(offset, 32) || 0);

          if (key) {
            items[key] = value;
          }
        }
      } while (key !== null);

      updateKeys();
    }