diff --git a/packages/json-schema-ref-parser/src/bundle.ts b/packages/json-schema-ref-parser/src/bundle.ts index 7293f917d..e337b0a29 100644 --- a/packages/json-schema-ref-parser/src/bundle.ts +++ b/packages/json-schema-ref-parser/src/bundle.ts @@ -157,11 +157,31 @@ const inventory$Ref = ({ pointer = $refs._resolve($refPath, pathFromRoot, options); } catch (error) { if (error instanceof MissingPointerError) { - // Log warning but continue - common in complex schema ecosystems - console.warn(`Skipping unresolvable $ref: ${$refPath}`); - return; + // The ref couldn't be resolved in the target file. This commonly + // happens when a wrapper file redirects via $ref to a versioned + // file, and the bundler's crawl path retains the wrapper URL. + // Try resolving the hash fragment against other files in $refs + // that might contain the target schema. + const hash = url.getHash($refPath); + if (hash) { + const baseFile = url.stripHash($refPath); + for (const filePath of Object.keys($refs._$refs)) { + if (filePath === baseFile) continue; + try { + pointer = $refs._resolve(filePath + hash, pathFromRoot, options); + if (pointer) break; + } catch { + // try next file + } + } + } + if (!pointer) { + console.warn(`Skipping unresolvable $ref: ${$refPath}`); + return; + } + } else { + throw error; } - throw error; // Re-throw unexpected errors } if (pointer) { @@ -217,8 +237,19 @@ const inventory$Ref = ({ inventory.push(newEntry); inventoryLookup.add(newEntry); - // Recursively crawl the resolved value + // Recursively crawl the resolved value. + // When the resolution followed a $ref chain to a different file, + // use the resolved file as the base path so that local $ref values + // (e.g. #/components/schemas/SiblingSchema) inside the resolved + // value resolve against the correct file. if (!existingEntry || external) { + let crawlPath = pointer.path; + + const originalFile = url.stripHash($refPath); + if (file !== originalFile) { + crawlPath = file + url.getHash(pointer.path); + } + crawl({ $refs, indirections: indirections + 1, @@ -227,7 +258,7 @@ const inventory$Ref = ({ key: null, options, parent: pointer.value, - path: pointer.path, + path: crawlPath, pathFromRoot, resolvedRefs, visitedObjects,