@pdtf/schemas 3.6.0-dev.3 → 3.6.0-dev.30

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 (192) hide show
  1. package/docs/ta6-certificate-permit-contract.md +51 -0
  2. package/docs/v4-mapping-and-recomposition.md +419 -0
  3. package/index.js +210 -0
  4. package/package.json +10 -1
  5. package/src/schemas/v3/combined.json +2261 -657
  6. package/src/schemas/v3/compactSkeleton.txt +120 -51
  7. package/src/schemas/v3/overlays/baspi4.json +54 -74
  8. package/src/schemas/v3/overlays/baspi5.json +54 -74
  9. package/src/schemas/v3/overlays/extensions/ac.json +2 -1
  10. package/src/schemas/v3/overlays/extensions/dk.json +3 -2
  11. package/src/schemas/v3/overlays/extensions/fd.json +2 -1
  12. package/src/schemas/v3/overlays/extensions/ic.json +44 -9
  13. package/src/schemas/v3/overlays/extensions/lc.json +3 -2
  14. package/src/schemas/v3/overlays/extensions/mi.json +2 -1
  15. package/src/schemas/v3/overlays/extensions/nd.json +3 -2
  16. package/src/schemas/v3/overlays/extensions/pc.json +3 -2
  17. package/src/schemas/v3/overlays/extensions/ph.json +2 -1
  18. package/src/schemas/v3/overlays/extensions/rw.json +4 -3
  19. package/src/schemas/v3/overlays/extensions/sc.json +8 -4
  20. package/src/schemas/v3/overlays/extensions/sd.json +3 -2
  21. package/src/schemas/v3/overlays/extensions/tr.json +3 -2
  22. package/src/schemas/v3/overlays/extensions/wg.json +2 -1
  23. package/src/schemas/v3/overlays/llc1.json +1 -2
  24. package/src/schemas/v3/overlays/lpe1.json +3 -2
  25. package/src/schemas/v3/overlays/nts.json +7 -3
  26. package/src/schemas/v3/overlays/nts2.json +9 -4
  27. package/src/schemas/v3/overlays/ntsl.json +5 -2
  28. package/src/schemas/v3/overlays/ntsl2.json +7 -3
  29. package/src/schemas/v3/overlays/piq.json +34 -25
  30. package/src/schemas/v3/overlays/rds.json +24 -50
  31. package/src/schemas/v3/overlays/sef25.json +16 -2
  32. package/src/schemas/v3/overlays/ta10.json +0 -9
  33. package/src/schemas/v3/overlays/ta6.json +39 -70
  34. package/src/schemas/v3/overlays/ta6ed6.json +331 -307
  35. package/{pensive-tesla-d0d355/src/schemas/v3/overlays/ta6.json → src/schemas/v3/overlays/ta6ed6v2.json} +1574 -1464
  36. package/src/schemas/v3/overlays/ta7.json +2 -1
  37. package/src/schemas/v3/overlays/ta7ed5.json +68 -21
  38. package/src/schemas/v3/pdtf-transaction.json +1030 -492
  39. package/src/schemas/v3/skeleton.json +163 -57
  40. package/src/schemas/v4/Gift.json +88 -0
  41. package/src/schemas/v4/Offer.json +425 -0
  42. package/src/schemas/v4/Organisation.json +167 -0
  43. package/src/schemas/v4/Person.json +321 -0
  44. package/src/schemas/v4/Property.json +27813 -0
  45. package/src/schemas/v4/Representation.json +67 -0
  46. package/src/schemas/v4/SellerCapacity.json +193 -0
  47. package/src/schemas/v4/Title.json +14660 -0
  48. package/src/schemas/v4/Transaction.json +1612 -0
  49. package/src/schemas/v4/TransactionRole.json +59 -0
  50. package/src/schemas/v4/mapping.json +1161 -0
  51. package/src/utils/checkTa6OmissionCompatibility.js +146 -0
  52. package/src/utils/extractExtensionOverlays.js +11 -2
  53. package/src/utils/extractOverlay.js +21 -0
  54. package/src/utils/generateV4Schemas.js +1358 -0
  55. package/src/utils/syncTa6ed6v2Markers.js +92 -0
  56. package/src/utils/v4.js +838 -0
  57. package/CLAUDE.md +0 -101
  58. package/pensive-tesla-d0d355/CLAUDE.md +0 -101
  59. package/pensive-tesla-d0d355/LICENSE +0 -21
  60. package/pensive-tesla-d0d355/README.md +0 -435
  61. package/pensive-tesla-d0d355/docs/branch-release-workflow.md +0 -138
  62. package/pensive-tesla-d0d355/docs/sef25-extensions-ui-spec.md +0 -355
  63. package/pensive-tesla-d0d355/index.js +0 -654
  64. package/pensive-tesla-d0d355/package-lock.json +0 -7297
  65. package/pensive-tesla-d0d355/package.json +0 -44
  66. package/pensive-tesla-d0d355/src/examples/v1/exampleAddParticipantVouch.json +0 -32
  67. package/pensive-tesla-d0d355/src/examples/v1/exampleDocumentedVouch.json +0 -40
  68. package/pensive-tesla-d0d355/src/examples/v1/exampleElectronicRecord.json +0 -30
  69. package/pensive-tesla-d0d355/src/examples/v1/exampleTransaction.json +0 -878
  70. package/pensive-tesla-d0d355/src/examples/v1/exampleVouch.json +0 -25
  71. package/pensive-tesla-d0d355/src/examples/v2/exampleTransaction.json +0 -901
  72. package/pensive-tesla-d0d355/src/examples/v3/exampleAddParticipantVouch.json +0 -38
  73. package/pensive-tesla-d0d355/src/examples/v3/exampleCustomOverlay.json +0 -55
  74. package/pensive-tesla-d0d355/src/examples/v3/exampleCustomOverlay2.json +0 -93
  75. package/pensive-tesla-d0d355/src/examples/v3/exampleDocumentedVouch.json +0 -47
  76. package/pensive-tesla-d0d355/src/examples/v3/exampleElectronicRecord.json +0 -36
  77. package/pensive-tesla-d0d355/src/examples/v3/exampleTransaction.json +0 -1038
  78. package/pensive-tesla-d0d355/src/examples/v3/exampleVouch.json +0 -32
  79. package/pensive-tesla-d0d355/src/mappings/SendPropertyDetailsRequestSchema.json +0 -1588
  80. package/pensive-tesla-d0d355/src/mappings/adf.js +0 -198
  81. package/pensive-tesla-d0d355/src/schemas/v1/GeoJSON.json +0 -1279
  82. package/pensive-tesla-d0d355/src/schemas/v1/baspiNotes.html +0 -102
  83. package/pensive-tesla-d0d355/src/schemas/v1/energy-performance-certificate.json +0 -124
  84. package/pensive-tesla-d0d355/src/schemas/v1/freehold-information.json +0 -2051
  85. package/pensive-tesla-d0d355/src/schemas/v1/leasehold-information.json +0 -2064
  86. package/pensive-tesla-d0d355/src/schemas/v1/legal-information.json +0 -1045
  87. package/pensive-tesla-d0d355/src/schemas/v1/material-facts.json +0 -2109
  88. package/pensive-tesla-d0d355/src/schemas/v1/pdtf-transaction-search-results.json +0 -40
  89. package/pensive-tesla-d0d355/src/schemas/v1/pdtf-transaction.json +0 -191
  90. package/pensive-tesla-d0d355/src/schemas/v1/searches/drainage-and-water.json +0 -261
  91. package/pensive-tesla-d0d355/src/schemas/v1/searches/local-land-charges.json +0 -69
  92. package/pensive-tesla-d0d355/src/schemas/v1/searches/local-searches-required.json +0 -857
  93. package/pensive-tesla-d0d355/src/schemas/v1/searches.json +0 -237
  94. package/pensive-tesla-d0d355/src/schemas/v1/title-deed.json +0 -841
  95. package/pensive-tesla-d0d355/src/schemas/v2/baspiNotes.html +0 -102
  96. package/pensive-tesla-d0d355/src/schemas/v2/combined.json +0 -37731
  97. package/pensive-tesla-d0d355/src/schemas/v2/overlays/baspi.json +0 -8132
  98. package/pensive-tesla-d0d355/src/schemas/v2/overlays/con29DW.json +0 -705
  99. package/pensive-tesla-d0d355/src/schemas/v2/overlays/con29R.json +0 -2956
  100. package/pensive-tesla-d0d355/src/schemas/v2/overlays/fme1.json +0 -1259
  101. package/pensive-tesla-d0d355/src/schemas/v2/overlays/llc1.json +0 -25
  102. package/pensive-tesla-d0d355/src/schemas/v2/overlays/lpe1.json +0 -2171
  103. package/pensive-tesla-d0d355/src/schemas/v2/overlays/nts.json +0 -326
  104. package/pensive-tesla-d0d355/src/schemas/v2/overlays/oc1.json +0 -2799
  105. package/pensive-tesla-d0d355/src/schemas/v2/overlays/piq.json +0 -3419
  106. package/pensive-tesla-d0d355/src/schemas/v2/overlays/rds.json +0 -3736
  107. package/pensive-tesla-d0d355/src/schemas/v2/overlays/ta10.json +0 -5306
  108. package/pensive-tesla-d0d355/src/schemas/v2/overlays/ta6.json +0 -4533
  109. package/pensive-tesla-d0d355/src/schemas/v2/overlays/ta7.json +0 -1045
  110. package/pensive-tesla-d0d355/src/schemas/v2/pdtf-transaction.json +0 -34351
  111. package/pensive-tesla-d0d355/src/schemas/v2/skeleton.json +0 -3973
  112. package/pensive-tesla-d0d355/src/schemas/v3/combined.json +0 -48469
  113. package/pensive-tesla-d0d355/src/schemas/v3/compactSkeleton.txt +0 -4519
  114. package/pensive-tesla-d0d355/src/schemas/v3/overlays/README.md +0 -299
  115. package/pensive-tesla-d0d355/src/schemas/v3/overlays/baspi4.json +0 -8025
  116. package/pensive-tesla-d0d355/src/schemas/v3/overlays/baspi5.json +0 -8175
  117. package/pensive-tesla-d0d355/src/schemas/v3/overlays/con29DW.json +0 -716
  118. package/pensive-tesla-d0d355/src/schemas/v3/overlays/con29R.json +0 -2981
  119. package/pensive-tesla-d0d355/src/schemas/v3/overlays/extensions/ac.json +0 -333
  120. package/pensive-tesla-d0d355/src/schemas/v3/overlays/extensions/as.json +0 -74
  121. package/pensive-tesla-d0d355/src/schemas/v3/overlays/extensions/dk.json +0 -32
  122. package/pensive-tesla-d0d355/src/schemas/v3/overlays/extensions/dr.json +0 -73
  123. package/pensive-tesla-d0d355/src/schemas/v3/overlays/extensions/er.json +0 -85
  124. package/pensive-tesla-d0d355/src/schemas/v3/overlays/extensions/fd.json +0 -75
  125. package/pensive-tesla-d0d355/src/schemas/v3/overlays/extensions/hi.json +0 -51
  126. package/pensive-tesla-d0d355/src/schemas/v3/overlays/extensions/hs.json +0 -73
  127. package/pensive-tesla-d0d355/src/schemas/v3/overlays/extensions/ic.json +0 -59
  128. package/pensive-tesla-d0d355/src/schemas/v3/overlays/extensions/jk.json +0 -96
  129. package/pensive-tesla-d0d355/src/schemas/v3/overlays/extensions/la.json +0 -85
  130. package/pensive-tesla-d0d355/src/schemas/v3/overlays/extensions/lc.json +0 -75
  131. package/pensive-tesla-d0d355/src/schemas/v3/overlays/extensions/ma.json +0 -90
  132. package/pensive-tesla-d0d355/src/schemas/v3/overlays/extensions/mc.json +0 -38
  133. package/pensive-tesla-d0d355/src/schemas/v3/overlays/extensions/mi.json +0 -69
  134. package/pensive-tesla-d0d355/src/schemas/v3/overlays/extensions/nd.json +0 -43
  135. package/pensive-tesla-d0d355/src/schemas/v3/overlays/extensions/oa.json +0 -24
  136. package/pensive-tesla-d0d355/src/schemas/v3/overlays/extensions/oc.json +0 -57
  137. package/pensive-tesla-d0d355/src/schemas/v3/overlays/extensions/pc.json +0 -37
  138. package/pensive-tesla-d0d355/src/schemas/v3/overlays/extensions/ph.json +0 -194
  139. package/pensive-tesla-d0d355/src/schemas/v3/overlays/extensions/rw.json +0 -68
  140. package/pensive-tesla-d0d355/src/schemas/v3/overlays/extensions/sb.json +0 -73
  141. package/pensive-tesla-d0d355/src/schemas/v3/overlays/extensions/sc.json +0 -129
  142. package/pensive-tesla-d0d355/src/schemas/v3/overlays/extensions/sd.json +0 -63
  143. package/pensive-tesla-d0d355/src/schemas/v3/overlays/extensions/sf.json +0 -74
  144. package/pensive-tesla-d0d355/src/schemas/v3/overlays/extensions/sl.json +0 -68
  145. package/pensive-tesla-d0d355/src/schemas/v3/overlays/extensions/ta.json +0 -252
  146. package/pensive-tesla-d0d355/src/schemas/v3/overlays/extensions/tf.json +0 -103
  147. package/pensive-tesla-d0d355/src/schemas/v3/overlays/extensions/tr.json +0 -73
  148. package/pensive-tesla-d0d355/src/schemas/v3/overlays/extensions/wg.json +0 -350
  149. package/pensive-tesla-d0d355/src/schemas/v3/overlays/fme1.json +0 -1266
  150. package/pensive-tesla-d0d355/src/schemas/v3/overlays/llc1.json +0 -25
  151. package/pensive-tesla-d0d355/src/schemas/v3/overlays/lpe1.json +0 -2199
  152. package/pensive-tesla-d0d355/src/schemas/v3/overlays/nts.json +0 -2157
  153. package/pensive-tesla-d0d355/src/schemas/v3/overlays/nts2.json +0 -2742
  154. package/pensive-tesla-d0d355/src/schemas/v3/overlays/ntsl.json +0 -1813
  155. package/pensive-tesla-d0d355/src/schemas/v3/overlays/ntsl2.json +0 -2217
  156. package/pensive-tesla-d0d355/src/schemas/v3/overlays/oc1.json +0 -2817
  157. package/pensive-tesla-d0d355/src/schemas/v3/overlays/piq.json +0 -3322
  158. package/pensive-tesla-d0d355/src/schemas/v3/overlays/rds.json +0 -3665
  159. package/pensive-tesla-d0d355/src/schemas/v3/overlays/sef25.json +0 -1639
  160. package/pensive-tesla-d0d355/src/schemas/v3/overlays/sr24.json +0 -38
  161. package/pensive-tesla-d0d355/src/schemas/v3/overlays/ta10.json +0 -4654
  162. package/pensive-tesla-d0d355/src/schemas/v3/overlays/ta6ed6.json +0 -6534
  163. package/pensive-tesla-d0d355/src/schemas/v3/overlays/ta7.json +0 -1537
  164. package/pensive-tesla-d0d355/src/schemas/v3/overlays/ta7ed5.json +0 -1551
  165. package/pensive-tesla-d0d355/src/schemas/v3/pdtf-transaction.json +0 -41573
  166. package/pensive-tesla-d0d355/src/schemas/v3/skeleton.json +0 -5767
  167. package/pensive-tesla-d0d355/src/schemas/verifiedClaims/README.md +0 -21
  168. package/pensive-tesla-d0d355/src/schemas/verifiedClaims/pdtf-verified-claims.json +0 -447
  169. package/pensive-tesla-d0d355/src/utils/compactSkeleton.js +0 -84
  170. package/pensive-tesla-d0d355/src/utils/countTokens.js +0 -67
  171. package/pensive-tesla-d0d355/src/utils/extractExtensionOverlays.js +0 -624
  172. package/pensive-tesla-d0d355/src/utils/extractOverlay.js +0 -381
  173. package/pensive-tesla-d0d355/src/utils/extractProperties.js +0 -44
  174. package/pensive-tesla-d0d355/src/utils/listPathTitles.js +0 -36
  175. package/pensive-tesla-d0d355/src/utils/minimalSkeleton.js +0 -85
  176. package/pensive-tesla-d0d355/src/utils/pathList.csv +0 -903
  177. package/pensive-tesla-d0d355/src/utils/pathSkeleton.js +0 -181
  178. package/src/examples/v1/exampleAddParticipantVouch.json +0 -32
  179. package/src/examples/v1/exampleDocumentedVouch.json +0 -40
  180. package/src/examples/v1/exampleElectronicRecord.json +0 -30
  181. package/src/examples/v1/exampleTransaction.json +0 -878
  182. package/src/examples/v1/exampleVouch.json +0 -25
  183. package/src/examples/v2/exampleTransaction.json +0 -901
  184. package/src/examples/v3/exampleAddParticipantVouch.json +0 -38
  185. package/src/examples/v3/exampleCustomOverlay.json +0 -55
  186. package/src/examples/v3/exampleCustomOverlay2.json +0 -93
  187. package/src/examples/v3/exampleDocumentedVouch.json +0 -47
  188. package/src/examples/v3/exampleElectronicRecord.json +0 -36
  189. package/src/examples/v3/exampleTransaction.json +0 -1038
  190. package/src/examples/v3/exampleVouch.json +0 -32
  191. package/src/mappings/SendPropertyDetailsRequestSchema.json +0 -1588
  192. package/src/mappings/adf.js +0 -198
