@byojs/storage
Advanced tools
Comparing version 0.11.1 to 0.12.0
{ | ||
"name": "@byojs/storage", | ||
"description": "Simple key-value storage API backed by various client storage mechanisms", | ||
"version": "0.11.1", | ||
"version": "0.12.0", | ||
"exports": { | ||
@@ -34,5 +34,5 @@ "./idb": "./dist/adapter.idb.mjs", | ||
"devDependencies": { | ||
"micromatch": "~4.0.5", | ||
"micromatch": "~4.0.8", | ||
"recursive-readdir-sync": "~1.0.6", | ||
"terser": "~5.29.2" | ||
"terser": "~5.37.0" | ||
}, | ||
@@ -39,0 +39,0 @@ "repository": { |
@@ -41,3 +41,3 @@ # Storage | ||
**Warning:** [Browser support for `write()`](https://developer.mozilla.org/en-US/docs/Web/API/FileSystemWritableFileStream/write#browser_compatibility) into OPFS from the main thread (as this adapter does) is limited to desktop (not mobile!) Chromium and Firefox browsers. See `opfs-worker` for broader device/browser support. | ||
**Warning:** [Browser support for `write()`](https://developer.mozilla.org/en-US/docs/Web/API/FileSystemWritableFileStream/write#browser_compatibility) into OPFS from the main thread (as this adapter does) is limited to Chromium and Firefox browsers (not Safari). See `opfs-worker` for broader device/browser support. | ||
@@ -77,5 +77,5 @@ * `opfs-worker`: Uses a Web Worker (background thread) for OPFS access, specifically to [expand OPFS support to most devices/browsers ](https://developer.mozilla.org/en-US/docs/Web/API/FileSystemFileHandle/createSyncAccessHandle#browser_compatibility) (via synchronous `write()` in a Web Worker or Service Worker). | ||
The `cookie` adapter stores vault data in browser cookies. There are however some strong caveats to consider before choosing this storage mechanism. | ||
The `cookie` adapter stores data in browser cookies. There are however some strong caveats to consider before choosing this storage mechanism. | ||
Cookies are limited to ~4KB. Moreover, the provided data object has been JSON-serialized, encrypted and then base64 string encoded, then *that value* has been put into another object that's JSON-serialized, and that string (the actual cookie value) is URI-encoded (e.g, replacing `" "` with `%20`, etc). Taking into account all these steps that inflate your data size further towards the 4KB limit, you might only be able to squeeze ~2-3KB of original application data in, under the limit. | ||
Cookies are limited to ~4KB. Moreover, the provided data object has been JSON-serialized and URI-encoded (e.g, replacing `" "` with `%20`, etc). These steps inflate your data size further towards the 4KB limit, so you might only be able to squeeze ~3KB of original application data in, under the limit. | ||
@@ -90,3 +90,3 @@ Also, cookies are typically sent on *every request* to a first-party origin server (images, CSS, fetch calls, etc). So that data (encrypted, of course) will be sent remotely, and will significantly weigh down all those requests. | ||
The [Origin Private File System (OPFS)](https://developer.mozilla.org/en-US/docs/Web/API/File_System_API/Origin_private_file_system) web feature can be used to read/write "files" in a virtual filesystem on the client's device (private to the page's origin). The `opfs` and `opfs-worker` adapters provided with this library create JSON "files" in OPFS to store the vault data, one file per vault. | ||
The [Origin Private File System (OPFS)](https://developer.mozilla.org/en-US/docs/Web/API/File_System_API/Origin_private_file_system) web feature can be used to read/write "files" in a virtual filesystem on the client's device (private to the page's origin). The `opfs` and `opfs-worker` adapters provided with this library create JSON "files" in OPFS to store the data, one file per value. | ||
@@ -110,4 +110,4 @@ ## Deployment / Import | ||
```js | ||
// {WHICHEVER}: "idb", "local-storage", etc | ||
import { get, set } from "@byojs/storage/{WHICHEVER}"; | ||
// {TYPE}: "idb", "local-storage", etc | ||
import { get, set } from "@byojs/storage/{TYPE}"; | ||
``` | ||
@@ -141,4 +141,4 @@ | ||
```js | ||
// {WHICHEVER}: "idb", "local-storage", etc | ||
import { get, set } from "storage/{WHICHEVER}"; | ||
// {TYPE}: "idb", "local-storage", etc | ||
import { get, set } from "storage/{TYPE}"; | ||
``` | ||
@@ -156,3 +156,3 @@ | ||
// for IndexedDB: | ||
import { has, get, set, remove } from "@byojs/storage/idb"; | ||
import { has, get, set, remove } from "{..}/idb"; | ||
@@ -190,2 +190,66 @@ await has("Hello"); // false | ||
### Many API | ||
The `get(..)`, `set(..)`, and `remove(..)` methods also support a bulk-call form, to process multiple keys/values at once: | ||
```js | ||
// for IndexedDB: | ||
import { has, get, set, remove } from "{..}/idb"; | ||
var entries = [ | ||
[ "Hello", "World!" ], | ||
[ "special", 42 ] | ||
]; | ||
await set.many(entries); | ||
// true | ||
var keys = entries.map(([ key, val ]) => key); | ||
// [ "Hello", "special" ] | ||
await get.many(keys); | ||
// [ "World!", 42 ] | ||
await Promise.all(keys.map(has)); | ||
// [ true, true ] | ||
await remove.many(keys); | ||
// true | ||
await Promise.all(keys.map(has)); | ||
// [ false, false ] | ||
``` | ||
The `*.many(..)` methods also accept objects: | ||
```js | ||
import { has, get, set, remove } from "{..}/idb"; | ||
var obj = { | ||
Hello: "World!", | ||
special: 42 | ||
}; | ||
await set.many(obj); | ||
// true | ||
var keysObj = { | ||
Hello: null, | ||
special: null | ||
}; | ||
var keysArr = Object.keys(keys) | ||
await get.many(keysObj); | ||
// [ "World!", 42 ] | ||
await Promise.all(keysArr.map(has)); | ||
// [ true, true ] | ||
await remove.many(keysObj); | ||
// true | ||
await Promise.all(keysArr.map(has)); | ||
// [ false, false ] | ||
``` | ||
## Re-building `dist/*` | ||
@@ -192,0 +256,0 @@ |
@@ -60,3 +60,3 @@ #!/usr/bin/env node | ||
(contents,outputPath,filename = path.basename(outputPath)) => prepareFileContents( | ||
contents.replace(/(\.\/(util|worker\.opfs))\.js/g,"$1.mjs"), | ||
contents.replace(/(\.\/(util|many|worker\.opfs))\.js/g,"$1.mjs"), | ||
outputPath.replace(/\.js$/,".mjs"), | ||
@@ -63,0 +63,0 @@ filename.replace(/\.js$/,".mjs") |
import { safeJSONParse, } from "./util.js"; | ||
import { | ||
setMany, | ||
getMany, | ||
removeMany, | ||
} from "./many.js"; | ||
@@ -6,2 +11,9 @@ | ||
get.many = (...args) => getMany(get,...args); | ||
set.many = (...args) => setMany(set,...args); | ||
remove.many = (...args) => removeMany(remove,...args); | ||
// *********************** | ||
var storageType = "cookie"; | ||
@@ -31,11 +43,11 @@ export { | ||
function has(name) { | ||
async function has(name) { | ||
return (name in getAllCookies()); | ||
} | ||
function get(name) { | ||
async function get(name) { | ||
return safeJSONParse(getAllCookies()[name]); | ||
} | ||
function set(name,value) { | ||
async function set(name,value) { | ||
var expires = new Date(); | ||
@@ -69,3 +81,3 @@ var expiresSeconds = 400 * 24 * 60 * 60; // 400 days from now (max allowed) | ||
function remove(name) { | ||
async function remove(name) { | ||
var expires = new Date(); | ||
@@ -85,7 +97,7 @@ expires.setTime(expires.getTime() - 1000); | ||
function keys() { | ||
async function keys() { | ||
return Object.keys(getAllCookies()); | ||
} | ||
function entries() { | ||
async function entries() { | ||
return ( | ||
@@ -92,0 +104,0 @@ Object.entries(getAllCookies()) |
@@ -8,2 +8,7 @@ import { | ||
} from "idb-keyval"; | ||
import { | ||
setMany, | ||
getMany, | ||
removeMany, | ||
} from "./many.js"; | ||
@@ -13,2 +18,9 @@ | ||
get.many = (...args) => getMany(get,...args); | ||
set.many = (...args) => setMany(set,...args); | ||
remove.many = (...args) => removeMany(remove,...args); | ||
// *********************** | ||
var storageType = "idb"; | ||
@@ -15,0 +27,0 @@ export { |
import { safeJSONParse, } from "./util.js"; | ||
import { | ||
setMany, | ||
getMany, | ||
removeMany, | ||
} from "./many.js"; | ||
@@ -6,2 +11,9 @@ | ||
get.many = (...args) => getMany(get,...args); | ||
set.many = (...args) => setMany(set,...args); | ||
remove.many = (...args) => removeMany(remove,...args); | ||
// *********************** | ||
var storageType = "local-storage"; | ||
@@ -16,3 +28,3 @@ export { | ||
entries, | ||
} | ||
}; | ||
var publicAPI = { | ||
@@ -29,6 +41,5 @@ storageType, | ||
// *********************** | ||
function has(name) { | ||
async function has(name) { | ||
// note: https://developer.mozilla.org/en-US/docs/Web/API/Storage/getItem#return_value | ||
@@ -38,7 +49,7 @@ return (window.localStorage.getItem(name) !== null); | ||
function get(name) { | ||
async function get(name) { | ||
return safeJSONParse(window.localStorage.getItem(name)); | ||
} | ||
function set(name,value) { | ||
async function set(name,value) { | ||
try { | ||
@@ -61,3 +72,3 @@ window.localStorage.setItem( | ||
function remove(name) { | ||
async function remove(name) { | ||
window.localStorage.removeItem(name); | ||
@@ -67,3 +78,3 @@ return true; | ||
function keys() { | ||
async function keys() { | ||
var storeKeys = []; | ||
@@ -76,3 +87,3 @@ for (let i = 0; i < window.localStorage.length; i++) { | ||
function entries() { | ||
async function entries() { | ||
var storeEntries = []; | ||
@@ -79,0 +90,0 @@ for (let i = 0; i < window.localStorage.length; i++) { |
@@ -10,2 +10,12 @@ import { | ||
get.many = async (...args) => ( | ||
(await sendToWorker("get.many",...args)) | ||
.map(safeJSONParse) | ||
); | ||
set.many = (...args) => sendToWorker("set.many",...args); | ||
remove.many = (...args) => sendToWorker("remove.many",...args); | ||
// *********************** | ||
var worker = null; | ||
@@ -12,0 +22,0 @@ var pending = null; |
@@ -6,2 +6,7 @@ import { | ||
} from "./util.js"; | ||
import { | ||
setMany, | ||
getMany, | ||
removeMany, | ||
} from "./many.js"; | ||
@@ -11,2 +16,9 @@ | ||
get.many = (...args) => getMany(get,...args); | ||
set.many = (...args) => setMany(set,...args); | ||
remove.many = (...args) => removeMany(remove,...args); | ||
// *********************** | ||
var storageType = "opfs"; | ||
@@ -13,0 +25,0 @@ export { |
import { safeJSONParse, } from "./util.js"; | ||
import { | ||
setMany, | ||
getMany, | ||
removeMany, | ||
} from "./many.js"; | ||
@@ -6,2 +11,9 @@ | ||
get.many = (...args) => getMany(get,...args); | ||
set.many = (...args) => setMany(set,...args); | ||
remove.many = (...args) => removeMany(remove,...args); | ||
// *********************** | ||
var storageType = "session-storage"; | ||
@@ -16,3 +28,3 @@ export { | ||
entries, | ||
} | ||
}; | ||
var publicAPI = { | ||
@@ -32,3 +44,3 @@ storageType, | ||
function has(name) { | ||
async function has(name) { | ||
// note: https://developer.mozilla.org/en-US/docs/Web/API/Storage/getItem#return_value | ||
@@ -38,7 +50,7 @@ return (window.sessionStorage.getItem(name) !== null); | ||
function get(name) { | ||
async function get(name) { | ||
return safeJSONParse(window.sessionStorage.getItem(name)); | ||
} | ||
function set(name,value) { | ||
async function set(name,value) { | ||
try { | ||
@@ -61,3 +73,3 @@ window.sessionStorage.setItem( | ||
function remove(name) { | ||
async function remove(name) { | ||
window.sessionStorage.removeItem(name); | ||
@@ -67,3 +79,3 @@ return true; | ||
function keys() { | ||
async function keys() { | ||
var storeKeys = []; | ||
@@ -76,3 +88,3 @@ for (let i = 0; i < window.sessionStorage.length; i++) { | ||
function entries() { | ||
async function entries() { | ||
var storeEntries = []; | ||
@@ -79,0 +91,0 @@ for (let i = 0; i < window.sessionStorage.length; i++) { |
@@ -5,2 +5,7 @@ import { | ||
} from "./util.js"; | ||
import { | ||
setMany, | ||
getMany, | ||
removeMany, | ||
} from "./many.js"; | ||
@@ -10,2 +15,6 @@ | ||
get.many = (...args) => getMany(get,...args); | ||
set.many = (...args) => setMany(set,...args); | ||
remove.many = (...args) => removeMany(remove,...args); | ||
self.addEventListener("message",onMessage); | ||
@@ -21,4 +30,7 @@ self.postMessage({ "ready": true }); | ||
get, | ||
"get.many": get.many, | ||
set, | ||
"set.many": set.many, | ||
remove, | ||
"remove.many": remove.many, | ||
keys, | ||
@@ -25,0 +37,0 @@ entries, |
@@ -67,2 +67,10 @@ // note: these module specifiers come from the import-map | ||
[ "idb", "keys(2)", [ "meaning", ], ], | ||
[ "idb", "{cleared} (1)", [ false, false, ], ], | ||
[ "idb", "set.many (1)", true], | ||
[ "idb", "get.many (1)", [ "world", { ofLife: 42, }, ], ], | ||
[ "idb", "remove.many (1)", true], | ||
[ "idb", "set.many (2)", true], | ||
[ "idb", "get.many (2)", [ "world", { ofLife: 42, }, ], ], | ||
[ "idb", "remove.many (2)", true], | ||
[ "idb", "{cleared} (2)", [ false, false, ], ], | ||
[ "local-storage", "has(1)", false ], | ||
@@ -78,2 +86,10 @@ [ "local-storage", "get(1)", null ], | ||
[ "local-storage", "keys(2)", [ "meaning", ], ], | ||
[ "local-storage", "{cleared} (1)", [ false, false, ], ], | ||
[ "local-storage", "set.many (1)", true], | ||
[ "local-storage", "get.many (1)", [ "world", { ofLife: 42, }, ], ], | ||
[ "local-storage", "remove.many (1)", true], | ||
[ "local-storage", "set.many (2)", true], | ||
[ "local-storage", "get.many (2)", [ "world", { ofLife: 42, }, ], ], | ||
[ "local-storage", "remove.many (2)", true], | ||
[ "local-storage", "{cleared} (2)", [ false, false, ], ], | ||
[ "session-storage", "has(1)", false ], | ||
@@ -89,2 +105,10 @@ [ "session-storage", "get(1)", null ], | ||
[ "session-storage", "keys(2)", [ "meaning", ], ], | ||
[ "session-storage", "{cleared} (1)", [ false, false, ], ], | ||
[ "session-storage", "set.many (1)", true], | ||
[ "session-storage", "get.many (1)", [ "world", { ofLife: 42, }, ], ], | ||
[ "session-storage", "remove.many (1)", true], | ||
[ "session-storage", "set.many (2)", true], | ||
[ "session-storage", "get.many (2)", [ "world", { ofLife: 42, }, ], ], | ||
[ "session-storage", "remove.many (2)", true], | ||
[ "session-storage", "{cleared} (2)", [ false, false, ], ], | ||
[ "cookie", "has(1)", false ], | ||
@@ -100,2 +124,10 @@ [ "cookie", "get(1)", null ], | ||
[ "cookie", "keys(2)", [ "meaning", ], ], | ||
[ "cookie", "{cleared} (1)", [ false, false, ], ], | ||
[ "cookie", "set.many (1)", true], | ||
[ "cookie", "get.many (1)", [ "world", { ofLife: 42, }, ], ], | ||
[ "cookie", "remove.many (1)", true], | ||
[ "cookie", "set.many (2)", true], | ||
[ "cookie", "get.many (2)", [ "world", { ofLife: 42, }, ], ], | ||
[ "cookie", "remove.many (2)", true], | ||
[ "cookie", "{cleared} (2)", [ false, false, ], ], | ||
[ "opfs", "has(1)", false ], | ||
@@ -111,2 +143,10 @@ [ "opfs", "get(1)", null ], | ||
[ "opfs", "keys(2)", [ "meaning", ], ], | ||
[ "opfs", "{cleared} (1)", [ false, false, ], ], | ||
[ "opfs", "set.many (1)", true], | ||
[ "opfs", "get.many (1)", [ "world", { ofLife: 42, }, ], ], | ||
[ "opfs", "remove.many (1)", true], | ||
[ "opfs", "set.many (2)", true], | ||
[ "opfs", "get.many (2)", [ "world", { ofLife: 42, }, ], ], | ||
[ "opfs", "remove.many (2)", true], | ||
[ "opfs", "{cleared} (2)", [ false, false, ], ], | ||
[ "opfs-worker", "has(1)", false ], | ||
@@ -122,2 +162,10 @@ [ "opfs-worker", "get(1)", null ], | ||
[ "opfs-worker", "keys(2)", [ "meaning", ], ], | ||
[ "opfs-worker", "{cleared} (1)", [ false, false, ], ], | ||
[ "opfs-worker", "set.many (1)", true], | ||
[ "opfs-worker", "get.many (1)", [ "world", { ofLife: 42, }, ], ], | ||
[ "opfs-worker", "remove.many (1)", true], | ||
[ "opfs-worker", "set.many (2)", true], | ||
[ "opfs-worker", "get.many (2)", [ "world", { ofLife: 42, }, ], ], | ||
[ "opfs-worker", "remove.many (2)", true], | ||
[ "opfs-worker", "{cleared} (2)", [ false, false, ], ], | ||
]; | ||
@@ -141,2 +189,13 @@ var testResults = []; | ||
await store.remove("meaning"); | ||
testResults.push([ storageTypes[store.storageType][0], "{cleared} (1)", await Promise.all(["hello","world"].map(store.has)), ]); | ||
testResults.push([ storageTypes[store.storageType][0], "set.many (1)", await store.set.many([ [ "hello", "world", ], [ "meaning", { ofLife: 42, }, ], ]), ]); | ||
testResults.push([ storageTypes[store.storageType][0], "get.many (1)", await store.get.many([ "hello", "meaning", ]), ]); | ||
testResults.push([ storageTypes[store.storageType][0], "remove.many (1)", await store.remove.many([ "hello", "meaning", ]), ]); | ||
testResults.push([ storageTypes[store.storageType][0], "set.many (2)", await store.set.many({ hello: "world", meaning: { ofLife: 42, }, }), ]); | ||
testResults.push([ storageTypes[store.storageType][0], "get.many (2)", await store.get.many({ hello: null, meaning: null, }), ]); | ||
testResults.push([ storageTypes[store.storageType][0], "remove.many (2)", await store.remove.many({ hello: null, meaning: null, }), ]); | ||
testResults.push([ storageTypes[store.storageType][0], "{cleared} (2)", await Promise.all(["hello","world"].map(store.has)), ]); | ||
} | ||
@@ -143,0 +202,0 @@ var testsPassed = true; |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
67745
28
1410
282