Skip to content
Effect Days 2026 Get your ticket

OpenApiPatch

OpenAPI spec patching utilities.

Handles parsing and applying JSON Patch documents (RFC 6902) to OpenAPI specs. Supports patches from:

  • JSON files (.json)
  • YAML files (.yaml, .yml)
  • Inline JSON strings
12 exports Added in v4.0.0 Source

Errors

Error thrown when multiple JSON Patch operations fail.

Details

This error aggregates all application errors so users can see every failing operation at once instead of fixing them one at a time.

Signature

declare class JsonPatchAggregateError extends {
readonly _tag: "JsonPatchAggregateError";
readonly errors: readonly Array<unknown>;
} & YieldableError<this> {
constructor(...args: [props: {
readonly _tag?: "JsonPatchAggregateError";
readonly errors: readonly Array<unknown>;
}, options?: MakeOptions]);
message: string;
}

Example

(Creating an aggregate error)

import { JsonPatchAggregateError, JsonPatchApplicationError } from "@effect/openapi-generator/OpenApiPatch"
const error = new JsonPatchAggregateError({
errors: [
new JsonPatchApplicationError({
source: "./fix.json",
operationIndex: 0,
operation: "replace",
path: "/info/x",
reason: "Property does not exist"
}),
new JsonPatchApplicationError({
source: "./fix.json",
operationIndex: 2,
operation: "remove",
path: "/paths/~1users",
reason: "Property does not exist"
})
]
})
error.message.split("\n")[0] // => "2 patch operations failed:"

Error thrown when applying a JSON Patch operation fails.

Details

This error occurs when:

  • A path does not exist for remove/replace operations
  • An array index is out of bounds
  • The target location is not a valid container

Signature

declare class JsonPatchApplicationError extends {
readonly _tag: "JsonPatchApplicationError";
readonly operation: string;
readonly operationIndex: number;
readonly path: string;
readonly reason: string;
readonly source: string;
} & YieldableError<this> {
constructor(...args: [props: {
readonly _tag?: "JsonPatchApplicationError";
readonly operation: string;
readonly operationIndex: number;
readonly path: string;
readonly reason: string;
readonly source: string;
}, options?: MakeOptions]);
message: string;
}

Example

(Creating an application error)

import { JsonPatchApplicationError } from "@effect/openapi-generator/OpenApiPatch"
const error = new JsonPatchApplicationError({
source: "./patches/fix.json",
operationIndex: 2,
operation: "remove",
path: "/paths/~1users",
reason: "Property \"users\" does not exist"
})
error.message // => 'Failed to apply patch from ./patches/fix.json: operation 2 (remove at /paths/~1users): Property "users" does not exist'

Error thrown when parsing a JSON Patch input fails.

Details

This error occurs when:

  • A patch file cannot be read
  • JSON or YAML syntax is invalid
  • The file format is unsupported

Signature

declare class JsonPatchParseError extends {
readonly _tag: "JsonPatchParseError";
readonly reason: string;
readonly source: string;
} & YieldableError<this> {
constructor(...args: [props: {
readonly _tag?: "JsonPatchParseError";
readonly reason: string;
readonly source: string;
}, options?: MakeOptions]);
message: string;
}

Example

(Creating a parse error)

import { JsonPatchParseError } from "@effect/openapi-generator/OpenApiPatch"
const error = new JsonPatchParseError({
source: "./patches/fix.json",
reason: "Unexpected token at position 42"
})
error.message // => "Failed to parse patch from ./patches/fix.json: Unexpected token at position 42"

Error thrown when a parsed value does not conform to the JSON Patch schema.

Details

This error occurs when:

  • The patch is not an array
  • An operation is missing required fields (op, path)
  • An operation has an unsupported op value
  • An add/replace operation is missing the value field

Signature

declare class JsonPatchValidationError extends {
readonly _tag: "JsonPatchValidationError";
readonly reason: string;
readonly source: string;
} & YieldableError<this> {
constructor(...args: [props: {
readonly _tag?: "JsonPatchValidationError";
readonly reason: string;
readonly source: string;
}, options?: MakeOptions]);
message: string;
}

Example

(Creating a validation error)

