forked from andrewMacmurray/elm-concurrent-task
-
Notifications
You must be signed in to change notification settings - Fork 0
/
docs.json
1 lines (1 loc) · 39 KB
/
docs.json
1
[{"name":"ConcurrentTask","comment":" A Task similar to `elm/core`'s `Task` but:\n\n - Allows concurrent execution of `map2`, `map3`, ...\n - Can safely call external JavaScript and chain the results (also known as Task Ports).\n\n\n## Built-in Tasks\n\nBecause `elm-concurrent-task` uses a different type to `elm/core` `Task` it's unfortunately not compatible with `elm/core` `Task`s.\n\nHowever, there are a number of tasks built into the JavaScript runner and supporting modules that should cover a large amount of the existing functionality of `elm/core` `Task`s.\n\nCheck out the built-ins for more details:\n\n - [`Browser.Dom`](ConcurrentTask-Browser-Dom)\n - [`Http`](ConcurrentTask-Http)\n - [`Process`](ConcurrentTask-Process)\n - [`Random`](ConcurrentTask-Random)\n - [`Time`](ConcurrentTask-Time)\n\n\n# Concurrent Tasks\n\n@docs ConcurrentTask, define\n\n\n# Expectations\n\n@docs Expect, expectJson, expectString, expectWhatever\n\n\n# Error Handling\n\n@docs Errors, expectThrows, expectErrors, expectNoErrors\n\n\n# Error Hooks\n\nLift `UnexpectedError`s into regular task flow.\n\n@docs onResponseDecoderFailure, onJsException\n\n\n# Transforming Errors\n\n@docs mapError, onError\n\n\n# Chaining Tasks\n\n@docs succeed, fail, andThen\n\n\n# Convenience Helpers\n\nThese are some general helpers that can make chaining and combining tasks more convenient.\n\n@docs fromResult, andThenDo, return\n\n\n# Batch Helpers\n\nWhen you need to combine many tasks together.\n\n\n## Stack Safety\n\nThese helpers are carefully written to be stack safe. Use them if you're handling large lists of tasks (> 2000).\n\n@docs batch, sequence\n\n\n# Maps\n\nTransform values returned from tasks.\n\n@docs map, andMap, map2, map3, map4, map5\n\n\n# Run a Task\n\nOnce you've constructed a Task it needs to be passed to the runner to perform all of the effects.\n\nHere's a minimal complete example:\n\n\n## A task to fetch 3 resources concurrently:\n\n type alias Titles =\n { todo : String\n , post : String\n , album : String\n }\n\n getAllTitles : ConcurrentTask Http.Error Titles\n getAllTitles =\n Task.map3 Titles\n (getTitle \"/todos/1\")\n (getTitle \"/posts/1\")\n (getTitle \"/albums/1\")\n\n getTitle : String -> ConcurrentTask Http.Error String\n getTitle path =\n Http.request\n { url = \"https://jsonplaceholder.typicode.com\" ++ path\n , method = \"GET\"\n , headers = []\n , body = Http.emptyBody\n , expect = Http.expectJson (Decode.field \"title\" Decode.string)\n }\n\n\n## A program to run the task:\n\n port module Example exposing (main)\n\n import ConcurrentTask exposing (ConcurrentTask)\n import ConcurrentTask.Http as Http\n import Json.Decode as Decode\n\n type alias Model =\n { tasks : ConcurrentTask.Pool Msg Http.Error Titles\n }\n\n type Msg\n = OnProgress ( ConcurrentTask.Pool Msg Http.Error Titles, Cmd Msg )\n | OnComplete (ConcurrentTask.Response Http.Error Titles)\n\n init : ( Model, Cmd Msg )\n init =\n let\n ( tasks, cmd ) =\n ConcurrentTask.attempt\n { send = send\n , pool = Task.pool\n , onComplete = OnComplete\n }\n getAllTitles\n in\n ( { tasks = tasks }, cmd )\n\n update : Msg -> Model -> ( Model, Cmd Msg )\n update msg model =\n case msg of\n OnComplete response ->\n let\n _ =\n Debug.log \"response\" response\n in\n ( model, Cmd.none )\n\n OnProgress ( tasks, cmd ) ->\n ( { model | tasks = tasks }, cmd )\n\n subscriptions : Model -> Sub Msg\n subscriptions model =\n ConcurrentTask.onProgress\n { send = send\n , receive = receive\n , onProgress = OnProgress\n }\n model.tasks\n\n port send : Decode.Value -> Cmd msg\n\n port receive : (Decode.Value -> msg) -> Sub msg\n\n main : Program {} Model Msg\n main =\n Platform.worker\n { init = always init\n , update = update\n , subscriptions = subscriptions\n }\n\n@docs attempt, Response, UnexpectedError, onProgress, Pool, pool\n\n","unions":[{"name":"Response","comment":" The value returned from a task when it completes (returned in the `OnComplete` msg).\n\nCan be either:\n\n - `Success a` - the task succeeded with no errors, woo!\n - `Error x` - the task failed with an expected error.\n - `UnexpectedError` - the task failed with an unexpected error (see the section on `Error Handling` for more details).\n\n","args":["x","a"],"cases":[["Success",["a"]],["Error",["x"]],["UnexpectedError",["ConcurrentTask.UnexpectedError"]]]},{"name":"UnexpectedError","comment":" This error will surface if something **unexpected** has happened during the task flow.\n\n\n## Catchable Errors\n\nThese errors will be surfaced **if not handled** during task flow:\n\n - `UnhandledJsException` - a task threw an exception and was not caught with an error handler (can be caught with [expectThrows](ConcurrentTask#expectThrows) and [onJsException](ConcurrentTask#onJsException)).\n - `ResponseDecoderFailure` - a task returned an unexpected response (can be caught with [onResponseDecoderFailure](ConcurrentTask#onResponseDecoderFailure)).\n\n\n## Uncatchable Errors\n\nThese errors will **always surface**, as they are assumed to have no meaningful way to recover from during regular task flow:\n\n - `ErrorsDecoderFailure` - a task returned error data in an unexpected format when using an [expectErrors](ConcurrentTask#expectErrors) handler.\n - `MissingFunction` - a task tried to call a function in the JS runner which was not registered.\n - `InternalError` - something went wrong with the runner internals - this should not happen, but if you see this error [please leave details and an issue](https://github.com/andrewMacmurray/elm-concurrent-task/issues/new).\n\n","args":[],"cases":[["UnhandledJsException",["{ function : String.String, message : String.String, raw : Json.Decode.Value }"]],["ResponseDecoderFailure",["{ function : String.String, error : Json.Decode.Error }"]],["ErrorsDecoderFailure",["{ function : String.String, error : Json.Decode.Error }"]],["MissingFunction",["String.String"]],["InternalError",["String.String"]]]}],"aliases":[{"name":"ConcurrentTask","comment":" A `ConcurrentTask` represents an asynchronous unit of work with the possibility of failure.\n\nUnderneath, each task represents a call to a JavaScript function and the runner handles batching and sequencing the calls.\n\n","args":["x","a"],"type":"ConcurrentTask.Internal.ConcurrentTask.ConcurrentTask x a"},{"name":"Errors","comment":" The `Errors` type provides different ways to capture errors for a `ConcurrentTask`.\n\n\n## Understanding Errors\n\n`ConcurrentTask` has two main kinds of `Errors`:\n\n\n### [Error](ConcurrentTask#Response)\n\nThis is the `x` in the `ConcurrentTask x a` and represents an **expected error** as part of your task flow.\nYou can handle these with [mapError](ConcurrentTask#mapError) and [onError](ConcurrentTask#onError).\n\n\n### [UnexpectedError](ConcurrentTask#UnexpectedError)\n\nYou can think of these as **unhandled** errors that are not a normal part of your task flow.\n\nThe idea behind `UnexpectedError` is to keep your task flow types `ConcurrentTask x a` clean and meaningful,\nand optionally lift some of them into regular task flow where it makes sense.\nTwo hooks you can use for this are [onResponseDecoderFailure](ConcurrentTask#onResponseDecoderFailure) and [onJsException](ConcurrentTask#onJsException).\n\nSee the section on [UnexpectedError](ConcurrentTask#UnexpectedError)s for more details.\n\n","args":["x"],"type":"ConcurrentTask.Internal.ConcurrentTask.Errors x"},{"name":"Expect","comment":" Decode the response of a JS function into an Elm value.\n","args":["a"],"type":"ConcurrentTask.Internal.ConcurrentTask.Expect a"},{"name":"Pool","comment":" A Pool keeps track of each task's progress,\nand allows multiple Task attempts to be in-flight at the same time.\n","args":["msg","x","a"],"type":"ConcurrentTask.Internal.ConcurrentTask.Pool msg x a"}],"values":[{"name":"andMap","comment":" Combine an arbitrary number of tasks together concurrently.\n\nMaybe you want to load multiple pieces of config into a record:\n\n import ConcurrentTask exposing (ConcurrentTask)\n\n type alias Config =\n { dbConfig : DbConfig\n , yamlConfig : YamlConfig\n , envFile : EnvFile\n }\n\n loadConfig : ConcurrentTask Error Config\n loadConfig =\n ConcurrentTask.succeed Config\n |> ConcurrentTask.andMap loadDbConfig\n |> ConcurrentTask.andMap loadYamlConfig\n |> ConcurrentTask.andMap loadEnvFile\n\n","type":"ConcurrentTask.ConcurrentTask x a -> ConcurrentTask.ConcurrentTask x (a -> b) -> ConcurrentTask.ConcurrentTask x b"},{"name":"andThen","comment":" Chain the successful result of the previous Task into another one.\n\nMaybe you want to do a timestamped Http request\n\n import ConcurrentTask exposing (ConcurrentTask)\n import ConcurrentTask.Http as Http\n import ConcurrentTask.Time\n import Time\n\n task : ConcurrentTask Http.Error String\n task =\n ConcurrentTask.Time.now\n |> Task.andThen (createArticle \"my article\")\n\n createArticle : String -> Time.Posix -> ConcurrentTask Http.Error String\n createArticle title time =\n Http.request\n { url = \"http://blog.com/articles\"\n , method = \"POST\"\n , headers = []\n , expect = Http.expectString\n , body = Http.jsonBody (encodeArticle title time)\n }\n\n","type":"(a -> ConcurrentTask.ConcurrentTask x b) -> ConcurrentTask.ConcurrentTask x a -> ConcurrentTask.ConcurrentTask x b"},{"name":"andThenDo","comment":" Similar to `andThen` but ignores the successful result of the previous Task.\n\nMaybe you want to save a file then log a message to the console:\n\n import ConcurrentTask exposing (ConcurrentTask)\n\n task : ConcurrentTask Error ()\n task =\n saveFile |> ConcurrentTask.andThenDo (log \"file saved\")\n\n","type":"ConcurrentTask.ConcurrentTask x b -> ConcurrentTask.ConcurrentTask x a -> ConcurrentTask.ConcurrentTask x b"},{"name":"attempt","comment":" Start a `ConcurrentTask`. This needs:\n\n - A task `Pool` (The internal model to keep track of task progress).\n - The `send` port.\n - The `Msg` to be called when the task completes.\n - Your `ConcurrentTask` to be run.\n\nMake sure to update your `Model` and pass in the `Cmd` returned from `attempt`. e.g. in a branch of `update`:\n\n let\n ( tasks, cmd ) =\n ConcurrentTask.attempt\n { send = send\n , pool = model.pool\n , onComplete = OnComplete\n }\n myTask\n in\n ( { model | tasks = tasks }, cmd )\n\n","type":"{ pool : ConcurrentTask.Pool msg x a, send : Json.Decode.Value -> Platform.Cmd.Cmd msg, onComplete : ConcurrentTask.Response x a -> msg } -> ConcurrentTask.ConcurrentTask x a -> ( ConcurrentTask.Pool msg x a, Platform.Cmd.Cmd msg )"},{"name":"batch","comment":" Perform a List of tasks concurrently (similar to `Promise.all()` in JavaScript) and return the results in a List.\n\nIf any of the subtasks fail the whole ConcurrentTask will fail.\n\n","type":"List.List (ConcurrentTask.ConcurrentTask x a) -> ConcurrentTask.ConcurrentTask x (List.List a)"},{"name":"define","comment":" Define a `ConcurrentTask` from an external JavaScript function with:\n\n - The `name` of the registered function you want to call.\n - What you `expect` to come back from the function when it returns.\n - How to interpret `errors` coming from the function (exceptions or explicitly returned errors).\n - The encoded `args` to pass to the function.\n\nSay you wanted to interact with the node filesystem:\n\nDefine your task in `Elm`:\n\n import ConcurrentTask exposing (ConcurrentTask)\n import Json.Encode as Encode\n\n type Error\n = Error String\n\n readFile : String -> ConcurrentTask Error String\n readFile path =\n ConcurrentTask.define\n { function = \"fs:readFile\"\n , expect = ConcurrentTask.expectString\n , errors = ConcurrentTask.expectThrows Error\n , args = Encode.object [ ( \"path\", Encode.string path ) ]\n }\n\nAnd in your `JavaScript` runner:\n\n import * as fs from \"node:fs/promises\"\n import * as ConcurrentTask from \"@andrewmacmurray/elm-concurrent-task\";\n\n\n const app = Elm.Main.init({});\n\n ConcurrentTask.register({\n tasks: {\n \"fs:readFile\": (args) => fs.readFile(args.path),\n },\n ports: {\n send: app.ports.send,\n receive: app.ports.receive,\n },\n });\n\n\n## A note on Errors:\n\nThe example `fs:readFile` Task has very simple error handling (turn any thrown exceptions into the Error type).\nThis can be a great way to start, but what if you want more detailed errors?\n\nThe `Errors` section goes into more detail on different error handling strategies, including:\n\n - how to define and handle more meaningful error types.\n - bypassing all errors for Tasks which never fail (e.g. get the current time, log to the console).\n - handling unexpected return data (e.g. the function returns an `Int` when you were expecting a `String`).\n\n","type":"{ function : String.String, expect : ConcurrentTask.Expect a, errors : ConcurrentTask.Errors x, args : Json.Encode.Value } -> ConcurrentTask.ConcurrentTask x a"},{"name":"expectErrors","comment":" Decode explicit errors returned by a `ConcurrentTask`. Use this when you want more meaningful errors in your task.\n\nThis will decode the value from an `error` key returned by a JS function, e.g.:\n\n return {\n error: {\n code: \"MY_ERROR_CODE\",\n message: \"Something Went Wrong\",\n }\n }\n\n**IMPORTANT NOTES**:\n\n - If your function doesn't return an `\"error\"` key it will be interpreted as a success response.\n - If your JS function throws an exception it will surface an `UnhandledJsException` -\n make sure to either:\n - catch these in your JS function and return them as structured errors.\n - catch them with the [onJsException](ConcurrentTask#onJsException) hook.\n - If your error decoder fails the task will surface an `ExpectErrorFailure`.\n - This error is uncatchable, make sure to return data that matches your error decoder.\n\nMaybe you want to handle different kinds of errors when writing to `localStorage`:\n\n import ConcurrentTask exposing (ConcurrentTask)\n import Json.Decode as Decode\n import Json.Encode as Encode\n\n type WriteError\n = QuotaExceeded\n | WriteBlocked\n\n set : String -> String -> Task WriteError ()\n set key value =\n ConcurrentTask.define\n { function = \"storage:set\"\n , expect = ConcurrentTask.expectWhatever\n , errors = ConcurrentTask.expectErrors decodeWriteError\n , args =\n Encode.object\n [ ( \"key\", Encode.string key )\n , ( \"value\", Encode.string value )\n ]\n }\n\n decodeWriteError : Decode.Decoder WriteError\n decodeWriteError =\n Decode.string\n |> Decode.andThen\n (\\reason ->\n case reason of\n \"QUOTA_EXCEEDED\" ->\n Decode.succeed QuotaExceeded\n\n \"WRITE_BLOCKED\" ->\n Decode.succeed WriteBlocked\n\n _ ->\n Decode.fail (\"Unknown WriteError Reason: \" ++ reason)\n )\n\nAnd on the JS side:\n\n ConcurrentTask.register({\n tasks: {\n \"storage:set\": (args) => setItem(args),\n },\n ports: {\n send: app.ports.send,\n receive: app.ports.receive,\n },\n });\n\n\n function setItem(args) {\n try {\n localStorage.setItem(args.key, args.value);\n } catch (e) {\n if (e.name === \"QuotaExceededError\") {\n return {\n error: \"QUOTA_EXCEEDED\",\n };\n } else {\n return {\n error: \"WRITE_BLOCKED\",\n };\n }\n }\n }\n\n","type":"Json.Decode.Decoder x -> ConcurrentTask.Errors x"},{"name":"expectJson","comment":" Run a JSON decoder on the response of a Task\n","type":"Json.Decode.Decoder a -> ConcurrentTask.Expect a"},{"name":"expectNoErrors","comment":" Only use this handler for functions that you don't expect to fail.\n\n**NOTE**:\nIf the decoder fails or the function throws an exception, these will be surfaced as `UnexpectedError`s.\n\ne.g. logging to the console:\n\n import ConcurrentTask exposing (ConcurrentTask)\n\n log : String -> ConcurrentTask x ()\n log msg =\n ConcurrentTask.define\n { function = \"console:log\"\n , expect = ConcurrentTask.expectWhatever ()\n , errors = ConcurrentTask.expectNoErrors\n , args = Encode.string msg\n }\n\nOn the JS side:\n\n ConcurrentTask.register({\n tasks: {\n \"console:log\": (msg) => console.log(msg),\n },\n ports: {\n send: app.ports.send,\n receive: app.ports.receive,\n },\n });\n\n","type":"ConcurrentTask.Errors x"},{"name":"expectString","comment":" Expect the response of a Task to be a String\n","type":"ConcurrentTask.Expect String.String"},{"name":"expectThrows","comment":" The simplest Error handler. If a JS function throws an Exception, it will be wrapped in the provided `Error` type.\n\nMaybe your JS function throws an `AccessError`:\n\n import ConcurrentTask exposing (ConcurrentTask)\n\n type Error\n = MyError String\n\n example : ConcurrentTask Error String\n example =\n ConcurrentTask.define\n { function = \"functionThatThrows\"\n , expect = ConcurrentTask.expectString\n , errors = ConcurrentTask.expectThrows MyError\n , args = Encode.null\n }\n\nWhen the task is run it will complete with `Task.Error (MyError \"AccessError: access denied\")`.\nThis can be transformed and chained using `Task.mapError` and `Task.onError`.\n\n**NOTE:**\n\nThis kind of error handling can be useful to get started quickly,\nbut it's often much more expressive and useful if you catch and explicitly return error data in your JS function that can be decoded with the `expectError` handler.\n\n","type":"(String.String -> x) -> ConcurrentTask.Errors x"},{"name":"expectWhatever","comment":" Ignore the response of a Task\n","type":"ConcurrentTask.Expect ()"},{"name":"fail","comment":" A Task that fails immediately when it's run.\n","type":"x -> ConcurrentTask.ConcurrentTask x a"},{"name":"fromResult","comment":" Create a Task from a `Result error value`. The task will either immediately succeed or fail when run.\n\nMaybe you want to chain together tasks with CSV parsing:\n\n import ConcurrentTask exposing (ConcurrentTask)\n import Csv\n\n task : ConcurrentTask Error CsvData\n task =\n readFile |> ConcurrentTask.andThen parseCsv\n\n parseCsv : String -> ConcurrentTask Error CsvData\n parseCsv raw =\n Csv.decode decoder raw\n |> ConcurrentTask.fromResult\n |> ConcurrentTask.mapError CsvError\n\n","type":"Result.Result x a -> ConcurrentTask.ConcurrentTask x a"},{"name":"map","comment":" Transform the value from a task.\n\nMaybe you want to find what time it is in one hour.\n\n import ConcurrentTask as exposing (ConcurrentTask)\n import ConcurrentTask.Time\n import Time\n\n timeInOneHour : ConcurrentTask x Time.Posix\n timeInOneHour =\n ConcurrentTask.map addOneHour ConcurrentTask.Time.now\n\n addOneHour : Time.Posix -> Time.Posix\n addOneHour time =\n Time.millisToPosix (Time.posixToMillis time + 60 * 60 * 1000)\n\n","type":"(a -> b) -> ConcurrentTask.ConcurrentTask x a -> ConcurrentTask.ConcurrentTask x b"},{"name":"map2","comment":" Run two tasks concurrently and combine their results.\n\n import ConcurrentTask exposing (ConcurrentTask)\n import ConcurrentTask.Time\n import Time\n\n loadUserAndTime : ConcurrentTask Error ( User, Time.Posix )\n loadUserAndTime =\n ConcurrentTask.map2 Tuple.pair loadUser ConcurrentTask.Time.now\n\n","type":"(a -> b -> c) -> ConcurrentTask.ConcurrentTask x a -> ConcurrentTask.ConcurrentTask x b -> ConcurrentTask.ConcurrentTask x c"},{"name":"map3","comment":" Run three tasks concurrently and combine their results.\n","type":"(a -> b -> c -> d) -> ConcurrentTask.ConcurrentTask x a -> ConcurrentTask.ConcurrentTask x b -> ConcurrentTask.ConcurrentTask x c -> ConcurrentTask.ConcurrentTask x d"},{"name":"map4","comment":" Run four tasks concurrently and combine their results.\n","type":"(a -> b -> c -> d -> e) -> ConcurrentTask.ConcurrentTask x a -> ConcurrentTask.ConcurrentTask x b -> ConcurrentTask.ConcurrentTask x c -> ConcurrentTask.ConcurrentTask x d -> ConcurrentTask.ConcurrentTask x e"},{"name":"map5","comment":" Run five tasks concurrently and combine their results.\n","type":"(a -> b -> c -> d -> e -> f) -> ConcurrentTask.ConcurrentTask x a -> ConcurrentTask.ConcurrentTask x b -> ConcurrentTask.ConcurrentTask x c -> ConcurrentTask.ConcurrentTask x d -> ConcurrentTask.ConcurrentTask x e -> ConcurrentTask.ConcurrentTask x f"},{"name":"mapError","comment":" Transform the value of an Error (like `map` but for errors).\n","type":"(x -> y) -> ConcurrentTask.ConcurrentTask x a -> ConcurrentTask.ConcurrentTask y a"},{"name":"onError","comment":" If the previous Task fails, catch that error and return a new Task (like `andThen` but for errors).\n","type":"(x -> ConcurrentTask.ConcurrentTask y a) -> ConcurrentTask.ConcurrentTask x a -> ConcurrentTask.ConcurrentTask y a"},{"name":"onJsException","comment":" Use this to capture a raw JsException to lift it into the task flow.\n\n**NOTE**: Tasks defined with [expectThrows](ConcurrentTask#expectThrows) will never trigger this hook,\nmake sure to only use it with [expectErrors](ConcurrentTask#expectErrors) and [expectNoErrors](ConcurrentTask#expectNoErrors).\n\n","type":"({ message : String.String, raw : Json.Decode.Value } -> ConcurrentTask.ConcurrentTask x a) -> ConcurrentTask.ConcurrentTask x a -> ConcurrentTask.ConcurrentTask x a"},{"name":"onProgress","comment":" Subscribe to updates from the JavaScript task runner.\n\nThis needs:\n\n - The `send` port.\n - The `receive` port.\n - The `Msg` to be called with the updated progress.\n - The task `Pool` stored in your model.\n\nYou can wire this in like so:\n\n subscriptions : Model -> Sub Msg\n subscriptions model =\n ConcurrentTask.onProgress\n { send = send\n , receive = receive\n , onProgress = OnProgress\n }\n model.tasks\n\nMake sure to update your `Model` and pass in the `Cmd` in your `OnProgress` branch in `update`:\n\n OnProgress ( tasks, cmd ) ->\n ( { model | tasks = tasks }, cmd )\n\n","type":"{ send : Json.Decode.Value -> Platform.Cmd.Cmd msg, receive : (Json.Decode.Value -> msg) -> Platform.Sub.Sub msg, onProgress : ( ConcurrentTask.Pool msg x a, Platform.Cmd.Cmd msg ) -> msg } -> ConcurrentTask.Pool msg x a -> Platform.Sub.Sub msg"},{"name":"onResponseDecoderFailure","comment":" Use this alongside other error handlers to lift a `ResponseDecoderFailure`'s `Json.Decode` error into regular task flow.\n\nMaybe you want to represent an unexpected response as a `BadBody` error for a http request:\n\n import ConcurrentTask exposing (ConcurrentTask)\n\n type Error\n = Timeout\n | NetworkError\n | BadStatus Int\n | BadUrl String\n | BadBody Decode.Error\n\n request : Request a -> ConcurrentTask Error a\n request options =\n ConcurrentTask.define\n { function = \"http:request\"\n , expect = ConcurrentTask.expectJson options.expect\n , errors = ConcurrentTask.expectErrors decodeHttpErrors\n , args = encodeArgs options\n }\n |> ConcurrentTask.onResponseDecoderFailure (BadBody >> Task.fail)\n\n","type":"(Json.Decode.Error -> ConcurrentTask.ConcurrentTask x a) -> ConcurrentTask.ConcurrentTask x a -> ConcurrentTask.ConcurrentTask x a"},{"name":"pool","comment":" Create an empty ConcurrentTask Pool.\n\nRight now it doesn't expose any functionality, but it could be used in the future to do things like:\n\n - Buffer the number of in-flight tasks (e.g. a server request queue, or database connection pool).\n - Handle graceful process termination (e.g. abort or cleanup all in-flight tasks).\n - Expose metrics on previous or running tasks.\n\n","type":"ConcurrentTask.Pool msg x a"},{"name":"return","comment":" Succeed with a hardcoded value after the previous Task\n\nMaybe you want to do some Tasks on a User but allow it to be chained onwards:\n\n import ConcurrentTask exposing (ConcurrentTask)\n\n saveUser : User -> ConcurrentTask Error User\n saveUser user =\n saveToDatabase user\n |> ConcurrentTask.andThenDo (log \"user saved\")\n |> ConcurrentTask.return user\n\n","type":"b -> ConcurrentTask.ConcurrentTask x a -> ConcurrentTask.ConcurrentTask x b"},{"name":"sequence","comment":" Perform a List of tasks one after the other and return the results in a List.\n\nIf any of the subtasks fail the whole ConcurrentTask will fail.\n\n","type":"List.List (ConcurrentTask.ConcurrentTask x a) -> ConcurrentTask.ConcurrentTask x (List.List a)"},{"name":"succeed","comment":" A Task that succeeds immediately when it's run.\n","type":"a -> ConcurrentTask.ConcurrentTask x a"}],"binops":[]},{"name":"ConcurrentTask.Browser.Dom","comment":" Drop in replacements for [elm/browser's](https://package.elm-lang.org/packages/elm/browser/latest/Browser-Dom)'s `Browser.Dom` `Task`s.\n\nThe JavaScript runner has these tasks builtin by default. There shouldn't be much need to do this, but they can be overridden like so:\n\n**NOTE:** You can see the [built-in implementations here](https://github.com/andrewMacmurray/elm-concurrent-task/blob/main/runner/browser/dom.ts). They follow the [`Elm.Kernel`](https://github.com/elm/browser/blob/1.0.2/src/Elm/Kernel/Browser.js) implementations as closely as possible.\n\n import * as ConcurrentTask from \"@andrewmacmurray/elm-concurrent-task\"\n\n ConcurrentTask.register({\n tasks: {},\n ports: app.ports,\n builtins: {\n domFocus: customFocus,\n domBlur: customBlur,\n domGetViewport: customGetViewport,\n domGetViewportOf: customGetViewportOf,\n domSetViewport: customSetViewport,\n domSetViewportOf: customSetViewportOf,\n domGetElement: customGetElement,\n }\n });\n\n\n# Focus Tasks\n\n@docs focus, blur\n\n\n# Get Viewport Tasks\n\n@docs getViewport, getViewportOf\n\n\n# Set Viewport Tasks\n\n@docs setViewport, setViewportOf\n\n\n# Position Tasks\n\n@docs getElement\n\n","unions":[],"aliases":[],"values":[{"name":"blur","comment":" A direct replacement for `elm/browser`'s [`Browser.Dom.blur`](https://package.elm-lang.org/packages/elm/browser/latest/Browser-Dom#blur).\n","type":"String.String -> ConcurrentTask.ConcurrentTask Browser.Dom.Error ()"},{"name":"focus","comment":" A direct replacement for `elm/browser`'s [`Browser.Dom.focus`](https://package.elm-lang.org/packages/elm/browser/latest/Browser-Dom#focus).\n","type":"String.String -> ConcurrentTask.ConcurrentTask Browser.Dom.Error ()"},{"name":"getElement","comment":" A direct replacement for `elm/browser`'s [`Browser.Dom.getElement`](https://package.elm-lang.org/packages/elm/browser/latest/Browser-Dom#getElement).\n","type":"String.String -> ConcurrentTask.ConcurrentTask Browser.Dom.Error Browser.Dom.Element"},{"name":"getViewport","comment":" A direct replacement for `elm/browser`'s [`Browser.Dom.getViewport`](https://package.elm-lang.org/packages/elm/browser/latest/Browser-Dom#getViewport).\n","type":"ConcurrentTask.ConcurrentTask x Browser.Dom.Viewport"},{"name":"getViewportOf","comment":" A direct replacement for `elm/browser`'s [`Browser.Dom.getViewportOf`](https://package.elm-lang.org/packages/elm/browser/latest/Browser-Dom#getViewportOf).\n","type":"String.String -> ConcurrentTask.ConcurrentTask Browser.Dom.Error Browser.Dom.Viewport"},{"name":"setViewport","comment":" A direct replacement for `elm/browser`'s [`Browser.Dom.setViewport`](https://package.elm-lang.org/packages/elm/browser/latest/Browser-Dom#setViewport).\n","type":"Basics.Float -> Basics.Float -> ConcurrentTask.ConcurrentTask x ()"},{"name":"setViewportOf","comment":" A direct replacement for `elm/browser`'s [`Browser.Dom.setViewportOf`](https://package.elm-lang.org/packages/elm/browser/latest/Browser-Dom#setViewportOf).\n","type":"String.String -> Basics.Float -> Basics.Float -> ConcurrentTask.ConcurrentTask Browser.Dom.Error ()"}],"binops":[]},{"name":"ConcurrentTask.Http","comment":" Make concurrent http requests.\n\nThe JavaScript runner has this task builtin by default.\nInternally It uses the [fetch api](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch) which is widely supported in the Browser and (as of Node 18) in NodeJS.\n\nIf needed you can supply a custom implementation like so:\n\n import * as ConcurrentTask from \"@andrewmacmurray/elm-concurrent-task\"\n import { HttpRequest, HttpResponse } from \"@andrewmacmurray/elm-concurrent-task\"\n\n ConcurrentTask.register({\n tasks: {},\n ports: app.ports,\n builtins: {\n http: customRequest\n },\n });\n\n function customRequest(req: HttpRequest): Promise<HttpResponse> {\n return ...<Your Custom Http Request>\n }\n\nSee the [typescript definitions](https://github.com/andrewMacmurray/elm-concurrent-task/blob/main/runner/http/index.ts) and the [fetch adapter](https://github.com/andrewMacmurray/elm-concurrent-task/blob/main/runner/http/fetch.ts) to see how to create your own.\n\n**Note:**\n\nYou're not required to use this module for http requests in `ConcurrentTask`, it's here for convenience.\nYou could create entirely your own from scratch - maybe you want an http package with request caching or special retry logic built in on the JS side.\n\n\n# Requests\n\n@docs request, get, post\n\n\n# Body\n\n@docs Body, emptyBody, stringBody, jsonBody\n\n\n# Expect\n\n@docs Expect, expectJson, expectString, expectWhatever\n\n\n# Headers\n\n@docs Header, header\n\n\n# Error\n\n@docs Error, Metadata\n\n","unions":[{"name":"Body","comment":" Send data in your http request.\n","args":[],"cases":[]},{"name":"Error","comment":" A Request can fail in a couple ways:\n\n - `BadUrl` means you did not provide a valid URL.\n - `Timeout` means it took too long to get a response.\n - `NetworkError` means the user turned off their wifi, went in a cave, etc.\n - `BadStatus` means you got a response back, but the status code indicates failure. Contains:\n - The response `Metadata`.\n - The raw response body as a `Json.Decode.Value`.\n - `BadBody` means you got a response back with a nice status code, but the body of the response was something unexpected. Contains:\n - The response `Metadata`.\n - The raw response body as a `Json.Decode.Value`.\n - The `Json.Decode.Error` that caused the error.\n\n","args":[],"cases":[["BadUrl",["String.String"]],["Timeout",[]],["NetworkError",[]],["BadStatus",["ConcurrentTask.Http.Metadata","Json.Decode.Value"]],["BadBody",["ConcurrentTask.Http.Metadata","Json.Decode.Value","Json.Decode.Error"]]]},{"name":"Expect","comment":" Describe what you expect to be returned in an http response body.\n","args":["a"],"cases":[]}],"aliases":[{"name":"Header","comment":" An Http header for configuring a request.\n","args":[],"type":"( String.String, String.String )"},{"name":"Metadata","comment":" Extra information about the response:\n\n - url of the server that actually responded (so you can detect redirects)\n - statusCode like 200 or 404\n - statusText describing what the statusCode means a little\n - headers like Content-Length and Expires\n\n**Note:**\n\nIt is possible for a response to have the same header multiple times.\nIn that case, all the values end up in a single entry in the headers dictionary.\nThe values are separated by commas, following the rules outlined [here](https://stackoverflow.com/questions/4371328/are-duplicate-http-response-headers-acceptable).\n\n","args":[],"type":"{ url : String.String, statusCode : Basics.Int, statusText : String.String, headers : Dict.Dict String.String String.String }"}],"values":[{"name":"emptyBody","comment":" Create an empty body for your request.\nThis is useful for `GET` requests and `POST` requests where you are not sending any data.\n","type":"ConcurrentTask.Http.Body"},{"name":"expectJson","comment":" Expect the response body to be `JSON`, decode it using the supplied decoder.\n","type":"Json.Decode.Decoder a -> ConcurrentTask.Http.Expect a"},{"name":"expectString","comment":" Expect the response body to be a `String`.\n","type":"ConcurrentTask.Http.Expect String.String"},{"name":"expectWhatever","comment":" Discard the response body.\n","type":"ConcurrentTask.Http.Expect ()"},{"name":"get","comment":" Send an Http `GET` request\n","type":"{ url : String.String, headers : List.List ConcurrentTask.Http.Header, expect : ConcurrentTask.Http.Expect a, timeout : Maybe.Maybe Basics.Int } -> ConcurrentTask.ConcurrentTask ConcurrentTask.Http.Error a"},{"name":"header","comment":" Create a `Header`. e.g.:\n\n header \"X-Requested-With\" \"Fetch\"\n\n","type":"String.String -> String.String -> ConcurrentTask.Http.Header"},{"name":"jsonBody","comment":" Put some JSON value in the body of your request. This will automatically add the `Content-Type: application/json` header.\n","type":"Json.Encode.Value -> ConcurrentTask.Http.Body"},{"name":"post","comment":" Send an Http `POST` request\n","type":"{ url : String.String, headers : List.List ConcurrentTask.Http.Header, body : ConcurrentTask.Http.Body, expect : ConcurrentTask.Http.Expect a, timeout : Maybe.Maybe Basics.Int } -> ConcurrentTask.ConcurrentTask ConcurrentTask.Http.Error a"},{"name":"request","comment":" Send an Http request - similar to `elm/http`'s [`Http.Task`](https://package.elm-lang.org/packages/elm/http/latest/Http#task)\n","type":"{ url : String.String, method : String.String, headers : List.List ConcurrentTask.Http.Header, body : ConcurrentTask.Http.Body, expect : ConcurrentTask.Http.Expect a, timeout : Maybe.Maybe Basics.Int } -> ConcurrentTask.ConcurrentTask ConcurrentTask.Http.Error a"},{"name":"stringBody","comment":" Put a `String` in the body of your request. Defining `jsonBody` looks like this:\n\n import Json.Encode as Encode\n\n jsonBody : Encode.Value -> Body\n jsonBody value =\n stringBody \"application/json\" (Encode.encode 0 value)\n\nThe first argument is a [MIME type](https://en.wikipedia.org/wiki/Media_type) of the body.\n\n","type":"String.String -> String.String -> ConcurrentTask.Http.Body"}],"binops":[]},{"name":"ConcurrentTask.Process","comment":" A drop in replacement for [elm/core's](https://package.elm-lang.org/packages/elm/core/latest/Process#sleep) `Process.sleep`.\n\nThe JavaScript runner has this task builtin by default. If needed it can be overridden like so:\n\n**NOTE:** The custom example is the same as the built-in implementation.\n\n import * as ConcurrentTask from \"@andrewmacmurray/elm-concurrent-task\"\n\n ConcurrentTask.register({\n tasks: {},\n ports: app.ports,\n builtins: {\n sleep: customSleep\n }\n });\n\n function customSleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n }\n\n@docs sleep\n\n","unions":[],"aliases":[],"values":[{"name":"sleep","comment":" Wait for a number of milliseconds before continuing with the next Task.\n\nA direct replacement for `elm/core`'s [`Process.sleep`](https://package.elm-lang.org/packages/elm/core/latest/Process#sleep).\n\n","type":"Basics.Int -> ConcurrentTask.ConcurrentTask x ()"}],"binops":[]},{"name":"ConcurrentTask.Random","comment":" Generate random values based on an [elm/random](https://package.elm-lang.org/packages/elm/random/latest/Random#Generator) `Generator`.\n\nThis Task uses a builtin randomSeed task from the JavaScript runner (the [same seed `elm/random` uses](https://github.com/elm/random/blob/ecf97bb43f0d5cd75243428f69f45323957bda25/src/Random.elm#L873-L875) - `Date.now()`).\n\nIf needed you can override the randomSeed task like so (e.g. use node or web crypto module to generate secure randomness):\n\n import * as ConcurrentTask from \"@andrewmacmurray/elm-concurrent-task\"\n import crypto from \"node:crypto\"\n\n ConcurrentTask.register({\n tasks: {},\n ports: app.ports,\n builtins: {\n randomSeed: customRandomSeed,\n },\n });\n\n function customRandomSeed(): number {\n return crypto.getRandomValues(new Uint32Array(1))[0];\n }\n\n@docs generate\n\n","unions":[],"aliases":[],"values":[{"name":"generate","comment":" Generate a random value based on an [elm/random](https://package.elm-lang.org/packages/elm/random/latest/Random) `Generator`.\n","type":"Random.Generator a -> ConcurrentTask.ConcurrentTask x a"}],"binops":[]},{"name":"ConcurrentTask.Time","comment":" Drop in replacements for [elm/time's](https://package.elm-lang.org/packages/elm/time/latest/Time#now)'s `Task`s.\n\nThe JavaScript runner has these tasks builtin by default. If needed they can be overridden like so:\n\n**NOTE:** The custom examples are the same as the built-in implementations.\n\n import * as ConcurrentTask from \"@andrewmacmurray/elm-concurrent-task\"\n\n ConcurrentTask.register({\n tasks: {},\n ports: app.ports,\n builtins: {\n timeNow: customTimeNow,\n timeZoneOffset: customTimeZoneOffset,\n timeZoneName: customTimeZoneName,\n }\n });\n\n function customTimeNow(): number {\n return Date.now()\n }\n\n function customTimeZoneOffset(): number {\n return -new Date().getTimezoneOffset();\n }\n\n function customTimeZoneName(): string | number {\n try {\n return Intl.DateTimeFormat().resolvedOptions().timeZone;\n } catch (e) {\n return new Date().getTimezoneOffset();\n }\n }\n\n@docs now, here, getZoneName\n\n","unions":[],"aliases":[],"values":[{"name":"getZoneName","comment":" Use `Intl.DateTimeFormat().resolvedOptions().timeZone` to try to get names like Europe/Moscow or America/Havana.\n\nA direct replacement for `elm/time`'s [`Time.getZoneName`](https://package.elm-lang.org/packages/elm/time/latest/Time#getZoneName).\n\n","type":"ConcurrentTask.ConcurrentTask x Time.ZoneName"},{"name":"here","comment":" Produce a `Zone` based on the current UTC offset.\n\nA direct replacement for `elm/time`'s [`Time.here`](https://package.elm-lang.org/packages/elm/time/latest/Time#here).\n\n","type":"ConcurrentTask.ConcurrentTask x Time.Zone"},{"name":"now","comment":" Get the POSIX time at the moment when this task is run.\n\nA direct replacement for `elm/time`'s [`Time.now`](https://package.elm-lang.org/packages/elm/time/latest/Time#now).\n\n","type":"ConcurrentTask.ConcurrentTask x Time.Posix"}],"binops":[]}]