123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350moduletypeS=sig(** Tasks to be performed within {{!module:Command} Commands} *)type_randomtypetimetypetime_zonetypefiletype_nav_keytypevaluetype_decodertypehttp_errortypehttp_bodytype_http_expect(** {1 Error types} *)typeempty=|typenot_found=[`Not_found]typeread_failed=[`Read_failed](** {1 Basic type and functions} *)type('a,+'e)t(** Task succeeding with a value of type ['a] or failing with
an error object of type ['e] *)valsucceed:'a->('a,'e)t(** [succeed a] Task which immediately succeeds with value [a]. *)valreturn:'a->('a,'e)t(** Same as {!succeed}. *)valfail:'e->('a,'e)t(** [fail e] Task which immediately fails with the error [e]. *)valresult:('a,'e)result->('a,'e)t(** [result res] Task which immediately succeeds or fails depending on [res]
The effect of the function is described by the code
{[
match res with
| Ok a -> succeed a
| Error e -> fail e
]}
*)val(>>=):('a,'e)t->('a->('b,'e)t)->('b,'e)t(** [task >>= f]
First execute [task]. If it fails then the function fails. If [task]
succeeds with the result [a] then execute the task [f a].
*)val(let*):('a,'e)t->('a->('b,'e)t)->('b,'e)t(** More convenient syntax for the monadic bind operator {!(>>=)}.
The code
{[
let* a = task in
f a
]}
is equivalent to
{[
task >>= f
]}
With the [let*] operator it is more convenient to chain tasks.
{[
let* a = t1 in
let* b = t2 a in
let* c = t3 a b in
...
return f a b c ...
]}
*)valmap:('a->'b)->('a,'e)t->('b,'e)t(** [map f task] Map the success result of [task] via the function [f]. *)valmake_succeed:(('a,'e)result->'b)->('a,'e)t->('b,empty)t(** [make_succeed f task]
Convert the task which might fail into a task which always succeeds by
converting the positive or negative result via the function [f] into a
new result.
*)valparallel:'accu->('a->'accu->'accu)->('a,empty)tlist->('accu,empty)t(** [parallel accu_start accumulate task_list]
Run all the tasks in the task list in parallel. Collect the results of
the individual tasks via the function [accumulate] into the accumulator.
If all tasks of the list have finished, return the accumulator.
Note that the tasks of the list do not return errors. If they can have
errors then {!make_succeed} can be used to encode the error into the
result type ['a].
*)(** {1 Write to the console} *)vallog_string:string->(unit,'e)t(** [log_string str] Write [str] to the console. *)vallog_value:value->(unit,'e)t(** [log_value v] Write the javascript object [v] to the console. *)(** {1 Messages to the javascript world} *)valsend_to_javascript:value->(unit,'e)t(** [send_to_javascript value] Send the javascript object [value] to the
surrounding javascript world. *)(** {1 Focus and blur elements} *)valfocus:string->(unit,not_found)t(** [focus id] Put the dom element with [id] into focus. *)valblur:string->(unit,not_found)t(** [blur id] Unfocus the dom element with [id]. *)(** {1 Defer tasks a certain time} *)valsleep:int->'a->('a,'e)t(** [sleep millis a] Sleep for [millis] milliseconds and then return [a].
Examples:
{[
let* _ = sleep 1000 () in (* sleep 1000 milliseconds *)
task (* and then execute [task] *)
let* a = task1 >>= sleep 1000 (* excute [task1] and return result
[a] after 1000 milliseconds *)
in
task2 a (* then execute [task2 a] *)
]}
*)valnext_tick:'a->('a,'e)t(** [next_tick a] Return [a] in the next tick of the event loop.
Example: Execute [task] in the next round of the event loop.
{[
let* _ = next_tick () in
task
]}
*)(** {1 Time and time zone} *)valnow:(time,'e)t(** Get the current time. *)valtime_zone:(time_zone,'e)t(** Get the current time zone. *)(** {1 Random values} *)valrandom:'arandom->('a,'e)t(** [random ran] Execute the random generator [rand] and return the
generated random value. *)(** {1 Navigation} *)valload:string->(unit,empty)t(** [load url]
Load the given [url].
*)valreload:(unit,empty)t(** Reload the current page. *)(** {1 File operations} *)valselect_file:stringlist->(file,empty)t(** [select_file media_types]
Show the browser's file selection dialog and return a file when the user
selected one. The given list of [media_types] allows restricting what
file types are visible in the dialog (users can still select different
file types if they want to).
NOTE: This task only works if it is triggered in reaction to a user
event, such as a mouse click. This restriction is imposed by browsers
for security reasons (websites should not be able to ask for file access
without user interaction).
*)valselect_files:stringlist->(filelist,empty)t(** [select_files media_types]
The same as {!select_file} but allows selecting multiple files at once.
NOTE: This task only works if it is triggered in reaction to a user
event, such as a mouse click. This restriction is imposed by browsers
for security reasons (websites should not be able to ask for file access
without user interaction).
*)valfile_text:file->(string,read_failed)t(** [file_text file f]
Read the contents of [file] into a string. Reading can fail, e.g. in
case of missing filesystem permissions.
*)(** {1 Http requests} *)valhttp_request:string->string->(string*string)list->http_body->'ahttp_expect->('a,http_error)t(** [http_request method url headers body expect]
Make an http [method] request to [url] with [headers] and [body].
[expect] specifies the expected response format.
This is the most general http request function. See also the more
specific functions [http_text] and [http_json].
Example:
{[
let user = Value.(record [| ("username", string "Bob") |]) in
http_request "PUT" "/users" [] (Body.json user) (Expect.string)
|> Command.attempt (fun result ->
match result with
| Ok _ ->
GotUserCreated
| Error _ ->
GotError "failed to create user")
]}
*)valhttp_text:string->string->(string*string)list->string->(string,http_error)t(** [http_text method url headers body]
Make an http [method] request to [url] with [headers] and a string
as the [body]. Expect a string as the response.
Method is one of [GET, POST, DELETE, ... ].
The headers and the body can be empty. The [Content-Type] header
is automatically set to [text/plain].
Example:
{[
http_text "PUT" "/users" [] "Bob"
|> Command.attempt (fun result ->
match result with
| Ok _ ->
GotUserCreated
| Error _ ->
GotError "failed to create user")
]}
*)valhttp_json:string->string->(string*string)list->valueoption->'adecoder->('a,http_error)t(** [http_json method url headers body decoder]
Make an http [method] request to [url] with [headers] and an
optional json value as the [body]. Expect a json value as the
response which will be decoded by [decoder].
The [headers] can be empty. The [Content-Type] header is
automatically set to [application/json] if [body] is not [None].
Example:
{[
let decoder = Decoder.array Decoder.string in
http_json "GET" "/users" [] None decoder
|> Command.attempt (fun result ->
match result with
| Ok usernames -> (* the usernames were successfully decoded
into a string array *)
GotUsers (Array.to_list usernames)
| Error _ ->
GotError "failed to obtain users")
]}
*)end