Sortal - Username to Metadata Mapping Library#
Sortal is an OCaml library that provides a system for mapping usernames to various metadata including URLs, emails, ORCID identifiers, and social media handles. It uses the XDG Base Directory Specification for storage locations and jsont for JSON encoding/decoding.
Features#
- XDG-compliant storage: Contact metadata stored in standard XDG data directories
- JSON format: Type-safe JSON encoding/decoding using jsont
- Rich metadata: Support for multiple names, email, social media handles (GitHub, Twitter, Bluesky, Mastodon), ORCID, URLs, and Atom feeds
- Simple API: Easy-to-use functions for saving, loading, searching, and deleting contacts
Metadata Fields#
Each contact can include:
handle: Unique identifier/username (required)names: List of full names with primary name first (required)email: Email addressicon: Avatar/icon URLthumbnail: Path to a local thumbnail image filegithub: GitHub usernametwitter: Twitter/X usernamebluesky: Bluesky handlemastodon: Mastodon handle (with instance)orcid: ORCID identifierurl: Personal/professional websiteatom_feeds: List of Atom/RSS feed URLs
Storage#
Contact data is stored as individual JSON files in the XDG data directory:
- Default location:
$HOME/.local/share/{app_name}/ - Override with:
${APP_NAME}_DATA_DIRorXDG_DATA_HOME - Each contact stored as:
{handle}.json
Usage Example#
Basic Usage#
(* Create a contact store from filesystem *)
let store = Sortal.create env#fs "myapp" in
(* Or create from an existing XDG context (recommended when using eiocmd) *)
let store = Sortal.create_from_xdg xdg in
(* Create a new contact *)
let contact = Sortal.Contact.make
~handle:"avsm"
~names:["Anil Madhavapeddy"]
~email:"anil@recoil.org"
~github:"avsm"
~orcid:"0000-0002-7890-1234"
() in
(* Save the contact *)
Sortal.save store contact;
(* Lookup by handle *)
match Sortal.lookup store "avsm" with
| Some c -> Printf.printf "Found: %s\n" (Sortal.Contact.name c)
| None -> Printf.printf "Not found\n"
(* Search for contacts by name *)
let matches = Sortal.search_all store "Anil" in
List.iter (fun c ->
Printf.printf "%s: %s\n"
(Sortal.Contact.handle c)
(Sortal.Contact.name c)
) matches
(* List all contacts *)
let all_contacts = Sortal.list store in
List.iter (fun c ->
Printf.printf "%s: %s\n"
(Sortal.Contact.handle c)
(Sortal.Contact.name c)
) all_contacts
Integration with Eiocmd (for CLI applications)#
open Cmdliner
let my_command env xdg profile =
(* Create store from XDG context *)
let store = Sortal.create_from_xdg xdg in
(* Search for a contact *)
let matches = Sortal.search_all store "John" in
List.iter (fun c ->
match Sortal.Contact.best_url c with
| Some url -> Logs.app (fun m -> m "%s: %s" (Sortal.Contact.name c) url)
| None -> ()
) matches;
0
(* Use Sortal's built-in commands *)
let () =
let info = Cmd.info "myapp" in
let my_cmd = Eiocmd.run ~info ~app_name:"myapp" ~service:"myapp"
Term.(const my_command) in
(* Include sortal commands as subcommands *)
let list_contacts = Eiocmd.run ~use_keyeio:false
~info:Sortal.Cmd.list_info ~app_name:"myapp" ~service:"myapp"
Term.(const (fun () -> Sortal.Cmd.list_cmd ()) $ const ()) in
let cmd = Cmd.group info [my_cmd; list_contacts] in
exit (Cmd.eval' cmd)
Design Inspiration#
The contact metadata structure is inspired by the Contact module from Bushel, adapted to use JSON instead of YAML and stored in XDG-compliant locations.
Dependencies#
eio: For effect-based I/Oxdge: For XDG Base Directory Specification supportjsont: For type-safe JSON encoding/decodingfmt: For pretty printing
API Features#
The library provides two main ways to use contact metadata:
-
Core API: Direct functions for creating, saving, loading, and searching contacts
create/create_from_xdg: Initialize a contact storesave/lookup/delete/list: CRUD operationssearch_all: Flexible search across contact namesfind_by_name/find_by_name_opt: Exact name matching
-
Cmdliner Integration (
Sortal.Cmdmodule): Ready-to-use CLI commandslist_cmd: List all contactsshow_cmd: Show detailed contact informationsearch_cmd: Search contacts by namestats_cmd: Show database statistics- Pre-configured
Cmd.infoand argument definitions for easy integration
CLI Tool#
The library includes a standalone sortal CLI tool:
# List all contacts
sortal list
# Show details for a specific contact
sortal show avsm
# Search for contacts
sortal search "Anil"
# Show database statistics
sortal stats
Project Status#
Fully implemented and tested with 409 imported contacts.