@weborigami/async-tree 0.6.0 → 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.
Files changed (51) hide show
  1. package/index.ts +13 -1
  2. package/package.json +1 -1
  3. package/shared.js +13 -16
  4. package/src/Tree.js +3 -0
  5. package/src/drivers/AsyncMap.js +30 -3
  6. package/src/drivers/BrowserFileMap.js +30 -23
  7. package/src/drivers/CalendarMap.js +0 -2
  8. package/src/drivers/ConstantMap.js +1 -3
  9. package/src/drivers/FileMap.js +50 -57
  10. package/src/drivers/ObjectMap.js +22 -10
  11. package/src/drivers/SiteMap.js +4 -6
  12. package/src/drivers/SyncMap.js +22 -7
  13. package/src/jsonKeys.js +15 -1
  14. package/src/operations/assign.js +7 -12
  15. package/src/operations/cache.js +2 -2
  16. package/src/operations/child.js +35 -0
  17. package/src/operations/from.js +5 -6
  18. package/src/operations/isMaplike.js +1 -1
  19. package/src/operations/map.js +1 -0
  20. package/src/operations/mapReduce.js +28 -19
  21. package/src/operations/mask.js +34 -18
  22. package/src/operations/paths.js +14 -16
  23. package/src/operations/reduce.js +16 -0
  24. package/src/operations/set.js +20 -0
  25. package/src/operations/sync.js +2 -9
  26. package/src/operations/traverseOrThrow.js +5 -0
  27. package/src/utilities/castArraylike.js +23 -20
  28. package/src/utilities/toPlainValue.js +6 -8
  29. package/test/browser/index.html +0 -1
  30. package/test/drivers/BrowserFileMap.test.js +21 -23
  31. package/test/drivers/FileMap.test.js +2 -31
  32. package/test/drivers/ObjectMap.test.js +28 -0
  33. package/test/drivers/SyncMap.test.js +19 -5
  34. package/test/jsonKeys.test.js +18 -6
  35. package/test/operations/cache.test.js +11 -8
  36. package/test/operations/cachedKeyFunctions.test.js +8 -6
  37. package/test/operations/child.test.js +34 -0
  38. package/test/operations/deepMerge.test.js +20 -14
  39. package/test/operations/from.test.js +6 -4
  40. package/test/operations/inners.test.js +15 -12
  41. package/test/operations/map.test.js +24 -16
  42. package/test/operations/mapReduce.test.js +14 -12
  43. package/test/operations/mask.test.js +12 -0
  44. package/test/operations/merge.test.js +7 -5
  45. package/test/operations/paths.test.js +20 -27
  46. package/test/operations/regExpKeys.test.js +12 -9
  47. package/test/operations/set.test.js +11 -0
  48. package/test/operations/traverse.test.js +13 -0
  49. package/test/utilities/castArrayLike.test.js +53 -0
  50. package/src/drivers/DeepObjectMap.js +0 -27
  51. package/test/drivers/DeepObjectMap.test.js +0 -36
