@defra/forms-engine-plugin 4.0.43 → 4.0.44

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 (142) hide show
  1. package/.public/stylesheets/application.min.css +1 -1
  2. package/.public/stylesheets/application.min.css.map +1 -1
  3. package/.server/client/stylesheets/_payment-field.scss +8 -0
  4. package/.server/client/stylesheets/application.scss +2 -0
  5. package/.server/index.js +3 -1
  6. package/.server/index.js.map +1 -1
  7. package/.server/server/constants.d.ts +1 -0
  8. package/.server/server/constants.js +1 -0
  9. package/.server/server/constants.js.map +1 -1
  10. package/.server/server/forms/payment-test.yaml +42 -0
  11. package/.server/server/forms/register-as-a-unicorn-breeder.yaml +14 -0
  12. package/.server/server/plugins/engine/components/FormComponent.d.ts +1 -0
  13. package/.server/server/plugins/engine/components/FormComponent.js +1 -0
  14. package/.server/server/plugins/engine/components/FormComponent.js.map +1 -1
  15. package/.server/server/plugins/engine/components/PaymentField.d.ts +135 -0
  16. package/.server/server/plugins/engine/components/PaymentField.js +228 -0
  17. package/.server/server/plugins/engine/components/PaymentField.js.map +1 -0
  18. package/.server/server/plugins/engine/components/PaymentField.types.d.ts +21 -0
  19. package/.server/server/plugins/engine/components/PaymentField.types.js +2 -0
  20. package/.server/server/plugins/engine/components/PaymentField.types.js.map +1 -0
  21. package/.server/server/plugins/engine/components/UkAddressField.d.ts +1 -1
  22. package/.server/server/plugins/engine/components/UkAddressField.js +3 -1
  23. package/.server/server/plugins/engine/components/UkAddressField.js.map +1 -1
  24. package/.server/server/plugins/engine/components/helpers/components.d.ts +1 -1
  25. package/.server/server/plugins/engine/components/helpers/components.js +3 -0
  26. package/.server/server/plugins/engine/components/helpers/components.js.map +1 -1
  27. package/.server/server/plugins/engine/components/index.d.ts +1 -0
  28. package/.server/server/plugins/engine/components/index.js +1 -0
  29. package/.server/server/plugins/engine/components/index.js.map +1 -1
  30. package/.server/server/plugins/engine/helpers.d.ts +1 -0
  31. package/.server/server/plugins/engine/models/SummaryViewModel.d.ts +3 -0
  32. package/.server/server/plugins/engine/models/SummaryViewModel.js +7 -0
  33. package/.server/server/plugins/engine/models/SummaryViewModel.js.map +1 -1
  34. package/.server/server/plugins/engine/outputFormatters/human/v1.js +34 -1
  35. package/.server/server/plugins/engine/outputFormatters/human/v1.js.map +1 -1
  36. package/.server/server/plugins/engine/outputFormatters/machine/v2.d.ts +22 -0
  37. package/.server/server/plugins/engine/outputFormatters/machine/v2.js +43 -1
  38. package/.server/server/plugins/engine/outputFormatters/machine/v2.js.map +1 -1
  39. package/.server/server/plugins/engine/pageControllers/QuestionPageController.js +29 -8
  40. package/.server/server/plugins/engine/pageControllers/QuestionPageController.js.map +1 -1
  41. package/.server/server/plugins/engine/pageControllers/StartPageController.d.ts +2 -0
  42. package/.server/server/plugins/engine/pageControllers/SummaryPageController.d.ts +17 -0
  43. package/.server/server/plugins/engine/pageControllers/SummaryPageController.js +173 -51
  44. package/.server/server/plugins/engine/pageControllers/SummaryPageController.js.map +1 -1
  45. package/.server/server/plugins/engine/pageControllers/errors.d.ts +31 -0
  46. package/.server/server/plugins/engine/pageControllers/errors.js +59 -2
  47. package/.server/server/plugins/engine/pageControllers/errors.js.map +1 -1
  48. package/.server/server/plugins/engine/pageControllers/helpers/submission.d.ts +27 -0
  49. package/.server/server/plugins/engine/pageControllers/helpers/submission.js +77 -0
  50. package/.server/server/plugins/engine/pageControllers/helpers/submission.js.map +1 -0
  51. package/.server/server/plugins/engine/plugin.js +4 -1
  52. package/.server/server/plugins/engine/plugin.js.map +1 -1
  53. package/.server/server/plugins/engine/routes/index.js +8 -4
  54. package/.server/server/plugins/engine/routes/index.js.map +1 -1
  55. package/.server/server/plugins/engine/routes/payment-helper.d.ts +14 -0
  56. package/.server/server/plugins/engine/routes/payment-helper.js +41 -0
  57. package/.server/server/plugins/engine/routes/payment-helper.js.map +1 -0
  58. package/.server/server/plugins/engine/routes/payment-helper.test.js +81 -0
  59. package/.server/server/plugins/engine/routes/payment-helper.test.js.map +1 -0
  60. package/.server/server/plugins/engine/routes/payment.d.ts +8 -0
  61. package/.server/server/plugins/engine/routes/payment.js +140 -0
  62. package/.server/server/plugins/engine/routes/payment.js.map +1 -0
  63. package/.server/server/plugins/engine/routes/payment.test.js +187 -0
  64. package/.server/server/plugins/engine/routes/payment.test.js.map +1 -0
  65. package/.server/server/plugins/engine/services/localFormsService.js +6 -0
  66. package/.server/server/plugins/engine/services/localFormsService.js.map +1 -1
  67. package/.server/server/plugins/engine/types/schema.js +7 -0
  68. package/.server/server/plugins/engine/types/schema.js.map +1 -1
  69. package/.server/server/plugins/engine/types.d.ts +19 -1
  70. package/.server/server/plugins/engine/types.js +4 -0
  71. package/.server/server/plugins/engine/types.js.map +1 -1
  72. package/.server/server/plugins/engine/validationHelpers.d.ts +1 -1
  73. package/.server/server/plugins/engine/validationHelpers.js.map +1 -1
  74. package/.server/server/plugins/engine/views/components/paymentfield.html +42 -0
  75. package/.server/server/plugins/engine/views/index.html +9 -1
  76. package/.server/server/plugins/engine/views/partials/form.html +20 -5
  77. package/.server/server/plugins/engine/views/summary.html +17 -1
  78. package/.server/server/plugins/nunjucks/filters/field.d.ts +1 -1
  79. package/.server/server/plugins/payment/helper.d.ts +30 -0
  80. package/.server/server/plugins/payment/helper.js +49 -0
  81. package/.server/server/plugins/payment/helper.js.map +1 -0
  82. package/.server/server/plugins/payment/helper.test.js +37 -0
  83. package/.server/server/plugins/payment/helper.test.js.map +1 -0
  84. package/.server/server/plugins/payment/service.d.ts +40 -0
  85. package/.server/server/plugins/payment/service.js +129 -0
  86. package/.server/server/plugins/payment/service.js.map +1 -0
  87. package/.server/server/plugins/payment/service.test.js +162 -0
  88. package/.server/server/plugins/payment/service.test.js.map +1 -0
  89. package/.server/server/plugins/payment/types.d.ts +172 -0
  90. package/.server/server/plugins/payment/types.js +78 -0
  91. package/.server/server/plugins/payment/types.js.map +1 -0
  92. package/.server/server/types.d.ts +2 -0
  93. package/.server/server/types.js.map +1 -1
  94. package/.server/typings/hapi/index.d.js.map +1 -1
  95. package/README.md +12 -9
  96. package/package.json +2 -2
  97. package/src/client/stylesheets/_payment-field.scss +8 -0
  98. package/src/client/stylesheets/application.scss +2 -0
  99. package/src/index.ts +5 -1
  100. package/src/server/constants.js +1 -0
  101. package/src/server/forms/payment-test.yaml +42 -0
  102. package/src/server/forms/register-as-a-unicorn-breeder.yaml +14 -0
  103. package/src/server/plugins/engine/components/FormComponent.ts +1 -0
  104. package/src/server/plugins/engine/components/PaymentField.test.ts +611 -0
  105. package/src/server/plugins/engine/components/PaymentField.ts +367 -0
  106. package/src/server/plugins/engine/components/PaymentField.types.ts +21 -0
  107. package/src/server/plugins/engine/components/UkAddressField.ts +2 -1
  108. package/src/server/plugins/engine/components/helpers/components.ts +5 -0
  109. package/src/server/plugins/engine/components/index.ts +1 -0
  110. package/src/server/plugins/engine/models/SummaryViewModel.ts +8 -0
  111. package/src/server/plugins/engine/outputFormatters/human/v1.payment.test.ts +147 -0
  112. package/src/server/plugins/engine/outputFormatters/human/v1.test.ts +105 -103
  113. package/src/server/plugins/engine/outputFormatters/human/v1.ts +61 -2
  114. package/src/server/plugins/engine/outputFormatters/machine/v2.payment.test.ts +115 -0
  115. package/src/server/plugins/engine/outputFormatters/machine/v2.ts +60 -1
  116. package/src/server/plugins/engine/pageControllers/QuestionPageController.ts +32 -6
  117. package/src/server/plugins/engine/pageControllers/SummaryPageController.ts +247 -72
  118. package/src/server/plugins/engine/pageControllers/errors.test.ts +13 -1
  119. package/src/server/plugins/engine/pageControllers/errors.ts +79 -4
  120. package/src/server/plugins/engine/pageControllers/helpers/submission.test.ts +299 -0
  121. package/src/server/plugins/engine/pageControllers/helpers/submission.ts +110 -0
  122. package/src/server/plugins/engine/plugin.ts +11 -6
  123. package/src/server/plugins/engine/routes/index.ts +17 -16
  124. package/src/server/plugins/engine/routes/payment-helper.js +39 -0
  125. package/src/server/plugins/engine/routes/payment-helper.test.js +90 -0
  126. package/src/server/plugins/engine/routes/payment.js +151 -0
  127. package/src/server/plugins/engine/routes/payment.test.js +180 -0
  128. package/src/server/plugins/engine/services/localFormsService.js +7 -0
  129. package/src/server/plugins/engine/types/schema.ts +9 -0
  130. package/src/server/plugins/engine/types.ts +24 -1
  131. package/src/server/plugins/engine/validationHelpers.ts +1 -1
  132. package/src/server/plugins/engine/views/components/paymentfield.html +42 -0
  133. package/src/server/plugins/engine/views/index.html +9 -1
  134. package/src/server/plugins/engine/views/partials/form.html +20 -5
  135. package/src/server/plugins/engine/views/summary.html +17 -1
  136. package/src/server/plugins/payment/helper.js +56 -0
  137. package/src/server/plugins/payment/helper.test.js +52 -0
  138. package/src/server/plugins/payment/service.js +171 -0
  139. package/src/server/plugins/payment/service.test.js +205 -0
  140. package/src/server/plugins/payment/types.js +77 -0
  141. package/src/server/types.ts +2 -0
  142. package/src/typings/hapi/index.d.ts +1 -0
