@getodk/xforms-engine 0.7.0 → 0.8.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 (69) hide show
  1. package/dist/client/RootNode.d.ts +4 -4
  2. package/dist/client/UploadNode.d.ts +53 -0
  3. package/dist/client/attachments/InstanceAttachmentMeta.d.ts +8 -0
  4. package/dist/client/attachments/InstanceAttachmentsConfig.d.ts +8 -0
  5. package/dist/client/form/FormInstanceConfig.d.ts +2 -0
  6. package/dist/client/hierarchy.d.ts +4 -5
  7. package/dist/client/index.d.ts +5 -2
  8. package/dist/client/node-types.d.ts +2 -3
  9. package/dist/client/serialization/InstanceData.d.ts +7 -5
  10. package/dist/client/serialization/InstancePayloadOptions.d.ts +3 -2
  11. package/dist/error/UploadValueTypeError.d.ts +8 -0
  12. package/dist/index.js +6603 -5598
  13. package/dist/index.js.map +1 -1
  14. package/dist/instance/PrimaryInstance.d.ts +2 -3
  15. package/dist/instance/UploadControl.d.ts +58 -0
  16. package/dist/instance/attachments/InstanceAttachment.d.ts +42 -0
  17. package/dist/instance/attachments/InstanceAttachmentsState.d.ts +9 -0
  18. package/dist/instance/hierarchy.d.ts +6 -7
  19. package/dist/instance/internal-api/InstanceAttachmentContext.d.ts +19 -0
  20. package/dist/instance/internal-api/InstanceConfig.d.ts +2 -0
  21. package/dist/instance/internal-api/serialization/ClientReactiveSerializableInstance.d.ts +2 -0
  22. package/dist/lib/reactivity/createInstanceAttachment.d.ts +8 -0
  23. package/dist/lib/resource-helpers.d.ts +2 -0
  24. package/dist/parse/body/BodyDefinition.d.ts +2 -1
  25. package/dist/parse/body/control/UploadControlDefinition.d.ts +2 -0
  26. package/dist/parse/model/BindTypeDefinition.d.ts +2 -7
  27. package/dist/solid.js +6600 -5596
  28. package/dist/solid.js.map +1 -1
  29. package/package.json +15 -14
  30. package/src/client/RootNode.ts +8 -3
  31. package/src/client/UploadNode.ts +78 -0
  32. package/src/client/attachments/InstanceAttachmentMeta.ts +10 -0
  33. package/src/client/attachments/InstanceAttachmentsConfig.ts +13 -0
  34. package/src/client/form/FormInstanceConfig.ts +3 -0
  35. package/src/client/hierarchy.ts +5 -8
  36. package/src/client/index.ts +4 -2
  37. package/src/client/node-types.ts +2 -5
  38. package/src/client/serialization/InstanceData.ts +14 -6
  39. package/src/client/serialization/InstancePayloadOptions.ts +3 -2
  40. package/src/entrypoints/FormInstance.ts +3 -2
  41. package/src/error/UploadValueTypeError.ts +13 -0
  42. package/src/instance/PrimaryInstance.ts +4 -5
  43. package/src/instance/UploadControl.ts +184 -0
  44. package/src/instance/attachments/InstanceAttachment.ts +69 -0
  45. package/src/instance/attachments/InstanceAttachmentsState.ts +18 -0
  46. package/src/instance/children/buildChildren.ts +5 -8
  47. package/src/instance/hierarchy.ts +6 -9
  48. package/src/instance/input/InstanceAttachmentMap.ts +33 -21
  49. package/src/instance/internal-api/InstanceAttachmentContext.ts +20 -0
  50. package/src/instance/internal-api/InstanceConfig.ts +3 -0
  51. package/src/instance/internal-api/serialization/ClientReactiveSerializableInstance.ts +2 -0
  52. package/src/lib/client-reactivity/instance-state/prepareInstancePayload.ts +72 -8
  53. package/src/lib/reactivity/createInstanceAttachment.ts +212 -0
  54. package/src/lib/resource-helpers.ts +33 -0
  55. package/src/parse/XFormDOM.ts +1 -3
  56. package/src/parse/body/BodyDefinition.ts +4 -0
  57. package/src/parse/body/control/UploadControlDefinition.ts +42 -0
  58. package/src/parse/model/BindDefinition.ts +1 -1
  59. package/src/parse/model/BindTypeDefinition.ts +68 -26
  60. package/src/parse/model/ModelBindMap.ts +0 -5
  61. package/src/parse/model/SecondaryInstance/sources/ExternalSecondaryInstanceResource.ts +1 -30
  62. package/dist/client/unsupported/UnsupportedControlNode.d.ts +0 -30
  63. package/dist/client/unsupported/UploadNode.d.ts +0 -9
  64. package/dist/instance/unsupported/UploadControl.d.ts +0 -34
  65. package/dist/lib/codecs/TempUnsupportedControlCodec.d.ts +0 -7
  66. package/src/client/unsupported/UnsupportedControlNode.ts +0 -36
  67. package/src/client/unsupported/UploadNode.ts +0 -14
  68. package/src/instance/unsupported/UploadControl.ts +0 -120
  69. package/src/lib/codecs/TempUnsupportedControlCodec.ts +0 -32