import { JsonPatchValidationError } from "@effect/openapi-generator/OpenApiPatch"
const error = new JsonPatchValidationError({
source: "inline",
reason: "Expected 'add' | 'remove' | 'replace' at [0].op, got 'copy'"
})
error.message // => "Invalid JSON Patch from inline: Expected 'add' | 'remove' | 'replace' at [0].op, got 'copy'"

Models

JsonPatchDocument type

Added in v4.0.0 Source

Type for a JSON Patch document.

Signature

type JsonPatchDocument = typeof JsonPatchDocument.Type

Parsing

Parse a JSON Patch from either a file path or inline JSON string.

Details

The input is first checked as a file path. If the file exists, it is read and parsed based on its extension (.json, .yaml, .yml). Otherwise, the input is parsed as inline JSON.

Signature

declare const parsePatchInput: (...args: [input: string]) => Effect<readonly Array<JsonPatchOperation>, JsonPatchParseError | JsonPatchValidationError, Path | FileSystem>

Example

(Parsing patch input)

import { Effect } from "effect"
import { parsePatchInput } from "@effect/openapi-generator/OpenApiPatch"
// From inline JSON
const fromInline = parsePatchInput(
'[{"op":"replace","path":"/info/title","value":"My API"}]'
)
const program = Effect.gen(function*() {
const patch = yield* fromInline
return [patch[0].op, patch[0].path]
})
Effect.runSync(program) // => ["replace", "/info/title"]

Schemas

JsonPatchAdd

Added in v4.0.0 Source

Schema for a JSON Patch "add" operation.

Signature

declare const JsonPatchAdd: Schema.Codec<Extract<JsonPatch.JsonPatchOperation, {
op: "add";
}>>

Schema for a JSON Patch document (array of operations).

Details

A JSON Patch document is an ordered list of operations to apply to a JSON document. Operations are applied in sequence, with each operation seeing the result of previous operations.

Signature

declare const JsonPatchDocument: $Array<Codec<JsonPatchOperation, JsonPatchOperation, never, never>>

Example

(Decoding a patch document)

import { Schema } from "effect"
import { JsonPatchDocument } from "@effect/openapi-generator/OpenApiPatch"
const patch = Schema.decodeUnknownSync(JsonPatchDocument)([
{ op: "add", path: "/foo", value: "bar" },
{ op: "remove", path: "/baz" },
{ op: "replace", path: "/qux", value: 42 }
])
patch.map((operation) => operation.op) // => ["add", "remove", "replace"]

Schema for a single JSON Patch operation.

Details

Supports the subset of RFC 6902 operations that Effect's JsonPatch module implements: add, remove, and replace.

Signature

declare const JsonPatchOperation: Schema.Codec<JsonPatch.JsonPatchOperation>

Schema for a JSON Patch "remove" operation.

Signature

declare const JsonPatchRemove: Schema.Codec<Extract<JsonPatch.JsonPatchOperation, {
op: "remove";
}>>

Schema for a JSON Patch "replace" operation.

Signature

declare const JsonPatchReplace: Schema.Codec<Extract<JsonPatch.JsonPatchOperation, {
op: "replace";
}>>

Transforming

applyPatches

Added in v4.0.0 Source

Apply a sequence of JSON patches to a document.

Details

Patches are applied in order, with each patch operating on the result of the previous one. All operations are attempted, and if any fail, the errors are accumulated and reported together so users can fix all issues at once.

Signature

declare const applyPatches: (...args: [patches: readonly Array<{
readonly patch: readonly Array<JsonPatchOperation>;
readonly source: string;
}>, document: Json]) => Effect<Json, JsonPatchAggregateError, never>

Example

(Applying patches)

import { Effect } from "effect"
import { applyPatches } from "@effect/openapi-generator/OpenApiPatch"
const document = { info: { title: "Old Title" }, paths: {} }
const patches = [
{
source: "inline",
patch: [{ op: "replace" as const, path: "/info/title", value: "New Title" }]
}
]
const program = Effect.gen(function*() {
const result = yield* applyPatches(patches, document)
return (result as typeof document).info.title
})
Effect.runSync(program) // => "New Title"