@weborigami/async-tree 0.6.1 → 0.6.3
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/package.json +1 -1
- package/src/Tree.js +1 -0
- package/src/drivers/ExplorableSiteMap.js +2 -0
- package/src/operations/globKeys.js +2 -3
- package/src/operations/map.js +21 -3
- package/src/operations/root.js +2 -2
- package/src/operations/visit.js +14 -0
- package/test/operations/root.test.js +23 -0
- package/test/operations/visit.test.js +25 -0
package/package.json
CHANGED
package/src/Tree.js
CHANGED
|
@@ -67,4 +67,5 @@ export { default as traverse } from "./operations/traverse.js";
|
|
|
67
67
|
export { default as traverseOrThrow } from "./operations/traverseOrThrow.js";
|
|
68
68
|
export { default as traversePath } from "./operations/traversePath.js";
|
|
69
69
|
export { default as values } from "./operations/values.js";
|
|
70
|
+
export { default as visit } from "./operations/visit.js";
|
|
70
71
|
export { default as withKeys } from "./operations/withKeys.js";
|
|
@@ -24,9 +24,8 @@ export default async function globKeys(maplike) {
|
|
|
24
24
|
},
|
|
25
25
|
|
|
26
26
|
async *keys() {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
}
|
|
27
|
+
// Don't return globstar keys. When used, e.g., with a Tree.mask, we don't
|
|
28
|
+
// want the globstar keys to appear in the result.
|
|
30
29
|
},
|
|
31
30
|
|
|
32
31
|
trailingSlashKeys: /** @type {any} */ (source).trailingSlashKeys,
|
package/src/operations/map.js
CHANGED
|
@@ -167,9 +167,17 @@ function validateOptions(options) {
|
|
|
167
167
|
valueFn = validateOption(options, "value");
|
|
168
168
|
|
|
169
169
|
// Cast function options to functions
|
|
170
|
-
inverseKeyFn &&=
|
|
171
|
-
|
|
172
|
-
|
|
170
|
+
inverseKeyFn &&= castToFunction(inverseKeyFn, "inverseKey");
|
|
171
|
+
if (
|
|
172
|
+
typeof keyFn === "string" &&
|
|
173
|
+
(keyFn.includes("=>") || keyFn.includes("→"))
|
|
174
|
+
) {
|
|
175
|
+
throw new TypeError(
|
|
176
|
+
`map: The key option appears to be an extension mapping. Did you mean to call Tree.mapExtension() ?`
|
|
177
|
+
);
|
|
178
|
+
}
|
|
179
|
+
keyFn &&= castToFunction(keyFn, "key");
|
|
180
|
+
valueFn &&= castToFunction(valueFn, "value");
|
|
173
181
|
} else if (options === undefined) {
|
|
174
182
|
/** @type {any} */
|
|
175
183
|
const error = new TypeError(`map: The second parameter was undefined.`);
|
|
@@ -249,3 +257,13 @@ function validateOptions(options) {
|
|
|
249
257
|
valueFn,
|
|
250
258
|
};
|
|
251
259
|
}
|
|
260
|
+
|
|
261
|
+
function castToFunction(object, name) {
|
|
262
|
+
const fn = toFunction(object);
|
|
263
|
+
if (!fn) {
|
|
264
|
+
throw new TypeError(
|
|
265
|
+
`map: The ${name} option must be a function but couldn't be treated as one.`
|
|
266
|
+
);
|
|
267
|
+
}
|
|
268
|
+
return fn;
|
|
269
|
+
}
|
package/src/operations/root.js
CHANGED
|
@@ -8,9 +8,9 @@ import getMapArgument from "../utilities/getMapArgument.js";
|
|
|
8
8
|
*
|
|
9
9
|
* @param {Maplike} maplike
|
|
10
10
|
*/
|
|
11
|
-
export default function root(maplike) {
|
|
11
|
+
export default async function root(maplike) {
|
|
12
12
|
/** @type {any} */
|
|
13
|
-
let current = getMapArgument(maplike, "root");
|
|
13
|
+
let current = await getMapArgument(maplike, "root");
|
|
14
14
|
while (current.parent || current[symbols.parent]) {
|
|
15
15
|
current = current.parent || current[symbols.parent];
|
|
16
16
|
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import getMapArgument from "../utilities/getMapArgument.js";
|
|
2
|
+
import reduce from "./reduce.js";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Visit every node in the tree and return `undefined`.
|
|
6
|
+
*
|
|
7
|
+
* @typedef {import("../../index.ts").Maplike} Maplike
|
|
8
|
+
*
|
|
9
|
+
* @param {Maplike} source
|
|
10
|
+
*/
|
|
11
|
+
export default async function visit(source) {
|
|
12
|
+
const tree = await getMapArgument(source, "visit", { deep: true });
|
|
13
|
+
return reduce(tree, () => undefined);
|
|
14
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import assert from "node:assert";
|
|
2
|
+
import { describe, test } from "node:test";
|
|
3
|
+
import ObjectMap from "../../src/drivers/ObjectMap.js";
|
|
4
|
+
import root from "../../src/operations/root.js";
|
|
5
|
+
import traverse from "../../src/operations/traverse.js";
|
|
6
|
+
|
|
7
|
+
describe("root", () => {
|
|
8
|
+
test("returns root of a tree", async () => {
|
|
9
|
+
const tree = new ObjectMap(
|
|
10
|
+
{
|
|
11
|
+
a: {
|
|
12
|
+
b: {
|
|
13
|
+
c: {},
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
{ deep: true }
|
|
18
|
+
);
|
|
19
|
+
const c = await traverse(tree, "a", "b", "c");
|
|
20
|
+
const r = await root(c);
|
|
21
|
+
assert.strictEqual(r, tree);
|
|
22
|
+
});
|
|
23
|
+
});
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import assert from "node:assert";
|
|
2
|
+
import { describe, test } from "node:test";
|
|
3
|
+
import FunctionMap from "../../src/drivers/FunctionMap.js";
|
|
4
|
+
import visit from "../../src/operations/visit.js";
|
|
5
|
+
|
|
6
|
+
describe("visit", () => {
|
|
7
|
+
test("visits every node in the tree", async () => {
|
|
8
|
+
const values = [];
|
|
9
|
+
const map = new FunctionMap(
|
|
10
|
+
(key) => {
|
|
11
|
+
const value = `value for ${key}`;
|
|
12
|
+
values.push(value);
|
|
13
|
+
return value;
|
|
14
|
+
},
|
|
15
|
+
["a", "b", "c"]
|
|
16
|
+
);
|
|
17
|
+
const result = await visit(map);
|
|
18
|
+
assert.strictEqual(result, undefined);
|
|
19
|
+
assert.deepStrictEqual(values, [
|
|
20
|
+
"value for a",
|
|
21
|
+
"value for b",
|
|
22
|
+
"value for c",
|
|
23
|
+
]);
|
|
24
|
+
});
|
|
25
|
+
});
|