Docs: normalize and prettify both errors and rpc documentation
This commit is contained in:
parent
369b6d7988
commit
73ba0a3fb5
@ -7,13 +7,16 @@ BUILDDIR = _build
|
|||||||
|
|
||||||
DOCGENDIR = doc_gen
|
DOCGENDIR = doc_gen
|
||||||
DOCERRORDIR = $(DOCGENDIR)/errors
|
DOCERRORDIR = $(DOCGENDIR)/errors
|
||||||
DOCRPCDIR = $(DOCGENDIR)/rpcs
|
DOCRPCDIR = $(DOCGENDIR)/rpcs
|
||||||
|
|
||||||
all: html linkcheck
|
all: html linkcheck
|
||||||
|
|
||||||
linkcheck:
|
linkcheck:
|
||||||
$(SPHINXBUILD) -b linkcheck "$(SOURCEDIR)" "$(BUILDDIR)"
|
$(SPHINXBUILD) -b linkcheck "$(SOURCEDIR)" "$(BUILDDIR)"
|
||||||
|
|
||||||
|
introduction/readme.rst: ../README.rst
|
||||||
|
sed 's/TEZOS/How to build and run/' $< > $@
|
||||||
|
|
||||||
api/errors.rst: $(DOCERRORDIR)/error_doc.ml
|
api/errors.rst: $(DOCERRORDIR)/error_doc.ml
|
||||||
@jbuilder build $(DOCERRORDIR)/error_doc.exe
|
@jbuilder build $(DOCERRORDIR)/error_doc.exe
|
||||||
../_build/default/docs/$(DOCERRORDIR)/error_doc.exe > api/errors.rst
|
../_build/default/docs/$(DOCERRORDIR)/error_doc.exe > api/errors.rst
|
||||||
@ -31,4 +34,4 @@ html: Makefile api/errors.rst api/rpc.rst
|
|||||||
|
|
||||||
clean:
|
clean:
|
||||||
@-rm -Rf "$(BUILDDIR)"
|
@-rm -Rf "$(BUILDDIR)"
|
||||||
@-rm -Rf introduction/readme.rst api/errors.rst
|
@-rm -Rf introduction/readme.rst api/errors.rst api/rpc.rst
|
||||||
|
@ -7,7 +7,9 @@
|
|||||||
(* *)
|
(* *)
|
||||||
(**************************************************************************)
|
(**************************************************************************)
|
||||||
|
|
||||||
(* Todo : add section descriptions *)
|
open Format
|
||||||
|
|
||||||
|
(* TODO: add section descriptions *)
|
||||||
|
|
||||||
let default_section_id = "default"
|
let default_section_id = "default"
|
||||||
let default_section_title = "Miscellaneous"
|
let default_section_title = "Miscellaneous"
|
||||||
@ -21,45 +23,20 @@ let default_section_title = "Miscellaneous"
|
|||||||
bottom of the document. Unprefixed ids or unreferenced prefixes
|
bottom of the document. Unprefixed ids or unreferenced prefixes
|
||||||
will default to `Miscellaneous` *)
|
will default to `Miscellaneous` *)
|
||||||
let section_titles =
|
let section_titles =
|
||||||
[
|
[ [ "proto.alpha" ], "Protocol Alpha";
|
||||||
[ "proto" ], "Protocol Alpha";
|
[ "distributed_db" ; "node" ; "raw_store" ; "validator" ; "worker" ], "Shell" ;
|
||||||
[ "baking" ], "Baking" ;
|
[ "micheline" ; "michelson" ], "Michelson parsing/macros" ;
|
||||||
[ "contract" ], "Smart Contracts" ;
|
[ "rpc_client" ], "Client" ;
|
||||||
[ "distributed_db" ], "Database" ;
|
|
||||||
[ "micheline" ; "michelson" ], "Smart Contracts" ;
|
|
||||||
(* [ "michelson" ], "Michelson" ; *)
|
|
||||||
[ "node" ], "Client Node" ;
|
|
||||||
[ "operation" ], "Operations" ;
|
|
||||||
[ "prevalidation" ], "Prevalidation" ;
|
|
||||||
[ "raw_store" ], "Store" ;
|
|
||||||
[ "rpc_client" ], "RPC Client" ;
|
|
||||||
[ "tez" ], "Tezos operations" ;
|
|
||||||
[ "validator" ], "Validator" ;
|
|
||||||
[ "worker" ], "Worker" ;
|
|
||||||
(* [ "cli" ], "Command Line" ; *)
|
|
||||||
[ "cli"; "utils"; default_section_id ], default_section_title ;
|
[ "cli"; "utils"; default_section_id ], default_section_title ;
|
||||||
]
|
]
|
||||||
|
|
||||||
let categories_detail =
|
|
||||||
[ "temporary", "An error resulting from an operation that might be \
|
|
||||||
valid in the future, for example, a contract’s balance \
|
|
||||||
being too low to execute the intended operation. This \
|
|
||||||
can be fixed by adding more to the contract’s balance."
|
|
||||||
; "branch", "An error that occurs in one branch of the chain, but may not \
|
|
||||||
occur in a different one. For example, receiving an \
|
|
||||||
operation for an old or future protocol version."
|
|
||||||
; "permanent", "An error that is not recoverable because the operation \
|
|
||||||
is never going to be valid. For example, an invalid ꜩ \
|
|
||||||
notation." ]
|
|
||||||
|
|
||||||
let pp_rst_title ~char ppf title =
|
let pp_rst_title ~char ppf title =
|
||||||
let sub = String.map (fun _ -> char) title in
|
let sub = String.map (fun _ -> char) title in
|
||||||
Format.fprintf ppf "@[<v 0>%s@\n@]@[<v 0>%s@\n@\n@]" title sub
|
fprintf ppf "@[<v 0>%s@\n@]@[<v 0>%s@\n@\n@]" title sub
|
||||||
|
|
||||||
let pp_rst_h1 = pp_rst_title ~char:'#'
|
let pp_rst_h1 = pp_rst_title ~char:'#'
|
||||||
let pp_rst_h2 = pp_rst_title ~char:'*'
|
let pp_rst_h2 = pp_rst_title ~char:'*'
|
||||||
let pp_rst_h3 = pp_rst_title ~char:'='
|
(* let pp_rst_h3 = pp_rst_title ~char:'='
|
||||||
let pp_rst_h4 = pp_rst_title ~char:'`'
|
* let pp_rst_h4 = pp_rst_title ~char:'`' *)
|
||||||
|
|
||||||
let string_of_err_category =
|
let string_of_err_category =
|
||||||
let open Error_monad in function
|
let open Error_monad in function
|
||||||
@ -67,28 +44,68 @@ let string_of_err_category =
|
|||||||
| `Temporary -> "temporary"
|
| `Temporary -> "temporary"
|
||||||
| `Permanent -> "permanent"
|
| `Permanent -> "permanent"
|
||||||
|
|
||||||
|
let make_counter () =
|
||||||
|
let i = ref 1 in
|
||||||
|
fun () -> incr i; !i
|
||||||
|
|
||||||
|
let count = make_counter ()
|
||||||
|
|
||||||
|
let unique_label () =
|
||||||
|
let label = sprintf "ref%d" (count ()) in
|
||||||
|
label
|
||||||
|
|
||||||
|
let pp_print_html_tab_button fmt ?(default=false) ~shortlabel ~content idref =
|
||||||
|
fprintf fmt "<button class=\"tablinks%s\" onclick=\"showTab(this, '%s', '%s')\">%s</button>@ "
|
||||||
|
(if default then " defaultOpen" else "")
|
||||||
|
(idref ^ shortlabel) idref content
|
||||||
|
|
||||||
|
let pp_print_html_tabs fmt { Error_monad.id ; category ; description ; schema ; _ } =
|
||||||
|
let idref = unique_label () in
|
||||||
|
let descr_label = "descr" in
|
||||||
|
let schema_label = "schema" in
|
||||||
|
|
||||||
|
fprintf fmt "@[<v 2>.. raw:: html@ @ ";
|
||||||
|
fprintf fmt "@[<v 2><div class=\"tab\">@ ";
|
||||||
|
|
||||||
|
fprintf fmt "%a" (pp_print_html_tab_button ~default:true ~shortlabel:descr_label ~content:"Description") idref;
|
||||||
|
fprintf fmt "%a" (pp_print_html_tab_button ~default:false ~shortlabel:schema_label ~content:"JSON Schema") idref;
|
||||||
|
fprintf fmt "@ </div>@ @]";
|
||||||
|
|
||||||
|
let description_content =
|
||||||
|
asprintf "<p>%s</p><p><i>Id</i> : %s<br/><i>Category</i> : %s</p>" description id (string_of_err_category category)
|
||||||
|
in
|
||||||
|
|
||||||
|
open_vbox 2;
|
||||||
|
|
||||||
|
(* Print description *)
|
||||||
|
begin
|
||||||
|
fprintf fmt "<div id=\"%s\" class=\"%s tabcontent\" style=\"min-height:100px; max-height:200px; overflow:auto\" >@ "
|
||||||
|
(idref ^ descr_label) idref;
|
||||||
|
fprintf fmt "%s@ " description_content;
|
||||||
|
fprintf fmt "</div>@]";
|
||||||
|
end;
|
||||||
|
|
||||||
|
(* Print schema *)
|
||||||
|
begin
|
||||||
|
(* Hack: negative offset in order to reduce the <pre>'s content left-margin *)
|
||||||
|
(* TODO: pretty-(html)-print the schema *)
|
||||||
|
open_vbox (-8);
|
||||||
|
fprintf fmt "<div id=\"%s\" class=\"%s tabcontent\" style=\"min-height:100px; max-height:200px; overflow:auto\" >@ "
|
||||||
|
(idref ^ schema_label) idref;
|
||||||
|
fprintf fmt "<%s>@ %a</%s>@ " "pre" Json_schema.pp schema "pre";
|
||||||
|
fprintf fmt "</div>";
|
||||||
|
close_box ();
|
||||||
|
end;
|
||||||
|
|
||||||
|
close_box ()
|
||||||
|
|
||||||
let pp_info_to_rst
|
let pp_info_to_rst
|
||||||
ppf
|
ppf
|
||||||
{ Error_monad.id ; title ; category ; description ; schema } =
|
(Error_monad.{ title ; _ } as error_info) =
|
||||||
let open Format in
|
let open Format in
|
||||||
|
|
||||||
fprintf ppf "@[<v 2>- **%s**@,@,"
|
fprintf ppf "**%s**@\n@\n" (if title = "" then "<Untitled>" else title);
|
||||||
(if title = "" then "<Untitled>" else title) ;
|
fprintf ppf "@[<v>%a@ @ @]" pp_print_html_tabs error_info;
|
||||||
|
|
||||||
fprintf ppf "@[<v 0>%s@\n@\n@]"
|
|
||||||
(if description = "" then "Not description available" else description) ;
|
|
||||||
|
|
||||||
fprintf ppf "@[<v 0>* *Id* : %s@\n@\n@]" id ;
|
|
||||||
|
|
||||||
fprintf ppf "@[* *Category* : %s@\n@\n@]" (string_of_err_category category) ;
|
|
||||||
|
|
||||||
fprintf ppf "@[<v 2>.. container:: schema-button@\n@\n" ;
|
|
||||||
fprintf ppf "@[<v 2>Show schema@]@]@\n@\n" ;
|
|
||||||
|
|
||||||
fprintf ppf "@[<v 2>.. container:: schema@\n@\n" ;
|
|
||||||
fprintf ppf "@[<v 2>.. code-block:: json@\n@\n" ;
|
|
||||||
|
|
||||||
fprintf ppf "@[%a@]@]@]@]" Json_schema.pp schema
|
|
||||||
|
|
||||||
module ErrorSet = Set.Make(struct
|
module ErrorSet = Set.Make(struct
|
||||||
type t = Error_monad.error_info
|
type t = Error_monad.error_info
|
||||||
@ -113,32 +130,20 @@ module ErrorPartition = struct
|
|||||||
end)
|
end)
|
||||||
|
|
||||||
let add_error (id : key) (error : Error_monad.error_info) (map : 'a t) =
|
let add_error (id : key) (error : Error_monad.error_info) (map : 'a t) =
|
||||||
let lr_opt = Stringext.cut id ~on:"." in
|
|
||||||
|
|
||||||
let id_prefix =
|
|
||||||
match lr_opt with
|
|
||||||
| None -> default_section_id
|
|
||||||
| Some (prefix, _r) -> prefix
|
|
||||||
in
|
|
||||||
|
|
||||||
let title =
|
let title =
|
||||||
try
|
try
|
||||||
snd (List.find
|
snd
|
||||||
(fun (id_set, _) -> List.mem id_prefix id_set)
|
(List.find
|
||||||
section_titles)
|
(fun (id_set, _) ->
|
||||||
|
List.exists (fun pattern -> Stringext.find_from id ~pattern = Some 0) id_set)
|
||||||
|
section_titles)
|
||||||
with
|
with
|
||||||
| Not_found -> default_section_title
|
| Not_found -> default_section_title
|
||||||
in
|
in
|
||||||
|
|
||||||
let set =
|
let set =
|
||||||
try
|
try find title map with Not_found -> ErrorSet.empty
|
||||||
find title map
|
|
||||||
with
|
|
||||||
| Not_found -> ErrorSet.empty
|
|
||||||
in
|
in
|
||||||
|
|
||||||
add title (ErrorSet.add error set) map
|
add title (ErrorSet.add error set) map
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
let pp_error_map ppf (map : ErrorSet.t ErrorPartition.t) : unit =
|
let pp_error_map ppf (map : ErrorSet.t ErrorPartition.t) : unit =
|
||||||
@ -152,21 +157,67 @@ let pp_error_map ppf (map : ErrorSet.t ErrorPartition.t) : unit =
|
|||||||
) set
|
) set
|
||||||
) map
|
) map
|
||||||
|
|
||||||
|
let script =
|
||||||
|
"<script>\
|
||||||
|
function showTab(elt, tab, ref) {\
|
||||||
|
var i, tabcontent, tablinks;\
|
||||||
|
\
|
||||||
|
tabcontent = document.getElementsByClassName(ref);\
|
||||||
|
for (i = 0; i < tabcontent.length; i++) {\
|
||||||
|
tabcontent[i].style.display = 'none';\
|
||||||
|
}\
|
||||||
|
\
|
||||||
|
tablinks = elt.parentNode.children;\
|
||||||
|
for (i = 0; i < tablinks.length; i++) {\
|
||||||
|
tablinks[i].className = tablinks[i].className.replace(' active', '');\
|
||||||
|
}\
|
||||||
|
\
|
||||||
|
document.getElementById(tab).style.display = 'block';\
|
||||||
|
elt.className += ' active';\
|
||||||
|
}\
|
||||||
|
\
|
||||||
|
document.addEventListener('DOMContentLoaded', function(){\
|
||||||
|
var a = document.getElementsByClassName('defaultOpen');\
|
||||||
|
for (i = 0; i < a.length; i++) { a[i].click() }\
|
||||||
|
})\
|
||||||
|
</script>"
|
||||||
|
|
||||||
|
let style =
|
||||||
|
"<style>\
|
||||||
|
.tab {\
|
||||||
|
overflow: hidden;\
|
||||||
|
border: 1px solid #ccc;\
|
||||||
|
background-color: #f1f1f1;\
|
||||||
|
}\
|
||||||
|
.tab button {\
|
||||||
|
background-color: inherit;\
|
||||||
|
float: left;\
|
||||||
|
border: none;\
|
||||||
|
outline: none;\
|
||||||
|
cursor: pointer;\
|
||||||
|
padding: 5px 10px;\
|
||||||
|
}\
|
||||||
|
.tab button:hover {\
|
||||||
|
background-color: #ddd;\
|
||||||
|
}\
|
||||||
|
.tab button.active {\
|
||||||
|
background-color: #ccc;\
|
||||||
|
}\
|
||||||
|
.tabcontent {\
|
||||||
|
display: none;\
|
||||||
|
padding: 6px 12px;\
|
||||||
|
border: 1px solid #ccc;\
|
||||||
|
border-top: none;\
|
||||||
|
margin-bottom: 20px;\
|
||||||
|
}\
|
||||||
|
pre {\
|
||||||
|
font-size: 12px\
|
||||||
|
}</style>"
|
||||||
|
|
||||||
let print_script ppf =
|
let print_script ppf =
|
||||||
(* HACK : show/hide JSON schemas + style *)
|
(* HACK : show/hide JSON schemas + style *)
|
||||||
Format.fprintf ppf "@[<v 2>.. raw:: html@\n@\n" ;
|
fprintf ppf "@[<v 2>.. raw:: html@\n@\n" ;
|
||||||
Format.fprintf ppf "@[<v 0>%s%s@]@\n@\n@]"
|
fprintf ppf "@[<v 0>%s%s@]@\n@\n@]@]@." script style
|
||||||
"<script>document.addEventListener('DOMContentLoaded', function(){\
|
|
||||||
$(\".schema-button\").click(function(){$(this).next(\".schema\")\
|
|
||||||
.first().toggle()})}, false);</script>"
|
|
||||||
"<style>.schema { display:none; margin:0 0 0 10px; }\
|
|
||||||
.schema-button { cursor:pointer; font-size:11px;\
|
|
||||||
font-weight: bold; background-color: #EEEEEE;\
|
|
||||||
color: #333333; padding: 2px 6px 2px 6px;\
|
|
||||||
border-top: 1px solid #CCCCCC; border-right: 1px solid #333333;\
|
|
||||||
border-bottom: 1px solid #333333; border-left: 1px solid #CCCCCC;\
|
|
||||||
width : -moz-fit-content; }\
|
|
||||||
section li { margin:10px 0 10px 0; } </style>"
|
|
||||||
|
|
||||||
(* Main *)
|
(* Main *)
|
||||||
let () =
|
let () =
|
||||||
@ -174,22 +225,14 @@ let () =
|
|||||||
let ppf = std_formatter in
|
let ppf = std_formatter in
|
||||||
|
|
||||||
(* Header *)
|
(* Header *)
|
||||||
let title = "Tezos Client Errors" in
|
let title = "RPC Errors" in
|
||||||
fprintf ppf "%a" pp_rst_h1 title ;
|
fprintf ppf "%a" pp_rst_h1 title ;
|
||||||
|
|
||||||
print_script ppf ;
|
print_script ppf ;
|
||||||
|
|
||||||
fprintf ppf "This document references possible errors.@\n@\n" ;
|
fprintf ppf "This document references possible errors that can come\
|
||||||
|
from RPC calls. It is generated from the OCaml source\
|
||||||
fprintf ppf "There are three categories of error :@\n@\n" ;
|
code (master branch).@\n@\n" ;
|
||||||
|
|
||||||
List.iter (fun (cat, descr) ->
|
|
||||||
fprintf ppf "- :literal:`%s` - %s@\n@\n" cat descr) categories_detail ;
|
|
||||||
|
|
||||||
fprintf ppf "See `The Error Monad`_ for further details.@\n@\n" ;
|
|
||||||
fprintf
|
|
||||||
ppf ".. _The Error Monad: \
|
|
||||||
../tutorials/error_monad.html#the-actual-tezos-error-monad@\n@\n" ;
|
|
||||||
|
|
||||||
(* Body *)
|
(* Body *)
|
||||||
let map =
|
let map =
|
||||||
|
@ -4,13 +4,12 @@
|
|||||||
((name error_doc)
|
((name error_doc)
|
||||||
(libraries
|
(libraries
|
||||||
(tezos-shell
|
(tezos-shell
|
||||||
tezos-embedded-protocol-alpha))
|
tezos-client-alpha))
|
||||||
(flags (:standard -w -9+27-30-32-40@8
|
(flags (:standard -w -9+27-30-32-40@8
|
||||||
-open Tezos_base
|
-open Tezos_base
|
||||||
-open Tezos_error_monad
|
-open Tezos_error_monad
|
||||||
-open Tezos_data_encoding
|
-open Tezos_data_encoding
|
||||||
-open Tezos_embedded_protocol_alpha
|
-open Tezos_client_alpha
|
||||||
-open Tezos_embedded_protocol_environment_alpha
|
|
||||||
-safe-string
|
-safe-string
|
||||||
-linkall))))
|
-linkall))))
|
||||||
|
|
||||||
|
@ -7,124 +7,13 @@
|
|||||||
(* *)
|
(* *)
|
||||||
(**************************************************************************)
|
(**************************************************************************)
|
||||||
|
|
||||||
(* Utility functions *)
|
|
||||||
|
|
||||||
exception Unsupported_construct
|
|
||||||
|
|
||||||
type input = {
|
|
||||||
int : int -> int -> string option -> string list -> int ;
|
|
||||||
float : string option -> string list -> float ;
|
|
||||||
string : string option -> string list -> string ;
|
|
||||||
bool : string option -> string list -> bool ;
|
|
||||||
continue : string option -> string list -> bool ;
|
|
||||||
display : string -> unit ;
|
|
||||||
}
|
|
||||||
|
|
||||||
open Json_schema
|
|
||||||
|
|
||||||
(* generic JSON generation from a schema with callback for random or
|
|
||||||
interactive filling *)
|
|
||||||
let fill_in ?(show_optionals=true) input schema : ([> `A of 'a list | `Null | `O of (string * 'a) list | `String of string ]
|
|
||||||
as 'a) =
|
|
||||||
let rec element path { title ; kind }=
|
|
||||||
match kind with
|
|
||||||
| Integer { minimum ; maximum } ->
|
|
||||||
let minimum =
|
|
||||||
match minimum with
|
|
||||||
| None -> min_int
|
|
||||||
| Some (m, `Inclusive) -> int_of_float m
|
|
||||||
| Some (m, `Exclusive) -> int_of_float m + 1 in
|
|
||||||
let maximum =
|
|
||||||
match maximum with
|
|
||||||
| None -> max_int
|
|
||||||
| Some (m, `Inclusive) -> int_of_float m
|
|
||||||
| Some (m, `Exclusive) -> int_of_float m - 1 in
|
|
||||||
let i = input.int minimum maximum title path in
|
|
||||||
`Float (float i)
|
|
||||||
| Number _ ->
|
|
||||||
let f = input.float title path in
|
|
||||||
`Float f
|
|
||||||
| Boolean ->
|
|
||||||
let f = input.bool title path in
|
|
||||||
`Bool f
|
|
||||||
| String _ ->
|
|
||||||
let f = input.string title path in
|
|
||||||
`String f
|
|
||||||
| Combine ((One_of | Any_of), elts) ->
|
|
||||||
let nb = List.length elts in
|
|
||||||
let n = input.int 0 (nb - 1) (Some "Select the schema to follow") path in
|
|
||||||
element path (List.nth elts n)
|
|
||||||
| Combine ((All_of | Not), _) -> raise Unsupported_construct
|
|
||||||
| Def_ref name ->
|
|
||||||
(`String (Json_query.json_pointer_of_path name))
|
|
||||||
| Id_ref _ | Ext_ref _ ->
|
|
||||||
raise Unsupported_construct
|
|
||||||
| Array (elts, _) ->
|
|
||||||
let rec fill_loop acc n ls =
|
|
||||||
match ls with
|
|
||||||
| [] -> acc
|
|
||||||
| elt :: elts ->
|
|
||||||
let json = element (string_of_int n :: path) elt in
|
|
||||||
fill_loop (json :: acc) (succ n) elts
|
|
||||||
in
|
|
||||||
let acc = fill_loop [] 0 elts in
|
|
||||||
(`A (List.rev acc))
|
|
||||||
| Object { properties } ->
|
|
||||||
let properties =
|
|
||||||
if show_optionals
|
|
||||||
then properties
|
|
||||||
else (List.filter (fun (_, _, b, _) -> b) properties) in
|
|
||||||
let rec fill_loop acc ls =
|
|
||||||
match ls with
|
|
||||||
| [] -> acc
|
|
||||||
| (n, elt, _, _) :: elts ->
|
|
||||||
let json = element (n :: path) elt in
|
|
||||||
fill_loop ((n, json) :: acc) elts
|
|
||||||
in
|
|
||||||
let acc = fill_loop [] properties in
|
|
||||||
(`O (List.rev acc))
|
|
||||||
| Monomorphic_array (elt, specs) ->
|
|
||||||
let rec fill_loop acc min n max =
|
|
||||||
if n > max then
|
|
||||||
acc
|
|
||||||
else
|
|
||||||
let json = element (string_of_int n :: path) elt in
|
|
||||||
if n < min || input.continue title path then
|
|
||||||
fill_loop (json :: acc) min (succ n) max
|
|
||||||
else (json :: acc)
|
|
||||||
in
|
|
||||||
let max = match specs.max_items with None -> max_int | Some m -> m in
|
|
||||||
let acc = fill_loop [] specs.min_items 0 max in
|
|
||||||
`A (List.rev acc)
|
|
||||||
| Any -> raise Unsupported_construct
|
|
||||||
| Dummy -> raise Unsupported_construct
|
|
||||||
| Null -> `Null
|
|
||||||
in
|
|
||||||
element [] (Json_schema.root schema)
|
|
||||||
|
|
||||||
let random_fill_in ?(show_optionals=true) schema =
|
|
||||||
let display _ = () in
|
|
||||||
let int min max _ _ =
|
|
||||||
let max = Int64.of_int max
|
|
||||||
and min = Int64.of_int min in
|
|
||||||
let range = Int64.sub max min in
|
|
||||||
let random_int64 = Int64.add (Random.int64 range) min in
|
|
||||||
Int64.to_int random_int64 in
|
|
||||||
let string _title _ = "" in
|
|
||||||
let float _ _ = Random.float infinity in
|
|
||||||
let bool _ _ = (Random.int 2 = 0) in
|
|
||||||
let continue _ _ = (Random.int 4 = 0) in
|
|
||||||
fill_in ~show_optionals
|
|
||||||
{ int ; float ; string ; bool ; display ; continue }
|
|
||||||
schema
|
|
||||||
|
|
||||||
type service_repr =
|
type service_repr =
|
||||||
{ path : string list ;
|
{ path : string list ;
|
||||||
meth : Resto.meth ;
|
meth : Resto.meth ;
|
||||||
description : string ;
|
description : string ;
|
||||||
input : Json_schema.schema option;
|
input : Json_schema.schema option ;
|
||||||
output : Json_schema.schema ;
|
output : Json_schema.schema option ;
|
||||||
example : string option;
|
example : string option ;
|
||||||
error : Json_schema.schema option
|
error : Json_schema.schema option
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -137,51 +26,28 @@ let make_descr = function
|
|||||||
| None | Some "" -> "No description"
|
| None | Some "" -> "No description"
|
||||||
| Some s -> s
|
| Some s -> s
|
||||||
|
|
||||||
|
(** Inspect a JSON schema: if it doesn't contain any field (e.g. { }),
|
||||||
|
return None *)
|
||||||
|
let normalize_json_schema = function
|
||||||
|
| None -> None
|
||||||
|
| Some schema ->
|
||||||
|
let open Json_schema in
|
||||||
|
let elt = root schema in
|
||||||
|
match elt.kind with
|
||||||
|
| Object specs when
|
||||||
|
specs = object_specs ||
|
||||||
|
specs = { object_specs with additional_properties = None } ->
|
||||||
|
None
|
||||||
|
| _ -> Some schema
|
||||||
|
|
||||||
let repr_of_service path
|
let repr_of_service path
|
||||||
RPC_description.{ description ; error ;
|
RPC_description.{ description ; error ;
|
||||||
meth ; input ; output ; _ } : service_repr=
|
meth ; input ; output ; _ } : service_repr =
|
||||||
(* let escape_html_string str =
|
|
||||||
* let open Stringext in
|
|
||||||
* let str = replace_all str ~pattern:"<" ~with_:"<" in
|
|
||||||
* replace_all str ~pattern:">" ~with_:">"
|
|
||||||
* in
|
|
||||||
*
|
|
||||||
* let example = begin
|
|
||||||
* try
|
|
||||||
* match input with
|
|
||||||
* | None -> None
|
|
||||||
* | Some input -> begin
|
|
||||||
* let path = List.map escape_html_string path |> String.concat "/" in
|
|
||||||
* Printf.eprintf "%s\n%!" path;
|
|
||||||
* let json = random_fill_in ~show_optionals:true input in
|
|
||||||
* let tezos_client_cmd_example =
|
|
||||||
* Format.sprintf "tezos-client rpc call /%s with '%s'"
|
|
||||||
* path
|
|
||||||
* (Data_encoding.Json.to_string ~minify:true json)
|
|
||||||
* in
|
|
||||||
* let curl_cmd_example =
|
|
||||||
* Format.sprintf "curl -X %s -H \"Content-type: application/json\" http://%s/%s -d '%s'"
|
|
||||||
* (RPC_service.string_of_meth meth)
|
|
||||||
* "127.0.0.1:18731"
|
|
||||||
* path
|
|
||||||
* (Data_encoding.Json.to_string ~minify:true json)
|
|
||||||
* in
|
|
||||||
* let open Format in
|
|
||||||
* Some (
|
|
||||||
* List.fold_left (fun acc s ->
|
|
||||||
* (Format.sprintf "<div class=\"cmdline\">%s</div>" s) :: acc)
|
|
||||||
* [] [ curl_cmd_example ; tezos_client_cmd_example ]
|
|
||||||
* |> String.concat "or"
|
|
||||||
* )
|
|
||||||
*
|
|
||||||
* end
|
|
||||||
* with | Unsupported_construct -> None
|
|
||||||
* end in *)
|
|
||||||
|
|
||||||
{ path ; meth ;
|
{ path ; meth ;
|
||||||
description = make_descr description ;
|
description = make_descr description ;
|
||||||
input ; output ;
|
input = normalize_json_schema input ;
|
||||||
example=None ; error = Some error }
|
output = normalize_json_schema (Some output) ;
|
||||||
|
example = None ; error = Some error }
|
||||||
|
|
||||||
open Format
|
open Format
|
||||||
|
|
||||||
@ -216,34 +82,15 @@ let rec pp_print_service_tree fmt = function
|
|||||||
) l;
|
) l;
|
||||||
fprintf fmt "@]"
|
fprintf fmt "@]"
|
||||||
|
|
||||||
let collected_args = ref []
|
|
||||||
|
|
||||||
let pp_print_collected_args ppf () =
|
|
||||||
let open Resto.Arg in
|
|
||||||
fprintf ppf "@[<v 0>";
|
|
||||||
List.iter
|
|
||||||
(function
|
|
||||||
| { name ; descr=Some d } ->
|
|
||||||
fprintf ppf "@[<v 2>**<%s>** : @[%s@]@]@ @ " name d;
|
|
||||||
| { descr=None ; _ } -> assert false
|
|
||||||
)
|
|
||||||
(List.rev !collected_args);
|
|
||||||
fprintf ppf "@]"
|
|
||||||
|
|
||||||
let make_tree cctxt path =
|
let make_tree cctxt path =
|
||||||
let collect arg =
|
(* TODO : add automatic example generation *)
|
||||||
if not (arg.RPC_arg.descr = None ||
|
|
||||||
(List.exists (fun { Resto.Arg.name } -> name = arg.name)
|
|
||||||
!collected_args)) then
|
|
||||||
collected_args := arg :: !collected_args
|
|
||||||
in
|
|
||||||
let open RPC_description in
|
let open RPC_description in
|
||||||
describe cctxt ~recurse:true path >>=? fun dir ->
|
describe cctxt ~recurse:true path >>=? fun dir ->
|
||||||
let rec loop path : _ directory -> service_tree list = function
|
let rec loop path : _ directory -> service_tree list = function
|
||||||
| Dynamic descr ->
|
| Dynamic descr ->
|
||||||
[ Node ({ path ; meth=`POST ;
|
[ Node ({ path ; meth=`POST ;
|
||||||
description=make_descr descr ;
|
description=make_descr descr ;
|
||||||
input = None ; output = Json_schema.any ;
|
input = None ; output = None ;
|
||||||
example = None ; error = None }, []) ]
|
example = None ; error = None }, []) ]
|
||||||
|
|
||||||
| Empty -> []
|
| Empty -> []
|
||||||
@ -274,7 +121,6 @@ let make_tree cctxt path =
|
|||||||
end
|
end
|
||||||
|
|
||||||
| Static { services ; subdirs = Some (Arg (arg, solo)) } ->
|
| Static { services ; subdirs = Some (Arg (arg, solo)) } ->
|
||||||
collect arg;
|
|
||||||
let name = Printf.sprintf "<%s>" arg.RPC_arg.name in
|
let name = Printf.sprintf "<%s>" arg.RPC_arg.name in
|
||||||
|
|
||||||
let services = RPC_service.MethMap.bindings services in
|
let services = RPC_service.MethMap.bindings services in
|
||||||
@ -372,7 +218,7 @@ let rec pp_print_rst_hierarchy fmt ~title node =
|
|||||||
let rec loop str =
|
let rec loop str =
|
||||||
let open Stringext in
|
let open Stringext in
|
||||||
if find_from str ~pattern:"--" <> None then
|
if find_from str ~pattern:"--" <> None then
|
||||||
loop (Stringext.replace_all_assoc str [("--","-")])
|
loop (replace_all_assoc str [("--","-")])
|
||||||
else
|
else
|
||||||
str
|
str
|
||||||
in loop rst_name
|
in loop rst_name
|
||||||
@ -446,29 +292,20 @@ let pp_print_html_tab_content fmt ~tag ~shortlabel ~pp_content ~content path =
|
|||||||
fprintf fmt "<%s>@ %a</%s>@ " tag pp_content content tag;
|
fprintf fmt "<%s>@ %a</%s>@ " tag pp_content content tag;
|
||||||
fprintf fmt "</div>@]"
|
fprintf fmt "</div>@]"
|
||||||
|
|
||||||
let pp_print_html_tab_content_example fmt ~shortlabel ~pp_content ~content path =
|
let pp_print_html_tabs fmt { path ; description ; input ; output ; _ (* example ; error *) } =
|
||||||
let target_ref = ref_of_path path in
|
|
||||||
fprintf fmt "@[<v 2><div id=\"%s\" class=\"%s tabcontent\" style=\"max-height:200px; overflow:auto\" >@ %a</div>@]"
|
|
||||||
(target_ref ^ shortlabel) target_ref pp_content content
|
|
||||||
|
|
||||||
let pp_print_html_tabs fmt { path ; description ; input ; output ; example ; error } =
|
|
||||||
fprintf fmt "@[<v 2>.. raw:: html@ @ ";
|
fprintf fmt "@[<v 2>.. raw:: html@ @ ";
|
||||||
fprintf fmt "@[<v 2><div class=\"tab\">@ ";
|
fprintf fmt "@[<v 2><div class=\"tab\">@ ";
|
||||||
|
|
||||||
fprintf fmt "%a" (pp_print_html_tab_button ~default:true ~shortlabel:"descr" ~content:"Description") path;
|
fprintf fmt "%a" (pp_print_html_tab_button ~default:true ~shortlabel:"descr" ~content:"Description") path;
|
||||||
(match input with
|
(match input with
|
||||||
| Some _ ->
|
| Some _ ->
|
||||||
fprintf fmt "%a" (pp_print_html_tab_button ~default:false ~shortlabel:"input" ~content:"Input") path;
|
fprintf fmt "%a" (pp_print_html_tab_button ~default:false ~shortlabel:"input" ~content:"Input schema") path;
|
||||||
| None -> ());
|
|
||||||
fprintf fmt "%a" (pp_print_html_tab_button ~default:false ~shortlabel:"output" ~content:"Output") path;
|
|
||||||
(match example with
|
|
||||||
| Some _ ->
|
|
||||||
fprintf fmt "%a" (pp_print_html_tab_button ~default:false ~shortlabel:"example" ~content:"Example") path;
|
|
||||||
| None -> ());
|
|
||||||
(match error with
|
|
||||||
| Some _ ->
|
|
||||||
fprintf fmt "%a" (pp_print_html_tab_button ~default:false ~shortlabel:"error" ~content:"Errors") path;
|
|
||||||
| None -> ());
|
| None -> ());
|
||||||
|
fprintf fmt "%a" (pp_print_html_tab_button ~default:false ~shortlabel:"output" ~content:"Output schema") path;
|
||||||
|
(* (match example with
|
||||||
|
* | Some _ ->
|
||||||
|
* fprintf fmt "%a" (pp_print_html_tab_button ~default:false ~shortlabel:"example" ~content:"Example") path;
|
||||||
|
* | None -> ()); *)
|
||||||
fprintf fmt "</div>@]@ ";
|
fprintf fmt "</div>@]@ ";
|
||||||
|
|
||||||
fprintf fmt "%a@ " (pp_print_html_tab_content ~tag:"p" ~shortlabel:"descr"
|
fprintf fmt "%a@ " (pp_print_html_tab_content ~tag:"p" ~shortlabel:"descr"
|
||||||
@ -477,16 +314,15 @@ let pp_print_html_tabs fmt { path ; description ; input ; output ; example ; err
|
|||||||
| Some x -> fprintf fmt "%a@ " (pp_print_html_tab_content ~tag:"pre" ~shortlabel:"input"
|
| Some x -> fprintf fmt "%a@ " (pp_print_html_tab_content ~tag:"pre" ~shortlabel:"input"
|
||||||
~pp_content:Json_schema.pp ~content:x) path;
|
~pp_content:Json_schema.pp ~content:x) path;
|
||||||
| None -> ());
|
| None -> ());
|
||||||
fprintf fmt "%a@ " (pp_print_html_tab_content ~tag:"pre" ~shortlabel:"output"
|
(match output with
|
||||||
~pp_content:Json_schema.pp ~content:output) path;
|
| Some x -> fprintf fmt "%a@ " (pp_print_html_tab_content ~tag:"pre" ~shortlabel:"output"
|
||||||
(match example with
|
|
||||||
| Some x -> fprintf fmt "%a@ " (pp_print_html_tab_content_example ~shortlabel:"example"
|
|
||||||
~pp_content:pp_print_string ~content:x) path;
|
|
||||||
| None -> ());
|
|
||||||
(match error with
|
|
||||||
| Some x -> fprintf fmt "%a@ " (pp_print_html_tab_content ~tag:"pre" ~shortlabel:"error"
|
|
||||||
~pp_content:Json_schema.pp ~content:x) path;
|
~pp_content:Json_schema.pp ~content:x) path;
|
||||||
| None -> ());
|
| None -> ());
|
||||||
|
(* (match example with
|
||||||
|
* | Some x -> fprintf fmt "%a@ " (pp_print_html_tab_content ~tag:"pre" ~shortlabel:"example"
|
||||||
|
* ~pp_content:pp_print_string ~content:x) path;
|
||||||
|
* | None -> ()); *)
|
||||||
|
|
||||||
fprintf fmt "@]"
|
fprintf fmt "@]"
|
||||||
|
|
||||||
let pp_print_rst_full_service fmt ({ path ; meth } as repr) =
|
let pp_print_rst_full_service fmt ({ path ; meth } as repr) =
|
||||||
@ -536,11 +372,7 @@ let style =
|
|||||||
}\
|
}\
|
||||||
pre {\
|
pre {\
|
||||||
font-size: 12px\
|
font-size: 12px\
|
||||||
}\
|
}</style>"
|
||||||
.cmdline { font-family: monospace; background: #343131; padding: 2px 8px;\
|
|
||||||
border-radius:10px; color: white; margin: 5px; }\
|
|
||||||
.cmdline+.cmddoc { margin: -5px 5px 0 20px; padding: 5px }\
|
|
||||||
</style>"
|
|
||||||
|
|
||||||
let script =
|
let script =
|
||||||
"<script>\
|
"<script>\
|
||||||
@ -585,25 +417,25 @@ let run ?(rpc_port=18731) () =
|
|||||||
(* Script : hack *)
|
(* Script : hack *)
|
||||||
fprintf ppf "%a@." pp_print_rst_raw_html script;
|
fprintf ppf "%a@." pp_print_rst_raw_html script;
|
||||||
(* Page title *)
|
(* Page title *)
|
||||||
fprintf ppf "%a" pp_print_rst_h1 "Tezos RPCs";
|
fprintf ppf "%a" pp_print_rst_h1 "RPC API";
|
||||||
(* include/copy usage.rst from input *)
|
(* include/copy usage.rst from input *)
|
||||||
Lwt_io.(read stdin) >>= fun s ->
|
let rec loop () =
|
||||||
fprintf ppf "%s@\n" s;
|
let s = read_line () in
|
||||||
Lwt.return ()
|
fprintf ppf "%s@\n" s;
|
||||||
|
loop ()
|
||||||
|
in begin try loop () with End_of_file -> () end
|
||||||
in
|
in
|
||||||
|
|
||||||
(make_tree cctxt [] >>= function
|
(make_tree cctxt [] >>= function
|
||||||
| Ok service_tree ->
|
| Ok service_tree ->
|
||||||
(* Print header!! *)
|
(* Print header!! *)
|
||||||
fprintf ppf "@\n";
|
fprintf ppf "@\n";
|
||||||
print_header () >>= fun () ->
|
print_header ();
|
||||||
fprintf ppf "@\n";
|
fprintf ppf "@\n";
|
||||||
|
|
||||||
(* Shell RPCs tree *)
|
(* Shell RPCs tree *)
|
||||||
fprintf ppf "%a@." (pp_print_rst_hierarchy ~title:"Client RPCs - Index") service_tree;
|
fprintf ppf "%a@." (pp_print_rst_hierarchy ~title:"Client RPCs - Index") service_tree;
|
||||||
fprintf ppf "%a" pp_print_rst_h2 "Client RPCs - Full description";
|
fprintf ppf "%a" pp_print_rst_h2 "Client RPCs - Full description";
|
||||||
fprintf ppf "%a@." pp_print_rst_service_tree service_tree;
|
fprintf ppf "%a@." pp_print_rst_service_tree service_tree;
|
||||||
|
|
||||||
Lwt.return 0
|
Lwt.return 0
|
||||||
|
|
||||||
| Error _ ->
|
| Error _ ->
|
||||||
@ -620,13 +452,6 @@ let run ?(rpc_port=18731) () =
|
|||||||
fprintf ppf "%a" pp_print_rst_h2 "Protocol Alpha RPCs - Full description";
|
fprintf ppf "%a" pp_print_rst_h2 "Protocol Alpha RPCs - Full description";
|
||||||
fprintf ppf "%a@." pp_print_rst_service_tree service_tree;
|
fprintf ppf "%a@." pp_print_rst_service_tree service_tree;
|
||||||
|
|
||||||
if !collected_args <> [] then begin
|
|
||||||
(* If you modify this title, also modify the
|
|
||||||
hard-referenced link in 'usage.rst' *)
|
|
||||||
fprintf ppf "%a" pp_print_rst_h2 "Dynamic parameters description";
|
|
||||||
fprintf ppf "%a@." pp_print_collected_args ();
|
|
||||||
end;
|
|
||||||
|
|
||||||
Lwt.return 0
|
Lwt.return 0
|
||||||
|
|
||||||
| Error _ ->
|
| Error _ ->
|
||||||
|
@ -15,9 +15,3 @@ input, would display on the standard output : ``{ "balance":
|
|||||||
"4000000000000" }``. When calling a RPC that requires an input
|
"4000000000000" }``. When calling a RPC that requires an input
|
||||||
through command-line, you will be prompted to provide the JSON input
|
through command-line, you will be prompted to provide the JSON input
|
||||||
in your default configured text editor.
|
in your default configured text editor.
|
||||||
|
|
||||||
In the following sections, you may find the complete list of RPCs
|
|
||||||
available for the client and for the protocol Alpha. You may also
|
|
||||||
find, for each RPC, its input, output and errors in JSON schema
|
|
||||||
format. Dynamic parameters, such as ``<block-id>``, are described in
|
|
||||||
`Dynamic parameters description`_
|
|
||||||
|
@ -83,8 +83,8 @@ license when the main network lunches.
|
|||||||
README
|
README
|
||||||
api/api-inline
|
api/api-inline
|
||||||
api/cli-commands
|
api/cli-commands
|
||||||
api/errors
|
|
||||||
api/rpc
|
api/rpc
|
||||||
|
api/errors
|
||||||
|
|
||||||
Indices and tables
|
Indices and tables
|
||||||
==================
|
==================
|
||||||
|
Loading…
Reference in New Issue
Block a user