oastools

package module
v1.5.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 16, 2025 License: MIT Imports: 0 Imported by: 0

README

oastools

Note: All code has been generated by Claude Code using claude-4-5-sonnet

OpenAPI Specification (OAS) tools for validation, parsing, converting, and joining.

Go Reference

Features

  • Validate - Validate OpenAPI specification files for correctness
  • Parse - Parse and analyze OpenAPI specifications
  • Convert - Convert OpenAPI specifications between different versions (2.0 ↔ 3.x)
  • Join - Join multiple OpenAPI Specification documents
  • Library - Use as a Go library in your own applications

Supported OpenAPI Specification Versions

This tool supports all official OpenAPI Specification releases:

Version Specification
2.0 OAS 2.0 Specification
3.0.0 OAS 3.0.0 Specification
3.0.1 OAS 3.0.1 Specification
3.0.2 OAS 3.0.2 Specification
3.0.3 OAS 3.0.3 Specification
3.0.4 OAS 3.0.4 Specification
3.1.0 OAS 3.1.0 Specification
3.1.1 OAS 3.1.1 Specification
3.1.2 OAS 3.1.2 Specification
3.2.0 OAS 3.2.0 Specification

Note: Release candidate versions (e.g., 3.0.0-rc0, 3.1.0-rc1) are detected but not officially supported.

Installation

From Source
git clone https://github.com/erraggy/oastools.git
cd oastools
make install
Using Go
go install github.com/erraggy/oastools/cmd/oastools@latest
As a Library
go get github.com/erraggy/oastools@latest

Usage

Command-Line Interface
# Show help
oastools help

# Validate an OpenAPI spec
oastools validate openapi.yaml

# Parse an OpenAPI spec
oastools parse openapi.yaml

# Convert between OpenAPI versions
oastools convert -t 3.0.3 swagger.yaml -o openapi.yaml

# Join multiple OpenAPI specs
oastools join -o merged.yaml base.yaml extensions.yaml
Library Usage

The library provides two API styles for different use cases:

Simple API (Convenience Functions)

For quick, one-off operations, use the package-level convenience functions:

package main

import (
	"fmt"
	"log"

	"github.com/erraggy/oastools/parser"
	"github.com/erraggy/oastools/validator"
	"github.com/erraggy/oastools/converter"
	"github.com/erraggy/oastools/joiner"
)

func main() {
	// Parse an OpenAPI specification
	result, err := parser.Parse("openapi.yaml", false, true)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("Version: %s\n", result.Version)

	// Validate an OpenAPI specification
	vResult, err := validator.Validate("openapi.yaml", true, false)
	if err != nil {
		log.Fatal(err)
	}
	if !vResult.Valid {
		fmt.Printf("Found %d errors\n", vResult.ErrorCount)
	}

	// Convert between OpenAPI versions
	cResult, err := converter.Convert("swagger.yaml", "3.0.3")
	if err != nil {
		log.Fatal(err)
	}
	if cResult.HasCriticalIssues() {
		fmt.Printf("Conversion completed with %d critical issue(s)\n", cResult.CriticalCount)
	}

	// Join multiple OpenAPI specifications
	config := joiner.DefaultConfig()
	config.PathStrategy = joiner.StrategyAcceptLeft

	jResult, err := joiner.Join([]string{"base.yaml", "extensions.yaml"}, config)
	if err != nil {
		log.Fatal(err)
	}

	// Write the result using a Joiner instance
	j := joiner.New(config)
	err = j.WriteResult(jResult, "merged.yaml")
	if err != nil {
		log.Fatal(err)
	}
}
Advanced API (Reusable Instances)

For processing multiple files with the same configuration, create reusable instances:

package main

import (
	"fmt"
	"log"

	"github.com/erraggy/oastools/parser"
	"github.com/erraggy/oastools/validator"
	"github.com/erraggy/oastools/converter"
	"github.com/erraggy/oastools/joiner"
)

