m2m
Version:
m2m is a client module for machine-to-machine communication framework node-m2m for cloud and edge computing.
8 lines • 16.5 kB
JavaScript
/**!
* node-m2m.js
* v1.0.9
*
* Copyright(c) 2020 Ed Alegrid
*
*/
const NodeM2M=function(){let e=[],t={};const n=new class{constructor(){this.target=new EventTarget}on(t,n){return e.push(t),this.target.addEventListener(t,n)}once(e,t){return this.target.addEventListener(e,t,{once:!0})}off(t,n){let r=e.indexOf(t);return r&&e.splice(r,1),this.target.removeEventListener(t,n)}emit(t,n){return this.target.dispatchEvent(new CustomEvent(t,{detail:n,cancelable:!0})),e.includes(t)}};var r=null;const o=function(){let e="https://www.node-m2m.com",t=!1;const r=/^[A-Za-z0-9-_\/]*$/,o=/^[A-Za-z0-9 \[\]"{}':,._-]*$/,i={nodev:"-",npmv:"-",type:navigator.platform,mem:"-",m2mv:"v1.0.9",os:navigator.platform,browser:!0,online:navigator.onLine,language:navigator.language};return"Linux x86_64"===i.os&&(i.os="linux"),{rid:function(e){return function(e){let t="";for(let n=0;n<e;n++)t+="x";return t}(e).replace(/[xy]/g,(e=>{let t=16*Math.random()|0;return("x"==e?t:3&t|8).toString(16)}))},genUID:function(){return"xxxxxxxx-xxxx-5xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,(function(e){let t=16*Math.random()|0;return("x"==e?t:3&t|8).toString(16)}))},setError:function(e,t,r){try{let o=new Error(e);if(1006===e.code&&(o=new Error("ws close "+e.code)),n.emit("node-m2m-error",o))return;if(t)t({error:o.message});else{if(!r)throw o;1006===e.code?console.log("ws close error: "+e.code):r(o)}}catch(e){console.log("set error",e)}},systemInfo:i,getValidUrl:function(){return t},setValidUrl:function(e){t=e},getDefaultUrl:function(){return e},setDefaultUrl:function(t){return e=t,e},setEpErrorEvent:function(e,t){if("error"!==e)throw new Error(e+" event name is invalid");let r="node-m2m-"+e;n.on(r,(e=>{if("object"==typeof e)return t(e);"string"==typeof e&&t(e)}))},setActiveSyncData:function(e,t){if(t.length>0)for(let n=0;n<t.length;n++)if(t[n]&&t[n].id===e.id&&t[n].name===e.name)return!0;return t.push(e),!1},validateNameAndPayload:function(e){let t=!0,n=null,i=null;try{if(!e)throw new Error("invalid empty arg");if(Array.isArray(e)&&(i=e[0]),i&&(e=i),e.name&&("string"!=typeof e.name&&(t=null),e.name.length>75&&(t=null),e.name.match(r),!t))throw new Error("invalid channel/path");if((e.payload||e.body)&&(e.payload?n=e.payload:e.body&&(n=e.body),"number"==typeof n||"object"==typeof n||"string"==typeof n||(t=null)),n&&(n=JSON.stringify(n),n&&n.length>500&&(t=null),n&&n.match(o),!t)){if(e.payload)throw e.payload=null,new Error("write/sendData - invalid payload data");if(e.body)throw e.body=null,new Error("post - invalid body data")}return t}catch(e){throw e}}}}();let i=function(){let e=o.genUID(),t=o.rid(8);sessionStorage.getItem("clientId")?t=sessionStorage.getItem("clientId"):sessionStorage.setItem("clientId",t);let n={_sid:"m2m",id:t,clientId:t,srcId:t,src:"browser-client",_pid:"r-b",b:!0,browser:!0,uid:e,clientId:t,event:!1,watch:!1,active:!0,enable:!0,tid:Date.now()};return n.systemInfo=o.systemInfo,n}();const s=function(){function e(e,t,n,r,s){let l=function(e,t){let n=o.getDefaultUrl();if("object"!=typeof e)throw new Error("invalid http server");return e.url?n=e.url:e.server&&(n=e.server),n+e.path}(e),a={headers:{"Content-Type":"application/json",Authorization:"Bearer "+i.clientId,"X-API-Key":e.apiKey,"x-spl":"node-m2m-is-awesome","CSRF-Token":"csrfTkn"},method:"GET",referrerPolicy:"no-referrer"};if("GET"===t)a.method=t;else if("POST"===t){if(!e.body)return console.log("post error: invalid body"),n("invalid post body");if(a.method=t,"object"!=typeof e.body)throw"invalid http post body type - it must be an object";a.body=JSON.stringify(e.body)}fetch(l,a).then((function(e){return e.json()})).then((function(e){if(e.error){if(n)return void n(e.error);if(s)return void s(e.error)}("object"==typeof e||e)&&setTimeout((function(){n?n(e):r&&r(e)}),10)})).catch((function(e){e&&setTimeout((function(){n?n(e):s&&s(e)}),10)}))}return o.rid(12),{get:function(t,n){return new Promise((function(r,o){e(t,"GET",n,r,o)}))},post:function(t,n){return new Promise((function(r,o){e(t,"POST",n,r,o)}))},connect:function(t,n){return t.path="/m2m/usr/connect",t.body=Object.assign({},i,t),new Promise((function(r,o){e(t,"POST",n,r,o)}))}}}();let l=function(){let e=new EventTarget,s={},l=null,a=null,c=0,u=!1,d=!1,f=null;function h(e,n,r,s){if(125===e.code&&e.aid)delete e.code,i=e;else if(200!==e.code&&210!==e.code&&220!==e.code||"success"!==e.reason)"unauthorized"===e.result&&(n?n("unauthorized"):s?s("unauthorized"):r?r("unauthorized"):o.setError("unauthorized",n,s));else{if(t=Object.assign({},i),!e.servers)throw new Error("rxConnectionData - invalid spl");t.servers=e.servers,t.accessTkn&&delete t.accessTkn,t.tkn&&delete t.tkn,t.eatkn&&(delete t.eatkn,delete t.euc,delete t.esc),setTimeout((function(){n?n("success"):r?(r("success"),d&&console.log("reconnect - success")):console.log("connection: success"),d=!0}),10)}}function p(e){let t=null;e.activeStart?r.startServerActiveSyncOnlineEvent(e):e.exit?r.setServerActiveSyncOffLineEvent(e):e.getServers||e.serverSetup?t=e.id+e._pid:(e.name||e.channel||e.topic)&&(t=e.id+e.name+e.eventId),n.emit(t,e)}function v(e,n,d){a||(a=o.getDefaultUrl()),l=new WebSocket(a+"/m2m"),l.onerror=function(e){},l.onopen=function(e){1===l.readyState&&function(e){if(!e)throw"ws.onopen - invalid initial payload";c=0,u&&(e._pid="v-ep"),l.send(JSON.stringify(e)),u=!0,r.activateServerActiveSyncOnlineEvent(s)}(i)},l.onmessage=function(t){try{1===l.readyState&&(s=JSON.parse(t.data),Array.isArray(s)&&Object.keys(s[0]).length>0?(s=s[0],(s.browserId||s.activeStart||s.exit)&&setTimeout(p,10,s)):Object.keys(s).length>0&&setTimeout(h,10,s,e,n,d))}catch(t){console.log("ws.onmessage - JSON.parse:",t.message)}},l.onclose=function(r){1006===r.code&&o.setError(r,e,d),function(e,n,r,o){let i=Math.floor(1e4*Math.random()+1e4);if(1006===e.code||1003===e.code){if(u||t.aid||0===c&&console.log("Server is down or not ready."),!f)return void console.log("Please try again later.");0===c&&(u&&console.log("Server is down or not ready."),console.log("Please try again later or wait until the server is up again."),console.log("Attempt to reconnect 1 ...")),1===c&&console.log("There is no response from server\nAttempt to reconnect 2 ..."),2===c&&console.log("Cannot establish a connection with the server"),(3===c||c>3)&&console.log("Waiting for the server to be up and running ..."),setTimeout(v,i,n,r,o),c++}}(r,e,n,d)}}return{connect:function(e,t){try{return function(e,t){if(!i)throw"invalid connection";if("object"==typeof e)e.accessTkn?i.eatkn=btoa(e.accessTkn):e.tkn&&(i.eatkn=btoa(e.tkn)),e.userid&&e.pw?i.euc=btoa(JSON.stringify({email:e.userid,pw:e.pw,ref:o.rid(8)})):e.sc&&(i.esc=btoa(e.sc)),void 0===e.restart&&(f=!0),e.restart?f=!0:!1===e.restart&&(f=null),e.name&&(i.systemInfo.name=e.name),e.location&&(i.systemInfo.location=e.location),(e.url||e.server)&&function(e){"object"==typeof e?e.url?a=e.url:e.server&&(a=e.server):"string"==typeof e&&(a=o.getDefaultUrl()),a.includes("http")?a=a.replace("http","ws"):a.includes("https")&&(a=a.replace("https","wss")),a.includes("127.0.0.1:3000")||a.includes("https")||a.includes("wss")||(console.log("connect url must be secure TLS"),a=null)}(e);else{if("string"!=typeof e)return void console.log("setConnectPayload - invalid access error");i.accessTkn=e}if(e.accessTkn?i.browserId=e.accessTkn.slice(7,31):e.tkn&&(i.browserId=e.tkn.slice(7,31)),"function"!=typeof t)return new Promise(((e,n)=>{v(t,e,n)}));v(t)}(e,t)}catch(e){return"Server is not ready"}},webSocket:function(){return l},getEventEmitter:function(){return e},getConnectionStatus:function(){return u},setConnectionStatus:function(e){return u=e}}}(),a=function(){let e=!1,a=0,c={},u=[],d=!0,f=[];function h(e,n,r){1===n.readyState&&(t.aid?n.send(JSON.stringify(r)):setTimeout((function(){n.send(JSON.stringify(r))}),e))}function p(r,i,s,c,h,p,v){let g={};if("string"==typeof r&&h&&("function"==typeof i&&(v=i,"watch"===p&&(c=5e3)),"function"==typeof s&&(v=s),"function"==typeof c&&(v=c,Number.isInteger(i)&&(c=i)),"write"!==p&&"sendData"!==p&&"post"!==p||(s=i),i=r,r=h),Number.isInteger(r)?(g.id=r,"string"==typeof i&&("get"===p||"post"===p?g.path=i:g.channel=i),"number"!=typeof s&&"string"!=typeof s&&"object"!=typeof s||("post"===p?g.body=s:"write"!==p&&"sendData"!==p||(g.payload=s)),"function"==typeof c&&(v=c,c=5e3),Number.isInteger(c)&&(g.interval=c)):"object"==typeof r&&(v=i,h&&(r.id=h),"watch"===p&&(r.interval||(r.interval=5e3)),"function"==typeof i&&(v=i),g=r),!g.id)throw console.log(g),new Error("validateClientApi error - missing id");if("get"===p||"post"===p){if(!g.path)throw console.log(g),new Error("validateClientApi error - missing path")}else if(g.topic);else if(!g.channel)throw console.log(g),new Error("validateClientApi error - missing channel");if("post"===p){if(!g.body)throw console.log(g),new Error("validateClientApi error - missing body")}else if(("write"===p||"sendData"===p)&&!g.payload)throw console.log(g),new Error("validateClientApi error - missing payload");if("watch"===p&&!g.interval)throw console.log(g),new Error("validateClientApi error - missing interval");return new Promise((function(r,i){"function"==typeof v&&(r=null,i=null),function(r,i,s,c,h){let p=l.webSocket();if(1!==p.readyState)return;if(!t.browserId)throw new Error("setClientPayloadData system error - invalid/missing browserId");if(!t.clientId)throw new Error("setClientPayloadData system error - invalid/missing clientId");let v=Object.assign({},t,r);if(v.dst="server",v.eventId=o.rid(8),v.browser&&(v.srcId||(v.srcId=v.clientId)),v.id&&!v.dstId&&(v.dstId=v.id),v.id===v.dstId&&v.srcId===v.dstId)throw new Error("setClientPayloadData error - invalid id that will cause a race condition");if(v[i]=!0,v.method=i,v.get||v.post?(v._pid="http-data",v.http=!0,v.name=r.path,v=function(e,t){let n=null,r=null;const o=[],i=[],s={};if(!t.startsWith("/")){let e="invalid url, it must begin with a slash /";throw console.log(e),e}let l=t.indexOf("?",1);-1!==l&&(n=t.substring(l+1,t.length)),new URLSearchParams(n).forEach((function(e,t){s[t]=e}));let a=t.indexOf("?");-1!==a&&(t=t.slice(0,a));for(let e=0;e<t.length;e++)"/"===t[e]&&o.push(e);o.forEach((function(e,n){if(0==e&&o[n+1]){let e=t.slice(o[n],o[n+1]);i.push(e)}else if(0!==e&&o[n]&&o[n+1]){let e=t.slice(o[n],o[n+1]);i.push(e)}else{let e=t.slice(o[n],t.length);i.push(e)}}));let c=i[0].length;r=t.indexOf("?"),-1===r&&(r=t.length);let u=t.slice(c,r);return e.urlPathKeys=i,e.baseUrl=i[0],e.pathUrl=u,e.queryString=n,e.query=s,n||(e.query={}),e}(v,v.path)):(v._pid="channel-data",v.channel?(v.name=v.channel,v.topic=v.channel):v.topic&&(v.name=v.topic,v.channel=v.topic),v=function(e,t){const n=[],r=[];if(!t.startsWith("/"))return e;if(t.includes("?"))throw t+" - invalid topic attribute";for(let e=0;e<t.length;e++)("/"===t[e]||"#"===t[e])&&n.push(e);n.forEach((function(e,o){if(0===e&&n[o+1]){let e=t.slice(n[o],n[o+1]);r.push(e)}else if(0!==e&&n[o]&&n[o+1]){let e=t.slice(n[o],n[o+1]);r.push(e)}else{let e=t.slice(n[o],t.length);r.push(e)}}));let o={};r[0]===t&&1===r.length&&(o.root=r[0]);let i=r[0].length,s=t.slice(i);return e.topicKeys=r,e.baseTopic=r[0],e.subTopic=s,e.rootTopic=o.root,e}(v,v.topic),v.watch&&(v.polling?v.interval=v.polling:v.poll&&(v.interval=v.poll),v.interval?v.interval<1e3&&(v.interval=5e3):v.interval=5e3)),!v.name)throw new Error("system error - client data invalid/missing pl.name");if(v.watch?(v.watch=!0,v.event=!0):(v.watch=!1,v.event=!1),function(e){if(!e._pid)throw new Error("system error - client data invalid/missing pl._pid");if(!e.name)throw new Error("system error - client data invalid/missing pl.name");if(!e.eventId)throw new Error("system error - client data invalid/missing pl.eventId");if(e.get||e.post){if(!e.path)throw new Error("system error - client data invalid/missing pl.path");if(e.post&&!e.body)throw new Error("system error - client data invalid/missing pl.body")}else{if(!e.channel)throw new Error("system error - client data invalid/missing pl.channel");if((e.write||e.sendData)&&!e.payload)throw new Error("system error - client data invalid/missing pl.payload");if(e.watch&&!e.interval)throw new Error("system error - client data invalid/missing pl.interval")}}(v),o.validateNameAndPayload(v),function(t){let n=!1;if(!t.servers)throw new Error("Invalid server id");var r;return t.servers.forEach((e=>{e===t.id&&(n=!0)})),n?a<1&&(r=t,d&&(r.unwatch||f.push(r))):e||(n=!1),n}(v))(function(e,t,r,i){let s=e.id+e.name+e.eventId,l=Math.floor(100*Math.random());function a(c){let d=c.detail;d.eventId===e.eventId&&(d.error?o.setError(d.error,t,i):d.unwatch?(function(e,t,n){if(t.length>0)for(let r=0;r<t.length;r++)try{if(t[r]&&e.name&&e.unwatch&&t[r].id===e.id&&t[r].name===e.name)return t.splice(r,1),n(null)}catch(e){console.log("removeActiveSyncDataEvent error",e),n(e)}}(d,u,((e,r)=>{if(e){if(t)return t(e,null);if(i)return i(e)}n.off(s,a)})),setTimeout((function(){return t?t(d.result):r?r(d.result):void 0}),l)):d.value?setTimeout((function(){t?t(d.value):r&&r(d.value)}),l):d.result&&setTimeout((function(){t?t(d.result):r&&r(d.result)}),l))}if(e.event&&e.watch){if(o.setActiveSyncData(e,u))return void n.off(s,a);n.on(s,a)}else n.once(s,a)})(v,s,c,h),1===p.readyState&&setTimeout((function(){p.send(JSON.stringify(v))}),5);else{let e="server["+v.id+"] - id "+v.id+" is not registered";o.setError(e,s,h)}}(g,p,v,r,i)}))}function v(e,t,n){return p(e,t,null,null,this.id,"read",n)}function g(e,t,n,r){return p(e,t,n,null,this.id,"write",r)}function m(e,t,n,r){return p(e,t,null,n,this.id,"watch",r)}function y(e,t,n){return p(e,t,null,null,this.id,"unwatch",n)}function w(e,t,n){return p(e,t,null,null,this.id,"get",n)}function b(e,t,n,r){return p(e,t,n,null,this.id,"post",r)}function S(e,t,n){const r="sec-cli";return"object"==typeof e&&"function"==typeof t&&(e.channel=r,e.topic=r,n=t,e.cmd&&(e.payload=e.cmd),e.command&&(e.payload=e.command)),"string"==typeof e&&"function"==typeof t&&(n=t),"string"==typeof e&&(t=e,e=this.id),p(e,r,t,null,this.id,"write",n)}function E(e,t,r,i){let s=e.id+e._pid,l=Math.floor(50*Math.random());n.once(s,(function(n){let s=n.detail;s.id===e.id&&s._pid===e._pid&&(s.error?o.setError(s.error,t,i):t?setTimeout((function(){s.serverSetup?t(s.serverSetup):s.epServers&&t(s.epServers)}),l):r&&setTimeout((function(){s.serverSetup?r(s.serverSetup):s.epServers&&r(s.epServers)}),l))}))}function I(e,n){try{let r=l.webSocket();const o=Object.assign({},t);return"function"==typeof e?(n=e,o.id=this.id):o.id=e||n?e:this.id,o.dst="server",o._pid="serverSetup",o.serverSetup=!0,o.serverSystemInfo=!0,new Promise((function(e,t){E(o,n,e,t),h(1500,r,o)}))}catch(e){throw e}}function x(e){try{let n=l.webSocket();const r=Object.assign({},t);return r._pid="get-available-servers",r.getServers=!0,this.id?r.id=this.id:r.id=r.clientId,new Promise((function(t,o){E(r,e,t,o),h(1500,n,r)}))}catch(e){o.logEvent("getServers error:",e.message)}}function T(e){this.id=e}function O(e,t){let n=[],r=Math.floor(100*Math.random());try{Number.isInteger(e)?c=[e]:"object"==typeof e?e.id&&(c=[e.id]):Array.isArray(e)&&(c=e);for(let e=0;e<c.length;e++){if(!Number.isInteger(c[e]))throw console.log("invalid server id: "+c[e]),new Error("server id must be an integer number");n[e]=new T(c[e])}if(!t)return 1===n.length?n[0]:n;t&&(n.length>1?setTimeout((function(){t(n)}),r):setTimeout((function(){t(n[0])}),r))}catch(e){throw e}}return setTimeout((()=>{}),5e3),T.prototype={constructor:T,cli:S,getServers:x,getServerInfo:I,read:v,write:g,get:w,post:b,unsub:y,unsubscribe:y,sub:m,subscribe:m},i.options||(i.options={}),arguments.length>0&&"object"==typeof arguments[0]&&(i.options.userSettings=arguments[0],i.options.userSettings.src="browser"),r={cli:S,get:w,post:b,watch:m,unwatch:y,getServers:x,getServerInfo:I,read:v,write:g,sub:m,subscribe:m,unsub:y,unsubscribe:y,getResources:I,authenticate:l.connect,connect:l.connect,on:o.setEpErrorEvent,access:O,accessServer:O,httpGet:s.get,httpPost:s.post,httpConnect:s.connect,setServerActiveSyncOffLineEvent:function(e){u.forEach((t=>{if((t.id===e.id||t.dstId===e.id)&&t.aid===e.aid){let t="server["+e.id+"] is offline";console.log(t),activeSyncTry=0}}))},startServerActiveSyncOnlineEvent:function(e){let t=l.webSocket();0===a&&a++,u.forEach((n=>{if((n.id===e.id||n.dstId===e.id)&&n.aid===e.aid){let r="server["+e.id+"] is online";console.log(r),t.send(JSON.stringify(n))}}))},activateServerActiveSyncOnlineEvent:function(e){if(u.length>0){let e=l.webSocket();setTimeout((()=>{u.forEach((t=>{e.send(JSON.stringify(t))}))}),1e3)}}}};return{Client:a,createClient:a}};M2M=NodeM2M;