@defra/forms-model 3.0.178 → 3.0.180

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 (62) hide show
  1. package/dist/module/components/component-types.js +4 -42
  2. package/dist/module/components/component-types.js.map +1 -1
  3. package/dist/module/components/enums.js +0 -5
  4. package/dist/module/components/enums.js.map +1 -1
  5. package/dist/module/components/helpers.js +57 -0
  6. package/dist/module/components/helpers.js.map +1 -0
  7. package/dist/module/components/index.js +2 -1
  8. package/dist/module/components/index.js.map +1 -1
  9. package/dist/module/components/types.js.map +1 -1
  10. package/dist/module/conditions/condition-field.js +5 -5
  11. package/dist/module/conditions/condition-field.js.map +1 -1
  12. package/dist/module/conditions/condition-operators.js +64 -48
  13. package/dist/module/conditions/condition-operators.js.map +1 -1
  14. package/dist/module/conditions/condition-ref.js.map +1 -1
  15. package/dist/module/conditions/condition-values.js +9 -10
  16. package/dist/module/conditions/condition-values.js.map +1 -1
  17. package/dist/module/conditions/condition.js.map +1 -1
  18. package/dist/module/conditions/enums.js +31 -0
  19. package/dist/module/conditions/enums.js.map +1 -1
  20. package/dist/module/conditions/index.js +2 -2
  21. package/dist/module/conditions/index.js.map +1 -1
  22. package/dist/module/conditions/types.js.map +1 -1
  23. package/dist/types/components/component-types.d.ts +1 -0
  24. package/dist/types/components/component-types.d.ts.map +1 -1
  25. package/dist/types/components/enums.d.ts +1 -6
  26. package/dist/types/components/enums.d.ts.map +1 -1
  27. package/dist/types/components/helpers.d.ts +30 -0
  28. package/dist/types/components/helpers.d.ts.map +1 -0
  29. package/dist/types/components/index.d.ts +2 -1
  30. package/dist/types/components/index.d.ts.map +1 -1
  31. package/dist/types/components/types.d.ts +8 -40
  32. package/dist/types/components/types.d.ts.map +1 -1
  33. package/dist/types/conditions/condition-field.d.ts +6 -6
  34. package/dist/types/conditions/condition-field.d.ts.map +1 -1
  35. package/dist/types/conditions/condition-operators.d.ts +56 -232
  36. package/dist/types/conditions/condition-operators.d.ts.map +1 -1
  37. package/dist/types/conditions/condition-ref.d.ts +3 -3
  38. package/dist/types/conditions/condition-ref.d.ts.map +1 -1
  39. package/dist/types/conditions/condition-values.d.ts +5 -8
  40. package/dist/types/conditions/condition-values.d.ts.map +1 -1
  41. package/dist/types/conditions/condition.d.ts +6 -6
  42. package/dist/types/conditions/condition.d.ts.map +1 -1
  43. package/dist/types/conditions/enums.d.ts +28 -0
  44. package/dist/types/conditions/enums.d.ts.map +1 -1
  45. package/dist/types/conditions/index.d.ts +2 -2
  46. package/dist/types/conditions/index.d.ts.map +1 -1
  47. package/dist/types/conditions/types.d.ts +8 -0
  48. package/dist/types/conditions/types.d.ts.map +1 -1
  49. package/package.json +1 -1
  50. package/src/components/component-types.ts +6 -47
  51. package/src/components/enums.ts +1 -6
  52. package/src/components/helpers.ts +138 -0
  53. package/src/components/index.ts +14 -1
  54. package/src/components/types.ts +49 -58
  55. package/src/conditions/condition-field.ts +25 -11
  56. package/src/conditions/condition-operators.ts +129 -96
  57. package/src/conditions/condition-ref.ts +2 -2
  58. package/src/conditions/condition-values.ts +15 -20
  59. package/src/conditions/condition.ts +5 -5
  60. package/src/conditions/enums.ts +31 -0
  61. package/src/conditions/index.ts +7 -2
  62. package/src/conditions/types.ts +16 -0
@@ -1,182 +1,215 @@
1
1
  import { ComponentType } from '~/src/components/enums.js'
