@getodk/xforms-engine 0.5.0 → 0.7.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 (425) hide show
  1. package/README.md +1 -1
  2. package/dist/client/BaseNode.d.ts +8 -4
  3. package/dist/client/BaseValueNode.d.ts +8 -4
  4. package/dist/client/GroupNode.d.ts +1 -0
  5. package/dist/client/InputNode.d.ts +32 -3
  6. package/dist/client/ModelValueNode.d.ts +1 -0
  7. package/dist/client/NoteNode.d.ts +24 -7
  8. package/dist/client/RangeNode.d.ts +36 -0
  9. package/dist/client/RankNode.d.ts +46 -0
  10. package/dist/client/RootNode.d.ts +21 -14
  11. package/dist/client/SelectNode.d.ts +47 -25
  12. package/dist/client/SubtreeNode.d.ts +1 -0
  13. package/dist/client/TriggerNode.d.ts +10 -6
  14. package/dist/client/constants.d.ts +11 -12
  15. package/dist/client/form/CreateFormInstance.d.ts +14 -0
  16. package/dist/client/form/EditFormInstance.d.ts +62 -0
  17. package/dist/client/form/FormInstance.d.ts +104 -0
  18. package/dist/client/form/FormInstanceConfig.d.ts +17 -0
  19. package/dist/client/form/FormResource.d.ts +1 -0
  20. package/dist/client/form/LoadForm.d.ts +79 -0
  21. package/dist/client/form/LoadFormResult.d.ts +67 -0
  22. package/dist/client/form/RestoreFormInstance.d.ts +8 -0
  23. package/dist/client/hierarchy.d.ts +5 -5
  24. package/dist/client/index.d.ts +37 -11
  25. package/dist/client/node-types.d.ts +2 -2
  26. package/dist/client/repeat/BaseRepeatRangeNode.d.ts +3 -4
  27. package/dist/client/repeat/RepeatInstanceNode.d.ts +4 -5
  28. package/dist/client/repeat/RepeatRangeControlledNode.d.ts +2 -2
  29. package/dist/client/repeat/RepeatRangeUncontrolledNode.d.ts +2 -2
  30. package/dist/client/resources.d.ts +1 -1
  31. package/dist/client/serialization/InstanceData.d.ts +12 -0
  32. package/dist/client/serialization/InstanceFile.d.ts +6 -0
  33. package/dist/client/serialization/InstancePayload.d.ts +93 -0
  34. package/dist/client/serialization/InstancePayloadOptions.d.ts +23 -0
  35. package/dist/client/serialization/InstanceState.d.ts +12 -0
  36. package/dist/client/submission/{SubmissionDefinition.d.ts → SubmissionMeta.d.ts} +1 -1
  37. package/dist/client/unsupported/UnsupportedControlNode.d.ts +1 -3
  38. package/dist/entrypoints/FormInstance.d.ts +20 -0
  39. package/dist/entrypoints/FormResult/BaseFormResult.d.ts +22 -0
  40. package/dist/entrypoints/FormResult/BaseInstantiableFormResult.d.ts +25 -0
  41. package/dist/entrypoints/FormResult/FormFailureResult.d.ts +17 -0
  42. package/dist/entrypoints/FormResult/FormSuccessResult.d.ts +15 -0
  43. package/dist/entrypoints/FormResult/FormWarningResult.d.ts +15 -0
  44. package/dist/entrypoints/createInstance.d.ts +9 -0
  45. package/dist/entrypoints/editInstance.d.ts +9 -0
  46. package/dist/entrypoints/index.d.ts +4 -0
  47. package/dist/entrypoints/loadForm.d.ts +4 -0
  48. package/dist/entrypoints/restoreInstance.d.ts +9 -0
  49. package/dist/error/LoadFormFailureError.d.ts +9 -0
  50. package/dist/error/MalformedInstanceDataError.d.ts +3 -0
  51. package/dist/error/RankMissingValueError.d.ts +3 -0
  52. package/dist/error/RankValueTypeError.d.ts +6 -0
  53. package/dist/error/SelectValueTypeError.d.ts +15 -0
  54. package/dist/error/TemplatedNodeAttributeSerializationError.d.ts +22 -0
  55. package/dist/error/XFormsSpecViolationError.d.ts +2 -0
  56. package/dist/index.d.ts +2 -34
  57. package/dist/index.js +7274 -5840
  58. package/dist/index.js.map +1 -1
  59. package/dist/instance/Group.d.ts +7 -5
  60. package/dist/instance/InputControl.d.ts +9 -6
  61. package/dist/instance/ModelValue.d.ts +7 -4
  62. package/dist/instance/Note.d.ts +14 -25
  63. package/dist/instance/PrimaryInstance.d.ts +36 -8
  64. package/dist/instance/RangeControl.d.ts +35 -0
  65. package/dist/instance/RankControl.d.ts +41 -0
  66. package/dist/instance/Root.d.ts +8 -9
  67. package/dist/instance/SelectControl.d.ts +67 -0
  68. package/dist/instance/Subtree.d.ts +7 -5
  69. package/dist/instance/TriggerControl.d.ts +10 -22
  70. package/dist/instance/abstract/DescendantNode.d.ts +11 -3
  71. package/dist/instance/abstract/InstanceNode.d.ts +10 -5
  72. package/dist/instance/abstract/ValueNode.d.ts +7 -6
  73. package/dist/instance/children/DescendantNodeInitOptions.d.ts +32 -0
  74. package/dist/instance/{children.d.ts → children/buildChildren.d.ts} +1 -1
  75. package/dist/instance/children/childrenInitOptions.d.ts +9 -0
  76. package/dist/instance/children/normalizeChildInitOptions.d.ts +2 -0
  77. package/dist/instance/hierarchy.d.ts +9 -9
  78. package/dist/instance/input/InitialInstanceState.d.ts +13 -0
  79. package/dist/instance/input/InstanceAttachmentMap.d.ts +19 -0
  80. package/dist/instance/internal-api/InstanceConfig.d.ts +2 -9
  81. package/dist/instance/internal-api/InstanceValueContext.d.ts +10 -1
  82. package/dist/instance/internal-api/serialization/ClientReactiveSerializableInstance.d.ts +14 -0
  83. package/dist/instance/internal-api/serialization/ClientReactiveSerializableLeafNode.d.ts +32 -0
  84. package/dist/instance/internal-api/serialization/ClientReactiveSerializableParentNode.d.ts +18 -0
  85. package/dist/instance/internal-api/serialization/ClientReactiveSerializableTemplatedNode.d.ts +13 -0
  86. package/dist/instance/internal-api/serialization/ClientReactiveSerializableValueNode.d.ts +21 -0
  87. package/dist/instance/repeat/BaseRepeatRange.d.ts +11 -8
  88. package/dist/instance/repeat/RepeatInstance.d.ts +11 -7
  89. package/dist/instance/repeat/RepeatRangeControlled.d.ts +27 -3
  90. package/dist/instance/repeat/RepeatRangeUncontrolled.d.ts +4 -3
  91. package/dist/instance/resource.d.ts +5 -1
  92. package/dist/instance/unsupported/UploadControl.d.ts +32 -4
  93. package/dist/integration/xpath/EngineXPathEvaluator.d.ts +2 -2
  94. package/dist/integration/xpath/adapter/kind.d.ts +4 -10
  95. package/dist/integration/xpath/adapter/names.d.ts +1 -11
  96. package/dist/integration/xpath/adapter/traversal.d.ts +10 -9
  97. package/dist/integration/xpath/static-dom/StaticAttribute.d.ts +10 -4
  98. package/dist/integration/xpath/static-dom/StaticDocument.d.ts +13 -11
  99. package/dist/integration/xpath/static-dom/StaticElement.d.ts +25 -18
  100. package/dist/integration/xpath/static-dom/StaticNode.d.ts +1 -1
  101. package/dist/integration/xpath/static-dom/StaticParentNode.d.ts +13 -0
  102. package/dist/integration/xpath/static-dom/staticNodeName.d.ts +3 -0
  103. package/dist/lib/client-reactivity/instance-state/createNodeRangeInstanceState.d.ts +4 -0
  104. package/dist/lib/client-reactivity/instance-state/createParentNodeInstanceState.d.ts +4 -0
  105. package/dist/lib/client-reactivity/instance-state/createPrimaryInstanceState.d.ts +3 -0
  106. package/dist/lib/client-reactivity/instance-state/createRootInstanceState.d.ts +3 -0
  107. package/dist/lib/client-reactivity/instance-state/createTemplatedNodeInstanceState.d.ts +6 -0
  108. package/dist/lib/client-reactivity/instance-state/createValueNodeInstanceState.d.ts +3 -0
  109. package/dist/lib/client-reactivity/instance-state/prepareInstancePayload.d.ts +8 -0
  110. package/dist/lib/codecs/Geopoint/Geopoint.d.ts +48 -0
  111. package/dist/lib/codecs/Geopoint/GeopointValueCodec.d.ts +5 -0
  112. package/dist/lib/codecs/NoteCodec.d.ts +8 -0
  113. package/dist/lib/codecs/RangeCodec.d.ts +8 -0
  114. package/dist/lib/codecs/TempUnsupportedControlCodec.d.ts +7 -0
  115. package/dist/lib/codecs/TriggerCodec.d.ts +7 -0
  116. package/dist/lib/codecs/ValueArrayCodec.d.ts +11 -0
  117. package/dist/lib/codecs/ValueCodec.d.ts +2 -2
  118. package/dist/lib/codecs/getNoteCodec.d.ts +3 -0
  119. package/dist/lib/codecs/getSelectCodec.d.ts +5 -0
  120. package/dist/lib/codecs/getSharedValueCodec.d.ts +3 -2
  121. package/dist/lib/codecs/items/BaseItemCodec.d.ts +9 -0
  122. package/dist/lib/codecs/items/MultipleValueItemCodec.d.ts +14 -0
  123. package/dist/lib/codecs/items/SingleValueItemCodec.d.ts +24 -0
  124. package/dist/lib/dom/query.d.ts +1 -2
  125. package/dist/lib/names/NamespaceDeclaration.d.ts +45 -0
  126. package/dist/lib/names/NamespaceDeclarationMap.d.ts +137 -0
  127. package/dist/lib/names/NamespaceURL.d.ts +30 -0
  128. package/dist/lib/names/QualifiedName.d.ts +113 -0
  129. package/dist/lib/names/UnprefixedXFormsName.d.ts +4 -0
  130. package/dist/lib/number-parsers.d.ts +2 -0
  131. package/dist/lib/reactivity/createInstanceValueState.d.ts +2 -27
  132. package/dist/lib/reactivity/createItemCollection.d.ts +21 -0
  133. package/dist/lib/xml-serialization.d.ts +11 -2
  134. package/dist/parse/XFormDOM.d.ts +1 -1
  135. package/dist/parse/body/BodyDefinition.d.ts +2 -2
  136. package/dist/parse/body/appearance/rangeAppearanceParser.d.ts +3 -0
  137. package/dist/parse/body/control/InputControlDefinition.d.ts +3 -0
  138. package/dist/parse/body/control/ItemDefinition.d.ts +14 -0
  139. package/dist/parse/body/control/ItemsetDefinition.d.ts +18 -0
  140. package/dist/parse/body/control/RangeControlDefinition.d.ts +31 -2
  141. package/dist/parse/body/control/RankControlDefinition.d.ts +7 -3
  142. package/dist/parse/body/control/{select/SelectDefinition.d.ts → SelectControlDefinition.d.ts} +9 -9
  143. package/dist/parse/expression/ItemsetNodesetExpression.d.ts +1 -1
  144. package/dist/parse/expression/ItemsetValueExpression.d.ts +1 -1
  145. package/dist/parse/model/BindDefinition.d.ts +3 -1
  146. package/dist/parse/model/BindPreloadDefinition.d.ts +42 -0
  147. package/dist/parse/model/DescendentNodeDefinition.d.ts +4 -13
  148. package/dist/parse/model/ItextTranslationsDefinition.d.ts +18 -0
  149. package/dist/parse/model/LeafNodeDefinition.d.ts +9 -7
  150. package/dist/parse/model/ModelDefinition.d.ts +9 -2
  151. package/dist/parse/model/NodeDefinition.d.ts +30 -45
  152. package/dist/parse/model/NoteNodeDefinition.d.ts +7 -5
  153. package/dist/parse/model/RangeNodeDefinition.d.ts +42 -0
  154. package/dist/parse/model/RepeatDefinition.d.ts +62 -0
  155. package/dist/parse/model/RootAttributeDefinition.d.ts +21 -0
  156. package/dist/parse/model/RootAttributeMap.d.ts +24 -0
  157. package/dist/parse/model/RootDefinition.d.ts +15 -14
  158. package/dist/parse/model/SecondaryInstance/SecondaryInstancesDefinition.d.ts +15 -2
  159. package/dist/parse/model/SecondaryInstance/assertSecondaryInstanceDefinition.d.ts +5 -0
  160. package/dist/parse/model/SecondaryInstance/defineSecondaryInstance.d.ts +5 -0
  161. package/dist/parse/model/SecondaryInstance/sources/BlankSecondaryInstanceSource.d.ts +1 -7
  162. package/dist/parse/model/SecondaryInstance/sources/CSVExternalSecondaryInstance.d.ts +1 -1
  163. package/dist/parse/model/SecondaryInstance/sources/GeoJSONExternalSecondaryInstance.d.ts +1 -1
  164. package/dist/parse/model/SecondaryInstance/sources/InternalSecondaryInstanceSource.d.ts +1 -1
  165. package/dist/parse/model/SecondaryInstance/sources/SecondaryInstanceSource.d.ts +1 -1
  166. package/dist/parse/model/SecondaryInstance/sources/XMLExternalSecondaryInstanceSource.d.ts +1 -1
  167. package/dist/parse/model/{FormSubmissionDefinition.d.ts → SubmissionDefinition.d.ts} +2 -2
  168. package/dist/parse/model/SubtreeDefinition.d.ts +9 -7
  169. package/dist/parse/model/nodeDefinitionMap.d.ts +5 -0
  170. package/dist/parse/shared/parseInstanceXML.d.ts +21 -0
  171. package/dist/parse/shared/parseStaticDocumentFromDOMSubtree.d.ts +4 -22
  172. package/dist/parse/text/ItemLabelDefinition.d.ts +1 -1
  173. package/dist/parse/text/ItemsetLabelDefinition.d.ts +2 -2
  174. package/dist/parse/text/abstract/TextElementDefinition.d.ts +1 -1
  175. package/dist/parse/xpath/semantic-analysis.d.ts +1 -3
  176. package/dist/solid.js +7247 -5813
  177. package/dist/solid.js.map +1 -1
  178. package/package.json +15 -12
  179. package/src/client/BaseNode.ts +9 -4
  180. package/src/client/BaseValueNode.ts +8 -4
  181. package/src/client/GroupNode.ts +1 -0
  182. package/src/client/InputNode.ts +38 -2
  183. package/src/client/ModelValueNode.ts +1 -0
  184. package/src/client/NoteNode.ts +43 -7
  185. package/src/client/RangeNode.ts +51 -0
  186. package/src/client/RankNode.ts +54 -0
  187. package/src/client/RootNode.ts +30 -16
  188. package/src/client/SelectNode.ts +53 -26
  189. package/src/client/SubtreeNode.ts +1 -0
  190. package/src/client/TriggerNode.ts +12 -6
  191. package/src/client/constants.ts +12 -14
  192. package/src/client/form/CreateFormInstance.ts +19 -0
  193. package/src/client/form/EditFormInstance.ts +93 -0
  194. package/src/client/form/FormInstance.ts +114 -0
  195. package/src/client/form/FormInstanceConfig.ts +18 -0
  196. package/src/client/form/FormResource.ts +1 -0
  197. package/src/client/form/LoadForm.ts +92 -0
  198. package/src/client/form/LoadFormResult.ts +103 -0
  199. package/src/client/form/RestoreFormInstance.ts +14 -0
  200. package/src/client/hierarchy.ts +7 -8
  201. package/src/client/index.ts +47 -29
  202. package/src/client/node-types.ts +3 -5
  203. package/src/client/repeat/BaseRepeatRangeNode.ts +3 -4
  204. package/src/client/repeat/RepeatInstanceNode.ts +4 -8
  205. package/src/client/repeat/RepeatRangeControlledNode.ts +2 -2
  206. package/src/client/repeat/RepeatRangeUncontrolledNode.ts +2 -2
  207. package/src/client/resources.ts +2 -2
  208. package/src/client/serialization/InstanceData.ts +16 -0
  209. package/src/client/serialization/InstanceFile.ts +9 -0
  210. package/src/client/serialization/InstancePayload.ts +126 -0
  211. package/src/client/serialization/InstancePayloadOptions.ts +28 -0
  212. package/src/client/serialization/InstanceState.ts +14 -0
  213. package/src/client/submission/{SubmissionDefinition.ts → SubmissionMeta.ts} +1 -1
  214. package/src/client/unsupported/UnsupportedControlNode.ts +2 -6
  215. package/src/entrypoints/FormInstance.ts +55 -0
  216. package/src/entrypoints/FormResult/BaseFormResult.ts +40 -0
  217. package/src/entrypoints/FormResult/BaseInstantiableFormResult.ts +109 -0
  218. package/src/entrypoints/FormResult/FormFailureResult.ts +44 -0
  219. package/src/entrypoints/FormResult/FormSuccessResult.ts +25 -0
  220. package/src/entrypoints/FormResult/FormWarningResult.ts +25 -0
  221. package/src/entrypoints/createInstance.ts +23 -0
  222. package/src/entrypoints/editInstance.ts +24 -0
  223. package/src/entrypoints/index.ts +4 -0
  224. package/src/entrypoints/loadForm.ts +154 -0
  225. package/src/entrypoints/restoreInstance.ts +27 -0
  226. package/src/error/LoadFormFailureError.ts +114 -0
  227. package/src/error/MalformedInstanceDataError.ts +3 -0
  228. package/src/error/RankMissingValueError.ts +5 -0
  229. package/src/error/RankValueTypeError.ts +13 -0
  230. package/src/error/SelectValueTypeError.ts +22 -0
  231. package/src/error/TemplatedNodeAttributeSerializationError.ts +24 -0
  232. package/src/error/XFormsSpecViolationError.ts +1 -0
  233. package/src/index.ts +2 -56
  234. package/src/instance/Group.ts +17 -15
  235. package/src/instance/InputControl.ts +58 -12
  236. package/src/instance/ModelValue.ts +19 -11
  237. package/src/instance/Note.ts +40 -64
  238. package/src/instance/PrimaryInstance.ts +70 -31
  239. package/src/instance/RangeControl.ts +119 -0
  240. package/src/instance/RankControl.ts +208 -0
  241. package/src/instance/Root.ts +21 -31
  242. package/src/instance/SelectControl.ts +228 -0
  243. package/src/instance/Subtree.ts +17 -15
  244. package/src/instance/TriggerControl.ts +50 -80
  245. package/src/instance/abstract/DescendantNode.ts +13 -8
  246. package/src/instance/abstract/InstanceNode.ts +19 -7
  247. package/src/instance/abstract/ValueNode.ts +14 -15
  248. package/src/instance/children/DescendantNodeInitOptions.ts +35 -0
  249. package/src/instance/children/buildChildren.ts +206 -0
  250. package/src/instance/children/childrenInitOptions.ts +117 -0
  251. package/src/instance/children/normalizeChildInitOptions.ts +332 -0
  252. package/src/instance/hierarchy.ts +21 -16
  253. package/src/instance/input/InitialInstanceState.ts +108 -0
  254. package/src/instance/input/InstanceAttachmentMap.ts +142 -0
  255. package/src/instance/internal-api/InstanceConfig.ts +3 -10
  256. package/src/instance/internal-api/InstanceValueContext.ts +11 -1
  257. package/src/instance/internal-api/serialization/ClientReactiveSerializableInstance.ts +20 -0
  258. package/src/instance/internal-api/serialization/ClientReactiveSerializableLeafNode.ts +43 -0
  259. package/src/instance/internal-api/serialization/ClientReactiveSerializableParentNode.ts +26 -0
  260. package/src/instance/internal-api/serialization/ClientReactiveSerializableTemplatedNode.ts +24 -0
  261. package/src/instance/internal-api/serialization/ClientReactiveSerializableValueNode.ts +28 -0
  262. package/src/instance/repeat/BaseRepeatRange.ts +21 -24
  263. package/src/instance/repeat/RepeatInstance.ts +27 -19
  264. package/src/instance/repeat/RepeatRangeControlled.ts +90 -17
  265. package/src/instance/repeat/RepeatRangeUncontrolled.ts +10 -9
  266. package/src/instance/resource.ts +18 -2
  267. package/src/instance/unsupported/UploadControl.ts +116 -5
  268. package/src/integration/xpath/EngineXPathEvaluator.ts +2 -2
  269. package/src/integration/xpath/adapter/kind.ts +1 -28
  270. package/src/integration/xpath/adapter/names.ts +66 -17
  271. package/src/integration/xpath/adapter/traversal.ts +12 -11
  272. package/src/integration/xpath/static-dom/StaticAttribute.ts +16 -7
  273. package/src/integration/xpath/static-dom/StaticDocument.ts +17 -18
  274. package/src/integration/xpath/static-dom/StaticElement.ts +211 -52
  275. package/src/integration/xpath/static-dom/StaticNode.ts +1 -1
  276. package/src/integration/xpath/static-dom/StaticParentNode.ts +22 -0
  277. package/src/integration/xpath/static-dom/staticNodeName.ts +20 -0
  278. package/src/lib/client-reactivity/instance-state/createNodeRangeInstanceState.ts +17 -0
  279. package/src/lib/client-reactivity/instance-state/createParentNodeInstanceState.ts +22 -0
  280. package/src/lib/client-reactivity/instance-state/createPrimaryInstanceState.ts +12 -0
  281. package/src/lib/client-reactivity/instance-state/createRootInstanceState.ts +19 -0
  282. package/src/lib/client-reactivity/instance-state/createTemplatedNodeInstanceState.ts +31 -0
  283. package/src/lib/client-reactivity/instance-state/createValueNodeInstanceState.ts +21 -0
  284. package/src/lib/client-reactivity/instance-state/prepareInstancePayload.ts +173 -0
  285. package/src/lib/codecs/Geopoint/Geopoint.ts +150 -0
  286. package/src/lib/codecs/Geopoint/GeopointValueCodec.ts +20 -0
  287. package/src/lib/codecs/NoteCodec.ts +32 -0
  288. package/src/lib/codecs/RangeCodec.ts +65 -0
  289. package/src/lib/codecs/TempUnsupportedControlCodec.ts +32 -0
  290. package/src/lib/codecs/TriggerCodec.ts +64 -0
  291. package/src/lib/codecs/ValueArrayCodec.ts +42 -0
  292. package/src/lib/codecs/ValueCodec.ts +2 -2
  293. package/src/lib/codecs/getNoteCodec.ts +27 -0
  294. package/src/lib/codecs/getSelectCodec.ts +27 -0
  295. package/src/lib/codecs/getSharedValueCodec.ts +5 -3
  296. package/src/lib/codecs/items/BaseItemCodec.ts +20 -0
  297. package/src/lib/codecs/items/MultipleValueItemCodec.ts +28 -0
  298. package/src/lib/codecs/items/SingleValueItemCodec.ts +67 -0
  299. package/src/lib/dom/query.ts +1 -2
  300. package/src/lib/names/NamespaceDeclaration.ts +106 -0
  301. package/src/lib/names/NamespaceDeclarationMap.ts +228 -0
  302. package/src/lib/names/NamespaceURL.ts +44 -0
  303. package/src/lib/names/QualifiedName.ts +170 -0
  304. package/src/lib/names/UnprefixedXFormsName.ts +12 -0
  305. package/src/lib/number-parsers.ts +25 -0
  306. package/src/lib/reactivity/createInstanceValueState.ts +69 -43
  307. package/src/lib/reactivity/{createSelectItems.ts → createItemCollection.ts} +41 -36
  308. package/src/lib/xml-serialization.ts +76 -9
  309. package/src/parse/XFormDOM.ts +141 -21
  310. package/src/parse/XFormDefinition.ts +1 -4
  311. package/src/parse/body/BodyDefinition.ts +4 -4
  312. package/src/parse/body/appearance/rangeAppearanceParser.ts +11 -0
  313. package/src/parse/body/control/InputControlDefinition.ts +9 -0
  314. package/src/parse/body/control/{select/ItemDefinition.ts → ItemDefinition.ts} +8 -6
  315. package/src/parse/body/control/{select/ItemsetDefinition.ts → ItemsetDefinition.ts} +11 -9
  316. package/src/parse/body/control/RangeControlDefinition.ts +91 -6
  317. package/src/parse/body/control/RankControlDefinition.ts +25 -7
  318. package/src/parse/body/control/{select/SelectDefinition.ts → SelectControlDefinition.ts} +9 -9
  319. package/src/parse/expression/ItemsetNodesetExpression.ts +1 -1
  320. package/src/parse/expression/ItemsetValueExpression.ts +1 -1
  321. package/src/parse/model/BindDefinition.ts +4 -0
  322. package/src/parse/model/BindPreloadDefinition.ts +100 -0
  323. package/src/parse/model/DescendentNodeDefinition.ts +7 -25
  324. package/src/parse/model/ItextTranslationsDefinition.ts +79 -0
  325. package/src/parse/model/LeafNodeDefinition.ts +13 -8
  326. package/src/parse/model/ModelDefinition.ts +36 -3
  327. package/src/parse/model/NodeDefinition.ts +38 -85
  328. package/src/parse/model/NoteNodeDefinition.ts +12 -10
  329. package/src/parse/model/RangeNodeDefinition.ts +119 -0
  330. package/src/parse/model/RepeatDefinition.ts +382 -0
  331. package/src/parse/model/RootAttributeDefinition.ts +44 -0
  332. package/src/parse/model/RootAttributeMap.ts +49 -0
  333. package/src/parse/model/RootDefinition.ts +42 -43
  334. package/src/parse/model/SecondaryInstance/SecondaryInstancesDefinition.ts +23 -2
  335. package/src/parse/model/SecondaryInstance/assertSecondaryInstanceDefinition.ts +14 -0
  336. package/src/parse/model/SecondaryInstance/defineSecondaryInstance.ts +32 -0
  337. package/src/parse/model/SecondaryInstance/sources/BlankSecondaryInstanceSource.ts +3 -24
  338. package/src/parse/model/SecondaryInstance/sources/CSVExternalSecondaryInstance.ts +33 -86
  339. package/src/parse/model/SecondaryInstance/sources/GeoJSONExternalSecondaryInstance.ts +64 -136
  340. package/src/parse/model/SecondaryInstance/sources/InternalSecondaryInstanceSource.ts +9 -7
  341. package/src/parse/model/SecondaryInstance/sources/SecondaryInstanceSource.ts +1 -1
  342. package/src/parse/model/SecondaryInstance/sources/XMLExternalSecondaryInstanceSource.ts +7 -7
  343. package/src/parse/model/{FormSubmissionDefinition.ts → SubmissionDefinition.ts} +2 -2
  344. package/src/parse/model/SubtreeDefinition.ts +15 -16
  345. package/src/parse/model/nodeDefinitionMap.ts +34 -0
  346. package/src/parse/shared/parseInstanceXML.ts +79 -0
  347. package/src/parse/shared/parseStaticDocumentFromDOMSubtree.ts +46 -131
  348. package/src/parse/text/ItemLabelDefinition.ts +1 -1
  349. package/src/parse/text/ItemsetLabelDefinition.ts +2 -2
  350. package/src/parse/text/abstract/TextElementDefinition.ts +1 -1
  351. package/src/parse/xpath/semantic-analysis.ts +4 -3
  352. package/dist/client/EngineConfig.d.ts +0 -79
  353. package/dist/client/submission/SubmissionData.d.ts +0 -7
  354. package/dist/client/submission/SubmissionInstanceFile.d.ts +0 -6
  355. package/dist/client/submission/SubmissionOptions.d.ts +0 -23
  356. package/dist/client/submission/SubmissionResult.d.ts +0 -91
  357. package/dist/client/submission/SubmissionState.d.ts +0 -12
  358. package/dist/client/unsupported/RangeNode.d.ts +0 -9
  359. package/dist/client/unsupported/RankNode.d.ts +0 -9
  360. package/dist/instance/SelectField.d.ts +0 -58
  361. package/dist/instance/abstract/UnsupportedControl.d.ts +0 -53
  362. package/dist/instance/index.d.ts +0 -8
  363. package/dist/instance/internal-api/ValueContext.d.ts +0 -23
  364. package/dist/instance/internal-api/submission/ClientReactiveSubmittableInstance.d.ts +0 -14
  365. package/dist/instance/internal-api/submission/ClientReactiveSubmittableLeafNode.d.ts +0 -31
  366. package/dist/instance/internal-api/submission/ClientReactiveSubmittableParentNode.d.ts +0 -18
  367. package/dist/instance/internal-api/submission/ClientReactiveSubmittableValueNode.d.ts +0 -17
  368. package/dist/instance/unsupported/RangeControl.d.ts +0 -6
  369. package/dist/instance/unsupported/RankControl.d.ts +0 -6
  370. package/dist/integration/xpath/static-dom/StaticNamedNode.d.ts +0 -17
  371. package/dist/lib/client-reactivity/submission/createInstanceSubmissionState.d.ts +0 -3
  372. package/dist/lib/client-reactivity/submission/createLeafNodeSubmissionState.d.ts +0 -3
  373. package/dist/lib/client-reactivity/submission/createNodeRangeSubmissionState.d.ts +0 -4
  374. package/dist/lib/client-reactivity/submission/createParentNodeSubmissionState.d.ts +0 -4
  375. package/dist/lib/client-reactivity/submission/createValueNodeSubmissionState.d.ts +0 -3
  376. package/dist/lib/client-reactivity/submission/prepareSubmission.d.ts +0 -8
  377. package/dist/lib/reactivity/createSelectItems.d.ts +0 -16
  378. package/dist/lib/reactivity/createValueState.d.ts +0 -40
  379. package/dist/parse/body/control/select/ItemDefinition.d.ts +0 -13
  380. package/dist/parse/body/control/select/ItemsetDefinition.d.ts +0 -17
  381. package/dist/parse/body/control/select/ItemsetNodesetContext.d.ts +0 -9
  382. package/dist/parse/model/ItextTranslation/ItextTranslationDefinition.d.ts +0 -4
  383. package/dist/parse/model/ItextTranslation/ItextTranslationRootDefinition.d.ts +0 -8
  384. package/dist/parse/model/ItextTranslation/ItextTranslationsDefinition.d.ts +0 -8
  385. package/dist/parse/model/RepeatInstanceDefinition.d.ts +0 -14
  386. package/dist/parse/model/RepeatRangeDefinition.d.ts +0 -29
  387. package/dist/parse/model/RepeatTemplateDefinition.d.ts +0 -28
  388. package/dist/parse/model/SecondaryInstance/SecondaryInstanceDefinition.d.ts +0 -4
  389. package/dist/parse/model/SecondaryInstance/SecondaryInstanceRootDefinition.d.ts +0 -7
  390. package/src/client/EngineConfig.ts +0 -84
  391. package/src/client/submission/SubmissionData.ts +0 -12
  392. package/src/client/submission/SubmissionInstanceFile.ts +0 -9
  393. package/src/client/submission/SubmissionOptions.ts +0 -28
  394. package/src/client/submission/SubmissionResult.ts +0 -124
  395. package/src/client/submission/SubmissionState.ts +0 -14
  396. package/src/client/unsupported/RangeNode.ts +0 -14
  397. package/src/client/unsupported/RankNode.ts +0 -14
  398. package/src/instance/SelectField.ts +0 -263
  399. package/src/instance/abstract/UnsupportedControl.ts +0 -174
  400. package/src/instance/children.ts +0 -158
  401. package/src/instance/index.ts +0 -55
  402. package/src/instance/internal-api/ValueContext.ts +0 -28
  403. package/src/instance/internal-api/submission/ClientReactiveSubmittableInstance.ts +0 -20
  404. package/src/instance/internal-api/submission/ClientReactiveSubmittableLeafNode.ts +0 -42
  405. package/src/instance/internal-api/submission/ClientReactiveSubmittableParentNode.ts +0 -25
  406. package/src/instance/internal-api/submission/ClientReactiveSubmittableValueNode.ts +0 -23
  407. package/src/instance/unsupported/RangeControl.ts +0 -9
  408. package/src/instance/unsupported/RankControl.ts +0 -9
  409. package/src/integration/xpath/static-dom/StaticNamedNode.ts +0 -45
  410. package/src/lib/client-reactivity/submission/createInstanceSubmissionState.ts +0 -12
  411. package/src/lib/client-reactivity/submission/createLeafNodeSubmissionState.ts +0 -20
  412. package/src/lib/client-reactivity/submission/createNodeRangeSubmissionState.ts +0 -17
  413. package/src/lib/client-reactivity/submission/createParentNodeSubmissionState.ts +0 -22
  414. package/src/lib/client-reactivity/submission/createValueNodeSubmissionState.ts +0 -21
  415. package/src/lib/client-reactivity/submission/prepareSubmission.ts +0 -172
  416. package/src/lib/reactivity/createValueState.ts +0 -200
  417. package/src/parse/body/control/select/ItemsetNodesetContext.ts +0 -21
  418. package/src/parse/model/ItextTranslation/ItextTranslationDefinition.ts +0 -4
  419. package/src/parse/model/ItextTranslation/ItextTranslationRootDefinition.ts +0 -41
  420. package/src/parse/model/ItextTranslation/ItextTranslationsDefinition.ts +0 -31
  421. package/src/parse/model/RepeatInstanceDefinition.ts +0 -34
  422. package/src/parse/model/RepeatRangeDefinition.ts +0 -94
  423. package/src/parse/model/RepeatTemplateDefinition.ts +0 -145
  424. package/src/parse/model/SecondaryInstance/SecondaryInstanceDefinition.ts +0 -4
  425. package/src/parse/model/SecondaryInstance/SecondaryInstanceRootDefinition.ts +0 -12
