@webreflection/utils 0.2.14 → 0.2.16
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 +3 -2
- package/package.json +7 -2
- package/src/README.md +47 -6
- package/src/iterable.js +37 -0
- package/types/iterable.d.ts +13 -0
package/README.md
CHANGED
|
@@ -5,13 +5,14 @@
|
|
|
5
5
|
<sup>**Social Media Photo by [benjamin lehman](https://unsplash.com/@abject) on [Unsplash](https://unsplash.com/)**</sup>
|
|
6
6
|
|
|
7
7
|
|
|
8
|
-
A [collection](./src/) of
|
|
8
|
+
A curated, *TypeScript* friendly, [collection](./src/) of utilities:
|
|
9
9
|
|
|
10
10
|
* **[all](https://github.com/WebReflection/utils/tree/main/src#all)** - `Promise.all` via object destructuring
|
|
11
11
|
* **[ascii](https://github.com/WebReflection/utils/tree/main/src#ascii)** - basic string to buffer conversion (without validation)
|
|
12
12
|
* **[bound-once](https://github.com/WebReflection/utils/tree/main/src#bound-once)** - to retrieve unique bound methods per realm
|
|
13
13
|
* **[bound](https://github.com/WebReflection/utils/tree/main/src#bound)** - to retrieve one-off bound methods
|
|
14
|
-
* **[
|
|
14
|
+
* **[iterable](https://github.com/WebReflection/utils/tree/main/src#iterable)** - to make plain objects iterable as `Object.entries(object)` pairs, without touching objects that already are iterable
|
|
15
|
+
* **[json-storage](https://github.com/WebReflection/utils/tree/main/src#json-storage)** - to use `localStorage` or `sessionStorage` through a JSON-aware, iterable, *Map* friendly API
|
|
15
16
|
* **[shared-array-buffer](https://github.com/WebReflection/utils/tree/main/src#shared-array-buffer)** - to simulate *SAB* when not available
|
|
16
17
|
* **[sticky](https://github.com/WebReflection/utils/tree/main/src#sticky)** - to stick once per realm anything useful
|
|
17
18
|
* **[with-resolvers](https://github.com/WebReflection/utils/tree/main/src#with-resolvers)** - a self bound `Promise.withResolver()` for older runtimes
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@webreflection/utils",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.16",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"types": {
|
|
6
6
|
"./all": "./types/all.d.ts",
|
|
@@ -28,6 +28,10 @@
|
|
|
28
28
|
"types": "./types/bound.d.ts",
|
|
29
29
|
"import": "./src/bound.js"
|
|
30
30
|
},
|
|
31
|
+
"./iterable": {
|
|
32
|
+
"types": "./types/iterable.d.ts",
|
|
33
|
+
"import": "./src/iterable.js"
|
|
34
|
+
},
|
|
31
35
|
"./json-storage": {
|
|
32
36
|
"types": "./types/json-storage.d.ts",
|
|
33
37
|
"import": "./src/json-storage.js"
|
|
@@ -51,6 +55,7 @@
|
|
|
51
55
|
"ascii",
|
|
52
56
|
"bound-once",
|
|
53
57
|
"bound",
|
|
58
|
+
"iterable",
|
|
54
59
|
"json-storage",
|
|
55
60
|
"shared-array-buffer",
|
|
56
61
|
"sticky",
|
|
@@ -60,7 +65,7 @@
|
|
|
60
65
|
"build": "npm run build:types && npm run test",
|
|
61
66
|
"build:types": "tsc --allowJs --checkJs --declaration --emitDeclarationOnly --stripInternal --outDir types --target es2022 --lib es2024 --module nodenext --moduleResolution nodenext src/*.js",
|
|
62
67
|
"coverage": "mkdir -p ./coverage; c8 report --reporter=text-lcov > ./coverage/lcov.info",
|
|
63
|
-
"test": "c8 node -e 'let q=Promise.resolve();for(const t of require(`./package.json`).tests)q=q.then(()=>import(`./test/${t}.js`));'"
|
|
68
|
+
"test": "c8 node --localstorage-file './test/.storage' -e 'let q=Promise.resolve();for(const t of require(`./package.json`).tests)q=q.then(()=>import(`./test/${t}.js`));'"
|
|
64
69
|
},
|
|
65
70
|
"files": [
|
|
66
71
|
"src",
|
package/src/README.md
CHANGED
|
@@ -71,23 +71,64 @@ resolve(4);
|
|
|
71
71
|
The **bound-once** variant ensures that repeated accesses, such as `boundOnce(Promise).all`, always return the same bound method.
|
|
72
72
|
|
|
73
73
|
|
|
74
|
+
## iterable
|
|
75
|
+
|
|
76
|
+
Ensures an object can be consumed by `for...of`, spread, `Array.from`, and
|
|
77
|
+
other iterable-aware APIs.
|
|
78
|
+
|
|
79
|
+
```js
|
|
80
|
+
import iterable from '@webreflection/utils/iterable';
|
|
81
|
+
|
|
82
|
+
const query = iterable({ page: 1, perPage: 20 });
|
|
83
|
+
|
|
84
|
+
console.log([...query]);
|
|
85
|
+
// [['page', 1], ['perPage', 20]]
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
If the object already defines or inherits `Symbol.iterator`, it is returned
|
|
89
|
+
unchanged. Otherwise, the same object receives a configurable own
|
|
90
|
+
`Symbol.iterator` method that yields `Object.entries(ref)`.
|
|
91
|
+
|
|
92
|
+
|
|
74
93
|
## json-storage
|
|
75
94
|
|
|
76
|
-
A *Map* like
|
|
95
|
+
A small *Map* like facade over `localStorage` by default, or `sessionStorage`
|
|
96
|
+
when requested. Values are serialized with `JSON.stringify` on write and parsed
|
|
97
|
+
with `JSON.parse` on read, so callers can store structured data without
|
|
98
|
+
manually converting every value.
|
|
77
99
|
|
|
78
100
|
```js
|
|
79
101
|
import JSONStorage from '@webreflection/utils/json-storage';
|
|
80
102
|
|
|
81
|
-
const
|
|
103
|
+
const preferences = new JSONStorage;
|
|
82
104
|
|
|
83
|
-
|
|
84
|
-
localJSONStorage.getOrInsert('key', { complex: true }).complex;
|
|
105
|
+
preferences.set('theme', { dark: true });
|
|
85
106
|
|
|
86
|
-
|
|
107
|
+
console.log(preferences.get('theme').dark);
|
|
108
|
+
// true
|
|
87
109
|
```
|
|
88
110
|
|
|
89
|
-
The
|
|
111
|
+
The API follows familiar `Map` names where they make sense: `get`, `set`,
|
|
112
|
+
`has`, `delete`, `clear`, `entries`, `keys`, `values`, and default iteration.
|
|
113
|
+
Missing keys return `undefined`, while `delete(key)` reports whether the key was
|
|
114
|
+
present.
|
|
115
|
+
|
|
116
|
+
```js
|
|
117
|
+
const cart = new JSONStorage(JSONStorage.SESSION);
|
|
118
|
+
|
|
119
|
+
const items = cart.getOrInsert('items', []);
|
|
120
|
+
items.push('book');
|
|
121
|
+
cart.set('items', items);
|
|
122
|
+
|
|
123
|
+
for (const [key, value] of cart) {
|
|
124
|
+
console.log(key, value);
|
|
125
|
+
}
|
|
126
|
+
```
|
|
90
127
|
|
|
128
|
+
Use `getOrInsert(key, value)` to create a value only when the key is absent, or
|
|
129
|
+
`getOrInsertComputed(key, callback)` when the initial value should be computed
|
|
130
|
+
from the key. A second constructor argument can replace the native *JSON* API as
|
|
131
|
+
long as it provides compatible `parse(source)` and `stringify(value)` methods.
|
|
91
132
|
|
|
92
133
|
|
|
93
134
|
## shared-array-buffer
|
package/src/iterable.js
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
3
|
+
/** @type {typeof Symbol.iterator} */
|
|
4
|
+
const iterator = Symbol.iterator;
|
|
5
|
+
|
|
6
|
+
const { defineProperty: dp, entries } = Object;
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @this {object}
|
|
10
|
+
* @returns {Generator<[string, any], void, unknown>}
|
|
11
|
+
*/
|
|
12
|
+
function* value() {
|
|
13
|
+
yield* entries(this);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const configurable = true;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Ensures an object is iterable.
|
|
20
|
+
*
|
|
21
|
+
* If `ref` already defines or inherits `Symbol.iterator`, it is returned
|
|
22
|
+
* unchanged. Otherwise, the same object is augmented with `Symbol.iterator`
|
|
23
|
+
* yielding the entries produced by `Object.entries(ref)`.
|
|
24
|
+
*
|
|
25
|
+
* @typedef {{
|
|
26
|
+
* <T extends Iterable<unknown>>(ref: T): T;
|
|
27
|
+
* <T extends object>(ref: T): T & Iterable<[string, T[keyof T]]>;
|
|
28
|
+
* }} EnsureIterable
|
|
29
|
+
*/
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* @param {object} ref
|
|
33
|
+
* @returns {object}
|
|
34
|
+
*/
|
|
35
|
+
const iterable = ref => iterator in ref ? ref : dp(ref, iterator, { configurable, value });
|
|
36
|
+
|
|
37
|
+
export default /** @type {EnsureIterable} */(iterable);
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
declare const _default: EnsureIterable;
|
|
2
|
+
export default _default;
|
|
3
|
+
/**
|
|
4
|
+
* Ensures an object is iterable.
|
|
5
|
+
*
|
|
6
|
+
* If `ref` already defines or inherits `Symbol.iterator`, it is returned
|
|
7
|
+
* unchanged. Otherwise, the same object is augmented with `Symbol.iterator`
|
|
8
|
+
* yielding the entries produced by `Object.entries(ref)`.
|
|
9
|
+
*/
|
|
10
|
+
export type EnsureIterable = {
|
|
11
|
+
<T extends Iterable<unknown>>(ref: T): T;
|
|
12
|
+
<T extends object>(ref: T): T & Iterable<[string, T[keyof T]]>;
|
|
13
|
+
};
|