@pdtf/schemas 1.1.2 → 2.0.0-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 (30) hide show
  1. package/index.js +86 -19
  2. package/package.json +5 -3
  3. package/src/examples/v2/exampleTransaction.json +899 -0
  4. package/src/schemas/v1/freehold-information.json +2051 -0
  5. package/src/schemas/v1/material-facts.json +3 -3
  6. package/src/schemas/v2/baspiNotes.html +102 -0
  7. package/src/schemas/v2/combined.json +27796 -0
  8. package/src/schemas/v2/core.json +26224 -0
  9. package/src/schemas/v2/overlays/baspi.json +8857 -0
  10. package/src/schemas/v2/overlays/con29DW.json +656 -0
  11. package/src/schemas/v2/overlays/con29R.json +3115 -0
  12. package/src/schemas/v2/overlays/fme1.json +1610 -0
  13. package/src/schemas/v2/overlays/llc1.json +46 -0
  14. package/src/schemas/v2/overlays/lpe1.json +2424 -0
  15. package/src/schemas/v2/overlays/nts.json +162 -0
  16. package/src/schemas/v2/overlays/oc1.json +2799 -0
  17. package/src/schemas/v2/overlays/rds.json +3746 -0
  18. package/src/schemas/v2/overlays/ta10.json +4 -0
  19. package/src/schemas/v2/overlays/ta6.json +2311 -0
  20. package/src/schemas/v2/overlays/ta7.json +901 -0
  21. package/src/tests/{pdtfVerifiedClaims.test.js → v1/pdtfVerifiedClaims.test.js} +4 -4
  22. package/src/tests/{transactionSchema.test.js → v1/transactionSchema.test.js} +3 -3
  23. package/src/tests/{verifiedClaimsValidator.test.js → v1/verifiedClaimsValidator.test.js} +3 -3
  24. package/src/tests/v2/transactionSchema.test.js +255 -0
  25. package/src/utils/extractOverlay.js +100 -0
  26. /package/src/examples/{exampleAddParticipantVouch.json → v1/exampleAddParticipantVouch.json} +0 -0
  27. /package/src/examples/{exampleDocumentedVouch.json → v1/exampleDocumentedVouch.json} +0 -0
  28. /package/src/examples/{exampleElectronicRecord.json → v1/exampleElectronicRecord.json} +0 -0
  29. /package/src/examples/{exampleTransaction.json → v1/exampleTransaction.json} +0 -0
  30. /package/src/examples/{exampleVouch.json → v1/exampleVouch.json} +0 -0
@@ -1,10 +1,10 @@
1
1
  const Ajv = require("ajv");
2
2
  const addFormats = require("ajv-formats");
3
3
 
4
- const verifiedClaimsSchema = require("../schemas/v1/pdtf-verified-claims.json");
5
- const exampleElectronicRecord = require("../examples/exampleElectronicRecord.json");
6
- const exampleVouch = require("../examples/exampleVouch.json");
7
- const exampleDocumentedVouch = require("../examples/exampleDocumentedVouch.json");
4
+ const verifiedClaimsSchema = require("../../schemas/v1/pdtf-verified-claims.json");
5
+ const exampleElectronicRecord = require("../../examples/v1/exampleElectronicRecord.json");
6
+ const exampleVouch = require("../../examples/v1/exampleVouch.json");
7
+ const exampleDocumentedVouch = require("../../examples/v1/exampleDocumentedVouch.json");
8
8
 
