@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.
1,082 lines (961 loc) • 34 kB
JavaScript
if (typeof IS_DOCKER === 'undefined' || typeof IS_PROCESS_SERVER === 'undefined') {
var SESSION_OBJ = {};
var DOCS_OBJ = {};
}
var glb = {};
var func = {};
func.UI = {};
func.GLB = {};
func.mobile = {};
glb.IS_STUDIO = null;
var PROJECT_OBJ = {};
var APP_OBJ = {};
var SESSION_ID = null;
var EXP_BUSY = false;
glb.PROTECTED_VARS = ['_NULL', '_THIS', '_FOR_KEY', '_FOR_VAL', '_ROWNO', '_ROWID', '_ROWDOC', '_KEY', '_VAL'];
// glb.newRecord = 999999;
func.common = {};
func.common.find_item_by_key = function (arr, key, val) {
return _.find(arr, function (e) {
return e.data[key] === val;
});
};
func.common.find_item_by_key_root = function (arr, key, val) {
return _.find(arr, function (e) {
return e[key] === val;
});
};
func.common.find_ROWID_idx = function (_ds, rowId) {
if (!_ds?.data_feed?.rows) {
throw new Error('data_feed not found');
}
// Find the index of the object with the given _ROWID
const index = _ds.data_feed.rows.findIndex((item) => item._ROWID === rowId);
// }
// If the index is -1, the ROWID was not found, so throw an error
if (index === -1) {
throw new Error(`ROWID "${rowId}" not found`);
}
// Return the found index
return index;
};
func.common.input_mask = async function (actionP, valP, typeP, maskP, elemP, grid_objP, grid_row_idP, grid_col_idP, dsSessionP) {
const module = await func.common.get_module(SESSION_ID, 'xuda-input-musk-utils-module.mjs');
module.input_mask(actionP, valP, typeP, maskP, elemP, grid_objP, grid_row_idP, grid_col_idP, dsSessionP);
};
glb.FUNCTION_NODES_ARR = ['batch', 'get_data', 'set_data', 'alert', 'javascript', 'api'];
glb.ALL_MENU_TYPE = ['globals', 'component', ...glb.FUNCTION_NODES_ARR];
glb.emailRegex = /^[\w\.-]+@[a-zA-Z\d\.-]+\.[a-zA-Z]{2,}$/;
const FIREBASE_AUTH_PROPERTIES_ARR = ['provider', 'token', 'first_name', 'last_name', 'email', 'user_id', 'picture', 'verified_email', 'locale', 'error_code', 'error_msg'];
const CLIENT_INFO_PROPERTIES_ARR = [
'fingerprint',
'device',
'user_agent',
'browser_version',
'browser_name',
'engine_version',
'engine_name',
'client_ip',
'os_name',
'os_version',
'device_model',
'device_vendor',
'device_type',
'screen_current_resolution_x',
'screen_current_resolution_y',
'screen_available_resolution_x',
'screen_available_resolution_y',
'language',
'time_zone',
'cpu_architecture',
'uuid',
'cursor_pos_x',
'cursor_pos_y',
];
const APP_PROPERTIES_ARR = ['build', 'author', 'date', 'name'];
const DATASOURCE_PROPERTIES_ARR = ['rows', 'type', 'first_row_id', 'last_row_id', 'query_from_segments_json', 'query_to_segments_json', 'locate_query_from_segments_json', 'locate_query_to_segments_json', 'first_row_segments_json', 'last_row_segments_json', 'rowid_snapshot', 'rowid'];
glb.MOBILE_ARR = ['component', 'web_app', 'ios_app', 'android_app', 'electron_app', 'osx_app', 'windows_app'];
glb.SYS_DATE_ARR = ['SYS_DATE', 'SYS_DATE_TIME', 'SYS_DATE_VALUE', 'SYS_DATE_WEEK_YEAR', 'SYS_DATE_MONTH_YEAR', 'SYS_TIME_SHORT', 'SYS_TIME'];
glb.API_OUTPUT_ARR = ['json', 'html', 'xml', 'text', 'css', 'javascript'];
const PROTECTED_NAMES_ARR = ['THIS', 'ROWID']; //tbd
func.common.db = async function (SESSION_ID, serviceP, dataP, opt = {}, dsSession) {
return new Promise(async function (resolve, reject) {
var _session = SESSION_OBJ[SESSION_ID];
const app_id = _session.app_id;
if (glb.DEBUG_MODE) {
console.log('request', dataP);
}
var data = {
app_id: app_id,
fingerprint: _session?.SYS_GLOBAL_OBJ_CLIENT_INFO?.fingerprint,
debug: glb.DEBUG_MODE,
session_id: SESSION_ID,
gtp_token: _session.gtp_token,
app_token: _session.app_token,
res_token: _session.res_token,
engine_mode: _session.engine_mode,
req_id: 'rt_req_' + crypto.randomUUID(),
app_replicate: APP_OBJ[app_id].app_replicate,
};
try {
if (typeof firebase !== 'undefined' && firebase?.auth()?.currentUser?.displayName) {
data.device_name = firebase.auth().currentUser.displayName;
}
} catch (error) {}
for (const [key, val] of Object.entries(dataP)) {
data[key] = val;
}
const success_callback = function (ret) {
if (dataP.table_id && DOCS_OBJ[app_id][dataP.table_id]) {
func.utils.debug.watch(SESSION_ID, dataP.table_id, 'table', DOCS_OBJ[app_id][dataP.table_id].properties.menuName, {
req: data,
res: ret,
});
}
if (glb.DEBUG_MODE) {
console.log('response', ret);
}
resolve(ret, true);
};
const error_callback = function (err) {
reject(err);
};
function cleanString(json) {
let str = JSON.stringify(json);
// Replace all non-alphanumeric characters with an empty string
return str.replace(/[^a-zA-Z0-9]/g, '');
}
const get_rep_id = function () {
let _data = {};
const fields_to_skip = ['fields', 'viewSourceDesc', 'skip', 'limit', 'count', 'reduce', 'prog_id', 'sortModel', 'filterModelMongo', 'filterModelSql', 'filterModelUserMongo', 'filterModelUserSql'];
for (let [key, val] of Object.entries(dataP)) {
if (typeof val !== 'undefined' && val !== null && !fields_to_skip.includes(key)) {
_data[key] = val;
}
}
return cleanString(_data);
};
const validate_existence_of_whole_table_request = async function (db) {
let table_req_id;
try {
table_req_id = cleanString({
key: data.table_id,
table_id: data.table_id,
});
const doc = await db.get(table_req_id);
let ret = await db.find({
selector: {
docType: 'rep_request',
table_id: data.table_id,
},
});
if (doc.stat < 3) {
throw 'not ready';
}
/// delete table refunded requests
for (let doc of ret.docs) {
if (doc.entire_table) continue;
func.db.pouch.remove_db_replication_from_server(SESSION_ID, doc._id);
}
return { code: 1, data: table_req_id };
} catch (err) {
return { code: -1, data: table_req_id };
}
};
const read_dbs_pouch = async function (db) {
if (_session?.DS_GLB?.[dsSession]?.refreshed && (dataP.filterModelMongo || dataP.filterModelSql)) {
return {
code: 1,
data: await func.db.pouch[serviceP](SESSION_ID, data),
};
}
const rep_id = get_rep_id();
const { code: table_req_code, data: table_req_id } = await validate_existence_of_whole_table_request(db);
if (table_req_code > 0) {
return {
code: 1,
data: await func.db.pouch[serviceP](SESSION_ID, data),
};
}
try {
const doc = await db.get(rep_id);
if (doc.stat < 3) throw 'replication not ready';
const json = {
code: 1,
data: await func.db.pouch[serviceP](SESSION_ID, data),
};
return json;
} catch (err) {
const json = await func.common.perform_rpi_request(SESSION_ID, serviceP, opt, data);
if (json.data.opt) {
try {
try {
await db.get(rep_id);
} catch (err) {
await db.put({
_id: rep_id,
selector: json.data.opt.selector,
stat: 1,
ts: Date.now(),
docType: 'rep_request',
table_id: dataP.table_id,
prog_id: dataP.prog_id,
entire_table: table_req_id === rep_id,
source: 'runtime',
e: data,
});
}
func.db.pouch.set_db_replication_from_server(SESSION_ID);
} catch (err) {}
}
return json;
}
};
const update_dbs_pouch = async function (db) {
try {
// if (_session.DS_GLB[0].data_system.SYS_GLOBAL_BOL_ONLINE) {
// throw "online";
// }
const { code: table_req_code, data: table_req_id } = await validate_existence_of_whole_table_request(db);
if (table_req_code > 0) {
data.full_table_downloaded = true;
}
await db.get(dataP.row_id);
return await func.db.pouch[serviceP](SESSION_ID, data);
} catch (err) {
return await func.common.perform_rpi_request(SESSION_ID, serviceP, opt, data);
}
};
const create_dbs_pouch = async function (db) {
try {
const { code: table_req_code, data: table_req_id } = await validate_existence_of_whole_table_request(db);
if (table_req_code > 0) {
data.full_table_downloaded = true;
}
return await func.db.pouch[serviceP](SESSION_ID, data);
} catch (err) {
return await func.common.perform_rpi_request(SESSION_ID, serviceP, opt, data);
}
};
const delete_dbs_pouch = async function (db) {
for await (let row_id of dataP.ids || []) {
try {
const { code: table_req_code, data: table_req_id } = await validate_existence_of_whole_table_request(db);
if (table_req_code > 0) {
data.full_table_downloaded = true;
}
await db.get(row_id);
let _data = _.cloneDeep(dataP);
_data.ids = [row_id];
return await func.db.pouch['dbs_delete'](SESSION_ID, _data);
} catch (err) {
return await func.common.perform_rpi_request(SESSION_ID, serviceP, opt, data);
}
}
};
if (typeof IS_DOCKER === 'undefined' && typeof IS_PROCESS_SERVER === 'undefined') {
try {
if (!SESSION_OBJ?.[SESSION_ID]?.rpi_http_methods?.includes(serviceP)) {
throw '';
}
if (!(await func?.db?.pouch?.get_replication_stat(SESSION_ID))) throw '';
const db = await func.utils.connect_pouchdb(SESSION_ID);
switch (serviceP) {
case 'dbs_read': {
try {
return success_callback(await read_dbs_pouch(db));
} catch (err) {
if (err === 'creating index in progress') {
throw '';
}
return error_callback(err);
}
break;
}
case 'dbs_update': {
try {
const ret = {
code: 1,
data: await update_dbs_pouch(db),
};
return success_callback(ret);
} catch (err) {
return error_callback(err);
}
break;
}
case 'dbs_create': {
try {
const ret = {
code: 1,
data: await create_dbs_pouch(db),
};
return success_callback(ret);
} catch (err) {
return error_callback(err);
}
break;
}
case 'dbs_delete': {
try {
const ret = {
code: 1,
data: await delete_dbs_pouch(db),
};
return success_callback(ret);
} catch (err) {
return error_callback(err);
}
break;
}
default:
throw '';
break;
}
} catch (err) {
try {
const json = await func.common.perform_rpi_request(SESSION_ID, serviceP, opt, data);
return success_callback(json, true);
} catch (err) {
return error_callback(err);
}
}
}
// DOCKER // PROCESS_SERVER
const response = function (res, ret) {
if (ret.code < 0) {
return error_callback(ret);
}
success_callback(ret);
};
const get_white_spaced_data = function (data) {
var e = {};
_.forEach(data, function (val, key) {
if (!val) {
if (typeof val === 'boolean') {
e[key] = 'false';
} else {
e[key] = '';
}
} else {
if (typeof val === 'boolean') {
e[key] = 'true';
} else {
e[key] = val;
}
}
});
if (data.fields && !data.fields.length) {
e.fields = '';
}
return e;
};
if (dataP.table_id) {
await func.utils.FILES_OBJ.get(SESSION_ID, dataP.table_id);
await func.utils.TREE_OBJ.get(SESSION_ID, dataP.table_id);
}
data.db_driver = 'xuda';
__.rpi.http_calls(serviceP, { body: get_white_spaced_data(data) }, null, response);
});
};
func.common.getJsonFromUrl = function () {
const queryString = window.location.search;
const urlParams = new URLSearchParams(queryString);
return urlParams;
};
func.common.getParametersFromUrl = function () {
const searchParams = new URLSearchParams(window.location.search);
const parameters = {};
for (const [key, value] of searchParams.entries()) {
parameters[key] = value;
}
return parameters;
};
func.common.getObjectFromUrl = function (url, element_attributes_obj, embed_params_obj) {
var result = {};
if (element_attributes_obj) {
for (let [key, val] of Object.entries(element_attributes_obj)) {
result[key] = val;
}
}
if (embed_params_obj) {
for (let [key, val] of Object.entries(embed_params_obj)) {
result[key] = val;
}
}
if (!url && typeof IS_DOCKER === 'undefined' && typeof IS_PROCESS_SERVER === 'undefined') {
url = location.href;
}
var question = url.indexOf('?');
var hash = url.indexOf('#');
if (hash == -1 && question == -1) return result;
if (hash == -1) hash = url.length;
var query = question == -1 || hash == question + 1 ? url.substring(hash) : url.substring(question + 1, hash);
// var result = {};
query.split('&').forEach(function (part) {
if (!part) return;
part = part.split('+').join(' '); // replace every + with space, regexp-free version
var eq = part.indexOf('=');
var key = eq > -1 ? part.substr(0, eq) : part;
var val = eq > -1 ? decodeURIComponent(part.substr(eq + 1)) : '';
var from = key.indexOf('[');
if (from == -1) {
result[decodeURIComponent(key)] = val;
} else {
var to = key.indexOf(']', from);
var index = decodeURIComponent(key.substring(from + 1, to));
key = decodeURIComponent(key.substring(0, from));
if (!result[key]) result[key] = [];
if (!index) result[key].push(val);
else result[key][index] = val;
}
});
return result;
};
func.common.getContrast_color = function (hexcolor) {
function colourNameToHex(colour) {
var colours = {
aliceblue: '#f0f8ff',
antiquewhite: '#faebd7',
aqua: '#00ffff',
aquamarine: '#7fffd4',
azure: '#f0ffff',
beige: '#f5f5dc',
bisque: '#ffe4c4',
black: '#000000',
blanchedalmond: '#ffebcd',
blue: '#0000ff',
blueviolet: '#8a2be2',
brown: '#a52a2a',
burlywood: '#deb887',
cadetblue: '#5f9ea0',
chartreuse: '#7fff00',
chocolate: '#d2691e',
coral: '#ff7f50',
cornflowerblue: '#6495ed',
cornsilk: '#fff8dc',
crimson: '#dc143c',
cyan: '#00ffff',
darkblue: '#00008b',
darkcyan: '#008b8b',
darkgoldenrod: '#b8860b',
darkgray: '#a9a9a9',
darkgreen: '#006400',
darkkhaki: '#bdb76b',
darkmagenta: '#8b008b',
darkolivegreen: '#556b2f',
darkorange: '#ff8c00',
darkorchid: '#9932cc',
darkred: '#8b0000',
darksalmon: '#e9967a',
darkseagreen: '#8fbc8f',
darkslateblue: '#483d8b',
darkslategray: '#2f4f4f',
darkturquoise: '#00ced1',
darkviolet: '#9400d3',
deeppink: '#ff1493',
deepskyblue: '#00bfff',
dimgray: '#696969',
dodgerblue: '#1e90ff',
firebrick: '#b22222',
floralwhite: '#fffaf0',
forestgreen: '#228b22',
fuchsia: '#ff00ff',
gainsboro: '#dcdcdc',
ghostwhite: '#f8f8ff',
gold: '#ffd700',
goldenrod: '#daa520',
gray: '#808080',
green: '#008000',
greenyellow: '#adff2f',
honeydew: '#f0fff0',
hotpink: '#ff69b4',
'indianred ': '#cd5c5c',
indigo: '#4b0082',
ivory: '#fffff0',
khaki: '#f0e68c',
lavender: '#e6e6fa',
lavenderblush: '#fff0f5',
lawngreen: '#7cfc00',
lemonchiffon: '#fffacd',
lightblue: '#add8e6',
lightcoral: '#f08080',
lightcyan: '#e0ffff',
lightgoldenrodyellow: '#fafad2',
lightgrey: '#d3d3d3',
lightgreen: '#90ee90',
lightpink: '#ffb6c1',
lightsalmon: '#ffa07a',
lightseagreen: '#20b2aa',
lightskyblue: '#87cefa',
lightslategray: '#778899',
lightsteelblue: '#b0c4de',
lightyellow: '#ffffe0',
lime: '#00ff00',
limegreen: '#32cd32',
linen: '#faf0e6',
magenta: '#ff00ff',
maroon: '#800000',
mediumaquamarine: '#66cdaa',
mediumblue: '#0000cd',
mediumorchid: '#ba55d3',
mediumpurple: '#9370d8',
mediumseagreen: '#3cb371',
mediumslateblue: '#7b68ee',
mediumspringgreen: '#00fa9a',
mediumturquoise: '#48d1cc',
mediumvioletred: '#c71585',
midnightblue: '#191970',
mintcream: '#f5fffa',
mistyrose: '#ffe4e1',
moccasin: '#ffe4b5',
navajowhite: '#ffdead',
navy: '#000080',
oldlace: '#fdf5e6',
olive: '#808000',
olivedrab: '#6b8e23',
orange: '#ffa500',
orangered: '#ff4500',
orchid: '#da70d6',
palegoldenrod: '#eee8aa',
palegreen: '#98fb98',
paleturquoise: '#afeeee',
palevioletred: '#d87093',
papayawhip: '#ffefd5',
peachpuff: '#ffdab9',
peru: '#cd853f',
pink: '#ffc0cb',
plum: '#dda0dd',
powderblue: '#b0e0e6',
purple: '#800080',
rebeccapurple: '#663399',
red: '#ff0000',
rosybrown: '#bc8f8f',
royalblue: '#4169e1',
saddlebrown: '#8b4513',
salmon: '#fa8072',
sandybrown: '#f4a460',
seagreen: '#2e8b57',
seashell: '#fff5ee',
sienna: '#a0522d',
silver: '#c0c0c0',
skyblue: '#87ceeb',
slateblue: '#6a5acd',
slategray: '#708090',
snow: '#fffafa',
springgreen: '#00ff7f',
steelblue: '#4682b4',
tan: '#d2b48c',
teal: '#008080',
thistle: '#d8bfd8',
tomato: '#ff6347',
turquoise: '#40e0d0',
violet: '#ee82ee',
wheat: '#f5deb3',
white: '#ffffff',
whitesmoke: '#f5f5f5',
yellow: '#ffff00',
yellowgreen: '#9acd32',
};
if (typeof colours[colour.toLowerCase()] != 'undefined') return colours[colour.toLowerCase()];
return false;
}
if (!hexcolor.includes('#')) {
hexcolor = colourNameToHex(hexcolor);
}
// If a leading # is provided, remove it
if (hexcolor.slice(0, 1) === '#') {
hexcolor = hexcolor.slice(1);
}
// Convert to RGB value
var r = Number(hexcolor.substr(0, 2), 16);
var g = Number(hexcolor.substr(2, 2), 16);
var b = Number(hexcolor.substr(4, 2), 16);
// Get YIQ ratio
var yiq = (r * 299 + g * 587 + b * 114) / 1000;
// Check contrast
return yiq >= 128 ? 'black' : 'white';
};
func.common.get_url = function (SESSION_ID, method, path) {
return `https://${SESSION_OBJ[SESSION_ID].domain}/${method}${path ? '/' + path : '/'}`;
};
var UI_FRAMEWORK_INSTALLED = null;
var UI_FRAMEWORK_PLUGIN = {};
func.common.get_cast_val = async function (SESSION_ID, source, attributeP, typeP, valP, errorP) {
const report_conversion_error = function (res) {
if (errorP) {
return func.utils.debug_report(SESSION_ID, _.capitalize(source), errorP, 'W');
}
var msg = `error converting ${attributeP} from ${valP} to ${typeP}`;
func.utils.debug_report(SESSION_ID, _.capitalize(source), msg, 'E');
};
const report_conversion_warn = function (msg) {
var msg = `type mismatch auto conversion made to ${attributeP} from value ${valP} to ${typeP}`;
func.utils.debug_report(SESSION_ID, _.capitalize(source), msg, 'W');
};
const module = await func.common.get_module(SESSION_ID, `xuda-get-cast-util-module.mjs`);
return module.cast(typeP, valP, report_conversion_error, report_conversion_warn);
};
var WEB_WORKER = {};
var WEB_WORKER_CALLBACK_QUEUE = {};
glb.DEBUG_MODE = null;
var DS_UI_EVENTS_GLB = {};
var RUNTIME_SERVER_WEBSOCKET = null;
var RUNTIME_SERVER_WEBSOCKET_CONNECTED = null;
var WEBSOCKET_PROCESS_PID = null;
glb.worker_queue_num = 0;
glb.websocket_queue_num = 0;
func.common.get_module = async function (SESSION_ID, module, paramsP = {}) {
let ret;
const get_ret = async function (src) {
const module_ret = await import(src);
var params = get_params();
const ret = module_ret.XudaModule ? new module_ret.XudaModule(params) : await invoke_init_module(module_ret, params);
return ret;
};
const get_params = function () {
let params = {
glb,
func,
APP_OBJ,
SESSION_ID,
PROJECT_OBJ,
DOCS_OBJ,
SESSION_OBJ,
_,
...paramsP,
};
if (typeof IS_PROCESS_SERVER !== 'undefined') params.IS_PROCESS_SERVER = IS_PROCESS_SERVER;
if (typeof IS_API_SERVER !== 'undefined') params.IS_API_SERVER = IS_API_SERVER;
if (typeof IS_DOCKER !== 'undefined') params.IS_DOCKER = IS_DOCKER;
return params;
};
const invoke_init_module = async function (module_ret, params) {
if (!module_ret.init_module) return module_ret;
await module_ret.init_module(params);
return module_ret;
};
const _session = SESSION_OBJ[SESSION_ID];
if (_session.worker_type === 'Dev') {
ret = await get_ret('./modules/' + module);
return ret;
}
if (_session.worker_type === 'Debug') {
if (typeof IS_DOCKER !== 'undefined' || typeof IS_PROCESS_SERVER !== 'undefined') {
ret = await get_ret(func.utils.get_resource_filename(['live_preview', 'miniapp'].includes(_session.engine_mode) ? '' : _session?.opt?.app_build_id, `${_conf.xuda_home}root/dist/runtime/js/modules/` + module));
} else {
ret = await get_ret(func.common.get_url(SESSION_ID, 'dist', func.utils.get_resource_filename(['live_preview', 'miniapp'].includes(_session.engine_mode) ? '' : _session?.opt?.app_build_id, 'runtime/js/modules/' + module)));
}
return ret;
}
const rep = function () {
return _.endsWith(module, '.js') ? module.replace('.js', '.min.js') : module.replace('.mjs', '.min.mjs');
};
if (typeof IS_DOCKER !== 'undefined' || typeof IS_PROCESS_SERVER !== 'undefined') {
ret = await get_ret(func.utils.get_resource_filename(['live_preview', 'miniapp'].includes(_session.engine_mode) ? '' : _session?.opt?.app_build_id, `${_conf.xuda_home}root/dist/runtime/js/modules/` + rep()));
} else {
ret = await get_ret(func.common.get_url(SESSION_ID, 'dist', func.utils.get_resource_filename(['live_preview', 'miniapp'].includes(_session.engine_mode) ? '' : _session?.opt?.app_build_id, 'runtime/js/modules/' + rep())));
}
return ret;
};
func.api = {};
func.api.set_field_value = async function (field_id, value, avoid_refresh) {
const SESSION_ID = Object.keys(SESSION_OBJ)[0];
const api_utils = 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),
});
return await api_utils.set_field_value(field_id, value, avoid_refresh);
};
func.api.get_field_value = async function (field_id) {
const SESSION_ID = Object.keys(SESSION_OBJ)[0];
const api_utils = 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),
});
return await api_utils.get_field_value(field_id);
};
func.api.invoke_event = async function (event_id) {
const SESSION_ID = Object.keys(SESSION_OBJ)[0];
const api_utils = 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),
});
return await api_utils.invoke_event(event_id);
};
func.api.call_project_api = async function (prog_id, params) {
const SESSION_ID = Object.keys(SESSION_OBJ)[0];
const api_utils = 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),
});
return await api_utils.call_project_api(prog_id, params, null);
};
func.api.call_system_api = async function (api_method, payload) {
const SESSION_ID = Object.keys(SESSION_OBJ)[0];
const api_utils = 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),
});
return await api_utils.call_system_api(api_method, payload, null);
};
func.api.dbs_create = async function (table_id, data, cb) {
const SESSION_ID = Object.keys(SESSION_OBJ)[0];
const api_utils = 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),
});
return await api_utils.dbs_create(table_id, row_id, data, cb);
};
func.api.dbs_read = async function (table_id, selector, fields, sort, limit, skip, cb) {
const SESSION_ID = Object.keys(SESSION_OBJ)[0];
const api_utils = 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),
});
return await api_utils.dbs_read(table_id, selector, fields, sort, limit, skip, cb);
};
func.api.dbs_update = async function (table_id, row_id, data, cb) {
const SESSION_ID = Object.keys(SESSION_OBJ)[0];
const api_utils = 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),
});
return await api_utils.dbs_update(table_id, row_id, data, cb);
};
func.api.dbs_delete = async function (table_id, row_id, cb) {
const SESSION_ID = Object.keys(SESSION_OBJ)[0];
const api_utils = 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),
});
return await api_utils.dbs_delete(table_id, row_id, cb);
};
func.api.call_javascript = async function (prog_id, params, evaluate) {
const SESSION_ID = Object.keys(SESSION_OBJ)[0];
const api_utils = 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),
});
return await api_utils.call_javascript(prog_id, params, evaluate);
};
// func.api.call_javascript = async function (prog_id, params, evaluate) {
// const SESSION_ID = Object.keys(SESSION_OBJ)[0];
// const api_utils = 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),
// });
// return await api_utils.call_javascript(prog_id, params, evaluate);
// };
glb.rpi_request_queue_num = 0;
func.common.perform_rpi_request = async function (SESSION_ID, serviceP, opt = {}, data) {
var _session = SESSION_OBJ[SESSION_ID];
var _data_system = _session?.DS_GLB?.[0]?.data_system;
const set_ajax = async function (stat) {
var datasource_changes = {
[0]: {
['data_system']: { SYS_GLOBAL_BOL_AJAX_BUSY: stat },
},
};
await func.datasource.update(SESSION_ID, datasource_changes);
};
if (_data_system) {
// _data_system.SYS_GLOBAL_BOL_AJAX_BUSY = 1;
await set_ajax(1);
if (!_data_system.SYS_GLOBAL_BOL_CONNECTED) {
func.utils.alerts.toast(SESSION_ID, 'Server connection error', 'You are not connected to the server, so your request cannot be processed.', 'error');
return { code: 88, data: {} };
}
}
const http = async function () {
const fetchWithTimeout = (url, options = {}, timeout = 600000) => {
// 100 seconds
const controller = new AbortController();
const { signal } = controller;
const timeoutPromise = new Promise((_, reject) =>
setTimeout(() => {
controller.abort();
reject(new Error('Request timed out'));
}, timeout),
);
const fetchPromise = fetch(url, { ...options, signal });
return Promise.race([fetchPromise, timeoutPromise]);
};
var url = func.common.get_url(SESSION_ID, 'rpi', '');
var _session = SESSION_OBJ[SESSION_ID];
const app_id = _session.app_id;
if (APP_OBJ[app_id].is_deployment && _session.rpi_http_methods?.includes(serviceP)) {
url = 'https://' + _session.host + '/rpi/';
}
url += serviceP;
try {
const response = await fetchWithTimeout(url, {
method: opt.type ? opt.type : 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
'xu-gtp-token': _session.gtp_token,
'xu-app-token': _session.app_token,
},
body: JSON.stringify(data),
});
if (!response.ok) {
throw response.status;
}
const json = await response.json();
return json;
} catch (err) {
console.error(err);
if (err === 503) {
_this.func.UI.utils.progressScreen.show(SESSION_ID, `Error code ${err}, reloading in 5 sec`);
setTimeout(async () => {
await func.index.delete_pouch(SESSION_ID);
location.reload();
}, 5000);
}
return {};
}
};
try {
if (_session.engine_mode === 'live_preview') {
throw new Error('live_preview');
}
if (_session.engine_mode === 'miniapp') {
throw new Error('miniapp');
}
if (SESSION_OBJ?.[SESSION_ID]?.rpi_http_methods?.includes(serviceP)) {
const ret = await func.common.get_data_from_websocket(SESSION_ID, serviceP, data);
if (_data_system) {
// _data_system.SYS_GLOBAL_BOL_AJAX_BUSY = 0;
await set_ajax(0);
}
return ret;
} else {
throw new Error('method not found in rpi_http_methods');
}
} catch (err) {
const ret = await http();
if (_data_system) {
// _data_system.SYS_GLOBAL_BOL_AJAX_BUSY = 0;
await set_ajax(0);
}
return ret;
}
};
func.common.get_data_from_websocket = async function (SESSION_ID, serviceP, data) {
var _session = SESSION_OBJ[SESSION_ID];
return new Promise(function (resolve, reject) {
const dbs_calls = function () {
glb.websocket_queue_num++;
const obj = {
service: serviceP,
data,
websocket_queue_num: glb.websocket_queue_num,
};
if (glb.IS_WORKER) {
func.utils.post_back_to_client(SESSION_ID, 'get_dbs_data_from_websocket', _session.worker_id, obj);
self.addEventListener('get_ws_data_worker_' + glb.websocket_queue_num, (event) => {
resolve(event.detail.data);
});
// throw new Error("not ready yet");
} else {
if (RUNTIME_SERVER_WEBSOCKET && RUNTIME_SERVER_WEBSOCKET_CONNECTED) {
RUNTIME_SERVER_WEBSOCKET.emit('message', obj);
$('body').on('get_ws_data_response_' + glb.websocket_queue_num, (e, data) => {
resolve(data.data);
$('body').off('get_ws_data_response_' + data.e.websocket_queue_num);
});
} else {
throw new Error('fail to fetch from ws websocket inactive');
}
}
};
const heartbeat = function () {
const obj = {
service: 'heartbeat',
data,
};
if (RUNTIME_SERVER_WEBSOCKET && RUNTIME_SERVER_WEBSOCKET_CONNECTED) {
RUNTIME_SERVER_WEBSOCKET.emit('message', obj);
$('body').on('heartbeat_response', (e, data) => {
resolve(data.data);
$('body').off('heartbeat_response');
});
} else {
throw new Error('fail to fetch from ws websocket inactive');
}
};
if (serviceP === 'heartbeat') {
return heartbeat();
}
dbs_calls();
});
};
func.common.sha256 = async function (inputString) {
// const enc = new TextEncoder();
// const buf = await crypto.subtle.digest('SHA-256', enc.encode(str));
// const bytes = new Uint8Array(buf);
// return [...bytes].map((b) => b.toString(16).padStart(2, '0')).join('');
// 1. Create a hash buffer from the input string using SHA-256.
// This part remains the same as it provides a strong, unique cryptographic starting point.
const buffer = await crypto.subtle.digest('SHA-256', new TextEncoder().encode(inputString));
// 2. Interpret the first 8 bytes (64 bits) of the hash as one big number.
const view = new DataView(buffer);
const bigInt = view.getBigUint64(0, false); // `false` for big-endian
// 3. Convert the BigInt to a Base36 string.
// The .toString(36) method handles the conversion to an alphanumeric representation (0-9, a-z).
const base36Hash = bigInt.toString(36);
// 4. Take the first 10 characters. If it's shorter, it will just return the whole string.
// For a 64-bit integer, the Base36 representation will be about 13 characters long,
// so slicing is a reliable way to get a fixed length.
const shortHash = base36Hash.slice(0, 10);
// 5. Pad the start in the unlikely case the hash is shorter than 10 characters.
// This ensures the output is always exactly 10 characters long.
return shortHash.padStart(10, '0');
};
glb.new_xu_render = false;
;