@getodk/xforms-engine 0.4.0 → 0.5.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 (285) hide show
  1. package/dist/client/BaseNode.d.ts +14 -3
  2. package/dist/client/BaseValueNode.d.ts +32 -0
  3. package/dist/client/EngineConfig.d.ts +49 -48
  4. package/dist/client/InputNode.d.ts +53 -0
  5. package/dist/client/ModelValueNode.d.ts +12 -7
  6. package/dist/client/NoteNode.d.ts +2 -2
  7. package/dist/client/RootNode.d.ts +34 -7
  8. package/dist/client/SelectNode.d.ts +2 -2
  9. package/dist/client/ValueType.d.ts +3 -0
  10. package/dist/client/constants.d.ts +50 -0
  11. package/dist/client/hierarchy.d.ts +4 -4
  12. package/dist/client/identity.d.ts +14 -0
  13. package/dist/client/node-types.d.ts +2 -1
  14. package/dist/client/resources.d.ts +93 -0
  15. package/dist/client/submission/SubmissionData.d.ts +7 -0
  16. package/dist/client/submission/SubmissionDefinition.d.ts +14 -0
  17. package/dist/client/submission/SubmissionInstanceFile.d.ts +6 -0
  18. package/dist/client/submission/SubmissionOptions.d.ts +23 -0
  19. package/dist/client/submission/SubmissionResult.d.ts +91 -0
  20. package/dist/client/submission/SubmissionState.d.ts +12 -0
  21. package/dist/client/validation.d.ts +2 -2
  22. package/dist/error/ErrorProductionDesignPendingError.d.ts +7 -0
  23. package/dist/error/ValueTypeInvariantError.d.ts +17 -0
  24. package/dist/error/XPathFunctionalityError.d.ts +14 -0
  25. package/dist/error/XPathFunctionalityNotSupportedError.d.ts +7 -0
  26. package/dist/error/XPathFunctionalityPendingError.d.ts +7 -0
  27. package/dist/index.d.ts +10 -1
  28. package/dist/index.js +10856 -8585
  29. package/dist/index.js.map +1 -1
  30. package/dist/instance/Group.d.ts +9 -4
  31. package/dist/instance/InputControl.d.ts +36 -0
  32. package/dist/instance/ModelValue.d.ts +16 -26
  33. package/dist/instance/Note.d.ts +10 -3
  34. package/dist/instance/PrimaryInstance.d.ts +84 -0
  35. package/dist/instance/Root.d.ts +29 -25
  36. package/dist/instance/SelectField.d.ts +10 -2
  37. package/dist/instance/Subtree.d.ts +10 -5
  38. package/dist/instance/TriggerControl.d.ts +10 -3
  39. package/dist/instance/abstract/DescendantNode.d.ts +31 -23
  40. package/dist/instance/abstract/InstanceNode.d.ts +49 -29
  41. package/dist/instance/abstract/UnsupportedControl.d.ts +10 -3
  42. package/dist/instance/abstract/ValueNode.d.ts +48 -0
  43. package/dist/instance/hierarchy.d.ts +9 -8
  44. package/dist/instance/identity.d.ts +2 -7
  45. package/dist/instance/internal-api/EvaluationContext.d.ts +53 -12
  46. package/dist/instance/internal-api/InstanceConfig.d.ts +8 -2
  47. package/dist/instance/internal-api/InstanceValueContext.d.ts +20 -0
  48. package/dist/instance/internal-api/PrimaryInstanceDocument.d.ts +36 -0
  49. package/dist/instance/internal-api/TranslationContext.d.ts +3 -2
  50. package/dist/instance/internal-api/ValidationContext.d.ts +3 -4
  51. package/dist/instance/internal-api/ValueContext.d.ts +2 -1
  52. package/dist/instance/internal-api/submission/ClientReactiveSubmittableInstance.d.ts +14 -0
  53. package/dist/instance/internal-api/submission/ClientReactiveSubmittableLeafNode.d.ts +31 -0
  54. package/dist/instance/internal-api/submission/ClientReactiveSubmittableParentNode.d.ts +18 -0
  55. package/dist/instance/internal-api/submission/ClientReactiveSubmittableValueNode.d.ts +17 -0
  56. package/dist/instance/repeat/BaseRepeatRange.d.ts +39 -83
  57. package/dist/instance/repeat/RepeatInstance.d.ts +11 -29
  58. package/dist/instance/repeat/RepeatRangeControlled.d.ts +2 -2
  59. package/dist/instance/repeat/RepeatRangeUncontrolled.d.ts +2 -2
  60. package/dist/instance/resource.d.ts +1 -1
  61. package/dist/instance/text/TextRange.d.ts +1 -1
  62. package/dist/instance/unsupported/RangeControl.d.ts +3 -1
  63. package/dist/instance/unsupported/RankControl.d.ts +3 -1
  64. package/dist/instance/unsupported/UploadControl.d.ts +3 -1
  65. package/dist/integration/xpath/EngineXPathEvaluator.d.ts +14 -0
  66. package/dist/integration/xpath/adapter/XFormsXPathNode.d.ts +71 -0
  67. package/dist/integration/xpath/adapter/engineDOMAdapter.d.ts +5 -0
  68. package/dist/integration/xpath/adapter/kind.d.ts +32 -0
  69. package/dist/integration/xpath/adapter/names.d.ts +16 -0
  70. package/dist/integration/xpath/adapter/traversal.d.ts +25 -0
  71. package/dist/integration/xpath/adapter/values.d.ts +2 -0
  72. package/dist/integration/xpath/static-dom/StaticAttribute.d.ts +19 -0
  73. package/dist/integration/xpath/static-dom/StaticDocument.d.ts +16 -0
  74. package/dist/integration/xpath/static-dom/StaticElement.d.ts +40 -0
  75. package/dist/integration/xpath/static-dom/StaticNamedNode.d.ts +17 -0
  76. package/dist/integration/xpath/static-dom/StaticNode.d.ts +33 -0
  77. package/dist/integration/xpath/static-dom/StaticText.d.ts +16 -0
  78. package/dist/lib/client-reactivity/submission/createInstanceSubmissionState.d.ts +3 -0
  79. package/dist/lib/client-reactivity/submission/createLeafNodeSubmissionState.d.ts +3 -0
  80. package/dist/lib/client-reactivity/submission/createNodeRangeSubmissionState.d.ts +4 -0
  81. package/dist/lib/client-reactivity/submission/createParentNodeSubmissionState.d.ts +4 -0
  82. package/dist/lib/client-reactivity/submission/createValueNodeSubmissionState.d.ts +3 -0
  83. package/dist/lib/client-reactivity/submission/prepareSubmission.d.ts +8 -0
  84. package/dist/lib/codecs/DecimalValueCodec.d.ts +6 -0
  85. package/dist/lib/codecs/IntValueCodec.d.ts +6 -0
  86. package/dist/lib/codecs/StringValueCodec.d.ts +4 -0
  87. package/dist/lib/codecs/ValueCodec.d.ts +30 -0
  88. package/dist/lib/codecs/ValueTypePlaceholderCodec.d.ts +12 -0
  89. package/dist/lib/codecs/getSharedValueCodec.d.ts +47 -0
  90. package/dist/lib/dom/query.d.ts +3 -0
  91. package/dist/lib/reactivity/createChildrenState.d.ts +7 -5
  92. package/dist/lib/reactivity/createComputedExpression.d.ts +18 -5
  93. package/dist/lib/reactivity/createInstanceValueState.d.ts +40 -0
  94. package/dist/lib/reactivity/createNoteReadonlyThunk.d.ts +2 -2
  95. package/dist/lib/reactivity/createTranslationState.d.ts +19 -0
  96. package/dist/lib/reactivity/createValueState.d.ts +6 -10
  97. package/dist/lib/reactivity/materializeCurrentStateChildren.d.ts +4 -4
  98. package/dist/lib/xml-serialization.d.ts +41 -0
  99. package/dist/parse/XFormDOM.d.ts +18 -7
  100. package/dist/parse/XFormDefinition.d.ts +1 -2
  101. package/dist/parse/attachments/FormAttachmentResource.d.ts +27 -0
  102. package/dist/parse/body/BodyDefinition.d.ts +3 -3
  103. package/dist/parse/body/RepeatElementDefinition.d.ts +1 -1
  104. package/dist/parse/body/appearance/inputAppearanceParser.d.ts +1 -1
  105. package/dist/parse/body/control/{InputDefinition.d.ts → InputControlDefinition.d.ts} +1 -1
  106. package/dist/parse/body/control/select/ItemsetNodesetContext.d.ts +0 -2
  107. package/dist/parse/expression/abstract/DependencyContext.d.ts +0 -5
  108. package/dist/parse/expression/abstract/DependentExpression.d.ts +2 -3
  109. package/dist/parse/model/BindDefinition.d.ts +4 -5
  110. package/dist/parse/model/BindTypeDefinition.d.ts +20 -0
  111. package/dist/parse/model/DescendentNodeDefinition.d.ts +0 -1
  112. package/dist/parse/model/FormSubmissionDefinition.d.ts +8 -0
  113. package/dist/parse/model/ItextTranslation/ItextTranslationDefinition.d.ts +4 -0
  114. package/dist/parse/model/ItextTranslation/ItextTranslationRootDefinition.d.ts +8 -0
  115. package/dist/parse/model/ItextTranslation/ItextTranslationsDefinition.d.ts +8 -0
  116. package/dist/parse/model/LeafNodeDefinition.d.ts +3 -1
  117. package/dist/parse/model/ModelBindMap.d.ts +1 -1
  118. package/dist/parse/model/ModelDefinition.d.ts +2 -0
  119. package/dist/parse/model/NodeDefinition.d.ts +0 -1
  120. package/dist/parse/model/NoteNodeDefinition.d.ts +4 -4
  121. package/dist/parse/model/RootDefinition.d.ts +3 -2
  122. package/dist/parse/model/SecondaryInstance/SecondaryInstanceDefinition.d.ts +4 -0
  123. package/dist/parse/model/SecondaryInstance/SecondaryInstanceRootDefinition.d.ts +7 -0
  124. package/dist/parse/model/SecondaryInstance/SecondaryInstancesDefinition.d.ts +13 -0
  125. package/dist/parse/model/SecondaryInstance/sources/BlankSecondaryInstanceSource.d.ts +14 -0
  126. package/dist/parse/model/SecondaryInstance/sources/CSVExternalSecondaryInstance.d.ts +22 -0
  127. package/dist/parse/model/SecondaryInstance/sources/ExternalSecondaryInstanceResource.d.ts +23 -0
  128. package/dist/parse/model/SecondaryInstance/sources/ExternalSecondaryInstanceSource.d.ts +9 -0
  129. package/dist/parse/model/SecondaryInstance/sources/GeoJSONExternalSecondaryInstance.d.ts +5 -0
  130. package/dist/parse/model/SecondaryInstance/sources/InternalSecondaryInstanceSource.d.ts +7 -0
  131. package/dist/parse/model/SecondaryInstance/sources/SecondaryInstanceSource.d.ts +13 -0
  132. package/dist/parse/model/SecondaryInstance/sources/XMLExternalSecondaryInstanceSource.d.ts +12 -0
  133. package/dist/parse/shared/parseStaticDocumentFromDOMSubtree.d.ts +24 -0
  134. package/dist/parse/text/abstract/TextRangeDefinition.d.ts +0 -2
  135. package/dist/parse/xpath/semantic-analysis.d.ts +5 -0
  136. package/dist/solid.js +8174 -5921
  137. package/dist/solid.js.map +1 -1
  138. package/package.json +13 -11
  139. package/src/client/BaseNode.ts +16 -6
  140. package/src/client/BaseValueNode.ts +35 -0
  141. package/src/client/EngineConfig.ts +52 -51
  142. package/src/client/InputNode.ts +77 -0
  143. package/src/client/ModelValueNode.ts +30 -7
  144. package/src/client/NoteNode.ts +2 -2
  145. package/src/client/RootNode.ts +37 -7
  146. package/src/client/SelectNode.ts +3 -3
  147. package/src/client/ValueType.ts +4 -0
  148. package/src/client/constants.ts +67 -0
  149. package/src/client/hierarchy.ts +5 -5
  150. package/src/client/identity.ts +16 -0
  151. package/src/client/node-types.ts +12 -6
  152. package/src/client/resources.ts +118 -0
  153. package/src/client/submission/SubmissionData.ts +12 -0
  154. package/src/client/submission/SubmissionDefinition.ts +16 -0
  155. package/src/client/submission/SubmissionInstanceFile.ts +9 -0
  156. package/src/client/submission/SubmissionOptions.ts +28 -0
  157. package/src/client/submission/SubmissionResult.ts +124 -0
  158. package/src/client/submission/SubmissionState.ts +14 -0
  159. package/src/client/validation.ts +2 -2
  160. package/src/error/ErrorProductionDesignPendingError.ts +6 -0
  161. package/src/error/ValueTypeInvariantError.ts +22 -0
  162. package/src/error/XPathFunctionalityError.ts +26 -0
  163. package/src/error/XPathFunctionalityNotSupportedError.ts +18 -0
  164. package/src/error/XPathFunctionalityPendingError.ts +18 -0
  165. package/src/index.ts +10 -1
  166. package/src/instance/Group.ts +17 -5
  167. package/src/instance/InputControl.ts +119 -0
  168. package/src/instance/ModelValue.ts +47 -54
  169. package/src/instance/Note.ts +24 -8
  170. package/src/instance/PrimaryInstance.ts +244 -0
  171. package/src/instance/Root.ts +62 -134
  172. package/src/instance/SelectField.ts +56 -19
  173. package/src/instance/Subtree.ts +19 -7
  174. package/src/instance/TriggerControl.ts +23 -6
  175. package/src/instance/abstract/DescendantNode.ts +90 -45
  176. package/src/instance/abstract/InstanceNode.ts +103 -105
  177. package/src/instance/abstract/UnsupportedControl.ts +28 -5
  178. package/src/instance/abstract/ValueNode.ts +127 -0
  179. package/src/instance/children.ts +9 -10
  180. package/src/instance/hierarchy.ts +19 -15
  181. package/src/instance/identity.ts +3 -9
  182. package/src/instance/index.ts +25 -7
  183. package/src/instance/internal-api/EvaluationContext.ts +60 -13
  184. package/src/instance/internal-api/InstanceConfig.ts +9 -2
  185. package/src/instance/internal-api/InstanceValueContext.ts +24 -0
  186. package/src/instance/internal-api/PrimaryInstanceDocument.ts +53 -0
  187. package/src/instance/internal-api/TranslationContext.ts +3 -2
  188. package/src/instance/internal-api/ValidationContext.ts +3 -4
  189. package/src/instance/internal-api/ValueContext.ts +2 -1
  190. package/src/instance/internal-api/submission/ClientReactiveSubmittableInstance.ts +20 -0
  191. package/src/instance/internal-api/submission/ClientReactiveSubmittableLeafNode.ts +42 -0
  192. package/src/instance/internal-api/submission/ClientReactiveSubmittableParentNode.ts +25 -0
  193. package/src/instance/internal-api/submission/ClientReactiveSubmittableValueNode.ts +23 -0
  194. package/src/instance/repeat/BaseRepeatRange.ts +50 -131
  195. package/src/instance/repeat/RepeatInstance.ts +20 -46
  196. package/src/instance/repeat/RepeatRangeControlled.ts +5 -5
  197. package/src/instance/repeat/RepeatRangeUncontrolled.ts +2 -4
  198. package/src/instance/resource.ts +1 -1
  199. package/src/instance/text/TextChunk.ts +1 -1
  200. package/src/instance/unsupported/RangeControl.ts +5 -1
  201. package/src/instance/unsupported/RankControl.ts +5 -1
  202. package/src/instance/unsupported/UploadControl.ts +5 -1
  203. package/src/integration/xpath/EngineXPathEvaluator.ts +22 -0
  204. package/src/integration/xpath/adapter/XFormsXPathNode.ts +126 -0
  205. package/src/integration/xpath/adapter/engineDOMAdapter.ts +57 -0
  206. package/src/integration/xpath/adapter/kind.ts +114 -0
  207. package/src/integration/xpath/adapter/names.ts +99 -0
  208. package/src/integration/xpath/adapter/traversal.ts +228 -0
  209. package/src/integration/xpath/adapter/values.ts +5 -0
  210. package/src/integration/xpath/static-dom/StaticAttribute.ts +33 -0
  211. package/src/integration/xpath/static-dom/StaticDocument.ts +38 -0
  212. package/src/integration/xpath/static-dom/StaticElement.ts +106 -0
  213. package/src/integration/xpath/static-dom/StaticNamedNode.ts +45 -0
  214. package/src/integration/xpath/static-dom/StaticNode.ts +68 -0
  215. package/src/integration/xpath/static-dom/StaticText.ts +28 -0
  216. package/src/lib/client-reactivity/README.md +0 -0
  217. package/src/lib/client-reactivity/submission/createInstanceSubmissionState.ts +12 -0
  218. package/src/lib/client-reactivity/submission/createLeafNodeSubmissionState.ts +20 -0
  219. package/src/lib/client-reactivity/submission/createNodeRangeSubmissionState.ts +17 -0
  220. package/src/lib/client-reactivity/submission/createParentNodeSubmissionState.ts +22 -0
  221. package/src/lib/client-reactivity/submission/createValueNodeSubmissionState.ts +21 -0
  222. package/src/lib/client-reactivity/submission/prepareSubmission.ts +172 -0
  223. package/src/lib/codecs/DecimalValueCodec.ts +46 -0
  224. package/src/lib/codecs/IntValueCodec.ts +100 -0
  225. package/src/lib/codecs/StringValueCodec.ts +11 -0
  226. package/src/lib/codecs/ValueCodec.ts +106 -0
  227. package/src/lib/codecs/ValueTypePlaceholderCodec.ts +19 -0
  228. package/src/lib/codecs/getSharedValueCodec.ts +77 -0
  229. package/src/lib/dom/query.ts +7 -0
  230. package/src/lib/reactivity/createChildrenState.ts +8 -6
  231. package/src/lib/reactivity/createComputedExpression.ts +57 -34
  232. package/src/lib/reactivity/createInstanceValueState.ts +166 -0
  233. package/src/lib/reactivity/createNoteReadonlyThunk.ts +12 -7
  234. package/src/lib/reactivity/createSelectItems.ts +21 -21
  235. package/src/lib/reactivity/createTranslationState.ts +61 -0
  236. package/src/lib/reactivity/createValueState.ts +62 -120
  237. package/src/lib/reactivity/materializeCurrentStateChildren.ts +7 -7
  238. package/src/lib/reactivity/text/createTextRange.ts +4 -3
  239. package/src/lib/reactivity/validation/createAggregatedViolations.ts +1 -1
  240. package/src/lib/reactivity/validation/createValidation.ts +2 -3
  241. package/src/lib/xml-serialization.ts +96 -0
  242. package/src/parse/XFormDOM.ts +110 -75
  243. package/src/parse/XFormDefinition.ts +1 -6
  244. package/src/parse/attachments/FormAttachmentResource.ts +40 -0
  245. package/src/parse/body/BodyDefinition.ts +3 -3
  246. package/src/parse/body/appearance/inputAppearanceParser.ts +1 -1
  247. package/src/parse/body/control/{InputDefinition.ts → InputControlDefinition.ts} +3 -5
  248. package/src/parse/body/control/select/ItemsetNodesetContext.ts +0 -5
  249. package/src/parse/expression/abstract/DependencyContext.ts +0 -26
  250. package/src/parse/expression/abstract/DependentExpression.ts +2 -13
  251. package/src/parse/model/BindDefinition.ts +5 -8
  252. package/src/parse/model/BindTypeDefinition.ts +175 -0
  253. package/src/parse/model/DescendentNodeDefinition.ts +0 -6
  254. package/src/parse/model/FormSubmissionDefinition.ts +44 -0
  255. package/src/parse/model/ItextTranslation/ItextTranslationDefinition.ts +4 -0
  256. package/src/parse/model/ItextTranslation/ItextTranslationRootDefinition.ts +41 -0
  257. package/src/parse/model/ItextTranslation/ItextTranslationsDefinition.ts +31 -0
  258. package/src/parse/model/LeafNodeDefinition.ts +4 -1
  259. package/src/parse/model/ModelBindMap.ts +6 -8
  260. package/src/parse/model/ModelDefinition.ts +6 -1
  261. package/src/parse/model/NodeDefinition.ts +0 -3
  262. package/src/parse/model/NoteNodeDefinition.ts +3 -3
  263. package/src/parse/model/RootDefinition.ts +2 -1
  264. package/src/parse/model/SecondaryInstance/SecondaryInstanceDefinition.ts +4 -0
  265. package/src/parse/model/SecondaryInstance/SecondaryInstanceRootDefinition.ts +12 -0
  266. package/src/parse/model/SecondaryInstance/SecondaryInstancesDefinition.ts +102 -0
  267. package/src/parse/model/SecondaryInstance/sources/BlankSecondaryInstanceSource.ts +40 -0
  268. package/src/parse/model/SecondaryInstance/sources/CSVExternalSecondaryInstance.ts +288 -0
  269. package/src/parse/model/SecondaryInstance/sources/ExternalSecondaryInstanceResource.ts +222 -0
  270. package/src/parse/model/SecondaryInstance/sources/ExternalSecondaryInstanceSource.ts +22 -0
  271. package/src/parse/model/SecondaryInstance/sources/GeoJSONExternalSecondaryInstance.ts +414 -0
  272. package/src/parse/model/SecondaryInstance/sources/InternalSecondaryInstanceSource.ts +19 -0
  273. package/src/parse/model/SecondaryInstance/sources/SecondaryInstanceSource.ts +29 -0
  274. package/src/parse/model/SecondaryInstance/sources/XMLExternalSecondaryInstanceSource.ts +32 -0
  275. package/src/parse/shared/parseStaticDocumentFromDOMSubtree.ts +149 -0
  276. package/src/parse/text/abstract/TextRangeDefinition.ts +0 -6
  277. package/src/parse/xpath/semantic-analysis.ts +29 -0
  278. package/dist/client/StringNode.d.ts +0 -46
  279. package/dist/instance/StringField.d.ts +0 -44
  280. package/dist/instance/internal-api/SubscribableDependency.d.ts +0 -59
  281. package/dist/parse/XFormDataType.d.ts +0 -25
  282. package/src/client/StringNode.ts +0 -52
  283. package/src/instance/StringField.ts +0 -120
  284. package/src/instance/internal-api/SubscribableDependency.ts +0 -61
  285. package/src/parse/XFormDataType.ts +0 -62
