@getodk/xforms-engine 0.3.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (429) hide show
  1. package/dist/client/BaseNode.d.ts +15 -5
  2. package/dist/client/BaseValueNode.d.ts +32 -0
  3. package/dist/client/EngineConfig.d.ts +49 -49
  4. package/dist/client/GroupNode.d.ts +2 -3
  5. package/dist/client/InputNode.d.ts +53 -0
  6. package/dist/client/ModelValueNode.d.ts +13 -9
  7. package/dist/client/NodeAppearances.d.ts +1 -2
  8. package/dist/client/NoteNode.d.ts +3 -4
  9. package/dist/client/RootNode.d.ts +36 -10
  10. package/dist/client/SelectNode.d.ts +4 -5
  11. package/dist/client/SubtreeNode.d.ts +1 -2
  12. package/dist/client/TextRange.d.ts +3 -4
  13. package/dist/client/TriggerNode.d.ts +25 -0
  14. package/dist/client/ValueType.d.ts +3 -0
  15. package/dist/client/constants.d.ts +50 -1
  16. package/dist/client/hierarchy.d.ts +9 -5
  17. package/dist/client/identity.d.ts +14 -0
  18. package/dist/client/index.d.ts +0 -1
  19. package/dist/client/node-types.d.ts +3 -1
  20. package/dist/client/repeat/BaseRepeatRangeNode.d.ts +1 -2
  21. package/dist/client/repeat/RepeatInstanceNode.d.ts +2 -3
  22. package/dist/client/repeat/RepeatRangeControlledNode.d.ts +1 -2
  23. package/dist/client/repeat/RepeatRangeUncontrolledNode.d.ts +1 -2
  24. package/dist/client/resources.d.ts +93 -0
  25. package/dist/client/submission/SubmissionData.d.ts +7 -0
  26. package/dist/client/submission/SubmissionDefinition.d.ts +14 -0
  27. package/dist/client/submission/SubmissionInstanceFile.d.ts +6 -0
  28. package/dist/client/submission/SubmissionOptions.d.ts +23 -0
  29. package/dist/client/submission/SubmissionResult.d.ts +91 -0
  30. package/dist/client/submission/SubmissionState.d.ts +12 -0
  31. package/dist/client/unsupported/RangeNode.d.ts +9 -0
  32. package/dist/client/unsupported/RankNode.d.ts +9 -0
  33. package/dist/client/unsupported/UnsupportedControlNode.d.ts +32 -0
  34. package/dist/client/unsupported/UploadNode.d.ts +9 -0
  35. package/dist/client/validation.d.ts +2 -3
  36. package/dist/error/ErrorProductionDesignPendingError.d.ts +7 -0
  37. package/dist/error/ValueTypeInvariantError.d.ts +17 -0
  38. package/dist/error/XPathFunctionalityError.d.ts +14 -0
  39. package/dist/error/XPathFunctionalityNotSupportedError.d.ts +7 -0
  40. package/dist/error/XPathFunctionalityPendingError.d.ts +7 -0
  41. package/dist/index.d.ts +16 -4
  42. package/dist/index.js +8559 -4700
  43. package/dist/index.js.map +1 -1
  44. package/dist/instance/Group.d.ts +9 -5
  45. package/dist/instance/InputControl.d.ts +36 -0
  46. package/dist/instance/ModelValue.d.ts +16 -27
  47. package/dist/instance/Note.d.ts +11 -5
  48. package/dist/instance/PrimaryInstance.d.ts +84 -0
  49. package/dist/instance/Root.d.ts +31 -28
  50. package/dist/instance/SelectField.d.ts +13 -6
  51. package/dist/instance/Subtree.d.ts +10 -6
  52. package/dist/instance/TriggerControl.d.ts +47 -0
  53. package/dist/instance/abstract/DescendantNode.d.ts +33 -26
  54. package/dist/instance/abstract/InstanceNode.d.ts +50 -31
  55. package/dist/instance/abstract/UnsupportedControl.d.ts +53 -0
  56. package/dist/instance/abstract/ValueNode.d.ts +48 -0
  57. package/dist/instance/children.d.ts +0 -1
  58. package/dist/instance/hierarchy.d.ts +13 -8
  59. package/dist/instance/identity.d.ts +2 -7
  60. package/dist/instance/index.d.ts +0 -1
  61. package/dist/instance/internal-api/EvaluationContext.d.ts +53 -13
  62. package/dist/instance/internal-api/InstanceConfig.d.ts +8 -3
  63. package/dist/instance/internal-api/InstanceValueContext.d.ts +20 -0
  64. package/dist/instance/internal-api/PrimaryInstanceDocument.d.ts +36 -0
  65. package/dist/instance/internal-api/TranslationContext.d.ts +3 -3
  66. package/dist/instance/internal-api/ValidationContext.d.ts +12 -6
  67. package/dist/instance/internal-api/ValueContext.d.ts +5 -5
  68. package/dist/instance/internal-api/submission/ClientReactiveSubmittableInstance.d.ts +14 -0
  69. package/dist/instance/internal-api/submission/ClientReactiveSubmittableLeafNode.d.ts +31 -0
  70. package/dist/instance/internal-api/submission/ClientReactiveSubmittableParentNode.d.ts +18 -0
  71. package/dist/instance/internal-api/submission/ClientReactiveSubmittableValueNode.d.ts +17 -0
  72. package/dist/instance/repeat/BaseRepeatRange.d.ts +40 -85
  73. package/dist/instance/repeat/RepeatInstance.d.ts +11 -30
  74. package/dist/instance/repeat/RepeatRangeControlled.d.ts +3 -4
  75. package/dist/instance/repeat/RepeatRangeUncontrolled.d.ts +3 -4
  76. package/dist/instance/resource.d.ts +1 -2
  77. package/dist/instance/text/TextChunk.d.ts +0 -1
  78. package/dist/instance/text/TextRange.d.ts +1 -2
  79. package/dist/instance/unsupported/RangeControl.d.ts +6 -0
  80. package/dist/instance/unsupported/RankControl.d.ts +6 -0
  81. package/dist/instance/unsupported/UploadControl.d.ts +6 -0
  82. package/dist/integration/xpath/EngineXPathEvaluator.d.ts +14 -0
  83. package/dist/integration/xpath/adapter/XFormsXPathNode.d.ts +71 -0
  84. package/dist/integration/xpath/adapter/engineDOMAdapter.d.ts +5 -0
  85. package/dist/integration/xpath/adapter/kind.d.ts +32 -0
  86. package/dist/integration/xpath/adapter/names.d.ts +16 -0
  87. package/dist/integration/xpath/adapter/traversal.d.ts +25 -0
  88. package/dist/integration/xpath/adapter/values.d.ts +2 -0
  89. package/dist/integration/xpath/static-dom/StaticAttribute.d.ts +19 -0
  90. package/dist/integration/xpath/static-dom/StaticDocument.d.ts +16 -0
  91. package/dist/integration/xpath/static-dom/StaticElement.d.ts +40 -0
  92. package/dist/integration/xpath/static-dom/StaticNamedNode.d.ts +17 -0
  93. package/dist/integration/xpath/static-dom/StaticNode.d.ts +33 -0
  94. package/dist/integration/xpath/static-dom/StaticText.d.ts +16 -0
  95. package/dist/lib/TokenListParser.d.ts +3 -3
  96. package/dist/lib/client-reactivity/submission/createInstanceSubmissionState.d.ts +3 -0
  97. package/dist/lib/client-reactivity/submission/createLeafNodeSubmissionState.d.ts +3 -0
  98. package/dist/lib/client-reactivity/submission/createNodeRangeSubmissionState.d.ts +4 -0
  99. package/dist/lib/client-reactivity/submission/createParentNodeSubmissionState.d.ts +4 -0
  100. package/dist/lib/client-reactivity/submission/createValueNodeSubmissionState.d.ts +3 -0
  101. package/dist/lib/client-reactivity/submission/prepareSubmission.d.ts +8 -0
  102. package/dist/lib/codecs/DecimalValueCodec.d.ts +6 -0
  103. package/dist/lib/codecs/IntValueCodec.d.ts +6 -0
  104. package/dist/lib/codecs/StringValueCodec.d.ts +4 -0
  105. package/dist/lib/codecs/ValueCodec.d.ts +30 -0
  106. package/dist/lib/codecs/ValueTypePlaceholderCodec.d.ts +12 -0
  107. package/dist/lib/codecs/getSharedValueCodec.d.ts +47 -0
  108. package/dist/lib/dom/query.d.ts +4 -2
  109. package/dist/lib/reactivity/createChildrenState.d.ts +7 -6
  110. package/dist/lib/reactivity/createComputedExpression.d.ts +19 -7
  111. package/dist/lib/reactivity/createInstanceValueState.d.ts +40 -0
  112. package/dist/lib/reactivity/createNoteReadonlyThunk.d.ts +2 -3
  113. package/dist/lib/reactivity/createSelectItems.d.ts +0 -1
  114. package/dist/lib/reactivity/createTranslationState.d.ts +19 -0
  115. package/dist/lib/reactivity/createValueState.d.ts +6 -11
  116. package/dist/lib/reactivity/materializeCurrentStateChildren.d.ts +4 -5
  117. package/dist/lib/reactivity/node-state/createClientState.d.ts +0 -1
  118. package/dist/lib/reactivity/node-state/createCurrentState.d.ts +0 -1
  119. package/dist/lib/reactivity/node-state/createEngineState.d.ts +0 -1
  120. package/dist/lib/reactivity/node-state/createSharedNodeState.d.ts +0 -1
  121. package/dist/lib/reactivity/node-state/createSpecifiedPropertyDescriptor.d.ts +0 -1
  122. package/dist/lib/reactivity/node-state/createSpecifiedState.d.ts +0 -1
  123. package/dist/lib/reactivity/node-state/representations.d.ts +0 -1
  124. package/dist/lib/reactivity/scope.d.ts +0 -1
  125. package/dist/lib/reactivity/text/createFieldHint.d.ts +1 -2
  126. package/dist/lib/reactivity/text/createNodeLabel.d.ts +1 -2
  127. package/dist/lib/reactivity/text/createNoteText.d.ts +1 -2
  128. package/dist/lib/reactivity/text/createTextRange.d.ts +0 -1
  129. package/dist/lib/reactivity/types.d.ts +0 -1
  130. package/dist/lib/reactivity/validation/createAggregatedViolations.d.ts +0 -1
  131. package/dist/lib/reactivity/validation/createValidation.d.ts +0 -1
  132. package/dist/lib/xml-serialization.d.ts +41 -0
  133. package/dist/parse/XFormDOM.d.ts +42 -0
  134. package/dist/{XFormDefinition.d.ts → parse/XFormDefinition.d.ts} +3 -5
  135. package/dist/parse/attachments/FormAttachmentResource.d.ts +27 -0
  136. package/dist/{body → parse/body}/BodyDefinition.d.ts +16 -11
  137. package/dist/{body → parse/body}/BodyElementDefinition.d.ts +7 -7
  138. package/dist/{body → parse/body}/RepeatElementDefinition.d.ts +3 -4
  139. package/dist/{body → parse/body}/UnsupportedBodyElementDefinition.d.ts +0 -1
  140. package/dist/parse/body/appearance/inputAppearanceParser.d.ts +3 -0
  141. package/dist/{body → parse/body}/appearance/selectAppearanceParser.d.ts +1 -2
  142. package/dist/{body → parse/body}/appearance/structureElementAppearanceParser.d.ts +1 -2
  143. package/dist/parse/body/appearance/unknownAppearanceParser.d.ts +3 -0
  144. package/dist/{body → parse/body}/control/ControlDefinition.d.ts +3 -4
  145. package/dist/{body/control/InputDefinition.d.ts → parse/body/control/InputControlDefinition.d.ts} +2 -3
  146. package/dist/parse/body/control/RangeControlDefinition.d.ts +11 -0
  147. package/dist/parse/body/control/RankControlDefinition.d.ts +11 -0
  148. package/dist/parse/body/control/TriggerControlDefinition.d.ts +11 -0
  149. package/dist/parse/body/control/UploadControlDefinition.d.ts +11 -0
  150. package/dist/{body → parse/body}/control/select/ItemDefinition.d.ts +2 -3
  151. package/dist/{body → parse/body}/control/select/ItemsetDefinition.d.ts +4 -5
  152. package/dist/{body → parse/body}/control/select/ItemsetNodesetContext.d.ts +1 -4
  153. package/dist/{body → parse/body}/control/select/SelectDefinition.d.ts +3 -12
  154. package/dist/{body → parse/body}/group/BaseGroupDefinition.d.ts +3 -5
  155. package/dist/{body → parse/body}/group/LogicalGroupDefinition.d.ts +0 -1
  156. package/dist/{body → parse/body}/group/PresentationGroupDefinition.d.ts +1 -2
  157. package/dist/{body → parse/body}/group/StructuralGroupDefinition.d.ts +0 -1
  158. package/dist/{model/BindComputation.d.ts → parse/expression/BindComputationExpression.d.ts} +5 -6
  159. package/dist/{body/control/select → parse/expression}/ItemsetNodesetExpression.d.ts +2 -3
  160. package/dist/{body/control/select → parse/expression}/ItemsetValueExpression.d.ts +2 -3
  161. package/dist/parse/expression/RepeatCountControlExpression.d.ts +2 -3
  162. package/dist/parse/expression/TextLiteralExpression.d.ts +9 -0
  163. package/dist/parse/expression/TextOutputExpression.d.ts +7 -0
  164. package/dist/parse/expression/TextReferenceExpression.d.ts +7 -0
  165. package/dist/parse/expression/TextTranslationExpression.d.ts +8 -0
  166. package/dist/parse/expression/abstract/DependencyContext.d.ts +7 -0
  167. package/dist/{expression → parse/expression/abstract}/DependentExpression.d.ts +4 -6
  168. package/dist/parse/expression/abstract/TextChunkExpression.d.ts +17 -0
  169. package/dist/parse/model/BindDefinition.d.ts +38 -0
  170. package/dist/parse/model/BindTypeDefinition.d.ts +20 -0
  171. package/dist/{model → parse/model}/DescendentNodeDefinition.d.ts +0 -2
  172. package/dist/parse/model/FormSubmissionDefinition.d.ts +8 -0
  173. package/dist/parse/model/ItextTranslation/ItextTranslationDefinition.d.ts +4 -0
  174. package/dist/parse/model/ItextTranslation/ItextTranslationRootDefinition.d.ts +8 -0
  175. package/dist/parse/model/ItextTranslation/ItextTranslationsDefinition.d.ts +8 -0
  176. package/dist/{model → parse/model}/LeafNodeDefinition.d.ts +4 -3
  177. package/dist/{model → parse/model}/ModelBindMap.d.ts +1 -2
  178. package/dist/{model → parse/model}/ModelDefinition.d.ts +3 -2
  179. package/dist/{model → parse/model}/NodeDefinition.d.ts +0 -2
  180. package/dist/parse/{NoteNodeDefinition.d.ts → model/NoteNodeDefinition.d.ts} +12 -13
  181. package/dist/{model → parse/model}/RepeatInstanceDefinition.d.ts +1 -2
  182. package/dist/{model → parse/model}/RepeatRangeDefinition.d.ts +2 -3
  183. package/dist/{model → parse/model}/RepeatTemplateDefinition.d.ts +2 -3
  184. package/dist/{model → parse/model}/RootDefinition.d.ts +5 -5
  185. package/dist/parse/model/SecondaryInstance/SecondaryInstanceDefinition.d.ts +4 -0
  186. package/dist/parse/model/SecondaryInstance/SecondaryInstanceRootDefinition.d.ts +7 -0
  187. package/dist/parse/model/SecondaryInstance/SecondaryInstancesDefinition.d.ts +13 -0
  188. package/dist/parse/model/SecondaryInstance/sources/BlankSecondaryInstanceSource.d.ts +14 -0
  189. package/dist/parse/model/SecondaryInstance/sources/CSVExternalSecondaryInstance.d.ts +22 -0
  190. package/dist/parse/model/SecondaryInstance/sources/ExternalSecondaryInstanceResource.d.ts +23 -0
  191. package/dist/parse/model/SecondaryInstance/sources/ExternalSecondaryInstanceSource.d.ts +9 -0
  192. package/dist/parse/model/SecondaryInstance/sources/GeoJSONExternalSecondaryInstance.d.ts +5 -0
  193. package/dist/parse/model/SecondaryInstance/sources/InternalSecondaryInstanceSource.d.ts +7 -0
  194. package/dist/parse/model/SecondaryInstance/sources/SecondaryInstanceSource.d.ts +13 -0
  195. package/dist/parse/model/SecondaryInstance/sources/XMLExternalSecondaryInstanceSource.d.ts +12 -0
  196. package/dist/{model → parse/model}/SubtreeDefinition.d.ts +1 -2
  197. package/dist/parse/shared/parseStaticDocumentFromDOMSubtree.d.ts +24 -0
  198. package/dist/parse/text/HintDefinition.d.ts +2 -3
  199. package/dist/parse/text/ItemLabelDefinition.d.ts +2 -3
  200. package/dist/parse/text/ItemsetLabelDefinition.d.ts +3 -4
  201. package/dist/parse/text/LabelDefinition.d.ts +5 -6
  202. package/dist/parse/text/MessageDefinition.d.ts +4 -5
  203. package/dist/parse/text/abstract/TextElementDefinition.d.ts +8 -9
  204. package/dist/parse/text/abstract/TextRangeDefinition.d.ts +4 -7
  205. package/dist/parse/xpath/path-resolution.d.ts +0 -1
  206. package/dist/parse/xpath/predicate-analysis.d.ts +0 -1
  207. package/dist/parse/xpath/reference-parsing.d.ts +0 -1
  208. package/dist/parse/xpath/semantic-analysis.d.ts +5 -1
  209. package/dist/parse/xpath/syntax-traversal.d.ts +0 -1
  210. package/dist/solid.js +8398 -4543
  211. package/dist/solid.js.map +1 -1
  212. package/package.json +14 -12
  213. package/src/client/BaseNode.ts +17 -7
  214. package/src/client/BaseValueNode.ts +35 -0
  215. package/src/client/EngineConfig.ts +52 -51
  216. package/src/client/GroupNode.ts +2 -2
  217. package/src/client/InputNode.ts +77 -0
  218. package/src/client/ModelValueNode.ts +31 -8
  219. package/src/client/NodeAppearances.ts +1 -1
  220. package/src/client/NoteNode.ts +3 -3
  221. package/src/client/RootNode.ts +39 -9
  222. package/src/client/SelectNode.ts +5 -5
  223. package/src/client/SubtreeNode.ts +1 -1
  224. package/src/client/TextRange.ts +4 -5
  225. package/src/client/TriggerNode.ts +29 -0
  226. package/src/client/ValueType.ts +4 -0
  227. package/src/client/constants.ts +67 -0
  228. package/src/client/hierarchy.ts +16 -4
  229. package/src/client/identity.ts +16 -0
  230. package/src/client/node-types.ts +19 -5
  231. package/src/client/repeat/BaseRepeatRangeNode.ts +1 -1
  232. package/src/client/repeat/RepeatInstanceNode.ts +2 -2
  233. package/src/client/repeat/RepeatRangeControlledNode.ts +1 -1
  234. package/src/client/repeat/RepeatRangeUncontrolledNode.ts +1 -1
  235. package/src/client/resources.ts +118 -0
  236. package/src/client/submission/SubmissionData.ts +12 -0
  237. package/src/client/submission/SubmissionDefinition.ts +16 -0
  238. package/src/client/submission/SubmissionInstanceFile.ts +9 -0
  239. package/src/client/submission/SubmissionOptions.ts +28 -0
  240. package/src/client/submission/SubmissionResult.ts +124 -0
  241. package/src/client/submission/SubmissionState.ts +14 -0
  242. package/src/client/unsupported/RangeNode.ts +14 -0
  243. package/src/client/unsupported/RankNode.ts +14 -0
  244. package/src/client/unsupported/UnsupportedControlNode.ts +40 -0
  245. package/src/client/unsupported/UploadNode.ts +14 -0
  246. package/src/client/validation.ts +2 -2
  247. package/src/error/ErrorProductionDesignPendingError.ts +6 -0
  248. package/src/error/ValueTypeInvariantError.ts +22 -0
  249. package/src/error/XPathFunctionalityError.ts +26 -0
  250. package/src/error/XPathFunctionalityNotSupportedError.ts +18 -0
  251. package/src/error/XPathFunctionalityPendingError.ts +18 -0
  252. package/src/index.ts +16 -2
  253. package/src/instance/Group.ts +17 -5
  254. package/src/instance/InputControl.ts +119 -0
  255. package/src/instance/ModelValue.ts +47 -54
  256. package/src/instance/Note.ts +26 -10
  257. package/src/instance/PrimaryInstance.ts +244 -0
  258. package/src/instance/Root.ts +64 -132
  259. package/src/instance/SelectField.ts +62 -25
  260. package/src/instance/Subtree.ts +19 -7
  261. package/src/instance/{StringField.ts → TriggerControl.ts} +61 -30
  262. package/src/instance/abstract/DescendantNode.ts +92 -47
  263. package/src/instance/abstract/InstanceNode.ts +104 -98
  264. package/src/instance/abstract/UnsupportedControl.ts +174 -0
  265. package/src/instance/abstract/ValueNode.ts +127 -0
  266. package/src/instance/children.ts +83 -14
  267. package/src/instance/hierarchy.ts +36 -14
  268. package/src/instance/identity.ts +3 -9
  269. package/src/instance/index.ts +26 -8
  270. package/src/instance/internal-api/EvaluationContext.ts +61 -14
  271. package/src/instance/internal-api/InstanceConfig.ts +9 -2
  272. package/src/instance/internal-api/InstanceValueContext.ts +24 -0
  273. package/src/instance/internal-api/PrimaryInstanceDocument.ts +53 -0
  274. package/src/instance/internal-api/TranslationContext.ts +3 -2
  275. package/src/instance/internal-api/ValidationContext.ts +13 -5
  276. package/src/instance/internal-api/ValueContext.ts +5 -4
  277. package/src/instance/internal-api/submission/ClientReactiveSubmittableInstance.ts +20 -0
  278. package/src/instance/internal-api/submission/ClientReactiveSubmittableLeafNode.ts +42 -0
  279. package/src/instance/internal-api/submission/ClientReactiveSubmittableParentNode.ts +25 -0
  280. package/src/instance/internal-api/submission/ClientReactiveSubmittableValueNode.ts +23 -0
  281. package/src/instance/repeat/BaseRepeatRange.ts +51 -132
  282. package/src/instance/repeat/RepeatInstance.ts +20 -46
  283. package/src/instance/repeat/RepeatRangeControlled.ts +6 -6
  284. package/src/instance/repeat/RepeatRangeUncontrolled.ts +3 -5
  285. package/src/instance/resource.ts +1 -1
  286. package/src/instance/text/TextChunk.ts +1 -1
  287. package/src/instance/unsupported/RangeControl.ts +9 -0
  288. package/src/instance/unsupported/RankControl.ts +9 -0
  289. package/src/instance/unsupported/UploadControl.ts +9 -0
  290. package/src/integration/xpath/EngineXPathEvaluator.ts +22 -0
  291. package/src/integration/xpath/adapter/XFormsXPathNode.ts +126 -0
  292. package/src/integration/xpath/adapter/engineDOMAdapter.ts +57 -0
  293. package/src/integration/xpath/adapter/kind.ts +114 -0
  294. package/src/integration/xpath/adapter/names.ts +99 -0
  295. package/src/integration/xpath/adapter/traversal.ts +228 -0
  296. package/src/integration/xpath/adapter/values.ts +5 -0
  297. package/src/integration/xpath/static-dom/StaticAttribute.ts +33 -0
  298. package/src/integration/xpath/static-dom/StaticDocument.ts +38 -0
  299. package/src/integration/xpath/static-dom/StaticElement.ts +106 -0
  300. package/src/integration/xpath/static-dom/StaticNamedNode.ts +45 -0
  301. package/src/integration/xpath/static-dom/StaticNode.ts +68 -0
  302. package/src/integration/xpath/static-dom/StaticText.ts +28 -0
  303. package/src/lib/TokenListParser.ts +11 -7
  304. package/src/lib/client-reactivity/README.md +0 -0
  305. package/src/lib/client-reactivity/submission/createInstanceSubmissionState.ts +12 -0
  306. package/src/lib/client-reactivity/submission/createLeafNodeSubmissionState.ts +20 -0
  307. package/src/lib/client-reactivity/submission/createNodeRangeSubmissionState.ts +17 -0
  308. package/src/lib/client-reactivity/submission/createParentNodeSubmissionState.ts +22 -0
  309. package/src/lib/client-reactivity/submission/createValueNodeSubmissionState.ts +21 -0
  310. package/src/lib/client-reactivity/submission/prepareSubmission.ts +172 -0
  311. package/src/lib/codecs/DecimalValueCodec.ts +46 -0
  312. package/src/lib/codecs/IntValueCodec.ts +100 -0
  313. package/src/lib/codecs/StringValueCodec.ts +11 -0
  314. package/src/lib/codecs/ValueCodec.ts +106 -0
  315. package/src/lib/codecs/ValueTypePlaceholderCodec.ts +19 -0
  316. package/src/lib/codecs/getSharedValueCodec.ts +77 -0
  317. package/src/lib/dom/query.ts +8 -1
  318. package/src/lib/reactivity/createChildrenState.ts +8 -6
  319. package/src/lib/reactivity/createComputedExpression.ts +59 -36
  320. package/src/lib/reactivity/createInstanceValueState.ts +166 -0
  321. package/src/lib/reactivity/createNoteReadonlyThunk.ts +12 -7
  322. package/src/lib/reactivity/createSelectItems.ts +23 -23
  323. package/src/lib/reactivity/createTranslationState.ts +61 -0
  324. package/src/lib/reactivity/createValueState.ts +64 -122
  325. package/src/lib/reactivity/materializeCurrentStateChildren.ts +7 -7
  326. package/src/lib/reactivity/node-state/createSpecifiedState.ts +1 -1
  327. package/src/lib/reactivity/text/createFieldHint.ts +1 -1
  328. package/src/lib/reactivity/text/createNodeLabel.ts +1 -1
  329. package/src/lib/reactivity/text/createNoteText.ts +1 -1
  330. package/src/lib/reactivity/text/createTextRange.ts +8 -7
  331. package/src/lib/reactivity/validation/createAggregatedViolations.ts +9 -4
  332. package/src/lib/reactivity/validation/createValidation.ts +2 -3
  333. package/src/lib/xml-serialization.ts +96 -0
  334. package/src/{XFormDOM.ts → parse/XFormDOM.ts} +110 -75
  335. package/src/{XFormDefinition.ts → parse/XFormDefinition.ts} +3 -8
  336. package/src/parse/attachments/FormAttachmentResource.ts +40 -0
  337. package/src/{body → parse/body}/BodyDefinition.ts +46 -29
  338. package/src/{body → parse/body}/BodyElementDefinition.ts +12 -6
  339. package/src/{body → parse/body}/RepeatElementDefinition.ts +7 -5
  340. package/src/{body → parse/body}/appearance/inputAppearanceParser.ts +2 -2
  341. package/src/{body → parse/body}/appearance/selectAppearanceParser.ts +1 -1
  342. package/src/{body → parse/body}/appearance/structureElementAppearanceParser.ts +1 -1
  343. package/src/parse/body/appearance/unknownAppearanceParser.ts +5 -0
  344. package/src/{body → parse/body}/control/ControlDefinition.ts +4 -4
  345. package/src/{body/control/InputDefinition.ts → parse/body/control/InputControlDefinition.ts} +3 -5
  346. package/src/parse/body/control/RangeControlDefinition.ts +26 -0
  347. package/src/parse/body/control/RankControlDefinition.ts +27 -0
  348. package/src/parse/body/control/TriggerControlDefinition.ts +26 -0
  349. package/src/parse/body/control/UploadControlDefinition.ts +26 -0
  350. package/src/{body → parse/body}/control/select/ItemDefinition.ts +2 -2
  351. package/src/{body → parse/body}/control/select/ItemsetDefinition.ts +5 -5
  352. package/src/{body → parse/body}/control/select/ItemsetNodesetContext.ts +1 -6
  353. package/src/{body → parse/body}/control/select/SelectDefinition.ts +3 -11
  354. package/src/{body → parse/body}/group/BaseGroupDefinition.ts +11 -22
  355. package/src/{body → parse/body}/group/PresentationGroupDefinition.ts +1 -1
  356. package/src/{model/BindComputation.ts → parse/expression/BindComputationExpression.ts} +8 -8
  357. package/src/{body/control/select → parse/expression}/ItemsetNodesetExpression.ts +2 -2
  358. package/src/{body/control/select → parse/expression}/ItemsetValueExpression.ts +2 -2
  359. package/src/parse/expression/RepeatCountControlExpression.ts +2 -2
  360. package/src/parse/expression/TextLiteralExpression.ts +19 -0
  361. package/src/parse/{text/OutputChunkDefinition.ts → expression/TextOutputExpression.ts} +4 -4
  362. package/src/parse/{text/ReferenceChunkDefinition.ts → expression/TextReferenceExpression.ts} +4 -4
  363. package/src/parse/{text/TranslationChunkDefinition.ts → expression/TextTranslationExpression.ts} +4 -4
  364. package/src/{expression → parse/expression/abstract}/DependencyContext.ts +0 -26
  365. package/src/{expression → parse/expression/abstract}/DependentExpression.ts +5 -16
  366. package/src/parse/expression/abstract/TextChunkExpression.ts +38 -0
  367. package/src/parse/model/BindDefinition.ts +104 -0
  368. package/src/parse/model/BindTypeDefinition.ts +175 -0
  369. package/src/{model → parse/model}/DescendentNodeDefinition.ts +0 -6
  370. package/src/parse/model/FormSubmissionDefinition.ts +44 -0
  371. package/src/parse/model/ItextTranslation/ItextTranslationDefinition.ts +4 -0
  372. package/src/parse/model/ItextTranslation/ItextTranslationRootDefinition.ts +41 -0
  373. package/src/parse/model/ItextTranslation/ItextTranslationsDefinition.ts +31 -0
  374. package/src/{model → parse/model}/LeafNodeDefinition.ts +4 -1
  375. package/src/{model → parse/model}/ModelBindMap.ts +6 -8
  376. package/src/parse/model/ModelDefinition.ts +24 -0
  377. package/src/{model → parse/model}/NodeDefinition.ts +0 -3
  378. package/src/parse/{NoteNodeDefinition.ts → model/NoteNodeDefinition.ts} +12 -12
  379. package/src/{model → parse/model}/RepeatRangeDefinition.ts +1 -1
  380. package/src/{model → parse/model}/RootDefinition.ts +4 -3
  381. package/src/parse/model/SecondaryInstance/SecondaryInstanceDefinition.ts +4 -0
  382. package/src/parse/model/SecondaryInstance/SecondaryInstanceRootDefinition.ts +12 -0
  383. package/src/parse/model/SecondaryInstance/SecondaryInstancesDefinition.ts +102 -0
  384. package/src/parse/model/SecondaryInstance/sources/BlankSecondaryInstanceSource.ts +40 -0
  385. package/src/parse/model/SecondaryInstance/sources/CSVExternalSecondaryInstance.ts +288 -0
  386. package/src/parse/model/SecondaryInstance/sources/ExternalSecondaryInstanceResource.ts +222 -0
  387. package/src/parse/model/SecondaryInstance/sources/ExternalSecondaryInstanceSource.ts +22 -0
  388. package/src/parse/model/SecondaryInstance/sources/GeoJSONExternalSecondaryInstance.ts +414 -0
  389. package/src/parse/model/SecondaryInstance/sources/InternalSecondaryInstanceSource.ts +19 -0
  390. package/src/parse/model/SecondaryInstance/sources/SecondaryInstanceSource.ts +29 -0
  391. package/src/parse/model/SecondaryInstance/sources/XMLExternalSecondaryInstanceSource.ts +32 -0
  392. package/src/parse/shared/parseStaticDocumentFromDOMSubtree.ts +149 -0
  393. package/src/parse/text/HintDefinition.ts +2 -2
  394. package/src/parse/text/ItemLabelDefinition.ts +2 -2
  395. package/src/parse/text/ItemsetLabelDefinition.ts +7 -7
  396. package/src/parse/text/LabelDefinition.ts +5 -5
  397. package/src/parse/text/MessageDefinition.ts +7 -7
  398. package/src/parse/text/abstract/TextElementDefinition.ts +14 -14
  399. package/src/parse/text/abstract/TextRangeDefinition.ts +4 -10
  400. package/src/parse/xpath/semantic-analysis.ts +29 -0
  401. package/dist/XFormDOM.d.ts +0 -32
  402. package/dist/XFormDataType.d.ts +0 -27
  403. package/dist/body/appearance/inputAppearanceParser.d.ts +0 -4
  404. package/dist/client/StringNode.d.ts +0 -47
  405. package/dist/expression/DependencyContext.d.ts +0 -13
  406. package/dist/instance/StringField.d.ts +0 -45
  407. package/dist/instance/internal-api/SubscribableDependency.d.ts +0 -60
  408. package/dist/model/BindDefinition.d.ts +0 -34
  409. package/dist/parse/text/OutputChunkDefinition.d.ts +0 -8
  410. package/dist/parse/text/ReferenceChunkDefinition.d.ts +0 -8
  411. package/dist/parse/text/StaticTextChunkDefinition.d.ts +0 -10
  412. package/dist/parse/text/TranslationChunkDefinition.d.ts +0 -9
  413. package/dist/parse/text/abstract/TextChunkDefinition.d.ts +0 -18
  414. package/src/XFormDataType.ts +0 -64
  415. package/src/client/StringNode.ts +0 -52
  416. package/src/instance/internal-api/SubscribableDependency.ts +0 -61
  417. package/src/model/BindDefinition.ts +0 -106
  418. package/src/model/ModelDefinition.ts +0 -19
  419. package/src/parse/TODO.md +0 -3
  420. package/src/parse/text/StaticTextChunkDefinition.ts +0 -19
  421. package/src/parse/text/abstract/TextChunkDefinition.ts +0 -38
  422. /package/dist/{model → parse/model}/BindElement.d.ts +0 -0
  423. /package/src/{body → parse/body}/UnsupportedBodyElementDefinition.ts +0 -0
  424. /package/src/{body → parse/body}/group/LogicalGroupDefinition.ts +0 -0
  425. /package/src/{body → parse/body}/group/StructuralGroupDefinition.ts +0 -0
  426. /package/src/{model → parse/model}/BindElement.ts +0 -0
  427. /package/src/{model → parse/model}/RepeatInstanceDefinition.ts +0 -0
  428. /package/src/{model → parse/model}/RepeatTemplateDefinition.ts +0 -0
  429. /package/src/{model → parse/model}/SubtreeDefinition.ts +0 -0
