UNPKG

web-localstorage-plus

Version:
655 lines (635 loc) 17.3 kB
"use strict"; var __defProp = Object.defineProperty; var __defProps = Object.defineProperties; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropDescs = Object.getOwnPropertyDescriptors; var __getOwnPropNames = Object.getOwnPropertyNames; var __getOwnPropSymbols = Object.getOwnPropertySymbols; var __hasOwnProp = Object.prototype.hasOwnProperty; var __propIsEnum = Object.prototype.propertyIsEnumerable; var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __spreadValues = (a, b) => { for (var prop in b || (b = {})) if (__hasOwnProp.call(b, prop)) __defNormalProp(a, prop, b[prop]); if (__getOwnPropSymbols) for (var prop of __getOwnPropSymbols(b)) { if (__propIsEnum.call(b, prop)) __defNormalProp(a, prop, b[prop]); } return a; }; var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b)); var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // src/index.ts var src_exports = {}; __export(src_exports, { default: () => src_default, useStorage: () => useStorage }); module.exports = __toCommonJS(src_exports); // src/helper/const.ts var pkgName = "web-localstorage-plus"; var defaultRootName = pkgName; var workerMsg = `${pkgName}-expired`; var defaultLocalStorage = { getItem: () => { }, setItem: () => { }, removeItem: () => { }, clearItem: () => { } }; var messages = /* @__PURE__ */ new Map([ ["DISABLED_LOC", `\u8BF7\u4F7F\u7528${pkgName}\u8FDB\u884C\u5B58\u50A8\u64CD\u4F5C`], ["NOT_FOUND_NAME", (name) => `\u65E0\u6CD5\u901A\u8FC7${name}\u627E\u5230\u5339\u914D\u7684\u5B58\u50A8\u6570\u636E\uFF0C\u8BF7\u6307\u5B9Anamespace\u8FDB\u884C\u5C1D\u8BD5`], ["NOT_FOUND_SPACE", (name) => `\u547D\u540D\u7A7A\u95F4\uFF08${name}\uFF09\u4E0D\u5B58\u5728`] ]); // src/helper/function.ts function cloneDeep(o) { return JSON.parse(JSON.stringify(o)); } var isObject = (p) => Object.prototype.toString.call(p) === "[object Object]"; function log(messageType, color = "log", rest) { let msg = messages.get(messageType); if (typeof msg === "function") { msg = msg(rest); } console[color](`[web-storage]:${msg}`); } function setupGlobal(that) { window.WEB_STORAGE_USE_LOCAL_STORAGE = () => that.localStorage; window.WEB_STORAGE_EXPIRES = []; window.WEB_STORAGE_USER_REGISTERED_CALLBACK = { change: [], expire: [], on: [] }; window.WEB_STORAGE_IS_WARNING = true; } function useCallback(eventType) { const [callback] = useGlobal("WEB_STORAGE_USER_REGISTERED_CALLBACK"); const curCb = callback[eventType] || []; return [ curCb, (newCb) => { window.WEB_STORAGE_USER_REGISTERED_CALLBACK[eventType] = newCb; } ]; } function useGlobal(type) { return [ window[type], (newValue) => { window[type] = newValue; } ]; } // src/core/native-storage.ts function native_storage_default(rootName) { const localStorage = window.WEB_STORAGE_USE_LOCAL_STORAGE(); const load = () => JSON.parse(localStorage.getItem(rootName) || "{}"); function _update(storage) { localStorage.setItem(rootName, JSON.stringify(storage)); } function _createSpace(storage, namespace) { if (namespace) { storage[namespace] = storage[namespace] || {}; return storage[namespace]; } return storage; } return { load, methods: { getItem(params) { const { key, namespace = "" } = params; const storage = load(); if (isObject(storage[namespace])) return storage[namespace][key]; if (storage[key]) return storage[key]; window.WEB_STORAGE_IS_WARNING && log("NOT_FOUND_NAME", "warn", key); }, setItem(params) { const { key, value, namespace } = params; const storage = load(); const space = _createSpace(storage, namespace); space[key] = value; _update(storage); }, removeItem(params) { const { key, namespace = "" } = params; const storage = load(); if (isObject(storage[namespace])) { delete storage[namespace][key]; } else { delete storage[key]; } _update(storage); }, removeSpace(space) { const storage = load(); delete storage[space]; _update(storage); }, clear() { const storage = load(); for (let key in storage) { delete storage[key]; } _update(storage); } } }; } // src/core/api/getItem.ts function getItem(key, namespace, isFlatten) { const params = { key: "", namespace: getNamespace() }; let flatten = false; const queue = []; if (typeof key === "string") { params.key = key; params.namespace = getNamespace(namespace); queue.push(params); flatten = true; } else if (Array.isArray(key)) { key.forEach((k) => { const p = __spreadValues({}, params); if (typeof k === "string") { p.key = k; if (namespace) { if (typeof namespace === "string") { p.namespace = getNamespace(namespace); } else { p.namespace = getNamespace(); flatten = namespace; } } if (isFlatten) { flatten = isFlatten; } } else { p.key = k.key; p.namespace = k.namespace; flatten = !!namespace; } queue.push(p); }); } let res = queue.map((v) => ({ value: runPlugin( __spreadProps(__spreadValues({}, v), { ctx: native, value: native.methods.getItem(v) }), "getItem" ), namespace: v.namespace })); if (flatten) { res = res.map((v) => v.value); } return typeof key === "string" ? res[0] : res; } var getItem_default = getItem; // src/core/api/worker.ts var workerFile = ` let timer = null; self.addEventListener("message", (params) => { clearInterval(timer); const { data } = params || {}; const { meaasgeType, payload } = data || {}; function run() { timer = setInterval(() => { if (meaasgeType && Array.isArray(payload)) { const legals = payload.filter((v) => Date.now() >= v.expireTime); if (Array.isArray(legals) && legals.length) { clearInterval(timer); postMessage(legals); run() } } }, 500); } run(); }); `; var workBlob = new Blob([workerFile]); var workUrl = URL.createObjectURL(workBlob); var WorkerSpace = class { static getInstance() { if (WorkerSpace.instance) { return WorkerSpace.instance.run(); } WorkerSpace.instance = new WorkerSpace(); WorkerSpace.instance.run(); } run() { if (!this.worker) { this.worker = new Worker(workUrl); } this.worker.postMessage({ meaasgeType: workerMsg, payload: window.WEB_STORAGE_EXPIRES }); this.worker.onmessage = (payload) => { const { data } = payload; if (Array.isArray(data)) { data.forEach((v) => window.WEB_STORAGE_APIS.getItem(v.key, v.namespace)); } }; } }; var worker_default = WorkerSpace.getInstance; // src/core/api/setItem.ts function setExpire({ expireTime, key, namespace }) { if (typeof expireTime === "number") { const [expires = [], update] = useGlobal("WEB_STORAGE_EXPIRES"); const params = { key, expireTime: Date.now() + expireTime, namespace }; const i = expires.findIndex((v) => { let legal = v.key === key; if (legal && namespace) { legal = v.namespace === namespace; } return legal; }); if (i === -1) { expires.push(params); } else { expires[i].expireTime = expireTime; } update(expires); worker_default(); } } function setItem(key, value, namespace, expireTime, encrypt) { const params = { key: "", value, namespace: getNamespace() }; const queue = []; if (typeof key === "string") { params.key = key; params.value = value; params.encrypt = encrypt; params.expireTime = expireTime; if (typeof namespace === "string") { params.namespace = namespace; } else if (typeof namespace === "boolean") { params.encrypt = namespace; } else if (typeof namespace === "number") { params.expireTime = namespace; } queue.push(params); } else { key.forEach((v) => { v.namespace = v.namespace || value; queue.push(v); }); } queue.forEach((v) => { setExpire(v); v.value = runPlugin( __spreadProps(__spreadValues({}, v), { ctx: native }), "setItem" ); native.methods.setItem(v); }); } var setItem_default = setItem; // src/core/api/removeItem.ts function removeItem(key, namespace) { const params = { key: "", namespace: getNamespace() }; const queue = []; if (typeof key === "string") { params.key = key; if (typeof namespace === "string") { params.namespace = namespace; } queue.push(params); } else { key.forEach((v) => { const p = __spreadValues({}, params); if (typeof v === "string") { p.key = v; p.namespace = getNamespace(namespace); } else { p.key = v.key; p.namespace = v.namespace || getNamespace(namespace); } queue.push(p); }); } queue.forEach((v) => { runPlugin.call( native, __spreadProps(__spreadValues({}, v), { ctx: native }), "removeItem" ); native.methods.removeItem(v); }); } var removeItem_default = removeItem; // src/core/api/clear.ts function clear(include, reverse) { let que = Array.isArray(include) ? include : []; if (!que.length) { native.methods.clear(); } else { if (reverse === true) { que = Object.keys(native.load()).filter((v) => !que.find((q) => v === q)); } que.forEach((v) => native.methods.removeSpace(v)); } runPlugin( { value: que, ctx: native }, "clear" ); } var clear_default = clear; // src/core/api/change.ts function change(key, callback, namespace) { const spacename = getNamespace(namespace); const [change2, setChange] = useCallback("change"); change2.push({ key, namespace: spacename, callback }); setChange(change2); } var change_default = change; // src/core/api/bus.ts function listen(key, callback, overwrite) { const [on, setOn] = useCallback("on"); const i = on.findIndex((v) => v.key === key); const ov = typeof overwrite === "string" ? false : overwrite; if (ov === true && i > -1) { on[i].callback = callback; } else { on.push({ key, callback }); } setOn(on); } function emit(key, payload, mode) { const [on] = useCallback("on"); const triggers = on.filter((v) => v.key === key); if (Array.isArray(triggers) && triggers.length) { triggers.forEach((trigger) => trigger.callback(payload)); } } var bus_default = { on: listen, emit }; // src/core/api/expire.ts function expire(key, callback, namespace) { const spacename = getNamespace(namespace); const [expire2, setExpire2] = useCallback("expire"); expire2.push({ key, namespace: spacename, callback }); setExpire2(expire2); } var expire_default = expire; // src/core/api/index.ts function getNamespace(namespace) { if (namespace) { return namespace; } return ""; } function runPlugin(payload, wark) { let value = payload.value; const buildIn = native.plugins.filter((v) => v.framework === "buildIn"); const users = native.plugins.filter((v) => v.framework === "customer"); const plugins = [...buildIn, ...users]; for (let i = 0; i < plugins.length; i++) { const plugin = plugins[i]; value = payload.value = plugin.apis[wark](payload); } return value; } // src/plugin/encrypt.ts var encrypts = /* @__PURE__ */ new Map([]); function encryptPlugin(params) { const { key, wark, value, namespace, encrypt } = params; if (wark === "setItem" && encrypt) { let s = "*"; if (namespace) { const space = encrypts.get(namespace) || []; space.push([key, value]); encrypts.set(namespace, space); } else { encrypts.set(key, [key, value]); } return s.repeat(String(value).length); } if (wark === "getItem") { let space = namespace ? encrypts.get(namespace) : encrypts.get(key); if (Array.isArray(space)) { space = Array.isArray(space[0]) ? space[0] : space; if (space[0] === key) { return space[1]; } } } if (wark === "removeItem") { const delKey = namespace || key; if (encrypts.has(delKey)) { encrypts.delete(delKey); } } if (wark === "clear") { if (Array.isArray(value)) { value.forEach((v) => { if (encrypts.has(v)) { encrypts.delete(v); } }); } else { encrypts.clear(); } } return value; } // src/plugin/watch.ts function watchPlugin(params) { const { key, wark, value, namespace, ctx } = params; if (["setItem", "removeItem", "clear"].includes(wark)) { const [changes] = useCallback("change"); if (Array.isArray(changes) && changes.length) { window.WEB_STORAGE_IS_WARNING = false; const oldValue = ctx.methods.getItem({ key, namespace }); changes.forEach((v) => { if (v.namespace === namespace && v.key === key) { v.callback({ newValue: wark === "setItem" ? value : void 0, oldValue, key, namespace }); } }); window.WEB_STORAGE_IS_WARNING = true; } } return value; } // src/plugin/expire.ts function watchPlugin2(params) { const { key, value, namespace, ctx } = params; const [expires] = useCallback("expire"); const [expireTimes, setExpireTimes] = useGlobal("WEB_STORAGE_EXPIRES"); const expired = []; for (let i = 0; i < expireTimes.length; i++) { if (Date.now() >= expireTimes[i].expireTime) { expired.push(cloneDeep(expireTimes[i])); expireTimes.splice(i, 1); i--; } } expired.forEach((v) => { ctx.methods.removeItem({ key: v.key, namespace: v.namespace }); }); setExpireTimes(expireTimes); if (Array.isArray(expires) && expires.length) { expires.forEach((v) => { const item = expired.find( (e) => e.key === v.key && e.namespace === v.namespace ); if (item) { v.callback({ key, namespace }); } }); } worker_default(); return value; } // src/core/api/use.ts function useBuildInPlugin(methods) { const buildIn = [watchPlugin2, encryptPlugin, watchPlugin]; buildIn.forEach((v) => { methods.use(v, "buildIn"); }); } function setApis(api) { return { getItem: (p) => api(__spreadProps(__spreadValues({}, p), { wark: "getItem" })), setItem: (p) => api(__spreadProps(__spreadValues({}, p), { wark: "setItem" })), removeItem: (p) => api(__spreadProps(__spreadValues({}, p), { wark: "removeItem" })), clear: (p) => api(__spreadProps(__spreadValues({}, p), { wark: "clear" })) }; } function use(userCallback, framework) { native.plugins.push({ framework: framework || "customer", apis: setApis(userCallback) }); } var use_default = use; // src/core/web-storage.ts var native; function web_storage_default(rootName) { const storage = native_storage_default(rootName); native = __spreadProps(__spreadValues({}, storage), { plugins: [] }); useBuildInPlugin({ use: use_default }); return { getItem: getItem_default, setItem: setItem_default, removeItem: removeItem_default, clear: clear_default, onChange: change_default, onExpire: expire_default, postMessage: bus_default.emit, onMessage: bus_default.on, use: use_default }; } // src/index.ts function proxyLocalStorage() { Object.defineProperty(window, "localStorage", { get() { log("DISABLED_LOC", "warn"); return defaultLocalStorage; } }); } var init = function(config) { if (init.created || window.WEB_STORAGE_APIS) return window.WEB_STORAGE_APIS; const { rootName, noUseLocalStorage = true } = config || {}; const name = rootName || defaultRootName; this.localStorage = window.localStorage; noUseLocalStorage && proxyLocalStorage(); setupGlobal(this); this.created = true; return window["WEB_STORAGE_APIS"] = web_storage_default(name); }; function useStorage() { return window.WEB_STORAGE_APIS; } var src_default = init.bind(init); // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { useStorage });