{"id":29541194,"url":"https://github.com/christianhelle/openapi2zig","last_synced_at":"2026-07-19T23:00:41.342Z","repository":{"id":304879266,"uuid":"1013999278","full_name":"christianhelle/openapi2zig","owner":"christianhelle","description":"A tool for generating API clients and models in Zig from OpenAPI specifications","archived":false,"fork":false,"pushed_at":"2026-07-19T22:57:01.000Z","size":3900,"stargazers_count":20,"open_issues_count":1,"forks_count":4,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-07-19T23:00:13.733Z","etag":null,"topics":["openapi","zig"],"latest_commit_sha":null,"homepage":"http://christianhelle.com/openapi2zig/","language":"Zig","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/christianhelle.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"github":"christianhelle","patreon":null,"open_collective":null,"ko_fi":"christianhelle","tidelift":null,"community_bridge":null,"liberapay":"christianhelle","issuehunt":null,"otechie":null,"lfx_crowdfunding":null,"custom":["https://paypal.me/christianhelle","https://buymeacoffee.com/christianhelle"]}},"created_at":"2025-07-04T21:06:57.000Z","updated_at":"2026-07-19T21:59:10.000Z","dependencies_parsed_at":"2025-07-17T00:12:17.534Z","dependency_job_id":"587e1e0c-e667-400e-b95a-4c70de5d7ed2","html_url":"https://github.com/christianhelle/openapi2zig","commit_stats":null,"previous_names":["christianhelle/openapi2zig"],"tags_count":5,"template":false,"template_full_name":null,"purl":"pkg:github/christianhelle/openapi2zig","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/christianhelle%2Fopenapi2zig","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/christianhelle%2Fopenapi2zig/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/christianhelle%2Fopenapi2zig/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/christianhelle%2Fopenapi2zig/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/christianhelle","download_url":"https://codeload.github.com/christianhelle/openapi2zig/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/christianhelle%2Fopenapi2zig/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35667461,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-19T02:00:06.923Z","response_time":112,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["openapi","zig"],"created_at":"2025-07-17T09:02:30.680Z","updated_at":"2026-07-19T23:00:41.335Z","avatar_url":"https://github.com/christianhelle.png","language":"Zig","funding_links":["https://github.com/sponsors/christianhelle","https://ko-fi.com/christianhelle","https://liberapay.com/christianhelle","https://paypal.me/christianhelle","https://buymeacoffee.com/christianhelle"],"categories":[],"sub_categories":[],"readme":"# openapi2zig\n\n[![CI](https://github.com/christianhelle/openapi2zig/actions/workflows/ci.yml/badge.svg)](https://github.com/christianhelle/openapi2zig/actions/workflows/ci.yml)\n[![Zig Version](https://img.shields.io/badge/zig-0.16.0%2B-orange.svg)](https://ziglang.org/download/)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\nA CLI tool and Zig library that generates type-safe API client code from OpenAPI specifications.\n\n\u003e **Note**: This project provides both a CLI tool for generating Zig code from OpenAPI specs and a library for parsing and working with OpenAPI documents programmatically in Zig.\n\n## Supported Specifications\n\nThis tool supports the following OpenAPI and Swagger specifications:\n- **Swagger v2.0** - Full support\n- **OpenAPI v3.0** - Full support\n- **OpenAPI v3.1** - Full support\n- **OpenAPI v3.2** - Full support\n\nAll specifications are supported in JSON and YAML format.\n\n## Features\n\n- Parse and generate from Swagger v2.0, OpenAPI v3.0, v3.1, and v3.2 specifications\n- Generate type-safe Zig client code\n- Support for complex OpenAPI schemas and operations\n- Cross-platform support (Linux, macOS, Windows)\n- Available as both CLI tool and Zig library\n- Unified document representation for all OpenAPI and Swagger versions\n\n## Prerequisites\n\n- [Zig](https://ziglang.org/download/) v0.16.0\n\n## Development Environment\n\n### Option 1: GitHub Codespaces (Recommended for Contributors)\n\nThe fastest way to get started with development is using GitHub Codespaces, which provides a pre-configured development environment with Zig, ZLS (Zig Language Server), and all necessary VS Code extensions.\n\n[![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/christianhelle/openapi2zig)\n\n1. Click the badge above or navigate to the repository on GitHub\n2. Click \"Code\" → \"Codespaces\" → \"Create codespace\"\n3. Wait for the environment to set up (2-3 minutes)\n4. Start coding! Everything is pre-configured.\n\n### Option 2: VS Code Dev Containers (Local)\n\nIf you prefer local development with Docker:\n\n1. Install [VS Code](https://code.visualstudio.com/) and the [Dev Containers extension](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers)\n2. Clone the repository and open it in VS Code\n3. When prompted, click \"Reopen in Container\"\n4. VS Code will build and configure the development environment automatically\n\n### Option 3: Manual Setup\n\nInstall Zig locally following the official [installation guide](https://ziglang.org/download/).\n\n## Installation\n\n### Option 1: Quick Install Script (Recommended)\n\n**Linux/macOS:**\n\n```bash\ncurl -fsSL https://christianhelle.com/openapi2zig/install | bash\n```\n\n**Windows (PowerShell):**\n\n```powershell\nirm https://christianhelle.com/openapi2zig/install.ps1 | iex\n```\n\nThe install scripts will:\n\n- Automatically detect your platform and architecture\n- Download the latest release from GitHub\n- Install the binary to an appropriate location\n- Add it to your PATH (if desired)\n\n**Custom installation directory:**\n\n```bash\n# Linux/macOS\nINSTALL_DIR=$HOME/.local/bin curl -fsSL https://christianhelle.com/openapi2zig/install | bash\n\n# Windows\nirm https://christianhelle.com/openapi2zig/install.ps1 | iex -InstallDir \"C:\\Tools\"\n```\n\n### Option 2: Manual Download\n\nDownload the latest release for your platform from the [GitHub Releases page](https://github.com/christianhelle/openapi2zig/releases/latest):\n\n- **Linux x86_64:** `openapi2zig-linux-x86_64.tar.gz`\n- **macOS x86_64:** `openapi2zig-macos-x86_64.tar.gz`\n- **macOS ARM64:** `openapi2zig-macos-aarch64.tar.gz`\n- **Windows x86_64:** `openapi2zig-windows-x86_64.zip`\n\nExtract the archive and add the binary to your PATH.\n\n### Option 3: Install from Snap Store\n\nInstall the latest build for Linux from the Snap Store:\n\n```bash\nsnap install --edge openapi2zig\n```\n\n### Option 4: Build from Source\n\nMake sure you have Zig installed (version 0.16.0 or newer).\n\n```bash\ngit clone https://github.com/christianhelle/openapi2zig.git\ncd openapi2zig\nzig build\n```\n\n### Option 5: Use Docker\n\nThe openapi2zig is available as a Docker image on Docker Hub at `christianhelle/openapi2zig`.\n\n```bash\n# Pull the latest image\ndocker pull christianhelle/openapi2zig\n```\n\n## Quick Start\n\n### Building from Source\n\n1. Clone the repository:\n\n   ```bash\n   git clone https://github.com/christianhelle/openapi2zig.git\n   cd openapi2zig\n   ```\n\n2. Build the project:\n\n   ```bash\n   zig build\n   ```\n\n3. Run tests to verify everything works:\n\n   ```bash\n   zig build test\n   ```\n\n4. The compiled binary will be available in `zig-out/bin/openapi2zig`\n\n### Development\n\nFor development builds with debug information:\n\n```bash\nzig build -Doptimize=Debug\n```\n\nTo run tests during development:\n\n```bash\nzig build test\n```\n\nTo check code formatting:\n\n```bash\nzig fmt --check src/\nzig fmt --check build.zig\n```\n\n### Smoke tests\n\nRun the broad smoke-test script to validate code generation against every supported sample specification:\n\n```bash\npwsh test/smoke-tests.ps1\n```\n\nWhat it does:\n\n- Validates all eligible JSON and YAML API specs under `openapi/v2.0`, `openapi/v3.0`, `openapi/v3.1`, and `openapi/v3.2`.\n- Runs each spec through every resource-wrapper mode: `none`, `tags`, `paths`, and `hybrid`.\n- Ignores the meta-schema documents under `openapi/json-schema/`, which are outside the smoke-test discovery roots.\n- Writes generated outputs to `test/output/` (gitignored), with filenames shaped like `\u003cbasename\u003e__\u003cformat\u003e__\u003cmode\u003e.zig` so JSON/YAML sibling fixtures do not collide.\n- Continues through individual failures and prints a final summary listing every failing spec/mode combination, then exits non-zero if any case failed.\n- Honors a temporary denylist for known-unsupported spec/mode combinations so the PR gate can stay green while generator gaps are tracked explicitly.\n\nIn CI, the same script runs in the `smoke-tests` job on pull requests and `main`, alongside the existing `zig build run-generate` + `zig run generated/main.zig` curated sample harness. The broad smoke discovery does not require JSON/YAML twins: YAML-only roots such as `openapi/v3.0/bot.paths.yaml` are still included when they live under the covered version folders. When the smoke-tests job fails, `test/output/` is uploaded as a workflow artifact for triage.\n\n### Cross-compilation\n\nBuild for different targets:\n\n```bash\n# Windows\nzig build -Dtarget=x86_64-windows\n\n# macOS\nzig build -Dtarget=x86_64-macos\n\n# Linux ARM64\nzig build -Dtarget=aarch64-linux\n```\n\n## Usage\n\n```bash\nopenapi2zig generate [options]\n```\n\nThe `generate` command reads a JSON or YAML OpenAPI/Swagger document from a local file or `http`/`https` URL, auto-detects the spec version, and writes one Zig source file containing models, runtime helpers, and API functions.\n\n### Options\n\n| Flag | Description |\n| :--- | :--- |\n| `-i`, `--input \u003cPATH_OR_URL\u003e` | OpenAPI/Swagger JSON or YAML spec from a file path or `http`/`https` URL. Required. |\n| `-o`, `--output \u003cpath\u003e` | Output file for the generated Zig code. Defaults to `generated.zig`. Parent directories are created when needed. |\n| `--base-url \u003curl\u003e` | Base URL baked into the generated `Client`. Defaults to the server URL from the OpenAPI/Swagger document. |\n| `--resource-wrappers \u003cmode\u003e` | Generate resource wrapper namespaces. Modes: `none`, `tags`, `paths`, `hybrid`. Defaults to `paths`. |\n\n### Examples\n\n**From a local file:**\n```bash\nopenapi2zig generate -i openapi/v3.0/petstore.json -o api.zig\n```\n\n**From a local YAML file:**\n```bash\nopenapi2zig generate -i openapi/v3.0/petstore.yaml -o api.zig\n```\n\n**From a remote URL:**\n```bash\nopenapi2zig generate -i https://petstore3.swagger.io/api/v3/openapi.json -o api.zig\n```\n\n**Override the generated client's base URL:**\n```bash\nopenapi2zig generate -i openapi/v3.0/petstore.json -o api.zig --base-url https://petstore3.swagger.io/api/v3\n```\n\n**Disable resource wrapper namespaces and keep only flat endpoint functions:**\n```bash\nopenapi2zig generate -i openapi/v3.0/petstore.json -o api.zig --resource-wrappers none\n```\n\n### Generated sample files\n\nThe build script also includes curated sample-generation targets used by the checked-in generated harness:\n\n```bash\nzig build run-generate-v2   # openapi/v2.0/petstore.json  -\u003e generated/generated_v2.zig\nzig build run-generate-v2-yaml  # openapi/v2.0/petstore.yaml -\u003e generated/generated_v2_yaml.zig\nzig build run-generate-v3   # openapi/v3.0/petstore.json  -\u003e generated/generated_v3.zig\nzig build run-generate-v3-yaml  # openapi/v3.0/petstore.yaml -\u003e generated/generated_v3_yaml.zig\nzig build run-generate-v31  # openapi/v3.1/webhook-example.json -\u003e generated/generated_v31.zig\nzig build run-generate-v31-yaml # openapi/v3.1/webhook-example.yaml -\u003e generated/generated_v31_yaml.zig\nzig build run-generate-v32  # openapi/v3.2/petstore.json  -\u003e generated/generated_v32.zig\nzig build run-generate      # runs all of the above\n```\n\nThis quick harness is intentionally selective: it covers the curated v2/v3 petstore JSON+YAML outputs, the v3.1 webhook JSON+YAML outputs, and the v3.2 JSON output. `openapi/v3.2` remains JSON-only here because the repository does not currently ship a v3.2 YAML root fixture. For broader JSON+YAML fixture coverage across the sample tree, use `pwsh test/smoke-tests.ps1`. `generated/main.zig` imports the curated v2/v3 JSON+YAML modules plus the v3.1 YAML module, initializes `Client` values, and exercises memory-managed endpoint calls. `generated/compile_generated.zig` extends compile coverage across all curated generated artifacts. When Zig is available, validate generated examples with:\n\n```bash\nzig build run-generate\nzig build test\nzig test generated/compile_generated.zig\nzig build-exe generated/main.zig -fno-emit-bin\nzig build test-package\n```\n\n## Using as a Library\n\nopenapi2zig can also be used as a Zig library for parsing OpenAPI/Swagger specifications and generating code programmatically.\n\n### Adding as a Dependency\n\nAdd openapi2zig to your `build.zig.zon`:\n\n```zig\n.{\n    .name = \"my-project\",\n    .version = \"0.1.0\",\n    .dependencies = .{\n        .openapi2zig = .{\n            .url = \"https://github.com/christianhelle/openapi2zig/archive/refs/tags/v1.0.0.tar.gz\",\n            .hash = \"12345...\", // Replace with actual hash from `zig fetch`\n        },\n    },\n}\n```\n\nThen in your `build.zig`:\n\n```zig\nconst openapi2zig_dep = b.dependency(\"openapi2zig\", .{\n    .target = target,\n    .optimize = optimize,\n});\n\nexe.root_module.addImport(\"openapi2zig\", openapi2zig_dep.module(\"openapi2zig\"));\n```\n\nThe repository includes a minimal downstream consumer fixture in `examples/package_consumer/`, and `zig build test-package` builds it against a clean package snapshot so ignored local files cannot mask packaging issues.\n\n### Library Usage Example\n\n```zig\nconst std = @import(\"std\");\nconst openapi2zig = @import(\"openapi2zig\");\n\npub fn main(init: std.process.Init) !void {\n    const allocator = init.gpa;\n    const io = init.io;\n\n    // Read OpenAPI specification\n    const content = try std.Io.Dir.cwd().readFileAlloc(io, \"api.json\", allocator, .limited(1024 * 1024));\n    defer allocator.free(content);\n\n    // Detect version\n    const version = try openapi2zig.detectVersion(allocator, content);\n    std.debug.print(\"Detected version: {}\\n\", .{version});\n\n    // Parse to unified document representation\n    var unified_doc = try openapi2zig.parseToUnified(allocator, content);\n    defer unified_doc.deinit(allocator);\n\n    std.debug.print(\"API: {s} v{s}\\n\", .{ unified_doc.info.title, unified_doc.info.version });\n\n    // Generate Zig code\n    const args = openapi2zig.CliArgs{\n        .input_path = \"api.json\",\n        .output_path = null,\n        .base_url = \"https://api.example.com\",\n    };\n\n    const generated_code = try openapi2zig.generateCode(allocator, io, unified_doc, args);\n    defer allocator.free(generated_code);\n\n    // Write generated code to file\n    try std.Io.Dir.cwd().writeFile(io, .{ .sub_path = \"generated.zig\", .data = generated_code });\n}\n```\n\n### Library API Reference\n\n#### Version Detection\n\n- `detectVersion(allocator, json_content)` - Detect OpenAPI/Swagger version from JSON\n- `detectVersionFromYaml(allocator, yaml_content)` - Detect OpenAPI/Swagger version from YAML\n- `ApiVersion` - Enum representing supported API versions (.v2_0, .v3_0, .v3_1, .v3_2, .Unsupported)\n\n#### Parsing Functions\n\n- `parseToUnified(allocator, json_content)` - Parse any supported JSON version (v2.0, v3.0, v3.1, v3.2) to unified representation\n- `parseOpenApi(allocator, json_content)` - Parse OpenAPI v3.0 specifically\n- `parseOpenApiYaml(allocator, yaml_content)` - Parse OpenAPI v3.0 YAML specifically\n- `parseOpenApi31(allocator, json_content)` - Parse OpenAPI v3.1 specifically\n- `parseOpenApi31Yaml(allocator, yaml_content)` - Parse OpenAPI v3.1 YAML specifically\n- `parseOpenApi32(allocator, json_content)` - Parse OpenAPI v3.2 specifically\n- `parseOpenApi32Yaml(allocator, yaml_content)` - Parse OpenAPI v3.2 YAML specifically\n- `parseSwagger(allocator, json_content)` - Parse Swagger v2.0 specifically\n- `parseSwaggerYaml(allocator, yaml_content)` - Parse Swagger v2.0 YAML specifically\n\n#### Code Generation\n\n- `generateCode(allocator, io, unified_doc, args)` - Generate complete Zig code (models + API). The output begins with a versioned `\u003cauto-generated\u003e` header (generator version, timestamp, and a regeneration warning); any manual edits will be overwritten when the code is regenerated.\n- `generateModels(allocator, unified_doc)` - Generate only model structs\n- `generateApi(allocator, unified_doc, args)` - Generate only API client functions\n\n#### Conversion Functions\n\n- `convertSwaggerToUnified(allocator, swagger_doc)` - Convert Swagger v2.0 to unified format\n- `convertOpenApiToUnified(allocator, openapi_doc)` - Convert OpenAPI v3.0 to unified format\n- `convertOpenApi31ToUnified(allocator, openapi_doc)` - Convert OpenAPI v3.1 to unified format\n- `convertOpenApi32ToUnified(allocator, openapi_doc)` - Convert OpenAPI v3.2 to unified format\n\n#### Data Types\n\n- `UnifiedDocument` - Common document representation for all OpenAPI and Swagger versions\n- `SwaggerDocument` - Swagger v2.0 specific document structure\n- `OpenApiDocument` - OpenAPI v3.0 specific document structure\n- `OpenApi31Document` - OpenAPI v3.1 specific document structure\n- `OpenApi32Document` - OpenAPI v3.2 specific document structure\n- `DocumentInfo`, `Schema`, `Operation`, etc. - Various OpenAPI components\n\n## Generated Output Structure\n\nGenerated files are self-contained Zig source files. The current unified generator emits:\n\n- Schema declarations such as `Pet`, `Order`, and nested helper types.\n- A reusable `Client` struct with allocator, `std.Io`, `std.http.Client`, API key, base URL, optional organization/project headers, and borrowed `default_headers`. `default_headers` and all header name/value storage must stay alive while requests use them.\n- Memory-safe response wrappers: `Owned(T)`, `RawResponse`, `ParseErrorResponse`, and `ApiResult(T)`.\n- Endpoint triplets when a response schema is known:\n  - `operation(...) !Owned(T)` for convenience parsed responses.\n  - `operationRaw(...) !RawResponse` for status/body inspection.\n  - `operationResult(...) !ApiResult(T)` for parsed success plus preserved API/parse-error bodies.\n- Generic helpers such as `requestRaw`, `getRaw`, `postJsonRaw`, `getJsonResult`, and `postJsonResult`.\n- Query parameter helpers that percent-encode names and string values with `std.Uri.Component.percentEncode`; optional query parameters are nullable.\n- Bounded SSE parsing helpers: `parseSseBytes`, `parseSseReader`, `parseSseBytesTyped`, and `parseSseReaderTyped`. Stream helpers are generated for every POST operation whose response declares `text/event-stream` content — the function name is `{operationId}Streaming` (with an `Events` variant for typed JSON events).\n- Resource wrapper namespaces by default, for example `pet.get(...)` and `store.order.get(...)`, derived from paths unless `--resource-wrappers` changes the mode. Wrapper names are sanitized generated conveniences, not hand-designed SDK names.\n\nParsed JSON responses use `.ignore_unknown_fields = true` so compatible providers can add response fields without breaking callers. Ambiguous or intentionally open-ended schemas use `std.json.Value`; see [`docs/json-value-typing-policy.md`](docs/json-value-typing-policy.md) for the current policy. For OpenAPI 3.1, the converter has stronger composite-schema handling for object/ref `allOf`, preserved `oneOf`/`anyOf` metadata, and nullable type arrays; do not assume every converter has identical composite support.\n\n### Request body content types\n\nThe generator inspects each operation's request body (or Swagger 2.0 `consumes`) and picks the first JSON-flavoured media type when one is available. Bodies classified as binary (`application/octet-stream`, `image/*`, `audio/*`, `video/*`, `*/*`, other `application/*`) or text (`text/*`) generate a `requestBody: []const u8` parameter that is passed straight to `std.http.Client.fetch` with the matching `Content-Type` header — no JSON encoding is applied.\n\n**Known limitations:** `multipart/form-data` and `application/x-www-form-urlencoded` request bodies are not yet supported. Operations declaring those media types currently fall back to JSON encoding and emit a `TODO(#53-followup)` comment in the generated source; full multipart support is tracked as follow-up work.\n\n## Example Generated Code\n\nThe snippets below reflect the current output from `zig build run-generate-v3`.\n\n### Models\n\n```zig\npub const Tag = struct {\n    id: ?i64 = null,\n    name: ?[]const u8 = null,\n};\n\npub const Category = struct {\n    id: ?i64 = null,\n    name: ?[]const u8 = null,\n};\n\npub const Pet = struct {\n    status: ?[]const u8 = null,\n    tags: ?[]const Tag = null,\n    category: ?Category = null,\n    id: ?i64 = null,\n    name: []const u8,\n    photoUrls: []const []const u8,\n};\n```\n\n### Client and response wrappers\n\n```zig\npub fn Owned(comptime T: type) type {\n    return struct {\n        allocator: std.mem.Allocator,\n        body: []u8,\n        parsed: std.json.Parsed(T),\n\n        pub fn deinit(self: *@This()) void {\n            self.parsed.deinit();\n            self.allocator.free(self.body);\n        }\n\n        pub fn value(self: *@This()) *T {\n            return \u0026self.parsed.value;\n        }\n    };\n}\n\npub const RawResponse = struct {\n    allocator: std.mem.Allocator,\n    status: std.http.Status,\n    body: []u8,\n\n    pub fn deinit(self: *@This()) void {\n        self.allocator.free(self.body);\n    }\n};\n\npub fn ApiResult(comptime T: type) type {\n    return union(enum) {\n        ok: Owned(T),\n        api_error: RawResponse,\n        parse_error: ParseErrorResponse,\n\n        pub fn deinit(self: *@This()) void {\n            switch (self.*) {\n                .ok =\u003e |*value| value.deinit(),\n                .api_error =\u003e |*value| value.deinit(),\n                .parse_error =\u003e |*value| value.raw.deinit(),\n            }\n        }\n    };\n}\n\npub const Client = struct {\n    allocator: std.mem.Allocator,\n    io: std.Io,\n    http: std.http.Client,\n    api_key: []const u8,\n    base_url: []const u8 = \"https://petstore3.swagger.io/api/v3\",\n    organization: ?[]const u8 = null,\n    project: ?[]const u8 = null,\n    default_headers: []const std.http.Header = \u0026.{},\n\n    pub fn init(allocator: std.mem.Allocator, io: std.Io, api_key: []const u8) Client {\n        return .{\n            .allocator = allocator,\n            .io = io,\n            .http = .{ .allocator = allocator, .io = io },\n            .api_key = api_key,\n        };\n    }\n\n    pub fn deinit(self: *Client) void {\n        self.http.deinit();\n    }\n\n    pub fn withBaseUrl(self: *Client, base_url: []const u8) void {\n        self.base_url = base_url;\n    }\n};\n```\n\n### Endpoint functions\n\n```zig\npub fn getPetById(client: *Client, petId: i64) !Owned(Pet) {\n    var result = try getPetByIdResult(client, petId);\n    switch (result) {\n        .ok =\u003e |ok| return ok,\n        .api_error =\u003e |*err| {\n            err.deinit();\n            return error.ResponseError;\n        },\n        .parse_error =\u003e |*err| {\n            err.raw.deinit();\n            return error.ResponseParseError;\n        },\n    }\n}\n\npub fn getPetByIdRaw(client: *Client, petId: i64) !RawResponse {\n    const allocator = client.allocator;\n    var uri_buf: std.Io.Writer.Allocating = .init(allocator);\n    defer uri_buf.deinit();\n    try uri_buf.writer.print(\"{s}/pet/{d}\", .{ client.base_url, petId });\n    const payload: ?[]const u8 = null;\n\n    return requestRaw(client, std.http.Method.GET, uri_buf.written(), payload);\n}\n\npub fn getPetByIdResult(client: *Client, petId: i64) !ApiResult(Pet) {\n    return parseRawResponse(Pet, try getPetByIdRaw(client, petId));\n}\n```\n\n### Calling generated code\n\n```zig\nvar client = api.Client.init(allocator, io, \"\");\ndefer client.deinit();\nclient.withBaseUrl(\"https://petstore3.swagger.io/api/v3\");\n\nvar pet = try api.getPetById(\u0026client, 1);\ndefer pet.deinit();\nstd.debug.print(\"pet name: {s}\\n\", .{pet.value().name});\n\nvar result = try api.getPetByIdResult(\u0026client, 1);\ndefer result.deinit();\nswitch (result) {\n    .ok =\u003e |*ok| std.debug.print(\"pet id: {?}\\n\", .{ok.value().id}),\n    .api_error =\u003e |raw| std.debug.print(\"HTTP status: {}\\n{s}\\n\", .{ raw.status, raw.body }),\n    .parse_error =\u003e |parse| std.debug.print(\"parse error: {s}\\n{s}\\n\", .{ parse.error_name, parse.raw.body }),\n}\n\n// Default path resource wrappers are also exported:\nvar wrapped = try api.pet.get(\u0026client, 1);\ndefer wrapped.deinit();\n```\n\n## Contributing\n\n1. Fork the repository\n2. Create a feature branch (`git checkout -b feature/amazing-feature`)\n3. Make your changes\n4. Run tests and ensure they pass (`zig build test`)\n5. Check code formatting (`zig fmt --check src/`)\n6. Commit your changes (`git commit -am 'Add some amazing feature'`)\n7. Push to the branch (`git push origin feature/amazing-feature`)\n8. Open a Pull Request\n\n### Code Style\n\nThis project follows standard Zig formatting. Use `zig fmt` to format your code before committing.\n\n## Project Status\n\n🚀 **Active Development** 🚀\n\nThis project is in active development with solid foundation for OpenAPI/Swagger support. Current capabilities include:\n\n- Full parsing support for Swagger v2.0, OpenAPI v3.0, v3.1, and v3.2 specifications\n- Comprehensive data model structures for all OpenAPI versions\n- Generate type-safe API client code using `std.http.Client`\n- Extensive test suite covering all specification versions\n- Cross-compilation support (Linux, macOS, Windows)\n- Both CLI tool and Zig library interfaces\n\nPlanned features and enhancements:\n\n- Enhanced authentication/authorization client support\n- Automatic API documentation generation\n- Performance optimizations for large specifications\n\n## License\n\nThis project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.\n\n## Support\n\nIf you encounter any issues or have questions, please [open an issue](https://github.com/christianhelle/openapi2zig/issues) on GitHub.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchristianhelle%2Fopenapi2zig","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fchristianhelle%2Fopenapi2zig","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchristianhelle%2Fopenapi2zig/lists"}