1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
{ depot, pkgs, ... }:

let
  goDeps = import ./go-deps.nix { inherit depot pkgs; };

  # Sources and templates are staged into one directory because //go:embed
  # resolves its patterns relative to the directory of the first `srcs` entry;
  # passing path literals would place each file in its own store path and the
  # templates would silently embed as empty. See `man ./nix/buildGo/buildGo.7`.
  src = pkgs.runCommandLocal "mailweb-src" {} ''
    mkdir -p $out/templates $out/static
    cp ${./main.go} $out/main.go
    cp ${./schema.go} $out/schema.go
    cp ${./db.go} $out/db.go
    cp ${./unsubscribe.go} $out/unsubscribe.go
    cp ${./account.go} $out/account.go
    cp ${./pool.go} $out/pool.go
    cp ${./forge.go} $out/forge.go
    cp ${./contacts.go} $out/contacts.go
    cp ${./imap.go} $out/imap.go
    cp ${./analyze.go} $out/analyze.go
    cp ${./attachments.go} $out/attachments.go
    cp ${./pdfjs.go} $out/pdfjs.go
    cp ${./ical.go} $out/ical.go
    cp ${./mime.go} $out/mime.go
    cp ${./smtp.go} $out/smtp.go
    cp ${./petname.go} $out/petname.go
    cp ${./recipient.go} $out/recipient.go
    cp ${./draft.go} $out/draft.go
    cp ${./drafthttp.go} $out/drafthttp.go
    cp ${./draftapi.go} $out/draftapi.go
    cp ${./draftassets.go} $out/draftassets.go
    cp ${./reply.go} $out/reply.go
    cp ${./render.go} $out/render.go
    cp ${./textview.go} $out/textview.go
    cp ${./templates}/*.html $out/templates/
    cp ${./templates}/*.llm $out/templates/
    # The block editor's script, embedded with //go:embed static.
    cp ${./static}/* $out/static/
  '';

  unwrapped = depot.nix.buildGo.program {
    name = "mailweb";
    srcs = [
      "${src}/main.go"
      "${src}/schema.go"
      "${src}/db.go"
      "${src}/unsubscribe.go"
      "${src}/account.go"
      "${src}/pool.go"
      "${src}/forge.go"
      "${src}/contacts.go"
      "${src}/imap.go"
      "${src}/analyze.go"
      "${src}/attachments.go"
      "${src}/pdfjs.go"
      "${src}/ical.go"
      "${src}/mime.go"
      "${src}/smtp.go"
      "${src}/petname.go"
      "${src}/recipient.go"
      "${src}/draft.go"
      "${src}/drafthttp.go"
      "${src}/draftapi.go"
      "${src}/draftassets.go"
      "${src}/reply.go"
      "${src}/render.go"
      "${src}/textview.go"
    ];
    deps = [
      goDeps.emersion-go-imap
      goDeps.emersion-go-imap.client
      goDeps.emersion-go-message
      goDeps.emersion-go-message.mail
      goDeps.emersion-go-message.charset
      goDeps.emersion-go-smtp
      goDeps.emersion-go-sasl
      goDeps.modernc-sqlite
      goDeps.modernc-libc
      goDeps.modernc-libc.sys.types
      goDeps.golang-x-sys-unix
      # The shared text/llm rendering: markers, escaping, paging, size hints
      # and the HTML-to-text conversion. Shared with webmail-proton so that the
      # trust boundary has exactly one implementation.
      depot.users.Profpatsch.mailtext
    ];
  };

in
pkgs.symlinkJoin {
  name = "mailweb";
  outputs = [ "out" "man" ];
  paths = [ unwrapped ];
  # mailweb.1 is the reference: flags, routes, files, caveats. mailweb.7 is the
  # reasoning behind them, split out because the reference is read by every
  # agent session and a page carrying both made every reader pay for it.
  postBuild = ''
    mkdir -p $man/share/man/man1 $man/share/man/man7
    cp ${./mailweb.1} $man/share/man/man1/mailweb.1
    cp ${./mailweb.7} $man/share/man/man7/mailweb.7
  '';
}