Immich bindings and CLI in OCaml
1(*---------------------------------------------------------------------------
2 Copyright (c) 2025 Anil Madhavapeddy. All rights reserved.
3 SPDX-License-Identifier: ISC
4 ---------------------------------------------------------------------------*)
5
6(** Authenticated Immich client with session persistence and profile support.
7
8 This module provides a high-level client that wraps the generated
9 {!Immich} module with authentication support. Sessions are stored in
10 profile-specific directories.
11
12 {2 Authentication Methods}
13
14 {b API Key} (recommended for CLI):
15 {[
16 let t = Client.login_api_key ~sw ~env
17 ~server_url:"https://immich.example.com"
18 ~api_key:"your-api-key"
19 ~key_name:(Some "cli")
20 () in
21 let albums = Immich.Album.get_all_albums (Client.client t) ()
22 ]}
23
24 {b Password} (for interactive use):
25 {[
26 let t = Client.login_password ~sw ~env
27 ~server_url:"https://immich.example.com"
28 ~email:"user@example.com"
29 ~password:"secret"
30 () in
31 ...
32 ]}
33
34 {2 Resuming Sessions}
35
36 {[
37 match Session.load fs () with
38 | Some session ->
39 let t = Client.resume ~sw ~env ~session () in
40 ...
41 | None ->
42 Fmt.epr "Not logged in@."
43 ]} *)
44
45type t
46(** Authenticated client state. *)
47
48(** {1 Authentication} *)
49
50val login_api_key :
51 sw:Eio.Switch.t ->
52 env:< clock : _ Eio.Time.clock
53 ; net : _ Eio.Net.t
54 ; fs : Eio.Fs.dir_ty Eio.Path.t
55 ; .. > ->
56 ?requests_config:Requests.Cmd.config ->
57 ?profile:string ->
58 server_url:string ->
59 api_key:string ->
60 ?key_name:string ->
61 unit ->
62 t
63(** [login_api_key ~sw ~env ?requests_config ?profile ~server_url ~api_key ?key_name ()]
64 authenticates using an API key. The API key is sent in the [x-api-key]
65 header for all requests.
66
67 The [server_url] can be either the full API URL (e.g., [https://example.com/api])
68 or the base server URL (e.g., [https://example.com]). If the base URL is
69 provided, the client automatically discovers the API endpoint via
70 [.well-known/immich].
71
72 @param requests_config Optional Requests.Cmd.config for HTTP settings
73 @param profile Profile name (default: "default")
74 @param key_name Optional name for the API key (for display purposes) *)
75
76val login_password :
77 sw:Eio.Switch.t ->
78 env:< clock : _ Eio.Time.clock
79 ; net : _ Eio.Net.t
80 ; fs : Eio.Fs.dir_ty Eio.Path.t
81 ; .. > ->
82 ?requests_config:Requests.Cmd.config ->
83 ?profile:string ->
84 server_url:string ->
85 email:string ->
86 password:string ->
87 unit ->
88 t
89(** [login_password ~sw ~env ?requests_config ?profile ~server_url ~email ~password ()]
90 authenticates using email and password. Returns a JWT access token.
91
92 @param requests_config Optional Requests.Cmd.config for HTTP settings
93 @param profile Profile name (default: email address) *)
94
95val resume :
96 sw:Eio.Switch.t ->
97 env:< clock : _ Eio.Time.clock
98 ; net : _ Eio.Net.t
99 ; fs : Eio.Fs.dir_ty Eio.Path.t
100 ; .. > ->
101 ?requests_config:Requests.Cmd.config ->
102 ?profile:string ->
103 session:Session.t ->
104 unit ->
105 t
106(** [resume ~sw ~env ?requests_config ?profile ~session ()] resumes from a saved session.
107
108 @param requests_config Optional Requests.Cmd.config for HTTP settings
109 @raise Failure if the JWT session is expired *)
110
111val logout : t -> unit
112(** [logout t] clears the session from disk. *)
113
114(** {1 Client Access} *)
115
116val client : t -> Immich.t
117(** [client t] returns the underlying Immich client for API calls. *)
118
119val session : t -> Session.t
120(** [session t] returns the current session. *)
121
122val profile : t -> string option
123(** [profile t] returns the current profile name, if set. *)
124
125val fs : t -> Eio.Fs.dir_ty Eio.Path.t
126(** [fs t] returns the filesystem capability. *)
127
128val is_valid : t -> bool
129(** [is_valid t] returns [true] if the session is still valid by calling
130 the validate endpoint. *)
131
132(** {1 URL Resolution} *)
133
134val resolve_api_url : session:Requests.t -> string -> string
135(** [resolve_api_url ~session base_url] resolves the actual API URL.
136
137 If [base_url] already ends with [/api], returns it unchanged.
138 Otherwise, tries to fetch [<base_url>/.well-known/immich] to discover
139 the API endpoint. Falls back to [<base_url>/api] if discovery fails.
140
141 This function is called automatically by {!login_api_key} and
142 {!login_password}, but is exposed for advanced use cases. *)