@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.
- package/README.md +1 -1
- package/dist/client/BaseNode.d.ts +18 -3
- package/dist/client/BaseValueNode.d.ts +32 -0
- package/dist/client/EngineConfig.d.ts +49 -48
- package/dist/client/GroupNode.d.ts +1 -0
- package/dist/client/InputNode.d.ts +82 -0
- package/dist/client/ModelValueNode.d.ts +13 -7
- package/dist/client/NoteNode.d.ts +26 -9
- package/dist/client/RangeNode.d.ts +36 -0
- package/dist/client/RankNode.d.ts +46 -0
- package/dist/client/RootNode.d.ts +37 -7
- package/dist/client/SelectNode.d.ts +47 -25
- package/dist/client/SubtreeNode.d.ts +1 -0
- package/dist/client/TriggerNode.d.ts +10 -6
- package/dist/client/ValueType.d.ts +3 -0
- package/dist/client/constants.d.ts +50 -0
- package/dist/client/hierarchy.d.ts +8 -8
- package/dist/client/identity.d.ts +14 -0
- package/dist/client/node-types.d.ts +3 -2
- package/dist/client/resources.d.ts +93 -0
- package/dist/client/submission/SubmissionData.d.ts +7 -0
- package/dist/client/submission/SubmissionDefinition.d.ts +14 -0
- package/dist/client/submission/SubmissionInstanceFile.d.ts +6 -0
- package/dist/client/submission/SubmissionOptions.d.ts +23 -0
- package/dist/client/submission/SubmissionResult.d.ts +91 -0
- package/dist/client/submission/SubmissionState.d.ts +12 -0
- package/dist/client/unsupported/UnsupportedControlNode.d.ts +1 -3
- package/dist/client/validation.d.ts +2 -2
- package/dist/error/ErrorProductionDesignPendingError.d.ts +7 -0
- package/dist/error/RankMissingValueError.d.ts +3 -0
- package/dist/error/RankValueTypeError.d.ts +6 -0
- package/dist/error/SelectValueTypeError.d.ts +15 -0
- package/dist/error/ValueTypeInvariantError.d.ts +17 -0
- package/dist/error/XFormsSpecViolationError.d.ts +2 -0
- package/dist/error/XPathFunctionalityError.d.ts +14 -0
- package/dist/error/XPathFunctionalityNotSupportedError.d.ts +7 -0
- package/dist/error/XPathFunctionalityPendingError.d.ts +7 -0
- package/dist/index.d.ts +12 -4
- package/dist/index.js +17864 -14655
- package/dist/index.js.map +1 -1
- package/dist/instance/Group.d.ts +10 -4
- package/dist/instance/InputControl.d.ts +38 -0
- package/dist/instance/ModelValue.d.ts +17 -25
- package/dist/instance/Note.d.ts +16 -21
- package/dist/instance/PrimaryInstance.d.ts +85 -0
- package/dist/instance/RangeControl.d.ts +34 -0
- package/dist/instance/RankControl.d.ts +40 -0
- package/dist/instance/Root.d.ts +30 -25
- package/dist/instance/SelectControl.d.ts +66 -0
- package/dist/instance/Subtree.d.ts +11 -5
- package/dist/instance/TriggerControl.d.ts +13 -19
- package/dist/instance/abstract/DescendantNode.d.ts +32 -25
- package/dist/instance/abstract/InstanceNode.d.ts +52 -30
- package/dist/instance/abstract/UnsupportedControl.d.ts +11 -3
- package/dist/instance/abstract/ValueNode.d.ts +47 -0
- package/dist/instance/hierarchy.d.ts +13 -12
- package/dist/instance/identity.d.ts +2 -7
- package/dist/instance/internal-api/EvaluationContext.d.ts +53 -12
- package/dist/instance/internal-api/InstanceConfig.d.ts +8 -2
- package/dist/instance/internal-api/InstanceValueContext.d.ts +22 -0
- package/dist/instance/internal-api/PrimaryInstanceDocument.d.ts +36 -0
- package/dist/instance/internal-api/TranslationContext.d.ts +3 -2
- package/dist/instance/internal-api/ValidationContext.d.ts +3 -4
- package/dist/instance/internal-api/ValueContext.d.ts +2 -1
- package/dist/instance/internal-api/submission/ClientReactiveSubmittableInstance.d.ts +14 -0
- package/dist/instance/internal-api/submission/ClientReactiveSubmittableLeafNode.d.ts +32 -0
- package/dist/instance/internal-api/submission/ClientReactiveSubmittableParentNode.d.ts +19 -0
- package/dist/instance/internal-api/submission/ClientReactiveSubmittableValueNode.d.ts +18 -0
- package/dist/instance/repeat/BaseRepeatRange.d.ts +40 -83
- package/dist/instance/repeat/RepeatInstance.d.ts +12 -29
- package/dist/instance/repeat/RepeatRangeControlled.d.ts +2 -2
- package/dist/instance/repeat/RepeatRangeUncontrolled.d.ts +2 -2
- package/dist/instance/resource.d.ts +1 -1
- package/dist/instance/text/TextRange.d.ts +1 -1
- package/dist/instance/unsupported/UploadControl.d.ts +3 -1
- package/dist/integration/xpath/EngineXPathEvaluator.d.ts +14 -0
- package/dist/integration/xpath/adapter/XFormsXPathNode.d.ts +71 -0
- package/dist/integration/xpath/adapter/engineDOMAdapter.d.ts +5 -0
- package/dist/integration/xpath/adapter/kind.d.ts +32 -0
- package/dist/integration/xpath/adapter/names.d.ts +6 -0
- package/dist/integration/xpath/adapter/traversal.d.ts +26 -0
- package/dist/integration/xpath/adapter/values.d.ts +2 -0
- package/dist/integration/xpath/static-dom/StaticAttribute.d.ts +26 -0
- package/dist/integration/xpath/static-dom/StaticDocument.d.ts +15 -0
- package/dist/integration/xpath/static-dom/StaticElement.d.ts +48 -0
- package/dist/integration/xpath/static-dom/StaticNode.d.ts +33 -0
- package/dist/integration/xpath/static-dom/StaticText.d.ts +16 -0
- package/dist/lib/client-reactivity/submission/createInstanceSubmissionState.d.ts +3 -0
- package/dist/lib/client-reactivity/submission/createLeafNodeSubmissionState.d.ts +3 -0
- package/dist/lib/client-reactivity/submission/createNodeRangeSubmissionState.d.ts +4 -0
- package/dist/lib/client-reactivity/submission/createParentNodeSubmissionState.d.ts +4 -0
- package/dist/lib/client-reactivity/submission/createRootSubmissionState.d.ts +3 -0
- package/dist/lib/client-reactivity/submission/createValueNodeSubmissionState.d.ts +3 -0
- package/dist/lib/client-reactivity/submission/prepareSubmission.d.ts +8 -0
- package/dist/lib/codecs/DecimalValueCodec.d.ts +6 -0
- package/dist/lib/codecs/Geopoint/Geopoint.d.ts +48 -0
- package/dist/lib/codecs/Geopoint/GeopointValueCodec.d.ts +5 -0
- package/dist/lib/codecs/IntValueCodec.d.ts +6 -0
- package/dist/lib/codecs/NoteCodec.d.ts +8 -0
- package/dist/lib/codecs/RangeCodec.d.ts +8 -0
- package/dist/lib/codecs/StringValueCodec.d.ts +4 -0
- package/dist/lib/codecs/TriggerCodec.d.ts +7 -0
- package/dist/lib/codecs/ValueArrayCodec.d.ts +11 -0
- package/dist/lib/codecs/ValueCodec.d.ts +30 -0
- package/dist/lib/codecs/ValueTypePlaceholderCodec.d.ts +12 -0
- package/dist/lib/codecs/getNoteCodec.d.ts +3 -0
- package/dist/lib/codecs/getSelectCodec.d.ts +5 -0
- package/dist/lib/codecs/getSharedValueCodec.d.ts +48 -0
- package/dist/lib/codecs/items/BaseItemCodec.d.ts +9 -0
- package/dist/lib/codecs/items/MultipleValueItemCodec.d.ts +14 -0
- package/dist/lib/codecs/items/SingleValueItemCodec.d.ts +24 -0
- package/dist/lib/dom/query.d.ts +4 -2
- package/dist/lib/names/NamespaceDeclaration.d.ts +45 -0
- package/dist/lib/names/NamespaceDeclarationMap.d.ts +137 -0
- package/dist/lib/names/NamespaceURL.d.ts +30 -0
- package/dist/lib/names/QualifiedName.d.ts +113 -0
- package/dist/lib/number-parsers.d.ts +2 -0
- package/dist/lib/reactivity/createChildrenState.d.ts +7 -5
- package/dist/lib/reactivity/createComputedExpression.d.ts +18 -5
- package/dist/lib/reactivity/createInstanceValueState.d.ts +40 -0
- package/dist/lib/reactivity/createItemCollection.d.ts +21 -0
- package/dist/lib/reactivity/createNoteReadonlyThunk.d.ts +2 -2
- package/dist/lib/reactivity/createTranslationState.d.ts +19 -0
- package/dist/lib/reactivity/createValueState.d.ts +6 -10
- package/dist/lib/reactivity/materializeCurrentStateChildren.d.ts +4 -4
- package/dist/lib/xml-serialization.d.ts +50 -0
- package/dist/parse/XFormDOM.d.ts +18 -7
- package/dist/parse/XFormDefinition.d.ts +1 -2
- package/dist/parse/attachments/FormAttachmentResource.d.ts +27 -0
- package/dist/parse/body/BodyDefinition.d.ts +4 -4
- package/dist/parse/body/RepeatElementDefinition.d.ts +1 -1
- package/dist/parse/body/appearance/inputAppearanceParser.d.ts +1 -1
- package/dist/parse/body/appearance/rangeAppearanceParser.d.ts +3 -0
- package/dist/parse/body/control/{InputDefinition.d.ts → InputControlDefinition.d.ts} +4 -1
- package/dist/parse/body/control/ItemDefinition.d.ts +14 -0
- package/dist/parse/body/control/ItemsetDefinition.d.ts +18 -0
- package/dist/parse/body/control/RangeControlDefinition.d.ts +31 -2
- package/dist/parse/body/control/RankControlDefinition.d.ts +7 -3
- package/dist/parse/body/control/{select/SelectDefinition.d.ts → SelectControlDefinition.d.ts} +9 -9
- package/dist/parse/expression/ItemsetNodesetExpression.d.ts +1 -1
- package/dist/parse/expression/ItemsetValueExpression.d.ts +1 -1
- package/dist/parse/expression/abstract/DependencyContext.d.ts +0 -5
- package/dist/parse/expression/abstract/DependentExpression.d.ts +2 -3
- package/dist/parse/model/BindDefinition.d.ts +6 -5
- package/dist/parse/model/BindPreloadDefinition.d.ts +42 -0
- package/dist/parse/model/BindTypeDefinition.d.ts +20 -0
- package/dist/parse/model/DescendentNodeDefinition.d.ts +4 -14
- package/dist/parse/model/FormSubmissionDefinition.d.ts +8 -0
- package/dist/parse/model/ItextTranslation/ItextTranslationDefinition.d.ts +4 -0
- package/dist/parse/model/ItextTranslation/ItextTranslationRootDefinition.d.ts +9 -0
- package/dist/parse/model/ItextTranslation/ItextTranslationsDefinition.d.ts +8 -0
- package/dist/parse/model/LeafNodeDefinition.d.ts +9 -4
- package/dist/parse/model/ModelBindMap.d.ts +1 -1
- package/dist/parse/model/ModelDefinition.d.ts +2 -0
- package/dist/parse/model/NodeDefinition.d.ts +16 -20
- package/dist/parse/model/NoteNodeDefinition.d.ts +9 -8
- package/dist/parse/model/RangeNodeDefinition.d.ts +41 -0
- package/dist/parse/model/RepeatInstanceDefinition.d.ts +7 -4
- package/dist/parse/model/RepeatRangeDefinition.d.ts +7 -4
- package/dist/parse/model/RepeatTemplateDefinition.d.ts +7 -4
- package/dist/parse/model/RootAttributeDefinition.d.ts +24 -0
- package/dist/parse/model/RootAttributeMap.d.ts +23 -0
- package/dist/parse/model/RootDefinition.d.ts +12 -9
- package/dist/parse/model/SecondaryInstance/SecondaryInstanceDefinition.d.ts +4 -0
- package/dist/parse/model/SecondaryInstance/SecondaryInstanceRootDefinition.d.ts +7 -0
- package/dist/parse/model/SecondaryInstance/SecondaryInstancesDefinition.d.ts +13 -0
- package/dist/parse/model/SecondaryInstance/sources/BlankSecondaryInstanceSource.d.ts +14 -0
- package/dist/parse/model/SecondaryInstance/sources/CSVExternalSecondaryInstance.d.ts +22 -0
- package/dist/parse/model/SecondaryInstance/sources/ExternalSecondaryInstanceResource.d.ts +23 -0
- package/dist/parse/model/SecondaryInstance/sources/ExternalSecondaryInstanceSource.d.ts +9 -0
- package/dist/parse/model/SecondaryInstance/sources/GeoJSONExternalSecondaryInstance.d.ts +5 -0
- package/dist/parse/model/SecondaryInstance/sources/InternalSecondaryInstanceSource.d.ts +7 -0
- package/dist/parse/model/SecondaryInstance/sources/SecondaryInstanceSource.d.ts +13 -0
- package/dist/parse/model/SecondaryInstance/sources/XMLExternalSecondaryInstanceSource.d.ts +12 -0
- package/dist/parse/model/SubtreeDefinition.d.ts +7 -4
- package/dist/parse/shared/parseStaticDocumentFromDOMSubtree.d.ts +23 -0
- package/dist/parse/text/ItemLabelDefinition.d.ts +1 -1
- package/dist/parse/text/ItemsetLabelDefinition.d.ts +2 -2
- package/dist/parse/text/abstract/TextElementDefinition.d.ts +1 -1
- package/dist/parse/text/abstract/TextRangeDefinition.d.ts +0 -2
- package/dist/parse/xpath/semantic-analysis.d.ts +6 -3
- package/dist/solid.js +15437 -12246
- package/dist/solid.js.map +1 -1
- package/package.json +18 -13
- package/src/client/BaseNode.ts +21 -6
- package/src/client/BaseValueNode.ts +35 -0
- package/src/client/EngineConfig.ts +52 -51
- package/src/client/GroupNode.ts +1 -0
- package/src/client/InputNode.ts +113 -0
- package/src/client/ModelValueNode.ts +31 -7
- package/src/client/NoteNode.ts +45 -9
- package/src/client/RangeNode.ts +51 -0
- package/src/client/RankNode.ts +54 -0
- package/src/client/RootNode.ts +43 -7
- package/src/client/SelectNode.ts +53 -26
- package/src/client/SubtreeNode.ts +1 -0
- package/src/client/TriggerNode.ts +12 -6
- package/src/client/ValueType.ts +4 -0
- package/src/client/constants.ts +67 -0
- package/src/client/hierarchy.ts +12 -13
- package/src/client/identity.ts +16 -0
- package/src/client/node-types.ts +13 -7
- package/src/client/resources.ts +118 -0
- package/src/client/submission/SubmissionData.ts +12 -0
- package/src/client/submission/SubmissionDefinition.ts +16 -0
- package/src/client/submission/SubmissionInstanceFile.ts +9 -0
- package/src/client/submission/SubmissionOptions.ts +28 -0
- package/src/client/submission/SubmissionResult.ts +124 -0
- package/src/client/submission/SubmissionState.ts +14 -0
- package/src/client/unsupported/UnsupportedControlNode.ts +2 -6
- package/src/client/validation.ts +2 -2
- package/src/error/ErrorProductionDesignPendingError.ts +6 -0
- package/src/error/RankMissingValueError.ts +5 -0
- package/src/error/RankValueTypeError.ts +13 -0
- package/src/error/SelectValueTypeError.ts +22 -0
- package/src/error/ValueTypeInvariantError.ts +22 -0
- package/src/error/XFormsSpecViolationError.ts +1 -0
- package/src/error/XPathFunctionalityError.ts +26 -0
- package/src/error/XPathFunctionalityNotSupportedError.ts +18 -0
- package/src/error/XPathFunctionalityPendingError.ts +18 -0
- package/src/index.ts +12 -13
- package/src/instance/Group.ts +18 -5
- package/src/instance/InputControl.ts +159 -0
- package/src/instance/ModelValue.ts +48 -53
- package/src/instance/Note.ts +40 -49
- package/src/instance/PrimaryInstance.ts +245 -0
- package/src/instance/RangeControl.ts +113 -0
- package/src/instance/RankControl.ts +199 -0
- package/src/instance/Root.ts +63 -134
- package/src/instance/SelectControl.ts +219 -0
- package/src/instance/Subtree.ts +20 -7
- package/src/instance/TriggerControl.ts +44 -66
- package/src/instance/abstract/DescendantNode.ts +91 -51
- package/src/instance/abstract/InstanceNode.ts +113 -107
- package/src/instance/abstract/UnsupportedControl.ts +29 -5
- package/src/instance/abstract/ValueNode.ts +128 -0
- package/src/instance/children.ts +80 -40
- package/src/instance/hierarchy.ts +39 -30
- package/src/instance/identity.ts +3 -9
- package/src/instance/index.ts +25 -7
- package/src/instance/internal-api/EvaluationContext.ts +60 -13
- package/src/instance/internal-api/InstanceConfig.ts +9 -2
- package/src/instance/internal-api/InstanceValueContext.ts +26 -0
- package/src/instance/internal-api/PrimaryInstanceDocument.ts +53 -0
- package/src/instance/internal-api/TranslationContext.ts +3 -2
- package/src/instance/internal-api/ValidationContext.ts +3 -4
- package/src/instance/internal-api/ValueContext.ts +2 -1
- package/src/instance/internal-api/submission/ClientReactiveSubmittableInstance.ts +20 -0
- package/src/instance/internal-api/submission/ClientReactiveSubmittableLeafNode.ts +43 -0
- package/src/instance/internal-api/submission/ClientReactiveSubmittableParentNode.ts +26 -0
- package/src/instance/internal-api/submission/ClientReactiveSubmittableValueNode.ts +24 -0
- package/src/instance/repeat/BaseRepeatRange.ts +52 -131
- package/src/instance/repeat/RepeatInstance.ts +21 -46
- package/src/instance/repeat/RepeatRangeControlled.ts +5 -5
- package/src/instance/repeat/RepeatRangeUncontrolled.ts +2 -4
- package/src/instance/resource.ts +5 -2
- package/src/instance/text/TextChunk.ts +1 -1
- package/src/instance/unsupported/UploadControl.ts +5 -1
- package/src/integration/xpath/EngineXPathEvaluator.ts +22 -0
- package/src/integration/xpath/adapter/XFormsXPathNode.ts +126 -0
- package/src/integration/xpath/adapter/engineDOMAdapter.ts +57 -0
- package/src/integration/xpath/adapter/kind.ts +114 -0
- package/src/integration/xpath/adapter/names.ts +148 -0
- package/src/integration/xpath/adapter/traversal.ts +229 -0
- package/src/integration/xpath/adapter/values.ts +5 -0
- package/src/integration/xpath/static-dom/StaticAttribute.ts +41 -0
- package/src/integration/xpath/static-dom/StaticDocument.ts +36 -0
- package/src/integration/xpath/static-dom/StaticElement.ts +119 -0
- package/src/integration/xpath/static-dom/StaticNode.ts +68 -0
- package/src/integration/xpath/static-dom/StaticText.ts +28 -0
- package/src/lib/client-reactivity/README.md +0 -0
- package/src/lib/client-reactivity/submission/createInstanceSubmissionState.ts +12 -0
- package/src/lib/client-reactivity/submission/createLeafNodeSubmissionState.ts +20 -0
- package/src/lib/client-reactivity/submission/createNodeRangeSubmissionState.ts +17 -0
- package/src/lib/client-reactivity/submission/createParentNodeSubmissionState.ts +22 -0
- package/src/lib/client-reactivity/submission/createRootSubmissionState.ts +19 -0
- package/src/lib/client-reactivity/submission/createValueNodeSubmissionState.ts +21 -0
- package/src/lib/client-reactivity/submission/prepareSubmission.ts +172 -0
- package/src/lib/codecs/DecimalValueCodec.ts +46 -0
- package/src/lib/codecs/Geopoint/Geopoint.ts +150 -0
- package/src/lib/codecs/Geopoint/GeopointValueCodec.ts +20 -0
- package/src/lib/codecs/IntValueCodec.ts +100 -0
- package/src/lib/codecs/NoteCodec.ts +32 -0
- package/src/lib/codecs/RangeCodec.ts +65 -0
- package/src/lib/codecs/StringValueCodec.ts +11 -0
- package/src/lib/codecs/TriggerCodec.ts +64 -0
- package/src/lib/codecs/ValueArrayCodec.ts +42 -0
- package/src/lib/codecs/ValueCodec.ts +106 -0
- package/src/lib/codecs/ValueTypePlaceholderCodec.ts +19 -0
- package/src/lib/codecs/getNoteCodec.ts +27 -0
- package/src/lib/codecs/getSelectCodec.ts +27 -0
- package/src/lib/codecs/getSharedValueCodec.ts +79 -0
- package/src/lib/codecs/items/BaseItemCodec.ts +20 -0
- package/src/lib/codecs/items/MultipleValueItemCodec.ts +28 -0
- package/src/lib/codecs/items/SingleValueItemCodec.ts +67 -0
- package/src/lib/dom/query.ts +8 -2
- package/src/lib/names/NamespaceDeclaration.ts +106 -0
- package/src/lib/names/NamespaceDeclarationMap.ts +228 -0
- package/src/lib/names/NamespaceURL.ts +44 -0
- package/src/lib/names/QualifiedName.ts +170 -0
- package/src/lib/number-parsers.ts +25 -0
- package/src/lib/reactivity/createChildrenState.ts +8 -6
- package/src/lib/reactivity/createComputedExpression.ts +57 -34
- package/src/lib/reactivity/createInstanceValueState.ts +216 -0
- package/src/lib/reactivity/createItemCollection.ts +173 -0
- package/src/lib/reactivity/createNoteReadonlyThunk.ts +12 -7
- package/src/lib/reactivity/createTranslationState.ts +61 -0
- package/src/lib/reactivity/createValueState.ts +62 -120
- package/src/lib/reactivity/materializeCurrentStateChildren.ts +7 -7
- package/src/lib/reactivity/text/createTextRange.ts +4 -3
- package/src/lib/reactivity/validation/createAggregatedViolations.ts +1 -1
- package/src/lib/reactivity/validation/createValidation.ts +2 -3
- package/src/lib/xml-serialization.ts +163 -0
- package/src/parse/XFormDOM.ts +231 -76
- package/src/parse/XFormDefinition.ts +2 -10
- package/src/parse/attachments/FormAttachmentResource.ts +40 -0
- package/src/parse/body/BodyDefinition.ts +7 -7
- package/src/parse/body/appearance/inputAppearanceParser.ts +1 -1
- package/src/parse/body/appearance/rangeAppearanceParser.ts +11 -0
- package/src/parse/body/control/InputControlDefinition.ts +29 -0
- package/src/parse/body/control/{select/ItemDefinition.ts → ItemDefinition.ts} +8 -6
- package/src/parse/body/control/{select/ItemsetDefinition.ts → ItemsetDefinition.ts} +11 -9
- package/src/parse/body/control/RangeControlDefinition.ts +91 -6
- package/src/parse/body/control/RankControlDefinition.ts +25 -7
- package/src/parse/body/control/{select/SelectDefinition.ts → SelectControlDefinition.ts} +9 -9
- package/src/parse/expression/ItemsetNodesetExpression.ts +1 -1
- package/src/parse/expression/ItemsetValueExpression.ts +1 -1
- package/src/parse/expression/abstract/DependencyContext.ts +0 -26
- package/src/parse/expression/abstract/DependentExpression.ts +2 -13
- package/src/parse/model/BindDefinition.ts +9 -8
- package/src/parse/model/BindPreloadDefinition.ts +100 -0
- package/src/parse/model/BindTypeDefinition.ts +175 -0
- package/src/parse/model/DescendentNodeDefinition.ts +7 -31
- package/src/parse/model/FormSubmissionDefinition.ts +44 -0
- package/src/parse/model/ItextTranslation/ItextTranslationDefinition.ts +4 -0
- package/src/parse/model/ItextTranslation/ItextTranslationRootDefinition.ts +42 -0
- package/src/parse/model/ItextTranslation/ItextTranslationsDefinition.ts +31 -0
- package/src/parse/model/LeafNodeDefinition.ts +15 -5
- package/src/parse/model/ModelBindMap.ts +6 -8
- package/src/parse/model/ModelDefinition.ts +6 -1
- package/src/parse/model/NodeDefinition.ts +24 -48
- package/src/parse/model/NoteNodeDefinition.ts +11 -10
- package/src/parse/model/RangeNodeDefinition.ts +118 -0
- package/src/parse/model/RepeatInstanceDefinition.ts +11 -7
- package/src/parse/model/RepeatRangeDefinition.ts +11 -7
- package/src/parse/model/RepeatTemplateDefinition.ts +11 -7
- package/src/parse/model/RootAttributeDefinition.ts +45 -0
- package/src/parse/model/RootAttributeMap.ts +44 -0
- package/src/parse/model/RootDefinition.ts +31 -29
- package/src/parse/model/SecondaryInstance/SecondaryInstanceDefinition.ts +4 -0
- package/src/parse/model/SecondaryInstance/SecondaryInstanceRootDefinition.ts +12 -0
- package/src/parse/model/SecondaryInstance/SecondaryInstancesDefinition.ts +102 -0
- package/src/parse/model/SecondaryInstance/sources/BlankSecondaryInstanceSource.ts +40 -0
- package/src/parse/model/SecondaryInstance/sources/CSVExternalSecondaryInstance.ts +288 -0
- package/src/parse/model/SecondaryInstance/sources/ExternalSecondaryInstanceResource.ts +222 -0
- package/src/parse/model/SecondaryInstance/sources/ExternalSecondaryInstanceSource.ts +22 -0
- package/src/parse/model/SecondaryInstance/sources/GeoJSONExternalSecondaryInstance.ts +415 -0
- package/src/parse/model/SecondaryInstance/sources/InternalSecondaryInstanceSource.ts +19 -0
- package/src/parse/model/SecondaryInstance/sources/SecondaryInstanceSource.ts +29 -0
- package/src/parse/model/SecondaryInstance/sources/XMLExternalSecondaryInstanceSource.ts +32 -0
- package/src/parse/model/SubtreeDefinition.ts +12 -12
- package/src/parse/shared/parseStaticDocumentFromDOMSubtree.ts +149 -0
- package/src/parse/text/ItemLabelDefinition.ts +1 -1
- package/src/parse/text/ItemsetLabelDefinition.ts +2 -2
- package/src/parse/text/abstract/TextElementDefinition.ts +1 -1
- package/src/parse/text/abstract/TextRangeDefinition.ts +0 -6
- package/src/parse/xpath/semantic-analysis.ts +33 -3
- package/dist/client/StringNode.d.ts +0 -46
- package/dist/client/unsupported/RangeNode.d.ts +0 -9
- package/dist/client/unsupported/RankNode.d.ts +0 -9
- package/dist/instance/SelectField.d.ts +0 -50
- package/dist/instance/StringField.d.ts +0 -44
- package/dist/instance/internal-api/SubscribableDependency.d.ts +0 -59
- package/dist/instance/unsupported/RangeControl.d.ts +0 -4
- package/dist/instance/unsupported/RankControl.d.ts +0 -4
- package/dist/lib/reactivity/createSelectItems.d.ts +0 -16
- package/dist/parse/XFormDataType.d.ts +0 -25
- package/dist/parse/body/control/select/ItemDefinition.d.ts +0 -13
- package/dist/parse/body/control/select/ItemsetDefinition.d.ts +0 -17
- package/dist/parse/body/control/select/ItemsetNodesetContext.d.ts +0 -11
- package/src/client/StringNode.ts +0 -52
- package/src/client/unsupported/RangeNode.ts +0 -14
- package/src/client/unsupported/RankNode.ts +0 -14
- package/src/instance/SelectField.ts +0 -226
- package/src/instance/StringField.ts +0 -120
- package/src/instance/internal-api/SubscribableDependency.ts +0 -61
- package/src/instance/unsupported/RangeControl.ts +0 -5
- package/src/instance/unsupported/RankControl.ts +0 -5
- package/src/lib/reactivity/createSelectItems.ts +0 -168
- package/src/parse/XFormDataType.ts +0 -62
- package/src/parse/body/control/InputDefinition.ts +0 -22
- 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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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 {
|
|
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:
|
|
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:
|
|
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
|
-
|
|
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
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
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 (
|
|
98
|
-
|
|
124
|
+
if (!context.isAttached()) {
|
|
125
|
+
return evaluatePreInitializationDefaultValue();
|
|
99
126
|
}
|
|
100
127
|
|
|
101
|
-
|
|
102
|
-
|
|
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
|
+
};
|