var LNVue = (function (){ let _unique = new Date().getTime(); function uniqueID(){ return _unique++; } let currentPromises = {}; /*\ |*| |*| Base64 / binary data / UTF-8 strings utilities (#1) |*| |*| https://developer.mozilla.org/en-US/docs/Web/API/WindowBase64/Base64_encoding_and_decoding |*| |*| Author: madmurphy |*| \*/ /* Array of bytes to base64 string decoding */ function b64ToUint6 (nChr) { return nChr > 64 && nChr < 91 ? nChr - 65 : nChr > 96 && nChr < 123 ? nChr - 71 : nChr > 47 && nChr < 58 ? nChr + 4 : nChr === 43 ? 62 : nChr === 47 ? 63 : 0; } function base64DecToArr (sBase64, nBlockSize) { var sB64Enc = sBase64.replace(/[^A-Za-z0-9\+\/]/g, ""), nInLen = sB64Enc.length, nOutLen = nBlockSize ? Math.ceil((nInLen * 3 + 1 >>> 2) / nBlockSize) * nBlockSize : nInLen * 3 + 1 >>> 2, aBytes = new Uint8Array(nOutLen); for (var nMod3, nMod4, nUint24 = 0, nOutIdx = 0, nInIdx = 0; nInIdx < nInLen; nInIdx++) { nMod4 = nInIdx & 3; nUint24 |= b64ToUint6(sB64Enc.charCodeAt(nInIdx)) << 18 - 6 * nMod4; if (nMod4 === 3 || nInLen - nInIdx === 1) { for (nMod3 = 0; nMod3 < 3 && nOutIdx < nOutLen; nMod3++, nOutIdx++) { aBytes[nOutIdx] = nUint24 >>> (16 >>> nMod3 & 24) & 255; } nUint24 = 0; } } return aBytes; } /* Base64 string to array encoding */ function uint6ToB64 (nUint6) { return nUint6 < 26 ? nUint6 + 65 : nUint6 < 52 ? nUint6 + 71 : nUint6 < 62 ? nUint6 - 4 : nUint6 === 62 ? 43 : nUint6 === 63 ? 47 : 65; } function base64EncArr (aBytes) { var eqLen = (3 - (aBytes.length % 3)) % 3, sB64Enc = ""; for (var nMod3, nLen = aBytes.length, nUint24 = 0, nIdx = 0; nIdx < nLen; nIdx++) { nMod3 = nIdx % 3; /* Uncomment the following line in order to split the output in lines 76-character long: */ /* if (nIdx > 0 && (nIdx * 4 / 3) % 76 === 0) { sB64Enc += "\r\n"; } */ nUint24 |= aBytes[nIdx] << (16 >>> nMod3 & 24); if (nMod3 === 2 || aBytes.length - nIdx === 1) { sB64Enc += String.fromCharCode(uint6ToB64(nUint24 >>> 18 & 63), uint6ToB64(nUint24 >>> 12 & 63), uint6ToB64(nUint24 >>> 6 & 63), uint6ToB64(nUint24 & 63)); nUint24 = 0; } } return eqLen === 0 ? sB64Enc : sB64Enc.substring(0, sB64Enc.length - eqLen) + (eqLen === 1 ? "=" : "=="); } class LNVuePromise { constructor(label,executor){ this.promise = new Promise( (resolve,reject) => { executor( (v) => { this._s.state = "ready"; resolve(v); this.release(); }, (e) => { this._s.state = "failed"; reject(e); this.release(); } ); } ); if (!label) label = "N.D."; this._s = { label, state: "waiting" }; this.idx = uniqueID(); currentPromises[this.idx] = this._s; } label(){ return this._s.label; } state(){ return this._s.state; } release(){ setTimeout(()=>{ Vue.delete(currentPromises, this.idx); },1000); } then(){ return this.promise.then.apply(this.promise, arguments); } } class LNVueWebSocket { constructor(lnvue,o){ this.LNVue = lnvue; this.options = Object.assign({},o); if (!this.options.url) this.options.url = this.constructURL(); this._id = 1; this.defaultTimeout = 30000; this.websocket = null; this.callbacks = {}; this._state = "initialized"; this._retry = null; this.closing = false; } constructURL(){ var pageURI = window.location; var scheme = pageURI.scheme == "https" ? "wss:" : "ws:"; var host = pageURI.host; return scheme + "//" + host + "/socket"; } open(){ if (this._retry){ clearTimeout(this._retry); } this.closing = false; this.websocket = new WebSocket(this.options.url); this.websocket.onopen = (e) =>{ console.log("WebSocket connected"); this._state = "ONLINE"; }; this.websocket.onclose = (e)=>{ this._onclose(e); this._state = "OFFLINE"; }; this.websocket.onerror = (e)=>{ this._onerror(e); this._state = "ERROR"; }; this.websocket.onmessage = (e)=>{ this._onmessage(e); }; return this; } close(){ if (this.websocket){ this.closing = true; this.websocket.close(200,"close() called"); } } request(msgtype,msg,timeout){ let message = { id: this._id++, type: msgtype, message: msg, } if (!timeout) timeout = this.defaultTimeout; if (timeout != -1){ return new Promise((resolve,reject)=>{ let to = setTimeout(()=>{ delete this.callbacks[message.id]; reject("timed out"); },timeout); this.callbacks[message.id] = (msgtype,msg)=>{ clearTimeout(to); delete this.callbacks[message.id]; if (msgtype == "error") reject(msg); else resolve({type: msgtype,message: msg}); }; this.websocket.send( JSON.stringify(message) ); }); } else { new Promise((resolve,reject)=>{ this.websocket.send( JSON.stringify(message) ); resolve(); }); } } _onclose(evt){ this.websocket = null; this.options.onclose && this.options.onclose(evt); if (!this.closing) { this._retry = setTimeout(() => { this._retry = null; console.log("reconnect...") this.open(); }, 5000); } } _onerror(evt){ this.options.onerror && this.options.onerror(evt); } _onmessage(evt){ try { let j = JSON.parse(evt.data); let cb = this.callbacks[ j.id ]; cb && cb(j.type,j.message); } catch(exc){ console.log(exc,evt.data); } } } class LNVue { constructor(el,options = {}){ this.options = Object.assign({ routes: [], data: {}, }, options ); this._el = el; this.data = Object.assign({}, options.data, { LNVue: this, msg: "Hello World" }); this.promises = []; this.globals = { currentPromises, }; this.statusText = "LNVue preparing"; Vue.prototype.$LNVue = this; LNVue.$_ = this; this.navigation = {}; this.identity = { UniqueID: null, IdentityName: "", }; Promise .all(LNVue.promises) .then(()=>{ this.status("LNVue: starting"); LNVue.vueRouter.addRoutes([{ path: "*", component: { template: `

404 Not Found

The URL you tried to reach is not existing.`, }, }]); }, (cause)=>{ this.status("LNVue: start failed: " + cause); }); this.vue = null; } Start(){ Promise .all(this.promises) .then(()=>{ LNVue.onidle(()=>{ this.vue = new Vue({ el: this._el, data: this.data, router: LNVue.vueRouter, }); }); }); LNVue.onidle(()=>{ this.socket = new LNVueWebSocket(this); this.socket.open(); }); } Version(){ return "0.2alpha"; }; getCurrentPromises() { return this.globals.currentPromises; } status(){ if (arguments.length == 1){ this.statusText = arguments[0]; return this; } else if (arguments.length == 0){ return this.statusText; } else throw "LNVue.status(): too many arguments"; } addModule(modSpec){ if (modSpec.navigation instanceof Object){ LNVue.deepAssign(modSpec.navigation,this.navigation); } LNVue.$each(modSpec.routes,(key,route)=>{ if ((route instanceof Object) && route.url) { let p = LNVue.LNPromise( "addModule()", (resolve,reject)=>{ LNVue .fetch(route.url) .then((src)=>{ this.addRoute(key,{ template: src, data: ()=>{ return this.data; }, }); resolve(); }, (cause)=>{ console.log("loading route.url failed: ",cause); }); }); this.promises.push(p); } else if (route instanceof Object){ this.addRoute(key,{ template: route.template, data: ()=>{ return this.data; }, } ); } else { this.addRoute(key,{ template: route, data: ()=>{ return this.data; }, } ); } }); } addRoute(path,component){ let self = this; LNVue.vueRouter.addRoutes([ { path, component, }, ]); } /* Authentication API */ requestChallenges(identityName,secureAttributeTypeName){ return new Promise((resolve,reject)=>{ this.socket.request("AuthenticationRequest",{ IdentityName: identityName, SecureAttributeTypeName: secureAttributeTypeName, }) .then((challenges)=>{ resolve(challenges); }, (error)=>{ console.log("Login challenges could not be retrieved", error); } ); }); } authenticate(identityName,secureAttributeID,challenge,prove){ let authenticationProve = { IdentityName: identityName, SecureAttributeUniqueID: secureAttributeID, Challenge: challenge, Prove: prove, }; console.log(authenticationProve); this.socket.request("AuthenticationProve", authenticationProve) .then((identity)=>{ this.identity = identity.message; }, (error)=>{ this.identity = { IdentityName: "", UniqueID: null, } console.log("auth error",error); }); } } Object.defineProperty( LNVue, '$LNVue', { get: ()=>{ return LNVue.$_; }, }); LNVue.vueRouter = new VueRouter({ mode: 'history', routes: [], }); LNVue.$idles = []; LNVue.onidle = function(cb,thisval = null){ let scheduled = LNVue.$idles.length > 0; let n=0; for (;n{ while (LNVue.$idles.length > 0){ let idle = LNVue.$idles.pop(); idle[0].call(idle[1]); } },0); } LNVue.$each = function(oa,cb){ if (oa instanceof Array){ let result = []; oa.forEach((value,index)=>{ result.push(cb.call(value,index,value)); }); return result; } else if (oa instanceof Object){ let result = {}; Object.keys(oa).forEach((key)=>{ if (oa.hasOwnProperty(key)){ result[key] = cb.call(oa[key],key,oa[key]); } }); return result; } } LNVue.deepAssign = function(source,target){ LNVue.$each(source,function(key){ if (target[key] instanceof Object){ LNVue.deepAssign(src[key],target[key]); } else { target[key] = source[key]; } }); } LNVue.$ = function(src){ let el = document.createElement("parse"); el.innerHTML = src; return el.firstChild; } LNVue.routes = []; LNVue.promises = []; LNVue.fetch = function(url,cb){ return LNVue.LNPromise("loading",(resolve,reject)=>{ fetch(url) .then((response => { if (response.status.toString().startsWith("2")) { let t = response.text(); cb && cb(t,null); resolve(t); } else { cb && cb(null, response.statusText); reject(response.statusText); } })); }); } LNVue.each = function(o,cb){ if (o instanceof Array) o.forEach((value,index)=> cb(value,index) ); else Object.keys(o).forEach((key)=>{ if (o.hasOwnProperty(key)) cb(o[key],key); }); }; LNVue.LNPromise = function(label, action){ console.log(label,action); return new LNVuePromise(label, action); } LNVue.encodeB64 = base64EncArr; LNVue.decodeB64 = base64DecToArr; LNVue.encodeHex = (bytes) => bytes.reduce((str, byte) => str + byte.toString(16).padStart(2, '0'), ''); LNVue.decodeHex = (hexString) => new Uint8Array(hexString.match(/.{1,2}/g).map(byte => parseInt(byte, 16))); ArrayBuffer.combine = function(...args){ let byteLength = 0; args.forEach((arg,index)=>{ byteLength = byteLength + arg.byteLength; }); let result = new Uint8Array(byteLength); let p = 0; args.forEach((arg,index)=>{ for (let n=0;n