@planning-inspectorate/data-model 2.23.0 → 2.25.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/docs/appeal-has.md +29 -0
  2. package/docs/appeal-s78.md +60 -0
  3. package/package.json +1 -1
  4. package/pins_data_model/models/model_appeal_document.py +1 -1
  5. package/pins_data_model/models/model_appeal_event.py +1 -1
  6. package/pins_data_model/models/model_appeal_event_estimate.py +1 -1
  7. package/pins_data_model/models/model_appeal_has.py +14 -1
  8. package/pins_data_model/models/model_appeal_representation.py +1 -1
  9. package/pins_data_model/models/model_appeal_s78.py +26 -1
  10. package/pins_data_model/models/model_dart_response.py +1 -1
  11. package/pins_data_model/models/model_entraid.py +1 -1
  12. package/pins_data_model/models/model_folder.py +1 -1
  13. package/pins_data_model/models/model_gettimesheets_response.py +1 -1
  14. package/pins_data_model/models/model_listed_building.py +1 -1
  15. package/pins_data_model/models/model_listed_buildings.py +1 -1
  16. package/pins_data_model/models/model_nsip_document.py +1 -1
  17. package/pins_data_model/models/model_nsip_exam_timetable.py +1 -1
  18. package/pins_data_model/models/model_nsip_invoice.py +1 -1
  19. package/pins_data_model/models/model_nsip_meeting.py +1 -1
  20. package/pins_data_model/models/model_nsip_project.py +1 -1
  21. package/pins_data_model/models/model_nsip_project_update.py +1 -1
  22. package/pins_data_model/models/model_nsip_representation.py +1 -1
  23. package/pins_data_model/models/model_nsip_subscription.py +1 -1
  24. package/pins_data_model/models/model_pins_inspector.py +1 -1
  25. package/pins_data_model/models/model_pins_lpa.py +1 -1
  26. package/pins_data_model/models/model_s51_advice.py +1 -1
  27. package/pins_data_model/models/model_service_user.py +1 -1
  28. package/schemas/appeal-has.schema.json +7 -1
  29. package/schemas/appeal-s78.schema.json +14 -1
  30. package/schemas/commands/appeals-components/lpa-questionnaire-enforcement-common.schema.json +60 -0
  31. package/schemas/commands/appeals-components/lpa-questionnaire-enforcement.schema.json +2 -50
  32. package/schemas/commands/lpa-questionnaire.schema.json +18 -2
  33. package/src/enums.cjs +42 -0
  34. package/src/enums.d.ts +38 -0
  35. package/src/enums.js +38 -0
  36. package/src/index.cjs +42 -0
  37. package/src/lib/gen-enum-impl.js +196 -0
  38. package/src/lib/gen-enum-impl.test.js +183 -0
  39. package/src/lib/gen-enums.js +11 -87
  40. package/src/schemas.d.ts +35 -6
  41. package/tests/appeals/appeal-has.test.js +1 -0
  42. package/tests/appeals/appeal-s78.test.js +2 -0
  43. package/tests/appeals/commands/enforcement-listed-questionnaire.test.js +2 -3
@@ -71,9 +71,9 @@
71
71
  ]
72
72
  },
73
73
  {
74
- "$comment": "Enforcement + Enforcement listed building",
74
+ "$comment": "Enforcement",
75
75
  "allOf": [
76
- { "properties": { "caseType": { "enum": ["C", "F"] } } },
76
+ { "properties": { "caseType": { "enum": ["C"] } } },
77
77
  { "$ref": "appeals-components/lpa-questionnaire-common.schema.json" },
78
78
  { "$ref": "appeals-components/lpa-questionnaire-has.schema.json" },
79
79
  { "$ref": "appeals-components/lpa-procedure-preference.schema.json" },
@@ -81,6 +81,7 @@
81
81
  { "$ref": "appeals-components/infrastructure-levy.schema.json" },
82
82
  { "$ref": "appeals-components/environmental-impact-assessment.schema.json" },
83
83
  { "$ref": "appeals-components/site-designations-protection.schema.json" },
84
+ { "$ref": "appeals-components/lpa-questionnaire-enforcement-common.schema.json" },
84
85
  { "$ref": "appeals-components/lpa-questionnaire-enforcement.schema.json" }
85
86
  ]
86
87
  },
