@eva-ics/webengine
Version:
EVA ICS HMI Web Engine
1,509 lines (1,508 loc) • 77.5 kB
JavaScript
var j = Object.defineProperty;
var P = (e, t, s) => t in e ? j(e, t, { enumerable: !0, configurable: !0, writable: !0, value: s }) : e[t] = s;
var n = (e, t, s) => (P(e, typeof t != "symbol" ? t + "" : t, s), s), $ = (e, t, s) => {
if (!t.has(e))
throw TypeError("Cannot " + s);
};
var N = (e, t, s) => ($(e, t, "read from private field"), s ? s.call(e) : t.get(e)), x = (e, t, s) => {
if (t.has(e))
throw TypeError("Cannot add the same private member more than once");
t instanceof WeakSet ? t.add(e) : t.set(e, s);
}, B = (e, t, s, i) => ($(e, t, "write to private field"), i ? i.call(e, s) : t.set(e, s), s);
import { Logger } from "bmat/log";
import { cookies } from "bmat/dom";
var m = Object.defineProperty, M = (e, t, s) => t in e ? m(e, t, { enumerable: !0, configurable: !0, writable: !0, value: s }) : e[t] = s, g = (e, t, s) => (M(e, typeof t != "symbol" ? t + "" : t, s), s), W = (e, t, s) => {
if (!t.has(e))
throw TypeError("Cannot " + s);
}, u = (e, t, s) => (W(e, t, "read from private field"), s ? s.call(e) : t.get(e)), E = (e, t, s) => {
if (t.has(e))
throw TypeError("Cannot add the same private member more than once");
t instanceof WeakSet ? t.add(e) : t.set(e, s);
}, h = (e, t, s, i) => (W(e, t, "write to private field"), i ? i.call(e, s) : t.set(e, s), s);
class C {
constructor() {
g(this, "subscribers"), g(this, "subtopics"), g(this, "subtopics_by_regex"), g(this, "subtopics_any"), g(this, "sub_any"), this.subscribers = /* @__PURE__ */ new Set(), this.subtopics = /* @__PURE__ */ new Map(), this.subtopics_by_regex = [], this.sub_any = /* @__PURE__ */ new Set();
}
isEmpty() {
return this.subscribers.size === 0 && this.subtopics.size === 0 && this.subtopics_by_regex.length === 0 && this.subtopics_any === void 0 && this.sub_any.size === 0;
}
}
var l, _, f, p, y;
class I {
constructor() {
g(this, "subscriptions"), g(this, "subscribed_topics"), E(this, l, void 0), E(this, _, void 0), E(this, f, void 0), E(this, p, void 0), E(this, y, void 0), this.subscriptions = new C(), this.subscribed_topics = /* @__PURE__ */ new Map(), h(this, l, 0), h(this, _, "/"), h(this, p, /* @__PURE__ */ new Set(["?"])), h(this, y, /* @__PURE__ */ new Set(["*"]));
}
separator(t) {
return h(this, _, t), this;
}
regexPrefix(t) {
return h(this, f, t), this;
}
matchAny(t) {
return Array.isArray(t) ? h(this, p, new Set(t)) : h(this, p, /* @__PURE__ */ new Set([t])), this;
}
wildcard(t) {
return Array.isArray(t) ? h(this, y, new Set(t)) : h(this, y, /* @__PURE__ */ new Set([t])), this;
}
listClients() {
return Array.from(this.subscriptions.subscribers);
}
listTopics(t) {
return Array.from(this.subscribed_topics.get(t) || []);
}
isEmpty() {
return this.subscribed_topics.size === 0;
}
registerClient(t) {
return this.subscribed_topics.has(t) ? !1 : (this.subscribed_topics.set(t, /* @__PURE__ */ new Set()), !0);
}
unregisterClient(t) {
const s = this.subscribed_topics.get(t);
if (s === void 0)
return !1;
for (const i of s)
d(
this.subscriptions,
i.split(u(this, _)),
0,
t,
u(this, y),
u(this, p),
u(this, f)
), h(this, l, u(this, l) - 1);
return this.subscribed_topics.delete(t), !0;
}
subscribe(t, s) {
const i = this.subscribed_topics.get(s);
return i === void 0 ? !1 : (i.has(t) || (R(
this.subscriptions,
t.split(u(this, _)),
0,
s,
u(this, y),
u(this, p),
u(this, f)
), i.add(t), h(this, l, u(this, l) + 1)), !0);
}
unsubscribe(t, s) {
const i = this.subscribed_topics.get(s);
return i === void 0 ? !1 : (i.has(t) && (d(
this.subscriptions,
t.split(u(this, _)),
0,
s,
u(this, y),
u(this, p),
u(this, f)
), i.delete(t), h(this, l, u(this, l) - 1)), !0);
}
unsubscribeAll(t) {
const s = this.subscribed_topics.get(t);
if (s === void 0)
return !1;
for (const i of s)
d(
this.subscriptions,
i.split(u(this, _)),
0,
t,
u(this, y),
u(this, p),
u(this, f)
);
return h(this, l, u(this, l) - s.size), s.clear(), !0;
}
getSubscribers(t) {
const s = /* @__PURE__ */ new Set();
return z(
this.subscriptions,
t.split(u(this, _)),
0,
u(this, f),
s
), s;
}
isSubscribed(t) {
return v(
this.subscriptions,
t.split(u(this, _)),
0,
u(this, f)
);
}
subscriptionCount() {
return u(this, l);
}
clientCount() {
return this.subscribed_topics.size;
}
}
l = /* @__PURE__ */ new WeakMap(), _ = /* @__PURE__ */ new WeakMap(), f = /* @__PURE__ */ new WeakMap(), p = /* @__PURE__ */ new WeakMap(), y = /* @__PURE__ */ new WeakMap();
function R(e, t, s, i, a, r, o) {
if (s < t.length) {
const c = t[s];
if (a.has(c))
e.sub_any.add(i);
else if (r.has(c))
e.subtopics_any || (e.subtopics_any = new C()), R(
e.subtopics_any,
t,
s + 1,
i,
a,
r,
o
);
else if (o && c.startsWith(o)) {
const A = c.slice(o.length);
try {
const k = new RegExp(A);
let b = e.subtopics_by_regex.find(
(T) => T.regex.source === k.source
);
b || (b = {
regex: k,
sub: new C()
}, e.subtopics_by_regex.push(b)), R(
b.sub,
t,
s + 1,
i,
a,
r,
o
);
} catch {
}
} else
e.subtopics.has(c) || e.subtopics.set(c, new C()), R(
e.subtopics.get(c),
t,
s + 1,
i,
a,
r,
o
);
} else
e.subscribers.add(i);
}
function d(e, t, s, i, a, r, o) {
if (s < t.length) {
const c = t[s];
if (a.has(c))
e.sub_any.delete(i);
else if (r.has(c))
e.subtopics_any && (d(
e.subtopics_any,
t,
s + 1,
i,
a,
r,
o
), e.subtopics_any.isEmpty() && (e.subtopics_any = void 0));
else if (o && c.startsWith(o)) {
const A = c.slice(o.length);
try {
const k = new RegExp(A), b = e.subtopics_by_regex.findIndex(
(T) => T.regex.source === k.source
);
if (b !== -1) {
const T = e.subtopics_by_regex[b].sub;
d(
T,
t,
s + 1,
i,
a,
r,
o
), T.isEmpty() && e.subtopics_by_regex.splice(b, 1);
}
} catch {
}
} else {
const A = e.subtopics.get(c);
A && (d(
A,
t,
s + 1,
i,
a,
r,
o
), A.isEmpty() && e.subtopics.delete(c));
}
} else
e.subscribers.delete(i);
}
function z(e, t, s, i, a) {
if (s < t.length) {
const r = t[s];
for (const o of e.sub_any)
a.add(o);
if (i && r.startsWith(i)) {
const o = r.slice(i.length);
try {
const c = new RegExp(o);
for (const [A, k] of e.subtopics)
c.test(A) && z(k, t, s + 1, i, a);
} catch {
}
} else {
const o = e.subtopics.get(r);
o && z(o, t, s + 1, i, a);
}
for (const o of e.subtopics_by_regex)
o.regex.test(r) && z(o.sub, t, s + 1, i, a);
e.subtopics_any && z(
e.subtopics_any,
t,
s + 1,
i,
a
);
} else
for (const r of e.subscribers)
a.add(r);
}
function v(e, t, s, i) {
if (s < t.length) {
const a = t[s];
if (e.sub_any.size > 0)
return !0;
if (i && a.startsWith(i)) {
const r = a.slice(i.length);
try {
const o = new RegExp(r);
for (const [c, A] of e.subtopics)
if (o.test(c) && v(A, t, s + 1, i))
return !0;
} catch {
}
} else {
const r = e.subtopics.get(a);
if (r && v(r, t, s + 1, i))
return !0;
}
for (const r of e.subtopics_by_regex)
if (r.regex.test(a) && v(r.sub, t, s + 1, i))
return !0;
if (e.subtopics_any && v(
e.subtopics_any,
t,
s + 1,
i
))
return !0;
} else if (e.subscribers.size > 0)
return !0;
return !1;
}
const eva_webengine_version = "0.9.15", WILDCARDS = ["*", "#"], MATCH_ANY = ["+", "?"], isMask = (e) => {
for (let t of e)
if (WILDCARDS.includes(t) || MATCH_ANY.includes(t))
return !0;
return !1;
};
var SerializationKind = /* @__PURE__ */ ((e) => (e.JSON = "json", e.MsgPack = "msgpack", e))(SerializationKind || {}), EvaErrorKind = /* @__PURE__ */ ((e) => (e[e.NOT_FOUND = -32001] = "NOT_FOUND", e[e.ACCESS_DENIED = -32002] = "ACCESS_DENIED", e[e.SYSTEM_ERROR = -32003] = "SYSTEM_ERROR", e[e.OTHER = -32004] = "OTHER", e[e.NOT_READY = -32005] = "NOT_READY", e[e.UNSUPPORTED = -32006] = "UNSUPPORTED", e[e.CORE_ERROR = -32007] = "CORE_ERROR", e[e.TIMEOUT = -32008] = "TIMEOUT", e[e.INVALID_DATA = -32009] = "INVALID_DATA", e[e.FUNC_FAILED = -32010] = "FUNC_FAILED", e[e.ABORTED = -32011] = "ABORTED", e[e.ALREADY_EXISTS = -32012] = "ALREADY_EXISTS", e[e.BUSY = -32013] = "BUSY", e[e.METHOD_NOT_IMPLEMENTED = -32014] = "METHOD_NOT_IMPLEMENTED", e[e.TOKEN_RESTRICTED = -32015] = "TOKEN_RESTRICTED", e[e.IO = -32016] = "IO", e[e.REGISTRY = -32017] = "REGISTRY", e[e.EVAHI_AUTH_REQUIRED = -32018] = "EVAHI_AUTH_REQUIRED", e[e.ACCESS_DENIED_MORE_DATA_REQUIRED = -32022] = "ACCESS_DENIED_MORE_DATA_REQUIRED", e[e.PARSE = -32700] = "PARSE", e[e.INVALID_REQUEST = -32600] = "INVALID_REQUEST", e[e.METHOD_NOT_FOUND = -32601] = "METHOD_NOT_FOUND", e[e.INVALID_PARAMS = -32602] = "INVALID_PARAMS", e[e.INTERNAL_RPC = -32603] = "INTERNAL_RPC", e[e.BUS_CLIENT_NOT_REGISTERED = -32113] = "BUS_CLIENT_NOT_REGISTERED", e[e.BUS_DATA = -32114] = "BUS_DATA", e[e.BUS_IO = -32115] = "BUS_IO", e[e.BUS_OTHER = -32116] = "BUS_OTHER", e[e.BUS_NOT_SUPPORTED = -32117] = "BUS_NOT_SUPPORTED", e[e.BUS_BUSY = -32118] = "BUS_BUSY", e[e.BUS_NOT_DELIVERED = -32119] = "BUS_NOT_DELIVERED", e[e.BUS_TIMEOUT = -32120] = "BUS_TIMEOUT", e[e.BUS_ACCESS = -32121] = "BUS_ACCESS", e))(EvaErrorKind || {}), EventKind = /* @__PURE__ */ ((e) => (e.HeartbeatSuccess = "heartbeat.success", e.HeartbeatError = "heartbeat.error", e.LoginSuccess = "login.success", e.LoginFailed = "login.failed", e.LoginOTPRequired = "login.otp_required", e.LoginOTPInvalid = "login.otp_invalid", e.LoginOTPSetup = "login.otp_setup", e.WsEvent = "ws.event", e.ServerReload = "server.reload", e.ServerRestart = "server.restart", e.LogRecord = "log.record", e.LogPostProcess = "log.postprocess", e.WASMError = "wasm.error", e))(EventKind || {}), StateProp = /* @__PURE__ */ ((e) => (e.Status = "status", e.Value = "value", e.Any = "any", e))(StateProp || {});
const GLOBAL_BLOCK_NAME = ".", ERR_REQUIRE_LOGGED_IN = "Not logged in";
var IntervalKind = /* @__PURE__ */ ((e) => (e.AjaxReload = "ajax_reload", e.AjaxLogReload = "log_reload", e.ActionWatch = "action_watch", e.Heartbeat = "heartbeat", e.Reload = "reload", e.Restart = "restart", e.WSBufTTL = "ws_buf_ttl", e))(IntervalKind || {});
class EvaError {
constructor(t, s, i) {
n(this, "code");
n(this, "message");
n(this, "data");
this.code = t, this.message = s, this.data = i;
}
}
class EvaBulkRequestPartHandler {
constructor() {
n(this, "fn_ok");
n(this, "fn_err");
}
then(t) {
return this.fn_ok = t, this;
}
catch(t) {
return this.fn_err = t, this;
}
}
class EvaBulkRequest {
constructor(t) {
n(this, "requests");
n(this, "payload");
n(this, "eva");
this.requests = /* @__PURE__ */ new Map(), this.payload = [], this.eva = t;
}
/**
* Prepare API function call for bulk calling
*
* Calls any available SFA API function
*
* @param p1 item OID (if required) or API call params
* @param p2 extra call params or empty object
* @param fn_ok function which is executed on successfull call
* @parma fn_err function which is executed on error
*
* @returns Part handler object
*/
prepare(t, s, i) {
let a;
typeof s == "string" || Array.isArray(s) ? (a = i || {}, a.i = s) : a = s;
let r = this.eva._prepare_call_params(a), o = this.eva._prepare_api_call(t, r), c = new EvaBulkRequestPartHandler();
return this.requests.set(o.id, c), this.payload.push(o), c;
}
/**
* Perform bulk API call
*/
call() {
let t = `${this.eva.api_uri}/jrpc`;
return this.eva._debug("call_bulk", `${t}`), new Promise((s, i) => {
if (this.eva.allow_logged_in_calls_only && !this.eva.logged_in)
throw new EvaError(-32002, ERR_REQUIRE_LOGGED_IN);
if (this.payload.length == 0) {
s(!0);
return;
}
this.eva.external.fetch(t, {
method: "POST",
headers: {
"Content-Type": "application/json"
},
redirect: "error",
body: JSON.stringify(this.payload)
}).then((a) => {
if (a.ok)
a.json().then((r) => {
if (this.eva._debug("call_bulk success"), Array.isArray(r))
r.forEach((o) => {
if (typeof o.id > "u" || typeof o.result > "u" && typeof o.error > "u")
i({
code: -32009,
message: "Invalid server response",
data: o
});
else {
let c = o.id, A = this.requests.get(c), k, b;
A !== void 0 && (k = A.fn_ok, b = A.fn_err), o.error !== void 0 ? (this.eva._debug(
"call_bulk req",
`${c} failed: ${o.error.code} (${o.error.message})`
), b && b({
code: o.error.code,
message: o.error.message,
data: o
})) : (this.eva.debug == 2 && this.eva.log.info(
`call_bulk API ${c} ${A.func} response`,
o.result
), k && k(o.result));
}
}), s(!0);
else {
let o = -32009, c = "Invalid server response (not an array)";
this.eva._debug("call_bulk", `failed: ${o} (${c})`), i(new EvaError(o, c, r));
}
}).catch((r) => {
let o = -32009, c = "Invalid server response";
this.eva._debug("call_bulk", `failed: ${o} (${c})`), i(new EvaError(o, c, r));
});
else {
let r = -32007, o = "Server error";
this.eva._debug("call_bulk", `failed: ${r} (${o})`), i(new EvaError(r, o));
}
}).catch((a) => {
let r = -32007, o = "Server error";
this.eva._debug("call_bulk", `failed: ${r} (${o})`), i(new EvaError(r, o, a));
});
});
}
}
class Eva_ACTION {
constructor(t) {
n(this, "eva");
this.eva = t;
}
/**
* Call unit action with value=1
*
* @param oid {string} unit OID
* @param wait {boolean} wait until the action is completed (default: true)
*/
async start(t, s = !0) {
return this.exec(t, { v: 1 }, s);
}
/**
* Call unit action with value=0
*
* @param oid {string} unit OID
* @param wait {boolean} wait until the action is completed (default: true)
*/
async stop(t, s = !0) {
return this.exec(t, { v: 0 }, s);
}
/**
* Call unit action to toggle its value
*
* @param oid {string} unit OID
* @param wait {boolean} wait until the action is completed (default: true)
*/
async toggle(t, s = !0) {
return this._act("action.toggle", t, {}, s);
}
/**
* Call unit action
*
* @param oid {string} unit OID
* @param params {object} action params
* @param wait {boolean} wait until the action is completed (default: true)
*/
exec(t, s, i = !0) {
return this._act("action", t, s, i);
}
/**
* Terminate all unit actions
*
* @param oid {string} unit OID
*/
async kill(t) {
await this.eva.call("action.kill", t);
}
/**
* Terminate a unit action
*
* @param uuid {string} action uuid
*/
async terminate(t) {
let s = "action.terminate";
await this.eva.call(s, { u: t });
}
/**
* Run lmacro
*
* @param oid {string} lmacro oid
* @param params {object} call params
* @param wait {boolean} wait until completed (default: true)
*/
async run(t, s, i = !0) {
return this._act("run", t, s, i);
}
_act(t, s, i, a = !1) {
return new Promise((r, o) => {
this.eva.call(t, s, i).then((c) => {
a === !1 ? r(c) : this.eva.watch_action(c.uuid, (A) => {
A.uuid !== void 0 ? A.finished && r(A) : o(A);
});
}).catch((c) => {
o(c);
});
});
}
}
class Eva_LVAR {
constructor(t) {
n(this, "eva");
this.eva = t;
}
/**
* Reset lvar (set status to 1)
*
* @param oid {string} lvar oid
*/
async reset(t) {
await this.eva.call("lvar.reset", t);
}
/**
* Clear lvar (set status to 0)
*
* @param oid {string} lvar oid
*/
async clear(t) {
await this.eva.call("lvar.clear", t);
}
/**
* Toggle lvar status
*
* @param oid {string} lvar oid
*/
async toggle(t) {
await this.eva.call("lvar.toggle", t);
}
/**
* Increment lvar value
*
* @param oid {string} lvar oid
*
* @returns the new value
*/
async incr(t) {
return (await this.eva.call("lvar.incr", t)).result;
}
/**
* Decrement lvar value
*
* @param oid {string} lvar oid
*
* @returns the new value
*/
async decr(t) {
return (await this.eva.call("lvar.decr", t)).result;
}
/**
* Set lvar state
*
* @param oid {string} lvar oid
* @param status {numberr} lvar status
* @param value lvar value
*/
async set(t, s, i) {
let a = {};
s !== void 0 && (a.status = s), i !== void 0 && (a.value = i), Object.keys(a).length && await this.eva.call("lvar.set", t, a);
}
/**
* Set lvar status
*
* @param oid {string} lvar oid
* @param status {number} lvar status
*/
async set_status(t, s) {
await this.set(t, s);
}
/**
* Set lvar value
*
* @param oid {string} lvar oid
* @param value lvar value
*/
async set_value(t, s) {
await this.set(t, s = s);
}
/**
* Get lvar expiration time left
*
* @param lvar_oid {string} lvar OID
*
* @returns seconds to expiration, -1 if expired, -2 if stopped
*/
expires(t) {
let s = this.eva.state(t);
if (s === void 0 || s.t === void 0)
return;
if (!s.meta || s.meta.expires === void 0 || s.meta.expires == 0)
return null;
if (s.status == 0)
return -2;
if (s.status == -1)
return -1;
let i = s.meta.expires - (/* @__PURE__ */ new Date()).getTime() / 1e3 + this.eva.tsdiff + s.t;
return i < 0 && (i = 0), i;
}
}
class _EvaStream {
constructor(t, s, i) {
n(this, "oid");
n(this, "eva");
n(this, "name");
n(this, "ws");
n(this, "onStart");
n(this, "onData");
n(this, "onError");
n(this, "onEOS");
this.oid = t, this.name = s, this.eva = i, this.ws = null, this.onStart = () => {
}, this.onData = (a) => {
}, this.onError = (a) => {
this.eva.log.error(`Stream ${this.name} error`, a);
}, this.onEOS = () => {
};
}
_restart() {
this._stop(), this._start();
}
_start() {
if (!this.eva.ws_mode) {
this.onError(
new EvaError(
-32006,
"WebSocket mode is disabled in EVA ICS WebEngine"
)
);
return;
}
if (!this.eva.api_token) {
this.onError(new EvaError(-32002, "Not logged in"));
return;
}
let t = this.eva._get_ws_uri();
t += `k=${this.eva.api_token}`;
const s = new this.eva.external.WebSocket(t);
s.binaryType = "arraybuffer", s.onerror = (i) => {
this.onError(
new EvaError(-32010, `WebSocket error: ${i.type}`)
), this._stop();
}, s.onmessage = (i) => {
if (typeof i.data == "string") {
let a = JSON.parse(i.data);
if (a.s !== "stream")
return;
switch (a.d) {
case "start":
this.onStart();
break;
case "eos":
this.onEOS();
break;
case "forbidden":
this.onError(
new EvaError(
-32002,
`Stream ${this.name} access denied (${this.oid})`
)
), this._stop();
break;
}
} else
this.onData(i.data);
}, s.onclose = () => {
this._stop();
}, s.addEventListener("open", () => {
let i = { m: "stream.start", p: { i: this.oid } };
s.send(JSON.stringify(i)), s.send("");
}), this.ws = s;
}
_stop() {
const t = this.ws;
if (t)
try {
t.onclose = null, t.onmessage = () => {
}, t.onerror = () => {
}, t.close();
} catch {
setTimeout(() => {
try {
t == null || t.close();
} catch {
}
}, 100);
}
}
}
class _EvaStateBlock {
constructor(t, s, i) {
n(this, "state_updates");
n(this, "eva");
n(this, "name");
n(this, "_ajax_reloader");
this.name = t, this.state_updates = s, this.eva = i;
}
_start() {
this.eva.ws_mode && this.eva._start_ws(this.state_updates, this.name), this.eva._load_states(this.state_updates, this.name).then(() => {
if (this.eva.ws_mode) {
const t = this.eva._intervals.get(
"reload"
/* Reload */
);
t && (this._ajax_reloader = setInterval(() => {
if (!this.eva.logged_in) {
this._stop();
return;
}
this.eva._load_states(this.state_updates, this.name);
}, t * 1e3));
} else
this._ajax_reloader = setInterval(
() => {
this.eva._load_states(this.state_updates, this.name);
},
this.eva._intervals.get(
"ajax_reload"
/* AjaxReload */
)
);
});
}
_restart() {
this._stop(), this._start();
}
_stop() {
this._ajax_reloader && clearInterval(this._ajax_reloader);
let t = this.eva.ws.get(this.name);
if (t) {
this.eva.ws.delete(this.name);
try {
t.onclose = null, t.onerror = function() {
}, t.close();
} catch {
setTimeout(() => {
try {
t == null || t.close();
} catch {
}
}, 100);
}
}
}
}
var TokenMode = /* @__PURE__ */ ((e) => (e.Normal = "normal", e.ReadOnly = "readonly", e))(TokenMode || {}), SessionAuthKind = /* @__PURE__ */ ((e) => (e.Token = "token", e.Key = "key", e.Login = "login", e.No = "unauthorized", e))(SessionAuthKind || {}), ACLOp = /* @__PURE__ */ ((e) => (e.Log = "log", e.Developer = "developer", e.Moderator = "moderator", e.Supervisor = "supervisor", e))(ACLOp || {}), LoginState = /* @__PURE__ */ ((e) => (e.Active = "active", e.Starting = "starting", e.Stopping = "stopping", e.Inactive = "inactive", e.Failed = "failed", e.OTPRequired = "otp.required", e.OTPInvalid = "otp.invalid", e.OTPSetup = "otp.setup", e))(LoginState || {});
const defaultSessionState = () => ({
login: "inactive",
error: null,
otp: null
});
var EventTopic = /* @__PURE__ */ ((e) => (e.ItemState = "ST", e.Server = "SERVER", e.Supervisor = "SUPERVISOR", e.WeSession = "WE/SESSION", e.WeItemState = "WE/ST", e))(EventTopic || {}), S, O;
class Eva {
constructor() {
n(this, "action");
n(this, "lvar");
n(this, "api_uri");
n(this, "ws_uri");
x(this, S, void 0);
n(this, "api_token");
//api_version: number | null;
n(this, "authorized_user");
n(this, "clear_unavailable");
n(this, "debug");
n(this, "allow_logged_in_calls_only");
n(this, "external");
n(this, "evajw");
n(this, "in_evaHI");
n(this, "log_params");
n(this, "log");
n(this, "logged_in");
n(this, "login");
n(this, "login_xopts");
n(this, "log_level_names");
x(this, O, void 0);
n(this, "set_auth_cookies");
n(this, "state_updates");
n(this, "tsdiff");
n(this, "version");
n(this, "wasm");
n(this, "ws_mode");
n(this, "server_info");
n(this, "ignore_password_set_on_next_login");
n(this, "_event_map");
n(this, "_api_call_id");
n(this, "_handlers");
n(this, "_intervals");
n(this, "_ws_handler_registered");
n(this, "_heartbeat_reloader");
n(this, "_ajax_reloader");
n(this, "_log_reloader");
n(this, "_scheduled_restarter");
n(this, "_states");
n(this, "_blocks");
n(this, "_streams");
n(this, "_last_ping");
n(this, "_last_pong");
n(this, "ws");
n(this, "_action_states");
n(this, "_action_watch_functions");
n(this, "_log_subscribed");
n(this, "_log_started");
n(this, "_log_first_load");
n(this, "_log_loaded");
n(this, "_update_state_functions");
n(this, "_update_state_mask_functions");
n(this, "_lr2p");
n(this, "_deserializePromise", (e, t) => {
switch (t) {
case "msgpack":
return new Promise((s, i) => {
e.arrayBuffer().then((a) => {
try {
const r = this.external.msgpack.decode(a);
s(r);
} catch (r) {
i(
new EvaError(
-32009,
"Invalid MsgPack response",
r
)
);
}
});
});
case "json":
return e.json();
default:
throw new EvaError(
-32006,
"Unknown serialization kind"
);
}
});
this.version = eva_webengine_version, this.log = new Logger(), this.login = "", B(this, O, ""), this.login_xopts = null, B(this, S, ""), this.api_uri = "", this.ws_uri = "/ws", this.set_auth_cookies = !0, this.api_token = "", this.authorized_user = null, this.logged_in = !1, this.ignore_password_set_on_next_login = !1, this.debug = !1, this.allow_logged_in_calls_only = !1, this.state_updates = !0, this.wasm = !1, this.clear_unavailable = !1, this._ws_handler_registered = !1, this.ws_mode = !0, this.ws = /* @__PURE__ */ new Map(), this._api_call_id = 0, this.tsdiff = 0, this._last_ping = /* @__PURE__ */ new Map(), this._last_ping.set(GLOBAL_BLOCK_NAME, null), this._last_pong = /* @__PURE__ */ new Map(), this._last_pong.set(GLOBAL_BLOCK_NAME, null), this._streams = /* @__PURE__ */ new Map(), this._log_subscribed = !1, this._log_started = !1, this._log_first_load = !1, this._log_loaded = !1, this._lr2p = [], this._event_map = null, this.in_evaHI = typeof navigator < "u" && typeof navigator.userAgent == "string" && navigator.userAgent.startsWith("evaHI "), this.log_params = {
level: 20,
records: 200
}, this._update_state_functions = /* @__PURE__ */ new Map(), this._update_state_mask_functions = /* @__PURE__ */ new Map(), this._handlers = /* @__PURE__ */ new Map(), this._handlers.set("heartbeat.error", this.restart), this._handlers.set("wasm.error", (e) => {
this.log.error(e), this._critical("WASM load error", !0, !0);
}), this._states = /* @__PURE__ */ new Map(), this._states.set(GLOBAL_BLOCK_NAME, /* @__PURE__ */ new Map()), this._blocks = /* @__PURE__ */ new Map(), this._intervals = /* @__PURE__ */ new Map([
["ajax_reload", 2],
["log_reload", 2],
["action_watch", 0.5],
["heartbeat", 5],
["reload", 5],
["restart", 1],
["ws_buf_ttl", 0]
]), this.log_level_names = /* @__PURE__ */ new Map([
[10, "DEBUG"],
[20, "INFO"],
[30, "WARNING"],
[40, "ERROR"],
[50, "CRITICAL"]
]), this._heartbeat_reloader = null, this._ajax_reloader = null, this._log_reloader = null, this._scheduled_restarter = null, this._action_watch_functions = /* @__PURE__ */ new Map(), this._action_states = /* @__PURE__ */ new Map(), this._clear(), this._clear_watchers(), this.action = new Eva_ACTION(this), this.lvar = new Eva_LVAR(this), this.evajw = null, this.external = {}, this.server_info = null, typeof window < "u" ? typeof window.fetch < "u" && (this.external.fetch = window.fetch.bind(window)) : typeof fetch < "u" ? this.external.fetch = fetch : this.external.fetch = null, typeof WebSocket < "u" ? this.external.WebSocket = WebSocket : this.external.WebSocket = null, typeof window < "u" && typeof window.QRious < "u" ? this.external.QRious = window.QRious : this.external.QRious = null;
}
// wasm override
/**
* Enables pub/sub event map. Usually not required to be called manually, as
* called automatically as soon as there is a subscription performed.
*/
enable_event_map() {
this._event_map === null && (this._event_map = new I().matchAny(MATCH_ANY).wildcard(WILDCARDS).regexPrefix("r~").separator("/"));
}
// wasm override
/**
* Subscribe to an event topic
*
* @param topic {string} event topic
* @param fn {EventHandler} event handler
*
* @returns true if subscription was successful
*/
subscribe_event_topic(e, t) {
return this.enable_event_map(), this._event_map.registerClient(t), this._event_map.subscribe(e, t), !0;
}
// wasm override
/**
* Subscribe to multiple event topics
*
* @param topics {Array<string>} event topics
* @param fn {EventHandler} event handler
* @returns true if subscription was successful
*/
subscribe_event_topics(e, t) {
this.enable_event_map(), this._event_map.registerClient(t);
for (let s of e)
this._event_map.subscribe(s, t);
return !0;
}
// wasm override
/**
* Unsubscribe from an event topic
*
* @param topic {string} event topic
* @param fn {EventHandler} event handler
*/
unsubscribe_event_topic(e, t) {
var s;
(s = this._event_map) == null || s.unsubscribe(e, t);
}
// wasm override
/**
* Unsubscribe from multiple event topics
*
* @param topics {Array<string>} event topics
* @param fn {EventHandler} event handler
*/
unsubscribe_event_topics(e, t) {
var s;
for (let i of e)
(s = this._event_map) == null || s.unsubscribe(i, t);
}
// wasm override
/**
* Unsubscribe from all event topics
*
* @param fn {EventHandler} event handler
*/
unsubscribe_all_event_topics(e) {
var t, s;
(t = this._event_map) == null || t.unsubscribeAll(e), (s = this._event_map) == null || s.unregisterClient(e);
}
// WASM override
_push_event_topic(e, t) {
if (this._event_map) {
const s = this._event_map.getSubscribers(e);
for (const i of s)
i(e, t);
}
}
/**
* Set engine login credentials
*
* @param login {string|null} login
* @param password {string|null} password
*/
set_login_password(e, t) {
this.login = e || "", B(this, O, t || ""), B(this, S, "");
}
/**
* Set/clear engine API key
*
* @param apikey {string | null} API key
*/
set_api_key(e) {
B(this, S, e || ""), this.login = "", B(this, O, "");
}
/**
* Is engine password set
*
* @returns true if password is set
*/
is_password_set() {
return N(this, O) !== "";
}
/**
* Is engine authentication set
*
* @returns true if auth is set
*/
is_auth_set() {
return N(this, S) !== "" || this.login !== "" && N(this, O) !== "";
}
/**
* Clear engine authenication credentials
*/
clear_auth() {
this.login = "", B(this, O, ""), B(this, S, "");
}
/**
* Start a binary stream
*
* @param params {EvaStreamParameters} stream parameters
*/
start_stream(e) {
const t = this._streams.get(e.oid);
t && t._stop();
const s = new _EvaStream(e.oid, e.name, this);
e.onStart && (s.onStart = e.onStart), e.onData && (s.onData = e.onData), e.onError && (s.onError = e.onError), e.onEOS && (s.onEOS = e.onEOS), this._streams.set(e.name, s), s._start();
}
/**
* Stop a binary stream
*
* @param name {string} stream name
*/
stop_stream(e) {
let t = this._streams.get(e);
t && (t._stop(), this._streams.delete(e));
}
/**
* Register a state block
*
* @param name {string} block name
* @param state_updates {boolean | Array<string>} state updates
*/
register_state_block(e, t) {
if (e == GLOBAL_BLOCK_NAME)
throw new EvaError(
-32602,
`WebEngine state block name ${GLOBAL_BLOCK_NAME} is reserved`
);
check_state_updates(t);
let s = this._blocks.get(e);
s && (console.error(
`WebEngine state block ${e} has been already registered, removing the old instance`
), s._stop());
let i = new _EvaStateBlock(e, t, this);
this.logged_in && i._start(), this._blocks.set(e, i), this._init_block(e), this._push_event_topic(`WE/ST/${e}`, t);
}
/**
* Unregister a state block
*
* @param name {string} block name
*/
unregister_state_block(e) {
let t = this._blocks.get(e);
t && (t._stop(), this._delete_block(e), this._blocks.delete(e), this._push_event_topic(`WE/ST/${e}`, null));
}
/**
* Unregister all state blocks
*/
unregister_all_state_blocks() {
for (let [e, t] of this._blocks)
t._stop(), this._delete_block(e), this._push_event_topic(`WE/ST/${e}`, null);
this._blocks.clear();
}
bulk_request() {
return new EvaBulkRequest(this);
}
// WASM override
/**
* Get engine mode
* @returns "js" or "wasm"
*/
get_mode() {
return "js";
}
/**
* Start the engine
*
* After calling the function authenticates user, opens a WebSocket (in
* case of WS mode) or schedule AJAXs refresh interval.
*/
start() {
if (this._cancel_scheduled_restart(), this._debug("EVA ICS WebEngine", `version: ${this.version}`), typeof fetch > "u") {
this.log.error(
'"fetch" function is unavailable. Upgrade your web browser or connect polyfill'
);
return;
}
if (this.logged_in) {
this._debug("start", "already logged in");
return;
}
this.wasm && !this.evajw ? this._start_evajw() : this._start_engine();
}
_start_engine() {
this._push_event_topic("WE/SESSION", {
login: "starting",
error: null,
otp: null
}), this._clear_last_pings();
let e = {};
if (N(this, S))
e = { k: N(this, S) }, this.login_xopts && (e.xopts = this.login_xopts), this._debug("start", "logging in with API key");
else if (this.api_token)
e = { a: this.api_token }, this._debug("start", "logging in with existing auth token");
else if (N(this, O) && !this.ignore_password_set_on_next_login)
e = { u: this.login, p: N(this, O) }, this.api_token && (e.a = this.api_token), this.login_xopts && (e.xopts = this.login_xopts), this._debug("start", "logging in with password");
else if (this.set_auth_cookies) {
let s = cookies.read("auth");
s && (e = { a: s }, this._debug("start", "logging in with cookie-cached auth token"));
}
Object.keys(e).length === 0 && this._debug("start", "logging in without credentials");
let t;
return this.ignore_password_set_on_next_login = !1, this._api_call("login", e).then((s) => (this.api_token = s.token, t = s.user, this._set_token_cookie(), Promise.all([
this._load_states(this.state_updates, GLOBAL_BLOCK_NAME),
this._heartbeat(!0),
this._start_ws(this.state_updates, GLOBAL_BLOCK_NAME)
]))).then(() => {
if (!this.ws_mode)
this._ajax_reloader && clearInterval(this._ajax_reloader), this._ajax_reloader = setInterval(
() => {
this._load_states(this.state_updates, GLOBAL_BLOCK_NAME).catch(
() => {
}
);
},
this._intervals.get(
"ajax_reload"
/* AjaxReload */
) * 1e3
);
else {
this._ajax_reloader && clearInterval(this._ajax_reloader);
let s = this._intervals.get(
"reload"
/* Reload */
);
s && (this._ajax_reloader = setInterval(() => {
this._load_states(this.state_updates, GLOBAL_BLOCK_NAME).catch(
() => {
}
);
}, s * 1e3));
}
this._heartbeat_reloader && clearInterval(this._heartbeat_reloader), this._heartbeat_reloader = setInterval(
() => {
this._heartbeat(!1).catch(() => {
});
},
this._intervals.get(
"heartbeat"
/* Heartbeat */
) * 1e3
), this._debug("start", `login successful, user: ${t}`), this.logged_in = !0, this.authorized_user = t, this._invoke_handler(
"login.success"
/* LoginSuccess */
), this._push_event_topic("WE/SESSION", {
login: "active",
error: null,
otp: null
});
for (let [s, i] of this._blocks)
i._restart();
}).catch((s) => {
this._debug("start", s), this.logged_in = !1, (s == null ? void 0 : s.code) === void 0 && (s = new EvaError(-32004, "Unknown error")), this._debug("start", `login failed: ${s.code} (${s.message})`), this._stop_engine(), (s.code != -32007 || s.message != "Server error") && this.erase_token_cookie(), this.error_handler(s, "login");
}), !0;
}
/**
* Get system name
*
* @returns the system name or null if the engine is not logged in
*/
system_name() {
return this.server_info ? this.server_info.system_name : null;
}
/**
* Sleep the number of seconds
*
* @param sec {number} seconds to sleep
*/
async sleep(e) {
return new Promise((t) => setTimeout(t, e * 1e3));
}
/**
* Start log processing
*
* Starts log processing. The engine must be already logged in.
*
* @param log_level {number} log processing level (optional)
*/
log_start(e) {
this._log_started = !0, e !== void 0 && (this.log_params.level = e), (!this.ws_mode || this._log_first_load) && (this._log_loaded = !1, this._load_log_entries(!0), this.ws_mode || (this._log_reloader = setInterval(
() => {
this._load_log_entries(!1);
},
this._intervals.get(
"log_reload"
/* AjaxLogReload */
) * 1e3
)));
}
/**
* Set state updates without restart required
*
* @param state_updates {boolean} true/false or a string array
* @param clear_existing {boolean} clear existing states
*
*/
async set_state_updates(e, t) {
check_state_updates(e), this.state_updates = e, this._push_event_topic("WE/ST", e);
let s = this.ws.get(GLOBAL_BLOCK_NAME);
if (s && s.readyState === 1) {
let i = { m: "unsubscribe.state" };
if (s.send(JSON.stringify(i)), s.send(""), this.state_updates) {
let a = { m: "subscribe.state" }, r;
this.state_updates == !0 ? r = ["#"] : r = this.state_updates, a.p = r, s.send(JSON.stringify(a)), s.send("");
}
}
t && this._clear_states(GLOBAL_BLOCK_NAME), await this._load_states(this.state_updates, GLOBAL_BLOCK_NAME);
}
/**
* Change log processing level
*
* @param log_level {number} log processing level
*/
set_log_level(e) {
this.log_params.level = e, this._set_ws_log_level(e), this._load_log_entries(!0);
}
/**
* Restart the engine
*
* e.g. used on heartbeat error or if subscription parameters are changed
*/
restart() {
this._cancel_scheduled_restart(), this._debug("restart", "performing restart"), this.stop(!0, !0).then(() => {
this._schedule_restart();
}).catch(() => {
this._schedule_restart();
});
}
/**
* Erase auth token cookie
*
* It is recommended to call this function when login form is displayed to
* prevent old token caching
*/
erase_token_cookie() {
this.api_token = "", this.authorized_user = null, this._set_token_cookie();
}
/**
* Load JSON configuration
*
* @param config_path {string} config path (default: config.json)
*
* @returns Promise object
*/
load_config(e) {
return new Promise((t, s) => {
const i = e || "config.json";
this.log.debug("Eva::load_config", `loading configuration from ${i}`), this.external.fetch(i).then((a) => a.json()).then((a) => {
this.apply_config(a), t(a);
}).catch((a) => s(a));
});
}
/**
* Apply configuration from an object
*
* @param config {object} configuration object
*/
apply_config(e) {
const t = e.engine;
t && (t.api_uri && (this.api_uri = t.api_uri), t.apikey && B(this, S, t.apikey), t.debug !== void 0 && (this.debug = t.debug), t.login && (this.login = t.login), t.password && B(this, O, t.password), t.set_auth_cookies !== void 0 && (this.set_auth_cookies = t.set_auth_cookies), t.state_updates !== void 0 && (this.state_updates = t.state_updates, this._push_event_topic("WE/ST", this.state_updates)), t.wasm !== void 0 && (this.wasm = t.wasm), t.ws_mode !== void 0 && (this.ws_mode = t.ws_mode), t.log_params && (this.log_params = t.log_params), t.interval && Object.keys(t.interval).forEach((s) => {
const i = s;
this.set_interval(i, t.interval[i]);
}));
}
/**
* Calls any available API function
*
* @param {Object} options - The options for the API call.
* @param {string} options.method - The API method to call.
* @param {object|string|string[]} [options.params] - Parameters to pass to the API method.
* @param {SerializationKind} [options.serialization_kind] - Optional serialization kind for the request.
* @returns {Promise<any>} - A promise that resolves with the result of the API call.
*/
async api_call({
method: e,
params: t,
serialization_kind: s
}) {
return this.call(e, t, void 0, s);
}
/**
* Call API function
*
* Calls any available API function (old version, may be deprecated soon)
*
* @param method {string} API method
* @param p1 {object} call parameters. if specified as a string/object, transformed to i=val
* @param p2 {object} additional call parameters if p1 is a string
*
* @returns Promise object
*/
async call(e, t, s, i) {
if (this.allow_logged_in_calls_only && !this.logged_in)
throw new EvaError(-32002, ERR_REQUIRE_LOGGED_IN);
let a;
typeof t == "string" || Array.isArray(t) ? (a = s || {}, a.i = t) : a = t;
let r = this._prepare_call_params(a);
return this._api_call(e, r, i);
}
/**
* Ask server to set the token read-only (e.g. after idle)
*
* (EVA ICS 3.3.2+)
*
* the current mode can be obtained from $eva.server_info.aci.token_mode
*/
set_readonly() {
return new Promise((e, t) => {
this.call("session.set_readonly").then(() => {
this.server_info && (this.server_info.aci.token_mode = "readonly"), this._push_event_topic("SERVER", this.server_info), e();
}).catch((s) => {
t(s);
});
});
}
/**
* Ask server to return the token to normal mode
*
* (EVA ICS 3.3.2+)
*
* @param u {string} login
* @param p {string} password
* @param xopts {object} extra options (e.g. OTP)
*/
set_normal(e, t, s) {
let i = {};
return typeof t > "u" || t === null ? i = { k: e } : i = { u: e, p: t }, i.a = this.api_token, s !== void 0 && (i.xopts = s), this._api_call("login", i).then(() => {
this.server_info && (this.server_info.aci.token_mode = "normal"), this._invoke_handler(
"login.success"
/* LoginSuccess */
);
}).catch((a) => {
this.error_handler(a, "set_normal");
}), !0;
}
error_handler(e, t) {
if (e.code == -32022) {
let s = this.parse_svc_message(e.message);
if (s.method = t, s && s.kind == "OTP")
switch (s.message) {
case "REQ":
this._invoke_handler("login.otp_required", s), this._push_event_topic("WE/SESSION", {
login: "otp.required",
error: null,
otp: s
});
return;
case "INVALID":
this._invoke_handler("login.otp_invalid", s), this._push_event_topic("WE/SESSION", {
login: "otp.invalid",
error: null,
otp: s
});
return;
case "SETUP":
this._invoke_handler("login.otp_setup", s), this._push_event_topic("WE/SESSION", {
login: "otp.setup",
error: null,
otp: s
});
return;
}
}
this._invoke_handler("login.failed", e), t == "login" && (e.data = void 0, this._push_event_topic("WE/SESSION", {
login: "failed",
error: e,
otp: null
}));
}
/**
* Set event handler function
*
* A single kind of event can have a single handler only
*
* @param event {EventKind} engine event kind
* @param func {function} function called on event
*/
on(e, t) {
this._handlers.set(e, t), this._debug("on", `setting handler for ${e}`), e == "ws.event" && (this._ws_handler_registered = !0);
}
/**
* Set intervals
*
* @param interval_id {IntervalKind} interval kind
* @param value {number} interval value (in seconds)
*/
set_interval(e, t) {
this._intervals.set(e, t);
}
/*
* Converts local date to server date
*
* @param date {Date} local date
*
* @returns {Date} server date
*/
date_local_to_server(e) {
return new Date(e.getTime() - this.tsdiff * 1e3);
}
/*
* Converts server date to local date
*
* @param date {Date}
*
* @returns {Date}
*/
date_server_to_local(e) {
return new Date(e.getTime() + this.tsdiff * 1e3);
}
/**
* Watch item state updates
*
* Registers the function to be called in case of state change event (or at
* first state load).
*
* If state is already loaded, function will be called immediately. One item
* (or item mask, set with "*" or a traditional OID mask) can have multiple
* watchers.
*
* @param oid {string} item oid (e.g. sensor:env/temp1, sensor:env/\*, sensor:+/temp1)
* @param func {function} function to be called
* @param ignore_initial {boolean} skip initial state callback
* @param prot {boolean} protected (not removed on global unwatch)
*
*/
// WASM override
watch(e, t, s = !1, i = !1) {
if (isMask(e)) {
let a = this._update_state_mask_functions, r = a == null ? void 0 : a.get(e);
if (r === void 0 && (r = [], a == null || a.set(e, r)), r.push({ func: t, prot: i }), !s) {
let o = this.state(e);
Array.isArray(o) ? o.map(t) : o !== void 0 && t(o);
}
} else {
let a = this._update_state_functions, r = a == null ? void 0 : a.get(e);
if (r === void 0 && (r = [], a == null || a.set(e, r)), r.push({ func: t, prot: i }), !s) {
let o = this.state(e);
o !== void 0 && t(o);
}
}
}
/**
* Watch action state by uuid
*
* Registers the function to be called in case of action status change
* event (or at first state load).
*
* If status is already loaded, function will be called immediately.
* Otherwise status is polled from the server with "action_watch" interval
* (default: 500ms).
*
* There is no unwatch function as watching is stopped as soon as the
* action is completed (or server error is occurred)
*
* @param uuid {string} action uuid
* @param func {function} function to be called
*
*/
watch_action(e, t) {
let s = this._action_watch_functions.get(e);
if (s === void 0) {
s = [], this._action_watch_functions.set(e, s), s.push(t);
const i = () => {
this.call("action.result", { u: e }).then((a) => {
let r = this._action_states.get(e);
if (r === void 0 || r.status != a.status) {
this._action_states.set(e, a);
let o = this._action_watch_functions.get(e);
o !== void 0 && o.map((c) => c(a));
}
a.finished ? (this._action_watch_functions.delete(e), this._action_states.delete(e)) : setTimeout(
i,
this._intervals.get(
"action_watch"
/* ActionWatch */
) * 1e3
);
}).catch((a) => {
let r = this._action_watch_functions.get(e);
r && r.map((o) => o(a)), this._action_watch_functions.delete(e), this._action_states.delete(e);
});
};
setTimeout(
i,
this._intervals.get(
"action_watch"
/* ActionWatch */
) * 1e3
);
} else {
s.push(t);
let i = this._action_states.get(e);
i !== void 0 && t(i);
}
}
/**
* Stop watching item state updates
*
* If item oid or function is not specified, all watching functions are
* removed for a single oid (mask) or for all the items watched.
*
* @param oid {string} item OID or a mask
* @param func {function} function to be removed
*/
unwatch(e, t) {
e ? isMask(e) ? t ? this._unwatch_mask_func(e, t) : this._unwatch_mask_all(e) : t ? this._unwatch_func(e, t) : this._unwatch_all(e) : this._clear_watchers();
}
// WASM override
_unwatch_func(e, t) {
let s = this._update_state_functions, i = s == null ? void 0 : s.get(e);
if (i !== void 0) {
const a = i.filter((r) => r.func !== t);
a.length > 0 ? s == null || s.set(e, a) : s == null || s.delete(e);
}
}
// WASM override
_unwatch_all(e) {
let t = this._update_state_functions, s = t == null ? void 0 : t.get(e);
if (s === void 0)
return;
const i = s.filter((a) => a.prot);
i.length > 0 ? t == null || t.set(e, i) : t == null || t.delete(e);
}
// WASM override (not supported)
_unwatch_mask_func(e, t) {
let s = this._update_state_mask_functions, i = s == null ? void 0 : s.get(e);
i !== void 0 && (s == null || s.set(
e,
i.filter((a) => a.func !== t)
));
}
// WASM override
_unwatch_mask_all(e) {
let t = this._update_state_mask_functions, s = t == null ?