@defra/forms-model 3.0.430 → 3.0.431

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 (45) hide show
  1. package/README.md +163 -1
  2. package/dist/module/common/pagination/index.js +2 -2
  3. package/dist/module/common/pagination/index.js.map +1 -1
  4. package/dist/module/common/search/index.js +4 -4
  5. package/dist/module/common/search/index.js.map +1 -1
  6. package/dist/module/common/sorting/index.js +2 -2
  7. package/dist/module/common/sorting/index.js.map +1 -1
  8. package/dist/module/form/form-definition/index.js +156 -156
  9. package/dist/module/form/form-definition/index.js.map +1 -1
  10. package/dist/module/form/form-editor/index.js +42 -42
  11. package/dist/module/form/form-editor/index.js.map +1 -1
  12. package/dist/module/form/form-manager/index.js +3 -3
  13. package/dist/module/form/form-manager/index.js.map +1 -1
  14. package/dist/module/form/form-metadata/index.js +34 -34
  15. package/dist/module/form/form-metadata/index.js.map +1 -1
  16. package/dist/module/form/form-submission/index.js +13 -13
  17. package/dist/module/form/form-submission/index.js.map +1 -1
  18. package/dist/module/types/joi-to-json.d.js +2 -0
  19. package/dist/module/types/joi-to-json.d.js.map +1 -0
  20. package/dist/types/common/pagination/index.d.ts.map +1 -1
  21. package/dist/types/common/search/index.d.ts.map +1 -1
  22. package/dist/types/common/sorting/index.d.ts.map +1 -1
  23. package/dist/types/form/form-definition/index.d.ts.map +1 -1
  24. package/dist/types/form/form-editor/index.d.ts +12 -12
  25. package/dist/types/form/form-editor/index.d.ts.map +1 -1
  26. package/dist/types/form/form-manager/index.d.ts.map +1 -1
  27. package/dist/types/form/form-metadata/index.d.ts.map +1 -1
  28. package/dist/types/form/form-submission/index.d.ts.map +1 -1
  29. package/package.json +6 -4
  30. package/scripts/generate-schemas.js +238 -0
  31. package/scripts/schema-modules/constants.js +39 -0
  32. package/scripts/schema-modules/schema-processors.js +109 -0
  33. package/scripts/schema-modules/schema-simplifiers.js +351 -0
  34. package/scripts/schema-modules/title-processors.js +327 -0
  35. package/scripts/schema-modules/types.js +21 -0
  36. package/scripts/schema-modules/utils.js +41 -0
  37. package/src/common/pagination/index.ts +8 -1
  38. package/src/common/search/index.ts +17 -3
  39. package/src/common/sorting/index.ts +8 -2
  40. package/src/form/form-definition/index.ts +567 -238
  41. package/src/form/form-editor/index.ts +202 -29
  42. package/src/form/form-manager/index.ts +11 -2
  43. package/src/form/form-metadata/index.ts +118 -40
  44. package/src/form/form-submission/index.ts +33 -10
  45. package/src/types/joi-to-json.d.ts +15 -0
@@ -17,6 +17,8 @@ export enum QuestionTypeSubGroup {
17
17
  export const pageTypeSchema = Joi.string()
18
18
  .required()
19
19
  .valid('question', 'guidance')
20
+ .description('Type of page - either a question page or guidance page')
21
+
20
22
  export const questionTypeSchema = Joi.string()
21
23
  .required()
22
24
  .valid(
@@ -32,6 +34,7 @@ export const questionTypeSchema = Joi.string()
32
34
  ComponentType.RadiosField,
33
35
  ComponentType.AutocompleteField
34
36
  )
37
+ .description('The high-level type of question, including grouped types')
35
38
 
36
39
  export const questionTypeFullSchema = Joi.string()
37
40
  .required()
@@ -50,6 +53,7 @@ export const questionTypeFullSchema = Joi.string()
50
53
  ComponentType.RadiosField,
51
54
  ComponentType.AutocompleteField
52
55
  )
56
+ .description('The specific component type to use for this question')
53
57
 
54
58
  export const writtenAnswerSubSchema = Joi.string()
