@pdtf/schemas 3.6.0-43 → 3.6.0-44

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pdtf/schemas",
3
- "version": "3.6.0-43",
3
+ "version": "3.6.0-44",
4
4
  "description": "Property Data Trust Framework Schemas and Utilities",
5
5
  "main": "index.js",
6
6
  "directories": {
@@ -11,6 +11,9 @@
11
11
  "type": "string"
12
12
  }
13
13
  },
14
+ "discriminator": {
15
+ "propertyName": "yesNo"
16
+ },
14
17
  "oneOf": [
15
18
  null,
16
19
  {
@@ -27,6 +30,9 @@
27
30
  "type": "string"
28
31
  }
29
32
  },
33
+ "discriminator": {
34
+ "propertyName": "yesNo"
35
+ },
30
36
  "required": [
31
37
  "yesNo"
32
38
  ],
@@ -39,6 +45,9 @@
39
45
  "type": "string"
40
46
  }
41
47
  },
48
+ "discriminator": {
49
+ "propertyName": "yesNo"
50
+ },
42
51
  "required": [
43
52
  "yesNo"
44
53
  ],
@@ -64,6 +73,9 @@
64
73
  "type": "string"
65
74
  }
66
75
  },
76
+ "discriminator": {
77
+ "propertyName": "yesNo"
78
+ },
67
79
  "oneOf": [
68
80
  null,
69
81
  {
@@ -80,6 +92,9 @@
80
92
  "type": "string"
81
93
  }
82
94
  },
95
+ "discriminator": {
96
+ "propertyName": "yesNo"
97
+ },
83
98
  "required": [
84
99
  "yesNo"
85
100
  ],
@@ -92,6 +107,9 @@
92
107
  "type": "string"
93
108
  }
94
109
  },
110
+ "discriminator": {
111
+ "propertyName": "yesNo"
112
+ },
95
113
  "required": [
96
114
  "yesNo"
97
115
  ],
@@ -117,6 +135,9 @@
117
135
  "type": "string"
118
136
  }
119
137
  },
138
+ "discriminator": {
139
+ "propertyName": "yesNo"
140
+ },
120
141
  "oneOf": [
121
142
  null,
122
143
  {
@@ -133,6 +154,9 @@
133
154
  "type": "string"
134
155
  }
135
156
  },
157
+ "discriminator": {
158
+ "propertyName": "yesNo"
159
+ },
136
160
  "required": [
137
161
  "yesNo"
138
162
  ],
@@ -145,6 +169,9 @@
145
169
  "type": "string"
146
170
  }
147
171
  },
172
+ "discriminator": {
173
+ "propertyName": "yesNo"
174
+ },
148
175
  "required": [
149
176
  "yesNo"
150
177
  ],
@@ -170,6 +197,9 @@
170
197
  "type": "string"
171
198
  }
172
199
  },
200
+ "discriminator": {
201
+ "propertyName": "yesNo"
202
+ },
173
203
  "oneOf": [
174
204
  null,
175
205
  {
@@ -186,6 +216,9 @@
186
216
  "type": "string"
187
217
  }
188
218
  },
219
+ "discriminator": {
220
+ "propertyName": "yesNo"
221
+ },
189
222
  "required": [
190
223
  "yesNo"
191
224
  ],
@@ -198,6 +231,9 @@
198
231
  "type": "string"
199
232
  }
200
233
  },
234
+ "discriminator": {
235
+ "propertyName": "yesNo"
236
+ },
201
237
  "required": [
202
238
  "yesNo"
203
239
  ],
@@ -223,6 +259,9 @@
223
259
  "type": "string"
224
260
  }
225
261
  },
262
+ "discriminator": {
263
+ "propertyName": "yesNo"
264
+ },
226
265
  "oneOf": [
227
266
  null,
228
267
  {
@@ -239,6 +278,9 @@
239
278
  "type": "string"
240
279
  }
241
280
  },
281
+ "discriminator": {
282
+ "propertyName": "yesNo"
283
+ },
242
284
  "required": [
243
285
  "yesNo"
244
286
  ],
@@ -251,6 +293,9 @@
251
293
  "type": "string"
252
294
  }
253
295
  },
296
+ "discriminator": {
297
+ "propertyName": "yesNo"
298
+ },
254
299
  "required": [
255
300
  "yesNo"
256
301
  ],