@@ -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 set() with EMPTY", () => {
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.set("empty", FileMap.EMPTY);
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("set with EMPTY value creates empty subtree", () => {
220
+ test("child creates new map when not present", () => {
221
+ // Create child when not present
221
222
  const map = new SyncMap();
222
- map.set("subtree", SyncMap.EMPTY);
223
- const subtree = map.get("subtree");
224
- assert(subtree instanceof SyncMap);
225
- assert.strictEqual(subtree.size, 0);
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", () => {
@@ -1,14 +1,26 @@
1
1
  import assert from "node:assert";
2
2
  import { describe, test } from "node:test";
3
- import DeepObjectMap from "../src/drivers/DeepObjectMap.js";
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("stringifies JSON Keys", async () => {
8
- const tree = new DeepObjectMap({
9
- about: {},
10
- "index.html": "Home",
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 DeepObjectMap from "../../src/drivers/DeepObjectMap.js";
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 DeepObjectMap({
13
- a: 1,
14
- b: 2,
15
- c: 3,
16
- more: {
17
- d: 4,
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 DeepObjectMap({
46
- a: "letter a",
47
- b: {
48
- c: "letter c",
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 DeepObjectMap from "../../src/drivers/DeepObjectMap.js";
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 DeepObjectMap({
11
- a: {
12
- b: 0, // Will be obscured by `b` below
13
- c: {
14
- d: 2,
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
- new DeepObjectMap({
19
- a: {
20
- b: 1,
21
- c: {
22
- e: 3,
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 DeepObjectMap from "../../src/drivers/DeepObjectMap.js";
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 DeepObjectMap);
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 DeepObjectMap);
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.only("returns an array for an Iterator", async () => {
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 DeepObjectMap from "../../src/drivers/DeepObjectMap.js";
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 DeepObjectMap({
10
- a: 1,
11
- b: {
12
- c: 2,
13
- d: {
14
- e: 3,
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
- f: 4,
18
- g: {
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 DeepObjectMap({
136
- a: "letter a",
137
- more: {
138
- b: "letter b",
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 DeepObjectMap({
155
- a: "letter a",
156
- more: {
157
- b: "letter b",
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 DeepObjectMap({
175
- a: "letter a",
176
- more: {
177
- b: "letter b",
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 DeepObjectMap from "../../src/drivers/DeepObjectMap.js";
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 DeepObjectMap({
9
- a: 1,
10
- b: 2,
11
- more: {
12
- c: 3,
9
+ const tree = new ObjectMap(
10
+ {
11
+ a: 1,
12
+ b: 2,
13
+ more: {
14
+ c: 3,
15
+ },
16
+ d: 4,
13
17
  },
14
- d: 4,
15
- });
16
- const reduced = await mapReduce(
17
- tree,
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 DeepObjectMap({
51
- a: {
52
- b: 2,
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 DeepObjectMap({
10
- a: 1,
11
- b: 2,
12
- c: {
13
- d: 3,
14
- e: 4,
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("can focus just on keys with trailing slashes", async () => {
21
- const tree = new ObjectMap({
22
- a: 1,
23
- b: 2,
24
- // This is a shallow ObjectMap, so `c` won't have a trailing slash
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/": new ObjectMap({
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
  });
@@ -1,21 +1,24 @@
1
1
  import assert from "node:assert";
2
2
  import { describe, test } from "node:test";
3
- import DeepObjectMap from "../../src/drivers/DeepObjectMap.js";
3
+ import ObjectMap from "../../src/drivers/ObjectMap.js";
4
4
  import regExpKeys from "../../src/operations/regExpKeys.js";
5
5
  import traverse from "../../src/operations/traverse.js";
6
6
 
7
7
  describe("regExpKeys", () => {
8
8
  test("matches keys using regular expressions", async () => {
9
9
  const fixture = await regExpKeys(
10
- new DeepObjectMap({
11
- "^a$": true,
12
- "^b.*": true,
13
- c: {
14
- d: true,
15
- "e*": true,
10
+ new ObjectMap(
11
+ {
12
+ "^a$": true,
13
+ "^b.*": true,
14
+ c: {
15
+ d: true,
16
+ "e*": true,
17
+ },
18
+ f: true,
16
19
  },
17
- f: true,
18
- })
20
+ { deep: true }
21
+ )
19
22
  );
20
23
  assert(await traverse(fixture, "a"));
21
24
  assert(!(await traverse(fixture, "alice")));
@@ -0,0 +1,11 @@
1
+ import assert from "node:assert";
2
+ import { describe, test } from "node:test";
3
+ import set from "../../src/operations/set.js";
4
+
5
+ describe("set", () => {
6
+ test("sets a value", async () => {
7
+ const map = new Map();
8
+ await set(map, "key", "value");
9
+ assert.strictEqual(map.get("key"), "value");
10
+ });
11
+ });
@@ -39,4 +39,17 @@ describe("traverse", () => {
39
39
  });
40
40
  assert.equal(await traverse(tree, "a", "b", "c"), "Hello");
41
41
  });
42
+
43
+ test("unpacks last value if key ends in a slash", async () => {
44
+ const tree = new ObjectMap({
45
+ a: {
46
+ b: Object.assign(new String("packed"), {
47
+ unpack() {
48
+ return "unpacked";
49
+ },
50
+ }),
51
+ },
52
+ });
53
+ assert.equal(await traverse(tree, "a/", "b/"), "unpacked");
54
+ });
42
55
  });