╭ changed ──╮ │src/web.zig│ ╰───────────╯ ╭───────────╮ │← all files│ ╰───────────╯ ╭────────────────────────────────────╮ │1 const std = @import("std"); │ │2 +const xit = @import("xit"); │ │3 +const rp = xit.repo; │ │4 const ui = @import("./ui.zig"); │ │5 +const pg = @import("./page.zig");│ │6 │ │7 const Asset = struct { │ │8 path: []const u8, │ ╰────────────────────────────────────╯ ╭───────────────────────────────────────╮ │22 allocator: std.mem.Allocator, │ │23 net_server: *std.Io.net.Server,│ │24 tasks: *std.Io.Group, │ │25 + admin_repo_path: []const u8, │ │26 err: *std.Io.Writer, │ │27 ) void { │ │28 const Listener = struct { │ ╰───────────────────────────────────────╯ ╭───────────────────────────────────────────╮ │30 allocator: std.mem.Allocator, │ │31 net_server: *std.Io.net.Server,│ │32 tasks: *std.Io.Group, │ │33 + admin_repo_path: []const u8, │ │34 err: *std.Io.Writer, │ │35 │ │36 fn run(ctx: @This()) void { │ ╰───────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────╮ │45 io: std.Io, │ │46 allocator: std.mem.Allocator,│ │47 stream: std.Io.net.Stream, │ │48 + admin_repo_path: []const u8, │ │49 err: *std.Io.Writer, │ │50 │ │51 fn run(conn: @This()) void { │ ╰─────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │52 defer conn.stream.close(conn.io); │ │47 - handleConnection(conn.io, conn.allocator, conn.stream, conn.err) catch |request_err| { │ │53 + handleConnection(conn.io, conn.allocator, conn.stream, conn.admin_repo_path, conn.err) catch |request_err| {│ │54 logError(conn.err, "web ui request failed: {s}\n", .{@errorName(request_err)}); │ │55 }; │ │56 } │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────╮ │60 .io = ctx.io, │ │61 .allocator = ctx.allocator, │ │62 .stream = stream, │ │63 + .admin_repo_path = ctx.admin_repo_path,│ │64 .err = ctx.err, │ │65 }}); │ │66 } │ ╰───────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────╮ │72 .allocator = allocator, │ │73 .net_server = net_server, │ │74 .tasks = tasks, │ │75 + .admin_repo_path = admin_repo_path,│ │76 .err = err, │ │77 }}); │ │78 } │ ╰───────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │79 │ │72 -fn renderIndexHtml(allocator: std.mem.Allocator) ![]const u8 { │ │80 +fn renderIndexHtml(io: std.Io, allocator: std.mem.Allocator, admin_repo_path: []const u8) ![]const u8 {│ │81 const template = (findAsset("/index.html") orelse return error.MissingIndexAsset).body; │ │82 │ │75 - var root = try ui.initRoot(allocator); │ │83 + // open the admin repo to read live user/repo data; if it doesn't exist │ │84 + // yet (e.g. a fresh `haxy serve` with no admin repo) fall back to empty. │ │85 + const repo_opts: rp.RepoOpts(.xit) = .{}; │ │86 + const Repo = rp.Repo(.xit, repo_opts); │ │87 + var repo_or_err = Repo.open(io, allocator, .{ .path = admin_repo_path }); │ │88 + var page_arena = std.heap.ArenaAllocator.init(allocator); │ │89 + defer page_arena.deinit(); │ │90 + const page: pg.Page = if (repo_or_err) |*repo| blk: { │ │91 + defer repo.deinit(io, allocator); │ │92 + break :blk .{ .user_repo = try .init(repo_opts, &page_arena, repo) }; │ │93 + } else |_| .{ .user_repo = .empty() }; │ │94 + │ │95 + var root = try ui.initRoot(allocator, &page); │ │96 defer root.deinit(); │ │97 │ │98 const content = try ui.generateHtml(allocator, &root); │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────╮ │113 io: std.Io, │ │114 allocator: std.mem.Allocator, │ │115 stream: std.Io.net.Stream, │ │116 + admin_repo_path: []const u8, │ │117 err: *std.Io.Writer, │ │118 ) !void { │ │119 var send_buffer = [_]u8{0} ** 4096;│ ╰────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │129 else => |e| return e, │ │130 }; │ │131 │ │111 - handleRequest(&http_server, &request, allocator) catch |request_err| { │ │132 + handleRequest(io, &http_server, &request, allocator, admin_repo_path) catch |request_err| {│ │133 try err.print("web ui request failed: {s}\n", .{@errorName(request_err)}); │ │134 try err.flush(); │ │135 if (http_server.reader.state == .received_head) { │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────╮ │next →│ ╰──────╯