@xuda.io/runtime-bundle
Version:
The Xuda Runtime Bundle refers to a collection of scripts and libraries packaged together to provide the necessary runtime environment for executing plugins or components in the Xuda platform.
2,601 lines • 80.5 kB
JavaScript
glb.DEBUG_INFO_OBJ = {};
// var CONNECTION_ATTEMPTS = 0;
glb.APP_INFO = {};
// var vars = {};
// var USERS_CACHE = {};
var SYSTEM_READY = null;
// var CPI_WEBSOCKET;
var GLB_JS_SCRIPTS_LOADED = [];
var STUDIO_WEBSOCKET = null;
var STUDIO_WEBSOCKET_CONNECTION_ID = null;
var STUDIO_PEER = null;
var STUDIO_PEER_CONN_SEND_METHOD = null;
var STUDIO_PEER_CONN_ID = null;
var SUPPORT_PEER = null;
var SUPPORT_PEER_CONN = null;
var STUDIO_PEER_CONN_MSG_QUEUE = [];
var CLIENT_ACTIVITY_TS;
var IS_ONLINE;
glb.REFERENCE_LESS_FUNCTIONS = ['update', 'raise_event', 'call_library', 'invoke_action', 'loader_on', 'loader_off', 'emit_event', 'delay', 'execute_evaluate_javascript', 'execute_native_javascript'];
var CACHE_PROG_UI = {};
var ALERT_IS_ACTIVE = false;
glb.WORKER_ATTEMPTS_NOT_RESPONDING = 200000;
glb.WORKER_TIMEOUT = 600000;
glb.WORKER_PAUSE = false;
// glb.EMAIL_SEND_RECEIVE_STATUS = {};
var DATASOURCE_INTERVALS = {};
var APP_MODAL_OBJ = {};
var CURRENT_APP_POPOVER = null;
var ELEMENT_CLICK_EVENT = null;
var posX = 0; //cursor x
var posY = 0; //cursor x
var LOADER_ACTIVE = false;
var LOADER_TEXT = '';
var REFRESHER_IN_PROGRESS = false;
glb.screen_num = 0;
var RESPONSE_FROM_STUDIO_QUEUE = {};
var SCREEN_BLOCKER_OBJ = {};
var IS_PROGRESS_SCREEN_OPEN = null;
// var UI_ENGINE_OBJ = null;
var UI_WORKER_OBJ = {
jobs: [],
num: 9000,
cache: {},
viewport_height_set_ids: [],
xu_render_cache: {},
// pending_for_viewport_render: {}
};
glb.html5_events_handler = [
'onabort',
'onafterprint',
'onautocomplete',
'onautocompleteerror',
'onbeforeprint',
'onbeforeunload',
'onblur',
'oncancel',
'oncanplay',
'oncanplaythrough',
'onchange',
'onclick',
'onclose',
'oncontextmenu',
'oncopy',
'oncuechange',
'oncut',
'ondblclick',
'ondrag',
'ondragend',
'ondragenter',
'ondragexit',
'ondragleave',
'ondragover',
'ondragstart',
'ondrop',
'ondurationchange',
'onemptied',
'onended',
'onerror',
'onfocus',
'onhashchange',
'oninput',
'oninvalid',
'onkeydown',
'onkeypress',
'onkeyup',
'onload',
'onloadeddata',
'onloadedmetadata',
'onloadstart',
'onmessage',
'onmousedown',
'onmouseenter',
'onmouseleave',
'onmousemove',
'onmouseout',
'onmouseover',
'onmouseup',
'onmousewheel',
'onoffline',
'ononline',
'onpagehide',
'onpageshow',
'onpaste',
'onpause',
'onplay',
'onplaying',
'onpopstate',
'onprogress',
'onratechange',
'onreset',
'onresize',
'onscroll',
'onsearch',
'onseeked',
'onseeking',
'onselect',
'onshow',
'onsort',
'onstalled',
'onstorage',
'onsubmit',
'onsuspend',
'ontimeupdate',
'ontoggle',
'onunload',
'onvolumechange',
'onwaiting',
];
glb.lifecycle = {
plugins: {},
// queue: [],
fn_arr: ['beforeInit', 'initialized', 'systemReady', 'beforeMounted', 'mounted'],
// add(type, fn, params) {
// this.queue.push({ type, fn, params });
// },
execute: async function (SESSION_ID, event) {
const _session = SESSION_OBJ[SESSION_ID];
const xu_api = await func.common.get_module(SESSION_ID, 'xuda-api-library.mjs', {
func,
glb,
SESSION_OBJ,
SESSION_ID,
APP_OBJ,
dsSession: func.utils.get_last_datasource_no(SESSION_ID),
});
var params = {
SESSION_ID,
session_data: _session,
app_obj: APP_OBJ[_session.app_id],
xu_api,
};
for await (const [plugin_name, val] of Object.entries(glb.lifecycle.plugins)) {
if (val?.plugin_script?.[event]) {
params.setup_data = val.setup_data;
await val.plugin_script[event](params);
}
}
},
};
glb.run_xu_before = [
'xu-cdn',
'xu-style',
'xu-render',
'xu-for-key',
'xu-for-val',
// "xu-ui-plugin",
// "programParameters",
];
glb.run_xu_after = ['xu-bind', 'xu-class', 'xu-script', 'xu-ui-plugin', 'xu-ref'];
glb.attr_abbreviations_arr = ['xu-click', 'xu-dblclick', 'xu-contextmenu', 'xu-focus', 'xu-keyup', 'xu-change', 'xu-blur', 'xu-init'];
glb.solid_attributes = ['disabled'];
func.utils = {};
func.utils.debug = {};
func.utils.debug.watch = async function (SESSION_ID, key, type, info, result, condition, not_executed) {
if (!glb.DEBUG_MODE) return;
const debug_utils = await func.common.get_module(SESSION_ID, 'xuda-debug-utils-module.mjs');
debug_utils.watch(SESSION_ID, key, type, info, result, condition, not_executed);
};
func.utils.debug.log = async function (SESSION_ID, node_idP, jsonP) {
if (typeof IS_PROCESS_SERVER !== 'undefined') return;
if (!glb.DEBUG_MODE && !glb.TRACE_ON) return;
const debug_utils = await func.common.get_module(SESSION_ID, 'xuda-debug-utils-module.mjs');
debug_utils.log(SESSION_ID, node_idP, jsonP);
// console.error(jsonP);
};
func.utils.debug.write = async function (SESSION_ID, logP, callbackP) {
if (!glb.DEBUG_MODE) return;
const debug_utils = await func.common.get_module(SESSION_ID, 'xuda-debug-utils-module.mjs');
debug_utils.write(SESSION_ID, logP, callbackP);
};
func.utils.debug.read_command = async function (data) {
if (!glb.DEBUG_MODE) return;
const debug_utils = await func.common.get_module(SESSION_ID, 'xuda-debug-utils-module.mjs');
debug_utils.read_command(data);
};
func.utils.DOCS_OBJ = {};
func.utils.DOCS_OBJ.get = async function (SESSION_ID, idP) {
if (!idP || idP === '0') return;
const normalize_runtime_doc = function (doc) {
if (!doc || !func.runtime.program?.normalize_doc_for_runtime) {
return doc;
}
return func.runtime.program.normalize_doc_for_runtime(doc);
};
var _session = SESSION_OBJ[SESSION_ID];
const _app_id = _session.app_id;
if (!DOCS_OBJ[_app_id]) {
DOCS_OBJ[_app_id] = {};
}
if (DOCS_OBJ[_app_id][idP]) {
return DOCS_OBJ[_app_id][idP];
}
if (_session.project_data) {
if (idP === 'system') {
if (_session.project_data.globals) {
DOCS_OBJ[_app_id][idP] = _session.project_data.globals;
} else {
DOCS_OBJ[_app_id][idP] = {};
}
return DOCS_OBJ[_app_id][idP];
}
let val = _session.project_data?.programs?.[idP];
if (val) {
DOCS_OBJ[_app_id][idP] = normalize_runtime_doc(val);
return DOCS_OBJ[_app_id][idP];
}
}
if (typeof _session.SLIM_BUNDLE === 'undefined' || !_session.SLIM_BUNDLE) {
const module = await func.common.get_module(SESSION_ID, `xuda-progs-loader-module.mjs`);
if (idP !== 'system') {
DOCS_OBJ[_app_id][idP] = normalize_runtime_doc(await module.DOCS_OBJ_get(SESSION_ID, idP));
if (DOCS_OBJ[_app_id][idP] && xu_isEmpty(DOCS_OBJ[_app_id][idP])) {
await func.utils.remove_cached_objects(SESSION_ID);
delete DOCS_OBJ[_app_id][idP];
}
return DOCS_OBJ[_app_id][idP];
}
DOCS_OBJ[_app_id][idP] = await module.DOCS_OBJ_get(SESSION_ID, 'global_' + (APP_OBJ[_app_id].app_replicate || _app_id));
if (APP_OBJ[_app_id].app_imported_projects) {
for await (const imported_app_id of APP_OBJ[_app_id].app_imported_projects) {
var view_ret = await module.DOCS_OBJ_get(SESSION_ID, 'global_' + imported_app_id);
DOCS_OBJ[_app_id][idP] = Object.assign(DOCS_OBJ[_app_id][idP], view_ret);
}
}
return DOCS_OBJ[_app_id][idP];
}
console.error(`${idP} not found`);
};
func.utils.FILES_OBJ = {};
func.utils.FILES_OBJ.get = async function (SESSION_ID, idP) {
if (!idP) return;
return await func.utils.DOCS_OBJ.get(SESSION_ID, idP);
};
func.utils.VIEWS_OBJ = {};
func.utils.VIEWS_OBJ.get = async function (SESSION_ID, idP) {
if (!idP) return;
return await func.utils.DOCS_OBJ.get(SESSION_ID, idP);
};
func.utils.TREE_OBJ = {};
func.utils.TREE_OBJ.get = async function (SESSION_ID, idP) {
if (!idP) return;
var ret = await func.utils.DOCS_OBJ.get(SESSION_ID, idP);
if (ret?.properties) {
ret.properties.id = idP;
}
return ret.properties;
};
func.utils.get_dateTime = async function (SESSION_ID, typeP, dateP) {
// const getUTC = function (ts) {
// var date = new Date(ts);
// var utc_date = new Date(
// date.getUTCFullYear(),
// date.getUTCMonth(),
// date.getUTCDate(),
// date.getUTCHours(),
// date.getUTCMinutes(),
// date.getUTCSeconds(),
// date.getUTCMilliseconds()
// );
// return utc_date;
// };
const get_server_ts = async function () {
var _session = SESSION_OBJ[SESSION_ID];
const response = await fetch(`https://${_session.domain}/cpi/get_utc_ts`, {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({}),
});
const json = await response.json();
return json.data;
// }
};
function getWeekNumber(d) {
// Copy date so don't modify original
d = new Date(+d);
d.setHours(0, 0, 0);
// Set to nearest Thursday: current date + 4 - current day number
// Make Sunday's day number 7
d.setDate(d.getDate() + 4 - (d.getDay() || 7));
// Get first day of year
var yearStart = new Date(d.getFullYear(), 0, 1);
// Calculate full weeks to nearest Thursday
var weekNo = Math.ceil(((d - yearStart) / 86400000 + 1) / 7);
// Return array of year and week number
return weekNo;
}
var sysDate = new Date(dateP); // getUTC(dateP); //new Date(dateP);
if (!dateP) {
let ts = await get_server_ts();
sysDate = new Date(ts);
}
var day = String(sysDate.getDate()).padStart(2, '0');
var month = String(sysDate.getMonth() + 1).padStart(2, '0');
var year = sysDate.getFullYear();
var week = String(getWeekNumber(sysDate)).padStart(2, '0');
var hour = String(sysDate.getHours()).padStart(2, '0');
var minute = String(sysDate.getMinutes()).padStart(2, '0');
var second = String(sysDate.getSeconds()).padStart(2, '0');
if (typeP === 'SYS_DATE') return year + '-' + month + '-' + day;
if (typeP === 'SYS_DATE_TIME') return year + '-' + month + '-' + day + 'T' + hour + ':' + minute;
if (typeP === 'SYS_DATE_VALUE') return sysDate.valueOf();
if (typeP === 'SYS_DATE_WEEK_YEAR') return year + 'W' + week;
if (typeP === 'SYS_DATE_MONTH_YEAR') return year + '-' + month;
if (typeP === 'SYS_TIME') return hour + ':' + minute + ':' + second;
if (typeP === 'SYS_TIME_SHORT') return hour + ':' + minute;
};
func.utils.is_onscreen_event = function (functionP) {
const arr = ['invoke_action', 'cache_refresh', 'call_popover', 'call_modal', 'call_page', 'loader_on', 'loader_off', 'emit_event'];
return arr.includes(functionP);
};
func.utils.get_screen_obj = async function (SESSION_ID, id) {
const prog_obj = await func.utils.VIEWS_OBJ.get(SESSION_ID, id);
if (!prog_obj) return console.error('prog not found: ' + id);
// if (prog_obj.properties.menuType === 'screen' || prog_obj.properties.menuType === 'api' || glb.FUNCTION_NODES_ARR.includes(prog_obj.properties.menuType) || glb.MOBILE_ARR.includes(prog_obj.properties.menuType)) {
if (['component', ...glb.FUNCTION_NODES_ARR].includes(prog_obj.properties.menuType)) {
return prog_obj;
}
return;
};
func.utils.clean_returned_datasource = function (SESSION_ID, DS) {
const clean_object_functions = function (obj) {
for (const [key, val] of Object.entries(obj)) {
if (typeof val === 'function') {
delete obj[key];
}
}
};
var _session = SESSION_OBJ[SESSION_ID];
if (!_session.DS_GLB[DS]) return;
var obj = { ..._session.DS_GLB[DS] };
delete obj.screen_params;
// try {
// clean_object_functions(obj);
// obj = JSON.parse(JSON.stringify(obj, func.utils.clean_stringify_null, '\t'));
// } catch (e) {
// console.error(e);
// }
delete obj.pre_init_fields;
delete obj.oninit_triggers_to_run;
// delete obj.raw_data;
delete obj.debug;
const clean_empty_objects = function () {
for (const [key, val] of Object.entries(obj)) {
if (typeof val === 'object' && !Array.isArray(val) && xu_isEmpty(val)) {
delete obj[key];
}
}
for (const [key, val] of Object.entries(obj)) {
if (typeof val === 'object' && Array.isArray(val) && !val.length) {
delete obj[key];
}
}
};
delete obj.screenInfo;
delete obj.viewEventsProp;
delete obj.viewSourceDesc;
delete obj.viewSourceProp;
delete obj.v;
clean_empty_objects();
try {
clean_object_functions(obj);
obj = JSON.parse(JSON.stringify(obj, func.utils.clean_stringify_null, '\t'));
} catch (e) {
console.error(e);
}
// clean_dataset();
return obj;
};
func.utils.post_back_to_client = function (SESSION_ID, service, id, data) {
if (typeof IS_PROCESS_SERVER !== 'undefined') return;
worker_post_message({
fx_to_execute: service,
params: data,
session_id: SESSION_ID,
worker_id: id,
});
};
func.utils.job_worker = {};
func.utils.job_worker = function (session_id) {
var SESSION_ID = session_id;
var _session = SESSION_OBJ[SESSION_ID];
var is_progressScreen_on;
var is_not_responding;
var attempt = 0;
const lock = function (dsP) {
if (!_session.WORKER_OBJ.jobs[_session.WORKER_OBJ.stat] || _session.WORKER_OBJ.jobs[_session.WORKER_OBJ.stat].typeP === 'system_interval' || _session.WORKER_OBJ.jobs[_session.WORKER_OBJ.stat].typeP === 'system event') {
return;
}
if (glb.IS_WORKER) {
func.utils.post_back_to_client(SESSION_ID, 'screen_blocker_on', _session.worker_id, null);
} else {
func.UI.utils.screen_blocker(true, 'Worker', dsP);
}
};
const unlock = function () {
if (glb.IS_WORKER) {
} else {
func.UI.utils.screen_blocker(false, 'Worker');
}
};
const not_responding = function () {
is_not_responding = true;
func.UI.utils.progressScreen.hide('Working, Please wait..');
setTimeout(function () {
if (!is_not_responding) return;
reset();
}, 500);
};
const idle = function () {
if (is_progressScreen_on) {
setTimeout(function () {
if (!attempt && is_progressScreen_on) {
is_progressScreen_on = false;
is_not_responding = false;
func.UI.utils.progressScreen.hide('Working, Please wait..');
} else if (attempt > 300 && is_not_responding) {
is_not_responding = false;
busy();
}
}, 310);
} else {
if (!glb.IS_WORKER) {
// func.UI.screen.garbage_collector(SESSION_ID);
}
}
};
const busy = function () {
if (glb.IS_WORKER) return;
func.utils.debug_report(SESSION_ID, 'utils.worker.busy', 'worker processing more then 10 second', 'W', '', _session.WORKER_OBJ.jobs);
is_progressScreen_on = true;
};
const reset = function () {
func.utils.debug_report(SESSION_ID, 'utils.worker.reset', 'worker not responding', 'E', '', _session.WORKER_OBJ.jobs);
_session.WORKER_OBJ.jobs = [];
_session.WORKER_OBJ.stat = null;
func.runtime.ui.clear_screen_blockers();
};
return {
_interval: null,
_was_busy: null,
init: async function () {
var _this = this;
this._interval = setInterval(async function () {
var _session = SESSION_OBJ[SESSION_ID];
if (!_session?.WORKER_OBJ) return;
if (typeof _session.WORKER_OBJ.stat === 'undefined' || _session.WORKER_OBJ.stat === 'undefined' || _session.WORKER_OBJ.stat === null) {
// idle
// if (_this._was_busy) {
// if (glb.IS_WORKER) {
// func.utils.post_back_to_client(
// SESSION_ID,
// "worker_busy_off",
// _session.worker_id,
// null
// );
// } else {
// func.UI.utils.indicator.worker.normal();
// }
// _this._was_busy = false;
// }
unlock();
if (_session.WORKER_OBJ.jobs.length) {
for await (const [key, val] of Object.entries(_session.WORKER_OBJ.jobs)) {
if (val.stat) {
break;
}
// if (!_session.WORKER_OBJ.stat) {
if (!_session.WORKER_OBJ.jobs[Number(key)] || val.job_num === 9999999) {
continue;
}
if (val.dsSessionP && !_session.DS_GLB[val.dsSessionP]) {
func.events.delete_job(SESSION_ID, val.job_num);
break;
}
await func.events.execute(
SESSION_ID,
val.job_num,
val.eventIdP,
val.triggerP,
val.functionP,
val.refIdP,
val.containerP,
val.elementP,
val.rowP,
val.evt,
val.descP,
val.rootScreenIdP,
val.dsSessionP,
null,
val.typeP,
null,
val.event_propertiesP,
val.calling_triggerP,
null,
val.paramsP,
val.target_frame_idP,
val.calling_trigger_prop,
val.calling_program,
val.argumentsP,
val.prog_id,
val.nodeId,
val.parentDataSourceNo,
val.$container,
val.event_optionsP,
);
}
_this._was_busy = true;
} else {
// idle
if (_this._was_busy) {
if (glb.IS_WORKER) {
func.utils.post_back_to_client(SESSION_ID, 'worker_busy_off', _session.worker_id, null);
} else {
func.UI.utils.indicator.worker.normal();
}
}
_this._was_busy = false;
}
attempt = 0;
is_not_responding = false;
idle();
} else {
//busy
_this._was_busy = true;
if (glb.IS_WORKER) {
func.utils.post_back_to_client(SESSION_ID, 'worker_busy_on', _session.worker_id, null);
} else {
func.UI.utils.indicator.worker.busy();
}
if (glb.WORKER_PAUSE) return;
attempt++;
if (!is_progressScreen_on && attempt > glb.WORKER_TIMEOUT) busy();
if (!is_not_responding && attempt >= glb.WORKER_ATTEMPTS_NOT_RESPONDING) {
not_responding();
}
var ds = null;
if (_session.WORKER_OBJ.jobs[0]) ds = _session.WORKER_OBJ.jobs[0].dsSessionP;
lock(ds);
}
}, 1);
},
stop: function () {
clearInterval(this._interval);
},
};
};
func.utils.base64MimeType = function (encoded) {
var result = null;
if (typeof encoded !== 'string') {
return result;
}
var mime = encoded.match(/data:([a-zA-Z0-9]+\/[a-zA-Z0-9-.+]+).*,.*/);
if (mime && mime.length) {
result = mime[1];
}
return result;
};
func.utils.makeid = function (length) {
var result = '';
var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
var charactersLength = characters.length;
for (var i = 0; i < length; i++) {
result += characters.charAt(Math.floor(Math.random() * charactersLength));
}
return result;
};
func.utils.get_device = function () {
var device;
try {
const win = func.runtime.platform.get_window();
if (win?.cordova) {
device = win.cordova.platformId;
}
} catch (e) {
console.error('error using ui element in server side request');
}
return device;
};
func.utils.ws_worker = {};
func.utils.ws_worker.functions = {
init: async function (data) {
var SESSION_ID = data.SESSION_ID;
APP_OBJ[data.app_id] = data.APP_OBJ;
PROJECT_OBJ[data.app_id] = data.PROJECT_OBJ;
if (['live_preview', 'miniapp'].includes(data.SESSION_INFO.engine_mode)) {
DOCS_OBJ[data.app_id] = data.DOCS_OBJ;
} else if (typeof IS_DOCKER === 'undefined' && typeof IS_PROCESS_SERVER === 'undefined') {
if (!DOCS_OBJ[data.app_id]) {
DOCS_OBJ[data.app_id] = {};
}
}
glb.APP_INFO[data.app_id] = data.APP_INFO;
glb.DEBUG_MODE = data.DEBUG_MODE;
glb.DEBUG_INFO_OBJ = data.DEBUG_INFO_OBJ;
glb.WINDOW_LOCATION_SEARCH = data.WINDOW_LOCATION_SEARCH;
glb.ROOT_ELEMENT_ATTRIBUTES = data.ROOT_ELEMENT_ATTRIBUTES;
DATASOURCE_INTERVALS[SESSION_ID] = {};
SESSION_OBJ[SESSION_ID] = data.SESSION_INFO;
var _session = SESSION_OBJ[SESSION_ID];
glb.SESSION_INFO = data.SESSION_INFO;
_session.engine_mode = data.engine_mode;
STUDIO_WEBSOCKET_CONNECTION_ID = data.STUDIO_WEBSOCKET_CONNECTION_ID;
for (let [key, val] of Object.entries(_session.DS_GLB)) {
if (Number(key) > _session.dataSourceSessionGlobal) {
_session.dataSourceSessionGlobal = Number(key);
}
}
if (typeof _session.SLIM_BUNDLE === 'undefined' || !_session.SLIM_BUNDLE) {
const db_adapter = await func.common.get_module(SESSION_ID, 'xuda-db-adapter-module.mjs');
func.db = db_adapter._db;
}
_session.WORKER_OBJ.fx = new func.utils.job_worker(SESSION_ID);
_session.WORKER_OBJ.fx.init();
if (_session.app_id === 'unknown') {
worker_post_message({
fx_to_execute: 'init_done',
worker_id: ws_worker_id,
session_id: SESSION_ID,
});
} else {
const module = await func.common.get_module(SESSION_ID, `xuda-progs-loader-module.mjs`);
await module.load_objects_cache(SESSION_ID);
worker_post_message({
fx_to_execute: 'init_done',
worker_id: ws_worker_id,
session_id: SESSION_ID,
});
}
WEB_WORKER_CALLBACK_QUEUE[SESSION_ID] = {};
},
datasource_create: async function (params, promise_queue_id) {
var SESSION_ID = params.session_id;
var _session = SESSION_OBJ[SESSION_ID];
_session.ts = new Date().getTime();
var args = params;
args.SESSION_ID = SESSION_ID;
if (show_log) {
console.log('DATASOURCE EXECUTING SESSION_ID: ' + SESSION_ID, APP_OBJ[_session.app_id].app_name);
}
if (Number(params.dataSourceSessionGlobal) > _session.dataSourceSessionGlobal) {
_session.dataSourceSessionGlobal = Number(params.dataSourceSessionGlobal);
}
const ret = await func.datasource.prepare(
args.SESSION_ID,
args.prog_id,
args.dataSourceNoP,
args.parentDataSourceNoP,
args.containerIdP,
args.rowIdP,
args.jobNoP,
args.calling_trigger_prop,
args.parameters_raw_obj,
null,
args.callingSourceP,
args.calling_jobP,
args.screen_dsP,
args.is_panelP,
args.parameters_obj_inP,
args.static_refreshP,
args.run_atP,
args.worker_id,
);
try {
let _ds = _session.DS_GLB[ret.dsSessionP];
if (show_log) console.log('DATASOURCE EXECUTION DONE ' + ret.dsSessionP + ' ' + _ds?.tree_obj?.menuName || '' + ' SESSION_ID: ' + SESSION_ID, APP_OBJ[_session.app_id].app_name);
var obj = func.utils.clean_returned_datasource(SESSION_ID, ret?.dsSessionP);
obj.dataSourceSessionGlobal = _session.dataSourceSessionGlobal;
worker_post_message({
promise_queue_id,
params: obj,
worker_id: ws_worker_id,
session_id: SESSION_ID,
process_pid: params.process_pid,
service: params.service,
});
_ds.stat = 'idle';
} catch (error) {
console.error('[xuda-runtime] caught xuda_utils.js:606:', error);
}
},
datasource_delete: function (params, promise_queue_id) {
var SESSION_ID = params.session_id;
var _session = SESSION_OBJ[SESSION_ID];
if (DATASOURCE_INTERVALS[SESSION_ID] && DATASOURCE_INTERVALS[SESSION_ID][params.dssession]) {
DATASOURCE_INTERVALS[SESSION_ID][params.dssession].clear();
}
delete _session.DS_GLB[params.dssession];
if (show_log) console.log('DATASOURCE DELETE SESSION_ID: ' + SESSION_ID, APP_OBJ[_session.app_id].app_name, params.dssession);
console.error('[xuda-runtime] caught xuda_utils.js:617:', error);
worker_post_message({
promise_queue_id,
worker_id: ws_worker_id,
session_id: SESSION_ID,
process_pid: params.process_pid,
service: params.service,
});
},
update_datasource_changes_from_client: async function (params, promise_queue_id) {
if (xu_isEmpty(SESSION_OBJ)) return;
var SESSION_ID = params.session_id;
var _session = SESSION_OBJ[SESSION_ID];
if (!_session) {
_session = {};
_session.app_id = params.app_id;
_session.dataSourceSessionGlobal = -1;
_session.DS_GLB = {};
}
if (show_log) console.log('DATASOURCE UPDATE SESSION_ID: ' + SESSION_ID, APP_OBJ[_session.app_id].app_name, params.dssession);
await func.datasource.update(SESSION_ID, params.datasource_changes, true);
worker_post_message({
promise_queue_id,
params: params.dssession,
worker_id: ws_worker_id,
session_id: SESSION_ID,
process_pid: params.process_pid,
service: params.service,
});
},
return_to_data_source: function (params, promise_queue_id) {
var SESSION_ID = params.session_id;
var _session = SESSION_OBJ[SESSION_ID];
var ds = _session.DS_GLB[params.dssession];
var type = params.return_to_data_source_type;
var args = ds.args;
if (show_log) console.log('DATASOURCE RETURN TO DATASOURCE ' + params.dssession + ' SESSION_ID: ' + SESSION_ID, APP_OBJ[_session.app_id].app_name);
_session.DS_GLB[params.dssession].v.onscreen_events_active = params.onscreen_events_active;
if (params.viewEventExec_arr) _session.DS_GLB[params.dssession].viewEventExec_arr = JSON.parse(params.viewEventExec_arr);
var done = function (SESSION_ID, DS) {
if (show_log) console.log('DATASOURCE RETURN TO DATASOURCE DONE ' + DS + ' SESSION_ID: ' + SESSION_ID, APP_OBJ[_session.app_id].app_name);
var obj = func.utils.clean_returned_datasource(SESSION_ID, DS);
obj.dataSourceSessionGlobal = _session.dataSourceSessionGlobal;
worker_post_message({
fx_to_execute: 'post_datasource',
params: {
ds_obj: obj,
dsSessionP: params.dssession,
},
worker_id: ws_worker_id,
session_id: SESSION_ID,
process_pid: params.process_pid,
service: params.service,
});
};
done(SESSION_ID, params.dssession);
},
acknowledged_worker_with_eventChangesResults_done: function (params) {
var SESSION_ID = params.session_id;
var _session = SESSION_OBJ[SESSION_ID];
var ds = _session.DS_GLB[params.dssession];
if (show_log) console.log('UPDATE CHANGE EVENT DONE TO DATASOURCE ' + params.dssession + ' SESSION_ID: ' + SESSION_ID, APP_OBJ[_session.app_id].app_name);
ds.eventChangesResults_done = true;
},
return_from_db_query: function (params) {
var SESSION_ID = params.session_id;
var _session = SESSION_OBJ[SESSION_ID];
var id = params.id;
if (show_log) console.log('RETURN FROM DB_QUERY ' + params.dssession + ' SESSION_ID: ' + SESSION_ID, APP_OBJ[_session.app_id].app_name);
var callback = func.utils.get_callback_queue(SESSION_ID, params.callback_id);
if (callback) callback(params.data);
},
return_from_sava_data: function (params) {
var SESSION_ID = params.session_id;
var _session = SESSION_OBJ[SESSION_ID];
var id = params.id;
if (show_log) console.log('RETURN FROM SAVE_DATA ' + params.dssession + ' SESSION_ID: ' + SESSION_ID, APP_OBJ[_session.app_id].app_name);
func.utils.get_callback_queue(SESSION_ID, params.callback_id)();
},
update_debug_info: function (params) {
glb.DEBUG_INFO_OBJ = params;
},
// update_VIEWS_OBJ: function (params) {
// delete VIEWS_OBJ[APP_ID][params.id];
// },
// update_TREE_OBJ: function (params) {
// delete TREE_OBJ[APP_ID][params.id];
// },
// send_object_to_worker: function (params) {
// if (RESPONSE_FROM_STUDIO_QUEUE[params.req_id]) {
// RESPONSE_FROM_STUDIO_QUEUE[params.req_id].data = params;
// }
// },
get_dataSourceSessionGlobal: function (params) {
var SESSION_ID = params.session_id;
SESSION_OBJ[SESSION_ID].dataSourceSessionGlobal++;
let new_dataSourceSessionGlobal = SESSION_OBJ[SESSION_ID].dataSourceSessionGlobal;
return { new_dataSourceSessionGlobal };
},
create_webworker_globals: function (params) {
var SESSION_ID = params.session_id;
SESSION_OBJ[SESSION_ID].DS_GLB[0] = params.ds_data;
},
return_doc_from_studio: function (params) {
var SESSION_ID = params.session_id;
function emitCustomEvent(eventName, detail) {
const event = new CustomEvent(eventName, { detail });
self.dispatchEvent(event);
}
emitCustomEvent('live_preview_get_obj_response_worker_' + params._id, {
data: params,
});
},
return_doc_from_websocket: function (params) {
var SESSION_ID = params.session_id;
function emitCustomEvent(eventName, detail) {
const event = new CustomEvent(eventName, { detail });
self.dispatchEvent(event);
}
emitCustomEvent('get_doc_obj_from_build_worker_' + params._id, {
data: params,
});
},
return_dbs_data_from_websocket: function (params) {
var SESSION_ID = params.session_id;
function emitCustomEvent(eventName, detail) {
const event = new CustomEvent(eventName, { detail });
self.dispatchEvent(event);
}
emitCustomEvent('get_ws_data_worker_' + params.websocket_queue_num, {
data: params.data,
});
},
heartbeat: async function (params) {
var SESSION_ID = params.session_id;
try {
const do_heartbeat = async function (app_replicate, app_id, token_id, fingerprint, device_name, stat) {
try {
module.exports.close_expired_device_log_sessions(app_id);
return await update_device(app_replicate, app_id, token_id, fingerprint, device_name, stat);
} catch (err) {
return { code: -400, data: err.message };
}
};
let ret = await do_heartbeat(params.app_replicate, params.app_id, params.gtp_token || req.body.app_token, params.fingerprint, params.device_name, params.stat);
// session_status: ret_session.data.stat
if (params.token) {
try {
const couch = await __.rpi.get_app_couch(req.body.app_id);
const session_doc = await couch.get(req.body.app_token);
ret.session_stat = session_doc.stat;
} catch (error) {}
}
} catch (error) {
console.error('[xuda-runtime] caught xuda_utils.js:780:', error);
}
},
return_rpi_request_from_studio: function (params) {
var SESSION_ID = params.session_id;
function emitCustomEvent(eventName, detail) {
const event = new CustomEvent(eventName, { detail });
self.dispatchEvent(event);
}
emitCustomEvent('rpi_request_response_worker_' + params.table_id, {
data: params.data,
});
},
};
func.utils.set_callback_queue = function (SESSION_ID, func) {
var t = new Date().valueOf().toString() + Math.random().toString();
try {
WEB_WORKER_CALLBACK_QUEUE[SESSION_ID][t] = func;
} catch (e) {
console.error(id);
func.utils.remove_cached_objects(SESSION_ID);
}
return t;
};
func.utils.get_callback_queue = function (SESSION_ID, t) {
var func = WEB_WORKER_CALLBACK_QUEUE[SESSION_ID][t];
setTimeout(function () {
if (WEB_WORKER_CALLBACK_QUEUE[SESSION_ID][t]) delete WEB_WORKER_CALLBACK_QUEUE[SESSION_ID][t];
}, 1000);
return func;
};
func.utils.clean_stringify_null = function (key, value) {
// Filtering out properties
if (value === null) {
return undefined;
}
return value;
};
func.utils.load_js_on_demand = async function (js_src, type) {
const normalized_src = typeof js_src === 'string' ? js_src.trim() : '';
if (!normalized_src || normalized_src === 'undefined' || normalized_src === 'null') {
return false;
}
const get_script = function (callback) {
if (glb.IS_WORKER) {
callback();
return;
}
function isScriptLoaded(src) {
return GLB_JS_SCRIPTS_LOADED.includes(src);
}
if (isScriptLoaded(normalized_src)) {
callback(false);
} else {
func.runtime.platform.load_script(normalized_src, type, function () {
callback(true);
GLB_JS_SCRIPTS_LOADED.push(normalized_src);
});
}
};
return new Promise((resolve) => {
get_script(resolve);
});
};
func.utils.load_css_on_demand = function (css_href) {
const normalized_href = typeof css_href === 'string' ? css_href.trim() : '';
if (!normalized_href || normalized_href === 'undefined' || normalized_href === 'null') {
return null;
}
return func.runtime.platform.load_css(normalized_href);
};
func.utils.remove_js_css_file = function (filename, filetype) {
func.runtime.platform.remove_js_css(filename, filetype);
};
func.utils.replace_studio_drive_url = function (SESSION_ID, val) {
var _session = SESSION_OBJ[SESSION_ID];
if (!_session.is_deployment) return val;
try {
const rep = APP_OBJ[_session.app_id].app_replicate;
const dest = `https://${_session.domain}/studio-drive/${rep}`;
const rep_esc = rep.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
// Rewrite every legacy studio-drive host to the live domain: stale xuda.io hardcodings,
// and any xuda.ai host incl. subdomains (xuda.ai, master.xuda.ai, eu.xuda.ai, ...).
return val
.replaceAll(`https://xuda.io/studio-drive/${rep}`, dest)
.replace(new RegExp(`https://(?:[a-z0-9-]+\\.)*xuda\\.ai/studio-drive/${rep_esc}`, 'g'), dest);
} catch (err) {
return val;
}
};
func.utils.get_drive_url = function (SESSION_ID, val, wrap) {
// wrap = false; // tbd bypass
var _session = SESSION_OBJ[SESSION_ID];
function replaceFiletoURL(fileString) {
const _app = APP_OBJ[_session.app_id];
let url = `https://${_session.domain}/workspace-drive/${_app.is_deployment ? _app.app_datacenter_id : _app.app_id_reference}/`;
let FILE_REPLACE_URL = `${url}${val}`;
if (!_app.is_deployment) {
// the deployment server will handle the app_token
FILE_REPLACE_URL += `?app_token=${_session.app_token}&ts=${Date.now()}`;
} else {
FILE_REPLACE_URL += `?ts=${_session?.opt?.app_build_id || 0}`;
}
let match = `drv_${_app.app_replicate || _session.app_id}_[0-9a-f\\-]+\\.[a-zA-Z0-9]+`;
let pat = new RegExp(match, 'g');
let URLString = fileString.replace(pat, function (match, idx) {
const hasURLbefore = fileString.substring(idx - url.length, idx) === url;
if (hasURLbefore) {
return match;
}
return FILE_REPLACE_URL.replace('{val}', match);
});
return URLString;
}
if (typeof val === 'string' || typeof val === 'object') {
if (typeof val === 'string') {
if (val.includes('.') && val.includes('drv_') && val.length > 30) {
var ret = replaceFiletoURL(val);
if (wrap) {
return { value: '"' + ret + '"', changed: true };
} else {
return { value: ret, changed: true };
}
} else {
return { value: val, changed: false };
}
}
if (typeof val === 'object') {
// XU_PERF fast path: stringifying every bound object per evaluation just
// to look for 'drv_' is a hot-loop tax. Clean verdicts are memoized per
// object reference; datasource.update clears the cache, so a mutation can
// never outlive the refresh that would re-evaluate it. Only on a
// (possible) hit fall through to the exact legacy stringify path.
if (glb.XU_PERF) {
if (func.utils.drive_ref_clean_cache.has(val)) {
return { value: val, changed: false };
}
if (!func.utils.has_drive_ref(val, 0)) {
func.utils.drive_ref_clean_cache.add(val);
return { value: val, changed: false };
}
}
try {
let str = JSON.stringify(val);
if (str.includes('.') && str.includes('drv_') && str.length > 30) {
let new_val = replaceFiletoURL(str);
return { value: new_val, changed: true };
} else {
return { value: val, changed: false };
}
} catch (err) {
return { value: val, changed: false };
}
}
} else {
return { value: val, changed: false };
}
};
func.utils.drive_ref_clean_cache = new WeakSet();
// Early-exit scan for 'drv_' drive-file references in keys or string values.
// Returns true on any hit OR when traversal gives up (depth cap), so callers
// fall back to the exact legacy stringify detection in those cases.
func.utils.has_drive_ref = function (v, depth) {
if (typeof v === 'string') return v.includes('drv_');
if (v === null || typeof v !== 'object') return false;
if (depth > 8) return true; // too deep to be sure: let legacy path decide
if (Array.isArray(v)) {
for (let i = 0; i < v.length; i++) {
if (func.utils.has_drive_ref(v[i], depth + 1)) return true;
}
return false;
}
for (const k in v) {
if (k.includes('drv_')) return true;
if (func.utils.has_drive_ref(v[k], depth + 1)) return true;
}
return false;
};
func.utils._error_registry_module = func.utils._error_registry_module || null;
func.utils._error_registry_pending = func.utils._error_registry_pending || null;
func.utils.get_error_registry = async function (SESSION_ID) {
if (func.utils._error_registry_module) {
return func.utils._error_registry_module;
}
if (func.utils._error_registry_pending) {
return await func.utils._error_registry_pending;
}
if (!SESSION_ID || !SESSION_OBJ?.[SESSION_ID]) {
return null;
}
func.utils._error_registry_pending = func.common
.get_module(SESSION_ID, 'xuda-error-registry-module.mjs')
.then((module) => {
func.utils._error_registry_module = module;
return module;
})
.catch((err) => {
console.warn('XUDA WARNING RUN_MSG_NET_010', 'Failed to load error registry module', err);
return null;
})
.finally(() => {
func.utils._error_registry_pending = null;
});
return await func.utils._error_registry_pending;
};
func.utils._normalize_issue_severity = function (type, fallback = 'error') {
if (!type) return fallback;
const normalized = type.toString().toLowerCase();
if (['w', 'warn', 'warning'].includes(normalized)) return 'warning';
if (['i', 'info', 'log'].includes(normalized)) return 'info';
return 'error';
};
func.utils._serialize_issue_value = function (value, seen = new WeakSet()) {
if (value instanceof Error) {
return {
name: value.name,
message: value.message,
stack: value.stack,
cause: value.cause,
};
}
if (typeof value === 'undefined' || value === null) {
return value;
}
if (typeof value === 'function') {
return `[Function ${value.name || 'anonymous'}]`;
}
if (typeof value !== 'object') {
return value;
}
if (seen.has(value)) {
return '[Circular]';
}
seen.add(value);
if (Array.isArray(value)) {
return value.map((item) => func.utils._serialize_issue_value(item, seen));
}
const ret = {};
for (const [key, val] of Object.entries(value)) {
ret[key] = func.utils._serialize_issue_value(val, seen);
}
return ret;
};
func.utils._stringify_issue_message = function (value) {
if (typeof value === 'undefined' || value === null) {
return '';
}
if (typeof value === 'string') {
return value;
}
if (value instanceof Error) {
return value.message || value.toString();
}
try {
return JSON.stringify(func.utils._serialize_issue_value(value));
} catch (error) {
return value?.toString?.() || '';
}
};
func.utils._build_fallback_issue_definition = function (payload = {}) {
const code = payload.code || 'RUN_MSG_GEN_000';
const severity = func.utils._normalize_issue_severity(payload.type || payload.severity, code.startsWith('CHK_MSG_') ? 'warning' : 'error');
return {
code,
title: payload.title || (code.startsWith('CHK_MSG_') ? 'Studio Checker Validation Issue' : 'Runtime Error'),
severity,
domain: code.startsWith('CHK_MSG_') ? 'checker' : 'runtime',
category: payload.category || 'general',
summary: payload.message || 'The runtime reported an issue.',
help_slug: payload.help_slug || code.toLowerCase().replace(/_/g, '-'),
};
};
func.utils.report_issue = async function (SESSION_ID, payload = {}) {
const err = payload.err instanceof Error ? payload.err : payload.error instanceof Error ? payload.error : null;
const source = payload.source || payload.method || 'runtime';
const message = func.utils._stringify_issue_message(
typeof payload.message !== 'undefined' ? payload.message : typeof payload.msg !== 'undefined' ? payload.msg : err || payload.details || 'Unknown runtime issue',
);
try {
const registry = await func.utils.get_error_registry(SESSION_ID);
const registry_payload = {
code: payload.code,
source,
message,
type: payload.type || payload.severity,
err,
details: payload.details,
category: payload.category,
};
let definition = null;
if (registry?.get_error_definition && payload.code) {
definition = registry.get_error_definition(payload.code, registry_payload);
}
if (!definition && registry?.get_runtime_report_definition) {
definition = registry.get_runtime_report_definition(registry_payload);
}
if (!definition) {
definition = func.utils._build_fallback_issue_definition({
...payload,
source,
message,
});
}
const severity = func.utils._normalize_issue_severity(payload.type || payload.severity, definition.severity || 'error');
const error_code = definition.code || payload.code || 'RUN_MSG_GEN_000';
const error_title = definition.title || payload.title || 'Runtime Error';
const help_slug = definition.help_slug || error_code.toLowerCase().replace(/_/g, '-');
const console_method = severity === 'warning' ? 'warn' : severity === 'info' ? 'log' : 'error';
const _session = SESSION_OBJ?.[SESSION_ID];
const report = {
error_code,
error_title,
help_slug,
severity,
error_domain: definition.domain || 'runtime',
error_category: definition.category || payload.category || 'general',
source,
message,
stack: err?.stack || null,
app_id: _session?.app_id || payload.app_id || null,
session_id: SESSION_ID || null,
worker: !!glb?.IS_WORKER,
summary: definition.summary || message,
};
const details = {
report,
error: func.utils._serialize_issue_value(err),
context: func.utils._serialize_issue_value(payload.details),
extra: func.utils._serialize_issue_value(payload.extra),
};
const console_prefix = `XUDA ${console_method.toUpperCase()} ${error_code}`;
const console_summary = `${error_title}: ${source}${message ? ' | ' + message : ''}`;
if (glb?.debug_js && console.groupCollapsed) {
console.groupCollapsed(console_prefix, console_summary);
console[console_method](report);
if (details.context) console.log('context', details.context);
if (err) console.error(err);
console.groupEnd();
} else {
console[console_method](console_prefix, console_summary, {
help_slug,
});
}
if (!payload.skip_log && SESSION_ID && _session) {
await func.utils.write_log(SESSION_ID, source, message || error_title, console_method, payload.log_source || 'runtime', details, report);
}
return report;
} catch (report_err) {
console.error('XUDA ERROR RUN_MSG_GEN_000', 'Failed to report runtime issue', report_err, {
source,
message,
payload,
});
return null;
}
};
func.utils.debug_report = async function (SESSION_ID, sourceP, msgP, typeP, errP, objP) {
if (!typeP || typeP === 'E') {
setTimeout(() => {
// if (
// typeof IS_DOCKER === "undefined" &&
// typeof IS_API_SERVER === "undefined" &&
// typeof IS_PROCESS_SERVER === "undefined" &&
// !glb?.IS_WORKER
// ) {
// func.index.delete_pouch(SESSION_ID);
// }
}, 1000);
}
await func.utils.report_issue(SESSION_ID, {
source: sourceP,
message: msgP,
type: typeP,
err: errP,
details: objP,
});
};
func.utils.request_error = function (SESSION_ID, type, e) {
var _session = SESSION_OBJ[SESSION_ID];
console.error(type, e);
if (typeof IS_PROCESS_SERVER !== 'undefined') return;
if (!glb.IS_WORKER) {
func.utils.debug_report(SESSION_ID, type, e, 'E');
setTimeout(function () {
if (!glb.debug_js) {
// location.reload();
console.warn('** reload request');
}
}, 2000);
} else {
func.utils.post_back_to_client(SESSION_ID, 'ajax_error', _session.worker_id, null);
}
};
func.utils.alerts = {};
func.utils.alerts.invoke = async function (SESSION_ID, typeP, paramsP, sourceP, dsSessionP, msgP) {
try {
var _session = SESSION_OBJ[SESSION_ID];
if (ALERT_IS_ACTIVE) return;
ALERT_IS_ACTIVE = true;
var title;
var message = '';
var alert_type = 'console';
var alertDisplay;
var expRet = {};
var _ds = _session.DS_GLB[dsSessionP];
var type = '';
var createLog;
const get_alert_properties = async function (value, fx) {
var ret = value || '';
if (fx) {
const exp_ret = await func.expression.get(SESSION_ID, fx, dsSessionP, 'alert');
ret = exp_ret.result;
}
return ret;
};
switch (typeP) {
case 'alert':
type = 'User defined alert';
title = await get_alert_properties(paramsP.alertTitle, paramsP.alertTitleFx);
alert_type = await get_alert_properties(paramsP.alertType, paramsP.alertTypeFx);
message = await get_alert_properties(paramsP.alertBody, paramsP.alertBodyFx);
alertDisplay = await get_alert_properties(paramsP.alertDisplay, paramsP.alertDisplayFx);
createLog = paramsP.createLog;
break;
case 'call_alert':
type = 'User defined call alert';
let prop = await func.utils.TREE_OBJ.get(SESSION_ID, paramsP.prog);
if (!prop) {
console.log('events.execute', 'Missing details for alert message object: ' + paramsP.prog, 'W');
}
// user defined
let ret = await func.utils.VIEWS_OBJ.get(SESSION_ID, paramsP.prog);
if (ret?.alertData) {
title = await get_alert_properties(ret.alertData.alertTitle, ret.alertData.alertTitleFx);
alert_type = await get_alert_properties(ret.alertData.alertType, ret.alertData.alertTypeFx);
message = await get_alert_properties(ret.alertData.alertBody, ret.alertData.alertBodyFx);
alertDisplay = await get_alert_properties(ret.alertData.alertDisplay, ret.alertData.alertDisplayFx);
createLog = ret.alertData.createLog;
}
if (!title) {
title = prop.menuTitle;
}
if (!alert_type) {
alert_type = 'console';
}
if (!alertDisplay) {
alertDisplay = 'modal';
} //window alert by definition
break;
case 'system_msg': {
type = 'System alert';
const sys_alerts_obj = func.utils.get_system_error_msg();
if (sys_alerts_obj[paramsP]) {
title = sys_alerts_obj[paramsP].subject;
alert_type = sys_alerts_obj[paramsP].alert_type;
alertDisplay = sys_alerts_obj[paramsP].alertDisplay;
expRet = await func.expression.get(SESSION_ID, sys_alerts_obj[paramsP].msg, dsSessionP, 'alert');
message = func.expression.remove_quotes(expRet.result);
if (msgP) message = msgP;
if (alert_type === 'error') {
if (_ds) _ds.error = title + ' ' + sourceP;
func.utils.debug_report(SESSION_ID, sourceP, title + ' ' + sourceP, 'E', '', _ds);
}
}
break;
}
default:
message = msgP;
break;
}
} catch (err) {
console.error(err);
ALERT_IS_ACTIVE = false;
return;
}
if (glb.IS_WORKER) {
if (_session.IS_API) {
if (_ds) {
_ds.api_rendered_output = message;
} else {
console.error(message);
}
return;
}
// if (typeof IS_PROCESS_SERVER !== "undefined") return;
ALERT_IS_ACTIVE = false;
return func.utils.post_back_to_client(SESSION_ID, 'alert', _session.worker_id, [SESSION_ID, alert_type, alertDisplay, message, title]);
}
// const sys_alerts_obj = func.utils.get_system_error_msg();
// if (sys_alerts_obj[paramsP]) {
// var str = paramsP + " " + title + " " + message;
// if (sys_alerts_obj[paramsP].alert_type === "error") {
// console.error(str);
// } else if (sys_alerts_obj[paramsP].alert_type === "warning") {
// console.warn(str);
// } else {
// console.log(str);
// }
// } else {
// console.log(str);
// }
ALERT_IS_ACTIVE = false;
func.utils.alerts.execute(SESSION_ID, alert_type, alertDisplay, message, title, type);
if (createLog) {
func.utils.write_log(SESSION_ID, title, message, alert_type);
}
};
func.utils.alerts.execute = function (SESSION_ID, alert_type, alertDisplay, message, title, type) {
if (!UI_FRAMEWORK_INSTALLED) {
ALERT_IS_ACTIVE = false;
if (alertDisplay !== 'console') {
return alert(title + '\n \n' + message);
}
return console[alert_type === 'error' ? 'error' : 'log'](alert_type, title, message);
}
switch (alertDisplay) {
case 'console':
console[alert_type === 'success' ? 'log' : alert_type === 'warning' ? 'warn' : alert_type](alert_type, title, message);
ALERT_IS_ACTIVE = false;
break;
case 'modal':
func.utils.alerts.popup(title, message, alert_type);
break;
case 'toast':
func.utils.alerts.toast(SESSION_ID, title, message, alert_type);
ALERT_IS_ACTIVE = false;
break;
case 'browser':
alert(title + '\n \n' + message);
ALERT_IS_ACTIVE = false;
default:
console.log(alert_type, title, message);
ALERT_IS_ACTIVE = false;
}
};
func.utils.alerts.toast = function (SESSION_ID, title, message, alert_type) {
if (!UI_FRAMEWORK_PLUGIN.toast) return;
const toast = new UI_FRAMEWORK_PLUGIN.toast();
toast.create(alert_type, message, title, func.common.get_url(SESSION_ID, 'dist', `runtime/images/${alert_type}_alert_ico.svg`));
ALERT_IS_ACTIVE = false;
};
func.utils.alerts.popup = function (title, message, alert_type) {
const popup = new UI_FRAMEWORK_PLUGIN.popup();
var buttons = [
{
text: 'Ok',
role: 'cancel',
// cssClass: "primary",
handler: () => {
ALERT_IS_ACTIVE = false;
},
},
];
popup.create(alert_type.charAt(0).toUpperCase() + alert_type.slice(1), title, message, buttons);
};
func.utils.get_system_error_msg = function () {
var m = {};
m['SYS_MSG_0101'] = {
alert_type: 'success',
alertDisplay: 'toast',
subject: 'Save Success',
msg: 'Settings successfully saved',
};
m['SYS_MSG_0102'] = {
alert_type: 'error',
alertDisplay: 'toast',
subject: 'Save Failed CouchDB',
msg: 'Data fail save to database',
};
m['SYS_MSG_0103'] = {
alert_type: 'error',
alertDisplay: 'toast',
subject: 'Save Failed Table Empty',
msg: 'Table empty, no fields declared',
};
m['SYS_MSG_0104'] = {
alert_type: 'error',
alertDisplay: 'toast',
subject: 'Save Failed Missing Primary Index',
msg: 'Update failed, table missing Primary index',
};
m['SYS_MSG_0105'] = {
alert_type: 'error',
alertDisplay: 'toast',
subject: 'Save Failed Table Missing',
msg: 'Table repository missing',
};
m['SYS_MSG_0106'] = {
alert_type: 'error',
alertDisplay: 'toast',
subject: 'Save Failed Record Not Exist',
msg: 'Save update failed record not exist',
};
m['SYS_MSG_0107'] = {
alert_type: 'error',
alertDisplay: 'modal',
subject: 'Save Failed Unique Key',
msg: 'Save Failed, record already exist',
};
m['SYS_MSG_0108'] = {
alert_type: 'error',
alertDisplay: 'modal',
subject: 'Error reading document',
msg: 'Save Failed, record not found',
};
m['SYS_MSG_0110'] = {
alert_type: 'warning',
alertDisplay: 'toast',
subject: 'Record Changed',
msg: 'Record changed by other user, reload to get the latest changes',
};
m['SYS_MSG_0120'] = {
alert_type: 'error',
alertDisplay: 'modal',
subject: 'Create Mode Denied',
msg: 'Create mode not allowed for this program',
};
m['SYS_MSG_0122'] = {
alert_type: 'error',
alertDisplay: 'modal',
subject: 'Modify Mode Denied',
msg: 'Modify mode not allowed for this program',
};
m['SYS_MSG_0124'] = {
alert_type: 'error',
alertDisplay: 'modal',
subject: 'Delete Mode Denied',
msg: 'Delete mode not allowed for this program',
};
m['SYS_MSG_0126'] = {
alert_type: 'error',
alertDisplay: 'modal',
subject: 'Program Read Only',
msg: 'Program set to Read Only',
};
m['SYS_MSG_0130'] = {
alert_type: 'error',
alertDisplay: 'modal',
subject: 'Error Reduce',
msg: 'Select Index to Reduce',
};
m['SYS_MSG_0201'] = {
alert_type: 'error',
alertDisplay: 'toast',
subject: 'Failed to change GUI Property',
msg: 'Failed to change GUI element property, GUI element missing',
};
m['SYS_MSG_0310'] = {
alert_type: 'error',
alertDisplay: 'toast',
subject: 'Missing Reference Parameters Out',
msg: 'Parameter out not exist in dataset',
};
m['SYS_MSG_0400'] = {
alert_type: 'error',
alertDisplay: 'modal',
subject: 'Delete Widget Folder Denied',
msg: 'The selected folder contains data, Please clean or move content to another folder',
};
m['SYS_MSG_0410'] = {
alert_type: 'error',
alertDisplay: 'toast',
subject: 'Recipient Error',
msg: 'Check recipient data',
};
m['SYS_MSG_0412'] = {
alert_type: 'error',
alertDisplay: 'modal',
subject: 'Recipient Empty',
msg: 'No recipients entered or selected',
};
m['SYS_MSG_0414'] = {
alert_type: 'error',
alertDisplay: 'modal',
subject: 'Data Save Error',
msg: 'Widget has no content',
};
m['SYS_MSG_0416'] = {
alert_type: 'error',
alertDisplay: 'modal',
subject: 'Required Field',
msg: 'Edit url field is empty',
};
m['SYS_MSG_0418'] = {
alert_type: 'error',
alertDisplay: 'modal',
subject: 'Required Field',
msg: 'Publish url field is empty',
};
m['SYS_MSG_0420'] = {
alert_type: 'error',
alertDisplay: 'modal',
subject: 'Connection Error',
msg: 'Cannot connect to mailbox',
};
m['SYS_MSG_0422'] = {
alert_type: 'success',
alertDisplay: 'modal',
subject: 'Connection Ok',
msg: 'Connection Ok :)',
};
m['SYS_MSG_0424'] = {
alert_type: 'error',
alertDisplay: 'modal',
subject: 'Connection Failed',
msg: 'Connection to POP3 failed',
};
m['SYS_MSG_0426'] = {
alert_type: 'error',
alertDisplay: 'modal',
subject: 'Connection Failed',
msg: 'SMTP Connection error, Test Email was not sent',
};
m['SYS_MSG_0430'] = {
alert_type: 'error',
alertDisplay: 'toast',
subject: 'Email Account Error',
msg: 'No email account found, Right Click Tree -> Settings->Manage Accounts -> Right click for menu options',
};
m['SYS_MSG_0440'] = {
alert_type: 'error',
alertDisplay: 'modal',
subject: 'Widget Initiation Error',
msg: 'Missing information for Link Type or Link Name',
};
m['SYS_MSG_0442'] = {
alert_type: 'error',
alertDisplay: 'modal',
subject: 'Error Init Widget',
msg: 'Missing record Id on Create Mode',
};
m['SYS_MSG_0450'] = {
alert_type: 'error',
alertDisplay: 'modal',
subject: 'Validation Failed',
msg: 'Fix fields highlight in Red',
};
m['SYS_MSG_0501'] = {
alert_type: 'error',
alertDisplay: 'modal',
subject: 'Mandatory Alert Save',
msg: 'Save action failed, Mandatory fields missing',
};
m['SYS_MSG_0550'] = {
alert_type: 'error',
alertDisplay: 'toast',
subject: 'Illegal input number',
msg: "@SYS_GLOBAL_OBJ_ACTIVE_FIELD_INFO.nameform +' only allow numbers!'",
};
m['SYS_MSG_0610'] = {
alert_type: 'error',
alertDisplay: 'toast',
subject: 'Form Field Conflict',
msg: 'Field declared more than once for the form',
};
m['SYS_MSG_0612'] = {
alert_type: 'error',
alertDisplay: 'toast',
subject: 'Mask Error - Missing Definition',
msg: 'Missing mask definition',
};
m['SYS_MSG_0614'] = {
alert_type: 'error',
alertDisplay: 'toast',
subject: 'Mask Error - Wrong Definition',
msg: 'Wrong mask definition',
};
m['SYS_MSG_0616'] = {
alert_type: 'error',
alertDisplay: 'toast',
subject: 'Mask Error - Size Parser',
msg: 'Size parser error',
};
m['SYS_MSG_0618'] = {
alert_type: 'error',
alertDisplay: 'toast',
subject: 'Mask Error - Illegal Z switch',
msg: "Illegal 'Z' in string mask",
};
m['SYS_MSG_0620'] = {
alert_type: 'error',
alertDisplay: 'toast',
subject: 'Mask Error - Illegal N switch',
msg: "Illegal 'N' in string mask",
};
m['SYS_MSG_0622'] = {
alert_type: 'error',
alertDisplay: 'toast',
subject: 'Mask Error - Illegal + switch',
msg: "Illegal '+' in string mask",
};
m['SYS_MSG_0624'] = {
alert_type: 'error',
alertDisplay: 'toast',
subject: 'Mask Error - Illegal - switch',
msg: "Illegal '-' in string mask",
};
m['SYS_MSG_0626'] = {
alert_type: 'error',
alertDisplay: 'toast',
subject: 'Mask Error - Illegal C switch',
msg: "Illegal 'C' in string mask",
};
m['SYS_MSG_0628'] = {
alert_type: 'error',
alertDisplay: 'toast',
subject: 'Mask Error - Invalid switch',
msg: 'Invalid switch in string mask',
};
m['SYS_MSG_0630'] = {
alert_type: 'error',
alertDisplay: 'toast',
subject: 'Mask Error - Missing DOM Element',
msg: 'Missing DOM element',
};
m['SYS_MSG_0632'] = {
alert_type: 'error',
alertDisplay: 'toast',
subject: 'Mask Error - Too Big',
msg: 'Size to big, max: 15.5',
};
m['SYS_MSG_0700'] = {
alert_type: 'warning',
alertDisplay: 'console',
subject: 'Table Warning - Empty',
msg: 'Table has no content',
};
m['SYS_MSG_0702'] = {
alert_type: 'error',
alertDisplay: 'console',
subject: 'Table Error - No Fields',
msg: 'Table missing fields content',
};
m['SYS_MSG_0704'] = {
alert_type: 'warning',
alertDisplay: 'console',
subject: 'Table Warning - Not In Use',
msg: 'Table not in use by any object',
};
m['SYS_MSG_0706'] = {
alert_type: 'error',
alertDisplay: 'console',
subject: 'Table Error - No Primary Index',
msg: 'Table must have at least one index',
};
m['SYS_MSG_0708'] = {
alert_type: 'error',
alertDisplay: 'console',
subject: 'Table Error - Bad Index Name',
msg: 'Index name is invalid or cannot contain any of non word characters',
};
m['SYS_MSG_0710'] = {
alert_type: 'error',
alertDisplay: 'console',
subject: 'Table Error - Empty Index',
msg: 'Index has no keys',
};
m['SYS_MSG_0712'] = {
alert_type: 'error',
alertDisplay: 'console',
subject: 'Table Error - Key Not Exist',
msg: 'Key not exist in the table fields repository',
};
m['SYS_MSG_0714'] = {
alert_type: 'error',
alertDisplay: 'console',
subject: 'Table Error - Duplicate Fields',
msg: 'Duplicate fields in the table fields repository',
};
m['SYS_MSG_0716'] = {
alert_type: 'error',
alertDisplay: 'console',
subject: 'Table Error - Bad Field Name',
msg: 'Field name is invalid or cannot contain any of non word characters',
};
m['SYS_MSG_0718'] = {
alert_type: 'error',
alertDisplay: 'console',
subject: 'Table Error - Integrity Broken',
msg: 'Field broken from its properties, edit the field and save',
};
m['SYS_MSG_0720'] = {
alert_type: 'error',
alertDisplay: 'console',
subject: 'Table Error - Model Not Exist',
msg: 'Model assigned to the field not exist',
};
m['SYS_MSG_0722'] = {
alert_type: 'warning',
alertDisplay: 'console',
subject: 'Object Warning - Not In Use',
msg: 'Object not in use or not call by any object',
};
m['SYS_MSG_0724'] = {
alert_type: 'error',
alertDisplay: 'console',
subject: 'Object Error - Table Not Exist',
msg: 'Table assigned in object datasource not exist',
};
m['SYS_MSG_0726'] = {
alert_type: 'error',
alertDisplay: 'console',
subject: 'Object Error - Index Keys Mismatch',
msg: 'Table index has different structure',
};
m['SYS_MSG_0728'] = {
alert_type: 'error',
alertDisplay: 'console',
subject: 'Object Error - Index Key From Empty',
msg: 'Index key From must have a value',
};
m['SYS_MSG_0730'] = {
alert_type: 'error',
alertDisplay: 'console',
subject: 'Object Error - Index Key From Reference',
msg: 'Field reference not exist in any dataset or parameters',
};
m['SYS_MSG_0732'] = {
alert_type: 'error',
alertDisplay: 'console',
subject: 'Object Error - Index Key To Empty',
msg: 'Index key To must have a value',
};
m['SYS_MSG_0734'] = {
alert_type: 'error',
alertDisplay: 'console',
subject: 'Object Error - Index Key To Reference',
msg: 'Field reference not exist in any dataset or parameters',
};
m['SYS_MSG_0736'] = {
alert_type: 'error',
alertDisplay: 'console',
subject: 'Object Error - Index Locate From Reference',
msg: 'Field reference not exist in any dataset or parameters',
};
m['SYS_MSG_0738'] = {
alert_type: 'error',
alertDisplay: 'console',
subject: 'Object Error - Index Locate To Reference',
msg: 'Field reference not exist in any dataset or parameters',
};
m['SYS_MSG_0740'] = {
alert_type: 'error',
alertDisplay: 'console',
subject: 'Object Error - Index Empty',
msg: 'Index empty - no keys defined',
};
m['SYS_MSG_0742'] = {
alert_type: 'error',
alertDisplay: 'console',
subject: 'Object Error - Index Reference',
msg: 'Table index reference error',
};
m['SYS_MSG_0744'] = {
alert_type: 'error',
alertDisplay: 'console',
subject: 'Object Error - Duplicate Fields',
msg: 'Duplicate fields in the dataset fields repository',
};
m['SYS_MSG_0746'] = {
alert_type: 'error',
alertDisplay: 'console',
subject: 'Object Error - Field reference error',
msg: 'Field not exist in datasource table fields repository',
};
m['SYS_MSG_0748'] = {
alert_type: 'error',
alertDisplay: 'console',
subject: 'Object Error - Mismatch Reference Type',
msg: 'Mismatch in calling reference type',
};
m['SYS_MSG_0750'] = {
alert_type: 'error',
alertDisplay: 'console',
subject: 'Object Error - Reference Broken',
msg: 'Reference broken calling object not exist',
};
m['SYS_MSG_0752'] = {
alert_type: 'error',
alertDisplay: 'console',
subject: 'Object Error - Empty Reference',
msg: 'Reference empty',
};
m['SYS_MSG_0754'] = {
alert_type: 'error',
alertDisplay: 'console',
subject: 'Object Error - Action Not Exist',
msg: 'Action not exist',
};
m['SYS_MSG_0756'] = {
alert_type: 'error',
alertDisplay: 'console',
subject: 'Object Error - Empty Event Reference',
msg: 'Empty event reference',
};
m['SYS_MSG_0758'] = {
alert_type: 'error',
alertDisplay: 'console',
subject: 'Object Error - Bad Field Name',
msg: 'Field name is invalid or cannot contain any of non word characters',
};
m['SYS_MSG_0760'] = {
alert_type: 'error',
alertDisplay: 'console',
subject: 'Object Error - Integrity Broken',
msg: 'Field broken from its properties, edit the object and save',
};
m['SYS_MSG_0762'] = {
alert_type: 'error',
alertDisplay: 'console',
subject: 'Object Error - Model Not Exist',
msg: 'Model assigned to the field not exist',
};
m['SYS_MSG_0764'] = {
alert_type: 'error',
alertDisplay: 'console',
subject: 'Object Error - Empty Dataset',
msg: 'Dataset empty from fields',
};
m['SYS_MSG_0766'] = {
alert_type: 'error',
alertDisplay: 'console',
subject: 'Object Error - Field Type Mismatch',
msg: 'Field type not match to the underlined table field definition',
};
m['SYS_MSG_0768'] = {
alert_type: 'error',
alertDisplay: 'console',
subject: 'Object Error - Field Mask Mismatch',
msg: 'Field masks not match to the underlined table field definition',
};
m['SYS_MSG_0770'] = {
alert_type: 'error',
alertDisplay: 'console',
subject: 'Object Error - Bad Event Name',
msg: 'Event name is invalid or cannot contain any of non word characters',
};
m['SYS_MSG_0772'] = {
alert_type: 'error',
alertDisplay: 'console',
subject: 'Object Error - UI Field Not Exist',
msg: 'UI Field not exist in the dataset repository',
};
m['SYS_MSG_0774'] = {
alert_type: 'error',
alertDisplay: 'console',
subject: 'Object Error - UI Field Reference Broken',
msg: 'UI Field reference broken',
};
m['SYS_MSG_0780'] = {
alert_type: 'error',
alertDisplay: 'toast',
subject: 'UI element error',
msg: 'UI element not exist',
};
m['SYS_MSG_1210'] = {
alert_type: 'error',
alertDisplay: 'modal',
subject: 'Program error',
msg: 'Program not exist',
};
m['SYS_MSG_1220'] = {
alert_type: 'error',
alertDisplay: 'modal',
subject: 'Program error',
msg: 'Non grid output defined',
};
m['SYS_MSG_1240'] = {
alert_type: 'error',
alertDisplay: 'toast',
subject: 'Debug error',
msg: '',
};
m['SYS_MSG_1250'] = {
alert_type: 'error',
alertDisplay: 'toast',
subject: 'Debug log error',
msg: '',
};
m['SYS_MSG_1260'] = {
alert_type: 'error',
alertDisplay: 'toast',
subject: 'Session Expired',
msg: 'Renew token session in Studio',
};
return m;
};
func.utils.find_key_in_ViewUITreeObj = function (arr, key, val) {
return arr.reduce((a, item) => {
if (a) return a;
if (item[key] === val) return item;
if (item.children) return findId(val, item.children);
}, null);
};
func.utils.get_plugin_setup = function (SESSION_ID, plugin_name) {
const _session = SESSION_OBJ[SESSION_ID];
const normalize_setup_response = function (value) {
if (value && typeof value === 'object' && Object.prototype.hasOwnProperty.call(value, 'code')) {
return value;
}
return {
code: 1,
data: value && typeof value === 'object' ? value : {},
};
};
const report_error = function (descP, warn) {
func.utils.debug.log(SESSION_ID, plugin_name, {
module: 'plugin',
action: 'Init',
source: 'get_plugin_setup',
prop: descP,
details: descP,
result: null,
error: warn ? false : true,
fields: null,
type: 'plugin',
});
};
return new Promise(async (resolve, reject) => {
try {
const db = await func.utils.connect_pouchdb(SESSION_ID);
const should_bypass_cache =
_session?.worker_type === 'Dev' ||
(_session?.engine_mode === 'miniapp' && !_session?.app_token);
if (!should_bypass_cache) {
try {
let ret = await db.get(`cache_plugin_setup_${plugin_name}`);
return resolve(normalize_setup_response(ret.data));
} catch (err) {
// cache miss
}
}
const json = normalize_setup_response(await func.common.db(SESSION_ID, 'get_plugin_setup', {
plugin_name,
}));
if (json.code < 0) {
report_error('Error: ' + json.data, json.error_type === 'W' ? true : false);
}
resolve(json);
if (!should_bypass_cache) {
var doc = {
_id: `cache_plugin_setup_${plugin_name}`,
data: json,
docType: 'cache_plugin',
};
db.put(doc);
}
} catch (e) {
console.error(e);
const error_message = e?.message || e?.msg || String(e || 'Unknown plugin setup error');
report_error('Error: ' + error_message, e?.error_type === 'W' ? true : false);
resolve({
code: -1,
data: error_message,
error_type: e?.error_type,
});
}
});
};
func.utils.connect_studio_pouchdb = function (app_id, rt, custom) {
if (custom) {
return new PouchDB(custom, { auto_compaction: true });
}
var db_name = 'xuda_studio_db';
if (app_id) {
db_name += '_' + app_id;
}
if (rt) {
db_name = `xuda_rt_${app_id}`;
}
return new PouchDB(db_name, { auto_compaction: true });
};
func.utils.connect_pouchdb = async function (SESSION_ID) {
const app_id = SESSION_OBJ[SESSION_ID].app_id;
return func.utils.connect_studio_pouchdb(app_id, true);
};
func.utils.base64_encode_utf8 = function (value = '') {
if (typeof btoa === 'function') {
return btoa(unescape(encodeURIComponent(value)));
}
if (typeof Buffer !== 'undefined') {
return Buffer.from(value, 'utf8').toString('base64');
}
throw new Error('base64 encoder unavailable');
};
func.utils.should_use_local_studio_plugin_resources = function (SESSION_ID) {
const _session = SESSION_OBJ[SESSION_ID];
return typeof IS_PROCESS_SERVER === 'undefined' && (['live_preview'].includes(_session?.engine_mode) || _session?.is_draft_runtime);
};
func.utils.get_local_studio_plugin_doc = async function (SESSION_ID, plugin_name) {
if (!func.utils.should_use_local_studio_plugin_resources(SESSION_ID)) {
return null;
}
try {
const db = func.utils.connect_studio_pouchdb(null, false, 'xuda_studio_resources');
return await db.get(plugin_name);
} catch (error) {
return null;
}
};
func.utils.get_local_studio_plugin_file = async function (SESSION_ID, plugin_name, resource) {
const plugin_doc = await func.utils.get_local_studio_plugin_doc(SESSION_ID, plugin_name);
return plugin_doc?.files?.[`${plugin_name}/${resource}`] || null;
};
func.utils.get_local_studio_plugin_resource_url = async function (SESSION_ID, plugin_name, resource) {
const file_contents = await func.utils.get_local_studio_plugin_file(SESSION_ID, plugin_name, resource);
if (!file_contents) {
return null;
}
const content_type = resource.endsWith('.css') ? 'text/css' : 'text/javascript';
return `data:${content_type};base64,${func.utils.base64_encode_utf8(file_contents)}`;
};
// func.utils.validate_pouchdb = async function (SESSION_ID) {
// const app_id = SESSION_OBJ[SESSION_ID].app_id;
// const db = new PouchDB("xuda_rt_" + app_id);
// // db.info()
// // .then((info) => {
// // console.log("Database exists", info);
// // })
// // .catch((error) => {
// // if (error.status === 404) {
// // throw new Error("Database does not exist");
// // } else {
// // throw new Error("Error accessing database", error);
// // }
// // });
// try {
// let ret = await db.get(`cache_rt_info`);
// } catch (error) {
// throw new Error("new pouch detect");
// }
// };
func.utils.call_plugin_api = function (SESSION_ID, plugin_nameP, dataP) {
var _session = SESSION_OBJ[SESSION_ID];
const report_error = function (descP, warn) {
func.utils.debug.log(SESSION_ID, plugin_nameP, {
module: 'plugin',
action: 'Init',
source: 'call_plugin_api',
prop: descP,
details: descP,
result: null,
error: warn ? false : true,
fields: null,
type: 'plugin',
});
};
return new Promise(async (resolve) => {
var data = {
app_id: APP_OBJ[_session.app_id]._id,
debug: glb.DEBUG_MODE,
uid: _session.USR_OBJ._id,
gtp_token: _session.gtp_token,
app_token: _session.app_token,
};
data = Object.assign(data, dataP);
fetch(`https://xuda.ai/ppi/${plugin_nameP}`, {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify(data),
})
.then((response) => {
if (!response.ok) {
return response.text().then((text) => {
throw new Error(text);
});
}
return response.json();
})
.then((json) => {
if (json.code < 0) {
report_error('Error: ' + json.data, json.error_type === 'W' ? true : false);
}
resolve(json.data);
// var doc = {
// _id: `cache_plugin_${plugin_nameP}`,
// data: json,
// docType: "cache_plugin",
// };
// db.put(doc);
})
.catch((err) => {
report_error('Error: ' + err.message);
resolve(err.message);
});
// }
});
};
func.utils.get_plugin_resource = function (SESSION_ID, plugin_name, plugin_resource) {
var _session = SESSION_OBJ[SESSION_ID];
const resource_ts =
(typeof globalThis !== 'undefined' ? globalThis.__XU_RUNTIME_MODULE_CACHE_TAG__ : '') ||
_session?.build_info?.runtime_ts ||
_session?.build_info?.last_changed_ts ||
_session?.build_info?.server_ts ||
_session?.opt?.app_build_id ||
(typeof globalThis !== 'undefined' ? globalThis.__XU_SERVER_BOOTSTRAP__?.version : 0) ||
0;
const plugin_resource_ts = `${resource_ts}-plugin-20260505-1`;
const get_path = function (resource) {
const server_origin = typeof globalThis !== 'undefined' ? globalThis.__XU_SERVER_ORIGIN__ : '';
if (server_origin) {
return `${server_origin}/plugins/${plugin_name}/${resource}?app_id=${_session.app_id}&ts=${plugin_resource_ts}`;
}
if (_session.worker_type === 'Dev') {
return `../../plugins/${plugin_name}/${resource}?ts=${plugin_resource_ts}`;
}
if (typeof IS_PROCESS_SERVER !== 'undefined') {
return `${_conf.plugins_drive_path}/${_session.app_id}/node_modules/${plugin_name}/${resource}`;
} else {
// return `./node_modules/${plugin_name}/${resource}?app_id=${_session.app_id}`;
return `https://${_session.domain}/plugins/${plugin_name}/${resource}?app_id=${_session.app_id}&ts=${plugin_resource_ts}`;
}
};
return new Promise(async (resolve, reject) => {
try {
const local_plugin_resource_url = await func.utils.get_local_studio_plugin_resource_url(SESSION_ID, plugin_name, plugin_resource);
if (local_plugin_resource_url) {
const plugin_resource_res = await import(/* @vite-ignore */ local_plugin_resource_url);
return resolve(plugin_resource_res);
}
} catch (err) {}
// const db = await func.utils.connect_pouchdb(SESSION_ID);
// try {
// if (_session.worker_type === "Dev") throw "bypass cache";
// let ret = await db.get(`cache_plugin_${plugin_name}_${plugin_resource}`);
// return resolve(ret.data);
// } catch (err) {
// try {
// const plugin_resource_res = await import(
// `${get_path(plugin_resource)}`
// );
// resolve(plugin_resource_res);
// // var doc = {
// // _id: `cache_plugin_${plugin_name}_${plugin_resource}`,
// // data: JSON.stringify(plugin_resource_res),
// // docType: "cache_plugin",
// // };
// // db.put(doc);
// } catch (err) {
// console.error(err);
// }
// }
try {
const plugin_resource_res = await import(`${get_path(plugin_resource)}`);
resolve(plugin_resource_res);
} catch (err) {
await func.utils.report_issue(SESSION_ID, {
code: 'RUN_MSG_GUI_020',
source: 'func.utils.get_plugin_resource',
message: 'plugin setup import failed',
err,
details: {
plugin_name,
plugin_resource,
plugin_path: get_path(plugin_resource),
},
});
reject(err);
}
});
};
func.utils.remove_cached_objects = async function (SESSION_ID) {
if (typeof IS_DOCKER !== 'undefined' || typeof IS_PROCESS_SERVER !== 'undefined') return;
try {
const db = await func.utils.connect_pouchdb(SESSION_ID);
let opt = {
$or: [
{
docType: 'cache_objects',
},
{
docType: 'cache_plugin',
},
{
docType: 'cache_app',
},
{
docType: 'cache_build_info',
},
],
};
const res = await db.find({ selector: opt });
for await (let val of res.docs) {
await db.remove(val);
}
} catch (err) {
return;
}
};
func.utils.get_plugin_npm_cdn = async function (SESSION_ID, plugin_name, resource) {
const _session = SESSION_OBJ[SESSION_ID];
const resource_ts =
(typeof globalThis !== 'undefined' ? globalThis.__XU_RUNTIME_MODULE_CACHE_TAG__ : '') ||
_session?.build_info?.runtime_ts ||
_session?.build_info?.last_changed_ts ||
_session?.build_info?.server_ts ||
_session?.opt?.app_build_id ||
(typeof globalThis !== 'undefined' ? globalThis.__XU_SERVER_BOOTSTRAP__?.version : 0) ||
0;
const plugin_resource_ts = `${resource_ts}-plugin-20260505-1`;
const local_plugin_resource_url = await func.utils.get_local_studio_plugin_resource_url(SESSION_ID, plugin_name, resource);
if (local_plugin_resource_url) {
return local_plugin_resource_url;
}
const get_path = function (resource) {
const server_origin = typeof globalThis !== 'undefined' ? globalThis.__XU_SERVER_ORIGIN__ : '';
if (server_origin) {
return `${server_origin}/plugins/${plugin_name}/${resource}?app_id=${_session.app_id}&ts=${plugin_resource_ts}`;
}
if (_session.worker_type === 'Dev') {
return `../../plugins/${plugin_name}/${resource}?ts=${plugin_resource_ts}`;
}
return `https://${_session.domain}/plugins/${plugin_name}/${resource}?app_id=${_session.app_id}&ts=${plugin_resource_ts}`;
};
return get_path(resource);
};
func.utils.write_log = async function (SESSION_ID, method = '', msg = '', log_type = 'error', source = 'runtime', details, meta = {}) {
const _session = SESSION_OBJ[SESSION_ID];
const body = {
msg,
log_type,
source,
details,
method,
...meta,
};
const is_offline =
(typeof IS_ONLINE !== 'undefined' && !IS_ONLINE) ||
(typeof navigator !== 'undefined' && navigator.onLine === false);
if (_session?.is_draft_runtime && is_offline) {
return null;
}
if (typeof IS_API_SERVER !== 'undefined' || typeof IS_DOCKER !== 'undefined' || typeof IS_PROCESS_SERVER !== 'undefined') {
return __.rpi.write_log(
_session?.app_id,
log_type,
source,
msg,
details,
null,
body,
method,
_session?.SYS_GLOBAL_OBJ_CLIENT_INFO?.fingerprint,
);
}
if (glb.IS_WORKER) {
let obj = {
service: 'write_log',
data: body,
log_type,
id: STUDIO_WEBSOCKET_CONNECTION_ID,
uid: _session?.USR_OBJ?._id,
source,
app_id: _session?.app_id,
gtp_token: _session?.gtp_token,
app_token: _session?.app_token,
};
return func.utils.post_back_to_client(SESSION_ID, 'write_log', _session.worker_id, obj);
}
await func.common.db(SESSION_ID, 'write_log', body);
};
func.utils.get_error_catalog_manifest = async function (SESSION_ID) {
const registry = await func.utils.get_error_registry(SESSION_ID);
return registry?.get_error_catalog_manifest?.() || null;
};
func.utils.get_resource_filename = function (build, filename) {
if (build) {
return filename.replace(/(\.\w+)$/, `.${build}$1`);
}
return filename;
};
func.utils.set_SYS_GLOBAL_OBJ_WIDGET_INFO = async function (SESSION_ID, docP) {
var obj = { ...docP };
obj.date = await func.utils.get_dateTime(SESSION_ID, 'SYS_DATE', docP.date);
obj.time = await func.utils.get_dateTime(SESSION_ID, 'SYS_TIME', docP.date);
var datasource_changes = {
[0]: {
['data_system']: {
['SYS_GLOBAL_OBJ_WIDGET_INFO']: obj,
},
},
};
await func.datasource.update(SESSION_ID, datasource_changes);
};
func.utils.get_last_datasource_no = function (SESSION_ID) {
if (typeof IS_PROCESS_SERVER !== 'undefined') {
return Object.keys(SESSION_OBJ[SESSION_ID].DS_GLB).at?.(-1);
} else {
const filtered = Object.values(SESSION_OBJ[SESSION_ID].DS_GLB).filter((e) => e.tree_obj.menuType !== 'api');
return filtered?.at?.(-1)?.dsSession;
}
};