Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 2 additions & 6 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,11 @@ updates:
day: "monday"
time: "09:00"
open-pull-requests-limit: 10
reviewers:
- "speakeasy-api/maintainers"
assignees:
- "speakeasy-api/maintainers"
commit-message:
prefix: "deps"
prefix-development: "deps"
prefix: "fix"
prefix-development: "chore"
include: "scope"
labels:
- "dependencies"
Expand Down Expand Up @@ -42,8 +40,6 @@ updates:
day: "monday"
time: "09:00"
open-pull-requests-limit: 5
reviewers:
- "speakeasy-api/maintainers"
assignees:
- "speakeasy-api/maintainers"
commit-message:
Expand Down
8 changes: 4 additions & 4 deletions .mise.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@ gotestsum = "latest"
[tasks.setup-vscode-symlinks]
description = "Create VSCode symlinks for tools not automatically handled by mise-vscode"
run = [
"mkdir -p .vscode/mise-tools",
"ln -sf $(mise exec golangci-lint@2.1.1 -- which golangci-lint) .vscode/mise-tools/golangci-lint",
"mkdir -p .vscode/mise-tools",
"ln -sf $(mise exec golangci-lint@2.1.1 -- which golangci-lint) .vscode/mise-tools/golangci-lint",
]

[hooks]
postinstall = [
"mise run setup-vscode-symlinks",
"go install go.uber.org/nilaway/cmd/nilaway@8ad05f0",
"mise run setup-vscode-symlinks",
"go install go.uber.org/nilaway/cmd/nilaway@8ad05f0",
]
14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,22 @@ go install github.com/speakeasy-api/openapi/cmd/openapi@latest
The CLI provides three main command groups:

- **`openapi spec`** - Commands for working with OpenAPI specifications ([documentation](./openapi/cmd/README.md))
- `bootstrap` - Create a new OpenAPI document with best practice examples
- `bundle` - Bundle external references into components section
- `clean` - Remove unused components from an OpenAPI specification
- `inline` - Inline all references in an OpenAPI specification
- `join` - Join multiple OpenAPI documents into a single document
- `optimize` - Optimize an OpenAPI specification by deduplicating inline schemas
- `upgrade` - Upgrade an OpenAPI specification to the latest supported version
- `validate` - Validate an OpenAPI specification document

- **`openapi arazzo`** - Commands for working with Arazzo workflow documents ([documentation](./arazzo/cmd/README.md))
- `validate` - Validate an Arazzo workflow document

- **`openapi overlay`** - Commands for working with OpenAPI overlays ([documentation](./overlay/cmd/README.md))
- `apply` - Apply an overlay to an OpenAPI specification
- `compare` - Compare two specifications and generate an overlay describing differences
- `validate` - Validate an OpenAPI overlay document

#### Quick Examples