@@ -1,17 +1,17 @@
1
+ import type { NoteNode } from '../../client/NoteNode.ts';
1
2
  import type { AnyBodyElementDefinition } from '../body/BodyDefinition.ts';
2
- import type { InputDefinition } from '../body/control/InputDefinition.ts';
3
- import type { NoteNode } from '../client/NoteNode.ts';
4
- import type { ConstantTruthyDependentExpression } from '../expression/DependentExpression.ts';
5
- import { BindComputation } from '../model/BindComputation.ts';
6
- import type { BindDefinition } from '../model/BindDefinition.ts';
7
- import { LeafNodeDefinition } from '../model/LeafNodeDefinition.ts';
8
- import type { ParentNodeDefinition } from '../model/NodeDefinition.ts';
9
- import type { HintDefinition } from './text/HintDefinition.ts';
10
- import type { LabelDefinition } from './text/LabelDefinition.ts';
3
+ import type { InputControlDefinition } from '../body/control/InputControlDefinition.ts';
4
+ import { BindComputationExpression } from '../expression/BindComputationExpression.ts';
5
+ import type { ConstantTruthyDependentExpression } from '../expression/abstract/DependentExpression.ts';
6
+ import type { HintDefinition } from '../text/HintDefinition.ts';
7
+ import type { LabelDefinition } from '../text/LabelDefinition.ts';
8
+ import type { BindDefinition } from './BindDefinition.ts';
9
+ import { LeafNodeDefinition } from './LeafNodeDefinition.ts';
10
+ import type { ParentNodeDefinition } from './NodeDefinition.ts';
11
11
 
