Skip to content

Commit 5923067

Browse files
authored
feat: support for copy operators in playground, a few overlay 1.1 examples, and a better "compare" command. (#25)
* feat: support for overlay 1.1 * chore: now we are on 1.1, x-speakeasy-jsonpath not necessary * chore: support sequences in quick-pass-through * chore: regen wasm
1 parent 85d5832 commit 5923067

7 files changed

Lines changed: 30 additions & 30 deletions

File tree

cmd/wasm/functions.go

Lines changed: 12 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import (
1010

1111
"github.com/speakeasy-api/jsonpath/pkg/jsonpath"
1212
"github.com/speakeasy-api/jsonpath/pkg/jsonpath/config"
13-
"github.com/speakeasy-api/jsonpath/pkg/jsonpath/token"
1413
"github.com/speakeasy-api/openapi/overlay"
1514
"gopkg.in/yaml.v3"
1615
)
@@ -34,7 +33,6 @@ func CalculateOverlay(originalYAML, targetYAML, existingOverlay string) (string,
3433
if err != nil {
3534
return "", fmt.Errorf("failed to parse overlay schema in CalculateOverlay: %w", err)
3635
}
37-
existingOverlayDocument.JSONPathVersion = "rfc9535" // force this in the playground.
3836
// now modify the original using the existing overlay
3937
err = existingOverlayDocument.ApplyTo(&orig)
4038
if err != nil {
@@ -46,8 +44,16 @@ func CalculateOverlay(originalYAML, targetYAML, existingOverlay string) (string,
4644
return "", fmt.Errorf("failed to compare schemas: %w", err)
4745
}
4846
// special case, is there only one action and it targets the same as the last overlayDocument.Actions item entry, we'll just replace it.
49-
if len(newOverlay.Actions) == 1 && len(existingOverlayDocument.Actions) > 0 && newOverlay.Actions[0].Target == existingOverlayDocument.Actions[len(existingOverlayDocument.Actions)-1].Target {
50-
existingOverlayDocument.Actions[len(existingOverlayDocument.Actions)-1] = newOverlay.Actions[0]
47+
lastAction := len(existingOverlayDocument.Actions) - 1
48+
if len(newOverlay.Actions) == 1 && lastAction >= 0 && newOverlay.Actions[0].Target == existingOverlayDocument.Actions[lastAction].Target {
49+
prev := &existingOverlayDocument.Actions[lastAction]
50+
next := &newOverlay.Actions[0]
51+
// If both are sequence updates, concatenate content rather than replacing
52+
if prev.Update.Kind == yaml.SequenceNode && next.Update.Kind == yaml.SequenceNode {
53+
prev.Update.Content = append(prev.Update.Content, next.Update.Content...)
54+
} else {
55+
existingOverlayDocument.Actions[lastAction] = *next
56+
}
5157
} else {
5258
// Otherwise, we'll just append the new overlay to the existing overlay
5359
existingOverlayDocument.Actions = append(existingOverlayDocument.Actions, newOverlay.Actions...)
@@ -115,16 +121,8 @@ func ApplyOverlay(originalYAML, overlayYAML string) (string, error) {
115121
if err != nil {
116122
return "", fmt.Errorf("failed to validate overlay schema in ApplyOverlay: %w", err)
117123
}
118-
hasFilterExpression := false
119-
// check to see if we have an overlay with an error, or a partial overlay: i.e. any overlay actions are missing an update or remove
124+
// If an action has a valid target but no operation (update, remove, or copy), return query results for the target path (explorer mode).
120125
for i, action := range overlay.Actions {
121-
tokenized := token.NewTokenizer(action.Target, config.WithPropertyNameExtension()).Tokenize()
122-
for _, tok := range tokenized {
123-
if tok.Token == token.FILTER {
124-
hasFilterExpression = true
125-
break
126-
}
127-
}
128126
parsed, pathErr := jsonpath.NewPath(action.Target, config.WithPropertyNameExtension())
129127

130128
var node *yaml.Node
@@ -136,7 +134,7 @@ func ApplyOverlay(originalYAML, overlayYAML string) (string, error) {
136134

137135
return applyOverlayJSONPathError(pathErr, node)
138136
}
139-
if reflect.ValueOf(action.Update).IsZero() && action.Remove == false {
137+
if reflect.ValueOf(action.Update).IsZero() && !action.Remove && action.Copy == "" {
140138
result := parsed.Query(&orig)
141139

142140
node, err = lookupOverlayActionTargetNode(overlayYAML, i)
@@ -147,10 +145,6 @@ func ApplyOverlay(originalYAML, overlayYAML string) (string, error) {
147145
return applyOverlayJSONPathIncomplete(result, node)
148146
}
149147
}
150-
if hasFilterExpression && overlay.JSONPathVersion != "rfc9535" {
151-
return "", fmt.Errorf("invalid overlay schema: must have `x-speakeasy-jsonpath: rfc9535`")
152-
}
153-
154148
err = overlay.ApplyTo(&orig)
155149
if err != nil {
156150
return "", fmt.Errorf("failed to apply overlay: %w", err)

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ go 1.24.3
44

55
require (
66
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2
7-
github.com/speakeasy-api/openapi v1.16.2
7+
github.com/speakeasy-api/openapi v1.18.1
88
github.com/stretchr/testify v1.11.1
99
gopkg.in/yaml.v3 v3.0.1
1010
)

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@ github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR
2828
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
2929
github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=
3030
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
31-
github.com/speakeasy-api/openapi v1.16.2 h1:ntN57Z4isk3jfckYf7L957/2JtZazpfm8qg76pPlpR0=
32-
github.com/speakeasy-api/openapi v1.16.2/go.mod h1:aiVj+JnirrwZDtKegt0hQrj/ixl3v17EkN2YGnTuSro=
31+
github.com/speakeasy-api/openapi v1.18.1 h1:re8tzO8u5U8q33z9mm1UiuiGo9fLrHJgk238WKYdIZM=
32+
github.com/speakeasy-api/openapi v1.18.1/go.mod h1:aiVj+JnirrwZDtKegt0hQrj/ixl3v17EkN2YGnTuSro=
3333
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
3434
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
3535
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=

pkg/jsonpath/jsonpath.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ func NewPath(input string, opts ...config.Option) (*JSONPath, error) {
1212
tokens := tokenizer.Tokenize()
1313
for i := 0; i < len(tokens); i++ {
1414
if tokens[i].Token == token.ILLEGAL {
15-
return nil, fmt.Errorf(tokenizer.ErrorString(&tokens[i], "unexpected token"))
15+
return nil, fmt.Errorf("%s", tokenizer.ErrorString(&tokens[i], "unexpected token"))
1616
}
1717
}
1818
parser := newParserPrivate(tokenizer, tokens, opts...)

pkg/jsonpath/token/token_test.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -610,12 +610,12 @@ func TestTokenizer_categorize(t *testing.T) {
610610
if token.Token == ILLEGAL {
611611
foundIllegal = true
612612
if !tc.illegal {
613-
t.Errorf(tokenizer.ErrorString(&token, "Illegal Token"))
613+
t.Errorf("%s", tokenizer.ErrorString(&token, "Illegal Token"))
614614
}
615615
}
616616
}
617617
if tc.illegal && !foundIllegal {
618-
t.Errorf(tokenizer.ErrorTokenString(&tokenizedJsonPath[0], "Expected an illegal token"))
618+
t.Errorf("%s", tokenizer.ErrorTokenString(&tokenizedJsonPath[0], "Expected an illegal token"))
619619
}
620620

621621
if tc.simple && foundIllegal {
@@ -632,12 +632,12 @@ func TestTokenizer_categorize(t *testing.T) {
632632
}
633633
}
634634
if !simple {
635-
t.Errorf(tokenizer.ErrorString(&token, "Expected a simple path, but found a non-simple token"))
635+
t.Errorf("%s", tokenizer.ErrorString(&token, "Expected a simple path, but found a non-simple token"))
636636
}
637637
}
638638
}
639639
if !tc.simple && tokenizedJsonPath.IsSimple() {
640-
t.Errorf(tokenizer.ErrorTokenString(&tokenizedJsonPath[0], "Expected a non-simple path, but found it was simple"))
640+
t.Errorf("%s", tokenizer.ErrorTokenString(&tokenizedJsonPath[0], "Expected a non-simple path, but found it was simple"))
641641
}
642642
})
643643
}

web/src/assets/wasm/lib.wasm

-3.42 KB
Binary file not shown.

web/src/defaults.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -817,16 +817,22 @@ components:
817817
`;
818818

819819
export const blankOverlay = `overlay: 1.1.0
820-
x-speakeasy-jsonpath: rfc9535
821820
info:
822821
title: example overlay
823822
version: 0.0.0
824-
actions:
823+
actions:
825824
- target: $.info.description
826-
update: Hello World`;
825+
description: Update the API description
826+
update: Hello World
827+
- target: $.components.schemas
828+
description: Create an empty schema to copy into
829+
update:
830+
PetSummary: {}
831+
- target: $.components.schemas.PetSummary
832+
description: Copy the Pet schema into PetSummary
833+
copy: $.components.schemas.Pet`;
827834

828835
export const emptyOverlay = `overlay: 1.1.0
829-
x-speakeasy-jsonpath: rfc9535
830836
info:
831837
title: example overlay
832838
version: 0.0.0

0 commit comments

Comments
 (0)