@defra/fcp-sfd-frontend-engine 0.9.0 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -31,12 +31,106 @@ var index_exports = {};
31
31
  __export(index_exports, {
32
32
  constants: () => constants,
33
33
  mappers: () => mappers,
34
+ mutations: () => mutations,
34
35
  presenters: () => presenters,
35
36
  schemas: () => schemas,
36
37
  utils: () => utils
37
38
  });
38
39
  module.exports = __toCommonJS(index_exports);
39
40
 
41
+ // src/constants/validation-fields.js
42
+ var FIRST_NAME_MAX = 100;
43
+ var LAST_NAME_MAX = 100;
44
+ var MIDDLE_NAMES_MAX = 100;
45
+ var BUSINESS_NAME_MAX = 160;
46
+ var EMAIL_MAX = 254;
47
+ var PHONE_NUMBER_MIN = 10;
48
+ var PHONE_NUMBER_MAX = 50;
49
+ var MAX_AGE_YEARS = 120;
50
+ var ADDRESS_LINE_MAX = 100;
51
+ var TOWN_CITY_MAX = 60;
52
+ var COUNTY_MAX = 60;
53
+ var COUNTRY_MAX = 60;
54
+ var POSTCODE_MAX = 8;
55
+
56
+ // src/constants/status-codes.js
57
+ var OK = 200;
58
+ var BAD_REQUEST = 400;
59
+ var UNAUTHORIZED = 401;
60
+ var FORBIDDEN = 403;
61
+ var NOT_FOUND = 404;
62
+ var NO_CONTENT = 204;
63
+ var FOUND = 302;
64
+ var INTERNAL_SERVER_ERROR = 500;
65
+ var SERVICE_UNAVAILABLE = 503;
66
+
67
+ // src/constants/patterns.js
68
+ var PHONE_NUMBER_PATTERN = /^\+?(?=[\d ()]*\d)[\d ()]*$/;
69
+ var NO_CONTROL_CHARS_PATTERN = /^[^\x00-\x1f\x7f-\x9f]*$/;
70
+
71
+ // src/constants/month-map.js
72
+ var MONTH_MAP = {
73
+ january: 1,
74
+ jan: 1,
75
+ february: 2,
76
+ feb: 2,
77
+ march: 3,
78
+ mar: 3,
79
+ april: 4,
80
+ apr: 4,
81
+ may: 5,
82
+ june: 6,
83
+ jun: 6,
84
+ july: 7,
85
+ jul: 7,
86
+ august: 8,
87
+ aug: 8,
88
+ september: 9,
89
+ sep: 9,
90
+ sept: 9,
91
+ october: 10,
92
+ oct: 10,
93
+ november: 11,
94
+ nov: 11,
95
+ december: 12,
96
+ dec: 12
97
+ };
98
+
99
+ // src/constants/index.js
100
+ var constants = {
101
+ statusCodes: {
102
+ BAD_REQUEST,
103
+ UNAUTHORIZED,
104
+ FORBIDDEN,
105
+ NOT_FOUND,
106
+ OK,
107
+ NO_CONTENT,
108
+ FOUND,
109
+ INTERNAL_SERVER_ERROR,
110
+ SERVICE_UNAVAILABLE
111
+ },
112
+ validationFields: {
113
+ FIRST_NAME_MAX,
114
+ LAST_NAME_MAX,
115
+ MIDDLE_NAMES_MAX,
116
+ BUSINESS_NAME_MAX,
117
+ EMAIL_MAX,
118
+ PHONE_NUMBER_MIN,
119
+ PHONE_NUMBER_MAX,
120
+ MAX_AGE_YEARS,
121
+ ADDRESS_LINE_MAX,
122
+ TOWN_CITY_MAX,
123
+ COUNTY_MAX,
124
+ COUNTRY_MAX,
125
+ POSTCODE_MAX
126
+ },
127
+ patterns: {
128
+ PHONE_NUMBER_PATTERN,
129
+ NO_CONTROL_CHARS_PATTERN
130
+ },
131
+ monthMap: MONTH_MAP
132
+ };
133
+
40
134
  // src/mappers/personal-business-details-mapper.js