@@ -1,5 +1,37 @@
1
1
  import { XFORMS_NAMESPACE_URI, XMLNS_NAMESPACE_URI } from '@getodk/common/constants/xmlns.ts';
2
- import { XFormsXPathEvaluator } from '@getodk/xpath';
2
+ import type {
3
+ KnownAttributeLocalNamedElement,
4
+ LocalNamedElement,
5
+ } from '@getodk/common/types/dom.ts';
6
+ import { DefaultEvaluator } from '@getodk/xpath';
7
+
8
+ interface DOMBindElement extends KnownAttributeLocalNamedElement<'bind', 'nodeset'> {}
9
+
10
+ export interface DOMItextTranslationElement
11
+ extends KnownAttributeLocalNamedElement<'translation', 'lang'> {}
12
+
13
+ interface DOMInstanceElement extends LocalNamedElement<'instance'> {}
14
+
15
+ export interface DOMSecondaryInstanceElement
16
+ extends KnownAttributeLocalNamedElement<'instance', 'id'> {}
17
+
18
+ type AssertDOMSecondaryInstanceElement = (
19
+ element: DOMInstanceElement
20
+ ) => asserts element is DOMSecondaryInstanceElement;
21
+
22
+ const assertDOMSecondaryInstanceElement: AssertDOMSecondaryInstanceElement = (element) => {
23
+ if (!element.hasAttribute('id')) {
24
+ throw new Error('Invalid secondary instance element: missing `id` attribute');
25
+ }
26
+ };
27
+
28
+ type AssertDOMSecondaryInstanceElements = (
29
+ elements: readonly DOMInstanceElement[]
30
+ ) => asserts elements is readonly DOMSecondaryInstanceElement[];
31
+
32
+ const assertDOMSecondaryInstanceElements: AssertDOMSecondaryInstanceElements = (elements) => {
33
+ elements.forEach(assertDOMSecondaryInstanceElement);
34
+ };
3
35
 
