@getodk/xforms-engine 0.4.0 → 0.6.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 (392) hide show
  1. package/README.md +1 -1
  2. package/dist/client/BaseNode.d.ts +18 -3
  3. package/dist/client/BaseValueNode.d.ts +32 -0
  4. package/dist/client/EngineConfig.d.ts +49 -48
  5. package/dist/client/GroupNode.d.ts +1 -0
  6. package/dist/client/InputNode.d.ts +82 -0
  7. package/dist/client/ModelValueNode.d.ts +13 -7
  8. package/dist/client/NoteNode.d.ts +26 -9
  9. package/dist/client/RangeNode.d.ts +36 -0
  10. package/dist/client/RankNode.d.ts +46 -0
  11. package/dist/client/RootNode.d.ts +37 -7
  12. package/dist/client/SelectNode.d.ts +47 -25
  13. package/dist/client/SubtreeNode.d.ts +1 -0
  14. package/dist/client/TriggerNode.d.ts +10 -6
  15. package/dist/client/ValueType.d.ts +3 -0
  16. package/dist/client/constants.d.ts +50 -0
  17. package/dist/client/hierarchy.d.ts +8 -8
  18. package/dist/client/identity.d.ts +14 -0
  19. package/dist/client/node-types.d.ts +3 -2
  20. package/dist/client/resources.d.ts +93 -0
  21. package/dist/client/submission/SubmissionData.d.ts +7 -0
  22. package/dist/client/submission/SubmissionDefinition.d.ts +14 -0
  23. package/dist/client/submission/SubmissionInstanceFile.d.ts +6 -0
  24. package/dist/client/submission/SubmissionOptions.d.ts +23 -0
  25. package/dist/client/submission/SubmissionResult.d.ts +91 -0
  26. package/dist/client/submission/SubmissionState.d.ts +12 -0
  27. package/dist/client/unsupported/UnsupportedControlNode.d.ts +1 -3
  28. package/dist/client/validation.d.ts +2 -2
  29. package/dist/error/ErrorProductionDesignPendingError.d.ts +7 -0
  30. package/dist/error/RankMissingValueError.d.ts +3 -0
  31. package/dist/error/RankValueTypeError.d.ts +6 -0
  32. package/dist/error/SelectValueTypeError.d.ts +15 -0
  33. package/dist/error/ValueTypeInvariantError.d.ts +17 -0
  34. package/dist/error/XFormsSpecViolationError.d.ts +2 -0
  35. package/dist/error/XPathFunctionalityError.d.ts +14 -0
  36. package/dist/error/XPathFunctionalityNotSupportedError.d.ts +7 -0
  37. package/dist/error/XPathFunctionalityPendingError.d.ts +7 -0
  38. package/dist/index.d.ts +12 -4
  39. package/dist/index.js +17864 -14655
  40. package/dist/index.js.map +1 -1
  41. package/dist/instance/Group.d.ts +10 -4
  42. package/dist/instance/InputControl.d.ts +38 -0
  43. package/dist/instance/ModelValue.d.ts +17 -25
  44. package/dist/instance/Note.d.ts +16 -21
  45. package/dist/instance/PrimaryInstance.d.ts +85 -0
  46. package/dist/instance/RangeControl.d.ts +34 -0
  47. package/dist/instance/RankControl.d.ts +40 -0
  48. package/dist/instance/Root.d.ts +30 -25
  49. package/dist/instance/SelectControl.d.ts +66 -0
  50. package/dist/instance/Subtree.d.ts +11 -5
  51. package/dist/instance/TriggerControl.d.ts +13 -19
  52. package/dist/instance/abstract/DescendantNode.d.ts +32 -25
  53. package/dist/instance/abstract/InstanceNode.d.ts +52 -30
  54. package/dist/instance/abstract/UnsupportedControl.d.ts +11 -3
  55. package/dist/instance/abstract/ValueNode.d.ts +47 -0
  56. package/dist/instance/hierarchy.d.ts +13 -12
  57. package/dist/instance/identity.d.ts +2 -7
  58. package/dist/instance/internal-api/EvaluationContext.d.ts +53 -12
  59. package/dist/instance/internal-api/InstanceConfig.d.ts +8 -2
  60. package/dist/instance/internal-api/InstanceValueContext.d.ts +22 -0
  61. package/dist/instance/internal-api/PrimaryInstanceDocument.d.ts +36 -0
  62. package/dist/instance/internal-api/TranslationContext.d.ts +3 -2
  63. package/dist/instance/internal-api/ValidationContext.d.ts +3 -4
  64. package/dist/instance/internal-api/ValueContext.d.ts +2 -1
  65. package/dist/instance/internal-api/submission/ClientReactiveSubmittableInstance.d.ts +14 -0
  66. package/dist/instance/internal-api/submission/ClientReactiveSubmittableLeafNode.d.ts +32 -0
  67. package/dist/instance/internal-api/submission/ClientReactiveSubmittableParentNode.d.ts +19 -0
  68. package/dist/instance/internal-api/submission/ClientReactiveSubmittableValueNode.d.ts +18 -0
  69. package/dist/instance/repeat/BaseRepeatRange.d.ts +40 -83
  70. package/dist/instance/repeat/RepeatInstance.d.ts +12 -29
  71. package/dist/instance/repeat/RepeatRangeControlled.d.ts +2 -2
  72. package/dist/instance/repeat/RepeatRangeUncontrolled.d.ts +2 -2
  73. package/dist/instance/resource.d.ts +1 -1
  74. package/dist/instance/text/TextRange.d.ts +1 -1
  75. package/dist/instance/unsupported/UploadControl.d.ts +3 -1
  76. package/dist/integration/xpath/EngineXPathEvaluator.d.ts +14 -0
  77. package/dist/integration/xpath/adapter/XFormsXPathNode.d.ts +71 -0
  78. package/dist/integration/xpath/adapter/engineDOMAdapter.d.ts +5 -0
  79. package/dist/integration/xpath/adapter/kind.d.ts +32 -0
  80. package/dist/integration/xpath/adapter/names.d.ts +6 -0
  81. package/dist/integration/xpath/adapter/traversal.d.ts +26 -0
  82. package/dist/integration/xpath/adapter/values.d.ts +2 -0
  83. package/dist/integration/xpath/static-dom/StaticAttribute.d.ts +26 -0
  84. package/dist/integration/xpath/static-dom/StaticDocument.d.ts +15 -0
  85. package/dist/integration/xpath/static-dom/StaticElement.d.ts +48 -0
  86. package/dist/integration/xpath/static-dom/StaticNode.d.ts +33 -0
  87. package/dist/integration/xpath/static-dom/StaticText.d.ts +16 -0
  88. package/dist/lib/client-reactivity/submission/createInstanceSubmissionState.d.ts +3 -0
  89. package/dist/lib/client-reactivity/submission/createLeafNodeSubmissionState.d.ts +3 -0
  90. package/dist/lib/client-reactivity/submission/createNodeRangeSubmissionState.d.ts +4 -0
  91. package/dist/lib/client-reactivity/submission/createParentNodeSubmissionState.d.ts +4 -0
  92. package/dist/lib/client-reactivity/submission/createRootSubmissionState.d.ts +3 -0
  93. package/dist/lib/client-reactivity/submission/createValueNodeSubmissionState.d.ts +3 -0
  94. package/dist/lib/client-reactivity/submission/prepareSubmission.d.ts +8 -0
  95. package/dist/lib/codecs/DecimalValueCodec.d.ts +6 -0
  96. package/dist/lib/codecs/Geopoint/Geopoint.d.ts +48 -0
  97. package/dist/lib/codecs/Geopoint/GeopointValueCodec.d.ts +5 -0
  98. package/dist/lib/codecs/IntValueCodec.d.ts +6 -0
  99. package/dist/lib/codecs/NoteCodec.d.ts +8 -0
  100. package/dist/lib/codecs/RangeCodec.d.ts +8 -0
  101. package/dist/lib/codecs/StringValueCodec.d.ts +4 -0
  102. package/dist/lib/codecs/TriggerCodec.d.ts +7 -0
  103. package/dist/lib/codecs/ValueArrayCodec.d.ts +11 -0
  104. package/dist/lib/codecs/ValueCodec.d.ts +30 -0
  105. package/dist/lib/codecs/ValueTypePlaceholderCodec.d.ts +12 -0
  106. package/dist/lib/codecs/getNoteCodec.d.ts +3 -0
  107. package/dist/lib/codecs/getSelectCodec.d.ts +5 -0
  108. package/dist/lib/codecs/getSharedValueCodec.d.ts +48 -0
  109. package/dist/lib/codecs/items/BaseItemCodec.d.ts +9 -0
  110. package/dist/lib/codecs/items/MultipleValueItemCodec.d.ts +14 -0
  111. package/dist/lib/codecs/items/SingleValueItemCodec.d.ts +24 -0
  112. package/dist/lib/dom/query.d.ts +4 -2
  113. package/dist/lib/names/NamespaceDeclaration.d.ts +45 -0
  114. package/dist/lib/names/NamespaceDeclarationMap.d.ts +137 -0
  115. package/dist/lib/names/NamespaceURL.d.ts +30 -0
  116. package/dist/lib/names/QualifiedName.d.ts +113 -0
  117. package/dist/lib/number-parsers.d.ts +2 -0
  118. package/dist/lib/reactivity/createChildrenState.d.ts +7 -5
  119. package/dist/lib/reactivity/createComputedExpression.d.ts +18 -5
  120. package/dist/lib/reactivity/createInstanceValueState.d.ts +40 -0
  121. package/dist/lib/reactivity/createItemCollection.d.ts +21 -0
  122. package/dist/lib/reactivity/createNoteReadonlyThunk.d.ts +2 -2
  123. package/dist/lib/reactivity/createTranslationState.d.ts +19 -0
  124. package/dist/lib/reactivity/createValueState.d.ts +6 -10
  125. package/dist/lib/reactivity/materializeCurrentStateChildren.d.ts +4 -4
  126. package/dist/lib/xml-serialization.d.ts +50 -0
  127. package/dist/parse/XFormDOM.d.ts +18 -7
  128. package/dist/parse/XFormDefinition.d.ts +1 -2
  129. package/dist/parse/attachments/FormAttachmentResource.d.ts +27 -0
  130. package/dist/parse/body/BodyDefinition.d.ts +4 -4
  131. package/dist/parse/body/RepeatElementDefinition.d.ts +1 -1
  132. package/dist/parse/body/appearance/inputAppearanceParser.d.ts +1 -1
  133. package/dist/parse/body/appearance/rangeAppearanceParser.d.ts +3 -0
  134. package/dist/parse/body/control/{InputDefinition.d.ts → InputControlDefinition.d.ts} +4 -1
  135. package/dist/parse/body/control/ItemDefinition.d.ts +14 -0
  136. package/dist/parse/body/control/ItemsetDefinition.d.ts +18 -0
  137. package/dist/parse/body/control/RangeControlDefinition.d.ts +31 -2
  138. package/dist/parse/body/control/RankControlDefinition.d.ts +7 -3
  139. package/dist/parse/body/control/{select/SelectDefinition.d.ts → SelectControlDefinition.d.ts} +9 -9
  140. package/dist/parse/expression/ItemsetNodesetExpression.d.ts +1 -1
  141. package/dist/parse/expression/ItemsetValueExpression.d.ts +1 -1
  142. package/dist/parse/expression/abstract/DependencyContext.d.ts +0 -5
  143. package/dist/parse/expression/abstract/DependentExpression.d.ts +2 -3
  144. package/dist/parse/model/BindDefinition.d.ts +6 -5
  145. package/dist/parse/model/BindPreloadDefinition.d.ts +42 -0
  146. package/dist/parse/model/BindTypeDefinition.d.ts +20 -0
  147. package/dist/parse/model/DescendentNodeDefinition.d.ts +4 -14
  148. package/dist/parse/model/FormSubmissionDefinition.d.ts +8 -0
  149. package/dist/parse/model/ItextTranslation/ItextTranslationDefinition.d.ts +4 -0
  150. package/dist/parse/model/ItextTranslation/ItextTranslationRootDefinition.d.ts +9 -0
  151. package/dist/parse/model/ItextTranslation/ItextTranslationsDefinition.d.ts +8 -0
  152. package/dist/parse/model/LeafNodeDefinition.d.ts +9 -4
  153. package/dist/parse/model/ModelBindMap.d.ts +1 -1
  154. package/dist/parse/model/ModelDefinition.d.ts +2 -0
  155. package/dist/parse/model/NodeDefinition.d.ts +16 -20
  156. package/dist/parse/model/NoteNodeDefinition.d.ts +9 -8
  157. package/dist/parse/model/RangeNodeDefinition.d.ts +41 -0
  158. package/dist/parse/model/RepeatInstanceDefinition.d.ts +7 -4
  159. package/dist/parse/model/RepeatRangeDefinition.d.ts +7 -4
  160. package/dist/parse/model/RepeatTemplateDefinition.d.ts +7 -4
  161. package/dist/parse/model/RootAttributeDefinition.d.ts +24 -0
  162. package/dist/parse/model/RootAttributeMap.d.ts +23 -0
  163. package/dist/parse/model/RootDefinition.d.ts +12 -9
  164. package/dist/parse/model/SecondaryInstance/SecondaryInstanceDefinition.d.ts +4 -0
  165. package/dist/parse/model/SecondaryInstance/SecondaryInstanceRootDefinition.d.ts +7 -0
  166. package/dist/parse/model/SecondaryInstance/SecondaryInstancesDefinition.d.ts +13 -0
  167. package/dist/parse/model/SecondaryInstance/sources/BlankSecondaryInstanceSource.d.ts +14 -0
  168. package/dist/parse/model/SecondaryInstance/sources/CSVExternalSecondaryInstance.d.ts +22 -0
  169. package/dist/parse/model/SecondaryInstance/sources/ExternalSecondaryInstanceResource.d.ts +23 -0
  170. package/dist/parse/model/SecondaryInstance/sources/ExternalSecondaryInstanceSource.d.ts +9 -0
  171. package/dist/parse/model/SecondaryInstance/sources/GeoJSONExternalSecondaryInstance.d.ts +5 -0
  172. package/dist/parse/model/SecondaryInstance/sources/InternalSecondaryInstanceSource.d.ts +7 -0
  173. package/dist/parse/model/SecondaryInstance/sources/SecondaryInstanceSource.d.ts +13 -0
  174. package/dist/parse/model/SecondaryInstance/sources/XMLExternalSecondaryInstanceSource.d.ts +12 -0
  175. package/dist/parse/model/SubtreeDefinition.d.ts +7 -4
  176. package/dist/parse/shared/parseStaticDocumentFromDOMSubtree.d.ts +23 -0
  177. package/dist/parse/text/ItemLabelDefinition.d.ts +1 -1
  178. package/dist/parse/text/ItemsetLabelDefinition.d.ts +2 -2
  179. package/dist/parse/text/abstract/TextElementDefinition.d.ts +1 -1
  180. package/dist/parse/text/abstract/TextRangeDefinition.d.ts +0 -2
  181. package/dist/parse/xpath/semantic-analysis.d.ts +6 -3
  182. package/dist/solid.js +15437 -12246
  183. package/dist/solid.js.map +1 -1
  184. package/package.json +18 -13
  185. package/src/client/BaseNode.ts +21 -6
  186. package/src/client/BaseValueNode.ts +35 -0
  187. package/src/client/EngineConfig.ts +52 -51
  188. package/src/client/GroupNode.ts +1 -0
  189. package/src/client/InputNode.ts +113 -0
  190. package/src/client/ModelValueNode.ts +31 -7
  191. package/src/client/NoteNode.ts +45 -9
  192. package/src/client/RangeNode.ts +51 -0
  193. package/src/client/RankNode.ts +54 -0
  194. package/src/client/RootNode.ts +43 -7
  195. package/src/client/SelectNode.ts +53 -26
  196. package/src/client/SubtreeNode.ts +1 -0
  197. package/src/client/TriggerNode.ts +12 -6
  198. package/src/client/ValueType.ts +4 -0
  199. package/src/client/constants.ts +67 -0
  200. package/src/client/hierarchy.ts +12 -13
  201. package/src/client/identity.ts +16 -0
  202. package/src/client/node-types.ts +13 -7
  203. package/src/client/resources.ts +118 -0
  204. package/src/client/submission/SubmissionData.ts +12 -0
  205. package/src/client/submission/SubmissionDefinition.ts +16 -0
  206. package/src/client/submission/SubmissionInstanceFile.ts +9 -0
  207. package/src/client/submission/SubmissionOptions.ts +28 -0
  208. package/src/client/submission/SubmissionResult.ts +124 -0
  209. package/src/client/submission/SubmissionState.ts +14 -0
  210. package/src/client/unsupported/UnsupportedControlNode.ts +2 -6
  211. package/src/client/validation.ts +2 -2
  212. package/src/error/ErrorProductionDesignPendingError.ts +6 -0
  213. package/src/error/RankMissingValueError.ts +5 -0
  214. package/src/error/RankValueTypeError.ts +13 -0
  215. package/src/error/SelectValueTypeError.ts +22 -0
  216. package/src/error/ValueTypeInvariantError.ts +22 -0
  217. package/src/error/XFormsSpecViolationError.ts +1 -0
  218. package/src/error/XPathFunctionalityError.ts +26 -0
  219. package/src/error/XPathFunctionalityNotSupportedError.ts +18 -0
  220. package/src/error/XPathFunctionalityPendingError.ts +18 -0
  221. package/src/index.ts +12 -13
  222. package/src/instance/Group.ts +18 -5
  223. package/src/instance/InputControl.ts +159 -0
  224. package/src/instance/ModelValue.ts +48 -53
  225. package/src/instance/Note.ts +40 -49
  226. package/src/instance/PrimaryInstance.ts +245 -0
  227. package/src/instance/RangeControl.ts +113 -0
  228. package/src/instance/RankControl.ts +199 -0
  229. package/src/instance/Root.ts +63 -134
  230. package/src/instance/SelectControl.ts +219 -0
  231. package/src/instance/Subtree.ts +20 -7
  232. package/src/instance/TriggerControl.ts +44 -66
  233. package/src/instance/abstract/DescendantNode.ts +91 -51
  234. package/src/instance/abstract/InstanceNode.ts +113 -107
  235. package/src/instance/abstract/UnsupportedControl.ts +29 -5
  236. package/src/instance/abstract/ValueNode.ts +128 -0
  237. package/src/instance/children.ts +80 -40
  238. package/src/instance/hierarchy.ts +39 -30
  239. package/src/instance/identity.ts +3 -9
  240. package/src/instance/index.ts +25 -7
  241. package/src/instance/internal-api/EvaluationContext.ts +60 -13
  242. package/src/instance/internal-api/InstanceConfig.ts +9 -2
  243. package/src/instance/internal-api/InstanceValueContext.ts +26 -0
  244. package/src/instance/internal-api/PrimaryInstanceDocument.ts +53 -0
  245. package/src/instance/internal-api/TranslationContext.ts +3 -2
  246. package/src/instance/internal-api/ValidationContext.ts +3 -4
  247. package/src/instance/internal-api/ValueContext.ts +2 -1
  248. package/src/instance/internal-api/submission/ClientReactiveSubmittableInstance.ts +20 -0
  249. package/src/instance/internal-api/submission/ClientReactiveSubmittableLeafNode.ts +43 -0
  250. package/src/instance/internal-api/submission/ClientReactiveSubmittableParentNode.ts +26 -0
  251. package/src/instance/internal-api/submission/ClientReactiveSubmittableValueNode.ts +24 -0
  252. package/src/instance/repeat/BaseRepeatRange.ts +52 -131
  253. package/src/instance/repeat/RepeatInstance.ts +21 -46
  254. package/src/instance/repeat/RepeatRangeControlled.ts +5 -5
  255. package/src/instance/repeat/RepeatRangeUncontrolled.ts +2 -4
  256. package/src/instance/resource.ts +5 -2
  257. package/src/instance/text/TextChunk.ts +1 -1
  258. package/src/instance/unsupported/UploadControl.ts +5 -1
  259. package/src/integration/xpath/EngineXPathEvaluator.ts +22 -0
  260. package/src/integration/xpath/adapter/XFormsXPathNode.ts +126 -0
  261. package/src/integration/xpath/adapter/engineDOMAdapter.ts +57 -0
  262. package/src/integration/xpath/adapter/kind.ts +114 -0
  263. package/src/integration/xpath/adapter/names.ts +148 -0
  264. package/src/integration/xpath/adapter/traversal.ts +229 -0
  265. package/src/integration/xpath/adapter/values.ts +5 -0
  266. package/src/integration/xpath/static-dom/StaticAttribute.ts +41 -0
  267. package/src/integration/xpath/static-dom/StaticDocument.ts +36 -0
  268. package/src/integration/xpath/static-dom/StaticElement.ts +119 -0
  269. package/src/integration/xpath/static-dom/StaticNode.ts +68 -0
  270. package/src/integration/xpath/static-dom/StaticText.ts +28 -0
  271. package/src/lib/client-reactivity/README.md +0 -0
  272. package/src/lib/client-reactivity/submission/createInstanceSubmissionState.ts +12 -0
  273. package/src/lib/client-reactivity/submission/createLeafNodeSubmissionState.ts +20 -0
  274. package/src/lib/client-reactivity/submission/createNodeRangeSubmissionState.ts +17 -0
  275. package/src/lib/client-reactivity/submission/createParentNodeSubmissionState.ts +22 -0
  276. package/src/lib/client-reactivity/submission/createRootSubmissionState.ts +19 -0
  277. package/src/lib/client-reactivity/submission/createValueNodeSubmissionState.ts +21 -0
  278. package/src/lib/client-reactivity/submission/prepareSubmission.ts +172 -0
  279. package/src/lib/codecs/DecimalValueCodec.ts +46 -0
  280. package/src/lib/codecs/Geopoint/Geopoint.ts +150 -0
  281. package/src/lib/codecs/Geopoint/GeopointValueCodec.ts +20 -0
  282. package/src/lib/codecs/IntValueCodec.ts +100 -0
  283. package/src/lib/codecs/NoteCodec.ts +32 -0
  284. package/src/lib/codecs/RangeCodec.ts +65 -0
  285. package/src/lib/codecs/StringValueCodec.ts +11 -0
  286. package/src/lib/codecs/TriggerCodec.ts +64 -0
  287. package/src/lib/codecs/ValueArrayCodec.ts +42 -0
  288. package/src/lib/codecs/ValueCodec.ts +106 -0
  289. package/src/lib/codecs/ValueTypePlaceholderCodec.ts +19 -0
  290. package/src/lib/codecs/getNoteCodec.ts +27 -0
  291. package/src/lib/codecs/getSelectCodec.ts +27 -0
  292. package/src/lib/codecs/getSharedValueCodec.ts +79 -0
  293. package/src/lib/codecs/items/BaseItemCodec.ts +20 -0
  294. package/src/lib/codecs/items/MultipleValueItemCodec.ts +28 -0
  295. package/src/lib/codecs/items/SingleValueItemCodec.ts +67 -0
  296. package/src/lib/dom/query.ts +8 -2
  297. package/src/lib/names/NamespaceDeclaration.ts +106 -0
  298. package/src/lib/names/NamespaceDeclarationMap.ts +228 -0
  299. package/src/lib/names/NamespaceURL.ts +44 -0
  300. package/src/lib/names/QualifiedName.ts +170 -0
  301. package/src/lib/number-parsers.ts +25 -0
  302. package/src/lib/reactivity/createChildrenState.ts +8 -6
  303. package/src/lib/reactivity/createComputedExpression.ts +57 -34
  304. package/src/lib/reactivity/createInstanceValueState.ts +216 -0
  305. package/src/lib/reactivity/createItemCollection.ts +173 -0
  306. package/src/lib/reactivity/createNoteReadonlyThunk.ts +12 -7
  307. package/src/lib/reactivity/createTranslationState.ts +61 -0
  308. package/src/lib/reactivity/createValueState.ts +62 -120
  309. package/src/lib/reactivity/materializeCurrentStateChildren.ts +7 -7
  310. package/src/lib/reactivity/text/createTextRange.ts +4 -3
  311. package/src/lib/reactivity/validation/createAggregatedViolations.ts +1 -1
  312. package/src/lib/reactivity/validation/createValidation.ts +2 -3
  313. package/src/lib/xml-serialization.ts +163 -0
  314. package/src/parse/XFormDOM.ts +231 -76
  315. package/src/parse/XFormDefinition.ts +2 -10
  316. package/src/parse/attachments/FormAttachmentResource.ts +40 -0
  317. package/src/parse/body/BodyDefinition.ts +7 -7
  318. package/src/parse/body/appearance/inputAppearanceParser.ts +1 -1
  319. package/src/parse/body/appearance/rangeAppearanceParser.ts +11 -0
  320. package/src/parse/body/control/InputControlDefinition.ts +29 -0
  321. package/src/parse/body/control/{select/ItemDefinition.ts → ItemDefinition.ts} +8 -6
  322. package/src/parse/body/control/{select/ItemsetDefinition.ts → ItemsetDefinition.ts} +11 -9
  323. package/src/parse/body/control/RangeControlDefinition.ts +91 -6
  324. package/src/parse/body/control/RankControlDefinition.ts +25 -7
  325. package/src/parse/body/control/{select/SelectDefinition.ts → SelectControlDefinition.ts} +9 -9
  326. package/src/parse/expression/ItemsetNodesetExpression.ts +1 -1
  327. package/src/parse/expression/ItemsetValueExpression.ts +1 -1
  328. package/src/parse/expression/abstract/DependencyContext.ts +0 -26
  329. package/src/parse/expression/abstract/DependentExpression.ts +2 -13
  330. package/src/parse/model/BindDefinition.ts +9 -8
  331. package/src/parse/model/BindPreloadDefinition.ts +100 -0
  332. package/src/parse/model/BindTypeDefinition.ts +175 -0
  333. package/src/parse/model/DescendentNodeDefinition.ts +7 -31
  334. package/src/parse/model/FormSubmissionDefinition.ts +44 -0
  335. package/src/parse/model/ItextTranslation/ItextTranslationDefinition.ts +4 -0
  336. package/src/parse/model/ItextTranslation/ItextTranslationRootDefinition.ts +42 -0
  337. package/src/parse/model/ItextTranslation/ItextTranslationsDefinition.ts +31 -0
  338. package/src/parse/model/LeafNodeDefinition.ts +15 -5
  339. package/src/parse/model/ModelBindMap.ts +6 -8
  340. package/src/parse/model/ModelDefinition.ts +6 -1
  341. package/src/parse/model/NodeDefinition.ts +24 -48
  342. package/src/parse/model/NoteNodeDefinition.ts +11 -10
  343. package/src/parse/model/RangeNodeDefinition.ts +118 -0
  344. package/src/parse/model/RepeatInstanceDefinition.ts +11 -7
  345. package/src/parse/model/RepeatRangeDefinition.ts +11 -7
  346. package/src/parse/model/RepeatTemplateDefinition.ts +11 -7
  347. package/src/parse/model/RootAttributeDefinition.ts +45 -0
  348. package/src/parse/model/RootAttributeMap.ts +44 -0
  349. package/src/parse/model/RootDefinition.ts +31 -29
  350. package/src/parse/model/SecondaryInstance/SecondaryInstanceDefinition.ts +4 -0
  351. package/src/parse/model/SecondaryInstance/SecondaryInstanceRootDefinition.ts +12 -0
  352. package/src/parse/model/SecondaryInstance/SecondaryInstancesDefinition.ts +102 -0
  353. package/src/parse/model/SecondaryInstance/sources/BlankSecondaryInstanceSource.ts +40 -0
  354. package/src/parse/model/SecondaryInstance/sources/CSVExternalSecondaryInstance.ts +288 -0
  355. package/src/parse/model/SecondaryInstance/sources/ExternalSecondaryInstanceResource.ts +222 -0
  356. package/src/parse/model/SecondaryInstance/sources/ExternalSecondaryInstanceSource.ts +22 -0
  357. package/src/parse/model/SecondaryInstance/sources/GeoJSONExternalSecondaryInstance.ts +415 -0
  358. package/src/parse/model/SecondaryInstance/sources/InternalSecondaryInstanceSource.ts +19 -0
  359. package/src/parse/model/SecondaryInstance/sources/SecondaryInstanceSource.ts +29 -0
  360. package/src/parse/model/SecondaryInstance/sources/XMLExternalSecondaryInstanceSource.ts +32 -0
  361. package/src/parse/model/SubtreeDefinition.ts +12 -12
  362. package/src/parse/shared/parseStaticDocumentFromDOMSubtree.ts +149 -0
  363. package/src/parse/text/ItemLabelDefinition.ts +1 -1
  364. package/src/parse/text/ItemsetLabelDefinition.ts +2 -2
  365. package/src/parse/text/abstract/TextElementDefinition.ts +1 -1
  366. package/src/parse/text/abstract/TextRangeDefinition.ts +0 -6
  367. package/src/parse/xpath/semantic-analysis.ts +33 -3
  368. package/dist/client/StringNode.d.ts +0 -46
  369. package/dist/client/unsupported/RangeNode.d.ts +0 -9
  370. package/dist/client/unsupported/RankNode.d.ts +0 -9
  371. package/dist/instance/SelectField.d.ts +0 -50
  372. package/dist/instance/StringField.d.ts +0 -44
  373. package/dist/instance/internal-api/SubscribableDependency.d.ts +0 -59
  374. package/dist/instance/unsupported/RangeControl.d.ts +0 -4
  375. package/dist/instance/unsupported/RankControl.d.ts +0 -4
  376. package/dist/lib/reactivity/createSelectItems.d.ts +0 -16
  377. package/dist/parse/XFormDataType.d.ts +0 -25
  378. package/dist/parse/body/control/select/ItemDefinition.d.ts +0 -13
  379. package/dist/parse/body/control/select/ItemsetDefinition.d.ts +0 -17
  380. package/dist/parse/body/control/select/ItemsetNodesetContext.d.ts +0 -11
  381. package/src/client/StringNode.ts +0 -52
  382. package/src/client/unsupported/RangeNode.ts +0 -14
  383. package/src/client/unsupported/RankNode.ts +0 -14
  384. package/src/instance/SelectField.ts +0 -226
  385. package/src/instance/StringField.ts +0 -120
  386. package/src/instance/internal-api/SubscribableDependency.ts +0 -61
  387. package/src/instance/unsupported/RangeControl.ts +0 -5
  388. package/src/instance/unsupported/RankControl.ts +0 -5
  389. package/src/lib/reactivity/createSelectItems.ts +0 -168
  390. package/src/parse/XFormDataType.ts +0 -62
  391. package/src/parse/body/control/InputDefinition.ts +0 -22
  392. package/src/parse/body/control/select/ItemsetNodesetContext.ts +0 -26