func main() {
	// Create a parser instance for reuse
	p := parser.New()
	p.ResolveRefs = false
	p.ValidateStructure = true

	result1, _ := p.Parse("api1.yaml")
	result2, _ := p.Parse("api2.yaml")
	result3, _ := p.Parse("api3.yaml")

	fmt.Printf("Parsed %d files\n", 3)

	// Create a validator instance for reuse
	v := validator.New()
	v.IncludeWarnings = true
	v.StrictMode = false

	vResult1, _ := v.Validate("api1.yaml")
	vResult2, _ := v.Validate("api2.yaml")

	// Create a converter instance for reuse
	c := converter.New()
	c.StrictMode = false
	c.IncludeInfo = true

	cResult1, _ := c.Convert("swagger-v1.yaml", "3.0.3")
	cResult2, _ := c.Convert("swagger-v2.yaml", "3.0.3")

	// Create a joiner instance for reuse
	config := joiner.DefaultConfig()
	config.SchemaStrategy = joiner.StrategyAcceptLeft

	j := joiner.New(config)
	jResult1, _ := j.Join([]string{"api1-base.yaml", "api1-ext.yaml"})
	jResult2, _ := j.Join([]string{"api2-base.yaml", "api2-ext.yaml"})

	j.WriteResult(jResult1, "merged-api1.yaml")
	j.WriteResult(jResult2, "merged-api2.yaml")
}

For complete API documentation, see pkg.go.dev.

Example Usage
go run github.com/erraggy/oastools/cmd/oastools validate testdata/invalid-oas3.yaml
OpenAPI Specification Validator
================================

File: testdata/invalid-oas3.yaml
Version: 3.0.3

Errors (12):
  ✗ document: oas 3.0.3: missing required field 'info.version': Info object must have a version string per spec
  ✗ document: oas 3.0.3: invalid path pattern 'paths.items': path must begin with '/'
  ✗ document: oas 3.0.3: missing required field 'paths.items.get.responses': Operation must have a responses object
  ✗ document: oas 3.0.3: invalid parameter 'paths.items.get.parameters[0]': path parameters must have 'required: true' per spec
  ✗ document: oas 3.0.3: missing required field 'paths.items.get.parameters[1].in': Parameter must specify location (query, header, path, cookie)
  ✗ document: oas 3.0.3: missing required field 'paths.items.post.requestBody.content': RequestBody must have at least one media type
  ✗ document: oas 3.0.3: duplicate operationId 'createItem' at 'paths./users.get': previously defined at 'paths.items.post' (operationIds must be unique across all operations)
  ✗ info.version: Info object must have a version
    Spec: https://spec.openapis.org/oas/v3.0.3.html#info-object
  ✗ paths.items: Path must start with '/'
    Spec: https://spec.openapis.org/oas/v3.0.3.html#paths-object
  ✗ paths.items.post.requestBody: RequestBody must have a content object with at least one media type
    Spec: https://spec.openapis.org/oas/v3.0.3.html#request-body-object
  ✗ paths.items.get.parameters[0]: Path parameters must have required: true
    Spec: https://spec.openapis.org/oas/v3.0.3.html#parameter-object
  ✗ paths.items.post: Duplicate operationId 'createItem' (first seen at paths./users.get)
    Spec: https://spec.openapis.org/oas/v3.0.3.html#operation-object

Warnings (3):
  ⚠ paths.items.post: Operation should have a description or summary for better documentation
    Spec: https://spec.openapis.org/oas/v3.0.3.html#operation-object
  ⚠ paths./users.get: Operation should have a description or summary for better documentation
    Spec: https://spec.openapis.org/oas/v3.0.3.html#operation-object
  ⚠ paths.items.get: Parameter 'id' is declared as path parameter but not used in path template
    Spec: https://spec.openapis.org/oas/v3.0.3.html#path-item-object

✗ Validation failed: 12 error(s), 3 warning(s)
exit status 1

Limitations

External References
  • HTTP(S) References Not Supported: The parser currently only supports local file references for external $ref values. References starting with http:// or https:// are not yet supported.
  • Security: External file references are restricted to the base directory and its subdirectories to prevent path traversal attacks.

Development

Prerequisites
  • Go 1.24 or higher
  • make (optional, but recommended)
Building
# Build the binary
make build

# Run tests
make test

# Run linter
make lint

# Format code
make fmt
Project Structure
.
├── cmd/oastools/       # CLI entry point
├── parser/             # OpenAPI parsing library
├── validator/          # OpenAPI validation library
├── converter/          # OpenAPI version conversion library
├── joiner/             # OpenAPI joining library
└── testdata/           # Test fixtures and sample specs

All four packages (parser, validator, converter, joiner) are public and can be imported directly in your Go applications.

License

MIT

Documentation

Overview

Package oastools provides comprehensive tools for working with OpenAPI Specification (OAS) documents.

oastools offers four main packages for parsing, validating, converting, and joining OpenAPI specifications across all major versions from OAS 2.0 (Swagger) through OAS 3.2.0.

Overview

The library consists of four primary packages:

  • parser: Parse and analyze OpenAPI specifications
  • validator: Validate OpenAPI specifications against their declared version
  • converter: Convert OpenAPI specifications between different versions
  • joiner: Join multiple OpenAPI specifications into a single document