@@ -1,624 +0,0 @@
1
- const traverse = require("traverse");
2
- const jp = require("jsonpointer");
3
- const fs = require("fs");
4
- const path = require("path");
5
-
6
- const combinedSchema = require("../schemas/v3/combined.json");
7
-
8
- // Derive ref-related field names from a refType
9
- function getRefConfig(refType) {
10
- if (refType === "nts2Ref") {
11
- // Legacy mapping: nts2Ref -> ntsRef in output
12
- return {
13
- ref: "nts2Ref",
14
- outputRef: "ntsRef",
15
- required: "nts2Required",
16
- title: "nts2Title",
17
- description: "nts2Description",
18
- enumKey: "nts2Enum",
19
- };
20
- }
21
- if (refType === "sef25Ref") {
22
- // SEF25 extensions also appear as ntsRef in output
23
- return {
24
- ref: "sef25Ref",
25
- outputRef: "ntsRef",
26
- required: "sef25Required",
27
- title: "sef25Title",
28
- description: "sef25Description",
29
- enumKey: "sef25Enum",
30
- };
31
- }
32
- // For other ref types, derive keys by replacing "Ref" suffix
33
- return {
34
- ref: refType,
35
- outputRef: refType,
36
- required: refType.replace("Ref", "Required"),
37
- title: refType.replace("Ref", "Title"),
38
- description: refType.replace("Ref", "Description"),
39
- enumKey: refType.replace("Ref", "Enum"),
40
- };
41
- }
42
-
43
- // Define the extension overlay mappings
44
- const extensionMappings = {
45
- // Outside areas
46
- oa: {
47
- name: "outsideAreas",
48
- description: "Outside areas extension for NTS",
49
- paths: [
50
- "/properties/propertyPack/properties/residentialPropertyFeatures/properties/outsideAreas",
51
- ],
52
- },
53
-
54
- // Estate rentcharges for freehold
55
- er: {
56
- name: "estateRentcharges",
57
- description: "Estate rentcharges for freehold properties",
58
- paths: [
59
- "/properties/propertyPack/properties/ownership/properties/ownershipsToBeTransferred/items/oneOf/0/properties/estateRentcharges",
60
- ],
61
- },
62
-
63
- // Managing agent contact details for leasehold
64
- ma: {
65
- name: "managingAgent",
66
- description: "Managing agent contact details for leasehold",
67
- paths: [
68
- "/properties/propertyPack/properties/ownership/properties/ownershipsToBeTransferred/items/oneOf/2/properties/leaseholdInformation/properties/contactDetails",
69
- ],
70
- },
71
-
72
- // Transfer fees for leasehold
73
- tf: {
74
- name: "transferFees",
75
- description: "Transfer fees for leasehold",
76
- paths: [
77
- "/properties/propertyPack/properties/ownership/properties/ownershipsToBeTransferred/items/oneOf/2/properties/leaseholdInformation/properties/serviceCharge/oneOf/1/properties/transferFees",
78
- ],
79
- },
80
-
81
- // Main construction type if standard
82
- mc: {
83
- name: "mainConstruction",
84
- description: "Main construction type if standard form",
85
- paths: [
86
- "/properties/propertyPack/properties/typeOfConstruction/properties/isStandardForm/oneOf/0/properties/constructionType",
87
- ],
88
- },
89
-
90
- // Loft access and details
91
- la: {
92
- name: "loftAccess",
93
- description: "Loft access and details",
94
- paths: [
95
- "/properties/propertyPack/properties/typeOfConstruction/properties/loft",
96
- ],
97
- },
98
-
99
- // Spray foam insulation
100
- sf: {
101
- name: "sprayFoam",
102
- description: "Spray foam insulation",
103
- paths: [
104
- "/properties/propertyPack/properties/typeOfConstruction/properties/sprayFoamInsulation",
105
- ],
106
- },
107
-
108
- // Specialist issues - dry rot
109
- dr: {
110
- name: "dryRot",
111
- description: "Dry rot treatment specialist issue",
112
- paths: [
113
- "/properties/propertyPack/properties/specialistIssues/properties/dryRotEtcTreatment",
114
- ],
115
- },
116
-
117
- // Specialist issues - asbestos
118
- as: {
119
- name: "asbestos",
120
- description: "Asbestos specialist issue",
121
- paths: [
122
- "/properties/propertyPack/properties/specialistIssues/properties/containsAsbestos",
123
- ],
124
- },
125
-
126
- // Specialist issues - Japanese knotweed
127
- jk: {
128
- name: "japaneseKnotweed",
129
- description: "Japanese knotweed specialist issue",
130
- paths: [
131
- "/properties/propertyPack/properties/specialistIssues/properties/japaneseKnotweed",
132
- ],
133
- },
134
-
135
- // Specialist issues - subsidence
136
- sb: {
137
- name: "subsidence",
138
- description: "Subsidence or structural fault specialist issue",
139
- paths: [
140
- "/properties/propertyPack/properties/specialistIssues/properties/subsidenceOrStructuralFault",
141
- ],
142
- },
143
-
144
- // Specialist issues - health and safety
145
- hs: {
146
- name: "healthSafety",
147
- description: "Health and safety specialist issue",
148
- paths: [
149
- "/properties/propertyPack/properties/specialistIssues/properties/ongoingHealthOrSafetyIssue",
150
- ],
151
- },
152
-
153
- // Solar panels leased
154
- sl: {
155
- name: "solarPanelsLeased",
156
- description: "Solar panels ownership details",
157
- paths: [
158
- "/properties/propertyPack/properties/electricity/properties/solarPanels/oneOf/1/properties/panelsOwnedOutright",
159
- ],
160
- },
161
-
162
- // Heating installation date
163
- hi: {
164
- name: "heatingInstalled",
165
- description: "Central heating installation date",
166
- paths: [
167
- "/properties/propertyPack/properties/heating/properties/heatingSystem/oneOf/1/properties/centralHeatingDetails/properties/centralHeatingInstalled",
168
- ],
169
- },
170
-
171
- // Flood defences
172
- fd: {
173
- name: "floodDefences",
174
- description: "Flood defence information",
175
- paths: [
176
- "/properties/propertyPack/properties/environmentalIssues/properties/flooding/properties/floodDefences",
177
- ],
178
- },
179
-
180
- // Other property in chain
181
- oc: {
182
- name: "otherPropertyChain",
183
- description: "Other property in chain dependency",
184
- paths: [
185
- "/properties/propertyPack/properties/completionAndMoving/properties/otherPropertyInChain",
186
- ],
187
- },
188
-
189
- // Private supply costs (water & sewerage)
190
- sc: {
191
- name: "supplyCosts",
192
- description: "Associated costs for private water and sewerage supply",
193
- refType: "sef25Ref",
194
- paths: [
195
- "/properties/propertyPack/properties/waterAndDrainage/properties/water/properties/mainsWater/oneOf/0/properties/associatedCost",
196
- "/properties/propertyPack/properties/waterAndDrainage/properties/drainage/properties/mainsFoulDrainage/oneOf/2/properties/associatedCost",
197
- ],
198
- },
199
-
200
- // Parking permit costs
201
- pc: {
202
- name: "parkingPermitCost",
203
- description: "Parking permit cost and frequency",
204
- refType: "sef25Ref",
205
- paths: [
206
- "/properties/propertyPack/properties/parking/properties/controlledParking/oneOf/1/properties/costOfPermit",
207
- "/properties/propertyPack/properties/parking/properties/controlledParking/oneOf/1/properties/costOfPermitFrequency",
208
- ],
209
- },
210
-
211
- // Property hazards
212
- ph: {
213
- name: "propertyHazards",
214
- description: "Property hazards and known issues",
215
- refType: "sef25Ref",
216
- paths: [
217
- "/properties/propertyPack/properties/specialistIssues",
218
- ],
219
- },
220
-
221
- // Dropped kerb access to parking
222
- dk: {
223
- name: "droppedKerbAccess",
224
- description: "Dropped kerb access to parking",
225
- refType: "sef25Ref",
226
- paths: [
227
- "/properties/propertyPack/properties/parking/properties/droppedKerbAccess",
228
- ],
229
- },
230
-
231
- // Private right of way
232
- rw: {
233
- name: "privateRightOfWay",
234
- description: "Private right of way",
235
- refType: "sef25Ref",
236
- paths: [
237
- "/properties/propertyPack/properties/rightsAndInformalArrangements/properties/rightsOrArrangements/properties/privateRightOfWay",
238
- ],
239
- },
240
-
241
- // Storm, fire or flood damage
242
- sd: {
243
- name: "stormFireFloodDamage",
244
- description: "Storm, fire or flood damage",
245
- refType: "sef25Ref",
246
- paths: [
247
- "/properties/propertyPack/properties/environmentalIssues/properties/stormFireFloodDamage",
248
- ],
249
- },
250
-
251
- // Solar panel lease costs
252
- lc: {
253
- name: "solarLeaseCosts",
254
- description: "Solar panel lease costs",
255
- refType: "sef25Ref",
256
- paths: [
257
- "/properties/propertyPack/properties/electricity/properties/solarPanels/oneOf/1/properties/panelsOwnedOutright/oneOf/1/properties/associatedCost",
258
- ],
259
- },
260
-
261
- // Warranties and guarantees upfront
262
- wg: {
263
- name: "warrantiesGuarantees",
264
- description: "Warranties and guarantees upfront Y/N for SEF25",
265
- refType: "sef25Ref",
266
- paths: [
267
- "/properties/propertyPack/properties/guaranteesWarrantiesAndIndemnityInsurances",
268
- ],
269
- },
270
-
271
- // Insurance claims upfront
272
- ic: {
273
- name: "insuranceClaims",
274
- description: "Insurance claims upfront for SEF25",
275
- refType: "sef25Ref",
276
- paths: [
277
- "/properties/propertyPack/properties/insurance/oneOf/1/properties/insuranceClaims",
278
- ],
279
- },
280
-
281
- // Neighbour development upfront
282
- nd: {
283
- name: "neighbourDevelopment",
284
- description: "Neighbour development upfront for SEF25",
285
- refType: "sef25Ref",
286
- paths: [
287
- "/properties/propertyPack/properties/notices/properties/neighbourDevelopment",
288
- ],
289
- },
290
-
291
- // Other material issue upfront
292
- mi: {
293
- name: "otherMaterialIssue",
294
- description: "Other material issue upfront for SEF25",
295
- refType: "sef25Ref",
296
- paths: [
297
- "/properties/propertyPack/properties/additionalInformation/properties/otherMaterialIssue",
298
- ],
299
- },
300
-
301
- // Title restrictions for freehold
302
- tr: {
303
- name: "titleRestrictions",
304
- description: "Title restrictions for freehold properties",
305
- refType: "sef25Ref",
306
- paths: [
307
- "/properties/propertyPack/properties/ownership/properties/ownershipsToBeTransferred/items/oneOf/0/properties/titleRestrictions",
308
- ],
309
- },
310
-
311
- // Alterations and changes
312
- ac: {
313
- name: "alterationsAndChanges",
314
- description: "Selected alterations and changes fields for SEF25",
315
- refType: "sef25Ref",
316
- preserveDiscriminators: true,
317
- paths: [
318
- "/properties/propertyPack/properties/alterationsAndChanges/properties/extension/properties/yesNo",
319
- "/properties/propertyPack/properties/alterationsAndChanges/properties/extension/oneOf/1/properties/details",
320
- "/properties/propertyPack/properties/alterationsAndChanges/properties/extension/oneOf/1/properties/planningPermission/properties/yesNo",
321
- "/properties/propertyPack/properties/alterationsAndChanges/properties/extension/oneOf/1/properties/buildingRegApproval/properties/yesNo",
322
- "/properties/propertyPack/properties/alterationsAndChanges/properties/loftConversion/properties/yesNo",
323
- "/properties/propertyPack/properties/alterationsAndChanges/properties/loftConversion/oneOf/1/properties/details",
324
- "/properties/propertyPack/properties/alterationsAndChanges/properties/loftConversion/oneOf/1/properties/planningPermission/properties/yesNo",
325
- "/properties/propertyPack/properties/alterationsAndChanges/properties/loftConversion/oneOf/1/properties/buildingRegApproval/properties/yesNo",
326
- "/properties/propertyPack/properties/alterationsAndChanges/properties/garageConversion/properties/yesNo",
327
- "/properties/propertyPack/properties/alterationsAndChanges/properties/garageConversion/oneOf/1/properties/details",
328
- "/properties/propertyPack/properties/alterationsAndChanges/properties/garageConversion/oneOf/1/properties/planningPermission/properties/yesNo",
329
- "/properties/propertyPack/properties/alterationsAndChanges/properties/garageConversion/oneOf/1/properties/buildingRegApproval/properties/yesNo",
330
- "/properties/propertyPack/properties/alterationsAndChanges/properties/removalOfInternalWalls/properties/yesNo",
331
- "/properties/propertyPack/properties/alterationsAndChanges/properties/removalOfInternalWalls/oneOf/1/properties/details",
332
- "/properties/propertyPack/properties/alterationsAndChanges/properties/removalOfInternalWalls/oneOf/1/properties/planningPermission/properties/yesNo",
333
- "/properties/propertyPack/properties/alterationsAndChanges/properties/removalOfInternalWalls/oneOf/1/properties/buildingRegApproval/properties/yesNo",
334
- "/properties/propertyPack/properties/alterationsAndChanges/properties/changeOfUse/properties/yesNo",
335
- "/properties/propertyPack/properties/alterationsAndChanges/properties/changeOfUse/oneOf/1/properties/details",
336
- "/properties/propertyPack/properties/alterationsAndChanges/properties/changeOfUse/oneOf/1/properties/planningPermission/properties/yesNo",
337
- "/properties/propertyPack/properties/alterationsAndChanges/properties/changeOfUse/oneOf/1/properties/buildingRegApproval/properties/yesNo",
338
- ],
339
- },
340
-
341
- // TA6 edition 6 compatibility for shared MI/NTS validation
342
- ta: {
343
- name: "ta6Ed6Compatibility",
344
- description:
345
- "Compatibility enum ranges for validating shared PDTF state containing TA6 edition 6 answers",
346
- refType: "ta6ed6CompatRef",
347
- paths: [
348
- "/properties/propertyPack/properties/parking",
349
- "/properties/propertyPack/properties/heating",
350
- "/properties/propertyPack/properties/rightsAndInformalArrangements",
351
- "/properties/propertyPack/properties/legalBoundaries",
352
- ],
353
- },
354
- };
355
-
356
- // Function to extract properties at specific paths with given ref type
357
- function extractPathsWithRef(
358
- schema,
359
- paths,
360
- refConfig,
361
- preserveDiscriminators = false
362
- ) {
363
- const result = {};
364
-
365
- paths.forEach((path) => {
366
- try {
367
- const value = jp.get(schema, path);
368
- if (value && hasRef(value, refConfig)) {
369
- // Set the value at the same path in result
370
- jp.set(result, path, extractRefProperties(value, refConfig));
371
- if (preserveDiscriminators) {
372
- addAncestorDiscriminators(result, schema, path);
373
- }
374
- }
375
- } catch (err) {
376
- console.warn(`Path not found: ${path}`);
377
- }
378
- });
379
-
380
- return result;
381
- }
382
-
383
- function addAncestorDiscriminators(result, schema, path) {
384
- const parts = path.split("/").filter(Boolean);
385
-
386
- for (let index = 1; index <= parts.length; index += 1) {
387
- const ancestorPath = `/${parts.slice(0, index).join("/")}`;
388
-
389
- try {
390
- const schemaNode = jp.get(schema, ancestorPath);
391
- if (!schemaNode?.discriminator) continue;
392
-
393
- const resultNode = jp.get(result, ancestorPath);
394
- if (resultNode && typeof resultNode === "object") {
395
- resultNode.discriminator = schemaNode.discriminator;
396
- }
397
- } catch (err) {
398
- // Ancestor was not materialised by this selected path.
399
- }
400
- }
401
- }
402
-
403
- // Check if an object or its descendants have the specified ref
404
- function hasRef(obj, refConfig) {
405
- let found = false;
406
- traverse(obj).forEach(function (element) {
407
- if (element && element[refConfig.ref]) {
408
- found = true;
409
- this.stop();
410
- }
411
- });
412
- return found;
413
- }
414
-
415
- // Extract only ref-specific properties
416
- function extractRefProperties(obj, refConfig, parentKey) {
417
- const result = {};
418
-
419
- // Copy ref-specific metadata at current level
420
- if (obj[refConfig.ref]) result[refConfig.outputRef] = obj[refConfig.ref];
421
- if (obj[refConfig.required]) result.required = obj[refConfig.required];
422
- if (obj[refConfig.title]) result.title = obj[refConfig.title];
423
- if (obj[refConfig.description]) result.description = obj[refConfig.description];
424
- if (obj[refConfig.enumKey]) result.enum = obj[refConfig.enumKey];
425
-
426
- // Handle discriminator
427
- if (obj.discriminator) {
428
- result.discriminator = obj.discriminator;
429
- }
430
-
431
- // Recursively process properties
432
- if (obj.properties) {
433
- result.properties = {};
434
- Object.keys(obj.properties).forEach((key) => {
435
- const prop = obj.properties[key];
436
- if (hasRef(prop, refConfig)) {
437
- result.properties[key] = extractRefProperties(prop, refConfig, key);
438
- }
439
- });
440
- // Only keep properties if we found some with ref
441
- if (Object.keys(result.properties).length === 0) {
442
- delete result.properties;
443
- }
444
- }
445
-
446
- // Handle arrays
447
- if (obj.items) {
448
- if (hasRef(obj.items, refConfig)) {
449
- result.items = extractRefProperties(obj.items, refConfig);
450
- }
451
- }
452
-
453
- // Handle oneOf
454
- if (obj.oneOf) {
455
- // Always preserve the full array structure and order
456
- const processedOneOf = obj.oneOf.map((schema, index) => {
457
- if (hasRef(schema, refConfig)) {
458
- const extracted = extractRefProperties(schema, refConfig);
459
- // For oneOf schemas, we need to preserve discriminator enum values
460
- if (obj.discriminator && schema.properties) {
461
- const propName = obj.discriminator.propertyName;
462
- if (schema.properties[propName]) {
463
- if (!extracted.properties) extracted.properties = {};
464
- extracted.properties[propName] = {
465
- enum:
466
- schema.properties[propName][refConfig.enumKey] ||
467
- schema.properties[propName].enum,
468
- };
469
- }
470
- }
471
- // Also preserve base enum values for all other properties in the extension
472
- if (schema.properties) {
473
- if (!extracted.properties) extracted.properties = {};
474
- Object.keys(schema.properties).forEach((propName) => {
475
- const prop = schema.properties[propName];
476
- if (prop.enum) {
477
- if (!extracted.properties[propName]) {
478
- extracted.properties[propName] = {
479
- enum: prop.enum,
480
- };
481
- } else if (!extracted.properties[propName].enum) {
482
- // If the property exists but doesn't have enum, add it
483
- extracted.properties[propName].enum = prop.enum;
484
- }
485
- }
486
- });
487
- }
488
- return extracted;
489
- } else {
490
- // If this branch doesn't have ref, preserve the base discriminator enum
491
- if (obj.discriminator && schema.properties) {
492
- const propName = obj.discriminator.propertyName;
493
- if (schema.properties[propName]) {
494
- return {
495
- properties: {
496
- [propName]: {
497
- enum: schema.properties[propName].enum,
498
- },
499
- },
500
- };
501
- }
502
- }
503
- // If no discriminator, return empty object to preserve structure
504
- return {};
505
- }
506
- });
507
- result.oneOf = processedOneOf;
508
-
509
- // --- NEW: If this is an extension property inside a oneOf, promote it to the parent overlay ---
510
- // If parentKey is set, and this object has extension metadata, return a stub for the parent
511
- if (
512
- parentKey &&
513
- (result[refConfig.outputRef] || result.required || result.discriminator)
514
- ) {
515
- // This is an extension property inside a oneOf branch
516
- // Return a stub for the parent property with metadata and oneOf structure
517
- const parentStub = {};
518
- Object.assign(parentStub, result);
519
- return parentStub;
520
- }
521
- }
522
-
523
- // Copy other JSON Schema keywords that might be present
524
- [
525
- "type",
526
- "format",
527
- "minimum",
528
- "maximum",
529
- "minLength",
530
- "maxLength",
531
- "minItems",
532
- "maxItems",
533
- ].forEach((keyword) => {
534
- if (obj[keyword] !== undefined) {
535
- result[keyword] = obj[keyword];
536
- }
537
- });
538
-
539
- return result;
540
- }
541
-
542
- // Add required array at parent levels if needed
543
- function addRequiredArrays(overlay, schema, refConfig) {
544
- traverse(overlay).forEach(function (node) {
545
- if (node && node.properties) {
546
- const schemaPath = "/" + this.path.join("/");
547
- try {
548
- const schemaNode = jp.get(schema, schemaPath);
549
- if (schemaNode && schemaNode[refConfig.required]) {
550
- // Filter to only include properties that exist in this overlay
551
- const overlayProps = Object.keys(node.properties);
552
- const requiredProps = schemaNode[refConfig.required].filter((prop) =>
553
- overlayProps.includes(prop)
554
- );
555
- if (requiredProps.length > 0) {
556
- node.required = requiredProps;
557
- }
558
- }
559
- } catch (err) {
560
- // Path doesn't exist in schema, skip
561
- }
562
- }
563
- });
564
- return overlay;
565
- }
566
-
567
- // Annotate intermediate nodes with refs from the source schema
568
- // This ensures every level of the overlay tree carries an ntsRef
569
- function addIntermediateRefs(overlay, schema, refConfig) {
570
- traverse(overlay).forEach(function (node) {
571
- if (node && typeof node === "object" && !Array.isArray(node) && node.properties) {
572
- // Skip if this node already has a ref
573
- if (node[refConfig.outputRef]) return;
574
-
575
- const schemaPath = "/" + this.path.join("/");
576
- try {
577
- const schemaNode = jp.get(schema, schemaPath);
578
- if (schemaNode && schemaNode[refConfig.ref]) {
579
- node[refConfig.outputRef] = schemaNode[refConfig.ref];
580
- }
581
- } catch (err) {
582
- // Path doesn't exist in schema, skip
583
- }
584
- }
585
- });
586
- return overlay;
587
- }
588
-
589
- // Generate extension overlays
590
- Object.entries(extensionMappings).forEach(([code, config]) => {
591
- const refType = config.refType || "nts2Ref";
592
- const refConfig = getRefConfig(refType);
593
-
594
- console.log(`\nGenerating extension overlay: ${code} (${config.name}) [${refType}]`);
595
-
596
- // Extract the specific paths
597
- let overlay = extractPathsWithRef(
598
- combinedSchema,
599
- config.paths,
600
- refConfig,
601
- config.preserveDiscriminators
602
- );
603
-
604
- // Add required arrays where needed
605
- overlay = addRequiredArrays(overlay, combinedSchema, refConfig);
606
-
607
- // Add refs to intermediate nodes in the path hierarchy
608
- overlay = addIntermediateRefs(overlay, combinedSchema, refConfig);
609
-
610
- // Add schema metadata
611
- overlay.$schema = "http://json-schema.org/draft-07/schema#";
612
- overlay.$id = `https://trust.propdata.org.uk/schemas/v3/overlays/extensions/${code}.json`;
613
- overlay.$comment = config.description;
614
-
615
- // Write the overlay file
616
- const fileName = path.join(
617
- __dirname,
618
- `../schemas/v3/overlays/extensions/${code}.json`
619
- );
620
- fs.writeFileSync(fileName, JSON.stringify(overlay, null, 2));
621
- console.log(`Extension overlay ${code} written to ${fileName}`);
622
- });
623
-
624
- console.log("\nExtension overlay extraction complete!");