@dwmt/comlink
Advanced tools
Comparing version 2.1.0 to 2.1.1
@@ -60,3 +60,5 @@ // rollup.config.js | ||
'js-cookie', | ||
'axios' | ||
'axios', | ||
'isomorphic-ws', | ||
'@dwmt/loader' | ||
]; | ||
@@ -63,0 +65,0 @@ |
import Cookies from 'js-cookie'; | ||
import axios from 'axios'; | ||
import WebSocket from 'isomorphic-ws'; | ||
import { Loader } from '@dwmt/loader'; | ||
@@ -105,10 +108,2 @@ var inherits; | ||
const axios = require('axios'); | ||
const WebSocket = require('isomorphic-ws'); | ||
const { | ||
Loader | ||
} = require('@dwmt/loader'); | ||
function getLoader(channel, options) { | ||
@@ -741,195 +736,6 @@ let loader = new Loader(); | ||
const { | ||
EventEmitter | ||
} = require('events'); | ||
var version = "2.1.1"; | ||
class Server { | ||
constructor(logger) { | ||
this._dialects = {}; | ||
this._channels = {}; | ||
this._clients = {}; | ||
this.session = {}; | ||
this.eventEmitter = new EventEmitter(); | ||
this.logger = logger || console; | ||
} | ||
registerDialect(_dialect) { | ||
this._dialects[_dialect.name] = _dialect; | ||
} | ||
registerChannel(_channel) { | ||
if (_channel.auth && !_channel.tokenValidator) { | ||
throw new Error('For authentication you need a token validator'); | ||
} | ||
if (_channel.type !== 'ws') { | ||
throw new Error('Only websocket listeners implemented yet!'); | ||
} | ||
this._channels[_channel.name] = _channel; | ||
this.session[_channel.name] = { | ||
clients: {}, | ||
tokens: {} | ||
}; | ||
} | ||
sendMessageToClient(channelName, clientID, event, message) { | ||
if (!this.session[channelName].clients[clientID]) { | ||
throw new Error('No user with given clientID'); | ||
} | ||
this.eventEmitter.emit(`sendEventTo:${clientID}`, { | ||
_type: 'event', | ||
event, | ||
message | ||
}); | ||
} | ||
getClientIDByToken(channelName, token) { | ||
let clientID = this.session[channelName].tokens[token].client; | ||
if (!clientID) { | ||
throw new Error('No user with given token'); | ||
} | ||
return clientID; | ||
} | ||
getTokenByClientID(channelName, clientID) { | ||
let token = this.session[channelName].clients[clientID].token; | ||
if (!token) { | ||
throw new Error('No user with given clientID'); | ||
} | ||
return token; | ||
} | ||
isTokenActive(channelName, token) { | ||
let clientID = this.session[channelName].tokens[token].client; | ||
return !!clientID; | ||
} | ||
isClientActive(channelName, clientID) { | ||
let token = this.session[channelName].clients[clientID].token; | ||
return !!token; | ||
} | ||
applyChannel(channelName, wss) { | ||
const channel = this._channels[channelName]; | ||
if (!channel) { | ||
throw new Error(`Channel with name ${channelName} is not registered!`); | ||
} | ||
wss.on('connection', async (ws, req) => { | ||
let clientID = generateUUID(); | ||
this.session[channelName].clients[clientID] = {}; | ||
if (channel.auth) { | ||
const token = req.headers['sec-websocket-protocol']; | ||
if (!token || token.length === 0) { | ||
return ws.close(); | ||
} | ||
let check = await channel.tokenValidator(token); | ||
if (!check) { | ||
return ws.close(); | ||
} | ||
this.session[channelName].clients[clientID].token = token; | ||
this.session[channelName].tokens[token] = { | ||
client: clientID | ||
}; | ||
ws.id = clientID; | ||
} | ||
this.eventEmitter.on(`sendEventTo:${clientID}`, msg => { | ||
ws.send(JSON.stringify(msg)); | ||
}); | ||
ws.on('close', async () => { | ||
let token = this.session[channelName].clients[ws.id].token; | ||
delete this.session[channelName].clients[ws.id]; | ||
delete this.session[channelName].tokens[token]; | ||
}); | ||
ws.on('message', async message => { | ||
const parsed = JSON.parse(message); | ||
const dialect = parsed._dialect; | ||
if (!dialect) { | ||
return; | ||
} | ||
const id = parsed.id; | ||
const channelDialect = this._channels[channelName].dialects.includes(dialect); | ||
if (!channelDialect) { | ||
ws.send(JSON.stringify({ | ||
_type: 'rpcError', | ||
id, | ||
error: `The used dialect ${dialect} is not supported on this channel` | ||
})); | ||
} | ||
let headers = {}; | ||
if (channel.headerInjector) { | ||
try { | ||
let h = await channel.headerInjector(this.session[channelName].clients[ws.id].token); | ||
headers = Object.assign({}, h); | ||
} catch (err) { | ||
ws.send(JSON.stringify({ | ||
_type: 'rpcError', | ||
id, | ||
error: err.message, | ||
headers: Object.assign({}, headers, { | ||
serverTime: Date.now() | ||
}) | ||
})); | ||
throw err; | ||
} | ||
} | ||
let ctx = {}; | ||
ctx.token = this.session[channelName].clients[ws.id].token; | ||
ctx.clientID = ws.id; | ||
try { | ||
const returnValue = await this._dialects[dialect].onRequest(parsed, ctx); | ||
if (parsed._type === 'request') { | ||
ws.send(JSON.stringify({ | ||
_type: 'rpcResponse', | ||
id, | ||
result: returnValue, | ||
headers: Object.assign({}, headers, { | ||
serverTime: Date.now() | ||
}) | ||
})); | ||
} | ||
} catch (err) { | ||
ws.send(JSON.stringify({ | ||
_type: 'rpcError', | ||
id, | ||
error: err.message, | ||
headers: Object.assign({}, headers, { | ||
serverTime: Date.now() | ||
}) | ||
})); | ||
throw err; | ||
} | ||
}); | ||
}); | ||
} | ||
} | ||
var version = "2.1.0"; | ||
var Comlink = { | ||
Client, | ||
Server, | ||
Storage: Storage$1, | ||
@@ -936,0 +742,0 @@ version |
@@ -1,1 +0,1 @@ | ||
!function(e,t){"use strict";function n(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var r=n(t),o="function"==typeof Object.create?function(e,t){e.super_=t,e.prototype=Object.create(t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}})}:function(e,t){e.super_=t;var n=function(){};n.prototype=t.prototype,e.prototype=new n,e.prototype.constructor=e};function s(){}function a(){this._cookie=r.default}function i(){this._store={}}s.prototype.getItem=function(e){console.error("getItem not implemented")},s.prototype.setItem=function(e,t,n){console.error("setItem not implemented")},s.prototype.removeItem=function(e,t){console.error("removeItem not implemented")},s.prototype.clear=function(){console.error("clear not implemented")},o(a,s),a.prototype.getItem=function(e){return this._cookie.get(e)},a.prototype.setItem=function(e,t,n){return this._cookie.set(e,t,n)},a.prototype.removeItem=function(e,t){return this._cookie.remove(e,t)},o(i,s),i.prototype.getItem=function(e){return this._store[e]||null},i.prototype.setItem=function(e,t,n){this._store[e]=t},i.prototype.removeItem=function(e,t){delete this._store[e]},i.prototype.clear=function(){this._store={}};var c={LocalStorage:"undefined"!=typeof window?window.localStorage:s,SessionStorage:"undefined"!=typeof window?window.sessionStorage:s,CookieStorage:new a,NodeStorage:new i};function l(){return"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,(function(e){var t=16*Math.random()|0;return("x"===e?t:3&t|8).toString(16)}))}const h=require("axios"),d=require("isomorphic-ws"),{Loader:u}=require("@dwmt/loader");function p(e,t){let n=new u;return"boolean"!=typeof t.loader||t.loader?(void 0===t.loader&&(n=e.loader),"object"==typeof t.loader&&t.loader.work&&t.loader.terminate&&(n=t.loader),n):n}function f(e){return{type:"http",name:e.name,protocol:e.ssl?"https://":"http://",uri:e.uri,default:e.default||!1,rpc:e.rpc||void 0,onError:e.onError||function(e){console.error(e)},headerHandler:e.headerHandler||async function(e){return!0},loader:e.loader||new u,logger:e.logger,connectable:!1}}function _(e){const t=this,n={type:"ws",name:e.name,protocol:e.ssl?"wss://":"ws://",uri:e.uri,default:e.default||!1,auth:e.auth,authHeader:e.authHeader,rpc:e.rpc,onError:e.onError||function(e){console.error(e)},loader:e.loader||new u,logger:e.logger,connection:null,connectable:!0,alive:!1,answers:{},listeners:{},onConnectionOpen:e.onConnectionOpen||function(){},onConnectionTermination:e.onConnectionTermination||function(){},onConnectionClose:e.onConnectionClose||function(){},onConnectionError:e.onConnectionError||function(){},callbacks:{onConnectionOpen:function(){},onConnectionClose:function(){},onConnectionError:function(){},onConnectionTermination:function(){}},terminate(){t._channels[e.name].connection.close(),t._channels[e.name].connection=null,t._channels[e.name].answers={},t._channels[e.name].listeners={},t._channels[e.name].onConnectionTermination(),t._channels[e.name].callbacks.onConnectionTermination()},connect:()=>new Promise(((r,o)=>{if(null!==t._channels[e.name].connection)return r(!0);const s=[];if(e.auth){const n=t.getHeader(e.authHeader);s.push(n.value)}const a=new d(n.protocol+n.uri,s);t._channels[e.name].connection=a,a.addEventListener("open",(()=>{t._channels[e.name].alive=!0,t._channels[e.name].onConnectionOpen(),t._channels[e.name].callbacks.onConnectionOpen(),r(!0)})),a.addEventListener("close",(()=>{t._channels[e.name].alive=!1,t._channels[e.name].onConnectionClose(),t._channels[e.name].callbacks.onConnectionClose()})),a.addEventListener("error",(n=>{t._channels[e.name].alive=!1,t._channels[e.name].onConnectionError(n),t._channels[e.name].callbacks.onConnectionError(n),o(n)})),e.rpc&&a.addEventListener("message",(function(n){try{const r=JSON.parse(n.data);if(e.rpc&&e.rpc.headerHandler&&e.rpc.headerHandler(r.headers||{}),"rpcResponse"!==r._type&&"rpcError"!==r._type&&void 0!==r._type||!r.id||(void 0!==r.result?t._channels[e.name].answers[r.id].resolve(r.result):t._channels[e.name].answers[r.id].reject({error:r.error})),"event"===r._type){let n=t._channels[e.name].listeners[r.event];if(n.length)for(let e of n)e(r.message)}}catch(e){console.error(e)}}))}))};return n}const{EventEmitter:m}=require("events");var w={Client:class{constructor(e={}){this._axios=h,this._ws=d,this._dialects={},this._channels={},this._headers={},this._deafultHTTPChannel=null,this._deafultWSChannel=null,this._deafultRPCChannel=null,this._defaultDialect=null,this._instanceID=l(),this._devtools=e.devtools||!0}get channels(){return Object.keys(this._channels)||[]}disableDevtools(){this._devtools=!1}bindDevtools(){global.window&&(global.window._COMLINK_DEV_TOOLS||(global.window._COMLINK_DEV_TOOLS={}),global.window._COMLINK_DEV_TOOLS[this._instanceID]=this,console.log("[COMLINK] Devtools enabled with instanceID: "+this._instanceID))}async connect(){let e=[];for(let t of Object.keys(this._channels)){let n=this._channels[t];"ws"!==n.type||n.alive||e.push(n.connect())}return Promise.all(e)}channel(e){if(!this._channels[e])throw new Error(`No channel registered with ${e}`);let t=this;const n={};return n.name=this._channels[e].name,n.alive=this._channels[e].alive,this._channels[e].connectable&&(n.connection=this._channels[e].connection,n.connect=this._channels[e].connect,n.terminate=this._channels[e].terminate),n.registerCallback=function(n,r){t._channels[e].callbacks[n]=r},n}registerDialect(e){const t=Object.assign({},e);t.router=t.router||function(e){return{path:e}},t.parameter=t.parameter||function(e){return{parameters:e}},t.optioner=t.optioner||function(){return{}},t.handler=t.handler||function(){return{}},this._dialects[t.name]=t,(t.default||null===this._defaultDialect)&&(this._defaultDialect=t.name)}registerHeader(e){this._headers[e.name]=e}registerChannel(e){if(!e.type in["http","ws"])throw new Error(`[Comlink] Channel type "${e.type}" is not supported!`);if("http"===e.type){const t=f.call(this,e);t.default&&(this._deafultHTTPChannel=t.name),t.default&&t.rpc&&(this._deafultRPCChannel=t.name),this._channels[t.name]=t}if("ws"===e.type){const t=_.call(this,e);t.default&&(this._deafultWSChannel=t.name),t.default&&t.rpc&&(this._deafultRPCChannel=t.name),this._channels[t.name]=t}}get headers(){return Object.keys(this._headers)}checkHeaders(){Object.keys(this._headers).forEach((e=>{const t=this._headers[e];if("automatic"===t.type){const e=t.storage.getItem(t.key);e&&(t.value=e)}}))}getHeader(e){if(!this._headers[e])throw new Error(`No registered header with name ${e}`);return{key:this._headers[e].key,value:this._headers[e].value}}setHeader(e,t){if(!this._headers[e])throw new Error(`No registered header with name ${e}`);this._headers[e].value=t,"automatic"===this._headers[e].type&&this._headers[e].storage.setItem(this._headers[e].key,t)}async get(e,t={}){this.checkDefaultHTTPChannel();const n=t.channel||this._deafultHTTPChannel,r=this._channels[n],o=p(r,t),s=t.onError||r.onError,a=o.work();try{let n=r.protocol+r.uri+"/"+e;/^https?:\/\//i.test(e)&&(n=e);const s=await h.get(n,t.axios||{});return await r.headerHandler(s.headers),s}catch(e){throw await r.headerHandler(e.response.headers),await s(e),e}finally{o.terminate(a)}}checkDefaultHTTPChannel(){if(!this._deafultHTTPChannel)throw new Error("[Comlink] No default HTTP channel")}async post(e,t,n={}){this.checkDefaultHTTPChannel();const r=n.channel||this._deafultHTTPChannel,o=this._channels[r],s=p(o,n),a=n.onError||o.onError,i=s.work();try{let r=o.protocol+o.uri+"/"+e;/^https?:\/\//i.test(e)&&(r=e);const a=await h.post(r,t,n.axios||{});return await o.headerHandler(a.headers),a}catch(e){throw await o.headerHandler(e.response.headers),await a(e),e}finally{s.terminate(i)}}async put(e,t,n={}){this.checkDefaultHTTPChannel();const r=n.channel||this._deafultHTTPChannel,o=this._channels[r],s=p(o,n),a=n.onError||o.onError,i=s.work();try{let r=o.protocol+o.uri+"/"+e;/^https?:\/\//i.test(e)&&(r=e);const a=await h.put(r,t,n.axios||{});return await o.headerHandler(a.headers),a}catch(e){throw await o.headerHandler(e.response.headers),await a(e),e}finally{s.terminate(i)}}async delete(e,t={}){this.checkDefaultHTTPChannel();const n=t.channel||this._deafultHTTPChannel,r=this._channels[n],o=p(r,t),s=t.onError||r.onError,a=o.work();try{let n=r.protocol+r.uri+"/"+e;/^https?:\/\//i.test(e)&&(n=e);const s=await h.delete(n,t.axios||{});return await r.headerHandler(s.headers),s}catch(e){throw await r.headerHandler(e.response.headers),await s(e),e}finally{o.terminate(a)}}subscribeToEvent(e,t,n={}){const r=n.channel||this._deafultRPCChannel,o=this._channels[r];o.listeners[e]||(o.listeners[e]=[]),o.listeners[e].push(t)}unsubscribeFromEvent(e,t,n={}){const r=n.channel||this._deafultRPCChannel,o=this._channels[r];o.listeners[e]&&(o.listeners[e]=o.listeners[e].filter((e=>e!==t)))}sendMessage(){throw new Error("Not implemented yet!")}async _rpc(e="request",t,n,r,o){const s=this._channels[r.channel||this._deafultRPCChannel],a=this._dialects[o||this._defaultDialect],i=s.rpc;if(!i.dialects.includes(a.name))throw new Error(`The channel ${s.name} not supports the ${a.name} dialect`);const c=((i[a.name]||{}).idGenerator||i.idGenerator||l)();let h={id:c};(void 0===a.sendMeta||a.sendMeta)&&(h._dialect=a.name,h._type=e);const d=a.router(t),u=a.parameter(n),p=a.optioner(r);h=Object.assign({},h,a.interface,d,u,p),null===s.connection&&await s.connect(),s.connection.send(JSON.stringify(h));const f=new Promise(((e,t)=>{s.answers[c]={resolve:e,reject:t}})),_=new Promise(((e,t)=>{setTimeout((()=>{t(`[Comlink] Maximum retries exceeded for message: ${c}`)}),i.retryInterval*i.maxRetries)}));return Promise.race([f,_])}async _rpcHTTP(e="request",t,n,r,o){const s=this._channels[r.channel||this._deafultRPCChannel],a=this._dialects[o||this._defaultDialect],i=s.rpc;if(!a.type||"http"!==a.type)throw new Error("ComlinkDialect is not supported on HTTPChannel yet!");if("http"===a.type&&"request"!==e)throw new Error("HTTPDialect only supports request now!");if(!i.dialects.includes(a.name))throw new Error(`The channel ${s.name} not supports the ${a.name} dialect`);let c=await a.handler(t,n,r);try{return(await h(c)).data}catch(e){throw new Error(e.response.data.message)}}async _rpcMethod(e="request",t,n,r,o){const s=this._channels[r.channel||this._deafultRPCChannel],a=this._dialects[o||this._defaultDialect];if(!s.rpc.dialects.includes(a.name))throw new Error(`The channel ${s.name} not supports the ${a.name} dialect`);return a.handler(t,n,r)}async request(e,t,n={},r){const o=n.channel||this._deafultRPCChannel,s=this._channels[o],a=this._dialects[r||this._defaultDialect],i=p(s,n),c=n.onError||s.onError,l=i.work();try{return"method"===a.type?await this._rpcMethod("request",e,t,n,r):"http"===s.type?await this._rpcHTTP("request",e,t,n,r):await this._rpc("request",e,t,n,r)}catch(e){throw await c(e,n),e}finally{i.terminate(l)}}async inform(e,t,n={},r){const o=n.channel||this._deafultRPCChannel,s=this._channels[o],a=p(s,n),i=n.onError||s.onError,c=a.work();try{return"http"===s.type?await this._rpc("inform",e,t,n,r):"method"===s.type?await this._rpcMethod("inform",e,t,n,r):await this._rpc("inform",e,t,n,r)}catch(e){throw await i(e),e}finally{a.terminate(c)}}},Server:class{constructor(e){this._dialects={},this._channels={},this._clients={},this.session={},this.eventEmitter=new m,this.logger=e||console}registerDialect(e){this._dialects[e.name]=e}registerChannel(e){if(e.auth&&!e.tokenValidator)throw new Error("For authentication you need a token validator");if("ws"!==e.type)throw new Error("Only websocket listeners implemented yet!");this._channels[e.name]=e,this.session[e.name]={clients:{},tokens:{}}}sendMessageToClient(e,t,n,r){if(!this.session[e].clients[t])throw new Error("No user with given clientID");this.eventEmitter.emit(`sendEventTo:${t}`,{_type:"event",event:n,message:r})}getClientIDByToken(e,t){let n=this.session[e].tokens[t].client;if(!n)throw new Error("No user with given token");return n}getTokenByClientID(e,t){let n=this.session[e].clients[t].token;if(!n)throw new Error("No user with given clientID");return n}isTokenActive(e,t){return!!this.session[e].tokens[t].client}isClientActive(e,t){return!!this.session[e].clients[t].token}applyChannel(e,t){const n=this._channels[e];if(!n)throw new Error(`Channel with name ${e} is not registered!`);t.on("connection",(async(t,r)=>{let o=l();if(this.session[e].clients[o]={},n.auth){const s=r.headers["sec-websocket-protocol"];if(!s||0===s.length)return t.close();if(!await n.tokenValidator(s))return t.close();this.session[e].clients[o].token=s,this.session[e].tokens[s]={client:o},t.id=o}this.eventEmitter.on(`sendEventTo:${o}`,(e=>{t.send(JSON.stringify(e))})),t.on("close",(async()=>{let n=this.session[e].clients[t.id].token;delete this.session[e].clients[t.id],delete this.session[e].tokens[n]})),t.on("message",(async r=>{const o=JSON.parse(r),s=o._dialect;if(!s)return;const a=o.id;this._channels[e].dialects.includes(s)||t.send(JSON.stringify({_type:"rpcError",id:a,error:`The used dialect ${s} is not supported on this channel`}));let i={};if(n.headerInjector)try{let r=await n.headerInjector(this.session[e].clients[t.id].token);i=Object.assign({},r)}catch(e){throw t.send(JSON.stringify({_type:"rpcError",id:a,error:e.message,headers:Object.assign({},i,{serverTime:Date.now()})})),e}let c={};c.token=this.session[e].clients[t.id].token,c.clientID=t.id;try{const e=await this._dialects[s].onRequest(o,c);"request"===o._type&&t.send(JSON.stringify({_type:"rpcResponse",id:a,result:e,headers:Object.assign({},i,{serverTime:Date.now()})}))}catch(e){throw t.send(JSON.stringify({_type:"rpcError",id:a,error:e.message,headers:Object.assign({},i,{serverTime:Date.now()})})),e}}))}))}},Storage:c,version:"2.1.0"};e.default=w,Object.defineProperty(e,"__esModule",{value:!0})}(this["@dwmt/comlink"]=this["@dwmt/comlink"]||{},Cookies); | ||
!function(e,t,n,r,o){"use strict";function a(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var s=a(t),i=a(n),l=a(r),c="function"==typeof Object.create?function(e,t){e.super_=t,e.prototype=Object.create(t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}})}:function(e,t){e.super_=t;var n=function(){};n.prototype=t.prototype,e.prototype=new n,e.prototype.constructor=e};function h(){}function d(){this._cookie=s.default}function u(){this._store={}}h.prototype.getItem=function(e){console.error("getItem not implemented")},h.prototype.setItem=function(e,t,n){console.error("setItem not implemented")},h.prototype.removeItem=function(e,t){console.error("removeItem not implemented")},h.prototype.clear=function(){console.error("clear not implemented")},c(d,h),d.prototype.getItem=function(e){return this._cookie.get(e)},d.prototype.setItem=function(e,t,n){return this._cookie.set(e,t,n)},d.prototype.removeItem=function(e,t){return this._cookie.remove(e,t)},c(u,h),u.prototype.getItem=function(e){return this._store[e]||null},u.prototype.setItem=function(e,t,n){this._store[e]=t},u.prototype.removeItem=function(e,t){delete this._store[e]},u.prototype.clear=function(){this._store={}};var p={LocalStorage:"undefined"!=typeof window?window.localStorage:h,SessionStorage:"undefined"!=typeof window?window.sessionStorage:h,CookieStorage:new d,NodeStorage:new u};function f(){return"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,(function(e){var t=16*Math.random()|0;return("x"===e?t:3&t|8).toString(16)}))}function _(e,t){let n=new o.Loader;return"boolean"!=typeof t.loader||t.loader?(void 0===t.loader&&(n=e.loader),"object"==typeof t.loader&&t.loader.work&&t.loader.terminate&&(n=t.loader),n):n}function m(e){return{type:"http",name:e.name,protocol:e.ssl?"https://":"http://",uri:e.uri,default:e.default||!1,rpc:e.rpc||void 0,onError:e.onError||function(e){console.error(e)},headerHandler:e.headerHandler||async function(e){return!0},loader:e.loader||new o.Loader,logger:e.logger,connectable:!1}}function w(e){const t=this,n={type:"ws",name:e.name,protocol:e.ssl?"wss://":"ws://",uri:e.uri,default:e.default||!1,auth:e.auth,authHeader:e.authHeader,rpc:e.rpc,onError:e.onError||function(e){console.error(e)},loader:e.loader||new o.Loader,logger:e.logger,connection:null,connectable:!0,alive:!1,answers:{},listeners:{},onConnectionOpen:e.onConnectionOpen||function(){},onConnectionTermination:e.onConnectionTermination||function(){},onConnectionClose:e.onConnectionClose||function(){},onConnectionError:e.onConnectionError||function(){},callbacks:{onConnectionOpen:function(){},onConnectionClose:function(){},onConnectionError:function(){},onConnectionTermination:function(){}},terminate(){t._channels[e.name].connection.close(),t._channels[e.name].connection=null,t._channels[e.name].answers={},t._channels[e.name].listeners={},t._channels[e.name].onConnectionTermination(),t._channels[e.name].callbacks.onConnectionTermination()},connect:()=>new Promise(((r,o)=>{if(null!==t._channels[e.name].connection)return r(!0);const a=[];if(e.auth){const n=t.getHeader(e.authHeader);a.push(n.value)}const s=new l.default(n.protocol+n.uri,a);t._channels[e.name].connection=s,s.addEventListener("open",(()=>{t._channels[e.name].alive=!0,t._channels[e.name].onConnectionOpen(),t._channels[e.name].callbacks.onConnectionOpen(),r(!0)})),s.addEventListener("close",(()=>{t._channels[e.name].alive=!1,t._channels[e.name].onConnectionClose(),t._channels[e.name].callbacks.onConnectionClose()})),s.addEventListener("error",(n=>{t._channels[e.name].alive=!1,t._channels[e.name].onConnectionError(n),t._channels[e.name].callbacks.onConnectionError(n),o(n)})),e.rpc&&s.addEventListener("message",(function(n){try{const r=JSON.parse(n.data);if(e.rpc&&e.rpc.headerHandler&&e.rpc.headerHandler(r.headers||{}),"rpcResponse"!==r._type&&"rpcError"!==r._type&&void 0!==r._type||!r.id||(void 0!==r.result?t._channels[e.name].answers[r.id].resolve(r.result):t._channels[e.name].answers[r.id].reject({error:r.error})),"event"===r._type){let n=t._channels[e.name].listeners[r.event];if(n.length)for(let e of n)e(r.message)}}catch(e){console.error(e)}}))}))};return n}var y={Client:class{constructor(e={}){this._axios=i.default,this._ws=l.default,this._dialects={},this._channels={},this._headers={},this._deafultHTTPChannel=null,this._deafultWSChannel=null,this._deafultRPCChannel=null,this._defaultDialect=null,this._instanceID=f(),this._devtools=e.devtools||!0}get channels(){return Object.keys(this._channels)||[]}disableDevtools(){this._devtools=!1}bindDevtools(){global.window&&(global.window._COMLINK_DEV_TOOLS||(global.window._COMLINK_DEV_TOOLS={}),global.window._COMLINK_DEV_TOOLS[this._instanceID]=this,console.log("[COMLINK] Devtools enabled with instanceID: "+this._instanceID))}async connect(){let e=[];for(let t of Object.keys(this._channels)){let n=this._channels[t];"ws"!==n.type||n.alive||e.push(n.connect())}return Promise.all(e)}channel(e){if(!this._channels[e])throw new Error(`No channel registered with ${e}`);let t=this;const n={};return n.name=this._channels[e].name,n.alive=this._channels[e].alive,this._channels[e].connectable&&(n.connection=this._channels[e].connection,n.connect=this._channels[e].connect,n.terminate=this._channels[e].terminate),n.registerCallback=function(n,r){t._channels[e].callbacks[n]=r},n}registerDialect(e){const t=Object.assign({},e);t.router=t.router||function(e){return{path:e}},t.parameter=t.parameter||function(e){return{parameters:e}},t.optioner=t.optioner||function(){return{}},t.handler=t.handler||function(){return{}},this._dialects[t.name]=t,(t.default||null===this._defaultDialect)&&(this._defaultDialect=t.name)}registerHeader(e){this._headers[e.name]=e}registerChannel(e){if(!e.type in["http","ws"])throw new Error(`[Comlink] Channel type "${e.type}" is not supported!`);if("http"===e.type){const t=m.call(this,e);t.default&&(this._deafultHTTPChannel=t.name),t.default&&t.rpc&&(this._deafultRPCChannel=t.name),this._channels[t.name]=t}if("ws"===e.type){const t=w.call(this,e);t.default&&(this._deafultWSChannel=t.name),t.default&&t.rpc&&(this._deafultRPCChannel=t.name),this._channels[t.name]=t}}get headers(){return Object.keys(this._headers)}checkHeaders(){Object.keys(this._headers).forEach((e=>{const t=this._headers[e];if("automatic"===t.type){const e=t.storage.getItem(t.key);e&&(t.value=e)}}))}getHeader(e){if(!this._headers[e])throw new Error(`No registered header with name ${e}`);return{key:this._headers[e].key,value:this._headers[e].value}}setHeader(e,t){if(!this._headers[e])throw new Error(`No registered header with name ${e}`);this._headers[e].value=t,"automatic"===this._headers[e].type&&this._headers[e].storage.setItem(this._headers[e].key,t)}async get(e,t={}){this.checkDefaultHTTPChannel();const n=t.channel||this._deafultHTTPChannel,r=this._channels[n],o=_(r,t),a=t.onError||r.onError,s=o.work();try{let n=r.protocol+r.uri+"/"+e;/^https?:\/\//i.test(e)&&(n=e);const a=await i.default.get(n,t.axios||{});return await r.headerHandler(a.headers),a}catch(e){throw await r.headerHandler(e.response.headers),await a(e),e}finally{o.terminate(s)}}checkDefaultHTTPChannel(){if(!this._deafultHTTPChannel)throw new Error("[Comlink] No default HTTP channel")}async post(e,t,n={}){this.checkDefaultHTTPChannel();const r=n.channel||this._deafultHTTPChannel,o=this._channels[r],a=_(o,n),s=n.onError||o.onError,l=a.work();try{let r=o.protocol+o.uri+"/"+e;/^https?:\/\//i.test(e)&&(r=e);const s=await i.default.post(r,t,n.axios||{});return await o.headerHandler(s.headers),s}catch(e){throw await o.headerHandler(e.response.headers),await s(e),e}finally{a.terminate(l)}}async put(e,t,n={}){this.checkDefaultHTTPChannel();const r=n.channel||this._deafultHTTPChannel,o=this._channels[r],a=_(o,n),s=n.onError||o.onError,l=a.work();try{let r=o.protocol+o.uri+"/"+e;/^https?:\/\//i.test(e)&&(r=e);const s=await i.default.put(r,t,n.axios||{});return await o.headerHandler(s.headers),s}catch(e){throw await o.headerHandler(e.response.headers),await s(e),e}finally{a.terminate(l)}}async delete(e,t={}){this.checkDefaultHTTPChannel();const n=t.channel||this._deafultHTTPChannel,r=this._channels[n],o=_(r,t),a=t.onError||r.onError,s=o.work();try{let n=r.protocol+r.uri+"/"+e;/^https?:\/\//i.test(e)&&(n=e);const a=await i.default.delete(n,t.axios||{});return await r.headerHandler(a.headers),a}catch(e){throw await r.headerHandler(e.response.headers),await a(e),e}finally{o.terminate(s)}}subscribeToEvent(e,t,n={}){const r=n.channel||this._deafultRPCChannel,o=this._channels[r];o.listeners[e]||(o.listeners[e]=[]),o.listeners[e].push(t)}unsubscribeFromEvent(e,t,n={}){const r=n.channel||this._deafultRPCChannel,o=this._channels[r];o.listeners[e]&&(o.listeners[e]=o.listeners[e].filter((e=>e!==t)))}sendMessage(){throw new Error("Not implemented yet!")}async _rpc(e="request",t,n,r,o){const a=this._channels[r.channel||this._deafultRPCChannel],s=this._dialects[o||this._defaultDialect],i=a.rpc;if(!i.dialects.includes(s.name))throw new Error(`The channel ${a.name} not supports the ${s.name} dialect`);const l=((i[s.name]||{}).idGenerator||i.idGenerator||f)();let c={id:l};(void 0===s.sendMeta||s.sendMeta)&&(c._dialect=s.name,c._type=e);const h=s.router(t),d=s.parameter(n),u=s.optioner(r);c=Object.assign({},c,s.interface,h,d,u),null===a.connection&&await a.connect(),a.connection.send(JSON.stringify(c));const p=new Promise(((e,t)=>{a.answers[l]={resolve:e,reject:t}})),_=new Promise(((e,t)=>{setTimeout((()=>{t(`[Comlink] Maximum retries exceeded for message: ${l}`)}),i.retryInterval*i.maxRetries)}));return Promise.race([p,_])}async _rpcHTTP(e="request",t,n,r,o){const a=this._channels[r.channel||this._deafultRPCChannel],s=this._dialects[o||this._defaultDialect],l=a.rpc;if(!s.type||"http"!==s.type)throw new Error("ComlinkDialect is not supported on HTTPChannel yet!");if("http"===s.type&&"request"!==e)throw new Error("HTTPDialect only supports request now!");if(!l.dialects.includes(s.name))throw new Error(`The channel ${a.name} not supports the ${s.name} dialect`);let c=await s.handler(t,n,r);try{return(await i.default(c)).data}catch(e){throw new Error(e.response.data.message)}}async _rpcMethod(e="request",t,n,r,o){const a=this._channels[r.channel||this._deafultRPCChannel],s=this._dialects[o||this._defaultDialect];if(!a.rpc.dialects.includes(s.name))throw new Error(`The channel ${a.name} not supports the ${s.name} dialect`);return s.handler(t,n,r)}async request(e,t,n={},r){const o=n.channel||this._deafultRPCChannel,a=this._channels[o],s=this._dialects[r||this._defaultDialect],i=_(a,n),l=n.onError||a.onError,c=i.work();try{return"method"===s.type?await this._rpcMethod("request",e,t,n,r):"http"===a.type?await this._rpcHTTP("request",e,t,n,r):await this._rpc("request",e,t,n,r)}catch(e){throw await l(e,n),e}finally{i.terminate(c)}}async inform(e,t,n={},r){const o=n.channel||this._deafultRPCChannel,a=this._channels[o],s=_(a,n),i=n.onError||a.onError,l=s.work();try{return"http"===a.type?await this._rpc("inform",e,t,n,r):"method"===a.type?await this._rpcMethod("inform",e,t,n,r):await this._rpc("inform",e,t,n,r)}catch(e){throw await i(e),e}finally{s.terminate(l)}}},Storage:p,version:"2.1.1"};e.default=y,Object.defineProperty(e,"__esModule",{value:!0})}(this["@dwmt/comlink"]=this["@dwmt/comlink"]||{},Cookies,axios,WebSocket,loader); |
@@ -1,2 +0,2 @@ | ||
'use strict';Object.defineProperty(exports,'__esModule',{value:true});var Cookies=require('js-cookie');function _interopDefaultLegacy(e){return e&&typeof e==='object'&&'default'in e?e:{'default':e}}var Cookies__default=/*#__PURE__*/_interopDefaultLegacy(Cookies);var inherits; | ||
'use strict';Object.defineProperty(exports,'__esModule',{value:true});var Cookies=require('js-cookie'),axios=require('axios'),WebSocket=require('isomorphic-ws'),loader=require('@dwmt/loader');function _interopDefaultLegacy(e){return e&&typeof e==='object'&&'default'in e?e:{'default':e}}var Cookies__default=/*#__PURE__*/_interopDefaultLegacy(Cookies);var axios__default=/*#__PURE__*/_interopDefaultLegacy(axios);var WebSocket__default=/*#__PURE__*/_interopDefaultLegacy(WebSocket);var inherits; | ||
if (typeof Object.create === 'function'){ | ||
@@ -97,26 +97,18 @@ inherits = function inherits(ctor, superCtor) { | ||
}); | ||
}const axios = require('axios'); | ||
}function getLoader(channel, options) { | ||
let loader$1 = new loader.Loader(); | ||
const WebSocket = require('isomorphic-ws'); | ||
const { | ||
Loader | ||
} = require('@dwmt/loader'); | ||
function getLoader(channel, options) { | ||
let loader = new Loader(); | ||
if (typeof options.loader === 'boolean' && !options.loader) { | ||
return loader; | ||
return loader$1; | ||
} | ||
if (typeof options.loader === 'undefined') { | ||
loader = channel.loader; | ||
loader$1 = channel.loader; | ||
} | ||
if (typeof options.loader === 'object' && options.loader.work && options.loader.terminate) { | ||
loader = options.loader; | ||
loader$1 = options.loader; | ||
} | ||
return loader; | ||
return loader$1; | ||
} | ||
@@ -138,3 +130,3 @@ | ||
}, | ||
loader: options.loader || new Loader(), | ||
loader: options.loader || new loader.Loader(), | ||
logger: options.logger, | ||
@@ -159,3 +151,3 @@ connectable: false | ||
}, | ||
loader: options.loader || new Loader(), | ||
loader: options.loader || new loader.Loader(), | ||
logger: options.logger, | ||
@@ -203,3 +195,3 @@ connection: null, | ||
const ws = new WebSocket(channel.protocol + channel.uri, opts); | ||
const ws = new WebSocket__default['default'](channel.protocol + channel.uri, opts); | ||
self._channels[options.name].connection = ws; | ||
@@ -274,4 +266,4 @@ ws.addEventListener('open', () => { | ||
constructor(options = {}) { | ||
this._axios = axios; | ||
this._ws = WebSocket; | ||
this._axios = axios__default['default']; | ||
this._ws = WebSocket__default['default']; | ||
this._dialects = {}; | ||
@@ -473,3 +465,3 @@ this._channels = {}; | ||
const resp = await axios.get(url, options.axios || {}); | ||
const resp = await axios__default['default'].get(url, options.axios || {}); | ||
await channel.headerHandler(resp.headers); | ||
@@ -508,3 +500,3 @@ return resp; | ||
const resp = await axios.post(url, data, options.axios || {}); | ||
const resp = await axios__default['default'].post(url, data, options.axios || {}); | ||
await channel.headerHandler(resp.headers); | ||
@@ -537,3 +529,3 @@ return resp; | ||
const resp = await axios.put(url, data, options.axios || {}); | ||
const resp = await axios__default['default'].put(url, data, options.axios || {}); | ||
await channel.headerHandler(resp.headers); | ||
@@ -566,3 +558,3 @@ return resp; | ||
const resp = await axios.delete(url, options.axios || {}); | ||
const resp = await axios__default['default'].delete(url, options.axios || {}); | ||
await channel.headerHandler(resp.headers); | ||
@@ -671,3 +663,3 @@ return resp; | ||
try { | ||
let response = await axios(requestObject); | ||
let response = await axios__default['default'](requestObject); | ||
return response.data; | ||
@@ -740,193 +732,6 @@ } catch (err) { | ||
}const { | ||
EventEmitter | ||
} = require('events'); | ||
class Server { | ||
constructor(logger) { | ||
this._dialects = {}; | ||
this._channels = {}; | ||
this._clients = {}; | ||
this.session = {}; | ||
this.eventEmitter = new EventEmitter(); | ||
this.logger = logger || console; | ||
} | ||
registerDialect(_dialect) { | ||
this._dialects[_dialect.name] = _dialect; | ||
} | ||
registerChannel(_channel) { | ||
if (_channel.auth && !_channel.tokenValidator) { | ||
throw new Error('For authentication you need a token validator'); | ||
} | ||
if (_channel.type !== 'ws') { | ||
throw new Error('Only websocket listeners implemented yet!'); | ||
} | ||
this._channels[_channel.name] = _channel; | ||
this.session[_channel.name] = { | ||
clients: {}, | ||
tokens: {} | ||
}; | ||
} | ||
sendMessageToClient(channelName, clientID, event, message) { | ||
if (!this.session[channelName].clients[clientID]) { | ||
throw new Error('No user with given clientID'); | ||
} | ||
this.eventEmitter.emit(`sendEventTo:${clientID}`, { | ||
_type: 'event', | ||
event, | ||
message | ||
}); | ||
} | ||
getClientIDByToken(channelName, token) { | ||
let clientID = this.session[channelName].tokens[token].client; | ||
if (!clientID) { | ||
throw new Error('No user with given token'); | ||
} | ||
return clientID; | ||
} | ||
getTokenByClientID(channelName, clientID) { | ||
let token = this.session[channelName].clients[clientID].token; | ||
if (!token) { | ||
throw new Error('No user with given clientID'); | ||
} | ||
return token; | ||
} | ||
isTokenActive(channelName, token) { | ||
let clientID = this.session[channelName].tokens[token].client; | ||
return !!clientID; | ||
} | ||
isClientActive(channelName, clientID) { | ||
let token = this.session[channelName].clients[clientID].token; | ||
return !!token; | ||
} | ||
applyChannel(channelName, wss) { | ||
const channel = this._channels[channelName]; | ||
if (!channel) { | ||
throw new Error(`Channel with name ${channelName} is not registered!`); | ||
} | ||
wss.on('connection', async (ws, req) => { | ||
let clientID = generateUUID(); | ||
this.session[channelName].clients[clientID] = {}; | ||
if (channel.auth) { | ||
const token = req.headers['sec-websocket-protocol']; | ||
if (!token || token.length === 0) { | ||
return ws.close(); | ||
} | ||
let check = await channel.tokenValidator(token); | ||
if (!check) { | ||
return ws.close(); | ||
} | ||
this.session[channelName].clients[clientID].token = token; | ||
this.session[channelName].tokens[token] = { | ||
client: clientID | ||
}; | ||
ws.id = clientID; | ||
} | ||
this.eventEmitter.on(`sendEventTo:${clientID}`, msg => { | ||
ws.send(JSON.stringify(msg)); | ||
}); | ||
ws.on('close', async () => { | ||
let token = this.session[channelName].clients[ws.id].token; | ||
delete this.session[channelName].clients[ws.id]; | ||
delete this.session[channelName].tokens[token]; | ||
}); | ||
ws.on('message', async message => { | ||
const parsed = JSON.parse(message); | ||
const dialect = parsed._dialect; | ||
if (!dialect) { | ||
return; | ||
} | ||
const id = parsed.id; | ||
const channelDialect = this._channels[channelName].dialects.includes(dialect); | ||
if (!channelDialect) { | ||
ws.send(JSON.stringify({ | ||
_type: 'rpcError', | ||
id, | ||
error: `The used dialect ${dialect} is not supported on this channel` | ||
})); | ||
} | ||
let headers = {}; | ||
if (channel.headerInjector) { | ||
try { | ||
let h = await channel.headerInjector(this.session[channelName].clients[ws.id].token); | ||
headers = Object.assign({}, h); | ||
} catch (err) { | ||
ws.send(JSON.stringify({ | ||
_type: 'rpcError', | ||
id, | ||
error: err.message, | ||
headers: Object.assign({}, headers, { | ||
serverTime: Date.now() | ||
}) | ||
})); | ||
throw err; | ||
} | ||
} | ||
let ctx = {}; | ||
ctx.token = this.session[channelName].clients[ws.id].token; | ||
ctx.clientID = ws.id; | ||
try { | ||
const returnValue = await this._dialects[dialect].onRequest(parsed, ctx); | ||
if (parsed._type === 'request') { | ||
ws.send(JSON.stringify({ | ||
_type: 'rpcResponse', | ||
id, | ||
result: returnValue, | ||
headers: Object.assign({}, headers, { | ||
serverTime: Date.now() | ||
}) | ||
})); | ||
} | ||
} catch (err) { | ||
ws.send(JSON.stringify({ | ||
_type: 'rpcError', | ||
id, | ||
error: err.message, | ||
headers: Object.assign({}, headers, { | ||
serverTime: Date.now() | ||
}) | ||
})); | ||
throw err; | ||
} | ||
}); | ||
}); | ||
} | ||
}var version = "2.1.0";var Comlink = { | ||
}var version = "2.1.1";var Comlink = { | ||
Client, | ||
Server, | ||
Storage: Storage$1, | ||
version | ||
};exports.default=Comlink; |
{ | ||
"name": "@dwmt/comlink", | ||
"version": "2.1.0", | ||
"version": "2.1.1", | ||
"description": "Communication library for lazy enthusiasts", | ||
"main": "dist/Comlink.js", | ||
"main": "dist/Comlink.ssr.js", | ||
"module": "dist/Comlink.esm.js", | ||
@@ -7,0 +7,0 @@ "scripts": { |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Minified code
QualityThis package contains minified code. This may be harmless in some cases where minified code is included in packaged libraries, however packages on npm should not minify code.
Found 1 instance in 1 package
1
66662
1529