Skip to content

Commit 6bac51a

Browse files
committed
feat: Public methods now return MultiError instead of []error
1 parent 06f6b24 commit 6bac51a

7 files changed

+299
-170
lines changed

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1-
test-operation.yaml
1+
test-operation.yaml
2+
.idea/

document.go

Lines changed: 53 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
package libopenapi
1515

1616
import (
17-
"errors"
1817
"fmt"
1918

2019
"github.com/pb33f/libopenapi/index"
@@ -48,13 +47,13 @@ type Document interface {
4847
// If there are any issues, then no model will be returned, instead a slice of errors will explain all the
4948
// problems that occurred. This method will only support version 2 specifications and will throw an error for
5049
// any other types.
51-
BuildV2Model() (*DocumentModel[v2high.Swagger], []error)
50+
BuildV2Model() (*DocumentModel[v2high.Swagger], error)
5251

5352
// BuildV3Model will build out an OpenAPI (version 3+) model from the specification used to create the document
5453
// If there are any issues, then no model will be returned, instead a slice of errors will explain all the
5554
// problems that occurred. This method will only support version 3 specifications and will throw an error for
5655
// any other types.
57-
BuildV3Model() (*DocumentModel[v3high.Document], []error)
56+
BuildV3Model() (*DocumentModel[v3high.Document], error)
5857

5958
// RenderAndReload will render the high level model as it currently exists (including any mutations, additions
6059
// and removals to and from any object in the tree). It will then reload the low level model with the new bytes
@@ -70,7 +69,7 @@ type Document interface {
7069
// **IMPORTANT** This method only supports OpenAPI Documents. The Swagger model will not support mutations correctly
7170
// and will not update when called. This choice has been made because we don't want to continue supporting Swagger,
7271
// it's too old, so it should be motivation to upgrade to OpenAPI 3.
73-
RenderAndReload() ([]byte, Document, *DocumentModel[v3high.Document], []error)
72+
RenderAndReload() ([]byte, Document, *DocumentModel[v3high.Document], error)
7473

7574
// Serialize will re-render a Document back into a []byte slice. If any modifications have been made to the
7675
// underlying data model using low level APIs, then those changes will be reflected in the serialized output.
@@ -155,41 +154,41 @@ func (d *document) Serialize() ([]byte, error) {
155154
return utils.ConvertYAMLtoJSON(yamlData)
156155
}
157156
}
157+
//func (d *document) RenderAndReload() ([]byte, Document, *DocumentModel[v3high.Document], []error) {
158+
// return nil, nil, nil, nil
159+
//}
158160

159-
func (d *document) RenderAndReload() ([]byte, Document, *DocumentModel[v3high.Document], []error) {
161+
func (d *document) RenderAndReload() ([]byte, Document, *DocumentModel[v3high.Document], error) {
160162
if d.highSwaggerModel != nil && d.highOpenAPI3Model == nil {
161-
return nil, nil, nil, []error{errors.New("this method only supports OpenAPI 3 documents, not Swagger")}
163+
return nil, nil, nil, errorMsg("this method only supports OpenAPI 3 documents, not Swagger")
162164
}
163165
newBytes, err := d.highOpenAPI3Model.Model.Render()
164166
if err != nil {
165-
return newBytes, nil, nil, []error{err}
167+
return newBytes, nil, nil, wrapErr(err)
166168
}
167169
newDoc, err := NewDocumentWithConfiguration(newBytes, d.config)
168170
if err != nil {
169-
return newBytes, newDoc, nil, []error{err}
171+
return newBytes, newDoc, nil, wrapErr(err)
170172
}
171173
// build the model.
172-
model, errs := newDoc.BuildV3Model()
173-
if errs != nil {
174-
return newBytes, newDoc, model, errs
174+
model, err := newDoc.BuildV3Model()
175+
if err != nil {
176+
return newBytes, newDoc, model, wrapErr(err)
175177
}
176178
// this document is now dead, long live the new document!
177179
return newBytes, newDoc, model, nil
178180
}
179181

180-
func (d *document) BuildV2Model() (*DocumentModel[v2high.Swagger], []error) {
182+
func (d *document) BuildV2Model() (*DocumentModel[v2high.Swagger], error) {
181183
if d.highSwaggerModel != nil {
182184
return d.highSwaggerModel, nil
183185
}
184-
var errors []error
185186
if d.info == nil {
186-
errors = append(errors, fmt.Errorf("unable to build swagger document, no specification has been loaded"))
187-
return nil, errors
187+
return nil, errorMsg("unable to build swagger document, no specification has been loaded")
188188
}
189189
if d.info.SpecFormat != datamodel.OAS2 {
190-
errors = append(errors, fmt.Errorf("unable to build swagger document, "+
191-
"supplied spec is a different version (%v). Try 'BuildV3Model()'", d.info.SpecFormat))
192-
return nil, errors
190+
return nil, errorMsgf("unable to build swagger document, "+
191+
"supplied spec is a different version (%v). Try 'BuildV3Model()'", d.info.SpecFormat)
193192
}
194193

195194
var lowDoc *v2low.Swagger
@@ -200,39 +199,36 @@ func (d *document) BuildV2Model() (*DocumentModel[v2high.Swagger], []error) {
200199
}
201200
}
202201

203-
lowDoc, errors = v2low.CreateDocumentFromConfig(d.info, d.config)
202+
lowDoc, errs := v2low.CreateDocumentFromConfig(d.info, d.config)
204203
// Do not short-circuit on circular reference errors, so the client
205204
// has the option of ignoring them.
206-
for _, err := range errors {
205+
for _, err := range errs {
207206
if refErr, ok := err.(*resolver.ResolvingError); ok {
208207
if refErr.CircularReference == nil {
209-
return nil, errors
208+
return nil, wrapErrs(errs)
210209
}
211210
} else {
212-
return nil, errors
211+
return nil, wrapErrs(errs)
213212
}
214213
}
215214
highDoc := v2high.NewSwaggerDocument(lowDoc)
216215
d.highSwaggerModel = &DocumentModel[v2high.Swagger]{
217216
Model: *highDoc,
218217
Index: lowDoc.Index,
219218
}
220-
return d.highSwaggerModel, errors
219+
return d.highSwaggerModel, wrapErrs(errs)
221220
}
222221

223-
func (d *document) BuildV3Model() (*DocumentModel[v3high.Document], []error) {
222+
func (d *document) BuildV3Model() (*DocumentModel[v3high.Document], error) {
224223
if d.highOpenAPI3Model != nil {
225224
return d.highOpenAPI3Model, nil
226225
}
227-
var errors []error
228226
if d.info == nil {
229-
errors = append(errors, fmt.Errorf("unable to build document, no specification has been loaded"))
230-
return nil, errors
227+
return nil, errorMsg("unable to build document, no specification has been loaded")
231228
}
232229
if d.info.SpecFormat != datamodel.OAS3 {
233-
errors = append(errors, fmt.Errorf("unable to build openapi document, "+
234-
"supplied spec is a different version (%v). Try 'BuildV2Model()'", d.info.SpecFormat))
235-
return nil, errors
230+
return nil, errorMsgf("unable to build openapi document, "+
231+
"supplied spec is a different version (%v). Try 'BuildV2Model()'", d.info.SpecFormat)
236232
}
237233

238234
var lowDoc *v3low.Document
@@ -243,24 +239,24 @@ func (d *document) BuildV3Model() (*DocumentModel[v3high.Document], []error) {
243239
}
244240
}
245241

246-
lowDoc, errors = v3low.CreateDocumentFromConfig(d.info, d.config)
242+
lowDoc, errs := v3low.CreateDocumentFromConfig(d.info, d.config)
247243
// Do not short-circuit on circular reference errors, so the client
248244
// has the option of ignoring them.
249-
for _, err := range errors {
245+
for _, err := range errs {
250246
if refErr, ok := err.(*resolver.ResolvingError); ok {
251247
if refErr.CircularReference == nil {
252-
return nil, errors
248+
return nil, wrapErrs(errs)
253249
}
254250
} else {
255-
return nil, errors
251+
return nil, wrapErrs(errs)
256252
}
257253
}
258254
highDoc := v3high.NewDocument(lowDoc)
259255
d.highOpenAPI3Model = &DocumentModel[v3high.Document]{
260256
Model: *highDoc,
261257
Index: lowDoc.Index,
262258
}
263-
return d.highOpenAPI3Model, errors
259+
return d.highOpenAPI3Model, wrapErrs(errs)
264260
}
265261

266262
// CompareDocuments will accept a left and right Document implementing struct, build a model for the correct
@@ -269,37 +265,40 @@ func (d *document) BuildV3Model() (*DocumentModel[v3high.Document], []error) {
269265
// If there are any errors when building the models, those errors are returned with a nil pointer for the
270266
// model.DocumentChanges. If there are any changes found however between either Document, then a pointer to
271267
// model.DocumentChanges is returned containing every single change, broken down, model by model.
272-
func CompareDocuments(original, updated Document) (*model.DocumentChanges, []error) {
273-
var errors []error
268+
func CompareDocuments(original, updated Document) (*model.DocumentChanges, error) {
269+
errs := &MultiError{}
274270
if original.GetSpecInfo().SpecType == utils.OpenApi3 && updated.GetSpecInfo().SpecType == utils.OpenApi3 {
275-
v3ModelLeft, errs := original.BuildV3Model()
276-
if len(errs) > 0 {
277-
errors = errs
271+
v3ModelLeft, err := original.BuildV3Model()
272+
if err != nil {
273+
errs.Append(err)
278274
}
279-
v3ModelRight, errs := updated.BuildV3Model()
280-
if len(errs) > 0 {
281-
errors = append(errors, errs...)
275+
v3ModelRight, err := updated.BuildV3Model()
276+
if err != nil {
277+
errs.Append(err)
282278
}
283279
if v3ModelLeft != nil && v3ModelRight != nil {
284-
return what_changed.CompareOpenAPIDocuments(v3ModelLeft.Model.GoLow(), v3ModelRight.Model.GoLow()), errors
280+
return what_changed.CompareOpenAPIDocuments(v3ModelLeft.Model.GoLow(), v3ModelRight.Model.GoLow()),
281+
errs.OrNil()
285282
} else {
286-
return nil, errors
283+
return nil, errs.OrNil()
287284
}
288285
}
289286
if original.GetSpecInfo().SpecType == utils.OpenApi2 && updated.GetSpecInfo().SpecType == utils.OpenApi2 {
290-
v2ModelLeft, errs := original.BuildV2Model()
291-
if len(errs) > 0 {
292-
errors = errs
287+
errs := &MultiError{}
288+
v2ModelLeft, err := original.BuildV2Model()
289+
if err != nil {
290+
errs.Append(err)
293291
}
294-
v2ModelRight, errs := updated.BuildV2Model()
295-
if len(errs) > 0 {
296-
errors = append(errors, errs...)
292+
v2ModelRight, err := updated.BuildV2Model()
293+
if err != nil {
294+
errs.Append(err)
297295
}
298296
if v2ModelLeft != nil && v2ModelRight != nil {
299-
return what_changed.CompareSwaggerDocuments(v2ModelLeft.Model.GoLow(), v2ModelRight.Model.GoLow()), errors
297+
return what_changed.CompareSwaggerDocuments(v2ModelLeft.Model.GoLow(), v2ModelRight.Model.GoLow()),
298+
errs.OrNil()
300299
} else {
301-
return nil, errors
300+
return nil, errs.OrNil()
302301
}
303302
}
304-
return nil, []error{fmt.Errorf("unable to compare documents, one or both documents are not of the same version")}
303+
return nil, errorMsg("unable to compare documents, one or both documents are not of the same version")
305304
}

0 commit comments

Comments
 (0)