Expand Down
2 changes: 1 addition & 1 deletion arazzo/successaction.go
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ func validationActionWorkflowIDAndStepID(ctx context.Context, parentName string,
// Get the parent match function from the location
parentLoc := item.Location[len(item.Location)-1]

err := parentLoc.Parent(Matcher{
err := parentLoc.ParentMatchFunc(Matcher{
Workflow: func(workflow *Workflow) error {
return item.Match(Matcher{
Step: func(step *Step) error {
Expand Down
58 changes: 29 additions & 29 deletions arazzo/walk.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,24 +68,24 @@ func walk(ctx context.Context, arazzo *Arazzo, yield func(WalkItem) bool) {
// Visit each of the top level fields in turn populating their location context with field and any key/index information
loc := Locations{}

if !walkInfo(ctx, &arazzo.Info, append(loc, LocationContext{Parent: arazzoMatchFunc, ParentField: "info"}), arazzo, yield) {
if !walkInfo(ctx, &arazzo.Info, append(loc, LocationContext{ParentMatchFunc: arazzoMatchFunc, ParentField: "info"}), arazzo, yield) {
return
}

if !walkSourceDescriptions(ctx, arazzo.SourceDescriptions, append(loc, LocationContext{Parent: arazzoMatchFunc, ParentField: "sourceDescriptions"}), arazzo, yield) {
if !walkSourceDescriptions(ctx, arazzo.SourceDescriptions, append(loc, LocationContext{ParentMatchFunc: arazzoMatchFunc, ParentField: "sourceDescriptions"}), arazzo, yield) {
return
}

if !walkWorkflows(ctx, arazzo.Workflows, append(loc, LocationContext{Parent: arazzoMatchFunc, ParentField: "workflows"}), arazzo, yield) {
if !walkWorkflows(ctx, arazzo.Workflows, append(loc, LocationContext{ParentMatchFunc: arazzoMatchFunc, ParentField: "workflows"}), arazzo, yield) {
return
}

if !walkComponents(ctx, arazzo.Components, append(loc, LocationContext{Parent: arazzoMatchFunc, ParentField: "components"}), arazzo, yield) {
if !walkComponents(ctx, arazzo.Components, append(loc, LocationContext{ParentMatchFunc: arazzoMatchFunc, ParentField: "components"}), arazzo, yield) {
return
}

// Visit Arazzo Extensions
yield(WalkItem{Match: getMatchFunc(arazzo.Extensions), Location: append(loc, LocationContext{Parent: arazzoMatchFunc, ParentField: ""}), Arazzo: arazzo})
yield(WalkItem{Match: getMatchFunc(arazzo.Extensions), Location: append(loc, LocationContext{ParentMatchFunc: arazzoMatchFunc, ParentField: ""}), Arazzo: arazzo})
}

func walkInfo(_ context.Context, info *Info, loc Locations, arazzo *Arazzo, yield func(WalkItem) bool) bool {
Expand All @@ -100,7 +100,7 @@ func walkInfo(_ context.Context, info *Info, loc Locations, arazzo *Arazzo, yiel
}

// Visit Info Extensions
return yield(WalkItem{Match: getMatchFunc(info.Extensions), Location: append(loc, LocationContext{Parent: infoMatchFunc, ParentField: ""}), Arazzo: arazzo})
return yield(WalkItem{Match: getMatchFunc(info.Extensions), Location: append(loc, LocationContext{ParentMatchFunc: infoMatchFunc, ParentField: ""}), Arazzo: arazzo})
}

func walkSourceDescriptions(ctx context.Context, sourceDescriptions []*SourceDescription, loc Locations, arazzo *Arazzo, yield func(WalkItem) bool) bool {
Expand Down Expand Up @@ -134,7 +134,7 @@ func walkSourceDescription(_ context.Context, sd *SourceDescription, loc Locatio
}

// Visit SourceDescription Extensions
return yield(WalkItem{Match: getMatchFunc(sd.Extensions), Location: append(loc, LocationContext{Parent: sdMatchFunc, ParentField: ""}), Arazzo: arazzo})
return yield(WalkItem{Match: getMatchFunc(sd.Extensions), Location: append(loc, LocationContext{ParentMatchFunc: sdMatchFunc, ParentField: ""}), Arazzo: arazzo})
}

func walkWorkflows(ctx context.Context, workflows []*Workflow, loc Locations, arazzo *Arazzo, yield func(WalkItem) bool) bool {
Expand Down Expand Up @@ -168,32 +168,32 @@ func walkWorkflow(ctx context.Context, workflow *Workflow, loc Locations, arazzo
}

// Walk through parameters
if !walkReusableParameters(ctx, workflow.Parameters, append(loc, LocationContext{Parent: workflowMatchFunc, ParentField: "parameters"}), arazzo, yield) {
if !walkReusableParameters(ctx, workflow.Parameters, append(loc, LocationContext{ParentMatchFunc: workflowMatchFunc, ParentField: "parameters"}), arazzo, yield) {
return false
}

// Walk through inputs schema using oas3 walking
if !walkJSONSchema(ctx, workflow.Inputs, append(loc, LocationContext{Parent: workflowMatchFunc, ParentField: "inputs"}), arazzo, yield) {
if !walkJSONSchema(ctx, workflow.Inputs, append(loc, LocationContext{ParentMatchFunc: workflowMatchFunc, ParentField: "inputs"}), arazzo, yield) {
return false
}

// Walk through steps
if !walkSteps(ctx, workflow.Steps, append(loc, LocationContext{Parent: workflowMatchFunc, ParentField: "steps"}), arazzo, yield) {
if !walkSteps(ctx, workflow.Steps, append(loc, LocationContext{ParentMatchFunc: workflowMatchFunc, ParentField: "steps"}), arazzo, yield) {
return false
}

// Walk through success actions
if !walkReusableSuccessActions(ctx, workflow.SuccessActions, append(loc, LocationContext{Parent: workflowMatchFunc, ParentField: "successActions"}), arazzo, yield) {
if !walkReusableSuccessActions(ctx, workflow.SuccessActions, append(loc, LocationContext{ParentMatchFunc: workflowMatchFunc, ParentField: "successActions"}), arazzo, yield) {
return false
}

// Walk through failure actions
if !walkReusableFailureActions(ctx, workflow.FailureActions, append(loc, LocationContext{Parent: workflowMatchFunc, ParentField: "failureActions"}), arazzo, yield) {
if !walkReusableFailureActions(ctx, workflow.FailureActions, append(loc, LocationContext{ParentMatchFunc: workflowMatchFunc, ParentField: "failureActions"}), arazzo, yield) {
return false
}

// Visit Workflow Extensions
return yield(WalkItem{Match: getMatchFunc(workflow.Extensions), Location: append(loc, LocationContext{Parent: workflowMatchFunc, ParentField: ""}), Arazzo: arazzo})
return yield(WalkItem{Match: getMatchFunc(workflow.Extensions), Location: append(loc, LocationContext{ParentMatchFunc: workflowMatchFunc, ParentField: ""}), Arazzo: arazzo})
}

func walkReusableParameters(ctx context.Context, parameters []*ReusableParameter, loc Locations, arazzo *Arazzo, yield func(WalkItem) bool) bool {
Expand Down Expand Up @@ -273,10 +273,10 @@ func convertSchemaLocation(schemaLoc walkpkg.Locations[oas3.SchemaMatchFunc], ba
// Convert each oas3 location context to arazzo location context
for _, schemaLocCtx := range schemaLoc {
result = append(result, LocationContext{
Parent: convertSchemaMatchFunc(schemaLocCtx.Parent),
ParentField: schemaLocCtx.ParentField,
ParentKey: schemaLocCtx.ParentKey,
ParentIndex: schemaLocCtx.ParentIndex,
ParentMatchFunc: convertSchemaMatchFunc(schemaLocCtx.ParentMatchFunc),
ParentField: schemaLocCtx.ParentField,
ParentKey: schemaLocCtx.ParentKey,
ParentIndex: schemaLocCtx.ParentIndex,
})
}

Expand Down Expand Up @@ -314,22 +314,22 @@ func walkStep(ctx context.Context, step *Step, loc Locations, arazzo *Arazzo, yi
}

// Walk through parameters
if !walkReusableParameters(ctx, step.Parameters, append(loc, LocationContext{Parent: stepMatchFunc, ParentField: "parameters"}), arazzo, yield) {
if !walkReusableParameters(ctx, step.Parameters, append(loc, LocationContext{ParentMatchFunc: stepMatchFunc, ParentField: "parameters"}), arazzo, yield) {
return false
}

// Walk through success actions
if !walkReusableSuccessActions(ctx, step.OnSuccess, append(loc, LocationContext{Parent: stepMatchFunc, ParentField: "onSuccess"}), arazzo, yield) {
if !walkReusableSuccessActions(ctx, step.OnSuccess, append(loc, LocationContext{ParentMatchFunc: stepMatchFunc, ParentField: "onSuccess"}), arazzo, yield) {
return false
}

// Walk through failure actions
if !walkReusableFailureActions(ctx, step.OnFailure, append(loc, LocationContext{Parent: stepMatchFunc, ParentField: "onFailure"}), arazzo, yield) {
if !walkReusableFailureActions(ctx, step.OnFailure, append(loc, LocationContext{ParentMatchFunc: stepMatchFunc, ParentField: "onFailure"}), arazzo, yield) {
return false
}

// Visit Step Extensions
return yield(WalkItem{Match: getMatchFunc(step.Extensions), Location: append(loc, LocationContext{Parent: stepMatchFunc, ParentField: ""}), Arazzo: arazzo})
return yield(WalkItem{Match: getMatchFunc(step.Extensions), Location: append(loc, LocationContext{ParentMatchFunc: stepMatchFunc, ParentField: ""}), Arazzo: arazzo})
}

func walkReusableSuccessActions(ctx context.Context, actions []*ReusableSuccessAction, loc Locations, arazzo *Arazzo, yield func(WalkItem) bool) bool {
Expand Down Expand Up @@ -414,27 +414,27 @@ func walkComponents(ctx context.Context, components *Components, loc Locations,
}

// Walk through inputs
if !walkComponentInputs(ctx, components.Inputs, append(loc, LocationContext{Parent: componentsMatchFunc, ParentField: "inputs"}), arazzo, yield) {
if !walkComponentInputs(ctx, components.Inputs, append(loc, LocationContext{ParentMatchFunc: componentsMatchFunc, ParentField: "inputs"}), arazzo, yield) {
return false
}

// Walk through parameters
if !walkComponentParameters(ctx, components.Parameters, append(loc, LocationContext{Parent: componentsMatchFunc, ParentField: "parameters"}), arazzo, yield) {
if !walkComponentParameters(ctx, components.Parameters, append(loc, LocationContext{ParentMatchFunc: componentsMatchFunc, ParentField: "parameters"}), arazzo, yield) {
return false
}

// Walk through success actions
if !walkComponentSuccessActions(ctx, components.SuccessActions, append(loc, LocationContext{Parent: componentsMatchFunc, ParentField: "successActions"}), arazzo, yield) {
if !walkComponentSuccessActions(ctx, components.SuccessActions, append(loc, LocationContext{ParentMatchFunc: componentsMatchFunc, ParentField: "successActions"}), arazzo, yield) {
return false
}

// Walk through failure actions
if !walkComponentFailureActions(ctx, components.FailureActions, append(loc, LocationContext{Parent: componentsMatchFunc, ParentField: "failureActions"}), arazzo, yield) {
if !walkComponentFailureActions(ctx, components.FailureActions, append(loc, LocationContext{ParentMatchFunc: componentsMatchFunc, ParentField: "failureActions"}), arazzo, yield) {
return false
}

// Visit Components Extensions
return yield(WalkItem{Match: getMatchFunc(components.Extensions), Location: append(loc, LocationContext{Parent: componentsMatchFunc, ParentField: ""}), Arazzo: arazzo})
return yield(WalkItem{Match: getMatchFunc(components.Extensions), Location: append(loc, LocationContext{ParentMatchFunc: componentsMatchFunc, ParentField: ""}), Arazzo: arazzo})
}

func walkComponentInputs(ctx context.Context, inputs *sequencedmap.Map[string, *oas3.JSONSchema[oas3.Referenceable]], loc Locations, arazzo *Arazzo, yield func(WalkItem) bool) bool {
Expand Down Expand Up @@ -487,7 +487,7 @@ func walkParameter(_ context.Context, parameter *Parameter, loc Locations, arazz
}

// Visit Parameter Extensions
return yield(WalkItem{Match: getMatchFunc(parameter.Extensions), Location: append(loc, LocationContext{Parent: parameterMatchFunc, ParentField: ""}), Arazzo: arazzo})
return yield(WalkItem{Match: getMatchFunc(parameter.Extensions), Location: append(loc, LocationContext{ParentMatchFunc: parameterMatchFunc, ParentField: ""}), Arazzo: arazzo})
}

func walkComponentSuccessActions(ctx context.Context, actions *sequencedmap.Map[string, *SuccessAction], loc Locations, arazzo *Arazzo, yield func(WalkItem) bool) bool {
Expand Down Expand Up @@ -521,7 +521,7 @@ func walkSuccessAction(_ context.Context, action *SuccessAction, loc Locations,
}

// Visit SuccessAction Extensions
return yield(WalkItem{Match: getMatchFunc(action.Extensions), Location: append(loc, LocationContext{Parent: actionMatchFunc, ParentField: ""}), Arazzo: arazzo})
return yield(WalkItem{Match: getMatchFunc(action.Extensions), Location: append(loc, LocationContext{ParentMatchFunc: actionMatchFunc, ParentField: ""}), Arazzo: arazzo})
}

func walkComponentFailureActions(ctx context.Context, actions *sequencedmap.Map[string, *FailureAction], loc Locations, arazzo *Arazzo, yield func(WalkItem) bool) bool {
Expand Down Expand Up @@ -555,7 +555,7 @@ func walkFailureAction(_ context.Context, action *FailureAction, loc Locations,
}

// Visit FailureAction Extensions
return yield(WalkItem{Match: getMatchFunc(action.Extensions), Location: append(loc, LocationContext{Parent: actionMatchFunc, ParentField: ""}), Arazzo: arazzo})
return yield(WalkItem{Match: getMatchFunc(action.Extensions), Location: append(loc, LocationContext{ParentMatchFunc: actionMatchFunc, ParentField: ""}), Arazzo: arazzo})
}

type matchHandler[T any] struct {
Expand Down
2 changes: 0 additions & 2 deletions jsonpointer/models.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,6 @@ func navigateModel(sourceVal reflect.Value, currentPart navigationPart, stack []

key := currentPart.unescapeValue()

// First, check if this is an embedded map (anonymous field that implements sequenced map interface)
// This follows the same pattern as in marshaller/unmarshaller.go
sourceType := sourceVal.Type()
if sourceType.Kind() == reflect.Ptr {
sourceType = sourceType.Elem()
Expand Down
12 changes: 7 additions & 5 deletions jsonschema/oas3/schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -673,7 +673,9 @@ func (s *Schema) IsEqual(other *Schema) bool {
// Both nil, continue
case s.Type == nil || other.Type == nil:
return false
case !s.Type.IsEqual(other.Type):
}
// Compare both type arrays have the same types
if !equalSlices(s.GetType(), other.GetType()) {
return false
}
Comment thread
TristanSpeakEasy marked this conversation as resolved.

Expand Down Expand Up @@ -806,7 +808,7 @@ func (s *Schema) IsEqual(other *Schema) bool {
}

// Compare string slices
if !equalStringSlices(s.Required, other.Required) {
if !equalSlices(s.Required, other.Required) {
return false
}

Expand Down Expand Up @@ -980,16 +982,16 @@ func equalSequencedMaps(a, b *sequencedmap.Map[string, *JSONSchema[Referenceable
return a.IsEqualFunc(b, equalJSONSchemas)
}

func equalStringSlices(a, b []string) bool {
func equalSlices[T any](a, b []T) bool {
// Treat nil and empty slices as equal
if len(a) == 0 && len(b) == 0 {
return true
}
if len(a) != len(b) {
return false
}
for i, itemA := range a {
if itemA != b[i] {
for i := range a {
if !reflect.DeepEqual(a[i], b[i]) {
return false
}
}
Expand Down
Loading
Loading