All packages support the following OpenAPI Specification versions:

Installation

Install the library using go get:

go get github.com/erraggy/oastools

Quick Start

Parse an OpenAPI specification:

import "github.com/erraggy/oastools/parser"

p := parser.New()
result, err := p.Parse("openapi.yaml")
if err != nil {
	log.Fatal(err)
}
fmt.Printf("Version: %s\n", result.Version)

Validate an OpenAPI specification:

import "github.com/erraggy/oastools/validator"

v := validator.New()
result, err := v.Validate("openapi.yaml")
if err != nil {
	log.Fatal(err)
}
if !result.Valid {
	fmt.Printf("Found %d errors\n", result.ErrorCount)
}

Join multiple OpenAPI specifications:

import "github.com/erraggy/oastools/joiner"

j := joiner.New(joiner.DefaultConfig())
result, err := j.Join([]string{"base.yaml", "extensions.yaml"})
if err != nil {
	log.Fatal(err)
}
err = j.WriteResult(result, "merged.yaml")

Parser Package

The parser package provides functionality to parse OpenAPI specification files in YAML or JSON format. It supports external reference resolution, version detection, and structural validation.

Key features:

  • Multi-format support (YAML, JSON)
  • External reference resolution ($ref)
  • Path traversal protection
  • Operation ID uniqueness checking
  • Memory-efficient caching

Example:

p := parser.New()
p.ValidateStructure = true
p.ResolveRefs = true

result, err := p.Parse("openapi.yaml")
if err != nil {
	log.Fatal(err)
}

// Type assertion to access version-specific fields
if doc, ok := result.Document.(*parser.OAS3Document); ok {
	fmt.Printf("Title: %s\n", doc.Info.Title)
	fmt.Printf("Paths: %d\n", len(doc.Paths))
}

See the parser package documentation for more details.

Validator Package

The validator package validates OpenAPI specifications against their declared version's requirements. It performs comprehensive structural, format, and semantic validation.

Key features:

  • Multi-version validation
  • Structural validation (required fields, formats)
  • Semantic validation (operation IDs, path parameters)
  • Schema validation (JSON Schema)
  • Security validation
  • Best practice warnings (optional)
  • Strict mode for additional checks

Example:

v := validator.New()
v.StrictMode = true
v.IncludeWarnings = true

result, err := v.Validate("openapi.yaml")
if err != nil {
	log.Fatal(err)
}

for _, verr := range result.Errors {
	fmt.Printf("%s: %s\n", verr.Path, verr.Message)
	if verr.SpecRef != "" {
		fmt.Printf("  See: %s\n", verr.SpecRef)
	}
}

See the validator package documentation for more details.

Converter Package

The converter package converts OpenAPI specifications between different OAS versions. It performs best-effort conversion while tracking issues and incompatibilities.

Key features:

  • OAS 2.0 ↔ OAS 3.x conversion
  • OAS 3.x → OAS 3.y version updates
  • Best-effort conversion preserving maximum information
  • Detailed issue tracking with severity levels (Info, Warning, Critical)
  • Security scheme conversion
  • Schema conversion across versions

Example:

c := converter.New()
result, err := c.Convert("swagger.yaml", "3.0.3")
if err != nil {
	log.Fatal(err)
}

if result.HasCriticalIssues() {
	fmt.Printf("Conversion completed with %d critical issue(s):\n", result.CriticalCount)
	for _, issue := range result.Issues {
		if issue.Severity == converter.SeverityCritical {
			fmt.Printf("  %s\n", issue.String())
		}
	}
}

See the converter package documentation for more details.

Joiner Package

The joiner package enables merging multiple OpenAPI specification documents into a single unified document. It provides flexible collision resolution strategies and supports all OAS versions.

Key features:

  • Flexible collision strategies (accept-left, accept-right, fail)
  • Component-specific strategies (paths, schemas, components)
  • Array merging (servers, security, tags)
  • Tag deduplication
  • Version compatibility checking
  • Detailed collision reporting

Example:

config := joiner.JoinerConfig{
	PathStrategy:      joiner.StrategyFailOnCollision,
	SchemaStrategy:    joiner.StrategyAcceptLeft,
	ComponentStrategy: joiner.StrategyAcceptLeft,
	MergeArrays:       true,
	DeduplicateTags:   true,
}

j := joiner.New(config)
result, err := j.Join([]string{"base.yaml", "ext1.yaml", "ext2.yaml"})
if err != nil {
	log.Fatal(err)
}

