module Id = Meta.Id type alias_t = string module Configuration = struct type t = { repository : Lpath.repo_t; title : string; owner : string; email : string; id : Id.t; } let of_config config = let open Confix in let open Confix.Config in let str k = ConfixToml.(string config ("archive" / k)) in try Ok { repository = (try Lpath.repo_of_string (str "repository" |> with_default ".") with | Invalid_argument s -> failwith ("Invalid repository: " ^ s) | Failure s -> failwith ("Missing repository value: " ^ s)); title = str "title" |> with_default ""; owner = str "owner" |> with_default ""; email = str "email" |> with_default ""; id = match Id.of_string (str "uuid" |> mandatory) with Some id -> id | None -> failwith "Invalid UUID in config"; } with Failure str -> Error str let validity config = let repo = Lpath.fpath_of_repo config.repository in let open Confix.Config.Validation in empty &> is_directory repo end module AliasMap = Meta.AliasMap module Make (Store : Store.T) = struct type t = { config : Configuration.t; store : Store.t; } let note_lens note = note let meta_lens note = note.Note.meta let recency_order a b = Meta.(Date.compare a.date b.date) let latest archive = Store.to_list ~order:recency_order meta_lens archive.store let listed archive = let notes = Store.to_list meta_lens archive.store in List.filter Meta.(fun e -> CategorySet.listed e.categories) notes let published archive = let notes = Store.to_list meta_lens archive.store in List.filter Meta.(fun e -> CategorySet.published e.categories) notes let latest_listed archive = let notes = Store.to_list ~order:recency_order meta_lens archive.store in List.filter Meta.(fun e -> CategorySet.listed e.categories) notes let with_topic archive topic = let notes = Store.to_list ~order:recency_order meta_lens archive.store in List.filter Meta.(fun e -> StringSet.exists (fun t -> t = topic) e.topics) notes let topics archive = let notes = Store.to_list meta_lens archive.store in List.fold_left Meta.(fun a e -> unique_topics a e) Meta.StringSet.empty notes let latest_entry archive fragment = let notes = Store.to_list ~order:recency_order meta_lens archive.store in let containing_fragment e = Re.Str.(string_match (regexp fragment)) (e.Meta.title) 0 in try Some (List.find containing_fragment notes) with Not_found -> None let note_with_id archive id = Store.note_with_id archive.store id let note_with_alias archive alias = Store.note_with_alias archive.store alias let with_note archive note = Store.with_note archive.store note let sublist ~from ~n list = let aggregate_subrange (i, elms) e = succ i, if i >= from && i <= n then e::elms else elms in List.fold_left aggregate_subrange (0, []) list |> snd end