@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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@weborigami/async-tree",
3
- "version": "0.6.1",
3
+ "version": "0.6.3",
4
4
  "description": "Asynchronous tree drivers based on standard JavaScript classes",
5
5
  "type": "module",
6
6
  "main": "./main.js",
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";
@@ -53,4 +53,6 @@ export default class ExplorableSiteMap extends SiteMap {
53
53
 
54
54
  return super.processResponse(response);
55
55
  }
56
+
57
+ trailingSlashKeys = true;
56
58
  }
@@ -24,9 +24,8 @@ export default async function globKeys(maplike) {
24
24
  },
25
25
 
26
26
  async *keys() {
27
- for await (const key of source.keys()) {
28
- yield key;
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,
@@ -167,9 +167,17 @@ function validateOptions(options) {
167
167
  valueFn = validateOption(options, "value");
168
168
 
169
169
  // Cast function options to functions
170
- inverseKeyFn &&= toFunction(inverseKeyFn);
171
- keyFn &&= toFunction(keyFn);
172
- valueFn &&= toFunction(valueFn);
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
+ }
@@ -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
+ });