expirableStorage

allow web storage api save data with expires.

This script should not be not be installed directly. It is a library for other scripts to include with the meta directive // @require https://greasyfork.org/scripts/32752-expirablestorage/code/expirableStorage.js?version=215251

// ==UserScript==
// @name               expirableStorage
// @namespace          https://github.com/cologler/
// @version            0.1.5
// @description        allow web storage api save data with expires.
// @author             cologler
// @grant              none
// ==/UserScript==

// this lib was hosting on https://greasyfork.org/scripts/32752.
// you can just require: https://greasyfork.org/scripts/32752/code/expirableStorage.js

// just let type script work.
(function() { function require(){}; require("greasemonkey"); })();

let ExpirableStorage = (() => {
    'use strict';

    class ExpirableStorage {
        constructor(baseStorage) {
            this._baseStorage = baseStorage;

            Object.defineProperties(this, {
                length: {
                    get: () => baseStorage.length
                },
                supportObject: {
                    get: () => true
                }
            });
        }

        key(index) {
            return this._baseStorage.key(index);
        }

        getItem(k) {
            let val = this.getEntity(k);
            if (val && !val.isExpired) {
                return val.content;
            }
            return null;
        }

        getEntity(k, removeExpired = true) {
            let val = this._baseStorage.getItem(k);
            if (val) {
                if (!this._baseStorage.supportObject) {
                    val = JSON.parse(val);
                }
                let ret = {
                    isExpired: !(val.expiresAt === undefined || new Date().getTime() < val.expiresAt),
                    content: val.content
                };
                if (ret.isExpired && removeExpired) {
                    this._baseStorage.removeItem(k);
                }
                return ret;
            }
            return null;
        }

        setItem(k, v, expiresAtTime=undefined) {
            if (expiresAtTime !== undefined) {
                if (typeof expiresAtTime !== 'number') throw 'expiresAtTime must be number.';
                if (isNaN(expiresAtTime)) throw 'expiresAtTime cannot be NaN.';
            }

            let val = {
                content: v,
                expiresAt: expiresAtTime
            };
            if (!this._baseStorage.supportObject) {
                val = JSON.stringify(val);
            }
            return this._baseStorage.setItem(k, val);
        }

        setItemExpiresAfter(k, v, expiresAfterMS) {
            if (typeof expiresAfterMS !== 'number') throw 'expiresAfterMS must be number.';
            if (isNaN(expiresAfterMS)) throw 'expiresAfterMS cannot be NaN.';

            return this.setItem(k, v, (new Date().getTime() + expiresAfterMS));
        }

        removeItem(k) {
            return this._baseStorage.removeItem(k);
        }

        clear() {
            return this._baseStorage.clear();
        }

        clearExpired() {
            let keys = null;
            if (this._baseStorage.keys) {
                keys = this._baseStorage.keys();
            } else {
                keys = [];
                let len = this._baseStorage.length;
                for (var i = 0; i < len; i++) {
                    keys.push(this._baseStorage.key(i));
                }
            }
            let self = this;
            keys.forEach(k => {
                try {
                    self.getItem(k);
                } catch (error) { /* ignore json parse error */ }
            });
        }
    }

    return ExpirableStorage;
})();