-2
CLAUDE.md
-2
CLAUDE.md
···-This is a monorepo of a collection of OCaml libraries that should all work together, but they are in different stages of porting. Ultimately, the goal is to use Eio for everything and move away from Lwt entirely. For HTTP(S) requests the idea is to use River as the main high evel 'http requests' API, so anything using Cohttp or other HTTP fetchers will need to be ported.
+232
stack/TODO.md
+232
stack/TODO.md
···+This document tracks remaining tasks to make the immutable Requests.t and refactored library patterns production-ready.+The README still documents the old API (passing `~sw ~clock ~net ~base_url ~api_key` on every call) instead of the new session-based pattern.+Type signatures like `([> float Eio.Time.clock_ty ] Eio.Resource.t, [> [> `Generic ] Eio.Net.ty ] Eio.Resource.t) t` are extremely verbose.+Zotero-translation was already using session pattern before we made Requests.t immutable. Need to verify it still works correctly.+With immutable sessions that share mutable cookie_jar and statistics, the concurrency model needs documentation.+Statistics (requests_made, total_time, retries_count) are still mutable and shared across derived sessions.+- **Alternative (immutable):** Would require returning `(Response.t * t)` from all request functions+- **Cookie handling:** Still mutable via shared cookie_jar - this is intentional for session state
+121
-132
stack/bushel/bin/bushel_doi.ml
+121
-132
stack/bushel/bin/bushel_doi.ml
······-let entry = Bushel.Doi_entry.create_resolved ~doi ~title ~authors ~year ~bibtype ~publisher ~source_urls:[doi_url] () in-Lwt.return (Bushel.Doi_entry.create_failed ~doi ~error:(Printexc.to_string e) ~source_urls:[doi_url] ())-Lwt.return (Bushel.Doi_entry.create_failed ~doi ~error:(Printexc.to_string exn) ~source_urls:[doi_url] ())+let entry = Bushel.Doi_entry.create_resolved ~doi ~title ~authors ~year ~bibtype ~publisher ~source_urls:[doi_url] () in-Lwt.return (Bushel.Doi_entry.create_failed ~doi:url ~error:"Empty response" ~source_urls:[url] ())-let entry = Bushel.Doi_entry.create_resolved ~doi ~title ~authors ~year ~bibtype ~publisher ~source_urls () in-Lwt.return (Bushel.Doi_entry.create_failed ~doi:url ~error:(Printexc.to_string e) ~source_urls:[url] ())-Lwt.return (Bushel.Doi_entry.create_failed ~doi:url ~error:(Printexc.to_string exn) ~source_urls:[url] ())+let entry = Bushel.Doi_entry.create_resolved ~doi ~title ~authors ~year ~bibtype ~publisher ~source_urls () in···Printf.printf "Resolving %d DOI(s) and %d URL(s)...\n%!" (List.length dois_to_resolve) (List.length urls_to_resolve);
+38
-95
stack/bushel/bin/bushel_faces.ml
+38
-95
stack/bushel/bin/bushel_faces.ml
······-Lwt.return (`Skipped (sprintf "Thumbnail for '%s' already exists at %s" (List.hd names) output_path))let ok_count = List.length (List.filter (fun (_, r) -> match r with `Ok _ -> true | _ -> false) results) inlet error_count = List.length (List.filter (fun (_, r) -> match r with `Error _ -> true | _ -> false) results) inlet skipped_count = List.length (List.filter (fun (_, r) -> match r with `Skipped _ -> true | _ -> false) results) in······-) $ Bushel_common.base_dir $ Bushel_common.output_dir ~default:"." $ Bushel_common.handle_opt $+) $ Bushel_common.base_dir $ Bushel_common.output_dir ~default:"." $ Bushel_common.handle_opt $Bushel_common.url_term ~default:"https://photos.recoil.org" ~doc:"Base URL of the Immich instance")
+187
-189
stack/bushel/bin/bushel_links.ml
+187
-189
stack/bushel/bin/bushel_links.ml
············+let process_batch ~sw ~env api_key base_url tag verbose updated_links batch_num total_batches batch =···-let upload_to_karakeep base_url api_key_opt links_file tag max_concurrent delay_seconds limit verbose =+let upload_to_karakeep ~sw ~env base_url api_key_opt links_file tag max_concurrent delay_seconds limit verbose =···(batch_num + 1) batch_successes (List.length batch) new_total (new_total + (List.length links_to_upload - new_total));···-Cmd.v info Term.(const update_from_karakeep $ base_url_arg $ api_key_arg $ tag_arg $ links_file_arg $ download_assets_arg)···-Cmd.v info Term.(const upload_to_karakeep $ base_url_arg $ api_key_arg $ links_file_arg $ tag_arg $ concurrent_arg $ delay_arg $ limit_arg $ verbose_arg)+Cmd.v info Term.(const (fun base_url api_key_opt links_file tag max_concurrent delay_seconds limit verbose ->+upload_to_karakeep ~sw ~env base_url api_key_opt links_file tag max_concurrent delay_seconds limit verbose)+$ base_url_arg $ api_key_arg $ links_file_arg $ tag_arg $ concurrent_arg $ delay_arg $ limit_arg $ verbose_arg)
+12
-10
stack/bushel/bin/bushel_paper.ml
+12
-10
stack/bushel/bin/bushel_paper.ml
············
+20
-22
stack/bushel/bin/bushel_search.ml
+20
-22
stack/bushel/bin/bushel_search.ml
······-let combined_response = Bushel.Typesense.combine_multisearch_results multisearch_resp ~limit ~offset () in-Printf.printf "Found %d results (%.2fms)\n\n" combined_response.total combined_response.query_time;-Printf.printf "%d. %s (score: %.2f)\n" (i + 1) (Bushel.Typesense.pp_search_result_oneline hit) hit.Bushel.Typesense.score+let combined_response = Bushel.Typesense.combine_multisearch_results multisearch_resp ~limit ~offset () in+Printf.printf "Found %d results (%.2fms)\n\n" combined_response.total combined_response.query_time;+Printf.printf "%d. %s (score: %.2f)\n" (i + 1) (Bushel.Typesense.pp_search_result_oneline hit) hit.Bushel.Typesense.score
+53
-57
stack/bushel/bin/bushel_typesense.ml
+53
-57
stack/bushel/bin/bushel_typesense.ml
············
+43
-55
stack/bushel/bin/bushel_video.ml
+43
-55
stack/bushel/bin/bushel_video.ml
···············-Lwt_main.run (process_videos output_dir overwrite base_url channel fetch_thumbs thumbs_dir); 0)
+12
-15
stack/bushel/bin/bushel_video_thumbs.ml
+12
-15
stack/bushel/bin/bushel_video_thumbs.ml
···············
+2
-2
stack/bushel/bin/dune
+2
-2
stack/bushel/bin/dune
···(modules bushel_main bushel_bibtex bushel_doi bushel_ideas bushel_info bushel_missing bushel_note_doi bushel_obsidian bushel_paper bushel_paper_classify bushel_paper_tex bushel_video bushel_video_thumbs bushel_thumbs bushel_faces bushel_links bushel_search)-(libraries bushel bushel_common cmdliner cohttp-lwt-unix lwt.unix yaml ezjsonm zotero-translation peertube fmt fmt.cli fmt.tty logs logs.cli logs.fmt cmarkit karakeep uri unix ptime.clock.os crockford))+(libraries bushel bushel_common cmdliner eio eio_main yaml ezjsonm zotero-translation peertubee fmt fmt.cli fmt.tty logs logs.cli logs.fmt cmarkit karakeepe uri unix ptime.clock.os crockford immiche))···
+7
-5
stack/bushel/bushel.opam
+7
-5
stack/bushel/bushel.opam
···
+7
-42
stack/bushel/dune-project
+7
-42
stack/bushel/dune-project
···
-35
stack/bushel/karakeep.opam
-35
stack/bushel/karakeep.opam
···
-4
stack/bushel/karakeep/dune
-4
stack/bushel/karakeep/dune
-568
stack/bushel/karakeep/karakeep.ml
-568
stack/bushel/karakeep/karakeep.ml
···-let fetch_bookmarks ~api_key ?(limit=50) ?(offset=0) ?cursor ?(include_content=false) ?filter_tags base_url =-let fetch_all_bookmarks ~api_key ?(page_size=50) ?max_pages ?filter_tags ?(include_content=false) base_url =-| Some cursor_str -> fetch_bookmarks ~api_key ~limit:page_size ~cursor:cursor_str ~include_content ?filter_tags base_url-| None -> fetch_bookmarks ~api_key ~limit:page_size ~offset:(page_num * page_size) ~include_content ?filter_tags base_url)-let create_bookmark ~api_key ~url ?title ?note ?tags ?(favourited=false) ?(archived=false) base_url =-Client.post ~headers ~body:(Cohttp_lwt.Body.of_string body_str) (Uri.of_string url_endpoint) >>= fun (resp, body) ->-Client.post ~headers ~body:(Cohttp_lwt.Body.of_string tags_body_str) (Uri.of_string tags_url) >>= fun (resp, body) ->-Lwt.fail_with (Fmt.str "Failed to create bookmark. HTTP error: %d. Details: %s" status_code error_body)
+44
-24
stack/bushel/karakeep/karakeep.mli
stack/karakeepe/karakeepe.mli
+44
-24
stack/bushel/karakeep/karakeep.mli
stack/karakeepe/karakeepe.mli
·········+env:< clock: [> float Eio.Time.clock_ty ] Eio.Resource.t; net: [> [> `Generic] Eio.Net.ty ] Eio.Resource.t; .. > ->+env:< clock: [> float Eio.Time.clock_ty ] Eio.Resource.t; net: [> [> `Generic] Eio.Net.ty ] Eio.Resource.t; .. > ->+env:< clock: [> float Eio.Time.clock_ty ] Eio.Resource.t; net: [> [> `Generic] Eio.Net.ty ] Eio.Resource.t; .. > ->+env:< clock: [> float Eio.Time.clock_ty ] Eio.Resource.t; net: [> [> `Generic] Eio.Net.ty ] Eio.Resource.t; .. > ->······+env:< clock: [> float Eio.Time.clock_ty ] Eio.Resource.t; net: [> [> `Generic] Eio.Net.ty ] Eio.Resource.t; .. > ->···
+4
-3
stack/bushel/lib/dune
+4
-3
stack/bushel/lib/dune
+100
-99
stack/bushel/lib/typesense.ml
+100
-99
stack/bushel/lib/typesense.ml
·········+let body = if body = "" then None else Some (Requests.Body.of_string Requests.Mime.json body) in······let upload_collection ((name, schema, documents) : string * Ezjsonm.value * Ezjsonm.value list) =-let* () = Lwt_io.write Lwt_io.stdout (Fmt.str "Creating collection %s with %d documents\n" name (List.length documents)) inif String.contains line ':' && Str.string_match (Str.regexp ".*success.*true.*") line 0 then acc + 1 else acc) 0 lines inif String.contains line ':' && Str.string_match (Str.regexp ".*success.*false.*") line 0 then acc + 1 else acc) 0 lines in-let* () = Lwt_io.write Lwt_io.stdout (Fmt.str "Upload results for %s: %d successful, %d failed out of %d total\n"let failed_lines = List.filter (fun line -> Str.string_match (Str.regexp ".*success.*false.*") line 0) lines in······+let search_collection ~sw ~env (config : config) collection_name query ?(limit=10) ?(offset=0) () =-let* result = Typesense_client.search_collection client_config collection_name query ~limit ~offset () in+let result = Typesense_cliente.search_collection ~sw ~env client_config collection_name query ~limit ~offset () in-| Error (Typesense_client.Http_error (code, msg)) -> Lwt.return_error (Http_error (code, msg))-let combined_response = Typesense_client.combine_multisearch_results multisearch_resp ~limit ~offset () in-| Error (Typesense_client.Http_error (code, msg)) -> Lwt.return_error (Http_error (code, msg))+let combined_response = Typesense_cliente.combine_multisearch_results multisearch_resp ~limit ~offset () in-| Error (Typesense_client.Http_error (code, msg)) -> Lwt.return_error (Http_error (code, msg))-| Error (Typesense_client.Http_error (code, msg)) -> Lwt.return_error (Http_error (code, msg))let combine_multisearch_results (multisearch_resp : multisearch_response) ?(limit=10) ?(offset=0) () =···
+73
-17
stack/bushel/lib/typesense.mli
+73
-17
stack/bushel/lib/typesense.mli
···+let config = { endpoint = "https://search.example.com"; api_key = "xyz123"; openai_key = "sk-..." } in······+env:< clock: [> float Eio.Time.clock_ty ] Eio.Resource.t; net: [> [> `Generic ] Eio.Net.ty ] Eio.Resource.t; .. > ->+env:< clock: [> float Eio.Time.clock_ty ] Eio.Resource.t; net: [> [> `Generic ] Eio.Net.ty ] Eio.Resource.t; .. > ->+env:< clock: [> float Eio.Time.clock_ty ] Eio.Resource.t; net: [> [> `Generic ] Eio.Net.ty ] Eio.Resource.t; .. > ->+env:< clock: [> float Eio.Time.clock_ty ] Eio.Resource.t; net: [> [> `Generic ] Eio.Net.ty ] Eio.Resource.t; .. > ->···+env:< clock: [> float Eio.Time.clock_ty ] Eio.Resource.t; net: [> [> `Generic ] Eio.Net.ty ] Eio.Resource.t; .. > ->···-val search_collection : config -> string -> string -> ?limit:int -> ?offset:int -> unit -> (search_response, error) result Lwt.t+env:< clock: [> float Eio.Time.clock_ty ] Eio.Resource.t; net: [> [> `Generic ] Eio.Net.ty ] Eio.Resource.t; .. > ->-val search_all : config -> string -> ?limit:int -> ?offset:int -> unit -> (search_response, error) result Lwt.t+env:< clock: [> float Eio.Time.clock_ty ] Eio.Resource.t; net: [> [> `Generic ] Eio.Net.ty ] Eio.Resource.t; .. > ->···-val multisearch : config -> string -> ?limit:int -> unit -> (multisearch_response, error) result Lwt.t+env:< clock: [> float Eio.Time.clock_ty ] Eio.Resource.t; net: [> [> `Generic ] Eio.Net.ty ] Eio.Resource.t; .. > ->···+env:< clock: [> float Eio.Time.clock_ty ] Eio.Resource.t; net: [> [> `Generic ] Eio.Net.ty ] Eio.Resource.t; .. > ->
-34
stack/bushel/peertube.opam
-34
stack/bushel/peertube.opam
···
-4
stack/bushel/peertube/dune
-4
stack/bushel/peertube/dune
+57
-63
stack/bushel/peertube/peertube.ml
stack/peertubee/peertubee.ml
+57
-63
stack/bushel/peertube/peertube.ml
stack/peertubee/peertubee.ml
···············+let response = Requests.One.get ~sw ~clock:(Eio.Stdenv.clock env) ~net:(Eio.Stdenv.net env) url in···+let response = Requests.One.get ~sw ~clock:(Eio.Stdenv.clock env) ~net:(Eio.Stdenv.net env) url in···+let response = Requests.One.get ~sw ~clock:(Eio.Stdenv.clock env) ~net:(Eio.Stdenv.net env) url in
+13
-6
stack/bushel/peertube/peertube.mli
stack/peertubee/peertubee.mli
+13
-6
stack/bushel/peertube/peertube.mli
stack/peertubee/peertubee.mli
······-val fetch_channel_videos : ?count:int -> ?start:int -> string -> string -> video_response Lwt.t+val fetch_channel_videos : sw:Eio.Switch.t -> env:< clock : 'a Eio.Time.clock; net : 'b Eio.Net.t; .. > -> ?count:int -> ?start:int -> string -> string -> video_response-val fetch_all_channel_videos : ?page_size:int -> ?max_pages:int -> string -> string -> video list Lwt.t+val fetch_all_channel_videos : sw:Eio.Switch.t -> env:< clock : 'a Eio.Time.clock; net : 'b Eio.Net.t; .. > -> ?page_size:int -> ?max_pages:int -> string -> string -> video list+val fetch_video_details : sw:Eio.Switch.t -> env:< clock : 'a Eio.Time.clock; net : 'b Eio.Net.t; .. > -> string -> string -> video···+val download_thumbnail : sw:Eio.Switch.t -> env:< clock : 'a Eio.Time.clock; net : 'b Eio.Net.t; fs : 'c Eio.Path.t; .. > -> string -> video -> string -> (unit, [> `Msg of string]) result
-36
stack/bushel/typesense-client.opam
-36
stack/bushel/typesense-client.opam
···
-5
stack/bushel/typesense-client/dune
-5
stack/bushel/typesense-client/dune
+89
-87
stack/bushel/typesense-client/typesense_client.ml
stack/typesense-cliente/typesense_cliente.ml
+89
-87
stack/bushel/typesense-client/typesense_client.ml
stack/typesense-cliente/typesense_cliente.ml
·········+let body = if body = "" then None else Some (Requests.Body.of_string Requests.Mime.json body) in·········let hits = get_dict json |> List.assoc "hits" |> get_list (parse_search_result collection) in······let path = Printf.sprintf "/collections/%s/documents/search?q=%s&query_by=%s&per_page=%d&page=%d&highlight_full_fields=%s"·········let body = Ezjsonm.dict [("searches", Ezjsonm.list (fun x -> x) searches)] |> Ezjsonm.value_to_string inlet combine_multisearch_results (multisearch_resp : multisearch_response) ?(limit=10) ?(offset=0) () =let total = List.fold_left (fun acc response -> acc + response.total) 0 multisearch_resp.results inlet query_time = List.fold_left (fun acc response -> acc +. response.query_time) 0.0 multisearch_resp.results in······| ts -> Printf.sprintf "%s (+%d more)" (String.concat ", " (take 2 ts)) (List.length ts - 2)······
-60
stack/bushel/typesense-client/typesense_client.mli
-60
stack/bushel/typesense-client/typesense_client.mli
···-val search_collection : config -> string -> string -> ?limit:int -> ?offset:int -> unit -> (search_response, error) result Lwt.t-val multisearch : config -> string -> ?limit:int -> unit -> (multisearch_response, error) result Lwt.t-val combine_multisearch_results : multisearch_response -> ?limit:int -> ?offset:int -> unit -> search_response
+195
stack/immiche/README.md
+195
stack/immiche/README.md
···+A clean Eio-based OCaml library for interacting with Immich instances, focusing on people and face recognition data.+Immiche provides a straightforward API for interacting with Immich's people management endpoints. It uses the Requests library for HTTP operations and follows Eio patterns for concurrency and resource management.+- `requests_session` - Optional Requests session for connection pooling. If not provided, a new session is created.+You can share a `Requests.t` session across multiple API clients for maximum connection reuse:
+4
stack/immiche/dune
+4
stack/immiche/dune
+19
stack/immiche/dune-project
+19
stack/immiche/dune-project
···
+137
stack/immiche/immiche.ml
+137
stack/immiche/immiche.ml
···
+100
stack/immiche/immiche.mli
+100
stack/immiche/immiche.mli
···+([> float Eio.Time.clock_ty ] Eio.Resource.t, [> [> `Generic ] Eio.Net.ty ] Eio.Resource.t) t ->+([> float Eio.Time.clock_ty ] Eio.Resource.t, [> [> `Generic ] Eio.Net.ty ] Eio.Resource.t) t ->+([> float Eio.Time.clock_ty ] Eio.Resource.t, [> [> `Generic ] Eio.Net.ty ] Eio.Resource.t) t ->+([> float Eio.Time.clock_ty ] Eio.Resource.t, [> [> `Generic ] Eio.Net.ty ] Eio.Resource.t) t ->
+31
stack/immiche/immiche.opam
+31
stack/immiche/immiche.opam
···
+5
-4
stack/jmap/jmap-client/jmap_client.ml
+5
-4
stack/jmap/jmap-client/jmap_client.ml
···
+4
stack/karakeepe/dune
+4
stack/karakeepe/dune
+19
stack/karakeepe/dune-project
+19
stack/karakeepe/dune-project
···+(description "An Eio-based OCaml client library for the Karakeep bookmark management service API")
+472
stack/karakeepe/karakeepe.ml
+472
stack/karakeepe/karakeepe.ml
···+let fetch_bookmarks ~sw ~env ~api_key ?(limit=50) ?(offset=0) ?cursor ?(include_content=false) ?filter_tags base_url =+let fetch_all_bookmarks ~sw ~env ~api_key ?(page_size=50) ?max_pages ?filter_tags ?(include_content=false) base_url =+| Some cursor_str -> fetch_bookmarks ~sw ~env ~api_key ~limit:page_size ~cursor:cursor_str ~include_content ?filter_tags base_url+| None -> fetch_bookmarks ~sw ~env ~api_key ~limit:page_size ~offset:(page_num * page_size) ~include_content ?filter_tags base_url+let create_bookmark ~sw ~env ~api_key ~url ?title ?note ?tags ?(favourited=false) ?(archived=false) base_url =+let response = Requests.One.post ~sw ~clock:env#clock ~net:env#net ~headers ~body url_endpoint in+let tags_response = Requests.One.post ~sw ~clock:env#clock ~net:env#net ~headers ~body:tags_body tags_url in+failwith (Fmt.str "Failed to create bookmark. HTTP error: %d. Details: %s" status_code error_body)
+32
stack/karakeepe/karakeepe.opam
+32
stack/karakeepe/karakeepe.opam
···
+39
stack/peertubee/README.md
+39
stack/peertubee/README.md
···+- **Replaced** `Cohttp_lwt.Body.to_string body >>= fun s ->` with `let s = Requests.Response.body response |> Eio.Flow.read_all in`
+4
stack/peertubee/dune
+4
stack/peertubee/dune
+18
stack/peertubee/dune-project
+18
stack/peertubee/dune-project
···
+31
stack/peertubee/peertubee.opam
+31
stack/peertubee/peertubee.opam
···
+5
-3
stack/requests/bin/ocurl.ml
+5
-3
stack/requests/bin/ocurl.ml
···
+112
-167
stack/requests/lib/one.ml
+112
-167
stack/requests/lib/one.ml
···+(Tls_eio.client_of_flow ~host:domain tls_cfg flow :> [`Close | `Flow | `R | `Shutdown | `W] Eio.Resource.t)···-Http_client.make_request ~method_:method_str ~uri:uri_to_fetch ~headers ~body_str:request_body_str flow·········
+80
-94
stack/requests/lib/one.mli
+80
-94
stack/requests/lib/one.mli
·········-(** [create ~sw ?default_headers ?timeout ?max_retries ?retry_backoff ?verify_tls ?tls_config ~clock ~net ()]-val default : sw:Eio.Switch.t -> clock:'a Eio.Time.clock -> net:'b Eio.Net.t -> ('a Eio.Time.clock, 'b Eio.Net.t) t···
+239
-80
stack/requests/lib/requests.ml
+239
-80
stack/requests/lib/requests.ml
·········+Log.info (fun m -> m "Created Requests session with connection pools (max_per_host=%d, TLS=%b)"·········let make_request_internal t ?headers ?body ?auth ?timeout ?follow_redirects ?max_redirects ~method_ url =······-Response.make ~sw:t.sw ~status:status_code ~headers:resp_headers ~body:new_body_flow ~url ~elapsed:0.0-Log.debug (fun m -> m "Cache not applicable for %s request to %s (cache enabled: %b, body present: %b)"+Response.Private.make ~sw:t.sw ~status ~headers:resp_headers ~body:body_flow ~url ~elapsed:0.0······
+43
-16
stack/requests/lib/requests.mli
+43
-16
stack/requests/lib/requests.mli
···-(** A stateful HTTP client that maintains cookies, auth, and configuration across requests. *)···< clock: 'clock Eio.Resource.t; net: 'net Eio.Resource.t; fs: Eio.Fs.dir_ty Eio.Path.t; .. > ->+@param xdg XDG directory context for cookies/cache (required if persist_cookies or enable_cache)
+12
-23
stack/requests/test/test_connection_pool.ml
+12
-23
stack/requests/test/test_connection_pool.ml
·········
+7
-5
stack/requests/test/test_requests.ml
+7
-5
stack/requests/test/test_requests.ml
·········
+4
stack/typesense-cliente/dune
+4
stack/typesense-cliente/dune
+18
stack/typesense-cliente/dune-project
+18
stack/typesense-cliente/dune-project
···
+30
stack/typesense-cliente/typesense-cliente.opam
+30
stack/typesense-cliente/typesense-cliente.opam
···
+85
stack/typesense-cliente/typesense_cliente.mli
+85
stack/typesense-cliente/typesense_cliente.mli
···+env:< clock: [> float Eio.Time.clock_ty ] Eio.Resource.t; net: [> [> `Generic ] Eio.Net.ty ] Eio.Resource.t; .. > ->+env:< clock: [> float Eio.Time.clock_ty ] Eio.Resource.t; net: [> [> `Generic ] Eio.Net.ty ] Eio.Resource.t; .. > ->+env:< clock: [> float Eio.Time.clock_ty ] Eio.Resource.t; net: [> [> `Generic ] Eio.Net.ty ] Eio.Resource.t; .. > ->
+1
-1
stack/zotero-translation/dune
+1
-1
stack/zotero-translation/dune
+66
-68
stack/zotero-translation/zotero_translation.ml
+66
-68
stack/zotero-translation/zotero_translation.ml
···(* From the ZTS source code: https://github.com/zotero/translation-server/blob/master/src/formats.js···+failwith "Zotero_translation.v is deprecated. Use Zotero_translation.create ~sw ~env base_uri instead"-Lwt.return_error (`Msg (Format.asprintf "Unexpected HTTP status: %a for %s" Http.Status.pp status body))-Lwt.return_error (`Msg (Format.asprintf "Unexpected HTTP status: %a for %s" Http.Status.pp status body))-Lwt.return_error (`Msg (Format.asprintf "Unexpected HTTP status: %a for %s" Http.Status.pp status body))-Lwt.return_error (`Msg (Format.asprintf "Unexpected HTTP status: %a for %s" Http.Status.pp status body))···let f = Bibtex.fields bib |> Bibtex.SM.bindings |> List.map (fun (k,v) -> k, (unescape_bibtex v)) in···
+25
-7
stack/zotero-translation/zotero_translation.mli
+25
-7
stack/zotero-translation/zotero_translation.mli
······+val resolve_doi: ([> float Eio.Time.clock_ty ] Eio.Resource.t, [> [> `Generic ] Eio.Net.ty ] Eio.Resource.t) t ->+val resolve_url: ([> float Eio.Time.clock_ty ] Eio.Resource.t, [> [> `Generic ] Eio.Net.ty ] Eio.Resource.t) t ->+val search_id: ([> float Eio.Time.clock_ty ] Eio.Resource.t, [> [> `Generic ] Eio.Net.ty ] Eio.Resource.t) t ->+val export: ([> float Eio.Time.clock_ty ] Eio.Resource.t, [> [> `Generic ] Eio.Net.ty ] Eio.Resource.t) t ->+val json_of_doi : ([> float Eio.Time.clock_ty ] Eio.Resource.t, [> [> `Generic ] Eio.Net.ty ] Eio.Resource.t) t ->