prefer-storage
Version:
1. key: 键名不唯一 2. value: 只能存储string类型 3. time: 没有过期时间 4. handle data: 不能对数据统一处理
563 lines (547 loc) • 26.8 kB
JavaScript
;
/******************************************************************************
Copyright (c) Microsoft Corporation.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
***************************************************************************** */
/* global Reflect, Promise, SuppressedError, Symbol */
var extendStatics = function(d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
function __extends(d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
}
var __assign = function() {
__assign = Object.assign || function __assign(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
function __awaiter(thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
}
function __generator(thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (g && (g = 0, op[0] && (_ = 0)), _) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
}
typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
var e = new Error(message);
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
};
var Project = /** @class */ (function () {
function Project(options) {
var _a, _b, _c, _d;
this.name = options.name;
this.keys = options.keys;
this.expire = (_a = options.expire) !== null && _a !== void 0 ? _a : 0;
this.idbVersion = (_b = options.idbVersion) !== null && _b !== void 0 ? _b : 1;
this.idbStoreOption = (_c = options.idbStoreOption) !== null && _c !== void 0 ? _c : { keyPath: '_key' };
this.idCreateIndexs = (_d = options.idCreateIndexs) !== null && _d !== void 0 ? _d : ['pathname'];
this.beforeGet = options.beforeGet;
this.afterGet = options.afterGet;
this.beforeSet = options.beforeSet;
this.afterSet = options.afterSet;
this.idBeforeGet = options.idBeforeGet;
this.idBeforeSet = options.idBeforeSet;
this.idAfterSet = options.idAfterSet;
var data = __assign({}, options);
delete data.name;
delete data.keys;
delete data.expire;
delete data.idbVersion;
delete data.beforeGet;
delete data.afterGet;
delete data.beforeSet;
delete data.afterSet;
delete data.idBeforeGet;
delete data.idBeforeSet;
delete data.idAfterSet;
this.options = data;
}
return Project;
}());
var StorageStrategy = {
boolean: {
read: function (v) { return v === 'true'; },
writeIn: function (v) { return String(v); }
},
object: {
read: function (v) { return JSON.parse(v); },
writeIn: function (v) { return JSON.stringify(v); }
},
array: {
read: function (v) { return JSON.parse(v); },
writeIn: function (v) { return JSON.stringify(v); }
},
number: {
read: function (v) { return +v; },
writeIn: function (v) { return String(v); }
},
any: {
read: function (v) { return v; },
writeIn: function (v) { return String(v); }
},
string: {
read: function (v) { return v; },
writeIn: function (v) { return v; }
},
map: {
read: function (v) { return new Map(JSON.parse(v)); },
writeIn: function (v) { return JSON.stringify(Array.from(v)); }
},
set: {
read: function (v) { return new Set(JSON.parse(v)); },
writeIn: function (v) { return JSON.stringify(Array.from(v)); }
},
date: {
read: function (v) { return new Date(v); },
writeIn: function (v) { return v.toISOString(); }
}
};
// 获取全路径key
var getNewKey = function (name, key) {
return "".concat(name, "__").concat(key);
};
// indexDb获取存储对象
var getIdbValue = function (keyKey, keyValue) {
var _a;
return _a = {}, _a[keyKey] = keyValue, _a;
};
// 获取value的类型
var getValueType = function (value) {
return Object.prototype.toString.call(value).slice(8, -1).toLowerCase();
};
// 判断是否过期
var isDue = function (time, expire) {
return (expire * 60 * 60 * 1000 + new Date(time).getTime()) < new Date().getTime();
};
// 获取当前页面的全路径(除了域名)
var getFullPath = function () {
return window.location.href.replace(/^https?:\/\/[^/]+(.*)$/, '$1');
};
// 对数据进行序列化
var handleGetJSONData = function (type, value, reject) {
var writeIn = (StorageStrategy[type] || {}).writeIn;
if (!writeIn)
reject(new Error("\u5F53\u524D\u5B58\u50A8\u7684\u6570\u636E\u7C7B\u578B\u662F".concat(type, ", \u6CA1\u6709\u5339\u914D\u5230")));
var _value;
try {
_value = writeIn(value);
}
catch (e) {
_value = value;
}
return _value;
};
var PreferStorage$1 = /** @class */ (function (_super) {
__extends(PreferStorage, _super);
function PreferStorage(storage, projectData) {
var _this = _super.call(this, projectData) || this;
_this.storageName = storage;
_this.storage = storage === 'local' ? window.localStorage : window.sessionStorage;
return _this;
}
PreferStorage.prototype.get = function (key) {
return __awaiter(this, void 0, void 0, function () {
var _this = this;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, new Promise(function (resolve, reject) {
var _a = _this, storage = _a.storage, name = _a.name;
if (!_this.keys.includes(key)) {
reject(new Error("\u5F53\u524D".concat(_this.name, "\u9879\u76EE\u4E2D").concat(_this.storageName + 'Storage', "\u4E0D\u5B58\u5728").concat(key, "\u7684\u952E\uFF0C\u8BF7\u786E\u5B9A\u53C2\u6570\u662F\u5426\u6B63\u786E")));
return;
}
var _key = getNewKey(name, key);
var v = storage.getItem(_key);
var _v;
var _time = '';
var _pathname = '';
try {
_v = JSON.parse(v);
var type = _v.type, value = _v.value, time = _v.time, pathname = _v.pathname;
_time = time;
_pathname = pathname;
var fn = StorageStrategy[type];
if (fn) {
_v = fn.read(value);
}
else {
_v = v;
}
}
catch (e) {
_v = v;
}
var result = { v: _v, _isDue: _time ? isDue(_time, _this.expire) : false, _key: _key, _pathname: _pathname };
if (_this.beforeGet) {
_this.beforeGet(result).then(function (newData) { resolve(newData || result); }).catch(function (e) { reject(e || new Error("".concat('beforeGet', "\u89C4\u5219\u6CA1\u901A\u8FC7\uFF0C\u8BF7\u67E5\u770BbeforeGet\u51FD\u6570"))); });
}
else {
resolve(result);
}
if (_this.afterGet) {
void _this.afterGet(key);
}
})];
case 1: return [2 /*return*/, _a.sent()];
}
});
});
};
PreferStorage.prototype.set = function (key, value) {
return __awaiter(this, void 0, void 0, function () {
var _this = this;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, new Promise(function (resolve, reject) {
var _a = _this, name = _a.name, storage = _a.storage;
if (!_this.keys.includes(key)) {
reject(new Error("\u5F53\u524D".concat(_this.name, "\u9879\u76EE\u4E2D").concat(_this.storageName + 'Storage', "\u4E0D\u80FD\u6DFB\u52A0").concat(key, "\u7684\u952E\uFF0C\u8BF7\u5728initProject\u51FD\u6570\u8C03\u7528\u5904\u6DFB\u52A0\u767D\u540D\u5355")));
return;
}
var _key = getNewKey(name, key);
var type = getValueType(value);
if (type === 'null')
reject(new Error('当前要存储的值为null'));
var _value = handleGetJSONData(type, value, reject);
var result = { type: type, time: new Date().toLocaleString(), pathname: getFullPath(), value: _value };
if (_this.beforeSet) {
_this.beforeSet(__assign(__assign({}, result), { key: key, value: value })).then(function (res) {
var type = getValueType(res.value);
if (type === 'null')
reject(new Error('当前要存储的值为null'));
res.type = type;
res.value = handleGetJSONData(type, res.value, reject);
storage.setItem(_key, JSON.stringify(res));
_this.setOrRemoveSuccess(resolve, res);
}).catch(function (e) { reject(e); });
}
else {
storage.setItem(_key, JSON.stringify(result));
_this.setOrRemoveSuccess(resolve, result);
}
})];
case 1:
_a.sent();
return [2 /*return*/];
}
});
});
};
PreferStorage.prototype.remove = function (key) {
return __awaiter(this, void 0, void 0, function () {
var _this = this;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, new Promise(function (resolve, reject) {
if (!_this.keys.includes(key)) {
reject(new Error("\u5F53\u524D".concat(_this.name, "\u9879\u76EE\u4E2D").concat(_this.storageName + 'Storage', "\u4E0D\u5B58\u5728").concat(key, "\u7684\u952E\uFF0C\u8BF7\u786E\u5B9A\u53C2\u6570\u662F\u5426\u6B63\u786E")));
return;
}
var _a = _this, name = _a.name, storage = _a.storage;
var _key = getNewKey(name, key);
storage.removeItem(_key);
_this.setOrRemoveSuccess(resolve);
})];
case 1:
_a.sent();
return [2 /*return*/];
}
});
});
};
PreferStorage.prototype.setOrRemoveSuccess = function (resolve, res) {
if (this.afterSet) {
this.afterSet(res).then(function () { resolve(true); }).catch(function (e) { console.log(e); });
}
else {
resolve(true);
}
};
PreferStorage.prototype.clear = function () {
return __awaiter(this, void 0, void 0, function () {
var _this = this;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, new Promise(function (resolve) {
var _a = _this, name = _a.name, storage = _a.storage;
var keys = Object.keys(storage);
keys.forEach(function (key) {
var regex = new RegExp("^".concat(name, ".*$"));
var isMatch = regex.test(key);
if (isMatch) {
void _this.remove(key);
}
});
resolve(true);
})];
case 1:
_a.sent();
return [2 /*return*/];
}
});
});
};
return PreferStorage;
}(Project));
var IndexedDB = /** @class */ (function (_super) {
__extends(IndexedDB, _super);
function IndexedDB(options, projectData) {
var _this = this;
var objectStoreName = options.objectStoreName, storeOption = options.storeOption, idCreateIndexs = options.idCreateIndexs;
_this = _super.call(this, projectData) || this;
_this.objectStoreName = objectStoreName;
_this.storeOption = storeOption;
_this.createIndexs = idCreateIndexs;
if (window.indexedDB) {
_this.init();
}
else {
throw new Error('本浏览器不支持indexDB');
}
return _this;
}
IndexedDB.prototype.init = function () {
var _this = this;
// 打开或创建数据库
var request = indexedDB.open(this.name, this.idbVersion);
this.readyPromise = new Promise(function (resolve, reject) {
_this.readyPromiseResolve = resolve;
_this.readyPromiseReject = reject;
});
// 数据库名不存在,或打开的数据库版本高于已存在的数据库版本
request.onupgradeneeded = function (event) {
_this.db = event.target.result;
_this.createStore();
};
// 数据库打开成功的回调
request.onsuccess = function (event) {
_this.db = event.target.result;
_this.readyPromiseResolve();
};
request.onerror = function (event) {
_this.readyPromiseReject(event.target.error);
};
};
IndexedDB.prototype.ready = function () {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, this.readyPromise];
case 1:
_a.sent();
return [2 /*return*/];
}
});
});
};
IndexedDB.prototype.createStore = function () {
var _a, _b;
var objectStoreNames = this.db.objectStoreNames;
// 创建表
if (!objectStoreNames.contains(this.objectStoreName)) {
var objectStore_1 = this.db.createObjectStore(this.objectStoreName, (_a = this.storeOption) !== null && _a !== void 0 ? _a : this.idbStoreOption);
((_b = this.createIndexs) !== null && _b !== void 0 ? _b : this.idCreateIndexs).forEach(function (key) {
objectStore_1.createIndex(key, key, { unique: false });
});
}
};
// 事务访问存储对象
IndexedDB.prototype.getObjectStore = function (transactionMode) {
var transaction = this.db.transaction(this.objectStoreName, transactionMode); // 创建事务
var objectStore = transaction.objectStore(this.objectStoreName); // 事务访问存储空间
return objectStore;
};
// 监听事务存储对象操作结果
IndexedDB.prototype.listenResult = function (request, resolve, reject, type, v) {
var _this = this;
request.onsuccess = function (event) {
var result = event.target.result;
var _a = result || {}, value = _a.value, time = _a.time, pathname = _a.pathname;
if (type === 'get') {
var result_1 = { v: value, _isDue: isDue(time, _this.expire), _pathname: pathname };
if (_this.idBeforeGet) {
_this.idBeforeGet(result_1).then(function (newData) { resolve(newData || result_1); }).catch(function (e) { reject(e || new Error("".concat('beforeGet', "\u89C4\u5219\u6CA1\u901A\u8FC7\uFF0C\u8BF7\u67E5\u770BbeforeGet\u51FD\u6570"))); });
}
else {
resolve(result_1);
}
}
else {
if (['set', 'remove'].includes(type)) {
if (_this.idAfterSet) {
_this.idAfterSet(v).then(function () { resolve(true); }).catch(function (e) { console.log(e); });
}
else {
resolve(true);
}
}
else {
resolve(true);
}
}
};
request.onerror = function (event) {
reject(event.target.error);
};
};
IndexedDB.prototype.get = function (key) {
return __awaiter(this, void 0, void 0, function () {
var _this = this;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, new Promise(function (resolve, reject) {
_this.ready()
.then(function () {
if (!_this.keys.includes(key)) {
reject(new Error("\u5F53\u524D".concat(_this.name, "\u6570\u636E\u5E93\u4E2D\u7684\u8868").concat(_this.objectStoreName, "\u4E0D\u5B58\u5728").concat(key, "\u7684\u952E\uFF0C\u8BF7\u786E\u5B9A\u53C2\u6570\u662F\u5426\u6B63\u786E")));
return;
}
var objectStore = _this.getObjectStore("readonly" /* TransactionMode.ReadOnly */);
var request = objectStore.get(key);
_this.listenResult(request, resolve, reject, 'get');
})
.catch(reject);
})];
case 1: return [2 /*return*/, _a.sent()];
}
});
});
};
IndexedDB.prototype.set = function (key, val) {
return __awaiter(this, void 0, void 0, function () {
var _this = this;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, new Promise(function (resolve, reject) {
_this.ready()
.then(function () {
var _a, _b;
if (!_this.keys.includes(key)) {
reject(new Error("\u5F53\u524D".concat(_this.name, "\u6570\u636E\u5E93\u4E2D\u4E0D\u80FD\u6DFB\u52A0").concat(key, "\u7684\u952E\uFF0C\u8BF7\u5728initProject\u51FD\u6570\u8C03\u7528\u5904\u6DFB\u52A0\u767D\u540D\u5355")));
return;
}
var temp = getIdbValue(((_b = (_a = _this.storeOption) === null || _a === void 0 ? void 0 : _a.keyPath) !== null && _b !== void 0 ? _b : _this.idbStoreOption.keyPath), key);
var value = __assign(__assign({}, temp), { value: val, time: new Date().toLocaleString(), pathname: getFullPath() });
var objectStore = _this.getObjectStore("readwrite" /* TransactionMode.ReadWrite */);
var request;
if (_this.idBeforeSet) {
_this.idBeforeSet(value).then(function (res) {
request = objectStore.put(res);
_this.listenResult(request, resolve, reject, 'set', res);
}).catch(function (e) { reject(e); });
}
else {
request = objectStore.put(value);
_this.listenResult(request, resolve, reject, 'set', value);
}
})
.catch(reject);
})];
case 1:
_a.sent();
return [2 /*return*/];
}
});
});
};
IndexedDB.prototype.remove = function (key) {
return __awaiter(this, void 0, void 0, function () {
var _this = this;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, new Promise(function (resolve, reject) {
_this.ready()
.then(function () {
if (!_this.keys.includes(key)) {
reject(new Error("\u5F53\u524D".concat(_this.name, "\u6570\u636E\u5E93\u4E2D\u8868").concat(_this.objectStoreName, "\u4E0D\u5B58\u5728").concat(key, "\u7684\u952E\uFF0C\u8BF7\u786E\u5B9A\u53C2\u6570\u662F\u5426\u6B63\u786E")));
return;
}
var objectStore = _this.getObjectStore("readwrite" /* TransactionMode.ReadWrite */);
var request = objectStore.delete(key);
_this.listenResult(request, resolve, reject, 'remove');
})
.catch(reject);
})];
case 1:
_a.sent();
return [2 /*return*/];
}
});
});
};
IndexedDB.prototype.clear = function () {
return __awaiter(this, void 0, void 0, function () {
var _this = this;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, new Promise(function (resolve, reject) {
_this.ready()
.then(function () {
var objectStore = _this.getObjectStore("readwrite" /* TransactionMode.ReadWrite */);
var request = objectStore.clear();
_this.listenResult(request, resolve, reject, 'clear');
})
.catch(reject);
})];
case 1:
_a.sent();
return [2 /*return*/];
}
});
});
};
return IndexedDB;
}(Project));
var PreferStorage = PreferStorage$1;
var IndexDBStorage = IndexedDB;
exports.IndexDBStorage = IndexDBStorage;
exports.PreferStorage = PreferStorage;