@xuda.io/runtime-bundle
Version:
The Xuda Runtime Bundle refers to a collection of scripts and libraries packaged together to provide the necessary runtime environment for executing plugins or components in the Xuda platform.
8 lines (7 loc) • 9.05 kB
JavaScript
export const run_javascript=async function(SESSION_ID,jobNoP,dsSession,script,evaluate,prog_id,params,evt,$container){const _session=SESSION_OBJ[SESSION_ID];const should_delete_job_after_script=function(source){return!String(source||"").includes("func.api.callback")};const get_script_base_url=function(){return`https://${_session.domain}/studio-drive/${APP_OBJ[_session.app_id].app_replicate||_session.app_id}/scripts/${prog_id}/`};const get_browser_api_utils=async function(){return await func.common.get_module(SESSION_ID,"xuda-api-library.mjs",{func:func,glb:glb,SESSION_OBJ:SESSION_OBJ,SESSION_ID:SESSION_ID,APP_OBJ:APP_OBJ,dsSession:dsSession,jobNoP:jobNoP})};const normalize_rows_array=function(rows,source){if(!Array.isArray(rows)){return rows}Object.defineProperties(rows,{rows:{value:rows,enumerable:false,configurable:true},code:{value:source?.code,enumerable:false,configurable:true},data:{value:source?.data,enumerable:false,configurable:true},total_rows:{value:source?.data?.total_rows??source?.total_rows??rows.length,enumerable:false,configurable:true},response:{value:source,enumerable:false,configurable:true}});return rows};const normalize_db_rows_value=function(value){if(Array.isArray(value)){return normalize_rows_array(value,value.response||value)}if(!value||typeof value!=="object"){return value}if(Array.isArray(value?.data?.rows)){return normalize_rows_array(value.data.rows,value)}if(Array.isArray(value?.rows)){return normalize_rows_array(value.rows,value)}return value};const normalize_javascript_params=function(value){const normalized_value=normalize_db_rows_value(value);if(normalized_value!==value){return normalized_value}if(!value||typeof value!=="object"||Array.isArray(value)){return value||{}}const params_obj={...value};for(const[key,val]of Object.entries(params_obj)){params_obj[key]=normalize_db_rows_value(val)}const keys=Object.keys(params_obj);if(keys.length===1&&keys[0]==="rows"&&Array.isArray(params_obj.rows)){return params_obj.rows}return params_obj};const script_params=normalize_javascript_params(params);const get_static_imports=function(source){return Array.from(String(source||"").matchAll(/(^|\n)([ \t]*import\s+(?:(?:[\s\S]*?)\s+from\s+)?['"][^'"]+['"]\s*(?:(?:assert|with)\s*\{[\s\S]*?\})?\s*;?)[ \t]*(?=\n|$)/g))};const has_module_syntax=function(source){return/^\s*(import|export)\s/m.test(source||"")};const rewrite_import_specifier=function(import_source){const base_url=get_script_base_url();const to_runtime_url=function(specifier){if(/^[a-z][a-z0-9+.-]*:/i.test(specifier))return specifier;if(specifier.startsWith(".")||specifier.startsWith("/"))return new URL(specifier,base_url).href;return specifier};return import_source.replace(/(\bfrom\s*)(['"])([^'"]+)\2/,function(_,prefix,quote,specifier){return`${prefix}${quote}${to_runtime_url(specifier)}${quote}`}).replace(/^(\s*import\s*)(['"])([^'"]+)\2/,function(_,prefix,quote,specifier){return`${prefix}${quote}${to_runtime_url(specifier)}${quote}`})};const build_source_module=function(source){const imports=[];const source_without_imports=source.replace(/(^|\n)([ \t]*import\s+(?:(?:[\s\S]*?)\s+from\s+)?['"][^'"]+['"]\s*(?:(?:assert|with)\s*\{[\s\S]*?\})?\s*;?)[ \t]*(?=\n|$)/g,function(match,prefix,import_source){imports.push(rewrite_import_specifier(import_source));return prefix});if(/^\s*export\s/m.test(source_without_imports)){return`${imports.join("\n")}
${source_without_imports}`}return`${imports.join("\n")}
export default async function(params, xu, SESSION_ID, SESSION_OBJ, jobNoP, $container, func, glb, APP_OBJ, evt) {
${source_without_imports}
}`};const create_module_url=function(source){if(typeof window!=="undefined"&&typeof Blob!=="undefined"&&typeof URL!=="undefined"&&typeof URL.createObjectURL==="function"){const url=URL.createObjectURL(new Blob([source],{type:"text/javascript"}));return{url:url,revoke:function(){URL.revokeObjectURL(url)}}}return{url:`data:text/javascript;charset=utf-8,${encodeURIComponent(source)}`,revoke:function(){}}};const run_source_javascript_module_in_browser=async function(source,xu){const module_source=build_source_module(source);const module_url=create_module_url(`${module_source}\n//# sourceURL=xuda-source-program-${prog_id||"inline"}.mjs`);try{const source_module=await import(module_url.url);const code=func.utils.replace_studio_drive_url(SESSION_ID,source_module.default);if(typeof code==="function"){return await code(script_params,xu,SESSION_ID,SESSION_OBJ,jobNoP,$container,func,glb,APP_OBJ,evt)}return code}finally{module_url.revoke()}};const run_source_javascript_program_in_browser=async function(import_error){if(!script){throw import_error}if(import_error){await func.utils.report_issue(SESSION_ID,{code:"RUN_MSG_JS_010",source:"run_javascript",message:"Compiled JavaScript module unavailable, running source script",type:"W",err:import_error,details:{prog_id:prog_id}})}const source=func.utils.replace_studio_drive_url(SESSION_ID,script);const xu=await get_browser_api_utils();let ret;if(has_module_syntax(source)||get_static_imports(source).length){ret=await run_source_javascript_module_in_browser(source,xu)}else{const AsyncFunction=Object.getPrototypeOf(async function(){}).constructor;const runner=new AsyncFunction("params","xu","SESSION_ID","SESSION_OBJ","jobNoP","$container","func","glb","APP_OBJ","evt",source);ret=await runner(script_params,xu,SESSION_ID,SESSION_OBJ,jobNoP,$container,func,glb,APP_OBJ,evt)}if(should_delete_job_after_script(source)){func.events.delete_job(SESSION_ID,jobNoP)}return ret};const run_native_javascript_program_in_browser=async function(){const path_to_dist=`${get_script_base_url()}dist/`;const native_script_cache_bust=_session.opt?.app_build_id||_session.opt?.last_changed_ts||"dev";const with_native_cache_bust=url=>`${url}${url.includes("?")?"&":"?"}xu_native_ts=${native_script_cache_bust}`;let index_mjs;try{const native_script_url=with_native_cache_bust(`${path_to_dist}index.mjs`);index_mjs=await import(native_script_url)}catch(import_error){return await run_source_javascript_program_in_browser(import_error)}if(index_mjs.css){const css_url=`${path_to_dist}index.css`;func.utils.load_css_on_demand(css_url)}const code=func.utils.replace_studio_drive_url(SESSION_ID,index_mjs.default);const xu=await get_browser_api_utils();const ret=await code(script_params,xu,SESSION_ID,SESSION_OBJ,jobNoP,$container);if(should_delete_job_after_script(code)){func.events.delete_job(SESSION_ID,jobNoP)}return ret};const run_native_javascript_program_in_server=async function(){return new Promise(async(resolve,reject)=>{const studio_drive_script_folder=path.join(_conf.studio_drive_path,app_id,"scripts");const studio_drive_script_program_folder=path.join(studio_drive_script_folder,prog_id);const dist=path.join(studio_drive_script_program_folder,"dist");const index_mjs=path.join(dist,"index.mjs");process.on("uncaughtException",err=>{console.error("Asynchronous error caught.",err)});const resolve_local=function(e){if(should_delete_job_after_script(script)){func.events.delete_job(SESSION_ID,jobNoP)}resolve(e)};const reject_local=function(e){func.events.delete_job(SESSION_ID,jobNoP);reject(e)};try{const script=new VMScript(`
const index_mjs = await import(${index_mjs});
try{index_mjs.default(req,params,setup_doc,resolve,reject);}catch(e){ console.error(e); }`,{filename:dist,dirname:dist});let vm=new NodeVM({require:{external:true},sandbox:{resolve:resolve_local,reject:reject_local},timeout:6e4});return await vm.run(script,{filename:dist,dirname:dist})}catch(err){console.error("Failed to execute script.",err)}})};if(evaluate){var script_ret=(await func.expression.get(SESSION_ID,script,dsSession,"javascript",null,null,null,null,null,null,null,()=>{},jobNoP)).result}else{if(prog_id){if(typeof IS_API_SERVER!=="undefined"||typeof IS_DOCKER!=="undefined"||typeof IS_PROCESS_SERVER!=="undefined"){return await run_native_javascript_program_in_server()}else{return await run_native_javascript_program_in_browser()}}else{await func.expression.secure_eval(SESSION_ID,"javascript",func.utils.replace_studio_drive_url(SESSION_ID,script),jobNoP,dsSession,()=>{},evt)}}if(should_delete_job_after_script(script)){func.events.delete_job(SESSION_ID,jobNoP);return}};export const call_javascript=async function(SESSION_ID,jobNoP,refIdP,dsSession,evaluate,$container){const error_log=async function(msg){let _session=SESSION_OBJ[SESSION_ID];func.events.delete_job(SESSION_ID,jobNoP);if(typeof IS_API_SERVER!=="undefined"){return __.rpi.write_log(_session.app_id,"error","api",msg)}if(typeof IS_DOCKER!=="undefined"){return __.rpi.write_log(_session.app_id,"error","worker",msg)}await func.common.db(SESSION_ID,"write_log",{msg:msg,log_type:"error",source:"runtime"})};let view_ret=await func.utils.VIEWS_OBJ.get(SESSION_ID,refIdP.prog);if(!view_ret){return error_log("program not found")}if(!view_ret?.scriptData?.value){return error_log("script is empty")}return await run_javascript(SESSION_ID,jobNoP,dsSession,view_ret.scriptData.value,evaluate,refIdP.prog,refIdP?.parameters,null,$container)};