polystore 0.1.1 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.min.js CHANGED
@@ -1,2 +1,2 @@
1
- var l={},g=/(-?(?:\d+\.?\d*|\d*\.?\d+)(?:e[-+]?\d+)?)\s*([\p{L}]*)/iu;t.millisecond=t.ms=1;t.second=t.sec=t.s=t[""]=t.ms*1e3;t.minute=t.min=t.m=t.s*60;t.hour=t.hr=t.h=t.m*60;t.day=t.d=t.h*24;t.week=t.wk=t.w=t.d*7;t.year=t.yr=t.y=t.d*365.25;t.month=t.b=t.y/12;function t(e){if(e==null)return null;if(typeof e=="number")return e;e=e.toLowerCase().replace(/[,_]/g,"");let[u,y,i]=g.exec(e)||[];if(!i)return null;let c=t[i]||t[i.replace(/s$/,"")];if(!c)return null;let d=c*parseFloat(y,10);return Math.abs(Math.round(d))}l.expire=e=>{let u=async n=>{if(!await e.has(n))return null;let{data:a,expire:o}=await e.get(n);return o===null?a:o-new Date().getTime()<=0?null:a},y=async(n,a,{expire:o=null}={})=>{let r=t(o),f=r!==null?new Date().getTime()+r:null;return e.set(n,{expire:f,data:a})},i=async n=>await e.get(n)!==null,c=e.del,d=e.keys,s=e.clear;return{get:u,set:y,has:i,del:c,keys:d,clear:s}};l.memory=e=>({get:async n=>e.get(n)||null,set:async(n,a)=>e.set(n,a),has:async n=>e.has(n),del:async n=>e.delete(n),keys:async(n="")=>[...await e.keys()].filter(a=>a.startsWith(n)),clear:()=>e.clear()});l.localStorage=e=>({get:async n=>e[n]?JSON.parse(e[n]):null,set:async(n,a)=>e.setItem(n,JSON.stringify(a)),has:async n=>n in e,del:async n=>e.removeItem(n),keys:async(n="")=>Object.keys(e).filter(a=>a.startsWith(n)),clear:()=>e.clear()});l.cookie=()=>{let e=async s=>{let n=document.cookie.split("; ").filter(Boolean).find(a=>a.startsWith(s+"="))?.split("=")[1]||null;return JSON.parse(decodeURIComponent(n))},u=async(s,n,{expire:a=null}={})=>{let o=t(a),r=new Date().getTime(),f=o!==null?`; expires=${new Date(r+o).toUTCString()}`:"",p=encodeURIComponent(JSON.stringify(n));document.cookie=s+"="+p+f},y=async s=>(await c()).includes(s),i=async s=>u(s,"",{expire:-100}),c=async(s="")=>document.cookie.split(";").map(n=>n.split("=")[0].trim()).filter(Boolean).filter(n=>n.startsWith(s));return{get:e,set:u,has:y,del:i,keys:c,clear:async()=>{await Promise.all((await c()).map(i))}}};l.redis=e=>{let u=async a=>{let r=await(await e).get(a);return r?JSON.parse(r):null},y=async(a,o,{expire:r=null}={})=>{if(o===null||r===0)return c(a);let f=await e,p=t(r),m=p?Math.round(p/1e3):void 0;return f.set(a,JSON.stringify(o),{EX:m})},i=async a=>!!await(await e).exists(a),c=async a=>(await e).del(a);return{get:u,set:y,has:i,del:c,keys:async(a="")=>(await e).keys(a+"*"),clear:async()=>(await e).flushAll(),close:async()=>(await e).quit()}};function w(e){return!e||e instanceof Map?l.expire(l.memory(e||new Map)):typeof localStorage<"u"&&e===localStorage||typeof sessionStorage<"u"&&e===sessionStorage?l.expire(l.localStorage(e)):e==="cookie"?l.cookie():l.redis(e)}export{w as default};
1
+ var c={},g=/(-?(?:\d+\.?\d*|\d*\.?\d+)(?:e[-+]?\d+)?)\s*([\p{L}]*)/iu;t.millisecond=t.ms=1;t.second=t.sec=t.s=t[""]=t.ms*1e3;t.minute=t.min=t.m=t.s*60;t.hour=t.hr=t.h=t.m*60;t.day=t.d=t.h*24;t.week=t.wk=t.w=t.d*7;t.year=t.yr=t.y=t.d*365.25;t.month=t.b=t.y/12;function t(e){if(e==null)return null;if(typeof e=="number")return e;e=e.toLowerCase().replace(/[,_]/g,"");let[o,y,i]=g.exec(e)||[];if(!i)return null;let l=t[i]||t[i.replace(/s$/,"")];if(!l)return null;let d=l*parseFloat(y,10);return Math.abs(Math.round(d))}c.expire=e=>{let o=async n=>{if(!await e.has(n))return null;let{data:a,expire:r}=await e.get(n);return r===null?a:r-new Date().getTime()<=0?null:a},y=async(n,a,{expire:r=null}={})=>{let u=t(r),f=u!==null?new Date().getTime()+u:null;return e.set(n,{expire:f,data:a})},i=async n=>await e.get(n)!==null,l=e.del,d=e.keys,s=e.clear;return{get:o,set:y,has:i,del:l,keys:d,clear:s}};c.memory=e=>({get:async n=>e.get(n)||null,set:async(n,a)=>e.set(n,a),has:async n=>e.has(n),del:async n=>e.delete(n),keys:async(n="")=>[...await e.keys()].filter(a=>a.startsWith(n)),clear:()=>e.clear()});c.localStorage=e=>({get:async n=>e[n]?JSON.parse(e[n]):null,set:async(n,a)=>e.setItem(n,JSON.stringify(a)),has:async n=>n in e,del:async n=>e.removeItem(n),keys:async(n="")=>Object.keys(e).filter(a=>a.startsWith(n)),clear:()=>e.clear()});c.cookie=()=>{let e=async s=>{let n=document.cookie.split("; ").filter(Boolean).find(a=>a.startsWith(s+"="))?.split("=")[1]||null;return JSON.parse(decodeURIComponent(n))},o=async(s,n,{expire:a=null}={})=>{let r=t(a),u=new Date().getTime(),f=r!==null?`; expires=${new Date(u+r).toUTCString()}`:"",m=encodeURIComponent(JSON.stringify(n));document.cookie=s+"="+m+f},y=async s=>(await l()).includes(s),i=async s=>o(s,"",{expire:-100}),l=async(s="")=>document.cookie.split(";").map(n=>n.split("=")[0].trim()).filter(Boolean).filter(n=>n.startsWith(s));return{get:e,set:o,has:y,del:i,keys:l,clear:async()=>{await Promise.all((await l()).map(i))}}};c.redis=e=>{let o=async a=>{let u=await(await e).get(a);return u?JSON.parse(u):null},y=async(a,r,{expire:u=null}={})=>{if(r===null||u===0)return l(a);let f=await e,m=t(u),p=m?Math.round(m/1e3):void 0;return f.set(a,JSON.stringify(r),{EX:p})},i=async a=>!!await(await e).exists(a),l=async a=>(await e).del(a);return{get:o,set:y,has:i,del:l,keys:async(a="")=>(await e).keys(a+"*"),clear:async()=>(await e).flushAll(),close:async()=>(await e).quit()}};c.localForage=e=>{let o=n=>e.getItem(n);return{get:o,set:(n,a)=>e.setItem(n,a),has:async n=>await o(n)!==null,del:n=>e.removeItem(n),keys:async(n="")=>(await e.keys()).filter(a=>a.startsWith(n)),clear:()=>e.clear()}};function w(e){return!e||e instanceof Map?c.expire(c.memory(e||new Map)):typeof localStorage<"u"&&e===localStorage||typeof sessionStorage<"u"&&e===sessionStorage?c.expire(c.localStorage(e)):e==="cookie"?c.cookie():e.defineDriver&&e.dropInstance&&e.INDEXEDDB?c.expire(c.localForage(e)):c.redis(e)}export{w as default};
2
2
  //# sourceMappingURL=index.min.js.map
