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.
RenameSchemais the first.
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-compressandopenapi-flattenthat run an algorithm over a whole specification and need the same primitives underneath.
go get github.com/MarkRosemaker/openapi-editimport (
"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.\-_]+$.
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
openapiinstead, so that users who only want to parse and validate a spec aren't made to carry it
| 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 |
If you have any contributions to make, please submit a pull request or open an issue on the GitHub repository.
This project is licensed under the Apache 2.0 License.