@@ -0,0 +1,172 @@
1
+ export type PaymentResponseState = {
2
+ /**
3
+ * - Current status of the payment
4
+ */
5
+ status: "created" | "started" | "submitted" | "capturable" | "success" | "failed" | "cancelled" | "error";
6
+ /**
7
+ * - Whether the payment process has completed
8
+ */
9
+ finished: boolean;
10
+ /**
11
+ * - Human-readable message about the payment state
12
+ */
13
+ message?: string | undefined;
14
+ /**
15
+ * - Error or status code for the payment state
16
+ */
17
+ code?: string | undefined;
18
+ };
19
+ export type PaymentLink = {
20
+ /**
21
+ * - URL of the linked resource
22
+ */
23
+ href: string;
24
+ /**
25
+ * - HTTP method to use for the link
26
+ */
27
+ method: string;
28
+ };
29
+ export type CreatePaymentRequest = {
30
+ /**
31
+ * - Payment amount in pence
32
+ */
33
+ amount: number;
34
+ /**
35
+ * - Unique reference for the payment
36
+ */
37
+ reference: string;
38
+ /**
39
+ * - Human-readable description of the payment
40
+ */
41
+ description: string;
42
+ /**
43
+ * - URL to redirect the user to after payment
44
+ */
45
+ return_url: string;
46
+ /**
47
+ * - Whether to delay capturing the payment
48
+ */
49
+ delayed_capture?: boolean | undefined;
50
+ /**
51
+ * - Additional metadata for the payment
52
+ */
53
+ metadata?: {
54
+ formId: string;
55
+ slug: string;
56
+ } | undefined;
57
+ };
58
+ export type CreatePaymentResponse = {
59
+ /**
60
+ * - Unique identifier for the created payment
61
+ */
62
+ payment_id: string;
63
+ /**
64
+ * - Current state of the payment
65
+ */
66
+ state: PaymentResponseState;
67
+ /**
68
+ * - HATEOAS links for the payment
69
+ */
70
+ _links: {
71
+ next_url: PaymentLink;
72
+ };
73
+ };
74
+ /**
75
+ * Base response from GOV.UK Pay GET /v1/payments/{PAYMENT_ID} endpoint
76
+ */
77
+ export type GetPaymentResponseBase = {
78
+ /**
79
+ * - Current state of the payment
80
+ */
81
+ state: PaymentResponseState;
82
+ /**
83
+ * - HATEOAS links for the payment
84
+ */
85
+ _links: {
86
+ self: PaymentLink;
87
+ next_url?: PaymentLink;
88
+ };
89
+ /**
90
+ * - The paying user's email address
91
+ */
92
+ email?: string | undefined;
93
+ };
94
+ /**
95
+ * Response from GOV.UK Pay GET /v1/payments/{PAYMENT_ID} endpoint - not underscore in property name
96
+ */
97
+ export type GetPaymentApiResponsePaymentProp = {
98
+ /**
99
+ * - Unique identifier for the payment
100
+ */
101
+ payment_id: string;
102
+ /**
103
+ * - amount of the payment
104
+ */
105
+ amount: number;
106
+ };
107
+ /**
108
+ * Response from GOV.UK Pay GET /v1/payments/{PAYMENT_ID} endpoint
109
+ */
110
+ export type GetPaymentApiResponse = GetPaymentResponseBase & GetPaymentApiResponsePaymentProp;
111
+ /**
112
+ * Response returned from getPaymentStatus - subtley different from GetPaymentApiResponse
113
+ */
114
+ export type GetPaymentResponsePaymentProp = {
115
+ /**
116
+ * - Unique identifier for the payment - note no underscore in property name
117
+ */
118
+ paymentId: string;
119
+ /**
120
+ * - amount of the payment
121
+ */
122
+ amount: number;
123
+ };
124
+ /**
125
+ * Response returned from getPaymentStatus - subtley different from GetPaymentApiResponse
126
+ */
127
+ export type GetPaymentResponse = GetPaymentResponseBase & GetPaymentResponsePaymentProp;
128
+ /**
129
+ * Payment session data stored when dispatching to GOV.UK Pay
130
+ */
131
+ export type PaymentSessionData = {
132
+ /**
133
+ * - unique identifier for this payment attempt
134
+ */
135
+ uuid: string;
136
+ /**
137
+ * - id of the form
138
+ */
139
+ formId: string;
140
+ /**
141
+ * - form reference number
142
+ */
143
+ reference: string;
144
+ /**
145
+ * - amount in pounds
146
+ */
147
+ amount: number;
148
+ /**
149
+ * - payment description
150
+ */
151
+ description: string;
152
+ /**
153
+ * - GOV.UK Pay payment ID
154
+ */
155
+ paymentId: string;
156
+ /**
157
+ * - name of the PaymentField component
158
+ */
159
+ componentName: string;
160
+ /**
161
+ * - URL to redirect to after successful payment
162
+ */
163
+ returnUrl: string;
164
+ /**
165
+ * - URL to redirect to after failed/cancelled payment
166
+ */
167
+ failureUrl: string;
168
+ /**
169
+ * - whether the payment is using live API key
170
+ */
171
+ isLivePayment: boolean;
172
+ };
@@ -0,0 +1,78 @@
1
+ /**
2
+ * @typedef {object} PaymentResponseState
3
+ * @property {'created' | 'started' | 'submitted' | 'capturable' | 'success' | 'failed' | 'cancelled' | 'error'} status - Current status of the payment
4
+ * @property {boolean} finished - Whether the payment process has completed
5
+ * @property {string} [message] - Human-readable message about the payment state
6
+ * @property {string} [code] - Error or status code for the payment state
7
+ */
8
+
9
+ /**
10
+ * @typedef {object} PaymentLink
11
+ * @property {string} href - URL of the linked resource
12
+ * @property {string} method - HTTP method to use for the link
13
+ */
14
+
15
+ /**
16
+ * @typedef {object} CreatePaymentRequest
17
+ * @property {number} amount - Payment amount in pence
18
+ * @property {string} reference - Unique reference for the payment
19
+ * @property {string} description - Human-readable description of the payment
20
+ * @property {string} return_url - URL to redirect the user to after payment
21
+ * @property {boolean} [delayed_capture] - Whether to delay capturing the payment
22
+ * @property {{ formId: string, slug: string }} [metadata] - Additional metadata for the payment
23
+ */
24
+
25
+ /**
26
+ * @typedef {object} CreatePaymentResponse
27
+ * @property {string} payment_id - Unique identifier for the created payment
28
+ * @property {PaymentResponseState} state - Current state of the payment
29
+ * @property {{ next_url: PaymentLink }} _links - HATEOAS links for the payment
30
+ */
31
+
32
+ /**
33
+ * Base response from GOV.UK Pay GET /v1/payments/{PAYMENT_ID} endpoint
34
+ * @typedef {object} GetPaymentResponseBase
35
+ * @property {PaymentResponseState} state - Current state of the payment
36
+ * @property {{ self: PaymentLink, next_url?: PaymentLink }} _links - HATEOAS links for the payment
37
+ * @property {string} [email] - The paying user's email address
38
+ */
39
+
40
+ /**
41
+ * Response from GOV.UK Pay GET /v1/payments/{PAYMENT_ID} endpoint - not underscore in property name
42
+ * @typedef {object} GetPaymentApiResponsePaymentProp
43
+ * @property {string} payment_id - Unique identifier for the payment
44
+ * @property {number} amount - amount of the payment
45
+ */
46
+
47
+ /**
48
+ * Response from GOV.UK Pay GET /v1/payments/{PAYMENT_ID} endpoint
49
+ * @typedef {GetPaymentResponseBase & GetPaymentApiResponsePaymentProp} GetPaymentApiResponse
50
+ */
51
+
52
+ /**
53
+ * Response returned from getPaymentStatus - subtley different from GetPaymentApiResponse
54
+ * @typedef {object} GetPaymentResponsePaymentProp
55
+ * @property {string} paymentId - Unique identifier for the payment - note no underscore in property name
56
+ * @property {number} amount - amount of the payment
57
+ */
58
+
59
+ /**
60
+ * Response returned from getPaymentStatus - subtley different from GetPaymentApiResponse
61
+ * @typedef {GetPaymentResponseBase & GetPaymentResponsePaymentProp} GetPaymentResponse
62
+ */
63
+
64
+ /**
65
+ * Payment session data stored when dispatching to GOV.UK Pay
66
+ * @typedef {object} PaymentSessionData
67
+ * @property {string} uuid - unique identifier for this payment attempt
68
+ * @property {string} formId - id of the form
69
+ * @property {string} reference - form reference number
70
+ * @property {number} amount - amount in pounds
71
+ * @property {string} description - payment description
72
+ * @property {string} paymentId - GOV.UK Pay payment ID
73
+ * @property {string} componentName - name of the PaymentField component
74
+ * @property {string} returnUrl - URL to redirect to after successful payment
75
+ * @property {string} failureUrl - URL to redirect to after failed/cancelled payment
76
+ * @property {boolean} isLivePayment - whether the payment is using live API key
77
+ */
78
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","names":[],"sources":["../../../../src/server/plugins/payment/types.js"],"sourcesContent":["/**\n * @typedef {object} PaymentResponseState\n * @property {'created' | 'started' | 'submitted' | 'capturable' | 'success' | 'failed' | 'cancelled' | 'error'} status - Current status of the payment\n * @property {boolean} finished - Whether the payment process has completed\n * @property {string} [message] - Human-readable message about the payment state\n * @property {string} [code] - Error or status code for the payment state\n */\n\n/**\n * @typedef {object} PaymentLink\n * @property {string} href - URL of the linked resource\n * @property {string} method - HTTP method to use for the link\n */\n\n/**\n * @typedef {object} CreatePaymentRequest\n * @property {number} amount - Payment amount in pence\n * @property {string} reference - Unique reference for the payment\n * @property {string} description - Human-readable description of the payment\n * @property {string} return_url - URL to redirect the user to after payment\n * @property {boolean} [delayed_capture] - Whether to delay capturing the payment\n * @property {{ formId: string, slug: string }} [metadata] - Additional metadata for the payment\n */\n\n/**\n * @typedef {object} CreatePaymentResponse\n * @property {string} payment_id - Unique identifier for the created payment\n * @property {PaymentResponseState} state - Current state of the payment\n * @property {{ next_url: PaymentLink }} _links - HATEOAS links for the payment\n */\n\n/**\n * Base response from GOV.UK Pay GET /v1/payments/{PAYMENT_ID} endpoint\n * @typedef {object} GetPaymentResponseBase\n * @property {PaymentResponseState} state - Current state of the payment\n * @property {{ self: PaymentLink, next_url?: PaymentLink }} _links - HATEOAS links for the payment\n * @property {string} [email] - The paying user's email address\n */\n\n/**\n * Response from GOV.UK Pay GET /v1/payments/{PAYMENT_ID} endpoint - not underscore in property name\n * @typedef {object} GetPaymentApiResponsePaymentProp\n * @property {string} payment_id - Unique identifier for the payment\n * @property {number} amount - amount of the payment\n */\n\n/**\n * Response from GOV.UK Pay GET /v1/payments/{PAYMENT_ID} endpoint\n * @typedef {GetPaymentResponseBase & GetPaymentApiResponsePaymentProp} GetPaymentApiResponse\n */\n\n/**\n * Response returned from getPaymentStatus - subtley different from GetPaymentApiResponse\n * @typedef {object} GetPaymentResponsePaymentProp\n * @property {string} paymentId - Unique identifier for the payment - note no underscore in property name\n * @property {number} amount - amount of the payment\n */\n\n/**\n * Response returned from getPaymentStatus - subtley different from GetPaymentApiResponse\n * @typedef {GetPaymentResponseBase & GetPaymentResponsePaymentProp} GetPaymentResponse\n */\n\n/**\n * Payment session data stored when dispatching to GOV.UK Pay\n * @typedef {object} PaymentSessionData\n * @property {string} uuid - unique identifier for this payment attempt\n * @property {string} formId - id of the form\n * @property {string} reference - form reference number\n * @property {number} amount - amount in pounds\n * @property {string} description - payment description\n * @property {string} paymentId - GOV.UK Pay payment ID\n * @property {string} componentName - name of the PaymentField component\n * @property {string} returnUrl - URL to redirect to after successful payment\n * @property {string} failureUrl - URL to redirect to after failed/cancelled payment\n * @property {boolean} isLivePayment - whether the payment is using live API key\n */\n"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA","ignoreList":[]}
@@ -4,6 +4,7 @@ import { type FormModel } from '~/src/server/plugins/engine/models/index.js';
4
4
  import { type DetailItem } from '~/src/server/plugins/engine/models/types.js';
