Support local dereferencing of schema anchors#492
Conversation
|
@mattpolzin Can you guide me on this pull request? I have tried to add local dereferencing to support anchors, while trying to stay aligned with the existing code patterns, especially since this ends up touching more lines than I’d ideally like, but my test suite is still hitting some test failures. So before I make further changes, would you mind taking a quick look and letting me know if the approach is headed in the right direction? |
mattpolzin
left a comment
There was a problem hiding this comment.
First of all, I apologize that this PR sat for so long. I ran out of time going over the last few PRs put up the same week as this one and just haven't been able to prioritize getting nice-to-have stuff for OpenAPIKit merged since.
I would fully understand if you have moved on from this work and do not want to revisit it at this point.
However, if you would like to continue, I have a few high level questions
- Did you considered building out information about anchors while parsing the OpenAPI document as an alternative to the code in this PR that crawls the document after the fact? I'm just looking for an explanation of the contrasting approaches if you have one, not asking you to change how you've done it outright unless the alternative approach ends up being nicer.
- The
collisionIndexstrategy is a bit hard to follow at first read and the opaque components object entries are a bit of a bummer. As I understand it, anchors must be unique within any given resource, so maybe a strategy more along the lines of just using the nearest$id(or document base URI) and the anchor to identify the anchor would be a bit more obvious to the reader of the code given that is the way anchors get referenced in practice?
| if case .anchor(name: let anchorName) = reference, | ||
| ReferenceType.self == JSONSchema.self { | ||
| guard let schema = localAnchorSchema(named: anchorName) else { | ||
| throw ReferenceError.missingOnLookup(name: reference.name ?? "unnamed", key: ReferenceType.openAPIComponentsKey) |
There was a problem hiding this comment.
This error message states the given name was not found in the Components Object at the given key, which is not where the anchor lookup would have pointed necessarily.
Closes #363
Summary
#anchorreferences as a first-classJSONReference.InternalReferencecaseDocument.locallyDereferenced()build an anchor-aware temporary lookup so schema anchors can resolve during local dereferencingImplementation Details
OpenAPI 3.1 schema anchors live outside the Components Object, but local dereferencing in OpenAPIKit currently resolves only through
document.components. To keep the fix narrow and avoid changing unrelated reference behavior, this patch keeps the anchor support scoped to local dereferencing:JSONReference<...>.InternalReferencenow preserves#anchorvalues as.anchor(name:)instead of collapsing them into a generic path reference.JSONReference<JSONSchema>.anchor(named:)was added as a convenience constructor for local schema anchor references.Document.locallyDereferenced()now uses a temporary, anchor-aware copy ofcomponentsthat is populated by walking the document's inline and component-hosted schemas and registering anchored schemas for lookup during dereferencing.Components+JSONReferencenow recognizes.anchor(name:)forJSONSchemalookups so the existing dereference machinery can resolve anchored schemas and continue following nested references/cycles consistently.This keeps the public fix focused on the issue at hand: local document dereferencing now works for
$ref: '#someAnchor'without widening non-schema or non-local lookup behavior.Testing
swift test --filter JSONReferenceTestsswift test --filter DereferencedDocumentTestsswift test --filter ComponentsTestsswift test