ghcjs-websockets 0.3.0.1 → 0.3.0.2
raw patch · 6 files changed
+173/−9 lines, 6 filesdep ~text
Dependency ranges changed: text
Files
- CHANGELOG.md +24/−0
- README.md +144/−0
- ghcjs-websockets.cabal +5/−4
- src/JavaScript/Blob.hs +0/−3
- src/JavaScript/WebSockets.hs +0/−1
- src/JavaScript/WebSockets/Internal.hs +0/−1
+ CHANGELOG.md view
@@ -0,0 +1,24 @@+0.3.0.2+-------+<https://github.com/mstksg/ghcjs-websockets/releases/tag/v0.3.0.2>++* Lowered bounds on *text* dependency.+* Added `CHANGELOG.md` and `README.md` to extra source dependecy fields, to+ count them in the cabal package.++0.3.0.1+-------+<https://github.com/mstksg/ghcjs-websockets/releases/tag/v0.3.0.1>++* Fixed the "other-modules" cabal file field to include non-exported but+ important modules.++0.3.0.0+-------+<https://github.com/mstksg/ghcjs-websockets/releases/tag/v0.3.0.0>++* First official release. API more or less stabilized. Library is more or+ less stable, but there are still some extra aspects of the javascript+ websockets API to hook onto for more power/information, and some+ javascript errors to be handled on edge cases.+
+ README.md view
@@ -0,0 +1,144 @@+ghcjs-websockets+================++*ghcjs-websockets* aims to provide a clean, idiomatic, efficient, low-level,+out-of-your-way, bare bones, concurrency-aware interface with minimal+abstractions over the [Javascript Websockets API][jsapi], inspired by common+Haskell idioms found in libraries like [io-stream][] and the server-side+[websockets][] library, targeting compilation to Javascript with `ghcjs`.++The interface abstracts websockets as simple IO/file handles, with additional+access to the natively "typed" (text vs binary) nature of the Javascript+Websockets API. There are also convenience functions to directly decode+serialized data (serialized with [binary][]) sent through channels.++The library is mostly intended to be a low-level FFI library, with the hopes+that other, more advanced libraries maybe build on the low-level FFI bindings+in order to provide more advanced and powerful abstractions. Most design+decisions were made with the intent of keeping things as simple as possible in+order for future libraries to abstract over it.++Most of the necessary functionality is in hopefully in+`JavaScript.WebSockets`; more of the low-level API is exposed in+`JavaScript.WebSockets.Internal` if you need it for library construction.++Documenation is [online on github pages][documentation].++[jsapi]: http://www.w3.org/TR/websockets/+[io-stream]: http://hackage.haskell.org/package/io-streams+[websockets]: http://hackage.haskell.org/package/websockets+[binary]: http://hackage.haskell.org/package/binary+[documentation]: http://mstksg.github.io/ghcjs-websockets/JavaScript-WebSockets.html++Usage+-----++```haskell+import Data.Text (unpack)++-- A simple echo client, echoing all incoming text data+main :: IO ()+main = withUrl "ws://my-server.com" $ \conn ->+ forever $ do+ t <- receiveText conn+ putStrLn (unpack t)+ sendText conn t+```++The above code will attempt to interpret all incoming data as UTF8-encoded+Text, and throw away data that does not.++`conn` is a `Connection`, which encapsulates a websocket channel.++You can also do the same thing to interpret all incoming data as any instance+of `Binary` --- say, `Int`s:++```haskell+-- A simple client waiting for connections and outputting the running sum+main :: IO ()+main = withUrl "ws://my-server.com" (runningSum 0)++runningSum :: Int -> Connection -> IO ()+runningSum n conn = do+ i <- receiveData conn+ print (n + i)+ runningSum (n + i) conn+```++`receiveData` will block until the `Connection` receives data that is+decodable as whatever type you expect, and will throw away all nondecodable+data (including `Text` data).++The `receive` function is provided as an over-indulgent layer of abstraction+where you can receive both `Text` and instances of `Binary` with the same+function using typeclass magic --- for the examples above, you could use+`receive` in place of both `receiveText` and `receiveData`.++`send` works the same way for `sendText` and `sendData`.++If you want to, you can access the incoming data directly using the+`SocketMsg` sum type, which exposes either a `Text` or a lazy `ByteString`:++```haskell+import Data.Text (unpack, append)+import qualified Data.ByteString.Base64.Lazy as B64++main :: IO ()+main = withUrl "ws://my-server.com" $ \conn ->+ forever $ do+ msg <- receiveMessage+ putStrLn $ case msg of+ SocketMsgText t ->+ unpack $ append "Received text: " t+ SocketMsgData d ->+ "Received data: " ++ show (B64.encode d)+```++You can talk to multiple connections by nesting `withUrl`:++```haskell+-- Act as a relay between two servers+main :: IO ()+main = withUrl "ws://server-1.com" $ \conn1 ->+ withUrl "ws://server-2.com" $ \conn2 ->+ forever $ do+ msg <- receiveMessage conn1+ sendMessage conn2 msg+```++And also alternatively, you can manually open and close connections:++```haskell+-- Act as a relay between two servers+main :: IO ()+main = do+ conn1 <- openConnection "ws://server-1.com"+ conn2 <- openConnection "ws://server-2.com"+ forever $ do+ msg <- receiveMessage conn1+ sendMessage conn2 msg+ closeConnection conn2+ closeConnection conn1+```++`receiveMessage` and its varieties will all throw an exception if the+connection closes while they're waiting or if you attempt to receive on a+closed connection. You can handle these with mechanisms from+`Control.Exception`, or you can use their "maybe"-family counterparts,+`receiveMessageMaybe`, etc., who will return results in `Just` on a success,+or return a `Nothing` if the connection is closed or if receiving on a closed+connection.++You can use also `connectionClosed :: Connection -> IO Bool` to check if the+given `Connection` object is closed (or `connectionCloseReason` to see *why*).++When closing connections, there might be some messages that were received by+the socket but never processed on the Haskell side with a `receive` method.+These will normally be deleted; however, you can use+`closeConnectionLeftovers` or `withUrlLeftovers` to grab a list of the raw+`SocketMsg`s remaining after closing.++### Copyright++Copyright (c) Justin Le 2015+
ghcjs-websockets.cabal view
@@ -1,5 +1,5 @@ name: ghcjs-websockets-version: 0.3.0.1+version: 0.3.0.2 synopsis: GHCJS interface for the Javascript Websocket API description: Documentation online at@@ -82,7 +82,8 @@ copyright: Copyright (c) Justin Le 2015 category: Web build-type: Simple--- extra-source-files: +extra-source-files: CHANGELOG.md+ , README.md cabal-version: >=1.10 source-repository head@@ -95,13 +96,13 @@ -- ghcjs-options: -O2 other-modules: JavaScript.Blob , JavaScript.WebSockets.FFI- -- other-extensions: + -- other-extensions: ghc-options: -Wall build-depends: base >= 4.7 && < 5 , base64-bytestring >= 1 , binary >= 0.7 , bytestring >= 0.10 , ghcjs-base >= 0.1- , text >= 1.2+ , text >= 1 hs-source-dirs: src default-language: Haskell2010
src/JavaScript/Blob.hs view
@@ -32,6 +32,3 @@ isBlob :: JSRef a -> IO Bool isBlob ref = ffi_blobCheck ref---
src/JavaScript/WebSockets.hs view
@@ -438,4 +438,3 @@ -- | Returns the origin url of the given 'Connection'. connectionOrigin :: Connection -> Text connectionOrigin = _connOrigin-
src/JavaScript/WebSockets/Internal.hs view
@@ -395,4 +395,3 @@ else do let blob = unsafeCoerce msg :: JSString return . Just . SocketMsgText . fromJSString $ blob-