err = j.WriteResult(result, "merged.yaml")
if err != nil {
	log.Fatal(err)
}

See the joiner package documentation for more details.

Common Workflows

Validate before processing:

// Validate first
v := validator.New()
vResult, err := v.Validate("api.yaml")
if err != nil || !vResult.Valid {
	log.Fatal("Invalid OpenAPI specification")
}

// Then parse
p := parser.New()
pResult, err := p.Parse("api.yaml")
if err != nil {
	log.Fatal(err)
}
// Process the parsed document...

Join and validate:

// Join multiple specs
j := joiner.New(joiner.DefaultConfig())
jResult, err := j.Join([]string{"base.yaml", "ext.yaml"})
if err != nil {
	log.Fatal(err)
}

// Write to temp file
tempFile := "merged-temp.yaml"
err = j.WriteResult(jResult, tempFile)
if err != nil {
	log.Fatal(err)
}

// Validate the joined result
v := validator.New()
vResult, err := v.Validate(tempFile)
if err != nil || !vResult.Valid {
	log.Fatal("Joined specification is invalid")
}

Parse multiple versions:

p := parser.New()
files := []string{"api-v2.yaml", "api-v3.0.yaml", "api-v3.1.yaml"}

for _, file := range files {
	result, err := p.Parse(file)
	if err != nil {
		log.Printf("Failed to parse %s: %v", file, err)
		continue
	}
	fmt.Printf("%s: OAS %s\n", file, result.Version)
}

Security Considerations

All packages implement security best practices:

  • Path traversal protection: External references are restricted to the base directory and subdirectories
  • Resource limits: Maximum cached documents (default: 1000) and schema nesting depth (default: 100) to prevent resource exhaustion
  • Input validation: All user-provided values are validated before processing
  • File permissions: Output files are created with restrictive permissions (0600)
  • No remote references: HTTP(S) URLs in $ref are not currently supported, limiting attack surface

Limitations

Current limitations across all packages:

  • HTTP(S) references: Remote URL references in $ref are not supported; only local file references are allowed
  • External reference resolution: The joiner preserves $ref values as-is and does not resolve or merge referenced content across documents
  • Cross-version joining: Cannot join OAS 2.0 with OAS 3.x documents
  • Custom extensions: OpenAPI extension fields (x-*) are preserved but not validated or merged with custom logic

Performance Tips

For best performance:

  • Disable reference resolution if not needed (parser.ResolveRefs = false)
  • Disable warnings if not needed (validator.IncludeWarnings = false)
  • Use appropriate collision strategies for joining (accept-left/right vs fail)
  • Cache validation results for unchanged documents
  • Process documents concurrently when possible (packages are not goroutine-safe, create separate instances for concurrent use)

Error Handling

All packages follow consistent error handling patterns:

  • File I/O errors: Returned directly (e.g., os.ErrNotExist)
  • Parse errors: Returned with context about what failed
  • Validation errors: Collected in ValidationResult.Errors (not returned as error)
  • Join errors: Returned with detailed collision information

Always check both the error return value and any error/warning collections in result objects.

Version Compatibility

This library is designed to be backward compatible within major versions. The public API follows semantic versioning:

  • Major version changes may include breaking API changes
  • Minor version changes add functionality in a backward-compatible manner
  • Patch version changes include backward-compatible bug fixes

When upgrading, check the CHANGELOG for any breaking changes or new features.

Command-Line Interface

In addition to the library packages, oastools provides a command-line interface:

# Validate a spec
oastools validate openapi.yaml

# Parse a spec
oastools parse openapi.yaml

# Convert between versions
oastools convert -t 3.0.3 swagger.yaml -o openapi.yaml

# Join multiple specs
oastools join -o merged.yaml base.yaml extensions.yaml

Install the CLI:

go install github.com/erraggy/oastools/cmd/oastools@latest

Additional Resources

License

This library is released under the MIT License. See the LICENSE file in the repository for full details.

Directories

Path Synopsis
cmd
oastools command
Package converter provides OpenAPI Specification (OAS) version conversion functionality.
Package converter provides OpenAPI Specification (OAS) version conversion functionality.
Package joiner provides OpenAPI Specification (OAS) joining functionality.
Package joiner provides OpenAPI Specification (OAS) joining functionality.
Package parser provides OpenAPI Specification (OAS) parsing functionality.
Package parser provides OpenAPI Specification (OAS) parsing functionality.
Package validator provides OpenAPI Specification (OAS) validation functionality.
Package validator provides OpenAPI Specification (OAS) validation functionality.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL