Skip to content

Commit b241c5c

Browse files
authored
fix: support overlay version 1.1.0 (#97)
* fix: support overlay version 1.1.0 * fix version.IsOneOf
1 parent ace098c commit b241c5c

File tree

6 files changed

+500
-5
lines changed

6 files changed

+500
-5
lines changed

internal/sliceutil/sliceutil.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package sliceutil
2+
3+
func Map[T any, U any](slice []T, fn func(T) U) []U {
4+
mapped := make([]U, len(slice))
5+
for i, elem := range slice {
6+
mapped[i] = fn(elem)
7+
}
8+
return mapped
9+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package sliceutil_test
2+
3+
import (
4+
"testing"
5+
6+
"github.com/speakeasy-api/openapi/internal/sliceutil"
7+
"github.com/stretchr/testify/assert"
8+
)
9+
10+
func TestMap(t *testing.T) {
11+
t.Parallel()
12+
tests := []struct {
13+
name string
14+
slice []int
15+
fn func(int) int
16+
expected []int
17+
}{
18+
{
19+
name: "empty slice",
20+
slice: []int{},
21+
fn: func(i int) int { return i },
22+
expected: []int{},
23+
},
24+
{
25+
name: "single element",
26+
slice: []int{1},
27+
fn: func(i int) int { return i },
28+
expected: []int{1},
29+
},
30+
{
31+
name: "multiple elements",
32+
slice: []int{1, 2, 3},
33+
fn: func(i int) int { return i },
34+
expected: []int{1, 2, 3},
35+
},
36+
}
37+
for _, tt := range tests {
38+
t.Run(tt.name, func(t *testing.T) {
39+
t.Parallel()
40+
result := sliceutil.Map(tt.slice, tt.fn)
41+
assert.Equal(t, tt.expected, result)
42+
})
43+
}
44+
}

internal/version/version.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,18 @@ func (v Version) LessThan(other Version) bool {
5050
return !v.Equal(other) && !v.GreaterThan(other)
5151
}
5252

53+
func (v Version) IsOneOf(versions []*Version) bool {
54+
for _, ver := range versions {
55+
if ver == nil {
56+
continue
57+
}
58+
if v.Equal(*ver) {
59+
return true
60+
}
61+
}
62+
return false
63+
}
64+
5365
func Parse(version string) (*Version, error) {
5466
parts := strings.Split(version, ".")
5567
if len(parts) != 3 {

internal/version/version_test.go

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,3 +137,94 @@ func Test_ParseVersion_Error(t *testing.T) {
137137
})
138138
}
139139
}
140+
141+
func Test_Version_IsOneOf(t *testing.T) {
142+
t.Parallel()
143+
tests := []struct {
144+
name string
145+
version Version
146+
versions []*Version
147+
expected bool
148+
}{
149+
{
150+
name: "version is in list",
151+
version: Version{Major: 1, Minor: 2, Patch: 3},
152+
versions: []*Version{
153+
{Major: 1, Minor: 0, Patch: 0},
154+
{Major: 1, Minor: 2, Patch: 3},
155+
{Major: 2, Minor: 0, Patch: 0},
156+
},
157+
expected: true,
158+
},
159+
{
160+
name: "version is not in list",
161+
version: Version{Major: 1, Minor: 2, Patch: 3},
162+
versions: []*Version{
163+
{Major: 1, Minor: 0, Patch: 0},
164+
{Major: 1, Minor: 2, Patch: 4},
165+
{Major: 2, Minor: 0, Patch: 0},
166+
},
167+
expected: false,
168+
},
169+
{
170+
name: "empty list",
171+
version: Version{Major: 1, Minor: 2, Patch: 3},
172+
versions: []*Version{},
173+
expected: false,
174+
},
175+
{
176+
name: "nil list",
177+
version: Version{Major: 1, Minor: 2, Patch: 3},
178+
versions: nil,
179+
expected: false,
180+
},
181+
{
182+
name: "list with nil values",
183+
version: Version{Major: 1, Minor: 2, Patch: 3},
184+
versions: []*Version{
185+
nil,
186+
{Major: 1, Minor: 2, Patch: 3},
187+
nil,
188+
},
189+
expected: true,
190+
},
191+
{
192+
name: "version is first in list",
193+
version: Version{Major: 1, Minor: 0, Patch: 0},
194+
versions: []*Version{
195+
{Major: 1, Minor: 0, Patch: 0},
196+
{Major: 1, Minor: 2, Patch: 3},
197+
{Major: 2, Minor: 0, Patch: 0},
198+
},
199+
expected: true,
200+
},
201+
{
202+
name: "version is last in list",
203+
version: Version{Major: 2, Minor: 0, Patch: 0},
204+
versions: []*Version{
205+
{Major: 1, Minor: 0, Patch: 0},
206+
{Major: 1, Minor: 2, Patch: 3},
207+
{Major: 2, Minor: 0, Patch: 0},
208+
},
209+
expected: true,
210+
},
211+
{
212+
name: "similar but different versions",
213+
version: Version{Major: 1, Minor: 2, Patch: 3},
214+
versions: []*Version{
215+
{Major: 1, Minor: 2, Patch: 2},
216+
{Major: 1, Minor: 2, Patch: 4},
217+
{Major: 1, Minor: 3, Patch: 3},
218+
},
219+
expected: false,
220+
},
221+
}
222+
223+
for _, tt := range tests {
224+
t.Run(tt.name, func(t *testing.T) {
225+
t.Parallel()
226+
result := tt.version.IsOneOf(tt.versions)
227+
assert.Equal(t, tt.expected, result)
228+
})
229+
}
230+
}

overlay/validate.go

Lines changed: 38 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,26 @@ import (
55
"fmt"
66
"net/url"
77
"strings"
8+
9+
"github.com/speakeasy-api/openapi/internal/sliceutil"
10+
"github.com/speakeasy-api/openapi/internal/version"
11+
)
12+
13+
var (
14+
SupportedVersions = []*version.Version{version.MustParse("1.0.0"), version.MustParse("1.1.0")}
15+
)
16+
17+
// Errors
18+
var (
19+
ErrOverlayVersionInvalid = errors.New("overlay version is invalid")
20+
ErrOverlayVersionNotSupported = fmt.Errorf("overlay version must be one of: %s", strings.Join(sliceutil.Map(SupportedVersions, func(v *version.Version) string { return v.String() }), ", "))
21+
ErrOverlayVersionMustBeDefined = errors.New("overlay version must be defined")
22+
ErrOverlayInfoTitleMustBeDefined = errors.New("overlay info title must be defined")
23+
ErrOverlayInfoVersionMustBeDefined = errors.New("overlay info version must be defined")
24+
ErrOverlayExtendsMustBeAValidURL = errors.New("overlay extends must be a valid URL")
25+
ErrOverlayMustDefineAtLeastOneAction = errors.New("overlay must define at least one action")
26+
ErrOverlayActionTargetMustBeDefined = errors.New("overlay action target must be defined")
27+
ErrOverlayActionRemoveAndUpdateCannotBeSet = errors.New("overlay action remove and update cannot be set")
828
)
929

1030
type ValidationErrors []error
@@ -24,18 +44,31 @@ func (v ValidationErrors) Return() error {
2444
return nil
2545
}
2646

47+
func (o *Overlay) ValidateVersion() []error {
48+
errs := make(ValidationErrors, 0)
49+
overlayVersion, err := version.Parse(o.Version)
50+
switch {
51+
case err != nil || overlayVersion == nil:
52+
errs = append(errs, ErrOverlayVersionInvalid)
53+
case !overlayVersion.IsOneOf(SupportedVersions):
54+
errs = append(errs, ErrOverlayVersionNotSupported)
55+
}
56+
57+
return errs
58+
}
59+
2760
func (o *Overlay) Validate() error {
2861
errs := make(ValidationErrors, 0)
29-
if o.Version != "1.0.0" {
30-
errs = append(errs, errors.New("overlay version must be 1.0.0"))
62+
63+
errs = append(errs, o.ValidateVersion()...)
64+
65+
if o.Info.Version == "" {
66+
errs = append(errs, errors.New("overlay info version must be defined"))
3167
}
3268

3369
if o.Info.Title == "" {
3470
errs = append(errs, errors.New("overlay info title must be defined"))
3571
}
36-
if o.Info.Version == "" {
37-
errs = append(errs, errors.New("overlay info version must be defined"))
38-
}
3972

4073
if o.Extends != "" {
4174
_, err := url.Parse(o.Extends)

0 commit comments

Comments
 (0)