dirvi-lib 0.11.0-beta.1 → 0.11.0-beta.13

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 (164) hide show
  1. package/dist/app/app-methods.d.ts +53 -0
  2. package/dist/app/app-methods.d.ts.map +1 -0
  3. package/dist/app/index.d.ts +1 -1
  4. package/dist/app/index.d.ts.map +1 -1
  5. package/dist/app/index.js +1 -1
  6. package/dist/app/reducer/effect-to-action.d.ts +2 -2
  7. package/dist/app/reducer/effect-to-action.d.ts.map +1 -1
  8. package/dist/app/reducer/effect-to-action.js +87 -32
  9. package/dist/app/reducer/reducer-action.d.ts +12 -6
  10. package/dist/app/reducer/reducer-action.d.ts.map +1 -1
  11. package/dist/app/reducer/reducer.d.ts +4 -2
  12. package/dist/app/reducer/reducer.d.ts.map +1 -1
  13. package/dist/app/reducer/reducer.js +106 -72
  14. package/dist/feedback/feedback.impl.d.ts.map +1 -1
  15. package/dist/feedback/feedback.types.d.ts +1 -1
  16. package/dist/feedback/feedback.types.d.ts.map +1 -1
  17. package/dist/index.d.ts +1 -1
  18. package/dist/index.d.ts.map +1 -1
  19. package/dist/index.js +1 -1
  20. package/dist/input/application/intent-to-effect.d.ts +2 -2
  21. package/dist/input/application/intent-to-effect.d.ts.map +1 -1
  22. package/dist/input/application/intent-to-effect.js +10 -11
  23. package/dist/input/application/parse-ex-command.d.ts +17 -0
  24. package/dist/input/application/parse-ex-command.d.ts.map +1 -0
  25. package/dist/input/application/{parse-command.js → parse-ex-command.js} +84 -54
  26. package/dist/input/application/parse-normal-command.d.ts +1 -1
  27. package/dist/input/application/parse-normal-command.d.ts.map +1 -1
  28. package/dist/input/domain/effect.d.ts +20 -9
  29. package/dist/input/domain/effect.d.ts.map +1 -1
  30. package/dist/state-and-nav/cursor.d.ts +89 -0
  31. package/dist/state-and-nav/cursor.d.ts.map +1 -0
  32. package/dist/state-and-nav/cursor.js +84 -0
  33. package/dist/{trees → state-and-nav}/fold-node/deprecated/fold-node.impl.d.ts +1 -1
  34. package/dist/state-and-nav/fold-node/deprecated/fold-node.impl.d.ts.map +1 -0
  35. package/dist/state-and-nav/fold-node/deprecated/fold-node.test.d.ts.map +1 -0
  36. package/dist/{trees → state-and-nav}/fold-node/deprecated/fold-node.test.js +2 -2
  37. package/dist/{trees → state-and-nav}/fold-node/deprecated/fold-node.types.d.ts +2 -2
  38. package/dist/state-and-nav/fold-node/deprecated/fold-node.types.d.ts.map +1 -0
  39. package/dist/{trees → state-and-nav}/fold-node/fold-node.impl.d.ts +3 -3
  40. package/dist/state-and-nav/fold-node/fold-node.impl.d.ts.map +1 -0
  41. package/dist/{trees → state-and-nav}/fold-node/fold-node.impl.js +2 -2
  42. package/dist/{trees → state-and-nav}/fold-node/fold-node.model.d.ts +1 -1
  43. package/dist/state-and-nav/fold-node/fold-node.model.d.ts.map +1 -0
  44. package/dist/{trees → state-and-nav}/fold-node/fold-node.types.d.ts +2 -2
  45. package/dist/state-and-nav/fold-node/fold-node.types.d.ts.map +1 -0
  46. package/dist/state-and-nav/fold-node/index.d.ts.map +1 -0
  47. package/dist/state-and-nav/index.d.ts +16 -0
  48. package/dist/state-and-nav/index.d.ts.map +1 -0
  49. package/dist/state-and-nav/index.js +6 -0
  50. package/dist/state-and-nav/nav/nav.ordered.impl.d.ts +12 -0
  51. package/dist/state-and-nav/nav/nav.ordered.impl.d.ts.map +1 -0
  52. package/dist/state-and-nav/nav/nav.ordered.impl.js +77 -0
  53. package/dist/state-and-nav/nav/nav.traversal.d.ts +11 -0
  54. package/dist/state-and-nav/nav/nav.traversal.d.ts.map +1 -0
  55. package/dist/state-and-nav/nav/nav.traversal.js +204 -0
  56. package/dist/{trees/nav-node/nav-node.types.d.ts → state-and-nav/nav/nav.types.d.ts} +37 -23
  57. package/dist/state-and-nav/nav/nav.types.d.ts.map +1 -0
  58. package/dist/state-and-nav/nav/nav.unordered.impl.d.ts +13 -0
  59. package/dist/state-and-nav/nav/nav.unordered.impl.d.ts.map +1 -0
  60. package/dist/state-and-nav/nav/nav.unordered.impl.js +77 -0
  61. package/dist/state-and-nav/state/state.impl.d.ts +9 -0
  62. package/dist/state-and-nav/state/state.impl.d.ts.map +1 -0
  63. package/dist/{trees → state-and-nav}/state/state.impl.js +62 -9
  64. package/dist/state-and-nav/state/state.schemas.d.ts +2 -0
  65. package/dist/state-and-nav/state/state.schemas.d.ts.map +1 -0
  66. package/dist/state-and-nav/state/state.schemas.js +39 -0
  67. package/dist/state-and-nav/state/state.types.d.ts +72 -0
  68. package/dist/state-and-nav/state/state.types.d.ts.map +1 -0
  69. package/dist/state-and-nav/tree/deprecated/tree-node.arb.d.ts.map +1 -0
  70. package/dist/state-and-nav/tree/deprecated/tree-node.arb.debug.test.d.ts.map +1 -0
  71. package/dist/state-and-nav/tree/deprecated/tree-node.impl.d.ts.map +1 -0
  72. package/dist/state-and-nav/tree/deprecated/tree-node.schemas.d.ts.map +1 -0
  73. package/dist/state-and-nav/tree/deprecated/tree-node.test.d.ts.map +1 -0
  74. package/dist/state-and-nav/tree/deprecated/tree-node.types.d.ts.map +1 -0
  75. package/dist/state-and-nav/tree/index.d.ts +7 -0
  76. package/dist/state-and-nav/tree/index.d.ts.map +1 -0
  77. package/dist/state-and-nav/tree/index.js +1 -0
  78. package/dist/state-and-nav/tree/tree-node.arb.d.ts +94 -0
  79. package/dist/state-and-nav/tree/tree-node.arb.d.ts.map +1 -0
  80. package/dist/state-and-nav/tree/tree-node.arb.debug.test.d.ts +2 -0
  81. package/dist/state-and-nav/tree/tree-node.arb.debug.test.d.ts.map +1 -0
  82. package/dist/state-and-nav/tree/tree-node.arb.debug.test.js +54 -0
  83. package/dist/state-and-nav/tree/tree-node.arb.js +188 -0
  84. package/dist/state-and-nav/tree/tree-node.model.d.ts +194 -0
  85. package/dist/state-and-nav/tree/tree-node.model.d.ts.map +1 -0
  86. package/dist/state-and-nav/tree/tree-node.model.js +110 -0
  87. package/dist/state-and-nav/tree/tree-node.test.d.ts +2 -0
  88. package/dist/state-and-nav/tree/tree-node.test.d.ts.map +1 -0
  89. package/dist/state-and-nav/tree/tree-node.test.js +234 -0
  90. package/dist/{trees/tree-node/tree-node.impl.d.ts → state-and-nav/tree/tree.impl.d.ts} +3 -3
  91. package/dist/state-and-nav/tree/tree.impl.d.ts.map +1 -0
  92. package/dist/{trees/tree-node/tree-node.impl.js → state-and-nav/tree/tree.impl.js} +20 -17
  93. package/dist/{trees/tree-node/tree-node.types.d.ts → state-and-nav/tree/tree.types.d.ts} +67 -47
  94. package/dist/state-and-nav/tree/tree.types.d.ts.map +1 -0
  95. package/dist/state-and-nav/tree/tree.types.js +1 -0
  96. package/package.json +3 -2
  97. package/dist/app/app-api.d.ts +0 -74
  98. package/dist/app/app-api.d.ts.map +0 -1
  99. package/dist/app/app-api.js +0 -11
  100. package/dist/input/application/parse-command.d.ts +0 -14
  101. package/dist/input/application/parse-command.d.ts.map +0 -1
  102. package/dist/trees/cursor.d.ts +0 -59
  103. package/dist/trees/cursor.d.ts.map +0 -1
  104. package/dist/trees/cursor.js +0 -55
  105. package/dist/trees/fold-node/deprecated/fold-node.impl.d.ts.map +0 -1
  106. package/dist/trees/fold-node/deprecated/fold-node.test.d.ts.map +0 -1
  107. package/dist/trees/fold-node/deprecated/fold-node.types.d.ts.map +0 -1
  108. package/dist/trees/fold-node/fold-node.impl.d.ts.map +0 -1
  109. package/dist/trees/fold-node/fold-node.model.d.ts.map +0 -1
  110. package/dist/trees/fold-node/fold-node.types.d.ts.map +0 -1
  111. package/dist/trees/fold-node/index.d.ts.map +0 -1
  112. package/dist/trees/index.d.ts +0 -9
  113. package/dist/trees/index.d.ts.map +0 -1
  114. package/dist/trees/index.js +0 -8
  115. package/dist/trees/nav-node/nav-node.impl.d.ts +0 -29
  116. package/dist/trees/nav-node/nav-node.impl.d.ts.map +0 -1
  117. package/dist/trees/nav-node/nav-node.impl.js +0 -223
  118. package/dist/trees/nav-node/nav-node.types.d.ts.map +0 -1
  119. package/dist/trees/state/state.impl.d.ts +0 -8
  120. package/dist/trees/state/state.impl.d.ts.map +0 -1
  121. package/dist/trees/state/state.schemas.d.ts +0 -25
  122. package/dist/trees/state/state.schemas.d.ts.map +0 -1
  123. package/dist/trees/state/state.schemas.js +0 -17
  124. package/dist/trees/state/state.types.d.ts +0 -36
  125. package/dist/trees/state/state.types.d.ts.map +0 -1
  126. package/dist/trees/tree-node/deprecated/tree-node.arb.d.ts.map +0 -1
  127. package/dist/trees/tree-node/deprecated/tree-node.arb.debug.test.d.ts.map +0 -1
  128. package/dist/trees/tree-node/deprecated/tree-node.impl.d.ts.map +0 -1
  129. package/dist/trees/tree-node/deprecated/tree-node.schemas.d.ts.map +0 -1
  130. package/dist/trees/tree-node/deprecated/tree-node.test.d.ts.map +0 -1
  131. package/dist/trees/tree-node/deprecated/tree-node.types.d.ts.map +0 -1
  132. package/dist/trees/tree-node/index.d.ts +0 -5
  133. package/dist/trees/tree-node/index.d.ts.map +0 -1
  134. package/dist/trees/tree-node/index.js +0 -2
  135. package/dist/trees/tree-node/tree-node.arb.d.ts +0 -104
  136. package/dist/trees/tree-node/tree-node.arb.d.ts.map +0 -1
  137. package/dist/trees/tree-node/tree-node.arb.js +0 -188
  138. package/dist/trees/tree-node/tree-node.impl.d.ts.map +0 -1
  139. package/dist/trees/tree-node/tree-node.model.d.ts +0 -78
  140. package/dist/trees/tree-node/tree-node.model.d.ts.map +0 -1
  141. package/dist/trees/tree-node/tree-node.model.js +0 -37
  142. package/dist/trees/tree-node/tree-node.types.d.ts.map +0 -1
  143. /package/dist/{trees/fold-node/deprecated/fold-node.types.js → app/app-methods.js} +0 -0
  144. /package/dist/{trees → state-and-nav}/fold-node/deprecated/fold-node.impl.js +0 -0
  145. /package/dist/{trees → state-and-nav}/fold-node/deprecated/fold-node.test.d.ts +0 -0
  146. /package/dist/{trees/fold-node → state-and-nav/fold-node/deprecated}/fold-node.types.js +0 -0
  147. /package/dist/{trees → state-and-nav}/fold-node/fold-node.model.js +0 -0
  148. /package/dist/{trees/nav-node/nav-node.types.js → state-and-nav/fold-node/fold-node.types.js} +0 -0
  149. /package/dist/{trees → state-and-nav}/fold-node/index.d.ts +0 -0
  150. /package/dist/{trees → state-and-nav}/fold-node/index.js +0 -0
  151. /package/dist/{trees/state/state.types.js → state-and-nav/nav/nav.types.js} +0 -0
  152. /package/dist/{trees/tree-node/deprecated/tree-node.types.js → state-and-nav/state/state.types.js} +0 -0
  153. /package/dist/{trees/tree-node → state-and-nav/tree}/deprecated/tree-node.arb.d.ts +0 -0
  154. /package/dist/{trees/tree-node → state-and-nav/tree}/deprecated/tree-node.arb.debug.test.d.ts +0 -0
  155. /package/dist/{trees/tree-node → state-and-nav/tree}/deprecated/tree-node.arb.debug.test.js +0 -0
  156. /package/dist/{trees/tree-node → state-and-nav/tree}/deprecated/tree-node.arb.js +0 -0
  157. /package/dist/{trees/tree-node → state-and-nav/tree}/deprecated/tree-node.impl.d.ts +0 -0
  158. /package/dist/{trees/tree-node → state-and-nav/tree}/deprecated/tree-node.impl.js +0 -0
  159. /package/dist/{trees/tree-node → state-and-nav/tree}/deprecated/tree-node.schemas.d.ts +0 -0
  160. /package/dist/{trees/tree-node → state-and-nav/tree}/deprecated/tree-node.schemas.js +0 -0
  161. /package/dist/{trees/tree-node → state-and-nav/tree}/deprecated/tree-node.test.d.ts +0 -0
  162. /package/dist/{trees/tree-node → state-and-nav/tree}/deprecated/tree-node.test.js +0 -0
  163. /package/dist/{trees/tree-node → state-and-nav/tree}/deprecated/tree-node.types.d.ts +0 -0
  164. /package/dist/{trees/tree-node → state-and-nav/tree/deprecated}/tree-node.types.js +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tree-node.schemas.d.ts","sourceRoot":"","sources":["../../../../src/state-and-nav/tree/deprecated/tree-node.schemas.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAEjE;;;;;;;;;GASG;AACH,eAAO,MAAM,qBAAqB,iDAA6C,CAAC;AAEhF;;;;GAIG;AACH,wBAAgB,qBAAqB,CACnC,EAAE,SAAS,eAAe,EAC1B,IAAI,SAAS,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC,EAC/B,QAAQ,EAAE,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,UAAU,EAAE,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC;;;;;;;;;;;;EAoBrD"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tree-node.test.d.ts","sourceRoot":"","sources":["../../../../src/state-and-nav/tree/deprecated/tree-node.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tree-node.types.d.ts","sourceRoot":"","sources":["../../../../src/state-and-nav/tree/deprecated/tree-node.types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,MAAM,CAAC;AAE9C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,MAAM,MAAM,QAAQ,CAClB,EAAE,SAAS,eAAe,EAC1B,IAAI,SAAS,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC,IAC7B,YAAY,CAAC,EAAE,CAAC,GAAG,cAAc,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;AAEhD,+BAA+B;AAC/B,MAAM,MAAM,YAAY,CAAC,EAAE,SAAS,eAAe,IAAI;IACrD,EAAE,EAAE,EAAE,CAAC;IACP,QAAQ,CAAC,EAAE,KAAK,CAAC;CAClB,CAAC;AAEF,gEAAgE;AAChE,MAAM,MAAM,cAAc,CACxB,EAAE,SAAS,eAAe,EAC1B,IAAI,SAAS,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC,IAC7B,kBAAkB,CAAC,EAAE,EAAE,IAAI,CAAC,GAAG,oBAAoB,CAAC,EAAE,CAAC,CAAC;AAE5D,uDAAuD;AACvD,MAAM,MAAM,kBAAkB,CAC5B,EAAE,SAAS,eAAe,EAC1B,IAAI,SAAS,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC,IAC7B;IACF,EAAE,EAAE,EAAE,CAAC;IACP,QAAQ,EAAE,IAAI,EAAE,CAAC;CAClB,CAAC;AAEF,2DAA2D;AAC3D,MAAM,MAAM,oBAAoB,CAAC,EAAE,SAAS,eAAe,IAAI;IAC7D,EAAE,EAAE,EAAE,CAAC;IACP,QAAQ,EAAE,IAAI,CAAC;CAChB,CAAC;AAEF;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,MAAM,WAAW,CACrB,EAAE,SAAS,eAAe,EAC1B,IAAI,SAAS,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC,IAC7B;IACF,MAAM,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,YAAY,CAAC,EAAE,CAAC,CAAC;IACpD,QAAQ,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,cAAc,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;IAC9D,cAAc,CACZ,IAAI,EAAE,cAAc,CAAC,EAAE,EAAE,IAAI,CAAC,GAC7B,IAAI,IAAI,oBAAoB,CAAC,EAAE,CAAC,CAAC;IACpC,YAAY,CACV,IAAI,EAAE,cAAc,CAAC,EAAE,EAAE,IAAI,CAAC,GAC7B,IAAI,IAAI,kBAAkB,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;IAExC;;;;;;;;OAQG;IACH,WAAW,CAAC,IAAI,EAAE,kBAAkB,CAAC,EAAE,EAAE,IAAI,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;IAEhE;;;;;;OAMG;IACH,YAAY,CAAC,IAAI,EAAE,kBAAkB,CAAC,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE,EAAE,EAAE,GAAG,IAAI,GAAG,SAAS,CAAC;IAE3E;;;;;;;;;;;OAWG;IACH,SAAS,CAAC,MAAM,EACd,IAAI,EAAE,IAAI,EACV,IAAI,EAAE,SAAS,EAAE,EAAE,EACnB,QAAQ,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,MAAM,GAC/B,MAAM,GAAG,SAAS,CAAC;IAEtB;;;;;;;;;;;;;;;OAeG;IACH,YAAY,CACV,IAAI,EAAE,IAAI,EACV,IAAI,EAAE,SAAS,EAAE,EAAE,EACnB,QAAQ,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,IAAI,GAAG,SAAS,GACzC,IAAI,GAAG,SAAS,CAAC;CACrB,CAAC"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * To be used as the dependencies of State and Navigation.
3
+ */
4
+ export type { SerializableKey } from './tree-node.model.js';
5
+ export type * from './tree.types.js';
6
+ export { createTreeMethods } from './tree.impl.js';
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/state-and-nav/tree/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,YAAY,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAC5D,mBAAmB,iBAAiB,CAAC;AACrC,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC"}
@@ -0,0 +1 @@
1
+ export { createTreeMethods } from './tree.impl.js';
@@ -0,0 +1,94 @@
1
+ import * as fc from 'fast-check';
2
+ import { TreeNodeModel } from './tree-node.model.js';
3
+ /**
4
+ * The ID and Values types used for the generated test trees.
5
+ *
6
+ * Short strings keep generated counterexamples readable. Values just have to
7
+ * be something easily checked for equality.
8
+ */
9
+ type Id = string;
10
+ type Value = number;
11
+ type ModelAndPath = {
12
+ model: TreeNodeModel<Id, Value>;
13
+ path: Id[];
14
+ };
15
+ /**
16
+ * A model and a pair of a model and its path for every reachable path in the
17
+ * model
18
+ *
19
+ * Includes this model at `[]` and every descendant reachable through loaded
20
+ * branches. Descendants behind unloaded branches are intentionally absent.
21
+ */
22
+ type ModelWithReachableModels = {
23
+ model: TreeNodeModel<Id, Value>;
24
+ reachableModels: ModelAndPath[];
25
+ };
26
+ /**
27
+ * Generates valid string IDs for test nodes. Note that the API just does
28
+ * comparisons on the IDs so we can safely restrict to any subset.
29
+ */
30
+ export declare const idArb: fc.Arbitrary<string>;
31
+ /**
32
+ * Generates serializable application values for test nodes.
33
+ */
34
+ export declare const valueArb: fc.Arbitrary<number>;
35
+ /**
36
+ * Generates a leaf model.
37
+ */
38
+ export declare const leafModelWRMArb: fc.Arbitrary<ModelWithReachableModels>;
39
+ /**
40
+ * Generates an unloaded-branch model.
41
+ */
42
+ export declare const unloadedBranchModelWRMArb: fc.Arbitrary<ModelWithReachableModels>;
43
+ /**
44
+ * Generates a leaf, an unloaded branch, or a loaded branch.
45
+ *
46
+ * Loaded branches have unique child IDs. Root IDs are made unique separately
47
+ * when generating a forest.
48
+ *
49
+ * The weighted choice gives recursive loaded branches a geometric drop off.
50
+ */
51
+ export declare const modelWithReachableModelsArb: fc.Arbitrary<ModelWithReachableModels>;
52
+ /**
53
+ * Generates an array of generated models with unique sibling IDs.
54
+ *
55
+ * The result is suitable for use as the loaded children of a loaded branch.
56
+ */
57
+ export declare const siblingModelsWRMArb: fc.Arbitrary<ModelWithReachableModels[]>;
58
+ /**
59
+ * Generates root-level models and a path to one of their reachable models.
60
+ *
61
+ * Every generated path is valid for `getAtPath`; unreachable paths are not
62
+ * included.
63
+ */
64
+ export declare const modelAndReachablePathArb: fc.Arbitrary<{
65
+ root: TreeNodeModel<string, number>;
66
+ path: string[];
67
+ expected: TreeNodeModel<string, number>;
68
+ }>;
69
+ /**
70
+ * Generates a root model and a path to one of its reachable branch models.
71
+ *
72
+ * Both loaded and unloaded branches are included.
73
+ */
74
+ export declare const modelAndBranchPathArb: fc.Arbitrary<{
75
+ root: TreeNodeModel<string, number>;
76
+ path: string[];
77
+ expected: TreeNodeModel<string, number>;
78
+ }>;
79
+ /**
80
+ * Generates a new array of loaded child models.
81
+ *
82
+ * The generated models have unique IDs, making the result suitable for use as
83
+ * the children of a loaded branch.
84
+ */
85
+ export declare const childrenModelsArb: fc.Arbitrary<TreeNodeModel<string, number>[]>;
86
+ /**
87
+ * Generates either a new array of loaded child models or `null`.
88
+ *
89
+ * An array represents a loaded branch, including a loaded branch with no
90
+ * children. `null` represents an unloaded branch.
91
+ */
92
+ export declare const childrenStateModelArb: fc.Arbitrary<TreeNodeModel<string, number>[] | null>;
93
+ export {};
94
+ //# sourceMappingURL=tree-node.arb.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tree-node.arb.d.ts","sourceRoot":"","sources":["../../../src/state-and-nav/tree/tree-node.arb.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,YAAY,CAAC;AAEjC,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAErD;;;;;GAKG;AACH,KAAK,EAAE,GAAG,MAAM,CAAC;AACjB,KAAK,KAAK,GAAG,MAAM,CAAC;AAEpB,KAAK,YAAY,GAAG;IAClB,KAAK,EAAE,aAAa,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;IAChC,IAAI,EAAE,EAAE,EAAE,CAAC;CACZ,CAAC;AAEF;;;;;;GAMG;AACH,KAAK,wBAAwB,GAAG;IAC9B,KAAK,EAAE,aAAa,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;IAChC,eAAe,EAAE,YAAY,EAAE,CAAC;CACjC,CAAC;AAWF;;;GAGG;AACH,eAAO,MAAM,KAAK,sBAIhB,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,QAAQ,sBAGnB,CAAC;AAyEH;;GAEG;AACH,eAAO,MAAM,eAAe,EAAE,EAAE,CAAC,SAAS,CAAC,wBAAwB,CAEhB,CAAC;AAEpD;;GAEG;AACH,eAAO,MAAM,yBAAyB,EAAE,EAAE,CAAC,SAAS,CAAC,wBAAwB,CAGd,CAAC;AAUhE;;;;;;;GAOG;AACH,eAAO,MAAM,2BAA2B,EAAE,EAAE,CAAC,SAAS,CAAC,wBAAwB,CAyCtE,CAAC;AASV;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,0CAI9B,CAAC;AAIH;;;;;GAKG;AACH,eAAO,MAAM,wBAAwB;;;;EAOpC,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,qBAAqB;;;;EAc/B,CAAC;AAEJ;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,+CAE7B,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB,sDAAiD,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=tree-node.arb.debug.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tree-node.arb.debug.test.d.ts","sourceRoot":"","sources":["../../../src/state-and-nav/tree/tree-node.arb.debug.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,54 @@
1
+ import { describe, it } from 'vitest';
2
+ import * as fc from 'fast-check';
3
+ import { modelWithReachableModelsArb, siblingModelsWRMArb } from './tree-node.arb.js';
4
+ /**
5
+ * Manual inspection of generated models and their reachable paths.
6
+ *
7
+ * Remove `.skip` temporarily to run these inspections.
8
+ * These are debugging aids, not assertions about the arbitraries.
9
+ */
10
+ describe.skip('inspect tree-node arbitraries', () => {
11
+ const seed = 12345;
12
+ it('prints generated models and reachable paths', () => {
13
+ const samples = fc.sample(modelWithReachableModelsArb, {
14
+ numRuns: 10,
15
+ seed,
16
+ });
17
+ for (const [index, generated] of samples.entries()) {
18
+ console.log(`\n--- model ${index + 1} ---`);
19
+ console.dir(generated.model, {
20
+ depth: Infinity,
21
+ colors: false,
22
+ });
23
+ console.log(`reachable nodes: ${generated.reachableModels.length}`, `maximum depth: ${Math.max(...generated.reachableModels.map(({ path }) => path.length))}`);
24
+ console.log('reachable paths:');
25
+ console.dir(generated.reachableModels.map(({ path, model }) => ({
26
+ path,
27
+ id: model.id,
28
+ kind: !('children' in model)
29
+ ? 'leaf'
30
+ : model.children === null
31
+ ? 'unloaded-branch'
32
+ : 'loaded-branch',
33
+ })), {
34
+ depth: Infinity,
35
+ colors: false,
36
+ });
37
+ }
38
+ });
39
+ it('prints generated sibling collections', () => {
40
+ const samples = fc.sample(siblingModelsWRMArb, {
41
+ numRuns: 5,
42
+ seed,
43
+ });
44
+ for (const [index, generatedNodes] of samples.entries()) {
45
+ console.log(`\n--- sibling collection ${index + 1} ---`);
46
+ console.dir(generatedNodes.map(({ model }) => model), {
47
+ depth: Infinity,
48
+ colors: false,
49
+ });
50
+ console.log('sibling IDs:', generatedNodes.map(({ model }) => model.id));
51
+ console.log('total reachable nodes:', generatedNodes.reduce((count, generated) => count + generated.reachableModels.length, 0));
52
+ }
53
+ });
54
+ });
@@ -0,0 +1,188 @@
1
+ import * as fc from 'fast-check';
2
+ // =============================================================================
3
+ // ID and Value Arbitraries
4
+ // =============================================================================
5
+ /**
6
+ * Characters used for readable generated node IDs.
7
+ */
8
+ const smallLetterCharacters = Array.from('abcdefghijklmnopqrstuvwxyz');
9
+ /**
10
+ * Generates valid string IDs for test nodes. Note that the API just does
11
+ * comparisons on the IDs so we can safely restrict to any subset.
12
+ */
13
+ export const idArb = fc.string({
14
+ unit: fc.constantFrom(...smallLetterCharacters),
15
+ minLength: 1,
16
+ maxLength: 8,
17
+ });
18
+ /**
19
+ * Generates serializable application values for test nodes.
20
+ */
21
+ export const valueArb = fc.integer({
22
+ min: -10_000,
23
+ max: 10_000,
24
+ });
25
+ // =============================================================================
26
+ // Generating Models with Reachable Models
27
+ // =============================================================================
28
+ // Helpers
29
+ const createLeafModel = (id, value) => {
30
+ const model = {
31
+ id,
32
+ value,
33
+ };
34
+ return {
35
+ model,
36
+ reachableModels: [{ path: [], model }],
37
+ };
38
+ };
39
+ function createUnloadedBranchModel(id, value) {
40
+ const model = {
41
+ id,
42
+ value,
43
+ children: null,
44
+ };
45
+ return {
46
+ model,
47
+ reachableModels: [{ path: [], model }],
48
+ };
49
+ }
50
+ /**
51
+ * Creates the metadata for a loaded branch and all descendants reachable
52
+ * through its loaded child collection.
53
+ *
54
+ * Child-array order is preserved, both in the model and in the enumeration
55
+ * of reachable descendants.
56
+ */
57
+ function createLoadedBranchModel(id, value, children) {
58
+ const model = {
59
+ id,
60
+ value,
61
+ children: children.map(({ model: child }) => child),
62
+ };
63
+ const reachableDescendants = children.flatMap(({ model: childModel, reachableModels }) => reachableModels.map(({ path, model: reachableModel }) => ({
64
+ path: [childModel.id, ...path],
65
+ model: reachableModel,
66
+ })));
67
+ return {
68
+ model,
69
+ reachableModels: [{ path: [], model }, ...reachableDescendants],
70
+ };
71
+ }
72
+ // Arbs
73
+ /**
74
+ * Generates a leaf model.
75
+ */
76
+ export const leafModelWRMArb = fc
77
+ .tuple(idArb, valueArb)
78
+ .map(([id, value]) => createLeafModel(id, value));
79
+ /**
80
+ * Generates an unloaded-branch model.
81
+ */
82
+ export const unloadedBranchModelWRMArb = fc
83
+ .tuple(idArb, valueArb)
84
+ .map(([id, value]) => createUnloadedBranchModel(id, value));
85
+ /**
86
+ * Generates either kind of 'terminal' model.
87
+ *
88
+ * Both leaves and unloaded branches terminate path traversal.
89
+ */
90
+ const terminalModelWRMArb = fc.oneof(leafModelWRMArb, unloadedBranchModelWRMArb);
91
+ /**
92
+ * Generates a leaf, an unloaded branch, or a loaded branch.
93
+ *
94
+ * Loaded branches have unique child IDs. Root IDs are made unique separately
95
+ * when generating a forest.
96
+ *
97
+ * The weighted choice gives recursive loaded branches a geometric drop off.
98
+ */
99
+ export const modelWithReachableModelsArb = fc.letrec((tie) => {
100
+ const generatedChildModelArb = tie('node');
101
+ /**
102
+ * Generates the loaded children of a loaded branch.
103
+ *
104
+ * Sibling IDs must be unique so that child lookup is unambiguous. The
105
+ * maximum length also limits the branching factor of recursive examples.
106
+ */
107
+ const generatedLoadedChildrenArb = fc.uniqueArray(generatedChildModelArb, {
108
+ minLength: 0,
109
+ maxLength: 4,
110
+ size: 'medium',
111
+ selector: ({ model }) => model.id,
112
+ });
113
+ /**
114
+ * Generates a loaded branch and its reachable descendants.
115
+ */
116
+ const generatedLoadedBranchModelArb = fc
117
+ .tuple(idArb, valueArb, generatedLoadedChildrenArb)
118
+ .map(([id, value, children]) => createLoadedBranchModel(id, value, children));
119
+ return {
120
+ node: fc
121
+ .integer({
122
+ min: 0,
123
+ max: 9999,
124
+ })
125
+ .chain((choice) =>
126
+ // 5046 works for getAtPath tests, but too heavy for modifyAtPath tests
127
+ choice >= 5050
128
+ ? generatedLoadedBranchModelArb
129
+ : terminalModelWRMArb),
130
+ };
131
+ }).node;
132
+ // =============================================================================
133
+ // Generating Models
134
+ // =============================================================================
135
+ // Prepares inputs for particular tests.
136
+ // Generating Replacement Child State
137
+ /**
138
+ * Generates an array of generated models with unique sibling IDs.
139
+ *
140
+ * The result is suitable for use as the loaded children of a loaded branch.
141
+ */
142
+ export const siblingModelsWRMArb = fc.uniqueArray(modelWithReachableModelsArb, {
143
+ minLength: 0,
144
+ size: 'small',
145
+ selector: (generated) => generated.model.id,
146
+ });
147
+ // Generating Models with a Selected Reachable Target
148
+ /**
149
+ * Generates root-level models and a path to one of their reachable models.
150
+ *
151
+ * Every generated path is valid for `getAtPath`; unreachable paths are not
152
+ * included.
153
+ */
154
+ export const modelAndReachablePathArb = modelWithReachableModelsArb.chain(({ model: root, reachableModels }) => fc.constantFrom(...reachableModels).map(({ path, model }) => ({
155
+ root,
156
+ path,
157
+ expected: model,
158
+ })));
159
+ /**
160
+ * Generates a root model and a path to one of its reachable branch models.
161
+ *
162
+ * Both loaded and unloaded branches are included.
163
+ */
164
+ export const modelAndBranchPathArb = modelWithReachableModelsArb
165
+ .map(({ model: root, reachableModels }) => ({
166
+ root,
167
+ branchPathEntries: reachableModels.filter(({ model }) => 'children' in model),
168
+ }))
169
+ .filter(({ branchPathEntries }) => branchPathEntries.length > 0)
170
+ .chain(({ root, branchPathEntries }) => fc.constantFrom(...branchPathEntries).map(({ path, model }) => ({
171
+ root,
172
+ path,
173
+ expected: model,
174
+ })));
175
+ /**
176
+ * Generates a new array of loaded child models.
177
+ *
178
+ * The generated models have unique IDs, making the result suitable for use as
179
+ * the children of a loaded branch.
180
+ */
181
+ export const childrenModelsArb = siblingModelsWRMArb.map((generatedNodes) => generatedNodes.map(({ model }) => model));
182
+ /**
183
+ * Generates either a new array of loaded child models or `null`.
184
+ *
185
+ * An array represents a loaded branch, including a loaded branch with no
186
+ * children. `null` represents an unloaded branch.
187
+ */
188
+ export const childrenStateModelArb = fc.oneof(childrenModelsArb, fc.constant(null));
@@ -0,0 +1,194 @@
1
+ import { z } from 'zod';
2
+ import type { SerializableKey } from 'dirvi-apis';
3
+ /**
4
+ * A serializable primitive suitable for use as a stable tree-node ID.
5
+ *
6
+ * @remarks
7
+ *
8
+ * A node ID identifies a node among its direct siblings. It is not required
9
+ * to be globally unique across the whole tree: two nodes in different
10
+ * branches may have the same ID.
11
+ *
12
+ * Numeric IDs must be finite. TypeScript cannot represent the exclusion of
13
+ * `NaN`, `Infinity`, and `-Infinity` from `number`, so values received from
14
+ * an untrusted source should be validated at an application boundary, for
15
+ * example with `serializableKeySchema`.
16
+ *
17
+ * Applications should normally define a narrower domain-specific ID type.
18
+ * Branded ID types prevent IDs from unrelated domains from being mixed
19
+ * accidentally, even when both use strings at runtime.
20
+ *
21
+ * @example
22
+ *
23
+ * ```ts
24
+ * const myIdSchema = z
25
+ * .string()
26
+ * .min(1)
27
+ * .brand<'MyId'>();
28
+ *
29
+ * type MyId = z.output<typeof myIdSchema>;
30
+ *
31
+ * type MyItem = Readonly<{
32
+ * label: string;
33
+ * href?: string;
34
+ * }>;
35
+ *
36
+ * type MyTreeModel = TreeNodeModel<MyId, MyItem>;
37
+ * ```
38
+ */
39
+ export type { SerializableKey };
40
+ /**
41
+ * Validates a serializable primitive suitable for use as a tree-node ID.
42
+ *
43
+ * Strings are accepted without additional restrictions. Numbers must be
44
+ * finite: `NaN`, `Infinity`, and `-Infinity` are rejected.
45
+ *
46
+ * Applications can derive narrower schemas to impose domain-specific
47
+ * restrictions or produce branded ID types.
48
+ *
49
+ * @remarks
50
+ *
51
+ * Requires Zod v4, where `z.number()` rejects non-finite values.
52
+ */
53
+ export declare const serializableKeySchema: z.ZodType<SerializableKey>;
54
+ /**
55
+ * A structural model for persisting or exchanging a tree node.
56
+ *
57
+ * @remarks
58
+ *
59
+ * This model is independent of the opaque runtime tree representation.
60
+ * It consists of ordinary objects and ordered child arrays.
61
+ *
62
+ * The presence and value of `children` distinguish three node states:
63
+ *
64
+ * - Absent: a leaf, which cannot contain children.
65
+ * - `null`: a branch whose children have not been loaded.
66
+ * - An array: a branch whose children are loaded, possibly with no children.
67
+ *
68
+ * Loaded children form an ordered sequence. Their array positions describe
69
+ * child order, while their IDs identify them independently of those positions.
70
+ * Direct siblings must have unique IDs.
71
+ *
72
+ * The model is suitable for JSON serialization when `Id` and `Value` are
73
+ * JSON-serializable. The generic `Value` type does not itself guarantee this.
74
+ *
75
+ * `Readonly` prevents structural mutation through these types at compile time.
76
+ * It does not freeze objects at runtime or make application-owned values
77
+ * deeply immutable.
78
+ *
79
+ * Models represent finite trees, not cyclic object graphs.
80
+ *
81
+ * @typeParam Id - The type identifying each node among its direct siblings.
82
+ * @typeParam Value - Application-owned data associated with each node.
83
+ */
84
+ export type TreeNodeModel<Id extends SerializableKey, Value> = LeafTreeNodeModel<Id, Value> | UnloadedBranchTreeNodeModel<Id, Value> | LoadedBranchTreeNodeModel<Id, Value>;
85
+ /**
86
+ * A structural model of a leaf node.
87
+ *
88
+ * A leaf cannot contain children. This is distinct from a loaded branch
89
+ * whose child array is currently empty.
90
+ *
91
+ * @typeParam Id - The type identifying this node among its direct siblings.
92
+ * @typeParam Value - Application-owned data associated with this node.
93
+ */
94
+ export type LeafTreeNodeModel<Id extends SerializableKey, Value> = Readonly<{
95
+ id: Id;
96
+ value: Value;
97
+ children?: never;
98
+ }>;
99
+ /**
100
+ * A structural model of a branch whose children have not been loaded.
101
+ *
102
+ * The branch may contain children, but their identities, order, and values
103
+ * are unavailable in this model. `null` does not mean the branch is empty.
104
+ *
105
+ * @typeParam Id - The type identifying this node among its direct siblings.
106
+ * @typeParam Value - Application-owned data associated with this node.
107
+ */
108
+ export type UnloadedBranchTreeNodeModel<Id extends SerializableKey, Value> = Readonly<{
109
+ id: Id;
110
+ value: Value;
111
+ children: null;
112
+ }>;
113
+ /**
114
+ * A structural model of a branch with loaded children.
115
+ *
116
+ * An empty child array represents a loaded branch with no current children,
117
+ * not a leaf. The branch can still contain children.
118
+ *
119
+ * @typeParam Id - The type identifying this node among its direct siblings.
120
+ * @typeParam Value - Application-owned data associated with this node.
121
+ */
122
+ export type LoadedBranchTreeNodeModel<Id extends SerializableKey, Value> = Readonly<{
123
+ id: Id;
124
+ value: Value;
125
+ children: readonly TreeNodeModel<Id, Value>[];
126
+ }>;
127
+ /**
128
+ * Creates a recursive schema for validating structural tree-node models.
129
+ *
130
+ * @remarks
131
+ *
132
+ * The supplied schemas validate every node's ID and application-owned value.
133
+ * The returned schema validates the three node shapes recursively:
134
+ *
135
+ * - Leaves omit `children`.
136
+ * - Unloaded branches have `children: null`.
137
+ * - Loaded branches have an ordered array of valid child models.
138
+ *
139
+ * Node objects are strict: properties other than `id`, `value`, and the
140
+ * appropriate `children` property are rejected. Validation of properties
141
+ * inside `value` is controlled by `valueSchema`.
142
+ *
143
+ * Child arrays are parsed in their existing order; this schema does not sort
144
+ * or reorder children.
145
+ *
146
+ * This schema validates shape and field values, but does not enforce
147
+ * sibling-ID uniqueness. That invariant must be checked when constructing
148
+ * runtime tree nodes or by an additional validation step.
149
+ *
150
+ * The supplied ID schema is responsible for enforcing the runtime ID
151
+ * constraints, including finite numeric IDs. The generic constraint alone
152
+ * cannot enforce those restrictions.
153
+ *
154
+ * Inputs must describe finite trees. Cyclic object graphs are not supported.
155
+ *
156
+ * @typeParam Id - The validated node-ID type.
157
+ * @typeParam Value - The validated application-value type.
158
+ * @param idSchema - Schema used to validate every node's ID.
159
+ * @param valueSchema - Schema used to validate every node's application data.
160
+ * @returns A recursive schema for the application's tree-node models.
161
+ *
162
+ * @example
163
+ *
164
+ * ```ts
165
+ * const myIdSchema = serializableKeySchema
166
+ * .pipe(z.string().min(1))
167
+ * .brand<'MyId'>();
168
+ *
169
+ * type MyId = z.output<typeof myIdSchema>;
170
+ *
171
+ * const modelSchema = createTreeNodeModelSchema(
172
+ * myIdSchema,
173
+ * z.object({ label: z.string() }).strict(),
174
+ * );
175
+ *
176
+ * const model = modelSchema.parse({
177
+ * id: 'root',
178
+ * value: { label: 'My' },
179
+ * children: [
180
+ * {
181
+ * id: 'home',
182
+ * value: { label: 'Home' },
183
+ * },
184
+ * {
185
+ * id: 'settings',
186
+ * value: { label: 'Settings' },
187
+ * children: null,
188
+ * },
189
+ * ],
190
+ * });
191
+ * ```
192
+ */
193
+ export declare function createTreeNodeModelSchema<Id extends SerializableKey, Value>(idSchema: z.ZodType<Id>, valueSchema: z.ZodType<Value>): z.ZodType<TreeNodeModel<Id, Value>>;
194
+ //# sourceMappingURL=tree-node.model.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tree-node.model.d.ts","sourceRoot":"","sources":["../../../src/state-and-nav/tree/tree-node.model.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,YAAY,EAAE,eAAe,EAAE,CAAA;AAE/B;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,qBAAqB,EAAE,CAAC,CAAC,OAAO,CAAC,eAAe,CAG3D,CAAC;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,MAAM,MAAM,aAAa,CAAC,EAAE,SAAS,eAAe,EAAE,KAAK,IACvD,iBAAiB,CAAC,EAAE,EAAE,KAAK,CAAC,GAC5B,2BAA2B,CAAC,EAAE,EAAE,KAAK,CAAC,GACtC,yBAAyB,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;AAEzC;;;;;;;;GAQG;AACH,MAAM,MAAM,iBAAiB,CAAC,EAAE,SAAS,eAAe,EAAE,KAAK,IAAI,QAAQ,CAAC;IAC1E,EAAE,EAAE,EAAE,CAAC;IACP,KAAK,EAAE,KAAK,CAAC;IACb,QAAQ,CAAC,EAAE,KAAK,CAAC;CAClB,CAAC,CAAC;AAEH;;;;;;;;GAQG;AACH,MAAM,MAAM,2BAA2B,CACrC,EAAE,SAAS,eAAe,EAC1B,KAAK,IACH,QAAQ,CAAC;IACX,EAAE,EAAE,EAAE,CAAC;IACP,KAAK,EAAE,KAAK,CAAC;IACb,QAAQ,EAAE,IAAI,CAAC;CAChB,CAAC,CAAC;AAEH;;;;;;;;GAQG;AACH,MAAM,MAAM,yBAAyB,CACnC,EAAE,SAAS,eAAe,EAC1B,KAAK,IACH,QAAQ,CAAC;IACX,EAAE,EAAE,EAAE,CAAC;IACP,KAAK,EAAE,KAAK,CAAC;IACb,QAAQ,EAAE,SAAS,aAAa,CAAC,EAAE,EAAE,KAAK,CAAC,EAAE,CAAC;CAC/C,CAAC,CAAC;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiEG;AACH,wBAAgB,yBAAyB,CAAC,EAAE,SAAS,eAAe,EAAE,KAAK,EACzE,QAAQ,EAAE,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,EACvB,WAAW,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,GAC5B,CAAC,CAAC,OAAO,CAAC,aAAa,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC,CA+BrC"}