package/index.min.js.map CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["src/index.js"],
4
- "sourcesContent": ["const layers = {};\n\nconst times = /(-?(?:\\d+\\.?\\d*|\\d*\\.?\\d+)(?:e[-+]?\\d+)?)\\s*([\\p{L}]*)/iu;\n\nparse.millisecond = parse.ms = 1;\nparse.second = parse.sec = parse.s = parse[\"\"] = parse.ms * 1000;\nparse.minute = parse.min = parse.m = parse.s * 60;\nparse.hour = parse.hr = parse.h = parse.m * 60;\nparse.day = parse.d = parse.h * 24;\nparse.week = parse.wk = parse.w = parse.d * 7;\nparse.year = parse.yr = parse.y = parse.d * 365.25;\nparse.month = parse.b = parse.y / 12;\n\nfunction parse(str) {\n if (str === null || str === undefined) return null;\n if (typeof str === \"number\") return str;\n // ignore commas/placeholders\n str = str.toLowerCase().replace(/[,_]/g, \"\");\n let [_, value, units] = times.exec(str) || [];\n if (!units) return null;\n const unitValue = parse[units] || parse[units.replace(/s$/, \"\")];\n if (!unitValue) return null;\n const result = unitValue * parseFloat(value, 10);\n return Math.abs(Math.round(result));\n}\n\nlayers.expire = (store) => {\n // Item methods\n const get = async (key) => {\n if (!(await store.has(key))) return null;\n const { data, expire } = await store.get(key);\n if (expire === null) return data;\n const diff = expire - new Date().getTime();\n if (diff <= 0) return null;\n return data;\n };\n const set = async (key, data, { expire = null } = {}) => {\n const time = parse(expire);\n const expDiff = time !== null ? new Date().getTime() + time : null;\n return store.set(key, { expire: expDiff, data });\n };\n const has = async (key) => (await store.get(key)) !== null;\n const del = store.del;\n\n // Group methods\n const keys = store.keys;\n const clear = store.clear;\n\n return { get, set, has, del, keys, clear };\n};\n\nlayers.memory = (store) => {\n // Item methods\n const get = async (key) => store.get(key) || null;\n const set = async (key, data) => store.set(key, data);\n const has = async (key) => store.has(key);\n const del = async (key) => store.delete(key);\n\n // Group methods\n const keys = async (prefix = \"\") =>\n [...(await store.keys())].filter((k) => k.startsWith(prefix)); // \uD83E\uDD37\u200D\u2642\uFE0F\n const clear = () => store.clear();\n\n return { get, set, has, del, keys, clear };\n};\n\nlayers.localStorage = (store) => {\n // Item methods\n const get = async (key) => (store[key] ? JSON.parse(store[key]) : null);\n const set = async (key, data) => store.setItem(key, JSON.stringify(data));\n const has = async (key) => key in store;\n const del = async (key) => store.removeItem(key);\n\n // Group methods\n const keys = async (prefix = \"\") =>\n Object.keys(store).filter((k) => k.startsWith(prefix));\n const clear = () => store.clear();\n\n return { get, set, has, del, keys, clear };\n};\n\nlayers.cookie = () => {\n const get = async (key) => {\n const value =\n document.cookie\n .split(\"; \")\n .filter(Boolean)\n .find((row) => row.startsWith(key + \"=\"))\n ?.split(\"=\")[1] || null;\n return JSON.parse(decodeURIComponent(value));\n };\n\n const set = async (key, data, { expire = null } = {}) => {\n const time = parse(expire);\n const now = new Date().getTime();\n const expireStr =\n time !== null ? `; expires=${new Date(now + time).toUTCString()}` : \"\";\n const value = encodeURIComponent(JSON.stringify(data));\n document.cookie = key + \"=\" + value + expireStr;\n };\n const has = async (key) => (await keys()).includes(key);\n const del = async (key) => set(key, \"\", { expire: -100 });\n\n // Group methods\n const keys = async (prefix = \"\") =>\n document.cookie\n .split(\";\")\n .map((l) => l.split(\"=\")[0].trim())\n .filter(Boolean)\n .filter((k) => k.startsWith(prefix));\n const clear = async () => {\n await Promise.all((await keys()).map(del));\n };\n\n return { get, set, has, del, keys, clear };\n};\n\nlayers.redis = (store) => {\n const get = async (key) => {\n const client = await store;\n const value = await client.get(key);\n if (!value) return null;\n return JSON.parse(value);\n };\n const set = async (key, value, { expire = null } = {}) => {\n if (value === null || expire === 0) return del(key);\n const client = await store;\n const exp = parse(expire);\n const EX = exp ? Math.round(exp / 1000) : undefined;\n return client.set(key, JSON.stringify(value), { EX });\n };\n const has = async (key) => Boolean(await (await store).exists(key));\n const del = async (key) => (await store).del(key);\n\n const keys = async (prefix = \"\") => (await store).keys(prefix + \"*\");\n const clear = async () => (await store).flushAll();\n const close = async () => (await store).quit();\n\n return { get, set, has, del, keys, clear, close };\n};\n\nexport default function compat(store) {\n if (!store || store instanceof Map) {\n // Convert it to the normalized kv, then add the expiry layer on top\n return layers.expire(layers.memory(store || new Map()));\n }\n if (typeof localStorage !== \"undefined\" && store === localStorage) {\n return layers.expire(layers.localStorage(store));\n }\n if (typeof sessionStorage !== \"undefined\" && store === sessionStorage) {\n return layers.expire(layers.localStorage(store));\n }\n if (store === \"cookie\") {\n return layers.cookie();\n }\n return layers.redis(store);\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["const layers = {};\n\nconst times = /(-?(?:\\d+\\.?\\d*|\\d*\\.?\\d+)(?:e[-+]?\\d+)?)\\s*([\\p{L}]*)/iu;\n\nparse.millisecond = parse.ms = 1;\nparse.second = parse.sec = parse.s = parse[\"\"] = parse.ms * 1000;\nparse.minute = parse.min = parse.m = parse.s * 60;\nparse.hour = parse.hr = parse.h = parse.m * 60;\nparse.day = parse.d = parse.h * 24;\nparse.week = parse.wk = parse.w = parse.d * 7;\nparse.year = parse.yr = parse.y = parse.d * 365.25;\nparse.month = parse.b = parse.y / 12;\n\nfunction parse(str) {\n if (str === null || str === undefined) return null;\n if (typeof str === \"number\") return str;\n // ignore commas/placeholders\n str = str.toLowerCase().replace(/[,_]/g, \"\");\n let [_, value, units] = times.exec(str) || [];\n if (!units) return null;\n const unitValue = parse[units] || parse[units.replace(/s$/, \"\")];\n if (!unitValue) return null;\n const result = unitValue * parseFloat(value, 10);\n return Math.abs(Math.round(result));\n}\n\nlayers.expire = (store) => {\n // Item methods\n const get = async (key) => {\n if (!(await store.has(key))) return null;\n const { data, expire } = await store.get(key);\n if (expire === null) return data;\n const diff = expire - new Date().getTime();\n if (diff <= 0) return null;\n return data;\n };\n const set = async (key, data, { expire = null } = {}) => {\n const time = parse(expire);\n const expDiff = time !== null ? new Date().getTime() + time : null;\n return store.set(key, { expire: expDiff, data });\n };\n const has = async (key) => (await store.get(key)) !== null;\n const del = store.del;\n\n // Group methods\n const keys = store.keys;\n const clear = store.clear;\n\n return { get, set, has, del, keys, clear };\n};\n\nlayers.memory = (store) => {\n // Item methods\n const get = async (key) => store.get(key) || null;\n const set = async (key, data) => store.set(key, data);\n const has = async (key) => store.has(key);\n const del = async (key) => store.delete(key);\n\n // Group methods\n const keys = async (prefix = \"\") =>\n [...(await store.keys())].filter((k) => k.startsWith(prefix)); // \uD83E\uDD37\u200D\u2642\uFE0F\n const clear = () => store.clear();\n\n return { get, set, has, del, keys, clear };\n};\n\nlayers.localStorage = (store) => {\n // Item methods\n const get = async (key) => (store[key] ? JSON.parse(store[key]) : null);\n const set = async (key, data) => store.setItem(key, JSON.stringify(data));\n const has = async (key) => key in store;\n const del = async (key) => store.removeItem(key);\n\n // Group methods\n const keys = async (prefix = \"\") =>\n Object.keys(store).filter((k) => k.startsWith(prefix));\n const clear = () => store.clear();\n\n return { get, set, has, del, keys, clear };\n};\n\nlayers.cookie = () => {\n const get = async (key) => {\n const value =\n document.cookie\n .split(\"; \")\n .filter(Boolean)\n .find((row) => row.startsWith(key + \"=\"))\n ?.split(\"=\")[1] || null;\n return JSON.parse(decodeURIComponent(value));\n };\n\n const set = async (key, data, { expire = null } = {}) => {\n const time = parse(expire);\n const now = new Date().getTime();\n const expireStr =\n time !== null ? `; expires=${new Date(now + time).toUTCString()}` : \"\";\n const value = encodeURIComponent(JSON.stringify(data));\n document.cookie = key + \"=\" + value + expireStr;\n };\n const has = async (key) => (await keys()).includes(key);\n const del = async (key) => set(key, \"\", { expire: -100 });\n\n // Group methods\n const keys = async (prefix = \"\") =>\n document.cookie\n .split(\";\")\n .map((l) => l.split(\"=\")[0].trim())\n .filter(Boolean)\n .filter((k) => k.startsWith(prefix));\n const clear = async () => {\n await Promise.all((await keys()).map(del));\n };\n\n return { get, set, has, del, keys, clear };\n};\n\nlayers.redis = (store) => {\n const get = async (key) => {\n const client = await store;\n const value = await client.get(key);\n if (!value) return null;\n return JSON.parse(value);\n };\n const set = async (key, value, { expire = null } = {}) => {\n if (value === null || expire === 0) return del(key);\n const client = await store;\n const exp = parse(expire);\n const EX = exp ? Math.round(exp / 1000) : undefined;\n return client.set(key, JSON.stringify(value), { EX });\n };\n const has = async (key) => Boolean(await (await store).exists(key));\n const del = async (key) => (await store).del(key);\n\n const keys = async (prefix = \"\") => (await store).keys(prefix + \"*\");\n const clear = async () => (await store).flushAll();\n const close = async () => (await store).quit();\n\n return { get, set, has, del, keys, clear, close };\n};\n\nlayers.localForage = (store) => {\n const get = (key) => store.getItem(key);\n const set = (key, value) => store.setItem(key, value);\n const has = async (key) => (await get(key)) !== null;\n const del = (key) => store.removeItem(key);\n\n const keys = async (prefix = \"\") =>\n (await store.keys()).filter((k) => k.startsWith(prefix));\n const clear = () => store.clear();\n\n return { get, set, has, del, keys, clear };\n};\n\nexport default function compat(store) {\n if (!store || store instanceof Map) {\n // Convert it to the normalized kv, then add the expiry layer on top\n return layers.expire(layers.memory(store || new Map()));\n }\n if (typeof localStorage !== \"undefined\" && store === localStorage) {\n return layers.expire(layers.localStorage(store));\n }\n if (typeof sessionStorage !== \"undefined\" && store === sessionStorage) {\n return layers.expire(layers.localStorage(store));\n }\n if (store === \"cookie\") {\n return layers.cookie();\n }\n if (store.defineDriver && store.dropInstance && store.INDEXEDDB) {\n return layers.expire(layers.localForage(store));\n }\n return layers.redis(store);\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["layers", "times", "parse", "str", "_", "value", "units", "unitValue", "result", "store", "get", "key", "data", "expire", "set", "time", "expDiff", "has", "del", "keys", "clear", "prefix", "k", "row", "now", "expireStr", "l", "client", "exp", "EX", "compat"]
7
7
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "polystore",
3
- "version": "0.1.1",
4
- "description": "Add a unified API for any KV store like localStorage, Redis, FileSystem, etc.",
3
+ "version": "0.2.0",
4
+ "description": "A small compatibility layer for many popular KV stores like localStorage, Redis, FileSystem, etc.",
5
5
  "homepage": "https://github.com/franciscop/polystore",
6
6
  "repository": "https://github.com/franciscop/polystore.git",
7
7
  "bugs": "https://github.com/franciscop/polystore/issues",
@@ -24,6 +24,7 @@
24
24
  "esbuild": "^0.19.4",
25
25
  "jest": "^29.7.0",
26
26
  "jest-environment-jsdom": "^29.7.0",
27
+ "localforage": "^1.10.0",
27
28
  "redis": "^4.6.10"
28
29
  },
29
30
  "jest": {
package/readme.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Polystore [![npm install polystore](https://img.shields.io/badge/npm%20install-polystore-blue.svg)](https://www.npmjs.com/package/polystore) [![test badge](https://github.com/franciscop/polystore/workflows/tests/badge.svg "test badge")](https://github.com/franciscop/polystore/blob/master/.github/workflows/tests.yml) [![gzip size](https://img.badgesize.io/franciscop/polystore/master/index.min.js.svg?compression=gzip)](https://github.com/franciscop/polystore/blob/master/index.min.js)
2
2
 
3
- Add a unified API for any KV store like localStorage, Redis, FileSystem, etc:
3
+ A small compatibility layer for many popular KV stores like localStorage, Redis, FileSystem, etc:
4
4
 
5
5
  ```js
6
6
  import kv from "polystore";
@@ -25,26 +25,22 @@ Available stores:
25
25
  - **Local Storage** `localStorage` (fe): persist the data in the browser's localStorage
26
26
  - **Session Storage** `sessionStorage` (fe): persist the data in the browser's sessionStorage
27
27
  - **Cookies** `"cookie"` (fe): persist the data using cookies
28
- - (WIP) **LocalForage** `localForage` (fe): persist the data on IndexedDB
28
+ - **LocalForage** `localForage` (fe): persist the data on IndexedDB
29
29
  - **Redis Client** `redisClient` (be): persist the data in the Redis instance that you connect to.
30
30
  - (WIP) **FS File** `fs.open(pathToFile)` (be): store the data in a single file
31
31
  - (WIP) **FS Folder** `fs.opendir(pathToFolder)` (be): store the data in files inside the folder
32
32
  - (WIP) **Cloudflare KV** `env.KV_NAMESPACE` (be): use Cloudflare's KV store
33
33
 
34
- It main usage is for _libraries using this library_, so that _your_ library can easily accept many cache stores! For example, let's say you create an API library, then you can accept the stores from your client:
34
+ I build this library to be used as a "building block" of other libraries, so that _your library_ can accept many cache stores effortlessly! It's isomorphic (Node.js and the Browser) and tiny (1~2KB). For example, let's say you create an API library, then you can accept the stores from your client:
35
35
 
36
36
  ```js
37
37
  import MyApi from "my-api";
38
38
 
39
- MyApi({ cache: new Map() });
40
- // OR
41
- MyApi({ cache: localStorage });
42
- // OR
43
- MyApi({ cache: fs.opendir("./data/") });
44
- // OR
45
- MyApi({ cache: redisClient });
46
- // OR
47
- MyApi({ cache: env.KV_NAMESPACE });
39
+ MyApi({ cache: new Map() }); // OR
40
+ MyApi({ cache: localStorage }); // OR
41
+ MyApi({ cache: redisClient }); // OR
42
+ MyApi({ cache: env.KV_NAMESPACE }); // OR
43
+ // ...
48
44
  ```
49
45
 
50
46
  ## API
@@ -218,7 +214,11 @@ console.log(await store.get("key1"));
218
214
 
219
215
  ```js
220
216
  import kv from "polystore";
221
- // TODO
217
+ import localForage from "localforage";
218
+
219
+ const store = kv(localForage);
220
+ await store.set("key1", "Hello world");
221
+ console.log(await store.get("key1"));
222
222
  ```
223
223
 
224
224
  ### Redis Client
package/src/index.js CHANGED
@@ -139,6 +139,19 @@ layers.redis = (store) => {
139
139
  return { get, set, has, del, keys, clear, close };
140
140
  };
141
141
 
142
+ layers.localForage = (store) => {
143
+ const get = (key) => store.getItem(key);
144
+ const set = (key, value) => store.setItem(key, value);
145
+ const has = async (key) => (await get(key)) !== null;
146
+ const del = (key) => store.removeItem(key);
147
+
148
+ const keys = async (prefix = "") =>
149
+ (await store.keys()).filter((k) => k.startsWith(prefix));
150
+ const clear = () => store.clear();
151
+
152
+ return { get, set, has, del, keys, clear };
153
+ };
154
+
142
155
  export default function compat(store) {
143
156
  if (!store || store instanceof Map) {
144
157
  // Convert it to the normalized kv, then add the expiry layer on top
@@ -153,5 +166,8 @@ export default function compat(store) {
153
166
  if (store === "cookie") {
154
167
  return layers.cookie();
155
168
  }
169
+ if (store.defineDriver && store.dropInstance && store.INDEXEDDB) {
170
+ return layers.expire(layers.localForage(store));
171
+ }
156
172
  return layers.redis(store);
157
173
  }
package/src/index.test.js CHANGED
@@ -1,5 +1,6 @@
1
1
  import "dotenv/config";
2
2
 
3
+ import localForage from "localforage";
3
4
  import { createClient } from "redis";
4
5
 
5
6
  import kv from "./";
@@ -11,6 +12,7 @@ stores.push(["kv()", kv()]);
11
12
  stores.push(["kv(new Map())", kv(new Map())]);
12
13
  stores.push(["kv(localStorage)", kv(localStorage)]);
13
14
  stores.push(["kv(sessionStorage)", kv(sessionStorage)]);
15
+ stores.push(["kv(localForage)", kv(localForage)]);
14
16
  if (process.env.REDIS) {
15
17
  stores.push(["kv(redis)", kv(createClient().connect())]);
16
18
  }