@pdtf/schemas 3.4.1-1 → 3.4.1-3

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/index.js CHANGED
@@ -22,23 +22,23 @@ const extensionOverlays = {
22
22
  jk: require("./src/schemas/v3/overlays/extensions/jk.json"),
23
23
  sb: require("./src/schemas/v3/overlays/extensions/sb.json"),
24
24
  hs: require("./src/schemas/v3/overlays/extensions/hs.json"),
25
-
25
+
26
26
  // Property Features Extensions
27
27
  oa: require("./src/schemas/v3/overlays/extensions/oa.json"),
28
28
  la: require("./src/schemas/v3/overlays/extensions/la.json"),
29
29
  sf: require("./src/schemas/v3/overlays/extensions/sf.json"),
30
30
  mc: require("./src/schemas/v3/overlays/extensions/mc.json"),
31
-
31
+
32
32
  // Ownership & Financial Extensions
33
33
  er: require("./src/schemas/v3/overlays/extensions/er.json"),
34
34
  ma: require("./src/schemas/v3/overlays/extensions/ma.json"),
35
35
  tf: require("./src/schemas/v3/overlays/extensions/tf.json"),
36
-
36
+
37
37
  // Utilities & Services Extensions
38
38
  sl: require("./src/schemas/v3/overlays/extensions/sl.json"),
39
39
  hi: require("./src/schemas/v3/overlays/extensions/hi.json"),
40
40
  fd: require("./src/schemas/v3/overlays/extensions/fd.json"),
41
-
41
+
42
42
  // Transaction Extensions
43
43
  oc: require("./src/schemas/v3/overlays/extensions/oc.json"),
44
44
  };
@@ -92,98 +92,92 @@ const transactionSchemas = {
92
92
  v3CoreSchema,
93
93
  };
94
94
 
