From e98c5ec3dfe2c28e4bb9bbdb34db6ad3942454b9 Mon Sep 17 00:00:00 2001 From: Bob Farrell Date: Sun, 18 Aug 2024 18:51:25 +0100 Subject: [PATCH] Update http.zig Refactor routes generation to standalone exe (fixes some build-time vs. run-time issues). --- build.zig | 79 +++++++++++++++-------------- build.zig.zon | 12 ++--- demo/src/app/views/basic/index.zmpl | 1 + src/Routes.zig | 2 +- src/jetzig.zig | 2 +- src/jetzig/http/Server.zig | 2 +- src/jetzig/testing/App.zig | 8 +-- src/routes_file.zig | 53 +++++++++++++++++++ 8 files changed, 108 insertions(+), 51 deletions(-) create mode 100644 src/routes_file.zig diff --git a/build.zig b/build.zig index b4fb83b..7a6d504 100644 --- a/build.zig +++ b/build.zig @@ -2,13 +2,13 @@ const std = @import("std"); pub const Routes = @import("src/Routes.zig"); pub const GenerateMimeTypes = @import("src/GenerateMimeTypes.zig"); -pub const TemplateFn = @import("src/jetzig.zig").TemplateFn; -pub const StaticRequest = @import("src/jetzig.zig").StaticRequest; -pub const http = @import("src/jetzig/http.zig"); -pub const data = @import("src/jetzig/data.zig"); -pub const views = @import("src/jetzig/views.zig"); -pub const Route = views.Route; -pub const Job = @import("src/jetzig.zig").Job; +// pub const TemplateFn = @import("src/jetzig.zig").TemplateFn; +// pub const StaticRequest = @import("src/jetzig.zig").StaticRequest; +// pub const http = @import("src/jetzig/http.zig"); +// pub const data = @import("src/jetzig/data.zig"); +// pub const views = @import("src/jetzig/views.zig"); +// pub const Route = views.Route; +// pub const Job = @import("src/jetzig.zig").Job; const zmpl_build = @import("zmpl"); @@ -155,39 +155,31 @@ pub fn jetzigInit(b: *std.Build, exe: *std.Build.Step.Compile, options: JetzigIn &[_][]const u8{ root_path, "src", "app", "mailers" }, ); - var routes = try Routes.init( - b.allocator, + const exe_routes_file = b.addExecutable(.{ + .name = "routes", + .root_source_file = jetzig_dep.path("src/routes_file.zig"), + .target = target, + .optimize = optimize, + }); + + exe_routes_file.root_module.addImport("jetzig", jetzig_module); + exe_routes_file.root_module.addImport("jetkv", jetzig_module); + exe_routes_file.root_module.addImport("httpz", jetzig_module); + exe_routes_file.root_module.addImport("zmpl", zmpl_module); + + const run_routes_file_cmd = b.addRunArtifact(exe_routes_file); + const routes_file_path = run_routes_file_cmd.addOutputFileArg("routes.zig"); + run_routes_file_cmd.addArgs(&.{ root_path, + b.pathFromRoot("src"), templates_path, views_path, jobs_path, mailers_path, - ); - const generated_routes = try routes.generateRoutes(); - const routes_write_files = b.addWriteFiles(); - const routes_file = routes_write_files.add("routes.zig", generated_routes); - const tests_write_files = b.addWriteFiles(); - const tests_file = tests_write_files.add("tests.zig", generated_routes); - const routes_module = b.createModule(.{ .root_source_file = routes_file }); - - var src_dir = try std.fs.openDirAbsolute(b.pathFromRoot("src"), .{ .iterate = true }); - defer src_dir.close(); - var walker = try src_dir.walk(b.allocator); - defer walker.deinit(); - - while (try walker.next()) |entry| { - if (entry.kind == .file) { - const stat = try src_dir.statFile(entry.path); - const src_data = try src_dir.readFileAlloc(b.allocator, entry.path, @intCast(stat.size)); - defer b.allocator.free(src_data); - - const relpath = try std.fs.path.join(b.allocator, &[_][]const u8{ "src", entry.path }); - defer b.allocator.free(relpath); - - _ = routes_write_files.add(relpath, src_data); - _ = tests_write_files.add(relpath, src_data); - } - } + }); + const routes_module = b.createModule(.{ .root_source_file = routes_file_path }); + routes_module.addImport("jetzig", jetzig_module); + exe.root_module.addImport("routes", routes_module); const exe_static_routes = b.addExecutable(.{ .name = "static", @@ -196,12 +188,9 @@ pub fn jetzigInit(b: *std.Build, exe: *std.Build.Step.Compile, options: JetzigIn .optimize = optimize, }); - exe.root_module.addImport("routes", routes_module); - exe_static_routes.root_module.addImport("routes", routes_module); exe_static_routes.root_module.addImport("jetzig", jetzig_module); exe_static_routes.root_module.addImport("zmpl", zmpl_module); - // exe_static_routes.root_module.addImport("jetzig_app", &exe.root_module); const markdown_fragments_write_files = b.addWriteFiles(); const path = markdown_fragments_write_files.add("markdown_fragments.zig", try generateMarkdownFragments(b)); @@ -215,8 +204,19 @@ pub fn jetzigInit(b: *std.Build, exe: *std.Build.Step.Compile, options: JetzigIn run_static_routes_cmd.expectExitCode(0); + const run_tests_file_cmd = b.addRunArtifact(exe_routes_file); + const tests_file_path = run_tests_file_cmd.addOutputFileArg("tests.zig"); + run_tests_file_cmd.addArgs(&.{ + root_path, + b.pathFromRoot("src"), + templates_path, + views_path, + jobs_path, + mailers_path, + }); + const exe_unit_tests = b.addTest(.{ - .root_source_file = tests_file, + .root_source_file = tests_file_path, .target = target, .optimize = optimize, .test_runner = jetzig_dep.path("src/test_runner.zig"), @@ -238,6 +238,7 @@ pub fn jetzigInit(b: *std.Build, exe: *std.Build.Step.Compile, options: JetzigIn const test_step = b.step("jetzig:test", "Run tests"); test_step.dependOn(&run_static_routes_cmd.step); test_step.dependOn(&run_exe_unit_tests.step); + test_step.dependOn(&run_tests_file_cmd.step); exe_unit_tests.root_module.addImport("routes", routes_module); const routes_step = b.step("jetzig:routes", "List all routes in your app"); diff --git a/build.zig.zon b/build.zig.zon index 4c85f33..4198870 100644 --- a/build.zig.zon +++ b/build.zig.zon @@ -11,20 +11,20 @@ .hash = "12207c30c6fbcb8c7519719fc47ff9d0acca72a3557ec671984d16260bdf1c832740", }, .jetkv = .{ - .url = "https://github.com/jetzig-framework/jetkv/archive/78bcdcc6b0cbd3ca808685c64554a15701f13250.tar.gz", - .hash = "12201944769794b2f18e3932ec3d5031066d0ccb3293cf7c3fb1f5b269e56b76c57e", + .url = "https://github.com/jetzig-framework/jetkv/archive/cf1c611a9c406ccadb50b1bf7798e2b88c43fd2b.tar.gz", + .hash = "1220434169bfbfbb3a0bbe7073f9bcff5401979a967d25ba3915046f6ea44e40839d", }, .args = .{ .url = "https://github.com/ikskuh/zig-args/archive/03af1b6c5bfda9646a562c861055024daed5b238.tar.gz", .hash = "1220904d2fdcd970dd0d216211d092eb3ef6da01117163cc9393ab845a1d66c029d9", }, .smtp_client = .{ - .url = "https://github.com/karlseguin/smtp_client.zig/archive/48971bc919fe22d2bf6accb832b73ab53e534836.tar.gz", - .hash = "122024d52d160022a6fefdbebfd94ac664f637583c8a44c2a50d0ad12acca160cb17", + .url = "https://github.com/karlseguin/smtp_client.zig/archive/8fcfad9ca2d9e446612c79f4e54050cfbe81b38d.tar.gz", + .hash = "1220cebfcf6c63295819df92ec54abe62aad91b1d16666781194c29a7874bb7bbbda", }, .httpz = .{ - .url = "https://github.com/karlseguin/http.zig/archive/fbca868592dc83ee3ee3cad414c62afa266f4866.tar.gz", - .hash = "122089946af5ba1cdfae3f515f0fa1c96327f42a462515fbcecc719fe94fab38d9b8", + .url = "https://github.com/karlseguin/http.zig/archive/e1df408cd530d058a7e1652bd8dcfa7191ff776e.tar.gz", + .hash = "1220efbc744de6e13e57ab9fa6370ea9690601e55ba6ced74179c081a295c99fd422", }, }, diff --git a/demo/src/app/views/basic/index.zmpl b/demo/src/app/views/basic/index.zmpl index 76457d0..2333601 100644 --- a/demo/src/app/views/basic/index.zmpl +++ b/demo/src/app/views/basic/index.zmpl @@ -1,3 +1,4 @@
Content goes here +
Hello
diff --git a/src/Routes.zig b/src/Routes.zig index eb3bc44..868bede 100644 --- a/src/Routes.zig +++ b/src/Routes.zig @@ -1,5 +1,5 @@ const std = @import("std"); -const jetzig = @import("jetzig.zig"); +const jetzig = @import("jetzig"); ast: std.zig.Ast = undefined, allocator: std.mem.Allocator, diff --git a/src/jetzig.zig b/src/jetzig.zig index 49d58b5..8bcd644 100644 --- a/src/jetzig.zig +++ b/src/jetzig.zig @@ -2,7 +2,7 @@ const std = @import("std"); pub const zmpl = @import("zmpl").zmpl; pub const zmd = @import("zmd").zmd; -pub const jetkv = @import("jetkv"); +pub const jetkv = @import("jetkv").jetkv; pub const http = @import("jetzig/http.zig"); pub const loggers = @import("jetzig/loggers.zig"); diff --git a/src/jetzig/http/Server.zig b/src/jetzig/http/Server.zig index 4a73c9e..40a7875 100644 --- a/src/jetzig/http/Server.zig +++ b/src/jetzig/http/Server.zig @@ -79,7 +79,7 @@ const Dispatcher = struct { pub fn listen(self: *Server) !void { try self.decodeStaticParams(); - var httpz_server = try httpz.ServerCtx(Dispatcher, Dispatcher).init( + var httpz_server = try httpz.Server(Dispatcher).init( self.allocator, .{ .port = self.options.port, diff --git a/src/jetzig/testing/App.zig b/src/jetzig/testing/App.zig index bf35cc7..10375d7 100644 --- a/src/jetzig/testing/App.zig +++ b/src/jetzig/testing/App.zig @@ -135,7 +135,7 @@ pub fn request( return .{ .allocator = self.arena.allocator(), .status = httpz_response.status, - .body = try self.arena.allocator().dupe(u8, httpz_response.body orelse ""), + .body = try self.arena.allocator().dupe(u8, httpz_response.body), .headers = try headers.toOwnedSlice(), .jobs = try jobs.toOwnedSlice(), }; @@ -208,6 +208,7 @@ fn stubbedRequest( multipart_boundary: ?[]const u8, options: RequestOptions, ) !httpz.Request { + // TODO: Use httpz.testing var request_headers = try keyValue(allocator, 32); for (options.headers) |header| request_headers.add(header.name, header.value); if (options.json != null) { @@ -256,6 +257,7 @@ fn stubbedRequest( } fn stubbedResponse(allocator: std.mem.Allocator) !httpz.Response { + // TODO: Use httpz.testing return .{ .conn = undefined, .pos = 0, @@ -265,9 +267,9 @@ fn stubbedResponse(allocator: std.mem.Allocator) !httpz.Response { .arena = allocator, .written = false, .chunked = false, - .disowned = false, .keepalive = false, - .body = null, + .body = "", + .buffer = .{ .pos = 0, .data = "" }, }; } diff --git a/src/routes_file.zig b/src/routes_file.zig new file mode 100644 index 0000000..8fafc02 --- /dev/null +++ b/src/routes_file.zig @@ -0,0 +1,53 @@ +const std = @import("std"); +const Routes = @import("Routes.zig"); + +pub fn main() !void { + var gpa = std.heap.GeneralPurposeAllocator(.{}){}; + defer std.debug.assert(gpa.deinit() == .ok); + const gpa_allocator = gpa.allocator(); + + var arena = std.heap.ArenaAllocator.init(gpa_allocator); + const allocator = arena.allocator(); + defer arena.deinit(); + + var it = try std.process.argsWithAllocator(allocator); + _ = it.next().?; + const output_path = it.next().?; + const root_path = it.next().?; + const src_path = it.next().?; + const templates_path = it.next().?; + const views_path = it.next().?; + const jobs_path = it.next().?; + const mailers_path = it.next().?; + + var routes = try Routes.init( + allocator, + root_path, + templates_path, + views_path, + jobs_path, + mailers_path, + ); + const generated_routes = try routes.generateRoutes(); + var src_dir = try std.fs.openDirAbsolute(src_path, .{ .iterate = true }); + defer src_dir.close(); + var walker = try src_dir.walk(allocator); + defer walker.deinit(); + + while (try walker.next()) |entry| { + if (entry.kind == .file) { + const stat = try src_dir.statFile(entry.path); + const src_data = try src_dir.readFileAlloc(allocator, entry.path, @intCast(stat.size)); + const relpath = try std.fs.path.join(allocator, &[_][]const u8{ "src", entry.path }); + var dir = try std.fs.openDirAbsolute(std.fs.path.dirname(output_path).?, .{}); + const dest_dir = try dir.makeOpenPath(std.fs.path.dirname(relpath).?, .{}); + const src_file = try dest_dir.createFile(std.fs.path.basename(relpath), .{}); + try src_file.writeAll(src_data); + src_file.close(); + } + } + + const file = try std.fs.createFileAbsolute(output_path, .{ .truncate = true }); + try file.writeAll(generated_routes); + file.close(); +}