Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions build.zig
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,20 @@ pub fn build(b: *std.Build) void {
const run_generate_v3_step = b.step("run-generate-v3", "Run the app with generate command");
run_generate_v3_step.dependOn(&run_generate_v3_cmd.step);

const run_generate_v3_multi_cmd = b.addRunArtifact(exe);
run_generate_v3_multi_cmd.addArgs(&.{
"generate",
"-i",
"openapi/v3.0/petstore.json",
"-o",
"generated/multi",
"--multiple-files",
"--base-url",
"https://petstore3.swagger.io/api/v3",
});
const run_generate_v3_multi_step = b.step("run-generate-v3-multi", "Generate multiple output files (models, runtime, client)");
run_generate_v3_multi_step.dependOn(&run_generate_v3_multi_cmd.step);

const run_generate_v2_cmd = b.addRunArtifact(exe);
run_generate_v2_cmd.addArgs(&.{
"generate",
Expand Down Expand Up @@ -188,6 +202,7 @@ pub fn build(b: *std.Build) void {

const run_generate = b.step("run-generate", "Run the app with generate commands");
run_generate.dependOn(&run_generate_v3_cmd.step);
run_generate.dependOn(&run_generate_v3_multi_cmd.step);
run_generate.dependOn(&run_generate_v3_yaml_cmd.step);
run_generate.dependOn(&run_generate_v2_cmd.step);
run_generate.dependOn(&run_generate_v2_yaml_cmd.step);
Expand Down Expand Up @@ -233,6 +248,16 @@ pub fn build(b: *std.Build) void {
const run_generated_tests = b.addRunArtifact(generated_tests);
test_step.dependOn(&run_generated_tests.step);

const multi_generated_tests = b.addTest(.{
.root_module = b.createModule(.{
.root_source_file = b.path("generated/compile_multi_generated.zig"),
.target = target,
.optimize = optimize,
}),
});
const run_multi_generated_tests = b.addRunArtifact(multi_generated_tests);
test_step.dependOn(&run_multi_generated_tests.step);

const test_package_cmd = b.addSystemCommand(&.{ b.graph.zig_exe, "build" });
test_package_cmd.step.dependOn(package_snapshot_step);
test_package_cmd.setCwd(b.path(".zig-cache/package-snapshot/examples/package_consumer"));
Expand Down
230 changes: 114 additions & 116 deletions generated/anthropic.zig
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// <auto-generated>
// this code was generated by openapi2zig 0.4.0 (2446685) on 2026-07-22 13:15:10 UTC
// changes to this file may cause incorrect behavior and will be lost if the code is regenerated
// This code was generated by openapi2zig 0.4.0 (f1b1b79) on 2026-07-29 10:38:20 UTC
// Changes to this file may cause incorrect behavior and will be lost if the code is regenerated
// </auto-generated>

const std = @import("std");
Expand Down Expand Up @@ -11646,6 +11646,118 @@ pub fn getJsonResult(comptime T: type, client: *Client, path: []const u8) !ApiRe
pub fn postJsonResult(comptime T: type, client: *Client, path: []const u8, payload: anytype) !ApiResult(T) {
return parseRawResponse(T, try postJsonRaw(client, path, payload));
}
fn stringifyStreamRequest(allocator: std.mem.Allocator, requestBody: anytype) ![]u8 {
var buf: std.Io.Writer.Allocating = .init(allocator);
defer buf.deinit();
try std.json.Stringify.value(requestBody, .{ .emit_null_optional_fields = false }, &buf.writer);

var parsed = try std.json.parseFromSlice(std.json.Value, allocator, buf.written(), .{ .ignore_unknown_fields = true });
defer parsed.deinit();

if (parsed.value == .object) {
try parsed.value.object.put(parsed.arena.allocator(), "stream", .{ .bool = true });
}

var out: std.Io.Writer.Allocating = .init(allocator);
errdefer out.deinit();
try std.json.Stringify.value(parsed.value, .{ .emit_null_optional_fields = false }, &out.writer);
return try out.toOwnedSlice();
}

fn streamJsonTyped(comptime T: type, client: *Client, path: []const u8, requestBody: anytype, callback: anytype, cancellation_token: ?*CancellationToken) !void {
const Callback = @TypeOf(callback.*);
var typed_callback: TypedSseCallback(T, Callback) = .{ .allocator = client.allocator, .callback = callback };
try streamJson(client, path, requestBody, &typed_callback, cancellation_token);
}

fn streamJson(client: *Client, path: []const u8, requestBody: anytype, callback: anytype, cancellation_token: ?*CancellationToken) !void {
const allocator = client.allocator;
const payload = try stringifyStreamRequest(allocator, requestBody);
defer allocator.free(payload);

var headers = std.ArrayList(std.http.Header).empty;
defer headers.deinit(allocator);
const auth_header = try appendClientHeaders(allocator, &headers, client, "application/json", "text/event-stream");
defer if (auth_header) |value| allocator.free(value);

const url = try std.fmt.allocPrint(allocator, "{s}{s}", .{ client.base_url, path });
defer allocator.free(url);

if (client.http_observer) |obs| {
if (obs.onRequest) |cb| cb(obs.ctx, .POST, url, headers.items, payload);
}

const uri = try std.Uri.parse(url);
try checkCancellation(cancellation_token);

const start = std.Io.Clock.awake.now(client.io);
var req = client.http.request(.POST, uri, .{
.redirect_behavior = .unhandled,
.headers = .{ .accept_encoding = .{ .override = "identity" } },
.extra_headers = headers.items,
}) catch |err| {
if (client.http_observer) |obs| {
if (obs.onError) |cb| cb(obs.ctx, .POST, url, @errorName(err));
}
return err;
};
defer req.deinit();

req.transfer_encoding = .{ .content_length = payload.len };
var request_body = try req.sendBodyUnflushed(&.{});
try request_body.writer.writeAll(payload);
try request_body.end();
try req.connection.?.flush();
try checkCancellation(cancellation_token);

var response = req.receiveHead(&.{}) catch |err| {
if (client.http_observer) |obs| {
if (obs.onError) |cb| cb(obs.ctx, .POST, url, @errorName(err));
}
return err;
};
const elapsed_ns = @as(u64, @intCast(start.untilNow(client.io, .awake).nanoseconds));
if (response.head.status.class() != .success) {
if (client.http_observer) |obs| {
if (obs.onResponse) |cb| cb(obs.ctx, .POST, url, response.head.status, &.{}, "", elapsed_ns);
}
return error.ResponseError;
}

if (client.http_observer) |obs| {
if (obs.onResponse) |cb| cb(obs.ctx, .POST, url, response.head.status, &.{}, "", elapsed_ns);
}

var transfer_buffer: [8 * 1024]u8 = undefined;
const reader = response.reader(&transfer_buffer);
parseSseReader(allocator, reader, callback, cancellation_token) catch |err| switch (err) {
error.ReadFailed => return response.bodyErr() orelse err,
else => return err,
};
}

fn appendClientHeaders(allocator: std.mem.Allocator, headers: *std.ArrayList(std.http.Header), client: *Client, content_type: ?[]const u8, accept: []const u8) !?[]u8 {
if (content_type) |ct| {
try headers.append(allocator, .{ .name = "Content-Type", .value = ct });
}
try headers.append(allocator, .{ .name = "Accept", .value = accept });

var auth_header: ?[]u8 = null;
if (client.api_key.len > 0) {
auth_header = try std.fmt.allocPrint(allocator, "Bearer {s}", .{client.api_key});
try headers.append(allocator, .{ .name = "Authorization", .value = auth_header.? });
}
if (client.organization) |organization| {
try headers.append(allocator, .{ .name = "OpenAI-Organization", .value = organization });
}
if (client.project) |project| {
try headers.append(allocator, .{ .name = "OpenAI-Project", .value = project });
}
for (client.default_headers) |header| {
try headers.append(allocator, header);
}
return auth_header;
}

pub const CancellationToken = struct {
cancelled: std.atomic.Value(bool),
Expand Down Expand Up @@ -11762,120 +11874,6 @@ pub fn parseSseReaderTyped(comptime T: type, allocator: std.mem.Allocator, reade
var typed_callback: TypedSseCallback(T, Callback) = .{ .allocator = allocator, .callback = callback };
try parseSseReader(allocator, reader, &typed_callback, cancellation_token);
}

fn stringifyStreamRequest(allocator: std.mem.Allocator, requestBody: anytype) ![]u8 {
var buf: std.Io.Writer.Allocating = .init(allocator);
defer buf.deinit();
try std.json.Stringify.value(requestBody, .{ .emit_null_optional_fields = false }, &buf.writer);

var parsed = try std.json.parseFromSlice(std.json.Value, allocator, buf.written(), .{ .ignore_unknown_fields = true });
defer parsed.deinit();

if (parsed.value == .object) {
try parsed.value.object.put(parsed.arena.allocator(), "stream", .{ .bool = true });
}

var out: std.Io.Writer.Allocating = .init(allocator);
errdefer out.deinit();
try std.json.Stringify.value(parsed.value, .{ .emit_null_optional_fields = false }, &out.writer);
return try out.toOwnedSlice();
}

fn streamJsonTyped(comptime T: type, client: *Client, path: []const u8, requestBody: anytype, callback: anytype, cancellation_token: ?*CancellationToken) !void {
const Callback = @TypeOf(callback.*);
var typed_callback: TypedSseCallback(T, Callback) = .{ .allocator = client.allocator, .callback = callback };
try streamJson(client, path, requestBody, &typed_callback, cancellation_token);
}

fn streamJson(client: *Client, path: []const u8, requestBody: anytype, callback: anytype, cancellation_token: ?*CancellationToken) !void {
const allocator = client.allocator;
const payload = try stringifyStreamRequest(allocator, requestBody);
defer allocator.free(payload);

var headers = std.ArrayList(std.http.Header).empty;
defer headers.deinit(allocator);
const auth_header = try appendClientHeaders(allocator, &headers, client, "application/json", "text/event-stream");
defer if (auth_header) |value| allocator.free(value);

const url = try std.fmt.allocPrint(allocator, "{s}{s}", .{ client.base_url, path });
defer allocator.free(url);

if (client.http_observer) |obs| {
if (obs.onRequest) |cb| cb(obs.ctx, .POST, url, headers.items, payload);
}

const uri = try std.Uri.parse(url);
try checkCancellation(cancellation_token);

const start = std.Io.Clock.awake.now(client.io);
var req = client.http.request(.POST, uri, .{
.redirect_behavior = .unhandled,
.headers = .{ .accept_encoding = .{ .override = "identity" } },
.extra_headers = headers.items,
}) catch |err| {
if (client.http_observer) |obs| {
if (obs.onError) |cb| cb(obs.ctx, .POST, url, @errorName(err));
}
return err;
};
defer req.deinit();

req.transfer_encoding = .{ .content_length = payload.len };
var request_body = try req.sendBodyUnflushed(&.{});
try request_body.writer.writeAll(payload);
try request_body.end();
try req.connection.?.flush();
try checkCancellation(cancellation_token);

var response = req.receiveHead(&.{}) catch |err| {
if (client.http_observer) |obs| {
if (obs.onError) |cb| cb(obs.ctx, .POST, url, @errorName(err));
}
return err;
};
const elapsed_ns = @as(u64, @intCast(start.untilNow(client.io, .awake).nanoseconds));
if (response.head.status.class() != .success) {
if (client.http_observer) |obs| {
if (obs.onResponse) |cb| cb(obs.ctx, .POST, url, response.head.status, &.{}, "", elapsed_ns);
}
return error.ResponseError;
}

if (client.http_observer) |obs| {
if (obs.onResponse) |cb| cb(obs.ctx, .POST, url, response.head.status, &.{}, "", elapsed_ns);
}

var transfer_buffer: [8 * 1024]u8 = undefined;
const reader = response.reader(&transfer_buffer);
parseSseReader(allocator, reader, callback, cancellation_token) catch |err| switch (err) {
error.ReadFailed => return response.bodyErr() orelse err,
else => return err,
};
}

fn appendClientHeaders(allocator: std.mem.Allocator, headers: *std.ArrayList(std.http.Header), client: *Client, content_type: ?[]const u8, accept: []const u8) !?[]u8 {
if (content_type) |ct| {
try headers.append(allocator, .{ .name = "Content-Type", .value = ct });
}
try headers.append(allocator, .{ .name = "Accept", .value = accept });

var auth_header: ?[]u8 = null;
if (client.api_key.len > 0) {
auth_header = try std.fmt.allocPrint(allocator, "Bearer {s}", .{client.api_key});
try headers.append(allocator, .{ .name = "Authorization", .value = auth_header.? });
}
if (client.organization) |organization| {
try headers.append(allocator, .{ .name = "OpenAI-Organization", .value = organization });
}
if (client.project) |project| {
try headers.append(allocator, .{ .name = "OpenAI-Project", .value = project });
}
for (client.default_headers) |header| {
try headers.append(allocator, header);
}
return auth_header;
}

const max_sse_line_size = 8192;
const max_sse_event_size = 65536;

Expand Down
7 changes: 7 additions & 0 deletions generated/compile_multi_generated.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
const std = @import("std");

const multi_v3 = @import("multi/client.zig");

test "multi-file generated clients compile" {
std.testing.refAllDecls(multi_v3);
}
Loading
Loading