hugo-theme-cyberscopes/assets/js/common.ts

164 lines
3.6 KiB
TypeScript

import { createApp } from 'petite-vue'
import { domain, nopoll } from '@params'
type Config = {
apiurl: string
pollurl: string
domain: string
itemid: string
sid: string
iid: string
nopoll: boolean
}
export function config (api, polling): Config {
const pu = polling ? `${api.path}/${polling.msgbase.join('/')}` : ''
const urlparams = new URL(location.href).searchParams
return {
apiurl: api.path,
pollurl: pu,
domain: domain,
itemid: urlparams.get('id'),
sid: getSid(),
iid: createRandString(1),
nopoll: nopoll
}
}
export const pvapp = {
run(conf: Config) {
appdata.conf = conf
createApp(appdata).mount()
if (appdata.conf.pollurl && !appdata.conf.nopoll) {
appdata.poll()
}
}
}
const appdata = {
$delimiters: ['{|', '|}'],
conf: {} as Config,
components: {},
output: '',
handle,
poll,
mounted(name: string) {
console.log('app mounted: ', name)
},
Data
}
// components
function Data(name, action, domain: string): object {
domain = domain || this.conf.domain
const comp = {
name: name, // -> class of incoming/outgoing message
action: action, // (default) action of outgoing message
domain: domain, // domain of incoming/outgoing message
data: {}, // model (2-way data store)
exec // default function to execute upon button click
}
appdata.components[name] = comp
return comp
}
// appdata and component method definitions
function exec() {
const data = this.data
const conf = this.conf
let value = ''
for (const k of Object.keys(data)) {
value += `${k}: ${data[k]}, `
}
this.output += '\n' + value
console.log('exec:', value)
sendMsg(conf, [this.domain, this.action, this.name, data.id], data)
}
function handle(msg) {
const data = JSON.parse(msg.payload)
const [ domain, action, class_, item ] = msg.path.split('/')
//console.log('msgbase: ', domain, action, class_, item)
// TODO: check message parts (using default values), select handler fct
const comp = this.components[class_ || 'data']
if (domain && domain != comp.domain) {
return
}
if (comp != undefined) {
Object.assign(comp.data, data)
}
}
function poll() {
dopoll(this)
}
// basic functions - move to api.ts
async function sendMsg(conf: Config, basemsg: string[], data: any) {
const url = `${conf.apiurl}/${basemsg.join('/')}`
await send(url, conf, data)
}
async function send(url: string, conf: Config, data: any) {
data._interaction = conf.iid
const body = JSON.stringify(data)
const headers = {}
headers['X-Integrator-Session'] = conf.sid
return fetch(url, {
method: 'POST',
headers: headers,
body: body
})
}
function createRandString(size: number): string {
const arr = new Uint32Array(size)
crypto.getRandomValues(arr)
const result: string[] = []
arr.forEach((x) => result.push(x.toString(36)))
return result.join('')
}
function getSid(): string {
const sid_key = 'api.sessionid'
let sid = localStorage.getItem(sid_key)
if (!sid) {
sid = createRandString(2)
localStorage.setItem(sid_key, sid)
}
return sid
}
//console.log("sid: ", getSid())
// TODO: clear sid - when?
//localStorage.setItem('api.sessionid', '')
async function dopoll(app: typeof appdata) {
const wait_time = 10000
while (true) {
try {
const res = await(send(app.conf.pollurl, app.conf, {}))
const msg = await res.json()
console.log(msg)
switch (msg.status) {
case 'idle':
break
case 'data':
app.handle(msg)
break
default:
console.log('poll response: ', msg)
await sleep(wait_time)
}
} catch (error) {
console.log(error)
await sleep(wait_time)
}
}
}
const sleep = (delay: number) => new Promise(r => setTimeout(r, delay))