@@ -0,0 +1,170 @@
1
+ import type { XPathDOMAdapter } from '@getodk/xpath';
2
+ import { NamespaceURL } from './NamespaceURL.ts';
3
+
4
+ export type NamespaceURI = NamespaceURL | null;
5
+ export type QualifiedNamePrefix = string | null;
6
+
7
+ export interface NamespaceQualifiedNameSource {
8
+ readonly namespaceURI: NamespaceURI | string;
9
+ readonly localName: string;
10
+
11
+ /**
12
+ * Note that this property is intentionally optional as one of the
13
+ * {@link QualifiedNameSource | QualifiedName source input}, and its absence
14
+ * is treated differently from an explicitly assigned `null` value.
15
+ *
16
+ * @see {@link SourcePrefixUnspecified}, {@link DeferredPrefix}
17
+ */
18
+ readonly prefix?: QualifiedNamePrefix;
19
+ }
20
+
21
+ const SOURCE_PREFIX_UNSPECIFIED = Symbol('SOURCE_PREFIX_UNSPECIFIED');
22
+
23
+ /**
24
+ * May be used as a placeholder for a {@link QualifiedName.prefix}, where the
25
+ * actual prefix may not be known at definition time.
26
+ *
27
+ * Example: parsing non-XML sources into an XML-like tree, e.g. for XPath
28
+ * evaluation; in which case, we may not need to resolve a prefix for the name
29
+ * until such a node is serialized as XML, if it ever is.
30
+ */
31
+ type SourcePrefixUnspecified = typeof SOURCE_PREFIX_UNSPECIFIED;
32
+
33
+ /**
34
+ * Represents a {@link QualifiedName.prefix} whose resolution may be deferred,
35
+ * e.g. until all requisite parsing is complete and/or until XML serialization
36
+ * requires use of a prefix to represent the corresponding
37
+ * {@link QualifiedName.namespaceURI}.
38
+ */
39
+ // prettier-ignore
40
+ type DeferredPrefix =
41
+ // eslint-disable-next-line @typescript-eslint/sort-type-constituents
42
+ | string
43
+ | null
44
+ | SourcePrefixUnspecified;
45
+
46
+ interface DeferredPrefixedQualifiedNameSource {
47
+ readonly namespaceURI: NamespaceURI | string;
48
+ readonly prefix: DeferredPrefix;
49
+ readonly localName: string;
50
+ }
51
+
52
+ // prettier-ignore
53
+ export type QualifiedNameSource =
54
+ // eslint-disable-next-line @typescript-eslint/sort-type-constituents
55
+ | NamespaceQualifiedNameSource
56
+ | DeferredPrefixedQualifiedNameSource;
57
+
58
+ interface PrefixResolutionOptions {
59
+ lookupPrefix(namespaceURI: NamespaceURI | string): string | null;
60
+ }
61
+
62
+ /**
63
+ * @todo This is in the `lib` directory because it's a cross-cutting concern,
64
+ * applicable to:
65
+ *
66
+ * - Parsing XML into a useful runtime data model (usage which motivated initial
67
+ * development of this class)
68
+ * - Serializing XML from a runtime data model (also motivated initial dev)
69
+ * - `@getodk/xpath` (internal) e.g. references to
70
+ * {@link https://www.w3.org/TR/REC-xml-names/#NT-QName | QName} in various
71
+ * parts of XPath expression _syntax_, as well as various parts of the package
72
+ * interpreting those parts of syntax
73
+ * - `@getodk/xpath` (cross-package), e.g. in aspects of the
74
+ * {@link XPathDOMAdapter} APIs, and implementations thereof
75
+ * - A zillion potential optimizations, e.g. where names are useful in a lookup
76
+ * table (or used in conjunction with other information to construct keys for
77
+ * same)
78
+ *
79
+ * @todo As a cross-cutting concern, there are subtle but important differences
80
+ * between certain XPath and XML semantics around expressions of a "null"
81
+ * {@link prefix}. E.g. in the expression `/foo`, **technically** the `foo` Step
82
+ * should select child elements _in the null namespace_, whereas in most other
83
+ * cases a null prefix (when explicitly assigned `null`, rather than
84
+ * {@link DeferredPrefix | deferred for later resolution}) is expected to
85
+ * correspond _to the default namespace_ (whatever that is in the context of the
86
+ * {@link QualifiedName | qualified-named thing}).
87
+ *
88
+ * @todo As a mechanism for many optimizations, an evolution of this class would
89
+ * be **BY FAR** most useful if it can be treated as a _value type_, despite
90
+ * challenges using non-primitives as such in a JS runtime. To be clear: it
91
+ * would be most useful if every instance of {@link QualifiedName} having the
92
+ * same property values (or in some cases, the same combined
93
+ * {@link namespaceURI}/{@link localName} or combined
94
+ * {@link prefix}/{@link localName}) would also have _reference equality_ with
95
+ * other instances having the same property values (or pertinent subset
96
+ * thereof). Making a somewhat obvious point explicit: this would be
97
+ * particularly useful in cases where a lookup table is implemented as a native
98
+ * {@link Map}, where using {@link QualifiedName} as a key would break
99
+ * expectations (and probably quite a lot of functionality!) if 2+ equivalent
100
+ * keys mapped to different values.
101
+ *
102
+ * @todo Where we would want to treat instances as a value type, it would be
103
+ * useful to look at prior art for representation of the same data as a string.
104
+ * One frame of reference worth looking at is
105
+ * {@link https://www.w3.org/TR/xpath-30/#prod-xpath30-URIQualifiedName | XPath 3.0's URIQualifiedName}
106
+ * (but note that this syntax is mutually exclusive with the prefixed `QName`).
107
+ */
108
+ export class QualifiedName implements DeferredPrefixedQualifiedNameSource {
109
+ private readonly defaultPrefixResolutionOptions: PrefixResolutionOptions;
110
+
111
+ readonly namespaceURI: NamespaceURI;
112
+
113
+ /**
114
+ * @see {@link SourcePrefixUnspecified}, {@link DeferredPrefix}
115
+ */
116
+ readonly prefix: DeferredPrefix;
117
+
118
+ readonly localName: string;
119
+
120
+ constructor(source: QualifiedNameSource) {
121
+ const { localName } = source;
122
+
123
+ let prefix = source.prefix;
124
+
125
+ if (typeof prefix === 'undefined') {
126
+ prefix = SOURCE_PREFIX_UNSPECIFIED;
127
+ }
128
+
129
+ const namespaceURI = NamespaceURL.from(source.namespaceURI);
130
+
131
+ this.namespaceURI = namespaceURI;
132
+ this.prefix = prefix;
133
+ this.localName = localName;
134
+
135
+ this.defaultPrefixResolutionOptions = {
136
+ lookupPrefix: () => {
137
+ if (prefix === SOURCE_PREFIX_UNSPECIFIED) {
138
+ throw new Error(`Failed to resolve prefix for namespace URI: ${String(namespaceURI)}`);
139
+ }
140
+
141
+ return prefix;
142
+ },
143
+ };
144
+ }
145
+
146
+ /**
147
+ * @todo at time of writing, it's not expected we will actually supply
148
+ * {@link options} in calls to this method! Current calls are from definitions
149
+ * whose prefixes are known at parse time (i.e. they are prefixed in the
150
+ * source XML from which they're parsed).
151
+ *
152
+ * The intent of accepting the options here now is to leave a fairly large
153
+ * breadcrumb, for any use case where we might want to serialize XML from
154
+ * artificially constructed DOM-like trees (e.g. `StaticNode` implementations
155
+ * defined by parsing non-XML external secondary instances such as CSV and
156
+ * GeoJSON). AFAIK this doesn't correspond to any known feature in the "like
157
+ * Collect" scope, but it could have implications for inspecting form details
158
+ * in e.g. "debug/form design/dev mode" scenarios.
159
+ */
160
+ getPrefixedName(options: PrefixResolutionOptions = this.defaultPrefixResolutionOptions): string {
161
+ const { namespaceURI, localName } = this;
162
+ const prefix = options.lookupPrefix(namespaceURI);
163
+
164
+ if (prefix == null) {
165
+ return localName;
166
+ }
167
+
168
+ return `${prefix}:${localName}`;
169
+ }
170
+ }
@@ -0,0 +1,25 @@
1
+ export const parseToInteger = (value: string | null): number | null => {
2
+ if (value === null) {
3
+ return null;
4
+ }
5
+
6
+ const parsed = Number(value);
7
+ if (typeof value !== 'string' || value.trim() === '' || !Number.isInteger(parsed)) {
8
+ throw new Error(`Expected an integer, but got: ${value}`);
9
+ }
10
+
11
+ return parsed;
12
+ };
13
+
14
+ export const parseToFloat = (value: string | null): number | null => {
15
+ if (value === null) {
16
+ return null;
17
+ }
18
+
19
+ const parsed = Number(value);
20
+ if (typeof value !== 'string' || value.trim() === '' || Number.isNaN(parsed)) {
21
+ throw new Error(`Expected a float, but got: ${value}`);
22
+ }
23
+
24
+ return parsed;
25
+ };
@@ -1,8 +1,8 @@
1
1
  import type { Accessor, Setter, Signal } from 'solid-js';
