@weborigami/async-tree 0.6.0 → 0.6.2
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.ts +13 -1
- package/package.json +1 -1
- package/shared.js +13 -16
- package/src/Tree.js +3 -0
- package/src/drivers/AsyncMap.js +30 -3
- package/src/drivers/BrowserFileMap.js +30 -23
- package/src/drivers/CalendarMap.js +0 -2
- package/src/drivers/ConstantMap.js +1 -3
- package/src/drivers/ExplorableSiteMap.js +2 -0
- package/src/drivers/FileMap.js +50 -57
- package/src/drivers/ObjectMap.js +22 -10
- package/src/drivers/SiteMap.js +4 -6
- package/src/drivers/SyncMap.js +22 -7
- package/src/jsonKeys.js +15 -1
- package/src/operations/assign.js +7 -12
- package/src/operations/cache.js +2 -2
- package/src/operations/child.js +35 -0
- package/src/operations/from.js +5 -6
- package/src/operations/globKeys.js +2 -3
- package/src/operations/isMaplike.js +1 -1
- package/src/operations/map.js +22 -3
- package/src/operations/mapReduce.js +28 -19
- package/src/operations/mask.js +34 -18
- package/src/operations/paths.js +14 -16
- package/src/operations/reduce.js +16 -0
- package/src/operations/root.js +2 -2
- package/src/operations/set.js +20 -0
- package/src/operations/sync.js +2 -9
- package/src/operations/traverseOrThrow.js +5 -0
- package/src/utilities/castArraylike.js +23 -20
- package/src/utilities/toPlainValue.js +6 -8
- package/test/browser/index.html +0 -1
- package/test/drivers/BrowserFileMap.test.js +21 -23
- package/test/drivers/FileMap.test.js +2 -31
- package/test/drivers/ObjectMap.test.js +28 -0
- package/test/drivers/SyncMap.test.js +19 -5
- package/test/jsonKeys.test.js +18 -6
- package/test/operations/cache.test.js +11 -8
- package/test/operations/cachedKeyFunctions.test.js +8 -6
- package/test/operations/child.test.js +34 -0
- package/test/operations/deepMerge.test.js +20 -14
- package/test/operations/from.test.js +6 -4
- package/test/operations/inners.test.js +15 -12
- package/test/operations/map.test.js +24 -16
- package/test/operations/mapReduce.test.js +14 -12
- package/test/operations/mask.test.js +12 -0
- package/test/operations/merge.test.js +7 -5
- package/test/operations/paths.test.js +20 -27
- package/test/operations/regExpKeys.test.js +12 -9
- package/test/operations/root.test.js +23 -0
- package/test/operations/set.test.js +11 -0
- package/test/operations/traverse.test.js +13 -0
- package/test/utilities/castArrayLike.test.js +53 -0
- package/src/drivers/DeepObjectMap.js +0 -27
- package/test/drivers/DeepObjectMap.test.js +0 -36
|
@@ -95,31 +95,29 @@ if (isBrowser) {
|
|
|
95
95
|
});
|
|
96
96
|
});
|
|
97
97
|
|
|
98
|
-
test("can create
|
|
98
|
+
test("can return or create a subfolder via child", async () => {
|
|
99
99
|
const fixture = await createFixture();
|
|
100
|
-
await fixture.set("emptyFolder", BrowserFileMap.EMPTY);
|
|
101
|
-
assert.deepEqual(await strings(fixture), {
|
|
102
|
-
"Alice.md": "Hello, **Alice**.",
|
|
103
|
-
"Bob.md": "Hello, **Bob**.",
|
|
104
|
-
"Carol.md": "Hello, **Carol**.",
|
|
105
|
-
emptyFolder: {},
|
|
106
|
-
subfolder: {},
|
|
107
|
-
});
|
|
108
|
-
});
|
|
109
100
|
|
|
110
|
-
|
|
111
|
-
const
|
|
112
|
-
const
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
101
|
+
// Return existing subfolder
|
|
102
|
+
const subfolder = await fixture.get("subfolder");
|
|
103
|
+
const child = await fixture.child("subfolder");
|
|
104
|
+
assert.equal(child, subfolder);
|
|
105
|
+
|
|
106
|
+
// Create new subfolder
|
|
107
|
+
const newChild = await fixture.child("newSubfolder");
|
|
108
|
+
assert.equal(newChild, subfolder);
|
|
109
|
+
|
|
110
|
+
// Replace existing file with folder
|
|
111
|
+
const replacedChild = await fixture.child("Alice.md");
|
|
112
|
+
assert.equal(replacedChild.parent, fixture);
|
|
113
|
+
|
|
114
|
+
assert.deepEqual(await keys(fixture), [
|
|
115
|
+
"Alice.md/",
|
|
116
|
+
"Bob.md",
|
|
117
|
+
"Carol.md",
|
|
118
|
+
"subfolder/",
|
|
119
|
+
"newSubfolder/",
|
|
120
|
+
]);
|
|
123
121
|
});
|
|
124
122
|
});
|
|
125
123
|
}
|
|
@@ -4,8 +4,6 @@ import path from "node:path";
|
|
|
4
4
|
import { describe, test } from "node:test";
|
|
5
5
|
import { fileURLToPath } from "node:url";
|
|
6
6
|
import FileMap from "../../src/drivers/FileMap.js";
|
|
7
|
-
import map from "../../src/operations/map.js";
|
|
8
|
-
import plain from "../../src/operations/plain.js";
|
|
9
7
|
|
|
10
8
|
const dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
11
9
|
const tempDirectory = path.join(dirname, "fixtures/temp");
|
|
@@ -82,12 +80,12 @@ describe("FileMap", () => {
|
|
|
82
80
|
removeTempDirectory();
|
|
83
81
|
});
|
|
84
82
|
|
|
85
|
-
test("create subfolder via
|
|
83
|
+
test("create subfolder via child()", () => {
|
|
86
84
|
createTempDirectory();
|
|
87
85
|
|
|
88
86
|
// Write out new, empty folder called "empty".
|
|
89
87
|
const tempFiles = new FileMap(tempDirectory);
|
|
90
|
-
tempFiles.
|
|
88
|
+
tempFiles.child("empty");
|
|
91
89
|
|
|
92
90
|
// Verify folder exists and has no contents.
|
|
93
91
|
const folderPath = path.join(tempDirectory, "empty");
|
|
@@ -99,33 +97,6 @@ describe("FileMap", () => {
|
|
|
99
97
|
removeTempDirectory();
|
|
100
98
|
});
|
|
101
99
|
|
|
102
|
-
test("can write out subfolder via set()", async () => {
|
|
103
|
-
createTempDirectory();
|
|
104
|
-
|
|
105
|
-
// Create a tiny set of "files".
|
|
106
|
-
// @ts-ignore
|
|
107
|
-
const files = new Map([
|
|
108
|
-
["file1", "This is the first file."],
|
|
109
|
-
["subfolder", new Map([["file2", "This is the second file."]])],
|
|
110
|
-
]);
|
|
111
|
-
const object = await plain(files);
|
|
112
|
-
|
|
113
|
-
// Write out files as a new folder called "folder".
|
|
114
|
-
const tempFiles = new FileMap(tempDirectory);
|
|
115
|
-
tempFiles.set("folder", files);
|
|
116
|
-
|
|
117
|
-
// Read them back in.
|
|
118
|
-
const actualFiles = tempFiles.get("folder");
|
|
119
|
-
const strings = await map(actualFiles, {
|
|
120
|
-
deep: true,
|
|
121
|
-
value: (buffer) => textDecoder.decode(buffer),
|
|
122
|
-
});
|
|
123
|
-
const result = await plain(strings);
|
|
124
|
-
assert.deepEqual(result, object);
|
|
125
|
-
|
|
126
|
-
removeTempDirectory();
|
|
127
|
-
});
|
|
128
|
-
|
|
129
100
|
test("can delete a file", () => {
|
|
130
101
|
createTempDirectory();
|
|
131
102
|
const tempFile = path.join(tempDirectory, "file");
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import assert from "node:assert";
|
|
2
2
|
import { describe, test } from "node:test";
|
|
3
3
|
import ObjectMap from "../../src/drivers/ObjectMap.js";
|
|
4
|
+
import plain from "../../src/operations/plain.js";
|
|
4
5
|
import * as symbols from "../../src/symbols.js";
|
|
5
6
|
|
|
6
7
|
describe("ObjectMap", () => {
|
|
@@ -155,6 +156,33 @@ describe("ObjectMap", () => {
|
|
|
155
156
|
});
|
|
156
157
|
assert.deepEqual(Array.from(map.keys()), ["a", "b", "c"]);
|
|
157
158
|
});
|
|
159
|
+
|
|
160
|
+
test("deep option treats sub-objects and sub-arrays as child nodes", async () => {
|
|
161
|
+
const map = new ObjectMap(
|
|
162
|
+
{
|
|
163
|
+
a: 1,
|
|
164
|
+
object: {
|
|
165
|
+
b: 2,
|
|
166
|
+
},
|
|
167
|
+
array: [3],
|
|
168
|
+
},
|
|
169
|
+
{ deep: true }
|
|
170
|
+
);
|
|
171
|
+
|
|
172
|
+
// Adds trailing slashes to keys for sub-objects and sub-arrays
|
|
173
|
+
const keys = Array.from(await map.keys());
|
|
174
|
+
assert.deepEqual(keys, ["a", "object/", "array/"]);
|
|
175
|
+
|
|
176
|
+
const object = await map.get("object");
|
|
177
|
+
assert.equal(object instanceof ObjectMap, true);
|
|
178
|
+
assert.deepEqual(await plain(object), { b: 2 });
|
|
179
|
+
assert.equal(object.parent, map);
|
|
180
|
+
|
|
181
|
+
const array = await map.get("array");
|
|
182
|
+
assert.equal(array instanceof ObjectMap, true);
|
|
183
|
+
assert.deepEqual(await plain(array), [3]);
|
|
184
|
+
assert.equal(array.parent, map);
|
|
185
|
+
});
|
|
158
186
|
});
|
|
159
187
|
|
|
160
188
|
function createFixture() {
|
|
@@ -217,12 +217,26 @@ describe("SyncMap", () => {
|
|
|
217
217
|
assert.strictEqual(map.get("b"), 3);
|
|
218
218
|
});
|
|
219
219
|
|
|
220
|
-
test("
|
|
220
|
+
test("child creates new map when not present", () => {
|
|
221
|
+
// Create child when not present
|
|
221
222
|
const map = new SyncMap();
|
|
222
|
-
map.
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
assert.strictEqual(
|
|
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);
|
|
226
240
|
});
|
|
227
241
|
|
|
228
242
|
test("set on read-only map throws", () => {
|
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,6 @@
|
|
|
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 SyncMap from "../../src/drivers/SyncMap.js";
|
|
5
5
|
import cache from "../../src/operations/cache.js";
|
|
6
6
|
import keys from "../../src/operations/keys.js";
|
|
@@ -9,14 +9,17 @@ describe("cache", () => {
|
|
|
9
9
|
test("caches reads of values from one tree into another", async () => {
|
|
10
10
|
const objectCache = new SyncMap();
|
|
11
11
|
const fixture = await cache(
|
|
12
|
-
new
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
12
|
+
new ObjectMap(
|
|
13
|
+
{
|
|
14
|
+
a: 1,
|
|
15
|
+
b: 2,
|
|
16
|
+
c: 3,
|
|
17
|
+
more: {
|
|
18
|
+
d: 4,
|
|
19
|
+
},
|
|
18
20
|
},
|
|
19
|
-
|
|
21
|
+
{ deep: true }
|
|
22
|
+
),
|
|
20
23
|
objectCache
|
|
21
24
|
);
|
|
22
25
|
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import assert from "node:assert";
|
|
2
2
|
import { describe, test } from "node:test";
|
|
3
|
-
import DeepObjectMap from "../../src/drivers/DeepObjectMap.js";
|
|
4
3
|
import ObjectMap from "../../src/drivers/ObjectMap.js";
|
|
5
4
|
import cachedKeyFunctions from "../../src/operations/cachedKeyFunctions.js";
|
|
6
5
|
import * as trailingSlash from "../../src/trailingSlash.js";
|
|
@@ -42,12 +41,15 @@ describe("cachedKeyFunctions", () => {
|
|
|
42
41
|
});
|
|
43
42
|
|
|
44
43
|
test("maps keys with caching and deep option", async () => {
|
|
45
|
-
const tree = new
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
44
|
+
const tree = new ObjectMap(
|
|
45
|
+
{
|
|
46
|
+
a: "letter a",
|
|
47
|
+
b: {
|
|
48
|
+
c: "letter c",
|
|
49
|
+
},
|
|
49
50
|
},
|
|
50
|
-
|
|
51
|
+
{ deep: true }
|
|
52
|
+
);
|
|
51
53
|
|
|
52
54
|
let callCount = 0;
|
|
53
55
|
const addUnderscore = async (sourceValue, sourceKey, tree) => {
|
|
@@ -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,29 +1,35 @@
|
|
|
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 deepMerge from "../../src/operations/deepMerge.js";
|
|
5
5
|
import plain from "../../src/operations/plain.js";
|
|
6
6
|
|
|
7
7
|
describe("mergeDeep", () => {
|
|
8
8
|
test("can merge deep", async () => {
|
|
9
9
|
const fixture = await deepMerge(
|
|
10
|
-
new
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
10
|
+
new ObjectMap(
|
|
11
|
+
{
|
|
12
|
+
a: {
|
|
13
|
+
b: 0, // Will be obscured by `b` below
|
|
14
|
+
c: {
|
|
15
|
+
d: 2,
|
|
16
|
+
},
|
|
15
17
|
},
|
|
16
18
|
},
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
19
|
+
{ deep: true }
|
|
20
|
+
),
|
|
21
|
+
new ObjectMap(
|
|
22
|
+
{
|
|
23
|
+
a: {
|
|
24
|
+
b: 1,
|
|
25
|
+
c: {
|
|
26
|
+
e: 3,
|
|
27
|
+
},
|
|
28
|
+
f: 4,
|
|
23
29
|
},
|
|
24
|
-
f: 4,
|
|
25
30
|
},
|
|
26
|
-
|
|
31
|
+
{ deep: true }
|
|
32
|
+
)
|
|
27
33
|
);
|
|
28
34
|
assert.deepEqual(await plain(fixture), {
|
|
29
35
|
a: {
|
|
@@ -1,6 +1,6 @@
|
|
|
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 SetMap from "../../src/drivers/SetMap.js";
|
|
5
5
|
import from from "../../src/operations/from.js";
|
|
6
6
|
import values from "../../src/operations/values.js";
|
|
@@ -23,7 +23,8 @@ describe("from", () => {
|
|
|
23
23
|
},
|
|
24
24
|
};
|
|
25
25
|
const tree = from(obj, { deep: true });
|
|
26
|
-
assert(tree instanceof
|
|
26
|
+
assert(tree instanceof ObjectMap);
|
|
27
|
+
assert(tree.deep);
|
|
27
28
|
});
|
|
28
29
|
|
|
29
30
|
test("returns a deep object map if object has [deep] symbol set", async () => {
|
|
@@ -34,7 +35,8 @@ describe("from", () => {
|
|
|
34
35
|
};
|
|
35
36
|
Object.defineProperty(obj, symbols.deep, { value: true });
|
|
36
37
|
const tree = from(obj);
|
|
37
|
-
assert(tree instanceof
|
|
38
|
+
assert(tree instanceof ObjectMap);
|
|
39
|
+
assert(tree.deep);
|
|
38
40
|
});
|
|
39
41
|
|
|
40
42
|
test("returns a SetMap for Set objects", async () => {
|
|
@@ -44,7 +46,7 @@ describe("from", () => {
|
|
|
44
46
|
assert.deepEqual(await values(map), ["a", "b", "c"]);
|
|
45
47
|
});
|
|
46
48
|
|
|
47
|
-
test
|
|
49
|
+
test("returns an array for an Iterator", async () => {
|
|
48
50
|
const set = new Set(["a", "b", "c"]);
|
|
49
51
|
const map = from(set.values());
|
|
50
52
|
assert.deepEqual(await values(map), ["a", "b", "c"]);
|
|
@@ -1,24 +1,27 @@
|
|
|
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 inners from "../../src/operations/inners.js";
|
|
5
5
|
import plain from "../../src/operations/plain.js";
|
|
6
6
|
|
|
7
7
|
describe("inners", () => {
|
|
8
8
|
test("returns the interior nodes of a tree", async () => {
|
|
9
|
-
const obj = new
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
9
|
+
const obj = new ObjectMap(
|
|
10
|
+
{
|
|
11
|
+
a: 1,
|
|
12
|
+
b: {
|
|
13
|
+
c: 2,
|
|
14
|
+
d: {
|
|
15
|
+
e: 3,
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
f: 4,
|
|
19
|
+
g: {
|
|
20
|
+
h: 5,
|
|
15
21
|
},
|
|
16
22
|
},
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
h: 5,
|
|
20
|
-
},
|
|
21
|
-
});
|
|
23
|
+
{ deep: true }
|
|
24
|
+
);
|
|
22
25
|
const result = await inners(obj);
|
|
23
26
|
assert.deepEqual(await plain(result), {
|
|
24
27
|
b: {
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import assert from "node:assert";
|
|
2
2
|
import { describe, test } from "node:test";
|
|
3
|
-
import DeepObjectMap from "../../src/drivers/DeepObjectMap.js";
|
|
4
3
|
import ObjectMap from "../../src/drivers/ObjectMap.js";
|
|
5
4
|
import map from "../../src/operations/map.js";
|
|
6
5
|
import plain from "../../src/operations/plain.js";
|
|
@@ -132,12 +131,15 @@ describe("map", () => {
|
|
|
132
131
|
});
|
|
133
132
|
|
|
134
133
|
test("deep maps values", async () => {
|
|
135
|
-
const tree = new
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
134
|
+
const tree = new ObjectMap(
|
|
135
|
+
{
|
|
136
|
+
a: "letter a",
|
|
137
|
+
more: {
|
|
138
|
+
b: "letter b",
|
|
139
|
+
},
|
|
139
140
|
},
|
|
140
|
-
|
|
141
|
+
{ deep: true }
|
|
142
|
+
);
|
|
141
143
|
const uppercaseValues = await map(tree, {
|
|
142
144
|
deep: true,
|
|
143
145
|
value: (sourceValue, sourceKey, tree) => sourceValue.toUpperCase(),
|
|
@@ -151,12 +153,15 @@ describe("map", () => {
|
|
|
151
153
|
});
|
|
152
154
|
|
|
153
155
|
test("deep maps leaf keys", async () => {
|
|
154
|
-
const tree = new
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
156
|
+
const tree = new ObjectMap(
|
|
157
|
+
{
|
|
158
|
+
a: "letter a",
|
|
159
|
+
more: {
|
|
160
|
+
b: "letter b",
|
|
161
|
+
},
|
|
158
162
|
},
|
|
159
|
-
|
|
163
|
+
{ deep: true }
|
|
164
|
+
);
|
|
160
165
|
const underscoreKeys = await map(tree, {
|
|
161
166
|
deep: true,
|
|
162
167
|
key: addUnderscore,
|
|
@@ -171,12 +176,15 @@ describe("map", () => {
|
|
|
171
176
|
});
|
|
172
177
|
|
|
173
178
|
test("deep maps leaf keys and values", async () => {
|
|
174
|
-
const tree = new
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
179
|
+
const tree = new ObjectMap(
|
|
180
|
+
{
|
|
181
|
+
a: "letter a",
|
|
182
|
+
more: {
|
|
183
|
+
b: "letter b",
|
|
184
|
+
},
|
|
178
185
|
},
|
|
179
|
-
|
|
186
|
+
{ deep: true }
|
|
187
|
+
);
|
|
180
188
|
const underscoreKeysUppercaseValues = await map(tree, {
|
|
181
189
|
deep: true,
|
|
182
190
|
key: addUnderscore,
|
|
@@ -1,22 +1,24 @@
|
|
|
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 mapReduce from "../../src/operations/mapReduce.js";
|
|
5
|
+
import values from "../../src/operations/values.js";
|
|
5
6
|
|
|
6
7
|
describe("mapReduce", () => {
|
|
7
8
|
test("can map values and reduce them", async () => {
|
|
8
|
-
const tree = new
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
const tree = new ObjectMap(
|
|
10
|
+
{
|
|
11
|
+
a: 1,
|
|
12
|
+
b: 2,
|
|
13
|
+
more: {
|
|
14
|
+
c: 3,
|
|
15
|
+
},
|
|
16
|
+
d: 4,
|
|
13
17
|
},
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
const reduced = await mapReduce(
|
|
17
|
-
|
|
18
|
-
(value) => value,
|
|
19
|
-
async (values) => String.prototype.concat(...values)
|
|
18
|
+
{ deep: true }
|
|
19
|
+
);
|
|
20
|
+
const reduced = await mapReduce(tree, null, async (mapped) =>
|
|
21
|
+
String.prototype.concat(...(await values(mapped)))
|
|
20
22
|
);
|
|
21
23
|
assert.deepEqual(reduced, "1234");
|
|
22
24
|
});
|
|
@@ -30,4 +30,16 @@ describe("mask", () => {
|
|
|
30
30
|
},
|
|
31
31
|
});
|
|
32
32
|
});
|
|
33
|
+
|
|
34
|
+
test("can pull from a functional map", async () => {
|
|
35
|
+
const result = await mask((key) => key.toUpperCase(), {
|
|
36
|
+
a: true,
|
|
37
|
+
b: false,
|
|
38
|
+
c: true,
|
|
39
|
+
});
|
|
40
|
+
assert.deepEqual(await plain(result), {
|
|
41
|
+
a: "A",
|
|
42
|
+
c: "C",
|
|
43
|
+
});
|
|
44
|
+
});
|
|
33
45
|
});
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import assert from "node:assert";
|
|
2
2
|
import { describe, test } from "node:test";
|
|
3
|
-
import DeepObjectMap from "../../src/drivers/DeepObjectMap.js";
|
|
4
3
|
import ObjectMap from "../../src/drivers/ObjectMap.js";
|
|
5
4
|
import keys from "../../src/operations/keys.js";
|
|
6
5
|
import merge from "../../src/operations/merge.js";
|
|
@@ -47,11 +46,14 @@ describe("merge", () => {
|
|
|
47
46
|
new ObjectMap({
|
|
48
47
|
a: 1,
|
|
49
48
|
}),
|
|
50
|
-
new
|
|
51
|
-
|
|
52
|
-
|
|
49
|
+
new ObjectMap(
|
|
50
|
+
{
|
|
51
|
+
a: {
|
|
52
|
+
b: 2,
|
|
53
|
+
},
|
|
53
54
|
},
|
|
54
|
-
|
|
55
|
+
{ deep: true }
|
|
56
|
+
)
|
|
55
57
|
);
|
|
56
58
|
assert.deepEqual(await keys(fixture), ["a/"]);
|
|
57
59
|
assert.deepEqual(await plain(fixture), {
|
|
@@ -1,40 +1,33 @@
|
|
|
1
1
|
import assert from "node:assert";
|
|
2
2
|
import { describe, test } from "node:test";
|
|
3
|
-
import DeepObjectMap from "../../src/drivers/DeepObjectMap.js";
|
|
4
|
-
import ObjectMap from "../../src/drivers/ObjectMap.js";
|
|
5
3
|
import paths from "../../src/operations/paths.js";
|
|
6
4
|
|
|
7
5
|
describe("paths", () => {
|
|
8
6
|
test("returns an array of paths to the values in the tree", async () => {
|
|
9
|
-
const tree = new
|
|
10
|
-
a
|
|
11
|
-
b
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
7
|
+
const tree = new /** @type {any} */ (Map)([
|
|
8
|
+
["a", 1],
|
|
9
|
+
["b", 2],
|
|
10
|
+
[
|
|
11
|
+
"c",
|
|
12
|
+
new Map([
|
|
13
|
+
["d", 3],
|
|
14
|
+
["e", 4],
|
|
15
|
+
]),
|
|
16
|
+
],
|
|
17
|
+
]);
|
|
17
18
|
assert.deepEqual(await paths(tree), ["a", "b", "c/d", "c/e"]);
|
|
18
19
|
});
|
|
19
20
|
|
|
20
|
-
test("
|
|
21
|
-
const tree = new
|
|
22
|
-
a
|
|
23
|
-
b
|
|
24
|
-
//
|
|
25
|
-
c
|
|
26
|
-
d: 3,
|
|
27
|
-
},
|
|
21
|
+
test("focuses only on trailing slashes if map supports them", async () => {
|
|
22
|
+
const tree = new /** @type {any} */ (Map)([
|
|
23
|
+
["a", 1],
|
|
24
|
+
["b", 2],
|
|
25
|
+
// No trailing slash; paths will skip this subtree
|
|
26
|
+
["c", new Map([["d", 3]])],
|
|
28
27
|
// Explicitly include a trailing slash to signal a subtree
|
|
29
|
-
"d/"
|
|
30
|
-
e: 4,
|
|
31
|
-
}),
|
|
32
|
-
});
|
|
33
|
-
assert.deepEqual(await paths(tree, { assumeSlashes: true }), [
|
|
34
|
-
"a",
|
|
35
|
-
"b",
|
|
36
|
-
"c",
|
|
37
|
-
"d/e",
|
|
28
|
+
["d/", new Map([["e", 4]])],
|
|
38
29
|
]);
|
|
30
|
+
tree.trailingSlashKeys = true;
|
|
31
|
+
assert.deepEqual(await paths(tree), ["a", "b", "c", "d/e"]);
|
|
39
32
|
});
|
|
40
33
|
});
|