diff --git a/javascript/stimulus-websocket/index.js b/javascript/stimulus-websocket/index.js index b8f8a76..f7d0af1 100644 --- a/javascript/stimulus-websocket/index.js +++ b/javascript/stimulus-websocket/index.js @@ -1,30 +1,7 @@ +import StimulusReflex from "stimulus_reflex" import ReconnectingWebSocket from "reconnecting-websocket" import CableReady from "cable_ready" -// read up on the default options that actioncable has for websockets. - -const options = { - maxRetries: 3, - debug: true -} - -function createWebSocketURL(url) { - if (typeof url === "function") { - url = url() - } - - if (url && !/^wss?:/i.test(url)) { - const a = document.createElement("a") - a.href = url - // Fix populating Location properties in IE. Otherwise, protocol will be blank. - a.href = a.href - a.protocol = a.protocol.replace("http", "ws") - return a.href - } else { - return url - } -} - const extend = function(object, properties) { if (properties != null) { for (let key in properties) { @@ -80,47 +57,83 @@ class Subscriptions { } } -export default class WebsocketConsumer { - constructor(url) { - this._url = url - this.subscriptions = new Subscriptions(this) - - this.connection = new ReconnectingWebSocket(url, [], options) - this.connection.isOpen = function open() { - return this.readyState === ReconnectingWebSocket.OPEN; - } - - this.connection.addEventListener("message", (event) => { - let data = JSON.parse(event.data) - if (!data.cableReady) return - if (!data.operations.morph || !data.operations.morph.length) return - const urls = Array.from( - new Set(data.operations.morph.map(m => m.stimulusReflex.url)) - ) - if (urls.length !== 1 || urls[0] !== (location.href)) return - CableReady.perform(data.operations) - }) - - this.connection.addEventListener("message", (event) => { - let data = JSON.parse(event.data) - if (data.meta_type !== 'cookie') return - document.cookie = `${data.key}=${data.value||""}; max-age=${data.max_age}; path=/`; - }) - } - get url() { - return createWebSocketURL(this._url) - } +class Consumer { + constructor(url, options) { + this.connection = new ReconnectingWebSocket(url, [], options || {}) + this.subscriptions = new Subscriptions(this) + } - send(data) { - return this.connection.send(JSON.stringify(data)) - } + send(data) { + this.connection.send(data) + } +} - connect() { - return this.connection.open() - } +const getConsumer = (url) => { + // read up on the default options that actioncable has for websockets. + let options = { + maxRetries: 3, + debug: true + } - disconnect() { - return this.connection.close() - } + return new Consumer(url, options) +} + +const AbstractConsumerAdapter = StimulusReflex.getAbstractClass() + +class WebsocketConsumer extends AbstractConsumerAdapter{ + constructor(consumer) { + super(consumer) + + this.consumer.connection.addEventListener("message", (event) => { + let data = JSON.parse(event.data) + if (!data.cableReady) return + if (!data.operations.morph || !data.operations.morph.length) return + + const urls = Array.from( + new Set(data.operations.morph.map(m => m.stimulusReflex.url)) + ) + + if (urls.length !== 1 || urls[0] !== (location.href)) return + CableReady.perform(data.operations) + }) + + this.consumer.connection.addEventListener("message", (event) => { + let data = JSON.parse(event.data) + if (data.meta_type !== "cookie") return + document.cookie = `${data.key}=${data.value||""}; max-age=${data.max_age}; path=/` + }) + } + + find_subscription(identifier) { + return this.consumer.subscriptions.findAll(identifier)[0] + } + + create_subscription(channel) { + this.consumer.subscriptions.create(channel) + } + + connect() { + return this.consumer.connection.open() + } + + disconnect() { + return this.consumer.connection.close() + } + + isConnected() { + return this.consumer.connection.readyState == ReconnectingWebSocket.OPEN + } + + send(identifier, data, options) { + let subscription = this.find_subscription(identifier) + subscription.send(JSON.stringify(data)) + // return this.consumer.connection.send(JSON.stringify(data)) + } + +} + +export { + WebsocketConsumer, + getConsumer } diff --git a/package.json b/package.json index 955ac90..ec516c8 100644 --- a/package.json +++ b/package.json @@ -31,12 +31,12 @@ "rollup-plugin-babel": "^4.4.0", "rollup-plugin-terser": "^5.3.0", "stimulus": ">=1.1", - "stimulus_reflex": ">=3.1.4", "webpack": "^4.43.0", "webpack-bundle-analyzer": "^3.7.0", "webpack-cli": "^3.3.11" }, "dependencies": { + "stimulus_reflex": "file:./stimulus_reflex/javascript", "reconnecting-websocket": "^4.4.0", "cable_ready": ">=4.0" }, diff --git a/tests/example/javascript/example.js b/tests/example/javascript/example.js index 2437681..200e609 100644 --- a/tests/example/javascript/example.js +++ b/tests/example/javascript/example.js @@ -1,11 +1,12 @@ -import { Application } from 'stimulus' -import StimulusReflex from 'stimulus_reflex' +import { Application } from "stimulus" +import StimulusReflex from "stimulus_reflex" // because travis had issues with 'sockpuppet-js' we had to do this. -import WebsocketConsumer from '../../../javascript/stimulus-websocket/index' -import ExampleController from './controllers/example_controller' +import { WebsocketConsumer, getConsumer } from "../../../javascript/stimulus-websocket/index" +import ExampleController from "./controllers/example_controller" const application = Application.start() -const consumer = new WebsocketConsumer('ws://localhost:8000/ws/sockpuppet-sync') +const realConsumer = getConsumer("ws://localhost:8000/ws/sockpuppet-sync") +const consumer = new WebsocketConsumer(realConsumer) application.register("example", ExampleController) StimulusReflex.initialize(application, { consumer }) diff --git a/webpack.config.js b/webpack.config.js index cc1f166..4815c77 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -29,6 +29,9 @@ module.exports = function(env, argv) { path: __dirname + '/jsdist/js', filename: '[name].js' }, + optimization: { + minimize: false + }, plugins: [] }