2
2
  import { createSignal } from 'solid-js';
3
+ import type { FormNodeID } from '../../client/identity.ts';
3
4
  import type { OpaqueReactiveObjectFactory } from '../../index.ts';
4
5
  import type { AnyChildNode, AnyParentNode } from '../../instance/hierarchy.ts';
5
- import type { NodeID } from '../../instance/identity.ts';
6
6
  import type { materializeCurrentStateChildren } from './materializeCurrentStateChildren.ts';
7
7
  import type { ClientState } from './node-state/createClientState.ts';
8
8
  import type { CurrentState } from './node-state/createCurrentState.ts';
@@ -12,14 +12,15 @@ export interface ChildrenState<Child extends AnyChildNode> {
12
12
  readonly children: Signal<readonly Child[]>;
13
13
  readonly getChildren: Accessor<readonly Child[]>;
14
14
  readonly setChildren: Setter<readonly Child[]>;
15
- readonly childIds: Accessor<readonly NodeID[]>;
15
+ readonly childIds: Accessor<readonly FormNodeID[]>;
16
16
  }
17
17
 
18
18
  /**
19
19
  * Creates a synchronized pair of:
20
20
  *
21
21
  * - Internal children state suitable for all parent node types
22
- * - The same children state computed as an array of each child's {@link NodeID}
22
+ * - The same children state computed as an array of each child's
23
+ * {@link FormNodeID}
23
24
  *
24
25
  * This state is used, in tandem with {@link materializeCurrentStateChildren},
25
26
  * to ensure children in **client-facing** state are not written into nested
@@ -34,11 +35,12 @@ export interface ChildrenState<Child extends AnyChildNode> {
34
35
  * The produced {@link ChildrenState.childIds} memo is intended to be used to
35
36
  * specify each parent node's `children` in an instance of {@link EngineState}.
36
37
  * In so doing, the node's corresponding (internal, synchronized)
37
- * {@link ClientState} will likewise store only the children's {@link NodeID}s.
38
+ * {@link ClientState} will likewise store only the children's
39
+ * {@link FormNodeID}s.
38
40
  *
39
41
  * As a client reacts to changes in a given parent node's `children` state, that
40
42
  * node's {@link CurrentState} should produce the child nodes corresponding to
41
- * those {@link NodeID}s with the aforementioned
43
+ * those {@link FormNodeID}s with the aforementioned
42
44
  * {@link materializeCurrentStateChildren}.
43
45
  */
