Closed char0n closed 4 months ago
Good point raised on TDC Meeting: naming within Components Object
will be challenging
@darrelmiller If you have any follow up questions after you've read the article again, do let me know! Slack is probably the easiest way to get hold of me =]
I'm quite sure there isn't a way to bundle non-schema object easily. You'd have to re-write $ref
s and deal with naming conflicts in components
. However, if OpenAPI adopts the $id
keyword from JSON Schema, bundling any type of object would become as simple as it is in JSON Schema.
Example ...
main.openapi.yaml
paths:
/foo:
$ref: './foo-path-item.openapi.yaml'
foo.path-item.yaml
get:
parameters: []
... bundles to ...
bundled.openapi.yaml
paths:
/foo:
$ref: './foo-path-item.openapi.yaml'
components:
'foo.path-item.yaml':
$id: 'foo.path-item.yaml'
get:
parameters: []
We don't have to rewrite the $ref
to point to a new location because the $id
sets the URI for the Path Item Object as if it was still in the other document.
We can also add a place in components
for full OpenAPI documents. This would allow for the external document to not just include the Path Item Object, but also other things that are specific to that Path Item Object such as schemas. (Personally, I'd rather put the schema in it's own file as well, but I couldn't think of another example. I'm sure they exist.)
Example:
bundled.openapi.yaml
paths:
/:
$ref: './foo.openapi.yaml#/components/pathItems/foo'
components:
schemas:
createSchema:
# the $ref below will not resolve here
openapi:
$id: './foo.openapi.yaml'
components:
pathItems:
foo:
post:
requestBody:
required: true
content:
'application/json':
schema:
$ref: '#/components/schemas/createFoo'
schemas:
createFoo:
# The $ref resolves here
type: object
This example shows how embedding like this resolves the naming conflict with the "createFoo" schema. #/components/schemas/createFoo
resolves to the embedded foo.openapi.yaml document and not the root document. This also presents a solution to the problem that you can't reliably bundle a schema that uses discriminator
because discriminator
's behavior is coupled to components
(although ideally we fix the problems with discriminator
rather than work around them).
This is getting so complicated that my recommendation for "how should we bundle OpenAPI documents" would be "just don't".
@karenetheridge
This is getting so complicated
It's really not. I expected that people who are not familiar with JSON Schema's $id
keyword might find this confusing at first, but you're definitely not in that category. I think $id
is a simple, elegant, and prooven way to enable bundling scenarios from simple to complex.
my recommendation for "how should we bundle OpenAPI documents" would be "just don't".
If you're suggesting that OpenAPI documents should always be developed as one document that can be many thousands of lines long, then that's absolutely not an acceptable solution. That wouldn't be an acceptable way to write and maintain code and writing and maintaining OpenAPI documents should be no different.
If you're suggesting that tooling needs to know how to follow external references, then that's more reasonable. However, once you support external references, supporting $id
is fairly trivial, so there's really no reason not to include that as well and have support for bundling.
Another level of bundling is inlining. We often do this for tools to consume definitions without de-referencing. But we support recursion/cyclic dependencies when we introduced $refs. To accommodate that I'm thinking of proposing a new keyword to declare something as recursive. Then we'd be able to inline entire documents.
I'm putting the note here as a reminder, and I apologies if this isn't in scope of bundling. But thought it relevant.
Folks interested in this issue will likely be interested in the general referencing discussion that has recently started. Bundling is one topic covered.
This discussion is best continued in the context of Moonwalk (v4.0), specifically at:
Closing this in favor of that.
I was wondering if there is metaplan to formalize bundling of OAS definitions as well. Ben Hutton and Mike Ralphson did a great job of formalizing JSON Schema 2020-12 in their article and set guidelines how to bundle JSON Schemas when present in OAS definitions. That's a great start, but we have other specification objects that can be bundled within OAS spec:
Path Item Object
This will be eliminated in future versions of OAS spec and replaced by Reference Object. We have
components/pathItems
where we can bundle externally referenced Path Item Objects.All spec objects replaceable by Reference Object
We have special fields for all of these objects in Components Object.
Example.externalValue field
Value of externalValue field is resolved and set as value of
value
field of Example ObjectLink.operationRef field
This IMHO is a little bit problematic. If this field is referencing an Operation Object in external document, and there are multiple Link Objects pointing to the same Operation Object defined in this external document, we have no place where to bundle it as there is no reserved field in Components Object. We have reserved extension prefix so we could possibly use
components/x-oas-operations
field.I'm not sure if my reasoning is correct here, but having an explicit guideline how to create Compound OAS definitions/documents would be great.