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
Errors
JsonPatchAggregateError
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:"JsonPatchApplicationError
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'JsonPatchParseError
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"JsonPatchValidationError
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
Type for a JSON Patch document.
Signature
type JsonPatchDocument = typeof JsonPatchDocument.TypeParsing
parsePatchInput
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 JSONconst 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
Schema for a JSON Patch "add" operation.
Signature
declare const JsonPatchAdd: Schema.Codec<Extract<JsonPatch.JsonPatchOperation, { op: "add";}>>JsonPatchDocument
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"]JsonPatchOperation
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>JsonPatchRemove
Schema for a JSON Patch "remove" operation.
Signature
declare const JsonPatchRemove: Schema.Codec<Extract<JsonPatch.JsonPatchOperation, { op: "remove";}>>JsonPatchReplace
Schema for a JSON Patch "replace" operation.
Signature
declare const JsonPatchReplace: Schema.Codec<Extract<JsonPatch.JsonPatchOperation, { op: "replace";}>>Transforming
applyPatches
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"