| 129 | } |
| 130 | |
| 131 | function validateCrossReferences(schemas) { |
| 132 | const schemaIds = new Set(schemas.map(([_, schema]) => schema.$id)); |
| 133 | const missingRefs = []; |
| 134 | |
| 135 | for (const [schemaPath, schema] of schemas) { |
| 136 | // Find all $ref occurrences |
| 137 | const refs = JSON.stringify(schema).match(/"\$ref":\s*"([^"]+)"/g) || []; |
| 138 | |
| 139 | for (const refMatch of refs) { |
| 140 | const ref = refMatch.match(/"\$ref":\s*"([^"]+)"/)[1]; |
| 141 | |
| 142 | // Skip external references (http://, https://) |
| 143 | if (ref.startsWith('http://') || ref.startsWith('https://')) { |
| 144 | continue; |
| 145 | } |
| 146 | |
| 147 | // Skip internal references (#/$defs/..., #/properties/..., etc.) |
| 148 | if (ref.startsWith('#/')) { |
| 149 | continue; |
| 150 | } |
| 151 | |
| 152 | // Check if referenced schema exists |
| 153 | if (!schemaIds.has(ref)) { |
| 154 | missingRefs.push({ schema: schemaPath, ref }); |
| 155 | } |
| 156 | } |
| 157 | } |
| 158 | |
| 159 | if (missingRefs.length > 0) { |
| 160 | const errorMsg = missingRefs.map(({ schema, ref }) => |
| 161 | `${path.basename(schema)} -> ${ref}` |
| 162 | ).join(', '); |
| 163 | return `Missing referenced schemas: ${errorMsg}`; |
| 164 | } |
| 165 | |
| 166 | return true; |
| 167 | } |
| 168 | |
| 169 | function validateRegistryConsistency() { |
| 170 | const registryPath = path.join(SCHEMA_BASE_DIR, 'index.json'); |