@getodk/xforms-engine 0.2.0 → 0.3.0

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 (184) hide show
  1. package/dist/body/BodyElementDefinition.d.ts +4 -3
  2. package/dist/body/RepeatElementDefinition.d.ts +2 -2
  3. package/dist/body/control/ControlDefinition.d.ts +2 -2
  4. package/dist/body/control/select/ItemDefinition.d.ts +2 -2
  5. package/dist/body/control/select/ItemsetDefinition.d.ts +5 -4
  6. package/dist/body/group/BaseGroupDefinition.d.ts +1 -1
  7. package/dist/body/group/PresentationGroupDefinition.d.ts +1 -1
  8. package/dist/client/BaseNode.d.ts +68 -2
  9. package/dist/client/GroupNode.d.ts +2 -0
  10. package/dist/client/ModelValueNode.d.ts +37 -0
  11. package/dist/client/NoteNode.d.ts +53 -0
  12. package/dist/client/RootNode.d.ts +2 -0
  13. package/dist/client/SelectNode.d.ts +5 -3
  14. package/dist/client/StringNode.d.ts +5 -3
  15. package/dist/client/SubtreeNode.d.ts +2 -0
  16. package/dist/client/TextRange.d.ts +85 -2
  17. package/dist/client/constants.d.ts +9 -0
  18. package/dist/client/hierarchy.d.ts +14 -9
  19. package/dist/client/node-types.d.ts +2 -1
  20. package/dist/client/{RepeatRangeNode.d.ts → repeat/BaseRepeatRangeNode.d.ts} +18 -17
  21. package/dist/client/{RepeatInstanceNode.d.ts → repeat/RepeatInstanceNode.d.ts} +9 -8
  22. package/dist/client/repeat/RepeatRangeControlledNode.d.ts +19 -0
  23. package/dist/client/repeat/RepeatRangeUncontrolledNode.d.ts +20 -0
  24. package/dist/client/validation.d.ts +163 -0
  25. package/dist/expression/DependentExpression.d.ts +12 -8
  26. package/dist/index.d.ts +9 -4
  27. package/dist/index.js +2635 -678
  28. package/dist/index.js.map +1 -1
  29. package/dist/instance/Group.d.ts +3 -1
  30. package/dist/instance/ModelValue.d.ts +40 -0
  31. package/dist/instance/Note.d.ts +42 -0
  32. package/dist/instance/Root.d.ts +2 -0
  33. package/dist/instance/SelectField.d.ts +10 -4
  34. package/dist/instance/StringField.d.ts +11 -5
  35. package/dist/instance/Subtree.d.ts +2 -0
  36. package/dist/instance/abstract/DescendantNode.d.ts +5 -6
  37. package/dist/instance/abstract/InstanceNode.d.ts +2 -0
  38. package/dist/instance/hierarchy.d.ts +10 -5
  39. package/dist/instance/internal-api/ValidationContext.d.ts +21 -0
  40. package/dist/instance/{RepeatRange.d.ts → repeat/BaseRepeatRange.d.ts} +46 -45
  41. package/dist/instance/{RepeatInstance.d.ts → repeat/RepeatInstance.d.ts} +13 -12
  42. package/dist/instance/repeat/RepeatRangeControlled.d.ts +16 -0
  43. package/dist/instance/repeat/RepeatRangeUncontrolled.d.ts +35 -0
  44. package/dist/instance/text/TextRange.d.ts +4 -4
  45. package/dist/lib/reactivity/createComputedExpression.d.ts +6 -1
  46. package/dist/lib/reactivity/createNoteReadonlyThunk.d.ts +5 -0
  47. package/dist/lib/reactivity/node-state/createSharedNodeState.d.ts +1 -1
  48. package/dist/lib/reactivity/node-state/createSpecifiedState.d.ts +1 -1
  49. package/dist/lib/reactivity/text/createFieldHint.d.ts +3 -3
  50. package/dist/lib/reactivity/text/createNodeLabel.d.ts +2 -2
  51. package/dist/lib/reactivity/text/createNoteText.d.ts +25 -0
  52. package/dist/lib/reactivity/text/createTextRange.d.ts +5 -7
  53. package/dist/lib/reactivity/validation/createAggregatedViolations.d.ts +9 -0
  54. package/dist/lib/reactivity/validation/createValidation.d.ts +18 -0
  55. package/dist/model/BindDefinition.d.ts +4 -2
  56. package/dist/model/BindElement.d.ts +1 -0
  57. package/dist/model/{ValueNodeDefinition.d.ts → LeafNodeDefinition.d.ts} +2 -2
  58. package/dist/model/NodeDefinition.d.ts +8 -8
  59. package/dist/model/RepeatInstanceDefinition.d.ts +2 -2
  60. package/dist/model/RepeatRangeDefinition.d.ts +14 -4
  61. package/dist/parse/NoteNodeDefinition.d.ts +31 -0
  62. package/dist/parse/expression/RepeatCountControlExpression.d.ts +19 -0
  63. package/dist/parse/text/HintDefinition.d.ts +9 -0
  64. package/dist/parse/text/ItemLabelDefinition.d.ts +9 -0
  65. package/dist/parse/text/ItemsetLabelDefinition.d.ts +13 -0
  66. package/dist/parse/text/LabelDefinition.d.ts +15 -0
  67. package/dist/parse/text/MessageDefinition.d.ts +15 -0
  68. package/dist/parse/text/OutputChunkDefinition.d.ts +8 -0
  69. package/dist/parse/text/ReferenceChunkDefinition.d.ts +8 -0
  70. package/dist/parse/text/StaticTextChunkDefinition.d.ts +10 -0
  71. package/dist/parse/text/TranslationChunkDefinition.d.ts +9 -0
  72. package/dist/parse/text/abstract/TextChunkDefinition.d.ts +18 -0
  73. package/dist/parse/text/abstract/TextElementDefinition.d.ts +23 -0
  74. package/dist/parse/text/abstract/TextRangeDefinition.d.ts +35 -0
  75. package/dist/parse/xpath/dependency-analysis.d.ts +40 -0
  76. package/dist/parse/xpath/path-resolution.d.ts +70 -0
  77. package/dist/parse/xpath/predicate-analysis.d.ts +30 -0
  78. package/dist/parse/xpath/reference-parsing.d.ts +18 -0
  79. package/dist/parse/xpath/semantic-analysis.d.ts +98 -0
  80. package/dist/parse/xpath/syntax-traversal.d.ts +69 -0
  81. package/dist/solid.js +2636 -679
  82. package/dist/solid.js.map +1 -1
  83. package/package.json +14 -15
  84. package/src/body/BodyElementDefinition.ts +4 -3
  85. package/src/body/RepeatElementDefinition.ts +5 -17
  86. package/src/body/control/ControlDefinition.ts +4 -3
  87. package/src/body/control/select/ItemDefinition.ts +3 -3
  88. package/src/body/control/select/ItemsetDefinition.ts +29 -12
  89. package/src/body/control/select/ItemsetNodesetExpression.ts +1 -1
  90. package/src/body/group/BaseGroupDefinition.ts +3 -2
  91. package/src/body/group/PresentationGroupDefinition.ts +1 -1
  92. package/src/client/BaseNode.ts +73 -7
  93. package/src/client/GroupNode.ts +2 -0
  94. package/src/client/ModelValueNode.ts +40 -0
  95. package/src/client/NoteNode.ts +74 -0
  96. package/src/client/README.md +1 -0
  97. package/src/client/RootNode.ts +2 -0
  98. package/src/client/SelectNode.ts +5 -3
  99. package/src/client/StringNode.ts +5 -3
  100. package/src/client/SubtreeNode.ts +2 -0
  101. package/src/client/TextRange.ts +99 -2
  102. package/src/client/constants.ts +10 -0
  103. package/src/client/hierarchy.ts +30 -14
  104. package/src/client/node-types.ts +8 -1
  105. package/src/client/{RepeatRangeNode.ts → repeat/BaseRepeatRangeNode.ts} +18 -19
  106. package/src/client/{RepeatInstanceNode.ts → repeat/RepeatInstanceNode.ts} +10 -8
  107. package/src/client/repeat/RepeatRangeControlledNode.ts +20 -0
  108. package/src/client/repeat/RepeatRangeUncontrolledNode.ts +21 -0
  109. package/src/client/validation.ts +199 -0
  110. package/src/expression/DependentExpression.ts +45 -27
  111. package/src/index.ts +15 -8
  112. package/src/instance/Group.ts +10 -4
  113. package/src/instance/ModelValue.ts +104 -0
  114. package/src/instance/Note.ts +142 -0
  115. package/src/instance/Root.ts +9 -3
  116. package/src/instance/SelectField.ts +28 -6
  117. package/src/instance/StringField.ts +35 -9
  118. package/src/instance/Subtree.ts +9 -3
  119. package/src/instance/abstract/DescendantNode.ts +6 -7
  120. package/src/instance/abstract/InstanceNode.ts +20 -6
  121. package/src/instance/children.ts +42 -15
  122. package/src/instance/hierarchy.ts +21 -2
  123. package/src/instance/internal-api/ValidationContext.ts +23 -0
  124. package/src/instance/{RepeatRange.ts → repeat/BaseRepeatRange.ts} +114 -99
  125. package/src/instance/{RepeatInstance.ts → repeat/RepeatInstance.ts} +27 -22
  126. package/src/instance/repeat/RepeatRangeControlled.ts +82 -0
  127. package/src/instance/repeat/RepeatRangeUncontrolled.ts +67 -0
  128. package/src/instance/text/TextRange.ts +10 -4
  129. package/src/lib/reactivity/createComputedExpression.ts +22 -24
  130. package/src/lib/reactivity/createNoteReadonlyThunk.ts +33 -0
  131. package/src/lib/reactivity/createSelectItems.ts +21 -14
  132. package/src/lib/reactivity/node-state/createSharedNodeState.ts +1 -1
  133. package/src/lib/reactivity/text/createFieldHint.ts +9 -7
  134. package/src/lib/reactivity/text/createNodeLabel.ts +7 -5
  135. package/src/lib/reactivity/text/createNoteText.ts +72 -0
  136. package/src/lib/reactivity/text/createTextRange.ts +17 -90
  137. package/src/lib/reactivity/validation/createAggregatedViolations.ts +70 -0
  138. package/src/lib/reactivity/validation/createValidation.ts +196 -0
  139. package/src/model/BindComputation.ts +0 -4
  140. package/src/model/BindDefinition.ts +8 -6
  141. package/src/model/BindElement.ts +1 -0
  142. package/src/model/{ValueNodeDefinition.ts → LeafNodeDefinition.ts} +4 -4
  143. package/src/model/ModelBindMap.ts +4 -0
  144. package/src/model/NodeDefinition.ts +12 -12
  145. package/src/model/RepeatInstanceDefinition.ts +2 -2
  146. package/src/model/RepeatRangeDefinition.ts +49 -8
  147. package/src/model/RootDefinition.ts +7 -3
  148. package/src/parse/NoteNodeDefinition.ts +70 -0
  149. package/src/parse/TODO.md +3 -0
  150. package/src/parse/expression/RepeatCountControlExpression.ts +44 -0
  151. package/src/parse/text/HintDefinition.ts +25 -0
  152. package/src/parse/text/ItemLabelDefinition.ts +25 -0
  153. package/src/parse/text/ItemsetLabelDefinition.ts +44 -0
  154. package/src/parse/text/LabelDefinition.ts +61 -0
  155. package/src/parse/text/MessageDefinition.ts +49 -0
  156. package/src/parse/text/OutputChunkDefinition.ts +25 -0
  157. package/src/parse/text/ReferenceChunkDefinition.ts +14 -0
  158. package/src/parse/text/StaticTextChunkDefinition.ts +19 -0
  159. package/src/parse/text/TranslationChunkDefinition.ts +38 -0
  160. package/src/parse/text/abstract/TextChunkDefinition.ts +38 -0
  161. package/src/parse/text/abstract/TextElementDefinition.ts +71 -0
  162. package/src/parse/text/abstract/TextRangeDefinition.ts +70 -0
  163. package/src/parse/xpath/dependency-analysis.ts +105 -0
  164. package/src/parse/xpath/path-resolution.ts +475 -0
  165. package/src/parse/xpath/predicate-analysis.ts +61 -0
  166. package/src/parse/xpath/reference-parsing.ts +90 -0
  167. package/src/parse/xpath/semantic-analysis.ts +466 -0
  168. package/src/parse/xpath/syntax-traversal.ts +129 -0
  169. package/dist/body/text/HintDefinition.d.ts +0 -11
  170. package/dist/body/text/LabelDefinition.d.ts +0 -22
  171. package/dist/body/text/TextElementDefinition.d.ts +0 -33
  172. package/dist/body/text/TextElementOutputPart.d.ts +0 -13
  173. package/dist/body/text/TextElementPart.d.ts +0 -13
  174. package/dist/body/text/TextElementReferencePart.d.ts +0 -7
  175. package/dist/body/text/TextElementStaticPart.d.ts +0 -7
  176. package/dist/lib/xpath/analysis.d.ts +0 -23
  177. package/src/body/text/HintDefinition.ts +0 -26
  178. package/src/body/text/LabelDefinition.ts +0 -68
  179. package/src/body/text/TextElementDefinition.ts +0 -97
  180. package/src/body/text/TextElementOutputPart.ts +0 -27
  181. package/src/body/text/TextElementPart.ts +0 -31
  182. package/src/body/text/TextElementReferencePart.ts +0 -21
  183. package/src/body/text/TextElementStaticPart.ts +0 -26
  184. package/src/lib/xpath/analysis.ts +0 -241