@@ -1,3 +1,5 @@
1
+ import type { UploadMediaOptions, UploadNodeOptions } from '../../../client/UploadNode.ts';
2
+ import { ErrorProductionDesignPendingError } from '../../../error/ErrorProductionDesignPendingError.ts';
1
3
  import type { XFormDefinition } from '../../XFormDefinition.ts';
2
4
  import {
3
5
  unknownAppearanceParser,
@@ -6,6 +8,44 @@ import {
6
8
  import type { BodyElementParentContext } from '../BodyDefinition.ts';
7
9
  import { ControlDefinition } from './ControlDefinition.ts';
8
10
 
11
+ const MEDIATYPE_PATTERN = /^([^/]+)\/([^/]+)$/;
12
+
13
+ // prettier-ignore
14
+ type MediaTypeMatches =
15
+ | readonly [$0: string, $1: string, $2: string];
16
+
17
+ const parseUploadMediaOptions = (element: Element): UploadMediaOptions => {
18
+ const mediaType = element.getAttribute('mediatype')?.trim();
19
+
20
+ if (mediaType == null || mediaType === '') {
21
+ return {
22
+ accept: '*',
23
+ type: null,
24
+ subtype: null,
25
+ };
26
+ }
27
+
28
+ const matches = MEDIATYPE_PATTERN.exec(mediaType) as MediaTypeMatches | null;
29
+
30
+ if (matches == null) {
31
+ throw new ErrorProductionDesignPendingError(`Unsupported mediatype: ${mediaType}`);
32
+ }
33
+
34
+ const [accept, type, subtype] = matches;
35
+
36
+ return {
37
+ accept,
38
+ type,
39
+ subtype,
40
+ };
41
+ };
42
+
43
+ const parseUploadNodeOptions = (element: Element): UploadNodeOptions => {
44
+ const media = parseUploadMediaOptions(element);
45
+
46
+ return { media };
47
+ };
48
+
9
49
  export class UploadControlDefinition extends ControlDefinition<'upload'> {
10
50
  static override isCompatible(localName: string): boolean {
11
51
  return localName === 'upload';
@@ -13,11 +53,13 @@ export class UploadControlDefinition extends ControlDefinition<'upload'> {
13
53
 
14
54
  readonly type = 'upload';
15
55
  readonly appearances: UnknownAppearanceDefinition;
56
+ readonly options: UploadNodeOptions;
16
57
 
17
58
  constructor(form: XFormDefinition, parent: BodyElementParentContext, element: Element) {
18
59
  super(form, parent, element);
19
60
 
20
61
  this.appearances = unknownAppearanceParser.parseFrom(element, 'appearance');
62
+ this.options = parseUploadNodeOptions(element);
21
63
  }
22
64
 
23
65
  override toJSON(): object {
@@ -80,7 +80,7 @@ export class BindDefinition<T extends BindType = BindType> extends DependencyCon
80
80
  ) {
81
81
  super();
82
82
 
83
- this.type = BindTypeDefinition.from(bindElement);
83
+ this.type = BindTypeDefinition.from(form, nodeset, bindElement);
84
84
 
85
85
  const parentNodeset = nodeset.replace(/\/[^/]+$/, '');
86
86
 
@@ -1,19 +1,14 @@
1
1
  import { XSD_NAMESPACE_URI, XSD_PREFIX } from '@getodk/common/constants/xmlns.ts';
2
+ import type { AnyBodyElementType } from '../body/BodyDefinition.ts';
3
+ import type { XFormDefinition } from '../XFormDefinition.ts';
2
4
  import { parseQualifiedNameExpression } from '../xpath/semantic-analysis.ts';
3
5
  import type { BindElement } from './BindElement.ts';
4
6
 
5
- /**
6
- * As specified by {@link https://getodk.github.io/xforms-spec/#bind-attributes}
7
- */
8
- export const DEFAULT_BIND_TYPE = 'string';
9
-
10
- export type DefaultBindType = typeof DEFAULT_BIND_TYPE;
11
-
12
7
  /**
13
8
  * As specified by {@link https://getodk.github.io/xforms-spec/#data-types}
14
9
  */
15
10
  const BIND_TYPES = [
16
- DEFAULT_BIND_TYPE,
11
+ 'string',
17
12
  'int',
18
13
  'boolean',
19
14
  'decimal',
@@ -32,6 +27,47 @@ type BindTypes = typeof BIND_TYPES;
32
27
 
33
28
  export type BindType = BindTypes[number];
34
29
 
30
+ type BindTypeDefaultOverridesByBodyType = Partial<Readonly<Record<AnyBodyElementType, BindType>>>;
31
+
32
+ /**
33
+ * As specified by {@link https://getodk.github.io/xforms-spec/#bind-attributes}
34
+ */
35
+ const SPEC_BIND_TYPE_DEFAULT = 'string' satisfies BindType;
36
+
37
+ /**
38
+ * If an `<upload>` is not explicitly associated with any `<bind type>`, we can do one of two things:
39
+ *
40
+ * - correct: default to {@link SPEC_BIND_TYPE_DEFAULT | the spec default regardless of control type}
41
+ * - more useful and robust: default to "binary", which is the only type the spec allows for an `<upload>` control
42
+ *
43
+ * Asked which would be preferable, @lognaturel responded:
44
+ *
45
+ * > I think we should assume in the spirit of doing the most useful thing!
46
+ */
47
+ const UPLOAD_BIND_TYPE_DEFAULT = 'binary' satisfies BindType;
48
+
49
+ const BODY_BIND_TYPE_DEFAULT_OVERRIDES = {
50
+ upload: UPLOAD_BIND_TYPE_DEFAULT,
51
+ } as const satisfies BindTypeDefaultOverridesByBodyType;
52
+
53
+ type BodyBindTypeDefaultOverrides = typeof BODY_BIND_TYPE_DEFAULT_OVERRIDES;
54
+
55
+ type BodyBindTypeDefaultOverride = keyof BodyBindTypeDefaultOverrides;
56
+
57
+ const isBodyBindTypeDefaultOverride = (
58
+ bodyElementType: AnyBodyElementType | null
59
+ ): bodyElementType is BodyBindTypeDefaultOverride => {
60
+ return bodyElementType != null && bodyElementType in BODY_BIND_TYPE_DEFAULT_OVERRIDES;
61
+ };
62
+
63
+ const resolveDefaultBindType = (bodyElementType: AnyBodyElementType | null): BindType => {
64
+ if (isBodyBindTypeDefaultOverride(bodyElementType)) {
65
+ return BODY_BIND_TYPE_DEFAULT_OVERRIDES[bodyElementType];
66
+ }
67
+
68
+ return SPEC_BIND_TYPE_DEFAULT;
69
+ };
70
+
35
71
  const isBindType = (value: string): value is BindType => {
36
72
  return BIND_TYPES.includes(value as BindType);
37
73
  };
@@ -42,14 +78,10 @@ const resolveSupportedBindType = (sourceType: string): BindType | null => {
42
78
 
43
79
  type BindTypeAliasMapping = Readonly<Record<string, BindType>>;
44
80
 
45
- /**
46
- * @todo should we make these aliases explicit (rather than relying on {@link resolveUnsupportedBindType})?
47
- *
48
- * - select1
49
- * - rank
50
- * - odk:rank
51
- */
52
81
  const BIND_TYPE_ALIASES: BindTypeAliasMapping = {
82
+ select1: SPEC_BIND_TYPE_DEFAULT,
83
+ rank: SPEC_BIND_TYPE_DEFAULT,
84
+ 'odk:rank': SPEC_BIND_TYPE_DEFAULT,
53
85
  integer: 'int',
54
86
  };
55
87
 
@@ -65,7 +97,7 @@ const resolveAliasedBindType = (sourceType: string): BindType | null => {
65
97
  * @todo Should we warn on this fallback?
66
98
  */
67
99
  const resolveUnsupportedBindType = (_unsupportedType: string): BindType => {
68
- return DEFAULT_BIND_TYPE;
100
+ return SPEC_BIND_TYPE_DEFAULT;
69
101
  };
70
102
 
71
103
  interface BindDataTypeNamespaceResolver {
@@ -144,7 +176,15 @@ const resolveNamespacedBindType = (
144
176
  return null;
145
177
  };
146
178
 
147
- const resolveBindType = (bindElement: BindElement, sourceType: string): BindType => {
179
+ const resolveBindType = (
180
+ bodyElementType: AnyBodyElementType | null,
181
+ bindElement: BindElement,
182
+ sourceType: string | null
183
+ ): BindType => {
184
+ if (sourceType == null) {
185
+ return resolveDefaultBindType(bodyElementType);
186
+ }
187
+
148
188
  return (
149
189
  resolveSupportedBindType(sourceType) ??
150
190
  resolveAliasedBindType(sourceType) ??
@@ -154,20 +194,22 @@ const resolveBindType = (bindElement: BindElement, sourceType: string): BindType
154
194
  };
155
195
 
156
196
  export class BindTypeDefinition<T extends BindType = BindType> {
157
- static from<T extends BindType>(bindElement: BindElement): BindTypeDefinition<T> {
197
+ static from<T extends BindType>(
198
+ form: XFormDefinition,
199
+ nodeset: string,
200
+ bindElement: BindElement
201
+ ): BindTypeDefinition<T> {
202
+ const bodyElementType = form.body.getBodyElementType(nodeset);
158
203
  const sourceType = bindElement.getAttribute('type');
159
-
160
- if (sourceType == null) {
161
- return new this(sourceType, DEFAULT_BIND_TYPE);
162
- }
163
-
164
- const resolved = resolveBindType(bindElement, sourceType);
204
+ const resolved = resolveBindType(
205
+ bodyElementType,
206
+ bindElement,
207
+ sourceType
208
+ ) satisfies BindType as T;
165
209
 
166
210
  return new this(sourceType, resolved);
167
211
  }
168
212
 
169
- private constructor(source: null, resolved: DefaultBindType);
170
- private constructor(source: string, resolved: BindType);
171
213
  private constructor(
172
214
  readonly source: string | null,
173
215
  readonly resolved: T
@@ -1,7 +1,6 @@
1
1
  import type { XFormDefinition } from '../XFormDefinition.ts';
2
2
  import { BindDefinition } from './BindDefinition.ts';
3
3
  import type { BindElement, BindNodeset } from './BindElement.ts';
4
- import { DEFAULT_BIND_TYPE } from './BindTypeDefinition.ts';
5
4
  import type { ModelDefinition } from './ModelDefinition.ts';
6
5
 
7
6
  class ArtificialBindElement implements BindElement {
@@ -16,10 +15,6 @@ class ArtificialBindElement implements BindElement {
16
15
  return this.ancestorNodeset;
17
16
  }
18
17
 
19
- if (name === 'type') {
20
- return DEFAULT_BIND_TYPE;
21
- }
22
-
23
18
  return null;
24
19
  }
25
20
 
@@ -2,6 +2,7 @@ import type { JRResourceURL } from '@getodk/common/jr-resources/JRResourceURL.ts
2
2
  import type { MissingResourceBehavior } from '../../../../client/constants.ts';
3
3
  import type { FetchResource, FetchResourceResponse } from '../../../../client/resources.ts';
4
4
  import { ErrorProductionDesignPendingError } from '../../../../error/ErrorProductionDesignPendingError.ts';
5
+ import { getResponseContentType } from '../../../../lib/resource-helpers.ts';
5
6
  import { FormAttachmentResource } from '../../../attachments/FormAttachmentResource.ts';
6
7
  import type { ExternalSecondaryInstanceSourceFormat } from './SecondaryInstanceSource.ts';
7
8
 
@@ -13,36 +14,6 @@ const assertResponseSuccess = (resourceURL: JRResourceURL, response: FetchResour
13
14
  }
14
15
  };
15
16
 
16
- const stripContentTypeCharset = (contentType: string): string => {
17
- return contentType.replace(/;charset=.*$/, '');
18
- };
19
-
20
- const getResponseContentType = (response: FetchResourceResponse): string | null => {
21
- const { headers } = response;
22
-
23
- if (headers == null) {
24
- return null;
25
- }
26
-
27
- const contentType = headers.get('content-type');
28
-
29
- if (contentType != null) {
30
- return stripContentTypeCharset(contentType);
31
- }
32
-
33
- if (headers instanceof Headers) {
34
- return contentType;
35
- }
36
-
37
- for (const [header, value] of headers) {
38
- if (header.toLowerCase() === 'content-type') {
39
- return stripContentTypeCharset(value);
40
- }
41
- }
42
-
43
- return null;
44
- };
45
-
46
17
  interface ExternalSecondaryInstanceResourceMetadata<
47
18
  Format extends ExternalSecondaryInstanceSourceFormat = ExternalSecondaryInstanceSourceFormat,
48
19
  > {
@@ -1,30 +0,0 @@
1
- import { UnknownAppearanceDefinition } from '../../parse/body/appearance/unknownAppearanceParser.ts';
2
- import { UploadControlDefinition } from '../../parse/body/control/UploadControlDefinition.ts';
3
- import { LeafNodeDefinition } from '../../parse/model/LeafNodeDefinition.ts';
4
- import { BaseNode, BaseNodeState } from '../BaseNode.ts';
5
- import { RootNode } from '../RootNode.ts';
6
- import { GeneralParentNode } from '../hierarchy.ts';
7
- import { UnsupportedControlNodeType } from '../node-types.ts';
8
- import { LeafNodeValidationState } from '../validation.ts';
9
- export interface UnsupportedControlNodeState extends BaseNodeState {
10
- get children(): null;
11
- get valueOptions(): unknown;
12
- get value(): unknown;
13
- }
14
- export type UnsupportedControlElementDefinition = UploadControlDefinition;
15
- export interface UnsupportedControlDefinition extends LeafNodeDefinition {
16
- readonly bodyElement: UnsupportedControlElementDefinition;
17
- }
18
- /**
19
- * Stub node, for form controls pending further engine support.
20
- */
21
- export interface UnsupportedControlNode extends BaseNode {
22
- readonly nodeType: UnsupportedControlNodeType;
23
- readonly appearances: UnknownAppearanceDefinition;
24
- readonly definition: UnsupportedControlDefinition;
25
- readonly root: RootNode;
26
- readonly parent: GeneralParentNode;
27
- readonly currentState: UnsupportedControlNodeState;
28
- readonly validationState: LeafNodeValidationState;
29
- setValue?(value: never): never;
30
- }
@@ -1,9 +0,0 @@
1
- import { UploadControlDefinition } from '../../parse/body/control/UploadControlDefinition.ts';
2
- import { UnsupportedControlDefinition, UnsupportedControlNode } from './UnsupportedControlNode.ts';
3
- export interface UploadNodeDefinition extends UnsupportedControlDefinition {
4
- readonly bodyElement: UploadControlDefinition;
5
- }
6
- export interface UploadNode extends UnsupportedControlNode {
7
- readonly nodeType: 'upload';
8
- readonly definition: UploadNodeDefinition;
9
- }
@@ -1,34 +0,0 @@
1
- import { XPathNodeKindKey } from '@getodk/xpath';
2
- import { Accessor } from 'solid-js';
3
- import { TextRange } from '../../client/TextRange.ts';
4
- import { ValueType } from '../../client/ValueType.ts';
5
- import { UploadNode, UploadNodeDefinition } from '../../client/unsupported/UploadNode.ts';
6
- import { XFormsXPathElement } from '../../integration/xpath/adapter/XFormsXPathNode.ts';
7
- import { StaticLeafElement } from '../../integration/xpath/static-dom/StaticElement.ts';
8
- import { TempUnsupportedInputValue, TempUnsupportedRuntimeValue } from '../../lib/codecs/TempUnsupportedControlCodec.ts';
9
- import { CurrentState } from '../../lib/reactivity/node-state/createCurrentState.ts';
10
- import { EngineState } from '../../lib/reactivity/node-state/createEngineState.ts';
11
- import { SharedNodeState } from '../../lib/reactivity/node-state/createSharedNodeState.ts';
12
- import { UnknownAppearanceDefinition } from '../../parse/body/appearance/unknownAppearanceParser.ts';
13
- import { ValueNode, ValueNodeStateSpec } from '../abstract/ValueNode.ts';
14
- import { GeneralParentNode } from '../hierarchy.ts';
15
- import { EvaluationContext } from '../internal-api/EvaluationContext.ts';
16
- import { ValidationContext } from '../internal-api/ValidationContext.ts';
17
- import { ClientReactiveSerializableValueNode } from '../internal-api/serialization/ClientReactiveSerializableValueNode.ts';
18
- interface UploadControlStateSpec extends ValueNodeStateSpec<TempUnsupportedRuntimeValue> {
19
- readonly label: Accessor<TextRange<'label'> | null>;
20
- readonly hint: Accessor<TextRange<'hint'> | null>;
21
- readonly valueOptions: null;
22
- }
23
- export declare class UploadControl extends ValueNode<ValueType, UploadNodeDefinition, TempUnsupportedRuntimeValue, TempUnsupportedInputValue> implements UploadNode, XFormsXPathElement, EvaluationContext, ValidationContext, ClientReactiveSerializableValueNode {
24
- readonly [XPathNodeKindKey] = "element";
25
- protected readonly state: SharedNodeState<UploadControlStateSpec>;
26
- protected readonly engineState: EngineState<UploadControlStateSpec>;
27
- readonly nodeType = "upload";
28
- readonly appearances: UnknownAppearanceDefinition;
29
- readonly nodeOptions: null;
30
- readonly currentState: CurrentState<UploadControlStateSpec>;
31
- constructor(parent: GeneralParentNode, instanceNode: StaticLeafElement | null, definition: UploadNodeDefinition);
32
- setValue(_: never): never;
33
- }
34
- export {};
@@ -1,7 +0,0 @@
1
- import { ValueType } from '../../client/ValueType.ts';
2
- import { ValueCodec } from './ValueCodec.ts';
3
- export type TempUnsupportedRuntimeValue = unknown;
4
- export type TempUnsupportedInputValue = unknown;
5
- export declare class TempUnsupportedControlCodec<V extends ValueType> extends ValueCodec<V, TempUnsupportedRuntimeValue, TempUnsupportedInputValue> {
6
- constructor(valueType: V);
7
- }
@@ -1,36 +0,0 @@
1
- import type { UnknownAppearanceDefinition } from '../../parse/body/appearance/unknownAppearanceParser.ts';
2
- import type { UploadControlDefinition } from '../../parse/body/control/UploadControlDefinition.ts';
3
- import type { LeafNodeDefinition } from '../../parse/model/LeafNodeDefinition.ts';
4
- import type { BaseNode, BaseNodeState } from '../BaseNode.ts';
5
- import type { RootNode } from '../RootNode.ts';
6
- import type { GeneralParentNode } from '../hierarchy.ts';
7
- import type { UnsupportedControlNodeType } from '../node-types.ts';
8
- import type { LeafNodeValidationState } from '../validation.ts';
9
-
10
- export interface UnsupportedControlNodeState extends BaseNodeState {
11
- get children(): null;
12
- get valueOptions(): unknown;
13
- get value(): unknown;
14
- }
15
-
16
- // prettier-ignore
17
- export type UnsupportedControlElementDefinition = UploadControlDefinition;
18
-
19
- export interface UnsupportedControlDefinition extends LeafNodeDefinition {
20
- readonly bodyElement: UnsupportedControlElementDefinition;
21
- }
22
-
23
- /**
24
- * Stub node, for form controls pending further engine support.
25
- */
26
- export interface UnsupportedControlNode extends BaseNode {
27
- readonly nodeType: UnsupportedControlNodeType;
28
- readonly appearances: UnknownAppearanceDefinition;
29
- readonly definition: UnsupportedControlDefinition;
30
- readonly root: RootNode;
31
- readonly parent: GeneralParentNode;
32
- readonly currentState: UnsupportedControlNodeState;
33
- readonly validationState: LeafNodeValidationState;
34
-
35
- setValue?(value: never): never;
36
- }
@@ -1,14 +0,0 @@
1
- import type { UploadControlDefinition } from '../../parse/body/control/UploadControlDefinition.ts';
2
- import type {
3
- UnsupportedControlDefinition,
4
- UnsupportedControlNode,
5
- } from './UnsupportedControlNode.ts';
6
-
7
- export interface UploadNodeDefinition extends UnsupportedControlDefinition {
8
- readonly bodyElement: UploadControlDefinition;
9
- }
10
-
11
- export interface UploadNode extends UnsupportedControlNode {
12
- readonly nodeType: 'upload';
13
- readonly definition: UploadNodeDefinition;
14
- }
@@ -1,120 +0,0 @@
1
- import { XPathNodeKindKey } from '@getodk/xpath';
2
- import type { Accessor } from 'solid-js';
3
- import type { TextRange } from '../../client/TextRange.ts';
4
- import type { ValueType } from '../../client/ValueType.ts';
5
- import type { UnsupportedControlNodeType } from '../../client/node-types.ts';
6
- import type { UploadNode, UploadNodeDefinition } from '../../client/unsupported/UploadNode.ts';
7
- import type { XFormsXPathElement } from '../../integration/xpath/adapter/XFormsXPathNode.ts';
8
- import type { StaticLeafElement } from '../../integration/xpath/static-dom/StaticElement.ts';
9
- import type {
10
- TempUnsupportedInputValue,
11
- TempUnsupportedRuntimeValue,
12
- } from '../../lib/codecs/TempUnsupportedControlCodec.ts';
13
- import { TempUnsupportedControlCodec } from '../../lib/codecs/TempUnsupportedControlCodec.ts';
14
- import type { CurrentState } from '../../lib/reactivity/node-state/createCurrentState.ts';
15
- import type { EngineState } from '../../lib/reactivity/node-state/createEngineState.ts';
16
- import type { SharedNodeState } from '../../lib/reactivity/node-state/createSharedNodeState.ts';
17
- import { createSharedNodeState } from '../../lib/reactivity/node-state/createSharedNodeState.ts';
18
- import { createFieldHint } from '../../lib/reactivity/text/createFieldHint.ts';
19
- import { createNodeLabel } from '../../lib/reactivity/text/createNodeLabel.ts';
20
- import type { UnknownAppearanceDefinition } from '../../parse/body/appearance/unknownAppearanceParser.ts';
21
- import { ValueNode, type ValueNodeStateSpec } from '../abstract/ValueNode.ts';
22
- import type { GeneralParentNode } from '../hierarchy.ts';
23
- import type { EvaluationContext } from '../internal-api/EvaluationContext.ts';
24
- import type { ValidationContext } from '../internal-api/ValidationContext.ts';
25
- import type { ClientReactiveSerializableValueNode } from '../internal-api/serialization/ClientReactiveSerializableValueNode.ts';
26
-
27
- interface UploadControlStateSpec extends ValueNodeStateSpec<TempUnsupportedRuntimeValue> {
28
- readonly label: Accessor<TextRange<'label'> | null>;
29
- readonly hint: Accessor<TextRange<'hint'> | null>;
30
- readonly valueOptions: null;
31
- }
32
-
33
- const codecs = {
34
- string: new TempUnsupportedControlCodec('string'),
35
- int: new TempUnsupportedControlCodec('int'),
36
- decimal: new TempUnsupportedControlCodec('decimal'),
37
- boolean: new TempUnsupportedControlCodec('boolean'),
38
- date: new TempUnsupportedControlCodec('date'),
39
- time: new TempUnsupportedControlCodec('time'),
40
- dateTime: new TempUnsupportedControlCodec('dateTime'),
41
- geopoint: new TempUnsupportedControlCodec('geopoint'),
42
- geotrace: new TempUnsupportedControlCodec('geotrace'),
43
- geoshape: new TempUnsupportedControlCodec('geoshape'),
44
- binary: new TempUnsupportedControlCodec('binary'),
45
- barcode: new TempUnsupportedControlCodec('barcode'),
46
- intent: new TempUnsupportedControlCodec('intent'),
47
- } as const;
48
-
49
- class UnsupportedControlWriteError extends Error {
50
- constructor(type: UnsupportedControlNodeType) {
51
- super(`Cannot write state for node (type: ${type}) - not implemented`);
52
- }
53
- }
54
-
55
- export class UploadControl
56
- extends ValueNode<
57
- ValueType,
58
- UploadNodeDefinition,
59
- TempUnsupportedRuntimeValue,
60
- TempUnsupportedInputValue
61
- >
62
- implements
63
- UploadNode,
64
- XFormsXPathElement,
65
- EvaluationContext,
66
- ValidationContext,
67
- ClientReactiveSerializableValueNode
68
- {
69
- // XFormsXPathElement
70
- override readonly [XPathNodeKindKey] = 'element';
71
-
72
- // InstanceNode
73
- protected readonly state: SharedNodeState<UploadControlStateSpec>;
74
- protected readonly engineState: EngineState<UploadControlStateSpec>;
75
-
76
- // UploadNode
77
- readonly nodeType = 'upload';
78
- readonly appearances: UnknownAppearanceDefinition;
79
- readonly nodeOptions = null;
80
- readonly currentState: CurrentState<UploadControlStateSpec>;
81
-
82
- constructor(
83
- parent: GeneralParentNode,
84
- instanceNode: StaticLeafElement | null,
85
- definition: UploadNodeDefinition
86
- ) {
87
- const codec = codecs[definition.valueType];
88
-
89
- super(parent, instanceNode, definition, codec);
90
-
91
- this.appearances = definition.bodyElement.appearances;
92
-
93
- const state = createSharedNodeState(
94
- this.scope,
95
- {
96
- reference: this.contextReference,
97
- readonly: this.isReadonly,
98
- relevant: this.isRelevant,
99
- required: this.isRequired,
100
-
101
- label: createNodeLabel(this, definition),
102
- hint: createFieldHint(this, definition),
103
- children: null,
104
- valueOptions: null,
105
- value: this.valueState,
106
- instanceValue: this.getInstanceValue,
107
- },
108
- this.instanceConfig
109
- );
110
-
111
- this.state = state;
112
- this.engineState = state.engineState;
113
- this.currentState = state.currentState;
114
- }
115
-
116
- // UnsupportedControlNode
117
- setValue(_: never): never {
118
- throw new UnsupportedControlWriteError(this.nodeType);
119
- }
120
- }
@@ -1,32 +0,0 @@
1
- import { identity } from '@getodk/common/lib/identity.ts';
2
- import type { ValueType } from '../../client/ValueType.ts';
3
- import { ValueCodec, type CodecDecoder, type CodecEncoder } from './ValueCodec.ts';
4
-
5
- class TempUnsupportedControlEncodeError extends Error {
6
- constructor() {
7
- super(`Cannot encode state: not implemented`);
8
- }
9
- }
10
-
11
- export type TempUnsupportedRuntimeValue = unknown;
12
- export type TempUnsupportedInputValue = unknown;
13
-
14
- export class TempUnsupportedControlCodec<V extends ValueType> extends ValueCodec<
15
- V,
16
- TempUnsupportedRuntimeValue,
17
- TempUnsupportedInputValue
18
- > {
19
- constructor(valueType: V) {
20
- const encodeValue: CodecEncoder<TempUnsupportedRuntimeValue> = (input): string => {
21
- if (typeof input === 'string') {
22
- return input;
23
- }
24
-
25
- throw new TempUnsupportedControlEncodeError();
26
- };
27
-
28
- const decodeValue: CodecDecoder<TempUnsupportedInputValue> = identity;
29
-
30
- super(valueType, encodeValue, decodeValue);
31
- }
32
- }