@weborigami/async-tree 0.6.8 → 0.6.10
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 +2 -2
- package/scripts/headlessTest.js +1 -3
- package/shared.js +2 -1
- package/src/TraverseError.js +6 -3
- package/src/drivers/CalendarMap.js +12 -4
- package/src/operations/addNextPrevious.js +2 -2
- package/src/operations/assign.js +7 -3
- package/src/operations/cache.js +4 -4
- package/src/operations/child.js +2 -2
- package/src/operations/clear.js +3 -3
- package/src/operations/deepEntries.js +3 -3
- package/src/operations/deepMap.js +2 -2
- package/src/operations/deepMerge.js +15 -2
- package/src/operations/deepReverse.js +4 -2
- package/src/operations/deepTake.js +3 -2
- package/src/operations/deepText.js +5 -4
- package/src/operations/deepValuesIterator.js +3 -3
- package/src/operations/delete.js +4 -5
- package/src/operations/entries.js +2 -2
- package/src/operations/filter.js +2 -2
- package/src/operations/first.js +2 -2
- package/src/operations/forEach.js +6 -2
- package/src/operations/from.js +5 -2
- package/src/operations/globKeys.js +2 -2
- package/src/operations/groupBy.js +5 -4
- package/src/operations/has.js +2 -2
- package/src/operations/indent.js +9 -3
- package/src/operations/inners.js +2 -2
- package/src/operations/invokeFunctions.js +2 -2
- package/src/operations/json.js +2 -2
- package/src/operations/keys.js +2 -2
- package/src/operations/length.js +2 -2
- package/src/operations/map.js +22 -18
- package/src/operations/mapExtension.js +3 -3
- package/src/operations/mapReduce.js +4 -4
- package/src/operations/mask.js +6 -6
- package/src/operations/match.js +7 -18
- package/src/operations/merge.js +13 -2
- package/src/operations/paginate.js +3 -2
- package/src/operations/parent.js +2 -2
- package/src/operations/paths.js +2 -2
- package/src/operations/plain.js +2 -2
- package/src/operations/reduce.js +2 -2
- package/src/operations/regExpKeys.js +5 -3
- package/src/operations/reverse.js +2 -2
- package/src/operations/root.js +2 -2
- package/src/operations/scope.js +5 -4
- package/src/operations/set.js +2 -2
- package/src/operations/shuffle.js +2 -2
- package/src/operations/size.js +2 -2
- package/src/operations/sort.js +4 -4
- package/src/operations/sync.js +2 -2
- package/src/operations/take.js +3 -2
- package/src/operations/toFunction.js +2 -2
- package/src/operations/traverse.js +3 -1
- package/src/operations/traverseOrThrow.js +40 -8
- package/src/operations/traversePath.js +5 -3
- package/src/operations/values.js +2 -2
- package/src/operations/visit.js +2 -2
- package/src/operations/withKeys.js +5 -3
- package/src/utilities/args.js +128 -0
- package/src/utilities/interop.js +9 -0
- package/src/utilities/setParent.js +1 -1
- package/test/operations/root.test.js +2 -2
- package/test/operations/traverse.test.js +1 -32
- package/test/operations/traverseOrThrow.test.js +73 -0
- package/src/utilities/getMapArgument.js +0 -38
package/src/operations/map.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import AsyncMap from "../drivers/AsyncMap.js";
|
|
2
2
|
import * as trailingSlash from "../trailingSlash.js";
|
|
3
|
-
import
|
|
3
|
+
import * as args from "../utilities/args.js";
|
|
4
4
|
import isPlainObject from "../utilities/isPlainObject.js";
|
|
5
5
|
import isUnpackable from "../utilities/isUnpackable.js";
|
|
6
6
|
import toFunction from "../utilities/toFunction.js";
|
|
@@ -28,7 +28,9 @@ export default async function map(maplike, options = {}) {
|
|
|
28
28
|
const validated = validateOptions(options);
|
|
29
29
|
const mapFn = createMapFn(validated);
|
|
30
30
|
|
|
31
|
-
const tree = await
|
|
31
|
+
const tree = await args.map(maplike, "Tree.map", {
|
|
32
|
+
deep: validated.deep,
|
|
33
|
+
});
|
|
32
34
|
return mapFn(tree);
|
|
33
35
|
}
|
|
34
36
|
|
|
@@ -37,7 +39,7 @@ function createGet(tree, options, mapFn) {
|
|
|
37
39
|
const { inverseKeyFn, deep, valueFn } = options;
|
|
38
40
|
return async (resultKey) => {
|
|
39
41
|
if (resultKey === undefined) {
|
|
40
|
-
throw new ReferenceError(`map: Cannot get an undefined key.`);
|
|
42
|
+
throw new ReferenceError(`Tree.map: Cannot get an undefined key.`);
|
|
41
43
|
}
|
|
42
44
|
|
|
43
45
|
// Step 1: Map the result key to the source key
|
|
@@ -102,8 +104,8 @@ function createKeys(tree, options) {
|
|
|
102
104
|
// Deep maps leave source keys for subtrees alone
|
|
103
105
|
deep && trailingSlash.has(sourceKey)
|
|
104
106
|
? sourceKey
|
|
105
|
-
: await keyFn(sourceValues[index], sourceKey, tree)
|
|
106
|
-
)
|
|
107
|
+
: await keyFn(sourceValues[index], sourceKey, tree),
|
|
108
|
+
),
|
|
107
109
|
);
|
|
108
110
|
// Filter out any cases where the keyFn returned undefined.
|
|
109
111
|
const resultKeys = mapped.filter((key) => key !== undefined);
|
|
@@ -135,7 +137,7 @@ function validateOption(options, key) {
|
|
|
135
137
|
const value = options[key];
|
|
136
138
|
if (key in options && value === undefined) {
|
|
137
139
|
throw new TypeError(
|
|
138
|
-
`map: The ${key} option is given but its value is undefined
|
|
140
|
+
`Tree.map: The ${key} option is given but its value is undefined.`,
|
|
139
141
|
);
|
|
140
142
|
}
|
|
141
143
|
return value;
|
|
@@ -173,38 +175,40 @@ function validateOptions(options) {
|
|
|
173
175
|
(keyFn.includes("=>") || keyFn.includes("→"))
|
|
174
176
|
) {
|
|
175
177
|
throw new TypeError(
|
|
176
|
-
`map: The key option appears to be an extension mapping. Did you mean to call Tree.mapExtension()
|
|
178
|
+
`Tree.map: The key option appears to be an extension mapping. Did you mean to call Tree.mapExtension() ?`,
|
|
177
179
|
);
|
|
178
180
|
}
|
|
179
181
|
keyFn &&= castToFunction(keyFn, "key");
|
|
180
182
|
valueFn &&= castToFunction(valueFn, "value");
|
|
181
183
|
} else if (options === undefined) {
|
|
182
184
|
/** @type {any} */
|
|
183
|
-
const error = new TypeError(
|
|
184
|
-
|
|
185
|
+
const error = new TypeError(
|
|
186
|
+
`Tree.map: The second parameter was undefined.`,
|
|
187
|
+
);
|
|
188
|
+
error.position = 2;
|
|
185
189
|
throw error;
|
|
186
190
|
} else {
|
|
187
191
|
/** @type {any} */
|
|
188
192
|
const error = new TypeError(
|
|
189
|
-
`map: You must specify a value function or options dictionary as the second parameter
|
|
193
|
+
`Tree.map: You must specify a value function or options dictionary as the second parameter.`,
|
|
190
194
|
);
|
|
191
|
-
error.position =
|
|
195
|
+
error.position = 2;
|
|
192
196
|
throw error;
|
|
193
197
|
}
|
|
194
198
|
|
|
195
199
|
if (extension && !options._noExtensionWarning) {
|
|
196
200
|
console.warn(
|
|
197
|
-
`map: The 'extension' option for Tree.map() is deprecated and will be removed in a future release. Use Tree.mapExtension() instead
|
|
201
|
+
`Tree.map: The 'extension' option for Tree.map() is deprecated and will be removed in a future release. Use Tree.mapExtension() instead.`,
|
|
198
202
|
);
|
|
199
203
|
}
|
|
200
204
|
if (extension && (keyFn || inverseKeyFn)) {
|
|
201
205
|
throw new TypeError(
|
|
202
|
-
`map: You can't specify extensions and also a key or inverseKey function
|
|
206
|
+
`Tree.map: You can't specify extensions and also a key or inverseKey function`,
|
|
203
207
|
);
|
|
204
208
|
}
|
|
205
209
|
if (extension && keyNeedsSourceValue === true) {
|
|
206
210
|
throw new TypeError(
|
|
207
|
-
`map: using extensions sets keyNeedsSourceValue to be false
|
|
211
|
+
`Tree.map: using extensions sets keyNeedsSourceValue to be false`,
|
|
208
212
|
);
|
|
209
213
|
}
|
|
210
214
|
|
|
@@ -213,7 +217,7 @@ function validateOptions(options) {
|
|
|
213
217
|
const parsed = parseExtensions(extension);
|
|
214
218
|
const keyFns = extensionKeyFunctions(
|
|
215
219
|
parsed.sourceExtension,
|
|
216
|
-
parsed.resultExtension
|
|
220
|
+
parsed.resultExtension,
|
|
217
221
|
);
|
|
218
222
|
keyFn = keyFns.key;
|
|
219
223
|
inverseKeyFn = keyFns.inverseKey;
|
|
@@ -225,7 +229,7 @@ function validateOptions(options) {
|
|
|
225
229
|
|
|
226
230
|
if (!keyFn && inverseKeyFn) {
|
|
227
231
|
throw new TypeError(
|
|
228
|
-
`map: You can't specify an inverseKey function without a key function
|
|
232
|
+
`Tree.map: You can't specify an inverseKey function without a key function`,
|
|
229
233
|
);
|
|
230
234
|
}
|
|
231
235
|
|
|
@@ -239,7 +243,7 @@ function validateOptions(options) {
|
|
|
239
243
|
|
|
240
244
|
if (!valueFn && !keyFn) {
|
|
241
245
|
throw new TypeError(
|
|
242
|
-
`map: You must specify a value function or a key function
|
|
246
|
+
`Tree.map: You must specify a value function or a key function`,
|
|
243
247
|
);
|
|
244
248
|
}
|
|
245
249
|
|
|
@@ -262,7 +266,7 @@ function castToFunction(object, name) {
|
|
|
262
266
|
const fn = toFunction(object);
|
|
263
267
|
if (!fn) {
|
|
264
268
|
throw new TypeError(
|
|
265
|
-
`map: The ${name} option must be a function but couldn't be treated as one
|
|
269
|
+
`Tree.map: The ${name} option must be a function but couldn't be treated as one.`,
|
|
266
270
|
);
|
|
267
271
|
}
|
|
268
272
|
return fn;
|
|
@@ -54,13 +54,13 @@ export default async function mapExtension(maplike, arg2, arg3) {
|
|
|
54
54
|
Object.assign(options, arg2);
|
|
55
55
|
} else {
|
|
56
56
|
throw new TypeError(
|
|
57
|
-
"mapExtension: Expected a string or options object for the second argument."
|
|
57
|
+
"Tree.mapExtension: Expected a string or options object for the second argument.",
|
|
58
58
|
);
|
|
59
59
|
}
|
|
60
60
|
} else {
|
|
61
61
|
if (typeof arg2 !== "string") {
|
|
62
62
|
throw new TypeError(
|
|
63
|
-
"mapExtension: Expected a string for the second argument."
|
|
63
|
+
"Tree.mapExtension: Expected a string for the second argument.",
|
|
64
64
|
);
|
|
65
65
|
}
|
|
66
66
|
options.extension = arg2;
|
|
@@ -73,7 +73,7 @@ export default async function mapExtension(maplike, arg2, arg3) {
|
|
|
73
73
|
Object.assign(options, arg3);
|
|
74
74
|
} else {
|
|
75
75
|
throw new TypeError(
|
|
76
|
-
"mapExtension: Expected a function or options object for the third argument."
|
|
76
|
+
"Tree.mapExtension: Expected a function or options object for the third argument.",
|
|
77
77
|
);
|
|
78
78
|
}
|
|
79
79
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as args from "../utilities/args.js";
|
|
2
2
|
import isMap from "./isMap.js";
|
|
3
3
|
|
|
4
4
|
/**
|
|
@@ -23,7 +23,7 @@ import isMap from "./isMap.js";
|
|
|
23
23
|
* @param {ReduceFn} reduceFn
|
|
24
24
|
*/
|
|
25
25
|
export default async function mapReduce(source, valueFn, reduceFn) {
|
|
26
|
-
const sourceMap = await
|
|
26
|
+
const sourceMap = await args.map(source, "Tree.mapReduce");
|
|
27
27
|
|
|
28
28
|
// We're going to fire off all the get requests in parallel, as quickly as
|
|
29
29
|
// the keys come in. We call the tree's `get` method for each key, but
|
|
@@ -37,8 +37,8 @@ export default async function mapReduce(source, valueFn, reduceFn) {
|
|
|
37
37
|
return isMap(value)
|
|
38
38
|
? mapReduce(value, valueFn, reduceFn) // subtree; recurse
|
|
39
39
|
: valueFn
|
|
40
|
-
|
|
41
|
-
|
|
40
|
+
? valueFn(value, key, sourceMap)
|
|
41
|
+
: value;
|
|
42
42
|
})();
|
|
43
43
|
promises.push(promise);
|
|
44
44
|
}
|
package/src/operations/mask.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import AsyncMap from "../drivers/AsyncMap.js";
|
|
2
2
|
import * as trailingSlash from "../trailingSlash.js";
|
|
3
|
-
import
|
|
3
|
+
import * as args from "../utilities/args.js";
|
|
4
4
|
import isMaplike from "./isMaplike.js";
|
|
5
5
|
import keys from "./keys.js";
|
|
6
6
|
|
|
@@ -16,13 +16,13 @@ import keys from "./keys.js";
|
|
|
16
16
|
* @returns {Promise<AsyncMap>}
|
|
17
17
|
*/
|
|
18
18
|
export default async function mask(aMaplike, bMaplike) {
|
|
19
|
-
const aMap = await
|
|
19
|
+
const aMap = await args.map(aMaplike, "Tree.mask", {
|
|
20
20
|
deep: true,
|
|
21
|
-
position:
|
|
21
|
+
position: 1,
|
|
22
22
|
});
|
|
23
|
-
const bMap = await
|
|
23
|
+
const bMap = await args.map(bMaplike, "Tree.mask", {
|
|
24
24
|
deep: true,
|
|
25
|
-
position:
|
|
25
|
+
position: 2,
|
|
26
26
|
});
|
|
27
27
|
|
|
28
28
|
return Object.assign(new AsyncMap(), {
|
|
@@ -66,7 +66,7 @@ export default async function mask(aMaplike, bMaplike) {
|
|
|
66
66
|
}
|
|
67
67
|
return trailingSlash.toggle(
|
|
68
68
|
key,
|
|
69
|
-
trailingSlash.has(key) || isMaplike(bValue)
|
|
69
|
+
trailingSlash.has(key) || isMaplike(bValue),
|
|
70
70
|
);
|
|
71
71
|
});
|
|
72
72
|
|
package/src/operations/match.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import AsyncMap from "../drivers/AsyncMap.js";
|
|
2
|
-
import
|
|
2
|
+
import * as args from "../utilities/args.js";
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Return a tree with the indicated keys (if provided).
|
|
@@ -27,15 +27,17 @@ export default function match(pattern, resultFn, keys = []) {
|
|
|
27
27
|
// Convert the simple pattern format into a regular expression.
|
|
28
28
|
const regexText = pattern.replace(
|
|
29
29
|
/\[(?<variable>.+)\]/g,
|
|
30
|
-
(match, p1, offset, string, groups) => `(?<${groups.variable}>.+)
|
|
30
|
+
(match, p1, offset, string, groups) => `(?<${groups.variable}>.+)`,
|
|
31
31
|
);
|
|
32
32
|
regex = new RegExp(`^${regexText}$`);
|
|
33
33
|
} else if (pattern instanceof RegExp) {
|
|
34
34
|
regex = pattern;
|
|
35
35
|
} else {
|
|
36
|
-
throw new Error(`match
|
|
36
|
+
throw new Error(`Tree.match: Unsupported pattern`);
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
+
const fn = args.invocable(resultFn, "Tree.match", { position: 2 });
|
|
40
|
+
|
|
39
41
|
const result = Object.assign(new AsyncMap(), {
|
|
40
42
|
description: "match",
|
|
41
43
|
|
|
@@ -45,24 +47,11 @@ export default function match(pattern, resultFn, keys = []) {
|
|
|
45
47
|
return undefined;
|
|
46
48
|
}
|
|
47
49
|
|
|
48
|
-
if (
|
|
49
|
-
typeof resultFn !== "function" &&
|
|
50
|
-
!(isMap(resultFn) && "parent" in resultFn)
|
|
51
|
-
) {
|
|
52
|
-
// Simple return value; return as is
|
|
53
|
-
return resultFn;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
50
|
// Copy the `groups` property to a real object
|
|
57
51
|
const matches = { ...keyMatch.groups };
|
|
58
52
|
|
|
59
|
-
// Invoke the result function
|
|
60
|
-
|
|
61
|
-
if (typeof resultFn === "function") {
|
|
62
|
-
value = await resultFn(matches);
|
|
63
|
-
} else {
|
|
64
|
-
value = Object.create(resultFn);
|
|
65
|
-
}
|
|
53
|
+
// Invoke the result function
|
|
54
|
+
const value = await fn(matches);
|
|
66
55
|
|
|
67
56
|
return value;
|
|
68
57
|
},
|
package/src/operations/merge.js
CHANGED
|
@@ -4,6 +4,7 @@ import isPlainObject from "../utilities/isPlainObject.js";
|
|
|
4
4
|
import isUnpackable from "../utilities/isUnpackable.js";
|
|
5
5
|
import from from "./from.js";
|
|
6
6
|
import isMap from "./isMap.js";
|
|
7
|
+
import isMaplike from "./isMaplike.js";
|
|
7
8
|
import keys from "./keys.js";
|
|
8
9
|
|
|
9
10
|
/**
|
|
@@ -25,10 +26,20 @@ export default async function merge(...treelikes) {
|
|
|
25
26
|
const filtered = treelikes.filter((source) => source);
|
|
26
27
|
const unpacked = await Promise.all(
|
|
27
28
|
filtered.map(async (source) =>
|
|
28
|
-
isUnpackable(source) ? await source.unpack() : source
|
|
29
|
-
)
|
|
29
|
+
isUnpackable(source) ? await source.unpack() : source,
|
|
30
|
+
),
|
|
30
31
|
);
|
|
31
32
|
|
|
33
|
+
// If any argument isn't maplike, throw an error.
|
|
34
|
+
for (const index in unpacked) {
|
|
35
|
+
if (!isMaplike(unpacked[index])) {
|
|
36
|
+
/** @type {any} */
|
|
37
|
+
const error = new TypeError(`Tree.merge: an argument wasn't maplike.`);
|
|
38
|
+
error.position = Number(index) + 1;
|
|
39
|
+
throw error;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
32
43
|
// If all arguments are plain objects, return a plain object.
|
|
33
44
|
if (unpacked.every((source) => !isMap(source) && isPlainObject(source))) {
|
|
34
45
|
return unpacked.reduce((acc, obj) => ({ ...acc, ...obj }), {});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import AsyncMap from "../drivers/AsyncMap.js";
|
|
2
2
|
import SyncMap from "../drivers/SyncMap.js";
|
|
3
3
|
import * as trailingSlash from "../trailingSlash.js";
|
|
4
|
-
import
|
|
4
|
+
import * as args from "../utilities/args.js";
|
|
5
5
|
import keys from "./keys.js";
|
|
6
6
|
|
|
7
7
|
/**
|
|
@@ -14,7 +14,8 @@ import keys from "./keys.js";
|
|
|
14
14
|
* @param {number} [size=10]
|
|
15
15
|
*/
|
|
16
16
|
export default async function paginate(maplike, size = 10) {
|
|
17
|
-
const source = await
|
|
17
|
+
const source = await args.map(maplike, "Tree.paginate");
|
|
18
|
+
size = args.number(size, "Tree.paginate", { position: 2 });
|
|
18
19
|
|
|
19
20
|
const treeKeys = await keys(source);
|
|
20
21
|
const pageCount = Math.ceil(treeKeys.length / size);
|
package/src/operations/parent.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as args from "../utilities/args.js";
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Returns the parent of the map, if any.
|
|
@@ -8,6 +8,6 @@ import getMapArgument from "../utilities/getMapArgument.js";
|
|
|
8
8
|
* @param {Maplike} maplike
|
|
9
9
|
*/
|
|
10
10
|
export default async function parent(maplike) {
|
|
11
|
-
const map = await
|
|
11
|
+
const map = await args.map(maplike, "Tree.parent");
|
|
12
12
|
return "parent" in map ? map.parent : undefined;
|
|
13
13
|
}
|
package/src/operations/paths.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as trailingSlash from "../trailingSlash.js";
|
|
2
|
-
import
|
|
2
|
+
import * as args from "../utilities/args.js";
|
|
3
3
|
import from from "./from.js";
|
|
4
4
|
import isMap from "./isMap.js";
|
|
5
5
|
import isMaplike from "./isMaplike.js";
|
|
@@ -15,7 +15,7 @@ import isMaplike from "./isMaplike.js";
|
|
|
15
15
|
* @param {{ base?: string }} options
|
|
16
16
|
*/
|
|
17
17
|
export default async function paths(maplike, options = {}) {
|
|
18
|
-
const tree = await
|
|
18
|
+
const tree = await args.map(maplike, "Tree.paths");
|
|
19
19
|
const base = options.base ?? "";
|
|
20
20
|
const result = [];
|
|
21
21
|
for await (const key of tree.keys()) {
|
package/src/operations/plain.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as args from "../utilities/args.js";
|
|
2
2
|
import toPlainValue from "../utilities/toPlainValue.js";
|
|
3
3
|
|
|
4
4
|
/**
|
|
@@ -29,6 +29,6 @@ export default async function plain(maplike) {
|
|
|
29
29
|
if (maplike instanceof Function) {
|
|
30
30
|
throw new TypeError("plain: can't convert a function to a plain object");
|
|
31
31
|
}
|
|
32
|
-
const tree = await
|
|
32
|
+
const tree = await args.map(maplike, "Tree.plain");
|
|
33
33
|
return toPlainValue(tree);
|
|
34
34
|
}
|
package/src/operations/reduce.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as args from "../utilities/args.js";
|
|
2
2
|
import mapReduce from "./mapReduce.js";
|
|
3
3
|
|
|
4
4
|
/**
|
|
@@ -11,6 +11,6 @@ import mapReduce from "./mapReduce.js";
|
|
|
11
11
|
* @param {ReduceFn} reduceFn
|
|
12
12
|
*/
|
|
13
13
|
export default async function reduce(maplike, reduceFn) {
|
|
14
|
-
const map = await
|
|
14
|
+
const map = await args.map(maplike, "Tree.reduce");
|
|
15
15
|
return mapReduce(map, null, reduceFn);
|
|
16
16
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import AsyncMap from "../drivers/AsyncMap.js";
|
|
2
2
|
import SyncMap from "../drivers/SyncMap.js";
|
|
3
3
|
import * as trailingSlash from "../trailingSlash.js";
|
|
4
|
-
import
|
|
4
|
+
import * as args from "../utilities/args.js";
|
|
5
5
|
import isMap from "./isMap.js";
|
|
6
6
|
|
|
7
7
|
/**
|
|
@@ -18,7 +18,9 @@ import isMap from "./isMap.js";
|
|
|
18
18
|
* @returns {Promise<AsyncMap>}
|
|
19
19
|
*/
|
|
20
20
|
export default async function regExpKeys(maplike) {
|
|
21
|
-
const source = await
|
|
21
|
+
const source = await args.map(maplike, "Tree.regExpKeys", {
|
|
22
|
+
deep: true,
|
|
23
|
+
});
|
|
22
24
|
|
|
23
25
|
const map = new SyncMap();
|
|
24
26
|
|
|
@@ -32,7 +34,7 @@ export default async function regExpKeys(maplike) {
|
|
|
32
34
|
if (key == null) {
|
|
33
35
|
// Reject nullish key.
|
|
34
36
|
throw new ReferenceError(
|
|
35
|
-
`regExpKeys: Cannot get a null or undefined key
|
|
37
|
+
`regExpKeys: Cannot get a null or undefined key.`,
|
|
36
38
|
);
|
|
37
39
|
}
|
|
38
40
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import AsyncMap from "../drivers/AsyncMap.js";
|
|
2
|
-
import
|
|
2
|
+
import * as args from "../utilities/args.js";
|
|
3
3
|
import keys from "./keys.js";
|
|
4
4
|
|
|
5
5
|
/**
|
|
@@ -11,7 +11,7 @@ import keys from "./keys.js";
|
|
|
11
11
|
* @returns {Promise<AsyncMap>}
|
|
12
12
|
*/
|
|
13
13
|
export default async function reverse(maplike) {
|
|
14
|
-
const source = await
|
|
14
|
+
const source = await args.map(maplike, "Tree.reverse");
|
|
15
15
|
return Object.assign(new AsyncMap(), {
|
|
16
16
|
description: "reverse",
|
|
17
17
|
|
package/src/operations/root.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as symbols from "../symbols.js";
|
|
2
|
-
import
|
|
2
|
+
import * as args from "../utilities/args.js";
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Walk up the `parent` chain to find the root of the tree.
|
|
@@ -10,7 +10,7 @@ import getMapArgument from "../utilities/getMapArgument.js";
|
|
|
10
10
|
*/
|
|
11
11
|
export default async function root(maplike) {
|
|
12
12
|
/** @type {any} */
|
|
13
|
-
let current = await
|
|
13
|
+
let current = await args.map(maplike, "Tree.root");
|
|
14
14
|
while (current.parent || current[symbols.parent]) {
|
|
15
15
|
current = current.parent || current[symbols.parent];
|
|
16
16
|
}
|
package/src/operations/scope.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import AsyncMap from "../drivers/AsyncMap.js";
|
|
2
|
-
import
|
|
2
|
+
import * as args from "../utilities/args.js";
|
|
3
|
+
import getParent from "../utilities/getParent.js";
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* A map's "scope" is the collection of everything in that map and all of its
|
|
@@ -11,7 +12,7 @@ import getMapArgument from "../utilities/getMapArgument.js";
|
|
|
11
12
|
* @returns {Promise<AsyncMap>}
|
|
12
13
|
*/
|
|
13
14
|
export default async function scope(maplike) {
|
|
14
|
-
const source = await
|
|
15
|
+
const source = await args.map(maplike, "Tree.scope");
|
|
15
16
|
|
|
16
17
|
return Object.assign(new AsyncMap(), {
|
|
17
18
|
description: "scope",
|
|
@@ -26,7 +27,7 @@ export default async function scope(maplike) {
|
|
|
26
27
|
if (value !== undefined) {
|
|
27
28
|
break;
|
|
28
29
|
}
|
|
29
|
-
current =
|
|
30
|
+
current = getParent(current);
|
|
30
31
|
}
|
|
31
32
|
return value;
|
|
32
33
|
},
|
|
@@ -40,7 +41,7 @@ export default async function scope(maplike) {
|
|
|
40
41
|
for await (const key of current.keys()) {
|
|
41
42
|
scopeKeys.add(key);
|
|
42
43
|
}
|
|
43
|
-
current =
|
|
44
|
+
current = getParent(current);
|
|
44
45
|
}
|
|
45
46
|
|
|
46
47
|
yield* scopeKeys;
|
package/src/operations/set.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as args from "../utilities/args.js";
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Set a key/value pair in a map.
|
|
@@ -10,7 +10,7 @@ import getMapArgument from "../utilities/getMapArgument.js";
|
|
|
10
10
|
* @param {any} value
|
|
11
11
|
*/
|
|
12
12
|
export default async function set(maplike, key, value) {
|
|
13
|
-
const map = await
|
|
13
|
+
const map = await args.map(maplike, "Tree.set");
|
|
14
14
|
await map.set(key, value);
|
|
15
15
|
|
|
16
16
|
// Unlike Map.prototype.set, we return undefined. This is more useful when
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import AsyncMap from "../drivers/AsyncMap.js";
|
|
2
|
-
import
|
|
2
|
+
import * as args from "../utilities/args.js";
|
|
3
3
|
import keys from "./keys.js";
|
|
4
4
|
|
|
5
5
|
/**
|
|
@@ -12,7 +12,7 @@ import keys from "./keys.js";
|
|
|
12
12
|
* @returns {Promise<AsyncMap>}
|
|
13
13
|
*/
|
|
14
14
|
export default async function shuffle(maplike, reshuffle = false) {
|
|
15
|
-
const source = await
|
|
15
|
+
const source = await args.map(maplike, "Tree.shuffle");
|
|
16
16
|
|
|
17
17
|
let mapKeys;
|
|
18
18
|
|
package/src/operations/size.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as args from "../utilities/args.js";
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Return the number of keys in the map.
|
|
@@ -8,6 +8,6 @@ import getMapArgument from "../utilities/getMapArgument.js";
|
|
|
8
8
|
* @param {Maplike} maplike
|
|
9
9
|
*/
|
|
10
10
|
export default async function size(maplike) {
|
|
11
|
-
const map = await
|
|
11
|
+
const map = await args.map(maplike, "Tree.size");
|
|
12
12
|
return map.size;
|
|
13
13
|
}
|
package/src/operations/sort.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import AsyncMap from "../drivers/AsyncMap.js";
|
|
2
|
-
import
|
|
2
|
+
import * as args from "../utilities/args.js";
|
|
3
3
|
import keys from "./keys.js";
|
|
4
4
|
|
|
5
5
|
/**
|
|
@@ -17,7 +17,7 @@ import keys from "./keys.js";
|
|
|
17
17
|
* @param {SortOptions|ValueKeyFn} [options]
|
|
18
18
|
*/
|
|
19
19
|
export default async function sort(maplike, options) {
|
|
20
|
-
const source = await
|
|
20
|
+
const source = await args.map(maplike, "Tree.sort");
|
|
21
21
|
|
|
22
22
|
let sortKey;
|
|
23
23
|
let compare;
|
|
@@ -49,11 +49,11 @@ export default async function sort(maplike, options) {
|
|
|
49
49
|
const sort = await sortKey(value, key, source);
|
|
50
50
|
if (sort === undefined) {
|
|
51
51
|
throw new Error(
|
|
52
|
-
`sortKey function returned undefined for key ${key}
|
|
52
|
+
`sortKey function returned undefined for key ${key}`,
|
|
53
53
|
);
|
|
54
54
|
}
|
|
55
55
|
return { key, sort };
|
|
56
|
-
})
|
|
56
|
+
}),
|
|
57
57
|
);
|
|
58
58
|
|
|
59
59
|
// Wrap the comparison function so it applies to sort keys.
|
package/src/operations/sync.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as args from "../utilities/args.js";
|
|
2
2
|
import reduce from "./reduce.js";
|
|
3
3
|
|
|
4
4
|
/**
|
|
@@ -9,6 +9,6 @@ import reduce from "./reduce.js";
|
|
|
9
9
|
* @param {Maplike} source
|
|
10
10
|
*/
|
|
11
11
|
export default async function sync(source) {
|
|
12
|
-
const tree = await
|
|
12
|
+
const tree = await args.map(source, "Tree.sync");
|
|
13
13
|
return reduce(tree, (mapped) => mapped);
|
|
14
14
|
}
|
package/src/operations/take.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import AsyncMap from "../drivers/AsyncMap.js";
|
|
2
|
-
import
|
|
2
|
+
import * as args from "../utilities/args.js";
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Returns a new map with the number of keys limited to the indicated count.
|
|
@@ -8,7 +8,8 @@ import getMapArgument from "../utilities/getMapArgument.js";
|
|
|
8
8
|
* @param {number} count
|
|
9
9
|
*/
|
|
10
10
|
export default async function take(maplike, count) {
|
|
11
|
-
const source = await
|
|
11
|
+
const source = await args.map(maplike, "Tree.take");
|
|
12
|
+
count = args.number(count, "Tree.take", { position: 2 });
|
|
12
13
|
return Object.assign(new AsyncMap(), {
|
|
13
14
|
description: `take ${count}`,
|
|
14
15
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as args from "../utilities/args.js";
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Returns a function that invokes the map's `get` method.
|
|
@@ -9,6 +9,6 @@ import getMapArgument from "../utilities/getMapArgument.js";
|
|
|
9
9
|
* @returns {Promise<Function>}
|
|
10
10
|
*/
|
|
11
11
|
export default async function toFunction(maplike) {
|
|
12
|
-
const map = await
|
|
12
|
+
const map = await args.map(maplike, "Tree.toFunction");
|
|
13
13
|
return map.get.bind(map);
|
|
14
14
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import TraverseError from "../TraverseError.js";
|
|
2
|
+
import * as args from "../utilities/args.js";
|
|
2
3
|
import traverseOrThrow from "./traverseOrThrow.js";
|
|
3
4
|
|
|
4
5
|
/**
|
|
@@ -10,10 +11,11 @@ import traverseOrThrow from "./traverseOrThrow.js";
|
|
|
10
11
|
* @param {...any} keys
|
|
11
12
|
*/
|
|
12
13
|
export default async function traverse(maplike, ...keys) {
|
|
14
|
+
const map = await args.map(maplike, "Tree.traverse");
|
|
13
15
|
try {
|
|
14
16
|
// Await the result here so that, if the path doesn't exist, the catch
|
|
15
17
|
// block below will catch the exception.
|
|
16
|
-
return await traverseOrThrow(
|
|
18
|
+
return await traverseOrThrow(map, ...keys);
|
|
17
19
|
} catch (/** @type {any} */ error) {
|
|
18
20
|
if (error instanceof TraverseError) {
|
|
19
21
|
return undefined;
|