55
59
  .required()
@@ -58,6 +62,8 @@ export const writtenAnswerSubSchema = Joi.string()
58
62
  ComponentType.MultilineTextField,
59
63
  ComponentType.NumberField
60
64
  )
65
+ .description('Subtype for written answer questions')
66
+
61
67
  export const dateSubSchema = Joi.string()
62
68
  .required()
63
69
  .valid(ComponentType.DatePartsField, ComponentType.MonthYearField)
@@ -69,60 +75,221 @@ export const listSubSchema = Joi.string()
69
75
  ComponentType.RadiosField,
70
76
  ComponentType.AutocompleteField
71
77
  )
78
+ .description('Subtype for date-related questions')
79
+
80
+ export const nameSchema = Joi.string()
81
+ .trim()
82
+ .required()
83
+ .description('Unique identifier for the field')
84
+
85
+ export const questionSchema = Joi.string()
86
+ .trim()
87
+ .required()
88
+ .description('The question text displayed to the user')
89
+
90
+ export const hintTextSchema = Joi.string()
91
+ .trim()
92
+ .optional()
93
+ .allow('')
94
+ .description('Optional guidance text displayed below the question')
72
95
 
73
- export const nameSchema = Joi.string().trim().required()
74
- export const questionSchema = Joi.string().trim().required()
75
- export const hintTextSchema = Joi.string().trim().optional().allow('')
76
96
  export const questionOptionalSchema = Joi.string()
77
97
  .trim()
78
98
  .optional()
79
99
  .valid('', 'true')
80
- export const shortDescriptionSchema = Joi.string().trim().required()
81
- export const pageHeadingAndGuidanceSchema = Joi.string().trim().optional()
82
- export const pageHeadingSchema = Joi.string().trim().required()
83
- export const guidanceTextSchema = Joi.string().trim()
84
- export const needDeclarationSchema = Joi.string().trim().required()
85
- export const declarationTextSchema = Joi.string().trim().required()
86
- export const exactFilesSchema = Joi.number().empty('').integer().min(1).max(25)
87
- export const minFilesSchema = Joi.number().empty('').integer().min(0).max(25)
88
- export const maxFilesSchema = Joi.number().empty('').integer().min(1).max(25)
89
- export const minSchema = Joi.number().empty('').integer()
90
- export const maxSchema = Joi.number().empty('').integer()
91
- export const minLengthSchema = Joi.number().empty('').integer().min(1)
92
- export const maxLengthSchema = Joi.number().empty('').integer().min(1)
93
- export const maxFutureSchema = Joi.number().empty('').integer().min(0)
94
- export const maxPastSchema = Joi.number().empty('').integer().min(0)
95
- export const precisionSchema = Joi.number().empty('').integer().min(0).max(5)
96
- export const prefixSchema = Joi.string().trim().optional().allow('')
97
- export const regexSchema = Joi.string().optional().allow('')
98
- export const rowsSchema = Joi.number().empty('').integer().min(1)
99
- export const suffixSchema = Joi.string().trim().optional().allow('')
100
- export const classesSchema = Joi.string().trim().optional().allow('')
100
+ .description(
101
+ 'Indicates whether a question is optional. Empty string or "true" values are accepted.'
102
+ )
103
+
104
+ export const exactFilesSchema = Joi.number()
105
+ .empty('')
106
+ .integer()
107
+ .min(1)
108
+ .max(25)
109
+ .description(
110
+ 'Specifies the exact number of files required for upload. Must be between 1 and 25.'
111
+ )
112
+
113
+ export const minFilesSchema = Joi.number()
114
+ .empty('')
115
+ .integer()
116
+ .min(0)
117
+ .max(25)
118
+ .description(
119
+ 'Minimum number of files required for upload. Must be between 0 and 25.'
120
+ )
121
+
122
+ export const maxFilesSchema = Joi.number()
123
+ .empty('')
124
+ .integer()
125
+ .min(1)
126
+ .max(25)
127
+ .description(
128
+ 'Maximum number of files allowed for upload. Must be between 1 and 25.'
129
+ )
130
+
101
131
  export const fileTypesSchema = Joi.array()