44
46
  export const createChildrenState = <Parent extends AnyParentNode, Child extends AnyChildNode>(
@@ -65,7 +67,7 @@ export const createChildrenState = <Parent extends AnyParentNode, Child extends
65
67
  * likely also slightly more efficient. We can revisit the tradeoff if/when
66
68
  * those hypothetical generalizations become a priority.
67
69
  */
68
- const ids = createSignal<readonly NodeID[]>([]);
70
+ const ids = createSignal<readonly FormNodeID[]>([]);
69
71
  const [childIds, setChildIds] = ids;
70
72
 
71
73
  type ChildrenSetterCallback = (prev: readonly Child[]) => readonly Child[];
@@ -1,9 +1,9 @@
1
1
  import { UnreachableError } from '@getodk/common/lib/error/UnreachableError.ts';
2
- import type { XFormsXPathEvaluator } from '@getodk/xpath';
3
2
  import type { Accessor } from 'solid-js';
4
3
  import { createMemo } from 'solid-js';
5
4
  import type { EvaluationContext } from '../../instance/internal-api/EvaluationContext.ts';
6
- import type { SubscribableDependency } from '../../instance/internal-api/SubscribableDependency.ts';
5
+ import type { EngineXPathNode } from '../../integration/xpath/adapter/kind.ts';
6
+ import type { EngineXPathEvaluator } from '../../integration/xpath/EngineXPathEvaluator.ts';
7
7
  import type {
8
8
  DependentExpression,
9
9
  DependentExpressionResultType,
@@ -12,7 +12,7 @@ import { isConstantExpression } from '../../parse/xpath/semantic-analysis.ts';
12
12
 
13
13
  interface ComputedExpressionResults {
14
14
  readonly boolean: boolean;
15
- readonly nodes: Node[];
15
+ readonly nodes: EngineXPathNode[];
16
16
  readonly number: number;
17
17
  readonly string: string;
18
18
  }
@@ -25,16 +25,18 @@ type EvaluatedExpression<
25
25
  // prettier-ignore
26
26
  type ExpressionEvaluator<
27
27
  Type extends DependentExpressionResultType
28
- > = () => EvaluatedExpression<Type>
28
+ > = () => EvaluatedExpression<Type>;
29
+
30
+ interface ExpressionEvaluatorOptions {
31
+ get contextNode(): EngineXPathNode;
32
+ }
29
33
 
30
34
  const expressionEvaluator = <Type extends DependentExpressionResultType>(
31
- evaluator: XFormsXPathEvaluator,
32
- contextNode: Node,
35
+ evaluator: EngineXPathEvaluator,
33
36
  type: Type,
34
- expression: string
37
+ expression: string,
38
+ options: ExpressionEvaluatorOptions
35
39
  ): ExpressionEvaluator<Type> => {
36
- const options = { contextNode };
37
-
38
40
  switch (type) {
39
41
  case 'boolean':
40
42
  return (() => {
@@ -61,50 +63,71 @@ const expressionEvaluator = <Type extends DependentExpressionResultType>(
61
63
  }
62
64
  };
63
65
 
66
+ type DefaultEvaluationsByType = {
67
+ readonly [Type in DependentExpressionResultType]: EvaluatedExpression<Type>;
68
+ };
69
+
70
+ const DEFAULT_BOOLEAN_EVALUATION = false;
71
+ const DEFAULT_NODES_EVALUATION: [] = [];
72
+ const DEFAULT_NUMBER_EVALUATION = NaN;
73
+ const DEFAULT_STRING_EVALUATION = '';
74
+
75
+ const defaultEvaluationsByType: DefaultEvaluationsByType = {
76
+ boolean: DEFAULT_BOOLEAN_EVALUATION,
77
+ nodes: DEFAULT_NODES_EVALUATION,
78
+ number: DEFAULT_NUMBER_EVALUATION,
79
+ string: DEFAULT_STRING_EVALUATION,
80
+ };
81
+
64
82
  // prettier-ignore
65
83
  type ComputedExpression<Type extends DependentExpressionResultType> = Accessor<
66
84
  EvaluatedExpression<Type>
67
85
  >;
68
86
 
69
- interface CreateComputedExpressionOptions {
70
- readonly arbitraryDependencies?: readonly SubscribableDependency[];
87
+ interface CreateComputedExpressionOptions<Type extends DependentExpressionResultType> {
88
+ /**
89
+ * If a default value is provided, {@link createComputedExpression} will
90
+ * produce this value for computations in a non-attached evaluation context,
91
+ * i.e. when evaluating an expression against a node which has not yet been
92
+ * appended to its parents children state (or which has since been removed
93
+ * from that state). A non-attached state is detected when
94
+ * {@link EvaluationContext.isAttached} returns false.
95
+ *
96
+ * If no default value is provided, an implicit default value is produced as
97
+ * appropriate for the expression's intrinsic result type.
98
+ *
99
+ * @see {@link defaultEvaluationsByType} for these implicit defaults.
100
+ */
101
+ readonly defaultValue?: EvaluatedExpression<Type>;
71
102
  }
72
103
 
73
104
  export const createComputedExpression = <Type extends DependentExpressionResultType>(
74
105
  context: EvaluationContext,
75
106
  dependentExpression: DependentExpression<Type>,
76
- options: CreateComputedExpressionOptions = {}
107
+ options: CreateComputedExpressionOptions<Type> = {}
77
108
  ): ComputedExpression<Type> => {
78
- const { contextNode, evaluator, root, scope } = context;
79
- const { expression, isTranslated, resultType } = dependentExpression;
80
- const dependencyReferences = Array.from(dependentExpression.dependencyReferences);
81
- const evaluateExpression = expressionEvaluator(evaluator, contextNode, resultType, expression);
109
+ return context.scope.runTask(() => {
110
+ const { contextNode, evaluator } = context;
111
+ const { expression, isTranslated, resultType } = dependentExpression;
112
+ const evaluatePreInitializationDefaultValue = () => {
113
+ return options?.defaultValue ?? defaultEvaluationsByType[resultType];
114
+ };
115
+ const evaluateExpression = expressionEvaluator(evaluator, resultType, expression, {
116
+ contextNode,
117
+ });
82
118
 
83
- return scope.runTask(() => {
84
119
  if (isConstantExpression(expression)) {
85
120
  return createMemo(evaluateExpression);
86
121
  }
87
122
 
88
- const { arbitraryDependencies = [] } = options;
89
-
90
- const getReferencedDependencies = createMemo(() => {
91
- return dependencyReferences.flatMap((reference) => {
92
- return context.getSubscribableDependenciesByReference(reference) ?? [];
93
- });
94
- });
95
-
96
123
  return createMemo(() => {
97
- if (isTranslated) {
98
- root.subscribe();
124
+ if (!context.isAttached()) {
125
+ return evaluatePreInitializationDefaultValue();
99
126
  }
100
127
 
101
- arbitraryDependencies.forEach((dependency) => {
102
- dependency.subscribe();
103
- });
104
-
105
- getReferencedDependencies().forEach((dependency) => {
106
- dependency.subscribe();
107
- });
128
+ if (isTranslated) {
129
+ context.getActiveLanguage();
130
+ }
108
131
 
109
132
  return evaluateExpression();
110
133
  });
@@ -0,0 +1,216 @@
1
+ import type { Signal } from 'solid-js';
2
+ import { createComputed, createMemo, createSignal, untrack } from 'solid-js';
3
+ import { ErrorProductionDesignPendingError } from '../../error/ErrorProductionDesignPendingError.ts';
4
+ import type { InstanceValueContext } from '../../instance/internal-api/InstanceValueContext.ts';
5
+ import type { BindComputationExpression } from '../../parse/expression/BindComputationExpression.ts';
6
+ import { createComputedExpression } from './createComputedExpression.ts';
7
+ import type { SimpleAtomicState, SimpleAtomicStateSetter } from './types.ts';
8
+
9
+ type InitialValueSource = 'FORM_DEFAULT' | 'PRIMARY_INSTANCE';
10
+
11
+ /**
12
+ * @todo {@link InitialValueSource} naming leaves a lot to be desired. As described in {@link InstanceValueStateOptions.initialValueSource}, this check (for now) will effectively answer the question: "are we **NOT** editing instance state (e.g. a submission)?". This answer, in turn, determines whether to {@link setPreloadUIDValue}
13
+ */
14
+ const isInstanceFirstLoad = (valueSource?: InitialValueSource) => {
15
+ return valueSource === 'FORM_DEFAULT';
16
+ };
17
+
18
+ export interface InstanceValueStateOptions {
19
+ /**
20
+ * Specifies the source of a {@link createInstanceValueState} signal's initial
21
+ * value state, where:
22
+ *
23
+ * - 'FORM_DEFAULT': Derives the initial state from the form's definition of
24
+ * the node itself. This is the default option, appropriate when
25
+ * initializing a form without additional primary instance data. In other
26
+ * words, this value should not be used for edits.
27
+ *
28
+ * - 'PRIMARY_INSTANCE': Derives the initial state from the current text
29
+ * content of the {@link ValueNode.contextNode}. This option should be
30
+ * specified when initializing a form with existing primary instance data,
31
+ * such as when editing a previous submission.
32
+ *
33
+ * @default 'FORM_DEFAULT'
34
+ *
35
+ * Specifies whether a {@link createInstanceValueState} signal's initial state
36
+ * should be derived from the current text content of the
37
+ * {@link ValueNode.contextNode | primary instance DOM state}.
38
+ */
39
+ readonly initialValueSource?: InitialValueSource;
40
+ }
41
+
42
+ const getInitialValue = (
43
+ context: InstanceValueContext,
44
+ options: InstanceValueStateOptions
45
+ ): string => {
46
+ const { initialValueSource = 'FORM_DEFAULT' } = options;
47
+
48
+ if (initialValueSource === 'FORM_DEFAULT') {
49
+ const { defaultValue } = context.definition;
50
+
51
+ return context.decodeInstanceValue(defaultValue);
52
+ }
53
+
54
+ throw new ErrorProductionDesignPendingError('Edit implementation pending');
55
+ };
56
+
57
+ type BaseValueState = Signal<string>;
58
+
59
+ type RelevantValueState = SimpleAtomicState<string>;
60
+
61
+ /**
62
+ * Wraps {@link baseValueState} in a signal-like interface which:
63
+ *
64
+ * - produces a blank value for nodes ({@link context}) in a non-relevant state
65
+ * - persists, and restores, the most recent non-blank value state when a
66
+ * node/context's relevance is restored
67
+ */
68
+ const createRelevantValueState = (
69
+ context: InstanceValueContext,
70
+ baseValueState: BaseValueState
71
+ ): RelevantValueState => {
72
+ return context.scope.runTask(() => {
73
+ const [getRelevantValue, setValue] = baseValueState;
74
+
75
+ const getValue = createMemo(() => {
76
+ if (context.isRelevant()) {
77
+ return getRelevantValue();
78
+ }
79
+
80
+ return '';
81
+ });
82
+
83
+ return [getValue, setValue];
84
+ });
85
+ };
86
+
87
+ /**
88
+ * For fields with a `readonly` bind expression, prevent downstream
89
+ * (client/user) writes when the field is in a `readonly` state.
90
+ */
91
+ const guardDownstreamReadonlyWrites = (
92
+ context: InstanceValueContext,
93
+ baseState: SimpleAtomicState<string>
94
+ ): SimpleAtomicState<string> => {
95
+ const { readonly } = context.definition.bind;
96
+
97
+ if (readonly.isDefaultExpression) {
98
+ return baseState;
99
+ }
100
+
101
+ const [getValue, baseSetValue] = baseState;
102
+
103
+ const setValue: SimpleAtomicStateSetter<string> = (value) => {
104
+ if (context.isReadonly()) {
105
+ const reference = untrack(() => context.contextReference());
106
+
107
+ throw new Error(`Cannot write to readonly field: ${reference}`);
108
+ }
109
+
110
+ return baseSetValue(value);
111
+ };
112
+
113
+ return [getValue, setValue];
114
+ };
115
+
116
+ /**
117
+ * Per {@link https://getodk.github.io/xforms-spec/#preload-attributes:~:text=concatenation%20of%20%E2%80%98uuid%3A%E2%80%99%20and%20uuid()}
118
+ */
119
+ const PRELOAD_UID_EXPRESSION = 'concat("uuid:", uuid())';
120
+
121
+ /**
122
+ * @todo This is a temporary one-off, until we support the full range of
123
+ * {@link https://getodk.github.io/xforms-spec/#preload-attributes | preloads}.
124
+ *
125
+ * @todo ALSO, IMPORTANTLY(!): the **call site** for this function is
126
+ * semantically where we would expect to trigger a
127
+ * {@link https://getodk.github.io/xforms-spec/#event:odk-instance-first-load | odk-instance-first-load event},
128
+ * _and compute_ preloads semantically associated with that event.
129
+ */
130
+ const setPreloadUIDValue = (
131
+ context: InstanceValueContext,
132
+ valueState: RelevantValueState,
133
+ options: InstanceValueStateOptions
134
+ ): void => {
135
+ const { preload } = context.definition.bind;
136
+
137
+ if (preload?.type !== 'uid' || !isInstanceFirstLoad(options?.initialValueSource)) {
138
+ return;
139
+ }
140
+
141
+ const preloadUIDValue = context.evaluator.evaluateString(PRELOAD_UID_EXPRESSION, {
142
+ contextNode: context.contextNode,
143
+ });
144
+
145
+ const [, setValue] = valueState;
146
+
147
+ setValue(preloadUIDValue);
148
+ };
149
+
150
+ /**
151
+ * Defines a reactive effect which writes the result of `calculate` bind
152
+ * computations to the provided value setter, on initialization and any
153
+ * subsequent reactive update.
154
+ *
155
+ * @see {@link setPreloadUIDValue} for important details about spec ordering of
156
+ * events and computations.
157
+ */
158
+ const createCalculation = (
159
+ context: InstanceValueContext,
160
+ setRelevantValue: SimpleAtomicStateSetter<string>,
161
+ calculateDefinition: BindComputationExpression<'calculate'>
162
+ ): void => {
163
+ context.scope.runTask(() => {
164
+ const calculate = createComputedExpression(context, calculateDefinition, {
165
+ defaultValue: '',
166
+ });
167
+
168
+ createComputed(() => {
169
+ if (context.isAttached() && context.isRelevant()) {
170
+ const calculated = calculate();
171
+ const value = context.decodeInstanceValue(calculated);
172
+
173
+ setRelevantValue(value);
174
+ }
175
+ });
176
+ });
177
+ };
178
+
179
+ export type InstanceValueState = SimpleAtomicState<string>;
180
+
181
+ /**
182
+ * Provides a consistent interface for value nodes of any type which:
183
+ *
184
+ * - derives initial state from either an existing instance (e.g. for edits) or
185
+ * the node's definition (e.g. initializing a new submission)
186
+ * - decodes current primary instance state into the value node's runtime type
187
+ * - encodes updated runtime values to store updated instance state
188
+ * - initializes reactive computation of `calculate` bind expressions for those
189
+ * nodes defined with one
190
+ * - prevents downstream writes to nodes in a readonly state
191
+ */
192
+ export const createInstanceValueState = (
193
+ context: InstanceValueContext,
194
+ options: InstanceValueStateOptions = {}
195
+ ): InstanceValueState => {
196
+ return context.scope.runTask(() => {
197
+ const initialValue = getInitialValue(context, options);
198
+ const baseValueState = createSignal(initialValue);
199
+ const relevantValueState = createRelevantValueState(context, baseValueState);
200
+
201
+ /**
202
+ * @see {@link setPreloadUIDValue} for important details about spec ordering of events and computations.
203
+ */
204
+ setPreloadUIDValue(context, relevantValueState, options);
205
+
206
+ const { calculate } = context.definition.bind;
207
+
208
+ if (calculate != null) {
209
+ const [, setValue] = relevantValueState;
210
+
211
+ createCalculation(context, setValue, calculate);
212
+ }
213
+
214
+ return guardDownstreamReadonlyWrites(context, relevantValueState);
215
+ });
216
+ };