@xuda.io/runtime-bundle 1.0.1228 → 1.0.1229
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/js/modules/xuda-db-adapter-module.min.mjs +1 -1
- package/js/modules/xuda-db-adapter-module.mjs +4 -1
- package/js/modules/xuda-project-loader-module.esm.js +1 -1
- package/js/modules/xuda-project-loader-module.esm.min.js +1 -1
- package/js/modules/xuda-studio-checker.min.mjs +1 -1
- package/js/modules/xuda-studio-checker.mjs +2 -2
- package/js/xuda-runtime-bundle.js +25 -2
- package/js/xuda-runtime-bundle.min.js +4 -4
- package/js/xuda-runtime-mini-bundle.js +1 -0
- package/js/xuda-runtime-mini-bundle.min.js +1 -1
- package/js/xuda-runtime-slim.js +25 -2
- package/js/xuda-runtime-slim.min.es.js +25 -2
- package/js/xuda-runtime-slim.min.js +4 -4
- package/js/xuda-server-bundle.min.mjs +1 -1
- package/js/xuda-server-bundle.mjs +1 -0
- package/js/xuda-worker-bundle.js +1 -0
- package/js/xuda-worker-bundle.min.js +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
const _this={};export const init_module=async e=>{_this.func=e.func;_this.glb=e.glb;_this.SESSION_OBJ=e.SESSION_OBJ;_this.APP_OBJ=e.APP_OBJ;_this.IS_DOCKER=e.IS_DOCKER;_this.IS_API_SERVER=e.IS_API_SERVER;_this.IS_PROCESS_SERVER=e.IS_PROCESS_SERVER;if(!_this.xuda_dbs_plugin&&typeof _this.IS_DOCKER==="undefined"&&typeof _this.IS_PROCESS_SERVER==="undefined"&&typeof _this.IS_API_SERVER==="undefined"){await init_xuda_dbs_plugin(e.SESSION_ID)}_this.db_replication_store;_this.db_changes_store;_this.db_replication_from_stat=3;_this.db_replication_to_stat=3};export let _db={};_db.save_data=async function(SESSION_ID,dsSessionP,keyP){var db_driver=await this.get_db_driver(SESSION_ID,dsSessionP);if(db_driver==="pouchdb"&&_this.glb.IS_WORKER){var callback_id=_this.func.utils.set_callback_queue(SESSION_ID,callbackP);var obj=_this.func.utils.clean_returned_datasource(SESSION_ID,dsSessionP);return _this.func.utils.post_back_to_client(SESSION_ID,"execute_local_sava_data",_this.SESSION_OBJ[SESSION_ID].worker_id,{ds_obj:obj,dsSessionP:dsSessionP,keyP:keyP,callback_id:callback_id})}_db.save_indicator(SESSION_ID,true);var _ds=_this.SESSION_OBJ[SESSION_ID].DS_GLB[dsSessionP];let _view_obj=await _this.func.utils.VIEWS_OBJ.get(SESSION_ID,_ds.prog_id);var dataSourceTableId=_view_obj?.progDataSource?.dataSourceTableId;if(!dataSourceTableId){_db.save_indicator(SESSION_ID,false);_this.func.utils.alerts.invoke(SESSION_ID,"system_msg","SYS_MSG_0105");return}var db_driver=await _db.get_db_driver(SESSION_ID,dsSessionP);let table_ret=await _this.func.utils.FILES_OBJ.get(SESSION_ID,dataSourceTableId);if(!table_ret.tableIndexes||_.isEmpty(table_ret.tableIndexes)){_db.save_indicator(SESSION_ID,false);_this.func.utils.alerts.invoke(SESSION_ID,"system_msg","SYS_MSG_0104");return}if(!_ds.data_feed.rows){return console.error("data_feed rows is empty")}const clean_virtual_fields=async function(table_id,data){let table_obj=await func.utils.VIEWS_OBJ.get(SESSION_ID,table_id);var data_obj={};for(const[key,val]of Object.entries(data)){const _tableFieldsObj=func.common.find_item_by_key(table_obj.tableFields,"field_id",key);if(_tableFieldsObj){data_obj[key]=val}}return data_obj};let save_ret;if(_view_obj.properties.menuType==="component"){if(_view_obj?.properties?.rwMode!=="U"){return _this.func.utils.alerts.invoke(SESSION_ID,"system_msg","SYS_MSG_0126")}let data={prog_id:_ds.prog_id};if(_ds.data_feed.rows_added?.length){if(!_view_obj?.properties?.allowCreate){_this.func.utils.alerts.invoke(SESSION_ID,"system_msg","SYS_MSG_0120")}_.forEach(_ds.data_feed.rows_added,function(val,key){data[key]=val});delete _ds.data_feed.rows_added["newRecord"];save_ret=await _this.func.common.db(SESSION_ID,"dbs_create",data,{},dsSessionP);refresh_document_changes_for_realtime_update(SESSION_ID,{row_id:save_ret.data.id,table_id:dataSourceTableId});return save_ret}if(_ds.data_feed.rows_deleted?.length){data.table_id=_ds._dataSourceTableId;data.ids=[];for await(const[key,val]of Object.entries(_ds.data_feed.rows_deleted)){data.ids.push(val);try{const row_idx=func.common.find_ROWID_idx(_ds,val);delete _ds.data_feed.rows[row_idx]}catch(error){}}_ds.data_feed.rows_deleted=[];save_ret=await _this.func.common.db(SESSION_ID,"dbs_delete",data,{},dsSessionP);refresh_document_changes_for_realtime_update(SESSION_ID,{row_id:save_ret.data?.id?.[0],table_id:dataSourceTableId});return save_ret}if(_ds.data_feed.rows_changed?.length){for await(const[key,row_id]of Object.entries(_ds.data_feed.rows_changed)){if(row_id==="datasource_main")continue;let data={prog_id:_ds.prog_id};try{const row_idx=func.common.find_ROWID_idx(_ds,row_id);data.table_data=await clean_virtual_fields(_ds._dataSourceTableId,_ds.data_feed.rows[row_idx])}catch(err){console.error(err)}data.table_id=_ds._dataSourceTableId;data.row_id=row_id;save_ret=await _this.func.common.db(SESSION_ID,"dbs_update",data,{},dsSessionP);refresh_document_changes_for_realtime_update(SESSION_ID,{row_id:save_ret.data?.id?.[0],table_id:dataSourceTableId})}return save_ret}return}if(_view_obj.properties.menuType!=="set_data"){return _this.func.utils.alerts.invoke(SESSION_ID,"system_msg","SYS_MSG_0126")}var mode=_ds.set_mode;if(!mode||mode==="U"){let data={prog_id:_ds.prog_id};data.table_id=_ds._dataSourceTableId;data.row_id=_ds.currentRecordId;data.table_data={};try{const row_idx=func.common.find_ROWID_idx(_ds,_ds.currentRecordId);data.table_data=await clean_virtual_fields(_ds._dataSourceTableId,_ds.data_feed.rows[row_idx])}catch(err){console.error(err)}save_ret=await _this.func.common.db(SESSION_ID,"dbs_update",data,{},dsSessionP);refresh_document_changes_for_realtime_update(SESSION_ID,{row_id:save_ret.data?.id?.[0],table_id:dataSourceTableId})}if(mode==="D"){let data={prog_id:_ds.prog_id};data.table_id=_ds._dataSourceTableId;data.ids=[_ds.currentRecordId];save_ret=await _this.func.common.db(SESSION_ID,"dbs_delete",data,{},dsSessionP);refresh_document_changes_for_realtime_update(SESSION_ID,{row_id:save_ret.data?.id?.[0],table_id:dataSourceTableId});return save_ret}if(mode==="C"){if(_view_obj.properties.crudMode!=="C"&&_view_obj.properties.crudMode==="U"&&!_view_obj.properties.allowCreate){return _this.func.utils.alerts.invoke(SESSION_ID,"system_msg","SYS_MSG_0120")}let data={prog_id:_ds.prog_id};data.table_id=_ds._dataSourceTableId;try{const row_idx=func.common.find_ROWID_idx(_ds,_ds.currentRecordId);data.table_data=_ds.data_feed.rows[row_idx];save_ret=await _this.func.common.db(SESSION_ID,"dbs_create",data,{},dsSessionP);refresh_document_changes_for_realtime_update(SESSION_ID,{row_id:save_ret.data.id,table_id:dataSourceTableId});return save_ret}catch(err){console.error(err)}}};_db.get_db_driver=async function(SESSION_ID,dsSessionP){var db_driver;if(dsSessionP){var _ds=_this.SESSION_OBJ[SESSION_ID].DS_GLB[dsSessionP];let _view_obj=await _this.func.utils.VIEWS_OBJ.get(SESSION_ID,_ds.prog_id);var dataSourceTableId=_view_obj?.progDataSource?.dataSourceTableId;if(!dataSourceTableId){_this.func.utils.alerts.invoke(SESSION_ID,"system_msg","SYS_MSG_0105");return}let file_ret=await _this.func.utils.FILES_OBJ.get(SESSION_ID,dataSourceTableId);db_driver=file_ret.properties.db_driver||"xuda"}if(_this.SESSION_OBJ[SESSION_ID].engine_mode==="live_preview"&&!db_driver&&_this.SESSION_OBJ[SESSION_ID].app_id==="temp"){db_driver="pouchdb"}return db_driver};_db.get_query=async function(SESSION_ID,table_id,queryP,dsSessionP,viewSourceDescP,sourceP,reduceP,skipP,limitP,countP,idsP,sortModel,sort_dir,filterModel={filterModelNative:filterModelNative,filterModelMongo:filterModelMongo,filterModelSql:filterModelSql,filterModelUserMongo:filterModelUserMongo,filterModelUserSql:filterModelUserSql},dataSourceFilterModelType="index",total_fields_info){const get_fields=async function(_ds){var fields=[];const _view_obj=await _this.func.utils.VIEWS_OBJ.get(SESSION_ID,_ds.prog_id);if(_view_obj.progFields){for(let val of _view_obj.progFields){if(val.data.type==="table"){fields.push(val.data.field_id)}}}return fields};const run_local=async function(){if(!_this.SESSION_OBJ[SESSION_ID])return;if(!_this.SESSION_OBJ[SESSION_ID].DS_GLB[dsSessionP])return;var ds=_this.SESSION_OBJ[SESSION_ID].DS_GLB[dsSessionP];var v=ds.v;var query_string;if(queryP.indexId){if(countP&&queryP.desc){query_string=`startkey=${JSON.stringify(queryP.endkey)}&endkey=${JSON.stringify(queryP.startkey)}`}else{query_string=`startkey=${JSON.stringify(queryP.startkey)}&endkey=${JSON.stringify(queryP.endkey)}&desc=${queryP.desc}`}}else{query_string="key="+queryP.table_id}var db_driver=await _db.get_db_driver(SESSION_ID,dsSessionP);var fields_arr=await get_fields(ds);const response={success:async function(json){if(dsSessionP&&!_this.SESSION_OBJ[SESSION_ID]?.DS_GLB?.[dsSessionP]){return}if(json.code<0){response.error(json.data);return}var data=json.data;if(dsSessionP)_this.func.utils.debug.log(SESSION_ID,ds._dataSourceTableId,{module:ds.viewModule,action:"read",prop:sourceP,details:query_string,result:data.rows?data.rows.length:0,error:null,source:viewSourceDescP,json:data,fields:_.assignIn(ds.locate_from,ds.locate_to),type:"file",dsSession:dsSessionP});return data},error:async function(err){if(dsSessionP&&!ds)return;if(dsSessionP){var err_msg=err&&err.data?err.data:err;_this.func.utils.debug.log(SESSION_ID,_this.SESSION_OBJ[SESSION_ID].DS_GLB[dsSessionP]._dataSourceTableId,{module:ds.viewModule,action:"read",prop:sourceP,details:query_string,result:null,error:err_msg,source:viewSourceDescP,json:null,fields:_.assignIn(ds.locate_from,ds.locate_to),type:"file",dsSession:dsSessionP})}_this.func.utils.debug_report(SESSION_ID,"datasource couchDB query "+sourceP,err_msg,"E");return{rows:[],error:true}}};var data={desc:queryP.desc,indexId:queryP.indexId,key:queryP.table_id,reduce:reduceP,viewSourceDesc:viewSourceDescP,limit:limitP,skip:skipP,count:countP,ids:idsP,table_id:queryP.table_id,prog_id:ds.prog_id};data.filter_from=JSON.stringify(queryP.filter_from);data.filter_to=JSON.stringify(queryP.filter_to);data.sortOrder=queryP.sortOrder;data.table_id=queryP.table_id;data.startkey=JSON.stringify(queryP.startkey);data.endkey=JSON.stringify(queryP.endkey);if(countP&&queryP.desc){data.sortOrder="asc";data.startkey=JSON.stringify(queryP.endkey);data.endkey=JSON.stringify(queryP.startkey)}data.dataSourceFilterModelType=dataSourceFilterModelType;if(sortModel){data.sortModel=JSON.stringify(sortModel);data.sort_dir=sort_dir}if(!_.isEmpty(filterModel?.filterModelNative)){data.filterModelNative=JSON.stringify(filterModel.filterModelNative)}if(!_.isEmpty(filterModel?.filterModelMongo)){data.filterModelMongo=JSON.stringify(filterModel.filterModelMongo)}if(filterModel?.filterModelSql){data.filterModelSql=JSON.stringify(filterModel.filterModelSql)}if(!_.isEmpty(filterModel?.filterModelUserMongo)){data.filterModelUserMongo=JSON.stringify(filterModel.filterModelUserMongo)}if(filterModel?.filterModelUserSql){data.filterModelUserSql=JSON.stringify(filterModel.filterModelUserSql)}if(total_fields_info){data.total_fields_info=JSON.stringify(total_fields_info)}if(!reduceP&&!countP){data.fields=fields_arr}try{const json=await _this.func.common.db(SESSION_ID,"dbs_read",data,{node:true},dsSessionP);return await response.success(json)}catch(e){return await response.error(e?.message||e?.data||e)}};var db_driver=await this.get_db_driver(SESSION_ID,dsSessionP);if(db_driver==="pouchdb"&&_this.glb.IS_WORKER&&!_this.SESSION_OBJ[SESSION_ID].engine_mode==="live_preview"){var callback_id=_this.func.utils.set_callback_queue(SESSION_ID,callbackP);var obj=_this.func.utils.clean_returned_datasource(SESSION_ID,dsSessionP);return _this.func.utils.post_back_to_client(SESSION_ID,"execute_local_db_query",_this.SESSION_OBJ[SESSION_ID].worker_id,{ds_obj:obj,dsSessionP:dsSessionP,table_id:table_id,queryP:queryP,dsSessionP:dsSessionP,viewSourceDescP:viewSourceDescP,sourceP:sourceP,reduceP:reduceP,skipP:skipP,limitP:limitP,countP:countP,idsP:idsP,callback_id:callback_id})}return await run_local()};_db.utils={};_db.save_indicator=function(SESSION_ID,stateP){if(!_this.glb.IS_WORKER){_this.func.UI.utils.save(SESSION_ID,stateP)}};const init_xuda_dbs_plugin=async function(SESSION_ID){var _session=_this.SESSION_OBJ[SESSION_ID];const plugin_name="@xuda.io/xuda-dbs-plugin-xuda";const get_path=function(plugin_name,resource){var path=`https://${_session.domain}/plugins/${plugin_name}${resource?"/"+resource:""}?app_id=${_session.app_id}`;return path};try{_this.xuda_dbs_plugin=await import(get_path(plugin_name,"studio.mjs"));const db=await func.utils.connect_pouchdb(SESSION_ID);await _db.call_pouch_xuda_dbs_plugin(SESSION_ID,"create_design",{db:db})}catch(err){return console.error(err.message)}};_db.call_pouch_xuda_dbs_plugin=async function(SESSION_ID,method,params){return new Promise(async(resolve,reject)=>{try{if(params.e){params.table_obj=await func.utils.DOCS_OBJ.get(SESSION_ID,params.e.table_id)}await _this.xuda_dbs_plugin[method](params,resolve,reject)}catch(err){reject()}})};_db.pouch={};_db.pouch.dbs_read=async function(SESSION_ID,e){const db=await func.utils.connect_pouchdb(SESSION_ID);return await _db.call_pouch_xuda_dbs_plugin(SESSION_ID,"read",{db:db,e:e})};_db.pouch.dbs_create=async function(SESSION_ID,e){const db=await func.utils.connect_pouchdb(SESSION_ID);return await _db.call_pouch_xuda_dbs_plugin(SESSION_ID,"create",{db:db,e:e})};_db.pouch.dbs_delete=async function(SESSION_ID,e){const db=await func.utils.connect_pouchdb(SESSION_ID);return await _db.call_pouch_xuda_dbs_plugin(SESSION_ID,"del",{db:db,e:e})};_db.pouch.dbs_update=async function(SESSION_ID,e){const db=await func.utils.connect_pouchdb(SESSION_ID);return await _db.call_pouch_xuda_dbs_plugin(SESSION_ID,"update",{db:db,e:e})};_db.pouch.init_db_replication=async function(SESSION_ID){const db=await func.utils.connect_pouchdb(SESSION_ID);var _session=_this.SESSION_OBJ[SESSION_ID];if(_session.url_params.avoid_local||_session.engine_mode==="miniapp"||_session.engine_mode!=="live_preview"&&!_session.opt.enable_offline){return}const changes=db.changes({live:true,include_docs:true}).on("change",function(change){if(!change.doc.udfData)return;func.UI.screen.refresh_document_changes_for_realtime_update(SESSION_ID,{row_id:change.id,table_id:change.doc.udfData.udffileid})}).on("complete",function(info){console.log("complete",info)}).on("error",function(err){console.error(err)});set_replication_stat(SESSION_ID,null,3);const db_name=APP_OBJ[_session.app_id].app_db_name;const rep=db.replicate.to(`https://${_session.domain}/db/${db_name}`,{selector:{docType:"database"},live:true,retry:true,fetch:function(url,opts){if(_session.gtp_token){opts.headers.set("xu-gtp-token",_session.gtp_token)}if(_session.app_token)opts.headers.set("xu-app-token",_session.app_token);{opts.headers.set("xu-db",db_name)}return PouchDB.fetch(url,opts)}}).on("change",function(info){}).on("paused",function(err){if(err){return set_replication_stat(SESSION_ID,null,2)}set_replication_stat(SESSION_ID,null,3)}).on("active",function(){}).on("denied",function(err){set_replication_stat(SESSION_ID,null,2)}).on("complete",function(info){}).on("error",function(err){set_replication_stat(SESSION_ID,null,2)});_db.pouch.set_db_replication_from_server(SESSION_ID)};_db.pouch.set_db_replication_from_server=async function(SESSION_ID){if(!navigator.onLine)return;const db=await func.utils.connect_pouchdb(SESSION_ID);const rep_docs=await _db.pouch.get_replications(SESSION_ID);const _session=_this.SESSION_OBJ[SESSION_ID];const db_name=APP_OBJ[_session.app_id].app_db_name;const remote_db_url=`https://${_session.domain}/db/${db_name}`;const remote_db=new PouchDB(remote_db_url,{fetch:function(url,opts){if(_session.gtp_token){opts.headers.set("xu-gtp-token",_session.gtp_token)}if(_session.app_token)opts.headers.set("xu-app-token",_session.app_token);{opts.headers.set("xu-db",db_name)}return PouchDB.fetch(url,opts)}});if(_this.db_changes_store){_this.db_changes_store.cancel()}const write_stat=async function(rep_id,stat,reason){try{let doc=await db.get(rep_id);doc.stat=stat;doc.stat_reason=reason;try{db.put(doc)}catch(err){}}catch(err){}};const download_documents=async function(rep_doc){await write_stat(rep_doc._id,2);const remote_db=new PouchDB(remote_db_url,{fetch:function(url,opts){opts.headers.set("xu-prog_id",rep_doc.prog_id);if(_session.gtp_token){opts.headers.set("xu-gtp-token",_session.gtp_token)}if(_session.app_token)opts.headers.set("xu-app-token",_session.app_token);{opts.headers.set("xu-db",db_name)}return PouchDB.fetch(url,opts)}});const ret=await remote_db.find({selector:rep_doc.selector,fields:["_id"],limit:9999999999});if(ret?.code<0){return func.utils.debug_report(SESSION_ID,"download_documents",ret.data,"E")}try{var doc_ids=[];for await(let doc of ret.docs){doc_ids.push(doc._id)}db.replicate.from(remote_db_url,{doc_ids:doc_ids,retry:true,style:"main_only",fetch:function(url,opts){if(_session.gtp_token){opts.headers.set("xu-gtp-token",_session.gtp_token)}if(_session.app_token)opts.headers.set("xu-app-token",_session.app_token);{opts.headers.set("xu-db",db_name)}return PouchDB.fetch(url,opts)}}).on("paused",async function(err){if(err){return}const read_ret=await _db.pouch.dbs_read(SESSION_ID,rep_doc.e);await write_stat(rep_doc._id,3)})}catch(err){await write_stat(rep_doc._id,2,err.message);console.error("replication from error",err)}};let filter_tables=[];for(let doc of rep_docs){if(!filter_tables.includes(doc.table_id))filter_tables.push(doc.table_id);if(doc.stat<3)await download_documents(doc)}try{_this.db_changes_store=remote_db.changes({since:"now",live:true,timeout:3e5,style:"main_only",include_docs:false}).on("change",async function(change){if(change.id.substr(0,4)!=="dbs-")return;if(_this.db_replication_from_stat!==3){set_replication_stat(SESSION_ID,3)}try{const existing_doc=await db.get(change.id);db.replicate.from(remote_db_url,{doc_ids:[change.id],retry:true,style:"main_only",fetch:function(url,opts){if(_session.gtp_token){opts.headers.set("xu-gtp-token",_session.gtp_token)}if(_session.app_token)opts.headers.set("xu-app-token",_session.app_token);{opts.headers.set("xu-db",db_name)}return PouchDB.fetch(url,opts)}})}catch(err){try{const table_id=change.id.split("_")[0].substr(4);for(let doc of rep_docs){if(doc.table_id===table_id){download_documents(doc)}}}catch(err){console.warn(err)}}}).on("complete",function(info){}).on("error",function(err){console.error(err);set_replication_stat(SESSION_ID,2);_this.db_changes_store.cancel()})}catch(err){console.error(err)}return};_db.pouch.remove_db_replication_from_server=async function(SESSION_ID,rep_id){const db=await func.utils.connect_pouchdb(SESSION_ID);try{const doc=await db.get(rep_id);db.remove(doc)}catch(error){}};_db.pouch.get_replications=async function(SESSION_ID=Object.keys(SESSION_OBJ)[0]){const db=await func.utils.connect_pouchdb(SESSION_ID);let ret=await db.find({selector:{docType:"rep_request"}});return ret.docs};_db.pouch.get_replication_stat=async function(SESSION_ID){const _session=_this.SESSION_OBJ[SESSION_ID];return _session?.DS_GLB?.[0]?.data_system?.SYS_GLOBAL_BOL_REPLICATION_STAT};const set_replication_stat=async function(SESSION_ID,from_stat,to_stat){var _session=_this.SESSION_OBJ[SESSION_ID];if(!_session?.DS_GLB?.[0]){return setTimeout(function(){set_replication_stat(SESSION_ID,from_stat,to_stat)},1e3)}if(from_stat)_this.db_replication_from_stat=from_stat;if(to_stat)_this.db_replication_to_stat=to_stat;var data={};if(_this.db_replication_from_stat===3&&_this.db_replication_to_stat===3){data.SYS_GLOBAL_BOL_REPLICATION_STAT=1;console.info("Replication On")}else{data.SYS_GLOBAL_BOL_REPLICATION_STAT=0;console.info("Replication Off")}var datasource_changes={[0]:{["data_system"]:data}};await func.datasource.update(SESSION_ID,datasource_changes)};const refresh_document_changes_for_realtime_update=function(SESSION_ID,doc_change){var _session=_this.SESSION_OBJ[SESSION_ID];if(glb.IS_WORKER){return func.utils.post_back_to_client(SESSION_ID,"refresh_document_changes_for_realtime_update",_session.worker_id,{doc_change:doc_change})}func.UI.screen.refresh_document_changes_for_realtime_update(SESSION_ID,doc_change)};
|
|
1
|
+
const _this={};export const init_module=async e=>{_this.func=e.func;_this.glb=e.glb;_this.SESSION_OBJ=e.SESSION_OBJ;_this.APP_OBJ=e.APP_OBJ;_this.IS_DOCKER=e.IS_DOCKER;_this.IS_API_SERVER=e.IS_API_SERVER;_this.IS_PROCESS_SERVER=e.IS_PROCESS_SERVER;if(!_this.xuda_dbs_plugin&&typeof _this.IS_DOCKER==="undefined"&&typeof _this.IS_PROCESS_SERVER==="undefined"&&typeof _this.IS_API_SERVER==="undefined"){await init_xuda_dbs_plugin(e.SESSION_ID)}_this.db_replication_store;_this.db_changes_store;_this.db_replication_from_stat=3;_this.db_replication_to_stat=3};export let _db={};_db.save_data=async function(SESSION_ID,dsSessionP,keyP){var db_driver=await this.get_db_driver(SESSION_ID,dsSessionP);if(db_driver==="pouchdb"&&_this.glb.IS_WORKER){var callback_id=_this.func.utils.set_callback_queue(SESSION_ID,callbackP);var obj=_this.func.utils.clean_returned_datasource(SESSION_ID,dsSessionP);return _this.func.utils.post_back_to_client(SESSION_ID,"execute_local_sava_data",_this.SESSION_OBJ[SESSION_ID].worker_id,{ds_obj:obj,dsSessionP:dsSessionP,keyP:keyP,callback_id:callback_id})}_db.save_indicator(SESSION_ID,true);var _ds=_this.SESSION_OBJ[SESSION_ID].DS_GLB[dsSessionP];let _view_obj=await _this.func.utils.VIEWS_OBJ.get(SESSION_ID,_ds.prog_id);var dataSourceTableId=_view_obj?.progDataSource?.dataSourceTableId;if(!dataSourceTableId){_db.save_indicator(SESSION_ID,false);_this.func.utils.alerts.invoke(SESSION_ID,"system_msg","SYS_MSG_0105");return}var db_driver=await _db.get_db_driver(SESSION_ID,dsSessionP);let table_ret=await _this.func.utils.FILES_OBJ.get(SESSION_ID,dataSourceTableId);if(!table_ret.tableIndexes||_.isEmpty(table_ret.tableIndexes)){_db.save_indicator(SESSION_ID,false);_this.func.utils.alerts.invoke(SESSION_ID,"system_msg","SYS_MSG_0104");return}if(!_ds.data_feed.rows){return console.error("data_feed rows is empty")}const clean_virtual_fields=async function(table_id,data){let table_obj=await func.utils.VIEWS_OBJ.get(SESSION_ID,table_id);var data_obj={};for(const[key,val]of Object.entries(data)){const _tableFieldsObj=func.common.find_item_by_key(table_obj.tableFields,"field_id",key);if(_tableFieldsObj){data_obj[key]=val}}return data_obj};let save_ret;if(_view_obj.properties.menuType==="component"){if(_view_obj?.properties?.rwMode!=="U"){return _this.func.utils.alerts.invoke(SESSION_ID,"system_msg","SYS_MSG_0126")}let data={prog_id:_ds.prog_id};if(_ds.data_feed.rows_added?.length){if(!_view_obj?.properties?.allowCreate){_this.func.utils.alerts.invoke(SESSION_ID,"system_msg","SYS_MSG_0120")}_.forEach(_ds.data_feed.rows_added,function(val,key){data[key]=val});delete _ds.data_feed.rows_added["newRecord"];save_ret=await _this.func.common.db(SESSION_ID,"dbs_create",data,{},dsSessionP);refresh_document_changes_for_realtime_update(SESSION_ID,{row_id:save_ret.data.id,table_id:dataSourceTableId});return save_ret}if(_ds.data_feed.rows_deleted?.length){data.table_id=_ds._dataSourceTableId;data.ids=[];for await(const[key,val]of Object.entries(_ds.data_feed.rows_deleted)){data.ids.push(val);try{const row_idx=func.common.find_ROWID_idx(_ds,val);delete _ds.data_feed.rows[row_idx]}catch(error){}}_ds.data_feed.rows_deleted=[];save_ret=await _this.func.common.db(SESSION_ID,"dbs_delete",data,{},dsSessionP);refresh_document_changes_for_realtime_update(SESSION_ID,{row_id:save_ret.data?.id?.[0],table_id:dataSourceTableId});return save_ret}if(_ds.data_feed.rows_changed?.length){for await(const[key,row_id]of Object.entries(_ds.data_feed.rows_changed)){if(row_id==="datasource_main")continue;let data={prog_id:_ds.prog_id};try{const row_idx=func.common.find_ROWID_idx(_ds,row_id);data.table_data=await clean_virtual_fields(_ds._dataSourceTableId,_ds.data_feed.rows[row_idx])}catch(err){console.error(err)}data.table_id=_ds._dataSourceTableId;data.row_id=row_id;save_ret=await _this.func.common.db(SESSION_ID,"dbs_update",data,{},dsSessionP);refresh_document_changes_for_realtime_update(SESSION_ID,{row_id:save_ret.data?.id?.[0],table_id:dataSourceTableId})}return save_ret}return}if(_view_obj.properties.menuType!=="set_data"){return _this.func.utils.alerts.invoke(SESSION_ID,"system_msg","SYS_MSG_0126")}var mode=_ds.set_mode;if(!mode||mode==="U"){let data={prog_id:_ds.prog_id};data.table_id=_ds._dataSourceTableId;data.row_id=_ds.currentRecordId;data.table_data={};try{const row_idx=func.common.find_ROWID_idx(_ds,_ds.currentRecordId);data.table_data=await clean_virtual_fields(_ds._dataSourceTableId,_ds.data_feed.rows[row_idx])}catch(err){console.error(err)}save_ret=await _this.func.common.db(SESSION_ID,"dbs_update",data,{},dsSessionP);refresh_document_changes_for_realtime_update(SESSION_ID,{row_id:save_ret.data?.id?.[0],table_id:dataSourceTableId})}if(mode==="D"){let data={prog_id:_ds.prog_id};data.table_id=_ds._dataSourceTableId;data.ids=[_ds.currentRecordId];save_ret=await _this.func.common.db(SESSION_ID,"dbs_delete",data,{},dsSessionP);refresh_document_changes_for_realtime_update(SESSION_ID,{row_id:save_ret.data?.id?.[0],table_id:dataSourceTableId});return save_ret}if(mode==="C"){if(_view_obj.properties.crudMode!=="C"&&_view_obj.properties.crudMode==="U"&&!_view_obj.properties.allowCreate){return _this.func.utils.alerts.invoke(SESSION_ID,"system_msg","SYS_MSG_0120")}let data={prog_id:_ds.prog_id};data.table_id=_ds._dataSourceTableId;try{const row_idx=func.common.find_ROWID_idx(_ds,_ds.currentRecordId);data.table_data=_ds.data_feed.rows[row_idx];save_ret=await _this.func.common.db(SESSION_ID,"dbs_create",data,{},dsSessionP);refresh_document_changes_for_realtime_update(SESSION_ID,{row_id:save_ret.data.id,table_id:dataSourceTableId});return save_ret}catch(err){console.error(err)}}};_db.get_db_driver=async function(SESSION_ID,dsSessionP){var db_driver;if(dsSessionP){var _ds=_this.SESSION_OBJ[SESSION_ID].DS_GLB[dsSessionP];let _view_obj=await _this.func.utils.VIEWS_OBJ.get(SESSION_ID,_ds.prog_id);var dataSourceTableId=_view_obj?.progDataSource?.dataSourceTableId;if(!dataSourceTableId){_this.func.utils.alerts.invoke(SESSION_ID,"system_msg","SYS_MSG_0105");return}let file_ret=await _this.func.utils.FILES_OBJ.get(SESSION_ID,dataSourceTableId);db_driver=file_ret.properties.db_driver||"xuda"}if(_this.SESSION_OBJ[SESSION_ID].engine_mode==="live_preview"&&!db_driver&&_this.SESSION_OBJ[SESSION_ID].app_id==="temp"){db_driver="pouchdb"}return db_driver};_db.get_query=async function(SESSION_ID,table_id,queryP,dsSessionP,viewSourceDescP,sourceP,reduceP,skipP,limitP,countP,idsP,sortModel,sort_dir,filterModel={filterModelNative:filterModelNative,filterModelMongo:filterModelMongo,filterModelSql:filterModelSql,filterModelUserMongo:filterModelUserMongo,filterModelUserSql:filterModelUserSql},dataSourceFilterModelType="index",total_fields_info){const get_fields=async function(_ds){var fields=[];const _view_obj=await _this.func.utils.VIEWS_OBJ.get(SESSION_ID,_ds.prog_id);if(_view_obj.progFields){for(let val of _view_obj.progFields){if(val.data.type==="table"){fields.push(val.data.field_id)}}}return fields};const run_local=async function(){if(!_this.SESSION_OBJ[SESSION_ID])return;if(!_this.SESSION_OBJ[SESSION_ID].DS_GLB[dsSessionP])return;var ds=_this.SESSION_OBJ[SESSION_ID].DS_GLB[dsSessionP];var v=ds.v;var query_string;if(queryP.indexId){if(countP&&queryP.desc){query_string=`startkey=${JSON.stringify(queryP.endkey)}&endkey=${JSON.stringify(queryP.startkey)}`}else{query_string=`startkey=${JSON.stringify(queryP.startkey)}&endkey=${JSON.stringify(queryP.endkey)}&desc=${queryP.desc}`}}else{query_string="key="+queryP.table_id}var db_driver=await _db.get_db_driver(SESSION_ID,dsSessionP);var fields_arr=await get_fields(ds);const response={success:async function(json){if(dsSessionP&&!_this.SESSION_OBJ[SESSION_ID]?.DS_GLB?.[dsSessionP]){return}if(json.code<0){response.error(json.data);return}var data=json.data;if(dsSessionP)_this.func.utils.debug.log(SESSION_ID,ds._dataSourceTableId,{module:ds.viewModule,action:"read",prop:sourceP,details:query_string,result:data.rows?data.rows.length:0,error:null,source:viewSourceDescP,json:data,fields:_.assignIn(ds.locate_from,ds.locate_to),type:"file",dsSession:dsSessionP});return data},error:async function(err){if(dsSessionP&&!ds)return;if(dsSessionP){var err_msg=err&&err.data?err.data:err;_this.func.utils.debug.log(SESSION_ID,_this.SESSION_OBJ[SESSION_ID].DS_GLB[dsSessionP]._dataSourceTableId,{module:ds.viewModule,action:"read",prop:sourceP,details:query_string,result:null,error:err_msg,source:viewSourceDescP,json:null,fields:_.assignIn(ds.locate_from,ds.locate_to),type:"file",dsSession:dsSessionP})}_this.func.utils.debug_report(SESSION_ID,"datasource couchDB query "+sourceP,err_msg,"E");return{rows:[],error:true}}};var data={desc:queryP.desc,indexId:queryP.indexId,key:queryP.table_id,reduce:reduceP,viewSourceDesc:viewSourceDescP,limit:limitP,skip:skipP,count:countP,ids:idsP,table_id:queryP.table_id,prog_id:ds.prog_id};data.filter_from=JSON.stringify(queryP.filter_from);data.filter_to=JSON.stringify(queryP.filter_to);data.sortOrder=queryP.sortOrder;data.table_id=queryP.table_id;data.startkey=JSON.stringify(queryP.startkey);data.endkey=JSON.stringify(queryP.endkey);if(countP&&queryP.desc){data.sortOrder="asc";data.startkey=JSON.stringify(queryP.endkey);data.endkey=JSON.stringify(queryP.startkey)}data.dataSourceFilterModelType=dataSourceFilterModelType;if(sortModel){data.sortModel=JSON.stringify(sortModel);data.sort_dir=sort_dir}if(!_.isEmpty(filterModel?.filterModelNative)){data.filterModelNative=JSON.stringify(filterModel.filterModelNative)}if(!_.isEmpty(filterModel?.filterModelMongo)){data.filterModelMongo=JSON.stringify(filterModel.filterModelMongo)}if(filterModel?.filterModelSql){data.filterModelSql=JSON.stringify(filterModel.filterModelSql)}if(!_.isEmpty(filterModel?.filterModelUserMongo)){data.filterModelUserMongo=JSON.stringify(filterModel.filterModelUserMongo)}if(filterModel?.filterModelUserSql){data.filterModelUserSql=JSON.stringify(filterModel.filterModelUserSql)}if(total_fields_info){data.total_fields_info=JSON.stringify(total_fields_info)}if(!reduceP&&!countP){data.fields=fields_arr}try{const json=await _this.func.common.db(SESSION_ID,"dbs_read",data,{node:true},dsSessionP);return await response.success(json)}catch(e){return await response.error(e?.message||e?.data||e)}};var db_driver=await this.get_db_driver(SESSION_ID,dsSessionP);if(db_driver==="pouchdb"&&_this.glb.IS_WORKER&&!_this.SESSION_OBJ[SESSION_ID].engine_mode==="live_preview"){var callback_id=_this.func.utils.set_callback_queue(SESSION_ID,callbackP);var obj=_this.func.utils.clean_returned_datasource(SESSION_ID,dsSessionP);return _this.func.utils.post_back_to_client(SESSION_ID,"execute_local_db_query",_this.SESSION_OBJ[SESSION_ID].worker_id,{ds_obj:obj,dsSessionP:dsSessionP,table_id:table_id,queryP:queryP,dsSessionP:dsSessionP,viewSourceDescP:viewSourceDescP,sourceP:sourceP,reduceP:reduceP,skipP:skipP,limitP:limitP,countP:countP,idsP:idsP,callback_id:callback_id})}return await run_local()};_db.utils={};_db.save_indicator=function(SESSION_ID,stateP){if(!_this.glb.IS_WORKER){_this.func.UI.utils.save(SESSION_ID,stateP)}};const init_xuda_dbs_plugin=async function(SESSION_ID){var _session=_this.SESSION_OBJ[SESSION_ID];const plugin_name="@xuda.io/xuda-dbs-plugin-xuda";const get_path=function(plugin_name,resource){var path=`https://${_session.domain}/plugins/${plugin_name}${resource?"/"+resource:""}?app_id=${_session.app_id}`;return path};try{_this.xuda_dbs_plugin=await import(get_path(plugin_name,"studio.mjs"));const db=await func.utils.connect_pouchdb(SESSION_ID);await _db.call_pouch_xuda_dbs_plugin(SESSION_ID,"create_design",{db:db})}catch(err){return console.error(err.message)}};_db.call_pouch_xuda_dbs_plugin=async function(SESSION_ID,method,params){return new Promise(async(resolve,reject)=>{try{if(params.e){params.table_obj=await func.utils.DOCS_OBJ.get(SESSION_ID,params.e.table_id)}await _this.xuda_dbs_plugin[method](params,resolve,reject)}catch(err){reject()}})};_db.pouch={};_db.pouch.dbs_read=async function(SESSION_ID,e){const db=await func.utils.connect_pouchdb(SESSION_ID);return await _db.call_pouch_xuda_dbs_plugin(SESSION_ID,"read",{db:db,e:e})};_db.pouch.dbs_create=async function(SESSION_ID,e){const db=await func.utils.connect_pouchdb(SESSION_ID);return await _db.call_pouch_xuda_dbs_plugin(SESSION_ID,"create",{db:db,e:e})};_db.pouch.dbs_delete=async function(SESSION_ID,e){const db=await func.utils.connect_pouchdb(SESSION_ID);return await _db.call_pouch_xuda_dbs_plugin(SESSION_ID,"del",{db:db,e:e})};_db.pouch.dbs_update=async function(SESSION_ID,e){const db=await func.utils.connect_pouchdb(SESSION_ID);return await _db.call_pouch_xuda_dbs_plugin(SESSION_ID,"update",{db:db,e:e})};_db.pouch.init_db_replication=async function(SESSION_ID){const db=await func.utils.connect_pouchdb(SESSION_ID);var _session=_this.SESSION_OBJ[SESSION_ID];if(_session.url_params.avoid_local||_session.engine_mode==="miniapp"||_session.engine_mode!=="live_preview"&&!_session.opt.enable_offline){return}const changes=db.changes({live:true,include_docs:true}).on("change",function(change){if(!change.doc.udfData)return;func.UI.screen.refresh_document_changes_for_realtime_update(SESSION_ID,{row_id:change.id,table_id:change.doc.udfData.udffileid})}).on("complete",function(info){console.log("complete",info)}).on("error",function(err){console.error(err)});set_replication_stat(SESSION_ID,null,3);const db_name=APP_OBJ[_session.app_id].app_db_name;const rep=db.replicate.to(`https://${_session.domain}/db/${db_name}`,{selector:{docType:"database"},live:true,retry:true,fetch:function(url,opts){if(_session.gtp_token){opts.headers.set("xu-gtp-token",_session.gtp_token)}if(_session.app_token)opts.headers.set("xu-app-token",_session.app_token);{opts.headers.set("xu-db",db_name)}return PouchDB.fetch(url,opts)}}).on("change",function(info){}).on("paused",function(err){if(err){return set_replication_stat(SESSION_ID,null,2)}set_replication_stat(SESSION_ID,null,3)}).on("active",function(){}).on("denied",function(err){set_replication_stat(SESSION_ID,null,2)}).on("complete",function(info){}).on("error",function(err){set_replication_stat(SESSION_ID,null,2)});_db.pouch.set_db_replication_from_server(SESSION_ID);$("body").on("set_db_replication_from_server",()=>{_db.pouch.set_db_replication_from_server(SESSION_ID)})};_db.pouch.set_db_replication_from_server=async function(SESSION_ID){if(!IS_ONLINE)return;const db=await func.utils.connect_pouchdb(SESSION_ID);const rep_docs=await _db.pouch.get_replications(SESSION_ID);const _session=_this.SESSION_OBJ[SESSION_ID];const db_name=APP_OBJ[_session.app_id].app_db_name;const remote_db_url=`https://${_session.domain}/db/${db_name}`;const remote_db=new PouchDB(remote_db_url,{fetch:function(url,opts){if(_session.gtp_token){opts.headers.set("xu-gtp-token",_session.gtp_token)}if(_session.app_token)opts.headers.set("xu-app-token",_session.app_token);{opts.headers.set("xu-db",db_name)}return PouchDB.fetch(url,opts)}});if(_this.db_changes_store){_this.db_changes_store.cancel()}const write_stat=async function(rep_id,stat,reason){try{let doc=await db.get(rep_id);doc.stat=stat;doc.stat_reason=reason;try{db.put(doc)}catch(err){}}catch(err){}};const download_documents=async function(rep_doc){await write_stat(rep_doc._id,2);const remote_db=new PouchDB(remote_db_url,{fetch:function(url,opts){opts.headers.set("xu-prog_id",rep_doc.prog_id);if(_session.gtp_token){opts.headers.set("xu-gtp-token",_session.gtp_token)}if(_session.app_token)opts.headers.set("xu-app-token",_session.app_token);{opts.headers.set("xu-db",db_name)}return PouchDB.fetch(url,opts)}});const ret=await remote_db.find({selector:rep_doc.selector,fields:["_id"],limit:9999999999});if(ret?.code<0){return func.utils.debug_report(SESSION_ID,"download_documents",ret.data,"E")}try{var doc_ids=[];for await(let doc of ret.docs){doc_ids.push(doc._id)}db.replicate.from(remote_db_url,{doc_ids:doc_ids,retry:true,style:"main_only",fetch:function(url,opts){if(_session.gtp_token){opts.headers.set("xu-gtp-token",_session.gtp_token)}if(_session.app_token)opts.headers.set("xu-app-token",_session.app_token);{opts.headers.set("xu-db",db_name)}return PouchDB.fetch(url,opts)}}).on("paused",async function(err){if(err){return}const read_ret=await _db.pouch.dbs_read(SESSION_ID,rep_doc.e);await write_stat(rep_doc._id,3)})}catch(err){await write_stat(rep_doc._id,2,err.message);console.error("replication from error",err)}};let filter_tables=[];for(let doc of rep_docs){if(!filter_tables.includes(doc.table_id))filter_tables.push(doc.table_id);if(doc.stat<3)await download_documents(doc)}try{_this.db_changes_store=remote_db.changes({since:"now",live:true,timeout:3e5,style:"main_only",include_docs:false}).on("change",async function(change){if(change.id.substr(0,4)!=="dbs-")return;if(_this.db_replication_from_stat!==3){set_replication_stat(SESSION_ID,3)}try{const existing_doc=await db.get(change.id);db.replicate.from(remote_db_url,{doc_ids:[change.id],retry:true,style:"main_only",fetch:function(url,opts){if(_session.gtp_token){opts.headers.set("xu-gtp-token",_session.gtp_token)}if(_session.app_token)opts.headers.set("xu-app-token",_session.app_token);{opts.headers.set("xu-db",db_name)}return PouchDB.fetch(url,opts)}})}catch(err){try{const table_id=change.id.split("_")[0].substr(4);for(let doc of rep_docs){if(doc.table_id===table_id){download_documents(doc)}}}catch(err){console.warn(err)}}}).on("complete",function(info){}).on("error",function(err){console.error(err);set_replication_stat(SESSION_ID,2);_this.db_changes_store.cancel()})}catch(err){console.error(err)}return};_db.pouch.remove_db_replication_from_server=async function(SESSION_ID,rep_id){const db=await func.utils.connect_pouchdb(SESSION_ID);try{const doc=await db.get(rep_id);db.remove(doc)}catch(error){}};_db.pouch.get_replications=async function(SESSION_ID=Object.keys(SESSION_OBJ)[0]){const db=await func.utils.connect_pouchdb(SESSION_ID);let ret=await db.find({selector:{docType:"rep_request"}});return ret.docs};_db.pouch.get_replication_stat=async function(SESSION_ID){const _session=_this.SESSION_OBJ[SESSION_ID];return _session?.DS_GLB?.[0]?.data_system?.SYS_GLOBAL_BOL_REPLICATION_STAT};const set_replication_stat=async function(SESSION_ID,from_stat,to_stat){var _session=_this.SESSION_OBJ[SESSION_ID];if(!_session?.DS_GLB?.[0]){return setTimeout(function(){set_replication_stat(SESSION_ID,from_stat,to_stat)},1e3)}if(from_stat)_this.db_replication_from_stat=from_stat;if(to_stat)_this.db_replication_to_stat=to_stat;var data={};if(_this.db_replication_from_stat===3&&_this.db_replication_to_stat===3){data.SYS_GLOBAL_BOL_REPLICATION_STAT=1;console.info("Replication On")}else{data.SYS_GLOBAL_BOL_REPLICATION_STAT=0;console.info("Replication Off")}var datasource_changes={[0]:{["data_system"]:data}};await func.datasource.update(SESSION_ID,datasource_changes)};const refresh_document_changes_for_realtime_update=function(SESSION_ID,doc_change){var _session=_this.SESSION_OBJ[SESSION_ID];if(glb.IS_WORKER){return func.utils.post_back_to_client(SESSION_ID,"refresh_document_changes_for_realtime_update",_session.worker_id,{doc_change:doc_change})}func.UI.screen.refresh_document_changes_for_realtime_update(SESSION_ID,doc_change)};
|
|
@@ -655,9 +655,12 @@ _db.pouch.init_db_replication = async function (SESSION_ID) {
|
|
|
655
655
|
});
|
|
656
656
|
|
|
657
657
|
_db.pouch.set_db_replication_from_server(SESSION_ID);
|
|
658
|
+
$('body').on('set_db_replication_from_server', () => {
|
|
659
|
+
_db.pouch.set_db_replication_from_server(SESSION_ID);
|
|
660
|
+
});
|
|
658
661
|
};
|
|
659
662
|
_db.pouch.set_db_replication_from_server = async function (SESSION_ID) {
|
|
660
|
-
if (!
|
|
663
|
+
if (!IS_ONLINE) return;
|
|
661
664
|
|
|
662
665
|
const db = await func.utils.connect_pouchdb(SESSION_ID);
|
|
663
666
|
const rep_docs = await _db.pouch.get_replications(SESSION_ID);
|
|
@@ -28,7 +28,7 @@ export const project_loader = async function (SESSION_ID, app_id, prog_id) {
|
|
|
28
28
|
const db = await func.utils.connect_pouchdb(SESSION_ID);
|
|
29
29
|
if (['live_preview', 'miniapp'].includes(_session.engine_mode)) {
|
|
30
30
|
// if on-line
|
|
31
|
-
if (
|
|
31
|
+
if (IS_ONLINE) {
|
|
32
32
|
ret_build_info = await get_app_build_info(SESSION_ID, app_id);
|
|
33
33
|
if (ret_build_info.code < 0) {
|
|
34
34
|
return console.error(ret_build_info);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
const _this={};export const init_module=e=>{_this.func=e.func;_this.glb=e.glb;_this.SESSION_OBJ=e.SESSION_OBJ;_this.APP_OBJ=e.APP_OBJ;_this.IS_DOCKER=e.IS_DOCKER;_this.IS_API_SERVER=e.IS_API_SERVER;_this.IS_PROCESS_SERVER=e.IS_PROCESS_SERVER};export const project_loader=async function(SESSION_ID,app_id,prog_id){try{var _session=_this.SESSION_OBJ[SESSION_ID];if(_this.func.UI.utils.get_url_attribute(SESSION_ID,"clear_cache")){await func.index.delete_pouch(SESSION_ID)}let last_changed_ts=0;var ret_build_info={};if(typeof XUDA_BUILD_INFO!=="undefined"){_session.build_info=XUDA_BUILD_INFO}else{const db=await func.utils.connect_pouchdb(SESSION_ID);if(["live_preview","miniapp"].includes(_session.engine_mode)){if(navigator.onLine){ret_build_info=await get_app_build_info(SESSION_ID,app_id);if(ret_build_info.code<0){return console.error(ret_build_info)}try{const{_id,_rev}=await db.get(`cache_build_info`);await db.remove({_id:_id,_rev:_rev})}catch(error){}try{await db.put({_id:`cache_build_info`,build_info:ret_build_info,docType:"cache_build_info"})}catch(error){}}else{try{ret_build_info=(await db.get(`cache_build_info`)).build_info}catch(error){return console.error("cache_build_info error")}}last_changed_ts=ret_build_info.data.last_changed_ts}else{try{await db.get(`cache_rt_info`)}catch(err){const startup_module=await func.common.get_module(SESSION_ID,"xuda-deploy-startup-loader.mjs");await startup_module.loader(SESSION_ID)}last_changed_ts=_session.opt.last_changed_ts}}await get_rt_info(SESSION_ID,app_id,last_changed_ts);insert_custom_prop(SESSION_ID);if(_session?.app_admin_prop?.app_admin_direction){$(_session.root_element).attr("dir",_session.app_admin_prop.app_admin_direction)}if(_session.engine_mode==="live_preview"){const module=await _this.func.common.get_module(SESSION_ID,"xuda-live-preview-module.esm.js");module.live_preview_loader(SESSION_ID);return}if(_this.APP_OBJ[app_id]?.is_deployment){try{await init_runtime_websocket(SESSION_ID,app_id)}catch(error){throw error}}const module=await _this.func.common.get_module(SESSION_ID,`xuda-progs-loader-module.mjs`);if(app_id!=="unknown"){await module.load_objects_cache(SESSION_ID)}await _this.func.UI.main.embed_loader(SESSION_ID)}catch(error){throw error}};const get_app_build_info=async function(SESSION_ID,app_id){return new Promise(function(resolve,reject){var _session=_this.SESSION_OBJ[SESSION_ID];let app_id_reference=_this.APP_OBJ[app_id].app_id_reference;fetch(_this.func.common.get_url(SESSION_ID,"rpi","get_app_build"),{method:"POST",headers:{Accept:"application/json","Content-Type":"application/json","xu-gtp-token":_session.gtp_token,"xu-app-token":_session.app_token},body:JSON.stringify({app_id:app_id,app_id_reference:app_id_reference,engine_mode:_session.engine_mode})}).then(response=>{if(!response.ok){return response.text().then(text=>{throw new Error(text)})}return response.json()}).then(async json=>{_this.SESSION_OBJ[SESSION_ID].build_info=json.data;resolve(json)}).catch(err=>{try{resolve(JSON.parse(err.message))}catch(error){resolve({code:-1,data:err.message})}})})};const get_user_group_account_info=async function(SESSION_ID,uid){var _session=SESSION_OBJ[SESSION_ID];const response=await fetch(`https://${_session.domain}/cpi/get_account_info`,{method:"POST",headers:{Accept:"application/json","Content-Type":"application/json"},body:JSON.stringify({uid:uid,uid_query:$.cookie("uid")})});const json=await response.json();return json.data};const get_rt_info=async function(SESSION_ID,app_id,last_changed_ts){var _session=_this.SESSION_OBJ[SESSION_ID];return new Promise(async function(resolve,reject){const response={success:async function(ret,ajaxP){if(ret.code<0){return response.error(ret.data)}const rt_info_obj=ret.data;var app_id=rt_info_obj._id;_this.APP_OBJ[app_id]=rt_info_obj;_session.app_id=app_id;if(rt_info_obj?.deploy_data?.global_variables){_session.url_params={..._session.url_params,...rt_info_obj.deploy_data.global_variables}}let account_info=_.clone(rt_info_obj?.account_info||{});if(_session.engine_mode==="user_group"){const user_group_data=await get_user_group_account_info(SESSION_ID,rt_info_obj?.account_info?.uid);account_info=user_group_data.account_info;account_info.uid=user_group_data._id}_session.USR_OBJ={_id:account_info?.uid,usr_name:account_info?.username,usr_first_name:account_info?.first_name||account_info?.email,usr_last_name:account_info?.last_name||"",usr_email:account_info?.email,usr_profile_picture:account_info?.profile_picture};_session.login_info=rt_info_obj?.login_info;_session.client_ip=rt_info_obj.client_ip;_session.rpi_http_methods=rt_info_obj.rpi_http_methods;_session.app_admin_prop=rt_info_obj.app_admin_prop;_session.is_deployment=rt_info_obj.is_deployment;resolve();$(".loader_logo").css("background-image",`url( ${rt_info_obj.app_pic})`).hide().fadeIn()},error:async function(err){if(err){return _this.func.UI.utils.progressScreen.show(SESSION_ID,err,null,true)}console.warn("** reload request")}};const db=await func.utils.connect_pouchdb(SESSION_ID);try{let ret=await db.get(`cache_rt_info`);const rt_info_obj=ret.data;if(rt_info_obj.data.last_changed_ts!==last_changed_ts||!["live_preview","miniapp"].includes(_session.engine_mode)&&rt_info_obj.data.app_build_id!==_session.opt.app_build_id){_this.func.UI.utils.progressScreen.show(SESSION_ID,"New application setup detected, refreshing data and reloading in 5 sec");setTimeout(async()=>{await func.index.delete_pouch(SESSION_ID);location.reload()},5e3);return}response.success(rt_info_obj)}catch(err){fetch(_this.func.common.get_url(SESSION_ID,"rpi","get_rt_info"),{method:"POST",headers:{Accept:"application/json","Content-Type":"application/json","xu-gtp-token":_session.gtp_token,"xu-app-token":_session.app_token},body:JSON.stringify({app_id:app_id,prog_id:_session.engine_mode==="live_preview"?"":_session.prog_id,engine_mode:_session.engine_mode,build:_session.build_info.build,session_id:SESSION_ID,is_cordova:_this.glb.is_cordova,client_info:_session.SYS_GLOBAL_OBJ_CLIENT_INFO,client_id:_session.SYS_GLOBAL_OBJ_CLIENT_INFO.fingerprint})}).then(response=>{if(!response.ok){return response.text().then(text=>{throw new Error(text)})}return response.json()}).then(json=>{if(json.code<0){throw new Error(json.data||"unknown error")}response.success(json);var doc={_id:`cache_rt_info`,data:json,docType:"cache_app"};db.put(doc)}).catch(err=>{response.error(err.message)})}})};const insert_custom_prop=function(SESSION_ID){try{var app_id=_this.SESSION_OBJ[SESSION_ID].app_id;if(_this.APP_OBJ[app_id]?.app_custom_prop?.app_custom_header){var head=document.getElementsByTagName("head")[0];const app_custom_header=_this.APP_OBJ[app_id].app_custom_prop.app_custom_header;$(head).append(func.utils.replace_studio_drive_url(SESSION_ID,app_custom_header))}if(_this.APP_OBJ[app_id]?.app_custom_prop?.app_custom_body){$(_this.SESSION_OBJ[SESSION_ID].root_element).prepend(_this.APP_OBJ[app_id].app_custom_prop.app_custom_body)}}catch(err){console.error(err)}};const init_runtime_websocket=function(SESSION_ID,app_id){return new Promise(function(resolve,reject){const set_connected=async function(stat){var datasource_changes={[0]:{["data_system"]:{SYS_GLOBAL_BOL_CONNECTED:stat}}};await func.datasource.update(SESSION_ID,datasource_changes)};var _session=_this.SESSION_OBJ[SESSION_ID];var _data_system=_session?.DS_GLB?.[0]?.data_system;const url=`https://${location.hostname}`;var error;RUNTIME_SERVER_WEBSOCKET=io(url,{secure:true,reconnection:true,rejectUnauthorized:false,path:"/ws/socket.io"});RUNTIME_SERVER_WEBSOCKET.on("connect",()=>{console.info("RUNTIME_SERVER_WEBSOCKET connected");if(_data_system){set_connected(1)}if(_session.opt.enable_offline){if($(_session.root_element).hasClass("runtime_offline")){$(_session.root_element).removeClass("runtime_offline");func.utils.alerts.toast(SESSION_ID,"Switched to on-line mode","You are now online. All data stored while you were offline will be synchronized to the server.","success")}}else{_this.func.UI.utils.progressScreen.hide(SESSION_ID)}if(error){if(!RUNTIME_SERVER_WEBSOCKET_CONNECTED){console.warn("** reload request")}}});RUNTIME_SERVER_WEBSOCKET.on("message",e=>{if(_this.APP_OBJ[app_id].is_deployment){_this.func.UI.utils.indicator.server.busy();setTimeout(function(){_this.func.UI.utils.indicator.server.normal()},e?.data?.length*100||100)}var data=e.data;if(e.source==="http_call"){if(e.service==="get_doc_obj_from_build"){return $("body").trigger("get_doc_obj_from_build_response_"+data._id,{data:data})}if(e.service==="heartbeat"){return $("body").trigger("heartbeat_response",{data:data})}return $("body").trigger("get_ws_data_response_"+e.websocket_queue_num,{data:data,e:e})}if(e.source==="deployment_server"){console.log("document_changed",e);return func.UI.screen.refresh_document_changes_for_realtime_update(SESSION_ID,e.data)}if(data!=="connected")return;RUNTIME_SERVER_WEBSOCKET_CONNECTED=true;resolve()});var callback_done=false;RUNTIME_SERVER_WEBSOCKET.on("connect_error",error=>{if(!callback_done){resolve();callback_done=true;error=true}});RUNTIME_SERVER_WEBSOCKET.on("disconnect",async()=>{RUNTIME_SERVER_WEBSOCKET_CONNECTED=false;if(_data_system){set_connected(0)}if(_session.opt.enable_offline){$(_session.root_element).addClass("runtime_offline");func.utils.alerts.toast(SESSION_ID,"Switched to off-line mode","You have lost connection to the server and are now working offline. Once the connection is restored, all data will be synchronized.","warning")}else{_this.func.UI.utils.progressScreen.show(SESSION_ID,"Your browser has temporarily disconnected from the server. Please wait while we attempt to reconnect.")}});window.addEventListener("beforeunload",function(event){var obj={service:"close_websocket",data:{session_id:SESSION_ID}};RUNTIME_SERVER_WEBSOCKET.emit("message",obj)})})};export const run_plugins_runtime_init=async function(SESSION_ID,app_id,method){var _session=_this.SESSION_OBJ[SESSION_ID];const get_path=function(plugin_name,resource){if(_session.worker_type==="Dev"){return`../../plugins/${_session.domain}/${plugin_name}/${resource}`}return`https://${_session.domain}/plugins/${plugin_name}/runtime/${resource}?gtp_token=${_session.gtp_token}&app_id=${_session.app_id}`};if(!_this.APP_OBJ[app_id].app_plugins_purchased)return;for await(const[key,val]of Object.entries(_this.APP_OBJ[app_id].app_plugins_purchased)){if(!val.installed)continue;if(val.manifest?.[method].mjs?.exist&&!val.manifest[method].mjs.is_empty){const module=await import(get_path(key,method+".mjs"));try{await module.default({SESSION_ID:SESSION_ID})}catch(error){console.error(error)}}}};
|
|
1
|
+
const _this={};export const init_module=e=>{_this.func=e.func;_this.glb=e.glb;_this.SESSION_OBJ=e.SESSION_OBJ;_this.APP_OBJ=e.APP_OBJ;_this.IS_DOCKER=e.IS_DOCKER;_this.IS_API_SERVER=e.IS_API_SERVER;_this.IS_PROCESS_SERVER=e.IS_PROCESS_SERVER};export const project_loader=async function(SESSION_ID,app_id,prog_id){try{var _session=_this.SESSION_OBJ[SESSION_ID];if(_this.func.UI.utils.get_url_attribute(SESSION_ID,"clear_cache")){await func.index.delete_pouch(SESSION_ID)}let last_changed_ts=0;var ret_build_info={};if(typeof XUDA_BUILD_INFO!=="undefined"){_session.build_info=XUDA_BUILD_INFO}else{const db=await func.utils.connect_pouchdb(SESSION_ID);if(["live_preview","miniapp"].includes(_session.engine_mode)){if(IS_ONLINE){ret_build_info=await get_app_build_info(SESSION_ID,app_id);if(ret_build_info.code<0){return console.error(ret_build_info)}try{const{_id,_rev}=await db.get(`cache_build_info`);await db.remove({_id:_id,_rev:_rev})}catch(error){}try{await db.put({_id:`cache_build_info`,build_info:ret_build_info,docType:"cache_build_info"})}catch(error){}}else{try{ret_build_info=(await db.get(`cache_build_info`)).build_info}catch(error){return console.error("cache_build_info error")}}last_changed_ts=ret_build_info.data.last_changed_ts}else{try{await db.get(`cache_rt_info`)}catch(err){const startup_module=await func.common.get_module(SESSION_ID,"xuda-deploy-startup-loader.mjs");await startup_module.loader(SESSION_ID)}last_changed_ts=_session.opt.last_changed_ts}}await get_rt_info(SESSION_ID,app_id,last_changed_ts);insert_custom_prop(SESSION_ID);if(_session?.app_admin_prop?.app_admin_direction){$(_session.root_element).attr("dir",_session.app_admin_prop.app_admin_direction)}if(_session.engine_mode==="live_preview"){const module=await _this.func.common.get_module(SESSION_ID,"xuda-live-preview-module.esm.js");module.live_preview_loader(SESSION_ID);return}if(_this.APP_OBJ[app_id]?.is_deployment){try{await init_runtime_websocket(SESSION_ID,app_id)}catch(error){throw error}}const module=await _this.func.common.get_module(SESSION_ID,`xuda-progs-loader-module.mjs`);if(app_id!=="unknown"){await module.load_objects_cache(SESSION_ID)}await _this.func.UI.main.embed_loader(SESSION_ID)}catch(error){throw error}};const get_app_build_info=async function(SESSION_ID,app_id){return new Promise(function(resolve,reject){var _session=_this.SESSION_OBJ[SESSION_ID];let app_id_reference=_this.APP_OBJ[app_id].app_id_reference;fetch(_this.func.common.get_url(SESSION_ID,"rpi","get_app_build"),{method:"POST",headers:{Accept:"application/json","Content-Type":"application/json","xu-gtp-token":_session.gtp_token,"xu-app-token":_session.app_token},body:JSON.stringify({app_id:app_id,app_id_reference:app_id_reference,engine_mode:_session.engine_mode})}).then(response=>{if(!response.ok){return response.text().then(text=>{throw new Error(text)})}return response.json()}).then(async json=>{_this.SESSION_OBJ[SESSION_ID].build_info=json.data;resolve(json)}).catch(err=>{try{resolve(JSON.parse(err.message))}catch(error){resolve({code:-1,data:err.message})}})})};const get_user_group_account_info=async function(SESSION_ID,uid){var _session=SESSION_OBJ[SESSION_ID];const response=await fetch(`https://${_session.domain}/cpi/get_account_info`,{method:"POST",headers:{Accept:"application/json","Content-Type":"application/json"},body:JSON.stringify({uid:uid,uid_query:$.cookie("uid")})});const json=await response.json();return json.data};const get_rt_info=async function(SESSION_ID,app_id,last_changed_ts){var _session=_this.SESSION_OBJ[SESSION_ID];return new Promise(async function(resolve,reject){const response={success:async function(ret,ajaxP){if(ret.code<0){return response.error(ret.data)}const rt_info_obj=ret.data;var app_id=rt_info_obj._id;_this.APP_OBJ[app_id]=rt_info_obj;_session.app_id=app_id;if(rt_info_obj?.deploy_data?.global_variables){_session.url_params={..._session.url_params,...rt_info_obj.deploy_data.global_variables}}let account_info=_.clone(rt_info_obj?.account_info||{});if(_session.engine_mode==="user_group"){const user_group_data=await get_user_group_account_info(SESSION_ID,rt_info_obj?.account_info?.uid);account_info=user_group_data.account_info;account_info.uid=user_group_data._id}_session.USR_OBJ={_id:account_info?.uid,usr_name:account_info?.username,usr_first_name:account_info?.first_name||account_info?.email,usr_last_name:account_info?.last_name||"",usr_email:account_info?.email,usr_profile_picture:account_info?.profile_picture};_session.login_info=rt_info_obj?.login_info;_session.client_ip=rt_info_obj.client_ip;_session.rpi_http_methods=rt_info_obj.rpi_http_methods;_session.app_admin_prop=rt_info_obj.app_admin_prop;_session.is_deployment=rt_info_obj.is_deployment;resolve();$(".loader_logo").css("background-image",`url( ${rt_info_obj.app_pic})`).hide().fadeIn()},error:async function(err){if(err){return _this.func.UI.utils.progressScreen.show(SESSION_ID,err,null,true)}console.warn("** reload request")}};const db=await func.utils.connect_pouchdb(SESSION_ID);try{let ret=await db.get(`cache_rt_info`);const rt_info_obj=ret.data;if(rt_info_obj.data.last_changed_ts!==last_changed_ts||!["live_preview","miniapp"].includes(_session.engine_mode)&&rt_info_obj.data.app_build_id!==_session.opt.app_build_id){_this.func.UI.utils.progressScreen.show(SESSION_ID,"New application setup detected, refreshing data and reloading in 5 sec");setTimeout(async()=>{await func.index.delete_pouch(SESSION_ID);location.reload()},5e3);return}response.success(rt_info_obj)}catch(err){fetch(_this.func.common.get_url(SESSION_ID,"rpi","get_rt_info"),{method:"POST",headers:{Accept:"application/json","Content-Type":"application/json","xu-gtp-token":_session.gtp_token,"xu-app-token":_session.app_token},body:JSON.stringify({app_id:app_id,prog_id:_session.engine_mode==="live_preview"?"":_session.prog_id,engine_mode:_session.engine_mode,build:_session.build_info.build,session_id:SESSION_ID,is_cordova:_this.glb.is_cordova,client_info:_session.SYS_GLOBAL_OBJ_CLIENT_INFO,client_id:_session.SYS_GLOBAL_OBJ_CLIENT_INFO.fingerprint})}).then(response=>{if(!response.ok){return response.text().then(text=>{throw new Error(text)})}return response.json()}).then(json=>{if(json.code<0){throw new Error(json.data||"unknown error")}response.success(json);var doc={_id:`cache_rt_info`,data:json,docType:"cache_app"};db.put(doc)}).catch(err=>{response.error(err.message)})}})};const insert_custom_prop=function(SESSION_ID){try{var app_id=_this.SESSION_OBJ[SESSION_ID].app_id;if(_this.APP_OBJ[app_id]?.app_custom_prop?.app_custom_header){var head=document.getElementsByTagName("head")[0];const app_custom_header=_this.APP_OBJ[app_id].app_custom_prop.app_custom_header;$(head).append(func.utils.replace_studio_drive_url(SESSION_ID,app_custom_header))}if(_this.APP_OBJ[app_id]?.app_custom_prop?.app_custom_body){$(_this.SESSION_OBJ[SESSION_ID].root_element).prepend(_this.APP_OBJ[app_id].app_custom_prop.app_custom_body)}}catch(err){console.error(err)}};const init_runtime_websocket=function(SESSION_ID,app_id){return new Promise(function(resolve,reject){const set_connected=async function(stat){var datasource_changes={[0]:{["data_system"]:{SYS_GLOBAL_BOL_CONNECTED:stat}}};await func.datasource.update(SESSION_ID,datasource_changes)};var _session=_this.SESSION_OBJ[SESSION_ID];var _data_system=_session?.DS_GLB?.[0]?.data_system;const url=`https://${location.hostname}`;var error;RUNTIME_SERVER_WEBSOCKET=io(url,{secure:true,reconnection:true,rejectUnauthorized:false,path:"/ws/socket.io"});RUNTIME_SERVER_WEBSOCKET.on("connect",()=>{console.info("RUNTIME_SERVER_WEBSOCKET connected");if(_data_system){set_connected(1)}if(_session.opt.enable_offline){if($(_session.root_element).hasClass("runtime_offline")){$(_session.root_element).removeClass("runtime_offline");func.utils.alerts.toast(SESSION_ID,"Switched to on-line mode","You are now online. All data stored while you were offline will be synchronized to the server.","success")}}else{_this.func.UI.utils.progressScreen.hide(SESSION_ID)}if(error){if(!RUNTIME_SERVER_WEBSOCKET_CONNECTED){console.warn("** reload request")}}});RUNTIME_SERVER_WEBSOCKET.on("message",e=>{if(_this.APP_OBJ[app_id].is_deployment){_this.func.UI.utils.indicator.server.busy();setTimeout(function(){_this.func.UI.utils.indicator.server.normal()},e?.data?.length*100||100)}var data=e.data;if(e.source==="http_call"){if(e.service==="get_doc_obj_from_build"){return $("body").trigger("get_doc_obj_from_build_response_"+data._id,{data:data})}if(e.service==="heartbeat"){return $("body").trigger("heartbeat_response",{data:data})}return $("body").trigger("get_ws_data_response_"+e.websocket_queue_num,{data:data,e:e})}if(e.source==="deployment_server"){console.log("document_changed",e);return func.UI.screen.refresh_document_changes_for_realtime_update(SESSION_ID,e.data)}if(data!=="connected")return;RUNTIME_SERVER_WEBSOCKET_CONNECTED=true;resolve()});var callback_done=false;RUNTIME_SERVER_WEBSOCKET.on("connect_error",error=>{if(!callback_done){resolve();callback_done=true;error=true}});RUNTIME_SERVER_WEBSOCKET.on("disconnect",async()=>{RUNTIME_SERVER_WEBSOCKET_CONNECTED=false;if(_data_system){set_connected(0)}if(_session.opt.enable_offline){$(_session.root_element).addClass("runtime_offline");func.utils.alerts.toast(SESSION_ID,"Switched to off-line mode","You have lost connection to the server and are now working offline. Once the connection is restored, all data will be synchronized.","warning")}else{_this.func.UI.utils.progressScreen.show(SESSION_ID,"Your browser has temporarily disconnected from the server. Please wait while we attempt to reconnect.")}});window.addEventListener("beforeunload",function(event){var obj={service:"close_websocket",data:{session_id:SESSION_ID}};RUNTIME_SERVER_WEBSOCKET.emit("message",obj)})})};export const run_plugins_runtime_init=async function(SESSION_ID,app_id,method){var _session=_this.SESSION_OBJ[SESSION_ID];const get_path=function(plugin_name,resource){if(_session.worker_type==="Dev"){return`../../plugins/${_session.domain}/${plugin_name}/${resource}`}return`https://${_session.domain}/plugins/${plugin_name}/runtime/${resource}?gtp_token=${_session.gtp_token}&app_id=${_session.app_id}`};if(!_this.APP_OBJ[app_id].app_plugins_purchased)return;for await(const[key,val]of Object.entries(_this.APP_OBJ[app_id].app_plugins_purchased)){if(!val.installed)continue;if(val.manifest?.[method].mjs?.exist&&!val.manifest[method].mjs.is_empty){const module=await import(get_path(key,method+".mjs"));try{await module.default({SESSION_ID:SESSION_ID})}catch(error){console.error(error)}}}};
|
|
@@ -47,4 +47,4 @@ var app_obj,progs_obj,_,progs_str,hide_not_in_use_check,is_server,deployments,Ug
|
|
|
47
47
|
Example: xu-store="{'temp_var':'@calculated_value','status':'ready'}"
|
|
48
48
|
|
|
49
49
|
- xu-viewport: Handles viewport-based logic during rendering
|
|
50
|
-
Example: xu-viewport="@mobile_view"`);const UiElementSchema=z.lazy(()=>z.object({id:z.union([z.literal(`root`),UuidSchema,z.string().regex(/^node-[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i),z.string().regex(/^ui-[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i)]).describe(`Element identifier: "root" for top-level, prefixed UUIDs like "ui-791ca98a-e284-4413-af0a-96e5527c338b"`),type:z.literal(`element`).describe(`Element type - only "element" allowed (no "comment" or "text" types)`),tagName:z.string().describe(`HTML tag name for the element (e.g., "div", "span", "input")`),attributes:UiAttributesSchema.optional().describe(`HTML attributes and Xuda directives (e.g., class, xu-bind, xu-on)`),content:z.string().optional().describe(`Text content for the element (replaces deprecated "text" type)`),text:z.string().optional().describe(`Alternative text property for element content`),children:z.array(UiElementSchema).optional().describe(`Array of child elements nested within this element`),workflow:z.array(WorkflowActionSchema).optional().describe(`Workflow actions associated with this UI element`),path:z.array(z.number()).optional().describe("Array representing the element`s position in the UI tree"),code:z.string().optional().describe(`Generated HTML code representation`),editCode:z.boolean().optional().describe(`Flag indicating if element is in code editing mode`),$folded:z.boolean().optional().describe(`UI editor state - whether element tree is collapsed`)}).describe(`UI element following Himalaya.js structure with Xuda extensions, 1. generate unique id using UUID for every item of the progUi (except the root node, leave the root node as is),2. never use "comment" or "text" type, 3. convert "text" type to "element" and add a text property instead next to the type property `));const DataSourceSchema=z.object({dataSourceType:z.union([z.literal(`table`).describe(`Connect to structured table from global Table Repository`),z.literal(`array`).describe(`Use static or dynamically populated array`),z.literal(`json`).describe(`Load structured data in JSON format`),z.literal(`csv`).describe(`Load data from CSV source`),z.literal(`none`).describe(`No data source attached - self-contained logic unit`),z.literal(``).describe(`Empty string indicating no datasource configured`)]).optional().describe(`Type of data source defining how data is retrieved and processed`),dataSourceFilterModelType:z.union([z.literal(`index`).describe(`Use predefined index with from/to values for fast range filtering`),z.literal(`query`).describe(`Use jQuery Mongo syntax for advanced conditional filters and logical rules`)]).optional().describe(`Filtering approach for table sources`),dataSourceSort:z.union([z.literal(`asc`),z.literal(`desc`)]).optional().describe(`Global sort direction for retrieved data`),dataSourceTableId:z.string().optional().describe(`Reference to table ID in Table Repository when dataSourceType is "table"`),dataSourceIndexId:z.string().optional().describe(`Default index ID used for efficient data lookup and filtering`),dataSourceIndexesObj:z.record(z.record(z.object({from:z.string().describe(`Starting value for index range (can be dynamic expression like @uid_in)`),locate_from:z.string().optional().describe(`Additional locate parameter for range start`),locate_to:z.string().optional().describe(`Additional locate parameter for range end`),to:z.string().describe(`Ending value for index range (can be dynamic expression)`),key:z.string().describe(`Field name being indexed and filtered`)}).describe(`Index field configuration with range values`))).optional().describe(`Index configurations mapped by index ID, defining field ranges and conditions for efficient filtering`),dataSourceReduce:z.boolean().optional().describe(`Whether to reduce results to single aggregated value (count, sum, avg) - requires DBS plugin`),filterModelMongo:z.object({}).optional().describe(`Static MongoDB-style filter query object built using jQuery QueryBuilder`),filterModelMongoFx:z.string().optional().describe(`Dynamic reference to input field containing filter query object (overrides filterModelMongo)`),sortModel:z.array(z.object({field_id:z.string().describe(`Field identifier to sort by`),sort_dir:z.union([z.literal(`asc`),z.literal(`desc`)]).describe(`Sort direction for this specific field`)})).optional().describe(`Array of field-level sorting rules for multi-column sorting`),dataSourceRealtime:z.boolean().optional().describe(`Enable real-time updates when source data changes (table sources only, requires @xuda.io/xuds-dbs-plugin-xuda)`),datafieldsOutputField:z.string().optional().describe(`Field name where raw query results will be stored within parent hierarchy`),dataSourceLimit:z.number().optional().describe(`Maximum number of rows or iterations to return for pagination`),dataSourceSkip:z.number().optional().describe(`Number of rows to skip before returning results, useful for pagination offset`),dataSourceUrl:z.string().optional().describe(`External URL endpoint for loading array/CSV/JSON data from REST APIs or static files`),dataSourceInputField:z.string().optional().describe(`Dynamic field reference in UI or app context for data source values (alternative to external URL)`)}).describe(`Comprehensive data source configuration defining how logic units retrieve, filter, and process data from tables, arrays, APIs, or external sources`);let properties_obj={menuType:z.literal(type).describe(`defines the object category`),menuName:z.string().describe(`Internal name displayed in the Studio interface`)};let properties=z.object(properties_obj).describe(`Core ${type} properties defining behavior, access, and UI framework settings`);const progFields=z.array(ProgFieldSchema).describe(`Defines the internal working fields of the ${type}. These include real and virtual fields used for data binding, user interaction, intermediate logic, and expression evaluation.`);const progEvents=z.array(ProgEventSchema).optional().describe(`Defines all functional logic associated with the ${type}. Events support lifecycle hooks (like on_load, screen_ready, client_interval), event-based workflow, custom utility functions, and conditional logic.`);const progUi=z.array(UiElementSchema).describe(`Describes the rendered interface in a structured JSON format, derived from Himalaya.js (HTML-to-JSON). Each node can be bound to logic via attributes such as xu-exp, bind, for, and trigger. This enables conditional rendering, looping constructs, inline script execution, and seamless integration with workflow.`);const progDataSource=DataSourceSchema.describe(`Defines where the ${type} pulls or binds its data from, such as a database table, external service, or static source.`);let main_obj={_id:z.string().regex(/^[a-zA-Z0-9_]+$/).describe(`Unique ${type} identifier with format constraints`),app_id:z.string().describe(`Reference to the parent application this ${type} belongs to`),stat:z.union([z.literal(1),z.literal(2),z.literal(3),z.literal(4)]).describe(`Document status: 1=draft, 2=review, 3=active, 4=archived`),docType:z.literal(`studio`).describe(`Always "studio" - indicates this is a Studio-authored ${type}`),docDate:TimestampSchema.describe(`Unix timestamp when the ${type} document was created`),ts:TimestampSchema.describe(`Unix timestamp of the most recent modification`),order_ts:TimestampSchema.describe(`Timestamp used for ordering components in the Studio interface`),description:z.string().optional().describe(`Describe in short the ${type}`),studio_meta:StudioMetaSchema};let XudaComponentSchema=z.object(main_obj);main_obj.properties=properties;switch(type){case`globals`:XudaComponentSchema.describe(`The globals object in the Xuda platform defines a universal logic layer shared across all programs, components, and workflows. It provides a centralized and consistent structure for declaring global fields, utility functions, and event-driven logic, ensuring logic reusability and reducing redundancy across the application.`);main_obj.progFields=progFields;main_obj.progEvents=progEvents;break;case`table`:XudaComponentSchema.describe(`The Table Object represents a data entity and serves as the structural definition for interacting with external databases. It supports integration via pluggable connectors, allowing seamless connection to various database engines such as MySQL, CouchDB, and others (see available database plugins for the full list).`);properties_obj.databaseSocket=z.string().default("@xuda.io/xuda-dbs-plugin-xuda").describe("Database driver to use for the table");const XudaFieldType=z.enum(["string","number","boolean","array","object","date"]).describe("Data type for table fields");const IndexDataSchema=z.object({name:z.string().describe("Name of the index"),unique:z.boolean().describe("If true, ensures no duplicates for indexed fields"),keys:z.array(z.string()).describe("List of field names used in this index")});const TableIndexSchema=z.object({id:z.string().describe("Unique identifier for the index"),data:IndexDataSchema.describe("Contains keys, uniqueness setting, and index name")});const FieldPropsSchema=z.object({fieldType:XudaFieldType.describe('Data type: "string", "number", "boolean", "array", "object", or "date"')});const FieldDataSchema=z.object({field_id:z.string().describe("Field identifier used in logic or database operations")});const TableFieldSchema=z.object({id:z.string().describe("Unique ID of the field object"),data:FieldDataSchema.describe("Contains the logical field ID"),props:FieldPropsSchema.describe("Properties of the field including data type")});main_obj.tableIndexes=z.array(TableIndexSchema).describe("Defines indexing rules for efficient lookups and uniqueness constraints");main_obj.tableFields=z.array(TableFieldSchema).describe("Defines each field used in the table and its data type");break;case`folder`:XudaComponentSchema.describe(`The Folder is a non-executable, project-level container represented as a structured JSON object. It is used to define a hierarchical structure for organizing application assets within the Xuda environment. Although it does not execute any logic at runtime, the folder object plays an essential role in shaping the overall architecture of a project by logically grouping related objects such as components, APIs, tables, datasets, and other program entities.`);break;case`component`:XudaComponentSchema.describe(`The component object in the Xuda platform defines a modular, self-contained program unit that encapsulates both front-end presentation and back-end logic. It serves as a reusable UI component that supports a full execution lifecycle, making it ideal for constructing low-code applications that are maintainable, scalable, and highly interactive. A component is engineered to allow seamless integration of logic, data, and rendering, enabling developers to build sophisticated interactive views without redundant code. Each component instance supports input/output parameters, can communicate with other components or programs, and can be dynamically rendered as a page, modal, or embedded panel.`);properties_obj.frameworkProperties=z.object({}).optional().describe(`Framework-specific rendering extensions and configuration`);properties_obj.renderType=z.string().describe(`Component layout type (e.g., "form", "grid", "list")`);properties_obj.rwMode=z.union([z.literal(`R`),z.literal(`W`),z.literal(`RW`)]).describe(`Access mode: R=read-only, W=write-only, RW=read-write`);properties_obj.uiFramework=z.string().describe(`Selected UI framework plugin (e.g., @xuda.io/xuda-framework-plugin-tailwind)`);properties_obj.menuTitle=z.string().optional().describe(`Display title for Studio UI or routing usage`);properties_obj.progParams=z.array(ProgParamSchema).optional().describe(`Array of input/output parameter definitions for ${type} interface`);main_obj.progDataSource=progDataSource;main_obj.progFields=progFields;main_obj.progEvents=progEvents;main_obj.progUi=progUi;break;case`get_data`:XudaComponentSchema.describe(`The Get Data Object defines a lightweight, read-only program unit designed to retrieve data from a structured source such as a table, array, or remote dataset. It is used to extract specific values, perform indexed lookups, and support transformations through reduce or conditional logic. This object is typically used when a logic program requires only data retrieval without the need to iterate or mutate records. It supports output parameter mapping and can be embedded into workflows and alerts for dynamic value extraction.`);properties_obj.frameworkProperties=z.object({}).optional().describe(`Framework-specific rendering extensions and configuration`);properties_obj.progParams=z.array(ProgParamSchema).optional().describe(`Array of input/output parameter definitions for ${type} interface`);main_obj.progDataSource=progDataSource;main_obj.progFields=progFields;main_obj.progEvents=progEvents;break;case`set_data`:XudaComponentSchema.describe(`The set_data object defines a program-level functional unit responsible for writing data to a specified table. It can be invoked from any program and is designed to handle create, update, and delete operations in a structured and reusable way. The object includes properties to determine the type of operation being performed and supports an optional flag to create a new record if one does not already exist. In addition to its core structure, the set_data object includes a parameter interface property that defines input and output parameters. This allows values to be passed into the function and returned to the calling context, enabling flexible, context-aware data handling.`);properties_obj.progParams=z.array(ProgParamSchema).optional().describe(`Array of input/output parameter definitions for ${type} interface`);properties_obj.crudMode=z.enum(["C","U","D"]).describe("Operation mode: C = Create, U = Update, D = Delete");properties_obj.crudMode=z.boolean().describe("If true, allows record creation if not found");main_obj.progDataSource=progDataSource;main_obj.progFields=progFields;main_obj.progEvents=progEvents;break;case`batch`:XudaComponentSchema.describe(`The Batch Object defines a program-level execution unit tailored for iterative, record-by-record operations across datasets. It enables controlled loops over structured data sources or arrays, making it a foundational element for multi-record processing, automation flows, and background job orchestration. The batch object can be invoked from within any Xuda logic program and serves as a reusable execution block for bulk workflows, such as saving multiple records, transforming arrays, or triggering chained program logic. It accepts dynamic input and output parameters, which allow context-aware execution and return values that can be consumed downstream.The batch unit also includes lifecycle hooks and event workflow, enabling custom logic at specific points within the loop (e.g., before/after each record or on error conditions). This supports advanced control, transformation, and external interactions during iterative processing.`);properties_obj.progParams=z.array(ProgParamSchema).optional().describe(`Array of input/output parameter definitions for ${type} interface`);main_obj.progDataSource=progDataSource;main_obj.progFields=progFields;main_obj.progEvents=progEvents;break;case`api`:XudaComponentSchema.describe(`The API Program-Level Logic Unit is a program-level logic unit represented as a structured JSON object that exposes backend functionality through internal or external interfaces. It can be invoked internally via the call_project_api method or externally through the api/mcp endpoint, enabling controlled access to application-level logic and data services. Acting as an orchestration layer, the API unit enables coordination of multiple subordinate logic units such as get_data, set_data, and batch, allowing compound workflows, transactional operations, and conditional executions to be encapsulated within a single, callable endpoint. This design abstracts complexity and promotes composability of business logic across the application. The API unit includes an interface definition for parameter binding, specifying dynamic input and output mappings. This supports stateless, context-aware executions where external values can be passed into the API call, and structured results returned to the calling layer. Response format configuration is also supported, with output types including json, text, html, and others—allowing precise control over the serialization and consumption of API responses.`);properties_obj.progParams=z.array(ProgParamSchema).optional().describe(`Array of input/output parameter definitions for ${type} interface`);const ApiOutputFormat=z.enum(["json","html","text","xml","csv","pdf"]).describe("Format of the API response: json, html, text, xml, csv, pdf, etc.");properties_obj.apiOutput=ApiOutputFormat.describe("Format of the API response: json, html, text, etc.");main_obj.progDataSource=progDataSource;main_obj.progFields=progFields;main_obj.progEvents=progEvents;main_obj.scriptData=z.object({value:z.string().describe("The return payload template as a stringified object. Placeholder bindings (e.g., @CS_Id) are replaced at runtime")});break;case`alert`:XudaComponentSchema.describe(`The Alert Object is a program-level UI unit in the Xuda platform used to deliver contextual messages and notifications to users or developers at runtime. These alerts can be triggered from within logic flows and offer various display formats (such as toast, modal, browser alert, or console message) based on the use case. The alert object is defined using a structured JSON format and can be embedded in broader program logic. It supports both static and dynamic content, and can optionally create log entries to support audit trails and debugging workflows.`);properties_obj.progParams=z.array(ProgParamSchema).optional().describe(`Array of input/output parameter definitions for ${type} interface`);main_obj.alertData=z.object({alertDisplay:AlertDisplay.describe('Mode of display: "toast", "modal", "browser", or "console"'),alertType:AlertType.describe('Type of message: "warning", "error", "info", or "success"'),alertTitle:z.string().describe("Main content of the alert shown to the user"),alertTitleFx:z.string().optional().describe("Optional dynamic override (e.g., @msg_v) for alert content"),createLog:z.boolean().describe("Whether to generate a system log entry associated with the alert")});break;case`javascript`:XudaComponentSchema.describe(`The javascript object is a functional unit designed to execute JavaScript code within the application context. It can be called from any program using methods such as call_native_javascript, call_evaluate_javascript, execute_native_javascript, or execute_evaluate_javascript. This object includes the following key property: Script – Contains the JavaScript code to be executed, along with any declared dependencies required for execution. The javascript object is ideal for performing advanced logic, custom client-side behavior, or dynamic scripting that extends the capabilities of low-code flows. Xuda also exposes a set of built-in API methods that can be easily called from JavaScript units. These include actions like reading from or writing to Drive, interacting with the Studio API, or performing database operations such as create, update, and delete. These ready-to-use APIs simplify common tasks and allow you to focus on building functionality instead of writing boilerplate code. By centralizing script execution in a modular and reusable way, the JavaScript unit enhances flexibility, promotes clean architecture, and empowers developers to go beyond standard configuration with native scripting power.`);properties_obj.progParams=z.array(ProgParamSchema).optional().describe(`Array of input/output parameter definitions for ${type} interface`);main_obj.scriptData=z.object({value:z.string().describe("JavaScript code to be executed"),dependencies:z.record(z.string()).optional().describe("Optional. Key-value map of external packages required")});break;default:break}return XudaComponentSchema};
|
|
50
|
+
Example: xu-viewport="@mobile_view"`);const UiElementSchema=z.lazy(()=>z.object({id:z.union([z.literal(`root`),UuidSchema,z.string().regex(/^node-[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i),z.string().regex(/^ui-[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i)]).describe(`Element identifier: "root" for top-level, prefixed UUIDs like "ui-791ca98a-e284-4413-af0a-96e5527c338b"`),type:z.literal(`element`).describe(`Element type - only "element" allowed (no "comment" or "text" types)`),tagName:z.string().describe(`HTML tag name for the element (e.g., "div", "span", "input")`),attributes:UiAttributesSchema.optional().describe(`HTML attributes and Xuda directives (e.g., class, xu-bind, xu-on)`),content:z.string().optional().describe(`Text content for the element (replaces deprecated "text" type)`),text:z.string().optional().describe(`Alternative text property for element content`),children:z.array(UiElementSchema).optional().describe(`Array of child elements nested within this element`),workflow:z.array(WorkflowActionSchema).optional().describe(`Workflow actions associated with this UI element`),path:z.array(z.number()).optional().describe("Array representing the element`s position in the UI tree"),code:z.string().optional().describe(`Generated HTML code representation`),editCode:z.boolean().optional().describe(`Flag indicating if element is in code editing mode`),$folded:z.boolean().optional().describe(`UI editor state - whether element tree is collapsed`)}).describe(`UI element following Himalaya.js structure with Xuda extensions, 1. generate unique id using UUID for every item of the progUi (except the root node, leave the root node as is),2. never use "comment" or "text" type, 3. convert "text" type to "element" and add a text property instead next to the type property `));const DataSourceSchema=z.object({dataSourceType:z.union([z.literal(`table`).describe(`Connect to structured table from global Table Repository`),z.literal(`array`).describe(`Use static or dynamically populated array`),z.literal(`json`).describe(`Load structured data in JSON format`),z.literal(`csv`).describe(`Load data from CSV source`),z.literal(`none`).describe(`No data source attached - self-contained logic unit`),z.literal(``).describe(`Empty string indicating no datasource configured`)]).optional().describe(`Type of data source defining how data is retrieved and processed`),dataSourceFilterModelType:z.union([z.literal(`index`).describe(`Use predefined index with from/to values for fast range filtering`),z.literal(`query`).describe(`Use jQuery Mongo syntax for advanced conditional filters and logical rules`)]).optional().describe(`Filtering approach for table sources`),dataSourceSort:z.union([z.literal(`asc`),z.literal(`desc`)]).optional().describe(`Global sort direction for retrieved data`),dataSourceTableId:z.string().optional().describe(`Reference to table ID in Table Repository when dataSourceType is "table"`),dataSourceIndexId:z.string().optional().describe(`Default index ID used for efficient data lookup and filtering`),dataSourceIndexesObj:z.record(z.record(z.object({from:z.string().describe(`Starting value for index range (can be dynamic expression like @uid_in)`),locate_from:z.string().optional().describe(`Additional locate parameter for range start`),locate_to:z.string().optional().describe(`Additional locate parameter for range end`),to:z.string().describe(`Ending value for index range (can be dynamic expression)`),key:z.string().describe(`Field name being indexed and filtered`)}).describe(`Index field configuration with range values`))).optional().describe(`Index configurations mapped by index ID, defining field ranges and conditions for efficient filtering`),dataSourceReduce:z.boolean().optional().describe(`Whether to reduce results to single aggregated value (count, sum, avg) - requires DBS plugin`),filterModelMongo:z.object({}).optional().describe(`Static MongoDB-style filter query object built using jQuery QueryBuilder`),filterModelMongoFx:z.string().optional().describe(`Dynamic reference to input field containing filter query object (overrides filterModelMongo)`),sortModel:z.array(z.object({field_id:z.string().describe(`Field identifier to sort by`),sort_dir:z.union([z.literal(`asc`),z.literal(`desc`)]).describe(`Sort direction for this specific field`)})).optional().describe(`Array of field-level sorting rules for multi-column sorting`),dataSourceRealtime:z.boolean().optional().describe(`Enable real-time updates when source data changes (table sources only, requires @xuda.io/xuds-dbs-plugin-xuda)`),datafieldsOutputField:z.string().optional().describe(`Field name where raw query results will be stored within parent hierarchy`),dataSourceLimit:z.number().optional().describe(`Maximum number of rows or iterations to return for pagination`),dataSourceSkip:z.number().optional().describe(`Number of rows to skip before returning results, useful for pagination offset`),dataSourceUrl:z.string().optional().describe(`External URL endpoint for loading array/CSV/JSON data from REST APIs or static files`),dataSourceInputField:z.string().optional().describe(`Dynamic field reference in UI or app context for data source values (alternative to external URL)`)}).describe(`Comprehensive data source configuration defining how logic units retrieve, filter, and process data from tables, arrays, APIs, or external sources`);let properties_obj={menuType:z.literal(type).describe(`defines the object category`),menuName:z.string().describe(`Internal name displayed in the Studio interface`)};let properties=z.object(properties_obj).describe(`Core ${type} properties defining behavior, access, and UI framework settings`);const progFields=z.array(ProgFieldSchema).describe(`Defines the internal working fields of the ${type}. These include real and virtual fields used for data binding, user interaction, intermediate logic, and expression evaluation.`);const progEvents=z.array(ProgEventSchema).optional().describe(`Defines all functional logic associated with the ${type}. Events support lifecycle hooks (like on_load, screen_ready, client_interval), event-based workflow, custom utility functions, and conditional logic.`);const progUi=z.array(UiElementSchema).describe(`Describes the rendered interface in a structured JSON format, derived from Himalaya.js (HTML-to-JSON). Each node can be bound to logic via attributes such as xu-exp, bind, for, and trigger. This enables conditional rendering, looping constructs, inline script execution, and seamless integration with workflow.`);const progDataSource=DataSourceSchema.describe(`Defines where the ${type} pulls or binds its data from, such as a database table, external service, or static source.`);let main_obj={_id:z.string().regex(/^[a-zA-Z0-9_]+$/).describe(`Unique ${type} identifier with format constraints`),app_id:z.string().describe(`Reference to the parent application this ${type} belongs to`),stat:z.union([z.literal(1),z.literal(2),z.literal(3),z.literal(4)]).describe(`Document status: 1=draft, 2=review, 3=active, 4=archived`),docType:z.literal(`studio`).describe(`Always "studio" - indicates this is a Studio-authored ${type}`),docDate:TimestampSchema.describe(`Unix timestamp when the ${type} document was created`),ts:TimestampSchema.describe(`Unix timestamp of the most recent modification`),order_ts:TimestampSchema.describe(`Timestamp used for ordering components in the Studio interface`),description:z.string().optional().describe(`Describe in short the ${type}`),studio_meta:StudioMetaSchema};let XudaComponentSchema=z.object(main_obj);main_obj.properties=properties;switch(type){case`globals`:XudaComponentSchema.describe(`The globals object in the Xuda platform defines a universal logic layer shared across all programs, components, and workflows. It provides a centralized and consistent structure for declaring global fields, utility functions, and event-driven logic, ensuring logic reusability and reducing redundancy across the application.`);main_obj.progFields=progFields;main_obj.progEvents=progEvents;break;case`table`:XudaComponentSchema.describe(`The Table Object represents a data entity and serves as the structural definition for interacting with external databases. It supports integration via pluggable connectors, allowing seamless connection to various database engines such as MySQL, CouchDB, and others (see available database plugins for the full list).`);properties_obj.databaseSocket=z.string().default("@xuda.io/xuda-dbs-plugin-xuda").describe("Database driver to use for the table");const XudaFieldType=z.enum(["string","number","boolean","array","object","date"]).describe("Data type for table fields");const IndexDataSchema=z.object({name:z.string().describe("Name of the index"),unique:z.boolean().describe("If true, ensures no duplicates for indexed fields"),keys:z.array(z.string()).describe("List of field names used in this index")});const TableIndexSchema=z.object({id:z.string().uuid().describe("Unique uuid identifier for the index"),data:IndexDataSchema.describe("Contains keys, uniqueness setting, and index name")});const FieldPropsSchema=z.object({fieldType:XudaFieldType.describe('Data type: "string", "number", "boolean", "array", "object", or "date"')});const FieldDataSchema=z.object({field_id:z.string().describe("Field identifier used in logic or database operations")});const TableFieldSchema=z.object({id:z.string().uuid().describe("Unique uuid of the field object"),data:FieldDataSchema.describe("Contains the logical field ID"),props:FieldPropsSchema.describe("Properties of the field including data type")});main_obj.tableIndexes=z.array(TableIndexSchema).describe("Defines indexing rules for efficient lookups and uniqueness constraints");main_obj.tableFields=z.array(TableFieldSchema).describe("Defines each field used in the table and its data type");break;case`folder`:XudaComponentSchema.describe(`The Folder is a non-executable, project-level container represented as a structured JSON object. It is used to define a hierarchical structure for organizing application assets within the Xuda environment. Although it does not execute any logic at runtime, the folder object plays an essential role in shaping the overall architecture of a project by logically grouping related objects such as components, APIs, tables, datasets, and other program entities.`);break;case`component`:XudaComponentSchema.describe(`The component object in the Xuda platform defines a modular, self-contained program unit that encapsulates both front-end presentation and back-end logic. It serves as a reusable UI component that supports a full execution lifecycle, making it ideal for constructing low-code applications that are maintainable, scalable, and highly interactive. A component is engineered to allow seamless integration of logic, data, and rendering, enabling developers to build sophisticated interactive views without redundant code. Each component instance supports input/output parameters, can communicate with other components or programs, and can be dynamically rendered as a page, modal, or embedded panel.`);properties_obj.frameworkProperties=z.object({}).optional().describe(`Framework-specific rendering extensions and configuration`);properties_obj.renderType=z.string().describe(`Component layout type (e.g., "form", "grid", "list")`);properties_obj.rwMode=z.union([z.literal(`R`),z.literal(`W`),z.literal(`RW`)]).describe(`Access mode: R=read-only, W=write-only, RW=read-write`);properties_obj.uiFramework=z.string().describe(`Selected UI framework plugin (e.g., @xuda.io/xuda-framework-plugin-tailwind)`);properties_obj.menuTitle=z.string().optional().describe(`Display title for Studio UI or routing usage`);properties_obj.progParams=z.array(ProgParamSchema).optional().describe(`Array of input/output parameter definitions for ${type} interface`);main_obj.progDataSource=progDataSource;main_obj.progFields=progFields;main_obj.progEvents=progEvents;main_obj.progUi=progUi;break;case`get_data`:XudaComponentSchema.describe(`The Get Data Object defines a lightweight, read-only program unit designed to retrieve data from a structured source such as a table, array, or remote dataset. It is used to extract specific values, perform indexed lookups, and support transformations through reduce or conditional logic. This object is typically used when a logic program requires only data retrieval without the need to iterate or mutate records. It supports output parameter mapping and can be embedded into workflows and alerts for dynamic value extraction.`);properties_obj.frameworkProperties=z.object({}).optional().describe(`Framework-specific rendering extensions and configuration`);properties_obj.progParams=z.array(ProgParamSchema).optional().describe(`Array of input/output parameter definitions for ${type} interface`);main_obj.progDataSource=progDataSource;main_obj.progFields=progFields;main_obj.progEvents=progEvents;break;case`set_data`:XudaComponentSchema.describe(`The set_data object defines a program-level functional unit responsible for writing data to a specified table. It can be invoked from any program and is designed to handle create, update, and delete operations in a structured and reusable way. The object includes properties to determine the type of operation being performed and supports an optional flag to create a new record if one does not already exist. In addition to its core structure, the set_data object includes a parameter interface property that defines input and output parameters. This allows values to be passed into the function and returned to the calling context, enabling flexible, context-aware data handling.`);properties_obj.progParams=z.array(ProgParamSchema).optional().describe(`Array of input/output parameter definitions for ${type} interface`);properties_obj.crudMode=z.enum(["C","U","D"]).describe("Operation mode: C = Create, U = Update, D = Delete");properties_obj.crudMode=z.boolean().describe("If true, allows record creation if not found");main_obj.progDataSource=progDataSource;main_obj.progFields=progFields;main_obj.progEvents=progEvents;break;case`batch`:XudaComponentSchema.describe(`The Batch Object defines a program-level execution unit tailored for iterative, record-by-record operations across datasets. It enables controlled loops over structured data sources or arrays, making it a foundational element for multi-record processing, automation flows, and background job orchestration. The batch object can be invoked from within any Xuda logic program and serves as a reusable execution block for bulk workflows, such as saving multiple records, transforming arrays, or triggering chained program logic. It accepts dynamic input and output parameters, which allow context-aware execution and return values that can be consumed downstream.The batch unit also includes lifecycle hooks and event workflow, enabling custom logic at specific points within the loop (e.g., before/after each record or on error conditions). This supports advanced control, transformation, and external interactions during iterative processing.`);properties_obj.progParams=z.array(ProgParamSchema).optional().describe(`Array of input/output parameter definitions for ${type} interface`);main_obj.progDataSource=progDataSource;main_obj.progFields=progFields;main_obj.progEvents=progEvents;break;case`api`:XudaComponentSchema.describe(`The API Program-Level Logic Unit is a program-level logic unit represented as a structured JSON object that exposes backend functionality through internal or external interfaces. It can be invoked internally via the call_project_api method or externally through the api/mcp endpoint, enabling controlled access to application-level logic and data services. Acting as an orchestration layer, the API unit enables coordination of multiple subordinate logic units such as get_data, set_data, and batch, allowing compound workflows, transactional operations, and conditional executions to be encapsulated within a single, callable endpoint. This design abstracts complexity and promotes composability of business logic across the application. The API unit includes an interface definition for parameter binding, specifying dynamic input and output mappings. This supports stateless, context-aware executions where external values can be passed into the API call, and structured results returned to the calling layer. Response format configuration is also supported, with output types including json, text, html, and others—allowing precise control over the serialization and consumption of API responses.`);properties_obj.progParams=z.array(ProgParamSchema).optional().describe(`Array of input/output parameter definitions for ${type} interface`);const ApiOutputFormat=z.enum(["json","html","text","xml","csv","pdf"]).describe("Format of the API response: json, html, text, xml, csv, pdf, etc.");properties_obj.apiOutput=ApiOutputFormat.describe("Format of the API response: json, html, text, etc.");main_obj.progDataSource=progDataSource;main_obj.progFields=progFields;main_obj.progEvents=progEvents;main_obj.scriptData=z.object({value:z.string().describe("The return payload template as a stringified object. Placeholder bindings (e.g., @CS_Id) are replaced at runtime")});break;case`alert`:XudaComponentSchema.describe(`The Alert Object is a program-level UI unit in the Xuda platform used to deliver contextual messages and notifications to users or developers at runtime. These alerts can be triggered from within logic flows and offer various display formats (such as toast, modal, browser alert, or console message) based on the use case. The alert object is defined using a structured JSON format and can be embedded in broader program logic. It supports both static and dynamic content, and can optionally create log entries to support audit trails and debugging workflows.`);properties_obj.progParams=z.array(ProgParamSchema).optional().describe(`Array of input/output parameter definitions for ${type} interface`);main_obj.alertData=z.object({alertDisplay:AlertDisplay.describe('Mode of display: "toast", "modal", "browser", or "console"'),alertType:AlertType.describe('Type of message: "warning", "error", "info", or "success"'),alertTitle:z.string().describe("Main content of the alert shown to the user"),alertTitleFx:z.string().optional().describe("Optional dynamic override (e.g., @msg_v) for alert content"),createLog:z.boolean().describe("Whether to generate a system log entry associated with the alert")});break;case`javascript`:XudaComponentSchema.describe(`The javascript object is a functional unit designed to execute JavaScript code within the application context. It can be called from any program using methods such as call_native_javascript, call_evaluate_javascript, execute_native_javascript, or execute_evaluate_javascript. This object includes the following key property: Script – Contains the JavaScript code to be executed, along with any declared dependencies required for execution. The javascript object is ideal for performing advanced logic, custom client-side behavior, or dynamic scripting that extends the capabilities of low-code flows. Xuda also exposes a set of built-in API methods that can be easily called from JavaScript units. These include actions like reading from or writing to Drive, interacting with the Studio API, or performing database operations such as create, update, and delete. These ready-to-use APIs simplify common tasks and allow you to focus on building functionality instead of writing boilerplate code. By centralizing script execution in a modular and reusable way, the JavaScript unit enhances flexibility, promotes clean architecture, and empowers developers to go beyond standard configuration with native scripting power.`);properties_obj.progParams=z.array(ProgParamSchema).optional().describe(`Array of input/output parameter definitions for ${type} interface`);main_obj.scriptData=z.object({value:z.string().describe("JavaScript code to be executed"),dependencies:z.record(z.string()).optional().describe("Optional. Key-value map of external packages required")});break;default:break}return XudaComponentSchema};
|
|
@@ -3771,7 +3771,7 @@ export const get_zod_schema = function (type) {
|
|
|
3771
3771
|
});
|
|
3772
3772
|
|
|
3773
3773
|
const TableIndexSchema = z.object({
|
|
3774
|
-
id: z.string().describe('Unique identifier for the index'),
|
|
3774
|
+
id: z.string().uuid().describe('Unique uuid identifier for the index'),
|
|
3775
3775
|
data: IndexDataSchema.describe('Contains keys, uniqueness setting, and index name'),
|
|
3776
3776
|
});
|
|
3777
3777
|
|
|
@@ -3782,7 +3782,7 @@ export const get_zod_schema = function (type) {
|
|
|
3782
3782
|
field_id: z.string().describe('Field identifier used in logic or database operations'),
|
|
3783
3783
|
});
|
|
3784
3784
|
const TableFieldSchema = z.object({
|
|
3785
|
-
id: z.string().describe('Unique
|
|
3785
|
+
id: z.string().uuid().describe('Unique uuid of the field object'),
|
|
3786
3786
|
data: FieldDataSchema.describe('Contains the logical field ID'),
|
|
3787
3787
|
props: FieldPropsSchema.describe('Properties of the field including data type'),
|
|
3788
3788
|
});
|
|
@@ -24679,6 +24679,7 @@ var SUPPORT_PEER_CONN = null;
|
|
|
24679
24679
|
var STUDIO_PEER_CONN_MSG_QUEUE = [];
|
|
24680
24680
|
|
|
24681
24681
|
var CLIENT_ACTIVITY_TS;
|
|
24682
|
+
var IS_ONLINE;
|
|
24682
24683
|
|
|
24683
24684
|
glb.REFERENCE_LESS_FUNCTIONS = ['update', 'raise_event', 'call_library', 'invoke_action', 'loader_on', 'loader_off', 'emit_event', 'delay', 'execute_evaluate_javascript', 'execute_native_javascript'];
|
|
24684
24685
|
|
|
@@ -38536,7 +38537,7 @@ func.UI.main.embed_loader = async function (SESSION_ID) {
|
|
|
38536
38537
|
async function updateOnlineStatus() {
|
|
38537
38538
|
if (!_session?.DS_GLB?.[0]) return;
|
|
38538
38539
|
var data = {};
|
|
38539
|
-
if (
|
|
38540
|
+
if (IS_ONLINE) {
|
|
38540
38541
|
data.SYS_GLOBAL_BOL_ONLINE = 1;
|
|
38541
38542
|
} else {
|
|
38542
38543
|
data.SYS_GLOBAL_BOL_ONLINE = 0;
|
|
@@ -39149,7 +39150,7 @@ function xuda(...args) {
|
|
|
39149
39150
|
};
|
|
39150
39151
|
|
|
39151
39152
|
print_xuda_banner();
|
|
39152
|
-
|
|
39153
|
+
await func.index.checkConnectivity();
|
|
39153
39154
|
var SESSION_ID = Date.now();
|
|
39154
39155
|
var components;
|
|
39155
39156
|
if (typeof glb.SLIM_BUNDLE === 'undefined' || !glb.SLIM_BUNDLE) {
|
|
@@ -39630,6 +39631,28 @@ func.index.init_document_listeners = function () {
|
|
|
39630
39631
|
|
|
39631
39632
|
glb.WINDOW_LOCATION_SEARCH = window.location.search;
|
|
39632
39633
|
};
|
|
39634
|
+
func.index.checkConnectivity = async function () {
|
|
39635
|
+
const endpoints = ['https://www.cloudflare.com/favicon.ico', 'https://xuda.io/favicon.ico'];
|
|
39636
|
+
|
|
39637
|
+
const promises = endpoints.map((url) =>
|
|
39638
|
+
fetch(url, { method: 'HEAD', mode: 'no-cors' })
|
|
39639
|
+
.then(() => true)
|
|
39640
|
+
.catch(() => false),
|
|
39641
|
+
);
|
|
39642
|
+
|
|
39643
|
+
const results = await Promise.all(promises);
|
|
39644
|
+
IS_ONLINE = results.some((result) => result === true);
|
|
39645
|
+
|
|
39646
|
+
// Add event listeners for online/offline events
|
|
39647
|
+
window.addEventListener('online', function () {
|
|
39648
|
+
$('body').trigger('set_db_replication_from_server');
|
|
39649
|
+
IS_ONLINE = true;
|
|
39650
|
+
});
|
|
39651
|
+
|
|
39652
|
+
window.addEventListener('offline', function () {
|
|
39653
|
+
IS_ONLINE = false;
|
|
39654
|
+
});
|
|
39655
|
+
};
|
|
39633
39656
|
|
|
39634
39657
|
func.index.init_service_workers = function () {
|
|
39635
39658
|
if ('serviceWorker' in navigator) {
|