2
- import { type ComponentDef } from '~/src/components/types.js'
3
- import { type ConditionValueAbstract } from '~/src/conditions/condition-value-abstract.js'
2
+ import {
3
+ type ConditionalComponentType,
4
+ type ComponentDef
5
+ } from '~/src/components/types.js'
4
6
  import {
5
7
  timeUnits,
6
8
  dateUnits,
7
9
  dateTimeUnits,
8
10
  ConditionValue,
9
- DateDirections,
10
11
  RelativeTimeValue
11
12
  } from '~/src/conditions/condition-values.js'
12
-
13
- type Operator = '==' | '!=' | '>=' | '<=' | '<' | '>'
13
+ import {
14
+ DateDirections,
15
+ Operator,
16
+ OperatorName
17
+ } from '~/src/conditions/enums.js'
18
+ import {
19
+ type Conditionals,
20
+ type DateUnits,
21
+ type OperatorDefinition,
22
+ type TimeUnits
23
+ } from '~/src/conditions/types.js'
14
24
 
15
25
  const defaultOperators = {
16
- is: inline('=='),
17
- 'is not': inline('!=')
26
+ [OperatorName.Is]: inline(Operator.Is),
27
+ [OperatorName.IsNot]: inline(Operator.IsNot)
18
28
  }
19
29
 
20
30
  function withDefaults<T>(param: T) {
21
31
  return Object.assign({}, param, defaultOperators)
22
32
  }
23
33
 
