UNPKG

@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
'use strict'; 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;