working web browser client (with quasar) uses json packets and specifically works with uci-websocket
parent
83ec3849dd
commit
b6be936f44
|
@ -0,0 +1,34 @@
|
||||||
|
module.exports = {
|
||||||
|
"ecmaFeatures": {
|
||||||
|
"modules": true,
|
||||||
|
"spread" : true,
|
||||||
|
"restParams" : true
|
||||||
|
},
|
||||||
|
"env": {
|
||||||
|
"es6": true,
|
||||||
|
"node": true,
|
||||||
|
"mocha": true
|
||||||
|
},
|
||||||
|
"parserOptions": {
|
||||||
|
"ecmaVersion": 2017,
|
||||||
|
"sourceType": "module",
|
||||||
|
"parser": 'babel-eslint',
|
||||||
|
},
|
||||||
|
"extends": "eslint:recommended",
|
||||||
|
"rules": {
|
||||||
|
"indent": [
|
||||||
|
"error",
|
||||||
|
2
|
||||||
|
],
|
||||||
|
"no-console": 0,
|
||||||
|
"semi": ["error", "never"],
|
||||||
|
"linebreak-style": [
|
||||||
|
"error",
|
||||||
|
"unix"
|
||||||
|
],
|
||||||
|
"quotes": [
|
||||||
|
"error",
|
||||||
|
"single"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,47 @@
|
||||||
|
module.exports = {
|
||||||
|
root: true,
|
||||||
|
parserOptions: {
|
||||||
|
parser: 'babel-eslint',
|
||||||
|
sourceType: 'module'
|
||||||
|
},
|
||||||
|
env: {
|
||||||
|
browser: true
|
||||||
|
},
|
||||||
|
extends: [
|
||||||
|
// https://github.com/vuejs/eslint-plugin-vue#priority-a-essential-error-prevention
|
||||||
|
// consider switching to `plugin:vue/strongly-recommended` or `plugin:vue/recommended` for stricter rules.
|
||||||
|
// 'plugin:vue/essential',
|
||||||
|
// https://github.com/standard/standard/blob/master/docs/RULES-en.md
|
||||||
|
'standard'
|
||||||
|
],
|
||||||
|
// required to lint *.vue files
|
||||||
|
plugins: [
|
||||||
|
// 'vue'
|
||||||
|
],
|
||||||
|
globals: {
|
||||||
|
'ga': true, // Google Analytics
|
||||||
|
'cordova': true,
|
||||||
|
'__statics': true
|
||||||
|
},
|
||||||
|
// add your custom rules here
|
||||||
|
'rules': {
|
||||||
|
// allow async-await
|
||||||
|
'generator-star-spacing': 'off',
|
||||||
|
|
||||||
|
// allow paren-less arrow functions
|
||||||
|
'arrow-parens': 0,
|
||||||
|
'one-var': 0,
|
||||||
|
|
||||||
|
'import/first': 0,
|
||||||
|
'import/named': 2,
|
||||||
|
'import/namespace': 2,
|
||||||
|
'import/default': 2,
|
||||||
|
'import/export': 2,
|
||||||
|
'import/extensions': 0,
|
||||||
|
'import/no-unresolved': 0,
|
||||||
|
'import/no-extraneous-dependencies': 0,
|
||||||
|
|
||||||
|
// allow debugger during development
|
||||||
|
'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
/node_modules/
|
||||||
|
/coverage/
|
||||||
|
/syncd/
|
||||||
|
*.log
|
||||||
|
/temp/
|
|
@ -0,0 +1,4 @@
|
||||||
|
tests/
|
||||||
|
test/
|
||||||
|
*.test.js
|
||||||
|
testing/
|
|
@ -0,0 +1,92 @@
|
||||||
|
// Websocket is a native global for vanilla JS
|
||||||
|
/* globals WebSocket:true */
|
||||||
|
|
||||||
|
import btc from 'better-try-catch'
|
||||||
|
import EventEmitter from 'eventemitter3'
|
||||||
|
import autoBind from 'auto-bind'
|
||||||
|
|
||||||
|
class Consumer extends EventEmitter {
|
||||||
|
constructor (url, opts = {}) {
|
||||||
|
super()
|
||||||
|
this.name = opts.name || 'browser'
|
||||||
|
this.instanceID = new Date().getTime()
|
||||||
|
this.url = url
|
||||||
|
this.protocol = opts.protocol
|
||||||
|
autoBind(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
async connect () {
|
||||||
|
return new Promise((resolve,reject) => {
|
||||||
|
const socket = new WebSocket(this.url, this.protocol)
|
||||||
|
// Connection opened
|
||||||
|
socket.addEventListener('open', open.bind(this))
|
||||||
|
function open () {
|
||||||
|
this.socket = socket
|
||||||
|
resolve(`socket open to server at : ${this.url}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
setTimeout(function () {
|
||||||
|
reject(new Error('Socket did not connect in 5 seconds'))
|
||||||
|
}, 5000)
|
||||||
|
|
||||||
|
socket.addEventListener('error', function () {
|
||||||
|
// console.log('Web Socket error occurred')
|
||||||
|
reject(new Error('Could not connect to socket server '))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
listen (func) {
|
||||||
|
this.socket.addEventListener('message', handler.bind(this))
|
||||||
|
|
||||||
|
function handler (event) {
|
||||||
|
let packet = {}
|
||||||
|
if (this.socket.readyState === 1) {
|
||||||
|
let [err, parsed] = btc(JSON.parse)(event.data)
|
||||||
|
if (err) packet = {error: `Could not parse JSON: ${event.data}`}
|
||||||
|
else packet = parsed
|
||||||
|
} else {
|
||||||
|
packet = {error: `Connection not Ready, CODE:${this.socket.readyState}`}
|
||||||
|
}
|
||||||
|
if (func) func(packet)
|
||||||
|
this.emit(packet._header.id, packet)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async send (packet) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
if (this.socket.readyState !== 1) reject(new Error(`Connection not Ready, CODE:${this.socket.readyState}`))
|
||||||
|
packet._header =
|
||||||
|
{ id: Math.random().toString().slice(2), // need this for when multiple sends for different consumers use same packet instanceack
|
||||||
|
sender: { name: this.name, instanceID: this.instanceID },
|
||||||
|
url: this.url
|
||||||
|
}
|
||||||
|
let [err, message] = btc(JSON.stringify)(packet)
|
||||||
|
if (err) reject(new Error(`Could not JSON stringify: ${packet}`))
|
||||||
|
// console.log('message to send', message)
|
||||||
|
this.socket.send(message)
|
||||||
|
// listen for when packet comes back with unique header id
|
||||||
|
this.once(packet._header.id, async function (reply) {
|
||||||
|
// console.log('reply emitted', reply)
|
||||||
|
let res = await this._packetProcess(reply)
|
||||||
|
if (!res) { // if process was not promise returning like just logged to console
|
||||||
|
res = reply
|
||||||
|
console.log('consumer function was not promise returning - resolving unprocessed')
|
||||||
|
}
|
||||||
|
if (res.cmd ==='reply') resolve(res.response)
|
||||||
|
else resolve(res)
|
||||||
|
}) // end reply listener
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
registerPacketProcessor (func) {
|
||||||
|
this._packetProcess = func
|
||||||
|
}
|
||||||
|
|
||||||
|
async _packetProcess (packet) {
|
||||||
|
return Promise.resolve(packet)
|
||||||
|
}
|
||||||
|
} // end Consumer Class
|
||||||
|
|
||||||
|
|
||||||
|
export default Consumer
|
|
@ -0,0 +1,34 @@
|
||||||
|
{
|
||||||
|
"name": "@uci/websocket-client",
|
||||||
|
"version": "0.1.2",
|
||||||
|
"description": "JSON packet browser client over web socket",
|
||||||
|
"main": "browser-client",
|
||||||
|
"scripts": {
|
||||||
|
"test": ""
|
||||||
|
},
|
||||||
|
"author": "David Kebler",
|
||||||
|
"license": "MIT",
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git+https://github.com/uCOMmandIt/websocket-client.git"
|
||||||
|
},
|
||||||
|
"keywords": [
|
||||||
|
"node.js",
|
||||||
|
"socket",
|
||||||
|
"websocket",
|
||||||
|
"net",
|
||||||
|
"JSON",
|
||||||
|
"packet",
|
||||||
|
"serialize",
|
||||||
|
"TCP"
|
||||||
|
],
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/uCOMmandIt/websocket-client/issues"
|
||||||
|
},
|
||||||
|
"homepage": "https://github.com/uCOMmandIt/websocket-client#readme",
|
||||||
|
"devDependencies": {},
|
||||||
|
"dependencies": {
|
||||||
|
"auto-bind": "^1.2.0",
|
||||||
|
"eventemitter3": "^3.0.1"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
# UComandIt Websocket Class for Browsers sending and receiving JSON packets
|
||||||
|
|
||||||
|
## What is it
|
||||||
|
|
||||||
|
## TL/DR;
|
||||||
|
|
||||||
|
## What's it good for
|
||||||
|
|
||||||
|
## Why Bother
|
||||||
|
|
||||||
|
## Getting Started
|
||||||
|
|
||||||
|
"babel-eslint": "^8.2.1",
|
||||||
|
"eslint": "^4.18.2",
|
||||||
|
"eslint-config-standard": "^11.0.0",
|
||||||
|
"eslint-friendly-formatter": "^3.0.0",
|
||||||
|
"eslint-loader": "^2.0.0",
|
||||||
|
"eslint-plugin-import": "^2.9.0",
|
||||||
|
"eslint-plugin-node": "^6.0.1",
|
||||||
|
"eslint-plugin-promise": "^3.7.0",
|
||||||
|
"eslint-plugin-standard": "^3.0.1"
|
Loading…
Reference in New Issue