Skip to content

Commit 7e161e3

Browse files
authored
Merge pull request #34 from tinymce/websocket
Add bindings for WebSocket
2 parents 4b860d6 + 8a161cc commit 7e161e3

File tree

6 files changed

+240
-0
lines changed

6 files changed

+240
-0
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ Done:
88
* Converted to rescript syntax (#18)
99
* Added `IntersectionObserver` and `IntersectionObserverEntry` bindings (#27)
1010
* Imported `bs-fetch` and converted it to "t-first" (#31)
11+
* Added `WebSocket` bindings (#34)
1112

1213
Todo:
1314
* Convert more input types to `node_like` and `element_like` to improve usability

examples/webapi_example.res

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
open Webapi
2+
3+
/* Adapted from https://developer.mozilla.org/en-US/docs/Web/API/WebSocket#examples */
4+
let _ = {
5+
// Create WebSocket connection.
6+
let socket = WebSocket.make("ws://localhost:8080")
7+
8+
// Connection opened
9+
socket->WebSocket.addOpenListener(_ => {
10+
socket->WebSocket.sendText("Hello Server!")
11+
})
12+
13+
// Listen for messages
14+
socket->WebSocket.addMessageListener(event => {
15+
Js.log2("Message from server ", event.data)
16+
})
17+
}

lib/js/examples/webapi_example.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
'use strict';
2+
3+
4+
var socket = new WebSocket("ws://localhost:8080");
5+
6+
socket.addEventListener("open", (function (param) {
7+
socket.send("Hello Server!");
8+
9+
}));
10+
11+
socket.addEventListener("message", (function ($$event) {
12+
console.log("Message from server ", $$event.data);
13+
14+
}));
15+
16+
/* socket Not a pure module */

src/Webapi.res

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ module ReadableStream = Webapi__ReadableStream
1616
module IntersectionObserver = Webapi__IntersectionObserver
1717
module ResizeObserver = Webapi__ResizeObserver
1818
module Url = Webapi__Url
19+
module WebSocket = Webapi__WebSocket
1920

2021
type rafId
2122

src/Webapi/Webapi__WebSocket.res

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
open Js.TypedArray2
2+
3+
type readyState
4+
type t<'binaryType> = private {
5+
binaryType: [#blob | #arraybuffer],
6+
bufferedAmount: float,
7+
extensions: string,
8+
protocol: string,
9+
readyState: readyState,
10+
url: string,
11+
}
12+
@new external make: string => t<Webapi__Blob.t> = "WebSocket"
13+
@new external makeArrayBuffer: string => t<array_buffer> = "WebSocket"
14+
@set external setArrayBuffer: (t<array_buffer>, @as("arraybuffer") _) => unit = "binaryType"
15+
let makeArrayBuffer = url => {
16+
let ws = makeArrayBuffer(url)
17+
ws->setArrayBuffer
18+
ws
19+
}
20+
21+
@val @scope("WebSocket") external readyStateClosing: readyState = "CLOSING"
22+
@val @scope("WebSocket") external readyStateClosed: readyState = "CLOSED"
23+
@val @scope("WebSocket") external readyStateConnected: readyState = "CONNECTING"
24+
@val @scope("WebSocket") external readyStateOpen: readyState = "OPEN"
25+
26+
let isOpen = ws => ws.readyState === readyStateOpen
27+
28+
@send external close: t<'binaryType> => unit = "close"
29+
@send external closeWithReason: (t<'binaryType>, ~code: int, ~reason: string) => unit = "close"
30+
31+
@send
32+
external addOpenListener: (t<'binaryType>, @as("open") _, Webapi__Dom__Event.t => unit) => unit =
33+
"addEventListener"
34+
@send
35+
external removeOpenListener: (t<'binaryType>, @as("open") _, Webapi__Dom__Event.t => unit) => unit =
36+
"removeEventListener"
37+
38+
type closeEvent = private {
39+
code: int,
40+
reason: string,
41+
wasClean: bool,
42+
}
43+
@send
44+
external addCloseListener: (t<'binaryType>, @as("close") _, closeEvent => unit) => unit =
45+
"addEventListener"
46+
@send
47+
external removeCloseListener: (t<'binaryType>, @as("close") _, closeEvent => unit) => unit =
48+
"removeEventListener"
49+
50+
@send
51+
external addErrorListener: (t<'binaryType>, @as("error") _, Webapi__Dom__Event.t => unit) => unit =
52+
"addEventListener"
53+
@send
54+
external removeErrorListener: (
55+
t<'binaryType>,
56+
@as("error") _,
57+
Webapi__Dom__Event.t => unit,
58+
) => unit = "removeEventListener"
59+
60+
type messageEvent<'binaryType> = {
61+
data: Js.Json.t,
62+
origin: string,
63+
lastEventId: string,
64+
}
65+
@send
66+
external addMessageListener: (
67+
t<'binaryType>,
68+
@as("message") _,
69+
messageEvent<'binaryType> => unit,
70+
) => unit = "addEventListener"
71+
@send
72+
external removeMessageListener: (
73+
t<'binaryType>,
74+
@as("message") _,
75+
messageEvent<'binaryType> => unit,
76+
) => unit = "removeEventListener"
77+
78+
@send external sendText: (t<'binaryType>, string) => unit = "send"
79+
@send external sendBlob: (t<'binaryType>, Webapi__Blob.t) => unit = "send"
80+
@send external sendArrayBuffer: (t<'binaryType>, array_buffer) => unit = "send"
81+
@send external sendInt8Array: (t<'binaryType>, Int8Array.t) => unit = "send"
82+
@send external sendInt16Array: (t<'binaryType>, Int16Array.t) => unit = "send"
83+
@send external sendInt32Array: (t<'binaryType>, Int32Array.t) => unit = "send"
84+
@send external sendUint8Array: (t<'binaryType>, Uint8Array.t) => unit = "send"
85+
@send external sendUint8ClampedArray: (t<'binaryType>, Uint8ClampedArray.t) => unit = "send"
86+
@send external sendUint16Array: (t<'binaryType>, Uint16Array.t) => unit = "send"
87+
@send external sendUint32Array: (t<'binaryType>, Uint32Array.t) => unit = "send"
88+
@send external sendFloat32Array: (t<'binaryType>, Float32Array.t) => unit = "send"
89+
@send external sendFloat64Array: (t<'binaryType>, Float64Array.t) => unit = "send"
90+
@send external sendDataView: (t<'binaryType>, DataView.t) => unit = "send"
91+
92+
// the data type for binary messages - blob or arraybuffer - is determined by the `binaryType` property set in `make()`.
93+
@get external unsafeMessageAsBinary: messageEvent<'binaryType> => 'binaryType = "data"
94+
@get external unsafeMessageAsText: messageEvent<'binaryType> => string = "data"
95+
let messageIsText = message => {
96+
open Js.Types
97+
test(message.data, String)
98+
}
99+
100+
let messageAsText = message => {
101+
if message->messageIsText {
102+
Some(message->unsafeMessageAsText)
103+
} else {
104+
None
105+
}
106+
}
107+
108+
let messageAsBinary = message => {
109+
if !(message->messageIsText) {
110+
Some(message->unsafeMessageAsBinary)
111+
} else {
112+
None
113+
}
114+
}

src/Webapi/Webapi__WebSocket.resi

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
open Js.TypedArray2
2+
3+
type readyState
4+
type t<'binaryType> = private {
5+
binaryType: [#blob | #arraybuffer],
6+
bufferedAmount: float,
7+
extensions: string,
8+
protocol: string,
9+
readyState: readyState,
10+
url: string,
11+
}
12+
@new external make: string => t<Webapi__Blob.t> = "WebSocket"
13+
let makeArrayBuffer: string => t<array_buffer>
14+
15+
@val @scope("WebSocket") external readyStateClosing: readyState = "CLOSING"
16+
@val @scope("WebSocket") external readyStateClosed: readyState = "CLOSED"
17+
@val @scope("WebSocket") external readyStateConnected: readyState = "CONNECTING"
18+
@val @scope("WebSocket") external readyStateOpen: readyState = "OPEN"
19+
20+
let isOpen: t<'binaryType> => bool
21+
22+
@send external close: t<'binaryType> => unit = "close"
23+
@send external closeWithReason: (t<'binaryType>, ~code: int, ~reason: string) => unit = "close"
24+
25+
@send
26+
external addOpenListener: (t<'binaryType>, @as("open") _, Webapi__Dom__Event.t => unit) => unit =
27+
"addEventListener"
28+
@send
29+
external removeOpenListener: (t<'binaryType>, @as("open") _, Webapi__Dom__Event.t => unit) => unit =
30+
"removeEventListener"
31+
32+
type closeEvent = private {
33+
code: int,
34+
reason: string,
35+
wasClean: bool,
36+
}
37+
@send
38+
external addCloseListener: (t<'binaryType>, @as("close") _, closeEvent => unit) => unit =
39+
"addEventListener"
40+
@send
41+
external removeCloseListener: (t<'binaryType>, @as("close") _, closeEvent => unit) => unit =
42+
"removeEventListener"
43+
44+
@send
45+
external addErrorListener: (t<'binaryType>, @as("error") _, Webapi__Dom__Event.t => unit) => unit =
46+
"addEventListener"
47+
@send
48+
external removeErrorListener: (
49+
t<'binaryType>,
50+
@as("error") _,
51+
Webapi__Dom__Event.t => unit,
52+
) => unit = "removeEventListener"
53+
54+
type messageEvent<'binaryType> = {
55+
data: Js.Json.t,
56+
origin: string,
57+
lastEventId: string,
58+
}
59+
@send
60+
external addMessageListener: (
61+
t<'binaryType>,
62+
@as("message") _,
63+
messageEvent<'binaryType> => unit,
64+
) => unit = "addEventListener"
65+
@send
66+
external removeMessageListener: (
67+
t<'binaryType>,
68+
@as("message") _,
69+
messageEvent<'binaryType> => unit,
70+
) => unit = "removeEventListener"
71+
72+
@send external sendText: (t<'binaryType>, string) => unit = "send"
73+
@send external sendBlob: (t<'binaryType>, Webapi__Blob.t) => unit = "send"
74+
@send external sendArrayBuffer: (t<'binaryType>, array_buffer) => unit = "send"
75+
@send external sendInt8Array: (t<'binaryType>, Int8Array.t) => unit = "send"
76+
@send external sendInt16Array: (t<'binaryType>, Int16Array.t) => unit = "send"
77+
@send external sendInt32Array: (t<'binaryType>, Int32Array.t) => unit = "send"
78+
@send external sendUint8Array: (t<'binaryType>, Uint8Array.t) => unit = "send"
79+
@send external sendUint8ClampedArray: (t<'binaryType>, Uint8ClampedArray.t) => unit = "send"
80+
@send external sendUint16Array: (t<'binaryType>, Uint16Array.t) => unit = "send"
81+
@send external sendUint32Array: (t<'binaryType>, Uint32Array.t) => unit = "send"
82+
@send external sendFloat32Array: (t<'binaryType>, Float32Array.t) => unit = "send"
83+
@send external sendFloat64Array: (t<'binaryType>, Float64Array.t) => unit = "send"
84+
@send external sendDataView: (t<'binaryType>, DataView.t) => unit = "send"
85+
86+
@get external unsafeMessageAsBinary: messageEvent<'binaryType> => 'binaryType = "data"
87+
@get external unsafeMessageAsText: messageEvent<'binaryType> => string = "data"
88+
89+
let messageIsText: messageEvent<'binaryType> => bool
90+
let messageAsText: messageEvent<'binaryType> => option<string>
91+
let messageAsBinary: messageEvent<'binaryType> => option<'binaryType>

0 commit comments

Comments
 (0)