[{"name":"WebsocketSimple","comment":" A small, typed WebSocket client for Elm with a compact, auditable JavaScript runtime. It supports multiple connections, lifecycle events, and text, binary, or JSON messages.\n\n\n# Installation\n\nInstall the Elm package:\n\n```sh\nelm install mbr/elm-wss\n```\n\nElm packages cannot declare ports. Make `Main.elm` a `port module`, or use another application-owned `port module`, then add these declarations:\n\n    import WebsocketSimple exposing (CommandPort, EventPort)\n\n    port wsCmd : CommandPort msg\n\n    port wsMsg : EventPort msg\n\nThe JavaScript runtime expects the exact port names `wsCmd` and `wsMsg`.\n\nCopy [`js/elm-websockets.js`](https://github.com/mbr/elm-wss/blob/2.0.0/js/elm-websockets.js) into the browser assets. Load the runtime and compiled Elm application, initialize Elm, and then initialize the runtime:\n\n```html\n<script src=\"elm-websockets.js\"></script>\n<script src=\"app.js\"></script>\n<script>\nvar app = Elm.Main.init({\n  node: document.getElementById(\"elm\")\n});\nElmWebsockets.initApp(app);\n</script>\n```\n\nThe JavaScript initialization is a no-op when the application does not contain the command port, so it can remain in the bootstrap while WebSocket code is temporarily unused.\n\n\n# Ports\n\nPass the application-owned ports described by these aliases to commands and subscriptions.\n\n@docs CommandPort, EventPort\n\n\n# Basic usage\n\nSubscribe to events before opening a connection, and wait for `Connected` before transmitting:\n\n    import WebsocketPorts as Ports\n    import WebsocketSimple as WebSocket\n\n    type Msg\n        = WebSocketEvent WebSocket.RawMsg\n\n    init : () -> ( List String, Cmd Msg )\n    init _ =\n        ( [], WebSocket.open Ports.wsCmd \"ws://127.0.0.1:8765\" )\n\n    update : Msg -> List String -> ( List String, Cmd Msg )\n    update msg model =\n        case msg of\n            WebSocketEvent (WebSocket.Connected _) ->\n                ( model, WebSocket.send Ports.wsCmd (WebSocket.Transmit \"hello\") )\n\n            WebSocketEvent (WebSocket.Text value) ->\n                ( value :: model, WebSocket.close Ports.wsCmd )\n\n            WebSocketEvent (WebSocket.Binary _) ->\n                ( model, WebSocket.close Ports.wsCmd )\n\n            WebSocketEvent (WebSocket.Disconnected _) ->\n                ( model, Cmd.none )\n\n            WebSocketEvent (WebSocket.TransportError error) ->\n                ( WebSocket.errorToString error :: model, Cmd.none )\n\n    subscriptions : List String -> Sub Msg\n    subscriptions _ =\n        Sub.map WebSocketEvent (WebSocket.subscribe Ports.wsMsg)\n\n\n# Commands\n\n`send` and its convenience functions use an implicit `\"default\"` handle. Use `sendWithHandle` for multiple connections.\n\n@docs Cmd, CloseRequest, open, close, send, sendWithHandle\n\n\n# Handles\n\nEach connection is identified by an opaque handle encoded as a string at the port boundary.\n\n    chat : WebSocket.Handle\n    chat =\n        WebSocket.handle \"chat\"\n\n    alerts : WebSocket.Handle\n    alerts =\n        WebSocket.handle \"alerts\"\n\n    openConnections : Cmd msg\n    openConnections =\n        Cmd.batch\n            [ WebSocket.sendWithHandle Ports.wsCmd chat (WebSocket.Open chatUrl [])\n            , WebSocket.sendWithHandle Ports.wsCmd alerts (WebSocket.Open alertsUrl [])\n            ]\n\n@docs Handle, handle, handleToString\n\n\n# Events\n\n`subscribe` discards handle information. Use `subscribeWithHandle` to distinguish events from multiple connections.\n\n    type Msg\n        = WebSocketEvent ( WebSocket.Handle, WebSocket.RawMsg )\n\n    subscriptions : model -> Sub Msg\n    subscriptions _ =\n        Sub.map WebSocketEvent (WebSocket.subscribeWithHandle Ports.wsMsg)\n\n@docs RawMsg, CloseDetails, TransportErrorKind, TransportErrorDetails, subscribe, subscribeWithHandle, errorKindToString, errorToString\n\n\n# JSON\n\nRegular subscriptions expose incoming text and binary frames as `Text String` and `Binary Bytes`. Typed subscriptions decode text frames while keeping transport errors separate from payload decoding failures. A binary frame received through a typed JSON subscription produces an `UnsupportedData` transport failure.\n\n    import Json.Decode as Decode\n\n    type alias Payload =\n        { message : String }\n\n    payloadDecoder : Decode.Decoder Payload\n    payloadDecoder =\n        Decode.map Payload (Decode.field \"message\" Decode.string)\n\n    type Msg\n        = WebSocketMessage (WebSocket.Msg Payload)\n\n    subscriptions : model -> Sub Msg\n    subscriptions _ =\n        WebSocket.subscribeMsg Ports.wsMsg payloadDecoder WebSocketMessage\n\n@docs Msg, subscribeMsg, subscribeMsgWithHandle, transmitMsg, transmitMsgWithHandle, parseIncoming\n\n","unions":[{"name":"Cmd","comment":" Command sent to a WebSocket connection.\n\n  - `Open` opens the URL with an ordered list of requested subprotocols. An empty list requests none.\n  - `Transmit` sends a text frame.\n  - `TransmitBinary` sends a binary frame.\n  - A rejected transmission produces a `TransportError`; an accepted transmission produces no acknowledgement.\n  - `Close Nothing` preserves the browser's default close behavior. `Close (Just request)` sends the supplied code and reason unchanged, leaving validation to the browser.\n\n","args":[],"cases":[["Open",["WebsocketSimple.Url","List.List String.String"]],["Transmit",["String.String"]],["TransmitBinary",["Bytes.Bytes"]],["Close",["Maybe.Maybe WebsocketSimple.CloseRequest"]]]},{"name":"Handle","comment":" Identifies a particular WebSocket connection.\n","args":[],"cases":[]},{"name":"Msg","comment":" Typed event received from a WebSocket connection carrying JSON text frames.\n\nTransport failures remain separate from payload decoding failures. `PayloadDecodeFailure` retains both the original text and the `Json.Decode.Error`.\n\n","args":["t"],"cases":[["Established",["Maybe.Maybe String.String"]],["Closed",["WebsocketSimple.CloseDetails"]],["Received",["t"]],["TransportFailure",["WebsocketSimple.TransportErrorDetails"]],["PayloadDecodeFailure",["String.String","Json.Decode.Error"]]]},{"name":"RawMsg","comment":" Raw event received from a WebSocket connection.\n\n  - `Connected` means the connection can transmit and contains the negotiated subprotocol, if any.\n  - `Disconnected` contains the browser's close details and may occur without a preceding `Connected` event.\n  - `Text` contains a received text frame.\n  - `Binary` contains a received binary frame.\n  - `TransportError` describes a construction, send, close, browser, unsupported-data, or port-decoding failure.\n\nEvents preserve browser delivery order even though binary reads are asynchronous.\n\n","args":[],"cases":[["Connected",["Maybe.Maybe String.String"]],["Disconnected",["WebsocketSimple.CloseDetails"]],["Text",["String.String"]],["Binary",["Bytes.Bytes"]],["TransportError",["WebsocketSimple.TransportErrorDetails"]]]},{"name":"TransportErrorKind","comment":" Categorizes a WebSocket transport error.\n","args":[],"cases":[["ConstructionFailure",[]],["SendFailure",[]],["CloseFailure",[]],["BrowserFailure",[]],["SendRejection",[]],["UnsupportedData",[]],["PortDecodingFailure",[]]]}],"aliases":[{"name":"CloseDetails","comment":" Details supplied when a WebSocket closes.\n\nThe event may arrive even when the connection never opened. `initiatedLocally` records whether this client successfully requested closure.\n\n","args":[],"type":"{ code : Basics.Int, reason : String.String, wasClean : Basics.Bool, initiatedLocally : Basics.Bool }"},{"name":"CloseRequest","comment":" Describes an application-requested close.\n\nUse an empty reason to send only the explicit close code.\n\n","args":[],"type":"{ code : Basics.Int, reason : String.String }"},{"name":"CommandPort","comment":" Type of an application-owned port that sends encoded commands to the JavaScript runtime.\n","args":["msg"],"type":"( String.String, String.String, Json.Encode.Value ) -> Platform.Cmd.Cmd msg"},{"name":"EventPort","comment":" Type of an application-owned port that receives encoded events from the JavaScript runtime.\n","args":["msg"],"type":"(( String.String, String.String, Json.Encode.Value ) -> msg) -> Platform.Sub.Sub msg"},{"name":"TransportErrorDetails","comment":" Describes a categorized WebSocket transport error.\n","args":[],"type":"{ kind : WebsocketSimple.TransportErrorKind, message : String.String }"}],"values":[{"name":"close","comment":" Close the implicit default connection with the browser's default status.\n","type":"WebsocketSimple.CommandPort msg -> Platform.Cmd.Cmd msg"},{"name":"errorKindToString","comment":" Render a transport error category as a string.\n","type":"WebsocketSimple.TransportErrorKind -> String.String"},{"name":"errorToString","comment":" Render a transport error as a readable string containing its category and message.\n","type":"WebsocketSimple.TransportErrorDetails -> String.String"},{"name":"handle","comment":" Construct a WebSocket handle from its port-boundary representation.\n","type":"String.String -> WebsocketSimple.Handle"},{"name":"handleToString","comment":" Return a WebSocket handle's string representation.\n","type":"WebsocketSimple.Handle -> String.String"},{"name":"open","comment":" Open the implicit default connection without requesting a subprotocol.\n","type":"WebsocketSimple.CommandPort msg -> String.String -> Platform.Cmd.Cmd msg"},{"name":"parseIncoming","comment":" Convert a raw event into a typed JSON event.\n","type":"Json.Decode.Decoder t -> WebsocketSimple.RawMsg -> WebsocketSimple.Msg t"},{"name":"send","comment":" Send a command to the implicit `\"default\"` connection.\n","type":"WebsocketSimple.CommandPort msg -> WebsocketSimple.Cmd -> Platform.Cmd.Cmd msg"},{"name":"sendWithHandle","comment":" Send a command to the connection identified by a handle.\n","type":"WebsocketSimple.CommandPort msg -> WebsocketSimple.Handle -> WebsocketSimple.Cmd -> Platform.Cmd.Cmd msg"},{"name":"subscribe","comment":" Subscribe to raw events from the implicit default connection.\n\nThis discards the originating handle from every event.\n\n","type":"WebsocketSimple.EventPort WebsocketSimple.RawMsg -> Platform.Sub.Sub WebsocketSimple.RawMsg"},{"name":"subscribeMsg","comment":" Subscribe to typed JSON events while discarding handle information.\n","type":"WebsocketSimple.EventPort msg -> Json.Decode.Decoder t -> (WebsocketSimple.Msg t -> msg) -> Platform.Sub.Sub msg"},{"name":"subscribeMsgWithHandle","comment":" Subscribe to typed JSON events paired with their originating handles.\n","type":"WebsocketSimple.EventPort msg -> Json.Decode.Decoder t -> (( WebsocketSimple.Handle, WebsocketSimple.Msg t ) -> msg) -> Platform.Sub.Sub msg"},{"name":"subscribeWithHandle","comment":" Subscribe to raw events paired with their originating handles.\n","type":"WebsocketSimple.EventPort ( WebsocketSimple.Handle, WebsocketSimple.RawMsg ) -> Platform.Sub.Sub ( WebsocketSimple.Handle, WebsocketSimple.RawMsg )"},{"name":"transmitMsg","comment":" Encode a value as JSON and transmit it through the implicit default connection.\n","type":"WebsocketSimple.CommandPort msg -> (t -> Json.Encode.Value) -> t -> Platform.Cmd.Cmd msg"},{"name":"transmitMsgWithHandle","comment":" Encode a value as JSON and transmit it through the connection identified by a handle.\n","type":"WebsocketSimple.CommandPort msg -> WebsocketSimple.Handle -> (t -> Json.Encode.Value) -> t -> Platform.Cmd.Cmd msg"}],"binops":[]}]