4
36
  const domParser = new DOMParser();
5
37
 
@@ -145,61 +177,33 @@ const normalizeRepeatGroups = (body: Element): void => {
145
177
  }
146
178
  };
147
179
 
148
- interface NormalizedXForm {
149
- readonly xformDocument: XMLDocument;
150
- readonly rootEvaluator: XFormsXPathEvaluator;
151
- readonly html: Element;
152
- readonly body: Element;
153
- readonly normalizedXML: string;
154
- }
155
-
156
- interface XFormDOMNormalizationOptions {
157
- readonly isNormalized: boolean;
158
- }
159
-
160
180
  /**
161
- * Performs preprocess operations to normalize certain aspects of an XForm
162
- * structure for consistency when building up its runtime representations.
181
+ * Performs preprocess operations to normalize certain aspects of the body of an
182
+ * XForm, for consistency when parsing its runtime representations.
183
+ *
163
184
  * Currently this preprocessing:
164
185
  *
165
- * - Ensures consistent use of `ref` and `nodeset` where ambiguous in the
166
- * ODK XForms spec
167
- * - Ensures `<repeat>` body elements are always enclosed by a `<group>`
168
- * with the same `ref`
186
+ * - Ensures consistent use of `ref` and `nodeset` where ambiguous in the ODK
187
+ * XForms spec
188
+ * - Ensures `<repeat>` body elements are always enclosed by a `<group>` with
189
+ * the same `ref`
169
190
  */