41
135
  var mapPersonalBusinessDetails = (value) => {
42
136
  return {
@@ -130,14 +224,201 @@ var mappers = {
130
224
  businessDetails: mapBusinessDetails
131
225
  };
132
226
 
133
- // src/utils/joi.js
134
- var import_joi = __toESM(require("joi"), 1);
227
+ // src/mutations/personal/update-customer-name.js
228
+ var updateCustomerNameMutation = `
229
+ mutation UpdateCustomerName($input: UpdateCustomerNameInput!) {
230
+ updateCustomerName(input: $input) {
231
+ customer {
232
+ info {
233
+ name {
234
+ first
235
+ last
236
+ middle
237
+ }
238
+ }
239
+ }
240
+ }
241
+ }
242
+ `;
135
243
 
136
- // src/constants/patterns.js
137
- var PHONE_NUMBER_PATTERN = /^\+?(?=[\d ()]*\d)[\d ()]*$/;
138
- var NO_CONTROL_CHARS_PATTERN = /^[^\x00-\x1f\x7f-\x9f]*$/;
244
+ // src/mutations/mutations.js
245
+ var mutations = {
246
+ updateCustomerName: updateCustomerNameMutation
247
+ };
248
+
249
+ // src/presenters/base-presenter.js
250
+ var BACK_LINK_DISPLAY_MAX = 50;
251
+ var formatBackLink = (businessName) => {
252
+ if (businessName.length > BACK_LINK_DISPLAY_MAX) {
253
+ return `Back to ${businessName.slice(0, BACK_LINK_DISPLAY_MAX)}\u2026`;
254
+ }
255
+ return `Back to ${businessName}`;
256
+ };
257
+ var formatNumber = (payloadNumber, changedNumber, originalNumber) => {
258
+ if (payloadNumber !== void 0) {
259
+ return payloadNumber;
260
+ }
261
+ if (changedNumber !== void 0) {
262
+ return changedNumber;
263
+ }
264
+ return originalNumber;
265
+ };
266
+ var formatDisplayAddress = (address) => {
267
+ const { lookup, manual, postcode, country, city } = address;
268
+ let addressLines = [];
269
+ if (lookup.uprn) {
270
+ const buildingAndStreet = [
271
+ lookup.buildingNumberRange,
272
+ lookup.street
273
+ ].filter(Boolean).join(" ");
274
+ addressLines = [
275
+ lookup.pafOrganisationName,
276
+ lookup.flatName,
277
+ lookup.buildingName,
278
+ buildingAndStreet,
279
+ lookup.doubleDependentLocality,
280
+ lookup.dependentLocality,
281
+ city,
282
+ lookup.county
283
+ ];
284
+ } else {
285
+ addressLines = [
286
+ manual.line1,
287
+ manual.line2,
288
+ manual.line3,
289
+ city,
290
+ manual.line4,
291
+ // County
292
+ manual.line5
293
+ ];
294
+ }
295
+ return [
296
+ ...addressLines.filter(Boolean),
297
+ postcode,
298
+ country
299
+ ];
300
+ };
301
+ var buildAddressLine = (parts) => {
302
+ return parts.filter(Boolean).join(", ") || null;
303
+ };
304
+ var buildStreetLine = (buildingRange, street) => {
305
+ return [buildingRange, street].filter(Boolean).join(" ") || null;
306
+ };
307
+ var formatLookupAddress = (lookup, city, country, postcode) => ({
308
+ address1: buildAddressLine([lookup.pafOrganisationName, lookup.flatName, lookup.buildingName]),
309
+ address2: buildStreetLine(lookup.buildingNumberRange, lookup.street),
310
+ address3: buildAddressLine([lookup.doubleDependentLocality, lookup.dependentLocality]),
311
+ county: lookup.county ?? null,
312
+ city: city ?? null,
313
+ country: country ?? null,
314
+ postcode: postcode ?? null
315
+ });
316
+ var formatManualAddress = (manual, city, country, postcode) => ({
317
+ address1: manual.line1 ?? null,
318
+ address2: manual.line2 ?? null,
319
+ address3: manual.line3 ?? null,
320
+ city: city ?? null,
321
+ county: manual.line4 ?? null,
322
+ country: country ?? null,
323
+ postcode: postcode ?? null
324
+ });
325
+ var formatOriginalAddress = (originalAddress) => {
326
+ const { lookup, manual, city, country, postcode } = originalAddress;
327
+ return lookup.uprn ? formatLookupAddress(lookup, city, country, postcode) : formatManualAddress(manual, city, country, postcode);
328
+ };
329
+ var formatChangedAddress = (changeBusinessAddress) => {
330
+ if (!changeBusinessAddress.uprn) {
331
+ return changeBusinessAddress;
332
+ }
333
+ const {
334
+ pafOrganisationName,
335
+ flatName,
336
+ buildingName,
337
+ buildingNumberRange,
338
+ street,
339
+ doubleDependentLocality,
340
+ dependentLocality,
341
+ city,
342
+ county,
343
+ country,
344
+ postcode
345
+ } = changeBusinessAddress;
346
+ return {
347
+ address1: buildAddressLine([pafOrganisationName, flatName, buildingName]),
348
+ address2: buildStreetLine(buildingNumberRange, street),
349
+ address3: buildAddressLine([doubleDependentLocality, dependentLocality]),
350
+ city: city ?? null,
351
+ county: county ?? null,
352
+ country: country ?? null,
353
+ postcode: postcode ?? null
354
+ };
355
+ };
356
+ var formatDisplayAddresses = (addresses, previouslyPickedAddress) => {
357
+ const displayAddresses = addresses.map((address) => ({
358
+ value: `${address.uprn}${address.displayAddress}`,
359
+ text: address.displayAddress,
360
+ selected: (previouslyPickedAddress == null ? void 0 : previouslyPickedAddress.uprn) === address.uprn && (previouslyPickedAddress == null ? void 0 : previouslyPickedAddress.displayAddress) === address.displayAddress
361
+ }));
362
+ const hasSelectedAddress = displayAddresses.some((addr) => addr.selected);
363
+ const text = addresses.length === 1 ? "1 address found" : `${addresses.length} addresses found`;
364
+ displayAddresses.unshift({
365
+ value: "display",
366
+ text,
367
+ selected: !hasSelectedAddress
368
+ });
369
+ return displayAddresses;
370
+ };
371
+ var sortErrorsBySectionOrder = (errors, orderedSectionsToFix, SECTION_FIELD_ORDER) => {
372
+ const sortedErrors = [];
373
+ for (const section of orderedSectionsToFix) {
374
+ const fieldsInSection = SECTION_FIELD_ORDER[section] || [];
375
+ for (const field of fieldsInSection) {
376
+ if (errors[field]) {
377
+ sortedErrors.push({
378
+ field,
379
+ ...errors[field]
380
+ });
381
+ }
382
+ }
383
+ }
384
+ return sortedErrors;
385
+ };
386
+
387
+ // src/presenters/business-details-presenter.js
388
+ var getActionText = (value) => {
389
+ return value ? "Change" : "Add";
390
+ };
391
+ var formatCph = (countyParishHoldings) => {
392
+ return (countyParishHoldings || []).filter((cph) => cph == null ? void 0 : cph.cphNumber).map((cph) => cph.cphNumber);
393
+ };
394
+ var formatCphText = (count) => {
395
+ return `County Parish Holding (CPH) number${count !== 1 ? "s" : ""}`;
396
+ };
397
+ var formatBusinessAddress = (businessAddress) => {
398
+ var _a, _b;
399
+ if (((_a = businessAddress == null ? void 0 : businessAddress.lookup) == null ? void 0 : _a.uprn) || ((_b = businessAddress == null ? void 0 : businessAddress.manual) == null ? void 0 : _b.line1)) {
400
+ return formatDisplayAddress(businessAddress);
401
+ }
402
+ return [];
403
+ };
404
+
405
+ // src/presenters/presenters.js
406
+ var presenters = {
407
+ formatBackLink,
408
+ formatNumber,
409
+ formatDisplayAddress,
410
+ formatOriginalAddress,
411
+ formatChangedAddress,
412
+ formatDisplayAddresses,
413
+ sortErrorsBySectionOrder,
414
+ getActionText,
415
+ formatCph,
416
+ formatCphText,
417
+ formatBusinessAddress
418
+ };
139
419
 
140
420
  // src/utils/joi.js
421
+ var import_joi = __toESM(require("joi"), 1);
141
422
  var Joi = import_joi.default.extend((joi) => ({
142
423
  type: "string",
143
424
  base: joi.string(),
@@ -157,23 +438,8 @@ var businessSbiSchema = Joi.object({
157
438
  sbi: Joi.string().pattern(/^\d{9}$/).allow("").optional().messages({
158
439
  "string.pattern.base": "Enter the full SBI",
159
440
  "string.noControlChars": "SBI must not contain invalid characters"
160
- })
161
- });
162
-
163
- // src/constants/validation-fields.js
164
- var FIRST_NAME_MAX = 100;
165
- var LAST_NAME_MAX = 100;
166
- var MIDDLE_NAMES_MAX = 100;
167
- var BUSINESS_NAME_MAX = 160;
168
- var EMAIL_MAX = 254;
169
- var PHONE_NUMBER_MIN = 10;
170
- var PHONE_NUMBER_MAX = 50;
171
- var MAX_AGE_YEARS = 120;
172
- var ADDRESS_LINE_MAX = 100;
173
- var TOWN_CITY_MAX = 60;
174
- var COUNTY_MAX = 60;
175
- var COUNTRY_MAX = 60;
176
- var POSTCODE_MAX = 8;
441
+ })
442
+ });
177
443
 
178
444
  // src/schemas/shared/address-schema.js
179
445
  var addressSchema = Joi.object({
@@ -266,6 +532,16 @@ var businessVatSchema = Joi.object({
266
532
  })
267
533
  });
268
534
 
535
+ // src/schemas/business/business-vat-change-schema.js
536
+ var businessVatChangeSchema = Joi.object({
537
+ vatNumber: Joi.string().pattern(/^\d{9}$/).required().messages({
538
+ "string.pattern.base": "Enter a VAT registration number, like 123456789",
539
+ "string.empty": "Enter a VAT registration number",
540
+ "any.required": "Enter a VAT registration number",
541
+ "string.noControlChars": "VAT registration number must not contain invalid characters"
542
+ })
543
+ });
544
+
269
545
  // src/schemas/business/business-vat-remove-schema.js
270
546
  var businessVatRemoveSchema = Joi.object({
271
547
  confirmRemove: Joi.string().valid("yes", "no").required().messages({
@@ -284,7 +560,10 @@ var businessSchemas = {
284
560
  email: businessEmailSchema,
285
561
  vat: businessVatSchema
286
562
  },
287
- vatRemove: businessVatRemoveSchema
563
+ vat: {
564
+ change: businessVatChangeSchema,
565
+ remove: businessVatRemoveSchema
566
+ }
288
567
  };
289
568
 
290
569
  // src/schemas/customer/customer-crn-schema.js
@@ -320,34 +599,6 @@ var personalNameSchema = Joi.object({
320
599
  })
321
600
  });
322
601
 
323
- // src/constants/month-map.js
324
- var MONTH_MAP = {
325
- january: 1,
326
- jan: 1,
327
- february: 2,
328
- feb: 2,
329
- march: 3,
330
- mar: 3,
331
- april: 4,
332
- apr: 4,
333
- may: 5,
334
- june: 6,
335
- jun: 6,
336
- july: 7,
337
- jul: 7,
338
- august: 8,
339
- aug: 8,
340
- september: 9,
341
- sep: 9,
342
- sept: 9,
343
- october: 10,
344
- oct: 10,
345
- november: 11,
346
- nov: 11,
347
- december: 12,
348
- dec: 12
349
- };
350
-
351
602
  // src/schemas/personal/personal-dob-schema.js
352
603
  var personalDobSchema = Joi.object({
353
604
  day: Joi.string().allow(""),
@@ -568,6 +819,15 @@ var schemas = {
568
819
  osPlaces: osPlacesSchemas
569
820
  };
570
821
 
822
+ // src/utils/format-full-name.js
823
+ var formatFullName = (nameData) => {
824
+ return [
825
+ nameData.first,
826
+ nameData.middle,
827
+ nameData.last
828
+ ].filter(Boolean).join(" ");
829
+ };
830
+
571
831
  // src/utils/format-validation-errors.js
572
832
  var formatValidationErrors = (errors) => {
573
833
  const formattedErrors = {};
@@ -596,229 +856,14 @@ var formatValidationErrors = (errors) => {
596
856
 
597
857
  // src/utils/utils.js
598
858
  var utils = {
859
+ formatFullName,
599
860
  formatValidationErrors
600
861
  };
601
-
602
- // src/presenters/base-presenter.js
603
- var BACK_LINK_DISPLAY_MAX = 50;
604
- var formatBackLink = (businessName) => {
605
- if (businessName.length > BACK_LINK_DISPLAY_MAX) {
606
- return `Back to ${businessName.slice(0, BACK_LINK_DISPLAY_MAX)}\u2026`;
607
- }
608
- return `Back to ${businessName}`;
609
- };
610
- var formatNumber = (payloadNumber, changedNumber, originalNumber) => {
611
- if (payloadNumber !== void 0) {
612
- return payloadNumber;
613
- }
614
- if (changedNumber !== void 0) {
615
- return changedNumber;
616
- }
617
- return originalNumber;
618
- };
619
- var formatDisplayAddress = (address) => {
620
- const { lookup, manual, postcode, country, city } = address;
621
- let addressLines = [];
622
- if (lookup.uprn) {
623
- const buildingAndStreet = [
624
- lookup.buildingNumberRange,
625
- lookup.street
626
- ].filter(Boolean).join(" ");
627
- addressLines = [
628
- lookup.pafOrganisationName,
629
- lookup.flatName,
630
- lookup.buildingName,
631
- buildingAndStreet,
632
- lookup.doubleDependentLocality,
633
- lookup.dependentLocality,
634
- city,
635
- lookup.county
636
- ];
637
- } else {
638
- addressLines = [
639
- manual.line1,
640
- manual.line2,
641
- manual.line3,
642
- city,
643
- manual.line4,
644
- // County
645
- manual.line5
646
- ];
647
- }
648
- return [
649
- ...addressLines.filter(Boolean),
650
- postcode,
651
- country
652
- ];
653
- };
654
- var buildAddressLine = (parts) => {
655
- return parts.filter(Boolean).join(", ") || null;
656
- };
657
- var buildStreetLine = (buildingRange, street) => {
658
- return [buildingRange, street].filter(Boolean).join(" ") || null;
659
- };
660
- var formatLookupAddress = (lookup, city, country, postcode) => ({
661
- address1: buildAddressLine([lookup.pafOrganisationName, lookup.flatName, lookup.buildingName]),
662
- address2: buildStreetLine(lookup.buildingNumberRange, lookup.street),
663
- address3: buildAddressLine([lookup.doubleDependentLocality, lookup.dependentLocality]),
664
- county: lookup.county ?? null,
665
- city: city ?? null,
666
- country: country ?? null,
667
- postcode: postcode ?? null
668
- });
669
- var formatManualAddress = (manual, city, country, postcode) => ({
670
- address1: manual.line1 ?? null,
671
- address2: manual.line2 ?? null,
672
- address3: manual.line3 ?? null,
673
- city: city ?? null,
674
- county: manual.line4 ?? null,
675
- country: country ?? null,
676
- postcode: postcode ?? null
677
- });
678
- var formatOriginalAddress = (originalAddress) => {
679
- const { lookup, manual, city, country, postcode } = originalAddress;
680
- return lookup.uprn ? formatLookupAddress(lookup, city, country, postcode) : formatManualAddress(manual, city, country, postcode);
681
- };
682
- var formatChangedAddress = (changeBusinessAddress) => {
683
- if (!changeBusinessAddress.uprn) {
684
- return changeBusinessAddress;
685
- }
686
- const {
687
- pafOrganisationName,
688
- flatName,
689
- buildingName,
690
- buildingNumberRange,
691
- street,
692
- doubleDependentLocality,
693
- dependentLocality,
694
- city,
695
- county,
696
- country,
697
- postcode
698
- } = changeBusinessAddress;
699
- return {
700
- address1: buildAddressLine([pafOrganisationName, flatName, buildingName]),
701
- address2: buildStreetLine(buildingNumberRange, street),
702
- address3: buildAddressLine([doubleDependentLocality, dependentLocality]),
703
- city: city ?? null,
704
- county: county ?? null,
705
- country: country ?? null,
706
- postcode: postcode ?? null
707
- };
708
- };
709
- var formatDisplayAddresses = (addresses, previouslyPickedAddress) => {
710
- const displayAddresses = addresses.map((address) => ({
711
- value: `${address.uprn}${address.displayAddress}`,
712
- text: address.displayAddress,
713
- selected: (previouslyPickedAddress == null ? void 0 : previouslyPickedAddress.uprn) === address.uprn && (previouslyPickedAddress == null ? void 0 : previouslyPickedAddress.displayAddress) === address.displayAddress
714
- }));
715
- const hasSelectedAddress = displayAddresses.some((addr) => addr.selected);
716
- const text = addresses.length === 1 ? "1 address found" : `${addresses.length} addresses found`;
717
- displayAddresses.unshift({
718
- value: "display",
719
- text,
720
- selected: !hasSelectedAddress
721
- });
722
- return displayAddresses;
723
- };
724
- var sortErrorsBySectionOrder = (errors, orderedSectionsToFix, SECTION_FIELD_ORDER) => {
725
- const sortedErrors = [];
726
- for (const section of orderedSectionsToFix) {
727
- const fieldsInSection = SECTION_FIELD_ORDER[section] || [];
728
- for (const field of fieldsInSection) {
729
- if (errors[field]) {
730
- sortedErrors.push({
731
- field,
732
- ...errors[field]
733
- });
734
- }
735
- }
736
- }
737
- return sortedErrors;
738
- };
739
-
740
- // src/presenters/business-details-presenter.js
741
- var getActionText = (value) => {
742
- return value ? "Change" : "Add";
743
- };
744
- var formatCph = (countyParishHoldings) => {
745
- return (countyParishHoldings || []).filter((cph) => cph == null ? void 0 : cph.cphNumber).map((cph) => cph.cphNumber);
746
- };
747
- var formatCphText = (count) => {
748
- return `County Parish Holding (CPH) number${count !== 1 ? "s" : ""}`;
749
- };
750
- var formatBusinessAddress = (businessAddress) => {
751
- var _a, _b;
752
- if (((_a = businessAddress == null ? void 0 : businessAddress.lookup) == null ? void 0 : _a.uprn) || ((_b = businessAddress == null ? void 0 : businessAddress.manual) == null ? void 0 : _b.line1)) {
753
- return formatDisplayAddress(businessAddress);
754
- }
755
- return [];
756
- };
757
-
758
- // src/presenters/presenters.js
759
- var presenters = {
760
- formatBackLink,
761
- formatNumber,
762
- formatDisplayAddress,
763
- formatOriginalAddress,
764
- formatChangedAddress,
765
- formatDisplayAddresses,
766
- sortErrorsBySectionOrder,
767
- getActionText,
768
- formatCph,
769
- formatCphText,
770
- formatBusinessAddress
771
- };
772
-
773
- // src/constants/status-codes.js
774
- var OK = 200;
775
- var BAD_REQUEST = 400;
776
- var UNAUTHORIZED = 401;
777
- var FORBIDDEN = 403;
778
- var NOT_FOUND = 404;
779
- var NO_CONTENT = 204;
780
- var FOUND = 302;
781
- var INTERNAL_SERVER_ERROR = 500;
782
- var SERVICE_UNAVAILABLE = 503;
783
-
784
- // src/constants/index.js
785
- var constants = {
786
- statusCodes: {
787
- BAD_REQUEST,
788
- UNAUTHORIZED,
789
- FORBIDDEN,
790
- NOT_FOUND,
791
- OK,
792
- NO_CONTENT,
793
- FOUND,
794
- INTERNAL_SERVER_ERROR,
795
- SERVICE_UNAVAILABLE
796
- },
797
- validationFields: {
798
- FIRST_NAME_MAX,
799
- LAST_NAME_MAX,
800
- MIDDLE_NAMES_MAX,
801
- BUSINESS_NAME_MAX,
802
- EMAIL_MAX,
803
- PHONE_NUMBER_MIN,
804
- PHONE_NUMBER_MAX,
805
- MAX_AGE_YEARS,
806
- ADDRESS_LINE_MAX,
807
- TOWN_CITY_MAX,
808
- COUNTY_MAX,
809
- COUNTRY_MAX,
810
- POSTCODE_MAX
811
- },
812
- patterns: {
813
- PHONE_NUMBER_PATTERN,
814
- NO_CONTROL_CHARS_PATTERN
815
- },
816
- monthMap: MONTH_MAP
817
- };
818
862
  // Annotate the CommonJS export names for ESM import in node:
819
863
  0 && (module.exports = {
820
864
  constants,
821
865
  mappers,
866
+ mutations,
822
867
  presenters,
823
868
  schemas,
824
869
  utils
package/dist/index.js CHANGED
@@ -1,3 +1,96 @@
1
+ // src/constants/validation-fields.js
2
+ var FIRST_NAME_MAX = 100;
3
+ var LAST_NAME_MAX = 100;
4
+ var MIDDLE_NAMES_MAX = 100;
5
+ var BUSINESS_NAME_MAX = 160;
6
+ var EMAIL_MAX = 254;
7
+ var PHONE_NUMBER_MIN = 10;
8
+ var PHONE_NUMBER_MAX = 50;
9
+ var MAX_AGE_YEARS = 120;
10
+ var ADDRESS_LINE_MAX = 100;
11
+ var TOWN_CITY_MAX = 60;
12
+ var COUNTY_MAX = 60;
13
+ var COUNTRY_MAX = 60;
14
+ var POSTCODE_MAX = 8;
15
+
16
+ // src/constants/status-codes.js
17
+ var OK = 200;
18
+ var BAD_REQUEST = 400;
19
+ var UNAUTHORIZED = 401;
20
+ var FORBIDDEN = 403;
21
+ var NOT_FOUND = 404;
22
+ var NO_CONTENT = 204;
23
+ var FOUND = 302;
24
+ var INTERNAL_SERVER_ERROR = 500;
25
+ var SERVICE_UNAVAILABLE = 503;
26
+
27
+ // src/constants/patterns.js
28
+ var PHONE_NUMBER_PATTERN = /^\+?(?=[\d ()]*\d)[\d ()]*$/;
29
+ var NO_CONTROL_CHARS_PATTERN = /^[^\x00-\x1f\x7f-\x9f]*$/;
30
+
31
+ // src/constants/month-map.js
32
+ var MONTH_MAP = {
33
+ january: 1,
34
+ jan: 1,
35
+ february: 2,
36
+ feb: 2,
37
+ march: 3,
38
+ mar: 3,
39
+ april: 4,
40
+ apr: 4,
41
+ may: 5,
42
+ june: 6,
43
+ jun: 6,
44
+ july: 7,
45
+ jul: 7,
46
+ august: 8,
47
+ aug: 8,
48
+ september: 9,
49
+ sep: 9,
50
+ sept: 9,
51
+ october: 10,
52
+ oct: 10,
53
+ november: 11,
54
+ nov: 11,
55
+ december: 12,
56
+ dec: 12
57
+ };
58
+
59
+ // src/constants/index.js
60
+ var constants = {
61
+ statusCodes: {
62
+ BAD_REQUEST,
63
+ UNAUTHORIZED,
64
+ FORBIDDEN,
65
+ NOT_FOUND,
66
+ OK,
67
+ NO_CONTENT,
68
+ FOUND,
69
+ INTERNAL_SERVER_ERROR,
70
+ SERVICE_UNAVAILABLE
71
+ },
72
+ validationFields: {
73
+ FIRST_NAME_MAX,
74
+ LAST_NAME_MAX,
75
+ MIDDLE_NAMES_MAX,
76
+ BUSINESS_NAME_MAX,
77
+ EMAIL_MAX,
78
+ PHONE_NUMBER_MIN,
79
+ PHONE_NUMBER_MAX,
80
+ MAX_AGE_YEARS,
81
+ ADDRESS_LINE_MAX,
82
+ TOWN_CITY_MAX,
83
+ COUNTY_MAX,
84
+ COUNTRY_MAX,
85
+ POSTCODE_MAX
86
+ },
87
+ patterns: {
88
+ PHONE_NUMBER_PATTERN,
89
+ NO_CONTROL_CHARS_PATTERN
90
+ },
91
+ monthMap: MONTH_MAP
92
+ };
93
+
1
94
  // src/mappers/personal-business-details-mapper.js
2
95
  var mapPersonalBusinessDetails = (value) => {
3
96
  return {
@@ -91,14 +184,201 @@ var mappers = {
91
184
  businessDetails: mapBusinessDetails
92
185
  };
93
186
 
94
- // src/utils/joi.js
95
- import BaseJoi from "joi";
187
+ // src/mutations/personal/update-customer-name.js
188
+ var updateCustomerNameMutation = `
189
+ mutation UpdateCustomerName($input: UpdateCustomerNameInput!) {
190
+ updateCustomerName(input: $input) {
191
+ customer {
192
+ info {
193
+ name {
194
+ first
195
+ last
196
+ middle
197
+ }
198
+ }
199
+ }
200
+ }
201
+ }
202
+ `;
96
203
 
97
- // src/constants/patterns.js
98
- var PHONE_NUMBER_PATTERN = /^\+?(?=[\d ()]*\d)[\d ()]*$/;
99
- var NO_CONTROL_CHARS_PATTERN = /^[^\x00-\x1f\x7f-\x9f]*$/;
204
+ // src/mutations/mutations.js
205
+ var mutations = {
206
+ updateCustomerName: updateCustomerNameMutation
207
+ };
208
+
209
+ // src/presenters/base-presenter.js
210
+ var BACK_LINK_DISPLAY_MAX = 50;
211
+ var formatBackLink = (businessName) => {
212
+ if (businessName.length > BACK_LINK_DISPLAY_MAX) {
213
+ return `Back to ${businessName.slice(0, BACK_LINK_DISPLAY_MAX)}\u2026`;
214
+ }
215
+ return `Back to ${businessName}`;
216
+ };
217
+ var formatNumber = (payloadNumber, changedNumber, originalNumber) => {
218
+ if (payloadNumber !== void 0) {
219
+ return payloadNumber;
220
+ }
221
+ if (changedNumber !== void 0) {
222
+ return changedNumber;
223
+ }
224
+ return originalNumber;
225
+ };
226
+ var formatDisplayAddress = (address) => {
227
+ const { lookup, manual, postcode, country, city } = address;
228
+ let addressLines = [];
229
+ if (lookup.uprn) {
230
+ const buildingAndStreet = [
231
+ lookup.buildingNumberRange,
232
+ lookup.street
233
+ ].filter(Boolean).join(" ");
234
+ addressLines = [
235
+ lookup.pafOrganisationName,
236
+ lookup.flatName,
237
+ lookup.buildingName,
238
+ buildingAndStreet,
239
+ lookup.doubleDependentLocality,
240
+ lookup.dependentLocality,
241
+ city,
242
+ lookup.county
243
+ ];
244
+ } else {
245
+ addressLines = [
246
+ manual.line1,
247
+ manual.line2,
248
+ manual.line3,
249
+ city,
250
+ manual.line4,
251
+ // County
252
+ manual.line5
253
+ ];
254
+ }
255
+ return [
256
+ ...addressLines.filter(Boolean),
257
+ postcode,
258
+ country
259
+ ];
260
+ };
261
+ var buildAddressLine = (parts) => {
262
+ return parts.filter(Boolean).join(", ") || null;
263
+ };
264
+ var buildStreetLine = (buildingRange, street) => {
265
+ return [buildingRange, street].filter(Boolean).join(" ") || null;
266
+ };
267
+ var formatLookupAddress = (lookup, city, country, postcode) => ({
268
+ address1: buildAddressLine([lookup.pafOrganisationName, lookup.flatName, lookup.buildingName]),
269
+ address2: buildStreetLine(lookup.buildingNumberRange, lookup.street),
270
+ address3: buildAddressLine([lookup.doubleDependentLocality, lookup.dependentLocality]),
271
+ county: lookup.county ?? null,
272
+ city: city ?? null,
273
+ country: country ?? null,
274
+ postcode: postcode ?? null
275
+ });
276
+ var formatManualAddress = (manual, city, country, postcode) => ({
277
+ address1: manual.line1 ?? null,
278
+ address2: manual.line2 ?? null,
279
+ address3: manual.line3 ?? null,
280
+ city: city ?? null,
281
+ county: manual.line4 ?? null,
282
+ country: country ?? null,
283
+ postcode: postcode ?? null
284
+ });
285
+ var formatOriginalAddress = (originalAddress) => {
286
+ const { lookup, manual, city, country, postcode } = originalAddress;
287
+ return lookup.uprn ? formatLookupAddress(lookup, city, country, postcode) : formatManualAddress(manual, city, country, postcode);
288
+ };
289
+ var formatChangedAddress = (changeBusinessAddress) => {
290
+ if (!changeBusinessAddress.uprn) {
291
+ return changeBusinessAddress;
292
+ }
293
+ const {
294
+ pafOrganisationName,
295
+ flatName,
296
+ buildingName,
297
+ buildingNumberRange,
298
+ street,
299
+ doubleDependentLocality,
300
+ dependentLocality,
301
+ city,
302
+ county,
303
+ country,
304
+ postcode
305
+ } = changeBusinessAddress;
306
+ return {
307
+ address1: buildAddressLine([pafOrganisationName, flatName, buildingName]),
308
+ address2: buildStreetLine(buildingNumberRange, street),
309
+ address3: buildAddressLine([doubleDependentLocality, dependentLocality]),
310
+ city: city ?? null,
311
+ county: county ?? null,
312
+ country: country ?? null,
313
+ postcode: postcode ?? null
314
+ };
315
+ };
316
+ var formatDisplayAddresses = (addresses, previouslyPickedAddress) => {
317
+ const displayAddresses = addresses.map((address) => ({
318
+ value: `${address.uprn}${address.displayAddress}`,
319
+ text: address.displayAddress,
320
+ selected: (previouslyPickedAddress == null ? void 0 : previouslyPickedAddress.uprn) === address.uprn && (previouslyPickedAddress == null ? void 0 : previouslyPickedAddress.displayAddress) === address.displayAddress
321
+ }));
322
+ const hasSelectedAddress = displayAddresses.some((addr) => addr.selected);
323
+ const text = addresses.length === 1 ? "1 address found" : `${addresses.length} addresses found`;
324
+ displayAddresses.unshift({
325
+ value: "display",
326
+ text,
327
+ selected: !hasSelectedAddress
328
+ });
329
+ return displayAddresses;
330
+ };
331
+ var sortErrorsBySectionOrder = (errors, orderedSectionsToFix, SECTION_FIELD_ORDER) => {
332
+ const sortedErrors = [];
333
+ for (const section of orderedSectionsToFix) {
334
+ const fieldsInSection = SECTION_FIELD_ORDER[section] || [];
335
+ for (const field of fieldsInSection) {
336
+ if (errors[field]) {
337
+ sortedErrors.push({
338
+ field,
339
+ ...errors[field]
340
+ });
341
+ }
342
+ }
343
+ }
344
+ return sortedErrors;
345
+ };
346
+
347
+ // src/presenters/business-details-presenter.js
348
+ var getActionText = (value) => {
349
+ return value ? "Change" : "Add";
350
+ };
351
+ var formatCph = (countyParishHoldings) => {
352
+ return (countyParishHoldings || []).filter((cph) => cph == null ? void 0 : cph.cphNumber).map((cph) => cph.cphNumber);
353
+ };
354
+ var formatCphText = (count) => {
355
+ return `County Parish Holding (CPH) number${count !== 1 ? "s" : ""}`;
356
+ };
357
+ var formatBusinessAddress = (businessAddress) => {
358
+ var _a, _b;
359
+ if (((_a = businessAddress == null ? void 0 : businessAddress.lookup) == null ? void 0 : _a.uprn) || ((_b = businessAddress == null ? void 0 : businessAddress.manual) == null ? void 0 : _b.line1)) {
360
+ return formatDisplayAddress(businessAddress);
361
+ }
362
+ return [];
363
+ };
364
+
365
+ // src/presenters/presenters.js
366
+ var presenters = {
367
+ formatBackLink,
368
+ formatNumber,
369
+ formatDisplayAddress,
370
+ formatOriginalAddress,
371
+ formatChangedAddress,
372
+ formatDisplayAddresses,
373
+ sortErrorsBySectionOrder,
374
+ getActionText,
375
+ formatCph,
376
+ formatCphText,
377
+ formatBusinessAddress
378
+ };
100
379
 
101
380
  // src/utils/joi.js
381
+ import BaseJoi from "joi";
102
382
  var Joi = BaseJoi.extend((joi) => ({
103
383
  type: "string",
104
384
  base: joi.string(),
@@ -118,23 +398,8 @@ var businessSbiSchema = Joi.object({
118
398
  sbi: Joi.string().pattern(/^\d{9}$/).allow("").optional().messages({
119
399
  "string.pattern.base": "Enter the full SBI",
120
400
  "string.noControlChars": "SBI must not contain invalid characters"
121
- })
122
- });
123
-
124
- // src/constants/validation-fields.js
125
- var FIRST_NAME_MAX = 100;
126
- var LAST_NAME_MAX = 100;
127
- var MIDDLE_NAMES_MAX = 100;
128
- var BUSINESS_NAME_MAX = 160;
129
- var EMAIL_MAX = 254;
130
- var PHONE_NUMBER_MIN = 10;
131
- var PHONE_NUMBER_MAX = 50;
132
- var MAX_AGE_YEARS = 120;
133
- var ADDRESS_LINE_MAX = 100;
134
- var TOWN_CITY_MAX = 60;
135
- var COUNTY_MAX = 60;
136
- var COUNTRY_MAX = 60;
137
- var POSTCODE_MAX = 8;
401
+ })
402
+ });
138
403
 
139
404
  // src/schemas/shared/address-schema.js
140
405
  var addressSchema = Joi.object({
@@ -227,6 +492,16 @@ var businessVatSchema = Joi.object({
227
492
  })
228
493
  });
229
494
 
495
+ // src/schemas/business/business-vat-change-schema.js
496
+ var businessVatChangeSchema = Joi.object({
497
+ vatNumber: Joi.string().pattern(/^\d{9}$/).required().messages({
498
+ "string.pattern.base": "Enter a VAT registration number, like 123456789",
499
+ "string.empty": "Enter a VAT registration number",
500
+ "any.required": "Enter a VAT registration number",
501
+ "string.noControlChars": "VAT registration number must not contain invalid characters"
502
+ })
503
+ });
504
+
230
505
  // src/schemas/business/business-vat-remove-schema.js
231
506
  var businessVatRemoveSchema = Joi.object({
232
507
  confirmRemove: Joi.string().valid("yes", "no").required().messages({
@@ -245,7 +520,10 @@ var businessSchemas = {
245
520
  email: businessEmailSchema,
246
521
  vat: businessVatSchema
247
522
  },
248
- vatRemove: businessVatRemoveSchema
523
+ vat: {
524
+ change: businessVatChangeSchema,
525
+ remove: businessVatRemoveSchema
526
+ }
249
527
  };
250
528
 
251
529
  // src/schemas/customer/customer-crn-schema.js
@@ -281,34 +559,6 @@ var personalNameSchema = Joi.object({
281
559
  })
282
560
  });
283
561
 
284
- // src/constants/month-map.js
285
- var MONTH_MAP = {
286
- january: 1,
287
- jan: 1,
288
- february: 2,
289
- feb: 2,
290
- march: 3,
291
- mar: 3,
292
- april: 4,
293
- apr: 4,
294
- may: 5,
295
- june: 6,
296
- jun: 6,
297
- july: 7,
298
- jul: 7,
299
- august: 8,
300
- aug: 8,
301
- september: 9,
302
- sep: 9,
303
- sept: 9,
304
- october: 10,
305
- oct: 10,
306
- november: 11,
307
- nov: 11,
308
- december: 12,
309
- dec: 12
310
- };
311
-
312
562
  // src/schemas/personal/personal-dob-schema.js
313
563
  var personalDobSchema = Joi.object({
314
564
  day: Joi.string().allow(""),
@@ -529,6 +779,15 @@ var schemas = {
529
779
  osPlaces: osPlacesSchemas
530
780
  };
531
781
 
782
+ // src/utils/format-full-name.js
783
+ var formatFullName = (nameData) => {
784
+ return [
785
+ nameData.first,
786
+ nameData.middle,
787
+ nameData.last
788
+ ].filter(Boolean).join(" ");
789
+ };
790
+
532
791
  // src/utils/format-validation-errors.js
533
792
  var formatValidationErrors = (errors) => {
534
793
  const formattedErrors = {};
@@ -557,228 +816,13 @@ var formatValidationErrors = (errors) => {
557
816
 
558
817
  // src/utils/utils.js
559
818
  var utils = {
819
+ formatFullName,
560
820
  formatValidationErrors
561
821
  };
562
-
563
- // src/presenters/base-presenter.js
564
- var BACK_LINK_DISPLAY_MAX = 50;
565
- var formatBackLink = (businessName) => {
566
- if (businessName.length > BACK_LINK_DISPLAY_MAX) {
567
- return `Back to ${businessName.slice(0, BACK_LINK_DISPLAY_MAX)}\u2026`;
568
- }
569
- return `Back to ${businessName}`;
570
- };
571
- var formatNumber = (payloadNumber, changedNumber, originalNumber) => {
572
- if (payloadNumber !== void 0) {
573
- return payloadNumber;
574
- }
575
- if (changedNumber !== void 0) {
576
- return changedNumber;
577
- }
578
- return originalNumber;
579
- };
580
- var formatDisplayAddress = (address) => {
581
- const { lookup, manual, postcode, country, city } = address;
582
- let addressLines = [];
583
- if (lookup.uprn) {
584
- const buildingAndStreet = [
585
- lookup.buildingNumberRange,
586
- lookup.street
587
- ].filter(Boolean).join(" ");
588
- addressLines = [
589
- lookup.pafOrganisationName,
590
- lookup.flatName,
591
- lookup.buildingName,
592
- buildingAndStreet,
593
- lookup.doubleDependentLocality,
594
- lookup.dependentLocality,
595
- city,
596
- lookup.county
597
- ];
598
- } else {
599
- addressLines = [
600
- manual.line1,
601
- manual.line2,
602
- manual.line3,
603
- city,
604
- manual.line4,
605
- // County
606
- manual.line5
607
- ];
608
- }
609
- return [
610
- ...addressLines.filter(Boolean),
611
- postcode,
612
- country
613
- ];
614
- };
615
- var buildAddressLine = (parts) => {
616
- return parts.filter(Boolean).join(", ") || null;
617
- };
618
- var buildStreetLine = (buildingRange, street) => {
619
- return [buildingRange, street].filter(Boolean).join(" ") || null;
620
- };
621
- var formatLookupAddress = (lookup, city, country, postcode) => ({
622
- address1: buildAddressLine([lookup.pafOrganisationName, lookup.flatName, lookup.buildingName]),
623
- address2: buildStreetLine(lookup.buildingNumberRange, lookup.street),
624
- address3: buildAddressLine([lookup.doubleDependentLocality, lookup.dependentLocality]),
625
- county: lookup.county ?? null,
626
- city: city ?? null,
627
- country: country ?? null,
628
- postcode: postcode ?? null
629
- });
630
- var formatManualAddress = (manual, city, country, postcode) => ({
631
- address1: manual.line1 ?? null,
632
- address2: manual.line2 ?? null,
633
- address3: manual.line3 ?? null,
634
- city: city ?? null,
635
- county: manual.line4 ?? null,
636
- country: country ?? null,
637
- postcode: postcode ?? null
638
- });
639
- var formatOriginalAddress = (originalAddress) => {
640
- const { lookup, manual, city, country, postcode } = originalAddress;
641
- return lookup.uprn ? formatLookupAddress(lookup, city, country, postcode) : formatManualAddress(manual, city, country, postcode);
642
- };
643
- var formatChangedAddress = (changeBusinessAddress) => {
644
- if (!changeBusinessAddress.uprn) {
645
- return changeBusinessAddress;
646
- }
647
- const {
648
- pafOrganisationName,
649
- flatName,
650
- buildingName,
651
- buildingNumberRange,
652
- street,
653
- doubleDependentLocality,
654
- dependentLocality,
655
- city,
656
- county,
657
- country,
658
- postcode
659
- } = changeBusinessAddress;
660
- return {
661
- address1: buildAddressLine([pafOrganisationName, flatName, buildingName]),
662
- address2: buildStreetLine(buildingNumberRange, street),
663
- address3: buildAddressLine([doubleDependentLocality, dependentLocality]),
664
- city: city ?? null,
665
- county: county ?? null,
666
- country: country ?? null,
667
- postcode: postcode ?? null
668
- };
669
- };
670
- var formatDisplayAddresses = (addresses, previouslyPickedAddress) => {
671
- const displayAddresses = addresses.map((address) => ({
672
- value: `${address.uprn}${address.displayAddress}`,
673
- text: address.displayAddress,
674
- selected: (previouslyPickedAddress == null ? void 0 : previouslyPickedAddress.uprn) === address.uprn && (previouslyPickedAddress == null ? void 0 : previouslyPickedAddress.displayAddress) === address.displayAddress
675
- }));
676
- const hasSelectedAddress = displayAddresses.some((addr) => addr.selected);
677
- const text = addresses.length === 1 ? "1 address found" : `${addresses.length} addresses found`;
678
- displayAddresses.unshift({
679
- value: "display",
680
- text,
681
- selected: !hasSelectedAddress
682
- });
683
- return displayAddresses;
684
- };
685
- var sortErrorsBySectionOrder = (errors, orderedSectionsToFix, SECTION_FIELD_ORDER) => {
686
- const sortedErrors = [];
687
- for (const section of orderedSectionsToFix) {
688
- const fieldsInSection = SECTION_FIELD_ORDER[section] || [];
689
- for (const field of fieldsInSection) {
690
- if (errors[field]) {
691
- sortedErrors.push({
692
- field,
693
- ...errors[field]
694
- });
695
- }
696
- }
697
- }
698
- return sortedErrors;
699
- };
700
-
701
- // src/presenters/business-details-presenter.js
702
- var getActionText = (value) => {
703
- return value ? "Change" : "Add";
704
- };
705
- var formatCph = (countyParishHoldings) => {
706
- return (countyParishHoldings || []).filter((cph) => cph == null ? void 0 : cph.cphNumber).map((cph) => cph.cphNumber);
707
- };
708
- var formatCphText = (count) => {
709
- return `County Parish Holding (CPH) number${count !== 1 ? "s" : ""}`;
710
- };
711
- var formatBusinessAddress = (businessAddress) => {
712
- var _a, _b;
713
- if (((_a = businessAddress == null ? void 0 : businessAddress.lookup) == null ? void 0 : _a.uprn) || ((_b = businessAddress == null ? void 0 : businessAddress.manual) == null ? void 0 : _b.line1)) {
714
- return formatDisplayAddress(businessAddress);
715
- }
716
- return [];
717
- };
718
-
719
- // src/presenters/presenters.js
720
- var presenters = {
721
- formatBackLink,
722
- formatNumber,
723
- formatDisplayAddress,
724
- formatOriginalAddress,
725
- formatChangedAddress,
726
- formatDisplayAddresses,
727
- sortErrorsBySectionOrder,
728
- getActionText,
729
- formatCph,
730
- formatCphText,
731
- formatBusinessAddress
732
- };
733
-
734
- // src/constants/status-codes.js
735
- var OK = 200;
736
- var BAD_REQUEST = 400;
737
- var UNAUTHORIZED = 401;
738
- var FORBIDDEN = 403;
739
- var NOT_FOUND = 404;
740
- var NO_CONTENT = 204;
741
- var FOUND = 302;
742
- var INTERNAL_SERVER_ERROR = 500;
743
- var SERVICE_UNAVAILABLE = 503;
744
-
745
- // src/constants/index.js
746
- var constants = {
747
- statusCodes: {
748
- BAD_REQUEST,
749
- UNAUTHORIZED,
750
- FORBIDDEN,
751
- NOT_FOUND,
752
- OK,
753
- NO_CONTENT,
754
- FOUND,
755
- INTERNAL_SERVER_ERROR,
756
- SERVICE_UNAVAILABLE
757
- },
758
- validationFields: {
759
- FIRST_NAME_MAX,
760
- LAST_NAME_MAX,
761
- MIDDLE_NAMES_MAX,
762
- BUSINESS_NAME_MAX,
763
- EMAIL_MAX,
764
- PHONE_NUMBER_MIN,
765
- PHONE_NUMBER_MAX,
766
- MAX_AGE_YEARS,
767
- ADDRESS_LINE_MAX,
768
- TOWN_CITY_MAX,
769
- COUNTY_MAX,
770
- COUNTRY_MAX,
771
- POSTCODE_MAX
772
- },
773
- patterns: {
774
- PHONE_NUMBER_PATTERN,
775
- NO_CONTROL_CHARS_PATTERN
776
- },
777
- monthMap: MONTH_MAP
778
- };
779
822
  export {
780
823
  constants,
781
824
  mappers,
825
+ mutations,
782
826
  presenters,
783
827
  schemas,
784
828
  utils
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@defra/fcp-sfd-frontend-engine",
3
- "version": "0.9.0",
3
+ "version": "0.10.0",
4
4
  "description": "Shared frontend engine used by both the internal and external frontend applications.",
5
5
  "main": "./dist/index.cjs",
6
6
  "exports": {
@@ -40,6 +40,7 @@
40
40
  "devDependencies": {
41
41
  "@vitest/coverage-v8": "4.1.10",
42
42
  "eslint": "9.39.2",
43
+ "graphql": "16.13.2",
43
44
  "neostandard": "0.13.0",
44
45
  "tsup": "8.5.1",
45
46
  "vitest": "4.1.10"
package/src/index.js CHANGED
@@ -1,5 +1,6 @@
1
+ export { constants } from './constants/index.js'
1
2
  export { mappers } from './mappers/mappers.js'
3
+ export { mutations } from './mutations/mutations.js'
4
+ export { presenters } from './presenters/presenters.js'
2
5
  export { schemas } from './schemas/schemas.js'
3
6
  export { utils } from './utils/utils.js'
4
- export { presenters } from './presenters/presenters.js'
5
- export { constants } from './constants/index.js'
@@ -0,0 +1,5 @@
1
+ import { updateCustomerNameMutation } from './personal/update-customer-name.js'
2
+
3
+ export const mutations = {
4
+ updateCustomerName: updateCustomerNameMutation
5
+ }
@@ -0,0 +1,15 @@
1
+ export const updateCustomerNameMutation = `
2
+ mutation UpdateCustomerName($input: UpdateCustomerNameInput!) {
3
+ updateCustomerName(input: $input) {
4
+ customer {
5
+ info {
6
+ name {
7
+ first
8
+ last
9
+ middle
10
+ }
11
+ }
12
+ }
13
+ }
14
+ }
15
+ `
@@ -4,6 +4,7 @@ import { businessNameSchema } from './business-name-schema.js'
4
4
  import { businessEmailSchema } from './business-email-schema.js'
5
5
  import { businessPhoneSchema } from './business-phone-schema.js'
6
6
  import { businessVatSchema } from './business-vat-schema.js'
7
+ import { businessVatChangeSchema } from './business-vat-change-schema.js'
7
8
  import { businessVatRemoveSchema } from './business-vat-remove-schema.js'
8
9
 
9
10
  /**
@@ -11,6 +12,15 @@ import { businessVatRemoveSchema } from './business-vat-remove-schema.js'
11
12
  * This is due to the interrupter journey. The journey required the business details to be validated in a single step,
12
13
  * these include name, address, phone, email and vat. The `details` property is used to group these schemas together.
13
14
  * The `sbi` property is separate as it is validated in a different step of the journey.
15
+ *
16
+ * The `vat` property groups the schemas for the standalone VAT action pages:
17
+ * - `vat.change` validates the dedicated VAT change page where a VAT registration number is mandatory
18
+ * (9 digits, `.required()`), so it is deliberately separate from `details.vat`.
19
+ * - `vat.remove` validates the VAT removal confirmation page (yes/no).
20
+ *
21
+ * Note `details.vat` and `vat.change` are two distinct validation contexts for the same field: within the
22
+ * interrupter `details` set VAT is optional and an empty string is allowed, whereas on the dedicated change
23
+ * page a valid VAT number must be entered (removal is handled by its own journey).
14
24
  */
15
25
  export const businessSchemas = {
16
26
  sbi: businessSbiSchema,
@@ -21,5 +31,8 @@ export const businessSchemas = {
21
31
  email: businessEmailSchema,
22
32
  vat: businessVatSchema
23
33
  },
24
- vatRemove: businessVatRemoveSchema
34
+ vat: {
35
+ change: businessVatChangeSchema,
36
+ remove: businessVatRemoveSchema
37
+ }
25
38
  }
@@ -0,0 +1,13 @@
1
+ import { Joi } from '../../utils/joi.js'
2
+
3
+ export const businessVatChangeSchema = Joi.object({
4
+ vatNumber: Joi.string()
5
+ .pattern(/^\d{9}$/)
6
+ .required()
7
+ .messages({
8
+ 'string.pattern.base': 'Enter a VAT registration number, like 123456789',
9
+ 'string.empty': 'Enter a VAT registration number',
10
+ 'any.required': 'Enter a VAT registration number',
11
+ 'string.noControlChars': 'VAT registration number must not contain invalid characters'
12
+ })
13
+ })
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Joins the parts of a name (first, middle, last) into a single display string,
3
+ * omitting any empty parts.
4
+ *
5
+ * @param {object} nameData - An object with `first`, `middle` and `last` name parts
6
+ * @returns {string} The formatted full name
7
+ */
8
+ export const formatFullName = (nameData) => {
9
+ return [
10
+ nameData.first,
11
+ nameData.middle,
12
+ nameData.last
13
+ ].filter(Boolean).join(' ')
14
+ }
@@ -1,5 +1,7 @@
1
+ import { formatFullName } from './format-full-name.js'
1
2
  import { formatValidationErrors } from './format-validation-errors'
2
3
 
3
4
  export const utils = {
5
+ formatFullName,
4
6
  formatValidationErrors
5
7
  }