@pdtf/schemas 3.6.0-1 → 3.6.0-11
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/.claude/settings.local.json +16 -2
- package/index.js +92 -58
- package/package.json +3 -2
- package/src/schemas/v3/combined.json +6463 -1167
- package/src/schemas/v3/compactSkeleton.txt +328 -10
- package/src/schemas/v3/overlays/baspi4.json +151 -15
- package/src/schemas/v3/overlays/baspi5.json +154 -15
- package/src/schemas/v3/overlays/fme1.json +16 -14
- package/src/schemas/v3/overlays/lpe1.json +48 -30
- package/src/schemas/v3/overlays/nts.json +68 -1
- package/src/schemas/v3/overlays/nts2.json +68 -1
- package/src/schemas/v3/overlays/ntsl.json +68 -1
- package/src/schemas/v3/overlays/ntsl2.json +68 -1
- package/src/schemas/v3/overlays/piq.json +38 -1
- package/src/schemas/v3/overlays/rds.json +118 -6
- package/src/schemas/v3/overlays/ta6.json +28 -10
- package/src/schemas/v3/overlays/ta6ed6.json +5812 -0
- package/src/schemas/v3/overlays/ta7.json +43 -3
- package/src/schemas/v3/overlays/ta7ed5.json +1551 -0
- package/src/schemas/v3/pdtf-transaction.json +3662 -564
- package/src/schemas/v3/skeleton.json +440 -31
- package/src/tests/v3/buyerCircumstances.test.js +543 -0
- package/src/tests/v3/offers.test.js +37 -40
- package/src/tests/v3/patternProperties.test.js +149 -30
- package/src/tests/v3/ta6ed6.test.js +2314 -0
- package/src/tests/v3/ta7ed5.test.js +567 -0
- package/src/utils/extractOverlay.js +76 -10
- package/src/utils/pathSkeleton.js +1 -1
|
@@ -15,7 +15,6 @@
|
|
|
15
15
|
"Bash(git commit:*)",
|
|
16
16
|
"Bash(git push:*)",
|
|
17
17
|
"Bash(git fetch:*)",
|
|
18
|
-
"Bash(git checkout:*)",
|
|
19
18
|
"Bash(gh pr view:*)",
|
|
20
19
|
"WebFetch(domain:github.com)",
|
|
21
20
|
"Bash(tree:*)",
|
|
@@ -35,7 +34,22 @@
|
|
|
35
34
|
"Bash(base64:*)",
|
|
36
35
|
"Bash(gh issue view:*)",
|
|
37
36
|
"Read(//Users/ed/.claude/**)",
|
|
38
|
-
"Bash(npm init:*)"
|
|
37
|
+
"Bash(npm init:*)",
|
|
38
|
+
"Bash(do echo \"=== printWidth $w ===\")",
|
|
39
|
+
"Bash(pdftoppm:*)",
|
|
40
|
+
"Bash(pdftotext:*)",
|
|
41
|
+
"Bash(/tmp/inspect2.js:*)",
|
|
42
|
+
"Bash(/tmp/inspect3.js:*)",
|
|
43
|
+
"Bash(/tmp/inspect4.js:*)",
|
|
44
|
+
"Bash(/tmp/inspect5.js:*)",
|
|
45
|
+
"Bash(/tmp/inspect6.js:*)",
|
|
46
|
+
"Bash(/tmp/final_inspect.js:*)",
|
|
47
|
+
"Bash(file:*)",
|
|
48
|
+
"Bash(gh pr create:*)",
|
|
49
|
+
"Bash(claude --version)",
|
|
50
|
+
"Bash(gh pr list --head ta6ed6 --json number,title,url)",
|
|
51
|
+
"Bash(gh pr:*)",
|
|
52
|
+
"Bash(sort -t'.' -k1,1n -k2,2n -k3,3n -k4,4n)"
|
|
39
53
|
],
|
|
40
54
|
"deny": []
|
|
41
55
|
}
|
package/index.js
CHANGED
|
@@ -18,7 +18,7 @@ const cacheStats = {
|
|
|
18
18
|
hits: 0,
|
|
19
19
|
misses: 0,
|
|
20
20
|
totalQueries: 0,
|
|
21
|
-
cacheStartTime: Date.now()
|
|
21
|
+
cacheStartTime: Date.now(),
|
|
22
22
|
};
|
|
23
23
|
|
|
24
24
|
const verifiedClaimsSchema = require("./src/schemas/verifiedClaims/pdtf-verified-claims.json");
|
|
@@ -75,7 +75,9 @@ const overlaysMap = {
|
|
|
75
75
|
baspiV4: require("./src/schemas/v3/overlays/baspi4.json"),
|
|
76
76
|
baspiV5: require("./src/schemas/v3/overlays/baspi5.json"),
|
|
77
77
|
ta6ed4: require("./src/schemas/v3/overlays/ta6.json"),
|
|
78
|
+
ta6ed6: require("./src/schemas/v3/overlays/ta6ed6.json"),
|
|
78
79
|
ta7ed3: require("./src/schemas/v3/overlays/ta7.json"),
|
|
80
|
+
ta7ed5: require("./src/schemas/v3/overlays/ta7ed5.json"),
|
|
79
81
|
ta10ed3: require("./src/schemas/v3/overlays/ta10.json"),
|
|
80
82
|
lpe1ed4: require("./src/schemas/v3/overlays/lpe1.json"),
|
|
81
83
|
fme1ed2: require("./src/schemas/v3/overlays/fme1.json"),
|
|
@@ -117,21 +119,27 @@ const arrayMerge = (target, source, options) => {
|
|
|
117
119
|
// Detect if this is a required array by checking the parent key
|
|
118
120
|
// Required arrays are property names (camelCase, no spaces)
|
|
119
121
|
// Enum arrays are values (can contain spaces, capitals, etc.)
|
|
120
|
-
const isRequiredArray =
|
|
121
|
-
(
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
(item
|
|
134
|
-
|
|
122
|
+
const isRequiredArray =
|
|
123
|
+
target.every(
|
|
124
|
+
(item) =>
|
|
125
|
+
typeof item === "string" &&
|
|
126
|
+
item.length > 0 &&
|
|
127
|
+
// Required field names are typically camelCase without spaces
|
|
128
|
+
!item.includes(" ") &&
|
|
129
|
+
// First character is usually lowercase for field names
|
|
130
|
+
(item[0] === item[0].toLowerCase() ||
|
|
131
|
+
item.startsWith("is") ||
|
|
132
|
+
item.startsWith("has")),
|
|
133
|
+
) &&
|
|
134
|
+
source.every(
|
|
135
|
+
(item) =>
|
|
136
|
+
typeof item === "string" &&
|
|
137
|
+
item.length > 0 &&
|
|
138
|
+
!item.includes(" ") &&
|
|
139
|
+
(item[0] === item[0].toLowerCase() ||
|
|
140
|
+
item.startsWith("is") ||
|
|
141
|
+
item.startsWith("has")),
|
|
142
|
+
);
|
|
135
143
|
|
|
136
144
|
if (isRequiredArray) {
|
|
137
145
|
// Combine required arrays
|
|
@@ -176,7 +184,7 @@ const arrayMerge = (target, source, options) => {
|
|
|
176
184
|
|
|
177
185
|
const getTransactionSchema = (
|
|
178
186
|
schemaId = "https://trust.propdata.org.uk/schemas/v3/pdtf-transaction.json",
|
|
179
|
-
overlays
|
|
187
|
+
overlays,
|
|
180
188
|
) => {
|
|
181
189
|
const sourceSchema = transactionSchemas[schemaId];
|
|
182
190
|
if (!overlays || overlays.length < 1) return sourceSchema;
|
|
@@ -184,7 +192,7 @@ const getTransactionSchema = (
|
|
|
184
192
|
let mergedSchema = JSON.parse(JSON.stringify(sourceSchema)); // Deep copy
|
|
185
193
|
overlays.forEach((overlay) => {
|
|
186
194
|
const overlaySchema = JSON.parse(
|
|
187
|
-
JSON.stringify(overlaysMap[schemaId][overlay] || {})
|
|
195
|
+
JSON.stringify(overlaysMap[schemaId][overlay] || {}),
|
|
188
196
|
); // Deep copy
|
|
189
197
|
mergedSchema = merge(mergedSchema, overlaySchema, { arrayMerge });
|
|
190
198
|
});
|
|
@@ -211,7 +219,7 @@ const getCachedSchemaData = (path, schemaId, overlays) => {
|
|
|
211
219
|
const sourceSchema = getTransactionSchema(schemaId, overlays);
|
|
212
220
|
const pathArray = path.split("/").slice(1);
|
|
213
221
|
let subSchema = sourceSchema;
|
|
214
|
-
|
|
222
|
+
|
|
215
223
|
if (pathArray.length >= 1) {
|
|
216
224
|
subSchema = pathArray.reduce((schema, pathElement) => {
|
|
217
225
|
if (!schema) return undefined;
|
|
@@ -233,7 +241,10 @@ const getCachedSchemaData = (path, schemaId, overlays) => {
|
|
|
233
241
|
}
|
|
234
242
|
} catch (e) {
|
|
235
243
|
// Invalid regex pattern in schema - skip it
|
|
236
|
-
console.warn(
|
|
244
|
+
console.warn(
|
|
245
|
+
`Invalid regex pattern in patternProperties: ${pattern}`,
|
|
246
|
+
e,
|
|
247
|
+
);
|
|
237
248
|
}
|
|
238
249
|
}
|
|
239
250
|
}
|
|
@@ -246,6 +257,18 @@ const getCachedSchemaData = (path, schemaId, overlays) => {
|
|
|
246
257
|
matchingProperty = aOneOf.items;
|
|
247
258
|
} else if (aOneOf.properties?.[pathElement]) {
|
|
248
259
|
matchingProperty = aOneOf.properties?.[pathElement];
|
|
260
|
+
} else if (aOneOf.patternProperties) {
|
|
261
|
+
for (const pattern in aOneOf.patternProperties) {
|
|
262
|
+
try {
|
|
263
|
+
const regex = new RegExp(pattern);
|
|
264
|
+
if (regex.test(pathElement)) {
|
|
265
|
+
matchingProperty = aOneOf.patternProperties[pattern];
|
|
266
|
+
break;
|
|
267
|
+
}
|
|
268
|
+
} catch (e) {
|
|
269
|
+
// Invalid regex pattern - skip
|
|
270
|
+
}
|
|
271
|
+
}
|
|
249
272
|
}
|
|
250
273
|
});
|
|
251
274
|
if (matchingProperty) return matchingProperty;
|
|
@@ -258,7 +281,7 @@ const getCachedSchemaData = (path, schemaId, overlays) => {
|
|
|
258
281
|
// Add schema to AJV and get validator
|
|
259
282
|
// Only add valid schemas to AJV
|
|
260
283
|
let validator;
|
|
261
|
-
if (subSchema && typeof subSchema ===
|
|
284
|
+
if (subSchema && typeof subSchema === "object") {
|
|
262
285
|
// Check if schema already exists in AJV to avoid duplicates
|
|
263
286
|
validator = ajv.getSchema(cacheKey);
|
|
264
287
|
if (!validator) {
|
|
@@ -275,7 +298,7 @@ const getCachedSchemaData = (path, schemaId, overlays) => {
|
|
|
275
298
|
subSchema,
|
|
276
299
|
validator,
|
|
277
300
|
cacheKey,
|
|
278
|
-
createdAt: Date.now()
|
|
301
|
+
createdAt: Date.now(),
|
|
279
302
|
};
|
|
280
303
|
schemaCache.set(cacheKey, cached);
|
|
281
304
|
} else {
|
|
@@ -341,13 +364,13 @@ const getTitleAtPath = (schema, path, rootPath = path) => {
|
|
|
341
364
|
if (oneOfs) {
|
|
342
365
|
// only single dependency discriminator, oneOf keyword is supported
|
|
343
366
|
const matchingOneOf = oneOfs.find(
|
|
344
|
-
(oneOf) => oneOf["properties"][propertyName]
|
|
367
|
+
(oneOf) => oneOf["properties"][propertyName],
|
|
345
368
|
);
|
|
346
369
|
if (matchingOneOf)
|
|
347
370
|
return getTitleAtPath(
|
|
348
371
|
matchingOneOf["properties"][propertyName],
|
|
349
372
|
subPath,
|
|
350
|
-
rootPath
|
|
373
|
+
rootPath,
|
|
351
374
|
);
|
|
352
375
|
}
|
|
353
376
|
};
|
|
@@ -380,7 +403,7 @@ const validateVerifiedClaims = (verifiedClaims, schemaId, overlays) => {
|
|
|
380
403
|
}
|
|
381
404
|
} else {
|
|
382
405
|
validationErrorsArr.push(
|
|
383
|
-
`Path ${path} is not a valid PDTF schema path
|
|
406
|
+
`Path ${path} is not a valid PDTF schema path`,
|
|
384
407
|
);
|
|
385
408
|
}
|
|
386
409
|
}
|
|
@@ -392,8 +415,11 @@ const validateVerifiedClaims = (verifiedClaims, schemaId, overlays) => {
|
|
|
392
415
|
// Cache management functions
|
|
393
416
|
const getCacheStats = () => {
|
|
394
417
|
const runtime = Date.now() - cacheStats.cacheStartTime;
|
|
395
|
-
const hitRate =
|
|
396
|
-
|
|
418
|
+
const hitRate =
|
|
419
|
+
cacheStats.totalQueries > 0
|
|
420
|
+
? (cacheStats.hits / cacheStats.totalQueries) * 100
|
|
421
|
+
: 0;
|
|
422
|
+
|
|
397
423
|
return {
|
|
398
424
|
totalEntries: schemaCache.size,
|
|
399
425
|
hits: cacheStats.hits,
|
|
@@ -405,8 +431,8 @@ const getCacheStats = () => {
|
|
|
405
431
|
memoryUsage: {
|
|
406
432
|
entriesCount: schemaCache.size,
|
|
407
433
|
// Rough estimate of memory usage per entry
|
|
408
|
-
estimatedSizeKB: Math.round((schemaCache.size * 2) / 1024 * 100) / 100 // Rough estimate
|
|
409
|
-
}
|
|
434
|
+
estimatedSizeKB: Math.round(((schemaCache.size * 2) / 1024) * 100) / 100, // Rough estimate
|
|
435
|
+
},
|
|
410
436
|
};
|
|
411
437
|
};
|
|
412
438
|
|
|
@@ -416,15 +442,17 @@ const getDetailedCacheStats = () => {
|
|
|
416
442
|
key,
|
|
417
443
|
createdAt: value.createdAt,
|
|
418
444
|
age: Date.now() - value.createdAt,
|
|
419
|
-
hasValidator: typeof value.validator ===
|
|
420
|
-
hasSubSchema: value.subSchema !== undefined
|
|
445
|
+
hasValidator: typeof value.validator === "function",
|
|
446
|
+
hasSubSchema: value.subSchema !== undefined,
|
|
421
447
|
}));
|
|
422
448
|
|
|
423
449
|
return {
|
|
424
450
|
...baseStats,
|
|
425
451
|
entries: entries.sort((a, b) => b.createdAt - a.createdAt), // Most recent first
|
|
426
|
-
oldestEntry:
|
|
427
|
-
|
|
452
|
+
oldestEntry:
|
|
453
|
+
entries.length > 0 ? Math.max(...entries.map((e) => e.age)) : 0,
|
|
454
|
+
newestEntry:
|
|
455
|
+
entries.length > 0 ? Math.min(...entries.map((e) => e.age)) : 0,
|
|
428
456
|
};
|
|
429
457
|
};
|
|
430
458
|
|
|
@@ -437,17 +465,17 @@ const clearSchemaCache = (pattern) => {
|
|
|
437
465
|
keysToDelete.push(key);
|
|
438
466
|
}
|
|
439
467
|
});
|
|
440
|
-
keysToDelete.forEach(key => schemaCache.delete(key));
|
|
441
|
-
|
|
468
|
+
keysToDelete.forEach((key) => schemaCache.delete(key));
|
|
469
|
+
|
|
442
470
|
// Also remove matching schemas from AJV
|
|
443
|
-
keysToDelete.forEach(key => {
|
|
471
|
+
keysToDelete.forEach((key) => {
|
|
444
472
|
try {
|
|
445
473
|
ajv.removeSchema(key);
|
|
446
474
|
} catch (e) {
|
|
447
475
|
// Schema might not exist in AJV, ignore
|
|
448
476
|
}
|
|
449
477
|
});
|
|
450
|
-
|
|
478
|
+
|
|
451
479
|
return keysToDelete.length;
|
|
452
480
|
} else {
|
|
453
481
|
// Clear all cache
|
|
@@ -458,20 +486,24 @@ const clearSchemaCache = (pattern) => {
|
|
|
458
486
|
cacheStats.misses = 0;
|
|
459
487
|
cacheStats.totalQueries = 0;
|
|
460
488
|
cacheStats.cacheStartTime = Date.now();
|
|
461
|
-
|
|
489
|
+
|
|
462
490
|
// Also clear AJV's internal cache to prevent duplicates
|
|
463
491
|
ajv.removeSchema();
|
|
464
|
-
|
|
492
|
+
|
|
465
493
|
return entriesCleared;
|
|
466
494
|
}
|
|
467
495
|
};
|
|
468
496
|
|
|
469
|
-
const warmupCache = (
|
|
497
|
+
const warmupCache = (
|
|
498
|
+
paths,
|
|
499
|
+
schemaId = "https://trust.propdata.org.uk/schemas/v3/pdtf-transaction.json",
|
|
500
|
+
overlaysList = [],
|
|
501
|
+
) => {
|
|
470
502
|
const warmupStats = {
|
|
471
503
|
totalAttempted: 0,
|
|
472
504
|
successful: 0,
|
|
473
505
|
failed: 0,
|
|
474
|
-
errors: []
|
|
506
|
+
errors: [],
|
|
475
507
|
};
|
|
476
508
|
|
|
477
509
|
// Default common paths if none provided
|
|
@@ -483,7 +515,7 @@ const warmupCache = (paths, schemaId = "https://trust.propdata.org.uk/schemas/v3
|
|
|
483
515
|
"/propertyPack/valuations",
|
|
484
516
|
"/propertyPack/waterAndDrainage",
|
|
485
517
|
"/propertyPack/ownership",
|
|
486
|
-
"/propertyPack/notices"
|
|
518
|
+
"/propertyPack/notices",
|
|
487
519
|
];
|
|
488
520
|
|
|
489
521
|
// Default common overlays if none provided
|
|
@@ -492,14 +524,15 @@ const warmupCache = (paths, schemaId = "https://trust.propdata.org.uk/schemas/v3
|
|
|
492
524
|
["baspiV5"],
|
|
493
525
|
["ta6ed4"],
|
|
494
526
|
["nts2023"],
|
|
495
|
-
["baspiV5", "ta6ed4"]
|
|
527
|
+
["baspiV5", "ta6ed4"],
|
|
496
528
|
];
|
|
497
529
|
|
|
498
530
|
const pathsToWarm = paths || defaultPaths;
|
|
499
|
-
const overlaysToWarm =
|
|
531
|
+
const overlaysToWarm =
|
|
532
|
+
overlaysList.length > 0 ? overlaysList : defaultOverlays;
|
|
500
533
|
|
|
501
|
-
pathsToWarm.forEach(path => {
|
|
502
|
-
overlaysToWarm.forEach(overlays => {
|
|
534
|
+
pathsToWarm.forEach((path) => {
|
|
535
|
+
overlaysToWarm.forEach((overlays) => {
|
|
503
536
|
warmupStats.totalAttempted++;
|
|
504
537
|
try {
|
|
505
538
|
// This will populate the cache
|
|
@@ -511,7 +544,7 @@ const warmupCache = (paths, schemaId = "https://trust.propdata.org.uk/schemas/v3
|
|
|
511
544
|
warmupStats.errors.push({
|
|
512
545
|
path,
|
|
513
546
|
overlays,
|
|
514
|
-
error: error.message
|
|
547
|
+
error: error.message,
|
|
515
548
|
});
|
|
516
549
|
}
|
|
517
550
|
});
|
|
@@ -523,14 +556,14 @@ const warmupCache = (paths, schemaId = "https://trust.propdata.org.uk/schemas/v3
|
|
|
523
556
|
const pruneCacheByAge = (maxAgeMs) => {
|
|
524
557
|
const now = Date.now();
|
|
525
558
|
const keysToDelete = [];
|
|
526
|
-
|
|
559
|
+
|
|
527
560
|
schemaCache.forEach((value, key) => {
|
|
528
561
|
if (now - value.createdAt > maxAgeMs) {
|
|
529
562
|
keysToDelete.push(key);
|
|
530
563
|
}
|
|
531
564
|
});
|
|
532
|
-
|
|
533
|
-
keysToDelete.forEach(key => {
|
|
565
|
+
|
|
566
|
+
keysToDelete.forEach((key) => {
|
|
534
567
|
schemaCache.delete(key);
|
|
535
568
|
try {
|
|
536
569
|
ajv.removeSchema(key);
|
|
@@ -538,21 +571,22 @@ const pruneCacheByAge = (maxAgeMs) => {
|
|
|
538
571
|
// Schema might not exist in AJV, ignore
|
|
539
572
|
}
|
|
540
573
|
});
|
|
541
|
-
|
|
574
|
+
|
|
542
575
|
return keysToDelete.length;
|
|
543
576
|
};
|
|
544
577
|
|
|
545
578
|
const setCacheMaxSize = (maxSize) => {
|
|
546
579
|
if (schemaCache.size <= maxSize) return 0;
|
|
547
|
-
|
|
580
|
+
|
|
548
581
|
// Get entries sorted by creation time (oldest first)
|
|
549
|
-
const entries = Array.from(schemaCache.entries())
|
|
550
|
-
|
|
551
|
-
|
|
582
|
+
const entries = Array.from(schemaCache.entries()).sort(
|
|
583
|
+
(a, b) => a[1].createdAt - b[1].createdAt,
|
|
584
|
+
);
|
|
585
|
+
|
|
552
586
|
const toRemove = schemaCache.size - maxSize;
|
|
553
587
|
const keysToDelete = entries.slice(0, toRemove).map(([key]) => key);
|
|
554
|
-
|
|
555
|
-
keysToDelete.forEach(key => {
|
|
588
|
+
|
|
589
|
+
keysToDelete.forEach((key) => {
|
|
556
590
|
schemaCache.delete(key);
|
|
557
591
|
try {
|
|
558
592
|
ajv.removeSchema(key);
|
|
@@ -560,7 +594,7 @@ const setCacheMaxSize = (maxSize) => {
|
|
|
560
594
|
// Schema might not exist in AJV, ignore
|
|
561
595
|
}
|
|
562
596
|
});
|
|
563
|
-
|
|
597
|
+
|
|
564
598
|
return keysToDelete.length;
|
|
565
599
|
};
|
|
566
600
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pdtf/schemas",
|
|
3
|
-
"version": "3.6.0-
|
|
3
|
+
"version": "3.6.0-11",
|
|
4
4
|
"description": "Property Data Trust Framework Schemas and Utilities",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"directories": {
|
|
@@ -8,7 +8,8 @@
|
|
|
8
8
|
},
|
|
9
9
|
"scripts": {
|
|
10
10
|
"test": "jest",
|
|
11
|
-
"test:watch": "jest --watch"
|
|
11
|
+
"test:watch": "jest --watch",
|
|
12
|
+
"extract-overlays": "cd src/utils && node extractOverlay.js"
|
|
12
13
|
},
|
|
13
14
|
"repository": {
|
|
14
15
|
"type": "git",
|