9
9
  const ajv = new Ajv({
10
10
  allErrors: true,
@@ -7,8 +7,8 @@ const {
7
7
  isPathValid,
8
8
  getSubschemaValidator,
9
9
  getTitleAtPath,
10
- } = require("../../index.js");
11
- const exampleTransaction = require("../examples/exampleTransaction.json");
10
+ } = require("../../../index.js");
11
+ const exampleTransaction = require("../../examples/v1/exampleTransaction.json");
12
12
 
13
13
  test("exports a property pack schema", () => {
14
14
  expect(transactionSchema).not.toBeNull();
@@ -34,7 +34,7 @@ test("sample with missing dependent required fields is invalid", () => {
34
34
  JSON.stringify(exampleTransaction)
35
35
  );
36
36
  clonedExampleTransaction.propertyPack.materialFacts.ownership.ownershipsToBeTransferred[0].ownershipType =
37
- "leashold";
37
+ "leasehold";
38
38
  const isValid = validator(clonedExampleTransaction);
39
39
  expect(isValid).toBe(false);
40
40
  });
@@ -1,7 +1,7 @@
1
- const { validateVerifiedClaims } = require("../../index.js");
1
+ const { validateVerifiedClaims } = require("../../../index.js");
2
2
 
3
- const exampleVouch = require("../examples/exampleVouch.json");
4
- const exampleDocumentedVouch = require("../examples/exampleDocumentedVouch.json");
3
+ const exampleVouch = require("../../examples/v1/exampleVouch.json");
4
+ const exampleDocumentedVouch = require("../../examples/v1/exampleDocumentedVouch.json");
5
5
 
6
6
  test("returns an empty array for a valid claim", () => {
7
7
  expect(validateVerifiedClaims([exampleVouch])).toEqual([]);
@@ -0,0 +1,255 @@
1
+ const jp = require("jsonpointer");
2
+ const fs = require("fs");
3
+
4
+ const {
5
+ getTransactionSchema,
6
+ getSubschema,
7
+ isPathValid,
8
+ getValidator,
9
+ getSubschemaValidator,
10
+ getTitleAtPath,
11
+ } = require("../../../index.js");
12
+
13
+ const exampleTransaction = require("../../examples/v2/exampleTransaction.json");
14
+ const schemaId =
15
+ "https://trust.propdata.org.uk/schemas/v2/pdtf-transaction.json";
16
+ // const validator = getValidator(schemaId);
17
+ const v2TransactionSchema = getTransactionSchema(schemaId);
18
+
19
+ test("exports a property pack schema, v2 with baspi overlay by default", () => {
20
+ const testSchema = getTransactionSchema();
21
+ expect(testSchema.$id).toEqual(
22
+ "https://trust.propdata.org.uk/schemas/v2/pdtf-transaction.json"
23
+ );
24
+ expect(
25
+ testSchema.properties.propertyPack.properties.materialFacts.baspiRef
26
+ ).toEqual("A");
27
+ });
28
+
29
+ test("sample is valid", () => {
30
+ const testSchema = getTransactionSchema();
31
+ expect(
32
+ testSchema.properties.propertyPack.properties.materialFacts.baspiRef
33
+ ).toEqual("A");
34
+ const validator = getValidator(schemaId);
35
+ const isValid = validator(exampleTransaction);
36
+ if (!isValid) console.log(validator.errors);
37
+ expect(isValid).toBe(true);
38
+ });
39
+
40
+ test("invalid sample is invalid", () => {
41
+ const clonedExampleTransaction = JSON.parse(
42
+ JSON.stringify(exampleTransaction)
43
+ );
44
+ delete clonedExampleTransaction.propertyPack.materialFacts.notices;
45
+ const validator = getValidator(schemaId);
46
+ const isValid = validator(clonedExampleTransaction);
47
+ expect(isValid).toBe(false);
48
+ });
49
+
50
+ test("sample with missing dependent required fields is invalid", () => {
51
+ const clonedExampleTransaction = JSON.parse(
52
+ JSON.stringify(exampleTransaction)
53
+ );
54
+ clonedExampleTransaction.propertyPack.materialFacts.ownership.ownershipsToBeTransferred[0].ownershipType =
55
+ "leasehold";
56
+ const validator = getValidator(schemaId);
57
+ const isValid = validator(clonedExampleTransaction);
58
+ expect(isValid).toBe(false);
59
+ });
60
+
61
+ test("correctly gets a top level subschema", () => {
62
+ const subschema = getSubschema("/propertyPack", v2TransactionSchema);
63
+ expect(subschema.title).toBe("Property Pack");
64
+ });
65
+
66
+ test("correctly identifies a valid path", () => {
67
+ const isValid = isPathValid(
68
+ "/propertyPack/materialFacts",
69
+ v2TransactionSchema
70
+ );
71
+ expect(isValid).toBe(true);
72
+ });
73
+
74
+ test("correctly identifies an undefined invalid path", () => {
75
+ const isValid = isPathValid(
76
+ "/propertyPack/materialItems",
77
+ v2TransactionSchema
78
+ );
79
+ expect(isValid).toBe(false);
80
+ });
81
+
82
+ test("correctly identifies an error generating invalid path", () => {
83
+ const isValid = isPathValid(
84
+ "/propertyPack/materialItems/someProperty/item",
85
+ v2TransactionSchema
86
+ );
87
+ expect(isValid).toBe(false);
88
+ });
89
+
90
+ test("correctly identifies an array invalid path", () => {
91
+ const isValid = isPathValid(
92
+ "/propertyPack/materialFacts/1/item",
93
+ v2TransactionSchema
94
+ );
95
+ expect(isValid).toBe(false);
96
+ });
97
+
98
+ test("correctly gets a subschema", () => {
99
+ const subschema = getSubschema(
100
+ "/propertyPack/materialFacts/notices",
101
+ v2TransactionSchema
102
+ );
103
+ expect(subschema.title).toBe("Notices which Affect the Property");
104
+ });
105
+
106
+ test("correctly gets a subschema through an arrays element", () => {
107
+ const subschema = getSubschema(
108
+ "/propertyPack/titlesToBeSold/0/registerExtract",
109
+ v2TransactionSchema
110
+ );
111
+ expect(Object.keys(subschema.properties)).toEqual([
112
+ "OCSummaryData",
113
+ "OCRegisterData",
114
+ ]);
115
+ });
116
+
117
+ test("correctly gets a subschema through a dependency", () => {
118
+ const subschema = getSubschema(
119
+ "/propertyPack/materialFacts/delayFactors/hasDelayFactors/details",
120
+ v2TransactionSchema
121
+ );
122
+ expect(subschema.title).toBe("Details");
123
+ });
124
+
125
+ test("correctly gets another subschema through a dependency", () => {
126
+ const subschema = getSubschema(
127
+ "/propertyPack/materialFacts/ownership/ownershipsToBeTransferred/0/leaseholdInformation/general/leaseTerm/lengthOfLeaseInYears",
128
+ v2TransactionSchema
129
+ );
130
+ expect(subschema.title).toBe("Length of lease (years)");
131
+ });
132
+
133
+ test("correctly gets yet another subschema through a dependency", () => {
134
+ const subschema = getSubschema(
135
+ "/propertyPack/materialFacts/ownership/ownershipsToBeTransferred/0/rentIncrease/details"
136
+ );
137
+ expect(subschema.title).toBe("Details");
138
+ });
139
+
140
+ test("correctly gets yet, yet another subschema through a dependency", () => {
141
+ const subschema = getSubschema(
142
+ "/propertyPack/materialFacts/listingAndConservation/isConservationArea/yesNo"
143
+ );
144
+ expect(subschema.type).toBe("string");
145
+ expect(subschema.enum).toStrictEqual(["Yes", "No"]);
146
+ });
147
+
148
+ test("correctly gets yet, yet, yet another subschema through a dependency", () => {
149
+ const subschema = getSubschema(
150
+ "/propertyPack/materialFacts/otherIssues/flooding/typeOfFlooding/groundWater/yesNo"
151
+ );
152
+ expect(subschema.type).toBe("string");
153
+ expect(subschema.enum).toStrictEqual(["Yes", "No"]);
154
+ });
155
+
156
+ test("correctly gets yet, yet, yet another subschema through a second item dependency", () => {
157
+ const subschema = getSubschema(
158
+ "/propertyPack/materialFacts/otherIssues/flooding/typeOfFlooding"
159
+ );
160
+ expect(subschema.type).toBe("object");
161
+ });
162
+
163
+ test("correctly gets yes another subschema but through a non-baspi oneOf structure", () => {
164
+ const subschema = getSubschema(
165
+ "/propertyPack/titlesToBeSold/0/registerExtract/OCSummaryData/RestrictionDetails/RestrictionEntry/ChargeRestriction/EntryDetails/EntryText"
166
+ );
167
+ expect(subschema).toEqual({ type: "string" });
168
+ });
169
+
170
+ test("correctly gets yes another subschema but through a non-baspi oneOf structure with array option", () => {
171
+ const subschema = getSubschema(
172
+ "/propertyPack/titlesToBeSold/0/registerExtract/OCSummaryData/RestrictionDetails/RestrictionEntry/0/ChargeRestriction/EntryDetails/EntryText"
173
+ );
174
+ expect(subschema).toEqual({ type: "string" });
175
+ });
176
+
177
+ test("correctly gets a subschema validator which is already cached", () => {
178
+ const validator = getSubschemaValidator(
179
+ "/propertyPack/energyPerformanceCertificate"
180
+ );
181
+ expect(validator).not.toBeNull();
182
+ const anotherValidator = getSubschemaValidator(
183
+ "/propertyPack/energyPerformanceCertificate"
184
+ );
185
+ expect(anotherValidator).not.toBeNull();
186
+ });
187
+
188
+ test("correctly gets a subschema validator which validates", () => {
189
+ const path = "/propertyPack/materialFacts/notices";
190
+ const validator = getSubschemaValidator(path);
191
+ const data = jp.get(exampleTransaction, path);
192
+ expect(data.neighbourDevelopment.yesNo).toBe("No");
193
+ let isValid = validator(data);
194
+ expect(isValid).toBe(true);
195
+ data.neighbourDevelopment.yesNo = "Invalid string";
196
+ isValid = validator(data);
197
+ expect(isValid).toBe(false);
198
+ });
199
+
200
+ test("correctly gets titles across schemas, arrays and non-existient title properties", () => {
201
+ expect(
202
+ getTitleAtPath(
203
+ v2TransactionSchema,
204
+ "/propertyPack/materialFacts/ownership/ownershipsToBeTransferred/0/ownershipType"
205
+ )
206
+ ).toBe("What type of ownership is the property?");
207
+ expect(
208
+ getTitleAtPath(
209
+ v2TransactionSchema,
210
+ "/propertyPack/materialFacts/ownership/ownershipsToBeTransferred/0/leaseholdInformation/general/leaseTerm/lengthOfLeaseInYears"
211
+ )
212
+ ).toBe("Length of lease (years)");
213
+ expect(
214
+ getTitleAtPath(
215
+ v2TransactionSchema,
216
+ "/propertyPack/materialFacts/ownership/ownershipsToBeTransferred/0/leaseholdInformation/serviceCharge/annualServiceCharge"
217
+ )
218
+ ).toBe("Amount of current annual service charge (£)");
219
+ expect(
220
+ getTitleAtPath(
221
+ v2TransactionSchema,
222
+ "/propertyPack/materialFacts/invalidPath"
223
+ )
224
+ ).toBe(undefined);
225
+ expect(
226
+ getTitleAtPath(
227
+ v2TransactionSchema,
228
+ "/propertyPack/titlesToBeSold/0/registerExtract"
229
+ )
230
+ ).toBe("HMLR Official Copy Register Extract");
231
+ expect(
232
+ getTitleAtPath(
233
+ v2TransactionSchema,
234
+ "/propertyPack/titlesToBeSold/0/registerExtract/OCSummaryData/PropertyAddress"
235
+ )
236
+ ).toBe("Property address");
237
+ expect(
238
+ getTitleAtPath(
239
+ v2TransactionSchema,
240
+ "/propertyPack/titlesToBeSold/0/registerExtract/OCSummaryData/InvalidProp"
241
+ )
242
+ ).toBe(undefined);
243
+ expect(
244
+ getTitleAtPath(
245
+ v2TransactionSchema,
246
+ "/propertyPack/materialFacts/energyEfficiency/certificate/currentEnergyRating"
247
+ )
248
+ ).toBe("Current energy efficiency rating");
249
+ expect(
250
+ getTitleAtPath(
251
+ v2TransactionSchema,
252
+ "/propertyPack/additionalLegalInfo/occupiers/othersAged17OrOver/aged17OrOverNames"
253
+ )
254
+ ).toBe("Please provide their full names and ages.");
255
+ });
@@ -0,0 +1,100 @@
1
+ const { dereference } = require("@jdw/jst");
2
+ const traverse = require("traverse");
3
+ const jp = require("jsonpointer");
4
+ const fs = require("fs");
5
+ const merge = require("deepmerge");
6
+
7
+ const combinedSchema = require("../schemas/v2/combined.json");
8
+
9
+ const extractFields = [
10
+ "baspi",
11
+ "nts",
12
+ "ta6",
13
+ "ta7",
14
+ "ta10",
15
+ "lpe1",
16
+ "fme1",
17
+ "con29R",
18
+ "con29DW",
19
+ "llc1",
20
+ "rds",
21
+ "oc1",
22
+ ];
23
+
24
+ const overlayIncludeProperties = [
25
+ "title",
26
+ "description",
27
+ "enum",
28
+ "discriminator",
29
+ ];
30
+
31
+ const extractOverlay = (sourceSchema, ref) => {
32
+ const refName = `${ref}Ref`;
33
+ const refRequired = `${ref}Required`;
34
+ const returnSchema = {
35
+ $schema: "http://json-schema.org/draft-07/schema#",
36
+ $id: `https://trust.propdata.org.uk/schemas/v2/overlays/${ref}.json`,
37
+ };
38
+ traverse(sourceSchema).forEach(function (element) {
39
+ let path = "/" + this.path.join("/");
40
+ if (path === "/") path = "";
41
+ if (element[refName]) {
42
+ jp.set(returnSchema, `${path}/${refName}`, element[refName]);
43
+ overlayIncludeProperties.forEach((property) => {
44
+ if (element[property]) {
45
+ jp.set(returnSchema, `${path}/${property}`, element[property]);
46
+ }
47
+ });
48
+ const { discriminator } = element;
49
+
50
+ if (discriminator) {
51
+ const { propertyName } = discriminator;
52
+ element.oneOf.forEach((item, index) => {
53
+ const discriminatorProperty = item.properties[propertyName];
54
+ jp.set(
55
+ returnSchema,
56
+ `${path}/oneOf/${index}/properties/${propertyName}`,
57
+ discriminatorProperty
58
+ );
59
+ });
60
+ }
61
+ }
62
+ if (element[refRequired]) {
63
+ jp.set(returnSchema, `${path}/required`, element[refRequired]);
64
+ }
65
+ });
66
+ return returnSchema;
67
+ };
68
+
69
+ const deleteProperties = (sourceSchema, propertyNames) => {
70
+ traverse(sourceSchema).forEach(function (element) {
71
+ if (propertyNames.includes(this.key)) {
72
+ this.delete(true); // true = stop here
73
+ }
74
+ });
75
+ return sourceSchema;
76
+ };
77
+
78
+ extractFields.forEach((key) => {
79
+ let overlay = extractOverlay(combinedSchema, key, [
80
+ "title",
81
+ "description",
82
+ "enum",
83
+ "discriminator",
84
+ ]);
85
+ const fileName = `../schemas/v2/overlays/${key}.json`;
86
+ fs.writeFileSync(fileName, JSON.stringify(overlay, null, 2));
87
+ console.log(`Overlay ${key} written to ${fileName}`);
88
+ });
89
+
90
+ const coreSchema = deleteProperties(combinedSchema, [
91
+ "discriminator",
92
+ ...extractFields.map((item) => `${item}Ref`),
93
+ ...extractFields.map((item) => `${item}Required`),
94
+ ]);
95
+
96
+ fs.writeFileSync(
97
+ "../schemas/v2/core.json",
98
+ JSON.stringify(coreSchema, null, 2)
99
+ );
100
+ console.log("Core schema written to ../schemas/v2/core.json");