@@ -93,6 +94,21 @@
93
94
  { "$ref": "appeals-components/infrastructure-levy.schema.json" },
94
95
  { "$ref": "appeals-components/lpa-questionnaire-ldc.schema.json" }
95
96
  ]
97
+ },
98
+ {
99
+ "$comment": "Enforcement listed building",
100
+ "allOf": [
101
+ { "properties": { "caseType": { "enum": ["F"] } } },
102
+ { "$ref": "appeals-components/lpa-questionnaire-common.schema.json" },
103
+ { "$ref": "appeals-components/lpa-questionnaire-has.schema.json" },
104
+ { "$ref": "appeals-components/lpa-procedure-preference.schema.json" },
105
+ { "$ref": "appeals-components/changed-listed-building-number.schema.json" },
106
+ { "$ref": "appeals-components/infrastructure-levy.schema.json" },
107
+ { "$ref": "appeals-components/environmental-impact-assessment.schema.json" },
108
+ { "$ref": "appeals-components/site-designations-protection.schema.json" },
109
+ { "$ref": "appeals-components/lpa-questionnaire-enforcement-common.schema.json" },
110
+ { "$ref": "appeals-components/lpa-questionnaire-listed-building.schema.json" }
111
+ ]
96
112
  }
97
113
  ]
98
114
  },
package/src/enums.cjs CHANGED
@@ -1,5 +1,34 @@
1
1
  'use strict';
2
2
 
