Skip to content

Updated Overlay proposal #2300

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

Merged
merged 3 commits into from
Apr 1, 2021
Merged
Show file tree
Hide file tree
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
27 changes: 14 additions & 13 deletions proposals/004_Overlays.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@
|---- | ---------------- | ---------- |
| 24th December 2019 | Darrel Miller | Initial draft |
| 2nd January 2019 | Darrel Miller | Update to wording around removing items from arrays. Added section on backward compatibility. Clarified process around applying a set of updates. Started to add supported scenarios.|
| 29th July 2020 | Darrel Miller | Updated to be explicit about update operations |

## Introduction

In recent months we have been discussing various use cases for overlays and various solutions. The following proposal takes a somewhat more radical approach to the problem. It is a more ambitious proposal than the others we have seen before but the additional complexity does allow for supporting many of the scenarios that have been discussed to date.


#### <a name="overlayDocument"></a>Overlay Document

An overlay document contains a list of [Update Objects](#overlayUpdates) that are to be applied to the target document. Each [Update Object](#updateObject) has a `target` property and a `value` property. The `target` property is a [JMESPath](http://jmespath.org/specification.html) query that identifies what part of the target document is to be updated and the `value` property contains an object with the properties to be overlaid.
Expand Down Expand Up @@ -63,10 +63,11 @@ This object represents one or more changes to be applied to the target document
Field Name | Type | Description
---|:---:|---
<a name="updateTarget"></a>target | `string` | A JMESPath expression referencing the target objects in the target document.
<a name="updateValue"></a>value | [Any](#valueObject) | An object with the properties and values to be updated in the target document. Property has no impact if `remove` property is `true`.
<a name="updateAdd"></a>add | [Any](#addObject) | An object to be added as a child of the object(s) referenced by the target. Property has no impact if `remove` property is `true`.
Copy link
Member

Choose a reason for hiding this comment

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

I can see how add works for arrays. For objects, what is the name/key of the child object being added, or is add not applicable to objects?

<a name="updateMerge"></a>merge | [Any](#mergeObject) | An object with the properties and values to be merged with the object(s) referenced by the target. Property has no impact if `remove` property is `true`.
Copy link
Member

Choose a reason for hiding this comment

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

I can see how merge works for objects, but we should either say how merge works for arrays (provide an example?) or expressly forbid it.

<a name="updateRemove"></a>remove | `boolean` | A boolean value that indicates that the target object is to be removed from the the map or array it is contained in. The default value is false.

The properties of the `Value Object` MUST be compatible with the target object referenced by the JMESPath key. When the Overlay document is applied, the properties in the `Value Object` replace properties in the target object with the same name and new properties are appended to the target object.
The properties of the merge object MUST be compatible with the target object referenced by the JMESPath key. When the Overlay document is applied, the properties in the merge object replace properties in the target object with the same name and new properties are appended to the target object.

##### Structured Overlays Example

Expand All @@ -79,7 +80,7 @@ info:
version: 1.0.0
updates:
- target: "@"
value:
merge:
info:
x-overlay-applied: structured-overlay
paths:
Expand All @@ -103,17 +104,17 @@ Alternatively, where only a small number of updates need to be applied to a larg
```yaml
overlay: 1.0.0
info:
title: Structured Overlay
title: Targeted Overlays
version: 1.0.0
updates:
- target: paths."/foo".get
value:
merge:
description: This is the new description
- target: paths."/bar".get
value:
merge:
description: This is the updated description
- target: paths."/bar"
value:
merge:
post:
description: This is an updated description of a child object
x-safe: false
Expand All @@ -130,10 +131,10 @@ info:
version: 1.0.0
updates:
- target: paths.*.get
value:
merge:
x-safe: true
- target: paths.*.get.parameters[?name=='filter' && in=='query']
value:
merge:
schema:
$ref: "/components/schemas/filterSchema"
```
Expand All @@ -148,8 +149,8 @@ info:
title: Add an array element
version: 1.0.0
updates:
- target: paths.*.get.parameters[length(@)]
value:
- target: paths.*.get.parameters
add:
name: newParam
in: query
```
Expand All @@ -160,7 +161,7 @@ info:
title: Remove a array element
version: 1.0.0
updates:
- target: $.paths[*].get.parameters[? name == 'dummy']
- target: paths[*].get.parameters[? name == 'dummy']
remove: true
```

Expand Down
70 changes: 70 additions & 0 deletions proposals/Overlays/Changes.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# Create update methods (add,replace,merge,delete)? Is merge necessary?
# Multiple additions or updates to the same target is more efficient with merge

# Different than JSON Patch because is works in JSON and YAML
# Has info object and spec version
# values

overlay: 1.0.0
info:
title: An example of an overlay that captures changes to an API
version: 1.0.0
updates:
# Add a property to a schema
- target: components.schemas."todo".properties
merge:
createdBy:
type: string
# Add constraints to a schema
- target: components.schemas."todo"
merge:
additionalProperties: false
- target: components.schemas."todo"
merge:
type: ["object","null"]
#Change a schema
- target: components.schemas."todo"
replace:
type: integer
# Add multiple constraints to a schema using merge
- target: components.schemas."todo"
merge:
additionalProperties: false
type: ["object","null"]
# Add multiple constraints to a schema using merge
- target: components.schemas."todo"
merge:
additionalProperties: false
type: ["object","null"]
properties:
someprop:
type: string
# Add an operation
- target: paths."/foo"
add:
delete:
description: delete a foo
responses:
200:
description: ok
# Add a path
- target: paths
add:
"/items":
get:
responses:
200:
description: ok
# Add an optional query parameter
- target: paths."/bar".parameters
add:
name: skip
in: query
type: string
# Mark an operation as deprecated

# Change the value of a JSON schema constraint
# Update the version of the API
# Change the license of an API
# Add support for a new request media type
# Add support for a new response media type
10 changes: 10 additions & 0 deletions proposals/Overlays/MergePatch.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
overlay: 1.0.0
info:
title: An example of an overlay that performs a Merge Patch
version: 1.0.0
updates:
- target: "@"
merge:
openapi: 3.0.3
paths: {}