@xuda.io/runtime-bundle 1.0.489 → 1.0.491

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.
@@ -10474,7 +10474,7 @@ func.events.invoke = async function (event_id) {
10474
10474
  };
10475
10475
  func.expression = {};
10476
10476
 
10477
- func.expression.get = async function (SESSION_ID, valP, dsSessionP, sourceP, rowIdP, sourceActionP, secondPassP, calling_fieldIdP, fieldsP, debug_infoP, iterate_info, js_script_callback, jobNo, api_output_type) {
10477
+ func.expression.get_org = async function (SESSION_ID, valP, dsSessionP, sourceP, rowIdP, sourceActionP, secondPassP, calling_fieldIdP, fieldsP, debug_infoP, iterate_info, js_script_callback, jobNo, api_output_type) {
10478
10478
  class xu_class {
10479
10479
  async get() {
10480
10480
  var ret;
@@ -10594,7 +10594,7 @@ func.expression.get = async function (SESSION_ID, valP, dsSessionP, sourceP, row
10594
10594
  // var split = [];
10595
10595
  var var_Arr = [];
10596
10596
  const split = func.expression.parse(ret) || [];
10597
- console.log(valP, split);
10597
+ // console.log(valP, split);
10598
10598
  for await (const [arr_key, val] of Object.entries(split)) {
10599
10599
  // run each field
10600
10600
  const key = Number(arr_key);
@@ -10828,6 +10828,177 @@ func.expression.get = async function (SESSION_ID, valP, dsSessionP, sourceP, row
10828
10828
  return new_class.get();
10829
10829
  };
10830
10830
 
10831
+ func.expression.get = async function (SESSION_ID, valP, dsSessionP, sourceP, rowIdP, sourceActionP, secondPassP, calling_fieldIdP, fieldsP = {}, debug_infoP, iterate_info, js_script_callback, jobNo, api_output_type) {
10832
+ const evalJson = (text) => eval(`(${text})`);
10833
+ const replaceQuotes = (str) => {
10834
+ for (const [key, val] of Object.entries(fields)) {
10835
+ if (typeof val === 'string') str = str.replace(`"${val}"`, val.replace(/"/g, ''));
10836
+ }
10837
+ return str;
10838
+ };
10839
+
10840
+ let ret, error, warning, var_error_found;
10841
+ const fields = { ...fieldsP };
10842
+
10843
+ // Initial value processing
10844
+ if (valP === null || typeof valP === 'undefined') ret = '';
10845
+ else if (typeof valP === 'boolean') ret = valP ? 'Y' : 'N';
10846
+ else ret = valP.toString();
10847
+
10848
+ ret = ret.replace(/\&/g, '&');
10849
+ ret = func.utils.replace_studio_drive_url(SESSION_ID, ret);
10850
+
10851
+ // End results helper
10852
+ const endResults = () => {
10853
+ if (['update', 'javascript'].includes(sourceP) && typeof ret === 'string') {
10854
+ ret = replaceQuotes(ret);
10855
+ }
10856
+ if ((error || warning) && SESSION_OBJ[SESSION_ID]?.DS_GLB[dsSessionP]) {
10857
+ func.utils.debug.log(SESSION_ID, SESSION_OBJ[SESSION_ID].DS_GLB[dsSessionP].nodeId, {
10858
+ module: 'expression',
10859
+ action: sourceP,
10860
+ source: calling_fieldIdP,
10861
+ prop: ret,
10862
+ details: ret,
10863
+ result: ret,
10864
+ error,
10865
+ warning,
10866
+ fields: null,
10867
+ type: 'exp',
10868
+ prog_id: SESSION_OBJ[SESSION_ID].DS_GLB[dsSessionP].prog_id,
10869
+ debug_info: debug_infoP,
10870
+ });
10871
+ }
10872
+ return { result: ret, fields, error, warning, req: valP, var_error_found };
10873
+ };
10874
+
10875
+ // Handle non-variable cases
10876
+ const handleNonVariable = async () => {
10877
+ try {
10878
+ if (sourceP !== 'arguments') {
10879
+ if (ret.startsWith('_DATE_')) ret = ret.slice(6);
10880
+ else if (/^\d{4}-\d{2}-\d{2}$/.test(ret) || ret === 'self') return endResults();
10881
+ else ret = await func.expression.secure_eval(SESSION_ID, sourceP, ret, jobNo, dsSessionP, js_script_callback);
10882
+ } else {
10883
+ ret = ret.replace(/_NULL/gi, '');
10884
+ }
10885
+ return endResults();
10886
+ } catch (err) {
10887
+ error = err.message;
10888
+ return endResults();
10889
+ }
10890
+ };
10891
+
10892
+ // Early return for simple cases
10893
+ if (!func.expression.validate_variables(valP)) return await handleNonVariable();
10894
+ if (glb.emailRegex.test(await func.expression.secure_eval(SESSION_ID, sourceP, valP, jobNo, dsSessionP, js_script_callback))) {
10895
+ return await handleNonVariable();
10896
+ }
10897
+
10898
+ // Parse and process variables
10899
+ const split = func.expression.parse(ret) || [];
10900
+ const var_Arr = await Promise.all(
10901
+ split.map(async (val, key) => {
10902
+ const result = { value: val.value, fieldId: val.fieldId };
10903
+
10904
+ if (!val.fieldId) return result;
10905
+
10906
+ // Handle _THIS substitution
10907
+ if (val.fieldId.startsWith('_THIS') && calling_fieldIdP) {
10908
+ result.fieldId = val.fieldId.length === 5 ? calling_fieldIdP : calling_fieldIdP + val.fieldId.slice(5);
10909
+ }
10910
+
10911
+ // Fetch value from datasource
10912
+ const { ret: fetchedValue, fieldIdP } = await func.datasource.get_value(SESSION_ID, result.fieldId, dsSessionP, rowIdP);
10913
+ result.value = fetchedValue?.value ?? (sourceP === 'exp' ? fetchedValue?.value : '""');
10914
+ result.type = fetchedValue?.type;
10915
+
10916
+ // Handle iteration
10917
+ if (iterate_info) {
10918
+ if (iterate_info.iterator_key === fieldIdP) result.value = iterate_info._key;
10919
+ if (iterate_info.iterator_val === fieldIdP) result.value = iterate_info._val;
10920
+ }
10921
+
10922
+ // Process nested properties
10923
+ if (val.value.includes('[') || val.value.includes('.')) {
10924
+ const { property1, property2 } = await func.expression.get_property(val.value);
10925
+ const data = fetchedValue?.type === 'object' ? fetchedValue.value : fetchedValue?.prop;
10926
+
10927
+ if (key > 0 && val.value.includes(']') && !val.value.includes('[') && split[key - 1].value) {
10928
+ const prevData = split[key - 1].value;
10929
+ result.value = prevData[fieldIdP];
10930
+ if (val.value.includes('.') && prevData[fieldIdP]) {
10931
+ result.value = prevData[fieldIdP][property2] ?? '';
10932
+ }
10933
+ } else if (data) {
10934
+ if (property1) result.value = data[property1] ?? '';
10935
+ if (property2) result.value = (property1 ? data[property1]?.[property2] : data[property2]) ?? '';
10936
+ }
10937
+ }
10938
+
10939
+ fields[fieldIdP] = result.value;
10940
+ return result;
10941
+ }),
10942
+ );
10943
+
10944
+ // Final evaluation
10945
+ try {
10946
+ const res = var_Arr.map((val, key) => {
10947
+ if (sourceP === 'UI Property EXP' || sourceP === 'UI Attr EXP') {
10948
+ const { changed, value } = func.utils.get_drive_url(SESSION_ID, val.value, sourceP === 'UI Attr EXP' && var_Arr.length > 1);
10949
+ if (changed) return value;
10950
+ }
10951
+
10952
+ let value = val.value;
10953
+ if (var_Arr.length > 1) {
10954
+ if (!['DbQuery', 'alert', 'exp', 'api_rendered_output'].includes(sourceP) && ['string', 'date'].includes(val.type)) {
10955
+ value = `\`${value}\``;
10956
+ } else if (sourceP === 'api_rendered_output' && api_output_type === 'json' && ['string', 'date'].includes(val.type)) {
10957
+ value = `"${value}"`;
10958
+ }
10959
+ }
10960
+
10961
+ if (val.fieldId && typeof value === 'string') {
10962
+ if (['query', 'condition', 'range', 'sort', 'locate'].includes(sourceP)) value = value.replace(/↵|\r\n|\n|\r/g, '');
10963
+ if (['init', 'update', 'virtual'].includes(sourceP)) value = value.replace(/↵|\r\n|\n|\r/g, '\\n');
10964
+ if (typeof IS_PROCESS_SERVER !== 'undefined') value = value.replace(/↵|\r\n|\n|\r/g, '<br>');
10965
+ fields[val.fieldId] = value;
10966
+ }
10967
+
10968
+ if (typeof value === 'object' && var_Arr.length > 1) {
10969
+ value = Array.isArray(value) || var_Arr[key + 1]?.value?.includes('.') ? JSON.stringify(value) : `(${JSON.stringify(value)})`;
10970
+ }
10971
+
10972
+ if (!val.type === 'exp' && sourceP !== 'exp' && typeof value === 'string' && value.startsWith('@')) {
10973
+ warning = `Error encoding ${value}`;
10974
+ var_error_found = true;
10975
+ return '0';
10976
+ }
10977
+ return value;
10978
+ });
10979
+
10980
+ ret = res.length === 1 ? res[0] : res.join('');
10981
+ if (var_Arr.some((v) => v.type === 'exp') && sourceP !== 'exp' && !secondPassP) {
10982
+ const exp = await func.expression.get(SESSION_ID, ret, dsSessionP, sourceP, rowIdP, sourceActionP, true, calling_fieldIdP, fields, debug_infoP);
10983
+ ret = exp.res?.[0] ?? exp.result;
10984
+ Object.assign(fields, exp.fields);
10985
+ } else if (!secondPassP && !['arguments', 'api_rendered_output', 'DbQuery'].includes(sourceP)) {
10986
+ ret = await func.expression.secure_eval(SESSION_ID, sourceP, ret, jobNo, dsSessionP, js_script_callback);
10987
+ } else if (sourceP === 'DbQuery') {
10988
+ ret = JSON.stringify(evalJson(ret));
10989
+ }
10990
+
10991
+ if (typeof ret === 'string' && ret.startsWith('@')) {
10992
+ error = 'Error encoding @ var';
10993
+ var_error_found = true;
10994
+ }
10995
+ } catch (err) {
10996
+ error = err.message;
10997
+ }
10998
+
10999
+ return endResults();
11000
+ };
11001
+
10831
11002
  func.expression.parse_org = function (strP) {
10832
11003
  var extract_str = function (strP, posP) {
10833
11004
  if (!posP) posP = 0;
@@ -11009,7 +11180,7 @@ func.expression.parse = function (input) {
11009
11180
  return segments;
11010
11181
  };
11011
11182
 
11012
- func.expression.get_property = async function (valP) {
11183
+ func.expression.get_property_org = async function (valP) {
11013
11184
  async function secure_eval(val) {
11014
11185
  if (typeof IS_PROCESS_SERVER === 'undefined') {
11015
11186
  try {
@@ -11047,21 +11218,73 @@ func.expression.get_property = async function (valP) {
11047
11218
  property2: property2,
11048
11219
  };
11049
11220
  };
11050
- func.expression.validate_constant = function (valP) {
11221
+
11222
+ func.expression.get_property = async function (valP) {
11223
+ if (typeof valP !== 'string') return { property1: undefined, property2: undefined };
11224
+
11225
+ const secureEval = async (expr) => {
11226
+ if (typeof IS_PROCESS_SERVER === 'undefined') {
11227
+ try {
11228
+ return eval(expr);
11229
+ } catch (err) {
11230
+ console.error(err);
11231
+ return undefined;
11232
+ }
11233
+ }
11234
+ try {
11235
+ const vm = new VM.VM({
11236
+ sandbox: {
11237
+ func,
11238
+ SESSION_ID,
11239
+ SESSION_OBJ: { [SESSION_ID]: SESSION_OBJ[SESSION_ID] },
11240
+ },
11241
+ timeout: 1000,
11242
+ allowAsync: false,
11243
+ });
11244
+ return await vm.run(expr);
11245
+ } catch {
11246
+ return undefined; // Simplified error handling
11247
+ }
11248
+ };
11249
+
11250
+ let property1, property2;
11251
+ const bracketStart = valP.indexOf('[');
11252
+ const bracketEnd = valP.indexOf(']');
11253
+
11254
+ if (bracketStart > -1 && bracketEnd > bracketStart) {
11255
+ const expr = valP.slice(bracketStart + 1, bracketEnd);
11256
+ property1 = await secureEval(expr);
11257
+ }
11258
+
11259
+ const dotIndex = valP.indexOf('.');
11260
+ if (dotIndex > -1) {
11261
+ property2 = valP.slice(dotIndex + 1);
11262
+ }
11263
+
11264
+ return { property1, property2 };
11265
+ };
11266
+
11267
+ func.expression.validate_constant_org = function (valP) {
11051
11268
  var patt = /["']/;
11052
11269
  if (typeof valP === 'string' && patt.test(valP.substr(0, 1)) && patt.test(valP.substr(0, valP.length - 1))) return true;
11053
11270
  else return false;
11054
11271
  };
11055
- func.expression.validate_variables = function (valP) {
11272
+ func.expression.validate_variables_org = function (valP) {
11056
11273
  if (typeof valP === 'string' && valP.indexOf('@') > -1) return true;
11057
11274
  else return false;
11058
11275
  };
11059
- func.expression.remove_quotes = function (valP) {
11276
+ func.expression.remove_quotes_org = function (valP) {
11060
11277
  if (func.expression.validate_constant(valP)) return valP.substr(1, valP.length - 2);
11061
11278
  else return valP;
11062
11279
  };
11063
11280
 
11064
- func.expression.secure_eval = async function (SESSION_ID, sourceP, val, job_id, dsSessionP, js_script_callback, evt) {
11281
+ func.expression.validate_constant = (valP) => typeof valP === 'string' && /^["'].*["']$/.test(valP);
11282
+
11283
+ func.expression.validate_variables = (valP) => typeof valP === 'string' && valP.includes('@');
11284
+
11285
+ func.expression.remove_quotes = (valP) => (func.expression.validate_constant(valP) && typeof valP === 'string' ? valP.slice(1, -1) : valP);
11286
+
11287
+ func.expression.secure_eval_org = async function (SESSION_ID, sourceP, val, job_id, dsSessionP, js_script_callback, evt) {
11065
11288
  const api_utils = await func.common.get_module(SESSION_ID, 'xuda-api-library.mjs', {
11066
11289
  func,
11067
11290
  glb,
@@ -11162,6 +11385,90 @@ func.expression.secure_eval = async function (SESSION_ID, sourceP, val, job_id,
11162
11385
  }
11163
11386
  }
11164
11387
  };
11388
+
11389
+ func.expression.secure_eval = async function (SESSION_ID, sourceP, val, job_id, dsSessionP, js_script_callback, evt) {
11390
+ if (typeof val !== 'string') return val;
11391
+
11392
+ const xu = await func.common.get_module(SESSION_ID, 'xuda-api-library.mjs', {
11393
+ func,
11394
+ glb,
11395
+ SESSION_OBJ,
11396
+ SESSION_ID,
11397
+ APP_OBJ,
11398
+ dsSession: dsSessionP,
11399
+ job_id,
11400
+ });
11401
+
11402
+ const isServer = typeof IS_PROCESS_SERVER !== 'undefined' || typeof IS_DOCKER !== 'undefined';
11403
+
11404
+ // Client-side execution
11405
+ if (!isServer) {
11406
+ try {
11407
+ return eval(val);
11408
+ } catch {
11409
+ try {
11410
+ return JSON5.parse(val);
11411
+ } catch {
11412
+ return val;
11413
+ }
11414
+ }
11415
+ }
11416
+
11417
+ // Server-side execution
11418
+ const sandbox = {
11419
+ func,
11420
+ xu,
11421
+ SESSION_ID,
11422
+ SESSION_OBJ: { [SESSION_ID]: SESSION_OBJ[SESSION_ID] },
11423
+ callback: js_script_callback,
11424
+ job_id,
11425
+ ...(sourceP === 'javascript' ? { axios, got, FormData } : {}),
11426
+ };
11427
+
11428
+ const handleError = (err) => {
11429
+ console.error('Execution error:', err);
11430
+ func.events.delete_job(SESSION_ID, job_id);
11431
+ if (isServer && !SESSION_OBJ[SESSION_ID].crawler) {
11432
+ if (sourceP === 'javascript') {
11433
+ __.rpi.write_log(SESSION_OBJ[SESSION_ID].app_id, 'error', 'worker', 'vm error', err, null, val, 'func.expression.get.secure_eval');
11434
+ } else {
11435
+ __.db.add_error_log(SESSION_OBJ[SESSION_ID].app_id, 'api', err);
11436
+ }
11437
+ }
11438
+ return val; // Fallback to original value
11439
+ };
11440
+
11441
+ if (sourceP === 'javascript') {
11442
+ process.on('uncaughtException', handleError);
11443
+ try {
11444
+ const dir = path.join(_conf.studio_drive_path, SESSION_OBJ[SESSION_ID].app_id, 'node_modules');
11445
+ const script = new VM.VMScript(`try { ${val} } catch (e) { func.api.error(SESSION_ID, "nodejs error", e); console.error(e); func.events.delete_job(SESSION_ID, "${job_id}"); }`, { filename: dir, dirname: dir });
11446
+ const vm = new VM.NodeVM({
11447
+ require: { external: true },
11448
+ sandbox,
11449
+ timeout: 60000,
11450
+ });
11451
+ return await vm.run(script, { filename: dir, dirname: dir });
11452
+ } catch (err) {
11453
+ return handleError(err);
11454
+ }
11455
+ }
11456
+
11457
+ try {
11458
+ const vm = new VM.VM({
11459
+ sandbox,
11460
+ timeout: 1000,
11461
+ allowAsync: false,
11462
+ });
11463
+ return await vm.run(val);
11464
+ } catch {
11465
+ try {
11466
+ return JSON5.parse(val);
11467
+ } catch {
11468
+ return val;
11469
+ }
11470
+ }
11471
+ };
11165
11472
  func.UI.screen = {};
11166
11473
  func.UI.screen.init = async function (SESSION_ID, prog_id, sourceScreenP, callingDataSource_objP, $callingContainerP, triggerIdP, rowIdP, jobNoP, is_panelP, parameters_obj_inP, source_functionP, call_screen_propertiesP) {
11167
11474
  if (!prog_id) return console.error('program is empty');