3
+ const APPEAL_HAS_CASE_DECISION_OUTCOME = Object.freeze({
4
+ ALLOWED: 'allowed',
5
+ DISMISSED: 'dismissed',
6
+ INVALID: 'invalid',
7
+ SPLIT_DECISION: 'split_decision',
8
+ });
9
+
10
+ const APPEAL_HAS_CASE_PROCEDURE = Object.freeze({
11
+ HEARING: 'hearing',
12
+ INQUIRY: 'inquiry',
13
+ WRITTEN: 'written',
14
+ });
15
+
16
+ const APPEAL_HAS_CASE_STATUS = Object.freeze({
17
+ ASSIGN_CASE_OFFICER: 'assign_case_officer',
18
+ AWAITING_EVENT: 'awaiting_event',
19
+ AWAITING_TRANSFER: 'awaiting_transfer',
20
+ CLOSED: 'closed',
21
+ COMPLETE: 'complete',
22
+ EVENT: 'event',
23
+ INVALID: 'invalid',
24
+ ISSUE_DETERMINATION: 'issue_determination',
25
+ LPA_QUESTIONNAIRE: 'lpa_questionnaire',
26
+ READY_TO_START: 'ready_to_start',
27
+ TRANSFERRED: 'transferred',
28
+ VALIDATION: 'validation',
29
+ WITHDRAWN: 'withdrawn',
30
+ });
31
+
3
32
  const APPEAL_ALLOCATION_LEVEL = Object.freeze({
4
33
  A: 'A',
5
34
  B: 'B',
@@ -312,6 +341,7 @@ const APPEAL_LPA_QUESTIONNAIRE_VALIDATION_OUTCOME = Object.freeze({
312
341
  const APPEAL_NOTIFICATION_METHOD = Object.freeze({
313
342
  ADVERT: 'advert',
314
343
  LETTER: 'letter',
344
+ NOT_NOTIFIED: 'not_notified',
315
345
  NOTICE: 'notice',
316
346
  });
317
347
 
@@ -409,6 +439,11 @@ const METHOD = Object.freeze({
409
439
  POST: 'post',
410
440
  });
411
441
 
442
+ const NSIP_PROJECT_SOURCE_SYSTEM = Object.freeze({
443
+ BACK_OFFICE_APPLICATIONS: 'back-office-applications',
444
+ HORIZON: 'horizon',
445
+ });
446
+
412
447
  const NSIP_CA_AND_TP_EVIDENCE = Object.freeze({
413
448
  AWAITING_SUBMISSION: 'awaiting_submission',
414
449
  NOT_APPLICABLE: 'not_applicable',
@@ -654,8 +689,11 @@ const NSIP_SECURITY_CLASSIFICATION = Object.freeze({
654
689
  });
655
690
 
656
691
  const NSIP_SOURCE_SYSTEM = Object.freeze({
692
+ BACK_OFFICE_APPEALS: 'back-office-appeals',
657
693
  BACK_OFFICE_APPLICATIONS: 'back-office-applications',
658
694
  HORIZON: 'horizon',
695
+ NI_FILE: 'ni_file',
696
+ SHAREPOINT: 'sharepoint',
659
697
  });
660
698
 
661
699
  const NSIP_STAGE = Object.freeze({
@@ -761,6 +799,9 @@ exports.APPEAL_EIA_DEVELOPMENT_DESCRIPTION = APPEAL_EIA_DEVELOPMENT_DESCRIPTION;
761
799
  exports.APPEAL_EIA_ENVIRONMENTAL_IMPACT_SCHEDULE = APPEAL_EIA_ENVIRONMENTAL_IMPACT_SCHEDULE;
762
800
  exports.APPEAL_EVENT_STATUS = APPEAL_EVENT_STATUS;
763
801
  exports.APPEAL_EVENT_TYPE = APPEAL_EVENT_TYPE;
802
+ exports.APPEAL_HAS_CASE_DECISION_OUTCOME = APPEAL_HAS_CASE_DECISION_OUTCOME;
803
+ exports.APPEAL_HAS_CASE_PROCEDURE = APPEAL_HAS_CASE_PROCEDURE;
804
+ exports.APPEAL_HAS_CASE_STATUS = APPEAL_HAS_CASE_STATUS;
764
805
  exports.APPEAL_INVALID_OR_INCOMPLETE_DETAILS = APPEAL_INVALID_OR_INCOMPLETE_DETAILS;
765
806
  exports.APPEAL_KNOWS_ALL_OWNERS = APPEAL_KNOWS_ALL_OWNERS;
766
807
  exports.APPEAL_KNOWS_OTHER_OWNERS = APPEAL_KNOWS_OTHER_OWNERS;
@@ -796,6 +837,7 @@ exports.NSIP_ORIGIN = NSIP_ORIGIN;
796
837
  exports.NSIP_PLANNING_INSPECTORATE_ROLE = NSIP_PLANNING_INSPECTORATE_ROLE;
797
838
  exports.NSIP_POLICY_COMPLIANCE_DOCUMENT = NSIP_POLICY_COMPLIANCE_DOCUMENT;
798
839
  exports.NSIP_PRINCIPAL_AREA_DISAGREEMENT_SUMMARY_STMT = NSIP_PRINCIPAL_AREA_DISAGREEMENT_SUMMARY_STMT;
840
+ exports.NSIP_PROJECT_SOURCE_SYSTEM = NSIP_PROJECT_SOURCE_SYSTEM;
799
841
  exports.NSIP_PROJECT_TYPE = NSIP_PROJECT_TYPE;
800
842
  exports.NSIP_PUBLIC_SECTOR_EQUALITY_DUTY = NSIP_PUBLIC_SECTOR_EQUALITY_DUTY;
801
843
  exports.NSIP_PUBLISHED_STATUS = NSIP_PUBLISHED_STATUS;
package/src/enums.d.ts CHANGED
@@ -1,3 +1,32 @@
1
+ export const APPEAL_HAS_CASE_DECISION_OUTCOME = {
2
+ ALLOWED: 'allowed',
3
+ DISMISSED: 'dismissed',
4
+ INVALID: 'invalid',
5
+ SPLIT_DECISION: 'split_decision',
6
+ } as const;
7
+
8
+ export const APPEAL_HAS_CASE_PROCEDURE = {
9
+ HEARING: 'hearing',
10
+ INQUIRY: 'inquiry',
11
+ WRITTEN: 'written',
12
+ } as const;
13
+
14
+ export const APPEAL_HAS_CASE_STATUS = {
15
+ ASSIGN_CASE_OFFICER: 'assign_case_officer',
16
+ AWAITING_EVENT: 'awaiting_event',
17
+ AWAITING_TRANSFER: 'awaiting_transfer',
18
+ CLOSED: 'closed',
19
+ COMPLETE: 'complete',
20
+ EVENT: 'event',
21
+ INVALID: 'invalid',
22
+ ISSUE_DETERMINATION: 'issue_determination',
23
+ LPA_QUESTIONNAIRE: 'lpa_questionnaire',
24
+ READY_TO_START: 'ready_to_start',
25
+ TRANSFERRED: 'transferred',
26
+ VALIDATION: 'validation',
27
+ WITHDRAWN: 'withdrawn',
28
+ } as const;
29
+
1
30
  export const APPEAL_ALLOCATION_LEVEL = {
2
31
  A: 'A',
3
32
  B: 'B',
@@ -310,6 +339,7 @@ export const APPEAL_LPA_QUESTIONNAIRE_VALIDATION_OUTCOME = {
310
339
  export const APPEAL_NOTIFICATION_METHOD = {
311
340
  ADVERT: 'advert',
312
341
  LETTER: 'letter',
342
+ NOT_NOTIFIED: 'not_notified',
313
343
  NOTICE: 'notice',
314
344
  } as const;
315
345
 
@@ -407,6 +437,11 @@ export const METHOD = {
407
437
  POST: 'post',
408
438
  } as const;
409
439
 
440
+ export const NSIP_PROJECT_SOURCE_SYSTEM = {
441
+ BACK_OFFICE_APPLICATIONS: 'back-office-applications',
442
+ HORIZON: 'horizon',
443
+ } as const;
444
+
410
445
  export const NSIP_CA_AND_TP_EVIDENCE = {
411
446
  AWAITING_SUBMISSION: 'awaiting_submission',
412
447
  NOT_APPLICABLE: 'not_applicable',
@@ -652,8 +687,11 @@ export const NSIP_SECURITY_CLASSIFICATION = {
652
687
  } as const;
653
688
 
654
689
  export const NSIP_SOURCE_SYSTEM = {
690
+ BACK_OFFICE_APPEALS: 'back-office-appeals',
655
691
  BACK_OFFICE_APPLICATIONS: 'back-office-applications',
656
692
  HORIZON: 'horizon',
693
+ NI_FILE: 'ni_file',
694
+ SHAREPOINT: 'sharepoint',
657
695
  } as const;
658
696
 
659
697
  export const NSIP_STAGE = {
package/src/enums.js CHANGED
@@ -1,3 +1,32 @@
1
+ export const APPEAL_HAS_CASE_DECISION_OUTCOME = Object.freeze({
2
+ ALLOWED: 'allowed',
3
+ DISMISSED: 'dismissed',
4
+ INVALID: 'invalid',
5
+ SPLIT_DECISION: 'split_decision',
6
+ });
7
+
8
+ export const APPEAL_HAS_CASE_PROCEDURE = Object.freeze({
9
+ HEARING: 'hearing',
10
+ INQUIRY: 'inquiry',
11
+ WRITTEN: 'written',
12
+ });
13
+
14
+ export const APPEAL_HAS_CASE_STATUS = Object.freeze({
15
+ ASSIGN_CASE_OFFICER: 'assign_case_officer',
16
+ AWAITING_EVENT: 'awaiting_event',
17
+ AWAITING_TRANSFER: 'awaiting_transfer',
18
+ CLOSED: 'closed',
19
+ COMPLETE: 'complete',
20
+ EVENT: 'event',
21
+ INVALID: 'invalid',
22
+ ISSUE_DETERMINATION: 'issue_determination',
23
+ LPA_QUESTIONNAIRE: 'lpa_questionnaire',
24
+ READY_TO_START: 'ready_to_start',
25
+ TRANSFERRED: 'transferred',
26
+ VALIDATION: 'validation',
27
+ WITHDRAWN: 'withdrawn',
28
+ });
29
+
1
30
  export const APPEAL_ALLOCATION_LEVEL = Object.freeze({
2
31
  A: 'A',
3
32
  B: 'B',
@@ -310,6 +339,7 @@ export const APPEAL_LPA_QUESTIONNAIRE_VALIDATION_OUTCOME = Object.freeze({
310
339
  export const APPEAL_NOTIFICATION_METHOD = Object.freeze({
311
340
  ADVERT: 'advert',
312
341
  LETTER: 'letter',
342
+ NOT_NOTIFIED: 'not_notified',
313
343
  NOTICE: 'notice',
314
344
  });
315
345
 
@@ -407,6 +437,11 @@ export const METHOD = Object.freeze({
407
437
  POST: 'post',
408
438
  });
409
439
 
440
+ export const NSIP_PROJECT_SOURCE_SYSTEM = Object.freeze({
441
+ BACK_OFFICE_APPLICATIONS: 'back-office-applications',
442
+ HORIZON: 'horizon',
443
+ });
444
+
410
445
  export const NSIP_CA_AND_TP_EVIDENCE = Object.freeze({
411
446
  AWAITING_SUBMISSION: 'awaiting_submission',
412
447
  NOT_APPLICABLE: 'not_applicable',
@@ -652,8 +687,11 @@ export const NSIP_SECURITY_CLASSIFICATION = Object.freeze({
652
687
  });
653
688
 
654
689
  export const NSIP_SOURCE_SYSTEM = Object.freeze({
690
+ BACK_OFFICE_APPEALS: 'back-office-appeals',
655
691
  BACK_OFFICE_APPLICATIONS: 'back-office-applications',
656
692
  HORIZON: 'horizon',
693
+ NI_FILE: 'ni_file',
694
+ SHAREPOINT: 'sharepoint',
657
695
  });
658
696
 
659
697
  export const NSIP_STAGE = Object.freeze({
package/src/index.cjs CHANGED
@@ -81,6 +81,35 @@ function loadSchemaSync(filePath) {
81
81
  return jsoncParser.parse(content.toString());
82
82
  }
83
83
 
84
+ const APPEAL_HAS_CASE_DECISION_OUTCOME = Object.freeze({
85
+ ALLOWED: 'allowed',
86
+ DISMISSED: 'dismissed',
87
+ INVALID: 'invalid',
88
+ SPLIT_DECISION: 'split_decision',
89
+ });
90
+
91
+ const APPEAL_HAS_CASE_PROCEDURE = Object.freeze({
92
+ HEARING: 'hearing',
93
+ INQUIRY: 'inquiry',
94
+ WRITTEN: 'written',
95
+ });
96
+
97
+ const APPEAL_HAS_CASE_STATUS = Object.freeze({
98
+ ASSIGN_CASE_OFFICER: 'assign_case_officer',
99
+ AWAITING_EVENT: 'awaiting_event',
100
+ AWAITING_TRANSFER: 'awaiting_transfer',
101
+ CLOSED: 'closed',
102
+ COMPLETE: 'complete',
103
+ EVENT: 'event',
104
+ INVALID: 'invalid',
105
+ ISSUE_DETERMINATION: 'issue_determination',
106
+ LPA_QUESTIONNAIRE: 'lpa_questionnaire',
107
+ READY_TO_START: 'ready_to_start',
108
+ TRANSFERRED: 'transferred',
109
+ VALIDATION: 'validation',
110
+ WITHDRAWN: 'withdrawn',
111
+ });
112
+
84
113
  const APPEAL_ALLOCATION_LEVEL = Object.freeze({
85
114
  A: 'A',
86
115
  B: 'B',
@@ -393,6 +422,7 @@ const APPEAL_LPA_QUESTIONNAIRE_VALIDATION_OUTCOME = Object.freeze({
393
422
  const APPEAL_NOTIFICATION_METHOD = Object.freeze({
394
423
  ADVERT: 'advert',
395
424
  LETTER: 'letter',
425
+ NOT_NOTIFIED: 'not_notified',
396
426
  NOTICE: 'notice',
397
427
  });
398
428
 
@@ -490,6 +520,11 @@ const METHOD = Object.freeze({
490
520
  POST: 'post',
491
521
  });
492
522
 
523
+ const NSIP_PROJECT_SOURCE_SYSTEM = Object.freeze({
524
+ BACK_OFFICE_APPLICATIONS: 'back-office-applications',
525
+ HORIZON: 'horizon',
526
+ });
527
+
493
528
  const NSIP_CA_AND_TP_EVIDENCE = Object.freeze({
494
529
  AWAITING_SUBMISSION: 'awaiting_submission',
495
530
  NOT_APPLICABLE: 'not_applicable',
@@ -735,8 +770,11 @@ const NSIP_SECURITY_CLASSIFICATION = Object.freeze({
735
770
  });
736
771
 
737
772
  const NSIP_SOURCE_SYSTEM = Object.freeze({
773
+ BACK_OFFICE_APPEALS: 'back-office-appeals',
738
774
  BACK_OFFICE_APPLICATIONS: 'back-office-applications',
739
775
  HORIZON: 'horizon',
776
+ NI_FILE: 'ni_file',
777
+ SHAREPOINT: 'sharepoint',
740
778
  });
741
779
 
742
780
  const NSIP_STAGE = Object.freeze({
@@ -874,6 +912,9 @@ exports.APPEAL_EIA_DEVELOPMENT_DESCRIPTION = APPEAL_EIA_DEVELOPMENT_DESCRIPTION;
874
912
  exports.APPEAL_EIA_ENVIRONMENTAL_IMPACT_SCHEDULE = APPEAL_EIA_ENVIRONMENTAL_IMPACT_SCHEDULE;
875
913
  exports.APPEAL_EVENT_STATUS = APPEAL_EVENT_STATUS;
876
914
  exports.APPEAL_EVENT_TYPE = APPEAL_EVENT_TYPE;
915
+ exports.APPEAL_HAS_CASE_DECISION_OUTCOME = APPEAL_HAS_CASE_DECISION_OUTCOME;
916
+ exports.APPEAL_HAS_CASE_PROCEDURE = APPEAL_HAS_CASE_PROCEDURE;
917
+ exports.APPEAL_HAS_CASE_STATUS = APPEAL_HAS_CASE_STATUS;
877
918
  exports.APPEAL_INVALID_OR_INCOMPLETE_DETAILS = APPEAL_INVALID_OR_INCOMPLETE_DETAILS;
878
919
  exports.APPEAL_KNOWS_ALL_OWNERS = APPEAL_KNOWS_ALL_OWNERS;
879
920
  exports.APPEAL_KNOWS_OTHER_OWNERS = APPEAL_KNOWS_OTHER_OWNERS;
@@ -909,6 +950,7 @@ exports.NSIP_ORIGIN = NSIP_ORIGIN;
909
950
  exports.NSIP_PLANNING_INSPECTORATE_ROLE = NSIP_PLANNING_INSPECTORATE_ROLE;
910
951
  exports.NSIP_POLICY_COMPLIANCE_DOCUMENT = NSIP_POLICY_COMPLIANCE_DOCUMENT;
911
952
  exports.NSIP_PRINCIPAL_AREA_DISAGREEMENT_SUMMARY_STMT = NSIP_PRINCIPAL_AREA_DISAGREEMENT_SUMMARY_STMT;
953
+ exports.NSIP_PROJECT_SOURCE_SYSTEM = NSIP_PROJECT_SOURCE_SYSTEM;
912
954
  exports.NSIP_PROJECT_TYPE = NSIP_PROJECT_TYPE;
913
955
  exports.NSIP_PUBLIC_SECTOR_EQUALITY_DUTY = NSIP_PUBLIC_SECTOR_EQUALITY_DUTY;
914
956
  exports.NSIP_PUBLISHED_STATUS = NSIP_PUBLISHED_STATUS;
@@ -0,0 +1,196 @@
1
+ import snakeCase from 'lodash.snakecase';
2
+
3
+ const SPACING = ' ';
4
+ const NEW_LINE = '\n';
5
+
6
+ /**
7
+ * Generate JS code to define exported constants for the given enum values
8
+ *
9
+ * @param {string} name
10
+ * @param {string[]} values
11
+ * @param {Object} opts
12
+ * @param {boolean} [opts.ts] - whether to generate the TS type or JS code
13
+ * @returns {string}
14
+ */
15
+ export function generateConstants(name, values, { ts = false } = {}) {
16
+ const freezeStart = ts ? '' : 'Object.freeze(';
17
+ const freezeEnd = ts ? ' as const' : ')';
18
+ const exportPrefix = 'export ';
19
+ const lines = [`${exportPrefix}const ${formatName(name)} = ${freezeStart}{`];
20
+ /**
21
+ * @param {string} line
22
+ * @param {number} spacing
23
+ */
24
+ const addWithSpace = (line, spacing = 0) => lines.push(SPACING.repeat(spacing) + line);
25
+
26
+ for (const value of values.sort()) {
27
+ addWithSpace(`${formatName(value)}: '${value}',`, 1);
28
+ }
29
+
30
+ lines.push(`}${freezeEnd};`);
31
+
32
+ return lines.join(NEW_LINE);
33
+ }
34
+
35
+ /**
36
+ * Format a name for use as a constant value: UPPER_SNAKE_CASE
37
+ *
38
+ * @param {string} name
39
+ * @returns {string}
40
+ */
41
+ function formatName(name) {
42
+ return snakeCase(name).toUpperCase();
43
+ }
44
+
45
+ /**
46
+ * @param {{schemaName: string, key: string, values: string[]}[]} enums
47
+ * @returns {Record<string, string[]>} map of enum name to values
48
+ */
49
+ export function generateEnumMap(enums) {
50
+ /** @type {Object<string, string[]>} */
51
+ const enumProps = {};
52
+
53
+ // only allow one duplicate - else the superset logic gets complex
54
+ const duplicateKeys = new Set();
55
+ const warnings = [];
56
+ const infos = [];
57
+
58
+ for (const e of enums) {
59
+ const prefix = schemaPrefix(e.schemaName);
60
+ const key = prefix ? prefix + '_' + e.key : e.key;
61
+
62
+ const existingEnum = enumProps[key];
63
+ const thisEnum = e.values;
64
+ if (!existingEnum) {
65
+ enumProps[key] = e.values;
66
+ } else if (!enumsMatch(existingEnum, thisEnum)) {
67
+ const existingEnumProps = enums.find((e) => e.values === existingEnum);
68
+ const setIndex = indexOfSuperset(existingEnum, thisEnum);
69
+ // handle duplicate enums - but one must be a superset of the other
70
+ if (setIndex === -1) {
71
+ throw new Error(
72
+ `Enums ${existingEnumProps.key} from ${existingEnumProps.schemaName} and ${e.key} from ${e.schemaName} have the same name but one is not a superset of the other`
73
+ );
74
+ }
75
+ // and only allow one duplicate
76
+ if (duplicateKeys.has(key)) {
77
+ throw new Error(
78
+ `enum ${e.key} is used by multiple schemas, including ${existingEnumProps.schemaName} and ${e.schemaName}`
79
+ );
80
+ }
81
+ duplicateKeys.add(key);
82
+ warnings.push([
83
+ '⚠️ enum key',
84
+ key,
85
+ 'is used with different values in',
86
+ existingEnumProps.schemaName,
87
+ 'and',
88
+ e.schemaName
89
+ ]);
90
+
91
+ if (setIndex === 1) {
92
+ // existing enum is the superset
93
+ // so this enum goes with a specific name
94
+ enumProps[e.schemaName.replace('.schema.json', '') + '_' + e.key] = e.values;
95
+ } else if (setIndex === 2) {
96
+ // this enum is the superset
97
+ // so 'swap in' this enum
98
+ enumProps[key] = e.values;
99
+ enumProps[existingEnumProps.schemaName.replace('.schema.json', '') + '_' + existingEnumProps.key] =
100
+ existingEnumProps.values;
101
+ }
102
+ } else {
103
+ // if the enums do match, nothing to change
104
+ infos.push(['ℹ️ enum key', key, 'is used multiple times but uses the same values']);
105
+ }
106
+ }
107
+ for (const info of infos) {
108
+ console.log(...info);
109
+ }
110
+ for (const warning of warnings) {
111
+ console.log(...warning);
112
+ }
113
+ return enumProps;
114
+ }
115
+
116
+ /**
117
+ * Do list1 and list2 match?
118
+ *
119
+ * @param {string[]} list1
120
+ * @param {string[]} list2
121
+ */
122
+ export function enumsMatch(list1, list2) {
123
+ const set1 = new Set(list1);
124
+ const set2 = new Set(list2);
125
+ // get all elements that are in set1 or set2 but not in both
126
+ // if there are none, they match
127
+ return set1.symmetricDifference(set2).size === 0;
128
+ }
129
+
130
+ /**
131
+ * Is list1 a superset of list2, or vice versa?
132
+ *
133
+ * @param {string[]} list1
134
+ * @param {string[]} list2
135
+ * @returns {1 | 2 | -1} -1 if neither list is a superset of the other
136
+ */
137
+ export function indexOfSuperset(list1, list2) {
138
+ const set1 = new Set(list1);
139
+ const set2 = new Set(list2);
140
+ if (set1.isSupersetOf(set2)) {
141
+ return 1;
142
+ }
143
+ if (set2.isSupersetOf(set1)) {
144
+ return 2;
145
+ }
146
+ return -1;
147
+ }
148
+
149
+ /**
150
+ *
151
+ * @param {{schemaName: string, key: string, values: string[]}[]} enums
152
+ * @param {Object<string, {type?: string|string[], enum?: string[]}>} properties
153
+ * @param {string} schemaName
154
+ */
155
+ export function collectEnumProps(enums, properties = {}, schemaName) {
156
+ for (const [key, prop] of Object.entries(properties)) {
157
+ const hasStringEnum = (p) =>
158
+ p && p.enum && Array.isArray(p.enum) && p.type && (p.type === 'string' || p.type.includes('string'));
159
+ const getEnumValues = (p) => p.filter((e) => e !== null);
160
+ const collectEnumFromProp = (p) => {
161
+ if (hasStringEnum(p)) {
162
+ const values = getEnumValues(p.enum);
163
+ const asSet = new Set(values);
164
+ if (values.length > asSet.size) {
165
+ throw new Error(`enum ${key} from ${schemaName} has duplicate elements`);
166
+ }
167
+ enums.push({
168
+ schemaName,
169
+ key,
170
+ values: values
171
+ });
172
+ }
173
+ };
174
+
175
+ collectEnumFromProp(prop);
176
+ collectEnumFromProp(prop.items);
177
+ }
178
+ }
179
+
180
+ /**
181
+ * Generate a prefix based on the schema name
182
+ *
183
+ * @param {string} schemaName
184
+ * @returns {string|undefined}
185
+ */
186
+ export function schemaPrefix(schemaName) {
187
+ if (schemaName === 'message') {
188
+ return 'message';
189
+ }
190
+ if (schemaName.toLowerCase().includes('appeal')) {
191
+ return 'appeal';
192
+ }
193
+ if (schemaName.toLowerCase().includes('nsip')) {
194
+ return 'nsip';
195
+ }
196
+ }