@pdtf/schemas 2.0.0-2 → 2.0.0-21
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 +33 -19
- package/package.json +1 -1
- package/src/examples/v2/exampleTransaction.json +86 -87
- package/src/schemas/v2/combined.json +7432 -1101
- package/src/schemas/v2/overlays/baspi.json +1087 -742
- package/src/schemas/v2/overlays/con29DW.json +256 -127
- package/src/schemas/v2/overlays/con29R.json +1 -1
- package/src/schemas/v2/overlays/fme1.json +46 -212
- package/src/schemas/v2/overlays/lpe1.json +92 -63
- package/src/schemas/v2/overlays/nts.json +39 -43
- package/src/schemas/v2/overlays/rds.json +339 -337
- package/src/schemas/v2/overlays/ta10.json +844 -1
- package/src/schemas/v2/overlays/ta6.json +330 -291
- package/src/schemas/v2/overlays/ta7.json +98 -33
- package/src/schemas/v2/{core.json → pdtf-transaction.json} +6901 -927
- package/src/schemas/v2/skeleton.json +3559 -0
- package/src/tests/v1/transactionSchema.test.js +21 -13
- package/src/tests/v2/transactionSchema.test.js +6 -4
- package/src/tests/v2/verifiedClaimsValidator.test.js +128 -0
- package/src/utils/extractOverlay.js +47 -9
- package/src/utils/extractProperties.js +44 -0
- package/src/schemas/v2/merged.json +0 -28697
|
@@ -10,6 +10,14 @@ const {
|
|
|
10
10
|
} = require("../../../index.js");
|
|
11
11
|
const exampleTransaction = require("../../examples/v1/exampleTransaction.json");
|
|
12
12
|
|
|
13
|
+
const getV1Subschema = (path) => {
|
|
14
|
+
return getSubschema(
|
|
15
|
+
path,
|
|
16
|
+
"https://trust.propdata.org.uk/schemas/v1/pdtf-transaction.json",
|
|
17
|
+
null
|
|
18
|
+
);
|
|
19
|
+
};
|
|
20
|
+
|
|
13
21
|
test("exports a property pack schema", () => {
|
|
14
22
|
expect(transactionSchema).not.toBeNull();
|
|
15
23
|
});
|
|
@@ -65,45 +73,45 @@ test("correctly identifies an array invalid path", () => {
|
|
|
65
73
|
});
|
|
66
74
|
|
|
67
75
|
test("correctly gets a subschema", () => {
|
|
68
|
-
const subschema =
|
|
76
|
+
const subschema = getV1Subschema("/propertyPack/materialFacts/notices");
|
|
69
77
|
expect(subschema.title).toBe("Notices which Affect the Property");
|
|
70
78
|
});
|
|
71
79
|
|
|
72
80
|
test("correctly gets a subschema through an arrays element", () => {
|
|
73
|
-
const subschema =
|
|
81
|
+
const subschema = getV1Subschema(
|
|
74
82
|
"/propertyPack/titlesToBeSold/0/registerExtract"
|
|
75
83
|
);
|
|
76
84
|
expect(subschema.title).toBe("HMLR Official Copy Register Extract");
|
|
77
85
|
});
|
|
78
86
|
|
|
79
87
|
test("correctly gets another subschema through an arrays element", () => {
|
|
80
|
-
const subschema =
|
|
88
|
+
const subschema = getV1Subschema("/participants/0/name/firstName");
|
|
81
89
|
expect(subschema.title).toBe("First name");
|
|
82
90
|
});
|
|
83
91
|
|
|
84
92
|
test("correctly gets a subschema through a dependency", () => {
|
|
85
|
-
const subschema =
|
|
93
|
+
const subschema = getV1Subschema(
|
|
86
94
|
"/propertyPack/materialFacts/delayFactors/hasDelayFactors/details"
|
|
87
95
|
);
|
|
88
96
|
expect(subschema.title).toBe("Details");
|
|
89
97
|
});
|
|
90
98
|
|
|
91
99
|
test("correctly gets another subschema through a dependency", () => {
|
|
92
|
-
const subschema =
|
|
100
|
+
const subschema = getV1Subschema(
|
|
93
101
|
"/propertyPack/materialFacts/ownership/ownershipsToBeTransferred/0/lengthOfLeaseInYears"
|
|
94
102
|
);
|
|
95
103
|
expect(subschema.title).toBe("Length of lease (years)");
|
|
96
104
|
});
|
|
97
105
|
|
|
98
106
|
test("correctly gets yet another subschema through a dependency", () => {
|
|
99
|
-
const subschema =
|
|
107
|
+
const subschema = getV1Subschema(
|
|
100
108
|
"/propertyPack/materialFacts/ownership/ownershipsToBeTransferred/0/rentIncrease/details"
|
|
101
109
|
);
|
|
102
110
|
expect(subschema.title).toBe("Details");
|
|
103
111
|
});
|
|
104
112
|
|
|
105
113
|
test("correctly gets yet, yet another subschema through a dependency", () => {
|
|
106
|
-
const subschema =
|
|
114
|
+
const subschema = getV1Subschema(
|
|
107
115
|
"/propertyPack/materialFacts/listingAndConservation/isConservationArea/yesNo"
|
|
108
116
|
);
|
|
109
117
|
expect(subschema.type).toBe("string");
|
|
@@ -111,7 +119,7 @@ test("correctly gets yet, yet another subschema through a dependency", () => {
|
|
|
111
119
|
});
|
|
112
120
|
|
|
113
121
|
test("correctly gets yet, yet, yet another subschema through a dependency", () => {
|
|
114
|
-
const subschema =
|
|
122
|
+
const subschema = getV1Subschema(
|
|
115
123
|
"/propertyPack/materialFacts/otherIssues/flooding/typeOfFlooding/groundWater/yesNo"
|
|
116
124
|
);
|
|
117
125
|
expect(subschema.type).toBe("string");
|
|
@@ -119,21 +127,21 @@ test("correctly gets yet, yet, yet another subschema through a dependency", () =
|
|
|
119
127
|
});
|
|
120
128
|
|
|
121
129
|
test("correctly gets yet, yet, yet another subschema through a second item dependency", () => {
|
|
122
|
-
const subschema =
|
|
130
|
+
const subschema = getV1Subschema(
|
|
123
131
|
"/propertyPack/materialFacts/otherIssues/flooding/typeOfFlooding"
|
|
124
132
|
);
|
|
125
133
|
expect(subschema.type).toBe("object");
|
|
126
134
|
});
|
|
127
135
|
|
|
128
136
|
test("correctly gets yes another subschema but through a non-baspi oneOf structure", () => {
|
|
129
|
-
const subschema =
|
|
137
|
+
const subschema = getV1Subschema(
|
|
130
138
|
"/propertyPack/titlesToBeSold/0/registerExtract/OCSummaryData/RestrictionDetails/RestrictionEntry/ChargeRestriction/EntryDetails/EntryText"
|
|
131
139
|
);
|
|
132
140
|
expect(subschema).toEqual({ type: "string" });
|
|
133
141
|
});
|
|
134
142
|
|
|
135
143
|
test("correctly gets yes another subschema but through a non-baspi oneOf structure with array option", () => {
|
|
136
|
-
const subschema =
|
|
144
|
+
const subschema = getV1Subschema(
|
|
137
145
|
"/propertyPack/titlesToBeSold/0/registerExtract/OCSummaryData/RestrictionDetails/RestrictionEntry/0/ChargeRestriction/EntryDetails/EntryText"
|
|
138
146
|
);
|
|
139
147
|
expect(subschema).toEqual({ type: "string" });
|
|
@@ -141,11 +149,11 @@ test("correctly gets yes another subschema but through a non-baspi oneOf structu
|
|
|
141
149
|
|
|
142
150
|
test("correctly gets a subschema validator which is already cached", () => {
|
|
143
151
|
const validator = getSubschemaValidator(
|
|
144
|
-
"/propertyPack/
|
|
152
|
+
"/propertyPack/materialFacts/energyEfficiency/certificate"
|
|
145
153
|
);
|
|
146
154
|
expect(validator).not.toBeNull();
|
|
147
155
|
const anotherValidator = getSubschemaValidator(
|
|
148
|
-
"/propertyPack/
|
|
156
|
+
"/propertyPack/materialFacts/energyEfficiency/certificate"
|
|
149
157
|
);
|
|
150
158
|
expect(anotherValidator).not.toBeNull();
|
|
151
159
|
});
|
|
@@ -110,12 +110,14 @@ test("correctly gets a subschema through a dependency", () => {
|
|
|
110
110
|
"/propertyPack/materialFacts/delayFactors/hasDelayFactors/details",
|
|
111
111
|
schemaId
|
|
112
112
|
);
|
|
113
|
-
expect(subschema.title).toBe(
|
|
113
|
+
expect(subschema.title).toBe(
|
|
114
|
+
"Provide details and likely timescale for delay (if known)"
|
|
115
|
+
);
|
|
114
116
|
});
|
|
115
117
|
|
|
116
118
|
test("correctly gets another subschema through a dependency", () => {
|
|
117
119
|
const subschema = getSubschema(
|
|
118
|
-
"/propertyPack/materialFacts/ownership/ownershipsToBeTransferred/0/leaseholdInformation/
|
|
120
|
+
"/propertyPack/materialFacts/ownership/ownershipsToBeTransferred/0/leaseholdInformation/leaseTerm/lengthOfLeaseInYears",
|
|
119
121
|
schemaId
|
|
120
122
|
);
|
|
121
123
|
expect(subschema.title).toBe("Length of lease (years)");
|
|
@@ -138,7 +140,7 @@ test("correctly gets yet, yet another subschema through a dependency", () => {
|
|
|
138
140
|
|
|
139
141
|
test("correctly gets yet, yet, yet another subschema through a dependency", () => {
|
|
140
142
|
const subschema = getSubschema(
|
|
141
|
-
"/propertyPack/materialFacts/environmentalIssues/flooding/typeOfFlooding/
|
|
143
|
+
"/propertyPack/materialFacts/environmentalIssues/flooding/typeOfFlooding/other/yesNo"
|
|
142
144
|
);
|
|
143
145
|
expect(subschema.type).toBe("string");
|
|
144
146
|
expect(subschema.enum).toStrictEqual(["Yes", "No"]);
|
|
@@ -198,7 +200,7 @@ test("correctly gets titles across schemas, arrays and non-existient title prope
|
|
|
198
200
|
expect(
|
|
199
201
|
getTitleAtPath(
|
|
200
202
|
v2TransactionSchema,
|
|
201
|
-
"/propertyPack/materialFacts/ownership/ownershipsToBeTransferred/0/leaseholdInformation/
|
|
203
|
+
"/propertyPack/materialFacts/ownership/ownershipsToBeTransferred/0/leaseholdInformation/leaseTerm/lengthOfLeaseInYears"
|
|
202
204
|
)
|
|
203
205
|
).toBe("Length of lease (years)");
|
|
204
206
|
expect(
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
const { validateVerifiedClaims } = require("../../../index.js");
|
|
2
|
+
|
|
3
|
+
const exampleVouch = require("../../examples/v1/exampleVouch.json");
|
|
4
|
+
const exampleDocumentedVouch = require("../../examples/v1/exampleDocumentedVouch.json");
|
|
5
|
+
const v2SchemaId =
|
|
6
|
+
"https://trust.propdata.org.uk/schemas/v2/pdtf-transaction.json";
|
|
7
|
+
|
|
8
|
+
test("returns an empty array for a valid claim", () => {
|
|
9
|
+
expect(validateVerifiedClaims([exampleVouch])).toEqual([]);
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
test("returns an empty array for a valid array of claims", () => {
|
|
13
|
+
const claimsArray = [exampleVouch, exampleDocumentedVouch];
|
|
14
|
+
expect(validateVerifiedClaims(claimsArray)).toEqual([]);
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
test("returns an array with an error stating if path is incorrect", () => {
|
|
18
|
+
const clonedVouch = JSON.parse(JSON.stringify(exampleVouch));
|
|
19
|
+
const originalPath = Object.keys(clonedVouch.claims)[0];
|
|
20
|
+
const data = clonedVouch.claims[originalPath];
|
|
21
|
+
clonedVouch.claims = {
|
|
22
|
+
"/propertyPack/INVALID/materialFacts/councilTax": data,
|
|
23
|
+
};
|
|
24
|
+
// v2 schema, no overlay
|
|
25
|
+
expect(validateVerifiedClaims([clonedVouch], v2SchemaId, null)).toEqual([
|
|
26
|
+
"Path /propertyPack/INVALID/materialFacts/councilTax is not a valid PDTF schema path",
|
|
27
|
+
]);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
test("returns errors if BASPI requirements are not met and BASPI overlay is specified (default)", () => {
|
|
31
|
+
const clonedVouch = JSON.parse(JSON.stringify(exampleVouch));
|
|
32
|
+
clonedVouch.claims = {
|
|
33
|
+
"/propertyPack/materialFacts/delayFactors": {
|
|
34
|
+
hasDelayFactors: { yesNo: "Yes" },
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
const errors = validateVerifiedClaims([clonedVouch], v2SchemaId);
|
|
38
|
+
expect(errors).toEqual([
|
|
39
|
+
{
|
|
40
|
+
instancePath: "/hasDelayFactors",
|
|
41
|
+
schemaPath: "#/properties/hasDelayFactors/oneOf/1/required",
|
|
42
|
+
keyword: "required",
|
|
43
|
+
params: { missingProperty: "details" },
|
|
44
|
+
message: "must have required property 'details'",
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
instancePath: "/hasDelayFactors",
|
|
48
|
+
schemaPath: "#/properties/hasDelayFactors/oneOf/1/required",
|
|
49
|
+
keyword: "required",
|
|
50
|
+
params: { missingProperty: "attachments" },
|
|
51
|
+
message: "must have required property 'attachments'",
|
|
52
|
+
},
|
|
53
|
+
]);
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
test("returns no errors if BASPI requirements are not met and null overlay is specified", () => {
|
|
57
|
+
const clonedVouch = JSON.parse(JSON.stringify(exampleVouch));
|
|
58
|
+
clonedVouch.claims = {
|
|
59
|
+
"/propertyPack/materialFacts/delayFactors": {
|
|
60
|
+
hasDelayFactors: { yesNo: "Yes" },
|
|
61
|
+
},
|
|
62
|
+
};
|
|
63
|
+
const errors = validateVerifiedClaims([clonedVouch], v2SchemaId, null);
|
|
64
|
+
expect(errors).toEqual([]);
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
test("returns errors for invalid fields even if null overlay is specified", () => {
|
|
68
|
+
const clonedVouch = JSON.parse(JSON.stringify(exampleVouch));
|
|
69
|
+
clonedVouch.claims = {
|
|
70
|
+
"/propertyPack/materialFacts/delayFactors": {
|
|
71
|
+
hasDelayFactors: { yesNo: "Maybe" },
|
|
72
|
+
},
|
|
73
|
+
};
|
|
74
|
+
const errors = validateVerifiedClaims([clonedVouch], v2SchemaId, null);
|
|
75
|
+
expect(errors).toHaveLength(4);
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
test("returns an array of errors for verified claim with multiple paths", () => {
|
|
79
|
+
const clonedVouch = JSON.parse(JSON.stringify(exampleVouch));
|
|
80
|
+
clonedVouch.claims = {
|
|
81
|
+
"/propertyPack/materialFacts/cousncilTaxBad": {
|
|
82
|
+
councilTaxBand: "D",
|
|
83
|
+
councilTaxAffectingAlterations: {
|
|
84
|
+
yesNo: "Yes",
|
|
85
|
+
details:
|
|
86
|
+
"Extension added in 2005 to add bedroom with ensuite shower room. Certificate of Compliance issued 17th Feb 2006 and council tax updated",
|
|
87
|
+
},
|
|
88
|
+
},
|
|
89
|
+
"/propertyPack/materialFacts/councilTaxBadTwo": {
|
|
90
|
+
councilTaxBand: "D",
|
|
91
|
+
councilTaxAffectingAlterations: {
|
|
92
|
+
yesNo: "Yes",
|
|
93
|
+
details:
|
|
94
|
+
"Extension added in 2005 to add bedroom with ensuite shower room. Certificate of Compliance issued 17th Feb 2006 and council tax updated",
|
|
95
|
+
},
|
|
96
|
+
},
|
|
97
|
+
};
|
|
98
|
+
expect(validateVerifiedClaims([clonedVouch], v2SchemaId, null)).toEqual([
|
|
99
|
+
"Path /propertyPack/materialFacts/cousncilTaxBad is not a valid PDTF schema path",
|
|
100
|
+
"Path /propertyPack/materialFacts/councilTaxBadTwo is not a valid PDTF schema path",
|
|
101
|
+
]);
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
test("returns an empty array of errors for verified claim with multiple valid paths", () => {
|
|
105
|
+
const clonedVouch = JSON.parse(
|
|
106
|
+
JSON.stringify(exampleVouch),
|
|
107
|
+
v2SchemaId,
|
|
108
|
+
null
|
|
109
|
+
);
|
|
110
|
+
clonedVouch.claims = {
|
|
111
|
+
"/propertyPack/materialFacts/councilTax": {
|
|
112
|
+
councilTaxBand: "D",
|
|
113
|
+
councilTaxAffectingAlterations: {
|
|
114
|
+
yesNo: "Yes",
|
|
115
|
+
details:
|
|
116
|
+
"Extension added in 2005 to add bedroom with ensuite shower room. Certificate of Compliance issued 17th Feb 2006 and council tax updated",
|
|
117
|
+
},
|
|
118
|
+
},
|
|
119
|
+
"/propertyPack/materialFacts/address": {
|
|
120
|
+
line1: "property.line1",
|
|
121
|
+
line2: "property.line2",
|
|
122
|
+
town: "property.city",
|
|
123
|
+
county: "property.province",
|
|
124
|
+
postcode: "property.postcode",
|
|
125
|
+
},
|
|
126
|
+
};
|
|
127
|
+
expect(validateVerifiedClaims([clonedVouch], v2SchemaId, null)).toEqual([]);
|
|
128
|
+
});
|
|
@@ -43,6 +43,32 @@ const combineMerge = (target, source, options) => {
|
|
|
43
43
|
return destination;
|
|
44
44
|
};
|
|
45
45
|
|
|
46
|
+
const flattenSkeleton = (schema) => {
|
|
47
|
+
if (!schema) return undefined;
|
|
48
|
+
// console.log(schema.properties);
|
|
49
|
+
let returnStructure = {};
|
|
50
|
+
if (schema.properties) {
|
|
51
|
+
Object.keys(schema.properties).forEach((key) => {
|
|
52
|
+
returnStructure[key] = flattenSkeleton(schema.properties[key]);
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
if (schema.oneOf) {
|
|
56
|
+
schema.oneOf.forEach((aOneOf) => {
|
|
57
|
+
// console.log(aOneOf);
|
|
58
|
+
if (aOneOf.properties) {
|
|
59
|
+
Object.entries(aOneOf.properties).forEach(([key, value]) => {
|
|
60
|
+
// console.log(aProperty);
|
|
61
|
+
returnStructure[key] = flattenSkeleton(value);
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
if (schema.items) {
|
|
67
|
+
returnStructure = flattenSkeleton(schema.items);
|
|
68
|
+
}
|
|
69
|
+
return returnStructure;
|
|
70
|
+
};
|
|
71
|
+
|
|
46
72
|
const extractOverlay = (sourceSchema, ref) => {
|
|
47
73
|
const refName = `${ref}Ref`;
|
|
48
74
|
const refRequired = `${ref}Required`;
|
|
@@ -112,17 +138,29 @@ const coreSchema = deleteProperties(combinedSchema, [
|
|
|
112
138
|
]);
|
|
113
139
|
|
|
114
140
|
fs.writeFileSync(
|
|
115
|
-
"../schemas/v2/
|
|
141
|
+
"../schemas/v2/pdtf-transaction.json",
|
|
116
142
|
JSON.stringify(coreSchema, null, 2)
|
|
117
143
|
);
|
|
118
|
-
console.log("Core schema written to ../schemas/v2/
|
|
119
|
-
|
|
120
|
-
const
|
|
121
|
-
|
|
122
|
-
|
|
144
|
+
console.log("Core schema written to ../schemas/v2/pdtf-transaction.json");
|
|
145
|
+
|
|
146
|
+
const skeletonSchema = deleteProperties(coreSchema, [
|
|
147
|
+
"$schema",
|
|
148
|
+
"$id",
|
|
149
|
+
"title",
|
|
150
|
+
"description",
|
|
151
|
+
"required",
|
|
152
|
+
"enum",
|
|
153
|
+
"minItems",
|
|
154
|
+
"minLength",
|
|
155
|
+
"format",
|
|
156
|
+
"minimum",
|
|
157
|
+
"maximum",
|
|
158
|
+
]);
|
|
159
|
+
|
|
160
|
+
const skeletonSchemaFlattened = flattenSkeleton(skeletonSchema);
|
|
123
161
|
|
|
124
162
|
fs.writeFileSync(
|
|
125
|
-
"../schemas/v2/
|
|
126
|
-
JSON.stringify(
|
|
163
|
+
"../schemas/v2/skeleton.json",
|
|
164
|
+
JSON.stringify(skeletonSchemaFlattened, null, 2)
|
|
127
165
|
);
|
|
128
|
-
console.log("
|
|
166
|
+
console.log("Flat Skeleton schema written to ../schemas/v2/skeleton.json");
|
|
@@ -0,0 +1,44 @@
|
|
|
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 overlay = "baspiUI";
|
|
10
|
+
const keys = [
|
|
11
|
+
"isDependent",
|
|
12
|
+
"component",
|
|
13
|
+
"htmlClass",
|
|
14
|
+
"addButtonLabelFirst",
|
|
15
|
+
"addButtonLabelSubsequent",
|
|
16
|
+
];
|
|
17
|
+
|
|
18
|
+
const returnSchema = {
|
|
19
|
+
$schema: "http://json-schema.org/draft-07/schema#",
|
|
20
|
+
$id: `https://trust.propdata.org.uk/schemas/v2/overlays/${overlay}.json`,
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
traverse(combinedSchema).forEach(function (element) {
|
|
24
|
+
let path = "/" + this.path.join("/");
|
|
25
|
+
if (path === "/") path = "";
|
|
26
|
+
if (keys.includes(this.key)) {
|
|
27
|
+
jp.set(returnSchema, path, element);
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
const fileName = `../schemas/v2/overlays/${overlay}.json`;
|
|
32
|
+
fs.writeFileSync(fileName, JSON.stringify(returnSchema, null, 2));
|
|
33
|
+
console.log(`Overlay ${overlay} written to ${overlay}`);
|
|
34
|
+
|
|
35
|
+
traverse(combinedSchema).forEach(function (element) {
|
|
36
|
+
if (keys.includes(this.key)) {
|
|
37
|
+
this.delete(true); // true = stop here
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
fs.writeFileSync(
|
|
42
|
+
"../schemas/v2/combined.json",
|
|
43
|
+
JSON.stringify(combinedSchema, null, 2)
|
|
44
|
+
);
|