@weborigami/async-tree 0.5.8 → 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 (182) hide show
  1. package/browser.js +1 -1
  2. package/index.ts +43 -35
  3. package/main.js +1 -2
  4. package/package.json +4 -7
  5. package/shared.js +74 -12
  6. package/src/Tree.js +11 -2
  7. package/src/drivers/AsyncMap.js +237 -0
  8. package/src/drivers/{BrowserFileTree.js → BrowserFileMap.js} +54 -38
  9. package/src/drivers/{calendarTree.js → CalendarMap.js} +80 -63
  10. package/src/drivers/ConstantMap.js +28 -0
  11. package/src/drivers/{ExplorableSiteTree.js → ExplorableSiteMap.js} +7 -7
  12. package/src/drivers/FileMap.js +238 -0
  13. package/src/drivers/{FunctionTree.js → FunctionMap.js} +19 -22
  14. package/src/drivers/ObjectMap.js +151 -0
  15. package/src/drivers/SetMap.js +13 -0
  16. package/src/drivers/{SiteTree.js → SiteMap.js} +17 -20
  17. package/src/drivers/SyncMap.js +260 -0
  18. package/src/jsonKeys.d.ts +2 -2
  19. package/src/jsonKeys.js +20 -5
  20. package/src/operations/addNextPrevious.js +35 -36
  21. package/src/operations/assign.js +27 -23
  22. package/src/operations/cache.js +30 -36
  23. package/src/operations/cachedKeyFunctions.js +1 -1
  24. package/src/operations/calendar.js +5 -0
  25. package/src/operations/child.js +35 -0
  26. package/src/operations/clear.js +13 -12
  27. package/src/operations/constant.js +5 -0
  28. package/src/operations/deepEntries.js +23 -0
  29. package/src/operations/deepMap.js +9 -9
  30. package/src/operations/deepMerge.js +36 -25
  31. package/src/operations/deepReverse.js +23 -16
  32. package/src/operations/deepTake.js +7 -7
  33. package/src/operations/deepText.js +4 -4
  34. package/src/operations/deepValues.js +3 -6
  35. package/src/operations/deepValuesIterator.js +11 -11
  36. package/src/operations/delete.js +8 -12
  37. package/src/operations/entries.js +17 -10
  38. package/src/operations/filter.js +9 -7
  39. package/src/operations/first.js +12 -10
  40. package/src/operations/forEach.js +10 -13
  41. package/src/operations/from.js +30 -39
  42. package/src/operations/globKeys.js +22 -17
  43. package/src/operations/group.js +2 -2
  44. package/src/operations/groupBy.js +24 -22
  45. package/src/operations/has.js +7 -9
  46. package/src/operations/indent.js +2 -2
  47. package/src/operations/inners.js +19 -15
  48. package/src/operations/invokeFunctions.js +22 -10
  49. package/src/operations/isAsyncMutableTree.js +5 -12
  50. package/src/operations/isAsyncTree.js +5 -20
  51. package/src/operations/isMap.js +39 -0
  52. package/src/operations/isMaplike.js +34 -0
  53. package/src/operations/isReadOnlyMap.js +14 -0
  54. package/src/operations/isTraversable.js +3 -3
  55. package/src/operations/isTreelike.js +5 -30
  56. package/src/operations/json.js +4 -12
  57. package/src/operations/keys.js +17 -8
  58. package/src/operations/length.js +9 -8
  59. package/src/operations/map.js +28 -30
  60. package/src/operations/mapExtension.js +20 -16
  61. package/src/operations/mapReduce.js +38 -24
  62. package/src/operations/mask.js +54 -29
  63. package/src/operations/match.js +13 -9
  64. package/src/operations/merge.js +43 -35
  65. package/src/operations/paginate.js +26 -18
  66. package/src/operations/parent.js +7 -7
  67. package/src/operations/paths.js +20 -22
  68. package/src/operations/plain.js +6 -6
  69. package/src/operations/reduce.js +16 -0
  70. package/src/operations/regExpKeys.js +21 -12
  71. package/src/operations/reverse.js +21 -15
  72. package/src/operations/root.js +6 -5
  73. package/src/operations/scope.js +31 -26
  74. package/src/operations/set.js +20 -0
  75. package/src/operations/shuffle.js +23 -16
  76. package/src/operations/size.js +13 -0
  77. package/src/operations/sort.js +55 -40
  78. package/src/operations/sync.js +14 -0
  79. package/src/operations/take.js +23 -11
  80. package/src/operations/text.js +4 -4
  81. package/src/operations/toFunction.js +7 -7
  82. package/src/operations/traverse.js +4 -4
  83. package/src/operations/traverseOrThrow.js +18 -9
  84. package/src/operations/traversePath.js +2 -2
  85. package/src/operations/values.js +18 -9
  86. package/src/operations/withKeys.js +22 -16
  87. package/src/symbols.js +1 -0
  88. package/src/utilities/castArraylike.js +24 -13
  89. package/src/utilities/getMapArgument.js +38 -0
  90. package/src/utilities/getParent.js +2 -2
  91. package/src/utilities/isStringlike.js +7 -5
  92. package/src/utilities/setParent.js +7 -7
  93. package/src/utilities/toFunction.js +2 -2
  94. package/src/utilities/toPlainValue.js +21 -19
  95. package/test/SampleAsyncMap.js +34 -0
  96. package/test/browser/assert.js +20 -0
  97. package/test/browser/index.html +53 -21
  98. package/test/drivers/AsyncMap.test.js +119 -0
  99. package/test/drivers/{BrowserFileTree.test.js → BrowserFileMap.test.js} +50 -33
  100. package/test/drivers/{calendarTree.test.js → CalendarMap.test.js} +17 -19
  101. package/test/drivers/ConstantMap.test.js +15 -0
  102. package/test/drivers/{ExplorableSiteTree.test.js → ExplorableSiteMap.test.js} +29 -14
  103. package/test/drivers/FileMap.test.js +156 -0
  104. package/test/drivers/FunctionMap.test.js +56 -0
  105. package/test/drivers/ObjectMap.test.js +194 -0
  106. package/test/drivers/SetMap.test.js +35 -0
  107. package/test/drivers/{SiteTree.test.js → SiteMap.test.js} +14 -10
  108. package/test/drivers/SyncMap.test.js +335 -0
  109. package/test/jsonKeys.test.js +18 -6
  110. package/test/operations/addNextPrevious.test.js +3 -2
  111. package/test/operations/assign.test.js +30 -35
  112. package/test/operations/cache.test.js +17 -12
  113. package/test/operations/cachedKeyFunctions.test.js +12 -9
  114. package/test/operations/child.test.js +34 -0
  115. package/test/operations/clear.test.js +6 -27
  116. package/test/operations/deepEntries.test.js +32 -0
  117. package/test/operations/deepMerge.test.js +23 -16
  118. package/test/operations/deepReverse.test.js +2 -2
  119. package/test/operations/deepTake.test.js +2 -2
  120. package/test/operations/deepText.test.js +4 -4
  121. package/test/operations/deepValuesIterator.test.js +2 -2
  122. package/test/operations/delete.test.js +2 -2
  123. package/test/operations/extensionKeyFunctions.test.js +6 -5
  124. package/test/operations/filter.test.js +3 -3
  125. package/test/operations/from.test.js +25 -31
  126. package/test/operations/globKeys.test.js +9 -9
  127. package/test/operations/groupBy.test.js +6 -5
  128. package/test/operations/inners.test.js +17 -14
  129. package/test/operations/invokeFunctions.test.js +2 -2
  130. package/test/operations/isMap.test.js +15 -0
  131. package/test/operations/isMaplike.test.js +15 -0
  132. package/test/operations/json.test.js +2 -2
  133. package/test/operations/keys.test.js +16 -3
  134. package/test/operations/map.test.js +40 -30
  135. package/test/operations/mapExtension.test.js +6 -6
  136. package/test/operations/mapReduce.test.js +14 -12
  137. package/test/operations/mask.test.js +16 -3
  138. package/test/operations/match.test.js +2 -2
  139. package/test/operations/merge.test.js +20 -14
  140. package/test/operations/paginate.test.js +5 -5
  141. package/test/operations/parent.test.js +3 -3
  142. package/test/operations/paths.test.js +20 -27
  143. package/test/operations/plain.test.js +8 -8
  144. package/test/operations/regExpKeys.test.js +22 -18
  145. package/test/operations/reverse.test.js +4 -3
  146. package/test/operations/scope.test.js +6 -5
  147. package/test/operations/set.test.js +11 -0
  148. package/test/operations/shuffle.test.js +3 -2
  149. package/test/operations/sort.test.js +7 -10
  150. package/test/operations/sync.test.js +43 -0
  151. package/test/operations/take.test.js +2 -2
  152. package/test/operations/toFunction.test.js +2 -2
  153. package/test/operations/traverse.test.js +17 -5
  154. package/test/operations/withKeys.test.js +2 -2
  155. package/test/utilities/castArrayLike.test.js +53 -0
  156. package/test/utilities/setParent.test.js +6 -6
  157. package/test/utilities/toFunction.test.js +2 -2
  158. package/test/utilities/toPlainValue.test.js +51 -12
  159. package/src/drivers/DeepMapTree.js +0 -23
  160. package/src/drivers/DeepObjectTree.js +0 -18
  161. package/src/drivers/DeferredTree.js +0 -81
  162. package/src/drivers/FileTree.js +0 -276
  163. package/src/drivers/MapTree.js +0 -70
  164. package/src/drivers/ObjectTree.js +0 -158
  165. package/src/drivers/SetTree.js +0 -34
  166. package/src/drivers/constantTree.js +0 -19
  167. package/src/drivers/limitConcurrency.js +0 -63
  168. package/src/internal.js +0 -16
  169. package/src/utilities/getTreeArgument.js +0 -43
  170. package/test/drivers/DeepMapTree.test.js +0 -17
  171. package/test/drivers/DeepObjectTree.test.js +0 -35
  172. package/test/drivers/DeferredTree.test.js +0 -22
  173. package/test/drivers/FileTree.test.js +0 -192
  174. package/test/drivers/FunctionTree.test.js +0 -46
  175. package/test/drivers/MapTree.test.js +0 -59
  176. package/test/drivers/ObjectTree.test.js +0 -163
  177. package/test/drivers/SetTree.test.js +0 -44
  178. package/test/drivers/constantTree.test.js +0 -13
  179. package/test/drivers/limitConcurrency.test.js +0 -41
  180. package/test/operations/isAsyncMutableTree.test.js +0 -17
  181. package/test/operations/isAsyncTree.test.js +0 -26
  182. package/test/operations/isTreelike.test.js +0 -13
