ownmedia/src/context.zig
2025-11-02 15:55:01 +11:00

91 lines
2.7 KiB
Zig

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("&lt;"),
'>' => _ = try writer.write("&gt;"),
'&' => _ = try writer.write("&amp;"),
'"' => _ = try writer.write("&quot;"),
'\'' => _ = try writer.write("&apos;"),
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", .{});
}