@pdtf/schemas 3.4.1-7 → 3.5.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.
@@ -0,0 +1,84 @@
1
+ const fs = require("fs");
2
+
3
+ // Read the current skeleton
4
+ const skeleton = require("../schemas/v3/skeleton.json");
5
+
6
+ // Convert to ultra-compact format
7
+ const toCompact = (obj, indent = "") => {
8
+ if (typeof obj === "string") {
9
+ // Type indicators
10
+ if (["string", "number", "integer", "boolean", "variant"].includes(obj)) {
11
+ return obj[0]; // Just first letter: s, n, i, b, v
12
+ }
13
+ return obj;
14
+ }
15
+
16
+ if (Array.isArray(obj)) {
17
+ if (obj.length === 0) return "[]";
18
+ // Array with content
19
+ const inner = toCompact(obj[0], indent + " ");
20
+ if (typeof inner === "string" && inner.length === 1) {
21
+ return `[${inner}]`; // Simple array like [s]
22
+ }
23
+ return `[\n${indent} ${inner}\n${indent}]`;
24
+ }
25
+
26
+ if (obj && typeof obj === "object") {
27
+ const keys = Object.keys(obj);
28
+ if (keys.length === 0) return "{}";
29
+
30
+ // Check if it's a simple object with only type indicators
31
+ const allSimple = keys.every(k =>
32
+ typeof obj[k] === "string" &&
33
+ ["s", "n", "i", "b", "v"].includes(toCompact(obj[k]))
34
+ );
35
+
36
+ if (allSimple && keys.length < 5) {
37
+ // Inline format: {a:s b:n c:s}
38
+ return `{${keys.map(k => `${k}:${toCompact(obj[k])}`).join(" ")}}`;
39
+ }
40
+
41
+ // Multi-line format
42
+ const lines = keys.map(k => {
43
+ const val = toCompact(obj[k], indent + " ");
44
+ if (typeof val === "string" && val.length === 1) {
45
+ return `${indent} ${k}:${val}`;
46
+ } else if (typeof val === "string" && (val === "{}" || val === "[]")) {
47
+ return `${indent} ${k}${val}`;
48
+ } else if (typeof val === "string" && val.startsWith("{") && val.endsWith("}")) {
49
+ return `${indent} ${k}${val}`;
50
+ } else if (typeof val === "string" && val.startsWith("[") && !val.includes("\n")) {
51
+ return `${indent} ${k}${val}`;
52
+ } else {
53
+ return `${indent} ${k}:\n${indent} ${val}`;
54
+ }
55
+ });
56
+
57
+ return `{\n${lines.join("\n")}\n${indent}}`;
58
+ }
59
+
60
+ return String(obj);
61
+ };
62
+
63
+ // Generate ultra-compact version
64
+ const compact = toCompact(skeleton);
65
+
66
+ // Write compact version
67
+ fs.writeFileSync("../schemas/v3/compactSkeleton.txt", compact);
68
+
69
+ console.log("Compact skeleton written to ../schemas/v3/compactSkeleton.txt");
70
+ console.log(`Size: ${compact.length} bytes`);
71
+
72
+ // Count tokens
73
+ try {
74
+ const GPT3Encoder = require('gpt-3-encoder');
75
+ const encoded = GPT3Encoder.encode(compact);
76
+ console.log(`Tokens (GPT-3): ${encoded.length}`);
77
+ console.log(`Reduction: ${((1 - encoded.length / 78734) * 100).toFixed(1)}% fewer tokens than JSON skeleton`);
78
+
79
+ // Show sample
80
+ console.log("\nFirst 500 chars:");
81
+ console.log(compact.substring(0, 500));
82
+ } catch (e) {
83
+ console.log(`Estimated tokens: ~${Math.ceil(compact.length / 4)}`);
84
+ }
@@ -0,0 +1,67 @@
1
+ const fs = require('fs');
2
+
3
+ // Try to use tiktoken or a similar library
4
+ // For Claude/Anthropic models, we can estimate using the cl100k_base encoding
5
+ // which is similar to what Claude uses
6
+
7
+ // First, let's check what's available
8
+ try {
9
+ // Option 1: Use gpt-tokenizer (common npm package)
10
+ const { encode } = require('gpt-tokenizer');
11
+
12
+ const content = fs.readFileSync('../schemas/v3/skeleton.json', 'utf8');
13
+ const tokens = encode(content);
14
+
15
+ console.log(`Using gpt-tokenizer:`);
16
+ console.log(`Total tokens: ${tokens.length}`);
17
+ console.log(`File size: ${content.length} characters`);
18
+ console.log(`Ratio: ${(content.length / tokens.length).toFixed(2)} characters per token`);
19
+
20
+ } catch (e1) {
21
+ console.log("gpt-tokenizer not found, trying gpt-3-encoder...");
22
+
23
+ try {
24
+ // Option 2: Use gpt-3-encoder
25
+ const GPT3Encoder = require('gpt-3-encoder');
26
+
27
+ const content = fs.readFileSync('../schemas/v3/skeleton.json', 'utf8');
28
+ const encoded = GPT3Encoder.encode(content);
29
+
30
+ console.log(`Using gpt-3-encoder:`);
31
+ console.log(`Total tokens: ${encoded.length}`);
32
+ console.log(`File size: ${content.length} characters`);
33
+ console.log(`Ratio: ${(content.length / encoded.length).toFixed(2)} characters per token`);
34
+
35
+ } catch (e2) {
36
+ console.log("No tokenizer library found. Falling back to estimation...");
37
+
38
+ // Option 3: Manual estimation
39
+ const content = fs.readFileSync('../schemas/v3/skeleton.json', 'utf8');
40
+
41
+ // Count different types of content for better estimation
42
+ const lines = content.split('\n');
43
+ const words = content.split(/\s+/);
44
+ const punctuation = content.match(/[{}:,\[\]"]/g) || [];
45
+
46
+ // Rough estimation:
47
+ // - JSON structure tokens (brackets, colons, quotes): ~1 token each
48
+ // - Words: ~1 token each
49
+ // - Whitespace: usually absorbed into adjacent tokens
50
+
51
+ const structureTokens = punctuation.length;
52
+ const wordTokens = words.length;
53
+ const estimatedTokens = Math.ceil((structureTokens + wordTokens) * 0.75); // 0.75 factor for overlap
54
+
55
+ console.log("Manual estimation:");
56
+ console.log(`File size: ${content.length} characters`);
57
+ console.log(`Lines: ${lines.length}`);
58
+ console.log(`Words: ${words.length}`);
59
+ console.log(`JSON punctuation: ${punctuation.length}`);
60
+ console.log(`Estimated tokens: ~${estimatedTokens}`);
61
+ console.log(`Ratio: ${(content.length / estimatedTokens).toFixed(2)} characters per token`);
62
+
63
+ // Also do a simple character-based estimation
64
+ const simpleEstimate = Math.ceil(content.length / 4);
65
+ console.log(`\nSimple estimation (chars/4): ~${simpleEstimate} tokens`);
66
+ }
67
+ }
@@ -29,25 +29,58 @@ const extractFields = [
29
29
 
30
30
  const flattenSkeleton = (schema) => {
31
31
  if (!schema) return undefined;
32
+
33
+ // Handle arrays - mark with special notation
34
+ if (schema.type === "array" && schema.items) {
35
+ const itemSchema = flattenSkeleton(schema.items);
36
+ // Use array notation to indicate this is an array
37
+ return [itemSchema];
38
+ }
39
+
40
+ // Handle primitives - return type indicator
41
+ if (schema.type && !schema.properties && !schema.oneOf && !schema.items) {
42
+ // Return a type indicator for primitive types
43
+ if (schema.type === "string") return "string";
44
+ if (schema.type === "number") return "number";
45
+ if (schema.type === "integer") return "integer";
46
+ if (schema.type === "boolean") return "boolean";
47
+ if (schema.type === "null") return "null";
48
+ }
49
+
32
50
  let returnStructure = {};
51
+
52
+ // Handle object properties
33
53
  if (schema.properties) {
34
54
  Object.keys(schema.properties).forEach((key) => {
35
55
  returnStructure[key] = flattenSkeleton(schema.properties[key]);
36
56
  });
37
57
  }
58
+
59
+ // Handle oneOf - merge all possible properties
38
60
  if (schema.oneOf) {
39
61
  schema.oneOf.forEach((aOneOf) => {
40
62
  if (aOneOf.properties) {
41
63
  Object.entries(aOneOf.properties).forEach(([key, value]) => {
42
- returnStructure[key] = flattenSkeleton(value);
64
+ // If property already exists and differs, mark as variant
65
+ const newValue = flattenSkeleton(value);
66
+ if (returnStructure[key] && JSON.stringify(returnStructure[key]) !== JSON.stringify(newValue)) {
67
+ // For primitive types, just mark as variant type
68
+ if (typeof returnStructure[key] === "string" || typeof newValue === "string") {
69
+ returnStructure[key] = "variant";
70
+ } else {
71
+ // For complex types, merge properties
72
+ returnStructure[key] = { ...returnStructure[key], ...newValue, _variants: true };
73
+ }
74
+ } else {
75
+ returnStructure[key] = newValue;
76
+ }
43
77
  });
44
78
  }
45
79
  });
46
80
  }
47
- if (schema.items) {
48
- returnStructure = flattenSkeleton(schema.items);
49
- }
50
- return returnStructure;
81
+
82
+ // Return empty object for objects without properties
83
+ return Object.keys(returnStructure).length > 0 ? returnStructure : {};
51
84
  };
52
85
 
53
86
  const extractOverlay = (sourceSchema, ref) => {
@@ -197,3 +230,61 @@ fs.writeFileSync(
197
230
  JSON.stringify(skeletonSchemaFlattened, null, 2)
198
231
  );
199
232
  console.log("Flat Skeleton schema written to ../schemas/v3/skeleton.json");
233
+
234
+ // Generate compact skeleton format for better token efficiency
235
+ const toCompact = (obj, indent = "") => {
236
+ if (typeof obj === "string") {
237
+ // Skip type indicators entirely
238
+ return "";
239
+ }
240
+
241
+ if (Array.isArray(obj)) {
242
+ if (obj.length === 0) return "[]";
243
+ // Array with content
244
+ const inner = toCompact(obj[0], indent);
245
+ if (inner === "") {
246
+ return "[]"; // Array of primitives
247
+ }
248
+ return `[\n${inner}\n${indent}]`;
249
+ }
250
+
251
+ if (obj && typeof obj === "object") {
252
+ const keys = Object.keys(obj);
253
+ if (keys.length === 0) return "";
254
+
255
+ // Process each key
256
+ const lines = [];
257
+ keys.forEach(k => {
258
+ const val = toCompact(obj[k], indent + " ");
259
+
260
+ if (val === "") {
261
+ // Leaf node - just show the property name
262
+ lines.push(`${indent} ${k}`);
263
+ } else if (val === "[]") {
264
+ // Array property
265
+ lines.push(`${indent} ${k}[]`);
266
+ } else if (val.startsWith("[")) {
267
+ // Array with nested content - simple concatenation
268
+ lines.push(`${indent} ${k}${val}`);
269
+ } else {
270
+ // Object property - show name on its own line, content below
271
+ lines.push(`${indent} ${k}`);
272
+ lines.push(val);
273
+ }
274
+ });
275
+
276
+ return lines.length > 0 ? lines.join("\n") : "";
277
+ }
278
+
279
+ return "";
280
+ };
281
+
282
+ // Since toCompact returns lines without wrapping braces, add them for the root
283
+ const innerContent = toCompact(skeletonSchemaFlattened, "");
284
+ const compactSkeleton = innerContent ? innerContent : "";
285
+
286
+ fs.writeFileSync(
287
+ "../schemas/v3/compactSkeleton.txt",
288
+ compactSkeleton
289
+ );
290
+ console.log("Compact Skeleton written to ../schemas/v3/compactSkeleton.txt");
@@ -0,0 +1,85 @@
1
+ const fs = require("fs");
2
+
3
+ // Read the current skeleton
4
+ const skeleton = require("../schemas/v3/skeleton.json");
5
+
6
+ // Ultra-minimal format: use indentation only, no brackets
7
+ const toMinimal = (obj, prefix = "", isArrayItem = false) => {
8
+ const lines = [];
9
+
10
+ if (typeof obj === "string") {
11
+ // Type indicators - single letter
12
+ const typeMap = {
13
+ "string": "s",
14
+ "number": "n",
15
+ "integer": "i",
16
+ "boolean": "b",
17
+ "variant": "v"
18
+ };
19
+ return typeMap[obj] || obj;
20
+ }
21
+
22
+ if (Array.isArray(obj)) {
23
+ lines.push(prefix + "[]");
24
+ if (obj.length > 0) {
25
+ const itemLines = toMinimal(obj[0], prefix + " ", true);
26
+ lines.push(...(Array.isArray(itemLines) ? itemLines : [itemLines]));
27
+ }
28
+ return lines;
29
+ }
30
+
31
+ if (obj && typeof obj === "object") {
32
+ const keys = Object.keys(obj);
33
+ if (keys.length === 0) {
34
+ return prefix + "{}";
35
+ }
36
+
37
+ keys.forEach((key, index) => {
38
+ const val = obj[key];
39
+ const keyPrefix = prefix + key;
40
+
41
+ if (typeof val === "string") {
42
+ const type = toMinimal(val);
43
+ lines.push(keyPrefix + ":" + type);
44
+ } else if (Array.isArray(val)) {
45
+ const arrLines = toMinimal(val, keyPrefix);
46
+ lines.push(...arrLines);
47
+ } else if (val && typeof val === "object" && Object.keys(val).length > 0) {
48
+ lines.push(keyPrefix);
49
+ const subLines = toMinimal(val, prefix + " ");
50
+ lines.push(...(Array.isArray(subLines) ? subLines : [subLines]));
51
+ } else {
52
+ lines.push(keyPrefix);
53
+ }
54
+ });
55
+
56
+ return lines;
57
+ }
58
+
59
+ return prefix + String(obj);
60
+ };
61
+
62
+ // Generate minimal version
63
+ const minimalLines = toMinimal(skeleton);
64
+ const minimal = minimalLines.join("\n");
65
+
66
+ // Write minimal version
67
+ fs.writeFileSync("../schemas/v3/minimalSkeleton.txt", minimal);
68
+
69
+ console.log("Minimal skeleton written to ../schemas/v3/minimalSkeleton.txt");
70
+ console.log(`Size: ${minimal.length} bytes`);
71
+ console.log(`Lines: ${minimalLines.length}`);
72
+
73
+ // Count tokens
74
+ try {
75
+ const GPT3Encoder = require('gpt-3-encoder');
76
+ const encoded = GPT3Encoder.encode(minimal);
77
+ console.log(`Tokens (GPT-3): ${encoded.length}`);
78
+ console.log(`Reduction: ${((1 - encoded.length / 78734) * 100).toFixed(1)}% fewer tokens than JSON skeleton`);
79
+
80
+ // Show sample
81
+ console.log("\nFirst 20 lines:");
82
+ console.log(minimalLines.slice(0, 20).join("\n"));
83
+ } catch (e) {
84
+ console.log(`Estimated tokens: ~${Math.ceil(minimal.length / 4)}`);
85
+ }
@@ -0,0 +1,181 @@
1
+ const fs = require("fs");
2
+ const traverse = require("traverse");
3
+
4
+ const combinedSchema = require("../schemas/v3/combined.json");
5
+
6
+ // Extract fields that have overlay-specific properties
7
+ const extractFields = [
8
+ "baspi4", "baspi5", "nts", "nts2", "ntsl", "ntsl2",
9
+ "ta6", "ta7", "ta10", "lpe1", "fme1", "piq",
10
+ "con29R", "con29DW", "llc1", "rds", "oc1", "sr24",
11
+ ];
12
+
13
+ // Delete properties we don't want in the skeleton
14
+ const deleteProperties = (sourceSchema, propertyNames) => {
15
+ traverse(sourceSchema).forEach(function (element) {
16
+ if (propertyNames.includes(this.key)) {
17
+ this.delete(true);
18
+ }
19
+ });
20
+ return sourceSchema;
21
+ };
22
+
23
+ // Collect all paths in path notation
24
+ const collectPaths = (schema, currentPath = "") => {
25
+ const paths = [];
26
+
27
+ if (!schema || typeof schema !== 'object') {
28
+ return paths;
29
+ }
30
+
31
+ // Handle arrays
32
+ if (schema.type === "array" && schema.items) {
33
+ const arrayPath = currentPath + "[]";
34
+ paths.push(arrayPath);
35
+ // Continue with items
36
+ const itemPaths = collectPaths(schema.items, arrayPath);
37
+ paths.push(...itemPaths);
38
+ return paths;
39
+ }
40
+
41
+ // Handle primitives - add type suffix
42
+ if (schema.type && !schema.properties && !schema.oneOf && !schema.items) {
43
+ let typeChar = "";
44
+ switch(schema.type) {
45
+ case "string": typeChar = ":s"; break;
46
+ case "number": typeChar = ":n"; break;
47
+ case "integer": typeChar = ":i"; break;
48
+ case "boolean": typeChar = ":b"; break;
49
+ default: typeChar = "";
50
+ }
51
+ if (currentPath) {
52
+ paths.push(currentPath + typeChar);
53
+ }
54
+ return paths;
55
+ }
56
+
57
+ // Handle objects with properties
58
+ if (schema.properties) {
59
+ // If this is an object without a path yet, don't add it
60
+ if (currentPath && !schema.type?.includes("array")) {
61
+ paths.push(currentPath);
62
+ }
63
+
64
+ Object.keys(schema.properties).forEach((propName) => {
65
+ const newPath = currentPath ? `${currentPath}.${propName}` : propName;
66
+ const propPaths = collectPaths(schema.properties[propName], newPath);
67
+ paths.push(...propPaths);
68
+ });
69
+ }
70
+
71
+ // Handle oneOf - collect all possible properties
72
+ if (schema.oneOf) {
73
+ const variantProps = new Set();
74
+ schema.oneOf.forEach((oneOfSchema) => {
75
+ if (oneOfSchema.properties) {
76
+ Object.keys(oneOfSchema.properties).forEach((propName) => {
77
+ variantProps.add(propName);
78
+ });
79
+ }
80
+ });
81
+
82
+ // Process each unique property
83
+ variantProps.forEach((propName) => {
84
+ const newPath = currentPath ? `${currentPath}.${propName}` : propName;
85
+ // Check if all variants have the same type
86
+ let commonType = null;
87
+ let isVariant = false;
88
+
89
+ schema.oneOf.forEach((oneOfSchema) => {
90
+ if (oneOfSchema.properties && oneOfSchema.properties[propName]) {
91
+ const propType = oneOfSchema.properties[propName].type;
92
+ if (commonType === null) {
93
+ commonType = propType;
94
+ } else if (commonType !== propType) {
95
+ isVariant = true;
96
+ }
97
+ }
98
+ });
99
+
100
+ if (isVariant || !commonType) {
101
+ paths.push(newPath + ":v"); // variant
102
+ } else {
103
+ // Process the first variant's version of this property
104
+ for (const oneOfSchema of schema.oneOf) {
105
+ if (oneOfSchema.properties && oneOfSchema.properties[propName]) {
106
+ const propPaths = collectPaths(oneOfSchema.properties[propName], newPath);
107
+ paths.push(...propPaths);
108
+ break;
109
+ }
110
+ }
111
+ }
112
+ });
113
+ }
114
+
115
+ // Empty objects
116
+ if (currentPath && !schema.properties && !schema.oneOf && !schema.items && !schema.type) {
117
+ paths.push(currentPath);
118
+ }
119
+
120
+ return paths;
121
+ };
122
+
123
+ // Remove duplicates
124
+ const deduplicatePaths = (paths) => {
125
+ return [...new Set(paths)];
126
+ };
127
+
128
+ // Sort paths for readability
129
+ const sortPaths = (paths) => {
130
+ return paths.sort((a, b) => {
131
+ // Sort by depth first (fewer dots = higher up)
132
+ const depthA = (a.match(/\./g) || []).length;
133
+ const depthB = (b.match(/\./g) || []).length;
134
+ if (depthA !== depthB) return depthA - depthB;
135
+
136
+ // Then alphabetically
137
+ return a.localeCompare(b);
138
+ });
139
+ };
140
+
141
+ // Create clean schema
142
+ const coreSchema = deleteProperties(JSON.parse(JSON.stringify(combinedSchema)), [
143
+ "discriminator",
144
+ ...extractFields.map((item) => `${item}Ref`),
145
+ ...extractFields.map((item) => `${item}Required`),
146
+ ...extractFields.map((item) => `${item}Title`),
147
+ ...extractFields.map((item) => `${item}Description`),
148
+ ...extractFields.map((item) => `${item}Enum`),
149
+ ]);
150
+
151
+ // Remove metadata
152
+ const skeletonSchema = deleteProperties(coreSchema, [
153
+ "$schema", "$id", "title", "description", "required",
154
+ "enum", "minItems", "minLength", "format", "minimum", "maximum",
155
+ ]);
156
+
157
+ // Collect paths
158
+ const allPaths = collectPaths(skeletonSchema);
159
+ const uniquePaths = deduplicatePaths(allPaths);
160
+ const sortedPaths = sortPaths(uniquePaths);
161
+
162
+ // Write as text file
163
+ const pathContent = sortedPaths.join('\n');
164
+ fs.writeFileSync("../schemas/v3/pathSkeleton.txt", pathContent);
165
+
166
+ // Also create a JSON version for comparison
167
+ fs.writeFileSync("../schemas/v3/pathSkeleton.json", JSON.stringify(sortedPaths, null, 2));
168
+
169
+ console.log(`Path skeleton written to ../schemas/v3/pathSkeleton.txt`);
170
+ console.log(`Total paths: ${sortedPaths.length}`);
171
+ console.log(`Text size: ${pathContent.length} bytes`);
172
+
173
+ // Count tokens
174
+ try {
175
+ const GPT3Encoder = require('gpt-3-encoder');
176
+ const encoded = GPT3Encoder.encode(pathContent);
177
+ console.log(`Tokens (GPT-3): ${encoded.length}`);
178
+ console.log(`Reduction: ${((1 - encoded.length / 78734) * 100).toFixed(1)}% fewer tokens than JSON skeleton`);
179
+ } catch (e) {
180
+ console.log(`Estimated tokens: ~${Math.ceil(pathContent.length / 4)}`);
181
+ }
@@ -1,91 +0,0 @@
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
- }