@@ -1,12 +1,14 @@
1
- import { RepeatRangeDefinition } from '../model/RepeatRangeDefinition.ts';
2
- import { BaseNode, BaseNodeState } from './BaseNode.ts';
3
- import { NodeAppearances } from './NodeAppearances.ts';
1
+ import { AnyRepeatRangeDefinition } from '../../model/RepeatRangeDefinition.ts';
2
+ import { BaseNode, BaseNodeState } from '../BaseNode.ts';
3
+ import { NodeAppearances } from '../NodeAppearances.ts';
4
+ import { RootNode } from '../RootNode.ts';
5
+ import { TextRange } from '../TextRange.ts';
6
+ import { GeneralParentNode } from '../hierarchy.ts';
7
+ import { RepeatRangeNodeType } from '../node-types.ts';
8
+ import { AncestorNodeValidationState } from '../validation.ts';
4
9
  import { RepeatInstanceNode } from './RepeatInstanceNode.ts';
5
- import { RootNode } from './RootNode.ts';
6
- import { TextRange } from './TextRange.ts';
7
- import { GeneralParentNode } from './hierarchy.ts';
8
10
 
9
- export interface RepeatRangeNodeState extends BaseNodeState {
11
+ export interface BaseRepeatRangeNodeState extends BaseNodeState {
10
12
  get hint(): null;
11
13
  get label(): TextRange<'label'> | null;
12
14
  /**
@@ -15,17 +17,17 @@ export interface RepeatRangeNodeState extends BaseNodeState {
15
17
  * Note: the web-forms engine's representation of this structure differs from
16
18
  * the underlying XForms specification's primary instance structure.
17
19
  *
18
- * @see {@link RepeatRangeNode} for additional detail.
20
+ * @see {@link BaseRepeatRangeNode} for additional detail.
19
21
  */
20
22
  get children(): readonly RepeatInstanceNode[];
21
23
  get valueOptions(): null;
22
24
  get value(): null;
23
25
  }
24
- export type RepeatRangeNodeAppearances = NodeAppearances<RepeatRangeDefinition>;
26
+ export type RepeatRangeNodeAppearances = NodeAppearances<AnyRepeatRangeDefinition>;
25
27
  /**
26
28
  * Represents a contiguous set of zero or more {@link RepeatInstanceNode}s
27
29
  * (accessed by its
28
- * {@link RepeatRangeNodeState.children | `currentState.children`}).
30
+ * {@link BaseRepeatRangeNodeState.children | `currentState.children`}).
29
31
  *
30
32
  * This structure is modeled as a node, like any other, in the web-forms engine
31
33
  * representation, which notably differs from the corresponding structure in the
@@ -84,15 +86,14 @@ export type RepeatRangeNodeAppearances = NodeAppearances<RepeatRangeDefinition>;
84
86
  * Importantly, if the state of a given repeat range has no instances, no aspect
85
87
  * of these repeats will be present in the underlying XForms primary instance
86
88
  * state, but the web-forms engine's representations **retains a reference** to
87
- * its {@link RepeatRangeNode}.
89
+ * its {@link BaseRepeatRangeNode}.
88
90
  */
89
- export interface RepeatRangeNode extends BaseNode {
90
- readonly nodeType: 'repeat-range';
91
+ export interface BaseRepeatRangeNode extends BaseNode {
92
+ readonly nodeType: RepeatRangeNodeType;
91
93
  readonly appearances: RepeatRangeNodeAppearances;
92
- readonly definition: RepeatRangeDefinition;
94
+ readonly definition: AnyRepeatRangeDefinition;
93
95
  readonly root: RootNode;
94
96
  readonly parent: GeneralParentNode;
95
- readonly currentState: RepeatRangeNodeState;
96
- addInstances(afterIndex?: number, count?: number): RootNode;
97
- removeInstances(startIndex: number, count?: number): RootNode;
97
+ readonly currentState: BaseRepeatRangeNodeState;
98
+ readonly validationState: AncestorNodeValidationState;
98
99
  }
@@ -1,10 +1,10 @@
1
- import { RepeatInstanceDefinition } from '../model/RepeatInstanceDefinition.ts';
2
- import { RepeatTemplateDefinition } from '../model/RepeatTemplateDefinition.ts';
3
- import { BaseNode, BaseNodeState } from './BaseNode.ts';
4
- import { NodeAppearances } from './NodeAppearances.ts';
5
- import { RepeatRangeNode } from './RepeatRangeNode.ts';
6
- import { RootNode } from './RootNode.ts';
7
- import { GeneralChildNode } from './hierarchy.ts';
1
+ import { RepeatInstanceDefinition } from '../../model/RepeatInstanceDefinition.ts';
2
+ import { RepeatTemplateDefinition } from '../../model/RepeatTemplateDefinition.ts';
3
+ import { BaseNode, BaseNodeState } from '../BaseNode.ts';
4
+ import { GeneralChildNode, RepeatRangeNode } from '../hierarchy.ts';
5
+ import { NodeAppearances } from '../NodeAppearances.ts';
6
+ import { RootNode } from '../RootNode.ts';
7
+ import { AncestorNodeValidationState } from '../validation.ts';
8
8
 
9
9
  export interface RepeatInstanceNodeState extends BaseNodeState {
10
10
  get hint(): null;
@@ -25,8 +25,9 @@ export interface RepeatInstanceNode extends BaseNode {
25
25
  * Note: the web-forms engine's representation of this structure differs from
26
26
  * the underlying XForms specification's primary instance structure.
27
27
  *
28
- * @see {@link RepeatRangeNode} for additional detail.
28
+ * @see {@link BaseRepeatRangeNode} for additional detail.
29
29
  */
30
30
  readonly parent: RepeatRangeNode;
31
31
  readonly currentState: RepeatInstanceNodeState;
32
+ readonly validationState: AncestorNodeValidationState;
32
33
  }
@@ -0,0 +1,19 @@
1
+ import { ControlledRepeatRangeDefinition } from '../../model/RepeatRangeDefinition.ts';
2
+ import { BaseRepeatRangeNode, BaseRepeatRangeNodeState } from './BaseRepeatRangeNode.ts';
3
+
4
+ /**
5
+ * {@inheritDoc BaseRepeatRangeNodeState}
6
+ * @see {@link BaseRepeatRangeNodeState}
7
+ */
8
+ export interface RepeatRangeControlledState extends BaseRepeatRangeNodeState {
9
+ }
10
+ /**
11
+ * Represents a repeat range whose repeat instances are controlled by the
12
+ * engine, and cannot be added or removed by a client. Functionality and
13
+ * semantics are otherwise consistent with an [uncontrolled]
14
+ * {@link RepeatRangeUncontrolledNode}.
15
+ */
16
+ export interface RepeatRangeControlledNode extends BaseRepeatRangeNode {
17
+ readonly nodeType: 'repeat-range:controlled';
18
+ readonly definition: ControlledRepeatRangeDefinition;
19
+ }
@@ -0,0 +1,20 @@
1
+ import { UncontrolledRepeatRangeDefinition } from '../../model/RepeatRangeDefinition.ts';
2
+ import { RootNode } from '../RootNode.ts';
3
+ import { BaseRepeatRangeNode, BaseRepeatRangeNodeState } from './BaseRepeatRangeNode.ts';
4
+
5
+ /**
6
+ * {@inheritDoc BaseRepeatRangeNodeState}
7
+ * @see {@link BaseRepeatRangeNodeState}
8
+ */
9
+ export interface RepeatRangeUncontrolledState extends BaseRepeatRangeNodeState {
10
+ }
11
+ /**
12
+ * {@inheritDoc BaseRepeatRangeNode}
13
+ * @see {@link BaseRepeatRangeNode}
14
+ */
15
+ export interface RepeatRangeUncontrolledNode extends BaseRepeatRangeNode {
16
+ readonly nodeType: 'repeat-range:uncontrolled';
17
+ readonly definition: UncontrolledRepeatRangeDefinition;
18
+ addInstances(afterIndex?: number, count?: number): RootNode;
19
+ removeInstances(startIndex: number, count?: number): RootNode;
20
+ }
@@ -0,0 +1,163 @@
1
+ import { NodeID } from '../instance/identity.ts';
2
+ import { TextRange } from './TextRange.ts';
3
+
4
+ interface BaseValidity {
5
+ /**
6
+ * Specifies the unambiguous validity state for each validity condition of a
7
+ * given node, or for the derived validity of any parent node whose descendants
8
+ * are validated.
9
+ *
10
+ * For {@link ValidationCondition | form-defined conditions}, validity is
11
+ * determined as follows:
12
+ *
13
+ *
14
+ * expression | state | blank | non-blank
15
+ * ------------:|:----------|:-------:|:---------:
16
+ * `constraint` | `true`\* | ✅ | ✅
17
+ * `constraint` | `false` | ✅ | ❌
18
+ * `required` | `false`\* | ✅ | ✅
19
+ * `required` | `true` | ❌ | ✅
20
+ *
21
+ * - \* = default (expression not defined)
22
+ * - ✅ = `valid: true`
23
+ * - ❌ = `valid: false`
24
+ */
25
+ readonly valid: boolean;
26
+ }
27
+ /**
28
+ * Form-defined conditions which determine node validity.
29
+ *
30
+ * @see {@link https://getodk.github.io/xforms-spec/#bind-attributes | `constraint` and `required` bind attributes}
31
+ */
32
+ export type ValidationCondition = 'constraint' | 'required';
33
+ interface ValidationConditionMessageRoles {
34
+ readonly constraint: 'constraintMsg';
35
+ readonly required: 'requiredMsg';
36
+ }
37
+ export type ValidationConditionMessageRole<Condition extends ValidationCondition> = ValidationConditionMessageRoles[Condition];
38
+ /**
39
+ * Source of a condition's violation message.
40
+ *
41
+ * - Form-defined messages (specified by the
42
+ * {@link https://getodk.github.io/xforms-spec/#bind-attributes | `jr:constraintMsg` and `jr:requiredMsg`}
43
+ * attributes) will be favored when provided by the form, and will be
44
+ * translated according to the form's active language (where applicable).
45
+ *
46
+ * - Otherwise, an engine-defined message will be provided as a fallback. This
47
+ * fallback is provided mainly for API consistency, and may be referenced for
48
+ * testing purposes; user-facing clients are expected to provide fallback
49
+ * messaging language most appropriate for their user neeeds. Engine-defined
50
+ * fallback messages **are not translated**. They are intended to be used, if
51
+ * at all, as sentinel values when a form-defined message is not available.
52
+ */
53
+ export type ViolationMessageSource = 'form' | 'engine';
54
+ /**
55
+ * @see {@link ViolationMessage.asString}
56
+ */
57
+ type ViolationMessageAsString<Source extends ViolationMessageSource, Condition extends ValidationCondition> = Source extends 'form' ? string : `Condition not satisfied: ${Condition}`;
58
+ /**
59
+ * A violation message is provided for every violation of a form-defined
60
+ * {@link ValidationCondition}.
61
+ */
62
+ export interface ViolationMessage<Condition extends ValidationCondition, Source extends ViolationMessageSource = ViolationMessageSource> extends TextRange<ValidationConditionMessageRole<Condition>> {
63
+ /**
64
+ * - Form-defined violation messages may produce arbitrary text. This text may
65
+ * be translated
66
+ * ({@link https://getodk.github.io/xforms-spec/#fn:jr:itext | `jr:itext`}),
67
+ * and it may be dynamic (translations may reference form state with
68
+ * {@link https://getodk.github.io/xforms-spec/#body-elements | `<output>`}).
69
+ *
70
+ * - When a form-defined violation message is not available, an engine-defined
71
+ * message will be provided in its place. Engine-defined violation messages
72
+ * are statically defined (and therefore not presently translated by the
73
+ * engine). Their static value can also be referenced as a static type, by
74
+ * checking {@link isFallbackMessage}.
75
+ */
76
+ get asString(): ViolationMessageAsString<Source, Condition>;
77
+ }
78
+ export interface ConditionSatisfied<Condition extends ValidationCondition> extends BaseValidity {
79
+ readonly condition: Condition;
80
+ readonly valid: true;
81
+ readonly message: null;
82
+ }
83
+ export interface ConditionViolation<Condition extends ValidationCondition> extends BaseValidity {
84
+ readonly condition: Condition;
85
+ readonly valid: false;
86
+ readonly message: ViolationMessage<Condition>;
87
+ }
88
+ export type ConditionValidation<Condition extends ValidationCondition> = ConditionSatisfied<Condition> | ConditionViolation<Condition>;
89
+ export type AnyViolation = ConditionViolation<ValidationCondition>;
90
+ /**
91
+ * Represents the validation state of a leaf (or value) node.
92
+ *
93
+ * Validity is computed for two conditions:
94
+ *
95
+ * - {@link constraint}: arbitrary form-defined condition which specifies
96
+ * whether a (non-blank) value is considered valid
97
+ *
98
+ * - {@link required}: when a node is required, the node must have a non-blank
99
+ * value to be considered valid
100
+ *
101
+ * Only one of these conditions can be violated (applicability is mutually
102
+ * exclusive). As such, {@link violation} provides a convenient way to determine
103
+ * whether a leaf/value node is valid with a single (null) check.
104
+ *
105
+ * @see {@link BaseValidity.valid} for additional details on how these
106
+ * conditions are evaluated (and how they interact with one another).
107
+ */
108
+ export interface LeafNodeValidationState {
109
+ get constraint(): ConditionValidation<'constraint'>;
110
+ get required(): ConditionValidation<'required'>;
111
+ /**
112
+ * Violations are mutually exclusive:
113
+ *
114
+ * - {@link constraint} can only be violated by a non-blank value
115
+ * - {@link required} can only be violated by a blank value
116
+ *
117
+ * As such, at most one violation can be present. If none is present,
118
+ * the node is considered valid.
119
+ */
120
+ get violation(): AnyViolation | null;
121
+ }
122
+ /**
123
+ * Provides a reference to any leaf/value node which currently violates either
124
+ * of its validity conditions.
125
+ *
126
+ * Any client can safely assume:
127
+ *
128
+ * - {@link nodeId} will be a stable reference to a node with the same
129
+ * {@link BaseNode.nodeId | `nodeId`}.
130
+ *
131
+ * - {@link node} will have reference equality to the same node object, within
132
+ * the active form instance's {@link RootNode} tree
133
+ *
134
+ * - {@link reference} will be a **current** reference to the same node object's
135
+ * **computed** {@link BaseNodeState.reference | `currentState.reference`}
136
+ *
137
+ * Any client utilizing the engine's reactive APIs (having provided an
138
+ * {@link OpaqueReactiveObjectFactory}) can safely assume that {@link reference}
139
+ * will be recomputed and updated in tandem with the affected node's own
140
+ * computed `currentState.reference` as well.
141
+ *
142
+ * @todo this type currently exposes multiple ways to reference the affected
143
+ * node. This is intended to maximize flexibility: it's not yet clear how
144
+ * clients will be best served by which reference mechanism. It is expected that
145
+ * each property will be directly computed from the affected node.
146
+ */
147
+ export interface DescendantNodeViolationReference {
148
+ readonly nodeId: NodeID;
149
+ get reference(): string;
150
+ get violation(): AnyViolation;
151
+ }
152
+ /**
153
+ * Provides access from any ancestor/parent node, to identify any validity
154
+ * violations present on any of its leaf/value node descendants.
155
+ *
156
+ * @see {@link DescendantNodeViolationReference} for details on how descendants
157
+ * may be referenced when such a violation is present.
158
+ */
159
+ export interface AncestorNodeValidationState {
160
+ get violations(): readonly DescendantNodeViolationReference[];
161
+ }
162
+ export type NodeValidationState = AncestorNodeValidationState | LeafNodeValidationState;
163
+ export {};
@@ -1,9 +1,11 @@
1
1
  import { XFormsXPathEvaluator } from '@getodk/xpath';
2
+ import { ConstantExpression, ConstantTruthyExpression } from '../parse/xpath/semantic-analysis.ts';
2
3
  import { DependencyContext } from './DependencyContext.ts';
3
4
 
4
5
  declare const evaluatorMethodsByResultType: {
5
6
  readonly boolean: "evaluateBoolean";
6
7
  readonly nodes: "evaluateNodes";
8
+ readonly number: "evaluateNumber";
7
9
  readonly string: "evaluateString";
8
10
  };
9
11
  type EvaluatorMethodsByResultType = typeof evaluatorMethodsByResultType;
@@ -11,10 +13,6 @@ export type DependentExpressionResultType = keyof EvaluatorMethodsByResultType;
11
13
  export type DependentExpressionEvaluatorMethod<Type extends DependentExpressionResultType> = EvaluatorMethodsByResultType[Type];
12
14
  export type DependentExpressionResult<Type extends DependentExpressionResultType> = ReturnType<XFormsXPathEvaluator[DependentExpressionEvaluatorMethod<Type>]>;
13
15
  interface SemanticDependencyOptions {
14
- /**
15
- * @default false
16
- */
17
- readonly parentContext?: boolean | undefined;
18
16
  /**
19
17
  * @default false
20
18
  */
@@ -25,19 +23,25 @@ interface DependentExpressionOptions {
25
23
  * @default false
26
24
  */
27
25
  readonly ignoreContextReference?: boolean;
28
- /**
29
- * @default true
30
- */
31
- readonly ignoreNullExpressions?: boolean;
32
26
  readonly semanticDependencies?: SemanticDependencyOptions;
33
27
  }
28
+ export interface ConstantDependentExpression<Type extends DependentExpressionResultType> extends DependentExpression<Type> {
29
+ readonly expression: ConstantExpression;
30
+ }
31
+ export interface ConstantTruthyDependentExpression extends ConstantDependentExpression<'boolean'> {
32
+ readonly expression: ConstantTruthyExpression;
33
+ }
34
34
  export declare class DependentExpression<Type extends DependentExpressionResultType> {
35
35
  readonly resultType: Type;
36
36
  readonly expression: string;
37
37
  readonly dependencyReferences: ReadonlySet<string>;
38
38
  readonly isTranslated: boolean;
39
39
  readonly evaluatorMethod: DependentExpressionEvaluatorMethod<Type>;
40
+ readonly constantExpression: ConstantExpression | null;
41
+ readonly constantTruthyExpression: ConstantTruthyExpression | null;
40
42
  constructor(context: DependencyContext, resultType: Type, expression: string, options?: DependentExpressionOptions);
43
+ isConstantExpression(): this is ConstantDependentExpression<Type>;
44
+ isConstantTruthyExpression(): this is ConstantTruthyDependentExpression;
41
45
  toString(): string | null;
42
46
  }
43
47
  export type AnyDependentExpression = DependentExpression<any>;
package/dist/index.d.ts CHANGED
@@ -1,17 +1,22 @@
1
1
  import { InitializeForm } from './index.ts';
2
2
 
3
3
  export declare const initializeForm: InitializeForm;
4
+ export * as constants from './client/constants.ts';
4
5
  export type * from './client/EngineConfig.ts';
5
6
  export type * from './client/FormLanguage.ts';
6
7
  export type * from './client/GroupNode.ts';
8
+ export type { AnyChildNode, AnyControlNode, AnyLeafNode, AnyNode, AnyParentNode, GeneralChildNode, GeneralParentNode, RepeatRangeNode, } from './client/hierarchy.ts';
9
+ export type * from './client/index.ts';
10
+ export type * from './client/ModelValueNode.ts';
11
+ export type * from './client/NoteNode.ts';
7
12
  export type * from './client/OpaqueReactiveObjectFactory.ts';
8
- export type * from './client/RepeatInstanceNode.ts';
9
- export type * from './client/RepeatRangeNode.ts';
13
+ export type * from './client/repeat/RepeatInstanceNode.ts';
14
+ export type * from './client/repeat/RepeatRangeControlledNode.ts';
15
+ export type * from './client/repeat/RepeatRangeUncontrolledNode.ts';
10
16
  export type * from './client/RootNode.ts';
11
17
  export type * from './client/SelectNode.ts';
12
18
  export type * from './client/StringNode.ts';
13
19
  export type * from './client/SubtreeNode.ts';
14
20
  export type * from './client/TextRange.ts';
15
- export type { AnyChildNode, AnyLeafNode, AnyNode, AnyParentNode, GeneralChildNode, GeneralParentNode, } from './client/hierarchy.ts';
16
- export type * from './client/index.ts';
21
+ export type * from './client/validation.ts';
17
22
  export type { AnySelectDefinition, SelectDefinition, } from './body/control/select/SelectDefinition.ts';