My aggregated monorepo of OCaml code, automaintained
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat: wire @x-ocaml.requires through to worker init

- Add --copy-file flag to jtw opam/opam-all for including x-ocaml.js
and other assets in universe output
- Pass findlib_requires and findlib_index from meta tags through to
the JTW worker init, so @x-ocaml.requires packages are loaded
during setup
- x_ocaml.ml reads <meta name="x-ocaml-packages"> and
<meta name="x-ocaml-universe"> before creating the backend

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

+70 -16
+28 -4
js_top_worker/bin/jtw.ml
··· 73 73 Format.eprintf "Warning: Failed to read deps file %s: %s\n%!" path m; 74 74 [] 75 75 76 - let opam verbose output_dir_str switch libraries no_worker path deps_file = 76 + let copy_extra_files output_dir files = 77 + List.iter (fun src -> 78 + let src = Fpath.v src in 79 + let dst = Fpath.(output_dir / Fpath.filename src) in 80 + Util.cp src dst; 81 + Format.eprintf "Copied %a to %a\n%!" Fpath.pp src Fpath.pp dst) 82 + files 83 + 84 + let opam verbose output_dir_str switch libraries no_worker path deps_file extra_files = 77 85 Opam.switch := switch; 78 86 (* When --path is specified, only compile the specified libraries (no deps) *) 79 87 let libraries_with_deps, libraries_only = ··· 293 301 let () = 294 302 if no_worker then () else Mk_backend.mk switch output_dir 295 303 in 304 + copy_extra_files output_dir extra_files; 296 305 297 306 `Ok () 298 307 ··· 404 413 let local_meta_path = Fpath.(v "lib" // meta_rel / "META" |> to_string) in 405 414 (pkg_path, local_meta_path, pkg_deps) 406 415 407 - let opam_all verbose output_dir_str switch libraries no_worker all_pkgs = 416 + let opam_all verbose output_dir_str switch libraries no_worker all_pkgs extra_files = 408 417 Opam.switch := switch; 409 418 410 419 (* Get all packages and their dependencies *) ··· 491 500 492 501 (* Generate worker.js if requested *) 493 502 let () = if no_worker then () else Mk_backend.mk switch output_dir in 503 + copy_extra_files output_dir extra_files; 494 504 495 505 `Ok () 496 506 ··· 530 540 in 531 541 Arg.(value & opt (some string) None & info [ "deps-file" ] ~doc) 532 542 in 543 + let extra_files = 544 + let doc = 545 + "Copy file into the output directory (e.g., --copy-file /path/to/x-ocaml.js). \ 546 + May be repeated." 547 + in 548 + Arg.(value & opt_all string [] & info [ "copy-file" ] ~doc) 549 + in 533 550 let info = Cmd.info "opam" ~doc:"Generate opam files" in 534 551 Cmd.v info 535 - Term.(ret (const opam $ verbose $ output_dir $ switch $ libraries $ no_worker $ path $ deps_file)) 552 + Term.(ret (const opam $ verbose $ output_dir $ switch $ libraries $ no_worker $ path $ deps_file $ extra_files)) 536 553 537 554 let opam_all_cmd = 538 555 let libraries = Arg.(value & pos_all string [] & info [] ~docv:"LIB") in ··· 558 575 let doc = "Build all installed packages (from ocamlfind list)" in 559 576 Arg.(value & flag & info [ "all" ] ~doc) 560 577 in 578 + let extra_files = 579 + let doc = 580 + "Copy file into the output directory (e.g., --copy-file /path/to/x-ocaml.js). \ 581 + May be repeated." 582 + in 583 + Arg.(value & opt_all string [] & info [ "copy-file" ] ~doc) 584 + in 561 585 let info = Cmd.info "opam-all" ~doc:"Generate universes for all packages and their dependencies" in 562 586 Cmd.v info 563 - Term.(ret (const opam_all $ verbose $ output_dir $ switch $ libraries $ no_worker $ all_pkgs)) 587 + Term.(ret (const opam_all $ verbose $ output_dir $ switch $ libraries $ no_worker $ all_pkgs $ extra_files)) 564 588 565 589 let main_cmd = 566 590 let doc = "An odoc notebook tool" in
+4 -4
x-ocaml/src/backend.ml
··· 25 25 let make_builtin ?extra_load url = 26 26 Builtin (Client.make ?extra_load url) 27 27 28 - let make_jtw url = 28 + let make_jtw ?findlib_requires ?findlib_index url = 29 29 let client = Jtw_client.make url in 30 - Jtw_client.init client; 30 + Jtw_client.init ?findlib_requires ?findlib_index client; 31 31 Jtw client 32 32 33 - let make ~backend ?extra_load url = 33 + let make ~backend ?extra_load ?findlib_requires ?findlib_index url = 34 34 match String.lowercase_ascii backend with 35 - | "jtw" | "js_top_worker" -> make_jtw url 35 + | "jtw" | "js_top_worker" -> make_jtw ?findlib_requires ?findlib_index url 36 36 | "builtin" | "x-ocaml" | _ -> make_builtin ?extra_load url 37 37 38 38 let on_message t fn =
+7 -3
x-ocaml/src/backend.mli
··· 57 57 (** Create a client with the built-in x-ocaml worker backend *) 58 58 val make_builtin : ?extra_load:string -> string -> t 59 59 60 - (** Create a client with the js_top_worker backend *) 61 - val make_jtw : string -> t 60 + (** Create a client with the js_top_worker backend. 61 + @param findlib_requires Packages to load during worker init 62 + @param findlib_index URL to findlib_index.json *) 63 + val make_jtw : ?findlib_requires:string list -> ?findlib_index:string -> string -> t 62 64 63 65 (** Create a client with the specified backend. 64 66 @param backend Backend name: "builtin", "x-ocaml", "jtw", or "js_top_worker" 65 67 @param extra_load Optional URL to load before the worker (builtin only) 68 + @param findlib_requires Packages to load during worker init (jtw only) 69 + @param findlib_index URL to findlib_index.json (jtw only) 66 70 @param url URL to the worker script *) 67 - val make : backend:string -> ?extra_load:string -> string -> t 71 + val make : backend:string -> ?extra_load:string -> ?findlib_requires:string list -> ?findlib_index:string -> string -> t 68 72 69 73 (** Set the response handler *) 70 74 val on_message : t -> (X_protocol.response -> unit) -> unit
+3 -3
x-ocaml/src/jtw_client.ml
··· 96 96 in 97 97 (loc, `String t.type_str, tail) 98 98 99 - let init t = 99 + let init ?(findlib_requires = []) ?findlib_index t = 100 100 let config : Msg.init_config = { 101 - findlib_requires = []; 101 + findlib_requires; 102 102 stdlib_dcs = None; 103 - findlib_index = None; 103 + findlib_index; 104 104 } in 105 105 Lwt.async (fun () -> 106 106 let open Lwt.Infix in
+1 -1
x-ocaml/src/jtw_client.mli
··· 2 2 type t 3 3 val make : string -> t 4 4 val on_message : t -> (X_protocol.response -> unit) -> unit 5 - val init : t -> unit 5 + val init : ?findlib_requires:string list -> ?findlib_index:string -> t -> unit 6 6 val post : t -> X_protocol.request -> unit 7 7 val eval : id:int -> line_number:int -> t -> string -> unit 8 8 val fmt : id:int -> t -> string -> unit
+27 -1
x-ocaml/src/x_ocaml.ml
··· 21 21 else "" 22 22 | Some url -> Jstr.to_string url 23 23 24 - let backend = Backend.make ~backend:backend_name ?extra_load worker_url 24 + let read_meta name = 25 + let doc = Brr.Document.to_jv Brr.G.document in 26 + let selector = Jstr.of_string ("meta[name=\"" ^ name ^ "\"]") in 27 + let result = Jv.call doc "querySelector" [| Jv.of_jstr selector |] in 28 + if Jv.is_none result then None 29 + else 30 + let content = Jv.call result "getAttribute" [| Jv.of_string "content" |] in 31 + if Jv.is_none content then None 32 + else Some (Jv.to_string content) 33 + 34 + let findlib_requires = 35 + match read_meta "x-ocaml-packages" with 36 + | None -> None 37 + | Some s -> 38 + let pkgs = List.filter (fun s -> s <> "") 39 + (List.map String.trim (String.split_on_char ',' s)) in 40 + if pkgs = [] then None else Some pkgs 41 + 42 + let findlib_index = 43 + match read_meta "x-ocaml-universe" with 44 + | None -> None 45 + | Some base -> 46 + let base = if String.length base > 0 && base.[String.length base - 1] = '/' 47 + then base else base ^ "/" in 48 + Some (base ^ "findlib_index.json") 49 + 50 + let backend = Backend.make ~backend:backend_name ?extra_load ?findlib_requires ?findlib_index worker_url 25 51 26 52 let format_config = 27 53 match current_attribute "x-ocamlformat" with