forestdb
Version:
An uncomplicated real-time database with encrypted HTTP and WebSocket server-client communication, fast caching, state management, a cross-runtime file system manager, and more, working seamlessly on both frontend and backend.
1,331 lines (1,330 loc) • 557 kB
JavaScript
// src/crypto.ts
var _key_len_ = 32;
var isKeyValidFunc = (x) => {
return /^[a-zA-Z0-9]+$/.test(x.pkey);
};
var bufferToHexFunc = (x) => {
const byteArray = new Uint8Array(x.data);
let hexString = "";
for (let i = 0; i < byteArray.length; i++) {
const hex = byteArray[i].toString(16).padStart(2, "0");
hexString += hex;
}
return hexString;
};
var hexToBufferFunc = (x) => {
const hex = x.data, len = hex.length, buffer = new Uint8Array(len / 2);
for (let i = 0; i < len; i += 2) {
buffer[i / 2] = parseInt(hex.substr(i, 2), 16);
}
return buffer;
};
var cipherStringToChunksFunc = (x) => {
const data = x.data, dataLength = data.length;
let len = 0;
const dv = Math.ceil(dataLength / 8);
len = dv < 5 ? 5 : dv;
let tab = [];
for (let i = 0; i < dataLength; i += len) {
tab.push(data.slice(i, i + len));
}
const res = String(tab.length) + String(tab.length > 1 ? tab.join("-") : tab[0]);
return res;
};
var L2_cipherMixerFunc = (x) => {
const data = x.data, key = x.key, iv = x.iv, authTag = x.authTag;
const ignoreKey = x.ignoreKey;
const inversed0 = data.split("").reverse().join("");
const dataChunks = cipherStringToChunksFunc({ data: inversed0 });
let keyChunks = "";
if (!ignoreKey) {
const inversed1 = key.split("").reverse().join("");
keyChunks = cipherStringToChunksFunc({ data: inversed1 });
}
const inversed2 = iv.split("").reverse().join("");
const ivChunks = cipherStringToChunksFunc({ data: inversed2 });
const inversed3 = authTag.split("").reverse().join("");
const authTagChunks = cipherStringToChunksFunc({ data: inversed3 });
const tab = ignoreKey ? [ivChunks, authTagChunks, dataChunks] : [ivChunks, authTagChunks, dataChunks, keyChunks];
const res = tab.join("-");
return res;
};
var L2_cipherDemixerFunc = (x) => {
let data = x.data, tab = data.split("-");
const ignoreKey = x.ignoreKey;
const n1 = parseInt(data[0]);
const d1 = tab.splice(0, n1).join("");
const iv = d1.slice(1).split("").reverse().join("");
data = tab.join("-");
tab = data.split("-");
const n2 = parseInt(data[0]);
const d2 = tab.splice(0, n2).join("");
const authTag = d2.slice(1).split("").reverse().join("");
data = tab.join("-");
tab = data.split("-");
const n3 = parseInt(data[0]);
const d3 = tab.splice(0, n3).join("");
const data1 = d3.slice(1).split("").reverse().join("");
data = tab.join("-");
tab = data.split("-");
let key = "";
if (!ignoreKey) {
const n4 = parseInt(data[0]);
const d4 = tab.splice(0, n4).join("");
key = d4.slice(1).split("").reverse().join("");
}
return { data: data1, key, iv, authTag };
};
var web_createHashFunc = async (x) => {
const data = x.data;
const encodedData = new TextEncoder().encode(data);
const hashBuffer = await crypto.subtle.digest("SHA-256", encodedData);
const hashArray = Array.from(new Uint8Array(hashBuffer));
const hashHex = hashArray.map((byte) => byte.toString(16).padStart(2, "0")).join("");
return hashHex;
};
var web_generateKeyFunc = async () => {
return await crypto.subtle.generateKey({ name: "AES-GCM", length: 128 }, true, ["encrypt", "decrypt"]);
};
var web_cipherFunc = async (x) => {
try {
if (typeof x.data !== "string") throw new Error(`Data to encrypt is not a string`);
const data = x.data;
const pkey = x.privateKey ?? void 0;
if (pkey !== void 0 && typeof pkey !== "string") throw new Error(`Invalid key "${pkey}"`);
if (typeof pkey === "string") {
if (pkey.length !== _key_len_) throw new Error(`Invalid key length "${pkey.length}" - The valid key length is "${_key_len_}"`);
if (!isKeyValidFunc({ pkey })) throw new Error();
}
const encoder = new TextEncoder();
const fpk = pkey !== void 0 ? hexToBufferFunc({ data: pkey }) : void 0;
const key = fpk !== void 0 ? await crypto.subtle.importKey("raw", fpk, { name: "AES-GCM" }, true, ["encrypt", "decrypt"]) : await web_generateKeyFunc();
const iv = crypto.getRandomValues(new Uint8Array(12));
const tagLength = 128;
const text = encoder.encode(data);
const ciphertext = await crypto.subtle.encrypt({ name: "AES-GCM", iv, tagLength }, key, text);
const authTagLength = 16;
const ciphertextArray = new Uint8Array(ciphertext);
const authTagIndex = ciphertextArray.length - authTagLength;
const authTag = ciphertextArray.slice(authTagIndex);
let keyExported = await crypto.subtle.exportKey("raw", key);
const encryptedTextOnly = ciphertext.slice(0, authTagIndex);
const res = bufferToHexFunc({ data: encryptedTextOnly });
const fkey = bufferToHexFunc({ data: keyExported });
const fiv = bufferToHexFunc({ data: iv });
const fauthTag = bufferToHexFunc({ data: authTag });
const mix = L2_cipherMixerFunc({ data: res, key: fkey, iv: fiv, authTag: fauthTag, ignoreKey: fpk !== void 0 ? true : false });
return { status: "success", log: "", data: mix };
} catch (e) {
return { status: "error", log: e.message, data: e.message };
}
};
var web_decipherFunc = async (x) => {
try {
if (typeof x.data !== "string") throw new Error(`Data to decrypt is not a string`);
const pkey = x.privateKey ?? void 0;
if (pkey !== void 0 && typeof pkey !== "string") throw new Error(`Invalid key "${pkey}"`);
const demixed = L2_cipherDemixerFunc({ data: x.data, ignoreKey: pkey !== void 0 ? true : false });
const data = demixed.data, key = pkey !== void 0 ? pkey : demixed.key, iv = demixed.iv, authTag = demixed.authTag;
const bdata = hexToBufferFunc({ data: data + authTag });
const bkey = hexToBufferFunc({ data: key });
const biv = hexToBufferFunc({ data: iv });
const dkey = await crypto.subtle.importKey("raw", bkey, "AES-GCM", true, ["decrypt"]);
const decrypted = await crypto.subtle.decrypt({ name: "AES-GCM", iv: biv, tagLength: 128 }, dkey, bdata);
const decipherText = new TextDecoder().decode(decrypted);
return { status: "success", log: "", data: decipherText };
} catch (e) {
return { status: "error", log: e, data: e };
}
};
var cipherAlgo = "aes-128-gcm";
var crypto_createHashFunc = async (x) => {
const api = x.api;
const hash = api.createHash("sha256");
hash.update(x.data);
const dig = hash.digest("hex");
return dig;
};
var crypto_cipherFunc = (x) => {
try {
if (typeof x.data !== "string") throw new Error(`Data to encrypt is not a string`);
const pkey = x.privateKey || void 0;
if (pkey !== void 0 && typeof pkey !== "string") throw new Error(`Invalid key "${pkey}"`);
if (typeof pkey === "string") {
if (pkey.length !== _key_len_) throw new Error(`Invalid key length "${pkey.length}" - The valid key length is "${_key_len_}"`);
if (!isKeyValidFunc({ pkey })) throw new Error();
}
const data = x.data;
const api = x.api;
const key = pkey !== void 0 ? hexToBufferFunc({ data: pkey }) : api.randomBytes(16);
const iv = api.randomBytes(12);
const cipher = api.createCipheriv(cipherAlgo, key, iv);
let encrypted = cipher.update(data, "utf8", "hex");
encrypted += cipher.final("hex");
const authTag = cipher.getAuthTag().toString("hex");
const fkey = bufferToHexFunc({ data: key });
const fiv = bufferToHexFunc({ data: iv });
const mix = L2_cipherMixerFunc({ data: encrypted, key: fkey, iv: fiv, authTag, ignoreKey: pkey !== void 0 ? true : false });
return { status: "success", data: mix };
} catch (e) {
return { status: "error", data: e.message };
}
};
var crypto_decipherFunc = (x) => {
try {
if (typeof x.data !== "string") throw new Error(`Data to decrypt is not a string`);
const pkey = x.privateKey;
if (pkey !== void 0 && typeof pkey !== "string") throw new Error(`Invalid key "${pkey}"`);
const demixed = L2_cipherDemixerFunc({ data: x.data, ignoreKey: pkey !== void 0 ? true : false });
const api = x.api;
const data = demixed.data, key = pkey !== void 0 ? hexToBufferFunc({ data: pkey }) : hexToBufferFunc({ data: demixed.key }), iv = hexToBufferFunc({ data: demixed.iv }), authTag = hexToBufferFunc({ data: demixed.authTag });
const fkey = api.createSecretKey(key);
const decipher = api.createDecipheriv(cipherAlgo, fkey, iv);
decipher.setAuthTag(authTag);
let decrypted = decipher.update(data, "hex", "utf8");
decrypted += decipher.final("utf8");
const res = pkey !== void 0 ? decrypted : JSON.parse(decrypted);
return { status: "success", data: res };
} catch (e) {
return { status: "error", data: e.message };
}
};
// src/main.ts
var _can_log_ = false;
var _valid_value_type_ = ["string", "number", "boolean", "object", "undefined"];
var _reserved_keys_ = ["_$$type", "_$$isMutation", "_$$isCondition", "_$$default"];
var _date_format_ = { current: ["YYYY_MM_DD", "MM_DD_YYYY", "DD_MM_YYYY"] };
var _headers_ = {
json: { headers: { "Content-type": "application/json", "Access-Control-Allow-Origin": "*", "Access-Control-Allow-Methods": "POST", "Access-Control-Allow-Headers": "Content-Type" } },
file: { headers: { "Content-type": "multipart/form-data", "Access-Control-Allow-Origin": "*", "Access-Control-Allow-Methods": "POST", "Access-Control-Allow-Headers": "Content-Type" } }
};
var _crypto_key_length_ = 32;
var _max_tree_name_length_ = 100;
var _max_json_key_length_ = 200;
var _max_json_field_size_ = 1 * 1024 * 1024;
var _max_feed_size_ = 1 * 1024 * 1024;
var _max_object_depth_length_ = 35;
var _max_ws_retry_count = 300;
var _max_ws_retry_time_interval = 2e3;
var _default_http_endpoint_ = "forest";
var _default_http_upload_endpoint_ = "butterfly";
var _default_http_host_ = "0.0.0.0";
var _default_http_timeout_ = 3e4;
var _default_http_static_files_routename_ = "static";
var _default_max_request_size_ = 256;
var _default_server_runtime_ = ["Deno", "Node", "Bun"];
var _default_client_runtime_ = ["Browser", "React_native"];
var _default_fs_storage_path_ = "./forest";
var errCode = {
initialization_failed: "initialization_failed",
max_tree_name_length_exceeded: "max_tree_name_length_exceeded",
not_branch_specified: "not_branch_specified",
empty_json_data: "empty_json_data",
transaction_failed: "transaction_failed",
feed_update_failed: "feed_update_failed",
request_failed: "request_failed",
phantom_tree: "phantom_tree",
phantom_branch: "phantom_branch",
phantom_feed: "phantom_feed",
corrupted_chain: "corrupted_chain",
corrupted_condition: "corrupted_condition",
invalid_path: "invalid_path",
invalid_tree_name: "invalid_tree_name",
invalid_tree_name_length: "invalid_tree_name_length",
invalid_tree_options: "invalid_tree_options",
invalid_argument: "invalid_argument",
invalid_chain: "invalid_chain",
invalid_date: "invalid_date",
invalid_mutation: "invalid_mutation",
invalid_mutation_path: "invalid_mutation_path",
invalid_json_path: "invalid_json_path",
invalid_condition: "invalid_condition",
invalid_condition_operator: "invalid_condition_operator",
invalid_condition_path: "invalid_condition_path",
invalid_condition_value: "invalid_condition_value",
invalid_value_type: "invalid_value_type",
invalid_target_value_type: "invalid_target_value_type",
unmatched_type: "unmatched_type",
unmatched_condition: "unmatched_condition",
unmatched_condition_type: "unmatched_condition_type",
tree_not_found: "tree_not_found",
no_tree_found: "no_tree_found",
branch_not_found: "branch_not_found",
feed_not_found: "feed_not_found",
incorrect_data_type: "incorrect_data_type",
incorrect_branch_name: "incorrect_branch_name",
nested_mutation_found: "nested_mutation_found",
nested_condition_found: "nested_condition_found"
};
var initConfig = {
config: {
mainKey: "id",
dateFormat: ["YYYY_MM_DD", "MM_DD_YYYY"]
}
};
var fs_API = { current: void 0 };
var fs_node_API = { current: void 0 };
var fs_storage_path = { current: _default_fs_storage_path_ };
var crypto_API = { current: void 0 };
var self_ws_API = { current: void 0 };
var LIB_config = { current: { rate: 2 * 1024 * 1024, ms: 60 } };
var Runtime = { current: void 0 };
var FNSS = { enable: false };
var crypto2 = { enable: false };
var secretKey = { value: void 0 };
var tree_DATA = {};
var branch_DATA = {};
var branch_feed_ref_DATA = {};
var feed_DATA = {};
var store_DATA = {};
var deleted_field_DATA = {};
var mk_to_branch_DATA = {};
var locked_feed_id_DATA = {};
var phantom_feed_id_DATA = {};
var phantom_branch_id_DATA = {};
var phantom_tree_id_DATA = {};
var transaction_scoope_DATA = {};
var active_transaction_per_branch_DATA = {};
var log_DATA = {};
var tid_DATA = {};
var env_DATA = {
/* store global env data */
hasInit: false,
isLoadingSchema: false,
runtime: void 0,
wstate: { status: "close", log: "WebSocket is off" }
};
var mutation_custom_func_DATA = {};
var feed_watcher_DATA = {};
var branch_watcher_DATA = {};
var store_watcher_DATA = { set: {}, update: {}, delete: {} };
var watcher_mapping_DATA = {};
var trigger_method_DATA = { id: {}, family: {} };
var ws_server_DATA = {};
var ws_client_DATA = {};
var ws_server_config_DATA = {};
var ws_callback_DATA = {};
var http_server_DATA = {};
var private_session_DATA = {
id: "",
oldSessionId: "",
runtime: void 0,
runtimeType: "client",
fsEnable: false,
cryptoEnable: false
};
var public_session_DATA = {};
var logFunc = (...log) => {
if (_can_log_) console.log(...log);
};
var plog = (...log) => {
console.log(...log);
};
var generateIdFunc = (x) => {
const ntmp = x?.noTmp ?? true;
const val = "0aW9zXe8CrVt1By5NuA46iZ3oEpRmTlYkUjIhOgPfMdQsSqDwFxGcHvJbKnL";
const length = x?.length !== void 0 ? x.length : val.length;
const tmp = String((/* @__PURE__ */ new Date()).getTime());
let id = "";
for (let i = 0; i < length; i++) id += val.charAt(Math.floor(Math.random() * 36));
id = ntmp ? id : id + tmp;
return id;
};
var isAlphanumericFunc = (x) => {
return x.acceptSpecial ? /^[a-zA-Z0-9_-]+$/.test(x.value) : /^[a-zA-Z0-9]+$/.test(x.value);
};
var keepPositiveFunc = (x) => {
return x.operation < 0 ? 0 : x.operation;
};
var delayFunc = (x) => {
return new Promise((resolve) => setTimeout(resolve, x?.ms || 0.5));
};
var getObjectTypeFunc = (x) => {
const obj = x.object, tobj = typeof obj;
if (tobj !== "object") return "undefined";
return tobj === null ? "null" : Array.isArray(obj) ? "array" : "json";
};
var setLogFunc = (x) => {
const treeName = x.treeName, status = x.status, type = x.type, value = x.value, transactionId = x.transactionId, joinId = x.joinId, skipCommit = x.skipCommit || false;
const t = (/* @__PURE__ */ new Date()).toISOString();
const log = `[${status}][${type}][${t}][GTID -> '${transactionId}'][JID -> '${joinId ?? null}'] :: [${value}];
`;
if (skipCommit) return log;
if (typeof log_DATA[treeName] !== "string") log_DATA[treeName] = "";
log_DATA[treeName] = log_DATA[treeName] + log;
if (typeof tid_DATA[treeName] !== "object") tid_DATA[treeName] = {};
tid_DATA[treeName][transactionId] = transactionId;
return log;
};
var checkMaxNestedObjFunc = (x) => {
const input = x.input, maxDepth = x.maxDepth || _max_object_depth_length_;
const recurse = (x2) => {
const value = typeof x2.value === "object" ? x2.value : void 0, currentDepth = x2.currentDepth;
if (currentDepth > maxDepth) return true;
if (value && (typeof value === "object" || Array.isArray(value))) {
for (let k in value) {
const exd = recurse({ value: value[k], currentDepth: currentDepth + 1 });
if (exd) return true;
}
}
return false;
};
return recurse({ value: input, currentDepth: 1 });
};
var hasMutationOrConditionFunc = (x) => {
const check = x.check, obj = x.obj;
if (typeof obj === "object" && obj !== null) {
const json = obj;
let hasFound = false;
if (check === "all" && (isMutationFunc({ obj: json }) || isConditionFunc({ obj: json }))) hasFound = true;
else if (check === "mutation" && isMutationFunc({ obj: json })) hasFound = true;
else if (check === "condition" && isConditionFunc({ obj: json })) hasFound = true;
if (hasFound) return true;
else {
const keys = Object.keys(json);
for (let i = 0; i < keys.length; i++) {
const target = keys[i];
const targetValue = json[target];
if (typeof targetValue === "object") {
const found = hasMutationOrConditionFunc({ check, obj: targetValue });
if (found) return true;
}
}
return false;
}
} else return false;
};
var hasPropertyFunc = (x, y) => {
const obj = typeof x === "object" && x !== null ? x : {};
return Object.prototype.hasOwnProperty.call(obj, y);
};
var cloneObjFunc = (x) => {
try {
const tp = typeof x.obj === "object" && x.obj !== null ? true : false;
const obj = x.obj, useLoop = x.useLoop ?? false;
let data = {};
if (tp) {
if (!useLoop) data = structuredClone(obj);
else {
data = [];
for (let f = 0; f < obj.length; f++) {
const cln = structuredClone(obj[f]);
data.push(cln);
}
}
return data;
}
return Array.isArray(x.obj) ? [] : {};
} catch (e) {
plog("Clonning failed !");
return { status: "error", log: e.message, data: void 0 };
}
};
var isMutationFunc = (x) => {
return typeof x.obj === "object" && !Array.isArray(x.obj) && x.obj !== null && hasPropertyFunc(x.obj, "_$$isMutation") ? true : false;
};
var isConditionFunc = (x) => {
return typeof x.obj === "object" && !Array.isArray(x.obj) && x.obj !== null && hasPropertyFunc(x.obj, "_$$isCondition") ? true : false;
};
var isNumericFunc = (x) => {
return isFinite(Number(x.value));
};
var mergeNestedArrayFunc = (x) => {
return x.arr.flat();
};
var getArrayDepthFunc = (x) => {
const arr = x.arr, maxLevel = x.maxLevel || 2;
if (!Array.isArray(arr)) return -1;
let depth = 1;
for (const item of arr) {
if (Array.isArray(item)) {
const itemDepth = getArrayDepthFunc({ arr: item, maxLevel });
if (itemDepth === -1) return -1;
depth = Math.max(depth, itemDepth + 1);
if (depth > maxLevel) return -1;
}
}
return depth;
};
var removeAccentFunc = (x) => {
const keepSpaces = x.keepSpaces ?? false;
const str = x.value.normalize("NFD").replace(/[\u0300-\u036f]/g, "");
const data = x.lowerCase ? str.toLocaleLowerCase() : str;
if (x.keepSpaces) data.replaceAll(" ", "");
return data;
};
var monthDays = {
1: 31,
// January
2: 28,
// February (29 in leap years)
3: 31,
// March
4: 30,
// April
5: 31,
// May
6: 30,
// June
7: 31,
// July
8: 31,
// August
9: 30,
// September
10: 31,
// October
11: 30,
// November
12: 31
// December
};
var getDaysInMonthFunc = (x) => {
const month = x.month, year = x.year;
return month === 2 && year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0) ? 29 : monthDays[month];
};
var getWordCountFunc = (x) => {
return (x.value.match(/\b\w+\b/g) || []).length;
};
var buildJsonFromPathFunc = (x) => {
const path = Array.isArray(x.path) ? x.path.join(".") : x.path, value = x.value;
const pathTab = path.split(".").reverse(), plen = pathTab.length;
let jtab = Array(plen).fill(void 0).map(() => {
return {};
});
for (let i = 0; i < plen; i++) {
const cp = pathTab[i];
if (i === 0) jtab[i][cp] = value;
else jtab[i][cp] = jtab[i - 1];
}
return jtab[plen - 1];
};
var resolvePathFunc = (x) => {
const path = Array.isArray(x.path) ? x.path.join(".") : x.path, firstKey = x.firstKey || void 0, sourceObj = x.sourceObj || void 0, asJson = x.asJson ?? false;
let mlog = "";
try {
let pathTab = path.split(".");
let pathType = "short";
const pcopy = cloneObjFunc({ obj: pathTab });
const strPath = pcopy.join(".");
pathType = strPath[0] === "#" ? "long" : "short";
let realObj = {}, realPath = [];
if (pathType === "short") {
const otype = getObjectTypeFunc({ object: sourceObj });
if (sourceObj === void 0 || otype !== "json") {
mlog = mlog + `Invalid source`;
throw new Error();
}
if (firstKey !== void 0 && pathTab[0] !== firstKey) pathTab = [firstKey, ...pathTab];
realObj = cloneObjFunc({ obj: sourceObj });
realPath = pathTab;
} else {
const fid = pathTab[0].replace("#", "");
const est = hasPropertyFunc(feed_DATA, fid);
if (!est) {
mlog = mlog + `The feed "${fid}" doesn't exists`;
throw new Error(mlog);
}
realObj = cloneObjFunc({ obj: feed_DATA[fid] });
realPath = strPath.replace("#", "").split(".");
}
const ptl = pathTab.length;
const currentPathValue = { current: void 0 };
let breakLoop = false;
for (let n = 0; n < ptl; n++) {
if (breakLoop) break;
const ky = pathTab[n];
const validPathData = currentPathValue.current === void 0 ? false : true;
const isNumericPath = isNumericFunc({ value: currentPathValue.current });
const isBeforeLastLoop = n === ptl - 2 ? true : false;
const isLastLoop = n === ptl - 1 ? true : false;
if (!isNumericPath && !hasPropertyFunc(validPathData ? currentPathValue.current : realObj, ky)) {
mlog = mlog + `The path "${path}" doesn't exists`;
throw new Error(mlog);
}
if (currentPathValue.current !== void 0) {
const propExists = hasPropertyFunc(currentPathValue.current, ky);
if (!propExists) {
currentPathValue.current[ky] = {};
}
}
currentPathValue.current = validPathData ? currentPathValue.current[ky] : realObj[ky];
}
if (asJson) currentPathValue.current = buildJsonFromPathFunc({ path: realPath, value: currentPathValue.current });
return { status: "success", log: mlog, data: currentPathValue.current };
} catch (e) {
return { status: "error", log: e.message, data: void 0 };
}
};
var extractNumberFunc = (x) => {
return (x.value.match(/\d+/g) || []).map(Number);
};
var extractNumberIndexFunc = (x) => {
const mtc = x.value.matchAll(/\d+/g);
let res = [];
mtc.forEach((e) => {
res.push({ index: e.index, value: e[0] });
});
return res;
};
var buildDateTemplateFunc = (x, y) => {
let md = x;
if (y !== void 0) {
const xp = x.point, yp = y.point;
md = xp >= yp ? x : y;
}
let proto = [];
let fullDate = "";
if (md.hasDate) {
proto.push(...["YYYY", "MM", "DD"]);
fullDate = fullDate + "YYYY-MM-DD";
}
if (md.hasTime) {
proto.push(...["HH", "mm"]);
fullDate = fullDate + "THH:mm";
}
if (md.hasSec) {
proto.push("ss");
fullDate = fullDate + ":ss";
}
if (md.hasMilli) {
proto.push("sss");
fullDate = fullDate + ".sss";
}
if (md.hasUTCHour) {
proto.push("+HH");
fullDate = fullDate + "++HH";
} else {
fullDate = fullDate + "Z";
}
if (md.hasUTCMin) {
proto.push("+mm");
fullDate = fullDate + ":+mm";
}
const final = { proto, fullDate };
return final;
};
var tmpExtractorFunc = (x) => {
let value = x.value, format = x.format;
const template = x.template || void 0;
const extractModel = x.extractModel || false;
const custom = template !== void 0 || extractModel ? true : false;
let mlog = "";
let model = { hasDate: false, hasTime: false, hasSec: false, hasMilli: false, hasUTCHour: false, hasUTCMin: false, point: 0 };
try {
if (!custom && typeof value === "number") {
const len = String(value).length;
return len === 10 ? value * 1e3 : (
/* Convert seconds to milliseconds */
len === 13 ? value : (
/* Milliseconds (standard) */
len > 13 && len <= 16 ? Math.floor(value / 10 ** (len - 13)) : (
/* Convert micro/nano to ms */
-1
)
)
);
}
if (custom && typeof value === "number") {
value = new Date(value).toISOString();
}
let nDate = custom ? value : String(value.replaceAll(" ", ""));
let numTab = extractNumberFunc({ value: nDate });
if (numTab.length < 3 || numTab.length === 4) {
mlog = mlog + `invalid date "${nDate}"`;
throw new Error(mlog);
}
const sdt = numTab.splice(0, 3);
let dArr = [
format === "DD_MM_YYYY" ? sdt[2] : format === "MM_DD_YYYY" ? sdt[2] : format === "YYYY_MM_DD" ? sdt[0] : -1,
/* extract year */
format === "DD_MM_YYYY" ? sdt[1] : format === "MM_DD_YYYY" ? sdt[0] : format === "YYYY_MM_DD" ? sdt[1] : -1,
/* extact month */
format === "DD_MM_YYYY" ? sdt[0] : format === "MM_DD_YYYY" ? sdt[1] : format === "YYYY_MM_DD" ? sdt[2] : -1
/* extact date */
];
let mArr = [];
if (nDate.includes(":")) {
const ix = nDate.lastIndexOf("+") || nDate.lastIndexOf("Z") || nDate.lastIndexOf("z") || -1;
const oc = nDate.match(/:/g) || [];
if (oc.length > 3 || oc.length < 1) {
mlog = mlog + `invalid date "${nDate}"`;
throw new Error(mlog);
}
const ioc = nDate.indexOf(":") - 2;
const str = ix !== -1 ? nDate.slice(ioc, ix) : nDate.slice(ioc);
const extr = extractNumberFunc({ value: str }), ixtr = extr.length;
if (ixtr === 0) {
mlog = mlog + `invalid date "${nDate}"`;
throw new Error(mlog);
}
mArr = [
extr[0],
/* hour */
ixtr === 1 ? 0 : extr[1]
/* minute */
];
if (extr[2] !== void 0) mArr.push(ixtr <= 2 ? 0 : extr[2]);
if (extr[3] !== void 0) mArr.push(ixtr === 3 ? 0 : extr[3]);
}
let uArr = [];
if (nDate.includes("+")) {
const ix = nDate.lastIndexOf("+"), str = nDate.slice(ix);
const extr = extractNumberFunc({ value: str }), ixtr = extr.length;
if (ixtr === 0) {
mlog = mlog + `invalid date "${nDate}"`;
throw new Error(mlog);
}
uArr = [
extr[0]
/* UTC hour */
];
if (extr[1] !== void 0) mArr.push(ixtr === 1 ? 0 : extr[1]);
}
numTab = [...dArr, ...mArr, ...uArr];
const protoTab = template?.proto || ["YYYY", "MM", "DD", "HH", "mm", "ss", "sss", "+HH", "+mm"];
let fullDate = template?.fullDate || "YYYY-MM-DDTHH:mm:ss.sss++HH:+mm";
for (let d = 0; d < protoTab.length; d++) {
const cprot = protoTab[d], val = numTab[d] ?? -1;
const pval = val === -1 ? numTab[d] : val;
switch (cprot) {
/* set year */
case "YYYY":
{
const len = String(val).length;
if (len < 4 || val === -1) {
mlog = mlog + `invalid year "${pval}"`;
throw new Error(mlog);
}
fullDate = fullDate.replace("YYYY", String(val));
model.hasDate = true;
}
break;
/* set month */
case "MM":
{
if (val < 1 || val > 12 || val === -1) {
mlog = mlog + `invalid month "${pval}"`;
throw new Error(mlog);
}
fullDate = fullDate.replace("MM", String(val).padStart(2, "0"));
}
break;
/* set date */
case "DD":
{
const days = getDaysInMonthFunc({ month: numTab[1], year: numTab[0] });
if (val < 1 || val > days || val === -1) {
mlog = mlog + `invalid date "${pval}", the range should be from 1 to "${days}"`;
throw new Error(mlog);
}
fullDate = fullDate.replace("DD", String(val).padStart(2, "0"));
}
break;
/* set hour */
case "HH":
{
if ((val < 0 || val > 23) && val !== -1) {
mlog = mlog + `invalid hour "${pval}"`;
throw new Error(mlog);
}
const ext = val !== -1 ? true : false;
fullDate = fullDate.replace("HH", !ext ? "00" : String(val).padStart(2, "0"));
model.hasTime = ext ? true : false;
}
break;
/* set minute */
case "mm":
{
if ((val < 0 || val > 59) && val !== -1) {
mlog = mlog + `invalid minute "${pval}"`;
throw new Error(mlog);
}
fullDate = fullDate.replace("mm", val === -1 ? "00" : String(val).padStart(2, "0"));
}
break;
/* set second */
case "ss":
{
if ((val < 0 || val > 59) && val !== -1) {
mlog = mlog + `invalid seconds "${pval}"`;
throw new Error(mlog);
}
const ext = val !== -1 ? true : false;
fullDate = fullDate.replace("ss", !ext ? "00" : String(val).padStart(2, "0"));
model.hasSec = ext ? true : false;
}
break;
/* set millisecond */
case "sss":
{
if ((val < 0 || val > 999) && val !== -1) {
mlog = mlog + `invalid seconds "${pval}"`;
throw new Error(mlog);
}
const ext = val !== -1 ? true : false;
fullDate = fullDate.replace("sss", !ext ? "000" : String(val).padStart(3, "0"));
model.hasMilli = ext ? true : false;
}
break;
/* set UTC hour */
case "+HH":
{
const ext = val !== -1 ? true : false;
if (!ext) {
fullDate = fullDate.replace("++HH:+mm", "Z");
break;
}
if (val < 0 || val > 23) {
mlog = mlog + `invalid UTC hour "${pval}"`;
throw new Error(mlog);
}
fullDate = fullDate.replace("+HH", String(val).padStart(2, "0"));
model.hasUTCHour = ext ? true : false;
}
break;
/* set UTC minute */
case "+mm":
{
if ((val < 0 || val > 59) && val !== -1) {
mlog = mlog + `invalid seconds "${pval}"`;
throw new Error(mlog);
}
const ext = val !== -1 ? true : false;
fullDate = fullDate.replace("+mm", !ext ? "00" : String(val).padStart(2, "0"));
model.hasUTCMin = ext ? true : false;
}
break;
/* - */
default:
{
mlog = mlog + `unknown date parameter "${cprot}"`;
throw new Error(mlog);
}
;
}
;
}
const mdv = Object.values(model);
const btr = mdv.filter((e) => e === true);
model.point = btr.length;
const dateObj = new Date(fullDate);
let final = isNaN(dateObj.getTime()) ? -1 : dateObj.getTime();
return extractModel ? { tmp: final, model } : final;
} catch (e) {
logFunc('err "tmpExtractorFunc" fail ::', e.message);
return -1;
}
};
var extractTimestampFunc = (x) => {
const value = x.value, dateFormat = x.dateFormat !== void 0 ? cloneObjFunc({ obj: x.dateFormat }) : cloneObjFunc({ obj: _date_format_.current });
let final = -1;
for (let i = 0; i < dateFormat.length; i++) {
const form = dateFormat[i], extract = tmpExtractorFunc({ value, format: form, template: x.template, extractModel: x.extractModel });
final = extract;
if (extract !== -1) break;
}
return final;
};
var transformIntoTimestampFunc = (x) => {
const value = x.value, format = x.format;
let mlog = "", currentTarget = void 0;
try {
for (let i = 0; i < value.length; i++) {
const target = value[i];
if (Array.isArray(target)) {
const newTar = target;
for (let j = 0; j < target.length; j++) {
const crtVal = newTar[j];
currentTarget = crtVal;
const xtmp = extractTimestampFunc({ value: crtVal, dateFormat: format });
if (xtmp === -1) {
mlog = mlog + `The date "${crtVal}" doesn't respect provided date format "[${_date_format_.current}]"`;
throw new Error(mlog);
}
newTar[j] = xtmp;
}
value[i] = newTar.sort((a, b) => a - b);
} else {
currentTarget = target;
value[i] = extractTimestampFunc({ value: target, dateFormat: format });
}
}
const marr = mergeNestedArrayFunc({ arr: value });
if (marr.includes(-1)) return { status: "error", log: mlog, data: currentTarget };
return { status: "success", log: mlog, data: value };
} catch (e) {
return { status: "error", log: mlog, data: currentTarget };
}
};
var mergeObjFunc = (x) => {
const target = x.target, data = x.data;
const ttype = getObjectTypeFunc({ object: target }), tdata = getObjectTypeFunc({ object: data });
if (ttype !== "json" || tdata !== "json") return data;
for (const key in data) {
if (hasPropertyFunc(data, key)) {
const ttk = getObjectTypeFunc({ object: target[key] }), tdk = getObjectTypeFunc({ object: data[key] });
if (key in target && ttk === "json" && tdk === "json") target[key] = mergeObjFunc({ target: target[key], data: data[key] });
else target[key] = data[key];
}
}
return target;
};
var deleteJsonFieldFunc = (x) => {
const path = Array.isArray(x.path) ? x.path.join(".") : x.path, obj = x.target, fk = x.firstkey;
let pathTab = path.split(".");
let res = { status: "success", log: "", data: void 0 };
try {
if (fk !== void 0 && pathTab[0] !== fk) pathTab = [fk, ...pathTab];
let plen = pathTab.length;
let cursor = {};
for (let i = 0; i < plen; i++) {
const ck = pathTab[i];
const who = i === 0 ? obj : cursor;
if (!hasPropertyFunc(who, ck)) {
res.status = "error";
throw new Error(`Path "${ck}" not found`);
}
cursor = who[ck];
if (i === plen - 2) {
const nk = pathTab[i + 1];
delete cursor[nk];
break;
}
}
res.data = obj;
} catch (e) {
res.log = e.message;
}
;
return res;
};
var parseUrlFunc = (x) => {
try {
const url = x.url;
if (url.includes("://")) {
const parsedUrl = new URL(url);
return {
protocol: parsedUrl.protocol.replace(":", ""),
hostname: parsedUrl.hostname,
port: parsedUrl.port || void 0
};
}
const [host, port] = url.split(":");
return {
protocol: void 0,
hostname: host,
port: port || void 0
};
} catch (error) {
return void 0;
}
};
var topLevelJsonFunc = (x) => {
let res = { status: "success", log: "", data: void 0 };
let coll = {};
try {
const data = x.data;
for (let key in data) {
const kdat = data[key], ktab = x.ktab ? [...x.ktab] : [];
const dtyp = getObjectTypeFunc({ object: kdat });
if (dtyp === "json") {
ktab.push(key);
const recu = topLevelJsonFunc({ data: kdat, ktab });
mergeObjFunc({ target: coll, data: recu.data });
} else {
ktab.push(key);
const fk = ktab.join(".");
coll[fk] = data[key];
}
}
res.data = coll;
} catch (e) {
res.status = "error";
res.log = e.message;
}
;
return res;
};
var removeUndefinedValuesFunc = (x) => {
let res = { status: "success", log: "", data: void 0 };
try {
const obj = x.obj;
const clone = x.clone ?? false;
const ocl = clone ? cloneObjFunc({ obj }) : obj;
const kys = Object.keys(ocl);
for (let k = 0; k < kys.length; k++) {
const ck = kys[k];
if (ocl[ck] === void 0) {
delete ocl[ck];
continue;
}
const val = ocl[ck];
if (typeof val === "object" && val !== null) removeUndefinedValuesFunc({ obj: val, clone: false, recursive: true });
}
} catch (e) {
res.status = "error";
res.log = e.message;
}
return res;
};
var getNewPathFunc = (x) => {
const normalized = x.oldPath.replace(/[\\/]/g, "/");
const lastSlash = normalized.lastIndexOf("/");
return lastSlash === -1 ? x.newName : normalized.slice(0, lastSlash + 1) + x.newName;
};
var createHashFunc = async (x) => {
const res = { status: "success", log: "", data: void 0 };
try {
const isNode = Runtime.current === "Node" ? true : false;
if (typeof x !== "string") throw new Error(`The value to hash is not a string`);
if (isNode && crypto_API.current === void 0) throw new Error(`Unable to find crypto's API`);
let edat = isNode ? await crypto_createHashFunc({ data: x, api: crypto_API.current }) : await web_createHashFunc({ data: x });
res.data = edat;
} catch (e) {
res.status = "error";
res.log = e.message;
}
return res;
};
var encryptFunc = async (x) => {
let res = { status: "success", log: "", data: void 0 };
try {
if (private_session_DATA.cryptoEnable) {
const scrt = secretKey.value || void 0;
const cp = crypto_API.current !== void 0 && private_session_DATA.runtime === "Node" ? crypto_cipherFunc({ data: x.data, api: crypto_API.current, privateKey: scrt }) : await web_cipherFunc({ data: x.data, privateKey: scrt });
if (cp.status !== "success") throw new Error(`Encryption failed`);
res.data = cp.data;
}
return res;
} catch (e) {
res.status = "error";
res.log = e.message;
res.data = x.data;
}
return res;
};
var decryptFunc = async (x) => {
let res = { status: "success", log: "", data: void 0 };
const data = x.data || void 0;
try {
if (data === void 0) throw new Error(`Invalid data`);
if (private_session_DATA.cryptoEnable) {
const scrt = secretKey.value || void 0;
const cp = crypto_API.current !== void 0 ? crypto_decipherFunc({ data: x.data, api: crypto_API.current, privateKey: scrt }) : await web_decipherFunc({ data: x.data, privateKey: scrt });
if (cp.status !== "success") throw new Error(`Decryption failed`);
res.data = cp.data;
}
return res;
} catch (e) {
res.status = "error";
res.log = e.message;
res.data = x.data;
}
return res;
};
var ws_sendFunc = async (x) => {
const api = x.api, msg = JSON.stringify(x.msg);
let res = { status: "success", log: "", data: void 0 };
let message = { value: msg };
let final = "";
try {
if (private_session_DATA.cryptoEnable) {
const enc = await encryptFunc({ data: message.value });
if (enc.status !== "success") throw new Error(enc.log);
message.value = enc.data;
}
final = JSON.stringify(message);
} catch (e) {
res.status = "error";
res.log = `[WebSocket] :: ${e.message}`;
}
;
api.send(final);
return res;
};
var ws_commitClientSessionFunc = async (x) => {
const data = x.data;
let res = { status: "success", log: "", data: void 0 };
try {
const srv = Object.keys(ws_server_DATA);
if (srv.length === 0) throw new Error("Not server found to commit client session");
let fail = [];
for (let s = 0; s < srv.length; s++) {
const cid = srv[s];
const targ = ws_server_DATA[cid];
const sid = targ.id, api = targ.api;
const wss = await ws_sendFunc({ api, msg: { id: private_session_DATA.id, object: "commit_session", data, target: "single", targetId: sid, oldSessionId: private_session_DATA.oldSessionId } });
if (wss.status !== "success") {
fail.push(sid);
logFunc("session failed to commit ::", wss.log);
continue;
}
}
const flen = fail.length, slen = srv.length;
if (flen > 0) {
if (flen < slen) res.log = `Failed to commit session to following server(s) "[${fail}"]`;
else if (flen === slen) throw new Error(`Failed to commit session`);
}
} catch (e) {
res.status = "error";
res.log = e.message;
}
;
return res;
};
var ws_filterFunc = async (x) => {
let res = { status: "success", log: "", data: void 0 };
try {
const targetType = x.targetType, filter = x.filter;
const dataSource = targetType === "client" ? ws_client_DATA : ws_server_DATA;
const targets = Object.keys(dataSource);
let collector = [];
let lrate = 0;
if (targets.length > 0) for (let f = 0; f < targets.length; f++) {
if (lrate > 0 && lrate % LIB_config.current.rate === 0) await delayFunc({ ms: LIB_config.current.ms });
const tid = targets[f];
const tdata = dataSource[tid];
const css = tdata.session;
if (css === void 0 || Object.keys(css).length === 0) continue;
const checond = checkConditionFunc({ feed: css, condition: filter });
if (checond.status !== "success") throw new Error(checond.log);
if (checond.data) collector.push(tdata.id);
lrate++;
}
res.data = collector;
} catch (e) {
res.status = "error";
res.log = e.message;
}
return res;
};
var ws_sendtriggerMethodFunc = async (x) => {
let res = { status: "success", log: "", data: void 0 };
try {
const arg = x;
const targetId = arg.targetId;
const isBroadcast = targetId === "*" ? true : false;
const hasFilter = arg.targetFilter !== void 0 && Object.keys(arg.targetFilter).length > 0 ? true : false;
const dly = 1e3;
const tgData = { type: arg.type, source: arg.source, func: arg.method, xorder: arg.execOrder };
switch (arg.targetType) {
/**
* Send from server to client(s)
*/
case "client":
{
if (isBroadcast) {
let clients = [];
if (Object.keys(ws_client_DATA).length === 0) await delayFunc({ ms: dly * 5 });
if (hasFilter) {
const fres = await ws_filterFunc({ targetType: "client", filter: arg.targetFilter || {} });
if (fres.status !== "success") throw new Error(fres.log);
clients = fres.data;
} else clients = Object.keys(ws_client_DATA);
if (clients.length === 0) throw new Error(hasFilter ? `No client matches the filter - Broadcast cancelled` : `No clients found - Broadcast cancelled`);
let lrate = 0;
for (let m = 0; m < clients.length; m++) {
if (lrate > 0 && lrate % LIB_config.current.rate === 0) await delayFunc({ ms: LIB_config.current.ms });
const cid = clients[m], capi = ws_client_DATA[cid].api;
if (capi === void 0) {
res.log = res.log + `Unable to send message to client with id "${cid}" - It API may be broken
`;
lrate++;
continue;
}
try {
await ws_sendFunc({ api: capi, msg: { id: private_session_DATA.id, object: "trigger_method", data: tgData } });
} catch (e) {
res.log = res.log + `Unable to send message to client with id "${cid}" - ${e.message}
`;
lrate++;
continue;
}
lrate++;
}
} else {
let tex = hasPropertyFunc(ws_client_DATA, arg.targetId);
if (!tex) {
await delayFunc({ ms: dly * 5 });
tex = hasPropertyFunc(ws_client_DATA, targetId);
}
if (!tex) throw new Error(`Can't found a client with id "${arg.targetId}"`);
const cid = arg.targetId, clientRealId = ws_client_DATA[cid].id, capi = ws_client_DATA[cid].api;
if (capi === void 0) throw new Error(`Invalid API for client "${cid}"`);
let callbackId = void 0, callbackOwnerId = void 0;
if (arg.callback !== void 0) {
if (typeof arg.callback !== "function") throw new Error(`Invalid callback`);
const cbid = arg.callbackId || generateIdFunc({ length: 8 });
if (hasPropertyFunc(ws_callback_DATA, cbid)) throw new Error(`The id "${cbid}" is already used by another callback`);
ws_callback_DATA[cbid] = arg.callback;
callbackId = cbid;
callbackOwnerId = private_session_DATA.id;
}
await ws_sendFunc({ api: capi, msg: { id: private_session_DATA.id, object: "trigger_method", data: tgData, callbackId, callbackOwnerId } });
}
}
break;
/**
* Send from client to server(s)
*/
case "server":
{
if (isBroadcast) {
let servers = Object.keys(ws_server_DATA);
if (servers.length === 0) {
await delayFunc({ ms: dly });
servers = Object.keys(ws_server_DATA);
}
if (servers.length === 0) throw new Error(`No server found - Broadcast cancelled`);
let lrate = 0;
for (let m = 0; m < servers.length; m++) {
if (lrate > 0 && lrate % LIB_config.current.rate) await delayFunc({ ms: LIB_config.current.ms });
const cid = servers[m];
const capi = ws_server_DATA[cid].api;
const serverRealId = ws_server_DATA[cid].id;
if (capi === void 0) {
res.log = res.log + `Unable to send message to server with id "${cid}" - It API may be broken
`;
lrate++;
continue;
}
try {
await ws_sendFunc({ api: capi, msg: { id: private_session_DATA.id, object: "trigger_method", data: tgData, targetId: serverRealId, sessionFilter: arg.targetFilter || {} } });
} catch (e) {
res.log = res.log + `Unable to send message to server with id "${cid}" - ${e.message}
`;
lrate++;
continue;
}
lrate++;
}
} else {
let tex = hasPropertyFunc(ws_server_DATA, targetId);
if (!tex) {
await delayFunc({ ms: dly });
tex = hasPropertyFunc(ws_server_DATA, targetId);
}
if (!tex) throw new Error(`Can't found a server with id "${targetId}"`);
const cid = targetId, serverRealId = ws_server_DATA[cid].id, capi = ws_server_DATA[cid].api;
if (capi === void 0) throw new Error(`Invalid API for server "${cid}"`);
let callbackId = void 0, callbackOwnerId = void 0;
if (arg.callback !== void 0) {
if (typeof arg.callback !== "function") throw new Error(`Invalid callback`);
const cbid = arg.callbackId || generateIdFunc({ length: 8 });
if (hasPropertyFunc(ws_callback_DATA, cbid)) throw new Error(`The id "${cbid}" is already used by another callback`);
ws_callback_DATA[cbid] = arg.callback;
callbackId = cbid;
callbackOwnerId = private_session_DATA.id;
}
await ws_sendFunc({ api: capi, msg: { id: private_session_DATA.id, object: "trigger_method", data: tgData, callbackId, callbackOwnerId } });
}
}
break;
/* default */
default:
{
}
;
}
;
} catch (e) {
res.status = "error";
res.log = `[WebSocket] :: ${res.log + `
` + e.message}`;
}
return res;
};
var ws_restartConnectionToServerFunc = (x) => {
let res = { status: "success", log: "", data: void 0 };
try {
setupWebsocketFunc(x.config);
} catch (e) {
res.status = "error", res.data = `[WebSocket] :: ${e.message}`;
}
return res;
};
var ws_restartDeadConnectionsFunc = () => {
let res = { status: "success", log: "", data: void 0 };
try {
if (Object.keys(ws_server_config_DATA).length === 0) {
res.log = `No server found`;
return res;
}
const wsClient = ws_server_config_DATA;
for (let key in wsClient) {
const targ = wsClient[key];
if (targ.isActive || targ.retryCount !== 0) continue;
const conf = ws_restartConnectionToServerFunc({ config: targ.config });
if (conf.status !== "success") {
const lg = conf.log.replaceAll("[WebSocket] :: ", "");
throw new Error(lg);
}
}
} catch (e) {
res.status = "error";
res.log = `[WebSocket] :: ${e.message}`;
}
return res;
};
var processWebsocketFunc = async (x) => {
try {
const event = x.event;
const type = x.type || private_session_DATA.runtimeType;
const serverId = x.serverId || void 0;
const data = x.data || void 0;
const api = x.api || void 0;
const config = x.config || void 0;
switch (event) {
/**
* On open
*/
case "open":
{
if (type === "client") {
if (serverId === void 0) {
plog(`[WebSocket] :: Unable to find server ID`);
return;
}
if (!hasPropertyFunc(ws_server_config_DATA, serverId)) ws_server_config_DATA[serverId] = { config, retryCount: 0, isActive: true };
else {
ws_server_config_DATA[serverId].retryCount = 0;
ws_server_config_DATA[serverId].isActive = true;
}
self_ws_API.current = api;
const sending = await ws_sendFunc({
api: self_ws_API.current,
msg: { id: private_session_DATA.id, oldSessionId: private_session_DATA.oldSessionId, object: "client_handshake" }
});
}
}
break;
/**
* On message
*/
case "message":
{
const str = String(data);
const pars = JSON.parse(str);
const val = pars.value;
let msg = val;
if (private_session_DATA.cryptoEnable) {
const dec = await decryptFunc({ data: val });
if (dec.status !== "success") {
logFunc("dec failed ::", dec.log);
throw new Error(`[WebSocket] :: Message descryption failed`);
}
msg = typeof dec.data === "string" ? JSON.parse(dec.data) : dec.data;
}
if (typeof msg === "string") msg = JSON.parse(msg);
if (type === "client") {
const id = msg.id, object = msg.object, callbackOwnerId = msg.callbackOwnerId;
const sid = serverId || id;
switch (object) {
/* [client] :: Client first connection */
case "server_handshake":
{
const ch = hasPropertyFunc(ws_server_DATA, sid);
ws_server_DATA[sid] = { id: sid, api, store: {}, session: {} };
await ws_commitClientSessionFunc({ data: public_session_DATA });
plog(`[WebSocket] :: Successfully connected to server "${si