95
- const combineMerge = (target, source, options) => {
96
- // Special handling for 'required' arrays - combine them uniquely
97
- if (target.some((item) => typeof item === "string")) {
98
- return [...new Set([...target, ...source])];
99
- }
100
-
101
- // For other arrays, concatenate while preserving uniqueness for primitive values
102
- if (!options.isMergeableObject(target[0])) {
103
- return [...new Set([...target, ...source])];
104
- }
105
-
106
- // Special handling for oneOf arrays - merge matching schemas based on discriminator
107
- if (target[0]?.properties && source[0]?.properties) {
108
- // Find a common discriminator property (a property with an enum)
109
- const findDiscriminator = (schema) => {
110
- const props = schema.properties;
111
- return Object.keys(props).find((key) => Array.isArray(props[key]?.enum));
112
- };
95
+ // Custom array merge function for oneOf arrays
96
+ const arrayMerge = (target, source) => {
97
+ // For string arrays (enum, required, etc.)
98
+ if (
99
+ target.length > 0 &&
100
+ source.length > 0 &&
101
+ target[0] &&
102
+ typeof target[0] === "string" &&
103
+ source[0] &&
104
+ typeof source[0] === "string"
105
+ ) {
106
+ // For required arrays, combine them (remove duplicates)
107
+ // Check if this looks like a required array (contains field names, not enum values)
108
+ const isRequiredArray = target.some(
109
+ (item) =>
110
+ typeof item === "string" &&
111
+ item.length > 0 &&
112
+ !item.includes("Yes") &&
113
+ !item.includes("No") &&
114
+ !item.includes("Not known") &&
115
+ !item.includes("To be connected")
116
+ );
113
117
 
114
- const discriminator = findDiscriminator(target[0]);
115
- if (discriminator) {
116
- return target.map((targetSchema) => {
117
- const targetEnum = targetSchema.properties?.[discriminator]?.enum || [];
118
- const matchingSourceSchema = source.find((sourceSchema) => {
119
- const sourceEnum =
120
- sourceSchema.properties?.[discriminator]?.enum || [];
121
- // Check if there's any overlap between the enum values
122
- return sourceEnum.some((value) => targetEnum.includes(value));
123
- });
124
- if (matchingSourceSchema) {
125
- return merge(targetSchema, matchingSourceSchema, options);
118
+ if (isRequiredArray) {
119
+ // Combine required arrays
120
+ const combined = [...target];
121
+ source.forEach((item) => {
122
+ if (!combined.includes(item)) {
123
+ combined.push(item);
126
124
  }
127
- return targetSchema;
128
125
  });
126
+ return combined;
129
127
  }
128
+
129
+ // For other string arrays (like enum), use source if it exists, otherwise use target
130
+ return source.length > 0 ? source : target;
130
131
  }
131
132
 
132
- // For arrays of objects, merge by index and append remaining items
133
- const destination = target.slice();
134
- source.forEach((item, index) => {
135
- if (typeof destination[index] === "undefined") {
136
- destination[index] = options.cloneUnlessOtherwiseSpecified(item, options);
137
- } else if (options.isMergeableObject(item)) {
138
- destination[index] = merge(target[index], item, options);
133
+ // If target is empty but source has values, use source
134
+ if (target.length === 0 && source.length > 0) {
135
+ return source;
136
+ }
137
+
138
+ // Ensure we only process arrays of the same length
139
+ // If source is shorter, pad with nulls
140
+ // If source is longer, truncate to target length
141
+ const paddedSource = [...source];
142
+ while (paddedSource.length < target.length) {
143
+ paddedSource.push(null);
144
+ }
145
+ paddedSource.splice(target.length);
146
+
147
+ return target.map((item, index) => {
148
+ if (paddedSource[index] === null || paddedSource[index] === undefined) {
149
+ return item;
150
+ }
151
+ if (item === null || item === undefined) {
152
+ return paddedSource[index];
139
153
  }
154
+ // Recursively merge nested objects and arrays
155
+ return merge(item, paddedSource[index], { arrayMerge });
140
156
  });
141
- return destination;
142
157
  };
143
158
 
144
- const mergeEnums = (target, source) => source;
145
-
146
159
  const getTransactionSchema = (
147
160
  schemaId = "https://trust.propdata.org.uk/schemas/v3/pdtf-transaction.json",
148
- overlays // = ["baspiV4"]
161
+ overlays
149
162
  ) => {
150
163
  const sourceSchema = transactionSchemas[schemaId];
151
164
  if (!overlays || overlays.length < 1) return sourceSchema;
152
- let mergedSchema = sourceSchema;
153
- overlays.forEach((overlay) => {
154
- // Handle both string keys and direct overlay objects
155
- const overlaySchema =
156
- typeof overlay === "string"
157
- ? overlaysMap[schemaId][overlay] || {}
158
- : overlay;
159
165
 
160
- mergedSchema = merge(mergedSchema, overlaySchema, {
161
- customMerge: (key) => {
162
- if (key === "enum") {
163
- return mergeEnums;
164
- }
165
- },
166
- arrayMerge: combineMerge,
167
- });
166
+ let mergedSchema = JSON.parse(JSON.stringify(sourceSchema)); // Deep copy
167
+ overlays.forEach((overlay) => {
168
+ const overlaySchema = JSON.parse(
169
+ JSON.stringify(overlaysMap[schemaId][overlay] || {})
170
+ ); // Deep copy
171
+ mergedSchema = merge(mergedSchema, overlaySchema, { arrayMerge });
168
172
  });
173
+
169
174
  return mergedSchema;
170
175
  };
171
176
 
172
177
  // Add helper function to generate cache key
173
178
  const generateOverlayKey = (overlays) => {
174
179
  if (!overlays) return "";
175
- return overlays
176
- .map((overlay) => {
177
- if (typeof overlay === "string") return overlay;
178
- // Generate a simple hash of the object for caching
179
- return JSON.stringify(overlay)
180
- .split("")
181
- .reduce((hash, char) => {
182
- return ((hash << 5) - hash + char.charCodeAt(0)) | 0;
183
- }, 0)
184
- .toString(36);
185
- })
186
- .join(".");
180
+ return overlays.join(".");
187
181
  };
188
182
 
189
183
  const getValidator = (schemaId, overlays) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pdtf/schemas",
3
- "version": "3.4.1-1",
3
+ "version": "3.4.1-3",
4
4
  "description": "Property Data Trust Framework Schemas and Utilities",
5
5
  "main": "index.js",
6
6
  "directories": {
@@ -19,6 +19,15 @@
19
19
  }
20
20
  },
21
21
  "oneOf": [
22
+ {
23
+ "properties": {
24
+ "yesNo": {
25
+ "enum": [
26
+ "No"
27
+ ]
28
+ }
29
+ }
30
+ },
22
31
  {
23
32
  "required": [
24
33
  "details"
@@ -34,6 +43,12 @@
34
43
  "enum": [
35
44
  "Yes"
36
45
  ]
46
+ },
47
+ "attachments": {
48
+ "enum": [
49
+ "Attached",
50
+ "To follow"
51
+ ]
37
52
  }
38
53
  }
39
54
  }
@@ -19,6 +19,15 @@
19
19
  }
20
20
  },
21
21
  "oneOf": [
22
+ {
23
+ "properties": {
24
+ "yesNo": {
25
+ "enum": [
26
+ "No"
27
+ ]
28
+ }
29
+ }
30
+ },
22
31
  {
23
32
  "required": [
24
33
  "details"
@@ -31,7 +40,11 @@
31
40
  },
32
41
  "attachments": {
33
42
  "ntsRef": "A5.1.3",
34
- "type": "string"
43
+ "type": "string",
44
+ "enum": [
45
+ "Attached",
46
+ "To follow"
47
+ ]
35
48
  },
36
49
  "yesNo": {
37
50
  "enum": [
@@ -24,6 +24,15 @@
24
24
  }
25
25
  },
26
26
  "oneOf": [
27
+ {
28
+ "properties": {
29
+ "yesNo": {
30
+ "enum": [
31
+ "No"
32
+ ]
33
+ }
34
+ }
35
+ },
27
36
  {
28
37
  "required": [
29
38
  "details",
@@ -21,6 +21,15 @@
21
21
  }
22
22
  },
23
23
  "oneOf": [
24
+ {
25
+ "properties": {
26
+ "hasFloodDefences": {
27
+ "enum": [
28
+ "No"
29
+ ]
30
+ }
31
+ }
32
+ },
24
33
  {
25
34
  "required": [
26
35
  "details"
@@ -13,6 +13,10 @@
13
13
  "properties": {
14
14
  "centralHeatingInstalled": {
15
15
  "ntsRef": "B3.4.3.2",
16
+ "oneOf": [
17
+ {},
18
+ {}
19
+ ],
16
20
  "type": "string"
17
21
  }
18
22
  },
@@ -19,6 +19,15 @@
19
19
  }
20
20
  },
21
21
  "oneOf": [
22
+ {
23
+ "properties": {
24
+ "yesNo": {
25
+ "enum": [
26
+ "No"
27
+ ]
28
+ }
29
+ }
30
+ },
22
31
  {
23
32
  "required": [
24
33
  "details"
@@ -33,6 +42,12 @@
33
42
  "enum": [
34
43
  "Yes"
35
44
  ]
45
+ },
46
+ "attachments": {
47
+ "enum": [
48
+ "Attached",
49
+ "To follow"
50
+ ]
36
51
  }
37
52
  }
38
53
  }
@@ -19,6 +19,16 @@
19
19
  }
20
20
  },
21
21
  "oneOf": [
22
+ {
23
+ "properties": {
24
+ "yesNo": {
25
+ "enum": [
26
+ "No",
27
+ "Not known"
28
+ ]
29
+ }
30
+ }
31
+ },
22
32
  {
23
33
  "required": [
24
34
  "managementPlanInPlace"
@@ -26,12 +36,23 @@
26
36
  "properties": {
27
37
  "managementPlanInPlace": {
28
38
  "ntsRef": "A5.3.2",
29
- "type": "string"
39
+ "type": "string",
40
+ "enum": [
41
+ "Yes",
42
+ "No",
43
+ "Not known"
44
+ ]
30
45
  },
31
46
  "yesNo": {
32
47
  "enum": [
33
48
  "Yes"
34
49
  ]
50
+ },
51
+ "attachments": {
52
+ "enum": [
53
+ "Attached",
54
+ "To follow"
55
+ ]
35
56
  }
36
57
  }
37
58
  }
@@ -19,6 +19,15 @@
19
19
  }
20
20
  },
21
21
  "oneOf": [
22
+ {
23
+ "properties": {
24
+ "loftAccess": {
25
+ "enum": [
26
+ "No"
27
+ ]
28
+ }
29
+ }
30
+ },
22
31
  {
23
32
  "required": [
24
33
  "details",
@@ -33,11 +42,19 @@
33
42
  },
34
43
  "loftBoarded": {
35
44
  "ntsRef": "A1.2.4.3",
36
- "type": "string"
45
+ "type": "string",
46
+ "enum": [
47
+ "Yes",
48
+ "No"
49
+ ]
37
50
  },
38
51
  "loftInsulated": {
39
52
  "ntsRef": "A1.2.4.4",
40
- "type": "string"
53
+ "type": "string",
54
+ "enum": [
55
+ "Yes",
56
+ "No"
57
+ ]
41
58
  },
42
59
  "loftAccess": {
43
60
  "enum": [
@@ -19,6 +19,26 @@
19
19
  "type": "string"
20
20
  }
21
21
  },
22
+ "oneOf": [
23
+ {
24
+ "properties": {
25
+ "yesNo": {
26
+ "enum": [
27
+ "No"
28
+ ]
29
+ }
30
+ }
31
+ },
32
+ {
33
+ "properties": {
34
+ "yesNo": {
35
+ "enum": [
36
+ "Yes"
37
+ ]
38
+ }
39
+ }
40
+ }
41
+ ],
22
42
  "type": "object"
23
43
  }
24
44
  },
@@ -19,6 +19,15 @@
19
19
  }
20
20
  },
21
21
  "oneOf": [
22
+ {
23
+ "properties": {
24
+ "yesNo": {
25
+ "enum": [
26
+ "No"
27
+ ]
28
+ }
29
+ }
30
+ },
22
31
  {
23
32
  "required": [
24
33
  "details"
@@ -33,6 +42,12 @@
33
42
  "enum": [
34
43
  "Yes"
35
44
  ]
45
+ },
46
+ "attachments": {
47
+ "enum": [
48
+ "Attached",
49
+ "To follow"
50
+ ]
36
51
  }
37
52
  }
38
53
  }
@@ -19,6 +19,15 @@
19
19
  }
20
20
  },
21
21
  "oneOf": [
22
+ {
23
+ "properties": {
24
+ "hasSprayFoamInstalled": {
25
+ "enum": [
26
+ "No"
27
+ ]
28
+ }
29
+ }
30
+ },
22
31
  {
23
32
  "required": [
24
33
  "details"
@@ -34,6 +43,12 @@
34
43
  "enum": [
35
44
  "Yes"
36
45
  ]
46
+ },
47
+ "attachments": {
48
+ "enum": [
49
+ "Attached",
50
+ "To follow"
51
+ ]
37
52
  }
38
53
  }
39
54
  }
@@ -23,6 +23,26 @@
23
23
  "type": "string"
24
24
  }
25
25
  },
26
+ "oneOf": [
27
+ {
28
+ "properties": {
29
+ "yesNo": {
30
+ "enum": [
31
+ "Yes"
32
+ ]
33
+ }
34
+ }
35
+ },
36
+ {
37
+ "properties": {
38
+ "yesNo": {
39
+ "enum": [
40
+ "No"
41
+ ]
42
+ }
43
+ }
44
+ }
45
+ ],
26
46
  "type": "object"
27
47
  }
28
48
  }
@@ -34,6 +34,15 @@
34
34
  }
35
35
  },