@@ -1493,10 +1493,25 @@ describe("Extension Overlays", () => {
1493
1493
  alterationFields.forEach((field) => {
1494
1494
  const fieldSchema = alterations.properties?.[field];
1495
1495
  const yesBranch = fieldSchema?.oneOf?.[1];
1496
+ const planningPermission =
1497
+ yesBranch?.properties?.planningPermission;
1498
+ const buildingRegApproval =
1499
+ yesBranch?.properties?.buildingRegApproval;
1500
+ const overlayFieldSchema = acOverlayAlterations.properties?.[field];
1496
1501
  const overlayYesBranch =
1497
- acOverlayAlterations.properties?.[field]?.oneOf?.[1];
1502
+ overlayFieldSchema?.oneOf?.[1];
1503
+ const overlayPlanningPermission =
1504
+ overlayYesBranch?.properties?.planningPermission;
1505
+ const overlayBuildingRegApproval =
1506
+ overlayYesBranch?.properties?.buildingRegApproval;
1498
1507
 
1499
1508
  expect(fieldSchema?.required).toContain("yesNo");
1509
+ expect(fieldSchema?.discriminator).toEqual({
1510
+ propertyName: "yesNo",
1511
+ });
1512
+ expect(overlayFieldSchema?.discriminator).toEqual({
1513
+ propertyName: "yesNo",
1514
+ });
1500
1515
  expect(fieldSchema?.properties?.yesNo?.ntsRef).toMatch(/^A1\./);
1501
1516
  expect(yesBranch?.required).toEqual(
1502
1517
  expect.arrayContaining([
@@ -1510,6 +1525,18 @@ describe("Extension Overlays", () => {
1510
1525
  "details",
1511
1526
  "planningPermission",
1512
1527
  ]);
1528
+ expect(planningPermission?.discriminator).toEqual({
1529
+ propertyName: "yesNo",
1530
+ });
1531
+ expect(buildingRegApproval?.discriminator).toEqual({
1532
+ propertyName: "yesNo",
1533
+ });
1534
+ expect(overlayPlanningPermission?.discriminator).toEqual({
1535
+ propertyName: "yesNo",
1536
+ });
1537
+ expect(overlayBuildingRegApproval?.discriminator).toEqual({
1538
+ propertyName: "yesNo",
1539
+ });
1513
1540
  expect(yesBranch?.properties?.workCompleted?.ntsRef).toBeUndefined();
1514
1541
  expect(yesBranch?.properties?.documents?.ntsRef).toBeUndefined();
1515
1542
  expect(yesBranch?.properties?.yearCompleted?.ntsRef).toBeUndefined();
@@ -1519,22 +1546,24 @@ describe("Extension Overlays", () => {
1519
1546
  });
1520
1547
 
1521
1548
  test("should require details and consent yesNo fields for Yes answers", () => {
1522
- const validator = getSubschemaValidator(
1523
- "/propertyPack/alterationsAndChanges/extension",
1524
- schemaId,
1525
- ["ac"]
1526
- );
1549
+ alterationFields.forEach((field) => {
1550
+ const validator = getSubschemaValidator(
1551
+ `/propertyPack/alterationsAndChanges/${field}`,
1552
+ schemaId,
1553
+ ["ac"]
1554
+ );
1527
1555
 
1528
- expect(validator({ yesNo: "No" })).toBe(true);
1529
- expect(validator({ yesNo: "Yes" })).toBe(false);
1530
- expect(
1531
- validator({
1532
- yesNo: "Yes",
1533
- details: "Single-storey rear extension in 2018",
1534
- planningPermission: { yesNo: "Not required" },
1535
- buildingRegApproval: { yesNo: "Yes" },
1536
- })
1537
- ).toBe(true);
1556
+ expect(validator({ yesNo: "No" })).toBe(true);
1557
+ expect(validator({ yesNo: "Yes" })).toBe(false);
1558
+ expect(
1559
+ validator({
1560
+ yesNo: "Yes",
1561
+ details: `${field} details`,
1562
+ planningPermission: { yesNo: "Not required" },
1563
+ buildingRegApproval: { yesNo: "Yes" },
1564
+ })
1565
+ ).toBe(true);
1566
+ });
1538
1567
  });
1539
1568
  });
1540
1569
 
@@ -313,6 +313,7 @@ const extensionMappings = {
313
313
  name: "alterationsAndChanges",
314
314
  description: "Selected alterations and changes fields for SEF25",
315
315
  refType: "sef25Ref",
316
+ preserveDiscriminators: true,
316
317
  paths: [
317
318
  "/properties/propertyPack/properties/alterationsAndChanges/properties/extension/properties/yesNo",
318
319
  "/properties/propertyPack/properties/alterationsAndChanges/properties/extension/oneOf/1/properties/details",
@@ -353,7 +354,12 @@ const extensionMappings = {
353
354
  };
354
355
 
355
356
  // Function to extract properties at specific paths with given ref type
356
- function extractPathsWithRef(schema, paths, refConfig) {
357
+ function extractPathsWithRef(
358
+ schema,
359
+ paths,
360
+ refConfig,
361
+ preserveDiscriminators = false
362
+ ) {
357
363
  const result = {};
358
364
 
359
365
  paths.forEach((path) => {
@@ -362,6 +368,9 @@ function extractPathsWithRef(schema, paths, refConfig) {
362
368
  if (value && hasRef(value, refConfig)) {
363
369
  // Set the value at the same path in result
364
370
  jp.set(result, path, extractRefProperties(value, refConfig));
371
+ if (preserveDiscriminators) {
372
+ addAncestorDiscriminators(result, schema, path);
373
+ }
365
374
  }
366
375
  } catch (err) {
367
376
  console.warn(`Path not found: ${path}`);
@@ -371,6 +380,26 @@ function extractPathsWithRef(schema, paths, refConfig) {
371
380
  return result;
372
381
  }
373
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
+
374
403
  // Check if an object or its descendants have the specified ref
375
404
  function hasRef(obj, refConfig) {
376
405
  let found = false;
@@ -565,7 +594,12 @@ Object.entries(extensionMappings).forEach(([code, config]) => {
565
594
  console.log(`\nGenerating extension overlay: ${code} (${config.name}) [${refType}]`);
566
595
 
567
596
  // Extract the specific paths
568
- let overlay = extractPathsWithRef(combinedSchema, config.paths, refConfig);
597
+ let overlay = extractPathsWithRef(
598
+ combinedSchema,
599
+ config.paths,
600
+ refConfig,
601
+ config.preserveDiscriminators
602
+ );
569
603
 
570
604
  // Add required arrays where needed
571
605
  overlay = addRequiredArrays(overlay, combinedSchema, refConfig);