Skip to content

Commit 1046dca

Browse files
refactor: add helper methods for creating validation errors to remove boilerplate (#13)
1 parent bfc75bc commit 1046dca

17 files changed

+220
-501
lines changed

arazzo/arazzo.go

Lines changed: 4 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -158,19 +158,11 @@ func (a *Arazzo) Validate(ctx context.Context, opts ...validation.Option) []erro
158158

159159
arazzoMajor, arazzoMinor, arazzoPatch, err := parseVersion(a.Arazzo)
160160
if err != nil {
161-
errs = append(errs, &validation.Error{
162-
Message: fmt.Sprintf("invalid Arazzo version in document %s: %s", a.Arazzo, err.Error()),
163-
Line: a.core.Arazzo.GetValueNodeOrRoot(a.core.RootNode).Line,
164-
Column: a.core.Arazzo.GetValueNodeOrRoot(a.core.RootNode).Column,
165-
})
161+
errs = append(errs, validation.NewValueError(fmt.Sprintf("invalid Arazzo version in document %s: %s", a.Arazzo, err.Error()), a.core, a.core.Arazzo))
166162
}
167163

168164
if arazzoMajor != VersionMajor || arazzoMinor != VersionMinor || arazzoPatch > VersionPatch {
169-
errs = append(errs, &validation.Error{
170-
Message: fmt.Sprintf("Only Arazzo version %s and below is supported", Version),
171-
Line: a.core.Arazzo.GetValueNodeOrRoot(a.core.RootNode).Line,
172-
Column: a.core.Arazzo.GetValueNodeOrRoot(a.core.RootNode).Column,
173-
})
165+
errs = append(errs, validation.NewValueError(fmt.Sprintf("only Arazzo version %s and below is supported", Version), a.core, a.core.Arazzo))
174166
}
175167

176168
errs = append(errs, a.Info.Validate(ctx, opts...)...)
@@ -181,11 +173,7 @@ func (a *Arazzo) Validate(ctx context.Context, opts ...validation.Option) []erro
181173
errs = append(errs, sourceDescription.Validate(ctx, opts...)...)
182174

183175
if _, ok := sourceDescriptionNames[sourceDescription.Name]; ok {
184-
errs = append(errs, &validation.Error{
185-
Message: fmt.Sprintf("sourceDescription name %s is not unique", sourceDescription.Name),
186-
Line: a.core.SourceDescriptions.GetSliceValueNodeOrRoot(i, a.core.RootNode).Line,
187-
Column: a.core.SourceDescriptions.GetSliceValueNodeOrRoot(i, a.core.RootNode).Column,
188-
})
176+
errs = append(errs, validation.NewSliceError(fmt.Sprintf("sourceDescription name %s is not unique", sourceDescription.Name), a.core, a.core.SourceDescriptions, i))
189177
}
190178

191179
sourceDescriptionNames[sourceDescription.Name] = true
@@ -197,11 +185,7 @@ func (a *Arazzo) Validate(ctx context.Context, opts ...validation.Option) []erro
197185
errs = append(errs, workflow.Validate(ctx, opts...)...)
198186

199187
if _, ok := workflowIds[workflow.WorkflowID]; ok {
200-
errs = append(errs, &validation.Error{
201-
Message: fmt.Sprintf("workflowId %s is not unique", workflow.WorkflowID),
202-
Line: a.core.Workflows.GetSliceValueNodeOrRoot(i, a.core.RootNode).Line,
203-
Column: a.core.Workflows.GetSliceValueNodeOrRoot(i, a.core.RootNode).Column,
204-
})
188+
errs = append(errs, validation.NewSliceError(fmt.Sprintf("workflowId %s is not unique", workflow.WorkflowID), a.core, a.core.Workflows, i))
205189
}
206190

207191
workflowIds[workflow.WorkflowID] = true

arazzo/arazzo_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,7 @@ sourceDescriptions:
254254

255255
assert.Equal(t, []error{
256256
&validation.Error{Line: 1, Column: 1, Message: "field workflows is missing"},
257-
&validation.Error{Line: 1, Column: 9, Message: "Only Arazzo version 1.0.1 and below is supported"},
257+
&validation.Error{Line: 1, Column: 9, Message: "only Arazzo version 1.0.1 and below is supported"},
258258
&validation.Error{Line: 4, Column: 3, Message: "field version is missing"},
259259
&validation.Error{Line: 6, Column: 5, Message: "field url is missing"},
260260
&validation.Error{Line: 7, Column: 11, Message: "type must be one of [openapi, arazzo]"},

arazzo/components.go

Lines changed: 4 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -52,11 +52,7 @@ func (c *Components) Validate(ctx context.Context, opts ...validation.Option) []
5252

5353
for key, input := range c.Inputs.All() {
5454
if !componentNameRegex.MatchString(key) {
55-
errs = append(errs, &validation.Error{
56-
Message: fmt.Sprintf("input key must be a valid key [%s]: %s", componentNameRegex.String(), key),
57-
Line: c.core.Inputs.GetMapKeyNodeOrRoot(key, c.core.RootNode).Line,
58-
Column: c.core.Inputs.GetMapKeyNodeOrRoot(key, c.core.RootNode).Column,
59-
})
55+
errs = append(errs, validation.NewMapKeyError(fmt.Sprintf("input key must be a valid key [%s]: %s", componentNameRegex.String(), key), c.core, c.core.Inputs, key))
6056
}
6157

6258
if input.IsLeft() {
@@ -68,11 +64,7 @@ func (c *Components) Validate(ctx context.Context, opts ...validation.Option) []
6864

6965
for key, parameter := range c.Parameters.All() {
7066
if !componentNameRegex.MatchString(key) {
71-
errs = append(errs, &validation.Error{
72-
Message: fmt.Sprintf("parameter key must be a valid key [%s]: %s", componentNameRegex.String(), key),
73-
Line: c.core.Parameters.GetMapKeyNodeOrRoot(key, c.core.RootNode).Line,
74-
Column: c.core.Parameters.GetMapKeyNodeOrRoot(key, c.core.RootNode).Column,
75-
})
67+
errs = append(errs, validation.NewMapKeyError(fmt.Sprintf("parameter key must be a valid key [%s]: %s", componentNameRegex.String(), key), c.core, c.core.Parameters, key))
7668
}
7769

7870
paramOps := append(opts, validation.WithContextObject(&componentKey{name: key}))
@@ -82,11 +74,7 @@ func (c *Components) Validate(ctx context.Context, opts ...validation.Option) []
8274

8375
for key, successAction := range c.SuccessActions.All() {
8476
if !componentNameRegex.MatchString(key) {
85-
errs = append(errs, &validation.Error{
86-
Message: fmt.Sprintf("successAction key must be a valid key [%s]: %s", componentNameRegex.String(), key),
87-
Line: c.core.SuccessActions.GetMapKeyNodeOrRoot(key, c.core.RootNode).Line,
88-
Column: c.core.SuccessActions.GetMapKeyNodeOrRoot(key, c.core.RootNode).Column,
89-
})
77+
errs = append(errs, validation.NewMapKeyError(fmt.Sprintf("successAction key must be a valid key [%s]: %s", componentNameRegex.String(), key), c.core, c.core.SuccessActions, key))
9078
}
9179

9280
successActionOps := append(opts, validation.WithContextObject(&componentKey{name: key}))
@@ -96,11 +84,7 @@ func (c *Components) Validate(ctx context.Context, opts ...validation.Option) []
9684

9785
for key, failureAction := range c.FailureActions.All() {
9886
if !componentNameRegex.MatchString(key) {
99-
errs = append(errs, &validation.Error{
100-
Message: fmt.Sprintf("failureAction key must be a valid key [%s]: %s", componentNameRegex.String(), key),
101-
Line: c.core.FailureActions.GetMapKeyNodeOrRoot(key, c.core.RootNode).Line,
102-
Column: c.core.FailureActions.GetMapKeyNodeOrRoot(key, c.core.RootNode).Column,
103-
})
87+
errs = append(errs, validation.NewMapKeyError(fmt.Sprintf("failureAction key must be a valid key [%s]: %s", componentNameRegex.String(), key), c.core, c.core.FailureActions, key))
10488
}
10589

10690
failureActionOps := append(opts, validation.WithContextObject(&componentKey{name: key}))

arazzo/criterion/criterion.go

Lines changed: 10 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -67,30 +67,18 @@ func (c *CriterionExpressionType) Validate(opts ...validation.Option) []error {
6767
switch c.Version {
6868
case CriterionTypeVersionDraftGoesnerDispatchJsonPath00:
6969
default:
70-
errs = append(errs, &validation.Error{
71-
Message: fmt.Sprintf("version must be one of [%s]", strings.Join([]string{string(CriterionTypeVersionDraftGoesnerDispatchJsonPath00)}, ", ")),
72-
Line: c.core.Type.GetValueNodeOrRoot(c.core.RootNode).Line,
73-
Column: c.core.Type.GetValueNodeOrRoot(c.core.RootNode).Column,
74-
})
70+
errs = append(errs, validation.NewValueError(fmt.Sprintf("version must be one of [%s]", strings.Join([]string{string(CriterionTypeVersionDraftGoesnerDispatchJsonPath00)}, ", ")), c.core, c.core.Type))
7571
}
7672
case CriterionTypeXPath:
7773
switch c.Version {
7874
case CriterionTypeVersionXPath30:
7975
case CriterionTypeVersionXPath20:
8076
case CriterionTypeVersionXPath10:
8177
default:
82-
errs = append(errs, &validation.Error{
83-
Message: fmt.Sprintf("version must be one of [%s]", strings.Join([]string{string(CriterionTypeVersionXPath30), string(CriterionTypeVersionXPath20), string(CriterionTypeVersionXPath10)}, ", ")),
84-
Line: c.core.Type.GetValueNodeOrRoot(c.core.RootNode).Line,
85-
Column: c.core.Type.GetValueNodeOrRoot(c.core.RootNode).Column,
86-
})
78+
errs = append(errs, validation.NewValueError(fmt.Sprintf("version must be one of [%s]", strings.Join([]string{string(CriterionTypeVersionXPath30), string(CriterionTypeVersionXPath20), string(CriterionTypeVersionXPath10)}, ", ")), c.core, c.core.Type))
8779
}
8880
default:
89-
errs = append(errs, &validation.Error{
90-
Message: fmt.Sprintf("type must be one of [%s]", strings.Join([]string{string(CriterionTypeJsonPath), string(CriterionTypeXPath)}, ", ")),
91-
Line: c.core.Type.GetValueNodeOrRoot(c.core.RootNode).Line,
92-
Column: c.core.Type.GetValueNodeOrRoot(c.core.RootNode).Column,
93-
})
81+
errs = append(errs, validation.NewValueError(fmt.Sprintf("type must be one of [%s]", strings.Join([]string{string(CriterionTypeJsonPath), string(CriterionTypeXPath)}, ", ")), c.core, c.core.Type))
9482
}
9583

9684
if len(errs) == 0 {
@@ -218,11 +206,7 @@ func (c *Criterion) Validate(opts ...validation.Option) []error {
218206
errs := []error{}
219207

220208
if c.Condition == "" {
221-
errs = append(errs, &validation.Error{
222-
Message: "condition is required",
223-
Line: c.core.Condition.GetValueNodeOrRoot(c.core.RootNode).Line,
224-
Column: c.core.Condition.GetValueNodeOrRoot(c.core.RootNode).Column,
225-
})
209+
errs = append(errs, validation.NewValueError("condition is required", c.core, c.core.Condition))
226210
}
227211

228212
if c.Type.Type != nil {
@@ -232,31 +216,19 @@ func (c *Criterion) Validate(opts ...validation.Option) []error {
232216
case CriterionTypeJsonPath:
233217
case CriterionTypeXPath:
234218
default:
235-
errs = append(errs, &validation.Error{
236-
Message: fmt.Sprintf("type must be one of [%s]", strings.Join([]string{string(CriterionTypeSimple), string(CriterionTypeRegex), string(CriterionTypeJsonPath), string(CriterionTypeXPath)}, ", ")),
237-
Line: c.core.Type.GetValueNodeOrRoot(c.core.RootNode).Line,
238-
Column: c.core.Type.GetValueNodeOrRoot(c.core.RootNode).Column,
239-
})
219+
errs = append(errs, validation.NewValueError(fmt.Sprintf("type must be one of [%s]", strings.Join([]string{string(CriterionTypeSimple), string(CriterionTypeRegex), string(CriterionTypeJsonPath), string(CriterionTypeXPath)}, ", ")), c.core, c.core.Type))
240220
}
241221
} else if c.Type.ExpressionType != nil {
242222
errs = append(errs, c.Type.ExpressionType.Validate(opts...)...)
243223
}
244224

245225
if c.Type.IsTypeProvided() && c.Context == nil {
246-
errs = append(errs, &validation.Error{
247-
Message: "context is required, if type is set",
248-
Line: c.core.Context.GetKeyNodeOrRoot(c.core.RootNode).Line,
249-
Column: c.core.Context.GetKeyNodeOrRoot(c.core.RootNode).Column,
250-
})
226+
errs = append(errs, validation.NewValueError("context is required, if type is set", c.core, c.core.Context))
251227
}
252228

253229
if c.Context != nil {
254230
if err := c.Context.Validate(true); err != nil {
255-
errs = append(errs, &validation.Error{
256-
Message: err.Error(),
257-
Line: c.core.Context.GetValueNodeOrRoot(c.core.RootNode).Line,
258-
Column: c.core.Context.GetValueNodeOrRoot(c.core.RootNode).Column,
259-
})
231+
errs = append(errs, validation.NewValueError(err.Error(), c.core, c.core.Context))
260232
}
261233
}
262234

@@ -279,30 +251,18 @@ func (c *Criterion) validateCondition(opts ...validation.Option) []error {
279251
case CriterionTypeSimple:
280252
cond, err := newCondition(c.Condition)
281253
if err != nil && c.Context == nil {
282-
errs = append(errs, &validation.Error{
283-
Message: err.Error(),
284-
Line: conditionLine,
285-
Column: conditionColumn,
286-
})
254+
errs = append(errs, validation.NewValueError(err.Error(), c.core, c.core.Condition))
287255
} else if cond != nil {
288256
errs = append(errs, cond.Validate(conditionLine, conditionColumn, opts...)...)
289257
}
290258
case CriterionTypeRegex:
291259
_, err := regexp.Compile(c.Condition)
292260
if err != nil {
293-
errs = append(errs, &validation.Error{
294-
Message: fmt.Errorf("invalid regex expression: %w", err).Error(),
295-
Line: conditionLine,
296-
Column: conditionColumn,
297-
})
261+
errs = append(errs, validation.NewValueError(fmt.Errorf("invalid regex expression: %w", err).Error(), c.core, c.core.Condition))
298262
}
299263
case CriterionTypeJsonPath:
300264
if _, err := jsonpath.NewPath(c.Condition); err != nil {
301-
errs = append(errs, &validation.Error{
302-
Message: fmt.Errorf("invalid jsonpath expression: %w", err).Error(),
303-
Line: conditionLine,
304-
Column: conditionColumn,
305-
})
265+
errs = append(errs, validation.NewValueError(fmt.Errorf("invalid jsonpath expression: %w", err).Error(), c.core, c.core.Condition))
306266
}
307267
case CriterionTypeXPath:
308268
// TODO validate xpath

arazzo/failureaction.go

Lines changed: 10 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -77,42 +77,22 @@ func (f *FailureAction) Validate(ctx context.Context, opts ...validation.Option)
7777
errs := []error{}
7878

7979
if f.core.Name.Present && f.Name == "" {
80-
errs = append(errs, &validation.Error{
81-
Message: "name is required",
82-
Line: f.core.Name.GetValueNodeOrRoot(f.core.RootNode).Line,
83-
Column: f.core.Name.GetValueNodeOrRoot(f.core.RootNode).Column,
84-
})
80+
errs = append(errs, validation.NewValueError("name is required", f.core, f.core.Name))
8581
}
8682

8783
switch f.Type {
8884
case FailureActionTypeEnd:
8985
if f.WorkflowID != nil {
90-
errs = append(errs, &validation.Error{
91-
Message: "workflowId is not allowed when type: end is specified",
92-
Line: f.core.WorkflowID.GetKeyNodeOrRoot(f.core.RootNode).Line,
93-
Column: f.core.WorkflowID.GetKeyNodeOrRoot(f.core.RootNode).Column,
94-
})
86+
errs = append(errs, validation.NewValueError("workflowId is not allowed when type: end is specified", f.core, f.core.WorkflowID))
9587
}
9688
if f.StepID != nil {
97-
errs = append(errs, &validation.Error{
98-
Message: "stepId is not allowed when type: end is specified",
99-
Line: f.core.StepID.GetKeyNodeOrRoot(f.core.RootNode).Line,
100-
Column: f.core.StepID.GetKeyNodeOrRoot(f.core.RootNode).Column,
101-
})
89+
errs = append(errs, validation.NewValueError("stepId is not allowed when type: end is specified", f.core, f.core.StepID))
10290
}
10391
if f.RetryAfter != nil {
104-
errs = append(errs, &validation.Error{
105-
Message: "retryAfter is not allowed when type: end is specified",
106-
Line: f.core.RetryAfter.GetKeyNodeOrRoot(f.core.RootNode).Line,
107-
Column: f.core.RetryAfter.GetKeyNodeOrRoot(f.core.RootNode).Column,
108-
})
92+
errs = append(errs, validation.NewValueError("retryAfter is not allowed when type: end is specified", f.core, f.core.RetryAfter))
10993
}
11094
if f.RetryLimit != nil {
111-
errs = append(errs, &validation.Error{
112-
Message: "retryLimit is not allowed when type: end is specified",
113-
Line: f.core.RetryLimit.GetKeyNodeOrRoot(f.core.RootNode).Line,
114-
Column: f.core.RetryLimit.GetKeyNodeOrRoot(f.core.RootNode).Column,
115-
})
95+
errs = append(errs, validation.NewValueError("retryLimit is not allowed when type: end is specified", f.core, f.core.RetryLimit))
11696
}
11797
case FailureActionTypeGoto:
11898
errs = append(errs, validationActionWorkflowIDAndStepID(ctx, validationActionWorkflowStepIDParams{
@@ -128,18 +108,10 @@ func (f *FailureAction) Validate(ctx context.Context, opts ...validation.Option)
128108
required: true,
129109
}, opts...)...)
130110
if f.RetryAfter != nil {
131-
errs = append(errs, &validation.Error{
132-
Message: "retryAfter is not allowed when type: goto is specified",
133-
Line: f.core.RetryAfter.GetKeyNodeOrRoot(f.core.RootNode).Line,
134-
Column: f.core.RetryAfter.GetKeyNodeOrRoot(f.core.RootNode).Column,
135-
})
111+
errs = append(errs, validation.NewValueError("retryAfter is not allowed when type: goto is specified", f.core, f.core.RetryAfter))
136112
}
137113
if f.RetryLimit != nil {
138-
errs = append(errs, &validation.Error{
139-
Message: "retryLimit is not allowed when type: goto is specified",
140-
Line: f.core.RetryLimit.GetKeyNodeOrRoot(f.core.RootNode).Line,
141-
Column: f.core.RetryLimit.GetKeyNodeOrRoot(f.core.RootNode).Column,
142-
})
114+
errs = append(errs, validation.NewValueError("retryLimit is not allowed when type: goto is specified", f.core, f.core.RetryLimit))
143115
}
144116
case FailureActionTypeRetry:
145117
errs = append(errs, validationActionWorkflowIDAndStepID(ctx, validationActionWorkflowStepIDParams{
@@ -156,28 +128,16 @@ func (f *FailureAction) Validate(ctx context.Context, opts ...validation.Option)
156128
}, opts...)...)
157129
if f.RetryAfter != nil {
158130
if *f.RetryAfter < 0 {
159-
errs = append(errs, &validation.Error{
160-
Message: "retryAfter must be greater than or equal to 0",
161-
Line: f.core.RetryAfter.GetValueNodeOrRoot(f.core.RootNode).Line,
162-
Column: f.core.RetryAfter.GetValueNodeOrRoot(f.core.RootNode).Column,
163-
})
131+
errs = append(errs, validation.NewValueError("retryAfter must be greater than or equal to 0", f.core, f.core.RetryAfter))
164132
}
165133
}
166134
if f.RetryLimit != nil {
167135
if *f.RetryLimit < 0 {
168-
errs = append(errs, &validation.Error{
169-
Message: "retryLimit must be greater than or equal to 0",
170-
Line: f.core.RetryLimit.GetValueNodeOrRoot(f.core.RootNode).Line,
171-
Column: f.core.RetryLimit.GetValueNodeOrRoot(f.core.RootNode).Column,
172-
})
136+
errs = append(errs, validation.NewValueError("retryLimit must be greater than or equal to 0", f.core, f.core.RetryLimit))
173137
}
174138
}
175139
default:
176-
errs = append(errs, &validation.Error{
177-
Message: fmt.Sprintf("type must be one of [%s]", strings.Join([]string{string(FailureActionTypeEnd), string(FailureActionTypeGoto), string(FailureActionTypeRetry)}, ", ")),
178-
Line: f.core.Type.GetValueNodeOrRoot(f.core.RootNode).Line,
179-
Column: f.core.Type.GetValueNodeOrRoot(f.core.RootNode).Column,
180-
})
140+
errs = append(errs, validation.NewValueError(fmt.Sprintf("type must be one of [%s]", strings.Join([]string{string(FailureActionTypeEnd), string(FailureActionTypeGoto), string(FailureActionTypeRetry)}, ", ")), f.core, f.core.Type))
181141
}
182142

183143
for _, criterion := range f.Criteria {

arazzo/info.go

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -41,19 +41,11 @@ func (i *Info) Validate(ctx context.Context, opts ...validation.Option) []error
4141
errs := []error{}
4242

4343
if i.core.Title.Present && i.Title == "" {
44-
errs = append(errs, &validation.Error{
45-
Message: "title is required",
46-
Line: i.core.Title.GetValueNodeOrRoot(i.core.RootNode).Line,
47-
Column: i.core.Title.GetValueNodeOrRoot(i.core.RootNode).Column,
48-
})
44+
errs = append(errs, validation.NewValueError("title is required", i.core, i.core.Title))
4945
}
5046

5147
if i.core.Version.Present && i.Version == "" {
52-
errs = append(errs, &validation.Error{
53-
Message: "version is required",
54-
Line: i.core.Version.GetValueNodeOrRoot(i.core.RootNode).Line,
55-
Column: i.core.Version.GetValueNodeOrRoot(i.core.RootNode).Column,
56-
})
48+
errs = append(errs, validation.NewValueError("version is required", i.core, i.core.Version))
5749
}
5850

5951
if len(errs) == 0 {

0 commit comments

Comments
 (0)