5
5
  import { type PageController } from '~/src/server/plugins/engine/pageControllers/PageController.js';
6
6
  import { type FormContext, type OnRequestCallback, type PluginOptions, type PreparePageEventRequestOptions } from '~/src/server/plugins/engine/types.js';
7
+ import { type PaymentService } from '~/src/server/plugins/payment/service.js';
7
8
  import { type FormRequestPayload, type FormStatus } from '~/src/server/routes/types.js';
8
9
  import { type CacheService } from '~/src/server/services/cacheService.js';
9
10
  export interface FormsService {
@@ -22,6 +23,7 @@ export interface Services {
22
23
  formsService: FormsService;
23
24
  formSubmissionService: FormSubmissionService;
24
25
  outputService: OutputService;
26
+ paymentService?: PaymentService;
25
27
  }
26
28
  export interface RouteConfig {
27
29
  formFileName?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","names":[],"sources":["../../src/server/types.ts"],"sourcesContent":["import {\n type FormDefinition,\n type FormMetadata,\n type SubmitPayload,\n type SubmitResponsePayload\n} from '@defra/forms-model'\nimport { type Server } from '@hapi/hapi'\n\nimport { type FormModel } from '~/src/server/plugins/engine/models/index.js'\nimport { type DetailItem } from '~/src/server/plugins/engine/models/types.js'\nimport { type PageController } from '~/src/server/plugins/engine/pageControllers/PageController.js'\nimport {\n type FormContext,\n type OnRequestCallback,\n type PluginOptions,\n type PreparePageEventRequestOptions\n} from '~/src/server/plugins/engine/types.js'\nimport {\n type FormRequestPayload,\n type FormStatus\n} from '~/src/server/routes/types.js'\nimport { type CacheService } from '~/src/server/services/cacheService.js'\n\nexport interface FormsService {\n getFormMetadata: (slug: string) => Promise<FormMetadata>\n getFormMetadataById: (id: string) => Promise<FormMetadata>\n getFormDefinition: (\n id: string,\n state: FormStatus\n ) => Promise<FormDefinition | undefined>\n}\n\nexport interface FormSubmissionService {\n persistFiles: (\n files: { fileId: string; initiatedRetrievalKey: string }[],\n persistedRetrievalKey: string\n ) => Promise<object>\n submit: (data: SubmitPayload) => Promise<SubmitResponsePayload | undefined>\n}\n\nexport interface Services {\n formsService: FormsService\n formSubmissionService: FormSubmissionService\n outputService: OutputService\n}\n\nexport interface RouteConfig {\n formFileName?: string\n formFilePath?: string\n enforceCsrf?: boolean\n services?: Services\n controllers?: Record<string, typeof PageController>\n preparePageEventRequestOptions?: PreparePageEventRequestOptions\n onRequest?: OnRequestCallback\n saveAndExit?: PluginOptions['saveAndExit']\n cacheServiceCreator?: (server: Server) => CacheService\n ordnanceSurveyApiKey?: string\n ordnanceSurveyApiSecret?: string\n}\n\nexport interface OutputService {\n submit: (\n context: FormContext,\n request: FormRequestPayload,\n model: FormModel,\n emailAddress: string,\n items: DetailItem[],\n submitResponse: SubmitResponsePayload,\n formMetadata?: FormMetadata\n ) => Promise<void>\n}\n"],"mappings":"","ignoreList":[]}
1
+ {"version":3,"file":"types.js","names":[],"sources":["../../src/server/types.ts"],"sourcesContent":["import {\n type FormDefinition,\n type FormMetadata,\n type SubmitPayload,\n type SubmitResponsePayload\n} from '@defra/forms-model'\nimport { type Server } from '@hapi/hapi'\n\nimport { type FormModel } from '~/src/server/plugins/engine/models/index.js'\nimport { type DetailItem } from '~/src/server/plugins/engine/models/types.js'\nimport { type PageController } from '~/src/server/plugins/engine/pageControllers/PageController.js'\nimport {\n type FormContext,\n type OnRequestCallback,\n type PluginOptions,\n type PreparePageEventRequestOptions\n} from '~/src/server/plugins/engine/types.js'\nimport { type PaymentService } from '~/src/server/plugins/payment/service.js'\nimport {\n type FormRequestPayload,\n type FormStatus\n} from '~/src/server/routes/types.js'\nimport { type CacheService } from '~/src/server/services/cacheService.js'\n\nexport interface FormsService {\n getFormMetadata: (slug: string) => Promise<FormMetadata>\n getFormMetadataById: (id: string) => Promise<FormMetadata>\n getFormDefinition: (\n id: string,\n state: FormStatus\n ) => Promise<FormDefinition | undefined>\n}\n\nexport interface FormSubmissionService {\n persistFiles: (\n files: { fileId: string; initiatedRetrievalKey: string }[],\n persistedRetrievalKey: string\n ) => Promise<object>\n submit: (data: SubmitPayload) => Promise<SubmitResponsePayload | undefined>\n}\n\nexport interface Services {\n formsService: FormsService\n formSubmissionService: FormSubmissionService\n outputService: OutputService\n paymentService?: PaymentService\n}\n\nexport interface RouteConfig {\n formFileName?: string\n formFilePath?: string\n enforceCsrf?: boolean\n services?: Services\n controllers?: Record<string, typeof PageController>\n preparePageEventRequestOptions?: PreparePageEventRequestOptions\n onRequest?: OnRequestCallback\n saveAndExit?: PluginOptions['saveAndExit']\n cacheServiceCreator?: (server: Server) => CacheService\n ordnanceSurveyApiKey?: string\n ordnanceSurveyApiSecret?: string\n}\n\nexport interface OutputService {\n submit: (\n context: FormContext,\n request: FormRequestPayload,\n model: FormModel,\n emailAddress: string,\n items: DetailItem[],\n submitResponse: SubmitResponsePayload,\n formMetadata?: FormMetadata\n ) => Promise<void>\n}\n"],"mappings":"","ignoreList":[]}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.js","names":[],"sources":["../../../src/typings/hapi/index.d.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/unified-signatures */\n\nimport { type Plugin } from '@hapi/hapi'\nimport { type ServerYar, type Yar } from '@hapi/yar'\nimport { type Logger } from 'pino'\n\nimport {\n type COMPONENT_STATE_ERROR,\n type EXTERNAL_STATE_APPENDAGE,\n type EXTERNAL_STATE_PAYLOAD\n} from '~/src/server/constants.js'\nimport { type FormModel } from '~/src/server/plugins/engine/models/index.js'\nimport {\n type AnyFormRequest,\n type FormSubmissionError,\n type PluginOptions\n} from '~/src/server/plugins/engine/types.ts'\nimport { type CacheService } from '~/src/server/services/index.js'\n\ndeclare module '@hapi/yar' {\n interface YarFlashes {\n [EXTERNAL_STATE_APPENDAGE]: object\n [EXTERNAL_STATE_PAYLOAD]: object\n [COMPONENT_STATE_ERROR]: string\n [key: string]: { errors: FormSubmissionError[] }\n }\n}\n\ndeclare module '@hapi/hapi' {\n // Here we are decorating Hapi interface types with\n // props from plugins which doesn't export @types\n interface PluginProperties {\n crumb: {\n generate?: (request: AnyRequest) => string\n }\n 'forms-engine-plugin': {\n baseLayoutPath: string\n cacheService: CacheService\n viewContext?: (\n request: AnyFormRequest | null\n ) => Record<string, unknown> | Promise<Record<string, unknown>>\n saveAndExit?: PluginOptions['saveAndExit']\n }\n }\n\n interface Request {\n logger: Logger\n yar: Yar\n }\n\n interface RequestApplicationState {\n model?: FormModel\n }\n\n interface Server {\n logger: Logger\n yar: ServerYar\n }\n\n interface ServerApplicationState {\n model?: FormModel\n models: Map<string, { model: FormModel; updatedAt: Date }>\n }\n}\n\ndeclare module 'blankie' {\n declare const blankie: {\n plugin: Plugin<Record<string, boolean | string | string[]>>\n }\n\n export = blankie\n}\n\ndeclare module 'blipp' {\n declare const blipp: {\n plugin: Plugin\n }\n\n export = blipp\n}\n\ndeclare module 'hapi-pulse' {\n declare const hapiPulse: {\n plugin: Plugin<{\n timeout: number\n }>\n }\n\n export = hapiPulse\n}\n"],"mappings":"","ignoreList":[]}
1
+ {"version":3,"file":"index.d.js","names":[],"sources":["../../../src/typings/hapi/index.d.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/unified-signatures */\n\nimport { type Plugin } from '@hapi/hapi'\nimport { type ServerYar, type Yar } from '@hapi/yar'\nimport { type Logger } from 'pino'\n\nimport {\n type COMPONENT_STATE_ERROR,\n type EXTERNAL_STATE_APPENDAGE,\n type EXTERNAL_STATE_PAYLOAD\n} from '~/src/server/constants.js'\nimport { type FormModel } from '~/src/server/plugins/engine/models/index.js'\nimport {\n type AnyFormRequest,\n type FormSubmissionError,\n type PluginOptions\n} from '~/src/server/plugins/engine/types.ts'\nimport { type CacheService } from '~/src/server/services/index.js'\n\ndeclare module '@hapi/yar' {\n interface YarFlashes {\n [EXTERNAL_STATE_APPENDAGE]: object\n [EXTERNAL_STATE_PAYLOAD]: object\n [COMPONENT_STATE_ERROR]: string\n [key: string]: { errors: FormSubmissionError[] }\n }\n}\n\ndeclare module '@hapi/hapi' {\n // Here we are decorating Hapi interface types with\n // props from plugins which doesn't export @types\n interface PluginProperties {\n crumb: {\n generate?: (request: AnyRequest) => string\n }\n 'forms-engine-plugin': {\n baseLayoutPath: string\n cacheService: CacheService\n viewContext?: (\n request: AnyFormRequest | null\n ) => Record<string, unknown> | Promise<Record<string, unknown>>\n saveAndExit?: PluginOptions['saveAndExit']\n baseUrl: string\n }\n }\n\n interface Request {\n logger: Logger\n yar: Yar\n }\n\n interface RequestApplicationState {\n model?: FormModel\n }\n\n interface Server {\n logger: Logger\n yar: ServerYar\n }\n\n interface ServerApplicationState {\n model?: FormModel\n models: Map<string, { model: FormModel; updatedAt: Date }>\n }\n}\n\ndeclare module 'blankie' {\n declare const blankie: {\n plugin: Plugin<Record<string, boolean | string | string[]>>\n }\n\n export = blankie\n}\n\ndeclare module 'blipp' {\n declare const blipp: {\n plugin: Plugin\n }\n\n export = blipp\n}\n\ndeclare module 'hapi-pulse' {\n declare const hapiPulse: {\n plugin: Plugin<{\n timeout: number\n }>\n }\n\n export = hapiPulse\n}\n"],"mappings":"","ignoreList":[]}
package/README.md CHANGED
@@ -6,15 +6,18 @@ It is designed to be embedded in the frontend of a digital service and provide a
6
6
 
7
7
  ## Table of Contents
8
8
 
9
- - [Demo of DXT](#demo-of-dxt)
10
- - [Installation](#installation)
11
- - [Documentation](#documentation)
12
- - [Publishing the Package](#publishing-the-package)
13
- - [Semantic Versioning Control](#semantic-versioning-control)
14
- - [Major-Version Release Branches](#major-version-release-branches)
15
- - [Manual Workflow Triggers](#manual-workflow-triggers)
16
- - [Workflow Triggers](#workflow-triggers)
17
- - [Safety and Consistency](#safety-and-consistency)
9
+ - [@defra/forms-engine-plugin](#defraforms-engine-plugin)
10
+ - [Table of Contents](#table-of-contents)
11
+ - [Demo of DXT](#demo-of-dxt)
12
+ - [Installation](#installation)
13
+ - [Documentation](#documentation)
14
+ - [Contributing](#contributing)
15
+ - [Publishing the package](#publishing-the-package)
16
+ - [Semantic Versioning Control](#semantic-versioning-control)
17
+ - [Major-Version Release Branches](#major-version-release-branches)
18
+ - [Manual Workflow Triggers](#manual-workflow-triggers)
19
+ - [Workflow Triggers](#workflow-triggers)
20
+ - [Safety and Consistency](#safety-and-consistency)
18
21
 
19
22
  ## Demo of DXT
20
23
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@defra/forms-engine-plugin",
3
- "version": "4.0.43",
3
+ "version": "4.0.44",
4
4
  "description": "Defra forms engine",
5
5
  "type": "module",
6
6
  "files": [
@@ -70,7 +70,7 @@
70
70
  },
71
71
  "license": "SEE LICENSE IN LICENSE",
72
72
  "dependencies": {
73
- "@defra/forms-model": "^3.0.603",
73
+ "@defra/forms-model": "^3.0.611",
74
74
  "@defra/hapi-tracing": "^1.29.0",
75
75
  "@defra/interactive-map": "^0.0.3-alpha",
76
76
  "@elastic/ecs-pino-format": "^1.5.0",
@@ -0,0 +1,8 @@
1
+ @use "govuk-frontend" as *;
2
+
3
+ .app-payment-field {
4
+ background-color: govuk-colour("light-grey");
5
+ border-top: 5px solid govuk-colour("blue");
6
+ padding: govuk-spacing(4);
7
+ margin-bottom: govuk-spacing(6);
8
+ }
@@ -2,6 +2,8 @@
2
2
  @use "shared";
3
3
  @use "code";
4
4
  @use "tag-env";
5
+ @use "location-fields";
6
+ @use "payment-field";
5
7
 
6
8
  // An example of some user-supplied styling
7
9
  // Not great practice but it illustrates the point
package/src/index.ts CHANGED
@@ -23,7 +23,11 @@ const ordnanceSurveyApiKey = config.get('ordnanceSurveyApiKey')
23
23
  * Main entrypoint to the application.
24
24
  */
25
25
  async function startServer() {
26
- const server = await createServer({ ordnanceSurveyApiKey })
26
+ const server = await createServer({
27
+ ordnanceSurveyApiKey,
28
+ // Enable save and exit for devserver
29
+ saveAndExit: (_request, h) => h.redirect('/')
30
+ })
27
31
  await server.start()
28
32
 
29
33
  process.send?.('online')
@@ -3,3 +3,4 @@ export const FORM_PREFIX = ''
3
3
  export const EXTERNAL_STATE_PAYLOAD = 'EXTERNAL_STATE_PAYLOAD'
4
4
  export const EXTERNAL_STATE_APPENDAGE = 'EXTERNAL_STATE_APPENDAGE'
5
5
  export const COMPONENT_STATE_ERROR = 'COMPONENT_STATE_ERROR'
6
+ export const PAYMENT_EXPIRED_NOTIFICATION = 'PAYMENT_EXPIRED_NOTIFICATION'
@@ -0,0 +1,42 @@
1
+ ---
2
+ schema: 2
3
+ name: Payment Test Form
4
+ declaration: "<p class=\"govuk-body\">All the answers you have provided are true to the best of your knowledge.</p>"
5
+ pages:
6
+ - title: What is your name?
7
+ path: '/person'
8
+ components:
9
+ - name: personName
10
+ title: What is your name?
11
+ type: TextField
12
+ shortDescription: Your name
13
+ options:
14
+ required: true
15
+ next:
16
+ - path: '/pay-for-your-licence'
17
+ - title: A page title
18
+ path: '/pay-for-your-licence'
19
+ components:
20
+ - name: pageGuidance
21
+ type: Html
22
+ title: Guidance
23
+ content: "<p class=\"govuk-body\">Random guidance</p>"
24
+ options: {}
25
+ - name: licencePayment
26
+ title: Payment details required
27
+ type: PaymentField
28
+ options:
29
+ required: true
30
+ amount: 300
31
+ description: Processing fee for your application.
32
+ next:
33
+ - path: '/summary'
34
+ - title: Summary
35
+ path: '/summary'
36
+ controller: './pages/summary.js'
37
+ components: []
38
+ next: []
39
+ conditions: []
40
+ sections: []
41
+ lists: []
42
+ startPage: '/person'
@@ -242,6 +242,20 @@ pages:
242
242
  content: 'Fill in this field'
243
243
  options:
244
244
  required: false
245
+ next:
246
+ - path: '/pay-for-your-licence'
247
+ - title: Pay for your licence
248
+ path: '/pay-for-your-licence'
249
+ section: section
250
+ components:
251
+ - name: licencePayment
252
+ title: Unicorn breeder licence fee
253
+ type: PaymentField
254
+ hint: You'll be redirected to GOV.UK Pay to complete your payment
255
+ options:
256
+ required: true
257
+ amount: 50
258
+ description: Unicorn breeder annual licence fee
245
259
  next:
246
260
  - path: '/summary'
247
261
  conditions:
@@ -30,6 +30,7 @@ export class FormComponent extends ComponentBase {
30
30
  label: string
31
31
 
32
32
  isFormComponent = true
33
+ isAppendageStateSingleObject = false
33
34
 
34
35
  constructor(
35
36
  def: FormComponentsDef,