edit

package module
v0.0.0-...-a4c3c65 Latest Latest
Warning

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

Go to latest
Published: Sep 8, 2026 License: Apache-2.0 Imports: 3 Imported by: 0

README

Go Reference Go Report Card Code Coverage

A gopher moving one luggage tag while others, connected by strings, swing into alignment

Change an API spec without breaking it.

openapi-edit provides safe structural edits to an OpenAPI 3.x specification — the kind of change where touching one place obliges you to touch several others, and forgetting one leaves a document that no longer resolves.

Status: early. The scope below is settled and operations arrive one at a time, as each earns its place. RenameSchema is the first.

Introduction

Renaming a schema is the canonical example. The rename itself is a single map operation, but every $ref that pointed at the old name is now dangling — and those $refs can be anywhere: nested inside another schema's properties, inside an allOf branch, in a response's content, in a parameter, in a callback. Getting this right means walking the entire document. Getting it wrong means a spec that looks fine and fails to resolve.

That traversal is worth writing once, carefully, and reusing.

This module serves two kinds of caller:

  • Directly, when you are writing code against your own specification and want to make a specific change safely, without reimplementing the bookkeeping.
  • As a dependency, for tools like openapi-compress and openapi-flatten that run an algorithm over a whole specification and need the same primitives underneath.

Usage

go get github.com/MarkRosemaker/openapi-edit
import (
    "github.com/MarkRosemaker/openapi"
    edit "github.com/MarkRosemaker/openapi-edit"
)

// Renames the schema and rewrites every reference to it.
if err := edit.RenameSchema(doc, "GetV1PetByPetIDOkJSONResponse", "Pet"); err != nil {
    log.Fatal(err)
}

The schema keeps its position among the components, so a rename produces a one-line change rather than reordering the section.

Renaming a schema to its current name does nothing and reports no error. Otherwise the rename fails, changing nothing at all, in three cases:

Error When
ErrSchemaNotFound components.schemas has no schema under the old name
ErrSchemaExists the new name is already taken by another schema
ErrInvalidSchemaName the new name is not a valid key under components

The second is the interesting one. Renaming onto an existing schema would silently discard one of two different definitions and repoint every reference at whichever survived — a change that looks successful and quietly alters the API.

The third matters more than validity alone suggests: a name containing / would produce a reference that resolves somewhere else entirely, and one containing a space would produce a reference that does not resolve at all. Component keys must match ^[a-zA-Z0-9.\-_]+$.

Scope

Operations belong here when they satisfy two conditions: they mutate a document, and doing them correctly requires knowledge of the document beyond the node being changed.

In scope

  • ✅ Renaming a component and rewriting every reference to it (RenameSchema)
  • Removing a component and reporting, or resolving, the references left behind
  • Moving a definition between inline and components, keeping references intact
  • Finding every location that refers to a given component

Out of scope

  • Deciding whether two things should be merged — that is openapi-compare
  • Combining two schemas into one wider schema — that is openapi-merge
  • Whole-document policies such as flattening or deduplication — those are their own modules, and they are expected to use this one
  • Anything universal enough to belong on the types themselves — that goes into openapi instead, so that users who only want to parse and validate a spec aren't made to carry it

The openapi family

Module Purpose
openapi Parse, validate, and write OpenAPI 3.x specifications
openapi-compare Compare specification objects — exact equality and shape equivalence
openapi-edit (this module) Safe structural edits, such as renaming a schema and rewriting every $ref to it
openapi-flatten Promote inline definitions into named components entries
openapi-compress Deduplicate and merge equivalent component schemas
openapi-merge Merge schemas that were inferred independently from different samples
openapi-enrich Infer specification content from observed HTTP traffic
openapi-codegen Generate Go types, clients, and servers from a specification

Contributing

If you have any contributions to make, please submit a pull request or open an issue on the GitHub repository.

License

This project is licensed under the Apache 2.0 License.

Documentation

Overview

Package edit provides structural edits to an OpenAPI document — changes where touching one place obliges you to touch several others.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func MergeSchema

func MergeSchema(doc *openapi.Document, oldName, newName, description string) error

MergeSchema repoints every reference to oldName at newName and removes oldName from components.schemas, leaving newName's own definition untouched.

It differs from RenameSchema, which refuses to rename a schema onto a name that already exists (ErrSchemaExists): merging onto an existing schema is exactly the point here, typically because several near-duplicate schemas (e.g. ones an OpenAPI generator produced one per endpoint, that happen to describe the same thing) are being consolidated into one.

If description is non-empty, it becomes the $ref-level description on every reference this repoints, replacing whatever description that reference already had. The usual reason to reach for Merge rather than Rename is that oldName's own definition — its bounds, its wording — is about to be discarded once oldName is gone; setting description is how that information survives on the fields that used it, rather than being lost in the merge.

It fails, changing nothing, if oldName or newName is not in components.schemas (ErrSchemaNotFound).

func RenameSchema

func RenameSchema(doc *openapi.Document, oldName, newName string) error

RenameSchema renames a schema in components.schemas and rewrites every reference to it, wherever in the document that reference occurs.

The schema keeps its position among the components, so renaming produces a one-line change rather than reordering the section.

Renaming a schema to its current name does nothing and reports no error. Otherwise it fails, changing nothing, if:

  • oldName is not in components.schemas (ErrSchemaNotFound);
  • newName is already taken (ErrSchemaExists) — renaming onto an existing schema would silently discard one of two different definitions, and point every reference to whichever survived;
  • newName could not be referenced (ErrInvalidSchemaName).

func WalkSchemaRefs

func WalkSchemaRefs(doc *openapi.Document, fn func(*openapi.SchemaRef))

WalkSchemaRefs calls fn once for every schema reference reachable from doc: through components (schemas, responses, parameters, request bodies, headers, callbacks, path items) and through every path, operation, and webhook.

A schema reachable through more than one reference — directly, or because two references resolve to the same schema — is still walked into only once, so fn can freely mutate the references it's given without risking infinite recursion on a self-referential schema.

This is the traversal RenameSchema uses to find every occurrence of a reference; it's exported because other structural edits need the same walk with a different fn, e.g. finding every reference to a schema that's about to be merged into another with MergeSchema.

Types

type ErrInvalidSchemaName

type ErrInvalidSchemaName struct{ Name string }

ErrInvalidSchemaName is returned when the new name is not a valid key under components, and so could not be referenced.

func (*ErrInvalidSchemaName) Error

func (e *ErrInvalidSchemaName) Error() string

type ErrSchemaExists

type ErrSchemaExists struct{ Name string }

ErrSchemaExists is returned when the new name is already taken by another schema. Renaming onto it would silently merge two definitions into one.

func (*ErrSchemaExists) Error

func (e *ErrSchemaExists) Error() string

type ErrSchemaNotFound

type ErrSchemaNotFound struct{ Name string }

ErrSchemaNotFound is returned when the schema to rename is not in components.schemas.

func (*ErrSchemaNotFound) Error

func (e *ErrSchemaNotFound) Error() string

Jump to

Keyboard shortcuts

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