Immich bindings and CLI in OCaml
1(*---------------------------------------------------------------------------
2 Copyright (c) 2025 Anil Madhavapeddy. All rights reserved.
3 SPDX-License-Identifier: ISC
4 ---------------------------------------------------------------------------*)
5
6(** Session management for Immich CLI with profile support.
7
8 This module provides session persistence for Immich authentication,
9 supporting both JWT tokens and API keys. Sessions are stored in
10 profile-specific directories under [~/.config/immich/profiles/<profile>/session.json].
11
12 {2 Directory Structure}
13
14 {v
15 ~/.config/immich/
16 config.json # Stores current_profile setting
17 profiles/
18 default/
19 session.json # Session for "default" profile
20 home/
21 session.json # Session for "home" profile
22 work/
23 session.json # Session for "work" profile
24 v}
25
26 {2 Authentication Methods}
27
28 Immich supports two authentication methods:
29 - {b JWT}: Obtained via email/password login. Tokens expire and need refresh.
30 - {b API Key}: Created in Immich settings. Never expires, simpler for CLI use.
31
32 {[
33 (* Login with API key *)
34 let session = Session.create
35 ~server_url:"https://immich.example.com"
36 ~auth:(Api_key { key = "xxx"; name = Some "cli" })
37 () in
38 Session.save fs ~profile:"home" session
39 ]} *)
40
41(** {1 Types} *)
42
43type auth_method =
44 | Jwt of { access_token : string; user_id : string; email : string }
45 | Api_key of { key : string; name : string option }
46(** Authentication method. API keys are preferred for CLI use as they
47 don't expire. *)
48
49type t
50(** Session data. *)
51
52val jsont : t Jsont.t
53(** JSON codec for sessions. *)
54
55(** {1 Session Construction} *)
56
57val create : server_url:string -> auth:auth_method -> unit -> t
58(** [create ~server_url ~auth ()] creates a new session with the current timestamp. *)
59
60(** {1 Session Accessors} *)
61
62val server_url : t -> string
63(** [server_url t] returns the server URL. *)
64
65val auth : t -> auth_method
66(** [auth t] returns the authentication method. *)
67
68val created_at : t -> string
69(** [created_at t] returns the creation timestamp (RFC 3339). *)
70
71(** {1 Profile Management} *)
72
73val default_profile : string
74(** The default profile name (["default"]). *)
75
76val get_current_profile : Eio.Fs.dir_ty Eio.Path.t -> string
77(** [get_current_profile fs] returns the current profile name. Returns
78 {!default_profile} if no profile has been set. *)
79
80val set_current_profile : Eio.Fs.dir_ty Eio.Path.t -> string -> unit
81(** [set_current_profile fs profile] sets the current profile. *)
82
83val list_profiles : Eio.Fs.dir_ty Eio.Path.t -> string list
84(** [list_profiles fs] returns all profiles that have sessions.
85 Returns profile names sorted alphabetically. *)
86
87(** {1 Directory Paths} *)
88
89val base_config_dir : Eio.Fs.dir_ty Eio.Path.t -> Eio.Fs.dir_ty Eio.Path.t
90(** [base_config_dir fs] returns the base config directory
91 ([~/.config/immich]), creating it if needed. *)
92
93val config_dir :
94 Eio.Fs.dir_ty Eio.Path.t ->
95 ?profile:string ->
96 unit ->
97 Eio.Fs.dir_ty Eio.Path.t
98(** [config_dir fs ?profile ()] returns the config directory for a
99 profile, creating it if needed.
100 @param profile Profile name (default: current profile) *)
101
102(** {1 Session Persistence} *)
103
104val save : Eio.Fs.dir_ty Eio.Path.t -> ?profile:string -> t -> unit
105(** [save fs ?profile session] saves the session.
106 @param profile Profile name (default: current profile) *)
107
108val load : Eio.Fs.dir_ty Eio.Path.t -> ?profile:string -> unit -> t option
109(** [load fs ?profile ()] loads a saved session.
110 @param profile Profile name (default: current profile) *)
111
112val clear : Eio.Fs.dir_ty Eio.Path.t -> ?profile:string -> unit -> unit
113(** [clear fs ?profile ()] removes the saved session.
114 @param profile Profile name (default: current profile) *)
115
116(** {1 Session Utilities} *)
117
118val is_jwt_expired : ?leeway:int -> string -> bool
119(** [is_jwt_expired ?leeway token] returns [true] if the JWT token is expired.
120 @param leeway Extra time buffer in seconds (default: 60) *)
121
122val is_expired : ?leeway:int -> t -> bool
123(** [is_expired ?leeway session] returns [true] if the session is expired.
124 API key sessions never expire.
125 @param leeway Extra time buffer in seconds for JWT (default: 60) *)
126
127val pp : t Fmt.t
128(** Pretty-print a session. *)