const zap = @import("zap"); const sqlite = @import("sqlite"); const std = @import("std"); const Allocator = std.mem.Allocator; const builtin = @import("builtin"); const optimize_mode = builtin.mode; db_connection: sqlite.Db, counter: u32 = 0, pub fn init(connection: sqlite.Db) @This() { return .{ .db_connection = connection, }; } pub fn SendInertiaResponse(endpoint: anytype, context: ?*@This(), r: zap.Request, arena: Allocator, component: []const u8, props: anytype) !void { _ = context; const inertia_json = try std.fmt.allocPrint( arena, "{f}", .{std.json.fmt(.{ .component = component, .props = .{ .nav = .{}, .page = props, }, .url = endpoint.path, .version = "", }, .{ .escape_unicode = true, })}, ); if (r.getHeader("x-inertia")) |_| { try r.setHeader("X-Inertia", "true"); try r.setHeader("Content-Type", "application/json"); r.setStatus(.ok); try r.sendBody(inertia_json); } else { try r.setHeader("Content-Type", "text/html"); const show_unbuilt_assets = (optimize_mode == .Debug) and (r.getHeader("x-vite") != null); const response_text = try std.fmt.allocPrint( arena, @embedFile("root.html"), .{ (if (show_unbuilt_assets) "/src/favicon.svg" else "/favicon.svg"), (if (show_unbuilt_assets) "/src/main.ts" else "/main.js"), (if (show_unbuilt_assets) "/src/style.css" else "/style.css"), HtmlEncodeFormatter{ .input = inertia_json }, }, ); r.setStatus(.ok); try r.sendBody(response_text); } } pub const HtmlEncodeFormatter = struct { input: []const u8, pub fn format(self: @This(), writer: *std.Io.Writer) std.Io.Writer.Error!void { for (self.input) |char_byte| { switch (char_byte) { '<' => _ = try writer.write("<"), '>' => _ = try writer.write(">"), '&' => _ = try writer.write("&"), '"' => _ = try writer.write("""), '\'' => _ = try writer.write("'"), else => _ = try writer.writeByte(char_byte), } } } }; pub fn unhandledRequest(ctx: *@This(), arena: Allocator, r: zap.Request) anyerror!void { const path = r.path orelse "/not-found"; try SendInertiaResponse(.{ .path = path }, ctx, r, arena, "404", .{}); }