102
132
  .items(Joi.string())
103
133
  .single()
104
134
  .empty(null)
105
135
  .default([])
136
+ .description(
137
+ 'Array of allowed file types. Can be provided as a single value or an array.'
138
+ )
139
+
106
140
  export const documentTypesSchema = Joi.array()
107
141
  .items(Joi.string())
108
142
  .single()
109
143
  .empty(null)
110
144
  .default([])
145
+ .description(
146
+ 'Array of allowed document types. Can be provided as a single value or an array.'
147
+ )
148
+
111
149
  export const imageTypesSchema = Joi.array()
112
150
  .items(Joi.string())
113
151
  .single()
114
152
  .empty(null)
115
153
  .default([])
154
+ .description(
155
+ 'Array of allowed image types. Can be provided as a single value or an array.'
156
+ )
157
+
116
158
  export const tabularDataTypesSchema = Joi.array()
117
159
  .items(Joi.string())
118
160
  .single()
119
161
  .empty(null)
120
162
  .default([])
121
- export const enhancedActionSchema = Joi.string().trim().optional().allow('')
122
- export const radioIdSchema = Joi.string().trim().optional().allow('')
123
- export const radioLabelSchema = Joi.string().trim().required()
124
- export const radioHintSchema = Joi.string().trim().optional().allow('')
125
- export const radioValueSchema = Joi.string().trim().optional().allow('')
163
+ export const enhancedActionSchema = Joi.string()
164
+ .trim()
165
+ .optional()
166
+ .allow('')
167
+ .description('Action field that can include enhanced functionality')
168
+
169
+ export const radioIdSchema = Joi.string()
170
+ .trim()
171
+ .optional()
172
+ .allow('')
173
+ .description('Unique identifier for radio options')
174
+
175
+ export const radioLabelSchema = Joi.string()
176
+ .trim()
177
+ .required()
178
+ .description('The visible text shown next to radio options')
179
+
180
+ export const radioHintSchema = Joi.string()
181
+ .trim()
182
+ .optional()
183
+ .allow('')
184
+ .description(
185
+ 'Optional hint text displayed with radio buttons to provide additional guidance'
186
+ )
187
+
188
+ export const radioValueSchema = Joi.string()
189
+ .trim()
190
+ .optional()
191
+ .allow('')
192
+ .description(
193
+ 'Array of allowed tabular data types. Can be provided as a single value or an array.'
194
+ )
195
+
196
+ export const shortDescriptionSchema = Joi.string()
197
+ .trim()
198
+ .required()
199
+ .description('Brief description of the question for internal use')
200
+
201
+ export const pageHeadingAndGuidanceSchema = Joi.string()
202
+ .trim()
203
+ .optional()
204
+ .description('Combined heading and guidance for the page')
205
+
206
+ export const pageHeadingSchema = Joi.string()
207
+ .trim()
208
+ .required()
209
+ .description('Main heading displayed at the top of the page')
210
+
211
+ export const guidanceTextSchema = Joi.string()
212
+ .trim()
213
+ .description('Guidance text to assist users in completing the page')
214
+
215
+ export const needDeclarationSchema = Joi.string()
216
+ .trim()
217
+ .required()
218
+ .description('Whether a declaration is needed')
219
+
220
+ export const declarationTextSchema = Joi.string()
221
+ .trim()
222
+ .required()
223
+ .description('Text of the declaration that users must agree to')
224
+
225
+ export const minSchema = Joi.number()
226
+ .empty('')
227
+ .integer()
228
+ .description('Minimum value for numeric inputs')
229
+
230
+ export const maxSchema = Joi.number()
231
+ .empty('')
232
+ .integer()
233
+ .description('Maximum value for numeric inputs')
234
+
235
+ export const minLengthSchema = Joi.number()
236
+ .empty('')
237
+ .integer()
238
+ .min(1)
239
+ .description('Minimum character length for text inputs')
240
+
241
+ export const maxLengthSchema = Joi.number()
242
+ .empty('')
243
+ .integer()
244
+ .min(1)
245
+ .description('Maximum character length for text inputs')
246
+
247
+ export const maxFutureSchema = Joi.number()
248
+ .empty('')
249
+ .integer()
250
+ .min(1)
251
+ .description('Maximum days in the future allowed for date inputs')
252
+
253
+ export const maxPastSchema = Joi.number()
254
+ .empty('')
255
+ .integer()
256
+ .min(1)
257
+ .description('Maximum days in the past allowed for date inputs')
258
+
259
+ export const precisionSchema = Joi.number()
260
+ .empty('')
261
+ .integer()
262
+ .min(1)
263
+ .description('Decimal precision for numeric inputs')
264
+
265
+ export const prefixSchema = Joi.string()
266
+ .trim()
267
+ .optional()
268
+ .allow('')
269
+ .description('Text to display before the input (e.g., £)')
270
+
271
+ export const regexSchema = Joi.string()
272
+ .optional()
273
+ .allow('')
274
+ .description('Regular expression pattern for validation')
275
+
276
+ export const rowsSchema = Joi.number()
277
+ .empty('')
278
+ .integer()
279
+ .min(1)
280
+ .description('Number of rows for multiline text fields')
281
+
282
+ export const suffixSchema = Joi.string()
283
+ .trim()
284
+ .optional()
285
+ .allow('')
286
+ .description('Text to display after the input (e.g., kg)')
287
+
288
+ export const classesSchema = Joi.string()
289
+ .trim()
290
+ .optional()
291
+ .allow('')
292
+ .description('Custom CSS classes to apply to the component')
126
293
 
