diff --git a/.bsb.lock b/.bsb.lock deleted file mode 100644 index 95f589b..0000000 --- a/.bsb.lock +++ /dev/null @@ -1 +0,0 @@ -96094 \ No newline at end of file diff --git a/.gitignore b/.gitignore index 0878545..177c9b7 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ lib /node_modules/ .merlin *.js +.bsb.lock diff --git a/bsconfig.json b/bsconfig.json index 7f569cb..6bf4c76 100644 --- a/bsconfig.json +++ b/bsconfig.json @@ -1,15 +1,13 @@ { "name": "bs-socket", - "bsc-flags": ["-w", "-20"], "package-specs": { "module": "commonjs", "in-source": true }, "suffix": ".bs.js", - "namespace": true, "sources": [ { - "dir": "src", + "dir": "src" }, { "dir": "example", diff --git a/example/BsSocket.re b/example/BsSocket.re deleted file mode 100644 index 162bd32..0000000 --- a/example/BsSocket.re +++ /dev/null @@ -1,11 +0,0 @@ -/* This is kind of a hack to make the example be as copy-pastable as possible. - Without this module, the example can't do `BsSocket.Server.Make`, it'd have to access `Server.Make` - directly, because bsb doesn't expose the namespace to the dev sources :( - - Ben - May the 4th 2018 -*/ - - -module Server = Server; -module Client = Client; -module Namespace = Namespace; diff --git a/example/ExampleClient.re b/example/ExampleClient.re index 97c0aea..07d787b 100644 --- a/example/ExampleClient.re +++ b/example/ExampleClient.re @@ -2,7 +2,8 @@ * All credit goes to Cheng Lou. It was just too hard to figure out jengaboot + bucklescript for now. * Copy pasted from https://github.com/chenglou/reason-js **/ -[@bs.send] external toString : Js.t('a) => string = "toString"; + +[@bs.send] external toString: Js.t('a) => string = "toString"; module Event = { type eventT; @@ -18,61 +19,48 @@ module Event = { /* Created a bunch of modules to keep things clean. This is just for demo purposes. */ module Element = { type elementT; - [@bs.set] external setInnerHTML : (elementT, string) => unit = "innerHTML"; - [@bs.get] external getInnerHTML : elementT => string = "innerHTML"; - [@bs.set] external setValue : (elementT, string) => unit = "value"; - [@bs.get] external getValue : elementT => string = "value"; + [@bs.set] external setInnerHTML: (elementT, string) => unit = "innerHTML"; + [@bs.get] external getInnerHTML: elementT => string = "innerHTML"; + [@bs.set] external setValue: (elementT, string) => unit = "value"; + [@bs.get] external getValue: elementT => string = "value"; [@bs.send] - external addEventListener : (elementT, string, Event.eventT => unit) => unit = - "addEventListener"; + external addEventListener: (elementT, string, Event.eventT => unit) => unit = "addEventListener"; }; module Document = { + [@bs.val] external getElementById: string => Element.elementT = "document.getElementById"; [@bs.val] - external getElementById : string => Element.elementT = - "document.getElementById"; - [@bs.val] - external addEventListener : (string, Event.eventT => unit) => unit = - "document.addEventListener"; + external addEventListener: (string, Event.eventT => unit) => unit = "document.addEventListener"; }; module Window = { type intervalIdT; - [@bs.val] - external setInterval : (unit => unit, int) => intervalIdT = - "window.setInterval"; - [@bs.val] - external clearInterval : intervalIdT => unit = "window.clearInterval"; + [@bs.val] external setInterval: (unit => unit, int) => intervalIdT = "window.setInterval"; + [@bs.val] external clearInterval: intervalIdT => unit = "window.clearInterval"; }; -module MyClient = BsSocket.Client.Make(ExampleMessages); - -let socket = MyClient.create(); +let socket = Client.create(); -MyClient.emit(socket, Hi); +// Fire an event on first connect. This isn't necessary as the server can listen for a `connection` event. +// But it shows that you can send different payloads with different event names. +socket->Socket.emit("login", SharedTypes.Hi); let chatarea = Document.getElementById("chatarea"); -MyClient.on(socket, x => +socket->Socket.on("message", (. x) => switch (x) { - | Message(Data(s)) => + | SharedTypes.Message(Data(s)) => let innerHTML = Element.getInnerHTML(chatarea); Element.setInnerHTML( chatarea, - innerHTML - ++ "
Message: " - ++ s - ++ "
", + innerHTML ++ "
Message: " ++ s ++ "
", ); - | Message(OrOthers) => print_endline("OrOthers") - | MessageOnEnter(s) => + | SharedTypes.Message(OrOthers) => print_endline("OrOthers") + | SharedTypes.MessageOnEnter(s) => let innerHTML = Element.getInnerHTML(chatarea); Element.setInnerHTML( chatarea, - innerHTML - ++ "
MessageOnEnter: " - ++ s - ++ "
", + innerHTML ++ "
MessageOnEnter: " ++ s ++ "
", ); } ); @@ -81,19 +69,13 @@ let sendbutton = Document.getElementById("sendbutton"); let chatinput = Document.getElementById("chatinput"); -Element.addEventListener(sendbutton, "click", (_) => - MyClient.emit( - socket, - Shared(Message(Data(Element.getValue(chatinput)))), - ) +Element.addEventListener(sendbutton, "click", _ => + socket->Socket.emit("message", SharedTypes.Message(Data(Element.getValue(chatinput)))) ); Document.addEventListener("keyup", e => if (Event.isEnterKey(e)) { - MyClient.emit( - socket, - Shared(MessageOnEnter(Element.getValue(chatinput))), - ); + socket->Socket.emit("message", SharedTypes.MessageOnEnter(Element.getValue(chatinput))); Element.setValue(chatinput, ""); } ); diff --git a/example/ExampleMessages.re b/example/ExampleMessages.re deleted file mode 100644 index 5ee3fa7..0000000 --- a/example/ExampleMessages.re +++ /dev/null @@ -1,18 +0,0 @@ -type dataT = - | Data(string) - | OrOthers; - -type data2T = string; - -type shared = - | Message(dataT) - | MessageOnEnter(data2T); - -type clientToServer = - | Shared(shared) - | Hi; - -/* In this simple example, the server has no unique messages, unlike - the client, which is polite and says hi after connecting (in addition - to sending all the shared message types). */ -type serverToClient = shared; diff --git a/example/ExampleServer.re b/example/ExampleServer.re index 2639f25..82eb9a0 100644 --- a/example/ExampleServer.re +++ b/example/ExampleServer.re @@ -1,25 +1,23 @@ /* Created a bunch of modules to keep things clean. This is just for demo purposes. */ module Path = { type pathT; - [@bs.module "path"] [@bs.splice] - external join : array(string) => string = ""; + [@bs.module "path"] [@bs.splice] external join: array(string) => string = "join"; }; module Express = { type expressT; - [@bs.module] external express : unit => expressT = ""; - [@bs.send] external use : (expressT, string) => unit = "use"; - [@bs.module "express"] external static : string => string = "static"; + [@bs.module] external express: unit => expressT = "express"; + [@bs.send] external use: (expressT, string) => unit = "use"; + [@bs.module "express"] external static: string => string = "static"; type responseT; - [@bs.send] external sendFile : (responseT, string, 'a) => unit = "sendFile"; - [@bs.send] - external get : (expressT, string, ('a, responseT) => unit) => unit = "get"; + [@bs.send] external sendFile: (responseT, string, 'a) => unit = "sendFile"; + [@bs.send] external get: (expressT, string, ('a, responseT) => unit) => unit = "get"; }; module Http = { type http; - [@bs.module "http"] external create : Express.expressT => http = "Server"; - [@bs.send] external listen : (http, int, unit => unit) => unit = ""; + [@bs.module "http"] external create: Express.expressT => http = "Server"; + [@bs.send] external listen: (http, int, unit => unit) => unit = "listen"; }; /* ------------ Real API demo stars here ------------ */ @@ -27,41 +25,35 @@ let app = Express.express(); let http = Http.create(app); -[@bs.val] external __dirname : string = ""; - +let __dirname = + switch ([%external __dirname]) { + | None => failwith("Should not happen") + | Some(d) => d + }; Express.use(app, Express.static(Path.join([|__dirname, ".."|]))); -Express.get(app, "/", (_, res) => - Express.sendFile(res, "index.html", {"root": __dirname}) -); - -module MyServer = BsSocket.Server.Make(ExampleMessages); - -let io = MyServer.createWithHttp(http); - -MyServer.onConnect( - io, - socket => { - open MyServer; - print_endline("Got a connection!"); - let socket = Socket.join(socket, "someRoom"); - /* Polymorphic pipe which actually knows about ExampleCommon.t from InnerServer */ - Socket.on( - socket, - fun - | Shared(message) => { - Socket.broadcast(socket, message); - Socket.emit(socket, message); - } - | Hi => { - Js.log("oh, hi client."); - Js.log( - "Sorry I can't say hi back. Try uncommenting the line below to see why.", - ); - /* Socket.emit(socket, Hi); */ - }, - ); - }, -); +Express.get(app, "/", (_, res) => Express.sendFile(res, "index.html", {"root": __dirname})); + +// module MyServer = BsSocket.Server.Make(ExampleMessages); + +let io = Server.createWithHttp(http); + +io->Server.onConnect(socket => { + print_endline("Got a connection!"); + let socket = socket->Socket.join("someRoom"); + /* Polymorphic pipe which actually knows about ExampleCommon.t from InnerServer */ + socket->Socket.on("login", (. data) => + switch (data) { + | SharedTypes.Hi => + Js.log("oh, hi client."); + Js.log("Sorry I can't say hi back. Try uncommenting the line below to see why."); + /* Socket.emit(socket, Hi); */ + } + ); + socket->Socket.on("message", (. data) => { + Server.emitBroadcast(socket, "myEvent", data); + Socket.emit(socket, "myEvent", data); + }); +}); Http.listen(http, 3000, () => print_endline("listening on *:3000")); diff --git a/example/SharedTypes.re b/example/SharedTypes.re new file mode 100644 index 0000000..dd61612 --- /dev/null +++ b/example/SharedTypes.re @@ -0,0 +1,14 @@ +type dataT = + | Data(string) + | OrOthers; + +type data2T = string; + +// Data sent with event named "message". +type shared = + | Message(dataT) + | MessageOnEnter(data2T); + +// Data sent with event named "login". +type loginT = + | Hi; diff --git a/package-lock.json b/package-lock.json index 58e70d7..d17cbed 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5,12 +5,32 @@ "requires": true, "dependencies": { "accepts": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.3.tgz", - "integrity": "sha1-w8p0NJOGSMPg2cHjKN1otiLChMo=", + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", + "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", "requires": { - "mime-types": "2.1.18", - "negotiator": "0.6.1" + "mime-types": "~2.1.24", + "negotiator": "0.6.2" + }, + "dependencies": { + "mime-db": { + "version": "1.44.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", + "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==" + }, + "mime-types": { + "version": "2.1.27", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", + "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", + "requires": { + "mime-db": "1.44.0" + } + }, + "negotiator": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", + "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==" + } } }, "after": { @@ -25,9 +45,14 @@ "dev": true }, "arraybuffer.slice": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.6.tgz", - "integrity": "sha1-8zshWfBTKj8xB6JywMz70a0peco=" + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz", + "integrity": "sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog==" + }, + "async-limiter": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", + "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==" }, "backo2": { "version": "1.0.2", @@ -40,9 +65,9 @@ "integrity": "sha1-c5JncZI7Whl0etZmqlzUv5xunOg=" }, "base64id": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/base64id/-/base64id-1.0.0.tgz", - "integrity": "sha1-R2iMuZu2gE8OBtPnY7HDLlfY5rY=" + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", + "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==" }, "better-assert": { "version": "1.0.2", @@ -53,26 +78,26 @@ } }, "blob": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/blob/-/blob-0.0.4.tgz", - "integrity": "sha1-vPEwUspURj8w+fx+lbmkdjCpSSE=" + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/blob/-/blob-0.0.5.tgz", + "integrity": "sha512-gaqbzQPqOoamawKg0LGVd7SzLgXS+JH61oWprSLH+P+abTczqJbhTR8CmJ2u9/bUYNmHTGJx/UEmn6doAvvuig==" }, "body-parser": { - "version": "1.18.2", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.2.tgz", - "integrity": "sha1-h2eKGdhLR9hZuDGZvVm84iKxBFQ=", + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", + "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", "dev": true, "requires": { - "bytes": "3.0.0", - "content-type": "1.0.4", + "bytes": "3.1.0", + "content-type": "~1.0.4", "debug": "2.6.9", - "depd": "1.1.2", - "http-errors": "1.6.3", - "iconv-lite": "0.4.19", - "on-finished": "2.3.0", - "qs": "6.5.1", - "raw-body": "2.3.2", - "type-is": "1.6.16" + "depd": "~1.1.2", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "on-finished": "~2.3.0", + "qs": "6.7.0", + "raw-body": "2.4.0", + "type-is": "~1.6.17" }, "dependencies": { "debug": { @@ -93,15 +118,15 @@ } }, "bs-platform": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bs-platform/-/bs-platform-3.0.0.tgz", - "integrity": "sha1-OPIAcw21L96jeBk3a2rD37ICRMA=", + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/bs-platform/-/bs-platform-7.2.2.tgz", + "integrity": "sha512-PWcFfN+jCTtT/rMaHDhKh+W9RUTpaRunmSF9vbLYcrJbpgCNW6aFKAY33u0P3mLxwuhshN3b4FxqGUBPj6exZQ==", "dev": true }, "bytes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", - "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", + "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", "dev": true }, "callsite": { @@ -115,9 +140,9 @@ "integrity": "sha1-AMYIq33Nk4l8AAllGx06jh5zu9E=" }, "component-emitter": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.1.2.tgz", - "integrity": "sha1-KWWU8nU9qmOZbSrwjRWpURbJrsM=" + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", + "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=" }, "component-inherit": { "version": "0.0.3", @@ -125,10 +150,13 @@ "integrity": "sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM=" }, "content-disposition": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", - "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=", - "dev": true + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", + "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", + "dev": true, + "requires": { + "safe-buffer": "5.1.2" + } }, "content-type": { "version": "1.0.4", @@ -148,11 +176,11 @@ "dev": true }, "debug": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.3.3.tgz", - "integrity": "sha1-QMRT5n5uE8kB3ewxeviYbNqe/4w=", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", "requires": { - "ms": "0.7.2" + "ms": "^2.1.1" } }, "depd": { @@ -180,55 +208,56 @@ "dev": true }, "engine.io": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-1.8.5.tgz", - "integrity": "sha512-j1DWIcktw4hRwrv6nWx++5nFH2X64x16MAG2P0Lmi5Dvdfi3I+Jhc7JKJIdAmDJa+5aZ/imHV7dWRPy2Cqjh3A==", + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.4.1.tgz", + "integrity": "sha512-8MfIfF1/IIfxuc2gv5K+XlFZczw/BpTvqBdl0E2fBLkYQp4miv4LuDTVtYt4yMyaIFLEr4vtaSgV4mjvll8Crw==", "requires": { - "accepts": "1.3.3", - "base64id": "1.0.0", + "accepts": "~1.3.4", + "base64id": "2.0.0", "cookie": "0.3.1", - "debug": "2.3.3", - "engine.io-parser": "1.3.2", - "ws": "1.1.5" + "debug": "~4.1.0", + "engine.io-parser": "~2.2.0", + "ws": "^7.1.2" } }, "engine.io-client": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-1.8.5.tgz", - "integrity": "sha512-AYTgHyeVUPitsseqjoedjhYJapNVoSPShbZ+tEUX9/73jgZ/Z3sUlJf9oYgdEBBdVhupUpUqSxH0kBCXlQnmZg==", + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.4.1.tgz", + "integrity": "sha512-RJNmA+A9Js+8Aoq815xpGAsgWH1VoSYM//2VgIiu9lNOaHFfLpTjH4tOzktBpjIs5lvOfiNY1dwf+NuU6D38Mw==", "requires": { "component-emitter": "1.2.1", "component-inherit": "0.0.3", - "debug": "2.3.3", - "engine.io-parser": "1.3.2", + "debug": "~4.1.0", + "engine.io-parser": "~2.2.0", "has-cors": "1.1.0", "indexof": "0.0.1", - "parsejson": "0.0.3", "parseqs": "0.0.5", "parseuri": "0.0.5", - "ws": "1.1.5", - "xmlhttprequest-ssl": "1.5.3", + "ws": "~6.1.0", + "xmlhttprequest-ssl": "~1.5.4", "yeast": "0.1.2" }, "dependencies": { - "component-emitter": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", - "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=" + "ws": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/ws/-/ws-6.1.4.tgz", + "integrity": "sha512-eqZfL+NE/YQc1/ZynhojeV8q+H050oR8AZ2uIev7RU10svA9ZnJUddHcOUZTJLinZ9yEfdA2kSATS2qZK5fhJA==", + "requires": { + "async-limiter": "~1.0.0" + } } } }, "engine.io-parser": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-1.3.2.tgz", - "integrity": "sha1-k3sHnwAH0Ik+xW1GyyILjLQ1Igo=", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.2.0.tgz", + "integrity": "sha512-6I3qD9iUxotsC5HEMuuGsKA0cXerGz+4uGcXQEkfBidgKf0amsjrrtwcbwK/nzpZBxclXlV7gGl9dgWvu4LF6w==", "requires": { "after": "0.8.2", - "arraybuffer.slice": "0.0.6", + "arraybuffer.slice": "~0.0.7", "base64-arraybuffer": "0.1.5", - "blob": "0.0.4", - "has-binary": "0.1.7", - "wtf-8": "1.0.0" + "blob": "0.0.5", + "has-binary2": "~1.0.2" } }, "escape-html": { @@ -244,52 +273,48 @@ "dev": true }, "express": { - "version": "4.16.3", - "resolved": "https://registry.npmjs.org/express/-/express-4.16.3.tgz", - "integrity": "sha1-avilAjUNsyRuzEvs9rWjTSL37VM=", + "version": "4.17.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", + "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", "dev": true, "requires": { - "accepts": "1.3.5", + "accepts": "~1.3.7", "array-flatten": "1.1.1", - "body-parser": "1.18.2", - "content-disposition": "0.5.2", - "content-type": "1.0.4", - "cookie": "0.3.1", + "body-parser": "1.19.0", + "content-disposition": "0.5.3", + "content-type": "~1.0.4", + "cookie": "0.4.0", "cookie-signature": "1.0.6", "debug": "2.6.9", - "depd": "1.1.2", - "encodeurl": "1.0.2", - "escape-html": "1.0.3", - "etag": "1.8.1", - "finalhandler": "1.1.1", + "depd": "~1.1.2", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "~1.1.2", "fresh": "0.5.2", "merge-descriptors": "1.0.1", - "methods": "1.1.2", - "on-finished": "2.3.0", - "parseurl": "1.3.2", + "methods": "~1.1.2", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", "path-to-regexp": "0.1.7", - "proxy-addr": "2.0.3", - "qs": "6.5.1", - "range-parser": "1.2.0", - "safe-buffer": "5.1.1", - "send": "0.16.2", - "serve-static": "1.13.2", - "setprototypeof": "1.1.0", - "statuses": "1.4.0", - "type-is": "1.6.16", + "proxy-addr": "~2.0.5", + "qs": "6.7.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.1.2", + "send": "0.17.1", + "serve-static": "1.14.1", + "setprototypeof": "1.1.1", + "statuses": "~1.5.0", + "type-is": "~1.6.18", "utils-merge": "1.0.1", - "vary": "1.1.2" + "vary": "~1.1.2" }, "dependencies": { - "accepts": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz", - "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=", - "dev": true, - "requires": { - "mime-types": "2.1.18", - "negotiator": "0.6.1" - } + "cookie": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", + "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==", + "dev": true }, "debug": { "version": "2.6.9", @@ -309,18 +334,18 @@ } }, "finalhandler": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz", - "integrity": "sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", + "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", "dev": true, "requires": { "debug": "2.6.9", - "encodeurl": "1.0.2", - "escape-html": "1.0.3", - "on-finished": "2.3.0", - "parseurl": "1.3.2", - "statuses": "1.4.0", - "unpipe": "1.0.0" + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "statuses": "~1.5.0", + "unpipe": "~1.0.0" }, "dependencies": { "debug": { @@ -352,12 +377,12 @@ "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", "dev": true }, - "has-binary": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/has-binary/-/has-binary-0.1.7.tgz", - "integrity": "sha1-aOYesWIQyVRaClzOBqhzkS/h5ow=", + "has-binary2": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-binary2/-/has-binary2-1.0.3.tgz", + "integrity": "sha512-G1LWKhDSvhGeAQ8mPVQlqNcOB2sJdwATtZKl2pDKKHfpf/rYj24lkinxf69blJbnsvtqqNU+L3SL50vzZhXOnw==", "requires": { - "isarray": "0.0.1" + "isarray": "2.0.1" } }, "has-cors": { @@ -366,22 +391,26 @@ "integrity": "sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk=" }, "http-errors": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", - "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", + "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", "dev": true, "requires": { - "depd": "1.1.2", + "depd": "~1.1.2", "inherits": "2.0.3", - "setprototypeof": "1.1.0", - "statuses": "1.4.0" + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" } }, "iconv-lite": { - "version": "0.4.19", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", - "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==", - "dev": true + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } }, "indexof": { "version": "0.0.1", @@ -395,20 +424,15 @@ "dev": true }, "ipaddr.js": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.6.0.tgz", - "integrity": "sha1-4/o1e3c9phnybpXwSdBVxyeW+Gs=", + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", "dev": true }, "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" - }, - "json3": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.2.tgz", - "integrity": "sha1-PAQ0dD35Pi9cQq7nsZvLSDV19OE=" + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", + "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=" }, "media-typer": { "version": "0.3.0", @@ -429,38 +453,30 @@ "dev": true }, "mime": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz", - "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", "dev": true }, "mime-db": { - "version": "1.33.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz", - "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==" + "version": "1.44.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", + "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==", + "dev": true }, "mime-types": { - "version": "2.1.18", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz", - "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", + "version": "2.1.27", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", + "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", + "dev": true, "requires": { - "mime-db": "1.33.0" + "mime-db": "1.44.0" } }, "ms": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz", - "integrity": "sha1-riXPJRKziFodldfwN4aNhDESR2U=" - }, - "negotiator": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", - "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=" - }, - "object-assign": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.0.tgz", - "integrity": "sha1-ejs9DpgGPUP0wD8uiubNUahog6A=" + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "object-component": { "version": "0.0.3", @@ -476,25 +492,12 @@ "ee-first": "1.1.1" } }, - "options": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/options/-/options-0.0.6.tgz", - "integrity": "sha1-7CLTEoBrtT5zF3Pnza788cZDEo8=" - }, - "parsejson": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/parsejson/-/parsejson-0.0.3.tgz", - "integrity": "sha1-q343WfIJ7OmUN5c/fQ8fZK4OZKs=", - "requires": { - "better-assert": "1.0.2" - } - }, "parseqs": { "version": "0.0.5", "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.5.tgz", "integrity": "sha1-1SCKNzjkZ2bikbouoXNoSSGouJ0=", "requires": { - "better-assert": "1.0.2" + "better-assert": "~1.0.0" } }, "parseuri": { @@ -502,13 +505,13 @@ "resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.5.tgz", "integrity": "sha1-gCBKUNTbt3m/3G6+J3jZDkvOMgo=", "requires": { - "better-assert": "1.0.2" + "better-assert": "~1.0.0" } }, "parseurl": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", - "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", "dev": true }, "path-to-regexp": { @@ -518,90 +521,70 @@ "dev": true }, "proxy-addr": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.3.tgz", - "integrity": "sha512-jQTChiCJteusULxjBp8+jftSQE5Obdl3k4cnmLA6WXtK6XFuWRnvVL7aCiBqaLPM8c4ph0S4tKna8XvmIwEnXQ==", + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz", + "integrity": "sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==", "dev": true, "requires": { - "forwarded": "0.1.2", - "ipaddr.js": "1.6.0" + "forwarded": "~0.1.2", + "ipaddr.js": "1.9.1" } }, "qs": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", - "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==", + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", + "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", "dev": true }, "range-parser": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", - "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", "dev": true }, "raw-body": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.2.tgz", - "integrity": "sha1-vNYMd9Prk83gBQKVw/N5OJvIj4k=", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", + "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", "dev": true, "requires": { - "bytes": "3.0.0", - "http-errors": "1.6.2", - "iconv-lite": "0.4.19", + "bytes": "3.1.0", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", "unpipe": "1.0.0" - }, - "dependencies": { - "depd": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", - "integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k=", - "dev": true - }, - "http-errors": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz", - "integrity": "sha1-CgAsyFcHGSp+eUbO7cERVfYOxzY=", - "dev": true, - "requires": { - "depd": "1.1.1", - "inherits": "2.0.3", - "setprototypeof": "1.0.3", - "statuses": "1.4.0" - } - }, - "setprototypeof": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz", - "integrity": "sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ=", - "dev": true - } } }, "safe-buffer": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", - "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==", + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "dev": true }, "send": { - "version": "0.16.2", - "resolved": "https://registry.npmjs.org/send/-/send-0.16.2.tgz", - "integrity": "sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==", + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", + "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", "dev": true, "requires": { "debug": "2.6.9", - "depd": "1.1.2", - "destroy": "1.0.4", - "encodeurl": "1.0.2", - "escape-html": "1.0.3", - "etag": "1.8.1", + "depd": "~1.1.2", + "destroy": "~1.0.4", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", "fresh": "0.5.2", - "http-errors": "1.6.3", - "mime": "1.4.1", - "ms": "2.0.0", - "on-finished": "2.3.0", - "range-parser": "1.2.0", - "statuses": "1.4.0" + "http-errors": "~1.7.2", + "mime": "1.6.0", + "ms": "2.1.1", + "on-finished": "~2.3.0", + "range-parser": "~1.2.1", + "statuses": "~1.5.0" }, "dependencies": { "debug": { @@ -611,112 +594,122 @@ "dev": true, "requires": { "ms": "2.0.0" + }, + "dependencies": { + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } } }, "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", "dev": true } } }, "serve-static": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.2.tgz", - "integrity": "sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", + "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", "dev": true, "requires": { - "encodeurl": "1.0.2", - "escape-html": "1.0.3", - "parseurl": "1.3.2", - "send": "0.16.2" + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.17.1" } }, "setprototypeof": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", - "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==", "dev": true }, "socket.io": { - "version": "1.7.4", - "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-1.7.4.tgz", - "integrity": "sha1-L37O3DORvy1cc+KR/iM+bjTU3QA=", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.3.0.tgz", + "integrity": "sha512-2A892lrj0GcgR/9Qk81EaY2gYhCBxurV0PfmmESO6p27QPrUK1J3zdns+5QPqvUYK2q657nSj0guoIil9+7eFg==", "requires": { - "debug": "2.3.3", - "engine.io": "1.8.5", - "has-binary": "0.1.7", - "object-assign": "4.1.0", - "socket.io-adapter": "0.5.0", - "socket.io-client": "1.7.4", - "socket.io-parser": "2.3.1" + "debug": "~4.1.0", + "engine.io": "~3.4.0", + "has-binary2": "~1.0.2", + "socket.io-adapter": "~1.1.0", + "socket.io-client": "2.3.0", + "socket.io-parser": "~3.4.0" } }, "socket.io-adapter": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-0.5.0.tgz", - "integrity": "sha1-y21LuL7IHhB4uZZ3+c7QBGBmu4s=", - "requires": { - "debug": "2.3.3", - "socket.io-parser": "2.3.1" - } + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-1.1.2.tgz", + "integrity": "sha512-WzZRUj1kUjrTIrUKpZLEzFZ1OLj5FwLlAFQs9kuZJzJi5DKdU7FsWc36SNmA8iDOtwBQyT8FkrriRM8vXLYz8g==" }, "socket.io-client": { - "version": "1.7.4", - "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-1.7.4.tgz", - "integrity": "sha1-7J+CA1btme9tNX8HVtZIcXvdQoE=", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.3.0.tgz", + "integrity": "sha512-cEQQf24gET3rfhxZ2jJ5xzAOo/xhZwK+mOqtGRg5IowZsMgwvHwnf/mCRapAAkadhM26y+iydgwsXGObBB5ZdA==", "requires": { "backo2": "1.0.2", + "base64-arraybuffer": "0.1.5", "component-bind": "1.0.0", "component-emitter": "1.2.1", - "debug": "2.3.3", - "engine.io-client": "1.8.5", - "has-binary": "0.1.7", + "debug": "~4.1.0", + "engine.io-client": "~3.4.0", + "has-binary2": "~1.0.2", + "has-cors": "1.1.0", "indexof": "0.0.1", "object-component": "0.0.3", + "parseqs": "0.0.5", "parseuri": "0.0.5", - "socket.io-parser": "2.3.1", + "socket.io-parser": "~3.3.0", "to-array": "0.1.4" }, "dependencies": { - "component-emitter": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", - "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=" + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "socket.io-parser": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.3.0.tgz", + "integrity": "sha512-hczmV6bDgdaEbVqhAeVMM/jfUfzuEZHsQg6eOmLgJht6G3mPKMxYm75w2+qhAQZ+4X+1+ATZ+QFKeOZD5riHng==", + "requires": { + "component-emitter": "1.2.1", + "debug": "~3.1.0", + "isarray": "2.0.1" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "requires": { + "ms": "2.0.0" + } + } + } } } }, "socket.io-parser": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-2.3.1.tgz", - "integrity": "sha1-3VMgJRA85Clpcya+/WQAX8/ltKA=", + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.4.0.tgz", + "integrity": "sha512-/G/VOI+3DBp0+DJKW4KesGnQkQPFmUCbA/oO2QGT6CWxU7hLGWqU3tyuzeSK/dqcyeHsQg1vTe9jiZI8GU9SCQ==", "requires": { - "component-emitter": "1.1.2", - "debug": "2.2.0", - "isarray": "0.0.1", - "json3": "3.3.2" - }, - "dependencies": { - "debug": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", - "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", - "requires": { - "ms": "0.7.1" - } - }, - "ms": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", - "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=" - } + "component-emitter": "1.2.1", + "debug": "~4.1.0", + "isarray": "2.0.1" } }, "statuses": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", - "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", "dev": true }, "to-array": { @@ -724,21 +717,22 @@ "resolved": "https://registry.npmjs.org/to-array/-/to-array-0.1.4.tgz", "integrity": "sha1-F+bBH3PdTz10zaek/zI46a2b+JA=" }, + "toidentifier": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", + "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", + "dev": true + }, "type-is": { - "version": "1.6.16", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz", - "integrity": "sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q==", + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", "dev": true, "requires": { "media-typer": "0.3.0", - "mime-types": "2.1.18" + "mime-types": "~2.1.24" } }, - "ultron": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.0.2.tgz", - "integrity": "sha1-rOEWq1V80Zc4ak6I9GhTeMiy5Po=" - }, "unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", @@ -758,23 +752,14 @@ "dev": true }, "ws": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/ws/-/ws-1.1.5.tgz", - "integrity": "sha512-o3KqipXNUdS7wpQzBHSe180lBGO60SoK0yVo3CYJgb2MkobuWuBX6dhkYP5ORCLd55y+SaflMOV5fqAB53ux4w==", - "requires": { - "options": "0.0.6", - "ultron": "1.0.2" - } - }, - "wtf-8": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wtf-8/-/wtf-8-1.0.0.tgz", - "integrity": "sha1-OS2LotDxw00e4tYw8V0O+2jhBIo=" + "version": "7.2.5", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.2.5.tgz", + "integrity": "sha512-C34cIU4+DB2vMyAbmEKossWq2ZQDr6QEyuuCzWrM9zfw1sGc0mYiJ0UnG9zzNykt49C2Fi34hvr2vssFQRS6EA==" }, "xmlhttprequest-ssl": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.3.tgz", - "integrity": "sha1-GFqIjATspGw+QHDZn3tJ3jUomS0=" + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz", + "integrity": "sha1-wodrBhaKrcQOV9l+gRkayPQ5iz4=" }, "yeast": { "version": "0.1.2", diff --git a/package.json b/package.json index ae2c385..1b96b61 100644 --- a/package.json +++ b/package.json @@ -9,12 +9,12 @@ "test": "exit 0", "run": "node example/ExampleServer.bs.js" }, - "dependencies": { - "socket.io": "^1.4.8" - }, "devDependencies": { - "express": "^4.14.0", - "bs-platform": "^3.0.0" + "bs-platform": "^7.2.2", + "express": "^4.17.1" }, - "author": "Benjamin San Souci " + "author": "Benjamin San Souci ", + "dependencies": { + "socket.io": "^2.3.0" + } } diff --git a/src/BsSocket.re b/src/BsSocket.re new file mode 100644 index 0000000..3213f11 --- /dev/null +++ b/src/BsSocket.re @@ -0,0 +1,4 @@ +module Client = Client; +module Server = Server; +module Namespace = Namespace; +module Socket = Socket; diff --git a/src/Client.re b/src/Client.re index 359d4ec..7b37867 100644 --- a/src/Client.re +++ b/src/Client.re @@ -1,11 +1,5 @@ -module Make = (Messages: Messages.S) => { - type t; - [@bs.new] external create : unit => t = "io"; - [@bs.new] external createWithUrl : string => t = "io"; - [@bs.send] external _emit : (t, string, 'a) => unit = "emit"; - let emit = (socket, obj: Messages.clientToServer) => - _emit(socket, "message", Json.toValidJson(obj)); - [@bs.send] external _on : (t, string, 'a => unit) => unit = "on"; - let on = (socket, func: Messages.serverToClient => unit) => - _on(socket, "message", obj => func(Json.fromValidJson(obj))); -}; +type t = Socket.socketT; + +/* Socket.io docs: https://socket.io/docs/client-api/#io-url-options */ +[@bs.new] external create: unit => t = "io"; +[@bs.new] external createWithUrl: string => t = "io"; diff --git a/src/Client.rei b/src/Client.rei deleted file mode 100644 index afa8ce5..0000000 --- a/src/Client.rei +++ /dev/null @@ -1,18 +0,0 @@ -module Make: - (Messages: Messages.S) => - { - type t; - - /*** Socket.io docs: https://socket.io/docs/client-api/#io-url-options */ - let create: unit => t; - - let createWithUrl: string => t; - - /*** Same as the server-side `emit`, doesn't take a message name. - The recommended payload type to send is a variant wSocket.io docs: https://socket.io/docs/client-api/#socket-emit-eventname-args-ack */ - let emit: (t, Messages.clientToServer) => unit; - - /*** Same ideas as explained above. - Socket.io docs: https://socket.io/docs/client-api/#socket-on-eventname-callback */ - let on: (t, Messages.serverToClient => unit) => unit; - }; diff --git a/src/Messages.re b/src/Messages.re deleted file mode 100644 index 6b6230d..0000000 --- a/src/Messages.re +++ /dev/null @@ -1,41 +0,0 @@ -/* The user of this library is intended to define a Messages module of - type S, which defines the type of the messages that the client can - send to the server, and the type of the messages that the server can - send to the client. - - For example, Messages could look something like: - - module Messages = { - type username = string; - - type clientToServer = - | LoginRequest(username); - - type loginResponse = { - username, - successful: bool, - }; - - type serverToClient = - | LoginResponse(loginResponse) - }; - - It's fairly common for the types of the messages to be the same, - regardless of whether they're from server to client or vice versa. - If that's the case, you can do something like: - - module Messages = { - type t = | ... | ...; - type clientToServer = t; - type serverToClient = t; - }; - - - The Messages module is the what you pass into the Server, Client, - and Namespace functors to instantiate those modules with your - particular message types in mind. For example: - - module MyServer = Server.Make(Messages) - let io = MyServer.create(); - */ -module type S = {type clientToServer; type serverToClient;}; diff --git a/src/Namespace.re b/src/Namespace.re index e81c44d..e87e693 100644 --- a/src/Namespace.re +++ b/src/Namespace.re @@ -1,43 +1,38 @@ -module Make = (Messages: Messages.S) => { - type t; - - /*** Getters */ - [@bs.get] external getName : t => string = "name"; - [@bs.get] external getAdapter : t => 'a = "adapter"; - /* Returns a JS object with socket IDs as keys. */ - [@bs.get] external getConnected : t => Js.t('a) = "connected"; - [@bs.send] - external clients : (t, ('a, list(string)) => unit) => unit = "clients"; - - /*** */ - [@bs.send] - external use : (t, (Server.socketT, unit => unit) => unit) => unit = "use"; - - /*** */ - [@bs.send] external default : Server.serverT => t = "sockets"; - - /*** This is "of" in socket.io. */ - [@bs.send] external of_ : (Server.serverT, string) => t = "of"; - - /*** This is "to" in socket.io or the "in" (they're synonyms apparently) */ - [@bs.send] external to_ : (t, string) => t = "to"; - - /*** */ - [@bs.send] external _emit : (t, string, 'a) => unit = "emit"; - let emit = (server: t, obj: Messages.serverToClient) : unit => - _emit(server, "message", Json.toValidJson(obj)); - - /*** Volatile */ - type volatileT; - [@bs.get] external getVolatile : t => volatileT = "volatile"; - [@bs.send] external _volatileEmit : (volatileT, string, 'a) => unit = "emit"; - let volatileEmit = (server: t, obj: Messages.serverToClient) : unit => - _volatileEmit(getVolatile(server), "message", Json.toValidJson(obj)); - - /*** Local */ - type localT; - [@bs.get] external getLocal : t => localT = "local"; - [@bs.send] external _localEmit : (localT, string, 'a) => unit = "emit"; - let localEmit = (server: t, obj: Messages.serverToClient) : unit => - _localEmit(getLocal(server), "message", Json.toValidJson(obj)); -}; +type t; + +/* Socket.io docs: https://socket.io/docs/server-api/#namespace-name */ +[@bs.get] external getName: t => string = "name"; + +/* Socket.io docs: https://socket.io/docs/server-api/#namespace-adapter */ +[@bs.get] external getAdapter: t => 'a = "adapter"; + +/* Socket.io docs: https://socket.io/docs/server-api/#namespace-connected */ +[@bs.get] external getConnected: t => Js.t('a) = "connected"; + +/* Socket.io docs: https://socket.io/docs/server-api/#namespace-clients-callback */ +[@bs.send] external clients: (t, ('a, list(string)) => unit) => unit = "clients"; + +/* Socket.io docs: https://socket.io/docs/server-api/#namespace-use-fn */ +[@bs.send] external use: (t, (Socket.socketT, unit => unit) => unit) => unit = "use"; + +/* Socket.io docs: https://socket.io/docs/server-api/#server-sockets */ +[@bs.send] external default: Server.serverT => t = "sockets"; + +/* See example in Socket.io docs: https://socket.io/docs/server-api/#namespace-emit-eventname-args */ +[@bs.send] external of_: (Server.serverT, string) => t = "of"; + +/* Socket.io docs: https://socket.io/docs/server-api/#namespace-to-room */ +[@bs.send] external to_: (t, string) => t = "to"; + +/* Socket.io docs: https://socket.io/docs/server-api/#namespace-emit-eventname-args */ +[@bs.send] external emit: (t, string, 'a) => unit = "emit"; + +/* Socket.io docs: https://socket.io/docs/server-api/#flag-volatile */ +type volatileT; +[@bs.get] external getVolatile: t => volatileT = "volatile"; +[@bs.send] external emitVolatile: (volatileT, string, 'a) => unit = "emit"; + +/* Socket.io docs: https://socket.io/docs/server-api/#flag-local */ +type localT; +[@bs.get] external getLocal: t => localT = "local"; +[@bs.send] external emitLocal: (localT, string, 'a) => unit = "emit"; diff --git a/src/Namespace.rei b/src/Namespace.rei deleted file mode 100644 index 8d0cc01..0000000 --- a/src/Namespace.rei +++ /dev/null @@ -1,42 +0,0 @@ -module Make: - (Messages: Messages.S) => - { - type t; - - /*** Socket.io docs: https://socket.io/docs/server-api/#namespace-name */ - let getName: t => string; - - /*** Socket.io docs: https://socket.io/docs/server-api/#namespace-adapter */ - let getAdapter: t => 'a; - - /*** Socket.io docs: https://socket.io/docs/server-api/#namespace-connected */ - let getConnected: t => Js.t('a); - - /*** Socket.io docs: https://socket.io/docs/server-api/#namespace-clients-callback */ - let clients: (t, ('a, list(string)) => unit) => unit; - - /*** Socket.io docs: https://socket.io/docs/server-api/#namespace-use-fn */ - let use: (t, (Server.socketT, unit => unit) => unit) => unit; - - /*** Socket.io docs: https://socket.io/docs/server-api/#server-sockets */ - let default: Server.serverT => t; - - /*** See example in Socket.io docs: https://socket.io/docs/server-api/#namespace-emit-eventname-args */ - let of_: (Server.serverT, string) => t; - - /*** Socket.io docs: https://socket.io/docs/server-api/#namespace-to-room */ - let to_: (t, string) => t; - - /*** Socket.io docs: https://socket.io/docs/server-api/#namespace-emit-eventname-args */ - let emit: (t, Messages.serverToClient) => unit; - - /*** Socket.io docs: https://socket.io/docs/server-api/#flag-volatile */ - type volatileT; - let getVolatile: t => volatileT; - let volatileEmit: (t, Messages.serverToClient) => unit; - - /*** Socket.io docs: https://socket.io/docs/server-api/#flag-local */ - type localT; - let getLocal: t => localT; - let localEmit: (t, Messages.serverToClient) => unit; - }; diff --git a/src/Json.re b/src/Serializer.re similarity index 58% rename from src/Json.re rename to src/Serializer.re index c7092d8..8b85ea0 100644 --- a/src/Json.re +++ b/src/Serializer.re @@ -1,13 +1,14 @@ /* @Performance - Special serialization logic because we cannot serialize variants using Json.stringify. - The reason for that is that Variants are represented as arrays under the hood with a property .tag - representing the tag kind. That property isn't one that's normally on array so Json.stringify won't serialize it. - We have to resort to using our own encoding. - Ben - July 24 2017 - */ -let toValidJson = [%raw - (o) => + Special serialization logic because we cannot serialize variants using Json.stringify. + The reason for that is that Variants are represented as arrays under the hood with a property .tag + representing the tag kind. That property isn't one that's normally on array so Json.stringify won't serialize it. + We have to resort to using our own encoding. + Ben - July 24 2017 + */ + +let toValidJson: (. 'a) => string = [%bs.raw {| +function toValidJson(o) { switch (typeof o){ case "boolean": case "number": @@ -21,12 +22,15 @@ let toValidJson = [%raw } throw new Error("Cannot serialize unidentified object [" + o + "].") } +} |} ]; -let fromValidJson = [%raw - (o) => +let toValidJson = a => toValidJson(. Obj.magic(a)); + +let fromValidJson: (. string) => 'a = [%raw {| +function fromValidJson(o) { switch (typeof o){ case "boolean": case "number": @@ -47,5 +51,8 @@ let fromValidJson = [%raw } throw new Error("Cannot deserialize unidentified object [" + o + "].") } +} |} ]; + +let fromValidJson = a => Obj.magic(fromValidJson(. a)); diff --git a/src/Server.re b/src/Server.re index 2ebc83e..04598b5 100644 --- a/src/Server.re +++ b/src/Server.re @@ -1,135 +1,72 @@ -type serverT; - -type socketT; - -type room = string; - -module Make = (Messages: Messages.S) => { - [@bs.module] external create : unit => serverT = "socket.io"; - [@bs.module] external createWithHttp : 'a => serverT = "socket.io"; - - /*** - * makeOptions is a simple way to get around the fact that ocaml won't allow you to declare - * partially defined records (and row polymorphism + ad hoc polymorphism is tricky in ocaml) - * This allows you to create a JS object with any of the defined properties, allowing to omit - * any number of them. - */ - type createOptionsT; - [@bs.obj] - external makeOptions : - ( - ~pingTimeout: int=?, - ~pingInterval: int=?, - ~maxHttpBufferSize: int=?, - ~transports: list(string)=?, - ~allowUpgrades: bool=?, - ~perMessageDeflate: int=?, - ~httpCompression: int=?, - ~cookie: string=?, - ~cookiePath: string=?, - ~wsEngine: string=?, - unit - ) => - createOptionsT = - ""; - [@bs.module] - external createWithOptions : createOptionsT => serverT = "socket.io"; - [@bs.module] - external createWithHttpAndOption : ('a, createOptionsT) => serverT = - "socket.io"; - [@bs.module] - external createWithPort : (int, createOptionsT) => serverT = "socket.io"; - - /*** */ - [@bs.send] external serveClient : (serverT, bool) => serverT = "serveClient"; - - /*** */ - [@bs.send] external path : (serverT, string) => serverT = "path"; - - /*** - * This kind of function is annoying because it relies on the type of another module which you might not - * care about (here https://github.com/socketio/socket.io-adapter), and which is defined by someone else. - * The only idea I have to typecheck this is to make sure this type is a module type representing an - * interface, and have the external package also use that module signature. The problem is to keep them in - * sync. No clue how to do that. - */ - [@bs.send] external adapter : (serverT, 'a) => serverT = "adapter"; - - /*** */ - [@bs.send] external origins : (serverT, string) => serverT = "origins"; - [@bs.send] - external originsWithFunc : (serverT, ('a, bool) => unit) => serverT = - "origins"; - - /*** */ - [@bs.send] external close : serverT => unit = "close"; - - /*** This is the same as "server.listen". */ - [@bs.send] - external attach : (serverT, 'a, createOptionsT) => serverT = "attach"; - [@bs.send] - external attachWithPort : (serverT, int, createOptionsT) => serverT = - "attach"; - - /*** */ - [@bs.send] external _emit : ('a, string, 'b) => unit = "emit"; - - /*** - * socketT is the representation of a connection received by the server. - * It's a pipeline through which one can emit and listen to events. - */ - module Socket = { - [@bs.get] external getId : socketT => room = "id"; - [@bs.get] external getRooms : socketT => Js.t('a) = "rooms"; - [@bs.get] external getHandshake : socketT => Js.t('a) = "handshake"; - /* Here 'a means that you can send anything you want, and it'll depend on - Bucklescript */ - [@bs.send] - external _on : (socketT, string, Messages.clientToServer => unit) => unit = - "on"; - let on = (socket, func) => - _on(socket, "message", obj => func(Json.fromValidJson(obj))); - - /*** */ - let emit = (socket: socketT, obj: Messages.serverToClient) => - _emit(socket, "message", Json.toValidJson(obj)); - - /*** */ - type broadcastT; - [@bs.get] - external _unsafeGetBroadcast : socketT => broadcastT = "broadcast"; - let broadcast = (socket, data: Messages.serverToClient) => - _emit(_unsafeGetBroadcast(socket), "message", Json.toValidJson(data)); - - /*** */ - [@bs.send] external join : (socketT, string) => socketT = "join"; - [@bs.send] external leave : (socketT, string) => socketT = "leave"; - [@bs.send] external to_ : (socketT, string) => socketT = "to"; - [@bs.send] external compress : (socketT, bool) => socketT = "compress"; - [@bs.send] external disconnect : (socketT, bool) => socketT = "disconnect"; - [@bs.send] - external use : (socketT, ('a, ~next: unit => unit) => unit) => unit = - "use"; - - /*** */ - [@bs.send] - external _once : (socketT, string, Messages.serverToClient => unit) => unit = - "once"; - let once = (socket, func) => - _once(socket, "message", obj => func(Json.fromValidJson(obj))); - - /*** Volatile */ - type volatileT; - [@bs.get] external getVolatile : socketT => volatileT = "volatile"; - [@bs.send] - external _volatileEmit : (volatileT, string, 'a) => unit = "emit"; - let volatileEmit = (server: socketT, obj: Messages.serverToClient) : unit => - _volatileEmit(getVolatile(server), "message", Json.toValidJson(obj)); - let onDisconnect = (socket, cb) => - _on(socket, "disconnect", (_) => cb()); - }; - [@bs.send] - external _unsafeOnConnect : (serverT, string, socketT => unit) => unit = - "on"; - let onConnect = (io, cb) => _unsafeOnConnect(io, "connection", cb); +type serverT = Socket.socketT; + +/* Socket.io docs: https://socket.io/docs/server-api/#server */ +[@bs.module] external create: unit => serverT = "socket.io"; +/* These functions takes an instance of `http` from NodeJS stdlib, which you can get by simply + doing `require('http')`. + + Socket.io docs: https://socket.io/docs/server-api/#server */ +[@bs.module] external createWithHttp: 'a => serverT = "socket.io"; + +/* + * makeOptions is a simple way to get around the fact that ocaml won't allow you to declare + * partially defined records (and row polymorphism + ad hoc polymorphism is tricky in ocaml) + * This allows you to create a JS object with any of the defined properties, allowing to omit + * any number of them. + */ +type optionsT; +[@bs.obj] +external makeOptions: + ( + ~pingTimeout: int=?, + ~pingInterval: int=?, + ~maxHttpBufferSize: int=?, + ~transports: list(string)=?, + ~allowUpgrades: bool=?, + ~perMessageDeflate: int=?, + ~httpCompression: int=?, + ~cookie: string=?, + ~cookiePath: string=?, + ~wsEngine: string=?, + unit + ) => + optionsT; + +[@bs.module] external createWithHttpAndOption: ('a, optionsT) => serverT = "socket.io"; +[@bs.module] external createWithOptions: optionsT => serverT = "socket.io"; +[@bs.module] external createWithPort: (int, optionsT) => serverT = "socket.io"; + +/* Socket.io docs: https://socket.io/docs/server-api/#server-serveclient-value */ +[@bs.send] external serveClient: (serverT, bool) => serverT = "serveClient"; + +/* Socket.io docs: https://socket.io/docs/server-api/#server-path-value */ +[@bs.send] external path: (serverT, string) => serverT = "path"; + +/* Socket.io docs: https://socket.io/docs/server-api/#server-adapter-value */ +[@bs.send] external adapter: (serverT, 'a) => serverT = "adapter"; + +/* Socket.io docs: https://socket.io/docs/server-api/#server-origins-value */ +[@bs.send] external origins: (serverT, string) => serverT = "origins"; + +/* Socket.io docs: https://socket.io/docs/server-api/#server-origins-fn */ +[@bs.send] external originsWithFunc: (serverT, ('a, bool) => unit) => serverT = "origins"; + +/* Socket.io docs: https://socket.io/docs/server-api/#server-path-value */ +[@bs.send] external close: serverT => unit = "close"; + +/* Socket.io docs: https://socket.io/docs/server-api/#server-attach-httpserver-options */ +[@bs.send] external attach: (serverT, 'a, optionsT) => serverT = "attach"; + +/* Socket.io docs: https://socket.io/docs/server-api/#server-attach-port-options */ +[@bs.send] external attachWithPort: (serverT, int, optionsT) => serverT = "attach"; + +/* Socket.io docs: https://socket.io/docs/server-api/#Event-‘connection’ */ +[@bs.send] +external onConnect: (serverT, [@bs.as "connection"] _, Socket.socketT => unit) => unit = "on"; + +/* Socket.io docs: https://socket.io/docs/server-api/#Flag-‘broadcast’ */ +[@bs.send] [@bs.scope "broadcast"] +external emitBroadcast: (Socket.socketT, string, 'a) => unit = "emit"; +let emitBroadcast = (socket, message, data) => { + emitBroadcast(socket, message, Serializer.toValidJson(data)); }; diff --git a/src/Server.rei b/src/Server.rei deleted file mode 100644 index 8ed7afd..0000000 --- a/src/Server.rei +++ /dev/null @@ -1,125 +0,0 @@ -type serverT; - -type socketT; - -type room = string; - -/* This is a really thin wrapper around socket.io. I recommend checking their docs for explanation - of how this works. */ -module Make: - (Messages: Messages.S) => - { - - /*** These functions takes an instance of `http` from NodeJS stdlib, which you can get by simply - doing `require('http')`. - - Socket.io docs: https://socket.io/docs/server-api/#server */ - let createWithHttp: 'httpServer => serverT; - type createOptionsT; - let makeOptions: - ( - ~pingTimeout: int=?, - ~pingInterval: int=?, - ~maxHttpBufferSize: int=?, - ~transports: list(string)=?, - ~allowUpgrades: bool=?, - ~perMessageDeflate: int=?, - ~httpCompression: int=?, - ~cookie: string=?, - ~cookiePath: string=?, - ~wsEngine: string=?, - unit - ) => - createOptionsT; - let createWithHttpAndOption: ('httpServer, createOptionsT) => serverT; - - /*** Socket.io docs: https://socket.io/docs/server-api/#server */ - let create: unit => serverT; - let createWithOptions: createOptionsT => serverT; - let createWithPort: (int, createOptionsT) => serverT; - - /*** Socket.io docs: https://socket.io/docs/server-api/#server-serveclient-value */ - let serveClient: (serverT, bool) => serverT; - - /*** Socket.io docs: https://socket.io/docs/server-api/#server-path-value */ - let path: (serverT, string) => serverT; - - /*** Socket.io docs: https://socket.io/docs/server-api/#server-adapter-value */ - let adapter: (serverT, 'a) => serverT; - - /*** Socket.io docs: https://socket.io/docs/server-api/#server-origins-value */ - let origins: (serverT, string) => serverT; - - /*** Socket.io docs: https://socket.io/docs/server-api/#server-origins-fn */ - let originsWithFunc: (serverT, ('a, bool) => unit) => serverT; - - /*** Socket.io docs: https://socket.io/docs/server-api/#server-path-value */ - let close: serverT => unit; - - /*** Socket.io docs: https://socket.io/docs/server-api/#server-attach-httpserver-options */ - let attach: (serverT, 'a, createOptionsT) => serverT; - - /*** Socket.io docs: https://socket.io/docs/server-api/#server-attach-port-options */ - let attachWithPort: (serverT, int, createOptionsT) => serverT; - - /*** Socket.io docs: https://socket.io/docs/server-api/#socket */ - module Socket: { - - /*** Socket.io docs: https://socket.io/docs/server-api/#socket-id - A socket's unique id can be thought of as a room that has only that socket. */ - let getId: socketT => room; - - /*** Socket.io docs: https://socket.io/docs/server-api/#socket-rooms */ - let getRooms: socketT => Js.t(room); - - /*** Socket.io docs: https://socket.io/docs/server-api/#socket-handshake */ - let getHandshake: socketT => Js.t('a); - - /*** Small difference here between socket.io and bs-socket. You don't need to pass a string - for the event name, it's better to simply use a variant as the representation of the event - type and payload. - - Socket.io docs: https://socket.io/docs/server-api/#socket-on-eventname-callback */ - let on: (socketT, Messages.clientToServer => unit) => unit; - - /*** Same difference as stated above. - Socket.io docs: https://socket.io/docs/server-api/#socket-emit-eventname-args-ack */ - let emit: (socketT, Messages.serverToClient) => unit; - - /*** Socket.io docs: https://socket.io/docs/server-api/#flag-broadcast */ - type broadcastT; - let broadcast: (socketT, Messages.serverToClient) => unit; - - /*** Socket.io docs: https://socket.io/docs/server-api/#socket-join-room-callback */ - let join: (socketT, room) => socketT; - - /*** Socket.io docs: https://socket.io/docs/server-api/#socket-leave-room-callback */ - let leave: (socketT, room) => socketT; - - /*** Socket.io docs: https://socket.io/docs/server-api/#socket-to-room */ - let to_: (socketT, room) => socketT; - - /*** Socket.io docs: https://socket.io/docs/server-api/#socket-compress-value */ - let compress: (socketT, bool) => socketT; - - /*** Socket.io docs: https://socket.io/docs/server-api/#socket-disconnect-close */ - let disconnect: (socketT, bool) => socketT; - - /*** Socket.io docs: https://socket.io/docs/server-api/#socket-use-fn */ - let use: (socketT, ('packet, ~next: unit => unit) => unit) => unit; - - /*** Socket.io docs: https://socket.io/docs/server-api/#socket-once-eventname-listener */ - let once: (socketT, 'a => unit) => unit; - - /*** Socket.io docs: https://socket.io/docs/server-api/#flag-volatile */ - type volatileT; - let getVolatile: socketT => volatileT; - let volatileEmit: (socketT, Messages.serverToClient) => unit; - - /*** Special function listening for the message 'disconnect'. Same behavior as `on`. */ - let onDisconnect: (socketT, unit => unit) => unit; - }; - - /*** Special function listening for the message 'connection'. Same behavior as `on`. */ - let onConnect: (serverT, socketT => unit) => unit; - }; diff --git a/src/Socket.re b/src/Socket.re new file mode 100644 index 0000000..0e63df2 --- /dev/null +++ b/src/Socket.re @@ -0,0 +1,70 @@ +/* Socket.io docs: https://socket.io/docs/server-api/#socket */ +type broadcastT; +type socketT; + +/* Small difference here between socket.io and bs-socket. You don't need to pass a string + for the event name, it's better to simply use a variant as the representation of the event + type and payload. + + Socket.io docs: https://socket.io/docs/server-api/#socket-on-eventname-callback */ +[@bs.send] external on: (socketT, string, 'data => unit) => unit = "on"; +let on = (socket, message, cb) => { + on(socket, message, data => cb(. Serializer.fromValidJson(data))); +}; + +/* Special function listening for the message 'disconnect'. Same behavior as `on`. */ +[@bs.send] +external onDisconnect: (socketT, [@bs.as "disconnect"] _, string => unit) => unit = "on"; + +/* Special function listening for the message 'connection'. Same behavior as `on`. */ +[@bs.send] external onConnect: (socketT, [@bs.as "connection"] _, unit => unit) => unit = "on"; + +/* Same difference as stated above. + Socket.io docs: https://socket.io/docs/server-api/#socket-emit-eventname-args-ack */ +[@bs.send] external emit: (socketT, string, 'data) => unit = "emit"; +let emit = (socket, message, data) => { + emit(socket, message, Serializer.toValidJson(data)); +}; + +/* Socket.io docs: https://socket.io/docs/server-api/#socket-compress-value */ +[@bs.send] external compress: (socketT, bool) => socketT = "compress"; + +/* Socket.io docs: https://socket.io/docs/server-api/#socket-disconnect-close */ +[@bs.send] external disconnect: (socketT, bool) => socketT = "disconnect"; + +/* Socket.io docs: https://socket.io/docs/server-api/#socket-use-fn */ +[@bs.send] external use: (socketT, ('a, ~next: unit => unit) => unit) => unit = "use"; + +/* Socket.io docs: https://socket.io/docs/server-api/#socket-once-eventname-listener */ +[@bs.send] external once: (socketT, string, 'a => unit) => unit = "once"; +let once = (socket, message, cb) => { + once(socket, message, data => cb(. Serializer.fromValidJson(data))); +}; + +/* Socket.io docs: https://socket.io/docs/server-api/#flag-volatile */ +type volatileT; +[@bs.get] external getVolatile: socketT => volatileT = "volatile"; +[@bs.send] external emitVolatile: (volatileT, string, string) => unit = "emit"; +let emitVolatile = (socket, message, data) => { + emitVolatile(socket, message, Serializer.toValidJson(data)); +}; + +type room = string; +/* Socket.io docs: https://socket.io/docs/server-api/#socket-id + A socket's unique id can be thought of as a room that has only that socket. */ +[@bs.get] external getId: socketT => room = "id"; + +/* Socket.io docs: https://socket.io/docs/server-api/#socket-rooms */ +[@bs.get] external getRooms: socketT => Js.t('a) = "rooms"; + +/* Socket.io docs: https://socket.io/docs/server-api/#socket-handshake */ +[@bs.get] external getHandshake: socketT => Js.t('a) = "handshake"; + +/* Socket.io docs: https://socket.io/docs/server-api/#socket-join-room-callback */ +[@bs.send] external join: (socketT, room) => socketT = "join"; + +/* Socket.io docs: https://socket.io/docs/server-api/#socket-leave-room-callback */ +[@bs.send] external leave: (socketT, room) => socketT = "leave"; + +/* Socket.io docs: https://socket.io/docs/server-api/#socket-to-room */ +[@bs.send] external to_: (socketT, room) => socketT = "to";