12
12
  // prettier-ignore
13
13
  export type NoteReadonlyDefinition =
14
- & BindComputation<'readonly'>
14
+ & BindComputationExpression<'readonly'>
15
15
  & ConstantTruthyDependentExpression;
16
16
 
17
17
  export interface NoteBindDefinition extends BindDefinition {
@@ -31,7 +31,7 @@ export type NoteTextDefinition =
31
31
  /**
32
32
  * @package This class is used internally, both in static types and at runtime,
33
33
  * to guard and guide the distinction between instance state nodes for 'note'
34
- * and 'string' node types. It is intentionally package-private! The less
34
+ * and 'input' node types. It is intentionally package-private! The less
35
35
  * specific {@link NoteNode.definition} type, if it has any client value at all,
36
36
  * should be more than sufficient. Clients are otherwise expected to use other
37
37
  * aspects of the node's interface (such as its {@link NoteNode.nodeType} and
@@ -61,7 +61,7 @@ export class NoteNodeDefinition extends LeafNodeDefinition {
61
61
  constructor(
62
62
  parent: ParentNodeDefinition,
63
63
  override readonly bind: NoteBindDefinition,
64
- override readonly bodyElement: InputDefinition,
64
+ override readonly bodyElement: InputControlDefinition,
65
65
  readonly noteTextDefinition: NoteTextDefinition,
66
66
  node: Element
67
67
  ) {
@@ -1,5 +1,5 @@
1
1
  import type { RepeatElementDefinition } from '../body/RepeatElementDefinition.ts';
2
- import { RepeatCountControlExpression } from '../parse/expression/RepeatCountControlExpression.ts';
2
+ import { RepeatCountControlExpression } from '../expression/RepeatCountControlExpression.ts';
3
3
  import type { BindDefinition } from './BindDefinition.ts';
4
4
  import { DescendentNodeDefinition } from './DescendentNodeDefinition.ts';
5
5
  import type { NodeDefinition, ParentNodeDefinition } from './NodeDefinition.ts';
@@ -1,7 +1,7 @@
1
- import type { XFormDefinition } from '../XFormDefinition.ts';
2
1
  import type { BodyClassList } from '../body/BodyDefinition.ts';
3
- import { NoteNodeDefinition } from '../parse/NoteNodeDefinition.ts';
2
+ import type { XFormDefinition } from '../XFormDefinition.ts';
4
3
  import type { BindDefinition } from './BindDefinition.ts';
4
+ import type { FormSubmissionDefinition } from './FormSubmissionDefinition.ts';
5
5
  import { LeafNodeDefinition } from './LeafNodeDefinition.ts';
6
6
  import type { ModelDefinition } from './ModelDefinition.ts';
7
7
  import type {
@@ -9,6 +9,7 @@ import type {
9
9
  NodeDefinition,
10
10
  ParentNodeDefinition,
11
11
  } from './NodeDefinition.ts';
12
+ import { NoteNodeDefinition } from './NoteNodeDefinition.ts';
12
13
  import { RepeatRangeDefinition } from './RepeatRangeDefinition.ts';
13
14
  import { SubtreeDefinition } from './SubtreeDefinition.ts';
14
15
 
@@ -26,11 +27,11 @@ export class RootDefinition implements NodeDefinition<'root'> {
26
27
  readonly defaultValue = null;
27
28
 
28
29
  readonly isTranslated = false;
29
- readonly dependencyExpressions: ReadonlySet<string> = new Set<string>();
30
30
 
31
31
  constructor(
32
32
  protected readonly form: XFormDefinition,
33
33
  protected readonly model: ModelDefinition,
34
+ readonly submission: FormSubmissionDefinition,
34
35
  readonly classes: BodyClassList
35
36
  ) {
36
37
  // TODO: theoretically the pertinent step in the bind's `nodeset` *could* be
@@ -0,0 +1,4 @@
1
+ import { StaticDocument } from '../../../integration/xpath/static-dom/StaticDocument.ts';
2
+ import { SecondaryInstanceRootDefinition } from './SecondaryInstanceRootDefinition.ts';
3
+
4
+ export class SecondaryInstanceDefinition extends StaticDocument<SecondaryInstanceRootDefinition> {}
@@ -0,0 +1,12 @@
1
+ import type { XFormsSecondaryInstanceElement } from '@getodk/xpath';
2
+ import { XFORMS_KNOWN_ATTRIBUTE, XFORMS_LOCAL_NAME } from '@getodk/xpath';
3
+ import { StaticElement } from '../../../integration/xpath/static-dom/StaticElement.ts';
4
+ import type { SecondaryInstanceDefinition } from './SecondaryInstanceDefinition.ts';
5
+
6
+ export class SecondaryInstanceRootDefinition
7
+ extends StaticElement<SecondaryInstanceDefinition>
8
+ implements XFormsSecondaryInstanceElement<StaticElement>
9
+ {
10
+ override readonly [XFORMS_LOCAL_NAME] = 'instance';
11
+ override readonly [XFORMS_KNOWN_ATTRIBUTE] = 'id';
12
+ }
@@ -0,0 +1,102 @@
1
+ import { JRResourceURL } from '@getodk/common/jr-resources/JRResourceURL.ts';
2
+ import { UnreachableError } from '@getodk/common/lib/error/UnreachableError.ts';
3
+ import type { XFormsSecondaryInstanceMap } from '@getodk/xpath';
4
+ import { ErrorProductionDesignPendingError } from '../../../error/ErrorProductionDesignPendingError.ts';
5
+ import type { EngineXPathNode } from '../../../integration/xpath/adapter/kind.ts';
6
+ import type { XFormDOM } from '../../XFormDOM.ts';
7
+ import { SecondaryInstanceRootDefinition } from './SecondaryInstanceRootDefinition.ts';
8
+ import { BlankSecondaryInstanceSource } from './sources/BlankSecondaryInstanceSource.ts';
9
+ import { CSVExternalSecondaryInstanceSource } from './sources/CSVExternalSecondaryInstance.ts';
10
+ import type { ExternalSecondaryInstanceResourceLoadOptions } from './sources/ExternalSecondaryInstanceResource.ts';
11
+ import { ExternalSecondaryInstanceResource } from './sources/ExternalSecondaryInstanceResource.ts';
12
+ import { GeoJSONExternalSecondaryInstanceSource } from './sources/GeoJSONExternalSecondaryInstance.ts';
13
+ import { InternalSecondaryInstanceSource } from './sources/InternalSecondaryInstanceSource.ts';
14
+ import type { SecondaryInstanceSource } from './sources/SecondaryInstanceSource.ts';
15
+ import { XMLExternalSecondaryInstanceSource } from './sources/XMLExternalSecondaryInstanceSource.ts';
16
+
17
+ export class SecondaryInstancesDefinition
18
+ extends Map<string, SecondaryInstanceRootDefinition>
19
+ implements XFormsSecondaryInstanceMap<EngineXPathNode>
20
+ {
21
+ /**
22
+ * @package Only to be used for testing
23
+ */
24
+ static loadSync(xformDOM: XFormDOM): SecondaryInstancesDefinition {
25
+ const { secondaryInstanceElements } = xformDOM;
26
+ const sources = secondaryInstanceElements.map((domElement) => {
27
+ const instanceId = domElement.getAttribute('id');
28
+ const src = domElement.getAttribute('src');
29
+
30
+ if (src != null) {
31
+ throw new ErrorProductionDesignPendingError(
32
+ `Unexpected external secondary instance src attribute: ${src}`
33
+ );
34
+ }
35
+
36
+ return new InternalSecondaryInstanceSource(instanceId, src, domElement);
37
+ });
38
+
39
+ return new this(sources);
40
+ }
41
+
42
+ static async load(
43
+ xformDOM: XFormDOM,
44
+ options: ExternalSecondaryInstanceResourceLoadOptions
45
+ ): Promise<SecondaryInstancesDefinition> {
46
+ const { secondaryInstanceElements } = xformDOM;
47
+
48
+ const sources = await Promise.all(
49
+ secondaryInstanceElements.map(async (domElement) => {
50
+ const instanceId = domElement.getAttribute('id');
51
+ const src = domElement.getAttribute('src');
52
+
53
+ if (src == null) {
54
+ return new InternalSecondaryInstanceSource(instanceId, src, domElement);
55
+ }
56
+
57
+ if (!JRResourceURL.isJRResourceReference(src)) {
58
+ throw new ErrorProductionDesignPendingError(
59
+ `Unexpected external secondary instance src attribute: ${src}`
60
+ );
61
+ }
62
+
63
+ const resourceURL = JRResourceURL.from(src);
64
+ const resource = await ExternalSecondaryInstanceResource.load(
65
+ instanceId,
66
+ resourceURL,
67
+ options
68
+ );
69
+
70
+ if (resource.isBlank) {
71
+ return new BlankSecondaryInstanceSource(instanceId, resourceURL, domElement);
72
+ }
73
+
74
+ switch (resource.format) {
75
+ case 'csv':
76
+ return new CSVExternalSecondaryInstanceSource(domElement, resource);
77
+
78
+ case 'geojson':
79
+ return new GeoJSONExternalSecondaryInstanceSource(domElement, resource);
80
+
81
+ case 'xml':
82
+ return new XMLExternalSecondaryInstanceSource(domElement, resource);
83
+
84
+ default:
85
+ throw new UnreachableError(resource);
86
+ }
87
+ })
88
+ );
89
+
90
+ return new this(sources);
91
+ }
92
+
93
+ private constructor(sources: readonly SecondaryInstanceSource[]) {
94
+ super(
95
+ sources.map((source) => {
96
+ const { root } = source.parseDefinition();
97
+
98
+ return [root.getAttributeValue('id'), root];
99
+ })
100
+ );
101
+ }
102
+ }
@@ -0,0 +1,40 @@
1
+ import { XFORMS_NAMESPACE_URI } from '@getodk/common/constants/xmlns.ts';
2
+ import type { JRResourceURL } from '@getodk/common/jr-resources/JRResourceURL.ts';
3
+ import type { StaticNode } from '../../../../integration/xpath/static-dom/StaticNode.ts';
4
+ import { parseStaticDocumentFromDOMSubtree } from '../../../shared/parseStaticDocumentFromDOMSubtree.ts';
5
+ import type { DOMSecondaryInstanceElement } from '../../../XFormDOM.ts';
6
+ import { SecondaryInstanceDefinition } from '../SecondaryInstanceDefinition.ts';
7
+ import { SecondaryInstanceRootDefinition } from '../SecondaryInstanceRootDefinition.ts';
8
+ import { SecondaryInstanceSource } from './SecondaryInstanceSource.ts';
9
+
10
+ export class BlankSecondaryInstanceSource extends SecondaryInstanceSource<'blank'> {
11
+ constructor(
12
+ instanceId: string,
13
+ resourceURL: JRResourceURL,
14
+ domElement: DOMSecondaryInstanceElement
15
+ ) {
16
+ super('blank', instanceId, resourceURL, domElement);
17
+ }
18
+
19
+ /**
20
+ * @todo there is really no sense in using the DOM for this, other than it was
21
+ * quicker/more ergonomic than constructing the requisite {@link StaticNode}
22
+ * structures directly. Pretty good sign those constructor signatures could
23
+ * use some TLC!
24
+ */
25
+ parseDefinition(): SecondaryInstanceDefinition {
26
+ const xmlDocument = this.domElement.ownerDocument.implementation.createDocument(
27
+ XFORMS_NAMESPACE_URI,
28
+ 'instance'
29
+ );
30
+ const instanceElement = xmlDocument.documentElement;
31
+
32
+ instanceElement.setAttribute('id', this.instanceId);
33
+
34
+ return parseStaticDocumentFromDOMSubtree(
35
+ SecondaryInstanceDefinition,
36
+ SecondaryInstanceRootDefinition,
37
+ instanceElement
38
+ );
39
+ }
40
+ }
@@ -0,0 +1,288 @@
1
+ import { XFORMS_NAMESPACE_URI } from '@getodk/common/constants/xmlns.ts';
2
+ import type { JRResourceURL } from '@getodk/common/jr-resources/JRResourceURL.ts';
3
+ import * as papa from 'papaparse';
4
+ import { ErrorProductionDesignPendingError } from '../../../../error/ErrorProductionDesignPendingError.ts';
5
+ import { StaticAttribute } from '../../../../integration/xpath/static-dom/StaticAttribute.ts';
6
+ import { StaticElement } from '../../../../integration/xpath/static-dom/StaticElement.ts';
7
+ import { StaticText } from '../../../../integration/xpath/static-dom/StaticText.ts';
8
+ import { SecondaryInstanceDefinition } from '../SecondaryInstanceDefinition.ts';
9
+ import { SecondaryInstanceRootDefinition } from '../SecondaryInstanceRootDefinition.ts';
10
+ import { ExternalSecondaryInstanceSource } from './ExternalSecondaryInstanceSource.ts';
11
+
12
+ type CSVColumn = string;
13
+ type CSVRow = readonly CSVColumn[];
14
+
15
+ type AssertCSVRow = (columns: unknown) => asserts columns is CSVRow;
16
+
17
+ /**
18
+ * Based on {@link https://github.com/getodk/central-frontend/commit/29cebcc870c9be70ab0d222e3349e34639045d19}
19
+ *
20
+ * Central performs this check for header and rows. A comment is included there for the header check, but the logic is the same in both cases.
21
+ */
22
+ const rejectNullCharacters = (cell: string) => {
23
+ if (cell.includes('\0')) {
24
+ throw new ErrorProductionDesignPendingError(`Failed to parse CSV: null character`);
25
+ }
26
+ };
27
+
28
+ const assertCSVRow: AssertCSVRow = (columns) => {
29
+ if (!Array.isArray(columns)) {
30
+ throw new ErrorProductionDesignPendingError('Failed to parse CSV columns');
31
+ }
32
+
33
+ for (const [index, column] of columns.entries()) {
34
+ if (typeof column !== 'string') {
35
+ throw new ErrorProductionDesignPendingError(`Failed to parse CSV column at index ${index}`);
36
+ }
37
+
38
+ rejectNullCharacters(column);
39
+ }
40
+ };
41
+
42
+ type AssertPapaparseSuccess = (
43
+ resourceURL: JRResourceURL,
44
+ errors: readonly papa.ParseError[]
45
+ ) => asserts errors is readonly [];
46
+
47
+ const assertPapaparseSuccess: AssertPapaparseSuccess = (resourceURL, errors) => {
48
+ if (errors.length > 0) {
49
+ const cause = new AggregateError(errors);
50
+ throw new ErrorProductionDesignPendingError(
51
+ `Failed to parse CSV external secondary instance ${resourceURL.href}`,
52
+ { cause }
53
+ );
54
+ }
55
+ };
56
+
57
+ interface ParsedCSVHeader {
58
+ readonly columns: CSVRow;
59
+ readonly errors: readonly [];
60
+ readonly meta: papa.ParseMeta;
61
+ }
62
+
63
+ interface ParseCSVOptions {
64
+ readonly columns: readonly string[];
65
+ readonly delimiter: string;
66
+ }
67
+
68
+ const stripTrailingEmptyCells = (columns: CSVRow, row: CSVRow): CSVRow => {
69
+ const result = row.slice();
70
+
71
+ while (result.length > columns.length && result.at(-1) === '') {
72
+ result.pop();
73
+ }
74
+
75
+ return result;
76
+ };
77
+
78
+ interface ParsedCSVRows {
79
+ readonly rows: readonly CSVRow[];
80
+ readonly errors: readonly [];
81
+ readonly meta: papa.ParseMeta;
82
+ }
83
+
84
+ interface CSVExternalSecondaryInstanceItemColumn {
85
+ readonly columnName: string;
86
+ readonly cellValue: string;
87
+ }
88
+
89
+ type CSVExternalSecondaryInstanceItem = readonly CSVExternalSecondaryInstanceItemColumn[];
90
+
91
+ class CSVExternalSecondaryInstanceColumnElement extends StaticElement {
92
+ constructor(parent: StaticElement, column: CSVExternalSecondaryInstanceItemColumn) {
93
+ const { columnName, cellValue } = column;
94
+
95
+ super(
96
+ parent,
97
+ () => [],
98
+ (self) => [new StaticText(self, cellValue)],
99
+ {
100
+ namespaceURI: XFORMS_NAMESPACE_URI,
101
+ localName: columnName,
102
+ }
103
+ );
104
+ }
105
+ }
106
+
107
+ class CSVExternalSecondaryInstanceItemElement extends StaticElement {
108
+ constructor(parent: StaticElement, item: CSVExternalSecondaryInstanceItem) {
109
+ super(
110
+ parent,
111
+ () => [],
112
+ (self) => {
113
+ return item.map((column) => {
114
+ return new CSVExternalSecondaryInstanceColumnElement(self, column);
115
+ });
116
+ },
117
+ {
118
+ namespaceURI: XFORMS_NAMESPACE_URI,
119
+ localName: 'item',
120
+ }
121
+ );
122
+ }
123
+ }
124
+
125
+ class CSVExternalSecondaryInstanceRootElement extends StaticElement {
126
+ constructor(parent: StaticElement, items: readonly CSVExternalSecondaryInstanceItem[]) {
127
+ super(
128
+ parent,
129
+ () => [],
130
+ (self) => {
131
+ return items.map((item) => {
132
+ return new CSVExternalSecondaryInstanceItemElement(self, item);
133
+ });
134
+ },
135
+ {
136
+ namespaceURI: XFORMS_NAMESPACE_URI,
137
+ localName: 'root',
138
+ }
139
+ );
140
+ }
141
+ }
142
+
143
+ class CSVExternalSecondaryInstanceDocumentElement extends SecondaryInstanceRootDefinition {
144
+ constructor(
145
+ instanceId: string,
146
+ parent: CSVExternalSecondaryInstanceDefinition,
147
+ items: readonly CSVExternalSecondaryInstanceItem[]
148
+ ) {
149
+ super(
150
+ parent,
151
+ (self) => [
152
+ new StaticAttribute(self, {
153
+ namespaceURI: XFORMS_NAMESPACE_URI,
154
+ localName: 'id',
155
+ value: instanceId,
156
+ }),
157
+ ],
158
+ (self) => [new CSVExternalSecondaryInstanceRootElement(self, items)],
159
+ {
160
+ namespaceURI: XFORMS_NAMESPACE_URI,
161
+ localName: 'instance',
162
+ }
163
+ );
164
+ }
165
+ }
166
+
167
+ class CSVExternalSecondaryInstanceDefinition extends SecondaryInstanceDefinition {
168
+ constructor(instanceId: string, items: readonly CSVExternalSecondaryInstanceItem[]) {
169
+ super((self) => {
170
+ return new CSVExternalSecondaryInstanceDocumentElement(instanceId, self, items);
171
+ });
172
+ }
173
+ }
174
+
175
+ export class CSVExternalSecondaryInstanceSource extends ExternalSecondaryInstanceSource<'csv'> {
176
+ /**
177
+ * Based on
178
+ * {@link https://github.com/getodk/central-frontend/blob/42c9277709e593480d1462e28b4be5f1364532b7/src/util/csv.js#L79} (and {@link https://github.com/getodk/central-frontend/blob/42c9277709e593480d1462e28b4be5f1364532b7/src/util/csv.js#L13}).
179
+ *
180
+ * The most significant deviations at time of writing:
181
+ *
182
+ * - we have already retrieved the CSV resource, so we are parsing the raw CSV data directly.
183
+ * - we have no need for asynchronous/streaming parsing at this point in the
184
+ * form initialization process, so we can dispense with those details of the
185
+ * {@link papa | papaparse} API/config.
186
+ */
187
+ private parseCSVHeader(csvData: string): ParsedCSVHeader {
188
+ const { data, errors, meta } = papa.parse(csvData, {
189
+ delimitersToGuess: [',', ';', '\t', '|'],
190
+ download: false,
191
+ preview: 1,
192
+ });
193
+ const [columns = []] = data;
194
+
195
+ assertCSVRow(columns);
196
+ assertPapaparseSuccess(this.resourceURL, errors);
197
+
198
+ return {
199
+ errors,
200
+ meta,
201
+ columns,
202
+ };
203
+ }
204
+
205
+ /**
206
+ * Largely based on {@link https://github.com/getodk/central-frontend/blob/42c9277709e593480d1462e28b4be5f1364532b7/src/util/csv.js#L170}
207
+ */
208
+ private parseCSVRows(csvData: string, options: ParseCSVOptions): ParsedCSVRows {
209
+ const { columns, delimiter } = options;
210
+ const { data, errors, meta } = papa.parse(csvData, {
211
+ delimiter,
212
+ download: false,
213
+ });
214
+
215
+ assertPapaparseSuccess(this.resourceURL, errors);
216
+
217
+ const rowData = data.slice(1);
218
+ const lastRowIndex = rowData.length - 1;
219
+
220
+ let stripLastRow = false;
221
+
222
+ const rows = rowData.map((values, index) => {
223
+ assertCSVRow(values);
224
+
225
+ const rowIndex = index + 1;
226
+
227
+ // Central: Remove trailing empty cells.
228
+ const row = stripTrailingEmptyCells(columns, values);
229
+
230
+ // Central: Skip trailing empty rows and do not check them for warnings.
231
+ // Throw for an empty row that is not trailing.
232
+ if (row.every((cell) => cell === '')) {
233
+ if (index === lastRowIndex) {
234
+ stripLastRow = true;
235
+ } else {
236
+ throw new ErrorProductionDesignPendingError(
237
+ `Failed to parse CSV row ${rowIndex}: unexpected empty row`
238
+ );
239
+ }
240
+ }
241
+
242
+ // Central: Throw if there are too many cells.
243
+ if (row.length > columns.length) {
244
+ throw new ErrorProductionDesignPendingError(
245
+ `Failed to parse CSV row ${rowIndex}: expected ${columns.length} columns, got ${row.length}`
246
+ );
247
+ }
248
+
249
+ return row;
250
+ });
251
+
252
+ if (stripLastRow) {
253
+ rows.pop();
254
+ }
255
+
256
+ return {
257
+ errors,
258
+ meta,
259
+ rows,
260
+ };
261
+ }
262
+
263
+ private toItems(
264
+ columns: CSVRow,
265
+ rows: readonly CSVRow[]
266
+ ): readonly CSVExternalSecondaryInstanceItem[] {
267
+ return rows.map((row) => {
268
+ return columns.map((columnName, index) => {
269
+ return {
270
+ columnName,
271
+ cellValue: row[index] ?? '',
272
+ };
273
+ });
274
+ });
275
+ }
276
+
277
+ parseDefinition(): SecondaryInstanceDefinition {
278
+ const csvData = this.resource.data.replace(/[\n\r]+$/, '');
279
+ const { columns, meta } = this.parseCSVHeader(csvData);
280
+ const { rows } = this.parseCSVRows(csvData, {
281
+ columns,
282
+ delimiter: meta.delimiter,
283
+ });
284
+ const items = this.toItems(columns, rows);
285
+
286
+ return new CSVExternalSecondaryInstanceDefinition(this.instanceId, items);
287
+ }
288
+ }