127
294
  export const questionDetailsFullSchema = {
128
295
  classesSchema,
@@ -169,6 +336,7 @@ export const formEditorInputPageKeys = {
169
336
  export const formEditorInputPageSchema = Joi.object<FormEditorInputPage>()
170
337
  .keys(formEditorInputPageKeys)
171
338
  .required()
339
+ .description('Input schema for creating a new page in the form editor')
172
340
 
173
341
  export const formEditorInputheckAnswersSettingsKeys = {
174
342
  declarationText: shortDescriptionSchema
@@ -182,6 +350,7 @@ export const formEditorInputCheckAnswersSettingSchema =
182
350
  Joi.object<FormEditorInputCheckAnswersSettings>()
183
351
  .keys(formEditorInputheckAnswersSettingsKeys)
184
352
  .required()
353
+ .description('Configuration for the check-answers page')
185
354
 
186
355
  export const formEditorInputQuestionKeys = {
187
356
  question: questionSchema,
@@ -198,6 +367,9 @@ export const formEditorInputQuestionSchema =
198
367
  Joi.object<FormEditorInputQuestion>()
199
368
  .keys(formEditorInputQuestionKeys)
200
369
  .required()
370
+ .description(
371
+ 'Input schema for creating or updating a question in the form editor'
372
+ )
201
373
 
202
374
  export const formEditorInputPageSettingsKeys = {
203
375
  pageHeadingAndGuidance: pageHeadingAndGuidanceSchema,
@@ -213,3 +385,4 @@ export const formEditorInputPageSettingsSchema =
213
385
  Joi.object<FormEditorInputPageSettings>()
214
386
  .keys(formEditorInputPageSettingsKeys)
215
387
  .required()
388
+ .description('Settings for page content and display in the form editor')
@@ -5,8 +5,17 @@ import { pageSchema } from '~/src/index.js'
5
5
 
6
6
  export const patchPageSchema = Joi.object<PatchPageFields>()
7
7
  .keys({
8
- title: pageSchema.extract('title').optional(),
9
- path: pageSchema.extract('path').optional()
8
+ title: pageSchema
9
+ .extract('title')
10
+ .optional()
11
+ .description('New title to set for the page'),
12
+ path: pageSchema
13
+ .extract('path')
14
+ .optional()
15
+ .description('New URL path to set for the page')
10
16
  })
11
17
  .required()
12
18
  .min(1)
19
+ .description(
20
+ 'Schema for partially updating a page, requiring at least one field to be provided'
21
+ )
@@ -22,30 +22,63 @@ export const organisations = [
22
22
  'Veterinary Medicines Directorate – VMD'
23
23
  ]
24
24
 
25
- export const idSchema = Joi.string().hex().length(24).required()
26
- export const titleSchema = Joi.string().max(250).trim().required()
25
+ export const idSchema = Joi.string()
26
+ .hex()
27
+ .length(24)
28
+ .required()
29
+ .description(
30
+ 'Unique identifier for the form, 24-character hexadecimal string'
31
+ )
32
+
33
+ export const titleSchema = Joi.string()
34
+ .max(250)
35
+ .trim()
36
+ .required()
37
+ .description('Title of the form, displayed to users')
38
+
27
39
  export const slugSchema = Joi.string()
28
40
  .pattern(/^[a-z0-9-]+$/, { name: 'letters, numbers and hyphens only' })
29
41
  .required()
42
+ .description('URL-friendly identifier used in form paths')
30
43
 
31
44
  export const organisationSchema = Joi.string()
32
45
  .valid(...organisations)
33
46
  .required()
47
+ .description('Defra organisation responsible for the form')
48
+
49
+ export const teamNameSchema = Joi.string()
50
+ .max(100)
51
+ .trim()
52
+ .required()
53
+ .description('Name of the team responsible for the form')
34
54
 
35
- export const teamNameSchema = Joi.string().max(100).trim().required()
36
55
  export const teamEmailSchema = Joi.string()
37
56
  .email({ tlds: { allow: ['uk'] } })
38
57
  .trim()
39
58
  .required()
59
+ .description('Contact email for the team responsible for the form')
60
+
61
+ export const phoneSchema = Joi.string()
62
+ .trim()
63
+ .description('Phone number for form-related inquiries')
64
+
65
+ export const emailAddressSchema = Joi.string()
66
+ .email()
67
+ .trim()
68
+ .required()
69
+ .description('Email address for form-related inquiries')
40
70
 
41
- export const phoneSchema = Joi.string().trim()
71
+ export const emailResponseTimeSchema = Joi.string()
72
+ .trim()
73
+ .required()
74
+ .description('Expected response time for email inquiries')
42
75
 
43
- export const emailAddressSchema = Joi.string().email().trim().required()
44
- export const emailResponseTimeSchema = Joi.string().trim().required()
45
- export const emailSchema = Joi.object<FormMetadataContactEmail>().keys({
46
- address: emailAddressSchema,
47
- responseTime: emailResponseTimeSchema
48
- })
76
+ export const emailSchema = Joi.object<FormMetadataContactEmail>()
77
+ .keys({
78
+ address: emailAddressSchema,
79
+ responseTime: emailResponseTimeSchema
80
+ })
81
+ .description('Email contact details including response expectations')
49
82
 
50
83
  export const onlineUrlSchema = Joi.string()
51
84
  .uri({
@@ -53,34 +86,61 @@ export const onlineUrlSchema = Joi.string()
53
86
  })
54
87
  .trim()
55
88
  .required()
56
- export const onlineTextSchema = Joi.string().trim().required()
57
- export const onlineSchema = Joi.object<FormMetadataContactOnline>().keys({
58
- url: onlineUrlSchema,
59
- text: onlineTextSchema
60
- })
89
+ .description('URL for online contact method')
90
+
91
+ export const onlineTextSchema = Joi.string()
92
+ .trim()
93
+ .required()
94
+ .description('Descriptive text for the online contact link')
61
95
 
62
- export const contactSchema = Joi.object<FormMetadataContact>().keys({
63
- phone: phoneSchema,
64
- email: emailSchema,
65
- online: onlineSchema
66
- })
96
+ export const onlineSchema = Joi.object<FormMetadataContactOnline>()
97
+ .keys({
98
+ url: onlineUrlSchema,
99
+ text: onlineTextSchema
100
+ })
101
+ .description('Online contact details with URL and descriptive text')
67
102
 
68
- export const submissionGuidanceSchema = Joi.string().trim()
103
+ export const contactSchema = Joi.object<FormMetadataContact>()
104
+ .keys({
105
+ phone: phoneSchema,
106
+ email: emailSchema,
107
+ online: onlineSchema
108
+ })
109
+ .description('Complete contact information for form-related inquiries')
110
+
111
+ export const submissionGuidanceSchema = Joi.string()
112
+ .trim()
113
+ .description('Guidance text shown to users when submitting the form')
69
114
 
70
115
  export const privacyNoticeUrlSchema = Joi.string()
71
116
  .uri({
72
117
  scheme: ['http', 'https']
73
118
  })
74
119
  .trim()
120
+ .description('URL to the privacy notice for this form')
75
121
 
76
122
  export const notificationEmailAddressSchema = Joi.string()
77
123
  .email({ tlds: { allow: ['uk'] } })
78
124
  .trim()
79
125
  .pattern(/\.gov\.uk$|\.org\.uk$/)
126
+ .description(
127
+ 'Email address to receive form submission notifications, must be a .gov.uk or .org.uk address'
128
+ )
129
+
130
+ export const authoredAtSchema = Joi.date()
131
+ .iso()
132
+ .required()
133
+ .description('ISO format timestamp of when an action occurred')
80
134
 
81
- export const authoredAtSchema = Joi.date().iso().required()
82
- export const authorIdSchema = Joi.string().trim().required()
83
- export const authorDisplayNameSchema = Joi.string().trim().required()
135
+ export const authorIdSchema = Joi.string()
136
+ .trim()
137
+ .required()
138
+ .description('Unique identifier for the author')
139
+
140
+ export const authorDisplayNameSchema = Joi.string()
141
+ .trim()
142
+ .required()
143
+ .description('Human-readable name of the author')
84
144
 
85
145
  export const formMetadataInputKeys = {
86
146
  title: titleSchema,
@@ -100,6 +160,7 @@ export const formMetadataInputKeys = {
100
160
  export const formMetadataInputSchema = Joi.object<FormMetadataInput>()
101
161
  .keys(formMetadataInputKeys)
102
162
  .required()
163
+ .description('Input data for creating or updating form metadata')
103
164
 
104
165
  /**
105
166
  * Joi schema for `FormMetadataAuthor` interface
@@ -111,29 +172,46 @@ export const formMetadataAuthorSchema = Joi.object<FormMetadataAuthor>()
111
172
  displayName: authorDisplayNameSchema
112
173
  })
113
174
  .required()
175
+ .description('Information about the author of a form or form change')
114
176
 
115
177
  /**
116
178
  * Joi schema for `FormMetadataState` interface
117
179
  * @see {@link FormMetadataState}
118
180
  */
119
- export const formMetadataStateSchema = Joi.object<FormMetadataState>().keys({
120
- createdAt: authoredAtSchema,
121
- createdBy: formMetadataAuthorSchema,
122
- updatedAt: authoredAtSchema,
123
- updatedBy: formMetadataAuthorSchema
124
- })
181
+ export const formMetadataStateSchema = Joi.object<FormMetadataState>()
182
+ .keys({
183
+ createdAt: authoredAtSchema.description(
184
+ 'When this version was first created'
185
+ ),
186
+ createdBy: formMetadataAuthorSchema.description('Who created this version'),
187
+ updatedAt: authoredAtSchema.description(
188
+ 'When this version was last updated'
189
+ ),
190
+ updatedBy: formMetadataAuthorSchema.description(
191
+ 'Who last updated this version'
192
+ )
193
+ })
194
+ .description('Metadata about a specific version state (draft or live)')
125
195
 
126
196
  /**
127
197
  * Joi schema for `FormMetadata` interface
128
198
  * @see {@link FormMetadata}
129
199
  */
130
- export const formMetadataSchema = formMetadataInputSchema.append<FormMetadata>({
131
- id: idSchema,
132
- slug: slugSchema,
133
- draft: formMetadataStateSchema,
134
- live: formMetadataStateSchema,
135
- createdAt: authoredAtSchema,
136
- createdBy: formMetadataAuthorSchema,
137
- updatedAt: authoredAtSchema,
138
- updatedBy: formMetadataAuthorSchema
139
- })
200
+ export const formMetadataSchema = formMetadataInputSchema
201
+ .append<FormMetadata>({
202
+ id: idSchema,
203
+ slug: slugSchema,
204
+ draft: formMetadataStateSchema.description(
205
+ 'Metadata for the draft version'
206
+ ),
207
+ live: formMetadataStateSchema.description(
208
+ 'Metadata for the published version'
209
+ ),
210
+ createdAt: authoredAtSchema.description('When the form was first created'),
211
+ createdBy: formMetadataAuthorSchema.description('Who created the form'),
212
+ updatedAt: authoredAtSchema.description('When the form was last updated'),
213
+ updatedBy: formMetadataAuthorSchema.description('Who last updated the form')
214
+ })
215
+ .description(
216
+ 'Complete metadata for a form, including version information and authoring details'
217
+ )
@@ -11,22 +11,36 @@ import {
11
11
  * @see {@link SubmitRecord}
12
12
  */
13
13
  export const formSubmitRecordSchema = Joi.object<SubmitRecord>({
14
- name: Joi.string().required(),
15
- title: Joi.string().required(),
16
- value: Joi.string().required().allow('')
17
- })
14
+ name: Joi.string()
15
+ .required()
16
+ .description('Field identifier matching the component name'),
17
+ title: Joi.string()
18
+ .required()
19
+ .description('Human-readable label for the field'),
20
+ value: Joi.string()
21
+ .required()
22
+ .allow('')
23
+ .description('User-submitted value for the field, may be empty')
24
+ }).description('Individual field value in a form submission')
18
25
 
19
26
  /**
20
27
  * Joi schema for `SubmitRecordset` interface
21
28
  * @see {@link SubmitRecordset}
22
29
  */
23
30
  export const formSubmitRecordsetSchema = Joi.object<SubmitRecordset>({
24
- name: Joi.string().required(),
25
- title: Joi.string().required(),
31
+ name: Joi.string()
32
+ .required()
33
+ .description('Identifier for the repeatable section'),
34
+ title: Joi.string()
35
+ .required()
36
+ .description('Human-readable title for the repeatable section'),
26
37
  value: Joi.array<SubmitRecord[]>()
27
38
  .items(Joi.array<SubmitRecord>().items(formSubmitRecordSchema).required())
28
39
  .required()
29
- })
40
+ .description(
41
+ 'Array of record arrays, each representing a repeated instance'
42
+ )
43
+ }).description('Collection of repeated field values from a repeatable section')
30
44
 
31
45
  /**
32
46
  * Joi schema for `SubmitPayload` interface
@@ -34,11 +48,20 @@ export const formSubmitRecordsetSchema = Joi.object<SubmitRecordset>({
34
48
  */
35
49
  export const formSubmitPayloadSchema = Joi.object<SubmitPayload>()
36
50
  .keys({
37
- retrievalKey: Joi.string().required(),
38
- sessionId: Joi.string().required(),
39
- main: Joi.array<SubmitRecord>().items(formSubmitRecordSchema).required(),
51
+ retrievalKey: Joi.string()
52
+ .required()
53
+ .description('Unique key to retrieve this submission later'),
54
+ sessionId: Joi.string()
55
+ .required()
56
+ .description('User session identifier for tracking and security'),
57
+ main: Joi.array<SubmitRecord>()
58
+ .items(formSubmitRecordSchema)
59
+ .required()
60
+ .description('Main (non-repeating) field values from the form'),
40
61
  repeaters: Joi.array<SubmitRecordset>()
41
62
  .items(formSubmitRecordsetSchema)
42
63
  .required()
64
+ .description('Repeatable section values from the form')
43
65
  })
44
66
  .required()
67
+ .description('Complete form submission payload structure with all form data')
@@ -0,0 +1,15 @@
1
+ declare module 'joi-to-json' {
2
+ import { type Schema } from 'joi'
3
+
4
+ /**
5
+ * Converts a Joi schema to a JSON Schema
6
+ */
7
+ function parse(
8
+ joiSchema: Schema,
9
+ type?: string,
10
+ definitions?: object,
11
+ parserOptions?: object
12
+ ): object
13
+
14
+ export = parse
15
+ }