24
- const textBasedFieldCustomisations = {
25
- 'is longer than': lengthIs('>'),
26
- 'is shorter than': lengthIs('<'),
27
- 'has length': lengthIs('==')
34
+ const textFieldOperators = {
35
+ [OperatorName.IsLongerThan]: lengthIs(Operator.IsMoreThan),
36
+ [OperatorName.IsShorterThan]: lengthIs(Operator.IsLessThan),
37
+ [OperatorName.HasLength]: lengthIs(Operator.Is)
28
38
  }
29
39
 
30
40
  const absoluteDateTimeOperators = {
31
- is: absoluteDateTime('=='),
32
- 'is not': absoluteDateTime('!='),
33
- 'is before': absoluteDateTime('<'),
34
- 'is after': absoluteDateTime('>')
41
+ [OperatorName.Is]: absoluteDateTime(Operator.Is),
42
+ [OperatorName.IsNot]: absoluteDateTime(Operator.IsNot),
43
+ [OperatorName.IsBefore]: absoluteDateTime(Operator.IsLessThan),
44
+ [OperatorName.IsAfter]: absoluteDateTime(Operator.IsMoreThan)
35
45
  }
36
46
 
37
- const relativeTimeOperators = (units) => ({
38
- 'is at least': relativeTime('<=', '>=', units),
39
- 'is at most': relativeTime('>=', '<=', units),
40
- 'is less than': relativeTime('>', '<', units),
41
- 'is more than': relativeTime('<', '>', units)
47
+ const relativeTimeOperators = (units: DateUnits | TimeUnits) => ({
48
+ [OperatorName.IsAtLeast]: relativeTime(
49
+ Operator.IsAtMost,
50
+ Operator.IsAtLeast,
51
+ units
52
+ ),
53
+ [OperatorName.IsAtMost]: relativeTime(
54
+ Operator.IsAtLeast,
55
+ Operator.IsAtMost,
56
+ units
57
+ ),
58
+ [OperatorName.IsLessThan]: relativeTime(
59
+ Operator.IsMoreThan,
60
+ Operator.IsLessThan,
61
+ units
62
+ ),
63
+ [OperatorName.IsMoreThan]: relativeTime(
64
+ Operator.IsLessThan,
65
+ Operator.IsMoreThan,
66
+ units
67
+ )
42
68
  })
43
69
 
44
70
  export const customOperators = {
45
71
  [ComponentType.CheckboxesField]: {
46
- contains: reverseInline('in'),
47
- 'does not contain': not(reverseInline('in'))
72
+ [OperatorName.Contains]: reverseInline(Operator.Contains),
73
+ [OperatorName.DoesNotContain]: not(reverseInline(Operator.Contains))
48
74
  },
49
75
  [ComponentType.NumberField]: withDefaults({
50
- 'is at least': inline('>='),
51
- 'is at most': inline('<='),
52
- 'is less than': inline('<'),
53
- 'is more than': inline('>')
76
+ [OperatorName.IsAtLeast]: inline(Operator.IsAtLeast),
77
+ [OperatorName.IsAtMost]: inline(Operator.IsAtMost),
78
+ [OperatorName.IsLessThan]: inline(Operator.IsLessThan),
79
+ [OperatorName.IsMoreThan]: inline(Operator.IsMoreThan)
54
80
  }),
55
- [ComponentType.DateField]: Object.assign(
56
- {},
57
- absoluteDateTimeOperators,
58
- relativeTimeOperators(dateUnits)
59
- ),
60
- [ComponentType.TimeField]: Object.assign(
61
- {},
62
- absoluteDateTimeOperators,
63
- relativeTimeOperators(timeUnits)
64
- ),
65
- [ComponentType.DatePartsField]: Object.assign(
66
- {},
67
- absoluteDateTimeOperators,
68
- relativeTimeOperators(dateUnits)
69
- ),
70
- [ComponentType.DateTimeField]: Object.assign(
71
- {},
72
- absoluteDateTimeOperators,
73
- relativeTimeOperators(dateTimeUnits)
74
- ),
75
- [ComponentType.DateTimePartsField]: Object.assign(
76
- {},
77
- absoluteDateTimeOperators,
78
- relativeTimeOperators(dateTimeUnits)
79
- ),
80
- [ComponentType.TextField]: withDefaults(textBasedFieldCustomisations),
81
- [ComponentType.MultilineTextField]: withDefaults(
82
- textBasedFieldCustomisations
83
- ),
84
- [ComponentType.EmailAddressField]: withDefaults(textBasedFieldCustomisations)
85
- }
81
+ [ComponentType.TimeField]: {
82
+ ...absoluteDateTimeOperators,
83
+ ...relativeTimeOperators(timeUnits)
84
+ },
85
+ [ComponentType.DatePartsField]: {
86
+ ...absoluteDateTimeOperators,
87
+ ...relativeTimeOperators(dateUnits)
88
+ },
89
+ [ComponentType.TextField]: withDefaults(textFieldOperators),
90
+ [ComponentType.MultilineTextField]: withDefaults(textFieldOperators),
91
+ [ComponentType.EmailAddressField]: withDefaults(textFieldOperators),
92
+ [ComponentType.YesNoField]: defaultOperators
93
+ } as const satisfies Record<ConditionalComponentType, Partial<Conditionals>>
86
94
 
87
- export function getOperatorNames(fieldType) {
95
+ export function getOperatorNames(fieldType: ConditionalComponentType) {
88
96
  return Object.keys(getConditionals(fieldType)).sort()
89
97
  }
90
98
 
91
99
  export function getExpression(
92
- fieldType: ComponentType,
100
+ fieldType: ConditionalComponentType,
93
101
  fieldName: string,
94
- operator: string,
95
- value: ConditionValueAbstract
102
+ operator: OperatorName,
103
+ value: ConditionValue | RelativeTimeValue
96
104
  ) {
97
- return getConditionals(fieldType)[operator].expression(
105
+ return getConditionals(fieldType)[operator]?.expression(
98
106
  { type: fieldType, name: fieldName },
99
107
  value
100
108
  )
101
109
  }
102
110
 
103
- export function getOperatorConfig(fieldType: ComponentType, operator) {
111
+ export function getOperatorConfig(
112
+ fieldType: ConditionalComponentType,
113
+ operator: OperatorName
114
+ ) {
104
115
  return getConditionals(fieldType)[operator]
105
116
  }
106
117
 
107
- function getConditionals(fieldType: ComponentType) {
108
- return customOperators[fieldType] || defaultOperators
118
+ function getConditionals(
119
+ fieldType: ConditionalComponentType
120
+ ): Partial<Conditionals> {
121
+ if (fieldType in customOperators) {
122
+ return customOperators[fieldType]
123
+ }
124
+
125
+ return defaultOperators
109
126
  }
110
127
 
111
- function inline(operator: Operator) {
128
+ function inline(operator: Operator): OperatorDefinition {
112
129
  return {
113
- expression: (field: ComponentDef, value) =>
114
- `${field.name} ${operator} ${formatValue(field.type, value.value)}`
130
+ expression(field, value) {
131
+ return `${field.name} ${operator} ${formatValue(field, value)}`
132
+ }
115
133
  }
116
134
  }
117
135
 
118
- function lengthIs(operator: Operator) {
136
+ function lengthIs(operator: Operator): OperatorDefinition {
119
137
  return {
120
- expression: (field: ComponentDef, value) =>
121
- `length(${field.name}) ${operator} ${value.value}`
138
+ expression(field, value) {
139
+ return `length(${field.name}) ${operator} ${formatValue(field, value)}`
140
+ }
122
141
  }
123
142
  }
124
143
 
125
- function reverseInline(operator: 'in') {
144
+ function reverseInline(operator: Operator.Contains): OperatorDefinition {
126
145
  return {
127
- expression: (field: ComponentDef, value) =>
128
- `${formatValue(field.type, value.value)} ${operator} ${field.name}`
146
+ expression(field, value) {
147
+ return `${formatValue(field, value)} ${operator} ${field.name}`
148
+ }
129
149
  }
130
150
  }
131
151
 
132
- function not(operatorDefinition) {
152
+ function not(operatorDefinition: OperatorDefinition): OperatorDefinition {
133
153
  return {
134
- expression: (field: ComponentDef, value) =>
135
- `not (${operatorDefinition.expression(field, value)})`
154
+ expression(field, value) {
155
+ return `not (${operatorDefinition.expression(field, value)})`
156
+ }
136
157
  }
137
158
  }
138
159
 
139
- function formatValue(fieldType: ComponentType, value) {
160
+ function formatValue(
161
+ field: Pick<ComponentDef, 'type'>,
162
+ value: ConditionValue | RelativeTimeValue
163
+ ) {
140
164
  if (
141
- fieldType === ComponentType.YesNoField ||
142
- fieldType === ComponentType.NumberField
165
+ 'value' in value &&
166
+ (field.type === ComponentType.YesNoField ||
167
+ field.type === ComponentType.NumberField)
143
168
  ) {
144
- return value
169
+ return value.value
145
170
  }
146
171
 
147
- return `'${value}'`
172
+ return `'${value.toExpression()}'`
148
173
  }
149
174
 
150
175
  export const absoluteDateOrTimeOperatorNames = Object.keys(
151
176
  absoluteDateTimeOperators
152
177
  )
178
+
153
179
  export const relativeDateOrTimeOperatorNames = Object.keys(
154
180
  relativeTimeOperators(dateTimeUnits)
155
181
  )
156
182
 
157
- function absoluteDateTime(operator: Operator) {
183
+ function absoluteDateTime(operator: Operator): OperatorDefinition {
158
184
  return {
159
- expression: (field: ComponentDef, value) => {
160
- if (value instanceof ConditionValue) {
161
- return `${field.name} ${operator} '${value.toExpression()}'`
185
+ expression(field, value) {
186
+ if (!(value instanceof ConditionValue)) {
187
+ throw new Error(
188
+ "Expression param 'value' must be ConditionValue instance"
189
+ )
162
190
  }
163
- throw Error('only Value types are supported')
191
+
192
+ return `${field.name} ${operator} '${formatValue(field, value)}'`
164
193
  }
165
194
  }
166
195
  }
167
196
 
168
- function relativeTime(pastOperator, futureOperator, units) {
197
+ function relativeTime(
198
+ pastOperator: Operator,
199
+ futureOperator: Operator,
200
+ units: DateUnits | TimeUnits
201
+ ): OperatorDefinition {
169
202
  return {
170
203
  units,
171
- expression: (field: ComponentDef, value) => {
172
- if (value instanceof RelativeTimeValue) {
173
- const operator =
174
- value.direction === DateDirections.PAST
175
- ? pastOperator
176
- : futureOperator
177
- return `${field.name} ${operator} ${value.toExpression()}`
204
+ expression(field, value) {
205
+ if (!(value instanceof RelativeTimeValue)) {
206
+ throw new Error(
207
+ "Expression param 'value' must be RelativeTimeValue instance"
208
+ )
178
209
  }
179
- throw Error('time shift requires a TimeShiftValue')
210
+
211
+ const isPast = value.direction === DateDirections.PAST
212
+ return `${field.name} ${isPast ? pastOperator : futureOperator} ${value.toExpression()}`
180
213
  }
181
214
  }
182
215
  }
@@ -2,8 +2,8 @@ import { ConditionAbstract } from '~/src/conditions/condition-abstract.js'
2
2
  import { type Coordinator } from '~/src/conditions/enums.js'
3
3
 
4
4
  export class ConditionRef extends ConditionAbstract {
5
- conditionName: string
6
- conditionDisplayName: string
5
+ conditionName
6
+ conditionDisplayName
7
7
 
8
8
  constructor(
9
9
  conditionName: string,
@@ -1,4 +1,5 @@
1
1
  import { ConditionValueAbstract } from '~/src/conditions/condition-value-abstract.js'
2
+ import { ConditionType, DateDirections } from '~/src/conditions/enums.js'
2
3
  import {
3
4
  type DateTimeUnitValues,
4
5
  type DateUnits,
@@ -9,7 +10,7 @@ export class ConditionValue
9
10
  extends ConditionValueAbstract
10
11
  implements ConditionValueFrom
11
12
  {
12
- type: 'Value'
13
+ type: ConditionType.Value
13
14
  value: string
14
15
  display: string
15
16
 
@@ -24,7 +25,7 @@ export class ConditionValue
24
25
 
25
26
  super()
26
27
 
27
- this.type = 'Value'
28
+ this.type = ConditionType.Value
28
29
  this.value = value
29
30
  this.display = display ?? value
30
31
  }
@@ -51,34 +52,28 @@ export interface ConditionValueFrom {
51
52
  display?: string
52
53
  }
53
54
 
54
- export enum DateDirections {
55
- FUTURE = 'in the future',
56
- PAST = 'in the past'
57
- }
58
-
59
55
  export const dateUnits: DateUnits = {
60
56
  YEARS: { display: 'year(s)', value: 'years' },
61
57
  MONTHS: { display: 'month(s)', value: 'months' },
62
58
  DAYS: { display: 'day(s)', value: 'days' }
63
- }
59
+ } as const
64
60
 
65
61
  export const timeUnits: TimeUnits = {
66
62
  HOURS: { display: 'hour(s)', value: 'hours' },
67
63
  MINUTES: { display: 'minute(s)', value: 'minutes' },
68
64
  SECONDS: { display: 'second(s)', value: 'seconds' }
69
- }
65
+ } as const
70
66
 
71
- export const dateTimeUnits: DateUnits & TimeUnits = Object.assign(
72
- {},
73
- dateUnits,
74
- timeUnits
75
- )
67
+ export const dateTimeUnits: DateUnits & TimeUnits = {
68
+ ...dateUnits,
69
+ ...timeUnits
70
+ } as const
76
71
 
77
72
  export class RelativeTimeValue
78
73
  extends ConditionValueAbstract
79
74
  implements RelativeTimeValueFrom
80
75
  {
81
- type: 'RelativeTime'
76
+ type: ConditionType.RelativeTime
82
77
  timePeriod: string
83
78
  timeUnit: DateTimeUnitValues
84
79
  direction: DateDirections
@@ -112,7 +107,7 @@ export class RelativeTimeValue
112
107
 
113
108
  super()
114
109
 
115
- this.type = 'RelativeTime'
110
+ this.type = ConditionType.RelativeTime
116
111
  this.timePeriod = timePeriod
117
112
  this.timeUnit = timeUnit
118
113
  this.direction = direction
@@ -158,14 +153,14 @@ export function conditionValueFrom(
158
153
  obj:
159
154
  | ConditionValue
160
155
  | RelativeTimeValue
161
- | ({ type: 'Value' } & ConditionValueFrom)
162
- | ({ type: 'RelativeTime' } & RelativeTimeValueFrom)
156
+ | ({ type: ConditionType.Value } & ConditionValueFrom)
157
+ | ({ type: ConditionType.RelativeTime } & RelativeTimeValueFrom)
163
158
  ) {
164
159
  switch (obj.type) {
165
- case 'Value':
160
+ case ConditionType.Value:
166
161
  return ConditionValue.from(obj)
167
162
 
168
- case 'RelativeTime':
163
+ case ConditionType.RelativeTime:
169
164
  return RelativeTimeValue.from(obj)
170
165
  }
171
166
  }
@@ -6,16 +6,16 @@ import {
6
6
  type ConditionValue,
7
7
  type RelativeTimeValue
8
8
  } from '~/src/conditions/condition-values.js'
9
- import { type Coordinator } from '~/src/conditions/enums.js'
9
+ import { type Coordinator, type OperatorName } from '~/src/conditions/enums.js'
10
10
 
11
11
  export class Condition extends ConditionAbstract {
12
- field: ConditionField
13
- operator: string
14
- value: ConditionValue | RelativeTimeValue
12
+ field
13
+ operator
14
+ value
15
15
 
16
16
  constructor(
17
17
  field?: ConditionField,
18
- operator?: string,
18
+ operator?: OperatorName,
19
19
  value?: ConditionValue | RelativeTimeValue,
20
20
  coordinator?: Coordinator
21
21
  ) {
@@ -7,3 +7,34 @@ export enum Coordinator {
7
7
  AND = 'and',
8
8
  OR = 'or'
9
9
  }
10
+
11
+ export enum Operator {
12
+ Is = '==',
13
+ IsNot = '!=',
14
+ Contains = 'in',
15
+ IsAtLeast = '>=',
16
+ IsAtMost = '<=',
17
+ IsLessThan = '<',
18
+ IsMoreThan = '>'
19
+ }
20
+
21
+ export enum OperatorName {
22
+ Is = 'is',
23
+ IsNot = 'is not',
24
+ IsLongerThan = 'is longer than',
25
+ IsShorterThan = 'is shorter than',
26
+ HasLength = 'has length',
27
+ Contains = 'contains',
28
+ DoesNotContain = 'does not contain',
29
+ IsAtLeast = 'is at least',
30
+ IsAtMost = 'is at most',
31
+ IsLessThan = 'is less than',
32
+ IsMoreThan = 'is more than',
33
+ IsBefore = 'is before',
34
+ IsAfter = 'is after'
35
+ }
36
+
37
+ export enum DateDirections {
38
+ FUTURE = 'in the future',
39
+ PAST = 'in the past'
40
+ }
@@ -11,7 +11,6 @@ export {
11
11
  dateUnits,
12
12
  dateTimeUnits,
13
13
  ConditionValue,
14
- DateDirections,
15
14
  RelativeTimeValue,
16
15
  conditionValueFrom
17
16
  } from '~/src/conditions/condition-values.js'
@@ -24,4 +23,10 @@ export { ConditionsModel } from '~/src/conditions/condition-model.js'
24
23
  export { ConditionGroupDef } from '~/src/conditions/condition-group-def.js'
25
24
  export { toExpression, toPresentationString } from '~/src/conditions/helpers.js'
26
25
 
27
- export { ConditionType, Coordinator } from '~/src/conditions/enums.js'
26
+ export {
27
+ ConditionType,
28
+ Coordinator,
29
+ DateDirections,
30
+ Operator,
31
+ OperatorName
32
+ } from '~/src/conditions/enums.js'
@@ -1,6 +1,12 @@
1
+ import { type ConditionalComponentsDef } from '~/src/components/types.js'
1
2
  import { type ConditionGroup } from '~/src/conditions/condition-group.js'
2
3
  import { type ConditionRef } from '~/src/conditions/condition-ref.js'
4
+ import {
5
+ type ConditionValue,
6
+ type RelativeTimeValue
7
+ } from '~/src/conditions/condition-values.js'
3
8
  import { type Condition } from '~/src/conditions/condition.js'
9
+ import { type OperatorName } from '~/src/conditions/enums.js'
4
10
 
5
11
  export type ConditionsArray = (Condition | ConditionGroup | ConditionRef)[]
6
12
 
@@ -23,3 +29,13 @@ export interface TimeUnits {
23
29
  MINUTES: { display: 'minute(s)'; value: 'minutes' }
24
30
  SECONDS: { display: 'second(s)'; value: 'seconds' }
25
31
  }
32
+
33
+ export interface OperatorDefinition {
34
+ units?: DateUnits | TimeUnits
35
+ expression: (
36
+ component: Pick<ConditionalComponentsDef, 'type' | 'name'>,
37
+ conditionValue: ConditionValue | RelativeTimeValue
38
+ ) => string
39
+ }
40
+
41
+ export type Conditionals = Record<OperatorName, OperatorDefinition>