Skip to content

Commit

Permalink
Add more details on missing $ref (#368)
Browse files Browse the repository at this point in the history
* add more details on missing $ref

* Fix lint errors
  • Loading branch information
AlexHolly authored Jan 27, 2025
1 parent 9d0b1df commit 0d21ad2
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 2 deletions.
17 changes: 16 additions & 1 deletion lib/pointer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ class Pointer<S extends object = JSONSchema, O extends ParserOptions<S> = Parser
*/
resolve(obj: S, options?: O, pathFromRoot?: string) {
const tokens = Pointer.parse(this.path, this.originalPath);
const found: any = [];

// Crawl the object, one token at a time
this.value = unwrapOrThrow(obj);
Expand All @@ -103,6 +104,7 @@ class Pointer<S extends object = JSONSchema, O extends ParserOptions<S> = Parser
}

const token = tokens[i];

if (this.value[token] === undefined || (this.value[token] === null && i === tokens.length - 1)) {
// one final case is if the entry itself includes slashes, and was parsed out as a token - we can join the remaining tokens and try again
let didFindSubstringSlashMatch = false;
Expand All @@ -120,10 +122,23 @@ class Pointer<S extends object = JSONSchema, O extends ParserOptions<S> = Parser
}

this.value = null;
throw new MissingPointerError(token, decodeURI(this.originalPath));

let path: any = '';

if (path !== undefined) {
path = this.$ref.path;
}

const targetRef = this.path.replace(path, '');
const targetFound = Pointer.join('', found);
const parentPath = pathFromRoot?.replace(path, '');

throw new MissingPointerError(token, decodeURI(this.originalPath), targetRef, targetFound, parentPath);
} else {
this.value = this.value[token];
}

found.push(token)
}

// Resolve the final value
Expand Down
11 changes: 10 additions & 1 deletion lib/util/errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,8 +123,17 @@ export class UnmatchedResolverError extends JSONParserError {
export class MissingPointerError extends JSONParserError {
code = "EMISSINGPOINTER" as JSONParserErrorType;
name = "MissingPointerError";
constructor(token: string, path: string) {
public targetToken: any;
public targetRef: string;
public targetFound: string;
public parentPath: string;
constructor(token: any, path: any, targetRef: any, targetFound: any, parentPath: any) {
super(`Missing $ref pointer "${getHash(path)}". Token "${token}" does not exist.`, stripHash(path));

this.targetToken = token;
this.targetRef = targetRef;
this.targetFound = targetFound;
this.parentPath = parentPath;
}
}

Expand Down
16 changes: 16 additions & 0 deletions test/specs/missing-pointers/error-details.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
paths:
/pet:
post:
tags:
- pet
parameters:
- $ref: '#/components/parameters/ThisIsMissing'
components:
parameters:
petId:
name: petId
in: path
required: true
schema:
type: integer
format: int64
23 changes: 23 additions & 0 deletions test/specs/missing-pointers/missing-pointers.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,5 +90,28 @@ describe("Schema with missing pointers", () => {
]);
}
});

it("should throw an missing pointer error with details for target and parent", async () => {
const parser = new $RefParser();
try {
await parser.dereference({ foo: { $ref: path.abs("test/specs/missing-pointers/error-details.yaml") }}, { continueOnError: true });
helper.shouldNotGetCalled();
}
catch (err) {
expect(err).to.be.instanceof(JSONParserErrorGroup);
expect(err.files).to.equal(parser);
expect(err.message).to.have.string("1 error occurred while reading '");
expect(err.errors).to.containSubset([
{
name: MissingPointerError.name,
message: 'Missing $ref pointer \"#/components/parameters/ThisIsMissing\". Token \"ThisIsMissing\" does not exist.',
targetToken: 'ThisIsMissing',
targetRef: "#/components/parameters/ThisIsMissing",
targetFound: "#/components/parameters",
parentPath: "#/paths/~1pet/post/parameters/0"
}
]);
}
});
});
});

0 comments on commit 0d21ad2

Please sign in to comment.