Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Traits proposal #1865

Closed
wants to merge 2 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
117 changes: 117 additions & 0 deletions proposals/Traits.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
[Source](https://github.com/OAI/OpenAPI-Specification/issues/1843)


I'm opening this issue simply as a place to collect some ideas about how the concepts of [Overlays](#1722) and [Traits](#613) might be brought together.

In both proposals, I think the key notion is a "fragment", which I would describe as: a "sparse" sub-object of an OpenAPI definition. In the Overlay proposal, a fragment is the `value` of an "Update Object" and has a type of `any`.

I think fragments -- which I would like to call "mixins" -- can have a more well-defined structure than just `any`. If we use the `discriminator` approach already present in OpenAPI for "mixins", we can require (and validate) conformance to a particular structure. In particular, we can require a mixin to be a "sparse" form of any well-defined OpenAPI object, e.g. Operation, Response, Parameters, or even the whole OpenAPI definition.

Mixins could be defined as just another flavor of "component". So
```
components:
mixins:
pagable:
type: operation << so what follows should validate as a "sparse"* OpenAPI Operation object
< pageable parameters and response props in #613 >
```

Note *: "sparse" here means all props are optional

Mixins could then be included effectively anywhere in the API doc by reference:
```
$mixin: "/components/mixin/pageable"
```

By virtue of the mixin type, it could be validated as allowed or not allowed at the point it is referenced.

Now Overlays can become simply a mechanism for inserting mixins and mixin references into an API document. The JMESPath mechanism of overlays still provide the ability to apply a single update to multiple target objects using wildcards, but that update would now be expressed as simply adding a "mixin" to each of the target objects.

These are just strawman ideas and I do not claim to have thought them through any detail, but I hope they can serve as useful seeds for discussion.

### Examples

Mixins are a recasting of "Traits" as described in #613. Here's how I imagine mixins could be used to apply a "pageable" trait to operations.

The "pageable" mixin would be defined in the `components / mixins` section of the API doc:

```
components:
mixins:
pagable:
type: operation
content:
parameters:
- name: pageSize
in: query
type: number
required: false
default: 10
- name: pageNumber
in: query
type: number
required: false
default: 1
response:
200:
schema:
type: object
pagination:
$ref: "#/definitions/PaginationFragment"
```

and an operation would "apply" the "pageable" mixin with a $mixin property, as follows:
```
paths:
/foo:
get:
description: search for foo resources
$mixin:
- pagable
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be a JSON ref, not just a simple string.

parameters:
- name: q
in: query
type: string
required: true
responses:
200:
schema:
type: object
FooItems:
array:
items:
$ref: '#/definitions/FooItem'
```

The application of the mixin to the operation would yield on operation like:
```
paths:
/foo:
get:
description: search for foo resources
parameters:
- name: q
in: query
type: string
required: true
- name: pageSize
in: query
type: number
required: false
default: 10
- name: pageNumber
in: query
type: number
required: false
default: 1
responses:
200:
schema:
type: object
FooItems:
array:
items:
$ref: '#/definitions/FooItem'
pagination:
$ref: "#/definitions/PaginationFragment"
```