hyperstorage-js 5.0.7 → 5.1.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/README.md +67 -9
- package/dist/index.cjs +4 -3
- package/dist/index.mjs +4 -3
- package/dist/index.umd.js +1 -1
- package/package.json +1 -1
- package/src/index.ts +3 -2
package/README.md
CHANGED
|
@@ -39,7 +39,7 @@ yarn add hyperstorage-js
|
|
|
39
39
|
## Constructor Syntax
|
|
40
40
|
|
|
41
41
|
```ts
|
|
42
|
-
class
|
|
42
|
+
class HyperStorage<T> {
|
|
43
43
|
constructor(
|
|
44
44
|
itemName: string,
|
|
45
45
|
defaultValue: T,
|
|
@@ -67,7 +67,7 @@ const userStore = new HyperStorage('userSettings', defaultValue)
|
|
|
67
67
|
// If 'userSettings' is not present in the Storage, the defaultValue is set:
|
|
68
68
|
console.log(userStore.value) // { theme: 'light', language: 'en' }
|
|
69
69
|
|
|
70
|
-
// Change theme to dark
|
|
70
|
+
// Change theme to dark
|
|
71
71
|
userStore.value = { theme: 'dark', language: 'en' }
|
|
72
72
|
// or
|
|
73
73
|
userStore.set((v) => (v.theme = 'dark'))
|
|
@@ -75,7 +75,7 @@ userStore.set((v) => (v.theme = 'dark'))
|
|
|
75
75
|
console.log(userStore.value) // { theme: 'dark', language: 'en' }
|
|
76
76
|
console.log(userStore.value.theme) // 'dark'
|
|
77
77
|
|
|
78
|
-
// Present in localStorage
|
|
78
|
+
// Present in localStorage
|
|
79
79
|
console.log(userStore.storage) // Storage {userSettings: '\x00{"theme":"dark","language":"en"}', length: 1}
|
|
80
80
|
```
|
|
81
81
|
|
|
@@ -168,14 +168,19 @@ userStore.value = { theme: 'dark' }
|
|
|
168
168
|
Safe usage of `sync()` requires explicit runtime validation before accessing any properties. It quickly becomes clear how type-unsafe `sync()` is and why it should be avoided.
|
|
169
169
|
|
|
170
170
|
```ts
|
|
171
|
-
const
|
|
171
|
+
const result = userStore.sync() // (method): unknown
|
|
172
|
+
// Right now, 'result' equals 'userStore.value' exactly
|
|
172
173
|
|
|
173
|
-
// '
|
|
174
|
-
console.log(
|
|
174
|
+
// 'result' is of type 'unknown'. ts(18046)
|
|
175
|
+
console.log(result.theme) // 'dark'
|
|
175
176
|
|
|
176
|
-
//
|
|
177
|
-
|
|
178
|
-
|
|
177
|
+
// No error, but unsafe
|
|
178
|
+
console.log(userStore.value.theme) // 'dark'
|
|
179
|
+
|
|
180
|
+
// Must narrow down to be safe
|
|
181
|
+
if (result && typeof result === 'object' && 'theme' in result) {
|
|
182
|
+
// No error, safe
|
|
183
|
+
console.log(result.theme) // 'dark'
|
|
179
184
|
}
|
|
180
185
|
```
|
|
181
186
|
|
|
@@ -254,6 +259,59 @@ console.log(userStore.value) // { theme: 'dark' }
|
|
|
254
259
|
console.log(userStore.storage) // Storage {userSettings: '\x00{"theme":"dark"}', length: 1}
|
|
255
260
|
```
|
|
256
261
|
|
|
262
|
+
#### Why `sync()` is unsafe
|
|
263
|
+
|
|
264
|
+
1. The item in `Storage` is undecodable by the `decodeFn` passed to `sync()`.
|
|
265
|
+
|
|
266
|
+
```js
|
|
267
|
+
localStorage.setItem('userSettings', 'not an object')
|
|
268
|
+
|
|
269
|
+
// SyntaxError: Unexpected token 'o', "not an object" is not valid JSON
|
|
270
|
+
const result = userStore.sync((value) => JSON.parse(value))
|
|
271
|
+
// Execution continues because sync() uses a try-catch
|
|
272
|
+
|
|
273
|
+
console.log(result) // instance of SyntaxError
|
|
274
|
+
|
|
275
|
+
// Reset to default value
|
|
276
|
+
console.log(userStore.value) // {theme: 'system', language: 'en'}
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
2. The item in `Storage`, after being decoded, is not of type `T`.
|
|
280
|
+
|
|
281
|
+
```js
|
|
282
|
+
localStorage.setItem('userSettings', '{"not":"valid"}')
|
|
283
|
+
|
|
284
|
+
const result = userStore.sync((value) => JSON.parse(value))
|
|
285
|
+
console.log(result) // {not: 'valid'}
|
|
286
|
+
console.log(userStore.value) // {not: 'valid'}
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
No errors, but `result` and `userStore.value` are both not of type `T`.
|
|
290
|
+
|
|
291
|
+
This **must** be manually checked and `userStore.reset()` should be called if the check fails.
|
|
292
|
+
|
|
293
|
+
```js
|
|
294
|
+
// This example is specifically for type 'Settings'
|
|
295
|
+
if (
|
|
296
|
+
result &&
|
|
297
|
+
typeof result === 'object' &&
|
|
298
|
+
'theme' in result &&
|
|
299
|
+
'language' in result &&
|
|
300
|
+
(result.theme === 'system' ||
|
|
301
|
+
result.theme === 'light' ||
|
|
302
|
+
result.theme === 'dark') &&
|
|
303
|
+
typeof result.language === 'string'
|
|
304
|
+
) {
|
|
305
|
+
// 'result' is of type 'T'
|
|
306
|
+
} else {
|
|
307
|
+
// 'result' is not of type 'T'
|
|
308
|
+
userStore.reset()
|
|
309
|
+
console.log(userStore.value) // {theme: 'system', language: 'en'}
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
// 'userStore.value' is of type 'T'
|
|
313
|
+
```
|
|
314
|
+
|
|
257
315
|
<br>
|
|
258
316
|
|
|
259
317
|
## Source
|
package/dist/index.cjs
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
*/
|
|
10
10
|
class HyperStorage {
|
|
11
11
|
/** Version of the library, injected via Rollup replace plugin. */
|
|
12
|
-
static version = "5.0
|
|
12
|
+
static version = "5.1.0";
|
|
13
13
|
/** Key name under which the data is stored. */
|
|
14
14
|
itemName;
|
|
15
15
|
/** Default value used when the key does not exist in storage. */
|
|
@@ -72,7 +72,7 @@ class HyperStorage {
|
|
|
72
72
|
(typeof value === 'number' &&
|
|
73
73
|
(isNaN(value) || value === Infinity || value === -Infinity))) {
|
|
74
74
|
// Manually stringify non-JSON values
|
|
75
|
-
stringValue = String(value);
|
|
75
|
+
stringValue = '\0' + String(value);
|
|
76
76
|
}
|
|
77
77
|
else {
|
|
78
78
|
stringValue = '\0' + JSON.stringify(value);
|
|
@@ -107,8 +107,9 @@ class HyperStorage {
|
|
|
107
107
|
value = decodeFn(value);
|
|
108
108
|
}
|
|
109
109
|
catch (err) {
|
|
110
|
+
this.reset();
|
|
110
111
|
console.error(err);
|
|
111
|
-
return
|
|
112
|
+
return err;
|
|
112
113
|
}
|
|
113
114
|
if (value[0] !== '\0')
|
|
114
115
|
return (this.value = value); // Raw string value
|
package/dist/index.mjs
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
*/
|
|
8
8
|
class HyperStorage {
|
|
9
9
|
/** Version of the library, injected via Rollup replace plugin. */
|
|
10
|
-
static version = "5.0
|
|
10
|
+
static version = "5.1.0";
|
|
11
11
|
/** Key name under which the data is stored. */
|
|
12
12
|
itemName;
|
|
13
13
|
/** Default value used when the key does not exist in storage. */
|
|
@@ -70,7 +70,7 @@ class HyperStorage {
|
|
|
70
70
|
(typeof value === 'number' &&
|
|
71
71
|
(isNaN(value) || value === Infinity || value === -Infinity))) {
|
|
72
72
|
// Manually stringify non-JSON values
|
|
73
|
-
stringValue = String(value);
|
|
73
|
+
stringValue = '\0' + String(value);
|
|
74
74
|
}
|
|
75
75
|
else {
|
|
76
76
|
stringValue = '\0' + JSON.stringify(value);
|
|
@@ -105,8 +105,9 @@ class HyperStorage {
|
|
|
105
105
|
value = decodeFn(value);
|
|
106
106
|
}
|
|
107
107
|
catch (err) {
|
|
108
|
+
this.reset();
|
|
108
109
|
console.error(err);
|
|
109
|
-
return
|
|
110
|
+
return err;
|
|
110
111
|
}
|
|
111
112
|
if (value[0] !== '\0')
|
|
112
113
|
return (this.value = value); // Raw string value
|
package/dist/index.umd.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e="undefined"!=typeof globalThis?globalThis:e||self).
|
|
1
|
+
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e="undefined"!=typeof globalThis?globalThis:e||self).HyperStorage=t()}(this,function(){"use strict";return class{static version="5.1.0";itemName;defaultValue;encodeFn;decodeFn;storage;#e;constructor(e,t,i={}){const{encodeFn:s,decodeFn:n,storage:o=window.localStorage}=i;if("string"!=typeof e)throw new TypeError("itemName is not a string");if(this.itemName=e,this.defaultValue=t,s&&"function"!=typeof s)throw new TypeError("encodeFn is defined but is not a function");if(this.encodeFn=s||(e=>e),n&&"function"!=typeof n)throw new TypeError("decodeFn is defined but is not a function");if(this.decodeFn=n||(e=>e),!(o instanceof Storage))throw new TypeError("storage must be an instance of Storage");this.storage=o,this.sync()}set value(e){let t;this.#e=e,t="string"==typeof e?"\0"===e[0]?"\0"+e:e:void 0===e||"number"==typeof e&&(isNaN(e)||e===1/0||e===-1/0)?"\0"+String(e):"\0"+JSON.stringify(e),this.storage.setItem(this.itemName,this.encodeFn(t))}get value(){return this.#e??this.defaultValue}set(e){return this.value=e(this.value)}sync(e=this.decodeFn){let t=this.storage.getItem(this.itemName);if("string"!=typeof t)return this.reset();try{t=e(t)}catch(e){return this.reset(),console.error(e),e}return"\0"!==t[0]?this.value=t:(t=t.slice(1),"\0"===t[0]?this.value=t:this.value="undefined"===t?void 0:"NaN"===t?NaN:"Infinity"===t?1/0:"-Infinity"===t?-1/0:JSON.parse(t))}reset(){return this.value=this.defaultValue}remove(){this.#e=void 0,this.storage.removeItem(this.itemName)}clear(){this.#e=void 0,this.storage.clear()}isDefault(){return this.#e===this.defaultValue}}});
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -95,7 +95,7 @@ class HyperStorage<T> {
|
|
|
95
95
|
(isNaN(value) || value === Infinity || value === -Infinity))
|
|
96
96
|
) {
|
|
97
97
|
// Manually stringify non-JSON values
|
|
98
|
-
stringValue = String(value)
|
|
98
|
+
stringValue = '\0' + String(value)
|
|
99
99
|
} else {
|
|
100
100
|
stringValue = '\0' + JSON.stringify(value)
|
|
101
101
|
}
|
|
@@ -133,8 +133,9 @@ class HyperStorage<T> {
|
|
|
133
133
|
try {
|
|
134
134
|
value = decodeFn(value)
|
|
135
135
|
} catch (err) {
|
|
136
|
+
this.reset()
|
|
136
137
|
console.error(err)
|
|
137
|
-
return
|
|
138
|
+
return err
|
|
138
139
|
}
|
|
139
140
|
|
|
140
141
|
if (value[0] !== '\0') return (this.value = value as T) // Raw string value
|