package/browser.js CHANGED
@@ -1,4 +1,4 @@
1
1
  // Exports for browser
2
2
 
3
3
  export * from "./shared.js";
4
- export { default as BrowserFileTree } from "./src/drivers/BrowserFileTree.js";
4
+ export { default as BrowserFileMap } from "./src/drivers/BrowserFileMap.js";
package/index.ts CHANGED
@@ -1,10 +1,10 @@
1
- import type { AsyncTree } from "@weborigami/types";
1
+ import AsyncMap from "./src/drivers/AsyncMap.js";
2
2
 
3
3
  export * from "./main.js";
4
4
 
5
- export type Invocable = Function | Treelike | Unpackable;
5
+ export type Invocable = Function | Maplike | Unpackable;
6
6
 
7
- export type KeyFn = (key: any, innerTree: AsyncTree) => any;
7
+ export type KeyFn = (key: any, map: SyncOrAsyncMap) => any;
8
8
 
9
9
  /**
10
10
  * An object with a non-trivial `toString` method.
@@ -17,36 +17,23 @@ export type HasString = {
17
17
  toString(): string;
18
18
  };
19
19
 
20
- /**
21
- * A packed value is one that can be written to a file via fs.writeFile or into
22
- * an HTTP response via response.write, or readily converted to such a form.
23
- */
24
- export type Packed = (ArrayBuffer | Buffer | ReadableStream | string | String | TypedArray) & {
25
- parent?: AsyncTree|null;
26
- unpack?(): Promise<any>;
27
- };
28
-
29
- export type PlainObject = {
30
- [key: string]: any;
20
+ export type MapExtensionOptions = {
21
+ deep?: boolean;
22
+ description?: string;
23
+ extension?: string;
24
+ needsSourceValue?: boolean;
25
+ value?: ValueKeyFn;
31
26
  };
32
27
 
33
- export type ReduceFn = (values: any[], keys: any[], tree: AsyncTree) => Promise<any>;
34
-
35
- export type Stringlike = string | HasString;
36
-
37
- export type NativeTreelike =
28
+ export type Maplike =
38
29
  any[] |
39
- AsyncTree |
30
+ Iterator<any> |
40
31
  Function |
41
- Map<any, any> |
32
+ SyncOrAsyncMap |
42
33
  PlainObject |
43
34
  Set<any>;
44
35
 
45
- export type Treelike =
46
- NativeTreelike |
47
- Unpackable;
48
-
49
- export type TreeMapOptions = {
36
+ export type MapOptions = {
50
37
  deep?: boolean;
51
38
  description?: string;
52
39
  extension?: string;
@@ -56,15 +43,36 @@ export type TreeMapOptions = {
56
43
  value?: ValueKeyFn;
57
44
  };
58
45
 
59
- export type TreeMapExtensionOptions = {
60
- deep?: boolean;
61
- description?: string;
62
- extension?: string;
63
- needsSourceValue?: boolean;
64
- value?: ValueKeyFn;
46
+ export interface SyncTree<MapType> {
47
+ child(key: any): MapType;
48
+ parent: MapType | null;
49
+ trailingSlashKeys: boolean;
50
+ }
51
+
52
+ export interface AsyncTree<MapType> {
53
+ child(key: any): Promise<MapType>;
54
+ parent: MapType | null;
55
+ trailingSlashKeys: boolean;
56
+ }
57
+
58
+ /**
59
+ * A packed value is one that can be written to a file via fs.writeFile or into
60
+ * an HTTP response via response.write, or readily converted to such a form.
61
+ */
62
+ export type Packed = (ArrayBuffer | Buffer | ReadableStream | string | String | TypedArray) & {
63
+ parent?: SyncOrAsyncMap|null;
64
+ unpack?(): Promise<any>;
65
+ };
66
+
67
+ export type PlainObject = {
68
+ [key: string]: any;
65
69
  };
66
-
67
- export type TreeTransform = (treelike: Treelike) => AsyncTree;
70
+
71
+ export type ReduceFn = (mapped: Map<any, any>, source: SyncOrAsyncMap) => any | Promise<any>;
72
+
73
+ export type Stringlike = string | HasString;
74
+
75
+ export type SyncOrAsyncMap = Map<any, any> | AsyncMap;
68
76
 
69
77
  export type TypedArray =
70
78
  Float32Array |
@@ -86,4 +94,4 @@ export type Unpackable = {
86
94
  */
87
95
  export type UnpackFunction = (input: Packed, options?: any) => any;
88
96
 
89
- export type ValueKeyFn = (value: any, key: any, innerTree: AsyncTree) => any;
97
+ export type ValueKeyFn = (value: any, key: any, map: SyncOrAsyncMap) => any;
package/main.js CHANGED
@@ -1,5 +1,4 @@
1
1
  // Exports for Node.js
2
2
 
3
3
  export * from "./shared.js";
4
- export { default as FileTree } from "./src/drivers/FileTree.js";
5
- export * as extension from "./src/extension.js";
4
+ export { default as FileMap } from "./src/drivers/FileMap.js";
package/package.json CHANGED
@@ -1,18 +1,15 @@
1
1
  {
2
2
  "name": "@weborigami/async-tree",
3
- "version": "0.5.8",
3
+ "version": "0.6.1",
4
4
  "description": "Asynchronous tree drivers based on standard JavaScript classes",
5
5
  "type": "module",
6
6
  "main": "./main.js",
7
7
  "browser": "./browser.js",
8
8
  "types": "./index.ts",
9
- "dependencies": {
10
- "@weborigami/types": "0.5.8"
11
- },
12
9
  "devDependencies": {
13
- "@types/node": "24.3.0",
14
- "puppeteer": "24.17.0",
15
- "typescript": "5.9.2"
10
+ "@types/node": "24.10.1",
11
+ "puppeteer": "24.30.0",
12
+ "typescript": "5.9.3"
16
13
  },
17
14
  "scripts": {
18
15
  "headlessTest": "node test/browser/headlessTest.js",
package/shared.js CHANGED
@@ -1,17 +1,19 @@
1
1
  // Exports for both Node.js and browser
2
2
 
3
- export { default as calendar } from "./src/drivers/calendarTree.js";
4
- export { default as constant } from "./src/drivers/constantTree.js";
5
- export { default as DeepMapTree } from "./src/drivers/DeepMapTree.js";
6
- export { default as DeepObjectTree } from "./src/drivers/DeepObjectTree.js";
7
- export { default as DeferredTree } from "./src/drivers/DeferredTree.js";
8
- export { default as ExplorableSiteTree } from "./src/drivers/ExplorableSiteTree.js";
9
- export { default as FunctionTree } from "./src/drivers/FunctionTree.js";
10
- export { default as MapTree } from "./src/drivers/MapTree.js";
11
- export { default as ObjectTree } from "./src/drivers/ObjectTree.js";
12
- export { default as SetTree } from "./src/drivers/SetTree.js";
13
- export { default as SiteTree } from "./src/drivers/SiteTree.js";
3
+ import { default as ExplorableSiteMap } from "./src/drivers/ExplorableSiteMap.js";
4
+ import { default as FileMap } from "./src/drivers/FileMap.js";
5
+ import { default as FunctionMap } from "./src/drivers/FunctionMap.js";
6
+ import { default as ObjectMap } from "./src/drivers/ObjectMap.js";
7
+ import { default as SetMap } from "./src/drivers/SetMap.js";
8
+ import { default as SiteMap } from "./src/drivers/SiteMap.js";
9
+
10
+ export { default as AsyncMap } from "./src/drivers/AsyncMap.js";
11
+ export { default as CalendarMap } from "./src/drivers/CalendarMap.js";
12
+ export { default as ConstantMap } from "./src/drivers/ConstantMap.js";
13
+ export { default as SyncMap } from "./src/drivers/SyncMap.js";
14
+ export * as extension from "./src/extension.js";
14
15
  export * as jsonKeys from "./src/jsonKeys.js";
16
+ export { default as reduce } from "./src/operations/reduce.js";
15
17
  export { default as scope } from "./src/operations/scope.js";
16
18
  export * as symbols from "./src/symbols.js";
17
19
  export * as trailingSlash from "./src/trailingSlash.js";
@@ -19,9 +21,9 @@ export { default as TraverseError } from "./src/TraverseError.js";
19
21
  export * as Tree from "./src/Tree.js";
20
22
  export { default as box } from "./src/utilities/box.js";
21
23
  export { default as castArraylike } from "./src/utilities/castArraylike.js";
24
+ export { default as getTreeArgument } from "./src/utilities/getMapArgument.js";
22
25
  export { default as getParent } from "./src/utilities/getParent.js";
23
26
  export { default as getRealmObjectPrototype } from "./src/utilities/getRealmObjectPrototype.js";
24
- export { default as getTreeArgument } from "./src/utilities/getTreeArgument.js";
25
27
  export { default as isPacked } from "./src/utilities/isPacked.js";
26
28
  export { default as isPlainObject } from "./src/utilities/isPlainObject.js";
27
29
  export { default as isStringlike } from "./src/utilities/isStringlike.js";
@@ -32,3 +34,63 @@ export { default as pathFromKeys } from "./src/utilities/pathFromKeys.js";
32
34
  export { default as setParent } from "./src/utilities/setParent.js";
33
35
  export { default as toPlainValue } from "./src/utilities/toPlainValue.js";
34
36
  export { default as toString } from "./src/utilities/toString.js";
37
+
38
+ export { ExplorableSiteMap, FileMap, FunctionMap, ObjectMap, SetMap, SiteMap };
39
+
40
+ export class DeepObjectMap extends ObjectMap {
41
+ constructor(object) {
42
+ super(object, { deep: true });
43
+ console.warn("DeepObjectMap is deprecated. Please use ObjectMap instead.");
44
+ }
45
+ }
46
+
47
+ export class ObjectTree extends ObjectMap {
48
+ constructor(...args) {
49
+ super(...args);
50
+ console.warn("ObjectTree is deprecated. Please use ObjectMap instead.");
51
+ }
52
+ }
53
+
54
+ export class DeepObjectTree extends ObjectMap {
55
+ constructor(object) {
56
+ super(object, { deep: true });
57
+ console.warn("DeepObjectTree is deprecated. Please use ObjectMap instead.");
58
+ }
59
+ }
60
+
61
+ export class ExplorableSiteTree extends ExplorableSiteMap {
62
+ constructor(href) {
63
+ super(href);
64
+ console.warn(
65
+ "ExplorableSiteTree is deprecated. Please use ExplorableSiteMap instead."
66
+ );
67
+ }
68
+ }
69
+
70
+ export class FileTree extends FileMap {
71
+ constructor(...args) {
72
+ super(...args);
73
+ console.warn("FileTree is deprecated. Please use FileMap instead.");
74
+ }
75
+ }
76
+
77
+ export class FunctionTree extends FunctionMap {
78
+ constructor(...args) {
79
+ super(...args);
80
+ console.warn("FunctionTree is deprecated. Please use FunctionMap instead.");
81
+ }
82
+ }
83
+
84
+ export class SetTree extends SetMap {
85
+ constructor(set) {
86
+ super(set);
87
+ console.warn("SetTree is deprecated. Please use SetMap instead.");
88
+ }
89
+ }
90
+
91
+ export class SiteTree extends SiteMap {
92
+ constructor(...args) {
93
+ super(...args);
94
+ console.warn("SiteTree is deprecated. Please use SiteMap instead.");
95
+ }
96
+ }
package/src/Tree.js CHANGED
@@ -2,12 +2,14 @@
2
2
  * Collection of functions for working with async trees
3
3
  */
4
4
 
5
- export { default as calendar } from "./drivers/calendarTree.js";
6
- export { default as constant } from "./drivers/constantTree.js";
7
5
  export { default as addNextPrevious } from "./operations/addNextPrevious.js";
8
6
  export { default as assign } from "./operations/assign.js";
9
7
  export { default as cache } from "./operations/cache.js";
8
+ export { default as calendar } from "./operations/calendar.js";
9
+ export { default as child } from "./operations/child.js";
10
10
  export { default as clear } from "./operations/clear.js";
11
+ export { default as constant } from "./operations/constant.js";
12
+ export { default as deepEntries } from "./operations/deepEntries.js";
11
13
  export { default as deepMap } from "./operations/deepMap.js";
12
14
  export { default as deepMerge } from "./operations/deepMerge.js";
13
15
  export { default as deepReverse } from "./operations/deepReverse.js";
@@ -30,6 +32,9 @@ export { default as inners } from "./operations/inners.js";
30
32
  export { default as invokeFunctions } from "./operations/invokeFunctions.js";
31
33
  export { default as isAsyncMutableTree } from "./operations/isAsyncMutableTree.js";
32
34
  export { default as isAsyncTree } from "./operations/isAsyncTree.js";
35
+ export { default as isMap } from "./operations/isMap.js";
36
+ export { default as isMaplike } from "./operations/isMaplike.js";
37
+ export { default as isReadOnlyMap } from "./operations/isReadOnlyMap.js";
33
38
  export { default as isTraversable } from "./operations/isTraversable.js";
34
39
  export { default as isTreelike } from "./operations/isTreelike.js";
35
40
  export { default as json } from "./operations/json.js";
@@ -45,12 +50,16 @@ export { default as paginate } from "./operations/paginate.js";
45
50
  export { default as parent } from "./operations/parent.js";
46
51
  export { default as paths } from "./operations/paths.js";
47
52
  export { default as plain } from "./operations/plain.js";
53
+ export { default as reduce } from "./operations/reduce.js";
48
54
  export { default as regExpKeys } from "./operations/regExpKeys.js";
49
55
  export { default as reverse } from "./operations/reverse.js";
50
56
  export { default as root } from "./operations/root.js";
51
57
  export { default as scope } from "./operations/scope.js";
58
+ export { default as set } from "./operations/set.js";
52
59
  export { default as shuffle } from "./operations/shuffle.js";
60
+ export { default as size } from "./operations/size.js";
53
61
  export { default as sort } from "./operations/sort.js";
62
+ export { default as sync } from "./operations/sync.js";
54
63
  export { default as take } from "./operations/take.js";
55
64
  export { default as text } from "./operations/text.js";
56
65
  export { default as toFunction } from "./operations/toFunction.js";
@@ -0,0 +1,237 @@
1
+ import isMap from "../operations/isMap.js";
2
+ import * as trailingSlash from "../trailingSlash.js";
3
+
4
+ /**
5
+ * Base class for asynchronous maps. These have the same interface as Map but the methods
6
+ * are asynchronous.
7
+ *
8
+ * @typedef {import("../../index.ts").AsyncTree<AsyncMap>} AsyncTree
9
+ * @implements {AsyncTree}
10
+ */
11
+ export default class AsyncMap {
12
+ /** @type {AsyncMap|null} */
13
+ _parent = null;
14
+
15
+ _readOnly;
16
+
17
+ [Symbol.asyncIterator]() {
18
+ return this.entries();
19
+ }
20
+
21
+ /**
22
+ * Return the child node for the given key, creating it if necessary.
23
+ */
24
+ async child(key) {
25
+ let result = await this.get(key);
26
+
27
+ // If child is already a map we can use it as is
28
+ if (!isMap(result)) {
29
+ // Create new child node using no-arg constructor
30
+ result = new /** @type {any} */ (this.constructor)();
31
+ await this.set(key, result);
32
+ }
33
+
34
+ result.parent = this;
35
+ return result;
36
+ }
37
+
38
+ /**
39
+ * Remove all key/value entries from the map.
40
+ *
41
+ * This method invokes the `keys()` and `delete()` methods.
42
+ */
43
+ async clear() {
44
+ const promises = [];
45
+ for await (const key of this.keys()) {
46
+ promises.push(this.delete(key));
47
+ }
48
+ await Promise.all(promises);
49
+ }
50
+
51
+ /**
52
+ * Removes the entry for the given key, return true if an entry was removed
53
+ * and false if there was no entry for the key.
54
+ *
55
+ * @param {any} key
56
+ * @returns {Promise<boolean>}
57
+ */
58
+ async delete(key) {
59
+ throw new Error("delete() not implemented");
60
+ }
61
+
62
+ /**
63
+ * Returns a new `AsyncIterator` object that contains a two-member array of
64
+ * [key, value] for each element in the map in insertion order.
65
+ *
66
+ * This method invokes the `keys()` and `get()` methods.
67
+ *
68
+ * @returns {AsyncIterableIterator<[any, any]>}
69
+ */
70
+ async *entries() {
71
+ const keys = [];
72
+ const valuePromises = [];
73
+ // Invoke get() calls without waiting; some may take longer than others
74
+ for await (const key of this.keys()) {
75
+ keys.push(key);
76
+ valuePromises.push(this.get(key));
77
+ }
78
+ // Now wait for all promises to resolve
79
+ const values = await Promise.all(valuePromises);
80
+ for (let i = 0; i < keys.length; i++) {
81
+ yield [keys[i], values[i]];
82
+ }
83
+ }
84
+
85
+ /**
86
+ * Calls `callback` once for each key/value pair in the map, in insertion order.
87
+ *
88
+ * This method invokes the `entries()` method.
89
+ *
90
+ * @param {(value: any, key: any, thisArg: any) => Promise<void>} callback
91
+ * @param {any?} thisArg
92
+ */
93
+ async forEach(callback, thisArg = this) {
94
+ for await (const [key, value] of this.entries()) {
95
+ await callback(value, key, thisArg);
96
+ }
97
+ }
98
+
99
+ /**
100
+ * Returns the value associated with the key, or undefined if there is none.
101
+ *
102
+ * @param {any} key
103
+ * @returns {Promise<any>}
104
+ */
105
+ async get(key) {
106
+ throw new Error("get() not implemented");
107
+ }
108
+
109
+ /**
110
+ * Groups items from an async iterable into an AsyncMap according to the keys
111
+ * returned by the given function.
112
+ *
113
+ * @param {Iterable<any>|AsyncIterable<any>} iterable
114
+ * @param {(element: any, index: any) => Promise<any>} keyFn
115
+ * @returns {Promise<Map>}
116
+ */
117
+ static async groupBy(iterable, keyFn) {
118
+ const map = new Map();
119
+ let index = 0;
120
+ for await (const element of iterable) {
121
+ const key = await keyFn(element, index);
122
+ if (!map.has(key)) {
123
+ map.set(key, []);
124
+ }
125
+ map.get(key).push(element);
126
+ index++;
127
+ }
128
+ return map;
129
+ }
130
+
131
+ /**
132
+ * Returns true if the given key appears in the set returned by keys().
133
+ *
134
+ * It doesn't matter whether the value returned by get() is defined or not.
135
+ *
136
+ * If the requested key has a trailing slash but has no associated value, but
137
+ * the alternate form with a slash does appear, this returns true.
138
+ *
139
+ * @param {any} key
140
+ */
141
+ async has(key) {
142
+ const alternateKey = !trailingSlash.has(key)
143
+ ? trailingSlash.add(key)
144
+ : null;
145
+ for await (const k of this.keys()) {
146
+ if (k === key) {
147
+ return true;
148
+ }
149
+ if (alternateKey && k === alternateKey) {
150
+ return true;
151
+ }
152
+ }
153
+ return false;
154
+ }
155
+
156
+ /**
157
+ * Returns a new `AsyncIterator` object that contains the keys for each
158
+ * element in the map in insertion order.
159
+ *
160
+ * @returns {AsyncIterableIterator<any>}
161
+ */
162
+ async *keys() {
163
+ throw new Error("keys() not implemented");
164
+ }
165
+
166
+ /**
167
+ * The parent of this node in a tree.
168
+ */
169
+ get parent() {
170
+ return this._parent;
171
+ }
172
+ set parent(parent) {
173
+ this._parent = parent;
174
+ }
175
+
176
+ /**
177
+ * True if the object is read-only. This will be true if `get()` has been
178
+ * overridden but `set()` and `delete()` have not.
179
+ */
180
+ get readOnly() {
181
+ return (
182
+ this.get !== AsyncMap.prototype.get &&
183
+ (this.set === AsyncMap.prototype.set ||
184
+ this.delete === AsyncMap.prototype.delete)
185
+ );
186
+ }
187
+
188
+ /**
189
+ * Sets the value for the given key.
190
+ *
191
+ * @param {any} key
192
+ * @param {any} value
193
+ * @returns {Promise<AsyncMap>}
194
+ */
195
+ async set(key, value) {
196
+ throw new Error("set() not implemented");
197
+ }
198
+
199
+ /**
200
+ * Returns the number of keys in the map.
201
+ *
202
+ * The `size` property invokes an overridden `keys()` to ensure proper
203
+ * behavior in subclasses. Because a subclass may not enforce a direct
204
+ * correspondence between `keys()` and `get()`, the size may not reflect the
205
+ * number of values that can be retrieved.
206
+ *
207
+ * @type {Promise<number>}
208
+ */
209
+ get size() {
210
+ return (async () => {
211
+ let count = 0;
212
+ for await (const _ of this.keys()) {
213
+ count++;
214
+ }
215
+ return count;
216
+ })();
217
+ }
218
+
219
+ trailingSlashKeys = false;
220
+
221
+ /**
222
+ * Returns a new `AsyncIterator` object that contains the values for each
223
+ * element in the map in insertion order.
224
+ *
225
+ * @returns {AsyncIterableIterator<any>}
226
+ */
227
+ async *values() {
228
+ const valuePromises = [];
229
+ // Invoke get() calls without waiting; some may take longer than others
230
+ for await (const key of this.keys()) {
231
+ valuePromises.push(this.get(key));
232
+ }
233
+ // Now wait for all promises to resolve
234
+ const values = await Promise.all(valuePromises);
235
+ yield* values;
236
+ }
237
+ }