@weborigami/async-tree 0.5.4 → 0.5.5

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 (158) hide show
  1. package/index.ts +16 -6
  2. package/package.json +2 -2
  3. package/shared.js +20 -30
  4. package/src/Tree.js +62 -513
  5. package/src/constants.js +2 -0
  6. package/src/drivers/BrowserFileTree.js +9 -10
  7. package/src/drivers/DeepMapTree.js +3 -3
  8. package/src/drivers/DeepObjectTree.js +4 -5
  9. package/src/drivers/DeferredTree.js +2 -2
  10. package/src/drivers/FileTree.js +11 -33
  11. package/src/drivers/FunctionTree.js +1 -1
  12. package/src/drivers/MapTree.js +6 -6
  13. package/src/drivers/ObjectTree.js +4 -3
  14. package/src/drivers/SetTree.js +1 -1
  15. package/src/drivers/SiteTree.js +1 -1
  16. package/src/drivers/constantTree.js +1 -1
  17. package/src/extension.js +5 -3
  18. package/src/jsonKeys.js +5 -7
  19. package/src/operations/addNextPrevious.js +10 -9
  20. package/src/operations/assign.js +40 -0
  21. package/src/operations/cache.js +18 -12
  22. package/src/operations/cachedKeyFunctions.js +15 -4
  23. package/src/operations/clear.js +20 -0
  24. package/src/operations/concat.js +17 -0
  25. package/src/operations/deepMap.js +25 -0
  26. package/src/operations/deepMerge.js +11 -25
  27. package/src/operations/deepReverse.js +6 -7
  28. package/src/operations/deepTake.js +6 -7
  29. package/src/operations/deepText.js +4 -4
  30. package/src/operations/deepValuesIterator.js +8 -6
  31. package/src/operations/defineds.js +32 -0
  32. package/src/operations/delete.js +20 -0
  33. package/src/operations/entries.js +16 -0
  34. package/src/operations/extensionKeyFunctions.js +1 -1
  35. package/src/operations/filter.js +7 -8
  36. package/src/operations/first.js +18 -0
  37. package/src/operations/forEach.js +20 -0
  38. package/src/operations/from.js +77 -0
  39. package/src/operations/fromFn.js +26 -0
  40. package/src/operations/globKeys.js +8 -8
  41. package/src/operations/group.js +9 -7
  42. package/src/operations/has.js +16 -0
  43. package/src/operations/indent.js +4 -2
  44. package/src/operations/inners.js +29 -0
  45. package/src/operations/invokeFunctions.js +5 -4
  46. package/src/operations/isAsyncMutableTree.js +15 -0
  47. package/src/operations/isAsyncTree.js +21 -0
  48. package/src/operations/isTraversable.js +15 -0
  49. package/src/operations/isTreelike.js +33 -0
  50. package/src/operations/json.js +4 -3
  51. package/src/operations/keys.js +14 -0
  52. package/src/operations/length.js +15 -0
  53. package/src/operations/map.js +151 -95
  54. package/src/operations/mapExtension.js +27 -0
  55. package/src/operations/mapReduce.js +44 -0
  56. package/src/operations/mask.js +18 -16
  57. package/src/operations/match.js +74 -0
  58. package/src/operations/merge.js +22 -20
  59. package/src/operations/paginate.js +3 -5
  60. package/src/operations/parent.js +13 -0
  61. package/src/operations/paths.js +51 -0
  62. package/src/operations/plain.js +34 -0
  63. package/src/operations/regExpKeys.js +4 -5
  64. package/src/operations/remove.js +14 -0
  65. package/src/operations/reverse.js +4 -6
  66. package/src/operations/root.js +17 -0
  67. package/src/operations/scope.js +4 -6
  68. package/src/operations/setDeep.js +50 -0
  69. package/src/operations/shuffle.js +46 -0
  70. package/src/operations/sort.js +19 -12
  71. package/src/operations/take.js +3 -5
  72. package/src/operations/text.js +3 -3
  73. package/src/operations/toFunction.js +14 -0
  74. package/src/operations/traverse.js +25 -0
  75. package/src/operations/traverseOrThrow.js +64 -0
  76. package/src/operations/traversePath.js +16 -0
  77. package/src/operations/values.js +15 -0
  78. package/src/operations/withKeys.js +33 -0
  79. package/src/utilities/TypedArray.js +2 -0
  80. package/src/utilities/box.js +20 -0
  81. package/src/utilities/castArraylike.js +38 -0
  82. package/src/utilities/getParent.js +33 -0
  83. package/src/utilities/getRealmObjectPrototype.js +19 -0
  84. package/src/utilities/getTreeArgument.js +43 -0
  85. package/src/utilities/isPacked.js +20 -0
  86. package/src/utilities/isPlainObject.js +29 -0
  87. package/src/utilities/isPrimitive.js +13 -0
  88. package/src/utilities/isStringlike.js +25 -0
  89. package/src/utilities/isUnpackable.js +13 -0
  90. package/src/utilities/keysFromPath.js +34 -0
  91. package/src/utilities/naturalOrder.js +9 -0
  92. package/src/utilities/pathFromKeys.js +18 -0
  93. package/src/utilities/setParent.js +38 -0
  94. package/src/utilities/toFunction.js +41 -0
  95. package/src/utilities/toPlainValue.js +95 -0
  96. package/src/utilities/toString.js +37 -0
  97. package/test/drivers/ExplorableSiteTree.test.js +1 -1
  98. package/test/drivers/FileTree.test.js +1 -1
  99. package/test/drivers/calendarTree.test.js +1 -1
  100. package/test/jsonKeys.test.js +1 -1
  101. package/test/operations/assign.test.js +54 -0
  102. package/test/operations/cache.test.js +1 -1
  103. package/test/operations/cachedKeyFunctions.test.js +16 -16
  104. package/test/operations/clear.test.js +34 -0
  105. package/test/operations/deepMap.test.js +29 -0
  106. package/test/operations/deepMerge.test.js +2 -6
  107. package/test/operations/deepReverse.test.js +1 -1
  108. package/test/operations/defineds.test.js +25 -0
  109. package/test/operations/delete.test.js +20 -0
  110. package/test/operations/entries.test.js +18 -0
  111. package/test/operations/extensionKeyFunctions.test.js +10 -10
  112. package/test/operations/first.test.js +15 -0
  113. package/test/operations/fixtures/README.md +1 -0
  114. package/test/operations/forEach.test.js +22 -0
  115. package/test/operations/from.test.js +67 -0
  116. package/test/operations/globKeys.test.js +3 -3
  117. package/test/operations/has.test.js +15 -0
  118. package/test/operations/inners.test.js +30 -0
  119. package/test/operations/invokeFunctions.test.js +1 -1
  120. package/test/operations/isAsyncMutableTree.test.js +17 -0
  121. package/test/operations/isAsyncTree.test.js +26 -0
  122. package/test/operations/isTreelike.test.js +13 -0
  123. package/test/operations/keys.test.js +15 -0
  124. package/test/operations/length.test.js +15 -0
  125. package/test/operations/map.test.js +61 -42
  126. package/test/operations/mapExtension.test.js +0 -0
  127. package/test/operations/mapReduce.test.js +23 -0
  128. package/test/operations/mask.test.js +1 -1
  129. package/test/operations/match.test.js +33 -0
  130. package/test/operations/merge.test.js +23 -9
  131. package/test/operations/parent.test.js +15 -0
  132. package/test/operations/paths.test.js +40 -0
  133. package/test/operations/plain.test.js +69 -0
  134. package/test/operations/reverse.test.js +1 -1
  135. package/test/operations/scope.test.js +1 -1
  136. package/test/operations/setDeep.test.js +53 -0
  137. package/test/operations/shuffle.test.js +18 -0
  138. package/test/operations/sort.test.js +3 -3
  139. package/test/operations/toFunction.test.js +16 -0
  140. package/test/operations/traverse.test.js +43 -0
  141. package/test/operations/traversePath.test.js +16 -0
  142. package/test/operations/values.test.js +18 -0
  143. package/test/operations/withKeys.test.js +21 -0
  144. package/test/utilities/box.test.js +26 -0
  145. package/test/utilities/getRealmObjectPrototype.test.js +11 -0
  146. package/test/utilities/isPlainObject.test.js +13 -0
  147. package/test/utilities/keysFromPath.test.js +14 -0
  148. package/test/utilities/naturalOrder.test.js +11 -0
  149. package/test/utilities/pathFromKeys.test.js +12 -0
  150. package/test/utilities/setParent.test.js +34 -0
  151. package/test/utilities/toFunction.test.js +34 -0
  152. package/test/utilities/toPlainValue.test.js +27 -0
  153. package/test/utilities/toString.test.js +22 -0
  154. package/src/Tree.d.ts +0 -24
  155. package/src/utilities.d.ts +0 -21
  156. package/src/utilities.js +0 -443
  157. package/test/Tree.test.js +0 -407
  158. package/test/utilities.test.js +0 -141