170
- const parseNormalizedXForm = (
171
- sourceXML: string,
172
- options: XFormDOMNormalizationOptions
173
- ): NormalizedXForm => {
174
- const xformDocument: XMLDocument = domParser.parseFromString(sourceXML, 'text/xml');
175
- const rootEvaluator = new XFormsXPathEvaluator({
176
- rootNode: xformDocument,
177
- });
178
- const html = rootEvaluator.evaluateNonNullElement('/h:html');
179
- const body = rootEvaluator.evaluateNonNullElement('./h:body', {
180
- contextNode: html,
181
- });
182
-
183
- let normalizedXML: string;
191
+ const normalizeXFormBody = <T extends Element>(body: T): T => {
192
+ normalizeBodyRefNodesetAttributes(body);
193
+ normalizeRepeatGroups(body);
184
194
 
185
- if (options.isNormalized) {
186
- normalizedXML = sourceXML;
187
- } else {
188
- normalizeBodyRefNodesetAttributes(body);
189
- normalizeRepeatGroups(body);
190
-
191
- normalizedXML = html.outerHTML;
192
- }
193
-
194
- return {
195
- xformDocument,
196
- rootEvaluator,
197
- html,
198
- body,
199
- normalizedXML,
200
- };
195
+ return body;
201
196
  };
202
197
 
198
+ interface XFormDOMOptions {
199
+ readonly isNormalized: boolean;
200
+ }
201
+
202
+ /**
203
+ * @todo **Everything** in this class should be cacheable. Maybe not worth it
204
+ * for small forms, but may make a pretty substantial difference for very large
205
+ * forms (in bytes) in sessions creating multiple instances of the same form.
206
+ */
203
207
  export class XFormDOM {
204
208
  static from(sourceXML: string) {
205
209
  return new this(sourceXML, { isNormalized: false });
@@ -207,10 +211,6 @@ export class XFormDOM {
207
211
 
208
212
  protected readonly normalizedXML: string;
209
213
 
210
- // XPath
211
- readonly rootEvaluator: XFormsXPathEvaluator;
212
- readonly primaryInstanceEvaluator: XFormsXPathEvaluator;
213
-
214
214
  // Commonly accessed landmark nodes
215
215
  readonly xformDocument: XMLDocument;
216
216
 
@@ -220,59 +220,94 @@ export class XFormDOM {
220
220
  readonly title: Element;
221
221
 
222
222
  readonly model: Element;
223
+ readonly binds: readonly DOMBindElement[];
223
224
  readonly primaryInstance: Element;
224
225
  readonly primaryInstanceRoot: Element;
225
226
 
227
+ readonly itextTranslationElements: readonly DOMItextTranslationElement[];
228
+ readonly secondaryInstanceElements: readonly DOMSecondaryInstanceElement[];
229
+
226
230
  readonly body: Element;
227
231
 
228
232
  protected constructor(
229
233
  protected readonly sourceXML: string,
230
- options: XFormDOMNormalizationOptions
234
+ options: XFormDOMOptions
231
235
  ) {
232
- const normalizedXForm: NormalizedXForm = parseNormalizedXForm(sourceXML, options);
233
- const { xformDocument, html, body, rootEvaluator, normalizedXML } = normalizedXForm;
234
- const head = rootEvaluator.evaluateNonNullElement('./h:head', {
236
+ const evaluator = new DefaultEvaluator();
237
+ const xformDocument: XMLDocument = domParser.parseFromString(sourceXML, 'text/xml');
238
+ const html = evaluator.evaluateNonNullElement('/h:html', {
239
+ contextNode: xformDocument,
240
+ });
241
+
242
+ let body = evaluator.evaluateNonNullElement('./h:body', {
235
243
  contextNode: html,
236
244
  });
237
- const title = rootEvaluator.evaluateNonNullElement('./h:title', {
245
+ let normalizedXML: string;
246
+
247
+ if (options.isNormalized) {
248
+ normalizedXML = sourceXML;
249
+ } else {
250
+ body = normalizeXFormBody(body);
251
+
252
+ // TODO: if we keep doing normalization this way long term (or using the DOM
253
+ // for parsing long term, for that matter!), we should measure this. And we
254
+ // should measure against XMLSerializer while we're at it!
255
+ normalizedXML = xformDocument.documentElement.outerHTML;
256
+ }
257
+
258
+ const head = evaluator.evaluateNonNullElement('./h:head', {
259
+ contextNode: html,
260
+ });
261
+ const title = evaluator.evaluateNonNullElement('./h:title', {
238
262
  contextNode: head,
239
263
  });
240
- const model = rootEvaluator.evaluateNonNullElement('./xf:model', {
264
+ const model = evaluator.evaluateNonNullElement('./xf:model', {
241
265
  contextNode: head,
242
266
  });
243
- // TODO: Evidently primary instance root will not always have an id
244
- const primaryInstanceRoot = rootEvaluator.evaluateNonNullElement('./xf:instance/*[@id]', {
267
+ const binds = evaluator.evaluateNodes<DOMBindElement>('./xf:bind[@nodeset]', {
245
268
  contextNode: model,
246
269
  });
247
- // TODO: invert primary instance/root lookups
248
- const primaryInstance = rootEvaluator.evaluateNonNullElement('..', {
249
- contextNode: primaryInstanceRoot,
270
+
271
+ const instances = evaluator.evaluateNodes<DOMInstanceElement>('./xf:instance', {
272
+ contextNode: model,
250
273
  });
251
274
 
252
- this.normalizedXML = normalizedXML;
253
- this.rootEvaluator = rootEvaluator;
254
- this.primaryInstanceEvaluator = new XFormsXPathEvaluator({
255
- rootNode: primaryInstance,
275
+ const [primaryInstance, ...secondaryInstanceElements] = instances;
276
+
277
+ assertDOMSecondaryInstanceElements(secondaryInstanceElements);
278
+
279
+ if (primaryInstance == null) {
280
+ throw new Error('Form is missing primary instance');
281
+ }
282
+
283
+ // TODO: Evidently primary instance root will not always have an id
284
+ const primaryInstanceRoot = evaluator.evaluateNonNullElement('./*[@id]', {
285
+ contextNode: primaryInstance,
256
286
  });
287
+
288
+ const itextTranslationElements = evaluator.evaluateNodes<DOMItextTranslationElement>(
289
+ './xf:itext/xf:translation[@lang]',
290
+ {
291
+ contextNode: model,
292
+ }
293
+ );
294
+
295
+ this.normalizedXML = normalizedXML;
257
296
  this.xformDocument = xformDocument;
258
297
  this.html = html;
259
298
  this.head = head;
260
299
  this.title = title;
261
300
  this.model = model;
301
+ this.binds = binds;
262
302
  this.primaryInstance = primaryInstance;
263
303
  this.primaryInstanceRoot = primaryInstanceRoot;
304
+ this.itextTranslationElements = itextTranslationElements;
305
+ this.secondaryInstanceElements = secondaryInstanceElements;
264
306
  this.body = body;
265
307
  }
266
308
 
267
- // TODO: anticipating this will be an entry point for edits as well
268
- createInstance(): XFormDOM {
269
- return new XFormDOM(this.normalizedXML, { isNormalized: true });
270
- }
271
-
272
309
  toJSON() {
273
310
  const {
274
- rootEvaluator,
275
- primaryInstanceEvaluator,
276
311
  html,
277
312
  head,
278
313
  title,
@@ -3,7 +3,6 @@ import { ModelDefinition } from './model/ModelDefinition.ts';
3
3
  import { XFormDOM } from './XFormDOM.ts';
4
4
 
5
5
  export class XFormDefinition {
6
- readonly xformDOM: XFormDOM;
7
6
  readonly xformDocument: XMLDocument;
8
7
 
9
8
  readonly id: string;
@@ -14,11 +13,7 @@ export class XFormDefinition {
14
13
  readonly body: BodyDefinition;
15
14
  readonly model: ModelDefinition;
16
15
 
17
- constructor(readonly sourceXML: string) {
18
- const xformDOM = XFormDOM.from(sourceXML);
19
-
20
- this.xformDOM = xformDOM;
21
-
16
+ constructor(readonly xformDOM: XFormDOM) {
22
17
  const { primaryInstanceRoot, title, xformDocument } = xformDOM;
23
18
  const id = primaryInstanceRoot.getAttribute('id');
24
19
 
@@ -0,0 +1,40 @@
1
+ import type { JRResourceURL } from '@getodk/common/jr-resources/JRResourceURL.ts';
2
+
3
+ export type FormAttachmentDataType = 'media' | 'secondary-instance';
4
+
5
+ /**
6
+ * @todo This type anticipates work to support media form attachments, which
7
+ * will tend to be associated with binary data. The
8
+ * expectation is that:
9
+ *
10
+ * - {@link Blob} would be appropriate for representing data from attachment
11
+ * resources which are conventionally loaded to completion (where network
12
+ * conditions are favorable), such as images
13
+ *
14
+ * - {@link MediaSource} or {@link ReadableStream} may be more appropriate for
15
+ * representing data from resources which are conventionally streamed in a
16
+ * browser context (often regardless of network conditions), such as video and
17
+ * audio
18
+ */
19
+ // prettier-ignore
20
+ export type FormAttachmentMediaData =
21
+ | Blob
22
+ | MediaSource
23
+ | ReadableStream<unknown>;
24
+
25
+ export type FormAttachmentSecondaryInstanceData = string;
26
+
27
+ // prettier-ignore
28
+ type FormAttachmentData<DataType extends FormAttachmentDataType> =
29
+ DataType extends 'media'
30
+ ? FormAttachmentMediaData
31
+ : FormAttachmentSecondaryInstanceData;
32
+
33
+ export abstract class FormAttachmentResource<DataType extends FormAttachmentDataType> {
34
+ protected constructor(
35
+ readonly dataType: DataType,
36
+ readonly resourceURL: JRResourceURL,
37
+ readonly contentType: string,
38
+ readonly data: FormAttachmentData<DataType>
39
+ ) {}
40
+ }
@@ -3,7 +3,7 @@ import { TokenListParser } from '../../lib/TokenListParser.ts';
3
3
  import type { XFormDefinition } from '../../parse/XFormDefinition.ts';
4
4
  import { DependencyContext } from '../expression/abstract/DependencyContext.ts';
5
5
  import { ControlDefinition } from './control/ControlDefinition.ts';
6
- import { InputDefinition } from './control/InputDefinition.ts';
6
+ import { InputControlDefinition } from './control/InputControlDefinition.ts';
7
7
  import { RangeControlDefinition } from './control/RangeControlDefinition.ts';
8
8
  import { RankControlDefinition } from './control/RankControlDefinition.ts';
9
9
  import type { AnySelectDefinition } from './control/select/SelectDefinition.ts';
@@ -25,7 +25,7 @@ export interface BodyElementParentContext {
25
25
  // prettier-ignore
26
26
  export type ControlElementDefinition =
27
27
  | AnySelectDefinition
28
- | InputDefinition
28
+ | InputControlDefinition
29
29
  | RangeControlDefinition
30
30
  | RankControlDefinition
31
31
  | TriggerControlDefinition
@@ -47,7 +47,7 @@ const BodyElementDefinitionConstructors = [
47
47
  LogicalGroupDefinition,
48
48
  PresentationGroupDefinition,
49
49
  StructuralGroupDefinition,
50
- InputDefinition,
50
+ InputControlDefinition,
51
51
  SelectDefinition,
52
52
  RangeControlDefinition,
53
53
  RankControlDefinition,
@@ -4,7 +4,7 @@ export const inputAppearanceParser = new TokenListParser([
4
4
  'multiline',
5
5
  'numbers',
6
6
  'url',
7
- 'thousand-sep',
7
+ 'thousands-sep',
8
8
 
9
9
  // date (TODO: data types)
10
10
  'no-calendar',
@@ -1,12 +1,10 @@
1
1
  import type { XFormDefinition } from '../../XFormDefinition.ts';
2
- import {
3
- inputAppearanceParser,
4
- type InputAppearanceDefinition,
5
- } from '../appearance/inputAppearanceParser.ts';
2
+ import type { InputAppearanceDefinition } from '../appearance/inputAppearanceParser.ts';
3
+ import { inputAppearanceParser } from '../appearance/inputAppearanceParser.ts';
6
4
  import type { BodyElementParentContext } from '../BodyDefinition.ts';
7
5
  import { ControlDefinition } from './ControlDefinition.ts';
8
6
 
9
- export class InputDefinition extends ControlDefinition<'input'> {
7
+ export class InputControlDefinition extends ControlDefinition<'input'> {
10
8
  static override isCompatible(localName: string): boolean {
11
9
  return localName === 'input';
12
10
  }
@@ -1,5 +1,4 @@
1
1
  import { DependencyContext } from '../../../expression/abstract/DependencyContext.ts';
2
- import type { AnyDependentExpression } from '../../../expression/abstract/DependentExpression.ts';
3
2
  import type { ItemsetDefinition } from './ItemsetDefinition.ts';
4
3
 
5
4
  export class ItemsetNodesetContext extends DependencyContext {
@@ -19,8 +18,4 @@ export class ItemsetNodesetContext extends DependencyContext {
19
18
  super.isTranslated = value;
20
19
  this.itemset.isTranslated = value;
21
20
  }
22
-
23
- override registerDependentExpression(expression: AnyDependentExpression): void {
24
- this.itemset.registerDependentExpression(expression);
25
- }
26
21
  }
@@ -1,28 +1,7 @@
1
- import type { AnyDependentExpression } from './DependentExpression.ts';
2
-
3
1
  export abstract class DependencyContext {
4
2
  abstract get parentReference(): string | null;
5
3
  abstract get reference(): string | null;
6
4
 
7
- protected readonly dependentExpressions = new Set<AnyDependentExpression>();
8
-
9
- protected dependencyExpressionsCache: ReadonlySet<string> | null = null;
10
-
11
- get dependencyExpressions(): ReadonlySet<string> {
12
- let { dependencyExpressionsCache } = this;
13
-
14
- if (dependencyExpressionsCache == null) {
15
- dependencyExpressionsCache = new Set(
16
- Array.from(this.dependentExpressions).flatMap((expression) => {
17
- return Array.from(expression.dependencyReferences);
18
- })
19
- );
20
- this.dependencyExpressionsCache = dependencyExpressionsCache;
21
- }
22
-
23
- return dependencyExpressionsCache;
24
- }
25
-
26
5
  get isTranslated(): boolean {
27
6
  return this._isTranslated;
28
7
  }
@@ -45,9 +24,4 @@ export abstract class DependencyContext {
45
24
 
46
25
  // Update note on `set isTranslated` if this internal storage changes.
47
26
  protected _isTranslated = false;
48
-
49
- registerDependentExpression(expression: AnyDependentExpression): void {
50
- this.dependencyExpressionsCache = null;
51
- this.dependentExpressions.add(expression);
52
- }
53
27
  }
@@ -1,5 +1,4 @@
1
- import type { XFormsXPathEvaluator } from '@getodk/xpath';
2
- import { resolveDependencyNodesets } from '../../xpath/dependency-analysis.ts';
1
+ import type { EngineXPathEvaluator } from '../../../integration/xpath/EngineXPathEvaluator.ts';
3
2
  import type {
4
3
  ConstantExpression,
5
4
  ConstantTruthyExpression,
@@ -26,7 +25,7 @@ export type DependentExpressionEvaluatorMethod<Type extends DependentExpressionR
26
25
  EvaluatorMethodsByResultType[Type];
27
26
 
28
27
  export type DependentExpressionResult<Type extends DependentExpressionResultType> = ReturnType<
29
- XFormsXPathEvaluator[DependentExpressionEvaluatorMethod<Type>]
28
+ EngineXPathEvaluator[DependentExpressionEvaluatorMethod<Type>]
30
29
  >;
31
30
 
32
31
  interface SemanticDependencyOptions {
@@ -55,7 +54,6 @@ export interface ConstantTruthyDependentExpression extends ConstantDependentExpr
55
54
  }
56
55
 
57
56
  export abstract class DependentExpression<Type extends DependentExpressionResultType> {
58
- readonly dependencyReferences: ReadonlySet<string> = new Set();
59
57
  readonly isTranslated: boolean = false;
60
58
  readonly evaluatorMethod: DependentExpressionEvaluatorMethod<Type>;
61
59
  readonly constantExpression: ConstantExpression | null;
@@ -81,26 +79,17 @@ export abstract class DependentExpression<Type extends DependentExpressionResult
81
79
  this.evaluatorMethod = evaluatorMethodsByResultType[resultType];
82
80
 
83
81
  const {
84
- ignoreContextReference = false,
85
82
  semanticDependencies = {
86
83
  translations: false,
87
84
  },
88
85
  } = options;
89
86
 
90
- this.dependencyReferences = new Set(
91
- resolveDependencyNodesets(context.reference, expression, {
92
- ignoreReferenceToContextPath: ignoreContextReference,
93
- })
94
- );
95
-
96
87
  const isTranslated = semanticDependencies.translations && isTranslationExpression(expression);
97
88
 
98
89
  if (isTranslated) {
99
90
  this.isTranslated = true;
100
91
  context.isTranslated = true;
101
92
  }
102
-
103
- context.registerDependentExpression(this);
104
93
  }
105
94
 
106
95
  isConstantExpression(): this is ConstantDependentExpression<Type> {
@@ -2,15 +2,14 @@ import { DependencyContext } from '../expression/abstract/DependencyContext.ts';
2
2
  import type { DependentExpression } from '../expression/abstract/DependentExpression.ts';
3
3
  import { BindComputationExpression } from '../expression/BindComputationExpression.ts';
4
4
  import { MessageDefinition } from '../text/MessageDefinition.ts';
5
- import type { XFormDataType } from '../XFormDataType.ts';
6
- import { bindDataType } from '../XFormDataType.ts';
7
5
  import type { XFormDefinition } from '../XFormDefinition.ts';
8
6
  import type { BindElement } from './BindElement.ts';
7
+ import type { BindType } from './BindTypeDefinition.ts';
8
+ import { BindTypeDefinition } from './BindTypeDefinition.ts';
9
9
  import type { ModelDefinition } from './ModelDefinition.ts';
10
10
 
11
- export class BindDefinition extends DependencyContext {
12
- readonly bindType: string | null;
13
- readonly dataType: XFormDataType;
11
+ export class BindDefinition<T extends BindType = BindType> extends DependencyContext {
12
+ readonly type: BindTypeDefinition<T>;
14
13
  readonly parentNodeset: string | null;
15
14
 
16
15
  readonly calculate: BindComputationExpression<'calculate'> | null;
@@ -78,9 +77,7 @@ export class BindDefinition extends DependencyContext {
78
77
  ) {
79
78
  super();
80
79
 
81
- const bindType = (this.bindType = bindElement.getAttribute('type'));
82
-
83
- this.dataType = bindDataType(bindType);
80
+ this.type = BindTypeDefinition.from(bindElement);
84
81
 
85
82
  const parentNodeset = nodeset.replace(/\/[^/]+$/, '');
86
83
 
@@ -0,0 +1,175 @@
1
+ import { XSD_NAMESPACE_URI, XSD_PREFIX } from '@getodk/common/constants/xmlns.ts';
2
+ import { parseQualifiedNameExpression } from '../xpath/semantic-analysis.ts';
3
+ import type { BindElement } from './BindElement.ts';
4
+
5
+ /**
6
+ * As specified by {@link https://getodk.github.io/xforms-spec/#bind-attributes}
7
+ */
8
+ export const DEFAULT_BIND_TYPE = 'string';
9
+
10
+ export type DefaultBindType = typeof DEFAULT_BIND_TYPE;
11
+
12
+ /**
13
+ * As specified by {@link https://getodk.github.io/xforms-spec/#data-types}
14
+ */
15
+ const BIND_TYPES = [
16
+ DEFAULT_BIND_TYPE,
17
+ 'int',
18
+ 'boolean',
19
+ 'decimal',
20
+ 'date',
21
+ 'time',
22
+ 'dateTime',
23
+ 'geopoint',
24
+ 'geotrace',
25
+ 'geoshape',
26
+ 'binary',
27
+ 'barcode',
28
+ 'intent',
29
+ ] as const;
30
+
31
+ type BindTypes = typeof BIND_TYPES;
32
+
33
+ export type BindType = BindTypes[number];
34
+
35
+ const isBindType = (value: string): value is BindType => {
36
+ return BIND_TYPES.includes(value as BindType);
37
+ };
38
+
39
+ const resolveSupportedBindType = (sourceType: string): BindType | null => {
40
+ return isBindType(sourceType) ? sourceType : null;
41
+ };
42
+
43
+ type BindTypeAliasMapping = Readonly<Record<string, BindType>>;
44
+
45
+ /**
46
+ * @todo should we make these aliases explicit (rather than relying on {@link resolveUnsupportedBindType})?
47
+ *
48
+ * - select1
49
+ * - rank
50
+ * - odk:rank
51
+ */
52
+ const BIND_TYPE_ALIASES: BindTypeAliasMapping = {
53
+ integer: 'int',
54
+ };
55
+
56
+ /**
57
+ * @todo Should this be marked deprecated?
58
+ * @todo Should we warn on alias resolution?
59
+ */
60
+ const resolveAliasedBindType = (sourceType: string): BindType | null => {
61
+ return BIND_TYPE_ALIASES[sourceType] ?? null;
62
+ };
63
+
64
+ /**
65
+ * @todo Should we warn on this fallback?
66
+ */
67
+ const resolveUnsupportedBindType = (_unsupportedType: string): BindType => {
68
+ return DEFAULT_BIND_TYPE;
69
+ };
70
+
71
+ interface BindDataTypeNamespaceResolver {
72
+ lookupNamespaceURI(prefix: string | null): string | null;
73
+ lookupPrefix(namespaceURI: string | null): string | null;
74
+ }
75
+
76
+ /**
77
+ * Resolves the XML Schema namespace prefix by:
78
+ *
79
+ * - Explicitly declared prefix, if any
80
+ * - Default to {@link XSD_PREFIX} _unless that prefix is bound to some other
81
+ * namespace URI_
82
+ */
83
+ const resolveXMLSchemaNamespacePrefix = (
84
+ resolver: BindDataTypeNamespaceResolver
85
+ ): string | null => {
86
+ const declaredPrefix = resolver.lookupPrefix(XSD_NAMESPACE_URI);
87
+
88
+ if (declaredPrefix != null) {
89
+ return declaredPrefix;
90
+ }
91
+
92
+ if (resolver.lookupNamespaceURI(XSD_PREFIX) == null) {
93
+ return XSD_PREFIX;
94
+ }
95
+
96
+ return null;
97
+ };
98
+
99
+ interface MaybeBindElementNamespaceResolver
100
+ extends BindElement,
101
+ Partial<BindDataTypeNamespaceResolver> {}
102
+
103
+ interface BindElementNamespaceResolver extends BindElement, BindDataTypeNamespaceResolver {}
104
+
105
+ const isNamespaceResolver = (
106
+ bindElement: MaybeBindElementNamespaceResolver
107
+ ): bindElement is BindElementNamespaceResolver => {
108
+ return (
109
+ typeof bindElement.lookupNamespaceURI === 'function' &&
110
+ typeof bindElement.lookupPrefix === 'function'
111
+ );
112
+ };
113
+
114
+ const resolveNamespacedBindType = (
115
+ bindElement: BindElement,
116
+ sourceType: string
117
+ ): BindType | null => {
118
+ if (!isNamespaceResolver(bindElement)) {
119
+ return null;
120
+ }
121
+
122
+ const qualifiedName = parseQualifiedNameExpression(sourceType);
123
+
124
+ if (qualifiedName == null) {
125
+ return null;
126
+ }
127
+
128
+ const xsdPrefix = resolveXMLSchemaNamespacePrefix(bindElement);
129
+
130
+ if (xsdPrefix == null) {
131
+ return null;
132
+ }
133
+
134
+ const { prefix, localPart } = qualifiedName;
135
+
136
+ if (prefix === xsdPrefix) {
137
+ return (
138
+ resolveSupportedBindType(localPart) ??
139
+ resolveAliasedBindType(localPart) ??
140
+ resolveUnsupportedBindType(localPart)
141
+ );
142
+ }
143
+
144
+ return null;
145
+ };
146
+
147
+ const resolveBindType = (bindElement: BindElement, sourceType: string): BindType => {
148
+ return (
149
+ resolveSupportedBindType(sourceType) ??
150
+ resolveAliasedBindType(sourceType) ??
151
+ resolveNamespacedBindType(bindElement, sourceType) ??
152
+ resolveUnsupportedBindType(sourceType)
153
+ );
154
+ };
155
+
156
+ export class BindTypeDefinition<T extends BindType = BindType> {
157
+ static from<T extends BindType>(bindElement: BindElement): BindTypeDefinition<T> {
158
+ const sourceType = bindElement.getAttribute('type');
159
+
160
+ if (sourceType == null) {
161
+ return new this(sourceType, DEFAULT_BIND_TYPE);
162
+ }
163
+
164
+ const resolved = resolveBindType(bindElement, sourceType);
165
+
166
+ return new this(sourceType, resolved);
167
+ }
168
+
169
+ private constructor(source: null, resolved: DefaultBindType);
170
+ private constructor(source: string, resolved: BindType);
171
+ private constructor(
172
+ readonly source: string | null,
173
+ readonly resolved: T
174
+ ) {}
175
+ }