@@ -0,0 +1,119 @@
1
+ import type { ValueType } from '../../client/ValueType.ts';
2
+ import { ErrorProductionDesignPendingError } from '../../error/ErrorProductionDesignPendingError.ts';
3
+ import type { StaticLeafElement } from '../../integration/xpath/static-dom/StaticElement.ts';
4
+ import type { RuntimeValue, SharedValueCodec } from '../../lib/codecs/getSharedValueCodec.ts';
5
+ import { getSharedValueCodec } from '../../lib/codecs/getSharedValueCodec.ts';
6
+ import type {
7
+ RangeControlBoundsDefinition,
8
+ RangeControlDefinition,
9
+ } from '../body/control/RangeControlDefinition.ts';
10
+ import type { BindDefinition } from './BindDefinition.ts';
11
+ import { LeafNodeDefinition } from './LeafNodeDefinition.ts';
12
+ import type { ParentNodeDefinition } from './NodeDefinition.ts';
13
+
14
+ const RANGE_VALUE_TYPES = ['decimal', 'int'] as const;
15
+
16
+ export type RangeValueType = (typeof RANGE_VALUE_TYPES)[number];
17
+
18
+ type AssertedRangeValueType<V extends ValueType> = Extract<V, RangeValueType>;
19
+
20
+ type AssertRangeBindDefinition = <V extends ValueType>(
21
+ bind: BindDefinition<V>
22
+ ) => asserts bind is BindDefinition<AssertedRangeValueType<V>>;
23
+
24
+ const assertRangeBindDefinition: AssertRangeBindDefinition = (bind) => {
25
+ if (!RANGE_VALUE_TYPES.includes(bind.type.resolved as RangeValueType)) {
26
+ throw new ErrorProductionDesignPendingError(
27
+ `Expected range to have bind type "decimal" or "int", got: ${bind.type.resolved}`
28
+ );
29
+ }
30
+ };
31
+
32
+ export interface RangeLeafNodeDefinition<V extends ValueType = ValueType>
33
+ extends LeafNodeDefinition<V> {
34
+ readonly bodyElement: RangeControlDefinition;
35
+ }
36
+
37
+ const decodeBoundsValue = <V extends ValueType>(
38
+ codec: SharedValueCodec<V>,
39
+ value: string
40
+ ): NonNullable<RuntimeValue<V>> => {
41
+ const decoded = codec.decodeValue(value);
42
+
43
+ if (decoded == null) {
44
+ throw new ErrorProductionDesignPendingError(
45
+ `Failed to decode bounds value (encoded as ${JSON.stringify(value)})`
46
+ );
47
+ }
48
+
49
+ return decoded;
50
+ };
51
+
52
+ class RangeNodeBoundsDefinition<V extends RangeValueType = RangeValueType> {
53
+ static from<V extends RangeValueType>(
54
+ bounds: RangeControlBoundsDefinition,
55
+ bind: BindDefinition<V>
56
+ ): RangeNodeBoundsDefinition<V> {
57
+ const type = bind.type.resolved;
58
+ const codec = getSharedValueCodec(type);
59
+ const min = decodeBoundsValue(codec, bounds.start);
60
+ const max = decodeBoundsValue(codec, bounds.end);
61
+ const step = decodeBoundsValue(codec, bounds.step);
62
+
63
+ return new this(min, max, step);
64
+ }
65
+
66
+ constructor(
67
+ readonly min: NonNullable<RuntimeValue<V>>,
68
+ readonly max: NonNullable<RuntimeValue<V>>,
69
+ readonly step: NonNullable<RuntimeValue<V>>
70
+ ) {}
71
+ }
72
+
73
+ /**
74
+ * @todo We should really consider making `LeafNodeDefinition` an abstract base
75
+ * class, and each node's definition an explicit concrete subclass of that. It
76
+ * would simplify a lot of things, reduce redundancy (and drift!) between
77
+ * various like `*Definition` types, and allow us to reason more clearly about
78
+ * what parse-product-input is used to construct each primary instance node.
79
+ * Furthermore, it would give us a great deal more flexibility to revisit some
80
+ * of the weaker parts of our current data model (e.g. splitting up selects).
81
+ *
82
+ * I explored this refactor as part of the prerequisite work to support range
83
+ * controls. I eventually backed out because it involved more churn than I felt
84
+ * comfortable with, but I do think we should keep an eye out for other
85
+ * opportunities to take on the churn.
86
+ */
87
+ export class RangeNodeDefinition<V extends RangeValueType = RangeValueType>
88
+ extends LeafNodeDefinition<V>
89
+ implements RangeLeafNodeDefinition<V>
90
+ {
91
+ static from<V extends ValueType>(
92
+ parent: ParentNodeDefinition,
93
+ bind: BindDefinition<V>,
94
+ bodyElement: RangeControlDefinition,
95
+ node: StaticLeafElement
96
+ ): RangeNodeDefinition<Extract<V, RangeValueType>> {
97
+ assertRangeBindDefinition(bind);
98
+
99
+ return new this(parent, bind, bodyElement, node);
100
+ }
101
+
102
+ readonly bounds: RangeNodeBoundsDefinition<V>;
103
+
104
+ private constructor(
105
+ parent: ParentNodeDefinition,
106
+ override readonly bind: BindDefinition<V>,
107
+ override readonly bodyElement: RangeControlDefinition,
108
+ node: StaticLeafElement
109
+ ) {
110
+ super(parent, bind, bodyElement, node);
111
+
112
+ this.bounds = RangeNodeBoundsDefinition.from(bodyElement.bounds, bind);
113
+ }
114
+ }
115
+
116
+ // prettier-ignore
117
+ export type AnyRangeNodeDefinition =
118
+ | RangeNodeDefinition<'decimal'>
119
+ | RangeNodeDefinition<'int'>;
@@ -0,0 +1,382 @@
1
+ import { JAVAROSA_NAMESPACE_URI } from '@getodk/common/constants/xmlns.ts';
2
+ import type { XFORMS_KNOWN_ATTRIBUTE } from '@getodk/xpath';
3
+ import type { RepeatRange } from '../../instance/hierarchy.ts';
4
+ import type { PrimaryInstance } from '../../instance/PrimaryInstance.ts';
5
+ import type { RepeatInstance } from '../../instance/repeat/RepeatInstance.ts';
6
+ import type {
7
+ StaticAttribute,
8
+ StaticAttributeOptions,
9
+ } from '../../integration/xpath/static-dom/StaticAttribute.ts';
10
+ import { StaticDocument } from '../../integration/xpath/static-dom/StaticDocument.ts';
11
+ import type {
12
+ StaticElement,
13
+ StaticElementOptions,
14
+ } from '../../integration/xpath/static-dom/StaticElement.ts';
15
+ import type { StaticNode } from '../../integration/xpath/static-dom/StaticNode.ts';
16
+ import type { StaticText } from '../../integration/xpath/static-dom/StaticText.ts';
17
+ import { NamespaceDeclarationMap } from '../../lib/names/NamespaceDeclarationMap.ts';
18
+ import type { NamespaceURL } from '../../lib/names/NamespaceURL.ts';
19
+ import type { QualifiedName, QualifiedNameSource } from '../../lib/names/QualifiedName.ts';
20
+ import type { RepeatElementDefinition } from '../body/RepeatElementDefinition.ts';
21
+ import { RepeatCountControlExpression } from '../expression/RepeatCountControlExpression.ts';
22
+ import type { BindDefinition } from './BindDefinition.ts';
23
+ import { DescendentNodeDefinition } from './DescendentNodeDefinition.ts';
24
+ import type { ChildNodeDefinition, ParentNodeDefinition } from './NodeDefinition.ts';
25
+ import type { RootDefinition } from './RootDefinition.ts';
26
+ import type { SubtreeDefinition } from './SubtreeDefinition.ts';
27
+
28
+ interface JavaRosaNamespaceURI extends NamespaceURL {
29
+ readonly href: JAVAROSA_NAMESPACE_URI;
30
+ }
31
+
32
+ interface JRTemplateAttributeName extends QualifiedName {
33
+ readonly namespaceURI: JavaRosaNamespaceURI;
34
+ readonly localName: 'template';
35
+ }
36
+
37
+ const isJRTemplateAttributeName = (name: QualifiedNameSource) => {
38
+ if (name.localName !== 'template') {
39
+ return false;
40
+ }
41
+
42
+ const namespaceURI = (name.namespaceURI as NamespaceURL)?.href ?? name.namespaceURI;
43
+
44
+ return namespaceURI === JAVAROSA_NAMESPACE_URI;
45
+ };
46
+
47
+ interface JRTemplateAttribute extends StaticAttribute {
48
+ readonly qualifiedName: JRTemplateAttributeName;
49
+ }
50
+
51
+ const isJRTemplateAttribute = (attribute: StaticAttribute): attribute is JRTemplateAttribute => {
52
+ return isJRTemplateAttributeName(attribute.qualifiedName);
53
+ };
54
+
55
+ interface ExplicitRepeatTemplateElement extends StaticElement {
56
+ readonly [XFORMS_KNOWN_ATTRIBUTE]: 'template';
57
+
58
+ getAttributeValue(localName: 'template'): string;
59
+ getAttributeValue(localName: string): string | null;
60
+ }
61
+
62
+ /**
63
+ * Determines whether a model instance node is an **explicit** repeat template,
64
+ * as defined by the presence of a `jr:template` attribute on that node.
65
+ *
66
+ * @see {@link https://getodk.github.io/xforms-spec/#default-values-in-repeats}
67
+ */
68
+ const isExplicitRepeatTemplateElement = (
69
+ sourceElement: StaticElement
70
+ ): sourceElement is ExplicitRepeatTemplateElement => {
71
+ return sourceElement.attributes.some(isJRTemplateAttribute);
72
+ };
73
+
74
+ const cloneStaticAttributeOptions = (attribute: StaticAttribute): StaticAttributeOptions => {
75
+ return {
76
+ name: attribute.qualifiedName,
77
+ value: attribute.value,
78
+ };
79
+ };
80
+
81
+ interface ClonedSubtreeStructure extends StaticElementOptions {
82
+ readonly attributes: readonly StaticAttributeOptions[];
83
+ readonly children: readonly StaticElementOptions[];
84
+ }
85
+
86
+ const cloneStaticSubtreeStructure = (sourceElement: StaticElement): ClonedSubtreeStructure => {
87
+ const name = sourceElement.qualifiedName;
88
+ const attributes = sourceElement.attributes.map(cloneStaticAttributeOptions);
89
+ const children = sourceElement.childElements.map(cloneStaticSubtreeStructure);
90
+
91
+ return {
92
+ name,
93
+ attributes,
94
+ children,
95
+ };
96
+ };
97
+
98
+ /**
99
+ * Clones the **structure** of a {@link StaticElement}, omitting
100
+ * {@link StaticText | text values} of the element itself, and any of its
101
+ * descendants.
102
+ *
103
+ * @todo This function's behavior is **plausibly** general purpose. The function
104
+ * itself, its argument, its local bindings are all named to reflect that fact.
105
+ *
106
+ * However, the **use case** for the function is quite specific: when a form
107
+ * defines a `<repeat>` that isn't associated with an explicit `jr:template`, we
108
+ * fabricate a template by cloning its structure with all text values removed
109
+ * (described in more detail for {@link parseRepeatTemplateElement}).
110
+ *
111
+ * As generalized as this the function is, it's not at all clear how or why we'd
112
+ * use it for other purposes. Even the top-of-mind (at time of writing) use case
113
+ * which might semantically line up with it (i.e. potentially as a basis to
114
+ * reconcile edit instance state into a form definition, as sort of a three-way
115
+ * merge) would effectively be pure overhead. For now, we have something
116
+ * library-ish living here private in this module unless/until we find another
117
+ * good reason to use it elsewhere!
118
+ *
119
+ * If we do find another plausible use case for this behavior, it's pretty
120
+ * likely we'd want to implement it as a part of the {@link StaticElement} (or
121
+ * somewhere else up the class hierarchy to {@link StaticNode}), to encapsulate
122
+ * as much as possible about how it's done. We've been pretty aggressive about
123
+ * changing the internals and signatures of {@link StaticNode}s and the
124
+ * static-dom abstraction. It'd be nice if ongoing changes were a lot more
125
+ * isolated, with far less impact on the growing set of use cases actually
126
+ * consuming the abstraction.
127
+ */
128
+ const cloneStaticElementStructure = (sourceElement: StaticElement): StaticElement => {
129
+ const { root: clone } = new StaticDocument({
130
+ documentRoot: cloneStaticSubtreeStructure(sourceElement),
131
+ nodesetPrefix: sourceElement.parent.nodeset,
132
+ });
133
+
134
+ return clone;
135
+ };
136
+
137
+ export type RepeatInstanceNodes = readonly [StaticElement, ...StaticElement[]];
138
+
139
+ /**
140
+ * Produces a consistent "repeat template" interface for each
141
+ * {@link RepeatDefinition}, which is used to produce new repeat instances in
142
+ * {@link PrimaryInstance | runtime form instance state}. How a "repeat
143
+ * template" is parsed is as follows:
144
+ *
145
+ * - If the form definition includes an **explicit template** (as described by
146
+ * {@link isExplicitRepeatTemplateElement}) as the
147
+ * {@link firstRepeatInstanceNode | first} node referenced by a `<repeat
148
+ * nodeset>`, that node is returned as it was already parsed.
149
+ *
150
+ * - If the {@link firstRepeatInstanceNode | first} repeat instance node is
151
+ * **NOT** an explicit template, a template is **implicitly created** from its
152
+ * blank structure, as a
153
+ * {@link cloneStaticElementStructure | clone of its structure}.
154
+ *
155
+ * The latter behavior may sound surprising if unfamiliar, but it is well
156
+ * understood. It is also known to be consistent with Collect (JavaRosa), as
157
+ * demonstrated by affected tests in `@getodk/scenario` which fail when this
158
+ * behavior is changed.
159
+ *
160
+ * - - -
161
+ *
162
+ * Note: this is a vastly simplified evolution of what was previously
163
+ * implemented in
164
+ * {@link https://github.com/getodk/web-forms/blob/99295eb1d6ec78cd6a758385793e97859b6a74cc/packages/xforms-engine/src/parse/model/RepeatTemplateDefinition.ts#L81 | `RepeatTemplateDefinition.parseModelNodes`}
165
+ * (permalink to implementation at time of writing/refactor).
166
+ *
167
+ * That previous implementation was based on a flawed mental model of how a
168
+ * parsed form model relates to the form's instance structure. The following
169
+ * describes the previous flawed mental model, and the reasoning behind revising
170
+ * the mental model established here.
171
+ *
172
+ * - - -
173
+ *
174
+ * **Flawed mental model**
175
+ *
176
+ * Repeat model definitions were composed of a combination of:
177
+ *
178
+ * 1. `RepeatRangeDefinition`: this effectively had a 1:1 correspondence to the
179
+ * `<repeat>` _body element_ referencing the `nodeset` of 1+ instance nodes
180
+ * (as defined in the form's model).
181
+ *
182
+ * 2. `RepeatTemplateDefinition`: this had a 0-1:1 correspondence between an
183
+ * instance node (as defined in the form's model) defining a `jr:template`
184
+ * attribute, if one exists; if none exists, one was synthesized at parse
185
+ * time.
186
+ *
187
+ * 3. `RepeatInstanceDefinition`: these had an N:N correspondence to _every
188
+ * non-template instance node_ (as defined in the form's model).
189
+ *
190
+ * For each instance of a form:
191
+ *
192
+ * - `RepeatRangeControlled` or `RepeatRangeUncontrolled` (engine-internal
193
+ * implementation of the `RepeatRangeControlledNode` and
194
+ * `RepeatRangeUncontrolledNode` client interfaces, respectively) also
195
+ * corresponded 1:1 with a `RepeatRangeDefinition`.
196
+ *
197
+ * - `RepeatInstance` (engine-internal implementation of the
198
+ * `RepeatInstanceNode`) had an N:N relationship with _either_:
199
+ * - `RepeatInstanceDefinition`, if one was defined for that repeat instance's
200
+ * the positional index
201
+ * - `RepeatTemplateDefinition`, otherwise
202
+ *
203
+ * **Revised mental model**
204
+ *
205
+ * 1. `RepeatDefinition`: merges the responsibilities of the former
206
+ * `RepeatRangeDefinition` and `RepeatTemplateDefinition`.
207
+ *
208
+ * 2. Repeat instance nodes (as defined in the form's model) are refereced
209
+ * _during the construction of instance state_ (`PrimaryInstance`):
210
+ *
211
+ * - if an instance node exists at the positional index of the
212
+ * `RepeatInstance` to be created, that node is used to populate the
213
+ * `RepeatInstance`'s initial state
214
+ *
215
+ * - if no instance node exists at that positional index, the template
216
+ * returned by {@link RepeatTemplateDefinition.parseRepeatTemplateElement}
217
+ * is referenced for the `RepeatInstance`'s initial state instead
218
+ *
219
+ * Aside from simplifying the parsing responsibilities associated with repeats,
220
+ * this also creates a roughly 1:1 relationship between the different
221
+ * representations of what we call an "instance node".
222
+ *
223
+ * @todo The above "revised mental model" for repeat definitions pretty much
224
+ * reflects the same principles which will be applied for non-form instance
225
+ * state, i.e. for (a) restoring previously serialized instance state and/or (b)
226
+ * editing previously submitted instance state. It will make sense to reflect
227
+ * that once that aspect of implementation is complete!
228
+ *
229
+ * - - -
230
+ *
231
+ * At time of writing, I believe that detailing the differences between these
232
+ * mental models will provide useful context, in the long term, for reasoning
233
+ * about the relationship between "node definition" and "instance node" (as
234
+ * defined in a form or a serialized and/or submitted instance; also the
235
+ * engine's active, stateful representations of those same nodes).
236
+ *
237
+ * Namely, the revised relationship is _1 (node definition) : N (instance
238
+ * node)_, associated by each instance node's nodeset.
239
+ */
240
+ const parseRepeatTemplateElement = (firstRepeatInstanceNode: StaticElement) => {
241
+ if (isExplicitRepeatTemplateElement(firstRepeatInstanceNode)) {
242
+ return firstRepeatInstanceNode;
243
+ }
244
+
245
+ return cloneStaticElementStructure(firstRepeatInstanceNode);
246
+
247
+ // TODO: We previously **intended** to check for duplicate explicit repeat
248
+ // templates (i.e. defined with a `jr:template` attribute). This was
249
+ // **partially** handled by defining a (temporary/local) mapping from the
250
+ // repeat's `BindDefinition` to an already-parsed explicit template element
251
+ // (if any). Identifying duplicates **should** have been handled by
252
+ // determining that an entry for the same binding already existed. **BUT NO
253
+ // ENTRY WAS NEVER WRITTEN!** This comment is now intended to recognize:
254
+ //
255
+ // 1. ... that the intended behavior was never implemented correctly in the
256
+ // first place, and we are not making any changes to that intended aspect
257
+ // of engine behavior/semantics by eliminating the flawed implementation
258
+ // now.
259
+ //
260
+ // 2. ... that whether this behavior should have even been implemented was
261
+ // also an open question! The previous text of this
262
+ // comment's conceptual successor is preserved below, either for clarity in review or for logner-term posterity.
263
+ //
264
+ // - - -
265
+ //
266
+ // Previous text of this comment:
267
+ //
268
+ // > TODO: this is under the assumption that for any depth > 1, if a
269
+ // > template has already been defined for the given form definition, any
270
+ // > subsequent nodes matching the repeat's nodeset are implicitly default
271
+ // > instances. Is this right?
272
+ };
273
+
274
+ export interface ControlledRepeatDefinition extends RepeatDefinition {
275
+ readonly count: RepeatCountControlExpression;
276
+ }
277
+
278
+ export interface UncontrolledRepeatDefinition extends RepeatDefinition {
279
+ readonly count: null;
280
+ }
281
+
282
+ /**
283
+ * Represents a definition of the combined concepts colloquially called a
284
+ * "repeat", as defined by a form, where those concepts include:
285
+ *
286
+ * - A {@link RepeatElementDefinition}—corresponding to a `<repeat>` {@link https://getodk.github.io/xforms-spec/#body-elements | body element}—which is associated with the nodeset referencing the "repeat template" and
287
+ * all "repeat instances" (see below points describing both concepts in more detail). The presence of such a body element determines whether to produce a repeat definition (rather than e.g. a {@link SubtreeDefinition}).
288
+ *
289
+ * - A "repeat template", defined by a form either
290
+ * explicitly,
291
+ * or derived from the structure of the first form-defined "repeat instance"
292
+ * (as described in the next point).
293
+ *
294
+ * - A sequence of one or more model instance nodes, each representing a "repeat instance"
295
+ * defined by the form. These nodes contribute to the definition in the following ways:
296
+ *
297
+ * - If an explicit "repeat template" is not defined for
298
+ * the "repeat", one is derived from the **structure** (but not the values!)
299
+ * of the first such model instance node.
300
+ *
301
+ * - If the "repeat" is {@link ControlledRepeatDefinition | controlled} (i.e. by either a `jr:count` or `jr:noAddRemove` {@link https://getodk.github.io/xforms-spec/#body-attributes | attribute} on the associated {@link RepeatElementDefinition}
302
+ *
303
+ * (For construction of this
304
+ * definition, all other referenced instance nodes are **consumed** in the
305
+ * process of building the repeat definition's subtree of a
306
+ * {@link RootDefinition}, ensuring that one repeat definition is produced for
307
+ * all applicable nodes; they are later referenced for construction of a
308
+ * form's {@link PrimaryInstance | instance state}.)
309
+ *
310
+ * Combined, these concepts produce the details required to instantiate the
311
+ * {@link RepeatRange} and {@link RepeatInstance} instance state nodes
312
+ * associated with a defined repeat.
313
+ */
314
+ export class RepeatDefinition extends DescendentNodeDefinition<'repeat', RepeatElementDefinition> {
315
+ static from(
316
+ parent: ParentNodeDefinition,
317
+ bind: BindDefinition,
318
+ bodyElement: RepeatElementDefinition,
319
+ instanceNodes: RepeatInstanceNodes
320
+ ): AnyRepeatDefinition;
321
+ static from(
322
+ parent: ParentNodeDefinition,
323
+ bind: BindDefinition,
324
+ bodyElement: RepeatElementDefinition,
325
+ instanceNodes: RepeatInstanceNodes
326
+ ): RepeatDefinition {
327
+ return new this(parent, bind, bodyElement, instanceNodes);
328
+ }
329
+
330
+ readonly type = 'repeat';
331
+ readonly children: readonly ChildNodeDefinition[];
332
+ readonly count: RepeatCountControlExpression | null;
333
+ readonly template: StaticElement;
334
+ readonly namespaceDeclarations: NamespaceDeclarationMap;
335
+ readonly qualifiedName: QualifiedName;
336
+
337
+ private constructor(
338
+ parent: ParentNodeDefinition,
339
+ bind: BindDefinition,
340
+ bodyElement: RepeatElementDefinition,
341
+ instanceNodes: RepeatInstanceNodes
342
+ ) {
343
+ super(parent, bind, bodyElement);
344
+
345
+ const { root } = parent;
346
+ const [instanceNode] = instanceNodes;
347
+ const template = parseRepeatTemplateElement(instanceNode);
348
+ const self = this as AnyRepeatDefinition;
349
+
350
+ this.template = template;
351
+ this.qualifiedName = template.qualifiedName;
352
+ this.namespaceDeclarations = new NamespaceDeclarationMap(this);
353
+ this.children = root.buildSubtree(self, template);
354
+
355
+ const initialCount = this.omitTemplate(instanceNodes).length;
356
+
357
+ this.count = RepeatCountControlExpression.from(bodyElement, initialCount);
358
+ }
359
+
360
+ isControlled(): this is ControlledRepeatDefinition {
361
+ return this.count != null;
362
+ }
363
+
364
+ isUncontrolled(): this is UncontrolledRepeatDefinition {
365
+ return this.count == null;
366
+ }
367
+
368
+ omitTemplate(instanceNodes: readonly StaticElement[]): readonly StaticElement[] {
369
+ return instanceNodes.filter((instanceNode) => {
370
+ return instanceNode !== this.template;
371
+ });
372
+ }
373
+
374
+ toJSON(): object {
375
+ return {};
376
+ }
377
+ }
378
+
379
+ // prettier-ignore
380
+ export type AnyRepeatDefinition =
381
+ | ControlledRepeatDefinition
382
+ | UncontrolledRepeatDefinition;
@@ -0,0 +1,44 @@
1
+ import { XMLNS_NAMESPACE_URI } from '@getodk/common/constants/xmlns.ts';
2
+ import type { NamedNodeDefinition } from '../../lib/names/NamespaceDeclarationMap.ts';
3
+ import { QualifiedName } from '../../lib/names/QualifiedName.ts';
4
+ import { escapeXMLText } from '../../lib/xml-serialization.ts';
5
+ import type { RootDefinition } from './RootDefinition.ts';
6
+
7
+ interface RootAttributeSource {
8
+ readonly qualifiedName: QualifiedName;
9
+ readonly value: string;
10
+ }
11
+
12
+ /**
13
+ * @todo This class is named and typed to emphasize its intentionally narrow
14
+ * usage and purpose. It **intentionally** avoids addressing the much broader
15
+ * set of concerns around modeling attributes in primary instance/submissions.
16
+ */
17
+ export class RootAttributeDefinition implements NamedNodeDefinition {
18
+ private readonly serializedXML: string;
19
+
20
+ readonly parent: RootDefinition;
21
+ readonly qualifiedName: QualifiedName;
22
+ readonly value: string;
23
+
24
+ constructor(root: RootDefinition, source: RootAttributeSource) {
25
+ const { qualifiedName, value } = source;
26
+
27
+ this.parent = root;
28
+ this.qualifiedName = qualifiedName;
29
+ this.value = value;
30
+
31
+ // We serialize namespace declarations separately
32
+ if (qualifiedName.namespaceURI?.href === XMLNS_NAMESPACE_URI) {
33
+ this.serializedXML = '';
34
+ } else {
35
+ const nodeName = qualifiedName.getPrefixedName();
36
+
37
+ this.serializedXML = ` ${nodeName}="${escapeXMLText(value, true)}"`;
38
+ }
39
+ }
40
+
41
+ serializeAttributeXML(): string {
42
+ return this.serializedXML;
43
+ }
44
+ }
@@ -0,0 +1,49 @@
1
+ import { XMLNS_NAMESPACE_URI } from '@getodk/common/constants/xmlns.ts';
2
+ import type { StaticAttribute } from '../../integration/xpath/static-dom/StaticAttribute.ts';
3
+ import type { StaticElement } from '../../integration/xpath/static-dom/StaticElement.ts';
4
+ import type { QualifiedName } from '../../lib/names/QualifiedName.ts';
5
+ import { RootAttributeDefinition } from './RootAttributeDefinition.ts';
6
+ import type { RootDefinition } from './RootDefinition.ts';
7
+
8
+ /**
9
+ * @todo We should probably just distinguish these as separate `StaticNode`
10
+ * subclasses, probably as separate collections on `StaticElement`!
11
+ */
12
+ const isNonNamespaceAttribute = (attribute: StaticAttribute) => {
13
+ return attribute.qualifiedName.namespaceURI?.href !== XMLNS_NAMESPACE_URI;
14
+ };
15
+
16
+ /**
17
+ * @todo This can be trivially expanded to a narrowly general case when we
18
+ * prioritize work to
19
+ * {@link https://github.com/getodk/web-forms/issues/285 | support attributes}
20
+ * (as modeled form nodes on par with elements). It's been deferred here to
21
+ * avoid expanding scope of an already fairly large yak shave.
22
+ *
23
+ * @todo There's a **much more expansive** general case just waiting for a good
24
+ * opportuntity to prioritize it. E.g. a `NamedNodeMap<T>`, where T is any
25
+ * generalized concept of a named node. This expansive generalization would have
26
+ * a ton of value in a variety of known performance optimization
27
+ * targets/solutions (i.e. optimizing the most redundant, suboptimal, frequently
28
+ * performed aspects of any typical XPath expression in a typical XForm).
29
+ *
30
+ * @see {@link QualifiedName} for more detail.
31
+ */
32
+ export class RootAttributeMap extends Map<QualifiedName, RootAttributeDefinition> {
33
+ static from(root: RootDefinition, instanceNode: StaticElement) {
34
+ const nonNamespaceAttributes = instanceNode.attributes.filter(isNonNamespaceAttribute);
35
+ const definitions = nonNamespaceAttributes.map((attribute) => {
36
+ return new RootAttributeDefinition(root, attribute);
37
+ });
38
+
39
+ return new this(definitions);
40
+ }
41
+
42
+ private constructor(definitions: readonly RootAttributeDefinition[]) {
43
+ super(
44
+ definitions.map((attribute) => {
45
+ return [attribute.qualifiedName, attribute];
46
+ })
47
+ );
48
+ }
49
+ }