@@ -12,7 +12,7 @@ describe("deepReverse", () => {
12
12
  d: 3,
13
13
  },
14
14
  };
15
- const reversed = deepReverse.call(null, tree);
15
+ const reversed = await deepReverse.call(null, tree);
16
16
  assert.deepEqual(await Tree.plain(reversed), {
17
17
  b: {
18
18
  d: 3,
@@ -0,0 +1,25 @@
1
+ import assert from "node:assert";
2
+ import { describe, test } from "node:test";
3
+ import { Tree } from "../../src/internal.js";
4
+ import defineds from "../../src/operations/defineds.js";
5
+
6
+ describe("defineds", () => {
7
+ test("returns only defined values in a tree", async () => {
8
+ const obj = {
9
+ a: 1,
10
+ b: undefined,
11
+ c: null,
12
+ d: {
13
+ e: 2,
14
+ f: undefined,
15
+ g: {
16
+ h: 3,
17
+ i: undefined,
18
+ },
19
+ },
20
+ };
21
+ const result = await defineds(obj);
22
+ const plain = await Tree.plain(result);
23
+ assert.deepEqual(plain, { a: 1, d: { e: 2, g: { h: 3 } } });
24
+ });
25
+ });
@@ -0,0 +1,20 @@
1
+ import assert from "node:assert";
2
+ import { describe, test } from "node:test";
3
+ import ObjectTree from "../../src/drivers/ObjectTree.js";
4
+ import { default as del } from "../../src/operations/delete.js";
5
+ import plain from "../../src/operations/plain.js";
6
+
7
+ describe("delete", () => {
8
+ test("removes a value", async () => {
9
+ const fixture = new ObjectTree({
10
+ "Alice.md": "Hello, **Alice**.",
11
+ "Bob.md": "Hello, **Bob**.",
12
+ "Carol.md": "Hello, **Carol**.",
13
+ });
14
+ await del(fixture, "Alice.md");
15
+ assert.deepEqual(await plain(fixture), {
16
+ "Bob.md": "Hello, **Bob**.",
17
+ "Carol.md": "Hello, **Carol**.",
18
+ });
19
+ });
20
+ });
@@ -0,0 +1,18 @@
1
+ import assert from "node:assert";
2
+ import { describe, test } from "node:test";
3
+ import entries from "../../src/operations/entries.js";
4
+
5
+ describe("entries", () => {
6
+ test("entries() returns the [key, value] pairs", async () => {
7
+ const fixture = {
8
+ "Alice.md": "Hello, **Alice**.",
9
+ "Bob.md": "Hello, **Bob**.",
10
+ "Carol.md": "Hello, **Carol**.",
11
+ };
12
+ assert.deepEqual(Array.from(await entries(fixture)), [
13
+ ["Alice.md", "Hello, **Alice**."],
14
+ ["Bob.md", "Hello, **Bob**."],
15
+ ["Carol.md", "Hello, **Carol**."],
16
+ ]);
17
+ });
18
+ });
@@ -9,28 +9,28 @@ describe("keyMapsForExtensions", () => {
9
9
  const { inverseKey, key } = extensionKeyFunctions(".txt");
10
10
  assert.equal(await inverseKey("file.txt"), "file.txt");
11
11
  assert.equal(await inverseKey("file.txt/"), "file.txt");
12
- assert.equal(await key("file.txt"), "file.txt");
13
- assert.equal(await key("file.txt/"), "file.txt/");
12
+ assert.equal(await key(null, "file.txt"), "file.txt");
13
+ assert.equal(await key(null, "file.txt/"), "file.txt/");
14
14
  assert.equal(await inverseKey("file.foo"), undefined);
15
- assert.equal(await key("file.foo"), undefined);
15
+ assert.equal(await key(null, "file.foo"), undefined);
16
16
  });
17
17
 
18
18
  test("returns key functions that can map extensions", async () => {
19
19
  const { inverseKey, key } = extensionKeyFunctions(".md", ".json");
20
20
  assert.equal(await inverseKey("file.json"), "file.md");
21
21
  assert.equal(await inverseKey("file.json/"), "file.md");
22
- assert.equal(await key("file.md"), "file.json");
23
- assert.equal(await key("file.md/"), "file.json/");
22
+ assert.equal(await key(null, "file.md"), "file.json");
23
+ assert.equal(await key(null, "file.md/"), "file.json/");
24
24
  assert.equal(await inverseKey("file.foo"), undefined);
25
- assert.equal(await key("file.foo"), undefined);
25
+ assert.equal(await key(null, "file.foo"), undefined);
26
26
  });
27
27
 
28
28
  test("key functions can handle a slash as an explicit extension", async () => {
29
29
  const { inverseKey, key } = extensionKeyFunctions("/", ".html");
30
30
  assert.equal(await inverseKey("file.html"), "file/");
31
31
  assert.equal(await inverseKey("file.html/"), "file/");
32
- assert.equal(await key("file"), undefined);
33
- assert.equal(await key("file/"), "file.html");
32
+ assert.equal(await key(null, "file"), undefined);
33
+ assert.equal(await key(null, "file/"), "file.html");
34
34
  });
35
35
 
36
36
  test("works with map to handle keys that end in a given resultExtension", async () => {
@@ -40,7 +40,7 @@ describe("keyMapsForExtensions", () => {
40
40
  "file3.foo": "won't be mapped",
41
41
  });
42
42
  const { inverseKey, key } = extensionKeyFunctions(".txt");
43
- const fixture = map(files, {
43
+ const fixture = await map(files, {
44
44
  inverseKey,
45
45
  key,
46
46
  value: (sourceValue, sourceKey, tree) => sourceValue.toUpperCase(),
@@ -57,7 +57,7 @@ describe("keyMapsForExtensions", () => {
57
57
  "file3.foo": "won't be mapped",
58
58
  });
59
59
  const { inverseKey, key } = extensionKeyFunctions(".txt", ".upper");
60
- const fixture = map(files, {
60
+ const fixture = await map(files, {
61
61
  inverseKey,
62
62
  key,
63
63
  value: (sourceValue, sourceKey, tree) => sourceValue.toUpperCase(),
@@ -0,0 +1,15 @@
1
+ import assert from "node:assert";
2
+ import { describe, test } from "node:test";
3
+ import first from "../../src/operations/first.js";
4
+
5
+ describe("first", () => {
6
+ test("returns the first value in the tree", async () => {
7
+ const obj = {
8
+ a: 1,
9
+ b: 2,
10
+ c: 3,
11
+ };
12
+ const result = await first(obj);
13
+ assert.equal(result, 1);
14
+ });
15
+ });
@@ -0,0 +1 @@
1
+ This folder is used as a temp directory by some tests
@@ -0,0 +1,22 @@
1
+ import assert from "node:assert";
2
+ import { describe, test } from "node:test";
3
+ import forEach from "../../src/operations/forEach.js";
4
+
5
+ describe("forEach", () => {
6
+ test("invokes a callback for each entry", async () => {
7
+ const fixture = {
8
+ "Alice.md": "Hello, **Alice**.",
9
+ "Bob.md": "Hello, **Bob**.",
10
+ "Carol.md": "Hello, **Carol**.",
11
+ };
12
+ const results = {};
13
+ await forEach(fixture, async (value, key) => {
14
+ results[key] = value;
15
+ });
16
+ assert.deepEqual(results, {
17
+ "Alice.md": "Hello, **Alice**.",
18
+ "Bob.md": "Hello, **Bob**.",
19
+ "Carol.md": "Hello, **Carol**.",
20
+ });
21
+ });
22
+ });
@@ -0,0 +1,67 @@
1
+ import assert from "node:assert";
2
+ import { describe, test } from "node:test";
3
+ import DeepObjectTree from "../../src/drivers/DeepObjectTree.js";
4
+ import ObjectTree from "../../src/drivers/ObjectTree.js";
5
+ import from from "../../src/operations/from.js";
6
+ import plain from "../../src/operations/plain.js";
7
+ import * as symbols from "../../src/symbols.js";
8
+
9
+ describe("from", () => {
10
+ test("returns an async tree as is", async () => {
11
+ const tree1 = new ObjectTree({
12
+ a: "Hello, a.",
13
+ });
14
+ const tree2 = from(tree1);
15
+ assert.equal(tree2, tree1);
16
+ });
17
+
18
+ test("uses an object's unpack() method if defined", async () => {
19
+ const obj = new String();
20
+ /** @type {any} */ (obj).unpack = () => ({
21
+ a: "Hello, a.",
22
+ });
23
+ const tree = from(obj);
24
+ assert.deepEqual(await plain(tree), {
25
+ a: "Hello, a.",
26
+ });
27
+ });
28
+
29
+ test("returns a deep object tree if deep option is true", async () => {
30
+ const obj = {
31
+ sub: {
32
+ a: 1,
33
+ },
34
+ };
35
+ const tree = from(obj, { deep: true });
36
+ assert(tree instanceof DeepObjectTree);
37
+ });
38
+
39
+ test("returns a deep object tree if object has [deep] symbol set", async () => {
40
+ const obj = {
41
+ sub: {
42
+ a: 1,
43
+ },
44
+ };
45
+ Object.defineProperty(obj, symbols.deep, { value: true });
46
+ const tree = from(obj);
47
+ assert(tree instanceof DeepObjectTree);
48
+ });
49
+
50
+ test("creates a deferred tree if unpack() returns a promise", async () => {
51
+ const obj = new String();
52
+ /** @type {any} */ (obj).unpack = async () => ({
53
+ a: "Hello, a.",
54
+ });
55
+ const tree = from(obj);
56
+ assert.deepEqual(await plain(tree), {
57
+ a: "Hello, a.",
58
+ });
59
+ });
60
+
61
+ test("autoboxes primitive values", async () => {
62
+ const tree = from("Hello, world.");
63
+ const slice = await tree.get("slice");
64
+ const result = await slice(0, 5);
65
+ assert.equal(result, "Hello");
66
+ });
67
+ });
@@ -5,7 +5,7 @@ import globKeys from "../../src/operations/globKeys.js";
5
5
 
6
6
  describe("globKeys", () => {
7
7
  test("matches globs", async () => {
8
- const globTree = globKeys({
8
+ const globTree = await globKeys({
9
9
  "*.txt": true,
10
10
  "*.js": false,
11
11
  "*.jsx": true,
@@ -20,7 +20,7 @@ describe("globKeys", () => {
20
20
  });
21
21
 
22
22
  test("matches nested globs", async () => {
23
- const globTree = globKeys({
23
+ const globTree = await globKeys({
24
24
  sub: {
25
25
  foo: "bar",
26
26
  "*": "default",
@@ -31,7 +31,7 @@ describe("globKeys", () => {
31
31
  });
32
32
 
33
33
  test("supports deep matches with globstar", async () => {
34
- const globTree = globKeys({
34
+ const globTree = await globKeys({
35
35
  "**": {
36
36
  "*.txt": true, // More specific glob pattern must come
37
37
  "*": false,
@@ -0,0 +1,15 @@
1
+ import assert from "node:assert";
2
+ import { describe, test } from "node:test";
3
+ import has from "../../src/operations/has.js";
4
+
5
+ describe("has", () => {
6
+ test("has returns true if the key exists", async () => {
7
+ const fixture = {
8
+ "Alice.md": "Hello, **Alice**.",
9
+ "Bob.md": "Hello, **Bob**.",
10
+ "Carol.md": "Hello, **Carol**.",
11
+ };
12
+ assert.equal(await has(fixture, "Alice.md"), true);
13
+ assert.equal(await has(fixture, "David.md"), false);
14
+ });
15
+ });
@@ -0,0 +1,30 @@
1
+ import assert from "node:assert";
2
+ import { describe, test } from "node:test";
3
+ import { DeepObjectTree, Tree } from "../../src/internal.js";
4
+ import inners from "../../src/operations/inners.js";
5
+
6
+ describe("inners", () => {
7
+ test("returns the interior nodes of a tree", async () => {
8
+ const obj = new DeepObjectTree({
9
+ a: 1,
10
+ b: {
11
+ c: 2,
12
+ d: {
13
+ e: 3,
14
+ },
15
+ },
16
+ f: 4,
17
+ g: {
18
+ h: 5,
19
+ },
20
+ });
21
+ const result = await inners(obj);
22
+ const plain = await Tree.plain(result);
23
+ assert.deepEqual(plain, {
24
+ b: {
25
+ d: {},
26
+ },
27
+ g: {},
28
+ });
29
+ });
30
+ });
@@ -5,7 +5,7 @@ import invokeFunctions from "../../src/operations/invokeFunctions.js";
5
5
 
6
6
  describe("invokeFunctions", () => {
7
7
  test("invokes function values, leaves other values as is", async () => {
8
- const fixture = invokeFunctions({
8
+ const fixture = await invokeFunctions({
9
9
  a: 1,
10
10
  b: () => 2,
11
11
  });
@@ -0,0 +1,17 @@
1
+ import assert from "node:assert";
2
+ import { describe, test } from "node:test";
3
+ import ObjectTree from "../../src/drivers/ObjectTree.js";
4
+ import isAsyncMutableTree from "../../src/operations/isAsyncMutableTree.js";
5
+
6
+ describe("isAsyncMutableTree", () => {
7
+ test("returns true if the object is a mutable tree", () => {
8
+ assert.equal(
9
+ isAsyncMutableTree({
10
+ get() {},
11
+ keys() {},
12
+ }),
13
+ false
14
+ );
15
+ assert.equal(isAsyncMutableTree(new ObjectTree({})), true);
16
+ });
17
+ });
@@ -0,0 +1,26 @@
1
+ import assert from "node:assert";
2
+ import { describe, test } from "node:test";
3
+ import isAsyncTree from "../../src/operations/isAsyncTree.js";
4
+
5
+ describe("isAsyncTree", () => {
6
+ test("returns true if the object is a tree", () => {
7
+ const missingGetAndKeys = {};
8
+ assert(!isAsyncTree(missingGetAndKeys));
9
+
10
+ const missingIterator = {
11
+ async get() {},
12
+ };
13
+ assert(!isAsyncTree(missingIterator));
14
+
15
+ const missingGet = {
16
+ async keys() {},
17
+ };
18
+ assert(!isAsyncTree(missingGet));
19
+
20
+ const hasGetAndKeys = {
21
+ async get() {},
22
+ async keys() {},
23
+ };
24
+ assert(isAsyncTree(hasGetAndKeys));
25
+ });
26
+ });
@@ -0,0 +1,13 @@
1
+ import assert from "node:assert";
2
+ import { describe, test } from "node:test";
3
+ import isTreelike from "../../src/operations/isTreelike.js";
4
+
5
+ describe("Fixture name goes here", () => {
6
+ test("isTreelike() returns true if the argument can be cast to an async tree", () => {
7
+ assert(!isTreelike(null));
8
+ assert(isTreelike({}));
9
+ assert(isTreelike([]));
10
+ assert(isTreelike(new Map()));
11
+ assert(isTreelike(new Set()));
12
+ });
13
+ });
@@ -0,0 +1,15 @@
1
+ import assert from "node:assert";
2
+ import { describe, test } from "node:test";
3
+ import keys from "../../src/operations/keys.js";
4
+
5
+ describe("keys", () => {
6
+ test("returns the keys of a tree as an array", async () => {
7
+ const obj = {
8
+ a: 1,
9
+ b: 2,
10
+ c: 3,
11
+ };
12
+ const result = await keys(obj);
13
+ assert.deepEqual(result, ["a", "b", "c"]);
14
+ });
15
+ });
@@ -0,0 +1,15 @@
1
+ import assert from "node:assert";
2
+ import { describe, test } from "node:test";
3
+ import length from "../../src/operations/length.js";
4
+
5
+ describe("length", () => {
6
+ test("returns the number of keys in the tree", async () => {
7
+ const obj = {
8
+ a: 1,
9
+ b: 2,
10
+ c: 3,
11
+ };
12
+ const result = await length(obj);
13
+ assert.equal(result, 3);
14
+ });
15
+ });
@@ -1,6 +1,5 @@
1
1
  import assert from "node:assert";
2
2
  import { describe, test } from "node:test";
3
- import FunctionTree from "../../src/drivers/FunctionTree.js";
4
3
  import { DeepObjectTree, ObjectTree, Tree } from "../../src/internal.js";
5
4
  import map from "../../src/operations/map.js";
6
5
  import * as trailingSlash from "../../src/trailingSlash.js";
@@ -11,8 +10,8 @@ describe("map", () => {
11
10
  a: "letter a",
12
11
  b: "letter b",
13
12
  };
14
- assert.throws(() => {
15
- map(tree, {});
13
+ assert.rejects(async () => {
14
+ await map(tree, {});
16
15
  });
17
16
  });
18
17
 
@@ -22,7 +21,7 @@ describe("map", () => {
22
21
  b: "letter b",
23
22
  c: undefined, // Won't be mapped
24
23
  });
25
- const mapped = map(tree, {
24
+ const mapped = await map(tree, {
26
25
  value: (sourceValue, sourceKey, innerTree) => {
27
26
  assert(sourceKey === "a" || sourceKey === "b");
28
27
  assert.equal(innerTree, tree);
@@ -41,7 +40,7 @@ describe("map", () => {
41
40
  a: "letter a",
42
41
  b: "letter b",
43
42
  };
44
- const uppercaseValues = map(tree, (sourceValue, sourceKey, tree) => {
43
+ const uppercaseValues = await map(tree, (sourceValue, sourceKey, tree) => {
45
44
  assert(sourceKey === "a" || sourceKey === "b");
46
45
  return sourceValue.toUpperCase();
47
46
  });
@@ -56,7 +55,7 @@ describe("map", () => {
56
55
  a: "letter a",
57
56
  b: "letter b",
58
57
  };
59
- const underscoreKeys = map(tree, {
58
+ const underscoreKeys = await map(tree, {
60
59
  key: addUnderscore,
61
60
  inverseKey: removeUnderscore,
62
61
  });
@@ -71,7 +70,7 @@ describe("map", () => {
71
70
  a: "letter a",
72
71
  b: "letter b",
73
72
  };
74
- const underscoreKeys = map(tree, {
73
+ const underscoreKeys = await map(tree, {
75
74
  key: addUnderscore,
76
75
  });
77
76
  assert.deepEqual(await Tree.plain(underscoreKeys), {
@@ -81,18 +80,19 @@ describe("map", () => {
81
80
  });
82
81
 
83
82
  test("maps keys and values", async () => {
84
- const tree = {
85
- a: "letter a",
86
- b: "letter b",
87
- };
88
- const underscoreKeysUppercaseValues = map(tree, {
89
- key: addUnderscore,
90
- inverseKey: removeUnderscore,
91
- value: async (sourceValue, sourceKey, tree) => sourceValue.toUpperCase(),
83
+ const treelike = new ObjectTree([
84
+ { name: "Alice", age: 1 },
85
+ { name: "Bob", age: 2 },
86
+ { name: "Carol", age: 3 },
87
+ ]);
88
+ const result = await map(treelike, {
89
+ key: (value, key, tree) => value.name,
90
+ value: (value, key, tree) => value.age,
92
91
  });
93
- assert.deepEqual(await Tree.plain(underscoreKeysUppercaseValues), {
94
- _a: "LETTER A",
95
- _b: "LETTER B",
92
+ assert.deepEqual(await Tree.plain(result), {
93
+ Alice: 1,
94
+ Bob: 2,
95
+ Carol: 3,
96
96
  });
97
97
  });
98
98
 
@@ -103,8 +103,8 @@ describe("map", () => {
103
103
  b: "letter b",
104
104
  },
105
105
  };
106
- const underscoreKeys = map(tree, {
107
- key: async (sourceKey, tree) => `_${sourceKey}`,
106
+ const underscoreKeys = await map(tree, {
107
+ key: async (value, sourceKey, tree) => `_${sourceKey}`,
108
108
  inverseKey: async (resultKey, tree) => resultKey.slice(1),
109
109
  value: async (sourceValue, sourceKey, tree) => sourceKey,
110
110
  });
@@ -122,7 +122,7 @@ describe("map", () => {
122
122
  a: "letter a",
123
123
  b: "letter b",
124
124
  };
125
- const mapped = map(tree, uppercase);
125
+ const mapped = await map(tree, uppercase);
126
126
  assert.deepEqual(await Tree.plain(mapped), {
127
127
  _a: "LETTER A",
128
128
  _b: "LETTER B",
@@ -136,7 +136,7 @@ describe("map", () => {
136
136
  b: "letter b",
137
137
  },
138
138
  });
139
- const uppercaseValues = map(tree, {
139
+ const uppercaseValues = await map(tree, {
140
140
  deep: true,
141
141
  value: (sourceValue, sourceKey, tree) => sourceValue.toUpperCase(),
142
142
  });
@@ -155,7 +155,7 @@ describe("map", () => {
155
155
  b: "letter b",
156
156
  },
157
157
  });
158
- const underscoreKeys = map(tree, {
158
+ const underscoreKeys = await map(tree, {
159
159
  deep: true,
160
160
  key: addUnderscore,
161
161
  inverseKey: removeUnderscore,
@@ -175,7 +175,7 @@ describe("map", () => {
175
175
  b: "letter b",
176
176
  },
177
177
  });
178
- const underscoreKeysUppercaseValues = map(tree, {
178
+ const underscoreKeysUppercaseValues = await map(tree, {
179
179
  deep: true,
180
180
  key: addUnderscore,
181
181
  inverseKey: removeUnderscore,
@@ -189,6 +189,42 @@ describe("map", () => {
189
189
  });
190
190
  });
191
191
 
192
+ test("keyNeedsSourceValue can be set to false in cases where the value isn't necessary", async () => {
193
+ const tree = {
194
+ a: "letter a",
195
+ b: "letter b",
196
+ c: "letter c",
197
+ };
198
+ const mapped = await map(tree, {
199
+ keyNeedsSourceValue: false,
200
+ key: (value, key) => {
201
+ assert.equal(value, null);
202
+ return key.toUpperCase();
203
+ },
204
+ });
205
+ assert.deepEqual(await Tree.plain(mapped), {
206
+ A: "letter a",
207
+ B: "letter b",
208
+ C: "letter c",
209
+ });
210
+ });
211
+
212
+ test("can add an extension to a key", async () => {
213
+ const treelike = {
214
+ "file0.txt": 1,
215
+ file1: 2,
216
+ file2: 3,
217
+ };
218
+ const fixture = await map(treelike, {
219
+ extension: "->.data",
220
+ });
221
+ assert.deepEqual(await Tree.plain(fixture), {
222
+ "file0.txt.data": 1,
223
+ "file1.data": 2,
224
+ "file2.data": 3,
225
+ });
226
+ });
227
+
192
228
  test("can change a key's extension", async () => {
193
229
  const treelike = {
194
230
  "file1.lower": "will be mapped",
@@ -222,26 +258,9 @@ describe("map", () => {
222
258
  },
223
259
  });
224
260
  });
225
-
226
- test("needsSourceValue can be set to false in cases where the value isn't necessary", async () => {
227
- let flag = false;
228
- const tree = new FunctionTree(() => {
229
- flag = true;
230
- }, ["a", "b", "c"]);
231
- const mapped = map(tree, {
232
- needsSourceValue: false,
233
- value: () => "X",
234
- });
235
- assert.deepEqual(await Tree.plain(mapped), {
236
- a: "X",
237
- b: "X",
238
- c: "X",
239
- });
240
- assert(!flag);
241
- });
242
261
  });
243
262
 
244
- function addUnderscore(key) {
263
+ function addUnderscore(value, key) {
245
264
  return `_${key}`;
246
265
  }
247
266
 
File without changes
@@ -0,0 +1,23 @@
1
+ import assert from "node:assert";
2
+ import { describe, test } from "node:test";
3
+ import DeepObjectTree from "../../src/drivers/DeepObjectTree.js";
4
+ import mapReduce from "../../src/operations/mapReduce.js";
5
+
6
+ describe("mapReduce", () => {
7
+ test("can map values and reduce them", async () => {
8
+ const tree = new DeepObjectTree({
9
+ a: 1,
10
+ b: 2,
11
+ more: {
12
+ c: 3,
13
+ },
14
+ d: 4,
15
+ });
16
+ const reduced = await mapReduce(
17
+ tree,
18
+ (value) => value,
19
+ async (values) => String.prototype.concat(...values)
20
+ );
21
+ assert.deepEqual(reduced, "1234");
22
+ });
23
+ });
@@ -5,7 +5,7 @@ import mask from "../../src/operations/mask.js";
5
5
 
6
6
  describe("mask", () => {
7
7
  test("removes keys and values whose mask values are falsy", async () => {
8
- const result = mask(
8
+ const result = await mask(
9
9
  {
10
10
  a: 1,
11
11
  b: 2,