36
36
  "oneOf": [
37
+ {
38
+ "properties": {
39
+ "yesNo": {
40
+ "enum": [
41
+ "No"
42
+ ]
43
+ }
44
+ }
45
+ },
37
46
  {
38
47
  "required": [
39
48
  "details"
@@ -0,0 +1,91 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "title": "Transaction Milestones",
4
+ "description": "Schema for tracking transaction milestones throughout the conveyancing process",
5
+ "type": "object",
6
+ "properties": {
7
+ "listed": {
8
+ "type": "object",
9
+ "properties": {
10
+ "completed": {
11
+ "type": "string",
12
+ "format": "date-time"
13
+ }
14
+ }
15
+ },
16
+ "legalForms": {
17
+ "type": "object",
18
+ "properties": {
19
+ "completed": {
20
+ "type": "string",
21
+ "format": "date-time"
22
+ }
23
+ }
24
+ },
25
+ "soldSubjectToContract": {
26
+ "type": "object",
27
+ "properties": {
28
+ "completed": {
29
+ "type": "string",
30
+ "format": "date-time"
31
+ }
32
+ }
33
+ },
34
+ "searches": {
35
+ "type": "object",
36
+ "properties": {
37
+ "ordered": {
38
+ "type": "string",
39
+ "format": "date-time"
40
+ },
41
+ "expected": {
42
+ "type": "string",
43
+ "format": "date-time"
44
+ },
45
+ "completed": {
46
+ "type": "string",
47
+ "format": "date-time"
48
+ }
49
+ }
50
+ },
51
+ "enquiries": {
52
+ "type": "object",
53
+ "properties": {
54
+ "completed": {
55
+ "type": "string",
56
+ "format": "date-time"
57
+ }
58
+ }
59
+ },
60
+ "exchangeOfContracts": {
61
+ "type": "object",
62
+ "properties": {
63
+ "expected": {
64
+ "type": "string",
65
+ "format": "date-time"
66
+ },
67
+ "completed": {
68
+ "type": "string",
69
+ "format": "date-time"
70
+ }
71
+ }
72
+ },
73
+ "completion": {
74
+ "type": "object",
75
+ "properties": {
76
+ "started": {
77
+ "type": "string",
78
+ "format": "date-time"
79
+ },
80
+ "expected": {
81
+ "type": "string",
82
+ "format": "date-time"
83
+ },
84
+ "completed": {
85
+ "type": "string",
86
+ "format": "date-time"
87
+ }
88
+ }
89
+ }
90
+ }
91
+ }