Skip to content

Commit 0f3fea1

Browse files
committed
feat: adds a copy action
Signed-off-by: Vincent Biret <[email protected]>
1 parent 637517d commit 0f3fea1

File tree

3 files changed

+209
-3
lines changed

3 files changed

+209
-3
lines changed

schemas/v1.1-dev/schema.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ $defs:
5151
- array
5252
- number
5353
- "null"
54+
copy:
55+
type: string
5456
remove:
5557
type: boolean
5658
default: false
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
overlay: 1.1.0
2+
info:
3+
title: Merge an existing path item with another one
4+
version: 1.0.0
5+
actions:
6+
- target: '$.paths["/bar"]'
7+
copy: '$.paths["/foo"]'

versions/1.1.0-dev.md

Lines changed: 200 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
The Overlay Specification defines a document format for information that augments an existing [[OpenAPI]] description yet remains separate from the OpenAPI description's source document(s).
66

7-
## Version 1.1.0
7+
## Version 1.0.0
88

99
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in [BCP 14](https://tools.ietf.org/html/bcp14) [RFC2119](https://tools.ietf.org/html/rfc2119) [RFC8174](https://tools.ietf.org/html/rfc8174) when, and only when, they appear in all capitals, as shown here.
1010

@@ -21,7 +21,7 @@ The main purpose of the Overlay Specification is to provide a way to repeatably
2121

2222
### Overlay
2323

24-
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.
24+
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.
2525

2626
## Specification
2727

@@ -115,7 +115,8 @@ This object represents one or more changes to be applied to the target document
115115
| ---- | :----: | ---- |
116116
| <a name="action-target"></a>target | `string` | **REQUIRED** A JSONPath expression selecting nodes in the target document. |
117117
| <a name="action-description"></a>description | `string` | A description of the action. [[CommonMark]] syntax MAY be used for rich text representation. |
118-
| <a name="action-update"></a>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`. |
118+
| <a name="action-update"></a>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. |
119+
| <a name="action-copy"></a>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. |
119120
| <a name="action-remove"></a>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`. |
120121

121122
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
126127

127128
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.
128129

130+
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.
131+
129132
This object MAY be extended with [Specification Extensions](#specification-extensions).
130133

131134
### Examples
@@ -265,6 +268,200 @@ actions:
265268

266269
This approach allows inversion of control as to where the Overlay updates apply to the target document itself.
267270

271+
#### Copy example
272+
273+
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.
274+
275+
##### Simple copy
276+
277+
This example shows how to copy all operations from the `items` path item to the `some-items` path item.
278+
279+
###### Source description
280+
281+
```yaml
282+
openapi: 3.1.0
283+
info:
284+
title: API with a paged collection
285+
version: 1.0.0
286+
paths:
287+
/items:
288+
get:
289+
responses:
290+
200:
291+
description: OK
292+
/some-items:
293+
delete:
294+
responses:
295+
200:
296+
description: OK
297+
```
298+
299+
###### Overlay
300+
301+
```yaml
302+
overlay: 1.1.0
303+
info:
304+
title: Demonstrates variations of "copy" uses
305+
version: 1.0.0
306+
actions:
307+
- target: '$.paths["/some-items"]'
308+
copy: '$.paths["/items"]'
309+
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'
310+
```
311+
312+
###### Result description
313+
314+
```yaml
315+
openapi: 3.1.0
316+
info:
317+
title: API with a paged collection
318+
version: 1.0.0
319+
paths:
320+
/items:
321+
get:
322+
responses:
323+
200:
324+
description: OK
325+
/some-items:
326+
get:
327+
responses:
328+
200:
329+
description: OK
330+
delete:
331+
responses:
332+
200:
333+
description: OK
334+
```
335+
336+
##### Ensure the target exists and copy
337+
338+
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.
339+
340+
###### Source description
341+
342+
```yaml
343+
openapi: 3.1.0
344+
info:
345+
title: API with a paged collection
346+
version: 1.0.0
347+
paths:
348+
/items:
349+
get:
350+
responses:
351+
200:
352+
description: OK
353+
/some-items:
354+
delete:
355+
responses:
356+
200:
357+
description: OK
358+
```
359+
360+
###### Overlay
361+
362+
```yaml
363+
overlay: 1.1.0
364+
info:
365+
title: Demonstrates variations of "copy" uses
366+
version: 1.0.0
367+
actions:
368+
- target: '$.paths'
369+
update: { "/other-items": {} }
370+
- target: '$.paths["/other-items"]'
371+
copy: '$.paths["/items"]'
372+
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'
373+
```
374+
375+
###### Result description
376+
377+
```yaml
378+
openapi: 3.1.0
379+
info:
380+
title: API with a paged collection
381+
version: 1.0.0
382+
paths:
383+
/items:
384+
get:
385+
responses:
386+
200:
387+
description: OK
388+
/other-items:
389+
get:
390+
responses:
391+
200:
392+
description: OK
393+
/some-items:
394+
delete:
395+
responses:
396+
200:
397+
description: OK
398+
```
399+
400+
##### Move example
401+
402+
This example shows how to rename the `items` path item to `new-items` using a sequence of overlay actions:
403+
404+
1. Use an `update` action to ensure the target path item exists.
405+
2. Use a `copy` action to copy the source path item to the target.
406+
3. Use a `remove` action to delete the original source path item.
407+
408+
###### Source description
409+
410+
```yaml
411+
openapi: 3.1.0
412+
info:
413+
title: API with a paged collection
414+
version: 1.0.0
415+
paths:
416+
/items:
417+
get:
418+
responses:
419+
200:
420+
description: OK
421+
/some-items:
422+
delete:
423+
responses:
424+
200:
425+
description: OK
426+
```
427+
428+
###### Overlay
429+
430+
```yaml
431+
overlay: 1.1.0
432+
info:
433+
title: Demonstrates variations of "copy" uses
434+
version: 1.0.0
435+
actions:
436+
- target: '$.paths'
437+
update: { "/new-items": {} }
438+
- target: '$.paths["/new-items"]'
439+
copy: '$.paths["/items"]'
440+
- target: '$.paths["/items"]'
441+
remove: true
442+
description: 'moves (renames) the "items" path item to "new-items"'
443+
```
444+
445+
###### Result description
446+
447+
```yaml
448+
openapi: 3.1.0
449+
info:
450+
title: API with a paged collection
451+
version: 1.0.0
452+
paths:
453+
/new-items:
454+
get:
455+
responses:
456+
200:
457+
description: OK
458+
/some-items:
459+
delete:
460+
responses:
461+
200:
462+
description: OK
463+
```
464+
268465
### Specification Extensions
269466

270467
While the Overlay Specification tries to accommodate most use cases, additional data can be added to extend the specification at certain points.

0 commit comments

Comments
 (0)