From cdeeeaac28625e5d51a71cbc78d9904b5eeebe90 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Wed, 29 Oct 2025 15:04:19 -0400 Subject: [PATCH 1/6] feat: adds copy actions Signed-off-by: Vincent Biret --- schemas/v1.1-dev/schema.yaml | 2 + .../v1.1-dev/pass/copy-path-item-example.yaml | 7 + versions/1.1.0-dev.md | 201 +++++++++++++++++- 3 files changed, 208 insertions(+), 2 deletions(-) create mode 100644 tests/v1.1-dev/pass/copy-path-item-example.yaml diff --git a/schemas/v1.1-dev/schema.yaml b/schemas/v1.1-dev/schema.yaml index 459cbef..9e78075 100644 --- a/schemas/v1.1-dev/schema.yaml +++ b/schemas/v1.1-dev/schema.yaml @@ -51,6 +51,8 @@ $defs: - array - number - "null" + copy: + type: string remove: type: boolean default: false diff --git a/tests/v1.1-dev/pass/copy-path-item-example.yaml b/tests/v1.1-dev/pass/copy-path-item-example.yaml new file mode 100644 index 0000000..529e486 --- /dev/null +++ b/tests/v1.1-dev/pass/copy-path-item-example.yaml @@ -0,0 +1,7 @@ +overlay: 1.1.0 +info: + title: Merge an existing path item with another one + version: 1.0.0 +actions: + - target: '$.paths["/bar"]' + copy: '$.paths["/foo"]' \ No newline at end of file diff --git a/versions/1.1.0-dev.md b/versions/1.1.0-dev.md index 96b04eb..ce6348d 100644 --- a/versions/1.1.0-dev.md +++ b/versions/1.1.0-dev.md @@ -21,7 +21,7 @@ The main purpose of the Overlay Specification is to provide a way to repeatably ### Overlay -An Overlay is a JSON or YAML structure containing an ordered list of [Action Objects](#overlay-actions) that are to be applied to the target document. Each [Action Object](#action-object) has a `target` property and a modifier type (`update` or `remove`). The `target` property is a [[RFC9535|JSONPath]] query expression that identifies the elements of the target document to be updated and the modifier determines the change. +An Overlay is a JSON or YAML structure containing an ordered list of [Action Objects](#overlay-actions) that are to be applied to the target document. Each [Action Object](#action-object) has a `target` property and a modifier type (`update`, `remove` or `copy`). The `target` property is a [[RFC9535|JSONPath]] query expression that identifies the elements of the target document to be updated and the modifier determines the change. ## Specification @@ -115,7 +115,8 @@ This object represents one or more changes to be applied to the target document | ---- | :----: | ---- | | target | `string` | **REQUIRED** A JSONPath expression selecting nodes in the target document. | | description | `string` | A description of the action. [[CommonMark]] syntax MAY be used for rich text representation. | -| update | Any | If the `target` selects an object node, the value of this field MUST be an object with the properties and values to merge with the selected node. If the `target` selects an array, the value of this field MUST be an entry to append to the array. This field has no impact if the `remove` field of this action object is `true`. | +| update | Any | If the `target` selects an object node, the value of this field MUST be an object with the properties and values to merge with the selected node. If the `target` selects an array, the value of this field MUST be an entry to append to the array. This field has no impact if the `remove` field of this action object is `true` or if the `copy` field contains a value. | +| copy | `string` | A JSONPath expression selecting a single node to copy into the `target` nodes. If the `target` selects an object node, the value of this field MUST be an object with the properties and values to merge with the selected node. If the `target` selects an array, the value of this field MUST be an entry to append to the array. This field has no impact if the `remove` field of this action object is `true` or if the `update` field contains a value. | | remove | `boolean` | A boolean value that indicates that the target object or array MUST be removed from the the map or array it is contained in. The default value is `false`. | The result of the `target` JSONPath expression MUST be zero or more objects or arrays (not primitive types or `null` values). @@ -126,6 +127,8 @@ Primitive-valued items of an array cannot be replaced or removed individually, o The properties of the `update` object MUST be compatible with the target object referenced by the JSONPath key. When the Overlay document is applied, the properties in the `update` object are recursively merged with the properties in the target object with the same names; new properties are added to the target object. +The properties of the resolved `copy` object MUST be compatible with the target object referenced by the JSONPath key. When the Overlay document is applied, the properties in the resolved `copy` object are recursively merged with the properties in the target object with the same names; new properties are added to the target object. + This object MAY be extended with [Specification Extensions](#specification-extensions). ### Examples @@ -265,6 +268,200 @@ actions: This approach allows inversion of control as to where the Overlay updates apply to the target document itself. +#### Copy example + +Copy actions behave similarly to `update` actions but source the node to from the document being transformed. Copy `actions` MAY be used in sequence with `update` or `remove` actions to perform more advanced transformations like moving or renaming nodes. + +##### Simple copy + +This example shows how to copy all operations from the `items` path item to the `some-items` path item. + +###### Source description + +```yaml +openapi: 3.1.0 +info: + title: API with a paged collection + version: 1.0.0 +paths: + /items: + get: + responses: + 200: + description: OK + /some-items: + delete: + responses: + 200: + description: OK +``` + +###### Overlay + +```yaml +overlay: 1.1.0 +info: + title: Demonstrates variations of "copy" uses + version: 1.0.0 +actions: + - target: '$.paths["/some-items"]' + copy: '$.paths["/items"]' + description: 'copies recursively all elements from the "items" path item to the new "some-items" path item without ensuring the node exists before the copy' +``` + +###### Result description + +```yaml +openapi: 3.1.0 +info: + title: API with a paged collection + version: 1.0.0 +paths: + /items: + get: + responses: + 200: + description: OK + /some-items: + get: + responses: + 200: + description: OK + delete: + responses: + 200: + description: OK +``` + +##### Ensure the target exists and copy + +This example shows how to copy all operations from the `items` path item to the `other-items` path item after first ensuring the target exists with an update action. + +###### Source description + +```yaml +openapi: 3.1.0 +info: + title: API with a paged collection + version: 1.0.0 +paths: + /items: + get: + responses: + 200: + description: OK + /some-items: + delete: + responses: + 200: + description: OK +``` + +###### Overlay + +```yaml +overlay: 1.1.0 +info: + title: Demonstrates variations of "copy" uses + version: 1.0.0 +actions: + - target: '$.paths' + update: { "/other-items": {} } + - target: '$.paths["/other-items"]' + copy: '$.paths["/items"]' + description: 'copies recursively all elements from the "items" path item to the new "other-items" path item while ensuring the node exists before the copy' +``` + +###### Result description + +```yaml +openapi: 3.1.0 +info: + title: API with a paged collection + version: 1.0.0 +paths: + /items: + get: + responses: + 200: + description: OK + /other-items: + get: + responses: + 200: + description: OK + /some-items: + delete: + responses: + 200: + description: OK +``` + +##### Move example + +This example shows how to rename the `items` path item to `new-items` using a sequence of overlay actions: + +1. Use an `update` action to ensure the target path item exists. +2. Use a `copy` action to copy the source path item to the target. +3. Use a `remove` action to delete the original source path item. + +###### Source description + +```yaml +openapi: 3.1.0 +info: + title: API with a paged collection + version: 1.0.0 +paths: + /items: + get: + responses: + 200: + description: OK + /some-items: + delete: + responses: + 200: + description: OK +``` + +###### Overlay + +```yaml +overlay: 1.1.0 +info: + title: Demonstrates variations of "copy" uses + version: 1.0.0 +actions: + - target: '$.paths' + update: { "/new-items": {} } + - target: '$.paths["/new-items"]' + copy: '$.paths["/items"]' + - target: '$.paths["/items"]' + remove: true + description: 'moves (renames) the "items" path item to "new-items"' +``` + +###### Result description + +```yaml +openapi: 3.1.0 +info: + title: API with a paged collection + version: 1.0.0 +paths: + /new-items: + get: + responses: + 200: + description: OK + /some-items: + delete: + responses: + 200: + description: OK +``` + ### Specification Extensions While the Overlay Specification tries to accommodate most use cases, additional data can be added to extend the specification at certain points. From f8c01950412da5eb52c2e519bc625723bae32aad Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Wed, 29 Oct 2025 16:36:02 -0400 Subject: [PATCH 2/6] chore: adds Oxford comma Co-authored-by: Ralf Handl --- versions/1.1.0-dev.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/versions/1.1.0-dev.md b/versions/1.1.0-dev.md index ce6348d..14ac1b7 100644 --- a/versions/1.1.0-dev.md +++ b/versions/1.1.0-dev.md @@ -21,7 +21,7 @@ The main purpose of the Overlay Specification is to provide a way to repeatably ### Overlay -An Overlay is a JSON or YAML structure containing an ordered list of [Action Objects](#overlay-actions) that are to be applied to the target document. Each [Action Object](#action-object) has a `target` property and a modifier type (`update`, `remove` or `copy`). The `target` property is a [[RFC9535|JSONPath]] query expression that identifies the elements of the target document to be updated and the modifier determines the change. +An Overlay is a JSON or YAML structure containing an ordered list of [Action Objects](#overlay-actions) that are to be applied to the target document. Each [Action Object](#action-object) has a `target` property and a modifier type (`update`, `remove`, or `copy`). The `target` property is a [[RFC9535|JSONPath]] query expression that identifies the elements of the target document to be updated and the modifier determines the change. ## Specification From d88c0a0324aec50c3479f2dab27010b289d0878e Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Mon, 3 Nov 2025 08:26:33 -0500 Subject: [PATCH 3/6] Apply suggestions from code review Co-authored-by: Lorna Jane Mitchell --- versions/1.1.0-dev.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/versions/1.1.0-dev.md b/versions/1.1.0-dev.md index 14ac1b7..cc1fe27 100644 --- a/versions/1.1.0-dev.md +++ b/versions/1.1.0-dev.md @@ -281,7 +281,7 @@ This example shows how to copy all operations from the `items` path item to the ```yaml openapi: 3.1.0 info: - title: API with a paged collection + title: Example API version: 1.0.0 paths: /items: @@ -301,7 +301,7 @@ paths: ```yaml overlay: 1.1.0 info: - title: Demonstrates variations of "copy" uses + title: Copy contents of an existing path to a new location version: 1.0.0 actions: - target: '$.paths["/some-items"]' @@ -362,7 +362,7 @@ paths: ```yaml overlay: 1.1.0 info: - title: Demonstrates variations of "copy" uses + title: Create a path and copy the contents of an existing path to the new path version: 1.0.0 actions: - target: '$.paths' @@ -430,7 +430,7 @@ paths: ```yaml overlay: 1.1.0 info: - title: Demonstrates variations of "copy" uses + title: Update the path for an API endpoint version: 1.0.0 actions: - target: '$.paths' From 31bc27069d5a055e4592bae9da621ccc57cddede Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Mon, 3 Nov 2025 12:39:08 -0500 Subject: [PATCH 4/6] Apply suggestions from code review Co-authored-by: Ralf Handl --- versions/1.1.0-dev.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/versions/1.1.0-dev.md b/versions/1.1.0-dev.md index f44c95b..01b5f36 100644 --- a/versions/1.1.0-dev.md +++ b/versions/1.1.0-dev.md @@ -316,7 +316,7 @@ actions: ```yaml openapi: 3.1.0 info: - title: API with a paged collection + title: Example API version: 1.0.0 paths: /items: @@ -344,7 +344,7 @@ This example shows how to copy all operations from the `items` path item to the ```yaml openapi: 3.1.0 info: - title: API with a paged collection + title: Example API version: 1.0.0 paths: /items: @@ -379,7 +379,7 @@ actions: ```yaml openapi: 3.1.0 info: - title: API with a paged collection + title: Example API version: 1.0.0 paths: /items: @@ -412,7 +412,7 @@ This example shows how to rename the `items` path item to `new-items` using a se ```yaml openapi: 3.1.0 info: - title: API with a paged collection + title: Example API version: 1.0.0 paths: /items: @@ -449,7 +449,7 @@ actions: ```yaml openapi: 3.1.0 info: - title: API with a paged collection + title: Example API version: 1.0.0 paths: /new-items: From 271160dae0df2a4f2ed5c5aa98abea7c3c12b2b3 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Tue, 4 Nov 2025 08:01:29 -0500 Subject: [PATCH 5/6] Update versions/1.1.0-dev.md Co-authored-by: Ralf Handl --- versions/1.1.0-dev.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/versions/1.1.0-dev.md b/versions/1.1.0-dev.md index 01b5f36..748d9a3 100644 --- a/versions/1.1.0-dev.md +++ b/versions/1.1.0-dev.md @@ -272,7 +272,7 @@ This approach allows inversion of control as to where the Overlay updates apply #### Copy example -Copy actions behave similarly to `update` actions but source the node to from the document being transformed. Copy `actions` MAY be used in sequence with `update` or `remove` actions to perform more advanced transformations like moving or renaming nodes. +Copy actions behave similarly to `update` actions but source the new values to merge with the target from the document being transformed instead of providing them in the Overlay document. Copy `actions` MAY be used in sequence with `update` or `remove` actions to perform more advanced transformations like moving or renaming nodes. ##### Simple copy From 4e3166792f462bccd12d4948019545320182e3be Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Tue, 4 Nov 2025 09:59:35 -0500 Subject: [PATCH 6/6] Update versions/1.1.0-dev.md Co-authored-by: Ralf Handl --- versions/1.1.0-dev.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/versions/1.1.0-dev.md b/versions/1.1.0-dev.md index 748d9a3..e8c127f 100644 --- a/versions/1.1.0-dev.md +++ b/versions/1.1.0-dev.md @@ -272,7 +272,7 @@ This approach allows inversion of control as to where the Overlay updates apply #### Copy example -Copy actions behave similarly to `update` actions but source the new values to merge with the target from the document being transformed instead of providing them in the Overlay document. Copy `actions` MAY be used in sequence with `update` or `remove` actions to perform more advanced transformations like moving or renaming nodes. +Copy actions behave similarly to `update` actions but source the new values to merge with the target from the document being transformed instead of providing them in the Overlay document. Copy actions MAY be used in sequence with `update` or `remove` actions to perform more advanced transformations like moving or renaming nodes. ##### Simple copy