@weborigami/async-tree 0.5.8 → 0.6.1
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/browser.js +1 -1
- package/index.ts +43 -35
- package/main.js +1 -2
- package/package.json +4 -7
- package/shared.js +74 -12
- package/src/Tree.js +11 -2
- package/src/drivers/AsyncMap.js +237 -0
- package/src/drivers/{BrowserFileTree.js → BrowserFileMap.js} +54 -38
- package/src/drivers/{calendarTree.js → CalendarMap.js} +80 -63
- package/src/drivers/ConstantMap.js +28 -0
- package/src/drivers/{ExplorableSiteTree.js → ExplorableSiteMap.js} +7 -7
- package/src/drivers/FileMap.js +238 -0
- package/src/drivers/{FunctionTree.js → FunctionMap.js} +19 -22
- package/src/drivers/ObjectMap.js +151 -0
- package/src/drivers/SetMap.js +13 -0
- package/src/drivers/{SiteTree.js → SiteMap.js} +17 -20
- package/src/drivers/SyncMap.js +260 -0
- package/src/jsonKeys.d.ts +2 -2
- package/src/jsonKeys.js +20 -5
- package/src/operations/addNextPrevious.js +35 -36
- package/src/operations/assign.js +27 -23
- package/src/operations/cache.js +30 -36
- package/src/operations/cachedKeyFunctions.js +1 -1
- package/src/operations/calendar.js +5 -0
- package/src/operations/child.js +35 -0
- package/src/operations/clear.js +13 -12
- package/src/operations/constant.js +5 -0
- package/src/operations/deepEntries.js +23 -0
- package/src/operations/deepMap.js +9 -9
- package/src/operations/deepMerge.js +36 -25
- package/src/operations/deepReverse.js +23 -16
- package/src/operations/deepTake.js +7 -7
- package/src/operations/deepText.js +4 -4
- package/src/operations/deepValues.js +3 -6
- package/src/operations/deepValuesIterator.js +11 -11
- package/src/operations/delete.js +8 -12
- package/src/operations/entries.js +17 -10
- package/src/operations/filter.js +9 -7
- package/src/operations/first.js +12 -10
- package/src/operations/forEach.js +10 -13
- package/src/operations/from.js +30 -39
- package/src/operations/globKeys.js +22 -17
- package/src/operations/group.js +2 -2
- package/src/operations/groupBy.js +24 -22
- package/src/operations/has.js +7 -9
- package/src/operations/indent.js +2 -2
- package/src/operations/inners.js +19 -15
- package/src/operations/invokeFunctions.js +22 -10
- package/src/operations/isAsyncMutableTree.js +5 -12
- package/src/operations/isAsyncTree.js +5 -20
- package/src/operations/isMap.js +39 -0
- package/src/operations/isMaplike.js +34 -0
- package/src/operations/isReadOnlyMap.js +14 -0
- package/src/operations/isTraversable.js +3 -3
- package/src/operations/isTreelike.js +5 -30
- package/src/operations/json.js +4 -12
- package/src/operations/keys.js +17 -8
- package/src/operations/length.js +9 -8
- package/src/operations/map.js +28 -30
- package/src/operations/mapExtension.js +20 -16
- package/src/operations/mapReduce.js +38 -24
- package/src/operations/mask.js +54 -29
- package/src/operations/match.js +13 -9
- package/src/operations/merge.js +43 -35
- package/src/operations/paginate.js +26 -18
- package/src/operations/parent.js +7 -7
- package/src/operations/paths.js +20 -22
- package/src/operations/plain.js +6 -6
- package/src/operations/reduce.js +16 -0
- package/src/operations/regExpKeys.js +21 -12
- package/src/operations/reverse.js +21 -15
- package/src/operations/root.js +6 -5
- package/src/operations/scope.js +31 -26
- package/src/operations/set.js +20 -0
- package/src/operations/shuffle.js +23 -16
- package/src/operations/size.js +13 -0
- package/src/operations/sort.js +55 -40
- package/src/operations/sync.js +14 -0
- package/src/operations/take.js +23 -11
- package/src/operations/text.js +4 -4
- package/src/operations/toFunction.js +7 -7
- package/src/operations/traverse.js +4 -4
- package/src/operations/traverseOrThrow.js +18 -9
- package/src/operations/traversePath.js +2 -2
- package/src/operations/values.js +18 -9
- package/src/operations/withKeys.js +22 -16
- package/src/symbols.js +1 -0
- package/src/utilities/castArraylike.js +24 -13
- package/src/utilities/getMapArgument.js +38 -0
- package/src/utilities/getParent.js +2 -2
- package/src/utilities/isStringlike.js +7 -5
- package/src/utilities/setParent.js +7 -7
- package/src/utilities/toFunction.js +2 -2
- package/src/utilities/toPlainValue.js +21 -19
- package/test/SampleAsyncMap.js +34 -0
- package/test/browser/assert.js +20 -0
- package/test/browser/index.html +53 -21
- package/test/drivers/AsyncMap.test.js +119 -0
- package/test/drivers/{BrowserFileTree.test.js → BrowserFileMap.test.js} +50 -33
- package/test/drivers/{calendarTree.test.js → CalendarMap.test.js} +17 -19
- package/test/drivers/ConstantMap.test.js +15 -0
- package/test/drivers/{ExplorableSiteTree.test.js → ExplorableSiteMap.test.js} +29 -14
- package/test/drivers/FileMap.test.js +156 -0
- package/test/drivers/FunctionMap.test.js +56 -0
- package/test/drivers/ObjectMap.test.js +194 -0
- package/test/drivers/SetMap.test.js +35 -0
- package/test/drivers/{SiteTree.test.js → SiteMap.test.js} +14 -10
- package/test/drivers/SyncMap.test.js +335 -0
- package/test/jsonKeys.test.js +18 -6
- package/test/operations/addNextPrevious.test.js +3 -2
- package/test/operations/assign.test.js +30 -35
- package/test/operations/cache.test.js +17 -12
- package/test/operations/cachedKeyFunctions.test.js +12 -9
- package/test/operations/child.test.js +34 -0
- package/test/operations/clear.test.js +6 -27
- package/test/operations/deepEntries.test.js +32 -0
- package/test/operations/deepMerge.test.js +23 -16
- package/test/operations/deepReverse.test.js +2 -2
- package/test/operations/deepTake.test.js +2 -2
- package/test/operations/deepText.test.js +4 -4
- package/test/operations/deepValuesIterator.test.js +2 -2
- package/test/operations/delete.test.js +2 -2
- package/test/operations/extensionKeyFunctions.test.js +6 -5
- package/test/operations/filter.test.js +3 -3
- package/test/operations/from.test.js +25 -31
- package/test/operations/globKeys.test.js +9 -9
- package/test/operations/groupBy.test.js +6 -5
- package/test/operations/inners.test.js +17 -14
- package/test/operations/invokeFunctions.test.js +2 -2
- package/test/operations/isMap.test.js +15 -0
- package/test/operations/isMaplike.test.js +15 -0
- package/test/operations/json.test.js +2 -2
- package/test/operations/keys.test.js +16 -3
- package/test/operations/map.test.js +40 -30
- package/test/operations/mapExtension.test.js +6 -6
- package/test/operations/mapReduce.test.js +14 -12
- package/test/operations/mask.test.js +16 -3
- package/test/operations/match.test.js +2 -2
- package/test/operations/merge.test.js +20 -14
- package/test/operations/paginate.test.js +5 -5
- package/test/operations/parent.test.js +3 -3
- package/test/operations/paths.test.js +20 -27
- package/test/operations/plain.test.js +8 -8
- package/test/operations/regExpKeys.test.js +22 -18
- package/test/operations/reverse.test.js +4 -3
- package/test/operations/scope.test.js +6 -5
- package/test/operations/set.test.js +11 -0
- package/test/operations/shuffle.test.js +3 -2
- package/test/operations/sort.test.js +7 -10
- package/test/operations/sync.test.js +43 -0
- package/test/operations/take.test.js +2 -2
- package/test/operations/toFunction.test.js +2 -2
- package/test/operations/traverse.test.js +17 -5
- package/test/operations/withKeys.test.js +2 -2
- package/test/utilities/castArrayLike.test.js +53 -0
- package/test/utilities/setParent.test.js +6 -6
- package/test/utilities/toFunction.test.js +2 -2
- package/test/utilities/toPlainValue.test.js +51 -12
- package/src/drivers/DeepMapTree.js +0 -23
- package/src/drivers/DeepObjectTree.js +0 -18
- package/src/drivers/DeferredTree.js +0 -81
- package/src/drivers/FileTree.js +0 -276
- package/src/drivers/MapTree.js +0 -70
- package/src/drivers/ObjectTree.js +0 -158
- package/src/drivers/SetTree.js +0 -34
- package/src/drivers/constantTree.js +0 -19
- package/src/drivers/limitConcurrency.js +0 -63
- package/src/internal.js +0 -16
- package/src/utilities/getTreeArgument.js +0 -43
- package/test/drivers/DeepMapTree.test.js +0 -17
- package/test/drivers/DeepObjectTree.test.js +0 -35
- package/test/drivers/DeferredTree.test.js +0 -22
- package/test/drivers/FileTree.test.js +0 -192
- package/test/drivers/FunctionTree.test.js +0 -46
- package/test/drivers/MapTree.test.js +0 -59
- package/test/drivers/ObjectTree.test.js +0 -163
- package/test/drivers/SetTree.test.js +0 -44
- package/test/drivers/constantTree.test.js +0 -13
- package/test/drivers/limitConcurrency.test.js +0 -41
- package/test/operations/isAsyncMutableTree.test.js +0 -17
- package/test/operations/isAsyncTree.test.js +0 -26
- package/test/operations/isTreelike.test.js +0 -13
|
@@ -0,0 +1,335 @@
|
|
|
1
|
+
import assert from "node:assert";
|
|
2
|
+
import { describe, test } from "node:test";
|
|
3
|
+
import SyncMap from "../../src/drivers/SyncMap.js";
|
|
4
|
+
|
|
5
|
+
describe("SyncMap", () => {
|
|
6
|
+
test("passes instanceof Map", () => {
|
|
7
|
+
const map = new SyncMap();
|
|
8
|
+
assert(map instanceof Map);
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
test("can be constructed with an iterable", () => {
|
|
12
|
+
const map = new SyncMap([
|
|
13
|
+
["a", 1],
|
|
14
|
+
["b", 2],
|
|
15
|
+
]);
|
|
16
|
+
assert.strictEqual(map.size, 2);
|
|
17
|
+
assert.strictEqual(map.get("a"), 1);
|
|
18
|
+
assert.strictEqual(map.get("b"), 2);
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
test("can be constructed with another SyncMap", () => {
|
|
22
|
+
const map1 = new SyncMap([
|
|
23
|
+
["a", 1],
|
|
24
|
+
["b", 2],
|
|
25
|
+
]);
|
|
26
|
+
const map2 = new SyncMap(map1);
|
|
27
|
+
const entries = Array.from(map2.entries());
|
|
28
|
+
assert.deepStrictEqual(entries, [
|
|
29
|
+
["a", 1],
|
|
30
|
+
["b", 2],
|
|
31
|
+
]);
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
test("clear calls delete for each key", () => {
|
|
35
|
+
const deletedKeys = [];
|
|
36
|
+
const keys = ["a", "b", "c"];
|
|
37
|
+
class Fixture extends SyncMap {
|
|
38
|
+
delete(key) {
|
|
39
|
+
deletedKeys.push(key);
|
|
40
|
+
return keys.includes(key);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
keys() {
|
|
44
|
+
return keys[Symbol.iterator]();
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
const map = new Fixture();
|
|
48
|
+
map.clear();
|
|
49
|
+
assert.deepStrictEqual(deletedKeys, ["a", "b", "c"]);
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
test("delete", () => {
|
|
53
|
+
const map = new SyncMap([
|
|
54
|
+
["a", 1],
|
|
55
|
+
["b", 2],
|
|
56
|
+
]);
|
|
57
|
+
assert.strictEqual(map.size, 2);
|
|
58
|
+
assert.strictEqual(map.delete("a"), true);
|
|
59
|
+
assert.strictEqual(map.size, 1);
|
|
60
|
+
assert.strictEqual(map.get("a"), undefined);
|
|
61
|
+
assert.strictEqual(map.delete("a"), false);
|
|
62
|
+
assert.strictEqual(map.size, 1);
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
test("delete on read-only map throws", () => {
|
|
66
|
+
class Fixture extends SyncMap {
|
|
67
|
+
get(key) {
|
|
68
|
+
return super.get(key);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
const map = new Fixture([
|
|
72
|
+
["a", 1],
|
|
73
|
+
["b", 2],
|
|
74
|
+
]);
|
|
75
|
+
assert.throws(() => map.delete("a"), {
|
|
76
|
+
name: "TypeError",
|
|
77
|
+
message: "delete() can't be called on a read-only map",
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
test("entries", () => {
|
|
82
|
+
const map = new SyncMap([
|
|
83
|
+
["a", 1],
|
|
84
|
+
["b", 2],
|
|
85
|
+
]);
|
|
86
|
+
const entries = Array.from(map.entries());
|
|
87
|
+
assert.deepStrictEqual(entries, [
|
|
88
|
+
["a", 1],
|
|
89
|
+
["b", 2],
|
|
90
|
+
]);
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
test("forEach", () => {
|
|
94
|
+
const map = new SyncMap([
|
|
95
|
+
["a", 1],
|
|
96
|
+
["b", 2],
|
|
97
|
+
]);
|
|
98
|
+
const calls = [];
|
|
99
|
+
map.forEach((value, key, theMap) => {
|
|
100
|
+
calls.push([key, value, theMap]);
|
|
101
|
+
});
|
|
102
|
+
assert.deepStrictEqual(calls, [
|
|
103
|
+
["a", 1, map],
|
|
104
|
+
["b", 2, map],
|
|
105
|
+
]);
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
test("get", () => {
|
|
109
|
+
const map = new SyncMap([
|
|
110
|
+
["a", 1],
|
|
111
|
+
["b", 2],
|
|
112
|
+
]);
|
|
113
|
+
assert.strictEqual(map.get("a"), 1);
|
|
114
|
+
assert.strictEqual(map.get("b"), 2);
|
|
115
|
+
assert.strictEqual(map.get("c"), undefined);
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
test("get with trailing slash", () => {
|
|
119
|
+
const subMap = new SyncMap();
|
|
120
|
+
const map = new SyncMap([
|
|
121
|
+
["a", 1],
|
|
122
|
+
["b/", subMap],
|
|
123
|
+
]);
|
|
124
|
+
assert.strictEqual(map.get("a"), 1);
|
|
125
|
+
|
|
126
|
+
const b = map.get("b/");
|
|
127
|
+
assert.strictEqual(b, subMap);
|
|
128
|
+
assert.strictEqual(b.parent, map);
|
|
129
|
+
|
|
130
|
+
// Trailing slash optional
|
|
131
|
+
assert.strictEqual(map.get("b"), subMap);
|
|
132
|
+
|
|
133
|
+
assert.strictEqual(map.get("c"), undefined);
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
test("has returns true if key exists in keys()", () => {
|
|
137
|
+
const map = new SyncMap();
|
|
138
|
+
map.keys = () => {
|
|
139
|
+
return ["a", "b/"][Symbol.iterator]();
|
|
140
|
+
};
|
|
141
|
+
assert.strictEqual(map.has("a"), true);
|
|
142
|
+
assert.strictEqual(map.has("b"), true); // trailing slash optional
|
|
143
|
+
assert.strictEqual(map.has("b/"), true);
|
|
144
|
+
assert.strictEqual(map.has("c"), false);
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
test("readOnly if get() is overridden but not delete() and set()", () => {
|
|
148
|
+
const map4 = new SyncMap();
|
|
149
|
+
assert.strictEqual(map4.readOnly, false);
|
|
150
|
+
|
|
151
|
+
class ReadOnly1 extends SyncMap {
|
|
152
|
+
get(key) {
|
|
153
|
+
return super.get(key);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
const map1 = new ReadOnly1();
|
|
157
|
+
assert.strictEqual(map1.readOnly, true);
|
|
158
|
+
|
|
159
|
+
class ReadOnly2 extends SyncMap {
|
|
160
|
+
get(key) {
|
|
161
|
+
return super.get(key);
|
|
162
|
+
}
|
|
163
|
+
set(key, value) {
|
|
164
|
+
return super.set(key, value);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
const map2 = new ReadOnly2();
|
|
168
|
+
assert.strictEqual(map2.readOnly, true);
|
|
169
|
+
|
|
170
|
+
class ReadWrite extends SyncMap {
|
|
171
|
+
get(key) {
|
|
172
|
+
return super.get(key);
|
|
173
|
+
}
|
|
174
|
+
set(key, value) {
|
|
175
|
+
return super.set(key, value);
|
|
176
|
+
}
|
|
177
|
+
delete(key) {
|
|
178
|
+
return super.delete(key);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
const map3 = new ReadWrite();
|
|
182
|
+
assert.strictEqual(map3.readOnly, false);
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
test("Symbol.iterator", () => {
|
|
186
|
+
const map = new SyncMap([
|
|
187
|
+
["a", 1],
|
|
188
|
+
["b", 2],
|
|
189
|
+
]);
|
|
190
|
+
const entries = Array.from(map[Symbol.iterator]());
|
|
191
|
+
assert.deepStrictEqual(entries, [
|
|
192
|
+
["a", 1],
|
|
193
|
+
["b", 2],
|
|
194
|
+
]);
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
test("keys", () => {
|
|
198
|
+
const map = new SyncMap([
|
|
199
|
+
["a", 1],
|
|
200
|
+
["b", 2],
|
|
201
|
+
]);
|
|
202
|
+
const keys = Array.from(map.keys());
|
|
203
|
+
assert.deepStrictEqual(keys, ["a", "b"]);
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
test("set", () => {
|
|
207
|
+
const map = new SyncMap();
|
|
208
|
+
assert.strictEqual(map.size, 0);
|
|
209
|
+
map.set("a", 1);
|
|
210
|
+
assert.strictEqual(map.size, 1);
|
|
211
|
+
assert.strictEqual(map.get("a"), 1);
|
|
212
|
+
map.set("a", 2);
|
|
213
|
+
assert.strictEqual(map.size, 1);
|
|
214
|
+
assert.strictEqual(map.get("a"), 2);
|
|
215
|
+
map.set("b", 3);
|
|
216
|
+
assert.strictEqual(map.size, 2);
|
|
217
|
+
assert.strictEqual(map.get("b"), 3);
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
test("child creates new map when not present", () => {
|
|
221
|
+
// Create child when not present
|
|
222
|
+
const map = new SyncMap();
|
|
223
|
+
const child1 = map.child("sub");
|
|
224
|
+
assert(child1 instanceof SyncMap);
|
|
225
|
+
const stored1 = map.get("sub");
|
|
226
|
+
assert.strictEqual(stored1, child1);
|
|
227
|
+
|
|
228
|
+
// Return existing child
|
|
229
|
+
const child2 = map.child("sub");
|
|
230
|
+
assert.strictEqual(child2, child1);
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
test("child overwrites non-map value", () => {
|
|
234
|
+
const map = new SyncMap();
|
|
235
|
+
map.set("sub", 123);
|
|
236
|
+
const child = map.child("sub");
|
|
237
|
+
assert(child instanceof SyncMap);
|
|
238
|
+
const stored = map.get("sub");
|
|
239
|
+
assert.strictEqual(stored, child);
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
test("set on read-only map throws", () => {
|
|
243
|
+
class Fixture extends SyncMap {
|
|
244
|
+
get(key) {
|
|
245
|
+
return super.get(key);
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
const map = new Fixture();
|
|
249
|
+
assert.throws(() => map.set("a", 1), {
|
|
250
|
+
name: "TypeError",
|
|
251
|
+
message: "set() can't be called on a read-only map",
|
|
252
|
+
});
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
test("size", () => {
|
|
256
|
+
const map = new SyncMap();
|
|
257
|
+
assert.strictEqual(map.size, 0);
|
|
258
|
+
map.set("a", 1);
|
|
259
|
+
assert.strictEqual(map.size, 1);
|
|
260
|
+
map.set("b", 2);
|
|
261
|
+
assert.strictEqual(map.size, 2);
|
|
262
|
+
map.delete("a");
|
|
263
|
+
assert.strictEqual(map.size, 1);
|
|
264
|
+
map.clear();
|
|
265
|
+
assert.strictEqual(map.size, 0);
|
|
266
|
+
});
|
|
267
|
+
|
|
268
|
+
test("values", () => {
|
|
269
|
+
const map = new SyncMap([
|
|
270
|
+
["a", 1],
|
|
271
|
+
["b", 2],
|
|
272
|
+
]);
|
|
273
|
+
const values = Array.from(map.values());
|
|
274
|
+
assert.deepStrictEqual(values, [1, 2]);
|
|
275
|
+
});
|
|
276
|
+
|
|
277
|
+
test("all methods work with prototype chain extension", () => {
|
|
278
|
+
const map = new SyncMap([
|
|
279
|
+
["a", 1],
|
|
280
|
+
["b", 2],
|
|
281
|
+
]);
|
|
282
|
+
const map2 = Object.create(map);
|
|
283
|
+
assert.strictEqual(map2.get("a"), 1);
|
|
284
|
+
assert.strictEqual(map2.has("b"), true);
|
|
285
|
+
assert.strictEqual(map2.size, 2);
|
|
286
|
+
|
|
287
|
+
const entries = Array.from(map2.entries());
|
|
288
|
+
assert.deepStrictEqual(entries, [
|
|
289
|
+
["a", 1],
|
|
290
|
+
["b", 2],
|
|
291
|
+
]);
|
|
292
|
+
|
|
293
|
+
const keys = Array.from(map2.keys());
|
|
294
|
+
assert.deepStrictEqual(keys, ["a", "b"]);
|
|
295
|
+
|
|
296
|
+
const values = Array.from(map2.values());
|
|
297
|
+
assert.deepStrictEqual(values, [1, 2]);
|
|
298
|
+
|
|
299
|
+
const iteratedEntries = Array.from(map2[Symbol.iterator]());
|
|
300
|
+
assert.deepStrictEqual(iteratedEntries, [
|
|
301
|
+
["a", 1],
|
|
302
|
+
["b", 2],
|
|
303
|
+
]);
|
|
304
|
+
|
|
305
|
+
const forEachCalls = [];
|
|
306
|
+
map2.forEach((value, key, thisArg) => {
|
|
307
|
+
forEachCalls.push([key, value, thisArg]);
|
|
308
|
+
});
|
|
309
|
+
assert.deepStrictEqual(forEachCalls, [
|
|
310
|
+
["a", 1, map2],
|
|
311
|
+
["b", 2, map2],
|
|
312
|
+
]);
|
|
313
|
+
});
|
|
314
|
+
|
|
315
|
+
if ("groupBy" in Map) {
|
|
316
|
+
test("acceptable to Map.groupBy", () => {
|
|
317
|
+
const map = new SyncMap([
|
|
318
|
+
["a", 1],
|
|
319
|
+
["b", 2],
|
|
320
|
+
["c", 3],
|
|
321
|
+
]);
|
|
322
|
+
// @ts-ignore
|
|
323
|
+
const grouped = Map.groupBy(map, ([key, value]) =>
|
|
324
|
+
value % 2 === 0 ? "even" : "odd"
|
|
325
|
+
);
|
|
326
|
+
assert(grouped instanceof Map);
|
|
327
|
+
assert.strictEqual(grouped.size, 2);
|
|
328
|
+
assert.deepStrictEqual(grouped.get("odd"), [
|
|
329
|
+
["a", 1],
|
|
330
|
+
["c", 3],
|
|
331
|
+
]);
|
|
332
|
+
assert.deepStrictEqual(grouped.get("even"), [["b", 2]]);
|
|
333
|
+
});
|
|
334
|
+
}
|
|
335
|
+
});
|
package/test/jsonKeys.test.js
CHANGED
|
@@ -1,14 +1,26 @@
|
|
|
1
1
|
import assert from "node:assert";
|
|
2
2
|
import { describe, test } from "node:test";
|
|
3
|
-
import
|
|
3
|
+
import ObjectMap from "../src/drivers/ObjectMap.js";
|
|
4
4
|
import * as jsonKeys from "../src/jsonKeys.js";
|
|
5
5
|
|
|
6
6
|
describe("jsonKeys", () => {
|
|
7
|
-
test("
|
|
8
|
-
const tree = new
|
|
9
|
-
|
|
10
|
-
"
|
|
11
|
-
|
|
7
|
+
test("creates JSON keys for a simple map", async () => {
|
|
8
|
+
const tree = new /** @type {any} */ (Map)([
|
|
9
|
+
["index.html", "Home"],
|
|
10
|
+
["about", new Map()],
|
|
11
|
+
]);
|
|
12
|
+
const json = await jsonKeys.stringify(tree);
|
|
13
|
+
assert.strictEqual(json, '["index.html","about/"]');
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
test("creates JSON keys for a map that supports trailing slashes", async () => {
|
|
17
|
+
const tree = new ObjectMap(
|
|
18
|
+
{
|
|
19
|
+
about: {},
|
|
20
|
+
"index.html": "Home",
|
|
21
|
+
},
|
|
22
|
+
{ deep: true }
|
|
23
|
+
);
|
|
12
24
|
const json = await jsonKeys.stringify(tree);
|
|
13
25
|
assert.strictEqual(json, '["about/","index.html"]');
|
|
14
26
|
});
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import assert from "node:assert";
|
|
2
2
|
import { describe, test } from "node:test";
|
|
3
3
|
import addNextPrevious from "../../src/operations/addNextPrevious.js";
|
|
4
|
+
import plain from "../../src/operations/plain.js";
|
|
4
5
|
|
|
5
6
|
describe("addNextPrevious", () => {
|
|
6
7
|
test("adds next/previous properties to values", async () => {
|
|
@@ -16,7 +17,7 @@ describe("addNextPrevious", () => {
|
|
|
16
17
|
},
|
|
17
18
|
};
|
|
18
19
|
const result = await addNextPrevious(tree);
|
|
19
|
-
assert.deepEqual(result, {
|
|
20
|
+
assert.deepEqual(await plain(result), {
|
|
20
21
|
alice: {
|
|
21
22
|
name: "Alice",
|
|
22
23
|
nextKey: "bob",
|
|
@@ -36,7 +37,7 @@ describe("addNextPrevious", () => {
|
|
|
36
37
|
test("returns a non-object value as a 'value' property", async () => {
|
|
37
38
|
const array = ["Alice", "Bob", "Carol"];
|
|
38
39
|
const result = await addNextPrevious(array);
|
|
39
|
-
assert.deepEqual(result, [
|
|
40
|
+
assert.deepEqual(await plain(result), [
|
|
40
41
|
{
|
|
41
42
|
value: "Alice",
|
|
42
43
|
nextKey: "1",
|
|
@@ -1,53 +1,48 @@
|
|
|
1
1
|
import assert from "node:assert";
|
|
2
2
|
import { describe, test } from "node:test";
|
|
3
|
-
import
|
|
4
|
-
import
|
|
3
|
+
import ObjectMap from "../../src/drivers/ObjectMap.js";
|
|
4
|
+
import SyncMap from "../../src/drivers/SyncMap.js";
|
|
5
5
|
import assign from "../../src/operations/assign.js";
|
|
6
6
|
import plain from "../../src/operations/plain.js";
|
|
7
|
+
import { deepEntries } from "../../src/Tree.js";
|
|
8
|
+
import SampleAsyncMap from "../SampleAsyncMap.js";
|
|
7
9
|
|
|
8
10
|
describe("assign", () => {
|
|
9
|
-
test("assign
|
|
10
|
-
const target = new
|
|
11
|
-
a
|
|
12
|
-
b
|
|
13
|
-
more
|
|
14
|
-
|
|
15
|
-
},
|
|
16
|
-
});
|
|
11
|
+
test("assign can apply updates from an async tree to a sync tree", async () => {
|
|
12
|
+
const target = new SyncMap([
|
|
13
|
+
["a", 1],
|
|
14
|
+
["b", 2],
|
|
15
|
+
["more", new SyncMap([["d", 3]])],
|
|
16
|
+
]);
|
|
17
17
|
|
|
18
|
-
const source = new
|
|
19
|
-
a
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
e: 6, // Add
|
|
25
|
-
},
|
|
26
|
-
// Add new subtree
|
|
27
|
-
extra: {
|
|
28
|
-
f: 7,
|
|
29
|
-
},
|
|
30
|
-
});
|
|
18
|
+
const source = new SampleAsyncMap([
|
|
19
|
+
["a", 4], // Overwrite existing value
|
|
20
|
+
["c", 5], // Add
|
|
21
|
+
["more", [["e", 6]]], // Should leave existing `more` keys alone.
|
|
22
|
+
["extra", [["f", 7]]], // Add new subtree
|
|
23
|
+
]);
|
|
31
24
|
|
|
32
25
|
// Apply changes.
|
|
33
26
|
const result = await assign(target, source);
|
|
34
27
|
|
|
35
28
|
assert.equal(result, target);
|
|
36
|
-
assert.deepEqual(await
|
|
37
|
-
a
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
29
|
+
assert.deepEqual(await deepEntries(target), [
|
|
30
|
+
["a", 4],
|
|
31
|
+
["b", 2],
|
|
32
|
+
[
|
|
33
|
+
"more",
|
|
34
|
+
[
|
|
35
|
+
["d", 3],
|
|
36
|
+
["e", 6],
|
|
37
|
+
],
|
|
38
|
+
],
|
|
39
|
+
["c", 5],
|
|
40
|
+
["extra", [["f", 7]]],
|
|
41
|
+
]);
|
|
47
42
|
});
|
|
48
43
|
|
|
49
44
|
test("assign() can apply updates to an array", async () => {
|
|
50
|
-
const target = new
|
|
45
|
+
const target = new ObjectMap(["a", "b", "c"]);
|
|
51
46
|
await assign(target, ["d", "e"]);
|
|
52
47
|
assert.deepEqual(await plain(target), ["d", "e", "c"]);
|
|
53
48
|
});
|
|
@@ -1,25 +1,30 @@
|
|
|
1
1
|
import assert from "node:assert";
|
|
2
2
|
import { describe, test } from "node:test";
|
|
3
|
-
import
|
|
3
|
+
import ObjectMap from "../../src/drivers/ObjectMap.js";
|
|
4
|
+
import SyncMap from "../../src/drivers/SyncMap.js";
|
|
4
5
|
import cache from "../../src/operations/cache.js";
|
|
6
|
+
import keys from "../../src/operations/keys.js";
|
|
5
7
|
|
|
6
8
|
describe("cache", () => {
|
|
7
9
|
test("caches reads of values from one tree into another", async () => {
|
|
8
|
-
const objectCache = new
|
|
10
|
+
const objectCache = new SyncMap();
|
|
9
11
|
const fixture = await cache(
|
|
10
|
-
new
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
12
|
+
new ObjectMap(
|
|
13
|
+
{
|
|
14
|
+
a: 1,
|
|
15
|
+
b: 2,
|
|
16
|
+
c: 3,
|
|
17
|
+
more: {
|
|
18
|
+
d: 4,
|
|
19
|
+
},
|
|
16
20
|
},
|
|
17
|
-
|
|
21
|
+
{ deep: true }
|
|
22
|
+
),
|
|
18
23
|
objectCache
|
|
19
24
|
);
|
|
20
25
|
|
|
21
|
-
const
|
|
22
|
-
assert.deepEqual(
|
|
26
|
+
const treeKeys = await keys(fixture);
|
|
27
|
+
assert.deepEqual(treeKeys, ["a", "b", "c", "more/"]);
|
|
23
28
|
|
|
24
29
|
assert.equal(await objectCache.get("a"), undefined);
|
|
25
30
|
assert.equal(await fixture.get("a"), 1);
|
|
@@ -31,7 +36,7 @@ describe("cache", () => {
|
|
|
31
36
|
|
|
32
37
|
assert.equal(await objectCache.get("more"), undefined);
|
|
33
38
|
const more = await fixture.get("more");
|
|
34
|
-
assert.deepEqual([...(await
|
|
39
|
+
assert.deepEqual([...(await keys(more))], ["d"]);
|
|
35
40
|
assert.equal(await more.get("d"), 4);
|
|
36
41
|
const moreCache = await objectCache.get("more");
|
|
37
42
|
assert.equal(await moreCache.get("d"), 4);
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import assert from "node:assert";
|
|
2
2
|
import { describe, test } from "node:test";
|
|
3
|
-
import
|
|
3
|
+
import ObjectMap from "../../src/drivers/ObjectMap.js";
|
|
4
4
|
import cachedKeyFunctions from "../../src/operations/cachedKeyFunctions.js";
|
|
5
5
|
import * as trailingSlash from "../../src/trailingSlash.js";
|
|
6
6
|
|
|
7
7
|
describe("cachedKeyFunctions", () => {
|
|
8
8
|
test("maps keys with caching", async () => {
|
|
9
|
-
const tree = new
|
|
9
|
+
const tree = new ObjectMap({
|
|
10
10
|
a: "letter a",
|
|
11
11
|
b: "letter b",
|
|
12
12
|
});
|
|
@@ -41,12 +41,15 @@ describe("cachedKeyFunctions", () => {
|
|
|
41
41
|
});
|
|
42
42
|
|
|
43
43
|
test("maps keys with caching and deep option", async () => {
|
|
44
|
-
const tree = new
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
44
|
+
const tree = new ObjectMap(
|
|
45
|
+
{
|
|
46
|
+
a: "letter a",
|
|
47
|
+
b: {
|
|
48
|
+
c: "letter c",
|
|
49
|
+
},
|
|
48
50
|
},
|
|
49
|
-
|
|
51
|
+
{ deep: true }
|
|
52
|
+
);
|
|
50
53
|
|
|
51
54
|
let callCount = 0;
|
|
52
55
|
const addUnderscore = async (sourceValue, sourceKey, tree) => {
|
|
@@ -76,7 +79,7 @@ describe("cachedKeyFunctions", () => {
|
|
|
76
79
|
});
|
|
77
80
|
|
|
78
81
|
test("preserves trailing slashes if key function does so", async () => {
|
|
79
|
-
const tree = new
|
|
82
|
+
const tree = new ObjectMap({
|
|
80
83
|
a: "letter a",
|
|
81
84
|
});
|
|
82
85
|
const addUnderscore = async (sourceValue, sourceKey) => `_${sourceKey}`;
|
|
@@ -90,7 +93,7 @@ describe("cachedKeyFunctions", () => {
|
|
|
90
93
|
});
|
|
91
94
|
|
|
92
95
|
test("if key function toggles slash, defers to key function slash handling", async () => {
|
|
93
|
-
const tree = new
|
|
96
|
+
const tree = new ObjectMap({
|
|
94
97
|
a: "letter a",
|
|
95
98
|
});
|
|
96
99
|
const addUnderscoreAndSlash = async (sourceValue, sourceKey) =>
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import assert from "node:assert";
|
|
2
|
+
import { describe, test } from "node:test";
|
|
3
|
+
import child from "../../src/operations/child.js";
|
|
4
|
+
|
|
5
|
+
describe("child", () => {
|
|
6
|
+
test("defers to map.child() if available", async () => {
|
|
7
|
+
class CustomMap extends Map {
|
|
8
|
+
child(key) {
|
|
9
|
+
return `child-${key}`;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
parent = null;
|
|
13
|
+
trailingSlashKeys = false;
|
|
14
|
+
}
|
|
15
|
+
const map = new CustomMap();
|
|
16
|
+
const result = await child(map, "test");
|
|
17
|
+
assert.strictEqual(result, "child-test");
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
test("returns existing subtree if present", async () => {
|
|
21
|
+
const subtree = new Map();
|
|
22
|
+
const map = new Map([["sub", subtree]]);
|
|
23
|
+
const result = await child(map, "sub");
|
|
24
|
+
assert.strictEqual(result, subtree);
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
test("creates new subtree if not present", async () => {
|
|
28
|
+
const map = new Map();
|
|
29
|
+
const result = await child(map, "sub");
|
|
30
|
+
assert.ok(result instanceof Map);
|
|
31
|
+
const stored = await map.get("sub");
|
|
32
|
+
assert.strictEqual(stored, result);
|
|
33
|
+
});
|
|
34
|
+
});
|
|
@@ -1,34 +1,13 @@
|
|
|
1
1
|
import assert from "node:assert";
|
|
2
|
-
import * as fs from "node:fs/promises";
|
|
3
|
-
import path from "node:path";
|
|
4
2
|
import { describe, test } from "node:test";
|
|
5
|
-
import
|
|
6
|
-
import
|
|
7
|
-
import
|
|
8
|
-
|
|
9
|
-
const dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
10
|
-
const tempDirectory = path.join(dirname, "fixtures/temp");
|
|
3
|
+
import ObjectMap from "../../src/drivers/ObjectMap.js";
|
|
4
|
+
import clear from "../../src/operations/clear.js";
|
|
5
|
+
import plain from "../../src/operations/plain.js";
|
|
11
6
|
|
|
12
7
|
describe("clear", () => {
|
|
13
8
|
test("unsets all public keys in an object tree", async () => {
|
|
14
|
-
const tree = new
|
|
15
|
-
await
|
|
16
|
-
assert.deepEqual(await
|
|
17
|
-
});
|
|
18
|
-
|
|
19
|
-
test("unsets all public keys in a file tree", async () => {
|
|
20
|
-
// Create a temp directory with some files
|
|
21
|
-
await fs.mkdir(tempDirectory, { recursive: true });
|
|
22
|
-
await fs.writeFile(path.join(tempDirectory, "a"), "1");
|
|
23
|
-
await fs.writeFile(path.join(tempDirectory, "b"), "2");
|
|
24
|
-
|
|
25
|
-
const tree = new FileTree(tempDirectory);
|
|
26
|
-
await Tree.clear(tree);
|
|
27
|
-
|
|
28
|
-
const files = await fs.readdir(tempDirectory);
|
|
29
|
-
assert.deepEqual(files, []);
|
|
30
|
-
|
|
31
|
-
// Remove temp directory
|
|
32
|
-
await fs.rm(tempDirectory, { recursive: true });
|
|
9
|
+
const tree = new ObjectMap({ a: 1, b: 2, c: 3 });
|
|
10
|
+
await clear(tree);
|
|
11
|
+
assert.deepEqual(await plain(tree), {});
|
|
33
12
|
});
|
|
34
13
|
});
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import assert from "node:assert";
|
|
2
|
+
import { describe, test } from "node:test";
|
|
3
|
+
import deepEntries from "../../src/operations/deepEntries.js";
|
|
4
|
+
import SampleAsyncMap from "../SampleAsyncMap.js";
|
|
5
|
+
|
|
6
|
+
describe("deepEntries", () => {
|
|
7
|
+
test("converts an async tree to an array of nested entries arrays", async () => {
|
|
8
|
+
const fixture = new SampleAsyncMap([
|
|
9
|
+
["a", 1],
|
|
10
|
+
["b", 2],
|
|
11
|
+
[
|
|
12
|
+
"more",
|
|
13
|
+
[
|
|
14
|
+
["c", 3],
|
|
15
|
+
["d", 4],
|
|
16
|
+
],
|
|
17
|
+
],
|
|
18
|
+
]);
|
|
19
|
+
const result = await deepEntries(fixture);
|
|
20
|
+
assert.deepStrictEqual(result, [
|
|
21
|
+
["a", 1],
|
|
22
|
+
["b", 2],
|
|
23
|
+
[
|
|
24
|
+
"more",
|
|
25
|
+
[
|
|
26
|
+
["c", 3],
|
|
27
|
+
["d", 4],
|
|
28
|
+
],
|
|
29
|
+
],
|
|
30
|
+
]);
|
|
31
|
+
});
|
|
32
|
+
});
|